harness-everything 0.20.0 → 0.20.1

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.0",
13
+ "version": "0.20.1",
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.0",
4
+ "version": "0.20.1",
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.20.1](https://github.com/dyphn1/Harness-everything/compare/v0.20.0...v0.20.1) (2026-09-22)
6
+
7
+ ### Bug Fixes
8
+
9
+ * **distribution:** support older claude plugin clis ([e00e665](https://github.com/dyphn1/Harness-everything/commit/e00e665eeebf6d1f6fc0469eed435ec0562bc226)), closes [#221](https://github.com/dyphn1/Harness-everything/issues/221)
10
+
5
11
  ## [0.20.0](https://github.com/dyphn1/Harness-everything/compare/v0.19.1...v0.20.0) (2026-09-21)
6
12
 
7
13
  ### Features
@@ -12,7 +12,7 @@ const {
12
12
 
13
13
  const ROOT = path.resolve(__dirname, '..');
14
14
 
15
- function fakeHost({ claudeInstalled = false, codexInstalled = false, claudeMarketplace = true, codexMarketplace = true, unknownClaudePluginState = false } = {}) {
15
+ function fakeHost({ claudeInstalled = false, codexInstalled = false, claudeMarketplace = true, codexMarketplace = true, unknownClaudePluginState = false, unknownClaudeYesFlag = false } = {}) {
16
16
  const calls = [];
17
17
  const state = {
18
18
  claudeInstalled,
@@ -44,6 +44,9 @@ function fakeHost({ claudeInstalled = false, codexInstalled = false, claudeMarke
44
44
  if (unknownClaudePluginState) return { status: 1, stdout: '', stderr: 'unsupported list' };
45
45
  return { status: 0, stdout: state.claudeInstalled ? 'harness-everything@harness-everything\n' : '', stderr: '' };
46
46
  }
47
+ if (unknownClaudeYesFlag && joined.includes('--yes')) {
48
+ return { status: 1, stdout: '', stderr: "error: unknown option '--yes'" };
49
+ }
47
50
  if (joined.startsWith('plugin install') || joined.startsWith('plugin update')) {
48
51
  state.claudeInstalled = true;
49
52
  return { status: 0, stdout: '{}', stderr: '' };
@@ -118,6 +121,17 @@ assert.strictEqual(findPlugin({ plugins: [{ id: 'harness-everything@harness-ever
118
121
  assert.strictEqual(callsFor(fake.calls, 'claude', 'plugin install').length, 0, 'installed Claude plugin must not reinstall');
119
122
  }
120
123
 
124
+ {
125
+ const fake = fakeHost({ claudeInstalled: true, unknownClaudeYesFlag: true });
126
+ const result = runHost('claude', fake);
127
+ const updateCalls = callsFor(fake.calls, 'claude', 'plugin update');
128
+ assert.strictEqual(result.failed, 0, 'unsupported Claude --yes must fall back to a compatible update command');
129
+ assert.strictEqual(result.results[0].action, 'update');
130
+ assert.strictEqual(updateCalls.length, 2, 'unsupported --yes must cause one compatibility retry');
131
+ assert.ok(updateCalls[0].args.includes('--yes'), 'first update attempt should use the current non-interactive flag');
132
+ assert.ok(!updateCalls[1].args.includes('--yes'), 'compatibility retry must omit unsupported --yes');
133
+ }
134
+
121
135
  {
122
136
  const fake = fakeHost({ codexInstalled: false });
123
137
  const result = runHost('codex', fake);
@@ -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.0",
4
+ "version": "0.20.1",
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.0",
3
+ "version": "0.20.1",
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.0",
3
+ "version": "0.20.1",
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.0",
4
+ "version": "0.20.1",
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:4a1f9475-5e4e-546c-884f-2449e48966ef",
5
+ "serialNumber": "urn:uuid:02942ee4-18db-5ce8-9307-59cd8d7ba31a",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-09-21T15:41:05.053Z",
8
+ "timestamp": "2026-09-22T01:14:56.692Z",
9
9
  "tools": [
10
10
  {
11
11
  "vendor": "Harness Everything",
12
12
  "name": "generate-sbom.js",
13
- "version": "0.20.0"
13
+ "version": "0.20.1"
14
14
  }
15
15
  ],
16
16
  "component": {
17
17
  "type": "application",
18
- "bom-ref": "pkg:npm/harness-everything@0.20.0",
18
+ "bom-ref": "pkg:npm/harness-everything@0.20.1",
19
19
  "name": "harness-everything",
20
- "version": "0.20.0",
21
- "purl": "pkg:npm/harness-everything@0.20.0"
20
+ "version": "0.20.1",
21
+ "purl": "pkg:npm/harness-everything@0.20.1"
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.0",
2002
+ "ref": "pkg:npm/harness-everything@0.20.1",
2003
2003
  "dependsOn": [
2004
2004
  "pkg:npm/%40commitlint/cli@19.8.1",
2005
2005
  "pkg:npm/%40commitlint/config-conventional@19.8.1",
@@ -162,14 +162,14 @@ function createContext(options = {}) {
162
162
  return context;
163
163
  }
164
164
 
165
- function invoke(context, command, args, { mutate = false, label = command } = {}) {
165
+ function invoke(context, command, args, { mutate = false, label = command, warnOnFailure = true } = {}) {
166
166
  const rendered = commandLine(command, args);
167
167
  if (mutate && context.dryRun) {
168
168
  context.log(`[dry-run] ${rendered}`);
169
169
  return { status: 0, stdout: '', stderr: '', dryRun: true };
170
170
  }
171
171
  const result = context.runner(command, args, { label });
172
- if (!result || result.status !== 0) {
172
+ if (warnOnFailure && (!result || result.status !== 0)) {
173
173
  context.warn(`[failed] ${rendered}\n ${resultError(result)}`);
174
174
  }
175
175
  return result || { status: 1, stdout: '', stderr: 'runner returned no result' };
@@ -179,6 +179,39 @@ function query(context, command, args) {
179
179
  return context.runner(command, args, { query: true }) || { status: 1, stdout: '', stderr: 'runner returned no result' };
180
180
  }
181
181
 
182
+ function hasUnknownOption(result, option) {
183
+ const output = [result && result.stderr, result && result.stdout, result && result.error && result.error.message]
184
+ .map(value => String(value || ''))
185
+ .join('\n');
186
+ return new RegExp(`unknown option\\s+['"]?${escapeRegExp(option)}['"]?`, 'i').test(output);
187
+ }
188
+
189
+ function runClaudePluginMutation(context, action, pluginId) {
190
+ const baseArgs = [
191
+ 'plugin', action, pluginId,
192
+ '--scope', 'user'
193
+ ];
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;
202
+
203
+ if (!hasUnknownOption(current, '--yes')) {
204
+ context.warn(`[failed] ${commandLine('claude', currentArgs)}\n ${resultError(current)}`);
205
+ return current;
206
+ }
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
+ }
214
+
182
215
  function listState(context, { command, jsonArgs, plainArgs, detectJson, detectText }) {
183
216
  const jsonResult = query(context, command, jsonArgs);
184
217
  if (jsonResult.status === 0) {
@@ -314,10 +347,11 @@ function syncClaude(context) {
314
347
  if (!refreshed.ok) return { host: 'claude', status: 'failed', error: refreshed.error };
315
348
 
316
349
  const action = installed.value ? 'update' : 'install';
317
- const result = invoke(context, 'claude', [
318
- 'plugin', action, `${context.plugin}@${context.marketplace}`,
319
- '--scope', 'user', '--yes', '--json'
320
- ], { mutate: true, label: `claude plugin ${action}` });
350
+ const result = runClaudePluginMutation(
351
+ context,
352
+ action,
353
+ `${context.plugin}@${context.marketplace}`
354
+ );
321
355
  if (result.status !== 0) return { host: 'claude', status: 'failed', error: resultError(result) };
322
356
 
323
357
  const verification = verifyPlugin(context, 'Claude', queryClaudePlugin);