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
|
@@ -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 = '';
|
|
@@ -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
|
}
|