harness-everything 0.20.1 → 0.20.3

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.
@@ -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.20.1",
13
+ "version": "0.20.3",
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.20.1",
4
+ "version": "0.20.3",
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.20.3](https://github.com/dyphn1/Harness-everything/compare/v0.20.2...v0.20.3) (2026-09-22)
6
+
7
+ ### Bug Fixes
8
+
9
+ * **distribution:** support windows cli shims ([f634e6d](https://github.com/dyphn1/Harness-everything/commit/f634e6d84fd8d0751604efa1d9b8acd5e7d90b8b)), closes [#221](https://github.com/dyphn1/Harness-everything/issues/221)
10
+
11
+ ## [0.20.2](https://github.com/dyphn1/Harness-everything/compare/v0.20.1...v0.20.2) (2026-09-22)
12
+
13
+ ### Bug Fixes
14
+
15
+ * **distribution:** handle legacy claude flags ([2e09915](https://github.com/dyphn1/Harness-everything/commit/2e09915cff6c7cbf7cd10b08587df18264403a01)), closes [#221](https://github.com/dyphn1/Harness-everything/issues/221)
16
+
5
17
  ## [0.20.1](https://github.com/dyphn1/Harness-everything/compare/v0.20.0...v0.20.1) (2026-09-22)
6
18
 
7
19
  ### Bug Fixes
@@ -2,8 +2,10 @@
2
2
 
3
3
  const assert = require('assert');
4
4
  const fs = require('fs');
5
+ const os = require('os');
5
6
  const path = require('path');
6
7
  const {
8
+ createContext,
7
9
  findMarketplace,
8
10
  findPlugin,
9
11
  parseJsonOutput,
@@ -12,7 +14,7 @@ const {
12
14
 
13
15
  const ROOT = path.resolve(__dirname, '..');
14
16
 
15
- function fakeHost({ claudeInstalled = false, codexInstalled = false, claudeMarketplace = true, codexMarketplace = true, unknownClaudePluginState = false, unknownClaudeYesFlag = false } = {}) {
17
+ function fakeHost({ claudeInstalled = false, codexInstalled = false, claudeMarketplace = true, codexMarketplace = true, unknownClaudePluginState = false, unknownClaudeYesFlag = false, unknownClaudeJsonFlag = false } = {}) {
16
18
  const calls = [];
17
19
  const state = {
18
20
  claudeInstalled,
@@ -47,6 +49,9 @@ function fakeHost({ claudeInstalled = false, codexInstalled = false, claudeMarke
47
49
  if (unknownClaudeYesFlag && joined.includes('--yes')) {
48
50
  return { status: 1, stdout: '', stderr: "error: unknown option '--yes'" };
49
51
  }
52
+ if (unknownClaudeJsonFlag && joined.includes('--json')) {
53
+ return { status: 1, stdout: '', stderr: "error: unknown option '--json'" };
54
+ }
50
55
  if (joined.startsWith('plugin install') || joined.startsWith('plugin update')) {
51
56
  state.claudeInstalled = true;
52
57
  return { status: 0, stdout: '{}', stderr: '' };
@@ -132,6 +137,17 @@ assert.strictEqual(findPlugin({ plugins: [{ id: 'harness-everything@harness-ever
132
137
  assert.ok(!updateCalls[1].args.includes('--yes'), 'compatibility retry must omit unsupported --yes');
133
138
  }
134
139
 
140
+ {
141
+ const fake = fakeHost({ claudeInstalled: true, unknownClaudeYesFlag: true, unknownClaudeJsonFlag: true });
142
+ const result = runHost('claude', fake);
143
+ const updateCalls = callsFor(fake.calls, 'claude', 'plugin update');
144
+ assert.strictEqual(result.failed, 0, 'unsupported Claude --yes and --json must fall back to a compatible update command');
145
+ assert.strictEqual(updateCalls.length, 3, 'each unsupported option must cause one compatibility retry');
146
+ assert.ok(updateCalls[0].args.includes('--yes') && updateCalls[0].args.includes('--json'), 'first update attempt should use current flags');
147
+ assert.ok(!updateCalls[1].args.includes('--yes') && updateCalls[1].args.includes('--json'), 'second attempt should omit only unsupported --yes');
148
+ assert.ok(!updateCalls[2].args.includes('--yes') && !updateCalls[2].args.includes('--json'), 'final attempt must omit both unsupported flags');
149
+ }
150
+
135
151
  {
136
152
  const fake = fakeHost({ codexInstalled: false });
137
153
  const result = runHost('codex', fake);
@@ -164,6 +180,21 @@ assert.strictEqual(findPlugin({ plugins: [{ id: 'harness-everything@harness-ever
164
180
  assert.strictEqual(result.failed, 0);
165
181
  }
166
182
 
183
+ if (process.platform === 'win32') {
184
+ const fixtureDir = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-plugin-sync-command-'));
185
+ const originalPath = process.env.PATH;
186
+ try {
187
+ fs.writeFileSync(path.join(fixtureDir, 'harness-codex-fixture.cmd'), '@echo off\r\necho codex-cli fixture\r\n');
188
+ process.env.PATH = `${fixtureDir};${originalPath || ''}`;
189
+ const context = createContext();
190
+ assert.strictEqual(context.commandAvailable('harness-codex-fixture'), true, 'Windows .cmd CLI shims must be detected');
191
+ } finally {
192
+ if (originalPath === undefined) delete process.env.PATH;
193
+ else process.env.PATH = originalPath;
194
+ fs.rmSync(fixtureDir, { recursive: true, force: true });
195
+ }
196
+ }
197
+
167
198
  for (const wrapper of ['scripts/plugin-sync.sh', 'scripts/plugin-sync.ps1']) {
168
199
  const text = fs.readFileSync(path.join(ROOT, wrapper), 'utf8');
169
200
  assert.match(text, /plugin-sync\.js/);
@@ -84,6 +84,8 @@ The command detects Claude Code and Codex independently, ensures the Harness mar
84
84
 
85
85
  The installed branch is intentionally an update branch even when the current release is already the newest version; the host command may report “already latest.” Codex marketplace upgrade is the current native refresh operation; the command does not edit private cache paths or `config.toml`. These are deterministic command/state tests, not live-host evidence, so `liveHostVerification` remains `Unknown` in the matrix.
86
86
 
87
+ On Windows, the synchronizer retries through `ComSpec` when Node cannot directly start a CLI shim, so npm-installed `codex.cmd` and `claude.cmd` commands remain discoverable when the wrapper is launched from Git Bash.
88
+
87
89
  ### Explicit Codex user-hook compatibility fallback
88
90
 
89
91
  Current Codex documentation supports plugin-bundled hooks, so native plugin mounting remains the preferred path. Some host/source combinations have nevertheless failed to expose enabled plugin hooks for review/entry attribution (#122 and upstream Codex reports). Harness therefore provides an **explicit compatibility fallback**, not an automatic replacement for native plugin hooks:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "harness-enforcement",
3
3
  "description": "Repository inventory for the opencode enforcement plugin and its standalone helper",
4
- "version": "0.20.1",
4
+ "version": "0.20.3",
5
5
  "runtime": "index.mjs",
6
6
  "hooks": {
7
7
  "verify": "hooks/verify.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harness-everything",
3
- "version": "0.20.1",
3
+ "version": "0.20.3",
4
4
  "description": "Harness OS: An Orchestrated Agent Operating System for AI-driven Development",
5
5
  "main": "harness-everything/scripts/bootstrap.js",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harness-everything",
3
- "version": "0.20.1",
3
+ "version": "0.20.3",
4
4
  "description": "Invariant-first engineering harness for routing, verification, and failure recovery while preserving agent autonomy.",
5
5
  "author": {
6
6
  "name": "Miya Daniel",
@@ -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.20.1",
4
+ "version": "0.20.3",
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",
package/sbom.cdx.json CHANGED
@@ -2,23 +2,23 @@
2
2
  "$schema": "https://cyclonedx.org/schema/bom-1.7.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.7",
5
- "serialNumber": "urn:uuid:02942ee4-18db-5ce8-9307-59cd8d7ba31a",
5
+ "serialNumber": "urn:uuid:c82181bb-3272-5951-8990-f785d038f412",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-22T01:14:56.692Z",
8
+ "timestamp": "2026-09-22T01:49:40.805Z",
9
9
  "tools": [
10
10
  {
11
11
  "vendor": "Harness Everything",
12
12
  "name": "generate-sbom.js",
13
- "version": "0.20.1"
13
+ "version": "0.20.3"
14
14
  }
15
15
  ],
16
16
  "component": {
17
17
  "type": "application",
18
- "bom-ref": "pkg:npm/harness-everything@0.20.1",
18
+ "bom-ref": "pkg:npm/harness-everything@0.20.3",
19
19
  "name": "harness-everything",
20
- "version": "0.20.1",
21
- "purl": "pkg:npm/harness-everything@0.20.1"
20
+ "version": "0.20.3",
21
+ "purl": "pkg:npm/harness-everything@0.20.3"
22
22
  }
23
23
  },
24
24
  "components": [
@@ -1999,7 +1999,7 @@
1999
1999
  ]
2000
2000
  },
2001
2001
  {
2002
- "ref": "pkg:npm/harness-everything@0.20.1",
2002
+ "ref": "pkg:npm/harness-everything@0.20.3",
2003
2003
  "dependsOn": [
2004
2004
  "pkg:npm/%40commitlint/cli@19.8.1",
2005
2005
  "pkg:npm/%40commitlint/config-conventional@19.8.1",
@@ -20,11 +20,21 @@ const DEFAULTS = Object.freeze({
20
20
  });
21
21
 
22
22
  function defaultRunner(command, args) {
23
- const result = spawnSync(command, args, {
23
+ const options = {
24
24
  encoding: 'utf8',
25
25
  stdio: ['ignore', 'pipe', 'pipe'],
26
26
  windowsHide: true
27
- });
27
+ };
28
+ let result = spawnSync(command, args, options);
29
+
30
+ // npm-installed Windows CLIs are often .cmd shims. Node can report those
31
+ // shims as an executable-resolution error when this script is launched from
32
+ // Git Bash, even though the same command is available to the shell.
33
+ if (process.platform === 'win32' && result.error && ['EACCES', 'EINVAL', 'ENOENT'].includes(result.error.code)) {
34
+ const comspec = process.env.ComSpec || process.env.COMSPEC || 'cmd.exe';
35
+ result = spawnSync(comspec, ['/d', '/c', command, ...args], options);
36
+ }
37
+
28
38
  return {
29
39
  status: result.status === null ? 1 : result.status,
30
40
  stdout: result.stdout || '',
@@ -191,25 +201,27 @@ function runClaudePluginMutation(context, action, pluginId) {
191
201
  'plugin', action, pluginId,
192
202
  '--scope', 'user'
193
203
  ];
194
- const currentArgs = [...baseArgs, '--yes', '--json'];
195
- const compatibleArgs = [...baseArgs, '--json'];
196
- const current = invoke(context, 'claude', currentArgs, {
197
- mutate: true,
198
- label: `claude plugin ${action}`,
199
- warnOnFailure: false
200
- });
201
- if (current.status === 0) return current;
204
+ let args = [...baseArgs, '--yes', '--json'];
205
+ let attempt = 0;
206
+
207
+ while (true) {
208
+ const result = invoke(context, 'claude', args, {
209
+ mutate: true,
210
+ label: attempt === 0 ? `claude plugin ${action}` : `claude plugin ${action} compatibility retry`,
211
+ warnOnFailure: false
212
+ });
213
+ if (result.status === 0) return result;
214
+
215
+ const unsupported = ['--yes', '--json'].find(option => args.includes(option) && hasUnknownOption(result, option));
216
+ if (!unsupported) {
217
+ context.warn(`[failed] ${commandLine('claude', args)}\n ${resultError(result)}`);
218
+ return result;
219
+ }
202
220
 
203
- if (!hasUnknownOption(current, '--yes')) {
204
- context.warn(`[failed] ${commandLine('claude', currentArgs)}\n ${resultError(current)}`);
205
- return current;
221
+ args = args.filter(arg => arg !== unsupported);
222
+ attempt += 1;
223
+ context.warn(`[notice] Claude CLI does not support ${unsupported}; retrying ${action} without that option.`);
206
224
  }
207
-
208
- context.warn(`[notice] Claude CLI does not support --yes; retrying ${action} without that option.`);
209
- return invoke(context, 'claude', compatibleArgs, {
210
- mutate: true,
211
- label: `claude plugin ${action} compatibility retry`
212
- });
213
225
  }
214
226
 
215
227
  function listState(context, { command, jsonArgs, plainArgs, detectJson, detectText }) {