harness-everything 0.46.1 → 0.46.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.46.1",
13
+ "version": "0.46.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.46.1",
4
+ "version": "0.46.3",
5
5
  "author": {
6
6
  "name": "Miya Daniel"
7
7
  },
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## [0.46.3](https://github.com/dyphn1/Harness-everything/compare/v0.46.2...v0.46.3) (2026-10-28)
6
+
7
+ ### Bug Fixes
8
+
9
+ * **doc-reconciliation:** clear outline reviewers that stopped before dispatch ([d62bdb8](https://github.com/dyphn1/Harness-everything/commit/d62bdb870523e39a19f63a117557794c21387e3c))
10
+ * **doc-reconciliation:** require a unique reviewer start before clearing it ([99527f6](https://github.com/dyphn1/Harness-everything/commit/99527f6df6729ae8a5db331fc39bed5359797f17))
11
+
12
+ ## [0.46.2](https://github.com/dyphn1/Harness-everything/compare/v0.46.1...v0.46.2) (2026-10-28)
13
+
14
+ ### Bug Fixes
15
+
16
+ * **doc-reconciliation:** pin the outline task binding at plan/start ([5823c48](https://github.com/dyphn1/Harness-everything/commit/5823c4881ccd6647c1af58e8d295f878e4f1020e))
17
+
5
18
  ## [0.46.1](https://github.com/dyphn1/Harness-everything/compare/v0.46.0...v0.46.1) (2026-10-28)
6
19
 
7
20
  ### Bug Fixes
@@ -770,6 +770,46 @@ test('pilot exposes a real-capture-only outline reference resolver', () => {
770
770
  assert.deepStrictEqual(resolve([], 'task-prb'), [], 'hand-authored JSON with no host capture creates no event ref');
771
771
  });
772
772
 
773
+ test('shipped route + plan/start CLI pins the outline task binding in canonical and packaged layouts', () => {
774
+ // Live run 2026-10-28: the pilot's module lookup missed workflow-obligations, so no task pin was ever written.
775
+ for (const [layout, base] of [['canonical', ROOT], ['packaged', path.join(ROOT, 'plugins/harness-everything')]]) {
776
+ const root = canonical(fs.mkdtempSync(path.join(os.tmpdir(), 'prb-task-pin-')));
777
+ const stateHome = fs.mkdtempSync(path.join(os.tmpdir(), 'prb-task-pin-state-'));
778
+ try {
779
+ fixtureGit(root, ['init', '-q']);
780
+ fs.writeFileSync(path.join(root, 'README.md'), 'B\n');
781
+ fixtureGit(root, ['add', '-A']);
782
+ fixtureGit(root, ['commit', '-q', '-m', 'B baseline']);
783
+ const sessionId = `task-pin-${layout}`;
784
+ const env = { ...process.env, HARNESS_STATE_HOME: stateHome, HARNESS_WORKSPACE_ROOT: root, HARNESS_DOC_RECONCILIATION_PILOT: '1' };
785
+ const kernel = layout === 'canonical' ? path.join(base, 'harness-everything/scripts/kernel-router.js')
786
+ : path.join(base, 'skills/harness-everything/scripts/kernel-router.js');
787
+ const run = (script, args, input) => {
788
+ const child = spawnSync(process.execPath, [script, ...args], { cwd: root, env, encoding: 'utf8', input });
789
+ assert.strictEqual(child.status, 0, `${layout} ${path.basename(script)} ${args[0] || ''}: ${child.stderr || child.stdout}`);
790
+ };
791
+ run(kernel, [], JSON.stringify({ session_id: sessionId, cwd: root, prompt: 'Draft an ADR from the reviewed outline and verify it' }));
792
+ const controller = path.join(base, 'hooks/scripts/workflow-disposition.js');
793
+ run(controller, ['plan', '--session-id', sessionId, '--strategy', 'iterative-single', '--evidence', 'task pin fixture',
794
+ '--requirements-json', JSON.stringify([
795
+ { id: 'adr', stepType: 'doc-change', summary: 'draft ADR', acceptance: 'outline review precedes drafting' },
796
+ { id: 'verify', stepType: 'verification', summary: 'verify', acceptance: 'checker runs' }])]);
797
+ run(controller, ['start', '--session-id', sessionId]);
798
+ const prior = process.env.HARNESS_STATE_HOME;
799
+ process.env.HARNESS_STATE_HOME = stateHome;
800
+ let sessionDir;
801
+ try { sessionDir = require(path.join(ROOT, 'hooks/scripts/lib/harness-state.js')).getSessionDir(root, sessionId); }
802
+ finally { if (prior === undefined) delete process.env.HARNESS_STATE_HOME; else process.env.HARNESS_STATE_HOME = prior; }
803
+ const workflow = JSON.parse(fs.readFileSync(path.join(sessionDir, 'workflow-run.json'), 'utf8'));
804
+ assert.ok(workflow.docReconciliationBaseline, `${layout}: baseline pin is captured`);
805
+ assert.strictEqual(workflow.docReconciliationTask?.taskId, 'task-adr+verify', `${layout}: task pin is captured at plan/start`);
806
+ } finally {
807
+ fs.rmSync(root, { recursive: true, force: true });
808
+ fs.rmSync(stateHome, { recursive: true, force: true });
809
+ }
810
+ }
811
+ });
812
+
773
813
  test('pre-dispatch seam requires review, exact worker root, clean O tree, lease, pin, and immutable handoff', () => {
774
814
  assert.strictEqual(typeof internals.captureOutlineDispatch, 'function', 'missing synchronous pre-dispatch seam');
775
815
  const differentWorkerRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'prb-outline-different-worker-'));
@@ -871,6 +911,46 @@ test('outline evidence binds exact task, B, O blobs, independent review, worker
871
911
  'a delayed write/edit callback from the coordinator remains visible and blocks ambiguous writer history');
872
912
  } finally { delayedWriter.cleanup(); }
873
913
 
914
+ // Live run 2026-10-28: a non-isolated reviewer starts in O; only a stop journaled before the dispatch clears it.
915
+ const reviewerStart = fixture => provider.buildCaptureRecord({ session_id: fixture.sessionId, cwd: fixture.root,
916
+ hook_event_name: 'SubagentStart', agent_id: 'outline-reviewer', agent_type: 'reviewer' }, 'SubagentStart', fixture.root);
917
+ const stoppedReviewer = createOutlineFixture();
918
+ try {
919
+ stoppedReviewer.reviewCaptures.unshift(reviewerStart(stoppedReviewer));
920
+ const completed = stoppedReviewer.finishDraft();
921
+ assert.strictEqual(completed.result.status, 'accepted',
922
+ `a reviewer that started and stopped in O before the dispatch is not a competing writer: ${JSON.stringify(completed.result)}`);
923
+ } finally { stoppedReviewer.cleanup(); }
924
+ for (const [name, arrange] of [
925
+ ['reviewer stop after the dispatch', fixture => {
926
+ const stop = fixture.reviewCaptures.findIndex(item => item.event === 'SubagentStop');
927
+ fixture.extraCaptures.push(...fixture.reviewCaptures.splice(stop, 1));
928
+ fixture.reviewCaptures.unshift(reviewerStart(fixture));
929
+ }],
930
+ ['reviewer start without a stop', fixture => {
931
+ fixture.reviewCaptures.unshift(provider.buildCaptureRecord({ session_id: fixture.sessionId, cwd: fixture.root,
932
+ hook_event_name: 'SubagentStart', agent_id: 'other-agent', agent_type: 'reviewer' }, 'SubagentStart', fixture.root));
933
+ }],
934
+ ['reviewer start after its stop', fixture => { fixture.reviewCaptures.push(reviewerStart(fixture)); }],
935
+ ['duplicate reviewer start with one stop before the dispatch', fixture => {
936
+ fixture.reviewCaptures.unshift(reviewerStart(fixture), reviewerStart(fixture));
937
+ }],
938
+ ['reviewer start with duplicate stops before the dispatch', fixture => {
939
+ const stop = fixture.reviewCaptures.find(item => item.event === 'SubagentStop');
940
+ fixture.reviewCaptures.unshift(reviewerStart(fixture));
941
+ fixture.reviewCaptures.push({ ...stop, ref: `${stop.ref}:dup`, captureId: `${stop.captureId}:dup` });
942
+ }],
943
+ ['reviewer start after the dispatch', fixture => { fixture.extraCaptures.push(reviewerStart(fixture)); }],
944
+ ]) {
945
+ const fixture = createOutlineFixture();
946
+ try {
947
+ arrange(fixture);
948
+ const completed = fixture.finishDraft();
949
+ assert.ok(completed.result.diagnostics?.some(item => item.code === 'outline-competing-writer-start'),
950
+ `${name} stays a competing writer start: ${JSON.stringify(completed.result)}`);
951
+ } finally { fixture.cleanup(); }
952
+ }
953
+
874
954
  const unqualified = createOutlineFixture();
875
955
  try {
876
956
  const completed = unqualified.finishDraft();
@@ -1256,6 +1256,6 @@ flowchart LR
1256
1256
  | Worker and D | The dispatch key is `(session_id, tool_use_id)`. Exactly one matching Task/Agent result must carry `tool_response.status === 'completed'`; its observed `tool_response.agentId` must map to exactly one `SubagentStart` and one `SubagentStop` with the same `session_id` and `agent_id`. Require PreToolUse < SubagentStart < SubagentStop in journal order, but do not order the completed result against Stop. Both worker events need exact canonical `cwd === workerRoot`. `prompt_id` and `parent_tool_use_id` are not correlation keys; `interrupted` is not completion proof. Async launches, failures, cancellation, missing/duplicate events, replayed IDs, worktree isolation and root mismatch stay unresolved. D is checked against the current candidate separately from O. O must be a strict ancestor of D. A squash may retain the cycle only when a coordinator correspondence record proves identical target blobs between retained pre-merge D and the merged tree; changed bytes need fresh final quality review. |
1257
1257
  | Checker outcome | `outline-confirmation` has its own pass/unresolved lane. Generic command success and waivers never satisfy it. No D is incomplete/unresolved. Its result is separate from the aggregate result over every MUST derived from original B→D; an outline pass never waives lint, conflict, quality review, requirement-sync or other MUSTs. |
1258
1258
 
1259
- Capture and validation failures stay fail-open to host tools and withhold evidence credit. Unclassified shell commands and writes outside the correlated worker/root remain unresolved. Retries use a fresh attempt, token, clean worktree and immutable handoff; only one non-superseded leaf is current. An identical same-tool-ID/input callback may reuse its stored seam, but repeated PreToolUse records remain ambiguous for evidence credit; changed input or token reuse is unresolved. OpenCode and Codex remain unsupported for positive outline credit.
1259
+ Capture and validation failures stay fail-open to host tools and withhold evidence credit. Unclassified shell commands and writes outside the correlated worker/root remain unresolved. Any other subagent start in the worker root rejects the outline as a competing writer, unless that start and its unique stop are both journaled before the dispatch PreToolUse (for example, a non-isolated outline reviewer). Retries use a fresh attempt, token, clean worktree and immutable handoff; only one non-superseded leaf is current. An identical same-tool-ID/input callback may reuse its stored seam, but repeated PreToolUse records remain ambiguous for evidence credit; changed input or token reuse is unresolved. OpenCode and Codex remain unsupported for positive outline credit.
1260
1260
 
1261
1261
  The current retained Claude qualification does not establish the versioned `claude-outline-dispatch-mapping/2` contract. The outline provider therefore grants no positive live-host credit until a retained Claude capture validates the prompt, coordinator, result status/agent ID, explicit non-background boundary, isolation absence and exact worker-root mapping. Deterministic fixtures exercise the real hook/provider/adapter/checker/pilot path with a synthetic inventory pin; they are mechanism evidence, not live-host behavior or E1 readiness.
@@ -45,7 +45,8 @@ function captureBaseline(context) {
45
45
  }
46
46
  if (!context.workflow.docReconciliationTask) {
47
47
  const plan = context.workflow.pendingPlan || context.workflow.workflowPlan;
48
- const loaded = plan && runtimeModule('workflow-obligations').loadObligationSet(context, plan);
48
+ // workflow-obligations is a hook-lib sibling in every layout, not a skill runtime script.
49
+ const loaded = plan && require('./workflow-obligations').loadObligationSet(context, plan);
49
50
  const requirementIds = loaded?.set?.requirements?.map(item => item.id);
50
51
  if (Array.isArray(requirementIds) && requirementIds.length && requirementIds.every(id => typeof id === 'string' && id)) {
51
52
  const baseline = context.workflow.docReconciliationBaseline;
@@ -1452,8 +1452,24 @@ function resolveOutlineEvidence({ safeInput, capture, captures, request, originR
1452
1452
  if (review.reviewerPrincipal === worker.agent_id) return fail('outline-reviewer-is-draft-worker');
1453
1453
  const principals = { author: safeInput.sessionId, executors: journalExecutors(captures, safeInput.sessionId) };
1454
1454
  if (!reviewRecordIndependent(review.review, captures, principals)) return fail('outline-review-not-independent');
1455
- const competingStarts = (Array.isArray(captures) ? captures : []).filter(item => recordOf(item)
1456
- && item.event === 'SubagentStart' && item.ref !== worker.ref && sameCanonicalPath(item.cwd, workerRoot));
1455
+ // An agent whose start and unique stop both precede the dispatch cannot write after the seam; earlier writes
1456
+ // are covered by the clean-O seam check and by unattributedWriters below.
1457
+ const journal = Array.isArray(captures) ? captures : [];
1458
+ const dispatchIndex = journal.indexOf(correlation.pre);
1459
+ const stoppedBeforeDispatch = start => {
1460
+ const lifecycle = event => journal.filter(item => recordOf(item) && item.event === event
1461
+ && item.session_id === start.session_id && textOf(start.agent_id) && item.agent_id === start.agent_id);
1462
+ // Exactly one Start and one Stop per (session_id, agent_id); a duplicate either way stays ambiguous.
1463
+ const starts = lifecycle('SubagentStart');
1464
+ const stops = lifecycle('SubagentStop');
1465
+ if (starts.length !== 1 || starts[0] !== start || stops.length !== 1) return false;
1466
+ const startIndex = journal.indexOf(start);
1467
+ const stopIndex = journal.indexOf(stops[0]);
1468
+ return dispatchIndex >= 0 && startIndex >= 0 && startIndex < stopIndex && stopIndex < dispatchIndex;
1469
+ };
1470
+ const competingStarts = journal.filter(item => recordOf(item)
1471
+ && item.event === 'SubagentStart' && item.ref !== worker.ref && sameCanonicalPath(item.cwd, workerRoot)
1472
+ && !stoppedBeforeDispatch(item));
1457
1473
  if (competingStarts.length) return fail('outline-competing-writer-start');
1458
1474
  const unattributedWriters = (Array.isArray(captures) ? captures : []).filter(item => possibleWriterCapture(item)
1459
1475
  && (item.agent_id !== worker.agent_id || !sameCanonicalPath(item.cwd, workerRoot)));
@@ -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.46.1",
4
+ "version": "0.46.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.46.1",
3
+ "version": "0.46.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.46.1",
3
+ "version": "0.46.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",
@@ -45,7 +45,8 @@ function captureBaseline(context) {
45
45
  }
46
46
  if (!context.workflow.docReconciliationTask) {
47
47
  const plan = context.workflow.pendingPlan || context.workflow.workflowPlan;
48
- const loaded = plan && runtimeModule('workflow-obligations').loadObligationSet(context, plan);
48
+ // workflow-obligations is a hook-lib sibling in every layout, not a skill runtime script.
49
+ const loaded = plan && require('./workflow-obligations').loadObligationSet(context, plan);
49
50
  const requirementIds = loaded?.set?.requirements?.map(item => item.id);
50
51
  if (Array.isArray(requirementIds) && requirementIds.length && requirementIds.every(id => typeof id === 'string' && id)) {
51
52
  const baseline = context.workflow.docReconciliationBaseline;
@@ -1452,8 +1452,24 @@ function resolveOutlineEvidence({ safeInput, capture, captures, request, originR
1452
1452
  if (review.reviewerPrincipal === worker.agent_id) return fail('outline-reviewer-is-draft-worker');
1453
1453
  const principals = { author: safeInput.sessionId, executors: journalExecutors(captures, safeInput.sessionId) };
1454
1454
  if (!reviewRecordIndependent(review.review, captures, principals)) return fail('outline-review-not-independent');
1455
- const competingStarts = (Array.isArray(captures) ? captures : []).filter(item => recordOf(item)
1456
- && item.event === 'SubagentStart' && item.ref !== worker.ref && sameCanonicalPath(item.cwd, workerRoot));
1455
+ // An agent whose start and unique stop both precede the dispatch cannot write after the seam; earlier writes
1456
+ // are covered by the clean-O seam check and by unattributedWriters below.
1457
+ const journal = Array.isArray(captures) ? captures : [];
1458
+ const dispatchIndex = journal.indexOf(correlation.pre);
1459
+ const stoppedBeforeDispatch = start => {
1460
+ const lifecycle = event => journal.filter(item => recordOf(item) && item.event === event
1461
+ && item.session_id === start.session_id && textOf(start.agent_id) && item.agent_id === start.agent_id);
1462
+ // Exactly one Start and one Stop per (session_id, agent_id); a duplicate either way stays ambiguous.
1463
+ const starts = lifecycle('SubagentStart');
1464
+ const stops = lifecycle('SubagentStop');
1465
+ if (starts.length !== 1 || starts[0] !== start || stops.length !== 1) return false;
1466
+ const startIndex = journal.indexOf(start);
1467
+ const stopIndex = journal.indexOf(stops[0]);
1468
+ return dispatchIndex >= 0 && startIndex >= 0 && startIndex < stopIndex && stopIndex < dispatchIndex;
1469
+ };
1470
+ const competingStarts = journal.filter(item => recordOf(item)
1471
+ && item.event === 'SubagentStart' && item.ref !== worker.ref && sameCanonicalPath(item.cwd, workerRoot)
1472
+ && !stoppedBeforeDispatch(item));
1457
1473
  if (competingStarts.length) return fail('outline-competing-writer-start');
1458
1474
  const unattributedWriters = (Array.isArray(captures) ? captures : []).filter(item => possibleWriterCapture(item)
1459
1475
  && (item.agent_id !== worker.agent_id || !sameCanonicalPath(item.cwd, workerRoot)));
@@ -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.46.1",
4
+ "version": "0.46.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:e14b39ac-6cf4-5711-b0c8-03de1649a568",
5
+ "serialNumber": "urn:uuid:194f592d-6226-519c-a5b8-9f6750fb3c19",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-10-28T02:23:43.789Z",
8
+ "timestamp": "2026-10-28T05:22:07.321Z",
9
9
  "tools": [
10
10
  {
11
11
  "vendor": "Harness Everything",
12
12
  "name": "generate-sbom.js",
13
- "version": "0.46.1"
13
+ "version": "0.46.3"
14
14
  }
15
15
  ],
16
16
  "component": {
17
17
  "type": "application",
18
- "bom-ref": "pkg:npm/harness-everything@0.46.1",
18
+ "bom-ref": "pkg:npm/harness-everything@0.46.3",
19
19
  "name": "harness-everything",
20
- "version": "0.46.1",
21
- "purl": "pkg:npm/harness-everything@0.46.1"
20
+ "version": "0.46.3",
21
+ "purl": "pkg:npm/harness-everything@0.46.3"
22
22
  }
23
23
  },
24
24
  "components": [
@@ -2033,7 +2033,7 @@
2033
2033
  ]
2034
2034
  },
2035
2035
  {
2036
- "ref": "pkg:npm/harness-everything@0.46.1",
2036
+ "ref": "pkg:npm/harness-everything@0.46.3",
2037
2037
  "dependsOn": [
2038
2038
  "pkg:npm/%40commitlint/cli@19.8.1",
2039
2039
  "pkg:npm/%40commitlint/config-conventional@19.8.1",