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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +23 -0
- package/README.md +7 -7
- package/VERIFICATION.md +3 -3
- package/bin/cli.js +17 -0
- package/ci/invariant-routing.test.js +58 -158
- package/ci/mechanism-2a-rule-of-3.test.js +73 -138
- package/ci/mechanism-2ac-atomic-commit-check.test.js +2 -2
- package/ci/mechanism-2af-worktree-isolation.test.js +38 -196
- package/ci/mechanism-2ah-workflow-lifecycle.test.js +20 -831
- package/ci/mechanism-2ai-workspace-fingerprint-batch.test.js +3 -4
- package/ci/mechanism-2al-codex-hooks-compat.test.js +286 -0
- package/ci/mechanism-2b-boundary-guard.test.js +6 -16
- package/ci/mechanism-2e-scope-guard.test.js +8 -24
- package/ci/mechanism-2f-stop-gate.test.js +21 -75
- package/ci/mechanism-2n-opencode-plugin.test.js +13 -28
- package/ci/openai-plugin-package.test.js +8 -8
- package/ci/openai-plugin-runtime.test.js +2 -2
- package/ci/router-workflow-plan.test.js +6 -6
- package/ci/self-evolve-loop.test.js +4 -1
- package/ci/workflow-execution-contract.test.js +51 -129
- package/ci/workflow-plan-consumers-edge.test.js +1 -1
- package/ci/workflow-plan-consumers.test.js +6 -6
- package/docs/architecture.md +21 -21
- package/docs/enforcement-locks.md +41 -102
- package/docs/mechanism-first-skill-mesh.md +2 -2
- package/docs/philosophy.md +2 -2
- package/docs/platform-capabilities.md +19 -3
- package/docs/platform-compatibility.json +4 -4
- package/docs/routing.md +14 -14
- package/docs/workflow-runtime.md +80 -110
- package/evals/harness-everything/tasks/positive-tier1.yaml +1 -1
- package/evals/harness-everything/tasks/positive-tier2.yaml +1 -1
- package/evals/harness-everything/tasks/positive-tier3.yaml +1 -1
- package/evals/using-git-worktrees/tasks/positive-trigger.yaml +1 -1
- package/fable-mode/SKILL.md +1 -1
- package/fable-mode/execution-guardrails/SKILL.md +1 -1
- package/fable-mode/fable-haiku/SKILL.md +1 -1
- package/fable-mode/fable-opus/SKILL.md +1 -1
- package/fable-mode/fable-sonnet/SKILL.md +1 -1
- package/fable-mode/scripts/workflow-plan-consumer.js +4 -3
- package/harness-everything/SKILL.md +11 -11
- package/harness-everything/references/triage-and-tiers.md +11 -11
- package/harness-everything/scripts/kernel-router-core.js +5 -5
- package/harness-everything/scripts/kernel-router.js +15 -17
- package/harness-everything/scripts/router-contract-core.js +1 -1
- package/hooks/hooks.json +10 -23
- package/hooks/scripts/atomic-commit-check.js +1 -1
- package/hooks/scripts/boundary-guard.js +4 -4
- package/hooks/scripts/contract-test.js +8 -11
- package/hooks/scripts/depth-guard.js +2 -2
- package/hooks/scripts/lib/workflow-runtime.js +24 -402
- package/hooks/scripts/rule-of-3-tracker.js +28 -31
- package/hooks/scripts/rule-of-3.js +4 -28
- package/hooks/scripts/state-persist.js +36 -136
- package/hooks/scripts/stop-gate.js +15 -48
- package/hooks/scripts/subagent-scope-guard.js +8 -8
- package/hooks/scripts/workflow-disposition.js +2 -10
- package/hooks/scripts/workflow-gate.js +33 -84
- package/hooks/scripts/workflow-mutation-denied.js +3 -15
- package/hooks/scripts/workflow-stop-gate.js +23 -38
- package/opencode-plugin/README.md +9 -10
- package/opencode-plugin/index.mjs +14 -30
- package/opencode-plugin/plugin.json +1 -1
- package/package.json +4 -2
- package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
- package/plugins/harness-everything/hooks/hooks.json +3 -3
- package/plugins/harness-everything/hooks/scripts/atomic-commit-check.js +1 -1
- package/plugins/harness-everything/hooks/scripts/boundary-guard.js +4 -4
- package/plugins/harness-everything/hooks/scripts/contract-test.js +8 -11
- package/plugins/harness-everything/hooks/scripts/depth-guard.js +2 -2
- package/plugins/harness-everything/hooks/scripts/lib/workflow-runtime.js +24 -402
- package/plugins/harness-everything/hooks/scripts/rule-of-3-tracker.js +28 -31
- package/plugins/harness-everything/hooks/scripts/rule-of-3.js +4 -28
- package/plugins/harness-everything/hooks/scripts/state-persist.js +36 -136
- package/plugins/harness-everything/hooks/scripts/stop-gate.js +15 -48
- package/plugins/harness-everything/hooks/scripts/subagent-scope-guard.js +8 -8
- package/plugins/harness-everything/hooks/scripts/workflow-disposition.js +2 -10
- package/plugins/harness-everything/hooks/scripts/workflow-gate.js +33 -84
- package/plugins/harness-everything/hooks/scripts/workflow-mutation-denied.js +3 -15
- package/plugins/harness-everything/hooks/scripts/workflow-stop-gate.js +23 -38
- package/plugins/harness-everything/plugin.json +1 -1
- package/plugins/harness-everything/scripts/lib/advisory-text.js +16 -29
- package/plugins/harness-everything/skills/fable-mode/SKILL.md +1 -1
- package/plugins/harness-everything/skills/fable-mode/execution-guardrails/SKILL.md +1 -1
- package/plugins/harness-everything/skills/fable-mode/fable-haiku/SKILL.md +1 -1
- package/plugins/harness-everything/skills/fable-mode/fable-opus/SKILL.md +1 -1
- package/plugins/harness-everything/skills/fable-mode/fable-sonnet/SKILL.md +1 -1
- package/plugins/harness-everything/skills/fable-mode/scripts/workflow-plan-consumer.js +4 -3
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +11 -11
- package/plugins/harness-everything/skills/harness-everything/references/triage-and-tiers.md +11 -11
- package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router-core.js +5 -5
- package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router.js +15 -17
- package/plugins/harness-everything/skills/harness-everything/scripts/router-contract-core.js +1 -1
- package/plugins/harness-everything/skills/using-git-worktrees/SKILL.md +5 -5
- package/scripts/codex-hooks-compat.js +521 -0
- package/scripts/lib/advisory-text.js +16 -29
- 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
|
|
11
|
-
let failed
|
|
12
|
-
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
check(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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 ===
|
|
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
|
|
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 ===
|
|
123
|
-
check(wideRun.execution.batches.
|
|
124
|
-
check(wideRun.execution.batches.flat().length === 6, 'worker
|
|
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 ===
|
|
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 ===
|
|
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');
|
package/docs/architecture.md
CHANGED
|
@@ -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
|
|
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
|
|
16
|
+
- explicit warnings/degraded/escape evidence instead of silent workflow deletion.
|
|
17
17
|
|
|
18
|
-
> **
|
|
18
|
+
> **Guidance-first workflow; flexible reasoning/implementation and execution.**
|
|
19
19
|
>
|
|
20
|
-
>
|
|
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:
|
|
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
|
|
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
|
|
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`
|
|
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`
|
|
72
|
-
- `workflow-disposition.js`
|
|
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
|
|
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):
|
|
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
|
|
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
|
|
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 +
|
|
107
|
-
- `PreToolUse`: workflow
|
|
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
|
|
109
|
+
- `Stop`: action-gate audit plus non-blocking workflow/verification reminders.
|
|
110
110
|
|
|
111
|
-
These hooks make
|
|
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
|
|
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
|
|
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
|
-
#
|
|
2
|
-
|
|
3
|
-
Harness
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
32
|
+
## Workflow reminders
|
|
90
33
|
|
|
91
|
-
|
|
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
|
-
|
|
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
|
-
|
|
38
|
+
## Why #190 removed hard workflow enforcement
|
|
98
39
|
|
|
99
|
-
|
|
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
|
|
42
|
+
The design test is simple:
|
|
102
43
|
|
|
103
|
-
|
|
44
|
+
> If better cognitive guidance requires another lock, lease, heartbeat, counter-recovery protocol, or parser exception, prefer a reminder.
|
|
104
45
|
|
|
105
|
-
##
|
|
46
|
+
## Troubleshooting
|
|
106
47
|
|
|
107
|
-
|
|
48
|
+
When a Harness message appears:
|
|
108
49
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
> **
|
|
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
|
|
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
|
|
package/docs/philosophy.md
CHANGED
|
@@ -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
|
|
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
|
-
> **
|
|
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
|
|