harness-everything 0.15.0 → 0.16.1

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 (100) 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 +23 -0
  5. package/README.md +7 -7
  6. package/VERIFICATION.md +3 -3
  7. package/bin/cli.js +17 -0
  8. package/ci/invariant-routing.test.js +58 -158
  9. package/ci/mechanism-2a-rule-of-3.test.js +73 -138
  10. package/ci/mechanism-2ac-atomic-commit-check.test.js +2 -2
  11. package/ci/mechanism-2af-worktree-isolation.test.js +38 -196
  12. package/ci/mechanism-2ah-workflow-lifecycle.test.js +20 -831
  13. package/ci/mechanism-2ai-workspace-fingerprint-batch.test.js +3 -4
  14. package/ci/mechanism-2al-codex-hooks-compat.test.js +286 -0
  15. package/ci/mechanism-2b-boundary-guard.test.js +6 -16
  16. package/ci/mechanism-2e-scope-guard.test.js +8 -24
  17. package/ci/mechanism-2f-stop-gate.test.js +21 -75
  18. package/ci/mechanism-2n-opencode-plugin.test.js +13 -28
  19. package/ci/openai-plugin-package.test.js +8 -8
  20. package/ci/openai-plugin-runtime.test.js +2 -2
  21. package/ci/router-workflow-plan.test.js +6 -6
  22. package/ci/self-evolve-loop.test.js +4 -1
  23. package/ci/workflow-execution-contract.test.js +51 -129
  24. package/ci/workflow-plan-consumers-edge.test.js +1 -1
  25. package/ci/workflow-plan-consumers.test.js +6 -6
  26. package/docs/architecture.md +21 -21
  27. package/docs/enforcement-locks.md +41 -102
  28. package/docs/mechanism-first-skill-mesh.md +2 -2
  29. package/docs/philosophy.md +2 -2
  30. package/docs/platform-capabilities.md +19 -3
  31. package/docs/platform-compatibility.json +4 -4
  32. package/docs/routing.md +14 -14
  33. package/docs/workflow-runtime.md +80 -110
  34. package/evals/harness-everything/tasks/positive-tier1.yaml +1 -1
  35. package/evals/harness-everything/tasks/positive-tier2.yaml +1 -1
  36. package/evals/harness-everything/tasks/positive-tier3.yaml +1 -1
  37. package/evals/using-git-worktrees/tasks/positive-trigger.yaml +1 -1
  38. package/fable-mode/SKILL.md +1 -1
  39. package/fable-mode/execution-guardrails/SKILL.md +1 -1
  40. package/fable-mode/fable-haiku/SKILL.md +1 -1
  41. package/fable-mode/fable-opus/SKILL.md +1 -1
  42. package/fable-mode/fable-sonnet/SKILL.md +1 -1
  43. package/fable-mode/scripts/workflow-plan-consumer.js +4 -3
  44. package/harness-everything/SKILL.md +11 -11
  45. package/harness-everything/references/triage-and-tiers.md +11 -11
  46. package/harness-everything/scripts/kernel-router-core.js +5 -5
  47. package/harness-everything/scripts/kernel-router.js +15 -17
  48. package/harness-everything/scripts/router-contract-core.js +1 -1
  49. package/hooks/hooks.json +10 -23
  50. package/hooks/scripts/atomic-commit-check.js +1 -1
  51. package/hooks/scripts/boundary-guard.js +4 -4
  52. package/hooks/scripts/contract-test.js +8 -11
  53. package/hooks/scripts/depth-guard.js +2 -2
  54. package/hooks/scripts/lib/workflow-runtime.js +24 -402
  55. package/hooks/scripts/rule-of-3-tracker.js +28 -31
  56. package/hooks/scripts/rule-of-3.js +4 -28
  57. package/hooks/scripts/state-persist.js +36 -136
  58. package/hooks/scripts/stop-gate.js +15 -48
  59. package/hooks/scripts/subagent-scope-guard.js +8 -8
  60. package/hooks/scripts/workflow-disposition.js +2 -10
  61. package/hooks/scripts/workflow-gate.js +33 -84
  62. package/hooks/scripts/workflow-mutation-denied.js +3 -15
  63. package/hooks/scripts/workflow-stop-gate.js +23 -38
  64. package/opencode-plugin/README.md +9 -10
  65. package/opencode-plugin/index.mjs +14 -30
  66. package/opencode-plugin/plugin.json +1 -1
  67. package/package.json +4 -2
  68. package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
  69. package/plugins/harness-everything/hooks/hooks.json +3 -3
  70. package/plugins/harness-everything/hooks/scripts/atomic-commit-check.js +1 -1
  71. package/plugins/harness-everything/hooks/scripts/boundary-guard.js +4 -4
  72. package/plugins/harness-everything/hooks/scripts/contract-test.js +8 -11
  73. package/plugins/harness-everything/hooks/scripts/depth-guard.js +2 -2
  74. package/plugins/harness-everything/hooks/scripts/lib/workflow-runtime.js +24 -402
  75. package/plugins/harness-everything/hooks/scripts/rule-of-3-tracker.js +28 -31
  76. package/plugins/harness-everything/hooks/scripts/rule-of-3.js +4 -28
  77. package/plugins/harness-everything/hooks/scripts/state-persist.js +36 -136
  78. package/plugins/harness-everything/hooks/scripts/stop-gate.js +15 -48
  79. package/plugins/harness-everything/hooks/scripts/subagent-scope-guard.js +8 -8
  80. package/plugins/harness-everything/hooks/scripts/workflow-disposition.js +2 -10
  81. package/plugins/harness-everything/hooks/scripts/workflow-gate.js +33 -84
  82. package/plugins/harness-everything/hooks/scripts/workflow-mutation-denied.js +3 -15
  83. package/plugins/harness-everything/hooks/scripts/workflow-stop-gate.js +23 -38
  84. package/plugins/harness-everything/plugin.json +1 -1
  85. package/plugins/harness-everything/scripts/lib/advisory-text.js +16 -29
  86. package/plugins/harness-everything/skills/fable-mode/SKILL.md +1 -1
  87. package/plugins/harness-everything/skills/fable-mode/execution-guardrails/SKILL.md +1 -1
  88. package/plugins/harness-everything/skills/fable-mode/fable-haiku/SKILL.md +1 -1
  89. package/plugins/harness-everything/skills/fable-mode/fable-opus/SKILL.md +1 -1
  90. package/plugins/harness-everything/skills/fable-mode/fable-sonnet/SKILL.md +1 -1
  91. package/plugins/harness-everything/skills/fable-mode/scripts/workflow-plan-consumer.js +4 -3
  92. package/plugins/harness-everything/skills/harness-everything/SKILL.md +11 -11
  93. package/plugins/harness-everything/skills/harness-everything/references/triage-and-tiers.md +11 -11
  94. package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router-core.js +5 -5
  95. package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router.js +15 -17
  96. package/plugins/harness-everything/skills/harness-everything/scripts/router-contract-core.js +1 -1
  97. package/plugins/harness-everything/skills/using-git-worktrees/SKILL.md +5 -5
  98. package/scripts/codex-hooks-compat.js +521 -0
  99. package/scripts/lib/advisory-text.js +16 -29
  100. package/using-git-worktrees/SKILL.md +5 -5
@@ -1,133 +1,55 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
-
4
- const fs = require('fs');
5
- const os = require('os');
6
- const path = require('path');
7
- const { spawnSync } = require('child_process');
8
-
3
+ const fs = require('fs'), os = require('os'), path = require('path'), { spawnSync } = require('child_process');
9
4
  const ROOT = path.resolve(__dirname, '..');
10
- const { recordBudgetEvent, resetWorkflowBudget } = require(path.join(ROOT, 'hooks/scripts/lib/workflow-runtime.js'));
11
- let failed = 0;
12
-
13
- function check(condition, message) {
14
- if (condition) console.log(` PASS ${message}`);
15
- else { console.error(` FAIL ${message}`); failed++; }
16
- }
17
-
18
- function runNode(args, options = {}) {
19
- return spawnSync(process.execPath, args, { cwd: ROOT, encoding: 'utf8', ...options });
20
- }
21
-
22
- console.log('=== Workflow Execution Enforcement ===');
23
-
24
- for (const rel of [
25
- 'harness-everything/scripts/kernel-router.js',
26
- 'harness-everything/scripts/kernel-router-core.js',
27
- 'hooks/scripts/workflow-gate.js',
28
- 'hooks/scripts/workflow-stop-gate.js',
29
- 'hooks/scripts/workflow-disposition.js',
30
- ]) {
31
- const result = runNode(['--check', path.join(ROOT, rel)]);
32
- check(result.status === 0, `${rel} parses as valid JavaScript`);
33
- }
34
-
35
- const routed = runNode([
36
- path.join(ROOT, 'harness-everything/scripts/kernel-router.js'),
37
- 'audit the entire repository architecture and coordinate multiple modules',
38
- ]);
39
- check(routed.status === 0, 'enforced kernel route exits successfully');
40
- check(routed.stdout.includes('"strategy":"fable-staged"'), 'macro prompt selects fable-staged');
41
- check(routed.stdout.includes('WORKFLOW EXECUTION CONTRACT (MANDATORY WHEN SELECTED)'), 'wrapper emits mandatory execution contract');
42
- check(routed.stdout.includes('Execute the selected workflow to resolution'), 'wrapper requires workflow resolution');
43
- check(routed.stdout.includes('workflow-uncovered-scope'), 'wrapper exposes only explicit evidence-backed escape path');
44
- check(!routed.stdout.includes('execution remains advisory after evaluation'), 'wrapper removes advisory-execution runtime wording');
45
-
46
- const disposition = fs.readFileSync(path.join(ROOT, 'hooks/scripts/workflow-disposition.js'), 'utf8');
47
- check(disposition.includes("'workflow-uncovered-scope'"), 'escape supports workflow-uncovered-scope');
48
- check(disposition.includes("'host-capability-unavailable'"), 'escape supports host-capability-unavailable');
49
- check(disposition.includes('generic simple/routine/already-clear reasons are intentionally rejected'), 'generic confidence-based escape reasons are rejected');
50
- check(disposition.includes('--scope is required') && disposition.includes('--evidence is required') && disposition.includes('--stage-id must name'), 'escape requires a declared stage, scope and evidence');
51
-
52
- const hooks = JSON.parse(fs.readFileSync(path.join(ROOT, 'hooks/hooks.json'), 'utf8'));
53
- check((hooks.hooks.PreToolUse || []).some(entry => entry.id === 'harness:pre:workflow-gate'), 'Claude hook wiring includes pre-mutation workflow gate');
54
- check((hooks.hooks.Stop || []).some(entry => entry.id === 'harness:stop:workflow-completion-gate'), 'Claude hook wiring includes workflow completion gate');
55
-
56
-
57
- const budgetRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-budget-'));
58
- function budgetContext(name, strategy = 'iterative-single', limits = {}) {
59
- const file = path.join(budgetRoot, name, 'workflow-run.json');
60
- return {
61
- root: path.join(budgetRoot, name),
62
- sessionId: name,
63
- sessionDir: path.join(budgetRoot, name),
64
- file,
65
- workflow: {
66
- schemaVersion: 2,
67
- sessionId: name,
68
- workflowId: `wf-${name}`,
69
- state: 'running',
70
- strategy,
71
- revision: 0,
72
- workflowPlan: {
73
- strategy,
74
- limits: { maxIterations: 8, maxRevisionRounds: 2, maxReplans: 2, maxWorkers: 4, ...limits },
75
- },
76
- },
77
- };
78
- }
79
- function expectBudgetBlock(fn, reason, message) {
80
- try {
81
- fn();
82
- check(false, message);
83
- } catch (error) {
84
- check(error.code === 'HARNESS_WORKFLOW_BUDGET' && error.message.includes(reason), `${message} (${error.message})`);
5
+ const runtime = require(path.join(ROOT, 'hooks/scripts/lib/workflow-runtime.js'));
6
+ let failed=0;
7
+ function check(c,m){if(c)console.log(' PASS '+m);else{console.error(' FAIL '+m);failed++;}}
8
+ function runNode(args){return spawnSync(process.execPath,args,{cwd:ROOT,encoding:'utf8'});}
9
+ console.log('=== Workflow Guidance Contract ===');
10
+ for(const rel of ['harness-everything/scripts/kernel-router.js','hooks/scripts/workflow-gate.js','hooks/scripts/workflow-stop-gate.js','hooks/scripts/workflow-disposition.js','hooks/scripts/state-persist.js','hooks/scripts/rule-of-3.js','hooks/scripts/rule-of-3-tracker.js'])check(runNode(['--check',path.join(ROOT,rel)]).status===0,rel+' parses as valid JavaScript');
11
+ const ctx={workflow:{workflowPlan:{limits:{maxIterations:8,maxRevisionRounds:2,maxReplans:2,maxWorkers:4}}}};
12
+ for(const type of ['iteration','revision','replan','worker-acquire'])check(runtime.recordBudgetEvent(ctx,type,{evidence:'fixture'}).advisory===true,type+' is advisory rather than blocking');
13
+ check(runtime.mutationProbeReservations(ctx)===0,'mutation probes reserve no capacity');
14
+ check(runtime.registerMutationProbe(ctx,'x','y')===null,'mutation probe registration is a no-op');
15
+ check(runtime.resetWorkflowBudget(ctx,'legacy').retired===true,'reset-budget API is retired compatibility only');
16
+ check(!runtime.WORKFLOW_CONTROLLER_COMMANDS.has('reset-budget'),'reset-budget is no longer a controller command');
17
+ const rs=fs.readFileSync(path.join(ROOT,'hooks/scripts/lib/workflow-runtime.js'),'utf8');
18
+ check(!rs.includes('.mutation-probes.lock'),'runtime contains no mutation-probe lock');
19
+ check(!rs.includes('budget-exhausted'),'runtime contains no budget-exhausted transition');
20
+ const gs=fs.readFileSync(path.join(ROOT,'hooks/scripts/workflow-gate.js'),'utf8');
21
+ check(!gs.includes('registerMutationProbe')&&!gs.includes('recordBudgetEvent'),'workflow gate has no probe/budget enforcement');
22
+ check(gs.includes('[Workflow Reminder]'),'workflow gate emits reminders');
23
+ const r3=fs.readFileSync(path.join(ROOT,'hooks/scripts/rule-of-3.js'),'utf8');
24
+ check(r3.includes('state.count >= 3'),'Rule of 3 uses fixed third-failure boundary');
25
+ check(!r3.includes('blockForHumanDecision'),'Rule of 3 has no second-stage permanent hard lock');
26
+ const tr=fs.readFileSync(path.join(ROOT,'hooks/scripts/rule-of-3-tracker.js'),'utf8');
27
+ check(!tr.includes('threshold = 2')&&!tr.includes('threshold = 4'),'Rule of 3 has no category-specific thresholds');
28
+ const oc=fs.readFileSync(path.join(ROOT,'opencode-plugin/index.mjs'),'utf8');
29
+ check(!oc.includes('action: "hard_lock"'),'OpenCode has no permanent hard-lock action');
30
+ const hk=JSON.parse(fs.readFileSync(path.join(ROOT,'hooks/hooks.json'),'utf8'));
31
+ check(!hk.hooks.PermissionDenied,'obsolete mutation-probe PermissionDenied hook is removed');
32
+
33
+ const freshnessRoot=fs.mkdtempSync(path.join(os.tmpdir(),'harness-fable-freshness-'));
34
+ try{
35
+ const contracts=path.join(freshnessRoot,'contracts'),evidence=path.join(freshnessRoot,'evidence');fs.mkdirSync(contracts);fs.mkdirSync(evidence);
36
+ const run={runId:'freshness-run',planId:'freshness-plan',sessionId:'freshness-session',stageIds:['worker','verifier']};
37
+ const workerAt=Date.now()-10000,verifierAt=Date.now()-5000;
38
+ const stages=[
39
+ {stageId:'worker',agent:'fable-worker',workerId:'worker-1',writeSet:['src/x.js'],dependsOn:[],checkCommand:'worker-check',verifiedAt:new Date(workerAt).toISOString()},
40
+ {stageId:'verifier',agent:'fable-verifier',workerId:'verifier-1',writeSet:[],dependsOn:['worker'],checkCommand:'verify-check',verifiedAt:new Date(verifierAt).toISOString()},
41
+ ];
42
+ for(const stage of stages){
43
+ const contract={...stage,runId:run.runId,planId:run.planId,sessionId:run.sessionId,status:'pass'};
44
+ fs.writeFileSync(path.join(contracts,stage.stageId+'.json'),JSON.stringify(contract));
45
+ fs.writeFileSync(path.join(evidence,stage.stageId+'.json'),JSON.stringify({status:'pass',exitCode:0,planId:run.planId,runId:run.runId,stageId:stage.stageId,sessionId:run.sessionId,checkCommand:stage.checkCommand,observedAt:stage.verifiedAt,workerId:stage.workerId}));
85
46
  }
86
- }
87
-
88
- const iterationCtx = budgetContext('iteration');
89
- for (let i = 0; i < 8; i++) recordBudgetEvent(iterationCtx, 'iteration', { evidence: `mutation-${i + 1}` });
90
- check(iterationCtx.workflow.budget.counters.iterations === 8, 'iteration budget allows exactly maxIterations events');
91
- expectBudgetBlock(() => recordBudgetEvent(iterationCtx, 'iteration', { evidence: 'mutation-9' }), 'iteration-budget-exhausted', 'ninth iterative event is blocked');
92
- check(iterationCtx.workflow.state === 'blocked' && iterationCtx.workflow.budget.state === 'budget-exhausted', 'iteration exhaustion is persisted as blocked evidence');
93
- const persistedIteration = JSON.parse(fs.readFileSync(iterationCtx.file, 'utf8'));
94
- check(persistedIteration.blockReason === 'iteration-budget-exhausted', 'budget exhaustion survives on-disk workflow state');
95
-
96
- const isolatedCtx = budgetContext('isolated');
97
- recordBudgetEvent(isolatedCtx, 'iteration', { evidence: 'independent-run' });
98
- check(isolatedCtx.workflow.budget.counters.iterations === 1, 'another run/session has independent accounting');
99
- check(iterationCtx.workflow.budget.counters.iterations === 8, 'independent accounting does not reset exhausted run');
100
-
101
- resetWorkflowBudget(iterationCtx, 'new explicitly authorized attempt');
102
- check(iterationCtx.workflow.state === 'pending' && iterationCtx.workflow.budget.epoch === 1, 'budget reset is explicit, auditable, and starts a new epoch');
103
- check(iterationCtx.workflow.budget.counters.iterations === 0 && iterationCtx.workflow.budget.resets.length === 1, 'reset clears only the target run counters and retains history');
104
-
105
- const revisionCtx = budgetContext('revision', 'fable-staged');
106
- recordBudgetEvent(revisionCtx, 'revision', { evidence: 'verifier-fail-1' });
107
- recordBudgetEvent(revisionCtx, 'revision', { evidence: 'verifier-fail-2' });
108
- expectBudgetBlock(() => recordBudgetEvent(revisionCtx, 'revision', { evidence: 'verifier-fail-3' }), 'revision-budget-exhausted', 'third revision round is blocked');
109
-
110
- const replanCtx = budgetContext('replan', 'fable-staged');
111
- recordBudgetEvent(replanCtx, 'replan', { evidence: 'replan-1' });
112
- recordBudgetEvent(replanCtx, 'replan', { evidence: 'replan-2' });
113
- expectBudgetBlock(() => recordBudgetEvent(replanCtx, 'replan', { evidence: 'replan-3' }), 'replan-budget-exhausted', 'third full replan is blocked');
114
-
115
- const workerCtx = budgetContext('workers', 'fable-parallel');
116
- for (const id of ['w1', 'w2', 'w3', 'w4']) recordBudgetEvent(workerCtx, 'worker-acquire', { workerId: id });
117
- check(Object.keys(workerCtx.workflow.budget.activeWorkers).length === 4, 'worker accounting reaches but does not exceed maxWorkers');
118
- recordBudgetEvent(workerCtx, 'worker-release', { workerId: 'w1' });
119
- recordBudgetEvent(workerCtx, 'worker-acquire', { workerId: 'w5' });
120
- check(Object.keys(workerCtx.workflow.budget.activeWorkers).length === 4 && workerCtx.workflow.budget.activeWorkers.w5, 'released worker capacity is reusable');
121
-
122
- const overflowCtx = budgetContext('worker-overflow', 'fable-parallel');
123
- for (const id of ['w1', 'w2', 'w3', 'w4']) recordBudgetEvent(overflowCtx, 'worker-acquire', { workerId: id });
124
- expectBudgetBlock(() => recordBudgetEvent(overflowCtx, 'worker-acquire', { workerId: 'w5' }), 'worker-budget-exhausted', 'fifth concurrent worker is blocked');
125
-
126
- try { fs.rmSync(budgetRoot, { recursive: true, force: true }); } catch (_) {}
127
-
128
- const pluginHooks = JSON.parse(fs.readFileSync(path.join(ROOT, 'plugins/harness-everything/hooks/hooks.json'), 'utf8'));
129
- check((pluginHooks.hooks.PreToolUse || []).some(entry => (entry.hooks || []).some(hook => /workflow-gate\.js/.test(hook.command || ''))), 'OpenAI plugin hook package carries workflow gate adapter');
130
- check((pluginHooks.hooks.Stop || []).some(entry => (entry.hooks || []).some(hook => /workflow-stop-gate\.js/.test(hook.command || ''))), 'OpenAI plugin hook package carries workflow completion adapter');
131
-
132
- console.log(`\n${failed === 0 ? 'PASS' : 'FAIL'}: workflow execution enforcement (${failed} failure${failed === 1 ? '' : 's'})`);
133
- process.exit(failed === 0 ? 0 : 1);
47
+ const workflow={lastMutationAt:0,verification:{independent:true}};
48
+ const fresh=runtime.unresolvedStages({runRoot:freshnessRoot,run},workflow,workerAt);
49
+ check(!fresh.includes('independent-verifier-missing'),'Fable independent verifier accepts edits older than verifier evidence');
50
+ const stale=runtime.unresolvedStages({runRoot:freshnessRoot,run},workflow,verifierAt+1000);
51
+ check(stale.includes('independent-verifier-missing'),'Fable independent verifier is invalidated by newer handoff shell-edit evidence');
52
+ }finally{fs.rmSync(freshnessRoot,{recursive:true,force:true});}
53
+
54
+ console.log('\n'+(failed===0?'PASS':'FAIL')+': workflow guidance contract ('+failed+' failures)');
55
+ process.exit(failed===0?0:1);
@@ -63,7 +63,7 @@ const result = spawnSync(process.execPath, [hook], {
63
63
  encoding: 'utf8',
64
64
  env: { ...process.env, HARNESS_STATE_HOME: stateHome },
65
65
  });
66
- check(result.status === 2, 'a check from another session cannot resolve this run contract');
66
+ check(result.status === 0 && /session|correlat|resolve/i.test(result.stderr), 'a cross-session check is reported without resolving the run contract');
67
67
  const manifest = JSON.parse(fs.readFileSync(path.join(isolated.runRoot, 'contracts', 'verify.json'), 'utf8'));
68
68
  check(manifest.status === 'planned', 'cross-session check leaves the target contract unmodified');
69
69
 
@@ -92,7 +92,7 @@ const runA = prepareRun({
92
92
  sessionId: 'phase3-session',
93
93
  });
94
94
  check(JSON.stringify(runA.execution.batches) === JSON.stringify([['architecture', 'security'], ['synthesis']]), 'parallel plan emits dependency-safe ready batches');
95
- check(runA.execution.limits.maxWorkers === 4, 'run manifest retains the numeric worker cap');
95
+ check(runA.execution.limits.maxWorkers === 4, 'run manifest retains maxWorkers as an advisory planning hint');
96
96
  check(fs.existsSync(path.join(runA.runRoot, 'contracts', 'security.json')), 'run-scoped stage contract is written');
97
97
  check(fs.existsSync(path.join(runA.runRoot, 'contracts', 'synthesis.json')), 'downstream stage has its own contract');
98
98
 
@@ -119,9 +119,9 @@ const wideRun = prepareRun({
119
119
  runId: 'phase3-wide-parallel',
120
120
  sessionId: 'wide-session',
121
121
  });
122
- check(wideRun.execution.batches.length === 2, 'ready set larger than worker cap is deterministically chunked');
123
- check(wideRun.execution.batches.every(batch => batch.length <= 4), 'no dispatchable batch exceeds maxWorkers=4');
124
- check(wideRun.execution.batches.flat().length === 6, 'worker-cap chunking preserves every ready stage');
122
+ check(wideRun.execution.batches.length === 1, 'ready set is not hard-chunked by the advisory maxWorkers hint');
123
+ check(wideRun.execution.batches[0].length === 6, 'all dependency-ready stages remain dispatchable');
124
+ check(wideRun.execution.batches.flat().length === 6, 'advisory worker guidance preserves every ready stage');
125
125
 
126
126
  const stagedRun = prepareRun({
127
127
  routerContract: stagedContract,
@@ -235,7 +235,7 @@ const ambiguousResult = spawnSync(process.execPath, [contractHook], {
235
235
  encoding: 'utf8',
236
236
  env: { ...process.env, HARNESS_STATE_HOME: stateHome },
237
237
  });
238
- check(ambiguousResult.status === 2, 'ambiguous same-command correlation blocks acceptance');
238
+ check(ambiguousResult.status === 0 && /ambiguous|multiple/i.test(ambiguousResult.stderr), 'ambiguous same-command correlation is reported without blocking');
239
239
  for (const runId of ['ambiguous-a', 'ambiguous-b']) {
240
240
  const manifest = JSON.parse(fs.readFileSync(path.join(getWorkspaceStateRoot(workspace), 'fable-runs', runId, 'contracts', 'same-check.json'), 'utf8'));
241
241
  check(manifest.status === 'planned', `${runId} remains unmodified after ambiguous check`);
@@ -280,7 +280,7 @@ check(inScope.status === 0 && /in-scope/.test(inScope.stdout), 'declared in-scop
280
280
  check(runScope('PreToolUse').status === 0, 'next burst starts from rolled-forward baseline');
281
281
  fs.writeFileSync(path.join(gitWorkspace, 'docs', 'oops.txt'), 'unexpected\n');
282
282
  const outOfScope = runScope('PostToolUse');
283
- check(outOfScope.status === 2 && /OUT-OF-SCOPE/.test(outOfScope.stderr), 'undeclared worker edit is rejected by scope guard');
283
+ check(outOfScope.status === 0 && /OUT-OF-SCOPE/.test(outOfScope.stderr), 'undeclared worker edit is reported without blocking');
284
284
 
285
285
  const contractDoc = fs.readFileSync(path.join(ROOT, 'fable-mode', 'CONTRACT-FORMAT.md'), 'utf8');
286
286
  const orchestratorDoc = fs.readFileSync(path.join(ROOT, 'fable-mode', 'agents', 'fable-orchestrator.md'), 'utf8');
@@ -4,22 +4,22 @@ This document describes Harness runtime architecture and integration boundaries.
4
4
 
5
5
  ## Architectural Overview
6
6
 
7
- Harness is a **behavior and workflow supervisor**, not one universal fixed workflow. The router chooses the smallest sufficient execution topology; once selected, that topology becomes a lifecycle contract. The model retains freedom over reasoning, tools, and implementation technique inside the contract.
7
+ Harness is a **behavior and workflow observer/router**, not a universal fixed workflow or scheduler. The router chooses a useful topology; the model remains free to adapt execution.
8
8
 
9
9
  The minimal kernel establishes:
10
10
 
11
11
  - scope/tier before mutation,
12
- - a selected workflow topology when task evidence supports one,
12
+ - a selected workflow topology as planning guidance when task evidence supports one,
13
13
  - applicability evaluation for every suggested skill before omission,
14
14
  - objective evidence before completion,
15
15
  - bounded re-plan/recovery after repeated failure,
16
- - explicit blocked/degraded/escape state instead of silent workflow deletion.
16
+ - explicit warnings/degraded/escape evidence instead of silent workflow deletion.
17
17
 
18
- > **Mandatory applicable workflow; flexible reasoning/implementation inside it.**
18
+ > **Guidance-first workflow; flexible reasoning/implementation and execution.**
19
19
  >
20
- > A suggested skill can be `not-applicable` after evaluating its real flow. A selected topology cannot be replaced with a direct path merely because the model is confident. Escape is only for genuinely uncovered workflow scope and requires evidence.
20
+ > Suggested skills and topology are evaluated from their real flows. Missing or skipped cognitive workflow steps produce evidence/reminders rather than persistent Harness locks.
21
21
 
22
- This avoids both extremes: the old universal Tier-2/Tier-3 pipeline and a purely advisory system where the model can rationalize away verification, staging, documentation, or other applicable obligations.
22
+ This avoids both extremes: no universal Tier-2/Tier-3 pipeline and no maze of self-deadlocking cognitive gates.
23
23
 
24
24
  ```mermaid
25
25
  flowchart TD
@@ -50,7 +50,7 @@ flowchart TD
50
50
  - required invariants,
51
51
  - suggested skills that require applicability evaluation,
52
52
  - the visible routing checkpoint,
53
- - a workflow execution contract.
53
+ - a workflow guidance.
54
54
 
55
55
  The router does not tell the model *how* to solve each stage. It decides what lifecycle shape is required. `direct-single`, `iterative-single`, `fable-staged`, `fable-parallel`, and `fable-multi-agent-workspace` remain deliberately small, non-overlapping topology choices.
56
56
 
@@ -58,7 +58,7 @@ The router does not tell the model *how* to solve each stage. It decides what li
58
58
 
59
59
  Router suggestions remain useful domain/workflow knowledge, not a universal sequence. Before omission, the agent reads the complete `SKILL.md` entry and evaluates `USE FOR`, `DO NOT USE FOR`, workflow/basic flow, and hard rules. Name/description/router-summary or “routine task” is insufficient evidence.
60
60
 
61
- The selected topology is stronger. Once selected, it must be entered and resolved unless the runtime records a permitted workflow escape with uncovered scope + evidence. Covered obligations survive the escape.
61
+ The selected topology is a structured planning aid; it does not become a persistent execution lock.
62
62
 
63
63
  ### Runtime workflow state
64
64
 
@@ -66,16 +66,16 @@ On host paths that can persist it, `kernel-router.js` records session-scoped `wo
66
66
 
67
67
  For selected Fable topologies on Claude:
68
68
 
69
- - `workflow-gate.js` checks supported shell/direct mutation, actual direct/patch targets, and registered Git worktree isolation before major-workflow mutation; Fable also requires a run bound to the workflow/session identity;
69
+ - `workflow-gate.js` observes supported mutation/worktree/Fable state and emits reminders;
70
70
  - Fable owns stage contracts, `dependsOn`/`writeSet`, validated execution batches, objective per-stage checks, synthesis, cold verification, and bounded re-plans;
71
- - `workflow-stop-gate.js` rejects completion while correlated stage contracts remain unresolved;
72
- - `workflow-disposition.js` starts/replans within budget, records blockers, and permits only declared-stage evidence-backed escape (`workflow-uncovered-scope` or `host-capability-unavailable`). Covered obligations, isolation, and independent verification survive escape. See [runtime transitions and limitations](workflow-runtime.md).
71
+ - `workflow-stop-gate.js` reports unresolved stage/verification evidence without rejecting Stop;
72
+ - `workflow-disposition.js` records explicit lifecycle/audit decisions; numeric budgets are no longer authoritative control state.
73
73
 
74
74
  Other topologies use their own applicable mechanisms: loop budgets, regular verification stop-gates, action gates, and task-specific skills. Mechanism coverage is not assumed identical across hosts.
75
75
 
76
76
  ### Scoped runtime advisories and capabilities
77
77
 
78
- Two kernel mechanisms adjust plans without changing the mandatory-workflow contract:
78
+ Two kernel mechanisms annotate plans without creating hard workflow enforcement:
79
79
 
80
80
  - **Ensemble policy (`harness-everything/scripts/ensemble-policy.js`):** an advisory plan annotation, not a separate topology. It is selected only when uncertainty is high (or stakes are high) **and** the task asks for comparable outputs or preserves explicit disagreement **and** the selected strategy is already `fable-*`. Creative generation, mechanical bulk work, an explicit user prohibition, unavailable subagents, or a blocked base plan force exclusion. When selected, the plan caps at 3 candidates with `preserve-disagreement` synthesis, an independent verifier, and `parallel-self-consistency` pattern invariants. Covered by deterministic mechanism tests; no live-host effectiveness claim follows from the annotation alone.
81
81
  - **Single-use memory capability (`kernel-router.js#issueMemoryCapability`):** when the selected plan permits memory writes, the router issues one capability token bound to `sessionId`/`workflowId` with a stored SHA-256 hash (`memoryAuthorization`, coordinator-only writer role, `usedAt` tracking). Plans with `memory.write === 'none'` receive no capability. This binds a memory write to the workflow that authorized it; it is not a general credential and proves nothing about a live host honoring the binding.
@@ -84,11 +84,11 @@ Two kernel mechanisms adjust plans without changing the mandatory-workflow contr
84
84
 
85
85
  On the Claude hook path, three narrowly scoped `PreToolUse` guards sit alongside the workflow/action gates:
86
86
 
87
- - `boundary-guard.js` (Grep/Glob/Read): hard-blocks whole-file reads over 512KB without `offset`/`limit` and searches inside known noise directories (`node_modules`, `.git`, build output, etc.). Fails open on parse/lookup errors.
87
+ - `boundary-guard.js` (Grep/Glob/Read): warns about very large reads and noisy search roots; it fails open.
88
88
  - `depth-guard.js` (Write): blocks overwriting an existing file that was never Read earlier in the session transcript. New files are unaffected. Fails open on parse/lookup errors.
89
89
  - `context-compact.js`: estimates working-tree context pressure from `git status`/`git diff --numstat` so later stages can compact or halt before lost-in-the-middle degradation.
90
90
 
91
- Shell mutation accounting is per-tool-call: `workflow-isolation.js` fingerprints observed effects per tool-use identity, `state-persist.js` settles probes in a single ordered handler, and `workflow-mutation-denied.js` discards probes for denied shell executions so a denial never counts as an observed mutation. See [runtime transitions and limitations](workflow-runtime.md). These are mechanism-tested behaviors on the packaged hook surface, not proof that a live session loaded or fired them.
91
+ Shell mutation observation is best-effort evidence for reminders. The old mutation-probe reservation/lock subsystem was retired by #190.
92
92
 
93
93
  ## Integration Touchpoints
94
94
 
@@ -98,23 +98,23 @@ Harness aligns to each host's actual lifecycle/tool APIs. Shared skill text defi
98
98
 
99
99
  Runtime state includes hook metadata, workflow lifecycle, circuit-breaker counters, handoff/verification evidence, and WAL-style session state. Skill content is independently discoverable and remains useful on instruction-only surfaces.
100
100
 
101
- ### Claude Code — hook-enforced mechanisms
101
+ ### Claude Code — hook guidance plus explicit safety boundaries
102
102
 
103
103
  The installer configures native lifecycle hooks and project skills.
104
104
 
105
105
  - `SessionStart`: bootstrap/restoration.
106
- - `UserPromptSubmit`: kernel routing + active workflow contract.
107
- - `PreToolUse`: workflow bypass gate, action gate, rule-of-3, boundary/depth/context guards, subagent scope guard.
106
+ - `UserPromptSubmit`: kernel routing + workflow guidance.
107
+ - `PreToolUse`: workflow/boundary/depth/scope reminders, plus separate action permission and Rule-of-3 boundaries.
108
108
  - `PostToolUse`: outcomes, state, repeated-failure evidence, stage checks.
109
- - `Stop`: action-gate audit, selected-Fable completion gate, and ordinary verify-before-claim stop gate.
109
+ - `Stop`: action-gate audit plus non-blocking workflow/verification reminders.
110
110
 
111
- These hooks make some lifecycle obligations mechanically enforceable. They still do not prove a real session loaded/fired them; live evidence remains separate.
111
+ These hooks make reminders observable; they do not promote cognitive workflow guidance into hard enforcement.
112
112
 
113
113
  ### OpenCode — plugin enforcement, scoped live verification
114
114
 
115
115
  The retained [OpenCode evidence](../benchmarks/results/live-host/opencode-2026-09-16/README.md) supports **project-scope `.js` loading and edit/verification state on OpenCode 1.18.31 (macOS)**. The final snapshot is **post-reset**. Hard-lock is an **interactive observation** with **no retained blocked-tool trace**; reflection was **operator-seeded** and then agent-rewritten. Global scope, npm-package installation, and other OpenCode versions remain unverified.
116
116
 
117
- This evidence does not establish the new mandatory-workflow lifecycle on OpenCode. That requires its own adapter/evidence before parity is claimed.
117
+ This evidence predates #190 and does not establish behavioral effectiveness of the current guidance-first lifecycle.
118
118
 
119
119
  ### Cursor — skills plus advisory rules
120
120
 
@@ -161,7 +161,7 @@ flowchart TD
161
161
  R -- No --> Block
162
162
  ```
163
163
 
164
- The orchestrator controls lifecycle and completion; workers do not create peer-to-peer meshes or widen their own write scope. The model remains creative inside each bounded stage, while stage existence/checks/termination are contract state.
164
+ The orchestrator coordinates lifecycle and evidence; scope drift is reported for review rather than turned into a cognitive deadlock.
165
165
 
166
166
  ## Cognitive OS and Skill Mesh
167
167
 
@@ -1,114 +1,53 @@
1
- # Enforcement and Lock Diagnostic Flows
2
-
3
- Harness has several mechanisms that can deny a tool call or delay completion. Only one of them is a repeated-failure circuit breaker. Use the emitted mechanism name and the flows below before describing a denial as a lock problem.
4
-
5
- This guide describes the repository's current hook wiring. Mechanical enforcement depends on the host and installation surface; see [Platform Capability Matrix](platform-capabilities.md) before generalizing a behavior to every host.
6
-
7
- ## Lifecycle map
8
-
9
- On the Claude hook surface, a request enters the router before tool use. Pre-tool gates decide whether a tool call may start, post-tool hooks record outcomes, and stop gates decide whether the turn may finish.
10
-
11
- ```mermaid
12
- flowchart TD
13
- A["User prompt"] --> B["Kernel router<br/>select workflow contract"]
14
- B --> C["Pre-tool gates"]
15
- C --> D{"Tool allowed?"}
16
- D -- "No" --> E["Emit gate-specific reason<br/>and recovery"]
17
- D -- "Yes" --> F["Execute tool"]
18
- F --> G["Post-tool outcome tracking"]
19
- G --> H{"Turn stopping?"}
20
- H -- "No" --> C
21
- H -- "Yes" --> I["Completion gates"]
22
- I --> J{"Obligations resolved?"}
23
- J -- "Yes" --> K["Evidence-backed completion"]
24
- J -- "No" --> E
1
+ # Guidance and Safety Boundary Diagnostic Flows
2
+
3
+ Harness deliberately separates **cognitive guidance** from **authorization/safety boundaries**.
4
+
5
+ ## Classification
6
+
7
+ | Mechanism | Behavior | Hard block? |
8
+ |---|---|---|
9
+ | Workflow routing/state | Remind about selected topology, stale/blocked descriptive state, missing Fable correlation, or safer worktree usage | No |
10
+ | Iteration/revision/replan/worker guidance | Planning hints only | No |
11
+ | Verification / Stop | Remind when no successful verification is observed after an edit | No |
12
+ | Boundary guard | Warn about very large reads or noisy search roots | No |
13
+ | Depth guard | Remind when editing a file that has not been inspected | No |
14
+ | Subagent scope guard | Report ambiguous/out-of-scope changes for review | No |
15
+ | Atomic commit check | Warn when changes look broader than one atomic concern | No |
16
+ | Fable contract test | Record pass/fail/ambiguity/dependency evidence and warn | No |
17
+ | Rule of 3 | Third matching failure requires a zoom-out reflection before more mutation | **Yes — intentional cognitive boundary** |
18
+ | Action/permission gate | User/host authorization for destructive or external side effects | **Yes — trust boundary** |
19
+
20
+ ## Rule of 3
21
+
22
+ ```text
23
+ same signature #1 -> record
24
+ same signature #2 -> record
25
+ same signature #3 -> pause mutation and require zoom-out
26
+ reflection accepted -> count resets
27
+ later #1/#2/#3 -> another zoom-out
25
28
  ```
26
29
 
27
- The important separation is:
28
-
29
- - **Pre-tool denial:** the requested operation did not run.
30
- - **Post-tool tracking:** the operation ran and its outcome updated state.
31
- - **Stop denial:** the turn cannot claim completion yet; it does not necessarily prevent the next tool call.
32
- - **Approval request:** the exact destructive or external action waits for authorization; it is not a retry lock.
33
-
34
- ## Which mechanism stopped progress?
35
-
36
- Start with the prefix in the error or hook message. Do not infer the mechanism only from the fact that a command did not run.
37
-
38
- ```mermaid
39
- flowchart TD
40
- A["Operation or completion blocked"] --> B{"Message prefix or condition"}
41
- B -- "RULE OF 3" --> C["Repeated-failure circuit breaker"]
42
- B -- "Workflow gate" --> D["Workflow entry, state,<br/>run, or worktree precondition"]
43
- B -- "Action gate or permission" --> E["Exact side effect needs approval"]
44
- B -- "Workflow Completion Gate" --> F["Selected workflow obligations unresolved"]
45
- B -- "Stop Gate" --> G["Edits lack later successful verification"]
46
- B -- "Boundary, depth, context,<br/>or scope guard" --> H["Guard-specific policy denial"]
47
- C --> I["Follow Rule of 3 recovery flow"]
48
- D --> J["Satisfy named workflow precondition"]
49
- E --> K["Approve, reject, or change exact payload"]
50
- F --> L["Resolve stages or report blocked state"]
51
- G --> M["Run a relevant check or state why not applicable"]
52
- H --> N["Follow the emitted guard reason"]
53
- ```
54
-
55
- If a message has no Harness prefix, check the host permission system and the tool's own error before changing Harness state.
56
-
57
- ## Mechanism reference
58
-
59
- | Mechanism | Trigger | What it blocks | State and persistence | Recovery |
60
- |---|---|---|---|---|
61
- | Rule of 3 | The same normalized shell failure signature reaches its category threshold. Defaults to 3; timeout and permission use 2; environment and dependency use 4. | Mutating tools. Read-only investigation remains available, and the required zoom-out report is the only permitted write. | Session-scoped `rule-of-3-state.json`. A second trip of the same signature after one accepted reflection becomes a human-decision hard lock. | First trip: produce a fresh valid `zoom-out-report.md`. Repeat trip: human runs `npm run harness:reset`, starts a new session, or uses `/clear`. |
62
- | Workflow gate | Active workflow state or entry contract is incompatible with the requested mutation; examples include blocked/failed/satisfied state, missing correlated Fable run, or missing linked worktree for major work. | The requested mutation. Read-only commands and trusted workflow-controller commands have narrow exceptions. | Session workflow state. Major-workflow isolation is a hard precondition, not an automatic fallback. | Use the exact message: enter a linked worktree, start/replan through the controller, resolve blocked state, or submit a new task after satisfaction. |
63
- | Action gate | A shell rule or structured destructive/external action matches the policy. | Only the exact action payload; its hash is used for audit correlation. | Approval/audit state records pending, executed, failed, or rejected disposition. | Approve or reject through the host flow, or change the action. Approval of one payload does not authorize a different payload. |
64
- | Workflow completion gate | A selected workflow is stopping with unresolved stage, correlation, or verification obligations. | Completion. On a repeated stop-hook attempt it records a blocked state instead of looping forever. | `workflow-run.json` plus correlated stage/handoff state. | Resolve the named obligation. If genuinely blocked, report the blocker rather than claim completion. |
65
- | Ordinary stop gate | A dirty tree contains edits with no later successful verification-like command. | Completion once per edit batch. It is intentionally a bounce, not a persistent cage. | `stop-gate-state.json` remembers the edit timestamp already bounced. | Run a targeted test/build/lint check, or explicitly state why verification is not applicable and stop again. |
66
- | Boundary/depth/context/scope guards | A guard-specific read, write, context-pressure, or subagent-scope condition matches. | The matching tool or workflow step. | Mechanism-specific; these are not Rule of 3 counters. | Follow the emitted reason and the corresponding architecture documentation. |
67
-
68
- ## Rule of 3 state transitions
69
-
70
- The tracker hashes a normalized failure together with category, file path, and command context. A different signature starts a new counter. A confirmed successful action clears recovery state.
71
-
72
- ```mermaid
73
- stateDiagram-v2
74
- [*] --> Counting
75
- Counting --> Counting: same signature below threshold
76
- Counting --> Reflecting: threshold reached
77
- Reflecting --> Counting: valid fresh report with RESUME
78
- Reflecting --> Escalating: valid fresh report with ESCALATE
79
- Counting --> HardLocked: same signature trips after reflection
80
- HardLocked --> [*]: human reset or new session
81
- Counting --> [*]: confirmed success
82
- Escalating --> HardLocked: mutation retried and signature trips again
83
- ```
84
-
85
- A valid reflection report must be newer than the failure that tripped the breaker, contain `Goal`, `Failed Attempts`, `Verified Facts`, `Diagnosis`, and `Decision`, and end in a `RESUME` or `ESCALATE` decision. A stale report cannot release a later trip.
86
-
87
- ## Pre-tool ordering and overlapping denials
30
+ There are no category-specific 2/4 thresholds and no second-stage permanent hard lock.
88
31
 
89
- The configured Claude pre-tool order is workflow gate, action gate, Rule of 3, then the narrower boundary/depth/context/scope guards for their matched tools. This means the first emitted denial identifies the condition reached on that call; it does not prove that every later gate would pass.
32
+ ## Workflow reminders
90
33
 
91
- For example:
34
+ A workflow may be marked `blocked`, `failed`, or carry legacy `budget-exhausted` evidence. Those states are useful diagnostics but no longer cause `workflow-gate.js` to reject mutation.
92
35
 
93
- 1. A force push may first fail the workflow gate if the selected workflow has not been entered.
94
- 2. After workflow entry is fixed, the action gate may still require approval for the same force push.
95
- 3. Rule of 3 is relevant only when repeated tracked failures reached the signature threshold; it should not be reset to bypass workflow or approval requirements.
36
+ Missing verification at Stop similarly produces a reminder rather than a bounce.
96
37
 
97
- Treat each denial independently and re-evaluate after satisfying its stated condition.
38
+ ## Why #190 removed hard workflow enforcement
98
39
 
99
- ## Host and evidence boundary
40
+ The previous numeric enforcement required mutation probes, stale-probe recovery, shared counters, exact-limit exceptions, shell classification, reset controllers, and a filesystem lock. #190 removed that chain instead of hardening it.
100
41
 
101
- The hook sequence above is the canonical Claude package wiring. The local OpenAI/Codex plugin packages related lifecycle adapters, while general installer paths and the public Skills-only artifact may be advisory rather than mechanically enforced. OpenCode has a separate plugin implementation and a narrower retained live-host evidence boundary.
42
+ The design test is simple:
102
43
 
103
- Repository mechanism tests show that packaged code follows its tested contract. They do not by themselves prove that a particular live host loaded the package, fired the hook, or improved agent behavior. Record live-host evidence before making that stronger claim.
44
+ > If better cognitive guidance requires another lock, lease, heartbeat, counter-recovery protocol, or parser exception, prefer a reminder.
104
45
 
105
- ## Source map
46
+ ## Troubleshooting
106
47
 
107
- Use these implementation files when this guide and runtime appear to disagree:
48
+ When a Harness message appears:
108
49
 
109
- - `hooks/hooks.json` — lifecycle wiring and order.
110
- - `hooks/scripts/rule-of-3.js` and `rule-of-3-tracker.js` — counter, thresholds, reflection, and hard-lock behavior.
111
- - `hooks/scripts/workflow-gate.js` and `workflow-stop-gate.js` — mutation and completion workflow contracts.
112
- - `hooks/scripts/action-gate.js` and `action-gate-rules.json` — approval policy and audit behavior.
113
- - `hooks/scripts/stop-gate.js` — ordinary one-bounce verification behavior.
114
- - [Harness Architecture](architecture.md) and [Workflow Runtime](workflow-runtime.md) — broader runtime contracts and limitations.
50
+ 1. If it is a **Reminder**, use the evidence to improve the next action, but there is no Harness reset needed.
51
+ 2. If it is the **Rule of 3** third-failure boundary, complete the requested zoom-out report.
52
+ 3. If it is an **action/permission** decision, follow the host/user approval flow.
53
+ 4. Do not edit Harness state files merely to recover from a numeric workflow limit; those limits are no longer enforced.
@@ -4,7 +4,7 @@ Harness coordinates independently useful skills through a small workflow runtime
4
4
 
5
5
  The preferred shape is:
6
6
 
7
- > **mandatory applicable workflow + local skill autonomy + narrow runtime mechanisms**
7
+ > **guidance-first workflow + local skill autonomy + narrow runtime mechanisms**
8
8
 
9
9
  Platform-specific enforcement claims remain bounded by [platform-capabilities.md](platform-capabilities.md).
10
10
 
@@ -19,7 +19,7 @@ A skill should answer:
19
19
  3. **What workflow/mechanism do I expose?** A local flow, verifier, script, gate, or stable result when useful.
20
20
  4. **What evidence means I am done?** A check, artifact, or explicit blocked state.
21
21
 
22
- The router may surface several skills. Those suggestions must be evaluated from their actual `SKILL.md` flows before omission. They are **not** automatically all executed. Separately, the router selects one smallest sufficient outer topology. **The selected topology is mandatory for the run.**
22
+ The router may surface several skills. Those suggestions must be evaluated from their actual `SKILL.md` flows before omission. They are **not** automatically all executed. Separately, the router selects one smallest sufficient outer topology. **The selected topology guides the run.**
23
23
 
24
24
  ## Why Not One Global Skill Sequence?
25
25
 
@@ -9,14 +9,14 @@ The mechanism/enforcement boundary remains platform-specific; see [Platform Capa
9
9
  ## Core Philosophy: Constrain Lifecycle, Not Reasoning
10
10
 
11
11
  1. **Reasoning autonomy remains high.** The model chooses implementation technique, tools, decomposition details, and tactics inside the selected workflow.
12
- 2. **Applicable workflow is mandatory.** Once routing selects a topology, it must be executed to resolution. Model confidence, “simple”, “routine”, and “already clear” are not escape conditions.
12
+ 2. **Applicable workflow is guidance: routing should make useful structure visible without taking execution agency away from the model/user.
13
13
  3. **Skill applicability is explicit.** Router-suggested skills are read/evaluated before omission. A suggestion can be `not-applicable` when its actual flow does not match; a selected topology is stronger and cannot simply be skipped.
14
14
  4. **Escape is conditional, not default.** If the selected workflow genuinely cannot represent part of the task, record the uncovered scope and evidence, then allow model-defined handling only for that uncovered portion.
15
15
  5. **Mechanisms beat stronger wording.** Important lifecycle transitions should use structured state, objective evidence, hooks/plugins, exit codes, and completion gates where the host supports them rather than escalating `MUST`/`CRITICAL` prose.
16
16
 
17
17
  This principle can be summarized as:
18
18
 
19
- > **Mandatory applicable workflow; flexible reasoning/implementation inside it; evidence-backed escape only where the workflow does not cover the task.**
19
+ > **guidance-first applicable workflow; flexible reasoning/implementation inside it; evidence-backed escape only where the workflow does not cover the task.**
20
20
 
21
21
  The goal is not to make the model less capable. It is to prevent capability/confidence from silently deleting engineering obligations such as verification, bounded re-planning, stage checks, documentation checks, or safety gates when those obligations are applicable.
22
22