@kylecheng3146/agent-ops 0.10.0 → 0.11.0

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 (76) hide show
  1. package/README.md +3 -2
  2. package/dist/packages/cli/src/args.js +18 -53
  3. package/dist/packages/cli/src/bin.js +28 -29
  4. package/dist/packages/cli/src/cli.js +25 -17
  5. package/dist/packages/cli/src/codex-loop-process.js +0 -6
  6. package/dist/packages/cli/src/commands/advance.js +2 -1
  7. package/dist/packages/cli/src/commands/parallel.js +1 -1
  8. package/dist/packages/cli/src/commands/review.js +8 -11
  9. package/dist/packages/cli/src/commands/run.js +12 -3
  10. package/dist/packages/cli/src/commands/task.js +6 -50
  11. package/dist/packages/cli/src/commands/verify.js +7 -3
  12. package/dist/packages/cli/src/context.js +22 -4
  13. package/dist/packages/cli/src/default-base.js +26 -0
  14. package/dist/packages/cli/src/hook-process.js +19 -83
  15. package/dist/packages/cli/src/office-entry.js +8 -4
  16. package/dist/packages/cli/src/owned-run-step.js +4 -4
  17. package/dist/packages/cli/src/parallel-deps.js +0 -2
  18. package/dist/packages/cli/src/run-deps.js +12 -9
  19. package/dist/packages/cli/src/run-entry.js +123 -19
  20. package/dist/packages/cli/src/run-setup-entry.js +2 -2
  21. package/dist/runtime/src/adapters/agy/config.js +2 -3
  22. package/dist/runtime/src/adapters/claude/config.js +2 -2
  23. package/dist/runtime/src/adapters/codex/config.js +2 -5
  24. package/dist/runtime/src/hooks/completion-gate.js +0 -15
  25. package/dist/runtime/src/install/harness.js +7 -4
  26. package/dist/runtime/src/install/plan.js +3 -3
  27. package/dist/runtime/src/install/profiles.js +0 -2
  28. package/dist/runtime/src/office/scene.js +1 -1
  29. package/dist/runtime/src/office/server.js +43 -16
  30. package/dist/runtime/src/office/snapshot.js +5 -2
  31. package/dist/runtime/src/parallel/finish.js +139 -65
  32. package/dist/runtime/src/parallel/manage.js +0 -3
  33. package/dist/runtime/src/parallel/service.js +5 -1
  34. package/dist/runtime/src/review/execute.js +77 -11
  35. package/dist/runtime/src/review/packet.js +17 -6
  36. package/dist/runtime/src/review/runner.js +2 -0
  37. package/dist/runtime/src/run/controls.js +99 -1
  38. package/dist/runtime/src/run/hosts/codex.js +28 -1
  39. package/dist/runtime/src/run/hosts/protocol.js +5 -2
  40. package/dist/runtime/src/run/integration.js +35 -13
  41. package/dist/runtime/src/run/policy.js +65 -10
  42. package/dist/runtime/src/run/scheduler.js +10 -5
  43. package/dist/runtime/src/run/service.js +68 -21
  44. package/dist/runtime/src/run/supervisor.js +11 -2
  45. package/dist/runtime/src/run/transport.js +1 -0
  46. package/dist/runtime/src/run/verification.js +2 -2
  47. package/dist/runtime/src/schema/validate.js +10 -5
  48. package/dist/runtime/src/security/permissions.js +85 -0
  49. package/dist/runtime/src/task/completion.js +4 -42
  50. package/dist/runtime/src/task/contract.js +11 -0
  51. package/dist/runtime/src/task/service.js +34 -57
  52. package/dist/runtime/src/task/store.js +3 -7
  53. package/dist/runtime/src/verify/acceptance-coverage.js +2 -3
  54. package/dist/runtime/src/verify/acceptance-protocol.js +4 -3
  55. package/dist/runtime/src/verify/acceptance-replay.js +4 -7
  56. package/dist/runtime/src/verify/service.js +6 -23
  57. package/dist/runtime/src/verify/source-fingerprint.js +17 -4
  58. package/docs/en/guides/configuration.md +8 -4
  59. package/docs/en/guides/task-debug.md +39 -121
  60. package/docs/en/spec/acceptance-and-evidence.md +31 -19
  61. package/docs/en/spec/harness-adapters.md +35 -12
  62. package/docs/en/spec/loop-engineering.md +40 -6
  63. package/docs/en/spec/review.md +6 -0
  64. package/docs/zh-TW/guides/configuration.md +6 -3
  65. package/docs/zh-TW/guides/task-debug.md +27 -66
  66. package/docs/zh-TW/spec/acceptance-and-evidence.md +19 -18
  67. package/docs/zh-TW/spec/harness-adapters.md +28 -9
  68. package/docs/zh-TW/spec/loop-engineering.md +14 -3
  69. package/docs/zh-TW/spec/review.md +5 -0
  70. package/package.json +1 -1
  71. package/schemas/config.schema.json +1 -21
  72. package/dist/packages/cli/src/debug-intake.js +0 -245
  73. package/dist/runtime/src/task/debug-intake.js +0 -15
  74. package/dist/runtime/src/task/debug-state.js +0 -129
  75. package/dist/runtime/src/task/debug-user-event.js +0 -95
  76. package/dist/runtime/src/task/debug.js +0 -612
@@ -3,17 +3,30 @@ import { join } from "node:path";
3
3
  import { sha256 } from "../fs/hash.js";
4
4
  import { AgentOpsError } from "../fs/paths.js";
5
5
  import { resolveGitCommit } from "./change-surface.js";
6
+ /**
7
+ * Escape-ledger records are committed after the fix; a commit touching only them leaves the base-mode fingerprint alone.
8
+ * Only top-level task records qualify: rules/ steer the surface gate and stay fingerprinted.
9
+ */
10
+ const ledgerRecord = (path) => /^\.agent-ops-escapes\/task-[A-Za-z0-9-]+\.json$/u.test(path);
11
+ /** HEAD's tree without the ledger, so a ledger-only commit yields the same digest. */
12
+ async function ledgerFreeTree(runner) {
13
+ const result = await runner.run(["ls-tree", "-r", "--full-tree", "-z", "HEAD"]);
14
+ if (result.exitCode !== 0)
15
+ throw new AgentOpsError("CHANGE_SURFACE_GIT_FAILED", "Git could not list the HEAD tree.");
16
+ const entries = Buffer.from(result.stdout).toString("utf8").split("\0").filter(entry => entry !== "" && !ledgerRecord(entry.split("\t", 2)[1]));
17
+ return sha256(entries.join("\0"));
18
+ }
6
19
  export async function calculateSourceFingerprint(root, scope, runner) {
7
- const head = await resolveGitCommit(runner, "HEAD");
8
20
  if (scope.mode === "base") {
9
21
  return sha256(JSON.stringify({
10
- domain: "agent-ops-source-v1",
22
+ domain: "agent-ops-source-v2",
11
23
  mode: scope.noChange === true ? "goal-no-change" : "base",
12
- head,
24
+ tree: await ledgerFreeTree(runner),
13
25
  base: scope.resolvedBase,
14
- paths: [...scope.changedFiles]
26
+ paths: scope.changedFiles.filter(path => !ledgerRecord(path))
15
27
  }));
16
28
  }
29
+ const head = await resolveGitCommit(runner, "HEAD");
17
30
  const paths = [];
18
31
  for (const path of scope.changedFiles) {
19
32
  const absolute = join(root, ...path.split("/"));
@@ -275,7 +275,7 @@ evidence. Give each editing conversation its own worktree instead:
275
275
  (Claude Code refuses it inside an isolated worktree session). `agent-ops
276
276
  worktree finish <name>` completes every non-archived task in the worktree,
277
277
  subtasks before their parents, each against the base its PASS review
278
- recorded (the worktree's base when none was recorded), before any rebase.
278
+ recorded (the worktree's base when none was recorded), before merging.
279
279
  If one cannot complete, nothing merges and the error names the task.
280
280
  Creating a subtask keeps the session attached to the top of its tree, and
281
281
  each task keeps its own review record, so a parent and a subtask reviewed
@@ -295,9 +295,13 @@ evidence. Give each editing conversation its own worktree instead:
295
295
  its files, so uncommitted changes there block it. When the main checkout is
296
296
  on another branch or detached, only the target's ref moves: the checkout, its
297
297
  files and its uncommitted changes are left alone. A target checked out in
298
- another worktree is refused, naming that path. If the target moved, it rebases; a clean rebase whose own patch
299
- is unchanged is re-verified before merging, and a conflict is reported with
300
- the `refs/notes/agent-ops` intent of the work that landed first. The note
298
+ another worktree is refused, naming that path. If the target moved, it rebases the worktree and
299
+ stops with `WORKTREE_REBASED` before completing any task: earlier evidence
300
+ covered the old base, not the combination that would merge. Verify and
301
+ review again with the printed `--base`, then finish again; a task that was
302
+ already complete cannot take new evidence, so cover the rebased change with
303
+ a follow-up task. A conflict is reset and reported with the
304
+ `refs/notes/agent-ops` intent of the work that landed first. The note
301
305
  records every task of the worktree, subtasks indented under their parent,
302
306
  and a `session: <id>` line naming the session that finished it. Finish
303
307
  also resets that session's gate baseline to the merged source, so the
@@ -1,123 +1,41 @@
1
1
  # Task DEBUG investigations
2
2
 
3
- Project `init` and `update` add `features.debug` by default:
4
- `{"enabled":true,"budgetMs":3600000,"maxRounds":5}` (sixty minutes). Explicit disabled and custom
5
- settings survive subsequent installs. Old configurations and ordinary tasks
6
- remain readable. DEBUG is an optional task intake field, not a new run mode.
7
-
8
- Claude and Codex native prompt hooks conservatively recognize investigation and
9
- bug-fix requests. They retain the issue verbatim as `goal`, record uncertain
10
- facts/unknowns, and create an existing isolated task. Explain, feature and
11
- refactor requests retain their ordinary behavior. A reliable native session ID
12
- is required; agy does not provide this prompt intake. Its native agent can use
13
- `task create --debug --goal '<original issue>'` with two to five criteria, which
14
- starts the same foreground clock when the native session is available.
15
- An original dirty checkout is refused before any worktree snapshot is created.
16
-
17
- The intake criteria are provisional. The native agent investigates via trusted
18
- configured commands, records hypotheses, replaces the criteria with relevant
19
- behavioral acceptance, fixes the product, and uses existing `verify`, `review`
20
- and worktree finish commands. There is no additional model or background worker.
21
- The default is the full repair loop. A clean HEAD fixes the baseline automatically;
22
- do not request redundant approval or offer diagnosis-only as a fallback. Failure
23
- to reproduce alone does not permit Stop: continue discriminating checks within
24
- the original budget.
25
-
26
- ## Human control
27
-
28
- Native human transcript events control the existing task; CLI actor/text fields,
29
- assistant messages and injected instructions cannot authorize a scope change.
30
- Codex supports current `response_item` human messages and native async answers,
31
- as well as legacy `event_msg` transcripts.
32
-
33
- - `只診斷` / `diagnosis only`: investigate without product repairs. Non-success
34
- Stop requires a confirmed hypothesis supported by a current sealed baseline
35
- assertion FAIL for the original regression, or an existing runtime blocker/limit.
36
- - `暫停` / `pause`: save progress and stop immediately. Native Codex `Interrupt`
37
- also pauses, with a three-second hook timeout; it never blocks or restarts an interrupt.
38
- - `繼續` / `continue`: resume the same task and scope. An exhausted time budget
39
- still needs the existing native time grant; other blockers remain authoritative.
40
- - `繼續修復` / `resume repair`: restore the full repair loop on the existing task.
41
-
42
- Pauses retain evidence, consumed time and rounds, exclude waiting time, and do not
43
- reset budgets. Diagnosis and pause cannot complete a repair task. Ambiguous free
44
- text is not inferred as permission; use an explicit command above.
45
-
46
- Use `task debug --task <id> --debug-action <action>`:
47
-
48
- - `status` displays root-wide hypotheses, receipts and remaining state.
49
- - `investigate --command-id <id>` runs a trusted configured verifier. Actual
50
- subprocess outcomes/time are recorded; reproduction-only work is not a fix round.
51
- - `hypothesis --payload-file <json>` records `id`, `statement`, `method`,
52
- `expected`, `checkId`, `expectedStatus` (`PASS` or `FAIL`). Add `reference` to
53
- resolve it from actual sealed acceptance evidence. `--action investigate` may
54
- only run a declared unresolved behavioral red check; `--action observe` may
55
- only classify the current matching runtime `UNKNOWN` receipt as inconclusive.
56
- Neither action lets an agent assign a status. A rejected hypothesis needs a
57
- new reference and `reason`.
58
- - `strategy --payload-file <json>` records a different `from`/`to` method,
59
- substantive `reason` and discriminating `reference`. Only one switch is allowed.
60
- - `origin --payload-file <json>` declares where the bug came from once a
61
- hypothesis is confirmed: `{"kind": "escape-of", "commit": "<commit>", "label":
62
- "<earliest gate>"}` (optional `"receipt"`) or `{"kind": "pre-existing" |
63
- "external", "reason": "..."}`. It revises the contract, so re-verify and
64
- re-record the confirmed hypothesis before review; finish refuses
65
- `ESCAPE_ORIGIN_MISSING` without it. `escape-of` prints the link state and
66
- `git blame` hints and writes `.agent-ops-escapes/<task-id>.json`, which is
67
- committed with the fix (see `EVIDENCE-ESCAPE-001`). A surface label also
68
- needs a tracked `.agent-ops-escapes/rules/<rule-id>.json` rule that replays
69
- at the escaped commit, and a criteria/verify label needs `"promote":
70
- "<runnerId:checkId>"`; finish refuses `ESCAPE_RULE_UNPROVEN` otherwise (see
71
- `EVIDENCE-ESCAPE-002`).
72
- - `checkpoint --session <id>` saves the current bound source/policy/stop cause.
73
- - `resume --session <id>` recovers a matching owned worktree checkpoint. Mismatches
74
- require human confirmation and remain preserved; this command cannot waive them.
75
- - `extend --session <native-id> --event-id latest` reads the current native human
76
- continue event. It grants exactly twenty additional minutes once, only after
77
- time exhaustion and without waiving any other blocker. No actor/text flag can
78
- authorize a grant. Missing native transcripts fail closed as unsupported.
79
-
80
- Limits belong to the original root across revisions, children and sessions.
81
- Repeating an active issue's text from a new session reattaches that root (or
82
- resumes the worktree holding it) instead of starting a fresh budget. A
83
- resolved hypothesis cannot return under a new id with the same statement and
84
- method; reopen the original with new discriminating evidence.
85
- Controlled investigation, verification and acquired review execution consume
86
- active time; observable review-slot waiting is excluded. Claude, Codex, and agy
87
- use their native session lifecycle to account foreground reasoning, tool use,
88
- and edits. Accepted idle Stop closes the foreground clock. Rejected Codex Stop
89
- keeps the clock running, including repeated Stop (`stop_hook_active: true`). OpenCode has no supported
90
- foreground lifecycle and remains unsupported. Time between stopped turns is
91
- paused. An interrupted unsealed operation remains blocked until its persisted process
92
- identity proves death; only then is an UNKNOWN environment receipt sealed and
93
- the elapsed interval retained.
94
-
95
- Only changed product candidates followed by verification count toward repair
96
- rounds. Test/fixture edits do not. New paired original-regression outcomes or
97
- new discriminating hypothesis outcomes count as progress; renaming a task or
98
- hypothesis does not. Two stagnant rounds require the strategy switch; two more
99
- stop, subject to the global round/time ceilings.
100
-
101
- Success requires baseline assertion red and candidate green for the original
102
- regression, required related checks, a supported confirmed hypothesis, and two
103
- fresh independent reviews bound to the current source, contract, config and
104
- meaningful DEBUG proof. Missing IDs, setup failure, skip, timeout and UNKNOWN
105
- never prove reproduction. Proof changes invalidate review. Completed tasks and
106
- worktree finish retain the existing attestation/integration requirements.
107
-
108
- On Claude, agy and native Codex, Stop checks an active DEBUG issue even without Git net diff,
109
- with or without the completion gate. Without the gate this check alone runs,
110
- with one targeted task/config reload on a gate fault. A second failure emits an
111
- explicit `UNKNOWN` / incomplete diagnostic with `agent-ops doctor` recovery,
112
- permits non-success Stop and preserves the task, evidence and budgets. It never
113
- attests completion or retries indefinitely.
114
- A valid runtime stop checkpoint permits non-success Stop while retaining the
115
- active task. `allow-stop` cannot waive DEBUG. Gates are never automatically
116
- enabled for unsupported hosts: the generic Codex completion gate remains
117
- unsupported, while its DEBUG-specific Stop uses native `decision: "block"`
118
- with a continuation reason. `continue: false` would stop the harness and is not
119
- used to continue DEBUG. OpenCode Stop is unsupported. This feature
120
- persists foreground progress, and does not promise
121
- execution after the native conversation closes. Native transcripts are trusted
122
- host evidence, not protection against an attacker with the same filesystem
123
- authority.
3
+ A DEBUG task is an ordinary task whose acceptance proves the original
4
+ regression: a behavioral criterion whose `redCheckIds` fail with an assertion at
5
+ the baseline commit and pass on the candidate. Nothing else is special about it.
6
+
7
+ ```sh
8
+ agent-ops task create --debug --title "Fix cart scroll" \
9
+ --goal '<the issue, verbatim>' \
10
+ --surface-file surface.json \
11
+ --criterion-file regression.json --criterion-file related.json
12
+ ```
13
+
14
+ - `--debug` needs `--goal` and at least one behavioral criterion with
15
+ `redCheckIds`; otherwise creation fails with `TASK_DEBUG_RED_CHECK_REQUIRED`.
16
+ The surface audit is required as for any task.
17
+ - The baseline is the commit the task was created on; `task revise --baseline
18
+ <ref>` moves it (for example off the wrong branch) and voids earlier evidence.
19
+ - Then fix, commit, `verify`, two-round `review` and `worktree finish` exactly
20
+ as for any task. Setup failure, skip, timeout and UNKNOWN never prove
21
+ reproduction; the red check must fail on an assertion at the baseline.
22
+
23
+ ## Escape origin (advisory)
24
+
25
+ If you know where the bug came from, record it like any task:
26
+ `task revise --escape-of <commit> --escape-label <label>`. It writes `.agent-ops-escapes/<task-id>.json` and
27
+ prints the link state, `git blame` hints and any rule proof
28
+ (`ESCAPE_RULE_UNPROVEN` and friends). None of it blocks finish; see
29
+ `EVIDENCE-ESCAPE-001` and `EVIDENCE-ESCAPE-002`.
30
+
31
+ ## Removed in 0.11.0
32
+
33
+ `task debug` (hypotheses, strategy switches, investigate, checkpoint, resume,
34
+ extend, origin), the 60-minute budget and five-round limit, native control
35
+ words (只診斷, 暫停, 繼續, 繼續修復, 取消時間限制), automatic DEBUG intake from
36
+ prompt hooks, the DEBUG-specific Stop block and the Codex `Interrupt` hook are
37
+ gone. `task debug` now fails with `TASK_DEBUG_REMOVED`.
38
+
39
+ Older state still loads: tasks keep their `debug` tag, stored budget and
40
+ hypothesis state is ignored, `originRequired` no longer blocks finish, and a
41
+ config's `features.debug` is accepted and dropped by the next `update`.
@@ -18,6 +18,11 @@ Executable acceptance MUST bind the current contract to immutable replay evidenc
18
18
  build and test build. Tasks provide stable check IDs and explicit committed
19
19
  test/fixture/helper materials. Each checkout installs and builds its own version
20
20
  before candidate materials are overlaid. Tasks cannot override runner commands.
21
+ - A generic runner must emit every `checkId` requested by criteria sharing its
22
+ runner, baseline and materials, each exactly once; missing or duplicate rows are
23
+ UNKNOWN. Other rows are ignored, so a binding may list only its red checks. A
24
+ failing unrequested row still disagrees with a PASS aggregate through the
25
+ runner's exit code, which makes the candidate UNKNOWN, never green.
21
26
  - Fixture, collection, build, timeout, cancellation, truncated output, missing or
22
27
  duplicate IDs, retries and skips MUST NOT establish red or green. Complete raw
23
28
  execution artifacts are digest-bound to the contract, materials and commits.
@@ -30,9 +35,15 @@ Executable acceptance MUST bind the current contract to immutable replay evidenc
30
35
  counters and cannot supply mechanical proof by itself. Pytest requires one
31
36
  ordered setup/call/teardown lifecycle per nodeid; the Rust protocol requires
32
37
  explicit attempts. Missing metadata MUST NOT default to a successful attempt.
33
- - Baselines are immutable creation commits, or failed candidates for finding pins.
34
- Revise/replan preserve the original goal, every mapped requirement and previous
35
- contracts/evidence. New contracts require new proof and both fresh reviews.
38
+ - Baselines are creation commits, or failed candidates for finding pins.
39
+ `task revise --baseline <ref>` moves every typed criterion's baseline (and the
40
+ task's creation commit) at once to a commit that is an ancestor of HEAD, for example after a task was opened on the
41
+ wrong branch, and voids its verification. Revise/replan preserve the original
42
+ goal, every mapped requirement and previous contracts/evidence.
43
+ - Verification evidence binds an execution hash of the criteria only. A revise
44
+ that changes the surface or origin keeps it; a criteria or configuration change
45
+ voids it. Evidence from before 0.11 bound the full contract hash and still
46
+ matches an unchanged contract. Every new contract needs both fresh reviews.
36
47
  - `task pin-finding` validates saved report digest/index provenance. Recurrence
37
48
  explicitly names an existing pin. A sixth criterion returns a replan obligation
38
49
  without changing state; the mapped replan must retain the pin and all requirements.
@@ -72,7 +83,7 @@ Each child worktree MUST record its modification intent before editing.
72
83
 
73
84
  Every new task MUST record a surface audit of where else its change lands before writing criteria, and review MUST NOT run while discovery finds an unclassified place.
74
85
 
75
- - Trigger: Creating a task (`task create`, a run plan, or before a DEBUG task's first repair), revising its surface, or reviewing it.
86
+ - Trigger: Creating a task (`task create`, including `--debug`, or a run plan), revising its surface, or reviewing it.
76
87
  - Action: Search four axes with recorded fixed-string queries or `n/a: reason`, classify every hit as included, excluded (glob + reason) or UNKNOWN, give every surface row an observable `behavior`, and declare each shared contract compatible or breaking. Pass it with `task create|revise --surface-file <json>`.
77
88
  - Evidence: The surface is stored on the task, bound into its contract hash with revision history, replayed by `git grep -F` before review, and handed to both reviewers under the `surface-coverage` criterion.
78
89
  - Positive: `A diff token hits three copy-pasted sibling pages; the audit includes them with their behavior before review runs.`
@@ -114,8 +125,11 @@ Every new task MUST record a surface audit of where else its change lands before
114
125
  dismissals. Reviewers see each dismissal with its hit count, flagged when it
115
126
  hid a file an earlier `SURFACE_UNCLASSIFIED` block named.
116
127
  Results are cached by HEAD, base, diff, query set and config hash.
128
+ - `verify` runs the same gate after verification and prints its result as
129
+ advisory lines (`Surface: PASS`, or the code and unclassified paths), so the
130
+ surface is fixed before review; only review enforces it.
117
131
  - Review returns NOT_RUN with: `SURFACE_MISSING` (no or unparseable surface;
118
- also refused at create for non-DEBUG tasks), `SURFACE_UNCLASSIFIED`,
132
+ also refused at create), `SURFACE_UNCLASSIFIED`,
119
133
  `SURFACE_QUERY_TOO_BROAD` (one recorded query over 200 files),
120
134
  `SURFACE_EXCLUSION_TOO_BROAD` (one glob over 10 files, or any file in the
121
135
  diff), `SURFACE_DISMISSAL_TOO_BROAD` (over 128 dismissals),
@@ -133,17 +147,15 @@ Every new task MUST record a surface audit of where else its change lands before
133
147
 
134
148
  ## EVIDENCE-ESCAPE-001
135
149
 
136
- Every DEBUG fix MUST declare where its bug came from before review, and a declared escape MUST be linked, labelled and recorded mechanically.
150
+ A bug fix SHOULD declare where its bug came from when known, and a declared escape MUST be linked, labelled and recorded mechanically. The declaration is advisory: it never blocks finish.
137
151
 
138
- - Trigger: A DEBUG hypothesis is confirmed, or a normal task fixes a bug that passed earlier gates.
139
- - Action: Declare `origin` with `task debug --debug-action origin --payload-file <json>`: `{"kind": "escape-of", "commit": "<commit>", "label": "<label>"}` (optional `"receipt"`), or `{"kind": "pre-existing" | "external", "reason": "..."}`. A normal task may opt in with `task create|revise --escape-of <commit> --escape-label <label> [--escape-receipt <id>]`. Commit the `.agent-ops-escapes/<task-id>.json` record with the fix.
140
- - Evidence: `origin` is bound into the task contract hash; finish, `task complete` and the completion gate refuse a DEBUG task created after this rule without it as `ESCAPE_ORIGIN_MISSING`; both reviewers receive the link state, labels, facts and residual risks under the `escape-label` criterion.
141
- - Positive: `Hypothesis confirmed; origin escape-of 864dbbe2 label surface; replay marks the missed page surface-unseen; the record is committed with the fix.`
142
- - Negative: `Finish a DEBUG fix without an origin, or relabel a surface-excluded miss as review because the reviewer "should have noticed".`
152
+ - Trigger: A DEBUG task (`task create --debug`) or any task fixes a bug that passed earlier gates and its origin is known.
153
+ - Action: Declare `origin` with `task create|revise --escape-of <commit> --escape-label <label> [--escape-receipt <id>]`, the same for DEBUG and normal tasks. `pre-existing` and `external` origins (with a `reason`) recorded by 0.10 `task debug` still load; an undeclared origin is counted as such. Commit the `.agent-ops-escapes/<task-id>.json` record with the fix.
154
+ - Evidence: `origin` is bound into the task contract hash; both reviewers receive the link state, labels, facts and residual risks under the `escape-label` criterion. A task without an origin still finishes; 0.10 tasks marked `originRequired` are no longer refused (`ESCAPE_ORIGIN_MISSING` was removed in 0.11.0).
155
+ - Positive: `Regression red at the baseline, green on the fix; origin escape-of 864dbbe2 label surface; replay marks the missed page surface-unseen; the record is committed with the fix.`
156
+ - Negative: `Relabel a surface-excluded miss as review because the reviewer "should have noticed".`
143
157
 
144
- - The declaration comes after a confirmed hypothesis (`ESCAPE_ORIGIN_EARLY`
145
- otherwise), inside the DEBUG budget. It is a contract revision: re-verify,
146
- re-record the confirmed hypothesis with the new evidence, then review.
158
+ - The declaration is a contract revision: re-verify, then review.
147
159
  Re-declaring replaces the record. The output lists `git blame` hint commits
148
160
  for lines the fix changed or removed; blame is a hint only, because an
149
161
  omission bug lives in lines nobody wrote.
@@ -177,13 +189,13 @@ Every DEBUG fix MUST declare where its bug came from before review, and a declar
177
189
 
178
190
  ## EVIDENCE-ESCAPE-002
179
191
 
180
- A surface escape MUST become a proven, tracked rule before its fix finishes, and learned rules MUST only tighten the surface gate.
192
+ A surface escape SHOULD become a proven, tracked rule, and learned rules MUST only tighten the surface gate. The proof is advisory: it never blocks finish.
181
193
 
182
194
  - Trigger: A declared escape-of origin (EVIDENCE-ESCAPE-001), or a past escape backfilled with `task create --escape-of <commit> --escape-label <label> --escape-fix <fix-commit>`.
183
- - Action: For a `surface`, `surface-unseen` or `surface-excluded` label, commit a rule `.agent-ops-escapes/rules/<rule-id>.json` shaped `{"id", "escape", "label", "trigger": {"paths", "tokens"}, "expand": {"paths", "queries"}, "noExclude"}` and re-declare the origin. For `criteria` or `verify`, name the fixing task's red-to-green check with `--escape-promote <runnerId:checkId>` (DEBUG payload `"promote"`). Other labels record a lesson.
184
- - Evidence: Finish, `task complete` and the completion gate re-run the proof and refuse `ESCAPE_RULE_UNPROVEN`, `ESCAPE_RULE_TOO_BROAD` or `SURFACE_BUDGET_EXCEEDED`; the ledger record stores the proving rule, its content hash and its backtest fires, commits and rate.
195
+ - Action: For a `surface`, `surface-unseen` or `surface-excluded` label, commit a rule `.agent-ops-escapes/rules/<rule-id>.json` shaped `{"id", "escape", "label", "trigger": {"paths", "tokens"}, "expand": {"paths", "queries"}, "noExclude"}` and re-declare the origin. For `criteria` or `verify`, name the fixing task's red-to-green check with `--escape-promote <runnerId:checkId>` (origin field `"promote"`). Other labels record a lesson.
196
+ - Evidence: Declaring the origin runs the proof and prints `ESCAPE_RULE_UNPROVEN`, `ESCAPE_RULE_TOO_BROAD` or `SURFACE_BUDGET_EXCEEDED` when it fails; since 0.11.0 finish no longer refuses them. The ledger record stores the proving rule, its content hash and its backtest fires, commits and rate.
185
197
  - Positive: `Escape surface-unseen; rule image-size-siblings fires on the escaped commit, its query hits both missed sibling pages there, and fires on 2 of the last 200 commits.`
186
- - Negative: `Finish a surface escape whose rule never fires on the escaped commit, or add a rule field that excludes paths.`
198
+ - Negative: `Report a surface escape as proven when its rule never fires on the escaped commit, or add a rule field that excludes paths.`
187
199
 
188
200
  - Rules are data only and need no trust: triggers and expands become argv
189
201
  `git grep -F` queries and path globs, never shell or regex. The strict schema
@@ -253,7 +265,7 @@ New verification evidence uses schema 3. Schema 2 remains readable and its exit-
253
265
 
254
266
  Existing task files remain readable without migration. Legacy tasks without a config baseline, arbitrary evidence references, or unfinished archived children must be recreated and verified/reviewed before completion. Repeating completion also revalidates the evidence; an old completed status alone is insufficient. Runtime callers must supply `TaskServiceOptions.completion`; omitting this repository context fails closed for completion while leaving read-only task operations available.
255
267
 
256
- Before committing, use the default worktree scope for verify, review and completion. After committing, use the same `--base <git-ref>` on all three commands to produce fresh proof for that committed range; `TaskServiceOptions.completion.base` selects it for runtime callers. Base mode requires a clean worktree. Without a worktree change surface or an explicit base, completion returns `TASK_COMPLETION_SCOPE_REQUIRED`. The agy Stop gate still checks worktree-scoped proof: complete and stop before committing, or use its user-approved one-time permit after inspecting a completed base-scoped task.
268
+ Before committing, use the default worktree scope for verify, review and completion. After committing, use the same `--base <git-ref>` on all three commands to produce fresh proof for that committed range. When `--base` is absent and the tree is clean, verify and review choose it: a session worktree uses its merge-base with the target branch (which follows a finish rebase), elsewhere the task's creation commit when it is an ancestor of HEAD. Base-mode source fingerprints ignore escape-ledger task records (`.agent-ops-escapes/task-*.json`; rules stay fingerprinted), so committing the ledger keeps verification and review current; fingerprints from 0.10 differ, so re-verify once after upgrading; `TaskServiceOptions.completion.base` selects it for runtime callers. Base mode requires a clean worktree. Without a worktree change surface or an explicit base, completion returns `TASK_COMPLETION_SCOPE_REQUIRED`. The agy Stop gate still checks worktree-scoped proof: complete and stop before committing, or use its user-approved one-time permit after inspecting a completed base-scoped task.
257
269
 
258
270
  This enforces the toolkit's completion command, not a host's natural-language completion claim. It does not prevent a process with the same filesystem authority from editing task/evidence files directly, and it does not lock Git or external source writers.
259
271
 
@@ -109,7 +109,7 @@ The current registration matrix is intentionally asymmetric:
109
109
  | office-presence (Preview) | degraded | degraded | supported | degraded |
110
110
  | lifecycle-summary | degraded | supported | supported | degraded |
111
111
  | command-policy | supported | unknown | supported | supported |
112
- | completion-gate | supported | unsupported | unsupported | unsupported |
112
+ | completion-gate | supported | unsupported | supported | unsupported |
113
113
  | optional-stop-verify | degraded | unsupported | supported | degraded |
114
114
 
115
115
  For runtime-failure handling, only `command-policy` is fail-closed. Claude
@@ -118,17 +118,12 @@ installed configuration; the managed OpenCode `tool.execute.before` plugin can
118
118
  throw its documented denial or unavailable-runtime error for its supported Bash
119
119
  surface. Codex remains `unknown` and never emits a denial. Fixture tests assert
120
120
  these wire and plugin shapes only; they do not prove that a host honors a
121
- denial. `SessionStart` and ordinary `Stop` failures remain fail-open. Active
122
- DEBUG Stop faults instead retry one targeted reload, then explicitly report
123
- UNKNOWN/incomplete and preserve the original state before non-success Stop.
124
-
125
- Codex DEBUG lifecycle semantics were rechecked on 2026-10-11 against the
126
- [official hooks reference](https://learn.chatgpt.com/docs/hooks#stop): Stop
127
- `decision: "block"` with `reason` schedules a continuation; `continue: false`
128
- halts it. `stop_hook_active` identifies a prior continuation and cannot waive
129
- the DEBUG check. Native `Interrupt` pauses with a three-second timeout and
130
- never blocks or restarts the human interruption. This DEBUG-specific policy
131
- does not enable Codex's generic completion gate or optional Stop verifier.
121
+ denial. `SessionStart` and `Stop` failures remain fail-open.
122
+
123
+ Since 0.11.0 no hook is DEBUG-specific: prompts never open DEBUG tasks, Stop
124
+ never holds a session for one, and Codex `Interrupt` is no longer registered
125
+ (a stale registration from an older install is a no-op until `update`). Codex
126
+ still has no generic completion gate or optional Stop verifier.
132
127
  Codex separately trusts each exact native hook definition. After managed hook
133
128
  updates, review new or changed definitions in `/hooks`; agent-ops repository
134
129
  trust alone does not make an unreviewed native hook active.
@@ -191,6 +186,34 @@ removes only `run` and keeps `loop`.
191
186
  - Positive: `A Claude Code session with the run profile writes .agent-ops/state/run-goal.md in the main checkout and starts agent-ops run --host claude --wait in the background.`
192
187
  - Negative: `Split an eight-criteria change into subtasks while the run profile is active, add auto-run text to GEMINI.md, or resume a blocked run without the user.`
193
188
 
189
+ `run status` includes `recovery` in JSON and the same guidance in text: phase
190
+ (unknown for legacy records), original bounded redacted diagnostic, sealed proof
191
+ (`recorded-unchecked` is an observation, not validation), cleanup state,
192
+ resumability and concrete remediation. An unchanged cleanup failure retains its
193
+ original cause. Trust, native identity, generation and denial failures remain
194
+ fail-closed; a sealed proof never erases a native or organization denial.
195
+ The JSON `state` of `run status` and `run logs` omits the event history and goal
196
+ text, keeping `eventCount` and `goalHash`, so repeated polling stays small;
197
+ `run logs` returns the events themselves.
198
+
199
+ Manual resume of a receipt-bound integration validates the exact sealed proof,
200
+ receipt digest and transaction, owner/generation, candidate/target ancestry and
201
+ Git note before cleanup. It executes only missing note, gate, trust and checkout
202
+ cleanup steps; it preserves existing receipt bytes and completed task/proof work.
203
+ A missing unrecorded note may be bound to the sealed receipt; a missing or changed
204
+ recorded note blocks. Completed cleanup requires the owned checkouts to be gone.
205
+ The target is never moved again. A changed target is accepted only as a descendant
206
+ of the receipt-bound candidate with recorded integration history.
207
+
208
+ Cleanup records a bounded redacted original failure and a retry-input digest of
209
+ the transaction boundary, checkout status, untracked file metadata and heartbeat
210
+ liveness. Identical inputs return `RUN_CLEANUP_UNCHANGED` before repeating cleanup;
211
+ a remediation delta permits a fresh attempt after all safety checks. This digest
212
+ is a retry guard, not verification reuse or new authority. Finalization failure
213
+ does not immediately replay the failed integration: it preserves the original
214
+ cause for manual recovery. Live/unknown/forged/symlink heartbeats and unrelated
215
+ user files retain the existing non-force removal protections.
216
+
194
217
  ## HARNESS-ADAPTER-008
195
218
 
196
219
  `agent-ops office` (Preview) MUST show progress read-only from agent-ops state alone. The
@@ -14,8 +14,12 @@
14
14
  goals. Same-host writers use isolated worktrees and current generation leases;
15
15
  the coordinator counts toward the maximum two writers. Dependencies become
16
16
  available only through frozen deliveries; child baselines follow those commits.
17
- - The default 60-minute budget counts the union of active intervals, including
18
- setup, proof, review and integration. Resume keeps elapsed time and usage epochs.
17
+ - New runs have no total time cap (`budget.limitMs: null`). Active interval unions
18
+ still measure setup, proof, review and integration. Legacy finite runs upgrade
19
+ only on manual resume, retaining the old limit, intervals, elapsed time, usage
20
+ epochs and blocker history. Reads and installation never upgrade or awaken runs.
21
+ Command/review timeouts, provider quotas and no-progress/stop
22
+ controls remain independent and effective. Explicit --time-budget is rejected.
19
23
  Missing counters remain UNKNOWN; partial usage is not a complete cost estimate.
20
24
  - Questions pause work and require an explicit answer. Repair preserves the goal
21
25
  and records failures; two identical rounds without progress stop that worker
@@ -38,17 +42,47 @@
38
42
  setup requires explicit resume and retains its checkout and failure artifact.
39
43
  - A coordinator may assess additional fixed non-dangerous capabilities only under
40
44
  a run-scoped policy bound to the original repository trust, executable runtime
41
- and remaining budget. Explicit native or organization denial cannot be bypassed.
45
+ and a finite one-hour authorization window. Explicit native or organization denial cannot be bypassed.
42
46
  Policy changes fence all writers, preserve frozen deliveries and journal contract
43
47
  synchronization before new generations acquire leases. This never grants global
44
48
  repository trust. Native decisions retain redacted command scope and rationale;
45
49
  absent provider evidence remains UNKNOWN.
46
- Explicit resume renews expired authorization from the remaining budget and
47
- reconciles immutable renewal lineage before policy synchronization. An answer
48
- uses the same recovery checks; neither action can revive an explicit denial.
50
+ Active execution automatically renews an expired grant only when the original
51
+ repository trust, config, executable runtime and operation scope still match.
52
+ Renewal is digest-bound to its predecessor, preserves assessments, rejects
53
+ invalid/backward clocks, and loses to concurrent stop, denial or scope changes.
54
+ Changed/revoked authority requires genuine authorization through the existing
55
+ trust/resume process; renewal never grants permanent trust or clears denial.
56
+ Explicit resume reconciles immutable renewal lineage before policy synchronization.
57
+ An answer uses the same recovery checks; neither action can revive an explicit denial.
58
+ `run resume <id> --retry-approval <auth-event-id>` MAY explicitly retry a
59
+ Codex automatic approval review that failed with its usage-limit wrapper.
60
+ Each selected failure MUST retain its original private artifact, digest,
61
+ worker identity and policy lineage; unrelated or genuine denials still block.
62
+ Repeat the flag for multiple failures. Successful acknowledgements are audited
63
+ and revalidated on later resumes. This grants no command permission: native
64
+ approval runs again. Existing writer-death, checkout, trust and budget checks apply.
65
+ Initial recovery after a current manual resume MAY ignore an owned Codex limit
66
+ snapshot received before activation whose native update second strictly predates
67
+ that resume. Automatic restarts, unknown/equal/future timestamps, clock rollback,
68
+ and every limit received after activation starts remain authoritative. Native
69
+ activation MUST acknowledge an active goal before starting or steering a turn.
70
+ Manual resume releases derivative `RUN_POLICY_DISABLED` task blocks while
71
+ preserving IDs, accounting, history and unrelated product failures.
49
72
  - Convergence compares actual per-check statuses and outstanding finding pins.
50
73
  Source fingerprints, timing and diagnostics alone cannot establish progress.
51
74
 
75
+ For any `jobs` value, the coordinator MUST yield only through an explicit
76
+ `action=wait` request sent after it has planned its children; the supervisor
77
+ never stops a coordinator that is still planning. A wait confirms coordinator
78
+ process death, frees its slot and drops its native thread, so the coordinator does
79
+ not poll `run status` while children work. Recovery leaves a waiting coordinator
80
+ stopped; once every child is delivered, complete or blocked, it restarts under a
81
+ new generation in a fresh native session whose instructions list each child's
82
+ status and delivered commit. With `jobs=1`, child execution MUST wait for that
83
+ confirmed death. Native registration, recovery and start MUST enforce at most
84
+ `jobs` active agents; changing task slot accounting alone is insufficient.
85
+
52
86
  This module defines the bounded loop used to plan, implement, verify, and hand off work.
53
87
 
54
88
  ## LOOP-START-001
@@ -10,6 +10,8 @@ An independent reviewer MUST receive a minimal packet containing the request, cr
10
10
  - Positive: `Packet contains recorded task intent, criteria, files, and evidence requirements.`
11
11
  - Negative: `Forward the complete session transcript and environment.`
12
12
 
13
+ Large surface audits, including complete revision history, discovery and post-block exclusions, may use a digest-bound reference to an exact normalized match in the validated snapshot contract manifest. Both review rounds must read the complete manifest surface. The 64 KiB inline packet and 512 KiB manifest bounds remain enforced; small and legacy packets retain inline data.
14
+
13
15
  ## REVIEW-RESULT-001
14
16
 
15
17
  A review result MUST preserve PASS, FAIL, or NOT_RUN and MUST NOT convert NOT_RUN into PASS.
@@ -57,6 +59,10 @@ Raw reviewer output remains bounded and unstreamed. SIGINT or SIGTERM aborts
57
59
  the active process tree without fallback or attestation; timeout remains a
58
60
  distinct NOT_RUN reason rather than being flattened to `missing-cli`.
59
61
 
62
+ agy may remain silent throughout a generation. Its review and resumed answer
63
+ MUST NOT be cancelled solely for missing output; the configured round timeout
64
+ and caller cancellation remain effective.
65
+
60
66
  ## REVIEW-CHAIN-001
61
67
 
62
68
  The two planned sessions MUST be ordered as a necessary review followed by an
@@ -236,7 +236,7 @@ fingerprint,因此兩個對話修改同一個 checkout 會互相作廢對方
236
236
  詢問一次。
237
237
  - 在 worktree 裡對每個 task 執行 verify 與 review,但不要執行 `task complete`
238
238
  (Claude Code 在隔離的 worktree session 中會拒絕它)。`agent-ops worktree finish
239
- <name>` 會在任何 rebase 之前 complete worktree 內每個未封存的 task,先 subtask
239
+ <name>` 會在合併之前 complete worktree 內每個未封存的 task,先 subtask
240
240
  後 parent,各自使用其 PASS review 記錄的 base(沒有記錄時使用 worktree 的 base)。
241
241
  任一 task 無法完成時不會合併,錯誤訊息會指出是哪個 task。建立 subtask 時 session
242
242
  維持附著在 task 樹最上層,且每個 task 各自保留 review 紀錄,所以在同一份原始碼上
@@ -254,8 +254,11 @@ fingerprint,因此兩個對話修改同一個 checkout 會互相作廢對方
254
254
  finish。主 checkout 就在 target branch 上時,合併會更新它的檔案,所以那裡有未
255
255
  commit 的變更會擋住合併;主 checkout 在其他 branch 或 detached 時,只移動
256
256
  target 的 ref,checkout、檔案與未 commit 的變更都不會被動到。Target 若被其他
257
- worktree checkout 則拒絕,並指出該路徑。Target 若已前進會先 rebase;沒有衝突且自身 patch 不變的 rebase 會先
258
- 重新驗證再合併;衝突則連同先合併那份工作在 `refs/notes/agent-ops` 的意圖一起
257
+ worktree checkout 則拒絕,並指出該路徑。Target 若已前進,會 rebase worktree 後以
258
+ `WORKTREE_REBASED` 停下,不 complete 任何 task:先前的證據涵蓋的是舊 base,
259
+ 不是即將合併的組合。以印出的 `--base` 重新 verify 與 review,再執行一次 finish;
260
+ 已 complete 的 task 不能再記錄證據,需以 follow-up task 涵蓋 rebase 後的變更。
261
+ 衝突則重設並連同先合併那份工作在 `refs/notes/agent-ops` 的意圖一起
259
262
  回報。Note 會記錄 worktree 的每個 task,subtask 縮排在其 parent 之下,並附上
260
263
  一行 `session: <id>`,標明完成這次 finish 的 session。Finish 也會把該 session
261
264
  的 gate baseline 重設為合併後的原始碼,所以即使 task 現在只存在於 note 裡,