harness-everything 0.11.6 → 0.11.7

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 (49) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +13 -0
  4. package/README.md +7 -3
  5. package/ci/mechanism-2a-rule-of-3.test.js +71 -0
  6. package/ci/mechanism-2ah-workflow-lifecycle.test.js +139 -0
  7. package/ci/mechanism-2c-state-persist.test.js +45 -2
  8. package/ci/mechanism-2t-issue-20.test.js +0 -8
  9. package/ci/mechanism-30-opencode-plugin-loadability.test.js +39 -7
  10. package/docs/architecture.md +17 -0
  11. package/docs/audit.md +52 -5
  12. package/docs/release-evidence.md +3 -0
  13. package/docs/workflow-runtime.md +13 -0
  14. package/docs/workflows/environment-detection.md +47 -37
  15. package/docs/workflows/eval-harness.md +45 -38
  16. package/docs/workflows/fable-discipline.md +45 -33
  17. package/docs/workflows/git-commit.md +53 -45
  18. package/docs/workflows/grill-me.md +36 -38
  19. package/docs/workflows/grill-with-docs.md +36 -46
  20. package/docs/workflows/harness-everything.md +59 -57
  21. package/docs/workflows/improve-codebase-architecture.md +36 -44
  22. package/docs/workflows/install-cognitive-os.md +36 -29
  23. package/docs/workflows/repo-docs.md +29 -40
  24. package/docs/workflows/rewrite-commits.md +40 -36
  25. package/docs/workflows/security-review.md +34 -53
  26. package/docs/workflows/skill-creator.md +39 -56
  27. package/docs/workflows/skill-style.md +35 -40
  28. package/docs/workflows/using-git-worktrees.md +40 -44
  29. package/docs/workflows/verification-loop.md +43 -48
  30. package/docs/workflows/verify-before-claim.md +37 -40
  31. package/docs/workflows/zoom-out.md +39 -51
  32. package/harness-everything/SKILL.md +1 -1
  33. package/harness-everything/scripts/kernel-router.js +38 -10
  34. package/hooks/scripts/lib/workflow-isolation.js +30 -1
  35. package/hooks/scripts/rule-of-3-tracker.js +17 -9
  36. package/hooks/scripts/state-persist.js +14 -6
  37. package/hooks/scripts/workflow-gate.js +5 -1
  38. package/opencode-plugin/plugin.json +1 -1
  39. package/package.json +1 -1
  40. package/plugins/harness-everything/.codex-plugin/plugin.json +1 -1
  41. package/plugins/harness-everything/hooks/scripts/lib/workflow-isolation.js +30 -1
  42. package/plugins/harness-everything/hooks/scripts/rule-of-3-tracker.js +17 -9
  43. package/plugins/harness-everything/hooks/scripts/state-persist.js +14 -6
  44. package/plugins/harness-everything/hooks/scripts/workflow-gate.js +5 -1
  45. package/plugins/harness-everything/plugin.json +1 -1
  46. package/plugins/harness-everything/skills/harness-everything/SKILL.md +1 -1
  47. package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router.js +38 -10
  48. package/docs/issue-20-rollup.md +0 -47
  49. package/docs/reviews/pr-142-issue-131.md +0 -89
@@ -4,7 +4,7 @@
4
4
  const path = require('path');
5
5
  const fs = require('fs');
6
6
  const { loadWorkflow, saveWorkflow, isMajorWorkflow, matchingRun, registerMutationProbe, recordBudgetEvent, readHookInput, WORKFLOW_CONTROLLER_COMMANDS } = require('./lib/workflow-runtime');
7
- const { key, classifyShell, workspaceFingerprint, shellProbeKey, cwdOf, commandOf, mutationPaths, linkedWorktree, assertTargets, assertShellScope } = require('./lib/workflow-isolation');
7
+ const { key, classifyShell, workspaceFingerprint, shellProbeKey, cwdOf, commandOf, mutationPaths, directMutationInWorkspace, linkedWorktree, assertTargets, assertShellScope } = require('./lib/workflow-isolation');
8
8
 
9
9
  const DIRECT = new Set(['Edit', 'Write', 'apply_patch']);
10
10
  const SHELL = new Set(['Bash', 'PowerShell', 'exec_command']);
@@ -48,6 +48,10 @@ function decide(payload) {
48
48
  throw new Error('selected Fable workflow has no correlated run. Write workflow-stages.json at the displayed session path, then use workflow-disposition.js start.');
49
49
  }
50
50
  if (DIRECT.has(tool)) {
51
+ // Bookkeeping outside the workspace (scratchpad, memory files, temp
52
+ // notes) is not a workspace mutation: it consumes no Tier-2 iteration
53
+ // and advances no mutation milestone (#165).
54
+ if (!directMutationInWorkspace(payload, cwd, root)) return;
51
55
  if (workflow.strategy === 'iterative-single') {
52
56
  recordBudgetEvent(context, 'iteration', { evidence: `${tool}:direct-mutation` });
53
57
  }
@@ -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.11.6",
4
+ "version": "0.11.7",
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.11.6",
3
+ "version": "0.11.7",
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.11.6",
3
+ "version": "0.11.7",
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",
@@ -248,6 +248,35 @@ function mutationPaths(payload) {
248
248
  }
249
249
  return [input.file_path || input.filePath || input.path].filter(value => typeof value === 'string' && value.trim());
250
250
  }
251
+
252
+ // Bound workspace root plus its linked worktrees. Git failures (e.g. a
253
+ // non-git workspace) degrade to the root alone instead of throwing, so
254
+ // Tier-2 accounting never blocks on this enumeration (#165; cf. #162).
255
+ function worktreeRoots(root) {
256
+ const roots = [root];
257
+ try {
258
+ for (const field of git(root, ['worktree', 'list', '--porcelain', '-z']).split('\0')) {
259
+ if (field.startsWith('worktree ')) {
260
+ const candidate = field.slice('worktree '.length).trim();
261
+ if (candidate) roots.push(candidate);
262
+ }
263
+ }
264
+ } catch (_) { /* root alone */ }
265
+ return roots;
266
+ }
267
+
268
+ // Direct-tool (Edit/Write/apply_patch) targets count against the Tier-2
269
+ // budget only when at least one target lies inside the workspace (#165).
270
+ // Unknown targets (no parseable path) stay conservative and count.
271
+ function directMutationInWorkspace(payload, cwd, root) {
272
+ const targets = mutationPaths(payload);
273
+ if (!targets.length) return true;
274
+ const roots = worktreeRoots(root);
275
+ return targets.some(target => {
276
+ const resolved = path.resolve(cwd, target);
277
+ return roots.some(candidate => within(candidate, resolved));
278
+ });
279
+ }
251
280
  function assertTargets(payload, cwd, isolatedRoot) {
252
281
  const targets = mutationPaths(payload);
253
282
  if (!targets.length) throw new Error('mutation target is unknown; cannot verify worktree isolation');
@@ -274,4 +303,4 @@ function assertShellScope(command, cwd, isolatedRoot) {
274
303
  }
275
304
  }
276
305
 
277
- module.exports = { canonical, key, within, linkedWorktree, classifyShell, workspaceFingerprint, shellProbeKey, inputOf, cwdOf, commandOf, mutationPaths, assertTargets, assertShellScope };
306
+ module.exports = { canonical, key, within, linkedWorktree, classifyShell, workspaceFingerprint, shellProbeKey, inputOf, cwdOf, commandOf, mutationPaths, worktreeRoots, directMutationInWorkspace, assertTargets, assertShellScope };
@@ -17,6 +17,7 @@ process.stdin.on('end', () => {
17
17
  const payload = JSON.parse(inputData);
18
18
  const hookEventName = payload.hook_event_name || payload.hookEventName || '';
19
19
  const isFailureEvent = hookEventName === 'PostToolUseFailure';
20
+ const isSuccessEvent = hookEventName === 'PostToolUse';
20
21
  const toolResponse = payload.tool_response || {};
21
22
  const stdout = toolResponse.stdout ?? payload.stdout ?? '';
22
23
  const stderr = toolResponse.stderr ?? payload.stderr ?? '';
@@ -25,10 +26,10 @@ process.stdin.on('end', () => {
25
26
  const exitCode = typeof rawExitCode === 'number' ? rawExitCode : undefined;
26
27
 
27
28
  const explicitFailure = exitCode !== undefined && exitCode !== 0;
28
- const explicitSuccess = exitCode === 0;
29
29
  const stderrSignal = typeof stderr === 'string' && stderr.trim().length > 0;
30
30
  const looksLikeError = /\b(error|fail|failed|failure|exception|fatal|panic|traceback|denied|refused|cannot|unable)\b/i.test(stderr);
31
- const isFailure = isFailureEvent || explicitFailure || (exitCode === undefined && stderrSignal && looksLikeError);
31
+ const isFailure = isFailureEvent || explicitFailure ||
32
+ (!isSuccessEvent && exitCode === undefined && stderrSignal && looksLikeError);
32
33
  const errorText = isFailureEvent
33
34
  ? (failureText || (stderrSignal ? stderr : stdout) || '')
34
35
  : ((stderrSignal ? stderr : stdout) || failureText || '');
@@ -47,19 +48,22 @@ process.stdin.on('end', () => {
47
48
  const filePath = payload.tool_input?.file_path || payload.tool_input?.filePath || '';
48
49
  const command = payload.tool_input?.command || '';
49
50
 
50
- // Categorize failure type for context-aware thresholds
51
+ // Categorize failure type for context-aware thresholds.
52
+ // NOTE (#167): match anchored diagnostic phrases, not bare substrings.
53
+ // A bare `denied`/`timeout` substring matches file names such as
54
+ // `workflow-mutation-denied.js` and misclassifies the failure.
51
55
  let category = 'unknown';
52
- if (/SyntaxError|Unexpected token|Syntax Error/i.test(errorText)) {
56
+ if (/\bSyntaxError\b|Unexpected token|Syntax Error/i.test(errorText)) {
53
57
  category = 'syntax';
54
- } else if (/ENOENT|not found|No such file|找不到|不存在/i.test(errorText)) {
58
+ } else if (/\bENOENT\b|\bnot found\b|No such file|找不到|不存在/i.test(errorText)) {
55
59
  category = 'environment';
56
- } else if (/timeout|timed out|超時|逾時/i.test(errorText)) {
60
+ } else if (/\bETIMEDOUT\b|TimeoutError|\btimeout\b|\btimed out\b|\btiming out\b|超時|逾時/i.test(errorText)) {
57
61
  category = 'timeout';
58
62
  } else if (/test.*fail|assertion|AssertionError|測試.*失敗|斷言.*錯誤/i.test(errorText)) {
59
63
  category = 'test';
60
- } else if (/permission|denied|EACCES|權限/i.test(errorText)) {
64
+ } else if (/\bpermission denied\b|\bEACCES\b|\bEPERM\b|權限.*(拒絕|不足|被拒)|拒絕.*權限/i.test(errorText)) {
61
65
  category = 'permission';
62
- } else if (/dependency|module not found|Cannot find module|模組.*找不到/i.test(errorText)) {
66
+ } else if (/\bdependency\b|\bmodule not found\b|Cannot find module|模組.*找不到/i.test(errorText)) {
63
67
  category = 'dependency';
64
68
  }
65
69
 
@@ -114,7 +118,11 @@ process.stdin.on('end', () => {
114
118
  state.lastFailureAt = Date.now();
115
119
 
116
120
  fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf8');
117
- } else if (!isFailureEvent && explicitSuccess) {
121
+ } else if (!isFailure) {
122
+ // NOTE (#166, follows #153): Claude Code PostToolUse success payloads
123
+ // carry no numeric exit code. The lifecycle event is authoritative:
124
+ // PostToolUse is success unless a numeric non-zero status contradicts it;
125
+ // hosts without lifecycle event names keep the conservative stderr fallback.
118
126
  // A successful action after an accepted zoom-out is an objective recovery
119
127
  // boundary. Emit only IDs/hashes/category; never copy command/output text.
120
128
  if ((state.zoomOutCycles || 0) > 0 && state.lastHash) {
@@ -3,7 +3,7 @@ const fs = require('fs');
3
3
  const path = require('path');
4
4
  const { getWorkspaceRoot, getSessionDir } = require('./lib/harness-state');
5
5
  const { loadWorkflow, saveWorkflow, peekMutationProbe, settleMutationProbe } = require('./lib/workflow-runtime');
6
- const { cwdOf, shellProbeKey, workspaceFingerprint } = require('./lib/workflow-isolation');
6
+ const { cwdOf, shellProbeKey, workspaceFingerprint, directMutationInWorkspace } = require('./lib/workflow-isolation');
7
7
  const { observeTool } = require('./lib/telemetry');
8
8
 
9
9
  // Commands that count as "verification ran" for the Stop gate
@@ -79,9 +79,10 @@ function processState(payload) {
79
79
  const exitCode = typeof rawExitCode === 'number' ? rawExitCode : undefined;
80
80
  const stderrSignal = typeof stderr === 'string' && stderr.trim().length > 0;
81
81
  const hookEvent = payload.hook_event_name || payload.hookEventName || '';
82
+ const isSuccessEvent = hookEvent === 'PostToolUse';
82
83
  const isFailed = hookEvent === 'PostToolUseFailure' ||
83
84
  (exitCode !== undefined && exitCode !== 0) ||
84
- (exitCode === undefined && stderrSignal);
85
+ (!isSuccessEvent && exitCode === undefined && stderrSignal);
85
86
  const toolName = payload.tool_name || payload.tool || 'command';
86
87
  const observedMutation = observeWorkspaceMutation(payload, root);
87
88
 
@@ -97,8 +98,13 @@ function processState(payload) {
97
98
  state.tool = toolName;
98
99
  state.exitCode = exitCode;
99
100
  state.errorSummary = output.trim();
100
- } else if (exitCode === 0 && state.status === 'failed') {
101
- // Clear failed state or mark as idle/resolved
101
+ } else if (!isFailed && state.status === 'failed') {
102
+ // Clear failed state or mark as idle/resolved.
103
+ // NOTE (#166, follows #153): Claude Code Bash PostToolUse payloads
104
+ // carry no numeric exit code, so `exitCode === 0` never holds there.
105
+ // A PostToolUse event with no numeric non-zero exit status counts as
106
+ // success even when stderr contains diagnostics. Hosts that omit the
107
+ // lifecycle event name retain the conservative stderr fallback.
102
108
  state.lastResolved = { tool: state.tool, timestamp: state.timestamp };
103
109
  state.status = 'idle';
104
110
  state.timestamp = new Date().toISOString();
@@ -107,8 +113,10 @@ function processState(payload) {
107
113
  }
108
114
 
109
115
  // Milestones for the Stop gate: when did the last mutation happen, and
110
- // has any verification-ish command succeeded since.
111
- if (toolName === 'Edit' || toolName === 'Write' || toolName === 'apply_patch' || observedMutation) {
116
+ // has any verification-ish command succeeded since. Direct-tool edits
117
+ // outside the workspace advance neither milestone (#165).
118
+ const isDirectTool = toolName === 'Edit' || toolName === 'Write' || toolName === 'apply_patch';
119
+ if ((isDirectTool && directMutationInWorkspace(payload, cwdOf(payload, root), root)) || observedMutation) {
112
120
  state.lastEditAt = Date.now();
113
121
  }
114
122
  if ((toolName === 'Bash' || toolName === 'PowerShell') && !isFailed) {
@@ -4,7 +4,7 @@
4
4
  const path = require('path');
5
5
  const fs = require('fs');
6
6
  const { loadWorkflow, saveWorkflow, isMajorWorkflow, matchingRun, registerMutationProbe, recordBudgetEvent, readHookInput, WORKFLOW_CONTROLLER_COMMANDS } = require('./lib/workflow-runtime');
7
- const { key, classifyShell, workspaceFingerprint, shellProbeKey, cwdOf, commandOf, mutationPaths, linkedWorktree, assertTargets, assertShellScope } = require('./lib/workflow-isolation');
7
+ const { key, classifyShell, workspaceFingerprint, shellProbeKey, cwdOf, commandOf, mutationPaths, directMutationInWorkspace, linkedWorktree, assertTargets, assertShellScope } = require('./lib/workflow-isolation');
8
8
 
9
9
  const DIRECT = new Set(['Edit', 'Write', 'apply_patch']);
10
10
  const SHELL = new Set(['Bash', 'PowerShell', 'exec_command']);
@@ -48,6 +48,10 @@ function decide(payload) {
48
48
  throw new Error('selected Fable workflow has no correlated run. Write workflow-stages.json at the displayed session path, then use workflow-disposition.js start.');
49
49
  }
50
50
  if (DIRECT.has(tool)) {
51
+ // Bookkeeping outside the workspace (scratchpad, memory files, temp
52
+ // notes) is not a workspace mutation: it consumes no Tier-2 iteration
53
+ // and advances no mutation milestone (#165).
54
+ if (!directMutationInWorkspace(payload, cwd, root)) return;
51
55
  if (workflow.strategy === 'iterative-single') {
52
56
  recordBudgetEvent(context, 'iteration', { evidence: `${tool}:direct-mutation` });
53
57
  }
@@ -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.11.6",
4
+ "version": "0.11.7",
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,7 +4,7 @@ description: "Route software/project work through the Harness kernel: classify T
4
4
  license: Apache-2.0
5
5
  metadata:
6
6
  author: Miya Daniel
7
- version: 0.11.2
7
+ version: 0.11.7
8
8
  ---
9
9
 
10
10
  # Harness Everything
@@ -33,12 +33,26 @@ function issueMemoryCapability(workflow) {
33
33
  return token;
34
34
  }
35
35
 
36
+ // Host-generated background-task notifications arrive as UserPromptSubmit
37
+ // hook payloads but are not user input (#168). Routing them like prompts
38
+ // replaces the workflow contract mid-turn (e.g. deferred -> a new Tier-2).
39
+ // A prompt that is entirely a notification envelope must never create or
40
+ // replace a workflow; the current contract is kept unchanged.
41
+ function isHostNotificationPrompt(prompt) {
42
+ const text = String(prompt || '').trim();
43
+ if (!text) return false;
44
+ return /^<task-notification[\s>][\s\S]*<\/task-notification>\s*$/i.test(text);
45
+ }
46
+
36
47
  function persistWorkflow(plan, payload, prompt) {
37
48
  if (!payload || !(payload.session_id || payload.sessionId)) return null;
38
49
  const { runtime, hooksRoot } = loadRuntime();
39
50
  const context = runtime.loadWorkflow(payload);
40
51
  const { writeCurrentSession } = require(path.join(hooksRoot, 'lib/harness-state'));
41
52
  writeCurrentSession(context.root, context.sessionId);
53
+ if (isHostNotificationPrompt(prompt)) {
54
+ return { ...context, hooksRoot, retained: true, hostNotification: true };
55
+ }
42
56
  if (context.workflow && runtime.OPEN_STATES.has(context.workflow.state)) {
43
57
  if (!context.workflow.workflowPlan) throw new Error('legacy unresolved workflow needs explicit migration; refusing to replace its obligations');
44
58
  // Steering/status prompts cannot drop an unresolved execution contract.
@@ -92,17 +106,30 @@ function run(raw) {
92
106
  try { payload = JSON.parse(raw); } catch (_) { console.error('[Workflow Router] Invalid hook payload; lifecycle persistence unavailable.'); }
93
107
  }
94
108
  const prompt = promptArg || (typeof payload?.prompt === 'string' ? payload.prompt : '');
95
- const result = core.route(promptArg, raw || null);
96
- let plan = result.contract.workflowPlan;
109
+ const hostNotification = isHostNotificationPrompt(prompt);
110
+ // Host-generated notifications are lifecycle events, not user-authored task
111
+ // input. Never feed their text into the router: when there is an active
112
+ // contract we retain it below; when there is none, the event is a no-op.
113
+ const result = hostNotification ? null : core.route(promptArg, raw || null);
114
+ let plan = result?.contract?.workflowPlan || null;
97
115
  let persisted = null;
98
116
  let failure = null;
99
117
  try {
100
118
  persisted = persistWorkflow(plan, payload, prompt);
101
- if (persisted?.retained) plan = persisted.workflow.workflowPlan;
119
+ if (persisted?.retained && persisted.workflow) plan = persisted.workflow.workflowPlan;
102
120
  } catch (error) { failure = error; }
103
- if (result.sanitized) console.log(result.sanitized);
104
- if (result.stderr) process.stderr.write(result.stderr);
105
- if (persisted?.retained) console.log('\n=> Retaining unresolved workflow from earlier prompts; the checkpoint below is the active execution contract.');
121
+ if (hostNotification && !persisted?.workflow) {
122
+ console.log('\n=> Host notification — no active execution contract; ignored for routing.');
123
+ if (failure) {
124
+ console.error('[Workflow Router] ' + failure.message);
125
+ process.exitCode = 2;
126
+ }
127
+ return;
128
+ }
129
+ if (result?.sanitized) console.log(result.sanitized);
130
+ if (result?.stderr) process.stderr.write(result.stderr);
131
+ if (persisted?.hostNotification) console.log('\n=> Host notification — routing unchanged; keeping the active execution contract.');
132
+ else if (persisted?.retained) console.log('\n=> Retaining unresolved workflow from earlier prompts; the checkpoint below is the active execution contract.');
106
133
  core.printWorkflowPlan(plan);
107
134
  core.printRoutingCheckpoint(plan);
108
135
  core.printKernelContract(plan);
@@ -116,7 +143,7 @@ function run(raw) {
116
143
  console.log(' - Tier 3 / Fable source and artifact mutations require Git worktree isolation; unavailable isolation means BLOCKED.');
117
144
  console.log(' - Escape is limited to workflow-uncovered-scope or host-capability-unavailable, with stage, scope and evidence; other obligations remain mandatory.');
118
145
  }
119
- if (persisted) {
146
+ if (persisted?.workflow) {
120
147
  const controller = path.join(persisted.hooksRoot, 'workflow-disposition.js');
121
148
  console.log(' - Workflow id: ' + persisted.workflow.workflowId);
122
149
  console.log(' - Memory write disposition: ' + (persisted.workflow.workflowPlan.memory?.write || 'none'));
@@ -130,12 +157,13 @@ function run(raw) {
130
157
  if (failure) {
131
158
  console.error('[Workflow Router] ' + failure.message);
132
159
  process.exitCode = 2;
133
- } else if (result.status !== 0) process.exitCode = result.status || 1;
160
+ } else if (result && result.status !== 0) process.exitCode = result.status || 1;
134
161
  }
135
162
 
163
+ if (typeof module !== 'undefined') module.exports = { isHostNotificationPrompt };
164
+
136
165
  if (process.argv.length > 2 || process.stdin.isTTY) run('');
137
- else {
138
- let input = '';
166
+ else { let input = '';
139
167
  let finished = false;
140
168
  const finish = () => { if (finished) return; finished = true; clearTimeout(timeout); run(input); };
141
169
  const timeout = setTimeout(finish, 500);
@@ -1,47 +0,0 @@
1
- # Issue #20 umbrella rollup
2
-
3
- This rollup turns issue #20's historical checklist into bounded acceptance decisions. The review snapshot is `main` at `ba7853b`, checked on 2026-09-07. The umbrella owns coordination and release evidence; implementation details remain with the linked issue.
4
-
5
- ## Closure status
6
-
7
- Issue #20 remains open after this PR. This branch adds deterministic parser,
8
- collision-gate, plugin-runner, and negative-control coverage, but it does not
9
- provide live opencode session evidence, a paid behavioral rerun, the proposed
10
- 100-case study, or the three skill-specific improvements below. Those gaps are
11
- recorded explicitly rather than treated as closed by the deterministic gates.
12
-
13
- ## Workstream decisions
14
-
15
- | Workstream | Evidence in the review snapshot | Acceptance state | Remaining claim boundary |
16
- | --- | --- | --- | --- |
17
- | #37 opencode enforcement | The real plugin API is implemented and mechanism coverage exists in `ci/mechanism-2n-opencode-plugin.test.js`; the integrated reflection lifecycle is `d790e7f` on the integration branch. | Integrated, pending final integration gates | No live opencode loading or session smoke evidence was available; do not claim live enforcement. |
18
- | #52 behavioral transcript parsing | Claude stream fixtures and parser coverage are integrated in `77efb06`; deterministic parser tests are available. | Integrated, pending final integration gates | No new paid behavioral rerun is part of this umbrella. Parse failures and missing tool visibility remain evidence states, not skill failures. |
19
- | Systematic gate hardening | The local gates now execute real negative controls; YAML frontmatter parsing fails closed in `ci/description-collision.js`, `ci/routing-check.js` skips clearly when waza is absent, and `ci/mechanism-2t-issue-20.test.js` covers CRLF behavioral parsing and plugin validation. | Deterministic hardening integrated | Live platform loading and model behavior remain unverified. |
20
- | #42 workspace identity and migration | Workspace-keyed state and migration coverage are integrated in `9dd2e3d`; the issue review identified session and migration acceptance as the relevant boundary. | Integrated, pending final integration gates | Do not claim every host/session migration path is live verified until the integration gate and targeted fixtures pass. |
21
- | #43 multi-agent workspace layout | The reviewed plan makes its root contract depend on #42. No implementation commit was present in the issue #20 review snapshot. | Deferred to its owner | Do not duplicate its layout or runtime work in this umbrella. |
22
- | #44 progressive disclosure | Documentation and reference checks are integrated in `b33f598`; `ci/disclosure-check.js` and its mechanism coverage are present. | Integrated, pending final integration gates | This records repository documentation evidence; it does not establish behavioral-model effectiveness. |
23
- | #56 behavioral rubric triage | The review found grader/source-boundary issues, including `command_exit_0` proving the grader command rather than the agent action. | Deferred to its owner | Do not reuse the historical pass-rate claims until the rubric and trace evidence are corrected. |
24
- | Extended 100-case study | The original issue proposed 100 cases, but the review did not establish a decision threshold or clean attribution between skill text, plugin enforcement, and grader behavior. | Explicitly deferred | No uncontrolled 100-case run is authorized by this rollup. Define paired design, failure taxonomy, and decision rule first. |
25
- | Five historical baseline failures | The committed 2026-08-27 records show one failed expectation in each of `baseline-debugging` (edge-case consideration), `baseline-performance` (binary-search suggestion), `baseline-security-review` (MD5 identification), `baseline-simple-bugfix` (function understanding), and `verify-before-done` (verification actually run). | Explicitly deferred | These are historical observations, not a new causal investigation or rerun; do not claim they were fixed by this PR. |
26
- | Skill-specific improvements | No targeted changes were made to `verification-loop`, `zoom-out`, or `security-review` in this branch. | Explicitly deferred | Strengthening verification enforcement, reflection-report detection, and vulnerability detection requires separate design and behavioral evidence. |
27
- | Release | The tag-triggered full gate and provenance publish workflow already exists. Historical `0.3.6` evidence is recorded in [docs/release-evidence.md](release-evidence.md). | Documentation complete; next release unproven | A prepared `0.3.7-beta` version is not evidence of a tag, npm publication, or GitHub release. |
28
-
29
- ## Focused acceptance checks
30
-
31
- The integration owner should run these checks after incorporating the issue branches:
32
-
33
- ```text
34
- npm test
35
- npm run test:mechanism
36
- npm run test:consistency
37
- npm run test:references
38
- npm run test:release
39
- npm run test:collision
40
- npm run test:routing:skills
41
- ```
42
-
43
- The checks establish deterministic repository and routing health. They do not substitute for live opencode loading, a paid behavioral run, or npm/GitHub release evidence. Those claims require the artifacts named in [RELEASING.md](../RELEASING.md) and [docs/release-evidence.md](release-evidence.md).
44
-
45
- ## Historical evidence boundary
46
-
47
- The local review artifact `.git/issue-review-20260907/release-evidence.md` records a successful `0.3.6` workflow (`33466676632`) and npm observation. It explicitly says that this is not proof of a `0.3.7-beta` release. This rollup preserves that distinction so an old successful release cannot be mistaken for current publication evidence.
@@ -1,89 +0,0 @@
1
- # PR #142 / issue #131 completion review
2
-
3
- This review covers the implementation in the commit containing this report,
4
- starting from PR head `8b99baec44745e171f078fe9eb3dac6fd812b5c8`. It evaluates
5
- Harness engineering and the latest #131 decision, including mandatory mutation
6
- isolation. It is not a measured agent-performance benchmark.
7
-
8
- ## Findings resolved
9
-
10
- | Original gap | Delivered behavior | Regression evidence |
11
- | --- | --- | --- |
12
- | Escape changed the whole workflow state and skipped isolation | Stage-scoped escape; isolation survives legacy escape and blocked states | `mechanism-2af-worktree-isolation.test.js`, `mechanism-2ah-workflow-lifecycle.test.js` |
13
- | Only cwd was checked | Registered linked checkout of the bound repo; direct/patch targets, move destinations, traversal, and links checked | `mechanism-2af-worktree-isolation.test.js` |
14
- | Windows runner used 8.3 paths while Git reported long names | Native physical-path resolution equates both spellings without relaxing isolation | Windows path regression and worktree suites |
15
- | Read-only shell prefixes accepted writes | Reject redirects, substitutions, chained commands and dangerous options; require isolated cwd for mutation/unknown commands | `mechanism-2af-worktree-isolation.test.js` |
16
- | Next prompt erased unresolved obligations | Stable workflow identity across steering prompts; stronger route requires replan | `mechanism-2ah-workflow-lifecycle.test.js` |
17
- | Same strategy/timestamp loosely matched any Fable run | Exact workflow, session and run correlation | `mechanism-2ah-workflow-lifecycle.test.js` |
18
- | Entry gate blocked its own bootstrap path | One bounded stage-specification file and trusted start controller; state/source writes remain gated | `mechanism-2ah-workflow-lifecycle.test.js` |
19
- | Stop trusted directory contents and pass labels | Expected manifest stages, correlated exit-zero evidence, worker attribution and fresh verifier required | `mechanism-2ah-workflow-lifecycle.test.js` |
20
- | Stop retry silently passed unresolved work | Retry records blocked; no satisfied state without required evidence | `mechanism-2ah-workflow-lifecycle.test.js` |
21
- | Failures could not recover cleanly | Observed fail-to-pass checks; explicit bounded replan; retained prior run evidence | `mechanism-2ah-workflow-lifecycle.test.js` |
22
- | Runtime policy scraped human-readable output | Kernel imports the structured core result; complete invariants persist with the plan | routing tests and lifecycle tests |
23
- | Current documents contradicted the PR | README, platform matrix, routing, architecture, Fable/worktree references and mirrors aligned | consistency/capability/reference gates |
24
- | Existing CI selected the first matching hook group | Action-gate regression finds its actual adapter among shared tool matchers | `ci/action-gate.test.js` |
25
-
26
- The first added isolation regression run failed 16 assertions against the PR
27
- baseline, then passed after repair. The baseline's four failing GitHub CI jobs
28
- also reported the action-gate matcher defect. The initial local checkout lacked
29
- dependencies, producing a separate CRLF-fixture setup failure; `npm ci` resolved
30
- that environment prerequisite.
31
-
32
- ## Verification
33
-
34
- Local environment: Windows, PowerShell, Node.js 24.15.0, npm 11.12.1. Work was
35
- performed in an isolated linked worktree; the primary checkout remained clean.
36
-
37
- All 14 required gate categories passed: `npm test`, mutations, mechanism,
38
- consistency, repository contract, capability docs, references, release,
39
- collision, positive skill routing, routing invariants, OpenAI package/runtime,
40
- public submission, and platform compatibility. Failed checks were corrected and
41
- the affected gates rerun. The final `npm test` includes **44 mechanism suites**.
42
-
43
- The new lifecycle suite exercises **50 assertions against source and the same
44
- 50 against the packaged OpenAI layout**, using actual child processes, Git
45
- repositories, worktrees, controller commands and hook payloads. Host payloads
46
- are fixtures: these are deterministic mechanism tests, not live agent sessions.
47
-
48
- Waza passed 30 canonical/nested skill readiness checks, 26 routing-spec checks,
49
- and token validation (57 successful commands). Positive routing covered 34
50
- cases across 26 direct skills and classified four nested skills.
51
-
52
- Build/types/lint have no separate project scripts; repository syntax and
53
- consistency gates apply. No coverage percentage is claimed. The security scanner
54
- reported 12 pre-existing documentation/test-pattern matches, including its own
55
- patterns and an explicitly fake token fixture; changed production code added no
56
- scanner findings. `npm ci` reported zero dependency vulnerabilities. Diff review
57
- and `git diff --check` passed. See the retained [gate summary](../../benchmarks/results/reviews/pr142-verification.json).
58
-
59
- Remote CI is a separate evidence layer. Its result must be read at the final PR
60
- head; this local record does not assert a future GitHub Actions outcome.
61
-
62
- ## Reassessment
63
-
64
- Scores are review judgments about engineering readiness, each out of 100.
65
- Each row has four equally weighted criteria (25 points each), with the observed
66
- deductions shown. They are not success probabilities or benchmark results.
67
-
68
- | Dimension | Criteria scores | Total | Remaining deductions |
69
- | --- | --- | ---: | --- |
70
- | Contract coherence | entry 22, transitions 23, scoped exceptions 24, docs 23 | 92 | Skill applicability and iterative budgets still partly rely on executor compliance |
71
- | Mutation safety | worktree identity 23, targets 23, shell handling 17, state trust 12 | 75 | Arbitrary script effects need a host sandbox; runtime state is agent-writable |
72
- | Deterministic verification | gate breadth 25, negative cases 24, package parity 24, evidence checks 18 | 91 | Host-shaped fixtures cannot establish real host behavior or semantic check quality |
73
- | Operation and maintenance | entry/recovery 22, modularity 21, distribution 23, diagnostics/migration 18 | 84 | Manual stage setup, missing-metadata blocks and legacy-state repair add operator work |
74
-
75
- Equal-weight engineering score: **85.5/100** (approximately **86/100**).
76
- The system now has substantially stronger tested lifecycle and isolation
77
- contracts. It is suitable for further host validation with explicit boundaries.
78
-
79
- **Live-host reliability of these new gates remains unverified. Behavioral gain
80
- from this PR remains unmeasured.** Neither receives an invented effectiveness
81
- score. Older retained OpenCode evidence and older behavioral cases cannot prove
82
- this workflow change. This review does not claim superiority over other skill
83
- collections, reduced token cost, or improved task success rates.
84
-
85
- The next evidence needed is a retained Claude/Codex session showing routing,
86
- entry, mutation denial/allow, numeric stage results, worker correlation and Stop
87
- resolution; then paired same-model/same-task behavioral runs. OpenCode needs its
88
- own adapter before parity can be claimed. See [runtime limits](../workflow-runtime.md)
89
- and [platform capabilities](../platform-capabilities.md).