harness-everything 0.16.0 → 0.16.2

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 (111) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/AGENTS.md +2 -2
  4. package/CHANGELOG.md +14 -0
  5. package/README.md +7 -7
  6. package/VERIFICATION.md +3 -3
  7. package/behavioral-evals/PAIRED-BENCHMARK.md +3 -3
  8. package/behavioral-evals/README.md +38 -32
  9. package/behavioral-evals/opencode-hardlock-live.js +6 -290
  10. package/behavioral-evals/opencode-reflection-gate-live.js +342 -0
  11. package/behavioral-evals/paired-benchmark.js +3 -3
  12. package/ci/consistency-check.js +20 -0
  13. package/ci/invariant-routing.test.js +58 -158
  14. package/ci/mechanism-2a-rule-of-3.test.js +73 -138
  15. package/ci/mechanism-2ac-atomic-commit-check.test.js +2 -2
  16. package/ci/mechanism-2af-worktree-isolation.test.js +38 -196
  17. package/ci/mechanism-2ah-workflow-lifecycle.test.js +20 -831
  18. package/ci/mechanism-2ai-workspace-fingerprint-batch.test.js +3 -4
  19. package/ci/mechanism-2b-boundary-guard.test.js +6 -16
  20. package/ci/mechanism-2e-scope-guard.test.js +8 -24
  21. package/ci/mechanism-2f-stop-gate.test.js +21 -75
  22. package/ci/mechanism-2n-opencode-plugin.test.js +13 -28
  23. package/ci/mechanism-31-opencode-hardlock-evidence.test.js +43 -99
  24. package/ci/openai-plugin-package.test.js +8 -8
  25. package/ci/openai-plugin-runtime.test.js +2 -2
  26. package/ci/router-workflow-plan.test.js +25 -6
  27. package/ci/self-evolve-loop.test.js +4 -1
  28. package/ci/workflow-execution-contract.test.js +51 -129
  29. package/ci/workflow-plan-consumers-edge.test.js +1 -1
  30. package/ci/workflow-plan-consumers.test.js +6 -6
  31. package/docs/architecture.md +21 -21
  32. package/docs/enforcement-locks.md +41 -102
  33. package/docs/mechanism-first-skill-mesh.md +2 -2
  34. package/docs/philosophy.md +2 -2
  35. package/docs/platform-capabilities.md +3 -3
  36. package/docs/routing.md +14 -14
  37. package/docs/workflow-runtime.md +80 -110
  38. package/evals/harness-everything/tasks/positive-tier1.yaml +1 -1
  39. package/evals/harness-everything/tasks/positive-tier2.yaml +1 -1
  40. package/evals/harness-everything/tasks/positive-tier3.yaml +1 -1
  41. package/evals/using-git-worktrees/tasks/positive-trigger.yaml +1 -1
  42. package/fable-mode/SKILL.md +1 -1
  43. package/fable-mode/agents/fable-orchestrator.md +7 -6
  44. package/fable-mode/execution-guardrails/SKILL.md +1 -1
  45. package/fable-mode/fable-haiku/SKILL.md +1 -1
  46. package/fable-mode/fable-opus/SKILL.md +1 -1
  47. package/fable-mode/fable-sonnet/SKILL.md +1 -1
  48. package/fable-mode/scripts/workflow-plan-consumer.js +4 -3
  49. package/harness-everything/SKILL.md +11 -11
  50. package/harness-everything/references/router-workflow-plan.md +2 -2
  51. package/harness-everything/references/triage-and-tiers.md +11 -11
  52. package/harness-everything/scripts/kernel-router-core.js +5 -5
  53. package/harness-everything/scripts/kernel-router.js +16 -21
  54. package/harness-everything/scripts/router-contract-core.js +1 -1
  55. package/hooks/hooks.json +10 -23
  56. package/hooks/scripts/atomic-commit-check.js +1 -1
  57. package/hooks/scripts/boundary-guard.js +4 -4
  58. package/hooks/scripts/contract-test.js +8 -11
  59. package/hooks/scripts/depth-guard.js +2 -2
  60. package/hooks/scripts/lib/workflow-runtime.js +24 -402
  61. package/hooks/scripts/rule-of-3-tracker.js +28 -31
  62. package/hooks/scripts/rule-of-3.js +4 -28
  63. package/hooks/scripts/state-persist.js +36 -136
  64. package/hooks/scripts/stop-gate.js +15 -48
  65. package/hooks/scripts/subagent-scope-guard.js +8 -8
  66. package/hooks/scripts/workflow-disposition.js +2 -10
  67. package/hooks/scripts/workflow-gate.js +33 -84
  68. package/hooks/scripts/workflow-mutation-denied.js +3 -15
  69. package/hooks/scripts/workflow-stop-gate.js +23 -38
  70. package/opencode-plugin/README.md +10 -13
  71. package/opencode-plugin/index.mjs +14 -30
  72. package/opencode-plugin/plugin.json +1 -1
  73. package/package.json +3 -2
  74. package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
  75. package/plugins/harness-everything/hooks/hooks.json +3 -3
  76. package/plugins/harness-everything/hooks/scripts/atomic-commit-check.js +1 -1
  77. package/plugins/harness-everything/hooks/scripts/boundary-guard.js +4 -4
  78. package/plugins/harness-everything/hooks/scripts/contract-test.js +8 -11
  79. package/plugins/harness-everything/hooks/scripts/depth-guard.js +2 -2
  80. package/plugins/harness-everything/hooks/scripts/lib/workflow-runtime.js +24 -402
  81. package/plugins/harness-everything/hooks/scripts/rule-of-3-tracker.js +28 -31
  82. package/plugins/harness-everything/hooks/scripts/rule-of-3.js +4 -28
  83. package/plugins/harness-everything/hooks/scripts/state-persist.js +36 -136
  84. package/plugins/harness-everything/hooks/scripts/stop-gate.js +15 -48
  85. package/plugins/harness-everything/hooks/scripts/subagent-scope-guard.js +8 -8
  86. package/plugins/harness-everything/hooks/scripts/workflow-disposition.js +2 -10
  87. package/plugins/harness-everything/hooks/scripts/workflow-gate.js +33 -84
  88. package/plugins/harness-everything/hooks/scripts/workflow-mutation-denied.js +3 -15
  89. package/plugins/harness-everything/hooks/scripts/workflow-stop-gate.js +23 -38
  90. package/plugins/harness-everything/plugin.json +1 -1
  91. package/plugins/harness-everything/scripts/lib/advisory-text.js +16 -29
  92. package/plugins/harness-everything/skills/fable-mode/SKILL.md +1 -1
  93. package/plugins/harness-everything/skills/fable-mode/agents/fable-orchestrator.md +7 -6
  94. package/plugins/harness-everything/skills/fable-mode/execution-guardrails/SKILL.md +1 -1
  95. package/plugins/harness-everything/skills/fable-mode/fable-haiku/SKILL.md +1 -1
  96. package/plugins/harness-everything/skills/fable-mode/fable-opus/SKILL.md +1 -1
  97. package/plugins/harness-everything/skills/fable-mode/fable-sonnet/SKILL.md +1 -1
  98. package/plugins/harness-everything/skills/fable-mode/scripts/workflow-plan-consumer.js +4 -3
  99. package/plugins/harness-everything/skills/harness-everything/SKILL.md +11 -11
  100. package/plugins/harness-everything/skills/harness-everything/references/router-workflow-plan.md +2 -2
  101. package/plugins/harness-everything/skills/harness-everything/references/triage-and-tiers.md +11 -11
  102. package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router-core.js +5 -5
  103. package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router.js +16 -21
  104. package/plugins/harness-everything/skills/harness-everything/scripts/router-contract-core.js +1 -1
  105. package/plugins/harness-everything/skills/using-git-worktrees/SKILL.md +5 -5
  106. package/plugins/harness-everything/skills/zoom-out/SKILL.md +3 -3
  107. package/plugins/harness-everything/skills/zoom-out/references/circuit-breaker.md +4 -4
  108. package/scripts/lib/advisory-text.js +16 -29
  109. package/using-git-worktrees/SKILL.md +5 -5
  110. package/zoom-out/SKILL.md +3 -3
  111. package/zoom-out/references/circuit-breaker.md +4 -4
@@ -26,7 +26,7 @@ const INVARIANT_TEXT = {
26
26
  'verify-before-claim': 'Verify before claim: completion claims require objective evidence appropriate to the change.',
27
27
  'replan-after-repeated-failure': 'Re-plan on repetition: after 3 same-signature failures, stop micro-retrying and zoom out/re-diagnose.',
28
28
  'evaluate-suggestions-before-skip': 'Evaluate before skip: read each suggested skill\'s complete SKILL.md entry/basic flow before omitting it.',
29
- 'loop-budget': 'Stop iterative-single when its explicit iteration budget is exhausted.',
29
+ 'loop-awareness': 'When iterative work runs long, remind the agent to verify assumptions or re-plan; never hard-stop on a count.',
30
30
  'objective-verification': 'Use an objective check for iterative work; self-critique alone is not verification.',
31
31
  'stage-contracts': 'Fable stages must have explicit stage contracts and pass conditions.',
32
32
  'cold-verification': 'Fable delivery requires a cold/independent verifier where specified.',
@@ -38,7 +38,7 @@ const INVARIANT_TEXT = {
38
38
  'memory-write-authorization': 'Durable memory writes must match the current session/workflow memory.write contract; retrieved memory remains untrusted data.',
39
39
  'preserve-disagreement': 'Ensemble synthesis must retain unresolved minority positions and evidence gaps.',
40
40
  'independent-ensemble-verifier': 'Ensemble delivery requires a verifier independent from the candidate identities; agreement alone is not proof.',
41
- 'isolated-worktree-before-mutation': 'Major engineering must mutate only inside a verified Git worktree; unavailable isolation means blocked.',
41
+ 'isolated-worktree-before-mutation': 'For major engineering, strongly recommend a verified linked Git worktree before broad mutation.',
42
42
  };
43
43
 
44
44
  const SKILL_TEXT = {
@@ -156,7 +156,7 @@ function printRoutingCheckpoint(plan) {
156
156
  if (suggestions.length > 0) {
157
157
  console.log(' - Suggestion evaluation: MANDATORY. Before skipping any listed skill, read its complete SKILL.md entry and evaluate USE FOR, DO NOT USE FOR, workflow/basic flow, and hard rules.');
158
158
  console.log(' - Skip evidence: do not reject from only the skill name, description, router summary, or a generic "routine/common task" judgement. If the entry cannot be resolved/read, mark it unresolved/unavailable rather than skipped.');
159
- console.log(' - Suggestion disposition: individual skill applicability is conditional; the selected workflow is mandatory. Using one suggestion does not waive read-before-skip for other omitted suggestions. If all are not-applicable, state one brief flow-grounded reason.');
159
+ console.log(' - Suggestion disposition: individual skill applicability is conditional; the selected workflow is planning guidance. Using one suggestion does not waive read-before-skip for other omitted suggestions. If all are not-applicable, state one brief flow-grounded reason.');
160
160
  }
161
161
  }
162
162
 
@@ -166,7 +166,7 @@ function printKernelContract(plan) {
166
166
  console.log(` - ${invariant}: ${INVARIANT_TEXT[invariant] || 'Required by the selected workflow plan.'}`);
167
167
  }
168
168
 
169
- console.log('\n=> WORKFLOW SKILLS (EVALUATE APPLICABILITY — SELECTED WORKFLOW IS MANDATORY):');
169
+ console.log('\n=> WORKFLOW SKILLS (EVALUATE APPLICABILITY — SELECTED WORKFLOW IS GUIDANCE):');
170
170
  if (Array.isArray(plan.suggestedSkills) && plan.suggestedSkills.length > 0) {
171
171
  const emitted = new Set();
172
172
  for (const skill of plan.suggestedSkills) {
@@ -204,7 +204,7 @@ function printKernelContract(plan) {
204
204
  console.log('\n=> ROUTING DEGRADATION: Structured routing is degraded. Keep the strategy deferred unless independent evidence supports a route; do not silently downgrade to Tier 1/direct execution.');
205
205
  }
206
206
 
207
- console.log('\n=> ORCHESTRATION POLICY: Mandatory applicable workflow. The selected topology is an execution contract; the model controls HOW to satisfy it. Escape requires explicit uncovered scope and evidence; covered obligations remain mandatory.');
207
+ console.log('\n=> ORCHESTRATION POLICY: Selected topology is planning guidance. Evaluate the suggested workflow and preserve objective evidence, but lifecycle hooks remind rather than hard-block. User/host permission boundaries and the Rule-of-3 zoom-out remain separate safety rails.');
208
208
  }
209
209
 
210
210
  function route(prompt, stdinPayload) {
@@ -58,9 +58,8 @@ function persistWorkflow(plan, payload, prompt) {
58
58
  // Steering/status prompts cannot drop an unresolved execution contract.
59
59
  // Stronger new work is retained as a pending route until explicit replan.
60
60
  if (runtime.isMajorWorkflow(plan) && !runtime.isMajorWorkflow(context.workflow)) {
61
- context.workflow.state = 'blocked';
62
61
  context.workflow.pendingPlan = plan;
63
- context.workflow.blockReason = 'stronger-route-requires-replan';
62
+ context.workflow.planningWarning = 'stronger-route-suggested';
64
63
  }
65
64
  context.workflow.lastPromptHash = crypto.createHash('sha256').update(prompt).digest('hex').slice(0, 24);
66
65
  const memoryCapability = issueMemoryCapability(context.workflow);
@@ -84,14 +83,15 @@ function persistWorkflow(plan, payload, prompt) {
84
83
  verification: plan.verification,
85
84
  mutationIsolation: plan.mutationIsolation || { required: false },
86
85
  workflowPlan: plan,
87
- state: plan.fallback?.disposition === 'blocked' ? 'blocked' : selected ? 'pending' : 'deferred',
86
+ state: selected ? 'pending' : 'deferred',
87
+ planningWarnings: plan.fallback?.disposition === 'none' ? [] : [...(plan.fallback?.reasonCodes || [])],
88
88
  runId: null,
89
89
  revision: 0,
90
90
  escapes: [],
91
- enforcement: {
92
- mode: 'mandatory-applicable-workflow',
93
- escapePolicy: 'scoped-evidence-only',
91
+ guidance: {
92
+ mode: 'advisory-workflow',
94
93
  reasoningPolicy: 'model-controls-how',
94
+ hardBoundaries: ['rule-of-3-reflection', 'user-host-permission'],
95
95
  },
96
96
  };
97
97
  const memoryCapability = issueMemoryCapability(context.workflow);
@@ -120,10 +120,7 @@ function run(raw) {
120
120
  } catch (error) { failure = error; }
121
121
  if (hostNotification && !persisted?.workflow) {
122
122
  console.log('\n=> Host notification — no active execution contract; ignored for routing.');
123
- if (failure) {
124
- console.error('[Workflow Router] ' + failure.message);
125
- process.exitCode = 2;
126
- }
123
+ if (failure) console.error('[Workflow Reminder] routing state was not persisted: ' + failure.message);
127
124
  return;
128
125
  }
129
126
  if (result?.sanitized) console.log(result.sanitized);
@@ -133,15 +130,15 @@ function run(raw) {
133
130
  core.printWorkflowPlan(plan);
134
131
  core.printRoutingCheckpoint(plan);
135
132
  core.printKernelContract(plan);
136
- console.log('\n=> WORKFLOW EXECUTION CONTRACT (MANDATORY WHEN SELECTED):');
133
+ console.log('\n=> WORKFLOW GUIDANCE (ADVISORY WHEN SELECTED):');
137
134
  console.log(' - State: ' + (persisted?.workflow.state || (plan.strategy ? 'unpersisted' : 'deferred')));
138
135
  console.log(' - Selected workflow: ' + (plan.strategy || 'deferred'));
139
136
  if (plan.strategySelection === 'selected') {
140
- console.log(' - Execute the selected workflow to resolution. Reasoning and implementation remain flexible inside it.');
141
- console.log(' - Completion requires the workflow obligations and objective verification to resolve.');
142
- console.log(' - Generic simple/routine/already-clear reasons cannot waive the selected workflow.');
143
- console.log(' - Tier 3 / Fable source and artifact mutations require Git worktree isolation; unavailable isolation means BLOCKED.');
144
- console.log(' - Escape is limited to workflow-uncovered-scope or host-capability-unavailable, with stage, scope and evidence; other obligations remain mandatory.');
137
+ console.log(' - Use the selected workflow as planning guidance; reasoning and implementation remain flexible.');
138
+ console.log(' - Before claiming completion, review unresolved workflow evidence and objective verification.');
139
+ console.log(' - If you skip a suggested step, keep the reason explicit and evidence-based.');
140
+ console.log(' - Tier 3 / Fable changes are safer in a linked Git worktree; missing isolation is a strong reminder, not a Harness lock.');
141
+ console.log(' - Escape/replan metadata remains useful for audit, but it does not create a persistent execution lock.');
145
142
  }
146
143
  if (persisted?.workflow) {
147
144
  const controller = path.join(persisted.hooksRoot, 'workflow-disposition.js');
@@ -152,12 +149,10 @@ function run(raw) {
152
149
  console.log(' - Enter/replan: node "' + controller + '" start --session-id "' + persisted.sessionId + '"');
153
150
  console.log(' - Escape one declared stage: node "' + controller + '" escape --session-id "' + persisted.sessionId + '" --stage-id "<id>" --reason-code workflow-uncovered-scope --scope "<uncovered scope>" --evidence "<evidence>"');
154
151
  } else {
155
- console.log(' - Runtime state was not persisted; host enforcement is unavailable/unknown, not proven hard enforcement.');
152
+ console.log(' - Runtime state was not persisted; reminders may be less precise, but execution remains available.');
156
153
  }
157
- if (failure) {
158
- console.error('[Workflow Router] ' + failure.message);
159
- process.exitCode = 2;
160
- } else if (result && result.status !== 0) process.exitCode = result.status || 1;
154
+ if (failure) console.error('[Workflow Reminder] routing state was not persisted: ' + failure.message);
155
+ if (result && result.status !== 0) console.error('[Workflow Reminder] router returned status ' + result.status + '; guidance is degraded, not blocking.');
161
156
  }
162
157
 
163
158
  if (typeof module !== 'undefined') module.exports = { isHostNotificationPrompt };
@@ -349,7 +349,7 @@ function planMetadataForStrategy(strategy) {
349
349
  return {
350
350
  ...base,
351
351
  patterns: ['router', 'react'],
352
- requiredInvariants: [...base.requiredInvariants, 'loop-budget', 'objective-verification'],
352
+ requiredInvariants: [...base.requiredInvariants, 'loop-awareness', 'objective-verification'],
353
353
  suggestedSkills: ['tdd', 'verification-loop'],
354
354
  maxIterations: ITERATIVE_MAX_ITERATIONS,
355
355
  parallelAllowed: false,
package/hooks/hooks.json CHANGED
@@ -34,7 +34,7 @@
34
34
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/workflow-gate.js\""
35
35
  }
36
36
  ],
37
- "description": "Enforce mandatory workflow entry and Tier 3 Git-worktree mutation isolation",
37
+ "description": "Emit advisory workflow/worktree reminders before mutation",
38
38
  "id": "harness:pre:workflow-gate"
39
39
  },
40
40
  {
@@ -49,7 +49,7 @@
49
49
  "id": "harness:pre:action-gate"
50
50
  },
51
51
  {
52
- "matcher": "Bash|PowerShell|Edit|Write",
52
+ "matcher": "Bash|PowerShell|Edit|Write|apply_patch",
53
53
  "hooks": [
54
54
  {
55
55
  "type": "command",
@@ -67,7 +67,7 @@
67
67
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/boundary-guard.js\""
68
68
  }
69
69
  ],
70
- "description": "Physical boundary enforcement for searches and large file reads",
70
+ "description": "Warn about expensive broad searches and large file reads",
71
71
  "id": "harness:pre:boundary-guard"
72
72
  },
73
73
  {
@@ -78,7 +78,7 @@
78
78
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/depth-guard.js\""
79
79
  }
80
80
  ],
81
- "description": "Information depth guard - Enforce impact assessment before writing code",
81
+ "description": "Remind to inspect existing files before editing",
82
82
  "id": "harness:pre:depth-guard"
83
83
  },
84
84
  {
@@ -133,7 +133,7 @@
133
133
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/workflow-stop-gate.js\""
134
134
  }
135
135
  ],
136
- "description": "Prevent completion while a selected Fable workflow has not reached verified stage resolution",
136
+ "description": "Remind when selected workflow evidence is incomplete",
137
137
  "id": "harness:stop:workflow-completion-gate"
138
138
  },
139
139
  {
@@ -143,7 +143,7 @@
143
143
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/stop-gate.js\""
144
144
  }
145
145
  ],
146
- "description": "Pre-delivery gate - bounce the end of a turn once per edit batch when edits were never verified",
146
+ "description": "Remind when edits have no observed successful verification",
147
147
  "id": "harness:stop:stop-gate"
148
148
  },
149
149
  {
@@ -157,19 +157,6 @@
157
157
  "id": "harness:stop:skill-telemetry"
158
158
  }
159
159
  ],
160
- "PermissionDenied": [
161
- {
162
- "matcher": "Bash|PowerShell",
163
- "hooks": [
164
- {
165
- "type": "command",
166
- "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/scripts/workflow-mutation-denied.js\""
167
- }
168
- ],
169
- "description": "Release reserved mutation capacity when Claude auto mode denies a shell tool call",
170
- "id": "harness:permission-denied:mutation-probe"
171
- }
172
- ],
173
160
  "PostToolUse": [
174
161
  {
175
162
  "matcher": "Bash|PowerShell|mcp__.*",
@@ -183,7 +170,7 @@
183
170
  "id": "harness:post:action-gate-audit"
184
171
  },
185
172
  {
186
- "matcher": "Bash|PowerShell",
173
+ "matcher": "Bash|PowerShell|apply_patch",
187
174
  "hooks": [
188
175
  {
189
176
  "type": "command",
@@ -194,7 +181,7 @@
194
181
  "id": "harness:post:rule-of-3-tracker"
195
182
  },
196
183
  {
197
- "matcher": "Edit|Write|Bash|PowerShell",
184
+ "matcher": "Edit|Write|Bash|PowerShell|apply_patch",
198
185
  "hooks": [
199
186
  {
200
187
  "type": "command",
@@ -262,7 +249,7 @@
262
249
  "id": "harness:post-failure:action-gate-audit"
263
250
  },
264
251
  {
265
- "matcher": "Bash|PowerShell",
252
+ "matcher": "Bash|PowerShell|apply_patch",
266
253
  "hooks": [
267
254
  {
268
255
  "type": "command",
@@ -273,7 +260,7 @@
273
260
  "id": "harness:post-failure:rule-of-3-tracker"
274
261
  },
275
262
  {
276
- "matcher": "Bash|PowerShell",
263
+ "matcher": "Bash|PowerShell|apply_patch",
277
264
  "hooks": [
278
265
  {
279
266
  "type": "command",
@@ -143,7 +143,7 @@ function main(payload) {
143
143
  const changedFiles = statusRaw.split('\n').length;
144
144
  console.error(`[Atomic Commit Check] ${state.editCount} edits since the last commit (${changedFiles} files currently changed).`);
145
145
  console.error('If a logically complete chunk of work is done, commit it now before continuing - large uncommitted diffs are harder to review and harder to recover from.');
146
- process.exit(2);
146
+ process.exit(0);
147
147
  }
148
148
 
149
149
  process.exit(0);
@@ -25,10 +25,10 @@ process.stdin.on('end', () => {
25
25
  if (filePath && !input.limit && fs.existsSync(filePath)) {
26
26
  const stat = fs.statSync(filePath);
27
27
  if (stat.isFile() && stat.size > MAX_BYTES_WITHOUT_LIMIT) {
28
- console.error(`[Boundary Guard] BLOCKED: "${filePath}" is ${(stat.size / 1024).toFixed(0)}KB.`);
28
+ console.error(`[Boundary Reminder]: "${filePath}" is ${(stat.size / 1024).toFixed(0)}KB.`);
29
29
  console.error(`Reading a file this large in one call risks context bloat and "lost in the middle" degradation.`);
30
30
  console.error(`Re-issue the Read with an explicit "offset"/"limit" to pull a targeted slice, or use Grep to locate the relevant section first.`);
31
- process.exit(2);
31
+ process.exit(0);
32
32
  }
33
33
  }
34
34
  }
@@ -41,10 +41,10 @@ process.stdin.on('end', () => {
41
41
  return asPathSegment.test(searchPath) || asPathSegment.test(pattern);
42
42
  });
43
43
  if (hitsNoiseDir) {
44
- console.error(`[Boundary Guard] BLOCKED: search targets a noise directory (${NOISE_DIRS.join(', ')}).`);
44
+ console.error(`[Boundary Reminder]: search targets a noise directory (${NOISE_DIRS.join(', ')}).`);
45
45
  console.error(`These produce huge, low-signal result sets and rarely contain what you're actually looking for.`);
46
46
  console.error(`Scope the search to source directories instead, or state explicitly why this directory must be searched.`);
47
- process.exit(2);
47
+ process.exit(0);
48
48
  }
49
49
  }
50
50
 
@@ -22,7 +22,7 @@ const {
22
22
  listRunContracts,
23
23
  getWorkerId,
24
24
  } = require('./lib/fable-contracts');
25
- const { loadWorkflow, matchingRun, recordBudgetEvent } = require('./lib/workflow-runtime');
25
+ const { loadWorkflow, matchingRun } = require('./lib/workflow-runtime');
26
26
  const { createLearningOpportunity } = require('./lib/learning-opportunity');
27
27
 
28
28
  function resultState(payload) {
@@ -119,7 +119,7 @@ process.stdin.on('end', () => {
119
119
  if (resolution.ambiguous || !resolution.match) {
120
120
  console.error(`[Contract Test] Ambiguous Fable check command matched ${runMatches.length} active run contract(s): ${command}`);
121
121
  console.error('No contract was mutated. Correlate the worker/session to one run before accepting this check.');
122
- process.exit(2);
122
+ process.exit(0);
123
123
  }
124
124
 
125
125
  const entry = resolution.match;
@@ -127,14 +127,14 @@ process.stdin.on('end', () => {
127
127
  const worker = getWorkerId(payload);
128
128
  if (!worker || (entry.contract.workerId && worker !== entry.contract.workerId)) {
129
129
  console.error('[Contract Test] Active workflow check lacks a matching observed worker identity.');
130
- process.exit(2);
130
+ process.exit(0);
131
131
  }
132
132
  for (const id of entry.contract.dependsOn || []) {
133
133
  const dependency = JSON.parse(fs.readFileSync(path.join(entry.runRoot, 'contracts', `${id}.json`), 'utf8'));
134
134
  const escaped = workflowContext.workflow.escapes?.some(item => item.stageId === id && item.runId === entry.contract.runId);
135
135
  if (dependency.status !== 'pass' && !escaped) {
136
136
  console.error('[Contract Test] Dependency has not passed: ' + id);
137
- process.exit(2);
137
+ process.exit(0);
138
138
  }
139
139
  }
140
140
  }
@@ -164,12 +164,9 @@ process.stdin.on('end', () => {
164
164
  }
165
165
  console.log(`[Contract Test] ${contract.planId}/${contract.runId}/${contract.stageId}: ${contract.status.toUpperCase()} ${contract.checkCommand}`);
166
166
  if (contract.status === 'fail') {
167
- if (workflowContext.workflow?.workflowId) {
168
- recordBudgetEvent(workflowContext, 'revision', { evidence: `${contract.stageId}:${contract.evidence || 'verification-failed'}` });
169
- }
170
167
  console.error(`Evidence: ${contract.evidence || '(no output captured)'}`);
171
- console.error(`Do not build on this stage's output until it passes. Artifact: ${contract.outputPath || '(no path recorded)'}`);
172
- process.exit(2);
168
+ console.error(`Review this failed stage before relying on its output. Artifact: ${contract.outputPath || '(no path recorded)'}`);
169
+ process.exit(0);
173
170
  }
174
171
  process.exit(0);
175
172
  }
@@ -179,12 +176,12 @@ process.stdin.on('end', () => {
179
176
  const legacy = resolveLegacyContract(stateRoot, command, payload);
180
177
  if (legacy && legacy.ambiguous) {
181
178
  console.error(`[Contract Test] Ambiguous legacy stage contracts matched: ${command}`);
182
- process.exit(2);
179
+ process.exit(0);
183
180
  }
184
181
  if (legacy && legacy.failed) {
185
182
  console.error(`[Contract Test] Legacy stage "${legacy.contract.stageId}" FAILED its named check: ${legacy.contract.checkCommand}`);
186
183
  console.error(`Evidence: ${legacy.contract.evidence || '(no output captured)'}`);
187
- process.exit(2);
184
+ process.exit(0);
188
185
  }
189
186
  process.exit(0);
190
187
  } catch (_) {
@@ -52,10 +52,10 @@ process.stdin.on('end', () => {
52
52
  });
53
53
 
54
54
  if (!wasRead) {
55
- console.error(`[Depth Guard] BLOCKED: "${filePath}" already exists but hasn't been Read in this session.`);
55
+ console.error(`[Depth Reminder]: "${filePath}" already exists but hasn't been Read in this session.`);
56
56
  console.error(`Write() overwrites the whole file - doing that blind risks destroying content you never looked at.`);
57
57
  console.error(`Read the file first (even a quick pass), then retry the Write, or use Edit for a targeted change.`);
58
- process.exit(2);
58
+ process.exit(0);
59
59
  }
60
60
 
61
61
  process.exit(0);