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
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Metadata-only lookup of self-evolved skills registered in Harness
|
|
4
|
+
// manifests. The router uses it to emit step-input signals (ids only); the
|
|
5
|
+
// workflow runtime uses it to resolve a declared binding id to its SKILL.md
|
|
6
|
+
// once the declaring step is active. Nothing here reads or injects skill text.
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
11
|
+
const STOP_TRIGGERS = new Set(['the', 'and', 'for', 'with', 'your', 'this', 'that', 'some', 'from', 'prevent', 'resolved']);
|
|
12
|
+
|
|
13
|
+
function generatedManifestPaths(workspaceRoot, homeDir = process.env.HOME || process.env.USERPROFILE || '') {
|
|
14
|
+
const paths = [];
|
|
15
|
+
if (workspaceRoot) {
|
|
16
|
+
for (const platform of ['.claude', '.cursor', '.github', '.codex', '.continue']) {
|
|
17
|
+
paths.push(path.join(workspaceRoot, platform, 'harness-everything', 'manifest.json'));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (homeDir) {
|
|
21
|
+
paths.push(path.join(homeDir, '.agents', 'harness-everything', 'manifest.json'));
|
|
22
|
+
paths.push(path.join(homeDir, '.claude', 'harness-everything', 'manifest.json'));
|
|
23
|
+
}
|
|
24
|
+
return paths;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function readGeneratedSkills(workspaceRoot, homeDir) {
|
|
28
|
+
const skills = new Map();
|
|
29
|
+
for (const manifestPath of generatedManifestPaths(workspaceRoot, homeDir)) {
|
|
30
|
+
let data;
|
|
31
|
+
try { data = JSON.parse(fs.readFileSync(manifestPath, 'utf8')); } catch (_) { continue; }
|
|
32
|
+
if (!Array.isArray(data?.generated)) continue;
|
|
33
|
+
for (const entry of data.generated) {
|
|
34
|
+
const id = typeof entry?.id === 'string' ? entry.id.trim() : '';
|
|
35
|
+
if (!SAFE_ID.test(id) || skills.has(id) || typeof entry.dirPath !== 'string' || !entry.dirPath.trim()) continue;
|
|
36
|
+
const dirPath = path.isAbsolute(entry.dirPath)
|
|
37
|
+
? entry.dirPath
|
|
38
|
+
: path.resolve(workspaceRoot || path.dirname(manifestPath), entry.dirPath);
|
|
39
|
+
skills.set(id, {
|
|
40
|
+
id,
|
|
41
|
+
dirPath,
|
|
42
|
+
triggers: Array.isArray(entry.triggers) ? entry.triggers.filter(value => typeof value === 'string') : [],
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return skills;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function triggerScore(promptLower, rawTrigger) {
|
|
50
|
+
const trigger = rawTrigger.toLowerCase().trim();
|
|
51
|
+
if (trigger.length < 2 || STOP_TRIGGERS.has(trigger)) return 0;
|
|
52
|
+
if (/[一-龥]/.test(trigger)) return promptLower.includes(trigger) ? trigger.length * 2 : 0;
|
|
53
|
+
const escaped = trigger.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
54
|
+
if (!new RegExp(`\\b${escaped}\\b`, 'i').test(promptLower)) return 0;
|
|
55
|
+
return trigger.length >= 4 ? 3 : 1.5;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Returns matching generated-skill ids, strongest match first.
|
|
59
|
+
function matchGeneratedSkills(promptLower, skills) {
|
|
60
|
+
const matched = [];
|
|
61
|
+
for (const skill of skills.values()) {
|
|
62
|
+
const score = skill.triggers.reduce((total, trigger) => total + triggerScore(promptLower, trigger), 0);
|
|
63
|
+
if (score >= 3) matched.push({ id: skill.id, score });
|
|
64
|
+
}
|
|
65
|
+
return matched.sort((a, b) => b.score - a.score).map(item => item.id);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function findGeneratedSkill(id, workspaceRoot, homeDir) {
|
|
69
|
+
if (!SAFE_ID.test(id || '')) return null;
|
|
70
|
+
return readGeneratedSkills(workspaceRoot, homeDir).get(id) || null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
generatedManifestPaths,
|
|
75
|
+
readGeneratedSkills,
|
|
76
|
+
matchGeneratedSkills,
|
|
77
|
+
findGeneratedSkill,
|
|
78
|
+
};
|
|
@@ -37,6 +37,8 @@ Every planned stage declares dependency and write scope before dispatch:
|
|
|
37
37
|
"outputPath": "path/to/artifact-or-null",
|
|
38
38
|
"dependsOn": ["stage-1"],
|
|
39
39
|
"writeSet": ["src/auth", "tests/auth.test.js"],
|
|
40
|
+
"requiredBindings": [{ "id": "tdd", "path": "tdd/SKILL.md" }],
|
|
41
|
+
"optionalBindings": [{ "id": "security-review", "path": "security-review/SKILL.md" }],
|
|
40
42
|
"checkCommand": "node --test tests/auth.test.js",
|
|
41
43
|
"passCondition": "exit 0",
|
|
42
44
|
"failureReturn": "failure summary + evidence + missing prerequisite"
|
|
@@ -48,6 +50,7 @@ Rules:
|
|
|
48
50
|
- `stageId`, `goal`, `agent`, and `task` are required.
|
|
49
51
|
- `dependsOn` is always explicit. Use `[]` for a root stage.
|
|
50
52
|
- `writeSet` is always explicit. Use `[]` for a read-only stage.
|
|
53
|
+
- `requiredBindings` and `optionalBindings` are optional arrays. Each entry is a stable `id` and may declare a concrete repository-relative `path`; paths reject absolute names, globs, and traversal. Availability is `available` only when the path resolves to a readable file: workspace references resolve only under the workspace, while recognized Harness bindings (a registered id at its registered path, or a skill id naming its own `<id>/SKILL.md`) also search installed Harness skill roots (`missing` otherwise; `unverified` when no hook runtime is installed). An id without a path resolves through self-evolved manifest metadata, else remains visible with unknown availability. A binding that does not resolve cannot be recorded as `loaded`.
|
|
51
54
|
- `writeSet` contains concrete repository-relative path scopes, not globs,
|
|
52
55
|
absolute paths, or `..` traversal.
|
|
53
56
|
- a directory scope covers descendants; overlapping scopes cannot run in the
|
|
@@ -60,7 +63,7 @@ Rules:
|
|
|
60
63
|
|
|
61
64
|
## Workflow-plan consumer
|
|
62
65
|
|
|
63
|
-
For a session with an active mandatory workflow, write the stage array to the router-displayed `workflow-stages.json` path and invoke its `workflow-disposition.js start --session-id <id>` command. This binds the run to the active `workflowId` and bound workspace even after entering a linked worktree. Every required stage needs an objective check, and an independent plan needs a read-only `fable-verifier` stage depending on all other stages. Stage results need observed worker identities and numeric exit codes; missing metadata is
|
|
66
|
+
For a session with an active mandatory workflow, write the stage array to the router-displayed `workflow-stages.json` path and invoke its `workflow-disposition.js start --session-id <id>` command. This binds the run to the active `workflowId` and bound workspace even after entering a linked worktree. The start/check output exposes bindings only for dependency-ready stages; future-stage paths stay undisclosed. Resolve an active binding with `workflow-disposition.js stage-binding --stage-id <id> --binding-id <id> --disposition loaded|not-needed|unavailable --evidence <evidence>`. A successful check with unresolved bindings records `binding-unresolved`; resolve them, then rerun the exact check before the stage can pass. This state is a reminder, not a tool or Stop lock. Every required stage needs an objective check, and an independent plan needs a read-only `fable-verifier` stage depending on all other stages. Stage results need observed worker identities and numeric exit codes; missing metadata is unresolved, not success.
|
|
64
67
|
|
|
65
68
|
For standalone use without an active session contract, write the router contract and stage array to files and run:
|
|
66
69
|
|
|
@@ -4,7 +4,7 @@ description: "Stage large tasks through plans, named fable agents, failable chec
|
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
metadata:
|
|
6
6
|
author: Miya Daniel
|
|
7
|
-
version: 0.
|
|
7
|
+
version: 0.31.0
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Fable Mode
|
|
@@ -29,17 +29,15 @@ metadata:
|
|
|
29
29
|
|
|
30
30
|
## Select Operation First
|
|
31
31
|
|
|
32
|
-
For explanation/profile-only lookup, read only `<this-skill-dir>/references/profile-lookup.md` and answer. No stage state, delegation, or selector source reads. Quoted aliases do not start Fable. Mixed execution retains its topology.
|
|
33
|
-
|
|
34
|
-
Execution follows the workflow below.
|
|
32
|
+
For explanation/profile-only lookup, read only `<this-skill-dir>/references/profile-lookup.md` and answer. No stage state, delegation, or selector source reads. Quoted aliases do not start Fable. Mixed execution retains its topology; execution follows the workflow below.
|
|
35
33
|
|
|
36
34
|
## Workflow
|
|
37
35
|
|
|
38
36
|
1. Discover the runtime and lock the authorized file scope before edits.
|
|
39
|
-
2.
|
|
37
|
+
2. Per stage, set artifact, check, and required/optional bindings; dependency-ready stages disclose them, passing once resolved. Gaps never lock tools or Stop; advisory replans never halt. Rule-of-3 covers same-signature failures.
|
|
40
38
|
3. Resolve the requested behavior profile with `model-selector.js`; `opus`, `sonnet`/`sonnect`, and `haiku` are compatibility aliases, not model bindings.
|
|
41
|
-
4. Delegate by profile: orchestrator coordinates, reasoning
|
|
42
|
-
5.
|
|
43
|
-
6. Run
|
|
39
|
+
4. Delegate by profile: orchestrator coordinates, reasoning takes bounded judgment, mechanical takes low-ambiguity work; workers never spawn workers.
|
|
40
|
+
5. The host runtime-model floor is advisory; record it, never block on model choice alone.
|
|
41
|
+
6. Run stage checks, cold-review high-stakes artifacts, and audit profile/runtime/fallback fields.
|
|
44
42
|
|
|
45
43
|
Deep dive: <this-skill-dir>/references/model-matrix.md
|
|
@@ -45,6 +45,12 @@ first. Every stage declares `stageId`, goal, named agent, self-contained task,
|
|
|
45
45
|
expected output, `dependsOn`, and `writeSet` per
|
|
46
46
|
`fable-mode/CONTRACT-FORMAT.md`. `dependsOn: []` means no prerequisite;
|
|
47
47
|
`writeSet: []` means read-only. Workers never widen their own write set.
|
|
48
|
+
Declare stage-specific `requiredBindings` and `optionalBindings` in the same
|
|
49
|
+
contract. The consumer/start/check output exposes paths only for dependency-ready
|
|
50
|
+
stages; never preload bindings from future stages. Resolve active bindings with
|
|
51
|
+
`workflow-disposition.js stage-binding` and evidence before passing the stage.
|
|
52
|
+
If its objective check passes while bindings remain unresolved, the contract
|
|
53
|
+
records `binding-unresolved`; resolve the bindings and rerun that exact check.
|
|
48
54
|
|
|
49
55
|
Pass the router contract and stage array through
|
|
50
56
|
`fable-mode/scripts/workflow-plan-consumer.js` before spawning anything. Use the
|
|
@@ -97,10 +103,11 @@ that stage's check before continuing.
|
|
|
97
103
|
The run-scoped contract already exists before execution. When its exact
|
|
98
104
|
`checkCommand` runs, `contract-test.js` correlates it to one
|
|
99
105
|
`planId/runId/stageId`, updates that contract, and writes
|
|
100
|
-
`evidence/<stageId>.json`.
|
|
101
|
-
|
|
106
|
+
`evidence/<stageId>.json`. A `pass` requires both an objective check and
|
|
107
|
+
resolved declared bindings. If the command is ambiguous across runs, none of
|
|
108
|
+
the contracts is updated and the ambiguity must be resolved. Before delivery,
|
|
102
109
|
confirm every check-bearing contract in this run is `pass`; `planned`,
|
|
103
|
-
`running`, `pending`, or `
|
|
110
|
+
`running`, `pending`, `fail`, or `binding-unresolved` is not delivery evidence.
|
|
104
111
|
|
|
105
112
|
The subagent scope guard separately compares worker changes to the immutable
|
|
106
113
|
`writeSet` snapshot captured at burst start. An in-scope change is not proof of
|
|
@@ -63,7 +63,7 @@ function normalizeWritePath(value) {
|
|
|
63
63
|
if (typeof value !== 'string' || !value.trim()) throw new Error('writeSet entries must be non-empty strings');
|
|
64
64
|
let normalized = value.trim().replace(/\\/g, '/').replace(/^\.\//, '');
|
|
65
65
|
normalized = normalized.replace(/\/+$/g, '');
|
|
66
|
-
if (!normalized || normalized.startsWith('/') || /^[A-Za-z]
|
|
66
|
+
if (!normalized || normalized.startsWith('/') || /^[A-Za-z]:/.test(normalized)) {
|
|
67
67
|
throw new Error(`writeSet paths must be repository-relative: ${value}`);
|
|
68
68
|
}
|
|
69
69
|
const parts = normalized.split('/');
|
|
@@ -76,6 +76,95 @@ function normalizeWritePath(value) {
|
|
|
76
76
|
return normalized;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
// The resolver ships with the hook runtime. A Skills-only install has no hook
|
|
80
|
+
// runtime, so declared paths stay `unverified` instead of claiming availability.
|
|
81
|
+
function bindingResolver() {
|
|
82
|
+
for (const relative of ['../../hooks/scripts/lib/binding-resolver.js', '../../../hooks/scripts/lib/binding-resolver.js']) {
|
|
83
|
+
const file = path.resolve(__dirname, relative);
|
|
84
|
+
if (fs.existsSync(file)) return require(file);
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function resolveStageBindingAvailability(bindings, workspaceRoot) {
|
|
90
|
+
const resolver = bindingResolver();
|
|
91
|
+
for (const binding of bindings) {
|
|
92
|
+
const resolution = resolver
|
|
93
|
+
? resolver.resolveBinding(binding, workspaceRoot)
|
|
94
|
+
: { availability: binding.path ? 'unverified' : 'unknown', file: null };
|
|
95
|
+
binding.availability = resolution.availability;
|
|
96
|
+
binding.resolvedPath = resolution.file;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function normalizeBindings(values, label, required) {
|
|
101
|
+
if (values === undefined) return [];
|
|
102
|
+
if (!Array.isArray(values)) throw new Error(`${label} must be an array`);
|
|
103
|
+
const seen = new Set();
|
|
104
|
+
return values.map(raw => {
|
|
105
|
+
const value = typeof raw === 'string' ? { id: raw } : raw;
|
|
106
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`${label} entries must be ids or objects`);
|
|
107
|
+
const id = sanitizeId(value.id, `${label}.id`);
|
|
108
|
+
if (seen.has(id)) throw new Error(`${label} contains duplicate binding: ${id}`);
|
|
109
|
+
seen.add(id);
|
|
110
|
+
const bindingPath = value.path === undefined || value.path === null || value.path === ''
|
|
111
|
+
? null
|
|
112
|
+
: normalizeWritePath(value.path);
|
|
113
|
+
return {
|
|
114
|
+
id,
|
|
115
|
+
required,
|
|
116
|
+
path: bindingPath,
|
|
117
|
+
status: 'pending',
|
|
118
|
+
availability: bindingPath ? 'unverified' : 'unknown',
|
|
119
|
+
resolvedPath: null,
|
|
120
|
+
evidence: null,
|
|
121
|
+
reasonCode: null,
|
|
122
|
+
updatedAt: null,
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function activeStageBindings(runRoot, escapes = []) {
|
|
128
|
+
const run = readJson(path.join(runRoot, 'run.json'));
|
|
129
|
+
if (!run || !Array.isArray(run.stageIds)) return [];
|
|
130
|
+
const contractsDir = path.join(runRoot, 'contracts');
|
|
131
|
+
const stages = new Map();
|
|
132
|
+
for (const stageId of run.stageIds) {
|
|
133
|
+
const stage = readJson(path.join(contractsDir, `${stageId}.json`));
|
|
134
|
+
if (stage && stage.runId === run.runId && stage.stageId === stageId) stages.set(stageId, stage);
|
|
135
|
+
}
|
|
136
|
+
const escapedIds = new Set((escapes || []).filter(item => item?.runId === run.runId && item?.evidence && item?.uncoveredScope &&
|
|
137
|
+
['workflow-uncovered-scope', 'host-capability-unavailable'].includes(item.reasonCode))
|
|
138
|
+
.map(item => item.stageId));
|
|
139
|
+
const stagePassed = stage => stage?.status === 'pass' &&
|
|
140
|
+
(stage.requiredBindings || []).every(binding => binding.status === 'loaded') &&
|
|
141
|
+
(stage.optionalBindings || []).every(binding => ['loaded', 'not-needed'].includes(binding.status));
|
|
142
|
+
const bindingsResolved = stage =>
|
|
143
|
+
(stage.requiredBindings || []).every(binding => binding.status === 'loaded') &&
|
|
144
|
+
(stage.optionalBindings || []).every(binding => ['loaded', 'not-needed'].includes(binding.status));
|
|
145
|
+
return run.stageIds
|
|
146
|
+
.map(stageId => stages.get(stageId))
|
|
147
|
+
.filter(stage => stage && !escapedIds.has(stage.stageId) &&
|
|
148
|
+
(['planned', 'running', 'fail', 'binding-unresolved'].includes(stage.status) ||
|
|
149
|
+
(stage.status === 'pass' && !bindingsResolved(stage))) &&
|
|
150
|
+
(stage.dependsOn || []).every(id => stagePassed(stages.get(id)) || escapedIds.has(id)))
|
|
151
|
+
.map(stage => ({
|
|
152
|
+
stageId: stage.stageId,
|
|
153
|
+
goal: stage.goal,
|
|
154
|
+
status: stage.status === 'pass' && !bindingsResolved(stage) ? 'binding-unresolved' : stage.status,
|
|
155
|
+
requiredBindings: (stage.requiredBindings || []).map(binding => ({
|
|
156
|
+
id: binding.id, status: binding.status, availability: binding.availability, path: binding.path, resolvedPath: binding.resolvedPath || null,
|
|
157
|
+
})),
|
|
158
|
+
optionalBindings: (stage.optionalBindings || []).map(binding => ({
|
|
159
|
+
id: binding.id, status: binding.status, availability: binding.availability, path: binding.path, resolvedPath: binding.resolvedPath || null,
|
|
160
|
+
})),
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function readJson(filePath) {
|
|
165
|
+
try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); } catch (_) { return null; }
|
|
166
|
+
}
|
|
167
|
+
|
|
79
168
|
function normalizeStage(raw) {
|
|
80
169
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('stage must be an object');
|
|
81
170
|
const stageId = sanitizeId(raw.stageId, 'stageId');
|
|
@@ -87,6 +176,12 @@ function normalizeStage(raw) {
|
|
|
87
176
|
|
|
88
177
|
const dependsOn = [...new Set(raw.dependsOn.map(value => sanitizeId(value, `${stageId}.dependsOn`)))];
|
|
89
178
|
const writeSet = [...new Set(raw.writeSet.map(normalizeWritePath))].sort();
|
|
179
|
+
const requiredBindings = normalizeBindings(raw.requiredBindings, `${stageId}.requiredBindings`, true);
|
|
180
|
+
const optionalBindings = normalizeBindings(raw.optionalBindings, `${stageId}.optionalBindings`, false);
|
|
181
|
+
const bindingIds = new Set(requiredBindings.map(binding => binding.id));
|
|
182
|
+
for (const binding of optionalBindings) {
|
|
183
|
+
if (bindingIds.has(binding.id)) throw new Error(`${stageId}: binding cannot be both required and optional: ${binding.id}`);
|
|
184
|
+
}
|
|
90
185
|
|
|
91
186
|
return {
|
|
92
187
|
stageId,
|
|
@@ -98,6 +193,8 @@ function normalizeStage(raw) {
|
|
|
98
193
|
outputPath: raw.outputPath === undefined ? null : raw.outputPath,
|
|
99
194
|
dependsOn,
|
|
100
195
|
writeSet,
|
|
196
|
+
requiredBindings,
|
|
197
|
+
optionalBindings,
|
|
101
198
|
checkCommand: typeof raw.checkCommand === 'string' && raw.checkCommand.trim() ? raw.checkCommand.trim() : null,
|
|
102
199
|
passCondition: typeof raw.passCondition === 'string' && raw.passCondition.trim() ? raw.passCondition.trim() : null,
|
|
103
200
|
failureReturn: typeof raw.failureReturn === 'string' && raw.failureReturn.trim()
|
|
@@ -236,6 +333,7 @@ function prepareRun({ routerContract, stages, workspaceRoot, runId, sessionId =
|
|
|
236
333
|
fs.mkdirSync(evidenceDir, { recursive: true });
|
|
237
334
|
|
|
238
335
|
for (const stage of normalizedStages) {
|
|
336
|
+
resolveStageBindingAvailability([...stage.requiredBindings, ...stage.optionalBindings], root);
|
|
239
337
|
atomicWriteJson(path.join(contractsDir, `${stage.stageId}.json`), {
|
|
240
338
|
schemaVersion: STAGE_CONTRACT_VERSION,
|
|
241
339
|
planId,
|
|
@@ -319,7 +417,7 @@ if (require.main === module) {
|
|
|
319
417
|
runId: args.runId,
|
|
320
418
|
sessionId: args.sessionId || null,
|
|
321
419
|
});
|
|
322
|
-
process.stdout.write(`${JSON.stringify(manifest)}\n`);
|
|
420
|
+
process.stdout.write(`${JSON.stringify({ ...manifest, activeStages: activeStageBindings(manifest.runRoot) })}\n`);
|
|
323
421
|
} catch (err) {
|
|
324
422
|
console.error(`[FABLE PLAN CONSUMER] ${err.message}`);
|
|
325
423
|
process.exit(2);
|
|
@@ -328,6 +426,7 @@ if (require.main === module) {
|
|
|
328
426
|
|
|
329
427
|
module.exports = {
|
|
330
428
|
STAGE_CONTRACT_VERSION,
|
|
429
|
+
activeStageBindings,
|
|
331
430
|
derivePlanId,
|
|
332
431
|
getWorkspaceKey,
|
|
333
432
|
getWorkspaceStateRoot,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: harness-everything
|
|
3
|
-
description: "Route software/project work through Harness: classify tier/topology,
|
|
3
|
+
description: "Route software/project work through Harness: classify tier/topology, compose active-step knowledge bindings, apply semantic obligations, and keep tactics flexible. Use for software triage/routing/re-routing; not general Q&A or non-software writing."
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
metadata:
|
|
6
6
|
author: Miya Daniel
|
|
7
|
-
version: 0.
|
|
7
|
+
version: 0.31.0
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Harness Everything
|
|
@@ -20,16 +20,17 @@ metadata:
|
|
|
20
20
|
1. **Route (MUST)** — scope/tier plus selected/deferred topology.
|
|
21
21
|
2. **Verify (MUST)** — objective evidence via `verify-gate.js --json`.
|
|
22
22
|
3. **Zoom out (MUST)** — after 3 same-signature failures, use `zoom-out`.
|
|
23
|
-
4. **
|
|
23
|
+
4. **Bind knowledge by step (MUST)** — ordered steps declare required/optional skills/references; only the active step's bindings load and resolve.
|
|
24
24
|
5. **Surface status (MUST)** — non-trivial work renders `### 🚦 Harness Status` with bold `Current`, `Read / Evidence`, `Next`; `Risk / Blocked` optional.
|
|
25
25
|
6. **Keep agency** — required obligations are MUST; tactics MAY adapt. Numeric planning MAY guide, never hard-stop; only Rule-of-3 reflection and explicit user/host permission boundaries may block.
|
|
26
26
|
7. **Windows PowerShell (MUST)** — `Get-Content -Encoding UTF8 -Raw`; npm `.cmd` shims (`npx.cmd`); never weaken `ExecutionPolicy`.
|
|
27
27
|
|
|
28
28
|
## Workflow
|
|
29
29
|
1. Reuse kernel output or run `node "<this-skill-dir>/scripts/kernel-router.js" "<prompt summary>"`.
|
|
30
|
-
2. Keep the routing checkpoint internal.
|
|
31
|
-
3.
|
|
32
|
-
4.
|
|
33
|
-
5.
|
|
30
|
+
2. Keep the routing checkpoint internal; knowledge signals feed planning, not document selection.
|
|
31
|
+
3. Decompose ordered requirement steps, with their bindings, before execution.
|
|
32
|
+
4. Required active-step bindings and applicable core contracts MUST resolve before the step passes; unknown/unavailable stays visible.
|
|
33
|
+
5. Complete selected-topology invariants/stages/checks; Fable exposes only dependency-ready stage bindings.
|
|
34
|
+
6. Tier-3/Fable broad mutation MUST use a linked worktree or explicit degraded fallback.
|
|
34
35
|
|
|
35
36
|
Deep dive: <this-skill-dir>/references/triage-and-tiers.md
|
package/plugins/harness-everything/skills/harness-everything/references/router-workflow-plan.md
CHANGED
|
@@ -104,22 +104,27 @@ Irreversible or external side-effect intent (for example destructive database ch
|
|
|
104
104
|
|
|
105
105
|
This does not choose a topology and does not itself enforce the gate. Phase 5 owns PreToolUse enforcement. The router only declares the invariant so any eventual executor must preserve it.
|
|
106
106
|
|
|
107
|
-
## Invariants vs
|
|
107
|
+
## Invariants vs knowledge signals
|
|
108
108
|
|
|
109
|
-
`requiredInvariants` and `
|
|
109
|
+
`requiredInvariants` and `knowledgeSignals` have separate roles. Invariants state semantic MUSTs; normalized knowledge signals help decompose requirements but never select document paths. `suggestedSkills` remains an empty compatibility field and is not populated from topology or keywords.
|
|
110
110
|
|
|
111
111
|
Examples:
|
|
112
112
|
|
|
113
113
|
- `loop-awareness` and `objective-verification` are mandatory for `iterative-single`, on top of the base `scope-lock`, `verify-before-claim`, and `replan-after-repeated-failure`;
|
|
114
|
-
-
|
|
114
|
+
- TDD and verification-loop bindings are declared on behavior-change and verification steps, respectively;
|
|
115
115
|
- `stage-contracts` and `cold-verification` are mandatory for Fable topologies;
|
|
116
|
-
-
|
|
116
|
+
- domain skills and references are bound only to steps that need them;
|
|
117
|
+
- `fable-multi-agent-workspace` selects durable workspace behavior without globally loading a skill path.
|
|
117
118
|
|
|
118
119
|
There is no universal `TODO → TDD → verification` pipeline.
|
|
119
120
|
|
|
120
|
-
##
|
|
121
|
+
## Binding and disclosure rule
|
|
121
122
|
|
|
122
|
-
|
|
123
|
+
Each ordered requirement or Fable stage may declare `requiredBindings` and `optionalBindings` by stable id and concrete repository-relative path. Only the active requirement or dependency-ready stage exposes its paths. Required bindings must resolve before that step/stage passes; unknown required bindings remain visible and unresolved. Future-step paths and keyword-matched documents are never preloaded.
|
|
124
|
+
|
|
125
|
+
For single-agent steps, `workflow-disposition.js start`, `binding`, and `step` return command templates for resolving the current binding and passing the active step. Retained workflow reminders print the same commands. Record the binding evidence before the step disposition; the next step and its paths are disclosed only after the current step passes.
|
|
126
|
+
|
|
127
|
+
In typed-step mode, the aggregate `execute` and `verify` obligations resolve from their corresponding passed steps. A verification-only plan records an explicit no-execution disposition for `execute`; it still requires the verification binding, step evidence, and objective check.
|
|
123
128
|
|
|
124
129
|
## Determinism rule
|
|
125
130
|
|
|
@@ -14,10 +14,9 @@ flowchart TD
|
|
|
14
14
|
K --> W{Workflow selected?}
|
|
15
15
|
W -- No / deferred --> D[Preserve invariants<br/>choose smallest justified workflow]
|
|
16
16
|
W -- Yes --> A[ACTIVE workflow contract]
|
|
17
|
-
A -->
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
R --> E
|
|
17
|
+
A --> P[Decompose requirements<br/>into ordered steps]
|
|
18
|
+
P --> B[Bind skills/references<br/>to each step]
|
|
19
|
+
B --> E[Execute active step only]
|
|
21
20
|
E --> V{Required checks / stages resolved?}
|
|
22
21
|
V -- Yes --> O([Claim completion])
|
|
23
22
|
V -- No --> P[Diagnose / re-plan]
|
|
@@ -42,7 +41,7 @@ The kernel protects lifecycle obligations without micromanaging model reasoning.
|
|
|
42
41
|
1. **Route before execution** — establish task scope/tier and the smallest justified topology.
|
|
43
42
|
2. **Verify before claim** — completion requires objective evidence appropriate to the change.
|
|
44
43
|
3. **Re-plan on repetition** — after three same-signature failures, stop micro-retrying and use a fresh diagnosis / `zoom-out`.
|
|
45
|
-
4. **
|
|
44
|
+
4. **Bind knowledge by step** — compose ordered requirement steps and declare required/optional skills or references before execution.
|
|
46
45
|
5. **Resolve selected workflow** — selected-topology required obligations are semantic MUSTs; implementation tactics MAY adapt where the contract allows.
|
|
47
46
|
6. **Surface status** — non-trivial software/project work MUST use the single Harness Status format at required phase boundaries.
|
|
48
47
|
|
|
@@ -52,10 +51,10 @@ The model remains free to choose tools, implementation technique, decomposition
|
|
|
52
51
|
|
|
53
52
|
- One universal `TODO → TDD → verification-loop` sequence for every Tier 2/3 task.
|
|
54
53
|
- Multi-agent execution merely because a task is Tier 3.
|
|
55
|
-
- Every
|
|
54
|
+
- Every keyword-matched skill/reference regardless of whether an active requirement needs it.
|
|
56
55
|
- Every optional deep-dive/reference linked from a skill.
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
Keyword/domain matches are normalized planning signals, not document selectors. Each ordered step declares its required and optional skill/reference bindings; only the active step or dependency-ready Fable stage exposes those paths. Read a required skill's complete entry and follow its applicable core contract before the step passes. Required bindings without a known path remain visible and unresolved. Optional bindings resolve as loaded or not-needed. Hooks may remind, but missing bindings do not hard-block ordinary tools or Stop.
|
|
59
58
|
|
|
60
59
|
## 2. Routing Mechanism
|
|
61
60
|
|
|
@@ -67,28 +66,27 @@ node "<this-skill-dir>/scripts/kernel-router.js" "<brief prompt summary>"
|
|
|
67
66
|
npx github:dyphn1/Harness-everything next "<brief prompt summary>"
|
|
68
67
|
```
|
|
69
68
|
|
|
70
|
-
`kernel-router.js` delegates classification/
|
|
69
|
+
`kernel-router.js` delegates classification/knowledge-signal detection to `tier-router.js` and emits:
|
|
71
70
|
|
|
72
71
|
- classified tier + rationale,
|
|
73
72
|
- structured workflow plan,
|
|
74
73
|
- compact **Harness Routing Checkpoint**,
|
|
75
74
|
- required invariants,
|
|
76
|
-
-
|
|
75
|
+
- normalized knowledge signals that help compose requirement steps, not paths to read,
|
|
76
|
+
- ordered requirement steps and their active required/optional bindings after planning,
|
|
77
77
|
- **Workflow Contract** for the selected topology.
|
|
78
78
|
|
|
79
79
|
If `UserPromptSubmit` already ran the kernel this turn, reuse that output. Do not infer a silent Tier 1/direct path from missing or degraded routing.
|
|
80
80
|
|
|
81
|
-
###
|
|
81
|
+
### Active binding contract
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
- Before a selected Tier 2/3 workflow starts, decompose the request into ordered requirement steps and confirm the smallest sufficient topology.
|
|
84
|
+
- Put a required skill/reference only on steps whose acceptance criteria need it; put optional knowledge on its actual consumer step.
|
|
85
|
+
- Load/resolve only bindings for the active step. Do not print or preload future-step bindings.
|
|
86
|
+
- A required binding MUST resolve as loaded before the step passes; optional bindings resolve as loaded or not-needed. Unknown/unavailable required bindings stay visible and unresolved.
|
|
87
|
+
- Fable uses its existing dependency/write-set graph as the step graph. Only dependency-ready stage bindings are disclosed; unresolved bindings keep a successful check at `binding-unresolved` until they are resolved and that exact check is rerun.
|
|
84
88
|
|
|
85
|
-
|
|
86
|
-
2. **MUST** evaluate `USE FOR`, `DO NOT USE FOR`, workflow/basic flow, and hard rules.
|
|
87
|
-
3. Read extra material only when the entry explicitly requires it to decide applicability.
|
|
88
|
-
4. **MUST** resolve the suggestion as `use`, `not-applicable`, or `unresolved/unavailable`.
|
|
89
|
-
5. `use` means the skill's core contract **MUST** be followed; `not-applicable` **MUST** keep a flow-grounded reason.
|
|
90
|
-
|
|
91
|
-
A name, description, router summary, tier label, or generic "routine/common task" judgement is not enough to mark a suggestion not applicable. Using one suggestion does not resolve the others automatically.
|
|
89
|
+
The binding disposition is an execution contract, not proof that a real host loaded a file. Preserve a host/session trace before making live-host claims. Missing evidence stays a reminder and does not create a persistent Harness lock.
|
|
92
90
|
|
|
93
91
|
### Workflow escape contract
|
|
94
92
|
|
|
@@ -111,7 +109,7 @@ Default topology is normally `direct-single`. Keep the lifecycle minimal, but st
|
|
|
111
109
|
|
|
112
110
|
Typical shape: specific feature/bug fix, multi-file coordination, behavioral change, focused benchmark/review.
|
|
113
111
|
|
|
114
|
-
The router normally selects `iterative-single`: bounded reason/act work plus objective verification.
|
|
112
|
+
The router normally selects `iterative-single`: bounded reason/act work plus objective verification. Compose ordered steps and bind TDD to behavior-change, verification-loop to verification, and domain references only to steps whose acceptance needs them. Keyword matches alone never select or load documents.
|
|
115
113
|
|
|
116
114
|
When an evaluated skill is applicable, follow its workflow rather than reading it and then discarding it because the implementation seems obvious.
|
|
117
115
|
|
|
@@ -181,16 +179,16 @@ For software/project work, consume this internal runtime state when producing th
|
|
|
181
179
|
- Strategy: <selected/deferred strategy>
|
|
182
180
|
- Workflow state: <pending | running | satisfied | deferred | blocked>
|
|
183
181
|
- Required invariants: <router invariants>
|
|
184
|
-
-
|
|
185
|
-
-
|
|
182
|
+
- Knowledge signals: <normalized planning inputs; not document paths>
|
|
183
|
+
- Active step: <ordered requirement id/type, with only its declared bindings>
|
|
186
184
|
- Escape: <none | reason + uncovered scope + evidence>
|
|
187
185
|
```
|
|
188
186
|
|
|
189
|
-
The checkpoint is runtime/source state, not a competing user-facing template. Render user progress through the single Harness Status contract above. The key distinction is: **
|
|
187
|
+
The checkpoint is runtime/source state, not a competing user-facing template. Render user progress through the single Harness Status contract above. The key distinction is: **active required bindings and selected-topology obligations are MUSTs; unrelated future knowledge stays undisclosed, while tactics MAY adapt.**
|
|
190
188
|
|
|
191
189
|
## 8. Self-Healing and Dynamic Skills
|
|
192
190
|
|
|
193
|
-
Self-heal
|
|
191
|
+
Self-heal and fact-audit behavior remain part of the runtime. Prompt keyword matches emit normalized knowledge signals plus candidate step-binding ids; they do not print skill/reference paths. Self-evolved skills registered in a manifest's `generated` entries are matched on metadata (triggers) only: matching ids surface as `SELF-EVOLVED SKILL SIGNALS`, and a step that declares such an id resolves its `SKILL.md` from the manifest only once that step is active.
|
|
194
192
|
|
|
195
193
|
If bootstrap reports missing integration touchpoints:
|
|
196
194
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"patterns",
|
|
13
13
|
"requiredInvariants",
|
|
14
14
|
"suggestedSkills",
|
|
15
|
+
"knowledgeSignals",
|
|
15
16
|
"actionGate",
|
|
16
17
|
"limits",
|
|
17
18
|
"parallelism",
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
"patterns": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
|
|
35
36
|
"requiredInvariants": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
|
|
36
37
|
"suggestedSkills": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
|
|
38
|
+
"knowledgeSignals": { "type": "array", "items": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]{0,63}$" }, "uniqueItems": true },
|
|
37
39
|
"actionGate": {
|
|
38
40
|
"type": "object",
|
|
39
41
|
"required": ["required", "reasonCodes", "approver", "disposition"],
|