harness-everything 0.16.5 → 0.16.6
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 +6 -0
- package/ci/mechanism-2am-openai-packaged-helper-runtime.test.js +28 -0
- package/ci/mechanism-2an-environment-detection-readonly.test.js +113 -0
- package/docs/workflows/environment-detection.md +15 -7
- package/environment-detection/SKILL.md +15 -16
- package/harness-everything/SKILL.md +1 -1
- package/harness-everything/scripts/self-heal.js +30 -8
- 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/plugin.json +1 -1
- package/plugins/harness-everything/skills/environment-detection/SKILL.md +15 -16
- package/plugins/harness-everything/skills/harness-everything/SKILL.md +1 -1
- package/plugins/harness-everything/skills/harness-everything/scripts/self-heal.js +30 -8
|
@@ -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.6",
|
|
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.6",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Miya Daniel"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.16.6](https://github.com/dyphn1/Harness-everything/compare/v0.16.5...v0.16.6) (2026-09-21)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
* **environment-detection:** keep discovery read-only ([#214](https://github.com/dyphn1/Harness-everything/issues/214)) ([f6fa7ec](https://github.com/dyphn1/Harness-everything/commit/f6fa7ec57fb95072dce1177ee4e93718b77b21ef))
|
|
10
|
+
|
|
5
11
|
## [0.16.5](https://github.com/dyphn1/Harness-everything/compare/v0.16.4...v0.16.5) (2026-09-21)
|
|
6
12
|
|
|
7
13
|
### Bug Fixes
|
|
@@ -45,6 +45,34 @@ try {
|
|
|
45
45
|
});
|
|
46
46
|
assert.strictEqual(selfHeal.status, 0, `packaged self-heal --check failed:\n${describe(selfHeal)}`);
|
|
47
47
|
|
|
48
|
+
// Public OpenAI skills-only submissions intentionally omit the plugin-root
|
|
49
|
+
// installer/runtime. The read-only audit must degrade safely instead of
|
|
50
|
+
// searching arbitrary parent/cache paths or failing skill execution.
|
|
51
|
+
const skillsOnlyRoot = path.join(tempRoot, 'skills-only');
|
|
52
|
+
const skillsOnlyWorkspace = path.join(tempRoot, 'skills-only-workspace');
|
|
53
|
+
fs.cpSync(path.join(pluginRoot, 'skills'), path.join(skillsOnlyRoot, 'skills'), { recursive: true });
|
|
54
|
+
fs.mkdirSync(path.join(skillsOnlyWorkspace, '.git'), { recursive: true });
|
|
55
|
+
fs.writeFileSync(path.join(skillsOnlyWorkspace, 'AGENTS.md'), '# skills-only workspace\n', 'utf8');
|
|
56
|
+
const skillsOnlyAgentsBefore = fs.readFileSync(path.join(skillsOnlyWorkspace, 'AGENTS.md'), 'utf8');
|
|
57
|
+
const skillsOnlyCheck = runNode(
|
|
58
|
+
path.join(skillsOnlyRoot, 'skills', 'harness-everything', 'scripts', 'self-heal.js'),
|
|
59
|
+
['--check'],
|
|
60
|
+
{
|
|
61
|
+
cwd: skillsOnlyWorkspace,
|
|
62
|
+
env: {
|
|
63
|
+
HARNESS_STATE_HOME: path.join(tempRoot, 'skills-only-state'),
|
|
64
|
+
HARNESS_WORKSPACE_ROOT: skillsOnlyWorkspace,
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
assert.strictEqual(skillsOnlyCheck.status, 0, `skills-only self-heal --check failed:\n${describe(skillsOnlyCheck)}`);
|
|
69
|
+
assert.match(describe(skillsOnlyCheck), /Local repair runtime unavailable on this distribution surface/);
|
|
70
|
+
assert.strictEqual(
|
|
71
|
+
fs.readFileSync(path.join(skillsOnlyWorkspace, 'AGENTS.md'), 'utf8'),
|
|
72
|
+
skillsOnlyAgentsBefore,
|
|
73
|
+
'skills-only read-only audit must not rewrite workspace integration files'
|
|
74
|
+
);
|
|
75
|
+
|
|
48
76
|
const installer = runNode(path.join(pluginRoot, 'scripts', 'installer.js'), ['--codex', '--no-skills', '--yes'], {
|
|
49
77
|
cwd: workspaceRoot,
|
|
50
78
|
env,
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const assert = require('assert');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { spawnSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
11
|
+
const SELF_HEAL = path.join(ROOT, 'harness-everything', 'scripts', 'self-heal.js');
|
|
12
|
+
const SKILL = path.join(ROOT, 'environment-detection', 'SKILL.md');
|
|
13
|
+
const OPENCODE = path.join(ROOT, 'opencode-plugin', 'index.mjs');
|
|
14
|
+
|
|
15
|
+
function write(root, relative, content) {
|
|
16
|
+
const target = path.join(root, relative);
|
|
17
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
18
|
+
fs.writeFileSync(target, content, 'utf8');
|
|
19
|
+
return target;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function treeDigest(root) {
|
|
23
|
+
const hash = crypto.createHash('sha256');
|
|
24
|
+
function walk(dir, relative = '') {
|
|
25
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
26
|
+
const rel = relative ? `${relative}/${entry.name}` : entry.name;
|
|
27
|
+
const full = path.join(dir, entry.name);
|
|
28
|
+
hash.update(`${entry.isDirectory() ? 'D' : 'F'}:${rel}\0`);
|
|
29
|
+
if (entry.isDirectory()) walk(full, rel);
|
|
30
|
+
else hash.update(fs.readFileSync(full));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
walk(root);
|
|
34
|
+
return hash.digest('hex');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function run(workspace, home, args) {
|
|
38
|
+
const env = {
|
|
39
|
+
...process.env,
|
|
40
|
+
HARNESS_WORKSPACE_ROOT: workspace,
|
|
41
|
+
HARNESS_STATE_HOME: path.join(home, 'state'),
|
|
42
|
+
HOME: home,
|
|
43
|
+
USERPROFILE: home,
|
|
44
|
+
APPDATA: path.join(home, 'AppData', 'Roaming'),
|
|
45
|
+
VSCODE_USER_PROMPTS_FOLDER: path.join(home, 'vscode-prompts'),
|
|
46
|
+
};
|
|
47
|
+
for (const key of ['CLAUDE', 'CLAUDECODE', 'CLAUDE_CODE', 'CURSOR_SANDBOX', 'GITHUB_COPILOT_CHAT', 'COPILOT_AGENT', 'AI_AGENT']) {
|
|
48
|
+
delete env[key];
|
|
49
|
+
}
|
|
50
|
+
return spawnSync(process.execPath, [SELF_HEAL, ...args], {
|
|
51
|
+
cwd: workspace,
|
|
52
|
+
env,
|
|
53
|
+
encoding: 'utf8',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-213-readonly-'));
|
|
58
|
+
try {
|
|
59
|
+
const workspace = path.join(tempRoot, 'workspace');
|
|
60
|
+
const home = path.join(tempRoot, 'home');
|
|
61
|
+
fs.mkdirSync(path.join(workspace, '.git'), { recursive: true });
|
|
62
|
+
fs.mkdirSync(home, { recursive: true });
|
|
63
|
+
|
|
64
|
+
// Seed all six installer/self-heal adapter surfaces with user-owned content.
|
|
65
|
+
write(workspace, '.claude/settings.json', JSON.stringify({ customSetting: true, hooks: {} }, null, 2));
|
|
66
|
+
write(workspace, '.cursorrules', 'user cursor rule\n');
|
|
67
|
+
write(workspace, '.github/copilot-instructions.md', 'user copilot instruction\n');
|
|
68
|
+
write(workspace, 'AGENTS.md', 'user codex instruction\n');
|
|
69
|
+
write(workspace, '.continue/rules/user.md', '# user continue rule\n');
|
|
70
|
+
write(workspace, '.hermes.md', 'user hermes context\n');
|
|
71
|
+
|
|
72
|
+
const beforeAudit = treeDigest(workspace);
|
|
73
|
+
const audit = run(workspace, home, ['--check']);
|
|
74
|
+
assert.strictEqual(audit.status, 0, `read-only audit failed:\n${audit.stdout}\n${audit.stderr}`);
|
|
75
|
+
assert.strictEqual(treeDigest(workspace), beforeAudit, '--check changed the workspace');
|
|
76
|
+
for (const label of ['Claude Code hooks', 'Cursor rules', 'Copilot instructions', 'Codex instructions', 'Continue.dev rules', 'Hermes Agent instructions']) {
|
|
77
|
+
assert.ok(audit.stdout.includes(label), `audit omitted ${label}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Explicit repair remains available, preserves user-owned content, and is
|
|
81
|
+
// idempotent on the second run.
|
|
82
|
+
const repair = run(workspace, home, []);
|
|
83
|
+
assert.strictEqual(repair.status, 0, `explicit repair failed:\n${repair.stdout}\n${repair.stderr}`);
|
|
84
|
+
assert.strictEqual(JSON.parse(fs.readFileSync(path.join(workspace, '.claude/settings.json'), 'utf8')).customSetting, true);
|
|
85
|
+
assert.match(fs.readFileSync(path.join(workspace, '.cursorrules'), 'utf8'), /user cursor rule/);
|
|
86
|
+
assert.match(fs.readFileSync(path.join(workspace, '.github', 'copilot-instructions.md'), 'utf8'), /user copilot instruction/);
|
|
87
|
+
assert.match(fs.readFileSync(path.join(workspace, 'AGENTS.md'), 'utf8'), /user codex instruction/);
|
|
88
|
+
assert.match(fs.readFileSync(path.join(workspace, '.hermes.md'), 'utf8'), /user hermes context/);
|
|
89
|
+
assert.strictEqual(fs.readFileSync(path.join(workspace, '.continue', 'rules', 'user.md'), 'utf8'), '# user continue rule\n');
|
|
90
|
+
|
|
91
|
+
const afterRepair = treeDigest(workspace);
|
|
92
|
+
const secondRepair = run(workspace, home, []);
|
|
93
|
+
assert.strictEqual(secondRepair.status, 0, `second repair failed:\n${secondRepair.stdout}\n${secondRepair.stderr}`);
|
|
94
|
+
assert.strictEqual(treeDigest(workspace), afterRepair, 'explicit repair is not idempotent');
|
|
95
|
+
|
|
96
|
+
// The routed skill contract must keep default detection observational and
|
|
97
|
+
// use a portable sibling-skill path rather than a repository/cache root.
|
|
98
|
+
const skill = fs.readFileSync(SKILL, 'utf8');
|
|
99
|
+
assert.ok(skill.includes('self-heal.js" --check'));
|
|
100
|
+
assert.doesNotMatch(skill, /<skills-repo-root>/);
|
|
101
|
+
assert.match(skill, /Only explicit install\/setup\/repair intent may omit/);
|
|
102
|
+
assert.match(skill, /OpenCode has its own plugin runtime/);
|
|
103
|
+
assert.match(skill, /skills-only surfaces may lack repair/);
|
|
104
|
+
|
|
105
|
+
// OpenCode is a separate runtime surface; its session/plugin startup must
|
|
106
|
+
// not import or invoke the six-adapter installer/self-heal path implicitly.
|
|
107
|
+
const opencode = fs.readFileSync(OPENCODE, 'utf8');
|
|
108
|
+
assert.doesNotMatch(opencode, /self-heal\.js|scripts[\\/]installer\.js/);
|
|
109
|
+
|
|
110
|
+
console.log('Issue #213 verified: detection is read-only across six adapters, repair is explicit/idempotent, and OpenCode stays separate.');
|
|
111
|
+
} finally {
|
|
112
|
+
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
113
|
+
}
|
|
@@ -13,8 +13,12 @@ graph TD
|
|
|
13
13
|
PreflightOk -->|yes| ParseOut[Parse OS shell PATH and CLIs]
|
|
14
14
|
PreflightOk -->|no| FallbackProbe[Inspect environment_info and probe shell]
|
|
15
15
|
FallbackProbe --> ParseOut
|
|
16
|
-
ParseOut --> SelfHealAudit[
|
|
17
|
-
SelfHealAudit -->
|
|
16
|
+
ParseOut --> SelfHealAudit[Run self-heal.js --check when supported]
|
|
17
|
+
SelfHealAudit --> Drift{Integration drift found?}
|
|
18
|
+
Drift -->|ordinary detection| ReportOnly[Report only; do not mutate]
|
|
19
|
+
Drift -->|explicit repair intent| Repair[Run supported platform repair]
|
|
20
|
+
ReportOnly --> AdoptSyntax[Adopt shell-specific syntax]
|
|
21
|
+
Repair --> AdoptSyntax
|
|
18
22
|
AdoptSyntax --> DoneCtx([Session context aligned])
|
|
19
23
|
```
|
|
20
24
|
|
|
@@ -48,10 +52,11 @@ graph LR
|
|
|
48
52
|
A session starts on Windows with PowerShell as the active shell. The agent needs to list files and check Node availability before running tests.
|
|
49
53
|
|
|
50
54
|
1. Run `node "<skill-dir>/scripts/preflight.js"` to detect Windows + PowerShell + available CLIs.
|
|
51
|
-
2.
|
|
52
|
-
3. If
|
|
53
|
-
4.
|
|
54
|
-
5.
|
|
55
|
+
2. Where the local Harness runtime exists, run self-heal in `--check` mode only; report drift without changing hooks or advisory files.
|
|
56
|
+
3. If the helper/runtime is absent (for example a skills-only distribution), report that the local repair surface is unavailable and continue without searching parent/cache paths.
|
|
57
|
+
4. Only an explicit install/setup/repair request may invoke mutating self-heal. OpenCode keeps its separate plugin installation/runtime boundary.
|
|
58
|
+
5. Adopt PowerShell syntax for paths and env vars instead of Git Bash assumptions. If `preflight.js` cannot run, inspect `<environment_info>` and probe minimally.
|
|
59
|
+
6. Stay inside `process.cwd()`; if the same aligned command still fails three times, trigger `zoom-out`.
|
|
55
60
|
|
|
56
61
|
```mermaid
|
|
57
62
|
graph TD
|
|
@@ -68,6 +73,9 @@ graph TD
|
|
|
68
73
|
- [ ] Detection ran at session start via `environment-detection/scripts/preflight.js`, with `<environment_info>` inspection and probing used only as fallback
|
|
69
74
|
- [ ] Adopted syntax matches detected shell: Git Bash uses `/`, `$VAR`, Unix cmds without `dir`/`del`; PowerShell uses `$env:VAR` and cmdlets; CMD uses `\`, `%VAR%`, `dir`/`del`/`copy` without Unix cmds
|
|
70
75
|
- [ ] All commands stayed inside `process.cwd()`; no commands ran outside the current project root
|
|
71
|
-
- [ ]
|
|
76
|
+
- [ ] Ordinary detection changed no workspace integration files; touchpoint inspection used `--check` or safely skipped an unavailable local runtime
|
|
77
|
+
- [ ] Mutating self-heal ran only for explicit install/setup/repair intent and only on a supported local platform surface
|
|
78
|
+
- [ ] OpenCode was kept on its separate plugin runtime; skills-only distributions did not assume a local installer
|
|
79
|
+
- [ ] No toolchain installation was attempted; scope stayed to detection and alignment
|
|
72
80
|
- [ ] After three failures of the same command, execution stopped blind retry and triggered `zoom-out`
|
|
73
81
|
- [ ] Shell detail followed `environment-detection/references/shell-syntax-rules.md` where needed
|
|
@@ -4,38 +4,37 @@ description: Use at session start (Discover phase) to detect and align with the
|
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
metadata:
|
|
6
6
|
author: Miya Daniel
|
|
7
|
-
version: 0.
|
|
7
|
+
version: 0.16.6
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Environment Detection & Shell Alignment
|
|
11
11
|
|
|
12
|
-
Think > Try > Summarize > Record: detect before executing.
|
|
13
|
-
|
|
14
12
|
## 📋 Skill Contract
|
|
15
13
|
|
|
16
14
|
| Component | Specification |
|
|
17
15
|
| :--- | :--- |
|
|
18
16
|
| **Trigger / Input** | Session start or complex terminal sequences. |
|
|
19
|
-
| **Expected Output** |
|
|
20
|
-
| **State Mutations** |
|
|
21
|
-
| **Enforcement Gate** | Preflight; fall back to `<environment_info>`
|
|
17
|
+
| **Expected Output** | OS, shell, PATH, available CLIs. |
|
|
18
|
+
| **State Mutations** | Read-only by default; explicit repair may update Harness files. |
|
|
19
|
+
| **Enforcement Gate** | Preflight; fall back to `<environment_info>` and minimal probes. |
|
|
22
20
|
|
|
23
|
-
Boundary:
|
|
21
|
+
Boundary: stay inside `process.cwd()`. Detection never writes integrations or searches parent/cache paths for another runtime.
|
|
24
22
|
|
|
25
23
|
## Workflow
|
|
26
24
|
|
|
27
|
-
1.
|
|
28
|
-
2.
|
|
29
|
-
3.
|
|
30
|
-
4.
|
|
25
|
+
1. Run `node "<this-skill-dir>/scripts/preflight.js"`; detect OS, shell, CLIs.
|
|
26
|
+
2. Where supported, audit read-only: `node "<this-skill-dir>/../harness-everything/scripts/self-heal.js" --check`. If unavailable, report and continue.
|
|
27
|
+
3. Only explicit install/setup/repair intent may omit `--check`. Repair covers Claude, Codex, Copilot, Cursor, Continue, Hermes. OpenCode has its own plugin runtime; skills-only surfaces may lack repair.
|
|
28
|
+
4. Adopt shell syntax: Git Bash → `/`, `$VAR`, Unix commands; PowerShell → `$env:VAR`, cmdlets; CMD → `\`, `%VAR%`, Windows commands. Three repeated failures → `zoom-out`.
|
|
31
29
|
|
|
32
30
|
Deep dive: <this-skill-dir>/references/shell-syntax-rules.md
|
|
33
31
|
|
|
34
32
|
## USE FOR:
|
|
35
|
-
- session-start
|
|
36
|
-
-
|
|
37
|
-
-
|
|
33
|
+
- session-start environment detection
|
|
34
|
+
- shell/path/toolchain alignment
|
|
35
|
+
- read-only audit or explicit repair
|
|
38
36
|
|
|
39
37
|
## DO NOT USE FOR:
|
|
40
|
-
-
|
|
41
|
-
-
|
|
38
|
+
- implicit repair during detection
|
|
39
|
+
- six-adapter repair on OpenCode/skills-only surfaces
|
|
40
|
+
- work outside the workspace or toolchain installation
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Self-healing installation audit for Harness OS.
|
|
4
4
|
*
|
|
5
|
-
* Audits the six platform integration touchpoints in the current workspace
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* Audits the six platform integration touchpoints in the current workspace.
|
|
6
|
+
* Read-only callers use --check. Repair mode is explicit: only a direct run
|
|
7
|
+
* without --check may delegate to the idempotent installer.
|
|
8
|
+
*
|
|
9
|
+
* environment-detection uses the read-only path; ordinary Discover/preflight
|
|
10
|
+
* must never backfill hooks or advisory files as a side effect.
|
|
11
11
|
*
|
|
12
12
|
* Usage:
|
|
13
13
|
* node self-heal.js Audit and repair anything missing.
|
|
@@ -24,7 +24,26 @@ const fs = require('fs');
|
|
|
24
24
|
const path = require('path');
|
|
25
25
|
const { execSync } = require('child_process');
|
|
26
26
|
const { getHarnessRoot, requireWorkspace } = require('./runtime-paths');
|
|
27
|
-
|
|
27
|
+
|
|
28
|
+
function resolveLocalRuntime(checkOnly) {
|
|
29
|
+
try {
|
|
30
|
+
const { getWorkspaceRoot, isHarnessRepo } = requireWorkspace();
|
|
31
|
+
return { getWorkspaceRoot, isHarnessRepo, harnessSourceDir: getHarnessRoot() };
|
|
32
|
+
} catch (err) {
|
|
33
|
+
const message = err && err.message ? err.message : String(err);
|
|
34
|
+
if (!/Harness runtime root not found/.test(message)) throw err;
|
|
35
|
+
|
|
36
|
+
if (checkOnly) {
|
|
37
|
+
console.log('[Harness Self-Heal Audit]');
|
|
38
|
+
console.log(' SKIPPED Local repair runtime unavailable on this distribution surface.');
|
|
39
|
+
console.log('\nRead-only audit skipped; no workspace files were changed.');
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.error('Cannot repair: local Harness installer/runtime is unavailable on this distribution surface.');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
28
47
|
|
|
29
48
|
const MARKER = 'Harness OS Guidance (Advisory)';
|
|
30
49
|
const HOOK_ID = 'harness:pre:bootstrap';
|
|
@@ -194,8 +213,11 @@ function main() {
|
|
|
194
213
|
const checkOnly = process.argv.includes('--check');
|
|
195
214
|
const forceSelf = process.argv.includes('--force-self');
|
|
196
215
|
|
|
216
|
+
const runtime = resolveLocalRuntime(checkOnly);
|
|
217
|
+
if (!runtime) return;
|
|
218
|
+
|
|
219
|
+
const { getWorkspaceRoot, isHarnessRepo, harnessSourceDir } = runtime;
|
|
197
220
|
const workspaceRoot = getWorkspaceRoot();
|
|
198
|
-
const harnessSourceDir = getHarnessRoot();
|
|
199
221
|
const installerPath = path.join(harnessSourceDir, 'scripts', 'installer.js');
|
|
200
222
|
|
|
201
223
|
console.log(`Workspace: ${workspaceRoot}`);
|
package/package.json
CHANGED
|
@@ -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.6",
|
|
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",
|
|
@@ -4,38 +4,37 @@ description: Use at session start (Discover phase) to detect and align with the
|
|
|
4
4
|
license: Apache-2.0
|
|
5
5
|
metadata:
|
|
6
6
|
author: Miya Daniel
|
|
7
|
-
version: 0.
|
|
7
|
+
version: 0.16.6
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Environment Detection & Shell Alignment
|
|
11
11
|
|
|
12
|
-
Think > Try > Summarize > Record: detect before executing.
|
|
13
|
-
|
|
14
12
|
## 📋 Skill Contract
|
|
15
13
|
|
|
16
14
|
| Component | Specification |
|
|
17
15
|
| :--- | :--- |
|
|
18
16
|
| **Trigger / Input** | Session start or complex terminal sequences. |
|
|
19
|
-
| **Expected Output** |
|
|
20
|
-
| **State Mutations** |
|
|
21
|
-
| **Enforcement Gate** | Preflight; fall back to `<environment_info>`
|
|
17
|
+
| **Expected Output** | OS, shell, PATH, available CLIs. |
|
|
18
|
+
| **State Mutations** | Read-only by default; explicit repair may update Harness files. |
|
|
19
|
+
| **Enforcement Gate** | Preflight; fall back to `<environment_info>` and minimal probes. |
|
|
22
20
|
|
|
23
|
-
Boundary:
|
|
21
|
+
Boundary: stay inside `process.cwd()`. Detection never writes integrations or searches parent/cache paths for another runtime.
|
|
24
22
|
|
|
25
23
|
## Workflow
|
|
26
24
|
|
|
27
|
-
1.
|
|
28
|
-
2.
|
|
29
|
-
3.
|
|
30
|
-
4.
|
|
25
|
+
1. Run `node "<this-skill-dir>/scripts/preflight.js"`; detect OS, shell, CLIs.
|
|
26
|
+
2. Where supported, audit read-only: `node "<this-skill-dir>/../harness-everything/scripts/self-heal.js" --check`. If unavailable, report and continue.
|
|
27
|
+
3. Only explicit install/setup/repair intent may omit `--check`. Repair covers Claude, Codex, Copilot, Cursor, Continue, Hermes. OpenCode has its own plugin runtime; skills-only surfaces may lack repair.
|
|
28
|
+
4. Adopt shell syntax: Git Bash → `/`, `$VAR`, Unix commands; PowerShell → `$env:VAR`, cmdlets; CMD → `\`, `%VAR%`, Windows commands. Three repeated failures → `zoom-out`.
|
|
31
29
|
|
|
32
30
|
Deep dive: <this-skill-dir>/references/shell-syntax-rules.md
|
|
33
31
|
|
|
34
32
|
## USE FOR:
|
|
35
|
-
- session-start
|
|
36
|
-
-
|
|
37
|
-
-
|
|
33
|
+
- session-start environment detection
|
|
34
|
+
- shell/path/toolchain alignment
|
|
35
|
+
- read-only audit or explicit repair
|
|
38
36
|
|
|
39
37
|
## DO NOT USE FOR:
|
|
40
|
-
-
|
|
41
|
-
-
|
|
38
|
+
- implicit repair during detection
|
|
39
|
+
- six-adapter repair on OpenCode/skills-only surfaces
|
|
40
|
+
- work outside the workspace or toolchain installation
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Self-healing installation audit for Harness OS.
|
|
4
4
|
*
|
|
5
|
-
* Audits the six platform integration touchpoints in the current workspace
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* Audits the six platform integration touchpoints in the current workspace.
|
|
6
|
+
* Read-only callers use --check. Repair mode is explicit: only a direct run
|
|
7
|
+
* without --check may delegate to the idempotent installer.
|
|
8
|
+
*
|
|
9
|
+
* environment-detection uses the read-only path; ordinary Discover/preflight
|
|
10
|
+
* must never backfill hooks or advisory files as a side effect.
|
|
11
11
|
*
|
|
12
12
|
* Usage:
|
|
13
13
|
* node self-heal.js Audit and repair anything missing.
|
|
@@ -24,7 +24,26 @@ const fs = require('fs');
|
|
|
24
24
|
const path = require('path');
|
|
25
25
|
const { execSync } = require('child_process');
|
|
26
26
|
const { getHarnessRoot, requireWorkspace } = require('./runtime-paths');
|
|
27
|
-
|
|
27
|
+
|
|
28
|
+
function resolveLocalRuntime(checkOnly) {
|
|
29
|
+
try {
|
|
30
|
+
const { getWorkspaceRoot, isHarnessRepo } = requireWorkspace();
|
|
31
|
+
return { getWorkspaceRoot, isHarnessRepo, harnessSourceDir: getHarnessRoot() };
|
|
32
|
+
} catch (err) {
|
|
33
|
+
const message = err && err.message ? err.message : String(err);
|
|
34
|
+
if (!/Harness runtime root not found/.test(message)) throw err;
|
|
35
|
+
|
|
36
|
+
if (checkOnly) {
|
|
37
|
+
console.log('[Harness Self-Heal Audit]');
|
|
38
|
+
console.log(' SKIPPED Local repair runtime unavailable on this distribution surface.');
|
|
39
|
+
console.log('\nRead-only audit skipped; no workspace files were changed.');
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.error('Cannot repair: local Harness installer/runtime is unavailable on this distribution surface.');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
28
47
|
|
|
29
48
|
const MARKER = 'Harness OS Guidance (Advisory)';
|
|
30
49
|
const HOOK_ID = 'harness:pre:bootstrap';
|
|
@@ -194,8 +213,11 @@ function main() {
|
|
|
194
213
|
const checkOnly = process.argv.includes('--check');
|
|
195
214
|
const forceSelf = process.argv.includes('--force-self');
|
|
196
215
|
|
|
216
|
+
const runtime = resolveLocalRuntime(checkOnly);
|
|
217
|
+
if (!runtime) return;
|
|
218
|
+
|
|
219
|
+
const { getWorkspaceRoot, isHarnessRepo, harnessSourceDir } = runtime;
|
|
197
220
|
const workspaceRoot = getWorkspaceRoot();
|
|
198
|
-
const harnessSourceDir = getHarnessRoot();
|
|
199
221
|
const installerPath = path.join(harnessSourceDir, 'scripts', 'installer.js');
|
|
200
222
|
|
|
201
223
|
console.log(`Workspace: ${workspaceRoot}`);
|