@brainervirus/workit-cli 1.0.8 → 1.0.9

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.
Files changed (2) hide show
  1. package/dist/index.js +69 -10
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -50965,7 +50965,7 @@ var workerReportSchema = object({
50965
50965
  }).strict();
50966
50966
  var workerSchema = object({
50967
50967
  assignment: assignmentSchema,
50968
- state: _enum(["assigned", "running", "cancelling", "stopped", "unknown"]),
50968
+ state: _enum(["assigned", "dispatching", "running", "cancelling", "stopped", "unknown"]),
50969
50969
  session: refSchema.nullable(),
50970
50970
  report: workerReportSchema.nullable()
50971
50971
  }).strict();
@@ -58945,6 +58945,52 @@ function evaluateClosure(requestedOutcome, view) {
58945
58945
  });
58946
58946
  }
58947
58947
 
58948
+ // packages/workit-core/src/core/methods.ts
58949
+ var METHODS = {
58950
+ "workit-challenge": { dimensions: ["challenge", "decisions"] },
58951
+ "workit-behavioral-tdd": { dimensions: ["testing"] },
58952
+ "workit-review": { dimensions: ["review"] },
58953
+ "workit-plan": { dimensions: ["artifacts", "continuity"] },
58954
+ "workit-implement": { dimensions: ["delegation"] },
58955
+ "workit-debug": { ruleIds: ["root-cause-investigation"] },
58956
+ "workit-handoff": { ruleIds: ["durable-handoff"] },
58957
+ "workit-deslop": { ruleIds: ["pre-pr-cleanup"] }
58958
+ };
58959
+ var methodMatches = (id, definition, requirement) => definition.dimensions?.includes(requirement.dimension) === true && !(id === "workit-review" && requirement.ruleId === "self-review") || definition.ruleIds?.includes(requirement.ruleId) === true;
58960
+ var assuranceFor = (id, definition, capabilities) => {
58961
+ const keys = new Set([
58962
+ id,
58963
+ ...definition.dimensions ?? [],
58964
+ ...definition.ruleIds ?? []
58965
+ ]);
58966
+ const matches = capabilities.filter((capability) => keys.has(capability.name) || keys.has(capability.surface));
58967
+ if (id === "workit-review" && matches.length === 0)
58968
+ return { assurance: "unavailable", reasons: ["independent review capability is unavailable"] };
58969
+ if (matches.some((capability) => capability.assurance === "unavailable"))
58970
+ return {
58971
+ assurance: "unavailable",
58972
+ reasons: matches.filter((capability) => capability.assurance === "unavailable").map((capability) => capability.reason)
58973
+ };
58974
+ if (matches.some((capability) => capability.assurance === "enforced"))
58975
+ return { assurance: "enforced", reasons: matches.map((capability) => capability.reason) };
58976
+ return { assurance: "agent_guided", reasons: matches.map((capability) => capability.reason) };
58977
+ };
58978
+ function selectMethods(policy, capabilities) {
58979
+ return Object.entries(METHODS).flatMap(([id, definition]) => {
58980
+ const requirements = policy.requirements.filter((requirement) => methodMatches(id, definition, requirement));
58981
+ if (requirements.length === 0)
58982
+ return [];
58983
+ const capability = assuranceFor(id, definition, capabilities);
58984
+ const reasons = [
58985
+ ...new Set(requirements.map((requirement) => requirement.reason)),
58986
+ ...capability.reasons
58987
+ ];
58988
+ if (capability.assurance === "unavailable")
58989
+ reasons.unshift("required capability is unavailable");
58990
+ return [{ id, reason: reasons.join("; "), assurance: capability.assurance }];
58991
+ });
58992
+ }
58993
+
58948
58994
  // packages/workit-core/src/core/task-context.ts
58949
58995
  function reconcileResume(view, observations = []) {
58950
58996
  if (observations.length > 0)
@@ -58954,7 +59000,7 @@ function reconcileResume(view, observations = []) {
58954
59000
  return candidate;
58955
59001
  const staleEvidenceIds = evaluateEvidence(view.task, candidate.data).filter((entry) => entry.status === "stale").map((entry) => entry.evidenceId);
58956
59002
  const blockers = [...view.task.progress.blockers];
58957
- if (view.task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(entry.data.state)))
59003
+ if (view.task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(entry.data.state)))
58958
59004
  blockers.push({
58959
59005
  reason: "worker state requires reconciliation",
58960
59006
  dependentAction: "resume",
@@ -59004,6 +59050,11 @@ function compactTaskContext(view) {
59004
59050
  digest: entry.data.digest,
59005
59051
  references: entry.data.binding.contentRefs.slice(0, 1).map(compactReference)
59006
59052
  }));
59053
+ const methods = view.task.policy ? selectMethods(view.task.policy, view.capabilities).map((method) => ({
59054
+ id: method.id,
59055
+ assurance: method.assurance,
59056
+ reason: compactText(method.reason, COMPACT_TEXT_BYTES) ?? ""
59057
+ })) : [];
59007
59058
  const gaps = Array.from(new Set([
59008
59059
  ...view.evidence.filter((entry) => entry.status === "stale").map((entry) => `stale evidence: ${entry.evidenceId}`),
59009
59060
  ...view.requirements.filter((entry) => entry.status !== "satisfied").map((entry) => entry.reason),
@@ -59013,15 +59064,18 @@ function compactTaskContext(view) {
59013
59064
  objective: compactText(view.task.intent.data.objective, COMPACT_TEXT_BYTES) ?? "",
59014
59065
  status: view.task.status,
59015
59066
  decisions,
59067
+ methods,
59016
59068
  gaps,
59017
59069
  nextAction: compactText(view.task.progress.nextAction, COMPACT_TEXT_BYTES)
59018
59070
  };
59019
59071
  let encoded = JSON.stringify(context);
59020
- while (compactBytes(encoded) > COMPACT_MAX_BYTES && (context.decisions.length || context.gaps.length)) {
59072
+ while (compactBytes(encoded) > COMPACT_MAX_BYTES && (context.decisions.length || context.methods.length || context.gaps.length)) {
59021
59073
  if (context.gaps.length)
59022
59074
  context.gaps.pop();
59023
- else
59075
+ else if (context.decisions.length)
59024
59076
  context.decisions.pop();
59077
+ else
59078
+ context.methods.pop();
59025
59079
  encoded = JSON.stringify(context);
59026
59080
  }
59027
59081
  if (compactBytes(encoded) > COMPACT_MAX_BYTES) {
@@ -59796,10 +59850,10 @@ var applyWorkerLifecycle = (input) => {
59796
59850
  const notStarted = input.dispatch === true;
59797
59851
  if (notStarted && (input.state !== "stopped" || input.session !== null))
59798
59852
  return failure("invalid_input", "a never-dispatched worker stops with no session");
59799
- if (notStarted && (entry.data.state === "stopped" || entry.data.state === "unknown"))
59800
- return failure("invalid_transition", "worker is no longer awaiting dispatch");
59801
- if (notStarted && (entry.data.session !== null || entry.data.state === "running"))
59853
+ if (notStarted && entry.data.session !== null)
59802
59854
  return failure("invalid_transition", "worker already has an observed session");
59855
+ if (notStarted && !["dispatching", "cancelling"].includes(entry.data.state))
59856
+ return failure("invalid_transition", "worker launch was not claimed");
59803
59857
  if ((input.state === "running" || input.state === "cancelling" || input.state === "stopped" && !notStarted) && !input.session)
59804
59858
  return failure("invalid_input", "running worker observations require a session");
59805
59859
  if (entry.data.session && !sameValue(entry.data.session, input.session))
@@ -60186,7 +60240,7 @@ class WorkitCore {
60186
60240
  activeWorkerBlocker(task, workspace) {
60187
60241
  if (workspace.writer)
60188
60242
  return failure("recovery_required", "writer ownership must be released first");
60189
- if (task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(entry.data.state)))
60243
+ if (task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(entry.data.state)))
60190
60244
  return failure("recovery_required", "worker state requires reconciliation");
60191
60245
  return null;
60192
60246
  }
@@ -60950,7 +61004,12 @@ class WorkitCore {
60950
61004
  return failure("invalid_transition", "worker is not awaiting dispatch");
60951
61005
  return success(mutation.revision, null, {
60952
61006
  ...current,
60953
- workers: current.workers.map((item) => item.id === input.workerId ? { ...item, recordedAt: mutation.now, provenance: attested.data } : item)
61007
+ workers: current.workers.map((item) => item.id === input.workerId ? {
61008
+ ...item,
61009
+ recordedAt: mutation.now,
61010
+ provenance: attested.data,
61011
+ data: { ...item.data, state: "dispatching" }
61012
+ } : item)
60954
61013
  });
60955
61014
  }
60956
61015
  });
@@ -61419,7 +61478,7 @@ class WorkitCore {
61419
61478
  const base = reconcileResume(effectiveView);
61420
61479
  if (!base.ok)
61421
61480
  return base;
61422
- const needsReconciliation = view.task.workers.some((entry) => ["running", "cancelling", "unknown"].includes(observedStates.get(entry.id) ?? entry.data.state));
61481
+ const needsReconciliation = view.task.workers.some((entry) => ["dispatching", "running", "cancelling", "unknown"].includes(observedStates.get(entry.id) ?? entry.data.state));
61423
61482
  const blockers = [...base.data.blockers];
61424
61483
  if (needsReconciliation && !blockers.some((entry) => entry.reason === "worker state requires reconciliation"))
61425
61484
  blockers.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brainervirus/workit-cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "private": false,
5
5
  "description": "Workit CLI — setup wizard, doctor, and task control for agentic coding workflows",
6
6
  "keywords": [
@@ -37,9 +37,9 @@
37
37
  "typecheck": "tsc --noEmit"
38
38
  },
39
39
  "dependencies": {
40
- "@brainervirus/workit-core": "^1.0.8",
41
- "@brainervirus/workit-cursor": "^1.0.8",
42
- "@brainervirus/workit-opencode": "^1.0.8",
40
+ "@brainervirus/workit-core": "^1.0.9",
41
+ "@brainervirus/workit-cursor": "^1.0.9",
42
+ "@brainervirus/workit-opencode": "^1.0.9",
43
43
  "@inkjs/ui": "2.0.0",
44
44
  "ink": "7.1.1",
45
45
  "react": "19.2.8"