harness-everything 0.16.3 → 0.16.5
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/CHANGELOG.md +12 -0
- package/ci/mechanism-2am-openai-packaged-helper-runtime.test.js +82 -0
- package/ci/mechanism-33-issues-205-207.test.js +59 -0
- package/ci/skill-routing-check.js +1 -1
- package/commitlint.config.js +2 -2
- package/docker-verify.sh +18 -22
- package/docs/architecture.md +1 -1
- package/harness-everything/SKILL.md +1 -1
- package/harness-everything/scripts/bootstrap.js +4 -3
- package/harness-everything/scripts/runtime-paths.js +37 -0
- package/harness-everything/scripts/self-heal.js +3 -2
- package/harness-everything/scripts/tier-router.js +2 -6
- package/hooks/scripts/lib/platforms/claude.js +3 -3
- 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/lib/platforms/claude.js +3 -3
- package/plugins/harness-everything/plugin.json +1 -1
- package/plugins/harness-everything/scripts/installer.js +629 -0
- package/plugins/harness-everything/scripts/lib/claude-hooks.js +84 -0
- package/plugins/harness-everything/scripts/lib/execution-contract.js +70 -0
- package/plugins/harness-everything/scripts/lib/gitignore.js +199 -0
- package/plugins/harness-everything/scripts/lib/manifest.js +142 -0
- package/plugins/harness-everything/scripts/lib/path-boundary.js +90 -0
- package/plugins/harness-everything/scripts/lib/prompts.js +241 -0
- package/plugins/harness-everything/scripts/lib/skills.js +314 -0
- package/plugins/harness-everything/scripts/lib/workspace.js +290 -0
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +1 -1
- package/plugins/harness-everything/skills/harness-everything/scripts/bootstrap.js +4 -3
- package/plugins/harness-everything/skills/harness-everything/scripts/runtime-paths.js +37 -0
- package/plugins/harness-everything/skills/harness-everything/scripts/self-heal.js +3 -2
- package/plugins/harness-everything/skills/harness-everything/scripts/tier-router.js +2 -6
- package/scripts/installer.js +12 -4
- package/scripts/sync-openai-plugin.js +5 -2
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "harness-everything",
|
|
11
11
|
"source": "./",
|
|
12
12
|
"description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
|
|
13
|
-
"version": "0.16.
|
|
13
|
+
"version": "0.16.5",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Miya Daniel"
|
|
16
16
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harness-everything",
|
|
3
3
|
"description": "Harness OS: an orchestrated agent operating system — tier routing, circuit breaker guardrails, verification gates, WAL session memory, and self-evolving workspace rules.",
|
|
4
|
-
"version": "0.16.
|
|
4
|
+
"version": "0.16.5",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Miya Daniel"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.16.5](https://github.com/dyphn1/Harness-everything/compare/v0.16.4...v0.16.5) (2026-09-21)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* **codex:** make packaged helper runtime self-contained ([96cba55](https://github.com/dyphn1/Harness-everything/commit/96cba55b2347251c90306a727825377ba26465c2))
|
|
10
|
+
|
|
11
|
+
## [0.16.4](https://github.com/dyphn1/Harness-everything/compare/v0.16.3...v0.16.4) (2026-09-20)
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **repo:** close issues 205-207 ([423ff63](https://github.com/dyphn1/Harness-everything/commit/423ff638f08cdaa14d4ab0856bfe2d2bc6b050db)), closes [#205](https://github.com/dyphn1/Harness-everything/issues/205) [#206](https://github.com/dyphn1/Harness-everything/issues/206) [#205](https://github.com/dyphn1/Harness-everything/issues/205) [#206](https://github.com/dyphn1/Harness-everything/issues/206) [#207](https://github.com/dyphn1/Harness-everything/issues/207)
|
|
16
|
+
|
|
5
17
|
## [0.16.3](https://github.com/dyphn1/Harness-everything/compare/v0.16.2...v0.16.3) (2026-09-20)
|
|
6
18
|
|
|
7
19
|
### Bug Fixes
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const assert = require('assert');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { spawnSync } = require('child_process');
|
|
8
|
+
|
|
9
|
+
const repoRoot = path.resolve(__dirname, '..');
|
|
10
|
+
const packagedPlugin = path.join(repoRoot, 'plugins', 'harness-everything');
|
|
11
|
+
|
|
12
|
+
function runNode(script, args, options) {
|
|
13
|
+
return spawnSync(process.execPath, [script, ...args], {
|
|
14
|
+
cwd: options.cwd,
|
|
15
|
+
env: { ...process.env, ...options.env },
|
|
16
|
+
input: options.input,
|
|
17
|
+
encoding: 'utf8'
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function describe(result) {
|
|
22
|
+
return [result.stdout, result.stderr].filter(Boolean).join('\n');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-openai-plugin-'));
|
|
26
|
+
try {
|
|
27
|
+
const pluginRoot = path.join(tempRoot, 'plugin');
|
|
28
|
+
const workspaceRoot = path.join(tempRoot, 'workspace');
|
|
29
|
+
const stateHome = path.join(tempRoot, 'state');
|
|
30
|
+
fs.cpSync(packagedPlugin, pluginRoot, { recursive: true });
|
|
31
|
+
fs.mkdirSync(workspaceRoot, { recursive: true });
|
|
32
|
+
fs.mkdirSync(stateHome, { recursive: true });
|
|
33
|
+
fs.mkdirSync(path.join(workspaceRoot, '.git'), { recursive: true });
|
|
34
|
+
fs.writeFileSync(path.join(workspaceRoot, 'AGENTS.md'), '# managed workspace\n', 'utf8');
|
|
35
|
+
|
|
36
|
+
const env = {
|
|
37
|
+
HARNESS_STATE_HOME: stateHome,
|
|
38
|
+
HARNESS_WORKSPACE_ROOT: workspaceRoot,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const scriptsRoot = path.join(pluginRoot, 'skills', 'harness-everything', 'scripts');
|
|
42
|
+
const selfHeal = runNode(path.join(scriptsRoot, 'self-heal.js'), ['--check'], {
|
|
43
|
+
cwd: workspaceRoot,
|
|
44
|
+
env,
|
|
45
|
+
});
|
|
46
|
+
assert.strictEqual(selfHeal.status, 0, `packaged self-heal --check failed:\n${describe(selfHeal)}`);
|
|
47
|
+
|
|
48
|
+
const installer = runNode(path.join(pluginRoot, 'scripts', 'installer.js'), ['--codex', '--no-skills', '--yes'], {
|
|
49
|
+
cwd: workspaceRoot,
|
|
50
|
+
env,
|
|
51
|
+
});
|
|
52
|
+
assert.strictEqual(installer.status, 0, `packaged installer failed:\n${describe(installer)}`);
|
|
53
|
+
assert.match(
|
|
54
|
+
fs.readFileSync(path.join(workspaceRoot, 'AGENTS.md'), 'utf8'),
|
|
55
|
+
/Harness OS Guidance \(Advisory\)/,
|
|
56
|
+
'packaged installer did not write the Codex advisory file'
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const bootstrap = runNode(path.join(scriptsRoot, 'bootstrap.js'), [], {
|
|
60
|
+
cwd: workspaceRoot,
|
|
61
|
+
env,
|
|
62
|
+
input: JSON.stringify({ session_id: 'packaged-runtime-smoke', cwd: workspaceRoot }),
|
|
63
|
+
});
|
|
64
|
+
assert.strictEqual(bootstrap.status, 0, `packaged bootstrap failed:\n${describe(bootstrap)}`);
|
|
65
|
+
assert.match(describe(bootstrap), /Harness OS initialized/, 'packaged bootstrap did not initialize Harness');
|
|
66
|
+
|
|
67
|
+
const tierRouter = runNode(path.join(scriptsRoot, 'tier-router.js'), ['audit the repository and run tests'], {
|
|
68
|
+
cwd: workspaceRoot,
|
|
69
|
+
env,
|
|
70
|
+
});
|
|
71
|
+
assert.strictEqual(tierRouter.status, 0, `packaged tier-router failed:\n${describe(tierRouter)}`);
|
|
72
|
+
assert.doesNotMatch(
|
|
73
|
+
describe(tierRouter),
|
|
74
|
+
/BASE EXECUTION LOOP: Load 'todo-driven-workflow'/,
|
|
75
|
+
'direct packaged tier-router still emits retired mandatory todo guidance'
|
|
76
|
+
);
|
|
77
|
+
assert.match(describe(tierRouter), /WORKFLOW STRATEGY:/, 'packaged tier-router did not emit the workflow contract');
|
|
78
|
+
|
|
79
|
+
console.log('OpenAI packaged helper runtime smoke test passed');
|
|
80
|
+
} finally {
|
|
81
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
82
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { spawnSync } = require('child_process');
|
|
8
|
+
|
|
9
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
10
|
+
let failed = 0;
|
|
11
|
+
|
|
12
|
+
function check(condition, message) {
|
|
13
|
+
if (condition) {
|
|
14
|
+
console.log(`PASS ${message}`);
|
|
15
|
+
} else {
|
|
16
|
+
failed += 1;
|
|
17
|
+
console.error(`FAIL ${message}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const dockerVerify = fs.readFileSync(path.join(ROOT, 'docker-verify.sh'), 'utf8');
|
|
22
|
+
const legacyStatePath = '.claude/harness-everything/state/sessions/default';
|
|
23
|
+
check(/STATE_DIR=\$\(node -e[\s\S]*getSessionDir\(null, 'default'\)/.test(dockerVerify),
|
|
24
|
+
'#205 docker verifier resolves one canonical session state directory');
|
|
25
|
+
check(!dockerVerify.includes(legacyStatePath),
|
|
26
|
+
'#205 docker verifier does not seed or read the legacy repo-relative state directory');
|
|
27
|
+
check((dockerVerify.match(/\$STATE_DIR\//g) || []).length >= 10,
|
|
28
|
+
'#205 docker verifier routes all state checks through STATE_DIR');
|
|
29
|
+
|
|
30
|
+
const architecture = fs.readFileSync(path.join(ROOT, 'docs/architecture.md'), 'utf8');
|
|
31
|
+
check(architecture.includes('advisory loop-awareness reminders'),
|
|
32
|
+
'#206 architecture names loop-awareness as advisory');
|
|
33
|
+
check(!/\bloop budgets\b/.test(architecture),
|
|
34
|
+
'#206 architecture does not describe retired loop budgets as enforcement');
|
|
35
|
+
|
|
36
|
+
const commitlintConfig = require(path.join(ROOT, 'commitlint.config.js'));
|
|
37
|
+
check(JSON.stringify(commitlintConfig.rules['subject-case']) === JSON.stringify([2, 'always', 'lower-case']),
|
|
38
|
+
'#207 commitlint aligns subject-case with repository Conventional Commit history');
|
|
39
|
+
|
|
40
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-issue-207-'));
|
|
41
|
+
const messageFile = path.join(tempDir, 'commit-message.txt');
|
|
42
|
+
fs.writeFileSync(messageFile, 'fix(runtime): align post-190 advisory contracts\n', 'utf8');
|
|
43
|
+
const commitlintPackage = require.resolve('@commitlint/cli/package.json');
|
|
44
|
+
const commitlintMeta = JSON.parse(fs.readFileSync(commitlintPackage, 'utf8'));
|
|
45
|
+
const commitlintBin = typeof commitlintMeta.bin === 'string'
|
|
46
|
+
? commitlintMeta.bin
|
|
47
|
+
: commitlintMeta.bin.commitlint;
|
|
48
|
+
const commitlintCli = path.resolve(path.dirname(commitlintPackage), commitlintBin);
|
|
49
|
+
const result = spawnSync(process.execPath, [commitlintCli, '--edit', messageFile], {
|
|
50
|
+
cwd: ROOT,
|
|
51
|
+
encoding: 'utf8',
|
|
52
|
+
});
|
|
53
|
+
check(result.status === 0,
|
|
54
|
+
'#207 representative lowercase repository subject passes commitlint');
|
|
55
|
+
|
|
56
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
57
|
+
|
|
58
|
+
console.log(`\n${failed === 0 ? 'PASS' : 'FAIL'}: issues #205-#207 regression mechanism (${failed} failure${failed === 1 ? '' : 's'})`);
|
|
59
|
+
process.exit(failed === 0 ? 0 : 1);
|
|
@@ -49,7 +49,7 @@ function discoverNestedSkills(skillDir) {
|
|
|
49
49
|
|
|
50
50
|
function expectedMarker(skill) {
|
|
51
51
|
if (skill === 'harness-everything') return 'RECOMMENDED TIER';
|
|
52
|
-
if (skill === 'todo-driven-workflow') return '
|
|
52
|
+
if (skill === 'todo-driven-workflow') return 'WORKFLOW STRATEGY';
|
|
53
53
|
return `${skill}/SKILL.md`;
|
|
54
54
|
}
|
|
55
55
|
|
package/commitlint.config.js
CHANGED
package/docker-verify.sh
CHANGED
|
@@ -26,13 +26,12 @@ npm test
|
|
|
26
26
|
echo -e "\n[Step 3] Running Mechanism Checks..."
|
|
27
27
|
|
|
28
28
|
# 3a. Rule of 3 Circuit Breaker actually blocks
|
|
29
|
-
# Runtime state
|
|
30
|
-
#
|
|
31
|
-
|
|
29
|
+
# Runtime state is resolved once through the same workspace-keyed helper used by
|
|
30
|
+
# the hooks. Invocations with no session_id use the fixed default session.
|
|
31
|
+
STATE_DIR=$(node -e "process.stdout.write(require('./hooks/scripts/lib/harness-state').getSessionDir(null, 'default'))")
|
|
32
32
|
echo -e "\n---> Running 3a: Rule of 3 Circuit Breaker"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
echo '{"count":3,"lastHash":"verify-test","zoomOutResolved":false}' > .claude/harness-everything/state/sessions/default/rule-of-3-state.json
|
|
33
|
+
rm -f "$STATE_DIR/zoom-out-report.md"
|
|
34
|
+
echo '{"count":3,"lastHash":"verify-test","zoomOutResolved":false}' > "$STATE_DIR/rule-of-3-state.json"
|
|
36
35
|
|
|
37
36
|
# We expect this to exit with 2 and print CRITICAL trigger message
|
|
38
37
|
set +e
|
|
@@ -68,8 +67,8 @@ echo "✅ PASS: Rule of 3 reset check passed."
|
|
|
68
67
|
|
|
69
68
|
# 3a-bis. Zoom-out reflection report releases the breaker (self-recovery path)
|
|
70
69
|
echo -e "\n---> Running 3a-bis: Zoom-out report releases the breaker"
|
|
71
|
-
echo '{"count":3,"lastHash":"verify-test","zoomOutResolved":false,"lastFailureAt":0,"zoomOutCycles":0}' >
|
|
72
|
-
printf '## Goal\nx\n## Failed Attempts\nx\n## Verified Facts\nx\n## Diagnosis\nx\n## Decision\nRESUME: new approach\n' >
|
|
70
|
+
echo '{"count":3,"lastHash":"verify-test","zoomOutResolved":false,"lastFailureAt":0,"zoomOutCycles":0}' > "$STATE_DIR/rule-of-3-state.json"
|
|
71
|
+
printf '## Goal\nx\n## Failed Attempts\nx\n## Verified Facts\nx\n## Diagnosis\nx\n## Decision\nRESUME: new approach\n' > "$STATE_DIR/zoom-out-report.md"
|
|
73
72
|
|
|
74
73
|
set +e
|
|
75
74
|
node hooks/scripts/rule-of-3.js
|
|
@@ -79,9 +78,9 @@ if [ "$EXIT_CODE" -ne 0 ]; then
|
|
|
79
78
|
echo "❌ FAIL: Valid reflection report did not release the breaker (expected 0, got $EXIT_CODE)"
|
|
80
79
|
exit 1
|
|
81
80
|
fi
|
|
82
|
-
if ! node -e "const s=require(
|
|
81
|
+
if ! node -e "const s=require(process.argv[1]); process.exit(s.count===0 && s.zoomOutResolved===true && s.zoomOutCycles===1 ? 0 : 1)" "$STATE_DIR/rule-of-3-state.json"; then
|
|
83
82
|
echo "❌ FAIL: Breaker state not updated after report release"
|
|
84
|
-
cat
|
|
83
|
+
cat "$STATE_DIR/rule-of-3-state.json"
|
|
85
84
|
exit 1
|
|
86
85
|
fi
|
|
87
86
|
echo "✅ PASS: Valid reflection report released the breaker (self-recovery)."
|
|
@@ -91,11 +90,8 @@ echo "✅ PASS: Valid reflection report released the breaker (self-recovery)."
|
|
|
91
90
|
# the contract is exit 2 plus the reflection-required message the hook actually
|
|
92
91
|
# prints - never a permanent lock (ci/mechanism-2a-rule-of-3.test.js:58-64).
|
|
93
92
|
echo -e "\n---> Running 3a-ter: Re-trip requests another zoom-out"
|
|
94
|
-
# Seed through the hooks' own resolver
|
|
95
|
-
#
|
|
96
|
-
# ~/.agents/harness-everything/...), and a repo-relative seed only reaches the
|
|
97
|
-
# hook while the one-time legacy migration can still move it.
|
|
98
|
-
STATE_DIR=$(node -e "process.stdout.write(require('./hooks/scripts/lib/harness-state').getSessionDir(null, 'default'))")
|
|
93
|
+
# Seed through the hooks' own resolver in the already resolved workspace-keyed
|
|
94
|
+
# state root.
|
|
99
95
|
RETRIP_AT=$(node -e "process.stdout.write(String(Date.now()))")
|
|
100
96
|
node -e "require('fs').writeFileSync(process.argv[1], JSON.stringify({count:3,lastHash:'verify-test',zoomOutResolved:false,lastFailureAt:Number(process.argv[2]),zoomOutCycles:1}))" "$STATE_DIR/rule-of-3-state.json" "$RETRIP_AT"
|
|
101
97
|
set +e
|
|
@@ -173,17 +169,17 @@ echo "✅ PASS: Boundary Guard blocked large read successfully."
|
|
|
173
169
|
|
|
174
170
|
# 3c. State persistence (WAL) records failure and handles clear
|
|
175
171
|
echo -e "\n---> Running 3c: State persistence (WAL)"
|
|
176
|
-
rm -f
|
|
172
|
+
rm -f "$STATE_DIR/handoff-state.json"
|
|
177
173
|
|
|
178
174
|
# Record failure
|
|
179
175
|
echo '{"tool_name":"Bash","tool_response":{"stdout":"","stderr":"npm ERR! verify-test failure"}}' | node hooks/scripts/state-persist.js
|
|
180
176
|
|
|
181
|
-
if [ ! -f "
|
|
177
|
+
if [ ! -f "$STATE_DIR/handoff-state.json" ]; then
|
|
182
178
|
echo "❌ FAIL: handoff-state.json was not created"
|
|
183
179
|
exit 1
|
|
184
180
|
fi
|
|
185
181
|
|
|
186
|
-
STATUS=$(node -e "console.log(JSON.parse(require('fs').readFileSync(
|
|
182
|
+
STATUS=$(node -e "console.log(JSON.parse(require('fs').readFileSync(process.argv[1],'utf8')).status)" "$STATE_DIR/handoff-state.json")
|
|
187
183
|
if [ "$STATUS" != "failed" ]; then
|
|
188
184
|
echo "❌ FAIL: Expected status to be 'failed', got '$STATUS'"
|
|
189
185
|
exit 1
|
|
@@ -254,8 +250,8 @@ echo "✅ PASS: Subagent scope guard successfully blocked out-of-scope modificat
|
|
|
254
250
|
|
|
255
251
|
# 3f. Stop gate bounces an unverified-edit stop exactly once
|
|
256
252
|
echo -e "\n---> Running 3f: Stop Gate"
|
|
257
|
-
rm -f
|
|
258
|
-
node -e "require('fs').
|
|
253
|
+
rm -f "$STATE_DIR/stop-gate-state.json"
|
|
254
|
+
node -e "require('fs').writeFileSync(process.argv[1], JSON.stringify({status:'idle',lastEditAt:Date.now(),lastVerifyAt:0}))" "$STATE_DIR/handoff-state.json"
|
|
259
255
|
echo "dirty" > .verify-dirty.tmp
|
|
260
256
|
|
|
261
257
|
set +e
|
|
@@ -285,7 +281,7 @@ if [ "$EXIT_CODE" -ne 0 ]; then
|
|
|
285
281
|
fi
|
|
286
282
|
|
|
287
283
|
# Loop guard: stop_hook_active always passes
|
|
288
|
-
rm -f
|
|
284
|
+
rm -f "$STATE_DIR/stop-gate-state.json"
|
|
289
285
|
set +e
|
|
290
286
|
echo '{"stop_hook_active":true}' | node hooks/scripts/stop-gate.js
|
|
291
287
|
EXIT_CODE=$?
|
|
@@ -294,7 +290,7 @@ if [ "$EXIT_CODE" -ne 0 ]; then
|
|
|
294
290
|
echo "❌ FAIL: Stop gate blocked despite stop_hook_active (expected 0, got $EXIT_CODE)"
|
|
295
291
|
exit 1
|
|
296
292
|
fi
|
|
297
|
-
rm -f .verify-dirty.tmp
|
|
293
|
+
rm -f .verify-dirty.tmp "$STATE_DIR/handoff-state.json" "$STATE_DIR/stop-gate-state.json"
|
|
298
294
|
echo "✅ PASS: Stop gate bounced once, then respected the batch and loop guards."
|
|
299
295
|
|
|
300
296
|
# Clean up temporary test output logs
|
package/docs/architecture.md
CHANGED
|
@@ -71,7 +71,7 @@ For selected Fable topologies on Claude:
|
|
|
71
71
|
- `workflow-stop-gate.js` reports unresolved stage/verification evidence without rejecting Stop;
|
|
72
72
|
- `workflow-disposition.js` records explicit lifecycle/audit decisions; numeric budgets are no longer authoritative control state.
|
|
73
73
|
|
|
74
|
-
Other topologies use their own applicable mechanisms: loop
|
|
74
|
+
Other topologies use their own applicable mechanisms: advisory loop-awareness reminders, regular verification stop-gates, action gates, and task-specific skills. Mechanism coverage is not assumed identical across hosts.
|
|
75
75
|
|
|
76
76
|
### Scoped runtime advisories and capabilities
|
|
77
77
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
|
+
const { getHarnessRoot, requireHarnessState, requireWorkspace } = require('./runtime-paths');
|
|
4
5
|
const {
|
|
5
6
|
getWorkspaceRoot,
|
|
6
7
|
getSessionId,
|
|
7
8
|
getSessionDir,
|
|
8
9
|
writeCurrentSession,
|
|
9
10
|
pruneStaleSessions,
|
|
10
|
-
} =
|
|
11
|
+
} = requireHarnessState();
|
|
11
12
|
|
|
12
13
|
console.log("Bootstrapping Harness Skills OS...");
|
|
13
14
|
|
|
@@ -162,9 +163,9 @@ try {
|
|
|
162
163
|
// npx/global install auditing the harness checkout itself compares two
|
|
163
164
|
// different paths and wrongly advises a repair that self-heal then skips
|
|
164
165
|
// (issue #40). Required lazily so a missing lib can never break session start.
|
|
165
|
-
const { isHarnessRepo } =
|
|
166
|
+
const { isHarnessRepo } = requireWorkspace();
|
|
166
167
|
const auditingSelf = isHarnessRepo(workspaceRoot)
|
|
167
|
-
|| path.resolve(workspaceRoot) === path.resolve(
|
|
168
|
+
|| path.resolve(workspaceRoot) === path.resolve(getHarnessRoot());
|
|
168
169
|
|
|
169
170
|
if (missing.length > 0 && !auditingSelf) {
|
|
170
171
|
console.log(`\n[Self-Heal] Missing integration touchpoints: ${missing.join(', ')}`);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Helpers live in both the source checkout and the packaged plugin's skill
|
|
7
|
+
// tree. Resolve the owning runtime root instead of assuming either layout.
|
|
8
|
+
function candidateRoots() {
|
|
9
|
+
return [
|
|
10
|
+
path.resolve(__dirname, '..', '..'),
|
|
11
|
+
path.resolve(__dirname, '..', '..', '..'),
|
|
12
|
+
];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getHarnessRoot() {
|
|
16
|
+
const root = candidateRoots().find(candidate =>
|
|
17
|
+
fs.existsSync(path.join(candidate, 'scripts', 'lib', 'workspace.js'))
|
|
18
|
+
);
|
|
19
|
+
if (!root) {
|
|
20
|
+
throw new Error(`Harness runtime root not found from ${__dirname}`);
|
|
21
|
+
}
|
|
22
|
+
return root;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function requireWorkspace() {
|
|
26
|
+
return require(path.join(getHarnessRoot(), 'scripts', 'lib', 'workspace.js'));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function requireHarnessState() {
|
|
30
|
+
return require(path.join(getHarnessRoot(), 'hooks', 'scripts', 'lib', 'harness-state.js'));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = {
|
|
34
|
+
getHarnessRoot,
|
|
35
|
+
requireWorkspace,
|
|
36
|
+
requireHarnessState,
|
|
37
|
+
};
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
const fs = require('fs');
|
|
24
24
|
const path = require('path');
|
|
25
25
|
const { execSync } = require('child_process');
|
|
26
|
-
const {
|
|
26
|
+
const { getHarnessRoot, requireWorkspace } = require('./runtime-paths');
|
|
27
|
+
const { getWorkspaceRoot, isHarnessRepo } = requireWorkspace();
|
|
27
28
|
|
|
28
29
|
const MARKER = 'Harness OS Guidance (Advisory)';
|
|
29
30
|
const HOOK_ID = 'harness:pre:bootstrap';
|
|
@@ -194,7 +195,7 @@ function main() {
|
|
|
194
195
|
const forceSelf = process.argv.includes('--force-self');
|
|
195
196
|
|
|
196
197
|
const workspaceRoot = getWorkspaceRoot();
|
|
197
|
-
const harnessSourceDir =
|
|
198
|
+
const harnessSourceDir = getHarnessRoot();
|
|
198
199
|
const installerPath = path.join(harnessSourceDir, 'scripts', 'installer.js');
|
|
199
200
|
|
|
200
201
|
console.log(`Workspace: ${workspaceRoot}`);
|
|
@@ -5,6 +5,7 @@ const {
|
|
|
5
5
|
buildRouterContract,
|
|
6
6
|
writeRouterContract,
|
|
7
7
|
} = require('./router-contract');
|
|
8
|
+
const { requireWorkspace } = require('./runtime-paths');
|
|
8
9
|
|
|
9
10
|
const DEFAULT_ROUTING_CONFIG = {
|
|
10
11
|
tiers: { tier3: [], tier2: [] },
|
|
@@ -163,7 +164,7 @@ function plannerInputsFromContext(context, promptLower) {
|
|
|
163
164
|
function emitDynamicSkills(promptLower, context, recommendedGuides) {
|
|
164
165
|
try {
|
|
165
166
|
const userHome = process.env.HOME || process.env.USERPROFILE || '';
|
|
166
|
-
const { getWorkspaceRoot } =
|
|
167
|
+
const { getWorkspaceRoot } = requireWorkspace();
|
|
167
168
|
const workspaceRoot = getWorkspaceRoot(context);
|
|
168
169
|
|
|
169
170
|
const manifestPaths = [
|
|
@@ -315,11 +316,6 @@ function run(userPrompt, context) {
|
|
|
315
316
|
console.log(`\n=> RECOMMENDED TIER: ${recommendedTier}`);
|
|
316
317
|
console.log(`=> RATIONALE: ${rationale}`);
|
|
317
318
|
|
|
318
|
-
if (recommendedTier.startsWith('Tier 2') || recommendedTier.startsWith('Tier 3')) {
|
|
319
|
-
console.log(`\n=> BASE EXECUTION LOOP: Load 'todo-driven-workflow' and initialize its checklist (3-7 verifiable sub-tasks) BEFORE editing any file.`);
|
|
320
|
-
console.log(` Track exactly ONE item in-progress at a time; verify with real evidence before marking completed.`);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
319
|
const requestedFableModel = detectFableModel(promptLower);
|
|
324
320
|
if (requestedFableModel) {
|
|
325
321
|
console.log(`\n=> REQUESTED FABLE MODEL MODE: ${requestedFableModel}`);
|
|
@@ -107,7 +107,7 @@ module.exports = {
|
|
|
107
107
|
manifestPath: manifest.getManifestPath(claudeDir)
|
|
108
108
|
};
|
|
109
109
|
},
|
|
110
|
-
install({ isGlobal, targetWorkspaceRoot, harnessSourceDir, packageVersion, claudeHooks, manifest }) {
|
|
110
|
+
install({ isGlobal, targetWorkspaceRoot, harnessSourceDir, harnessRuntimeRoot = harnessSourceDir, packageVersion, claudeHooks, manifest }) {
|
|
111
111
|
const userHome = require('os').homedir();
|
|
112
112
|
const claudeDir = isGlobal ? path.join(userHome, '.claude') : path.join(targetWorkspaceRoot, '.claude');
|
|
113
113
|
if (!fs.existsSync(claudeDir)) {
|
|
@@ -124,7 +124,7 @@ module.exports = {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
const sourceHooksFile = path.join(
|
|
127
|
+
const sourceHooksFile = path.join(harnessRuntimeRoot, 'hooks', 'hooks.json');
|
|
128
128
|
if (fs.existsSync(sourceHooksFile)) {
|
|
129
129
|
const sourceHooksObj = JSON.parse(fs.readFileSync(sourceHooksFile, 'utf8'));
|
|
130
130
|
const resolvedHooks = {};
|
|
@@ -134,7 +134,7 @@ module.exports = {
|
|
|
134
134
|
if (cloned.hooks) {
|
|
135
135
|
cloned.hooks = cloned.hooks.map(h => {
|
|
136
136
|
if (h.type === 'command' && h.command) {
|
|
137
|
-
h.command = resolveClaudeHookCommand(h.command,
|
|
137
|
+
h.command = resolveClaudeHookCommand(h.command, harnessRuntimeRoot);
|
|
138
138
|
}
|
|
139
139
|
return h;
|
|
140
140
|
});
|
package/package.json
CHANGED
|
@@ -107,7 +107,7 @@ module.exports = {
|
|
|
107
107
|
manifestPath: manifest.getManifestPath(claudeDir)
|
|
108
108
|
};
|
|
109
109
|
},
|
|
110
|
-
install({ isGlobal, targetWorkspaceRoot, harnessSourceDir, packageVersion, claudeHooks, manifest }) {
|
|
110
|
+
install({ isGlobal, targetWorkspaceRoot, harnessSourceDir, harnessRuntimeRoot = harnessSourceDir, packageVersion, claudeHooks, manifest }) {
|
|
111
111
|
const userHome = require('os').homedir();
|
|
112
112
|
const claudeDir = isGlobal ? path.join(userHome, '.claude') : path.join(targetWorkspaceRoot, '.claude');
|
|
113
113
|
if (!fs.existsSync(claudeDir)) {
|
|
@@ -124,7 +124,7 @@ module.exports = {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
const sourceHooksFile = path.join(
|
|
127
|
+
const sourceHooksFile = path.join(harnessRuntimeRoot, 'hooks', 'hooks.json');
|
|
128
128
|
if (fs.existsSync(sourceHooksFile)) {
|
|
129
129
|
const sourceHooksObj = JSON.parse(fs.readFileSync(sourceHooksFile, 'utf8'));
|
|
130
130
|
const resolvedHooks = {};
|
|
@@ -134,7 +134,7 @@ module.exports = {
|
|
|
134
134
|
if (cloned.hooks) {
|
|
135
135
|
cloned.hooks = cloned.hooks.map(h => {
|
|
136
136
|
if (h.type === 'command' && h.command) {
|
|
137
|
-
h.command = resolveClaudeHookCommand(h.command,
|
|
137
|
+
h.command = resolveClaudeHookCommand(h.command, harnessRuntimeRoot);
|
|
138
138
|
}
|
|
139
139
|
return h;
|
|
140
140
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "harness-everything",
|
|
4
|
-
"version": "0.16.
|
|
4
|
+
"version": "0.16.5",
|
|
5
5
|
"description": "Invariant-first engineering harness for routing, verification, and failure recovery while preserving agent autonomy.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Miya Daniel",
|