@brainervirus/workit-cursor 1.0.11 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor-plugin/plugin.json +1 -1
- package/dist/cursor-session-start.js +363 -212
- package/dist/mcp-server.js +2973 -2869
- package/dist/workit-hook.js +334 -210
- package/package.json +3 -3
|
@@ -7492,7 +7492,87 @@ var SCHEMA_VERSION = 1, POLICY_VERSION = "1.0.0", OPERATION_FAMILIES, uuidPatter
|
|
|
7492
7492
|
const covers = (path) => normOuter.paths.some((base) => base === "." || path === base || path.startsWith(`${base}/`)) && !excluded(path, normOuter);
|
|
7493
7493
|
const innerExcludes = (path) => innerExclusions.some((excludedPath) => excludedPath === path || path.startsWith(`${excludedPath}/`));
|
|
7494
7494
|
return innerPaths.every(covers) && !normOuter.exclusions.some((excludedPath) => innerPaths.some((base) => (base === "." || excludedPath === base || excludedPath.startsWith(`${base}/`)) && !innerExcludes(excludedPath)));
|
|
7495
|
-
}, refSchema,
|
|
7495
|
+
}, refSchema, rewriteUnknown = (value, map) => {
|
|
7496
|
+
if (Array.isArray(value)) {
|
|
7497
|
+
const out = [];
|
|
7498
|
+
for (const item of value) {
|
|
7499
|
+
const rewritten = rewriteUnknown(item, map);
|
|
7500
|
+
if (!rewritten.drop)
|
|
7501
|
+
out.push(rewritten.value);
|
|
7502
|
+
}
|
|
7503
|
+
return { drop: false, value: out };
|
|
7504
|
+
}
|
|
7505
|
+
if (typeof value === "object" && value !== null) {
|
|
7506
|
+
if (refSchema.safeParse(value).success) {
|
|
7507
|
+
const mapped = map(value);
|
|
7508
|
+
return mapped === null ? { drop: true } : { drop: false, value: mapped };
|
|
7509
|
+
}
|
|
7510
|
+
const out = {};
|
|
7511
|
+
for (const [key, item] of Object.entries(value)) {
|
|
7512
|
+
const rewritten = rewriteUnknown(item, map);
|
|
7513
|
+
out[key] = rewritten.drop ? null : rewritten.value;
|
|
7514
|
+
}
|
|
7515
|
+
return { drop: false, value: out };
|
|
7516
|
+
}
|
|
7517
|
+
return { drop: false, value };
|
|
7518
|
+
}, rewriteNode = (value, schema, map) => {
|
|
7519
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && refSchema.safeParse(value).success) {
|
|
7520
|
+
const mapped = map(value);
|
|
7521
|
+
return mapped === null ? { drop: true } : { drop: false, value: mapped };
|
|
7522
|
+
}
|
|
7523
|
+
let node = schema;
|
|
7524
|
+
while (node instanceof ZodNullable || node instanceof ZodOptional || node instanceof ZodDefault) {
|
|
7525
|
+
node = node.unwrap();
|
|
7526
|
+
}
|
|
7527
|
+
if (node === refSchema) {
|
|
7528
|
+
if (!refSchema.safeParse(value).success)
|
|
7529
|
+
return { drop: false, value };
|
|
7530
|
+
const mapped = map(value);
|
|
7531
|
+
return mapped === null ? { drop: true } : { drop: false, value: mapped };
|
|
7532
|
+
}
|
|
7533
|
+
if (node instanceof ZodArray) {
|
|
7534
|
+
if (!Array.isArray(value))
|
|
7535
|
+
return { drop: false, value };
|
|
7536
|
+
const out = [];
|
|
7537
|
+
for (const item of value) {
|
|
7538
|
+
const rewritten = rewriteNode(item, node.element, map);
|
|
7539
|
+
if (!rewritten.drop)
|
|
7540
|
+
out.push(rewritten.value);
|
|
7541
|
+
}
|
|
7542
|
+
return { drop: false, value: out };
|
|
7543
|
+
}
|
|
7544
|
+
if (node instanceof ZodObject) {
|
|
7545
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
7546
|
+
return { drop: false, value };
|
|
7547
|
+
const shape = node.shape;
|
|
7548
|
+
const record = value;
|
|
7549
|
+
const out = {};
|
|
7550
|
+
for (const [key, item] of Object.entries(record)) {
|
|
7551
|
+
if (!(key in shape)) {
|
|
7552
|
+
const scrubbed = rewriteUnknown(item, map);
|
|
7553
|
+
out[key] = scrubbed.drop ? null : scrubbed.value;
|
|
7554
|
+
continue;
|
|
7555
|
+
}
|
|
7556
|
+
const child = shape[key];
|
|
7557
|
+
const rewritten = rewriteNode(item, child, map);
|
|
7558
|
+
if (rewritten.drop) {
|
|
7559
|
+
if (child instanceof ZodOptional || child instanceof ZodDefault)
|
|
7560
|
+
continue;
|
|
7561
|
+
if (child instanceof ZodNullable) {
|
|
7562
|
+
out[key] = null;
|
|
7563
|
+
continue;
|
|
7564
|
+
}
|
|
7565
|
+
return { drop: true };
|
|
7566
|
+
}
|
|
7567
|
+
out[key] = rewritten.value;
|
|
7568
|
+
}
|
|
7569
|
+
return { drop: false, value: out };
|
|
7570
|
+
}
|
|
7571
|
+
return { drop: false, value };
|
|
7572
|
+
}, rewriteRecordRefs = (value, schema, map) => {
|
|
7573
|
+
const rewritten = rewriteNode(value, schema, map);
|
|
7574
|
+
return rewritten.drop ? null : rewritten.value;
|
|
7575
|
+
}, provenanceSchema, entrySchema = (data) => object({ id, recordedAt: utc, provenance: provenanceSchema, data }).strict(), factSchema, signalSchema, signalSet, consequenceSchema, verificationSchema, assessmentSchema, constraintSchema, intentSchema, progressSchema, dimensionSchema, policySchema, requirementSchema, policyChangeSchema, candidateSchema, evidenceSchema, evidenceEvaluationSchema, decisionSchema, findingSchema, assignmentSchema, workerReportSchema, workerSchema, ownerSchema, closureSchema, actionProgressSchema, actionProgressListSchema, runtimeSchema, taskRecordSchema, workspaceRecordSchema, capabilitySchema, requirementEvaluationSchema, taskViewSchema, taskSummarySchema, exportBundleSchema, callerSchema, base, revisions, taskId, operation = (shape) => object({ ...base, ...shape }).strict(), taskOperations, policyOperations, evidenceOperations, findingOperations, decisionOperations, workerOperations, writerOperations, stateOperations, operationSchemas, compiledOperationSchemas, success = (revisionValue, workspaceRevisionValue, data) => ({
|
|
7496
7576
|
ok: true,
|
|
7497
7577
|
schemaVersion: 1,
|
|
7498
7578
|
revision: revisionValue,
|
|
@@ -9075,11 +9155,11 @@ class TaskStore {
|
|
|
9075
9155
|
return workspace;
|
|
9076
9156
|
if (!workspace.data)
|
|
9077
9157
|
return failure("not_found", "workspace not found");
|
|
9078
|
-
const
|
|
9079
|
-
if (!
|
|
9158
|
+
const expected = input.expectedRevision;
|
|
9159
|
+
if (!expected)
|
|
9080
9160
|
return failure("invalid_input", "task revision is required");
|
|
9081
|
-
if (task.data.revision !==
|
|
9082
|
-
return this.conflict(
|
|
9161
|
+
if (task.data.revision !== expected)
|
|
9162
|
+
return this.conflict(expected, task.data.revision);
|
|
9083
9163
|
if (workspace.data.revision !== input.expectedWorkspaceRevision)
|
|
9084
9164
|
return this.conflict(input.expectedWorkspaceRevision, workspace.data.revision);
|
|
9085
9165
|
const previousWorkspaceBytes = this.snapshotBytes(this.workspacePath);
|
|
@@ -9705,7 +9785,7 @@ var same = (left, right) => {
|
|
|
9705
9785
|
} catch {
|
|
9706
9786
|
return false;
|
|
9707
9787
|
}
|
|
9708
|
-
}, UNCERTAIN_WORKER_STATES, isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state), callerSession = (caller) => caller.session ?? { kind: "host", host: caller.host, handle: caller.actor }, validPath = (value) => typeof value === "string" && value.length > 0 && ![...value].some((char) => {
|
|
9788
|
+
}, UNCERTAIN_WORKER_STATES, isUncertainWorker = (state) => UNCERTAIN_WORKER_STATES.includes(state), workerBlocksTransition = (transition, state) => transition === "pause" ? false : isUncertainWorker(state), callerSession = (caller) => caller.session ?? { kind: "host", host: caller.host, handle: caller.actor }, validPath = (value) => typeof value === "string" && value.length > 0 && ![...value].some((char) => {
|
|
9709
9789
|
const code = char.charCodeAt(0);
|
|
9710
9790
|
return code < 32 || code === 127;
|
|
9711
9791
|
}) && !value.split(/[\\/]/).includes(".."), callerValue = (value) => ({ host: value.host, actor: value.actor }), workerIdOf = (value) => value.workerId ?? null;
|
|
@@ -10000,6 +10080,33 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
10000
10080
|
const token = {};
|
|
10001
10081
|
verifiedAuthorities.set(token, { kind, provenance, ...expected, ...binding, caller });
|
|
10002
10082
|
return token;
|
|
10083
|
+
}, chainStepKey = (step) => step.kind === "commit" ? step.message : step.kind === "branch" ? `branch:${step.target}` : "pr", isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value), normalizeChainSteps = (steps) => {
|
|
10084
|
+
if (!Array.isArray(steps) || steps.length === 0 || steps.length > 32)
|
|
10085
|
+
return null;
|
|
10086
|
+
const normalized = [];
|
|
10087
|
+
for (const step of steps) {
|
|
10088
|
+
if (typeof step === "string") {
|
|
10089
|
+
if (!step.trim())
|
|
10090
|
+
return null;
|
|
10091
|
+
normalized.push({ kind: "commit", message: step });
|
|
10092
|
+
continue;
|
|
10093
|
+
}
|
|
10094
|
+
if (!isRecord(step))
|
|
10095
|
+
return null;
|
|
10096
|
+
if (typeof step.branch === "string" && step.branch.trim() && Object.keys(step).length === 1) {
|
|
10097
|
+
normalized.push({ kind: "branch", target: step.branch });
|
|
10098
|
+
continue;
|
|
10099
|
+
}
|
|
10100
|
+
if (step.pr === true && Object.keys(step).length === 1) {
|
|
10101
|
+
normalized.push({ kind: "pr" });
|
|
10102
|
+
continue;
|
|
10103
|
+
}
|
|
10104
|
+
return null;
|
|
10105
|
+
}
|
|
10106
|
+
const keys = normalized.map(chainStepKey);
|
|
10107
|
+
if (new Set(keys).size !== keys.length)
|
|
10108
|
+
return null;
|
|
10109
|
+
return normalized;
|
|
10003
10110
|
}, scopeEqual = (left, right) => canonicalJson(left) === canonicalJson(right), parseSteps = (content) => {
|
|
10004
10111
|
let value;
|
|
10005
10112
|
try {
|
|
@@ -10010,7 +10117,10 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
10010
10117
|
if (typeof value !== "object" || value === null || !("steps" in value))
|
|
10011
10118
|
return [];
|
|
10012
10119
|
const steps = value.steps;
|
|
10013
|
-
|
|
10120
|
+
if (!Array.isArray(steps))
|
|
10121
|
+
return null;
|
|
10122
|
+
const normalized = normalizeChainSteps(steps);
|
|
10123
|
+
return normalized;
|
|
10014
10124
|
}, decisionMatches = (entry, purpose, binding) => {
|
|
10015
10125
|
const decision = entry.data;
|
|
10016
10126
|
return binding.taskId === decision.binding.taskId && binding.workspaceId === decision.binding.workspaceId && decision.purpose === purpose && decision.response === "approved" && decision.revoked === null && (purpose !== "action" || decision.consumption === null) && decision.digest === decisionDigest(decision) && scopeEqual(decision.binding.scope, binding.scope) && canonicalJson(decision.binding) === canonicalJson(binding);
|
|
@@ -10180,14 +10290,12 @@ var verifiedAuthorities, trustedAuthority = (kind, provenance, expected, binding
|
|
|
10180
10290
|
return content;
|
|
10181
10291
|
const requestedSteps = parseSteps(decision.binding.approvedContent);
|
|
10182
10292
|
if (requestedSteps === null)
|
|
10183
|
-
return failure("invalid_input", "bounded action steps must be a
|
|
10184
|
-
if (input.steps && canonicalJson(input.steps) !== canonicalJson(requestedSteps))
|
|
10293
|
+
return failure("invalid_input", "bounded action steps must be a unique non-empty array");
|
|
10294
|
+
if (input.steps && canonicalJson(input.steps) !== canonicalJson(requestedSteps.map(chainStepKey)))
|
|
10185
10295
|
return failure("permission_denied", "bounded action steps do not match approved content");
|
|
10186
|
-
if (requestedSteps.some((step) => !step || typeof step !== "string") || new Set(requestedSteps).size !== requestedSteps.length)
|
|
10187
|
-
return failure("invalid_input", "bounded action steps must be unique and non-empty");
|
|
10188
10296
|
const stored = task.actionProgress?.find((item) => item.decisionId === input.decisionId);
|
|
10189
|
-
const workflow = stored ? { steps: stored.steps, completed: stored.completedSteps } : { steps: requestedSteps, completed: [] };
|
|
10190
|
-
if (workflow.steps.length && requestedSteps.length && canonicalJson(workflow.steps) !== canonicalJson(requestedSteps))
|
|
10297
|
+
const workflow = stored ? { steps: stored.steps, completed: stored.completedSteps } : { steps: requestedSteps.map(chainStepKey), completed: [] };
|
|
10298
|
+
if (workflow.steps.length && requestedSteps.length && canonicalJson(workflow.steps) !== canonicalJson(requestedSteps.map(chainStepKey)))
|
|
10191
10299
|
return failure("permission_denied", "bounded action scope changed");
|
|
10192
10300
|
return success(null, null, { entry, workflow });
|
|
10193
10301
|
}, bindingCovers, verifyDecisionContent;
|
|
@@ -10355,7 +10463,7 @@ function evaluateRequirements(task, workspace, capabilities, candidate, checkout
|
|
|
10355
10463
|
return (task.policy?.requirements ?? []).map((requirement) => {
|
|
10356
10464
|
const related = task.evidence.map((entry, index) => ({ entry, evaluation: evidence[index] })).filter(({ entry }) => entry.data.requirementIds.includes(requirement.id));
|
|
10357
10465
|
const passed = related.filter(({ entry, evaluation }) => {
|
|
10358
|
-
if (!evidenceMatchesRequirement(evaluation.status, entry.data.kind, requirement.dimension))
|
|
10466
|
+
if (!evidenceMatchesRequirement(evaluation.status, entry.data.kind, requirement.dimension, requirement.ruleId))
|
|
10359
10467
|
return false;
|
|
10360
10468
|
if ((entry.data.kind === "check" || entry.data.kind === "review") && (!entry.data.beforeCandidateId || !entry.data.candidateId || entry.data.beforeCandidateId !== entry.data.candidateId))
|
|
10361
10469
|
return false;
|
|
@@ -10363,11 +10471,12 @@ function evaluateRequirements(task, workspace, capabilities, candidate, checkout
|
|
|
10363
10471
|
return true;
|
|
10364
10472
|
const reviewSession = sessionFromRef(entry.data.reviewContext);
|
|
10365
10473
|
const sameImplementation = sameSession(reviewSession, task.intent.provenance.session);
|
|
10366
|
-
const sameEvidenceSession =
|
|
10474
|
+
const sameEvidenceSession = related.some(({ entry: other }) => other.id !== entry.id && other.data.kind === "review" && other.data.candidateId !== null && other.data.candidateId === entry.data.candidateId && sameSession(reviewSession, other.provenance.session));
|
|
10367
10475
|
return entry.data.kind === "review" && reviewSession !== null && sameSession(reviewSession, entry.provenance.session) && (requirement.ruleId === "self-review" || !sameImplementation && !sameEvidenceSession);
|
|
10368
10476
|
});
|
|
10369
10477
|
if (passed.length) {
|
|
10370
|
-
const
|
|
10478
|
+
const currentId = candidate?.id ?? null;
|
|
10479
|
+
const withRed = requirement.dimension === "testing" ? passed.filter(({ entry }) => related.some((other) => other.entry.data.kind === "check" && other.evaluation.status === "failed" && other.entry.data.requirementIds.includes(requirement.id) && other.entry.recordedAt <= entry.recordedAt) || related.some((baseline) => baseline.entry.id !== entry.id && baseline.entry.data.kind === "check" && baseline.entry.data.result === "passed" && baseline.entry.data.candidateId !== null && currentId !== null && baseline.entry.data.candidateId !== currentId)) : passed;
|
|
10371
10480
|
if (withRed.length)
|
|
10372
10481
|
return {
|
|
10373
10482
|
requirementId: requirement.id,
|
|
@@ -10416,6 +10525,14 @@ function evaluateRequirements(task, workspace, capabilities, candidate, checkout
|
|
|
10416
10525
|
reason: "an applicable approved limitation permits the missing evidence"
|
|
10417
10526
|
};
|
|
10418
10527
|
const unavailable = capabilities.some((capability) => capability.assurance === "unavailable" && (capability.name === requirement.dimension || capability.surface === requirement.dimension));
|
|
10528
|
+
if (!unavailable && related.length > 0 && !passed.length)
|
|
10529
|
+
return {
|
|
10530
|
+
requirementId: requirement.id,
|
|
10531
|
+
status: "unsatisfied",
|
|
10532
|
+
evidenceIds: related.map(({ entry }) => entry.id),
|
|
10533
|
+
decisionIds: [],
|
|
10534
|
+
reason: `no passing evidence (needs kind:${expectedKinds(requirement.dimension, requirement.ruleId)})`
|
|
10535
|
+
};
|
|
10419
10536
|
return {
|
|
10420
10537
|
requirementId: requirement.id,
|
|
10421
10538
|
status: unavailable ? "unavailable" : "unsatisfied",
|
|
@@ -10440,7 +10557,13 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
10440
10557
|
if (entry.data.disposition === "fixed") {
|
|
10441
10558
|
const verified = entry.data.resolution?.evidenceIds.some((id) => {
|
|
10442
10559
|
const evidence = view.task.evidence.find((item) => item.id === id);
|
|
10443
|
-
|
|
10560
|
+
if (!evidence)
|
|
10561
|
+
return false;
|
|
10562
|
+
return findingVerificationPasses(entry.data.candidateId, {
|
|
10563
|
+
kind: evidence.data.kind,
|
|
10564
|
+
candidateId: evidence.data.candidateId,
|
|
10565
|
+
status: evidenceById.get(id) ?? "missing"
|
|
10566
|
+
});
|
|
10444
10567
|
});
|
|
10445
10568
|
if (!verified)
|
|
10446
10569
|
return failure("requirements_unsatisfied", "fixed findings require current verification");
|
|
@@ -10456,7 +10579,12 @@ function evaluateClosure(requestedOutcome, view) {
|
|
|
10456
10579
|
}
|
|
10457
10580
|
}
|
|
10458
10581
|
}
|
|
10459
|
-
const blocking = evaluations.filter((item) =>
|
|
10582
|
+
const blocking = evaluations.filter((item) => {
|
|
10583
|
+
if (item.status !== "unsatisfied" && item.status !== "unavailable")
|
|
10584
|
+
return false;
|
|
10585
|
+
const requirement = view.task.policy?.requirements.find((candidate) => candidate.id === item.requirementId);
|
|
10586
|
+
return !requirement || requirement.before === "close";
|
|
10587
|
+
});
|
|
10460
10588
|
if (requestedOutcome !== "stopped" && blocking.length)
|
|
10461
10589
|
return failure("requirements_unsatisfied", "applicable requirements are unsatisfied", {
|
|
10462
10590
|
requirementIds: blocking.map((item) => item.requirementId),
|
|
@@ -10612,11 +10740,23 @@ var digestBytes3 = (value) => createHash4("sha256").update(value).digest("hex"),
|
|
|
10612
10740
|
}, sameSession = (left, right) => {
|
|
10613
10741
|
const other = sessionFromRef(right);
|
|
10614
10742
|
return left !== null && other !== null && left.host === other.host && left.handle === other.handle;
|
|
10615
|
-
}, evidenceScopes = (task, ids) => (task.policy?.requirements ?? []).filter((requirement) => ids.includes(requirement.id)).map((requirement) => requirement.scope), scopeCovers2,
|
|
10743
|
+
}, evidenceScopes = (task, ids) => (task.policy?.requirements ?? []).filter((requirement) => ids.includes(requirement.id)).map((requirement) => requirement.scope), scopeCovers2, checkPin = (assignment, beforeCandidateId, candidateId) => {
|
|
10744
|
+
const pin = assignment.candidateId ?? null;
|
|
10745
|
+
if (pin === null)
|
|
10746
|
+
return true;
|
|
10747
|
+
return (beforeCandidateId ?? null) === pin || (candidateId ?? null) === pin;
|
|
10748
|
+
}, resolveBinding = (evidence, pin, currentCandidateId) => {
|
|
10749
|
+
const bound = evidence.kind === "check" || evidence.kind === "review";
|
|
10750
|
+
const fallback = bound ? pin ?? currentCandidateId : null;
|
|
10751
|
+
return {
|
|
10752
|
+
beforeCandidateId: evidence.beforeCandidateId ?? fallback,
|
|
10753
|
+
candidateId: evidence.candidateId ?? fallback
|
|
10754
|
+
};
|
|
10755
|
+
}, findingVerificationPasses = (findingCandidateId, evidence) => evidence.status === "passed" && (evidence.kind === "check" || evidence.kind === "review") && ((findingCandidateId ?? null) === null || evidence.candidateId === findingCandidateId), applicableDecision2 = (task, workspace, requirement, checkoutRoot) => task.decisions.filter((entry) => entry.provenance.kind !== "imported").map((entry) => entry.data).filter((decision) => decision.purpose === "limitation" && decision.response === "approved" && decision.revoked === null && decision.binding.taskId === task.id && decision.binding.workspaceId === workspace.id && decision.requirementIds.includes(requirement.id) && decision.binding.scope && scopeCovers2(decision.binding.scope, requirement.scope) && decision.digest === decisionDigest(decision) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, decision.binding).ok : decision.binding.contentRefs.every((reference) => reference.kind !== "file"))), applicableRequirementDecision = (task, workspace, requirement, checkoutRoot) => task.decisions.filter(({ data, provenance }) => provenance.kind !== "imported" && data.purpose !== "limitation" && (data.response === "approved" || data.response === "stated") && data.revoked === null && data.binding.taskId === task.id && data.binding.workspaceId === workspace.id && data.requirementIds.includes(requirement.id) && scopeCovers2(data.binding.scope, requirement.scope) && data.digest === decisionDigest(data) && (checkoutRoot ? verifyDecisionContentAtRoot(checkoutRoot, data.binding).ok : data.binding.contentRefs.every((reference) => reference.kind !== "file"))).map(({ id }) => ({ id })), evidenceMatchesRequirement = (kind, evidenceKind, dimension, ruleId) => {
|
|
10616
10756
|
if (kind !== "passed")
|
|
10617
10757
|
return false;
|
|
10618
10758
|
if (dimension === "testing" || dimension === "verification")
|
|
10619
|
-
return evidenceKind === "check";
|
|
10759
|
+
return evidenceKind === "check" || ruleId === "pre-pr-cleanup" && evidenceKind === "artifact";
|
|
10620
10760
|
if (dimension === "review")
|
|
10621
10761
|
return evidenceKind === "review";
|
|
10622
10762
|
if (dimension === "investigation" || dimension === "challenge")
|
|
@@ -10624,6 +10764,20 @@ var digestBytes3 = (value) => createHash4("sha256").update(value).digest("hex"),
|
|
|
10624
10764
|
if (dimension === "artifacts" || dimension === "continuity")
|
|
10625
10765
|
return evidenceKind === "artifact";
|
|
10626
10766
|
return false;
|
|
10767
|
+
}, expectedKinds = (dimension, ruleId) => {
|
|
10768
|
+
if (dimension === "testing")
|
|
10769
|
+
return "check";
|
|
10770
|
+
if (dimension === "verification")
|
|
10771
|
+
return ruleId === "pre-pr-cleanup" ? "check or artifact" : "check";
|
|
10772
|
+
if (dimension === "review")
|
|
10773
|
+
return "review";
|
|
10774
|
+
if (dimension === "investigation" || dimension === "challenge")
|
|
10775
|
+
return "investigation";
|
|
10776
|
+
if (dimension === "artifacts" || dimension === "continuity")
|
|
10777
|
+
return "artifact";
|
|
10778
|
+
if (dimension === "decisions")
|
|
10779
|
+
return "decision";
|
|
10780
|
+
return "worker report";
|
|
10627
10781
|
};
|
|
10628
10782
|
var init_task_evaluation = __esm(() => {
|
|
10629
10783
|
init_task_contract();
|
|
@@ -10634,7 +10788,7 @@ var init_task_evaluation = __esm(() => {
|
|
|
10634
10788
|
// packages/workit-core/src/core/methods.ts
|
|
10635
10789
|
function selectMethods(policy, capabilities) {
|
|
10636
10790
|
return Object.entries(METHODS).flatMap(([id, definition]) => {
|
|
10637
|
-
const requirements = policy.requirements.filter((requirement) => methodMatches(
|
|
10791
|
+
const requirements = policy.requirements.filter((requirement) => methodMatches(definition, requirement));
|
|
10638
10792
|
if (requirements.length === 0)
|
|
10639
10793
|
return [];
|
|
10640
10794
|
const capability = assuranceFor(id, definition, capabilities);
|
|
@@ -10647,7 +10801,7 @@ function selectMethods(policy, capabilities) {
|
|
|
10647
10801
|
return [{ id, reason: reasons.join("; "), assurance: capability.assurance }];
|
|
10648
10802
|
});
|
|
10649
10803
|
}
|
|
10650
|
-
var METHODS, methodMatches = (
|
|
10804
|
+
var METHODS, methodMatches = (definition, requirement) => definition.dimensions?.includes(requirement.dimension) === true || definition.ruleIds?.includes(requirement.ruleId) === true, assuranceFor = (id, definition, capabilities) => {
|
|
10651
10805
|
const keys = new Set([
|
|
10652
10806
|
id,
|
|
10653
10807
|
...definition.dimensions ?? [],
|
|
@@ -10721,12 +10875,12 @@ act from memory of it.
|
|
|
10721
10875
|
var init_methods = __esm(() => {
|
|
10722
10876
|
METHODS = {
|
|
10723
10877
|
"workit-challenge": { dimensions: ["challenge", "decisions"] },
|
|
10724
|
-
"workit-behavioral-tdd": { dimensions: ["testing"] },
|
|
10725
|
-
"workit-review": { dimensions: ["review"], ruleIds: ["fresh-context-review"] },
|
|
10878
|
+
"workit-behavioral-tdd": { dimensions: ["testing"], ruleIds: ["mechanical-existing-checks"] },
|
|
10879
|
+
"workit-review": { dimensions: ["review"], ruleIds: ["fresh-context-review", "self-review"] },
|
|
10726
10880
|
"workit-plan": { dimensions: ["artifacts", "continuity"] },
|
|
10727
10881
|
"workit-implement": { dimensions: ["delegation"] },
|
|
10728
|
-
"workit-debug": {
|
|
10729
|
-
"workit-handoff": {
|
|
10882
|
+
"workit-debug": {},
|
|
10883
|
+
"workit-handoff": {},
|
|
10730
10884
|
"workit-deslop": { ruleIds: ["pre-pr-cleanup"] }
|
|
10731
10885
|
};
|
|
10732
10886
|
});
|
|
@@ -10837,10 +10991,66 @@ var init_route_intent = __esm(() => {
|
|
|
10837
10991
|
init_task_store();
|
|
10838
10992
|
});
|
|
10839
10993
|
|
|
10994
|
+
// packages/workit-core/src/core/git.ts
|
|
10995
|
+
var init_git = () => {};
|
|
10996
|
+
|
|
10997
|
+
// packages/workit-core/src/core/boundary.ts
|
|
10998
|
+
var init_boundary = () => {};
|
|
10999
|
+
|
|
11000
|
+
// packages/workit-core/src/core/config.ts
|
|
11001
|
+
var PRESETS, DEFAULTS;
|
|
11002
|
+
var init_config = __esm(() => {
|
|
11003
|
+
init_boundary();
|
|
11004
|
+
PRESETS = {
|
|
11005
|
+
gitflow: {
|
|
11006
|
+
allowed: ["feature/*", "bugfix/*", "hotfix/*", "release/*"],
|
|
11007
|
+
protected: ["main", "develop", "master", "prod", "production"]
|
|
11008
|
+
},
|
|
11009
|
+
"github-flow": { allowed: ["*"], protected: ["main"] },
|
|
11010
|
+
"trunk-based": { allowed: ["*"], protected: ["main"] },
|
|
11011
|
+
custom: { allowed: [], protected: [] }
|
|
11012
|
+
};
|
|
11013
|
+
DEFAULTS = {
|
|
11014
|
+
locale: "en",
|
|
11015
|
+
localeOptions: ["en", "es-CL", "es-MX", "es-AR", "pt-BR"],
|
|
11016
|
+
timezone: "America/Santiago",
|
|
11017
|
+
branchPolicy: {
|
|
11018
|
+
preset: "gitflow",
|
|
11019
|
+
allowed: [...PRESETS.gitflow.allowed],
|
|
11020
|
+
protected: [...PRESETS.gitflow.protected]
|
|
11021
|
+
},
|
|
11022
|
+
commitPolicy: { preset: "conventional" }
|
|
11023
|
+
};
|
|
11024
|
+
});
|
|
11025
|
+
|
|
11026
|
+
// packages/workit-core/src/core/workspaces.ts
|
|
11027
|
+
var init_workspaces = __esm(() => {
|
|
11028
|
+
init_config();
|
|
11029
|
+
});
|
|
11030
|
+
|
|
11031
|
+
// packages/workit-core/src/core/vcs-config.ts
|
|
11032
|
+
var init_vcs_config = __esm(() => {
|
|
11033
|
+
init_config();
|
|
11034
|
+
init_workspaces();
|
|
11035
|
+
init_branch();
|
|
11036
|
+
});
|
|
11037
|
+
|
|
11038
|
+
// packages/workit-core/src/core/branch.ts
|
|
11039
|
+
var init_branch = __esm(() => {
|
|
11040
|
+
init_git();
|
|
11041
|
+
init_config();
|
|
11042
|
+
init_workspaces();
|
|
11043
|
+
init_vcs_config();
|
|
11044
|
+
});
|
|
11045
|
+
|
|
11046
|
+
// packages/workit-core/src/core/runtime-identity.ts
|
|
11047
|
+
var init_runtime_identity = () => {};
|
|
11048
|
+
|
|
10840
11049
|
// packages/workit-core/src/core/external-action.ts
|
|
10841
11050
|
var externalActionSchema;
|
|
10842
11051
|
var init_external_action = __esm(() => {
|
|
10843
11052
|
init_task_contract();
|
|
11053
|
+
init_authority();
|
|
10844
11054
|
init_zod();
|
|
10845
11055
|
externalActionSchema = discriminatedUnion("operation", [
|
|
10846
11056
|
object({
|
|
@@ -11314,7 +11524,7 @@ class WorkitCore {
|
|
|
11314
11524
|
activeWorkerBlocker(task, workspace) {
|
|
11315
11525
|
if (workspace.writer)
|
|
11316
11526
|
return failure("recovery_required", "writer ownership must be released first");
|
|
11317
|
-
if (task.workers.some((entry) =>
|
|
11527
|
+
if (task.workers.some((entry) => workerBlocksTransition("close", entry.data.state)))
|
|
11318
11528
|
return failure("recovery_required", "worker state requires reconciliation");
|
|
11319
11529
|
return null;
|
|
11320
11530
|
}
|
|
@@ -11560,37 +11770,33 @@ class WorkitCore {
|
|
|
11560
11770
|
const currentCandidate = captureCandidate(this.store.root, task.data.intent.data.scope, environment());
|
|
11561
11771
|
if (!currentCandidate.ok)
|
|
11562
11772
|
return currentCandidate;
|
|
11563
|
-
|
|
11564
|
-
|
|
11565
|
-
evidence.candidateId ??= currentCandidate.data.id;
|
|
11566
|
-
} else {
|
|
11567
|
-
evidence.beforeCandidateId ??= null;
|
|
11568
|
-
evidence.candidateId ??= null;
|
|
11569
|
-
}
|
|
11773
|
+
const pin = helper && helper.ok ? helper.data.data.assignment.candidateId : null;
|
|
11774
|
+
const bound = resolveBinding(evidence, pin, currentCandidate.data.id);
|
|
11570
11775
|
if (helper?.ok) {
|
|
11571
11776
|
const assignment = helper.data.data.assignment;
|
|
11572
|
-
if (evidence.requirementIds.some((id) => !assignment.requirementIds.includes(id)) || assignment
|
|
11777
|
+
if (evidence.requirementIds.some((id) => !assignment.requirementIds.includes(id)) || !checkPin(assignment, bound.beforeCandidateId, bound.candidateId) || !refsWithinScope(evidence.refs, assignment.scope) || !refsWithinScope(evidence.refs, task.data.intent.data.scope))
|
|
11573
11778
|
return failure("permission_denied", "evidence is outside the worker assignment");
|
|
11574
11779
|
}
|
|
11575
11780
|
const knownCandidates = new Set(task.data.candidates.map((candidate) => candidate.id));
|
|
11576
|
-
for (const candidateId of [
|
|
11781
|
+
for (const candidateId of [bound.beforeCandidateId, bound.candidateId]) {
|
|
11577
11782
|
if (candidateId && candidateId !== currentCandidate.data.id && !knownCandidates.has(candidateId))
|
|
11578
11783
|
return failure("invalid_input", "evidence candidate is not a captured candidate");
|
|
11579
11784
|
}
|
|
11785
|
+
const boundEvidence = { ...evidence, ...bound };
|
|
11580
11786
|
const changed = this.store.mutateTask(task.data.id, input.expectedRevision, (current, mutation) => {
|
|
11581
11787
|
const candidates = current.candidates.some((item) => item.id === currentCandidate.data.id) ? current.candidates : [...current.candidates, currentCandidate.data];
|
|
11582
11788
|
const entry = {
|
|
11583
11789
|
id: newId(),
|
|
11584
11790
|
recordedAt: mutation.now,
|
|
11585
11791
|
provenance: provenance(this.context, "agent_reported"),
|
|
11586
|
-
data:
|
|
11792
|
+
data: boundEvidence
|
|
11587
11793
|
};
|
|
11588
11794
|
return success(mutation.revision, null, {
|
|
11589
11795
|
...current,
|
|
11590
11796
|
candidates,
|
|
11591
11797
|
evidence: [...current.evidence, entry],
|
|
11592
11798
|
findings: current.findings.map((finding) => {
|
|
11593
|
-
if (finding.data.disposition === "open" ||
|
|
11799
|
+
if (finding.data.disposition === "open" || boundEvidence.result === "skipped")
|
|
11594
11800
|
return finding;
|
|
11595
11801
|
if (finding.data.disposition !== "fixed")
|
|
11596
11802
|
return finding;
|
|
@@ -11599,8 +11805,12 @@ class WorkitCore {
|
|
|
11599
11805
|
item.evidenceId,
|
|
11600
11806
|
item.status
|
|
11601
11807
|
]));
|
|
11602
|
-
const verified = withEntry.evidence.some((item) =>
|
|
11603
|
-
|
|
11808
|
+
const verified = withEntry.evidence.some((item) => findingVerificationPasses(finding.data.candidateId, {
|
|
11809
|
+
kind: item.data.kind,
|
|
11810
|
+
candidateId: item.data.candidateId,
|
|
11811
|
+
status: statuses.get(item.id) ?? "missing"
|
|
11812
|
+
}));
|
|
11813
|
+
const contradicted = boundEvidence.result === "failed" && finding.data.refs.some((left) => boundEvidence.refs.some((right) => sameValue(left, right)));
|
|
11604
11814
|
return verified && !contradicted ? finding : { ...finding, data: { ...finding.data, disposition: "open", resolution: null } };
|
|
11605
11815
|
})
|
|
11606
11816
|
});
|
|
@@ -11758,7 +11968,7 @@ class WorkitCore {
|
|
|
11758
11968
|
if (input.action === "record") {
|
|
11759
11969
|
if (helper?.ok) {
|
|
11760
11970
|
const assignment = helper.data.data.assignment;
|
|
11761
|
-
if (!bindingCovers(assignment.scope, input.scope) || !bindingCovers(task.data.intent.data.scope, input.scope) || assignment
|
|
11971
|
+
if (!bindingCovers(assignment.scope, input.scope) || !bindingCovers(task.data.intent.data.scope, input.scope) || !checkPin(assignment, null, input.candidateId ?? null) || !refsWithinScope(input.refs, assignment.scope) || !refsWithinScope(input.refs, task.data.intent.data.scope))
|
|
11762
11972
|
return failure("permission_denied", "finding is outside the worker assignment");
|
|
11763
11973
|
}
|
|
11764
11974
|
if (input.candidateId && !task.data.candidates.some((candidate) => candidate.id === input.candidateId))
|
|
@@ -11805,7 +12015,11 @@ class WorkitCore {
|
|
|
11805
12015
|
const evaluations = evaluateEvidence(task.data, current.data);
|
|
11806
12016
|
const verified = evidence.some((entry) => {
|
|
11807
12017
|
const evaluation = evaluations.find((item) => item.evidenceId === entry.id);
|
|
11808
|
-
return
|
|
12018
|
+
return findingVerificationPasses(finding.data.candidateId, {
|
|
12019
|
+
kind: entry.data.kind,
|
|
12020
|
+
candidateId: entry.data.candidateId,
|
|
12021
|
+
status: evaluation?.status ?? "missing"
|
|
12022
|
+
});
|
|
11809
12023
|
});
|
|
11810
12024
|
if (!verified)
|
|
11811
12025
|
return failure("permission_denied", "fixed findings require passing verification evidence");
|
|
@@ -11817,7 +12031,7 @@ class WorkitCore {
|
|
|
11817
12031
|
if (entry.data.result === "missing" || entry.data.result === "skipped")
|
|
11818
12032
|
return false;
|
|
11819
12033
|
const candidateMatches = finding.data.candidateId === null ? entry.data.candidateId === null : entry.data.candidateId === finding.data.candidateId || entry.data.beforeCandidateId === finding.data.candidateId;
|
|
11820
|
-
const referenceMatches = finding.data.refs.some((left) => entry.data.refs.some((right) =>
|
|
12034
|
+
const referenceMatches = finding.data.refs.some((left) => entry.data.refs.some((right) => sameValue(left, right)));
|
|
11821
12035
|
return candidateMatches && (referenceMatches || entry.data.claim === finding.data.claim);
|
|
11822
12036
|
});
|
|
11823
12037
|
if (!relevant)
|
|
@@ -11895,7 +12109,7 @@ class WorkitCore {
|
|
|
11895
12109
|
const workerId = newId();
|
|
11896
12110
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
11897
12111
|
taskId: task.data.id,
|
|
11898
|
-
|
|
12112
|
+
expectedRevision: input.expectedRevision,
|
|
11899
12113
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
11900
12114
|
now: trustedNow(this.context),
|
|
11901
12115
|
workspace: (current, mutation) => success(mutation.revision, mutation.revision, current),
|
|
@@ -11933,7 +12147,7 @@ class WorkitCore {
|
|
|
11933
12147
|
return failure("permission_denied", "worker report is outside the worker assignment");
|
|
11934
12148
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
11935
12149
|
taskId: task.data.id,
|
|
11936
|
-
|
|
12150
|
+
expectedRevision: input.expectedRevision,
|
|
11937
12151
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
11938
12152
|
now: trustedNow(this.context),
|
|
11939
12153
|
workspace: (current, mutation) => success(mutation.revision, mutation.revision, current),
|
|
@@ -11957,24 +12171,25 @@ class WorkitCore {
|
|
|
11957
12171
|
return failure("invalid_transition", "closed task cannot cancel workers");
|
|
11958
12172
|
if (entry.data.state === "unknown")
|
|
11959
12173
|
return failure("recovery_required", "worker state requires recovery");
|
|
11960
|
-
if (entry.data.state === "stopped")
|
|
11961
|
-
|
|
11962
|
-
|
|
12174
|
+
if (entry.data.state === "stopped") {
|
|
12175
|
+
const stopped = task.data.workers.find((candidate) => candidate.id === input.workerId);
|
|
12176
|
+
return success(task.data.revision, workspace.data.revision, stopped);
|
|
12177
|
+
}
|
|
11963
12178
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
11964
12179
|
taskId: task.data.id,
|
|
11965
|
-
|
|
12180
|
+
expectedRevision: input.expectedRevision,
|
|
11966
12181
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
11967
12182
|
now: trustedNow(this.context),
|
|
11968
|
-
workspace: (current, mutation) => success(mutation.revision, mutation.revision,
|
|
12183
|
+
workspace: (current, mutation) => success(mutation.revision, mutation.revision, {
|
|
12184
|
+
...current,
|
|
12185
|
+
writer: current.writer?.owner.workerId === input.workerId ? null : current.writer
|
|
12186
|
+
}),
|
|
11969
12187
|
task: (current, mutation) => success(mutation.revision, null, {
|
|
11970
12188
|
...current,
|
|
11971
12189
|
workers: current.workers.map((candidate) => candidate.id === input.workerId ? {
|
|
11972
12190
|
...candidate,
|
|
11973
12191
|
recordedAt: mutation.now,
|
|
11974
|
-
data: {
|
|
11975
|
-
...candidate.data,
|
|
11976
|
-
state: settles ? "stopped" : "cancelling"
|
|
11977
|
-
}
|
|
12192
|
+
data: { ...candidate.data, state: "stopped" }
|
|
11978
12193
|
} : candidate)
|
|
11979
12194
|
})
|
|
11980
12195
|
});
|
|
@@ -12071,7 +12286,7 @@ class WorkitCore {
|
|
|
12071
12286
|
return attested;
|
|
12072
12287
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
12073
12288
|
taskId: task.data.id,
|
|
12074
|
-
|
|
12289
|
+
expectedRevision: input.expectedRevision,
|
|
12075
12290
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
12076
12291
|
now: trustedNow(this.context),
|
|
12077
12292
|
workspace: (current, mutation) => success(mutation.revision, mutation.revision, current),
|
|
@@ -12237,6 +12452,12 @@ class WorkitCore {
|
|
|
12237
12452
|
if (!sameSession2(helper.data.data.session, this.context))
|
|
12238
12453
|
return failure("permission_denied", "worker session does not match the caller");
|
|
12239
12454
|
}
|
|
12455
|
+
const gate = this.view(task.data);
|
|
12456
|
+
if (gate.ok) {
|
|
12457
|
+
const writeGates = (task.data.policy?.requirements ?? []).filter((requirement) => requirement.before === "write" && gate.data.requirements.some((evaluation) => evaluation.requirementId === requirement.id && (evaluation.status === "unsatisfied" || evaluation.status === "unavailable")));
|
|
12458
|
+
if (writeGates.length)
|
|
12459
|
+
return failure("requirements_unsatisfied", "writer ownership is gated by unsatisfied requirements; record their evidence or an approved limitation waiver first", { requirementIds: writeGates.map((requirement) => requirement.id) });
|
|
12460
|
+
}
|
|
12240
12461
|
const owner = {
|
|
12241
12462
|
taskId: task.data.id,
|
|
12242
12463
|
workerId: helperId,
|
|
@@ -12248,7 +12469,7 @@ class WorkitCore {
|
|
|
12248
12469
|
};
|
|
12249
12470
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
12250
12471
|
taskId: task.data.id,
|
|
12251
|
-
|
|
12472
|
+
expectedRevision: input.expectedRevision,
|
|
12252
12473
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
12253
12474
|
now: trustedNow(this.context),
|
|
12254
12475
|
workspace: (current, mutation) => success(mutation.revision, mutation.revision, {
|
|
@@ -12279,7 +12500,7 @@ class WorkitCore {
|
|
|
12279
12500
|
}
|
|
12280
12501
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
12281
12502
|
taskId: task.data.id,
|
|
12282
|
-
|
|
12503
|
+
expectedRevision: input.expectedRevision,
|
|
12283
12504
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
12284
12505
|
now: trustedNow(this.context),
|
|
12285
12506
|
workspace: (currentWorkspace, mutation) => success(mutation.revision, mutation.revision, { ...currentWorkspace, writer: null }),
|
|
@@ -12528,7 +12749,15 @@ class WorkitCore {
|
|
|
12528
12749
|
if (seen.has(observation.workerId))
|
|
12529
12750
|
return failure("invalid_input", "worker observations must be unique");
|
|
12530
12751
|
seen.add(observation.workerId);
|
|
12531
|
-
|
|
12752
|
+
const freshTask = this.store.readTask(view.task.id);
|
|
12753
|
+
const freshWorkspace = this.store.readWorkspace();
|
|
12754
|
+
if (!freshTask.ok)
|
|
12755
|
+
return freshTask;
|
|
12756
|
+
if (!freshWorkspace.ok)
|
|
12757
|
+
return freshWorkspace;
|
|
12758
|
+
if (!freshWorkspace.data)
|
|
12759
|
+
return failure("not_found", "workspace not found");
|
|
12760
|
+
if (observation.taskId !== view.task.id || observation.expectedRevision !== freshTask.data.revision || observation.expectedWorkspaceRevision !== freshWorkspace.data.revision)
|
|
12532
12761
|
return failure("revision_conflict", "worker observation is stale");
|
|
12533
12762
|
if (!view.task.workers.some((entry) => entry.id === observation.workerId))
|
|
12534
12763
|
return failure("permission_denied", "worker observation is not assigned");
|
|
@@ -12614,19 +12843,26 @@ class WorkitCore {
|
|
|
12614
12843
|
return failure("permission_denied", "imported resume requires native destination approval");
|
|
12615
12844
|
resumeCandidate = current.data.candidate;
|
|
12616
12845
|
}
|
|
12617
|
-
const blocker = this.activeWorkerBlocker(task.data, workspace.data);
|
|
12846
|
+
const blocker = status === "paused" ? workspace.data.writer ? failure("recovery_required", "writer ownership must be released first") : null : this.activeWorkerBlocker(task.data, workspace.data);
|
|
12618
12847
|
if (blocker)
|
|
12619
12848
|
return blocker;
|
|
12849
|
+
let pauseCandidate = null;
|
|
12850
|
+
if (status === "paused") {
|
|
12851
|
+
const captured = captureCandidate(this.store.root, task.data.intent.data.scope, environment());
|
|
12852
|
+
if (!captured.ok)
|
|
12853
|
+
return captured;
|
|
12854
|
+
pauseCandidate = captured.data;
|
|
12855
|
+
}
|
|
12620
12856
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
12621
12857
|
taskId: task.data.id,
|
|
12622
|
-
|
|
12858
|
+
expectedRevision: input.expectedRevision,
|
|
12623
12859
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
12624
12860
|
now: trustedNow(this.context),
|
|
12625
12861
|
workspace: (workspace, context) => success(context.revision, context.revision, workspace),
|
|
12626
12862
|
task: (current, context) => success(context.revision, null, {
|
|
12627
12863
|
...current,
|
|
12628
12864
|
status,
|
|
12629
|
-
candidates: resumeCandidate && !current.candidates.some((candidate) => candidate.id === resumeCandidate.id) ? [...current.candidates, resumeCandidate] : current.candidates,
|
|
12865
|
+
candidates: (resumeCandidate ?? pauseCandidate) && !current.candidates.some((candidate) => candidate.id === (resumeCandidate ?? pauseCandidate).id) ? [...current.candidates, resumeCandidate ?? pauseCandidate] : current.candidates,
|
|
12630
12866
|
progress: current.progress,
|
|
12631
12867
|
pauseReason: status === "paused" ? input.reason ?? null : null
|
|
12632
12868
|
})
|
|
@@ -12664,12 +12900,13 @@ class WorkitCore {
|
|
|
12664
12900
|
return workspace;
|
|
12665
12901
|
if (!workspace.data)
|
|
12666
12902
|
return failure("not_found", "workspace not found");
|
|
12667
|
-
|
|
12668
|
-
|
|
12903
|
+
const revisionBlocker = this.activeWorkerBlocker(task.data, workspace.data);
|
|
12904
|
+
if (revisionBlocker)
|
|
12905
|
+
return revisionBlocker;
|
|
12669
12906
|
this.fillRevisions(input, task.data, workspace.data);
|
|
12670
12907
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
12671
12908
|
taskId: task.data.id,
|
|
12672
|
-
|
|
12909
|
+
expectedRevision: input.expectedRevision,
|
|
12673
12910
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
12674
12911
|
now: trustedNow(this.context),
|
|
12675
12912
|
workspace: (workspace, context) => success(context.revision, context.revision, workspace),
|
|
@@ -12725,7 +12962,7 @@ class WorkitCore {
|
|
|
12725
12962
|
return closure;
|
|
12726
12963
|
const changed = this.store.mutateTaskAndWorkspace({
|
|
12727
12964
|
taskId: task.data.id,
|
|
12728
|
-
|
|
12965
|
+
expectedRevision: input.expectedRevision,
|
|
12729
12966
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
12730
12967
|
now: trustedNow(this.context),
|
|
12731
12968
|
workspace: (value, context) => success(context.revision, context.revision, value),
|
|
@@ -12850,6 +13087,8 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
12850
13087
|
if (task.data.status === "paused" && (input.state === "running" || input.state === "cancelling"))
|
|
12851
13088
|
return failure("invalid_transition", "paused task cannot run a worker");
|
|
12852
13089
|
const notStarted = input.dispatch === true;
|
|
13090
|
+
if (notStarted && entry.data.state === "stopped" && input.session === null)
|
|
13091
|
+
return success(task.data.revision, workspace.data.revision, entry);
|
|
12853
13092
|
if (notStarted && (input.state !== "stopped" || input.session !== null))
|
|
12854
13093
|
return failure("invalid_input", "a never-dispatched worker stops with no session");
|
|
12855
13094
|
if (notStarted && entry.data.session !== null)
|
|
@@ -12881,7 +13120,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
12881
13120
|
return success(task.data.revision, workspace.data.revision, entry);
|
|
12882
13121
|
const changed = input.store.mutateTaskAndWorkspace({
|
|
12883
13122
|
taskId: task.data.id,
|
|
12884
|
-
|
|
13123
|
+
expectedRevision: input.expectedRevision,
|
|
12885
13124
|
expectedWorkspaceRevision: input.expectedWorkspaceRevision,
|
|
12886
13125
|
now: input.now,
|
|
12887
13126
|
workspace: (current, mutation) => success(mutation.revision, mutation.revision, {
|
|
@@ -12920,90 +13159,22 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
12920
13159
|
workerId: null,
|
|
12921
13160
|
receipts: []
|
|
12922
13161
|
}), portableTask = (task) => {
|
|
12923
|
-
const
|
|
12924
|
-
|
|
12925
|
-
|
|
12926
|
-
|
|
12927
|
-
|
|
12928
|
-
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
|
|
12933
|
-
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
];
|
|
12937
|
-
for (const entry of entries)
|
|
12938
|
-
entry.provenance = portableProvenance(entry.provenance);
|
|
12939
|
-
for (const worker of clone.workers)
|
|
12940
|
-
worker.data.session = null;
|
|
12941
|
-
clone.intent = {
|
|
12942
|
-
...clone.intent,
|
|
12943
|
-
data: { ...clone.intent.data, authorityRefs: portableRefs(clone.intent.data.authorityRefs) }
|
|
12944
|
-
};
|
|
12945
|
-
clone.constraints = clone.constraints.flatMap((constraint) => {
|
|
12946
|
-
const source = portableRef(constraint.source);
|
|
12947
|
-
return source ? [
|
|
12948
|
-
{
|
|
12949
|
-
...constraint,
|
|
12950
|
-
source,
|
|
12951
|
-
requires: constraint.requires.map((requirement) => ({
|
|
12952
|
-
...requirement,
|
|
12953
|
-
refs: portableRefs(requirement.refs)
|
|
12954
|
-
}))
|
|
12955
|
-
}
|
|
12956
|
-
] : [];
|
|
12957
|
-
});
|
|
12958
|
-
clone.assessments = clone.assessments.map((entry) => ({
|
|
12959
|
-
...entry,
|
|
12960
|
-
data: {
|
|
12961
|
-
...entry.data,
|
|
12962
|
-
facts: entry.data.facts.map(portableFact),
|
|
12963
|
-
signals: Object.fromEntries(Object.entries(entry.data.signals).map(([name, signal]) => [name, portableSignal(signal)])),
|
|
12964
|
-
consequences: entry.data.consequences.map((consequence) => ({
|
|
12965
|
-
...consequence,
|
|
12966
|
-
fact: portableFact(consequence.fact)
|
|
12967
|
-
})),
|
|
12968
|
-
verification: entry.data.verification.map((verification) => ({
|
|
12969
|
-
...verification,
|
|
12970
|
-
availableChecks: portableRefs(verification.availableChecks)
|
|
12971
|
-
}))
|
|
12972
|
-
}
|
|
12973
|
-
}));
|
|
12974
|
-
clone.progress = {
|
|
12975
|
-
...clone.progress,
|
|
12976
|
-
blockers: clone.progress.blockers.map((blocker) => ({
|
|
12977
|
-
...blocker,
|
|
12978
|
-
refs: portableRefs(blocker.refs)
|
|
12979
|
-
}))
|
|
13162
|
+
const stripped = rewriteRecordRefs(task, taskRecordSchema, portableRef);
|
|
13163
|
+
if (typeof stripped !== "object" || stripped === null || Array.isArray(stripped))
|
|
13164
|
+
throw new TypeError("portable task rewrite produced a non-record");
|
|
13165
|
+
const clone = structuredClone(stripped);
|
|
13166
|
+
const demote = (facts, signals, consequences) => {
|
|
13167
|
+
for (const fact of facts)
|
|
13168
|
+
Object.assign(fact, portableFact(fact));
|
|
13169
|
+
for (const name of Object.keys(signals)) {
|
|
13170
|
+
const signal = signals[name];
|
|
13171
|
+
Object.assign(signal, portableSignal(signal));
|
|
13172
|
+
}
|
|
13173
|
+
for (const consequence of consequences)
|
|
13174
|
+
Object.assign(consequence.fact, portableFact(consequence.fact));
|
|
12980
13175
|
};
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
data: {
|
|
12984
|
-
...entry.data,
|
|
12985
|
-
refs: portableRefs(entry.data.refs),
|
|
12986
|
-
reviewContext: portableRef(entry.data.reviewContext)
|
|
12987
|
-
}
|
|
12988
|
-
}));
|
|
12989
|
-
clone.decisions = clone.decisions.map((entry) => ({
|
|
12990
|
-
...entry,
|
|
12991
|
-
data: {
|
|
12992
|
-
...entry.data,
|
|
12993
|
-
consumption: entry.data.consumption ? portableRef(entry.data.consumption.actionRef) ? {
|
|
12994
|
-
...entry.data.consumption,
|
|
12995
|
-
actionRef: portableRef(entry.data.consumption.actionRef)
|
|
12996
|
-
} : null : null,
|
|
12997
|
-
binding: {
|
|
12998
|
-
...entry.data.binding,
|
|
12999
|
-
contentRefs: portableRefs(entry.data.binding.contentRefs)
|
|
13000
|
-
}
|
|
13001
|
-
}
|
|
13002
|
-
}));
|
|
13003
|
-
clone.findings = clone.findings.map((entry) => ({
|
|
13004
|
-
...entry,
|
|
13005
|
-
data: { ...entry.data, refs: portableRefs(entry.data.refs) }
|
|
13006
|
-
}));
|
|
13176
|
+
for (const entry of clone.assessments)
|
|
13177
|
+
demote(entry.data.facts, entry.data.signals, entry.data.consequences);
|
|
13007
13178
|
clone.candidates = [];
|
|
13008
13179
|
return clone;
|
|
13009
13180
|
}, importedTask = (source, bundle, destinationWorkspaceId, context, timestamp) => {
|
|
@@ -13027,15 +13198,13 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
13027
13198
|
allocate(entry.id);
|
|
13028
13199
|
const fresh = (id) => allocate(id);
|
|
13029
13200
|
const provenance = importedProvenance(context);
|
|
13201
|
+
const remap = (ref) => mapRef(ref, ids);
|
|
13030
13202
|
const intent = {
|
|
13031
13203
|
...source.intent,
|
|
13032
13204
|
id: fresh(source.intent.id),
|
|
13033
13205
|
recordedAt: timestamp,
|
|
13034
13206
|
provenance,
|
|
13035
|
-
data:
|
|
13036
|
-
...source.intent.data,
|
|
13037
|
-
authorityRefs: source.intent.data.authorityRefs.map((ref) => mapRef(ref, ids))
|
|
13038
|
-
}
|
|
13207
|
+
data: rewriteRecordRefs(source.intent.data, intentSchema, remap)
|
|
13039
13208
|
};
|
|
13040
13209
|
const assessments = source.assessments.map((entry) => {
|
|
13041
13210
|
const data = entry.data;
|
|
@@ -13044,28 +13213,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
13044
13213
|
id: fresh(entry.id),
|
|
13045
13214
|
recordedAt: timestamp,
|
|
13046
13215
|
provenance,
|
|
13047
|
-
data:
|
|
13048
|
-
...data,
|
|
13049
|
-
facts: data.facts.map((fact) => ({
|
|
13050
|
-
...fact,
|
|
13051
|
-
refs: fact.refs.map((ref) => mapRef(ref, ids))
|
|
13052
|
-
})),
|
|
13053
|
-
signals: Object.fromEntries(Object.entries(data.signals).map(([name, signal]) => [
|
|
13054
|
-
name,
|
|
13055
|
-
{ ...signal, refs: signal.refs.map((ref) => mapRef(ref, ids)) }
|
|
13056
|
-
])),
|
|
13057
|
-
consequences: data.consequences.map((consequence) => ({
|
|
13058
|
-
...consequence,
|
|
13059
|
-
fact: {
|
|
13060
|
-
...consequence.fact,
|
|
13061
|
-
refs: consequence.fact.refs.map((ref) => mapRef(ref, ids))
|
|
13062
|
-
}
|
|
13063
|
-
})),
|
|
13064
|
-
verification: data.verification.map((verification) => ({
|
|
13065
|
-
...verification,
|
|
13066
|
-
availableChecks: verification.availableChecks.map((ref) => mapRef(ref, ids))
|
|
13067
|
-
}))
|
|
13068
|
-
}
|
|
13216
|
+
data: rewriteRecordRefs(data, assessmentSchema, remap)
|
|
13069
13217
|
};
|
|
13070
13218
|
});
|
|
13071
13219
|
const evidence = source.evidence.map((entry) => ({
|
|
@@ -13073,11 +13221,7 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
13073
13221
|
id: fresh(entry.id),
|
|
13074
13222
|
recordedAt: timestamp,
|
|
13075
13223
|
provenance,
|
|
13076
|
-
data:
|
|
13077
|
-
...entry.data,
|
|
13078
|
-
refs: entry.data.refs.map((ref) => mapRef(ref, ids)),
|
|
13079
|
-
reviewContext: entry.data.reviewContext ? mapRef(entry.data.reviewContext, ids) : null
|
|
13080
|
-
}
|
|
13224
|
+
data: rewriteRecordRefs(entry.data, evidenceSchema, remap)
|
|
13081
13225
|
}));
|
|
13082
13226
|
const decisions = source.decisions.map((entry) => ({
|
|
13083
13227
|
...entry,
|
|
@@ -13085,21 +13229,23 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
13085
13229
|
recordedAt: timestamp,
|
|
13086
13230
|
provenance
|
|
13087
13231
|
}));
|
|
13088
|
-
const findings = source.findings.map((entry) =>
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13232
|
+
const findings = source.findings.map((entry) => {
|
|
13233
|
+
const data = rewriteRecordRefs(entry.data, findingSchema, remap);
|
|
13234
|
+
return {
|
|
13235
|
+
...entry,
|
|
13236
|
+
id: fresh(entry.id),
|
|
13237
|
+
recordedAt: timestamp,
|
|
13238
|
+
provenance,
|
|
13239
|
+
data: {
|
|
13240
|
+
...data,
|
|
13241
|
+
resolution: data.resolution ? {
|
|
13242
|
+
...data.resolution,
|
|
13243
|
+
evidenceIds: data.resolution.evidenceIds.map((id) => ids.get(id) ?? id),
|
|
13244
|
+
decisionIds: data.resolution.decisionIds.map((id) => ids.get(id) ?? id)
|
|
13245
|
+
} : null
|
|
13246
|
+
}
|
|
13247
|
+
};
|
|
13248
|
+
});
|
|
13103
13249
|
const workers = source.workers.map((entry) => ({
|
|
13104
13250
|
...entry,
|
|
13105
13251
|
id: fresh(entry.id),
|
|
@@ -13142,19 +13288,21 @@ var provenance = (context, kind = context.provenanceKind ?? "host_observed") =>
|
|
|
13142
13288
|
closure: null,
|
|
13143
13289
|
assessments,
|
|
13144
13290
|
evidence,
|
|
13145
|
-
decisions: decisions.map((entry) =>
|
|
13146
|
-
|
|
13147
|
-
|
|
13148
|
-
...entry
|
|
13149
|
-
|
|
13150
|
-
...
|
|
13151
|
-
|
|
13152
|
-
|
|
13153
|
-
|
|
13154
|
-
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13291
|
+
decisions: decisions.map((entry) => {
|
|
13292
|
+
const data = rewriteRecordRefs(entry.data, decisionSchema, remap);
|
|
13293
|
+
return {
|
|
13294
|
+
...entry,
|
|
13295
|
+
data: {
|
|
13296
|
+
...data,
|
|
13297
|
+
binding: {
|
|
13298
|
+
...data.binding,
|
|
13299
|
+
taskId: "",
|
|
13300
|
+
workspaceId: destinationWorkspaceId
|
|
13301
|
+
},
|
|
13302
|
+
consumption: null
|
|
13303
|
+
}
|
|
13304
|
+
};
|
|
13305
|
+
}),
|
|
13158
13306
|
...actionProgress ? { actionProgress } : {},
|
|
13159
13307
|
findings,
|
|
13160
13308
|
workers,
|
|
@@ -13196,6 +13344,9 @@ var init_core3 = __esm(() => {
|
|
|
13196
13344
|
init_task_context();
|
|
13197
13345
|
init_methods();
|
|
13198
13346
|
init_route_intent();
|
|
13347
|
+
init_branch();
|
|
13348
|
+
init_runtime_identity();
|
|
13349
|
+
init_authority();
|
|
13199
13350
|
init_authority();
|
|
13200
13351
|
init_external_action();
|
|
13201
13352
|
init_external_action();
|
|
@@ -13260,8 +13411,8 @@ var hostRef = (handle) => ({ kind: "host", host: "cursor", handle }), cursorCapa
|
|
|
13260
13411
|
refs: [hostRef("sessionStart"), hostRef("preCompact")]
|
|
13261
13412
|
}
|
|
13262
13413
|
];
|
|
13263
|
-
},
|
|
13264
|
-
if (!
|
|
13414
|
+
}, isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), eventNames, nonEmpty2 = (value) => typeof value === "string" && value.trim() !== "", parseCursorHookInput = (value) => {
|
|
13415
|
+
if (!isRecord2(value) || !eventNames.has(value.hook_event_name))
|
|
13265
13416
|
return { ok: false, error: "hook_event_name is required" };
|
|
13266
13417
|
const roots = value.workspace_roots;
|
|
13267
13418
|
if (!Array.isArray(roots) || roots.length !== 1 || !roots.every(nonEmpty2))
|
|
@@ -13399,7 +13550,7 @@ var hostRef = (handle) => ({ kind: "host", host: "cursor", handle }), cursorCapa
|
|
|
13399
13550
|
}, handleSubagentStop = () => ({}), handleCursorHook = (raw) => {
|
|
13400
13551
|
const parsed = parseCursorHookInput(raw);
|
|
13401
13552
|
if (!parsed.ok) {
|
|
13402
|
-
return
|
|
13553
|
+
return isRecord2(raw) && raw.hook_event_name === "sessionStart" ? {} : deny(parsed.error);
|
|
13403
13554
|
}
|
|
13404
13555
|
const input = parsed.data;
|
|
13405
13556
|
const root = realpathSync5(input.workspace_roots[0]);
|
|
@@ -13443,7 +13594,7 @@ ${invariantBootstrap()}${compact}
|
|
|
13443
13594
|
const output = handleCursorHook(input);
|
|
13444
13595
|
process.stdout.write(`${JSON.stringify(output)}
|
|
13445
13596
|
`);
|
|
13446
|
-
const event =
|
|
13597
|
+
const event = isRecord2(input) ? input.hook_event_name : undefined;
|
|
13447
13598
|
if (output.permission === "deny" && ["preToolUse", "beforeShellExecution", "subagentStart"].includes(String(event)))
|
|
13448
13599
|
process.exitCode = 2;
|
|
13449
13600
|
} catch {
|