harness-everything 0.30.9 → 0.31.0
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 +1 -1
- package/CHANGELOG.md +34 -0
- package/README.md +8 -9
- package/VERIFICATION.md +1 -1
- package/benchmarks/results/live-host/claude-2026-10-08-issue-297/README.md +27 -0
- package/benchmarks/results/live-host/codex-2026-10-13/README.md +55 -0
- package/benchmarks/results/live-host/codex-2026-10-13/observation-records.json +88 -0
- package/benchmarks/results/pr-303-review-2026-10-13/README.md +81 -0
- package/benchmarks/results/pr-303-review-2026-10-13/ci/run.json +1330 -0
- package/benchmarks/results/pr-303-review-2026-10-13/diagnostics/mechanism-35-clean-env.log +1 -0
- package/benchmarks/results/pr-303-review-2026-10-13/diagnostics/mechanism-35-inherited-flag.log +34 -0
- package/benchmarks/results/pr-303-review-2026-10-13/diagnostics/verify-gate-captured.json +46 -0
- package/benchmarks/results/pr-303-review-2026-10-13/diagnostics/verify-gate-diagnosis.md +13 -0
- package/benchmarks/results/pr-303-review-2026-10-13/diagnostics/verify-gate.json +46 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/summary.json +57 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-collision.log +8 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-consistency.log +624 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-docs-capabilities.log +131 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-platform-compatibility.log +9 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-plugin-openai.log +6 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-plugin-submission.log +5 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-references.log +6 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-release.log +73 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-repo-contract.log +5 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-routing-invariants.log +785 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/contracts/test-routing-skills.log +44 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/final-fast/summary.json +12 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/final-fast/test-consistency.log +624 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/final-fast/test-release.log +73 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/heavy/summary.json +79 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/heavy/test-mechanism.log +1737 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/heavy/test-mutations.log +16 -0
- package/benchmarks/results/pr-303-review-2026-10-13/gates/heavy/test.log +3297 -0
- package/benchmarks/results/pr-303-review-2026-10-13/manifest.json +319 -0
- package/benchmarks/results/pr-303-review-2026-10-13/regression/binding-resolution-green.log +36 -0
- package/benchmarks/results/pr-303-review-2026-10-13/regression/determinism.json +174 -0
- package/benchmarks/results/pr-303-review-2026-10-13/regression/quality-evidence.json +314 -0
- package/benchmarks/results/pr-303-review-2026-10-13/regression/quality-report.json +638 -0
- package/benchmarks/results/pr-303-review-2026-10-13/regression/red.log +240 -0
- package/benchmarks/results/pr-303-review-2026-10-13/regression/untyped-fable-probe.json +22 -0
- package/benchmarks/results/pr-303-review-2026-10-13/regression/workflow-obligations-green.log +254 -0
- package/benchmarks/results/pr-303-review-2026-10-13/verification/mechanism-35-clean-env-fixed.log +1 -0
- package/benchmarks/results/pr-303-review-2026-10-13/verification/mechanism-35-inherited-flag-fixed.log +1 -0
- package/benchmarks/results/pr-303-review-2026-10-13/verification/nested-test.meta.json +8 -0
- package/benchmarks/results/pr-303-review-2026-10-13/verification/nested-test.stderr.log +90 -0
- package/benchmarks/results/pr-303-review-2026-10-13/verification/nested-test.stdout.log +3186 -0
- package/benchmarks/results/pr-303-review-2026-10-13/verification/verify-gate-final.json +46 -0
- package/bin/cli.js +1 -1
- package/ci/doc-capability-consistency.test.js +11 -1
- package/ci/invariant-routing.test.js +7 -4
- package/ci/mechanism-2ag-router-worktree-contract.test.js +2 -2
- package/ci/mechanism-2ai-workspace-fingerprint-batch.test.js +2 -1
- package/ci/mechanism-2al-codex-hooks-compat.test.js +19 -0
- package/ci/mechanism-2am-observations-session-import.test.js +221 -0
- package/ci/mechanism-2an-workflow-obligations.test.js +352 -3
- package/ci/mechanism-2ao-plugin-sync.test.js +129 -4
- package/ci/mechanism-2aq-fable-stage-bindings.test.js +168 -0
- package/ci/mechanism-2ar-binding-resolution.test.js +211 -0
- package/ci/mechanism-2w-platform-compatibility.test.js +12 -0
- package/ci/mechanism-34-observations.test.js +64 -0
- package/ci/mechanism-35-verification-contract.test.js +1 -1
- package/ci/mutation-check.js +2 -0
- package/ci/mutation-loader.js +4 -0
- package/ci/openai-plugin-package.test.js +7 -5
- package/ci/prompt-contract-regressions.test.js +7 -6
- package/ci/router-workflow-plan.test.js +109 -14
- package/ci/skill-routing-check.js +44 -15
- package/ci/workflow-plan-consumers.test.js +41 -1
- package/docs/architecture.md +10 -10
- package/docs/enforcement-locks.md +1 -1
- package/docs/mechanism-first-skill-mesh.md +12 -11
- package/docs/openai-plugin.md +1 -1
- package/docs/philosophy.md +7 -6
- package/docs/platform-capabilities.md +14 -12
- package/docs/platform-compatibility.json +5 -5
- package/docs/routing.md +16 -17
- package/docs/system-one-observations.md +36 -9
- package/docs/system-one-routing.md +10 -7
- package/docs/system-one-suggestion-gates.md +5 -5
- package/docs/workflow-runtime.md +6 -2
- package/docs/workflows/harness-everything.md +14 -14
- 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/fable-mode/CONTRACT-FORMAT.md +4 -1
- package/fable-mode/SKILL.md +6 -8
- package/fable-mode/agents/fable-orchestrator.md +10 -3
- 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 +101 -2
- package/harness-everything/SKILL.md +8 -7
- package/harness-everything/references/router-workflow-plan.md +11 -6
- package/harness-everything/references/triage-and-tiers.md +21 -23
- package/harness-everything/schemas/router-workflow-plan.schema.json +2 -0
- package/harness-everything/scripts/kernel-router-core.js +52 -55
- package/harness-everything/scripts/kernel-router.js +48 -5
- package/harness-everything/scripts/router-contract-core.js +7 -7
- package/harness-everything/scripts/router-contract.js +1 -3
- package/harness-everything/scripts/routing-keywords.json +417 -121
- package/harness-everything/scripts/tier-router.js +64 -113
- package/hooks/scripts/contract-test.js +29 -3
- package/hooks/scripts/lib/binding-resolver.js +76 -0
- package/hooks/scripts/lib/fable-contracts.js +1 -1
- package/hooks/scripts/lib/observations.js +88 -12
- package/hooks/scripts/lib/workflow-obligations.js +292 -7
- package/hooks/scripts/lib/workflow-runtime.js +8 -1
- package/hooks/scripts/workflow-disposition.js +116 -2
- package/opencode-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
- package/plugins/harness-everything/hooks/scripts/contract-test.js +29 -3
- package/plugins/harness-everything/hooks/scripts/lib/binding-resolver.js +76 -0
- package/plugins/harness-everything/hooks/scripts/lib/fable-contracts.js +1 -1
- package/plugins/harness-everything/hooks/scripts/lib/observations.js +88 -12
- package/plugins/harness-everything/hooks/scripts/lib/workflow-obligations.js +292 -7
- package/plugins/harness-everything/hooks/scripts/lib/workflow-runtime.js +8 -1
- package/plugins/harness-everything/hooks/scripts/workflow-disposition.js +116 -2
- package/plugins/harness-everything/plugin.json +1 -1
- package/plugins/harness-everything/scripts/lib/advisory-text.js +2 -2
- package/plugins/harness-everything/scripts/lib/generated-skills.js +78 -0
- package/plugins/harness-everything/skills/fable-mode/CONTRACT-FORMAT.md +4 -1
- package/plugins/harness-everything/skills/fable-mode/SKILL.md +6 -8
- package/plugins/harness-everything/skills/fable-mode/agents/fable-orchestrator.md +10 -3
- 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 +101 -2
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +8 -7
- package/plugins/harness-everything/skills/harness-everything/references/router-workflow-plan.md +11 -6
- package/plugins/harness-everything/skills/harness-everything/references/triage-and-tiers.md +21 -23
- package/plugins/harness-everything/skills/harness-everything/schemas/router-workflow-plan.schema.json +2 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router-core.js +52 -55
- package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router.js +48 -5
- package/plugins/harness-everything/skills/harness-everything/scripts/router-contract-core.js +7 -7
- package/plugins/harness-everything/skills/harness-everything/scripts/router-contract.js +1 -3
- package/plugins/harness-everything/skills/harness-everything/scripts/routing-keywords.json +417 -121
- package/plugins/harness-everything/skills/harness-everything/scripts/tier-router.js +64 -113
- package/sbom.cdx.json +7 -7
- package/scripts/codex-hooks-compat.js +39 -14
- package/scripts/lib/advisory-text.js +2 -2
- package/scripts/lib/generated-skills.js +78 -0
- package/scripts/plugin-sync.js +100 -29
- package/scripts/system-one-observations-export.js +29 -2
- package/scripts/system-one-observations-import-codex-sessions.js +307 -0
- package/scripts/system-one-observations-review.js +11 -1
|
@@ -27,7 +27,6 @@ const INVARIANT_TEXT = {
|
|
|
27
27
|
'verify-before-claim': 'MUST verify before claim with objective evidence appropriate to the change.',
|
|
28
28
|
'visible-status-updates': 'MUST render the single Markdown Harness Status with a visible heading, bullet-aligned bold labels, Current, Read / Evidence, and Next; add Risk / Blocked only when materially applicable.',
|
|
29
29
|
'replan-after-repeated-failure': 'MUST stop micro-retrying after 3 same-signature failures and zoom out/re-diagnose.',
|
|
30
|
-
'evaluate-suggestions-before-skip': 'MUST read/evaluate each suggested skill\'s complete SKILL.md entry/basic flow before omission; an applicable skill core contract MUST be followed.',
|
|
31
30
|
'loop-awareness': 'MUST reconsider assumptions/re-plan when evidence shows iterative stagnation; numeric iteration values MAY guide but never hard-stop.',
|
|
32
31
|
'objective-verification': 'MUST use an objective check for iterative work; self-critique alone is not verification.',
|
|
33
32
|
'stage-contracts': 'When Fable is selected, stages MUST have explicit stage contracts and pass conditions.',
|
|
@@ -43,16 +42,6 @@ const INVARIANT_TEXT = {
|
|
|
43
42
|
'isolated-worktree-before-mutation': 'Tier-3/Fable broad mutation MUST resolve isolation: verified linked worktree or explicit degraded fallback.',
|
|
44
43
|
};
|
|
45
44
|
|
|
46
|
-
const SKILL_TEXT = {
|
|
47
|
-
'tdd': 'tdd: useful for behavioral changes where executable tests can drive the implementation.',
|
|
48
|
-
'verification-loop': 'verification-loop: useful for systematic build/lint/test/diff evidence before delivery.',
|
|
49
|
-
'using-git-worktrees': 'using-git-worktrees: resolves required Tier-3/Fable isolation disposition before broad mutation.',
|
|
50
|
-
'fable-mode': 'fable-mode / fable-discipline: useful for macro planning or deliberate multi-agent decomposition.',
|
|
51
|
-
'fable-discipline': null,
|
|
52
|
-
'multi-agent-workspace': 'multi-agent-workspace: useful when durable bounded delegation, handoffs, or workspace memory are required.',
|
|
53
|
-
'self-evolve': 'self-evolve: classify an evidence-backed lesson and use the authorized memory persistence path.',
|
|
54
|
-
};
|
|
55
|
-
|
|
56
45
|
function sanitizeClassifierOutput(stdout) {
|
|
57
46
|
const lines = String(stdout || '').split(/\r?\n/);
|
|
58
47
|
const filtered = [];
|
|
@@ -121,25 +110,12 @@ function printWorkflowPlan(plan) {
|
|
|
121
110
|
fallback: plan.fallback,
|
|
122
111
|
reasonCodes: plan.reasonCodes,
|
|
123
112
|
requiredInvariants: plan.requiredInvariants,
|
|
124
|
-
|
|
113
|
+
knowledgeSignals: plan.knowledgeSignals,
|
|
125
114
|
mutationIsolation: plan.mutationIsolation,
|
|
126
115
|
};
|
|
127
116
|
console.log(`\n=> ROUTER WORKFLOW PLAN (JSON): ${JSON.stringify(visible)}`);
|
|
128
117
|
}
|
|
129
118
|
|
|
130
|
-
function uniqueSuggestedSkills(plan) {
|
|
131
|
-
if (!Array.isArray(plan.suggestedSkills)) return [];
|
|
132
|
-
return [...new Set(plan.suggestedSkills.filter(skill => typeof skill === 'string' && skill.trim()))];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function enforceSuggestionEvaluation(plan) {
|
|
136
|
-
if (uniqueSuggestedSkills(plan).length === 0) return;
|
|
137
|
-
if (!Array.isArray(plan.requiredInvariants)) plan.requiredInvariants = [];
|
|
138
|
-
if (!plan.requiredInvariants.includes('evaluate-suggestions-before-skip')) {
|
|
139
|
-
plan.requiredInvariants.push('evaluate-suggestions-before-skip');
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
119
|
function displayTier(tier) {
|
|
144
120
|
if (tier === 'tier1') return 'Tier 1';
|
|
145
121
|
if (tier === 'tier2') return 'Tier 2';
|
|
@@ -149,19 +125,14 @@ function displayTier(tier) {
|
|
|
149
125
|
|
|
150
126
|
function printRoutingCheckpoint(plan) {
|
|
151
127
|
const invariants = Array.isArray(plan.requiredInvariants) ? plan.requiredInvariants : [];
|
|
152
|
-
const
|
|
128
|
+
const signals = Array.isArray(plan.knowledgeSignals) ? plan.knowledgeSignals : [];
|
|
153
129
|
|
|
154
130
|
console.log('\n=> HARNESS ROUTING CHECKPOINT (INTERNAL SOURCE STATE — DO NOT RENDER SEPARATELY):');
|
|
155
131
|
console.log(` - Tier: ${displayTier(plan.tier)}`);
|
|
156
132
|
console.log(` - Strategy: ${plan.strategy || 'deferred'}`);
|
|
157
133
|
console.log(` - Required invariants: ${invariants.length ? invariants.join(', ') : 'none'}`);
|
|
158
|
-
console.log(` -
|
|
159
|
-
console.log(' - User-visible progress: use this checkpoint as source state for the single Harness Status contract below
|
|
160
|
-
if (suggestions.length > 0) {
|
|
161
|
-
console.log(' - Suggestion evaluation: MANDATORY. Before skipping any listed skill, read its complete SKILL.md entry and evaluate USE FOR, DO NOT USE FOR, workflow/basic flow, and hard rules.');
|
|
162
|
-
console.log(' - Skip evidence: do not reject from only the skill name, description, router summary, or a generic "routine/common task" judgement. If the entry cannot be resolved/read, mark it unresolved/unavailable rather than skipped.');
|
|
163
|
-
console.log(' - Suggestion disposition: applicability is conditional, but resolution is mandatory. If a skill is applicable, follow its core contract; if not-applicable, keep one brief flow-grounded reason. The selected workflow is a semantic execution contract, not optional advice.');
|
|
164
|
-
}
|
|
134
|
+
console.log(` - Knowledge signals: ${signals.length ? signals.join(', ') : 'none'} (planning input only; not document selectors)`);
|
|
135
|
+
console.log(' - User-visible progress: use this checkpoint as source state for the single Harness Status contract below.');
|
|
165
136
|
}
|
|
166
137
|
|
|
167
138
|
function printKernelContract(plan) {
|
|
@@ -170,6 +141,11 @@ function printKernelContract(plan) {
|
|
|
170
141
|
console.log(` - ${invariant}: ${INVARIANT_TEXT[invariant] || 'Required by the selected workflow plan.'}`);
|
|
171
142
|
}
|
|
172
143
|
|
|
144
|
+
if (plan.strategy && ['tier2', 'tier3'].includes(plan.tier)) {
|
|
145
|
+
console.log('\n=> PLANNING STEP: decompose → compose');
|
|
146
|
+
console.log(' - Define ordered requirement steps and their bindings before starting execution.');
|
|
147
|
+
}
|
|
148
|
+
|
|
173
149
|
console.log('\n=> USER-VISIBLE HARNESS STATUS CONTRACT (MUST):');
|
|
174
150
|
console.log(' - For non-trivial software/project work, the agent MUST render this single Markdown status shape:');
|
|
175
151
|
console.log(' ### 🚦 Harness Status');
|
|
@@ -184,26 +160,10 @@ function printKernelContract(plan) {
|
|
|
184
160
|
console.log(' - Emit it before substantive execution, after a major phase, when direction materially changes, at meaningful long-running phase boundaries, and before final completion (the final response may merge it naturally).');
|
|
185
161
|
console.log(' - This is a semantic communication MUST, not a hard execution lock, counter, or reset condition.');
|
|
186
162
|
|
|
187
|
-
console.log('\n=>
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (emitted.has(skill)) continue;
|
|
192
|
-
const text = Object.prototype.hasOwnProperty.call(SKILL_TEXT, skill) ? SKILL_TEXT[skill] : `${skill}: evaluate applicability inside the selected topology.`;
|
|
193
|
-
if (text) console.log(` - ${text}`);
|
|
194
|
-
emitted.add(skill);
|
|
195
|
-
if (skill === 'fable-mode') emitted.add('fable-discipline');
|
|
196
|
-
}
|
|
197
|
-
if (plan.strategy && plan.strategy.startsWith('fable-')) {
|
|
198
|
-
console.log(' - Fable is not a universal pipeline, but a selected Fable topology must be entered and resolved before completion.');
|
|
199
|
-
}
|
|
200
|
-
} else if (plan.strategy === 'direct-single') {
|
|
201
|
-
console.log(' - No domain skill was suggested. The bounded direct path SHOULD remain minimal; a focused skill MAY be loaded when it adds value.');
|
|
202
|
-
} else if (plan.strategySelection === 'deferred') {
|
|
203
|
-
console.log(' - Strategy is deferred/unclassified. Do not infer triviality; choose the smallest justified approach from task evidence.');
|
|
204
|
-
} else {
|
|
205
|
-
console.log(' - No additional skill suggestion from the workflow plan.');
|
|
206
|
-
}
|
|
163
|
+
console.log('\n=> ACTIVE-STEP KNOWLEDGE BINDINGS (MUST):');
|
|
164
|
+
console.log(' - Compose ordered requirement steps before execution. Each step declares the required/optional skills or references for that step.');
|
|
165
|
+
console.log(' - MUST load/resolve only bindings declared for the active step; future-step bindings remain undisclosed until that step becomes active.');
|
|
166
|
+
console.log(' - A required binding MUST be loaded and its core contract followed before the active step passes. An unknown/unavailable binding stays visible and unresolved; it does not hard-block ordinary tools or Stop.');
|
|
207
167
|
|
|
208
168
|
if (plan.ensemble) {
|
|
209
169
|
console.log(`\n=> ENSEMBLE REVIEW: bounded to ${plan.ensemble.maxCandidates} candidates; synthesis=${plan.ensemble.synthesis}; verifier=${plan.ensemble.verifier}. Preserve minority positions and do not claim improvement without paired evidence.`);
|
|
@@ -224,6 +184,44 @@ function printKernelContract(plan) {
|
|
|
224
184
|
console.log('\n=> ORCHESTRATION POLICY: Selected-topology required obligations and applicable skill core contracts are semantic MUSTs; implementation tactics MAY adapt. Lifecycle hooks observe/remind rather than hard-block, except user/host permission boundaries and the Rule-of-3 zoom-out.');
|
|
225
185
|
}
|
|
226
186
|
|
|
187
|
+
function printRetainedWorkflow(plan, workflow, activeStep = null, activeStages = []) {
|
|
188
|
+
const invariants = Array.isArray(workflow?.requiredInvariants) ? workflow.requiredInvariants : plan.requiredInvariants || [];
|
|
189
|
+
const state = workflow?.state || 'unknown';
|
|
190
|
+
console.log('\n=> RETAINED EXECUTION CONTRACT (COMPACT):');
|
|
191
|
+
console.log(` - Workflow: ${workflow?.workflowId || 'unavailable'}; state=${state}; tier=${displayTier(workflow?.tier || plan.tier)}; strategy=${workflow?.strategy || plan.strategy || 'deferred'}.`);
|
|
192
|
+
console.log(` - Invariants remain active: ${invariants.length ? invariants.join(', ') : 'none'}.`);
|
|
193
|
+
console.log(` - Action gate: ${plan.actionGate?.required ? `MUST remain ${plan.actionGate.disposition} (${plan.actionGate.reasonCodes.join(', ')})` : 'not required'}.`);
|
|
194
|
+
console.log(` - Isolation: ${plan.mutationIsolation?.required ? 'MUST be resolved before broad mutation; missing host evidence remains visible, not a tool lock' : 'no topology-level isolation requirement'}.`);
|
|
195
|
+
if (activeStages.length) {
|
|
196
|
+
console.log(` - Active Fable stage${activeStages.length === 1 ? '' : 's'}: ${activeStages.map(stage => `${stage.stageId} [${stage.status}]`).join(', ')}.`);
|
|
197
|
+
for (const stage of activeStages) {
|
|
198
|
+
console.log(` - ${stage.stageId}: ${stage.goal}`);
|
|
199
|
+
for (const kind of ['requiredBindings', 'optionalBindings']) {
|
|
200
|
+
const bindings = stage[kind] || [];
|
|
201
|
+
if (bindings.length) {
|
|
202
|
+
console.log(` - ${kind === 'requiredBindings' ? 'Required' : 'Optional'}: ${bindings.map(binding => `${binding.id} [${binding.status}; ${binding.path || 'path unavailable'}]`).join(', ')}.`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
console.log(' - Future-stage bindings remain undisclosed until their dependencies pass.');
|
|
207
|
+
} else if (activeStep) {
|
|
208
|
+
console.log(` - Active step: ${activeStep.id} (${activeStep.stepType}) — ${activeStep.summary}; status=${activeStep.status}.`);
|
|
209
|
+
for (const kind of ['requiredBindings', 'optionalBindings']) {
|
|
210
|
+
const bindings = activeStep[kind] || [];
|
|
211
|
+
if (bindings.length) {
|
|
212
|
+
console.log(` - ${kind === 'requiredBindings' ? 'Required' : 'Optional'} active bindings: ${bindings.map(binding => `${binding.id} [${binding.status}; ${binding.path || 'path unavailable'}]`).join(', ')}.`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
console.log(' - Do not resolve, load, or disclose bindings for future steps yet.');
|
|
216
|
+
} else if (String(workflow?.strategy || plan.strategy || '').startsWith('fable-')) {
|
|
217
|
+
console.log(' - No dependency-ready Fable stage bindings are currently available.');
|
|
218
|
+
} else {
|
|
219
|
+
console.log(' - Active step: planning/execution obligations; step bindings are not composed or started yet.');
|
|
220
|
+
}
|
|
221
|
+
console.log(' - Harness Status stays MUST: one block with Current, Read / Evidence, and Next; add Risk / Blocked only when material. Turn label stays MUST.');
|
|
222
|
+
console.log(' - Permission boundary and Rule-of-3 remain active; this reminder is non-blocking.');
|
|
223
|
+
}
|
|
224
|
+
|
|
227
225
|
function route(prompt, stdinPayload) {
|
|
228
226
|
const classifierPath = path.join(__dirname, 'tier-router.js');
|
|
229
227
|
const contractPath = path.join(os.tmpdir(), `harness-router-${process.pid}-${crypto.randomUUID()}.json`);
|
|
@@ -244,7 +242,6 @@ function route(prompt, stdinPayload) {
|
|
|
244
242
|
|
|
245
243
|
const contract = readStructuredContract(contractPath);
|
|
246
244
|
applyEnsemblePolicy(contract, resolvePrompt(prompt, stdinPayload));
|
|
247
|
-
enforceSuggestionEvaluation(contract.workflowPlan);
|
|
248
245
|
try {
|
|
249
246
|
fs.rmSync(contractPath, { force: true });
|
|
250
247
|
} catch (err) {
|
|
@@ -279,4 +276,4 @@ if (prompt) {
|
|
|
279
276
|
}
|
|
280
277
|
}
|
|
281
278
|
|
|
282
|
-
module.exports = { route, printWorkflowPlan, printRoutingCheckpoint, printKernelContract };
|
|
279
|
+
module.exports = { route, printWorkflowPlan, printRoutingCheckpoint, printKernelContract, printRetainedWorkflow };
|
|
@@ -105,6 +105,27 @@ function persistWorkflow(contract, payload, prompt) {
|
|
|
105
105
|
return { ...context, hooksRoot, retained: false, memoryCapability };
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
function activeExecutionFor(persisted, plan) {
|
|
109
|
+
if (!persisted?.workflow || !persisted.hooksRoot) return null;
|
|
110
|
+
try {
|
|
111
|
+
if (String(persisted.workflow.strategy || '').startsWith('fable-')) {
|
|
112
|
+
const runtime = require(path.join(persisted.hooksRoot, 'lib/workflow-runtime'));
|
|
113
|
+
const match = runtime.matchingRun(persisted);
|
|
114
|
+
if (!match) return { activeStages: [] };
|
|
115
|
+
for (const relative of ['../../fable-mode/scripts/workflow-plan-consumer.js', '../../skills/fable-mode/scripts/workflow-plan-consumer.js']) {
|
|
116
|
+
const file = path.resolve(__dirname, relative);
|
|
117
|
+
if (fs.existsSync(file)) return { activeStages: require(file).activeStageBindings(match.runRoot, persisted.workflow.escapes) };
|
|
118
|
+
}
|
|
119
|
+
return { activeStages: [] };
|
|
120
|
+
}
|
|
121
|
+
const obligations = require(path.join(persisted.hooksRoot, 'lib/workflow-obligations'));
|
|
122
|
+
const loaded = obligations.loadObligationSet(persisted, plan);
|
|
123
|
+
return { activeStep: loaded.set ? obligations.activeStepSnapshot(loaded.set) : null };
|
|
124
|
+
} catch (_) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
108
129
|
// Printed last so it is the nearest instruction when the turn ends (docs/system-one-observations.md#label-line).
|
|
109
130
|
function printLabelContract() {
|
|
110
131
|
console.log('\n=> TURN LABEL LINE (MUST, EVERY TURN — short answers, lookups and trivial edits included):');
|
|
@@ -134,14 +155,35 @@ function run(raw) {
|
|
|
134
155
|
if (persisted?.retained && persisted.workflow) plan = persisted.workflow.workflowPlan;
|
|
135
156
|
} catch (error) { failure = error; }
|
|
136
157
|
if (hostNotification && !persisted?.workflow) {
|
|
137
|
-
console.log('\n=> Host notification
|
|
158
|
+
console.log('\n=> Host notification: no active execution contract; ignored for routing.');
|
|
159
|
+
if (failure) console.error('[Workflow Reminder] routing state was not persisted: ' + failure.message);
|
|
160
|
+
printLabelContract();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (persisted?.retained && persisted.workflow) {
|
|
164
|
+
if (persisted.hostNotification) console.log('\n=> Host notification: routing unchanged; keeping the active execution contract.');
|
|
165
|
+
else console.log('\n=> Retaining unresolved workflow; showing its compact active contract.');
|
|
166
|
+
const activeExecution = activeExecutionFor(persisted, plan) || {};
|
|
167
|
+
const activeStep = activeExecution.activeStep || null;
|
|
168
|
+
const activeStages = activeExecution.activeStages || [];
|
|
169
|
+
core.printRetainedWorkflow(plan, persisted.workflow, activeStep, activeStages);
|
|
170
|
+
if (activeStep) {
|
|
171
|
+
const controller = path.join(persisted.hooksRoot, 'workflow-disposition.js');
|
|
172
|
+
console.log(' - Resolve only bindings for this active step, then pass this step with evidence.');
|
|
173
|
+
console.log(' - Controller: ' + controller + '; session: ' + persisted.sessionId + '; step: ' + activeStep.id + '.');
|
|
174
|
+
console.log(' - Resolve binding: node "' + controller + '" binding --session-id "' + persisted.sessionId + '" --step-id "' + activeStep.id + '" --binding-id "<active-binding-id>" --disposition <loaded|not-needed|unavailable> --evidence "<binding evidence>"');
|
|
175
|
+
console.log(' - Pass step: node "' + controller + '" step --session-id "' + persisted.sessionId + '" --step-id "' + activeStep.id + '" --disposition pass --evidence "<completion evidence>"');
|
|
176
|
+
} else if (activeStages.length) {
|
|
177
|
+
const controller = path.join(persisted.hooksRoot, 'workflow-disposition.js');
|
|
178
|
+
console.log(' - Resolve only declared bindings with stage-binding --stage-id <active-stage> --binding-id <binding> --disposition <loaded|not-needed|unavailable> --evidence <evidence>.');
|
|
179
|
+
console.log(' - Controller: ' + controller + '; session: ' + persisted.sessionId + '.');
|
|
180
|
+
}
|
|
181
|
+
printLabelContract();
|
|
138
182
|
if (failure) console.error('[Workflow Reminder] routing state was not persisted: ' + failure.message);
|
|
139
183
|
return;
|
|
140
184
|
}
|
|
141
185
|
if (result?.sanitized) console.log(result.sanitized);
|
|
142
186
|
if (result?.stderr) process.stderr.write(result.stderr);
|
|
143
|
-
if (persisted?.hostNotification) console.log('\n=> Host notification — routing unchanged; keeping the active execution contract.');
|
|
144
|
-
else if (persisted?.retained) console.log('\n=> Retaining unresolved workflow from earlier prompts; the checkpoint below is the active execution contract.');
|
|
145
187
|
core.printWorkflowPlan(plan);
|
|
146
188
|
core.printRoutingCheckpoint(plan);
|
|
147
189
|
core.printKernelContract(plan);
|
|
@@ -163,7 +205,8 @@ function run(raw) {
|
|
|
163
205
|
if (plan.strategySelection === 'selected' && ['tier2', 'tier3'].includes(plan.tier)) {
|
|
164
206
|
console.log(' - Planning contract: ' + path.join(persisted.sessionDir, 'workflow-obligations.json'));
|
|
165
207
|
console.log(' - Requirements first: decompose intent into requirement fragments, then confirm the smallest sufficient workflow.');
|
|
166
|
-
console.log(' - Record
|
|
208
|
+
console.log(' - Record ordered step types (review, behavior-change, verification, commit) and their bindings before execution.');
|
|
209
|
+
console.log(' - Record plan: node "' + controller + '" plan --session-id "' + persisted.sessionId + '" --requirements-json "[{\\"id\\":\\"req-1\\",\\"stepType\\":\\"behavior-change\\",\\"summary\\":\\"...\\",\\"acceptance\\":\\"...\\"},{\\"id\\":\\"req-verify\\",\\"stepType\\":\\"verification\\",\\"summary\\":\\"...\\",\\"acceptance\\":\\"...\\"}]" --strategy "' + plan.strategy + '" --evidence "<why this workflow fits>"');
|
|
167
210
|
}
|
|
168
211
|
console.log(' - Enter selected workflow after planning: node "' + controller + '" start --session-id "' + persisted.sessionId + '"');
|
|
169
212
|
console.log(' - Escape one declared stage: node "' + controller + '" escape --session-id "' + persisted.sessionId + '" --stage-id "<id>" --reason-code workflow-uncovered-scope --scope "<uncovered scope>" --evidence "<evidence>"');
|
|
@@ -175,7 +218,7 @@ function run(raw) {
|
|
|
175
218
|
if (result && result.status !== 0) console.error('[Workflow Reminder] router returned status ' + result.status + '; contract observation is degraded, not blocking.');
|
|
176
219
|
}
|
|
177
220
|
|
|
178
|
-
if (typeof module !== 'undefined') module.exports = { isHostNotificationPrompt };
|
|
221
|
+
if (typeof module !== 'undefined') module.exports = { isHostNotificationPrompt, activeExecutionFor };
|
|
179
222
|
|
|
180
223
|
if (process.argv.length > 2 || process.stdin.isTTY) run('');
|
|
181
224
|
else { let input = '';
|
package/plugins/harness-everything/skills/harness-everything/scripts/router-contract-core.js
CHANGED
|
@@ -327,6 +327,7 @@ function planMetadataForStrategy(strategy) {
|
|
|
327
327
|
patterns: ['router'],
|
|
328
328
|
requiredInvariants: ['scope-lock', 'environment-alignment', 'verify-before-claim', 'replan-after-repeated-failure', 'visible-status-updates'],
|
|
329
329
|
suggestedSkills: [],
|
|
330
|
+
knowledgeSignals: [],
|
|
330
331
|
maxIterations: null,
|
|
331
332
|
parallelAllowed: null,
|
|
332
333
|
parallelReasonCodes: [],
|
|
@@ -355,7 +356,6 @@ function planMetadataForStrategy(strategy) {
|
|
|
355
356
|
...base,
|
|
356
357
|
patterns: ['router', 'react'],
|
|
357
358
|
requiredInvariants: [...base.requiredInvariants, 'loop-awareness', 'objective-verification'],
|
|
358
|
-
suggestedSkills: ['tdd', 'verification-loop'],
|
|
359
359
|
maxIterations: ITERATIVE_MAX_ITERATIONS,
|
|
360
360
|
parallelAllowed: false,
|
|
361
361
|
parallelReasonCodes: ['single-agent-loop'],
|
|
@@ -371,7 +371,6 @@ function planMetadataForStrategy(strategy) {
|
|
|
371
371
|
...base,
|
|
372
372
|
patterns: ['router', 'planner-executor', 'evaluator-optimizer'],
|
|
373
373
|
requiredInvariants: [...base.requiredInvariants, 'stage-contracts', 'cold-verification', 'isolated-worktree-before-mutation'],
|
|
374
|
-
suggestedSkills: ['using-git-worktrees', 'fable-mode', 'fable-discipline', 'verification-loop'],
|
|
375
374
|
parallelAllowed: false,
|
|
376
375
|
parallelReasonCodes: ['dependent-or-unproven-independent-stages'],
|
|
377
376
|
workspaceRequired: false,
|
|
@@ -386,7 +385,6 @@ function planMetadataForStrategy(strategy) {
|
|
|
386
385
|
...base,
|
|
387
386
|
patterns: ['router', 'planner-executor', 'evaluator-optimizer'],
|
|
388
387
|
requiredInvariants: [...base.requiredInvariants, 'stage-contracts', 'cold-verification', 'isolated-worktree-before-mutation', 'parallel-scope-contract', 'synthesis-barrier'],
|
|
389
|
-
suggestedSkills: ['using-git-worktrees', 'fable-mode', 'fable-discipline', 'verification-loop'],
|
|
390
388
|
parallelAllowed: true,
|
|
391
389
|
parallelReasonCodes: ['independent-read-only-or-disjoint-scopes'],
|
|
392
390
|
workspaceRequired: false,
|
|
@@ -401,7 +399,6 @@ function planMetadataForStrategy(strategy) {
|
|
|
401
399
|
...base,
|
|
402
400
|
patterns: ['router', 'planner-executor', 'evaluator-optimizer', 'multi-agent-memory'],
|
|
403
401
|
requiredInvariants: [...base.requiredInvariants, 'stage-contracts', 'cold-verification', 'isolated-worktree-before-mutation', 'handoff-contracts', 'workspace-state'],
|
|
404
|
-
suggestedSkills: ['using-git-worktrees', 'multi-agent-workspace', 'fable-mode', 'fable-discipline', 'verification-loop'],
|
|
405
402
|
parallelAllowed: false,
|
|
406
403
|
parallelReasonCodes: ['workspace-orchestrator-controls-concurrency'],
|
|
407
404
|
workspaceRequired: true,
|
|
@@ -427,13 +424,12 @@ function buildWorkflowPlan(input = {}) {
|
|
|
427
424
|
|
|
428
425
|
const requiredInvariants = [...meta.requiredInvariants];
|
|
429
426
|
const patterns = [...meta.patterns];
|
|
430
|
-
const
|
|
427
|
+
const knowledgeSignals = Array.from(new Set((input.knowledgeSignals || []).filter(value => typeof value === 'string' && value.trim())));
|
|
431
428
|
const memoryPersistenceRequested = Boolean(taskShape.observedSignals && taskShape.observedSignals.memoryPersistenceRequested);
|
|
432
429
|
const memoryProhibited = Boolean(taskShape.explicitRequest && taskShape.explicitRequest.prohibitions && taskShape.explicitRequest.prohibitions.includes('memory'));
|
|
433
430
|
const memoryWrite = memoryProhibited ? 'none' : (memoryPersistenceRequested ? 'persist-via-self-evolve' : meta.memoryWrite);
|
|
434
431
|
if (memoryPersistenceRequested && !memoryProhibited) {
|
|
435
432
|
requiredInvariants.push('memory-write-authorization');
|
|
436
|
-
suggestedSkills.push('self-evolve');
|
|
437
433
|
}
|
|
438
434
|
if (actionGateRequired) {
|
|
439
435
|
requiredInvariants.push('pre-action-approval');
|
|
@@ -467,7 +463,8 @@ function buildWorkflowPlan(input = {}) {
|
|
|
467
463
|
strategySelection: selection.strategySelection,
|
|
468
464
|
patterns: Array.from(new Set(patterns)),
|
|
469
465
|
requiredInvariants: Array.from(new Set(requiredInvariants)),
|
|
470
|
-
suggestedSkills:
|
|
466
|
+
suggestedSkills: [],
|
|
467
|
+
knowledgeSignals,
|
|
471
468
|
actionGate: {
|
|
472
469
|
required: actionGateRequired,
|
|
473
470
|
reasonCodes: actionGateReasonCodes,
|
|
@@ -527,6 +524,7 @@ function buildRouterContract(input = {}) {
|
|
|
527
524
|
routingStatus: input.routingStatus,
|
|
528
525
|
tier,
|
|
529
526
|
taskShape,
|
|
527
|
+
knowledgeSignals: input.knowledgeSignals,
|
|
530
528
|
actionGateReasonCodes: input.actionGateReasonCodes,
|
|
531
529
|
reasonCodes,
|
|
532
530
|
});
|
|
@@ -570,6 +568,8 @@ function validateWorkflowPlan(plan) {
|
|
|
570
568
|
if (plan.strategySelection === 'deferred' && plan.strategy !== null) errors.push('deferred strategy must be null');
|
|
571
569
|
if (!Array.isArray(plan.requiredInvariants)) errors.push('requiredInvariants must be an array');
|
|
572
570
|
if (!Array.isArray(plan.suggestedSkills)) errors.push('suggestedSkills must be an array');
|
|
571
|
+
if (!Array.isArray(plan.knowledgeSignals) || plan.knowledgeSignals.some(value => typeof value !== 'string' || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(value)) ||
|
|
572
|
+
new Set(plan.knowledgeSignals).size !== plan.knowledgeSignals.length) errors.push('knowledgeSignals must be unique normalized signal ids');
|
|
573
573
|
if (!plan.actionGate || typeof plan.actionGate.required !== 'boolean') errors.push('actionGate.required must be boolean');
|
|
574
574
|
if (plan.actionGate && plan.actionGate.required && plan.actionGate.disposition !== 'pending-approval') errors.push('required actionGate must be pending-approval before execution');
|
|
575
575
|
if (!plan.limits || !Object.prototype.hasOwnProperty.call(plan.limits, 'maxIterations')) errors.push('limits.maxIterations is required');
|
|
@@ -12,10 +12,8 @@ function isMajorWorkflow(plan) {
|
|
|
12
12
|
function augmentWorkflowPlan(plan) {
|
|
13
13
|
if (!plan || !isMajorWorkflow(plan)) return plan;
|
|
14
14
|
const requiredInvariants = Array.isArray(plan.requiredInvariants) ? [...plan.requiredInvariants] : [];
|
|
15
|
-
const suggestedSkills = Array.isArray(plan.suggestedSkills) ? [...plan.suggestedSkills] : [];
|
|
16
15
|
if (!requiredInvariants.includes('isolated-worktree-before-mutation')) requiredInvariants.push('isolated-worktree-before-mutation');
|
|
17
|
-
|
|
18
|
-
return { ...plan, requiredInvariants, suggestedSkills, mutationIsolation: {
|
|
16
|
+
return { ...plan, requiredInvariants, mutationIsolation: {
|
|
19
17
|
required: true, mechanism: 'git-worktree', transition: 'before-first-mutation', onUnavailable: 'degraded',
|
|
20
18
|
} };
|
|
21
19
|
}
|