@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.
- package/README.md +3 -2
- package/dist/packages/cli/src/args.js +18 -53
- package/dist/packages/cli/src/bin.js +28 -29
- package/dist/packages/cli/src/cli.js +25 -17
- package/dist/packages/cli/src/codex-loop-process.js +0 -6
- package/dist/packages/cli/src/commands/advance.js +2 -1
- package/dist/packages/cli/src/commands/parallel.js +1 -1
- package/dist/packages/cli/src/commands/review.js +8 -11
- package/dist/packages/cli/src/commands/run.js +12 -3
- package/dist/packages/cli/src/commands/task.js +6 -50
- package/dist/packages/cli/src/commands/verify.js +7 -3
- package/dist/packages/cli/src/context.js +22 -4
- package/dist/packages/cli/src/default-base.js +26 -0
- package/dist/packages/cli/src/hook-process.js +19 -83
- package/dist/packages/cli/src/office-entry.js +8 -4
- package/dist/packages/cli/src/owned-run-step.js +4 -4
- package/dist/packages/cli/src/parallel-deps.js +0 -2
- package/dist/packages/cli/src/run-deps.js +12 -9
- package/dist/packages/cli/src/run-entry.js +123 -19
- package/dist/packages/cli/src/run-setup-entry.js +2 -2
- package/dist/runtime/src/adapters/agy/config.js +2 -3
- package/dist/runtime/src/adapters/claude/config.js +2 -2
- package/dist/runtime/src/adapters/codex/config.js +2 -5
- package/dist/runtime/src/hooks/completion-gate.js +0 -15
- package/dist/runtime/src/install/harness.js +7 -4
- package/dist/runtime/src/install/plan.js +3 -3
- package/dist/runtime/src/install/profiles.js +0 -2
- package/dist/runtime/src/office/scene.js +1 -1
- package/dist/runtime/src/office/server.js +43 -16
- package/dist/runtime/src/office/snapshot.js +5 -2
- package/dist/runtime/src/parallel/finish.js +139 -65
- package/dist/runtime/src/parallel/manage.js +0 -3
- package/dist/runtime/src/parallel/service.js +5 -1
- package/dist/runtime/src/review/execute.js +77 -11
- package/dist/runtime/src/review/packet.js +17 -6
- package/dist/runtime/src/review/runner.js +2 -0
- package/dist/runtime/src/run/controls.js +99 -1
- package/dist/runtime/src/run/hosts/codex.js +28 -1
- package/dist/runtime/src/run/hosts/protocol.js +5 -2
- package/dist/runtime/src/run/integration.js +35 -13
- package/dist/runtime/src/run/policy.js +65 -10
- package/dist/runtime/src/run/scheduler.js +10 -5
- package/dist/runtime/src/run/service.js +68 -21
- package/dist/runtime/src/run/supervisor.js +11 -2
- package/dist/runtime/src/run/transport.js +1 -0
- package/dist/runtime/src/run/verification.js +2 -2
- package/dist/runtime/src/schema/validate.js +10 -5
- package/dist/runtime/src/security/permissions.js +85 -0
- package/dist/runtime/src/task/completion.js +4 -42
- package/dist/runtime/src/task/contract.js +11 -0
- package/dist/runtime/src/task/service.js +34 -57
- package/dist/runtime/src/task/store.js +3 -7
- package/dist/runtime/src/verify/acceptance-coverage.js +2 -3
- package/dist/runtime/src/verify/acceptance-protocol.js +4 -3
- package/dist/runtime/src/verify/acceptance-replay.js +4 -7
- package/dist/runtime/src/verify/service.js +6 -23
- package/dist/runtime/src/verify/source-fingerprint.js +17 -4
- package/docs/en/guides/configuration.md +8 -4
- package/docs/en/guides/task-debug.md +39 -121
- package/docs/en/spec/acceptance-and-evidence.md +31 -19
- package/docs/en/spec/harness-adapters.md +35 -12
- package/docs/en/spec/loop-engineering.md +40 -6
- package/docs/en/spec/review.md +6 -0
- package/docs/zh-TW/guides/configuration.md +6 -3
- package/docs/zh-TW/guides/task-debug.md +27 -66
- package/docs/zh-TW/spec/acceptance-and-evidence.md +19 -18
- package/docs/zh-TW/spec/harness-adapters.md +28 -9
- package/docs/zh-TW/spec/loop-engineering.md +14 -3
- package/docs/zh-TW/spec/review.md +5 -0
- package/package.json +1 -1
- package/schemas/config.schema.json +1 -21
- package/dist/packages/cli/src/debug-intake.js +0 -245
- package/dist/runtime/src/task/debug-intake.js +0 -15
- package/dist/runtime/src/task/debug-state.js +0 -129
- package/dist/runtime/src/task/debug-user-event.js +0 -95
- 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-
|
|
22
|
+
domain: "agent-ops-source-v2",
|
|
11
23
|
mode: scope.noChange === true ? "goal-no-change" : "base",
|
|
12
|
-
|
|
24
|
+
tree: await ledgerFreeTree(runner),
|
|
13
25
|
base: scope.resolvedBase,
|
|
14
|
-
paths:
|
|
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
|
|
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
|
|
299
|
-
|
|
300
|
-
the
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
The
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
34
|
-
|
|
35
|
-
|
|
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`,
|
|
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
|
|
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
|
-
|
|
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
|
|
139
|
-
- Action: Declare `origin` with `task
|
|
140
|
-
- Evidence: `origin` is bound into the task contract hash;
|
|
141
|
-
- Positive: `
|
|
142
|
-
- Negative: `
|
|
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
|
|
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
|
|
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>` (
|
|
184
|
-
- Evidence:
|
|
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: `
|
|
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 |
|
|
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
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
-
|
|
18
|
-
setup, proof, review and integration.
|
|
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
|
|
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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
package/docs/en/spec/review.md
CHANGED
|
@@ -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>`
|
|
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
|
|
258
|
-
|
|
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 裡,
|