harness-everything 0.30.7 → 0.30.9

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.
Files changed (36) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.github/workflows/ci.yml +31 -0
  4. package/CHANGELOG.md +38 -0
  5. package/README.md +1 -1
  6. package/ci/fixtures/system-one-resident-stub.py +7 -1
  7. package/ci/mechanism-system-one-resident.test.js +70 -3
  8. package/ci/prompt-contract-regressions.test.js +80 -0
  9. package/docs/workflows/fable-discipline.md +18 -59
  10. package/docs/workflows/git-commit.md +21 -67
  11. package/docs/workflows/grill-me.md +20 -12
  12. package/docs/workflows/grill-with-docs.md +21 -12
  13. package/evals/fable-discipline/tasks/positive-trigger.yaml +1 -1
  14. package/evals/git-commit/tasks/positive-trigger.yaml +1 -1
  15. package/evals/grill-me/tasks/positive-trigger.yaml +1 -1
  16. package/fable-discipline/SKILL.md +13 -13
  17. package/fable-discipline/references/discipline-rules.md +4 -4
  18. package/git-commit/SKILL.md +14 -14
  19. package/git-commit/references/commit-flow.md +4 -2
  20. package/grill-me/SKILL.md +19 -21
  21. package/grill-me/references/grilling-playbook.md +5 -5
  22. package/grill-with-docs/SKILL.md +3 -3
  23. package/grill-with-docs/references/session-playbook.md +4 -4
  24. package/opencode-plugin/plugin.json +1 -1
  25. package/package.json +1 -1
  26. package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
  27. package/plugins/harness-everything/plugin.json +1 -1
  28. package/plugins/harness-everything/skills/fable-discipline/SKILL.md +13 -13
  29. package/plugins/harness-everything/skills/fable-discipline/references/discipline-rules.md +4 -4
  30. package/plugins/harness-everything/skills/git-commit/SKILL.md +14 -14
  31. package/plugins/harness-everything/skills/git-commit/references/commit-flow.md +4 -2
  32. package/plugins/harness-everything/skills/grill-me/SKILL.md +19 -21
  33. package/plugins/harness-everything/skills/grill-me/references/grilling-playbook.md +5 -5
  34. package/plugins/harness-everything/skills/grill-with-docs/SKILL.md +3 -3
  35. package/plugins/harness-everything/skills/grill-with-docs/references/session-playbook.md +4 -4
  36. package/sbom.cdx.json +7 -7
@@ -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.30.7",
13
+ "version": "0.30.9",
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.30.7",
4
+ "version": "0.30.9",
5
5
  "author": {
6
6
  "name": "Miya Daniel"
7
7
  },
@@ -29,6 +29,37 @@ jobs:
29
29
  - name: Run focused mutation checks
30
30
  run: npm run test:mutations
31
31
 
32
+ # Pin the patched version: floating Node 24 already passed before #284.
33
+ system-one-windows-node24-patched:
34
+ runs-on: windows-latest
35
+ steps:
36
+ - uses: actions/checkout@v7
37
+ - uses: actions/setup-node@v7
38
+ with:
39
+ node-version: '24.20.0'
40
+ - name: Verify exact patched runtime
41
+ run: node -e "if (process.versions.node !== '24.20.0') process.exit(1)"
42
+ - name: Exercise real evaluator subprocess and repeated resident teardown
43
+ run: node --test ci/mechanism-system-one-resident.test.js
44
+
45
+ # Node >=22 also includes the odd-numbered Node 23 line. Keep its
46
+ # documented Windows shutdown failure visible, without narrowing engines.
47
+ system-one-windows-node-legacy-policy:
48
+ runs-on: windows-latest
49
+ strategy:
50
+ fail-fast: false
51
+ matrix:
52
+ node: ['23.6.0', '24.15.0']
53
+ steps:
54
+ - uses: actions/checkout@v7
55
+ - uses: actions/setup-node@v7
56
+ with:
57
+ node-version: ${{ matrix.node }}
58
+ - name: Verify exact affected runtime
59
+ run: node -e "if (process.versions.node !== '${{ matrix.node }}') process.exit(1)"
60
+ - name: Confirm explicit RS13 skip with version-policy unit coverage
61
+ run: node --test --test-name-pattern="S1-RS00|S1-RS13" ci/mechanism-system-one-resident.test.js
62
+
32
63
  runtime-floor:
33
64
  runs-on: ubuntu-latest
34
65
  steps:
package/CHANGELOG.md CHANGED
@@ -2,6 +2,44 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## [0.30.9](https://github.com/dyphn1/Harness-everything/compare/v0.30.8...v0.30.9) (2026-10-08)
6
+
7
+ ### Bug Fixes
8
+
9
+ * **system-one:** cover Windows Node 23 shutdown regression ([75ef983](https://github.com/dyphn1/Harness-everything/commit/75ef9833e4fcfb697c8323836f08eed3dfc7ff8d))
10
+ * **test:** correct Windows Node version policy regex ([c0b63cc](https://github.com/dyphn1/Harness-everything/commit/c0b63cc3f18dc7126e4680f4fa7682ea2a4729ef))
11
+
12
+ ## [0.30.8](https://github.com/dyphn1/Harness-everything/compare/v0.30.7...v0.30.8) (2026-10-07)
13
+
14
+ ### Bug Fixes
15
+
16
+ * **fable:** align discipline side effects ([#275](https://github.com/dyphn1/Harness-everything/issues/275) [#277](https://github.com/dyphn1/Harness-everything/issues/277)) ([8aa4c99](https://github.com/dyphn1/Harness-everything/commit/8aa4c99778c7f2c70e3ca434fce9ff34d30e7ea7))
17
+ * **fable:** compact contract and preserve advisory divergence ([81a97ad](https://github.com/dyphn1/Harness-everything/commit/81a97ad82c131f406aa2000bcda15e8819802744))
18
+ * **fable:** make build divergence advisory ([#275](https://github.com/dyphn1/Harness-everything/issues/275)) ([45aa418](https://github.com/dyphn1/Harness-everything/commit/45aa418b596e6bb11f8f9a08e0217923263c7594))
19
+ * **fable:** make commit boundaries permission-aware ([#277](https://github.com/dyphn1/Harness-everything/issues/277)) ([c778dd4](https://github.com/dyphn1/Harness-everything/commit/c778dd4f98b3ac4ecd375e2173d0bc839083b153))
20
+ * **fable:** restore semantic contract strength ([df80aa0](https://github.com/dyphn1/Harness-everything/commit/df80aa0d9dac9391258b990329e816f5c06af826))
21
+ * **fable:** restore Waza-compliant contract structure ([e26ffdf](https://github.com/dyphn1/Harness-everything/commit/e26ffdf68d1e492202e131eeebf57665e0e2c269))
22
+ * **fable:** sync compact contract ([946bb27](https://github.com/dyphn1/Harness-everything/commit/946bb27622f6244d55ddd352955ebe2210878278))
23
+ * **fable:** sync discipline side effects ([#275](https://github.com/dyphn1/Harness-everything/issues/275) [#277](https://github.com/dyphn1/Harness-everything/issues/277)) ([e0205c2](https://github.com/dyphn1/Harness-everything/commit/e0205c2063e745a47a58eb70959bfda67e1eebe2))
24
+ * **fable:** sync divergence contract ([#275](https://github.com/dyphn1/Harness-everything/issues/275)) ([f225241](https://github.com/dyphn1/Harness-everything/commit/f225241fe201f5468d58283396a96b3f703d8160))
25
+ * **fable:** sync permission-aware commits ([#277](https://github.com/dyphn1/Harness-everything/issues/277)) ([78b7a32](https://github.com/dyphn1/Harness-everything/commit/78b7a32ba61f759d82ca8d61e297239062ed713c))
26
+ * **fable:** sync semantic contract strength ([01a665d](https://github.com/dyphn1/Harness-everything/commit/01a665d6f95da0d250e4d080409e0ebba8756af7))
27
+ * **fable:** sync Waza-compliant contract ([74619c0](https://github.com/dyphn1/Harness-everything/commit/74619c00c3f1d76438f168dee1353e9fd4a112ef))
28
+ * **git:** compact authorized commit contract ([cd3a3eb](https://github.com/dyphn1/Harness-everything/commit/cd3a3eb1978778c372be03c4611b50fb570ba802))
29
+ * **git:** require commit authorization ([#277](https://github.com/dyphn1/Harness-everything/issues/277)) ([e91f90c](https://github.com/dyphn1/Harness-everything/commit/e91f90cc472ca0310f3bfdbd4fede3f1c89b6884))
30
+ * **git:** restore MUST SHOULD contract strength ([353ff80](https://github.com/dyphn1/Harness-everything/commit/353ff80ee2a17894b76799e96c6a2128a67aa7ee))
31
+ * **git:** restore Waza-compliant contract structure ([4e0db0a](https://github.com/dyphn1/Harness-everything/commit/4e0db0a173c0fa42695e0cbccf963186dbee1d35))
32
+ * **git:** sync commit authorization ([#277](https://github.com/dyphn1/Harness-everything/issues/277)) ([168fd1f](https://github.com/dyphn1/Harness-everything/commit/168fd1f69eed2f3246ca0eb2b7f5e457a1f8891d))
33
+ * **git:** sync compact commit contract ([f4bd248](https://github.com/dyphn1/Harness-everything/commit/f4bd2487d04e934014acb264275e1b694053364f))
34
+ * **git:** sync MUST SHOULD contract strength ([f2e01f3](https://github.com/dyphn1/Harness-everything/commit/f2e01f32a6174ea14c90751344a9357c32db2b2c))
35
+ * **git:** sync Waza-compliant contract ([dc73922](https://github.com/dyphn1/Harness-everything/commit/dc73922f7a2ac708ae319dfd29d3c57ccccfb3ba))
36
+ * **grill:** compact explicit handoff contract ([8aa0f3e](https://github.com/dyphn1/Harness-everything/commit/8aa0f3effbc523c1951a3f3697cb4939eab01b99))
37
+ * **grill:** preserve explicit docs handoff ([#274](https://github.com/dyphn1/Harness-everything/issues/274)) ([8cc7b4f](https://github.com/dyphn1/Harness-everything/commit/8cc7b4fe84fb628234d2142d4c12d6748aa23bbd))
38
+ * **grill:** preserve explicit spec handoff ([#274](https://github.com/dyphn1/Harness-everything/issues/274)) ([ffd3f45](https://github.com/dyphn1/Harness-everything/commit/ffd3f455c45049437a15c7ca69b686b5a155412c))
39
+ * **grill:** sync compact handoff contract ([900f03a](https://github.com/dyphn1/Harness-everything/commit/900f03a9c0fc6a14d6ce525ae6edd3fab6c27967))
40
+ * **grill:** sync explicit docs handoff ([#274](https://github.com/dyphn1/Harness-everything/issues/274)) ([3501bc5](https://github.com/dyphn1/Harness-everything/commit/3501bc54fb1fc905a366f6f26d816ca9b1157503))
41
+ * **grill:** sync explicit spec handoff ([#274](https://github.com/dyphn1/Harness-everything/issues/274)) ([4bf3c58](https://github.com/dyphn1/Harness-everything/commit/4bf3c58ac7f333eaf3a263ba1c61d5ea9c27a765))
42
+
5
43
  ## [0.30.7](https://github.com/dyphn1/Harness-everything/compare/v0.30.6...v0.30.7) (2026-10-07)
6
44
 
7
45
  ### Bug Fixes
package/README.md CHANGED
@@ -48,7 +48,7 @@ The exact "Harness" behavior depends on the installation surface. Claude Code ha
48
48
 
49
49
  Harness integrates directly into your workspace. There is no heavy daemon, no paid external APIs, and zero configuration required.
50
50
 
51
- **Runtime:** Harness supports **Node.js 22+**. Node.js **24** is the primary development and CI runtime (`.nvmrc`). The generated current-state runtime/workflow summary is [docs/repository-contract.md](docs/repository-contract.md).
51
+ **Runtime:** Harness supports **Node.js 22+** (including odd-numbered versions); Node.js **24** is the primary development and CI runtime (`.nvmrc`). **On Windows, System One evaluator subprocess verification should use Node 22 or Node 24.20+**. Node 23.x has a documented Windows process-shutdown assertion ([nodejs/node#56645](https://github.com/nodejs/node/issues/56645)); Node 24.0–24.19 predates the backported libuv fix ([nodejs/node#61999](https://github.com/nodejs/node/pull/61999)) and may likewise crash at process exit (`0xC0000409`). RS13 visibly skips **only** on those Windows versions while retaining the real evaluator subprocess elsewhere. A skip is not a pass or evidence of a fixed Node runtime. CI pins Windows Node 23.6.0 and 24.15.0 to validate their skip policy, and Node 24.20.0 to run the complete subprocess/regression suite. These tests do not reduce the package's general `>=22` engine compatibility claim. The generated current-state runtime/workflow summary is [docs/repository-contract.md](docs/repository-contract.md).
52
52
 
53
53
  ```bash
54
54
  # Option A: Claude Code plugin (marketplace manifest included)
@@ -1,5 +1,6 @@
1
1
  """Stub scorer behind the real resident server code; never model-quality evidence."""
2
2
  import importlib.util
3
+ import json
3
4
  from pathlib import Path
4
5
  import sys
5
6
  import time
@@ -28,4 +29,9 @@ def factory(weights, manifest):
28
29
  if __name__ == '__main__':
29
30
  if sys.argv[1:2] != ['--serve']:
30
31
  sys.exit(2)
31
- sys.exit(adapter.serve_main(sys.argv[2:], scorer_factory=factory))
32
+ result = adapter.serve_main(sys.argv[2:], scorer_factory=factory)
33
+ # Deterministic teardown fixture: the state/socket are closed, but PID is
34
+ # deliberately alive to distinguish state unlink from full process exit.
35
+ if json.loads(sys.argv[2]).get('modelId') == 'stub-exit-linger':
36
+ time.sleep(0.5)
37
+ sys.exit(result)
@@ -29,10 +29,57 @@ function fixture(modelId = 'stub', extra = {}) {
29
29
  const deps = { command: m => { spawns.push(m.modelId); return [python, [stub, '--serve']]; } };
30
30
  return { dir, manifest, manifestPath, spawns, deps };
31
31
  }
32
+ // State-file unlink precedes process exit. Windows cleanup must wait for the
33
+ // captured resident PID, not merely for the disappearance of its state file.
34
+ function pidAlive(pid) {
35
+ try { process.kill(pid, 0); return true; }
36
+ catch (err) { return err.code === 'EPERM'; }
37
+ }
32
38
  function cleanup(f) {
33
- try { resident.stop(f.manifest, f.manifestPath); } catch (_) { /* best effort */ }
34
- fs.rmSync(f.dir, { recursive: true, force: true });
39
+ const { state } = resident.stateFiles(f.manifest, f.manifestPath);
40
+ const server = resident.readState(state);
41
+ try { resident.stop(f.manifest, f.manifestPath); } catch (_) { /* best effort after an assertion failure */ }
42
+ const deadline = Date.now() + 7500;
43
+ while ((fs.existsSync(state) || (process.platform === 'win32' && server && pidAlive(server.pid)))
44
+ && Date.now() < deadline) sleep(25);
45
+ assert.equal(fs.existsSync(state), false, 'resident state must disappear before fixture removal');
46
+ if (process.platform === 'win32' && server) {
47
+ assert.equal(pidAlive(server.pid), false, `detached resident PID ${server.pid} survived shutdown`);
48
+ }
49
+ fs.rmSync(f.dir, { recursive: true, force: true, maxRetries: 20, retryDelay: 50 });
50
+ }
51
+ // Windows Node 23 (nodejs/node#56645) and Node 24 before the fix in
52
+ // 24.20.0 (nodejs/node#61999) can abort during libuv/process shutdown.
53
+ // Preserve RS13's actual evaluator subprocess on unaffected runtimes.
54
+ function windowsNodeShutdownIssue(platform, version) {
55
+ const parts = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
56
+ if (platform !== 'win32' || !parts) return false;
57
+ const major = Number(parts[1]);
58
+ if (major === 23) {
59
+ return 'Windows Node 23.x has a known process-shutdown assertion (nodejs/node#56645); use Node 22 or Node 24.20+';
60
+ }
61
+ if (major === 24 && Number(parts[2]) < 20) {
62
+ return 'Windows Node 24 < 24.20.0 lacks upstream shutdown fix nodejs/node#61999; use Node 24.20+ or Node 22';
63
+ }
64
+ return false;
35
65
  }
66
+ const nodeShutdownIssue = windowsNodeShutdownIssue(process.platform, process.versions.node);
67
+
68
+ test('S1-RS00 Windows Node 23 and 24 shutdown compatibility boundary', () => {
69
+ for (const version of ['23.0.0', '23.4.0', '23.6.0', '23.11.1']) {
70
+ assert.match(windowsNodeShutdownIssue('win32', version), /Node 23/);
71
+ assert.equal(windowsNodeShutdownIssue('linux', version), false);
72
+ assert.equal(windowsNodeShutdownIssue('darwin', version), false);
73
+ }
74
+ for (const version of ['24.0.0', '24.15.0', '24.18.0', '24.19.9']) {
75
+ assert.match(windowsNodeShutdownIssue('win32', version), /Node 24/);
76
+ assert.equal(windowsNodeShutdownIssue('linux', version), false);
77
+ }
78
+ for (const version of ['22.16.0', '24.20.0', '24.21.0', '25.0.0', '26.0.0', 'bogus']) {
79
+ assert.equal(windowsNodeShutdownIssue('win32', version), false, version);
80
+ }
81
+ });
82
+
36
83
  // A client view whose state file names the live server with a wrong token. The server polls only its own
37
84
  // state file and exits once that file stops naming it, so rewriting it would race the wrong-token request.
38
85
  function wrongTokenView(f) {
@@ -295,7 +342,7 @@ test('S1-RS12 the evaluator times the async path: no worker thread per warm scor
295
342
  } finally { cleanup(f); }
296
343
  });
297
344
 
298
- test('S1-RS13 manifest acceptance thresholds are validated, carried by scored results and applied by the evaluator', async () => {
345
+ test('S1-RS13 manifest acceptance thresholds are validated, carried by scored results and applied by the evaluator', { skip: nodeShutdownIssue }, async () => {
299
346
  const acceptance = { minConfidence: 0.6, minMargin: 0.3 };
300
347
  const base = fixture();
301
348
  try {
@@ -344,3 +391,23 @@ test('S1-RS14 resident transport names its adapter and stays inside the scripts
344
391
  assert.throws(() => resident.defaultCommand({ ...f.manifest, adapter: '../evil.py' }));
345
392
  } finally { cleanup(f); }
346
393
  });
394
+
395
+
396
+ // The test server keeps its PID alive for 500 ms after state-file unlink.
397
+ // A state-only teardown passes too early, whereas PID-aware cleanup cannot.
398
+ test('S1-RS15 repeated teardown waits for resident PID and removes every fixture', () => {
399
+ for (let round = 0; round < 6; round++) {
400
+ const f = fixture('stub-exit-linger');
401
+ let pid;
402
+ try {
403
+ assert.equal(resident.ensureReady(f.manifest, f.manifestPath, 20000, f.deps), true);
404
+ const state = resident.readState(resident.stateFiles(f.manifest, f.manifestPath).state);
405
+ assert.ok(state && state.pid > 0);
406
+ pid = state.pid;
407
+ } finally { cleanup(f); }
408
+ assert.equal(fs.existsSync(f.dir), false, `fixture remained after teardown ${round}`);
409
+ if (process.platform === 'win32') {
410
+ assert.equal(pidAlive(pid), false, `resident PID ${pid} leaked in teardown ${round}`);
411
+ }
412
+ }
413
+ });
@@ -33,6 +33,86 @@ const orchestratorContract = read('fable-mode/agents/fable-orchestrator.md');
33
33
  assert.ok(/maxReplans[\s\S]{0,60}is advisory/i.test(orchestratorContract), 'orchestrator keeps advisory replan guidance');
34
34
  assert.ok(/do not block execution/i.test(orchestratorContract), 'orchestrator does not block on replan count');
35
35
 
36
+ // #275: build divergence is a diagnostic signal, not a second hard-stop.
37
+ // Mandatory blocking/reflection remains limited to Rule-of-3 or permission boundaries.
38
+ const fableDiscipline = read('fable-discipline/SKILL.md');
39
+ assert.strictEqual(read('plugins/harness-everything/skills/fable-discipline/SKILL.md'), fableDiscipline, 'fable-discipline packaged contract matches canonical');
40
+ assert.ok(/divergence is a warning signal/i.test(fableDiscipline), 'fable-discipline must classify divergence as warning guidance');
41
+ assert.ok(/does not hard-stop execution/i.test(fableDiscipline), 'divergence must not create an independent hard stop');
42
+ assert.ok(/Rule-of-3 owns mandatory reflection/i.test(fableDiscipline), 'Rule-of-3 remains the mandatory reflection owner');
43
+ assert.ok(!/HALTS execution immediately/i.test(fableDiscipline), 'fable-discipline must not retain the divergent-build hard halt');
44
+ assert.ok(!/If build errors diverge, HALT/i.test(fableDiscipline), 'fable-discipline must not issue an immediate divergence halt');
45
+
46
+ // #274: grill skills may recommend the explicit publication/ticket commands,
47
+ // but must not auto-invoke state-mutating explicit-only skills.
48
+ const toSpec = read('to-spec/SKILL.md');
49
+ const toTickets = read('to-tickets/SKILL.md');
50
+ assert.ok(/Explicit `?\/to-spec`?; never auto-run/i.test(toSpec), 'to-spec remains explicit-only');
51
+ assert.ok(/Explicit `?\/to-tickets`? only/i.test(toTickets), 'to-tickets remains explicit-only');
52
+ for (const [canonical, packaged] of [
53
+ ['grill-me/SKILL.md', 'plugins/harness-everything/skills/grill-me/SKILL.md'],
54
+ ['grill-with-docs/SKILL.md', 'plugins/harness-everything/skills/grill-with-docs/SKILL.md'],
55
+ ]) {
56
+ const body = read(canonical);
57
+ assert.strictEqual(read(packaged), body, canonical + ' packaged contract matches');
58
+ assert.ok(/explicit `?\/to-spec`?/i.test(body), canonical + ' must surface the explicit to-spec handoff');
59
+ assert.ok(/Never auto-run `to-spec` or `to-tickets`/i.test(body), canonical + ' must preserve explicit-only publication/ticket gates');
60
+ }
61
+ assert.ok(!/on consensus, invoke `to-spec`/i.test(read('grill-me/SKILL.md')), 'grill-me must not auto-invoke to-spec');
62
+ for (const [canonical, packaged] of [
63
+ ['grill-me/references/grilling-playbook.md', 'plugins/harness-everything/skills/grill-me/references/grilling-playbook.md'],
64
+ ['grill-with-docs/references/session-playbook.md', 'plugins/harness-everything/skills/grill-with-docs/references/session-playbook.md'],
65
+ ]) {
66
+ const body = read(canonical);
67
+ assert.strictEqual(read(packaged), body, canonical + ' packaged reference matches');
68
+ assert.ok(/recommend explicit `?\/to-spec`?/i.test(body), canonical + ' keeps explicit specification handoff');
69
+ assert.ok(!/MUST[^\n]*hand off to `to-spec/i.test(body), canonical + ' must not mandate automatic to-spec handoff');
70
+ }
71
+
72
+ for (const rel of [
73
+ 'docs/workflows/grill-me.md',
74
+ 'docs/workflows/grill-with-docs.md',
75
+ ]) {
76
+ const body = read(rel);
77
+ assert.ok(/suggest|recommend/i.test(body) && /explicit `?\/to-spec`?/i.test(body), rel + ' must recommend an explicit to-spec command');
78
+ assert.ok(/explicit `?\/to-spec`? invocation/i.test(body), rel + ' must preserve the explicit invocation gate');
79
+ assert.ok(/not auto-run|does not invoke|not auto-invoked|does not publish automatically/i.test(body), rel + ' must reject automatic explicit-only handoff');
80
+ assert.ok(!/On consensus, `?to-spec`? invoked/i.test(body), rel + ' must not auto-invoke to-spec on consensus');
81
+ assert.ok(!/aligned design to `?to-spec`?; execution to `?to-tickets/i.test(body), rel + ' must not encode automatic downstream handoff');
82
+ }
83
+
84
+
85
+
86
+ // #277: completing a task phase does not authorize a Git commit.
87
+ // Commit boundaries are guidance unless the user or active host/workflow grants permission.
88
+ const gitCommit = read('git-commit/SKILL.md');
89
+ const gitCommitFlow = read('git-commit/references/commit-flow.md');
90
+ const fableDisciplineRules = read('fable-discipline/references/discipline-rules.md');
91
+ assert.strictEqual(read('plugins/harness-everything/skills/git-commit/SKILL.md'), gitCommit, 'git-commit packaged contract matches canonical');
92
+ assert.strictEqual(read('plugins/harness-everything/skills/git-commit/references/commit-flow.md'), gitCommitFlow, 'git-commit packaged flow matches canonical');
93
+ assert.strictEqual(read('plugins/harness-everything/skills/fable-discipline/references/discipline-rules.md'), fableDisciplineRules, 'fable-discipline packaged rules match canonical');
94
+ assert.ok(/task phase alone is not authorization/i.test(gitCommit), 'phase completion must not authorize a commit');
95
+ assert.ok(/commit authorization first/i.test(gitCommit), 'git-commit must gate mutation on authorization');
96
+ assert.ok(/User \/ Host-Authorized Commit/i.test(gitCommitFlow), 'commit flow must begin from explicit authorization');
97
+ assert.ok(/Do Not Commit; Surface Status/i.test(gitCommitFlow), 'unauthorized flow must stop before mutation');
98
+ assert.ok(/commits are authorized/i.test(fableDiscipline), 'fable discipline only applies atomic commits after authorization');
99
+ assert.ok(/otherwise leave changes uncommitted/i.test(fableDiscipline), 'fable discipline must preserve uncommitted state without authorization');
100
+ assert.ok(/Create the commit only when the user or active host\/workflow has authorized commits/i.test(fableDisciplineRules), 'fable reference must not autonomously commit');
101
+ assert.ok(!/explicit commit requests or concluded task phases/i.test(gitCommit), 'concluded phases must not remain a commit trigger');
102
+ assert.ok(!/Trigger: Commit Request \/ Task Complete/i.test(gitCommitFlow), 'task completion must not remain a flow trigger');
103
+
104
+ // #275 reference surface must agree with the non-blocking divergence contract.
105
+ assert.ok(/divergence alone is not a hard stop/i.test(fableDisciplineRules), 'fable reference keeps divergence advisory');
106
+ assert.ok(/Mandatory reflection remains owned by Rule-of-3/i.test(fableDisciplineRules), 'fable reference keeps Rule-of-3 as reflection owner');
107
+ assert.ok(!/HALT EXECUTION IMMEDIATELY/i.test(fableDisciplineRules), 'fable reference must not retain the old divergence hard halt');
108
+ const fableWorkflow = read('docs/workflows/fable-discipline.md');
109
+ const gitWorkflow = read('docs/workflows/git-commit.md');
110
+ assert.ok(/Divergence surfaced without creating an independent hard stop/i.test(fableWorkflow), 'fable workflow keeps divergence advisory');
111
+ assert.ok(!/HALT and call zoom-out|halt immediately/i.test(fableWorkflow), 'fable workflow must not retain divergence hard halt');
112
+ assert.ok(/completed task phase does \*\*not\*\* authorize a commit/i.test(gitWorkflow), 'git workflow rejects phase-completion authorization');
113
+ assert.ok(/Commit authorization existed before mutation/i.test(gitWorkflow), 'git workflow gates mutation on authorization');
114
+
115
+
36
116
  // #268: model aliases evolve, so worker prompts must encode behavior rather
37
117
  // than generation-specific personality/failure claims.
38
118
  const workerPairs = [
@@ -1,71 +1,30 @@
1
1
  # Workflow: Fable Discipline
2
2
 
3
- > Act as a background guard while staged multi-agent work runs, keeping output compact, stage scope tight, handoffs explicit, and diverging builds halted.
3
+ > Background guard for compact context, bounded stage scope, explicit handoffs, authorized commit boundaries, and build-divergence signals.
4
4
 
5
5
  Source of truth: `fable-discipline/SKILL.md`.
6
6
 
7
- ## 1. Skill Behavior Workflow
7
+ ## 1. Workflow
8
8
 
9
9
  ```mermaid
10
10
  graph TD
11
- FableActive([fable-mode active with staged work]) --> CompactMilestone[Compact state after milestone]
12
- CompactMilestone --> ScopeCheck[Enforce stage scope and output limits]
13
- ScopeCheck --> HandoffStep[Require state manifest at handoff]
14
- HandoffStep --> BuildHealth{Build errors diverging?}
15
- BuildHealth -->|yes| HaltZoom[HALT and call zoom-out]
16
- BuildHealth -->|no| KeepGuard[Continue background guard]
17
- KeepGuard --> CompactMilestone
18
- HaltZoom --> MapErrors[Map error dependency graph for human]
11
+ Active[fable-mode active] --> Compact[Compact milestone state]
12
+ Compact --> Handoff[Verify handoff manifest]
13
+ Handoff --> Diverge{Build errors diverging?}
14
+ Diverge -->|no| Continue[Continue guarded work]
15
+ Diverge -->|yes| Warn[Surface regression + recommend zoom-out]
16
+ Warn --> Rule3{Rule-of-3 reached?}
17
+ Rule3 -->|yes| Reflect[Mandatory reflection]
18
+ Rule3 -->|no| Continue
19
19
  ```
20
20
 
21
- ```mermaid
22
- graph TD
23
- IncomingAgent[Incoming stage agent] --> VerifyManifest[Verify outgoing state manifest first]
24
- VerifyManifest --> ManifestOk{Manifest complete?}
25
- ManifestOk -->|yes| DoStage[Run stage within allowed files]
26
- ManifestOk -->|no| AskManifest[Require missing APIs and IO details]
27
- AskManifest --> VerifyManifest
28
- DoStage --> OneCommit[One commit per independent logic block]
29
- OneCommit --> LeaveManifest[Leave manifest for next agent]
30
- ```
31
-
32
- ## 2. Triggering and Routing Path
33
-
34
- ```mermaid
35
- graph LR
36
- FableMode[fable-mode active] --> FableDisc[fable-discipline shadow guard]
37
- FableDisc --> WorkspaceGuard[Constrain multi-agent-workspace mutations]
38
- WorkspaceGuard --> FableMode
39
- FableDisc --> DivergedBuild{Diverging build errors?}
40
- DivergedBuild -->|yes| ZoomOut[zoom-out]
41
- DivergedBuild -->|no| FableMode
42
- ```
43
-
44
- ## 3. Real-World Use Case
45
-
46
- Long architectural migration runs under `fable-mode` with sub-agents handling separate stages.
47
-
48
- 1. After each milestone, compact decisions and drop unneeded history; avoid broad regex and avoid reading irrelevant files over 1000 lines.
49
- 2. Confirm working directory before touching core architecture; keep one commit per independent logic block.
50
- 3. Outgoing agent leaves a manifest with completed APIs and expected inputs/outputs; incoming agent verifies it first.
51
- 4. If fixes create more breakage, halt immediately, call `zoom-out`, and map the error dependency graph instead of continued patching.
52
-
53
- ```mermaid
54
- graph TD
55
- LongTask[Migration stage completes] --> CompactState[Compact milestone state]
56
- CompactState --> CheckBloat[Check for bloat or oversized reads]
57
- CheckBloat --> Handoff[Write and verify handoff manifest]
58
- Handoff --> BuildCheck{Build diverging?}
59
- BuildCheck -->|yes| HaltNow[HALT and zoom-out]
60
- BuildCheck -->|no| NextStage[Start next stage guarded]
61
- ```
21
+ Commit boundaries are guidance only. Create commits only when the user or active host/workflow has authorized them; otherwise leave changes uncommitted.
62
22
 
63
- ## 4. Verification Check
23
+ ## 2. Verification
64
24
 
65
- - [ ] Ran only as a background shadow for the whole `fable-mode` duration; not used standalone, not used for small tasks or routine single-file edits
66
- - [ ] After each milestone, state was compacted and unneeded history dropped; no broad regex without precise conditions and no irrelevant 1000+ line reads
67
- - [ ] Working directory was confirmed before core changes, with one commit per independent logic block
68
- - [ ] Every sub-agent handoff via `multi-agent-workspace` left a state manifest with completed APIs and expected inputs/outputs, verified by the incoming agent first
69
- - [ ] On diverging build errors, execution halted immediately and called `zoom-out` with an error dependency map instead of continued patching
70
- - [ ] Made no direct state mutations of its own; only constrained `fable-mode` and `multi-agent-workspace` mutations
71
- - [ ] Detail followed `fable-discipline/references/discipline-rules.md` where needed
25
+ - [ ] Milestone state compacted and irrelevant broad reads avoided.
26
+ - [ ] Handoff manifest written and verified.
27
+ - [ ] Divergence surfaced without creating an independent hard stop.
28
+ - [ ] Rule-of-3 remains the mandatory reflection owner.
29
+ - [ ] Commits occur only with user/host authorization.
30
+ - [ ] Detail follows `fable-discipline/references/discipline-rules.md`.
@@ -1,79 +1,33 @@
1
1
  # Workflow: Git Commit
2
2
 
3
- > Create clean Angular-style commit messages for an explicit commit request or a finished task phase, after checking repo state, submodules, and staged changes.
3
+ > Create and verify an Angular-style commit only after the user or active host/workflow authorizes the mutation.
4
4
 
5
5
  Source of truth: `git-commit/SKILL.md`.
6
6
 
7
- ## 1. Skill Behavior Workflow
7
+ ## 1. Workflow
8
8
 
9
9
  ```mermaid
10
10
  graph TD
11
- CommitTrig([Commit requested or phase concluded]) --> StatusCheck[Run git status]
12
- StatusCheck --> RepoOk{Git repo present?}
13
- RepoOk -->|no| InitOffer[Offer git init or skip]
14
- RepoOk -->|yes| SubCheck[Check submodule changes per SUBMODULES guide]
15
- SubCheck --> SubDirty{Submodules changed?}
16
- SubDirty -->|yes| SubFirst[Commit submodules first]
17
- SubDirty -->|no| DiffCheck[Run git diff-cached]
18
- SubFirst --> DiffCheck
19
- DiffCheck --> StagedOk{Anything staged?}
20
- StagedOk -->|no| PromptStage[Prompt user and stage targeted files]
21
- StagedOk -->|yes| FormatMsg[Format type-scope-subject message]
22
- PromptStage --> FormatMsg
23
- FormatMsg --> VerifyLog[Commit then verify with git log -1]
24
- VerifyLog --> DoneClean([Tree updated and clean])
11
+ Trigger[Commit requested / host-authorized] --> Auth{Commit authorized?}
12
+ Auth -->|no| Stop[Do not commit; surface status]
13
+ Auth -->|yes| Status[git status]
14
+ Status --> Diff[git diff --cached]
15
+ Diff --> Staged{Anything staged?}
16
+ Staged -->|no| Ask[Prompt user; stage only authorized targets]
17
+ Staged -->|yes| Format[Format Angular message]
18
+ Ask --> Format
19
+ Format --> Commit[git commit]
20
+ Commit --> Verify[git log -1]
25
21
  ```
26
22
 
27
- ```mermaid
28
- graph TD
29
- FormatSimple[Formatted Angular message] --> EscCheck{Simple single line?}
30
- EscCheck -->|yes| DirectM[git commit -m]
31
- EscCheck -->|no multiline or Windows| TempF[Write commit-msg file then git commit -F and cleanup]
32
- DirectM --> LogOne[git log -1 verifies commit]
33
- TempF --> LogOne
34
- LogOne --> CleanTree([Working tree clean])
35
- ```
36
-
37
- ## 2. Triggering and Routing Path
38
-
39
- ```mermaid
40
- graph LR
41
- UserReq[User requests commit] --> GitSkill[git-commit SKILL]
42
- PhaseDone[Task phase concludes with staged diff] --> GitSkill
43
- GitSkill --> StatusGate[git status gate]
44
- StatusGate --> SubGuide[guides SUBMODULES.md if needed]
45
- SubGuide --> StyleGuide[guides ANGULAR_STYLE.md formatting]
46
- StyleGuide --> CommitVerify[Commit and git log -1 check]
47
- ```
48
-
49
- ## 3. Real-World Use Case
50
-
51
- Developer finishes an auth fix and asks for a commit.
52
-
53
- 1. Run `git status`; if not a repo, offer `git init` or skip.
54
- 2. If submodules changed, commit those first per `git-commit/guides/SUBMODULES.md`.
55
- 3. Run `git diff --cached`; if nothing staged, prompt before staging targeted files.
56
- 4. Format `<type>(<scope>): <subject>` per `git-commit/guides/ANGULAR_STYLE.md`.
57
- 5. Use `git commit -m` for a simple line, or `.git-commit-msg.txt` + `git commit -F` with cleanup for multiline/Windows, then verify with `git log -1`.
58
-
59
- ```mermaid
60
- graph TD
61
- DevDone[Auth fix finished and staged] --> CheckStatus[Run git status and cached diff]
62
- CheckStatus --> FmtMsg[Format feat-auth style message]
63
- FmtMsg --> PickMethod{Multiline or Windows?}
64
- PickMethod -->|no| CommitM[git commit -m]
65
- PickMethod -->|yes| CommitF[git commit -F with temp file]
66
- CommitM --> VerifyOne[git log -1]
67
- CommitF --> VerifyOne
68
- VerifyOne --> CleanDone([Committed and verified])
69
- ```
23
+ A completed task phase does **not** authorize a commit.
70
24
 
71
- ## 4. Verification Check
25
+ ## 2. Verification
72
26
 
73
- - [ ] `git status` ran first; non-repo offered `git init` or skip, and empty staging prompted the user instead of committing nothing
74
- - [ ] Submodule changes were handled first per `git-commit/guides/SUBMODULES.md`
75
- - [ ] Staged diff was reviewed with `git diff --cached`, with targeted staging only after confirmation
76
- - [ ] Message followed `<type>(<scope>): <subject>` per `git-commit/guides/ANGULAR_STYLE.md`
77
- - [ ] Multiline/Windows path used `.git-commit-msg.txt` + `git commit -F` with cleanup; simple path used `git commit -m`; result verified with `git log -1`
78
- - [ ] No branch, rebase, merge, or push was performed, and no staging happened without confirmation
79
- - [ ] Detail followed `git-commit/references/commit-flow.md` where needed
27
+ - [ ] Commit authorization existed before mutation.
28
+ - [ ] `git status` and `git diff --cached` were inspected.
29
+ - [ ] Only authorized targeted files were staged.
30
+ - [ ] Message follows `<type>(<scope>): <subject>`.
31
+ - [ ] Result verified with `git log -1`.
32
+ - [ ] No branch/rebase/merge/push side effects were introduced.
33
+ - [ ] Detail follows `git-commit/references/commit-flow.md`.
@@ -1,6 +1,6 @@
1
1
  # Workflow: Grill Me
2
2
 
3
- > A demanding challenger that pressure-tests vague plans and architectures one question at a time, exposes loopholes and undefined boundaries, counters sycophantic agreement, keeps the CONTEXT.md glossary current, and passes settled decisions to to-spec for formal specs and ADRs.
3
+ > A demanding challenger that pressure-tests vague plans and architectures one question at a time, keeps the CONTEXT.md glossary current, and recommends an explicit `/to-spec` handoff after consensus.
4
4
 
5
5
  Source of truth: `grill-me/SKILL.md`.
6
6
 
@@ -15,8 +15,11 @@ graph TD
15
15
  ResolveBranch --> UpdateGlossary["Update CONTEXT.md glossary inline"]
16
16
  UpdateGlossary --> ConsensusCheck{"Consensus on all branches?"}
17
17
  ConsensusCheck -->|No| AskOne
18
- ConsensusCheck -->|Yes| HandoffSpec["Hand off to to-spec to preview outline and publish"]
19
- HandoffSpec --> RouteExec["Route execution to to-tickets, fable-mode, or tdd"]
18
+ ConsensusCheck -->|Yes| SuggestSpec["Recommend explicit /to-spec"]
19
+ SuggestSpec --> InvokeSpec{"User explicitly invokes /to-spec?"}
20
+ InvokeSpec -->|No| Await["Keep aligned decisions; await explicit command"]
21
+ InvokeSpec -->|Yes| ToSpec["to-spec previews outline and publishes under its approval gate"]
22
+ ToSpec --> SuggestExec["Suggest /to-tickets, fable-mode, or tdd as appropriate"]
20
23
  ```
21
24
 
22
25
  ## 2. Triggering and Routing Path
@@ -26,10 +29,11 @@ graph LR
26
29
  VaguePlan["Input: vague plan proposal"] --> GrillMe["grill-me / SKILL.md"]
27
30
  EvaluateArch["Input: evaluate architecture request"] --> GrillMe
28
31
  ExplicitAsk["Input: explicit grill me request"] --> GrillMe
29
- GrillMe --> ToSpec["to-spec: preview outline and publish PRD, CLI/API reference, Schema doc, or ADR"]
30
- ToSpec --> ToTickets["to-tickets for execution"]
31
- ToSpec --> FableMode["fable-mode for execution"]
32
- ToSpec --> TDD["tdd for execution"]
32
+ GrillMe --> SuggestSpec["Suggest explicit /to-spec"]
33
+ SuggestSpec --> InvokeGate{"Explicit /to-spec invoked?"}
34
+ InvokeGate -->|No| Wait["Stop at recommendation"]
35
+ InvokeGate -->|Yes| ToSpec["to-spec preview / publication flow"]
36
+ ToSpec --> SuggestRoutes["Suggest /to-tickets, fable-mode, or tdd"]
33
37
  ```
34
38
 
35
39
  ## 3. Real-World Use Case
@@ -42,10 +46,13 @@ graph TD
42
46
  A1 --> Glossary1["Update CONTEXT.md glossary for sync and lock terms"]
43
47
  Glossary1 --> Q2["Q2: What are boundary conditions for partial state?"]
44
48
  Q2 --> Consensus["Consensus reached on failure and boundary handling"]
45
- Consensus --> SpecHandoff["to-spec publishes ADR and spec"]
49
+ Consensus --> Recommend["Recommend explicit /to-spec"]
50
+ Recommend --> UserInvoke{"User invokes /to-spec?"}
51
+ UserInvoke -->|No| End["Preserve consensus; no publication"]
52
+ UserInvoke -->|Yes| Spec["to-spec previews and publishes ADR/spec"]
46
53
  ```
47
54
 
48
- Concrete example: a developer proposes a direct table-sync cron job. `grill-me` scans `CONTEXT.md` and related code, asks one question about mid-sync failure, resolves it, updates the glossary, asks the next question about monitoring and boundary conditions, then hands the hardened decisions to `to-spec` for a PRD or ADR. Execution follows via `to-tickets`, `fable-mode`, or `tdd`.
55
+ Concrete example: a developer proposes a direct table-sync cron job. `grill-me` resolves the design one question at a time and updates glossary terms. Once consensus is reached, it recommends explicit `/to-spec`; it does not publish automatically. Only after that command is invoked does `to-spec` enter its preview/publication flow. Any later execution route is suggested rather than auto-invoked.
49
56
 
50
57
  Deep detail: `grill-me/references/grilling-playbook.md`.
51
58
 
@@ -54,7 +61,8 @@ Deep detail: `grill-me/references/grilling-playbook.md`.
54
61
  - [ ] Exactly ONE question asked at a time; questionnaires prohibited
55
62
  - [ ] Each question carries the agent's insight and its branch is resolved before advancing
56
63
  - [ ] Questions use the project's domain model and terminology from `CONTEXT.md`, `README.md`, and `docs/adr/`
57
- - [ ] `CONTEXT.md` glossary updated inline as terms resolve; document creation left to `to-spec`
58
- - [ ] On consensus, `to-spec` invoked to preview outline and publish PRD, CLI/API reference, Schema doc, or ADR
59
- - [ ] No code implementation or ticket breakdown inside this skill; execution routed to `to-tickets`, `fable-mode`, or `tdd`
64
+ - [ ] `CONTEXT.md` glossary updated inline as terms resolve
65
+ - [ ] On consensus, explicit `/to-spec` is recommended, not auto-run
66
+ - [ ] Publication occurs only after explicit `/to-spec` invocation and its approval flow
67
+ - [ ] Execution routes such as `/to-tickets`, `fable-mode`, or `tdd` are suggested; explicit-only skills are not auto-invoked
60
68
  - [ ] Not used for casual Q and A, direct spec writing, or ticket breakdown of an approved spec