@kylecheng3146/agent-ops 0.2.3 → 0.2.5

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 CHANGED
@@ -325,9 +325,11 @@ and a missing second verdict is NOT_RUN. A same-target pair is still
325
325
  independent because the sessions and clones are fresh.
326
326
 
327
327
  Host network or loopback restrictions return `REVIEW_NOT_RUN` before any
328
- reviewer is started. A trusted outer host runner may rerun the exact same
329
- command once with both capabilities; the result remains NOT_RUN if that host
330
- is unavailable. There is no automatic permission bypass inside the repository.
328
+ reviewer is started. The managed instructions require a trusted outer host
329
+ runner to start the exact same command with both capabilities on its first
330
+ invocation; an in-sandbox retry is not an elevation. The result remains
331
+ `NOT_RUN` if that host is unavailable. There is no repository-level permission
332
+ bypass.
331
333
  Reviewer attempts and preflight diagnostics remain visible in JSON. `--yes` is
332
334
  required because a complete run spends provider quota twice.
333
335
 
@@ -282,6 +282,18 @@ export function resolveHarnessSelection(value) {
282
282
  export const COMMON_AGENTS_BLOCK = DESCRIPTORS.codex.control.routing.desired;
283
283
  export const COMMON_CLAUDE_BLOCK = DESCRIPTORS.claude.control.routing.desired;
284
284
  export const COMMON_GEMINI_BLOCK = DESCRIPTORS.agy.control.routing.desired;
285
+ function subagentInstruction(descriptor) {
286
+ // ponytail: keyed by instruction file, not harness id — codex and opencode
287
+ // share .agent-ops/AGENTS.md and install dedupe requires identical content.
288
+ switch (descriptor.control.instructionFile) {
289
+ case "CLAUDE.md":
290
+ return "Delegate it with the Task tool.";
291
+ case "GEMINI.md":
292
+ return "Delegate it with `invoke_subagent`: `research` for read-only scans, `self` for a bounded edit.";
293
+ default:
294
+ return "Delegate it with this harness's subagent or task tool when it has one; otherwise run the same bounded steps sequentially in this session.";
295
+ }
296
+ }
285
297
  export function managedRules(descriptor, context) {
286
298
  const lines = [
287
299
  "# Loop Engineering",
@@ -296,10 +308,10 @@ export function managedRules(descriptor, context) {
296
308
  ""
297
309
  ];
298
310
  if (context.capabilities.includes("rules")) {
299
- lines.push("For every change:", "", "1. Define two to five mechanically verifiable acceptance criteria.", "2. Inspect the smallest relevant scope and preserve unrelated changes.", "3. Apply the smallest safe change.", "4. Run evidence-producing verification for every criterion.", "5. Obtain complete independent review before claiming completion, via", " `agent-ops review --task <task-id> --yes` (or the CLI's equivalent invocation).", " Never call a", " review-target CLI (agy, codex, claude) directly — direct calls skip", " the enforced read-only sandbox flags and can hang or fail on command", " permission prompts.", " Review runs exactly two fresh sessions: with three configured targets,", " set `AGENT_OPS_HOST` to the current CLI id so it is excluded; with two", " targets both run in configured order; with one target it runs twice.", " The first session is necessary; a PASS then requires an adversarial", " re-check carrying the first report. A first FAIL or NOT_RUN stops.", "", "Treat `.agent-ops/config.json` as verifier authority. Discovery output is", "only a proposal until a user confirms it. Repository commands require an", "exact matching trust record. Confirmed project init/update grants it", "automatically when verification commands are configured.", "");
311
+ lines.push("For every change:", "", "1. Define two to five mechanically verifiable acceptance criteria.", "2. Inspect the smallest relevant scope and preserve unrelated changes.", "3. Apply the smallest safe change.", "4. Run evidence-producing verification for every criterion.", "5. Obtain complete independent review before claiming completion, via", " `agent-ops review --task <task-id> --yes` (or the CLI's equivalent invocation).", " Never call a", " review-target CLI (agy, codex, claude) directly — direct calls skip", " the enforced read-only sandbox flags and can hang or fail on command", " permission prompts.", " Start this command through the trusted outer host runner as its first", " and only invocation. On Codex, the outer tool request must use", " `sandbox_permissions: \"require_escalated\"` so network and loopback", " are available; in that same request, unset", " `CODEX_SANDBOX_NETWORK_DISABLED` and set `AGENT_OPS_HOST` when three", " targets are configured. The Codex shell form is", " `env -u CODEX_SANDBOX_NETWORK_DISABLED AGENT_OPS_HOST=<current-host> agent-ops review --task <task-id> --yes`.", " Do not run it once in the restricted sandbox and retry; changing the", " variable inside that sandbox is not elevation.", " Review runs exactly two fresh sessions: with three configured targets,", " set `AGENT_OPS_HOST` to the current CLI id so it is excluded; with two", " targets both run in configured order; with one target it runs twice.", " The first session is necessary; a PASS then requires an adversarial", " re-check carrying the first report. A first FAIL or NOT_RUN stops.", "", "Treat `.agent-ops/config.json` as verifier authority. Discovery output is", "only a proposal until a user confirms it. Repository commands require an", "exact matching trust record. Confirmed project init/update grants it", "automatically when verification commands are configured.", "");
300
312
  }
301
313
  if (context.capabilities.includes("task")) {
302
- lines.push("Split a change that exceeds five acceptance criteria into subtasks:", "`agent-ops task create --parent <task-id>` records one, and", "`agent-ops task status --parent <task-id>` lists them. Each subtask", "carries its own criteria, verification, and independent review;", "completing one never completes its parent.", "");
314
+ lines.push("Split a change that exceeds five acceptance criteria into subtasks:", "`agent-ops task create --parent <task-id>` records one, and", "`agent-ops task status --parent <task-id>` lists them. Each subtask", "carries its own criteria, verification, and independent review;", "completing one never completes its parent.", "", "Delegate a subtask whose scope spans unknown files, broad scans, or an", "independent workstream instead of doing it inline. Name the bounded", "scope, the artifact to return, and the acceptance criteria it serves.", subagentInstruction(descriptor), "Read every returned artifact back yourself: integration, verification,", "and review stay with the coordinator.", "", "One writer at a time. `agent-ops verify` and `agent-ops review`", "fingerprint the working tree and report UNKNOWN when anything else", "writes it during the run, so delegate edits to one subagent at a time,", "or give each writer its own Git worktree and merge before verifying.", "Read-only delegation has no such limit and may run in parallel.", "");
303
315
  }
304
316
  if (context.capabilities.includes("lifecycle-summary")) {
305
317
  lines.push("Advisory lifecycle summaries and local logs are informational. Advisory", "failures must remain fail-open and cannot become verification evidence.", "");
@@ -90,8 +90,9 @@ export function renderReviewResult(result) {
90
90
  lines.push(`Run: ${verifyCommand}, then run this review again.`);
91
91
  }
92
92
  if (result.reason === "host-required") {
93
- lines.push("No reviewer ran: the host runner must restart this exact review with " +
94
- "network and loopback permission.");
93
+ lines.push("No reviewer ran: start the outer host runner before the first invocation " +
94
+ "and run this exact review with network and loopback permission; do not " +
95
+ "retry inside the restricted sandbox.");
95
96
  }
96
97
  if (result.reason === "host-identity-required") {
97
98
  lines.push("Three configured targets require AGENT_OPS_HOST=agy|claude|codex; " +
@@ -187,8 +187,11 @@ export class TaskService {
187
187
  const now = assertTimestamp(this.#now());
188
188
  return await this.#store.mutate((state) => {
189
189
  const record = findTask(state, taskId);
190
- if (record.status !== "active") {
191
- throw taskError("TASK_NOT_ACTIVE", "Only an active task can be attached to a session.");
190
+ // A completed task still accepts attachment: the completion gate wants
191
+ // the session bound to a completed task, so refusing here would make
192
+ // "complete, then attach" an unrecoverable order.
193
+ if (record.status === "archived") {
194
+ throw taskError("TASK_NOT_ACTIVE", "An archived task cannot be attached to a session.");
192
195
  }
193
196
  const currentIndex = state.sessions.findIndex((attachment) => attachment.sessionId === sessionId);
194
197
  const attachment = { sessionId, taskId, attachedAt: now };
@@ -93,10 +93,11 @@ would consume the following flag instead. It deliberately does not pass
93
93
  `--disable-slash-commands`, which disables plan-mode behavior.
94
94
 
95
95
  Host network or loopback restrictions return `REVIEW_NOT_RUN` before any
96
- reviewer is started. A trusted outer host runner may rerun the exact same
97
- command once with both capabilities; an in-sandbox retry is not an elevation
98
- and cannot produce a PASS. Every attempt, preflight result, and diagnostic is
99
- preserved in human and JSON output.
96
+ reviewer is started. The managed instructions require a trusted outer host
97
+ runner to start the exact same command with both capabilities on its first
98
+ invocation; an in-sandbox retry is not an elevation and cannot produce a PASS.
99
+ Every attempt, preflight result, and diagnostic is preserved in human and JSON
100
+ output.
100
101
 
101
102
  Capability checks and model starts are reported on stderr, including under
102
103
  `--json`; stdout remains one final JSON envelope and raw reviewer output is
@@ -19,3 +19,13 @@ The coordinator MUST retain ownership of final integration and verification.
19
19
  - Evidence: The coordinator records the final command output.
20
20
  - Positive: `Reviewer reports PASS; coordinator reruns typecheck and tests.`
21
21
  - Negative: `Accept the delegated claim without inspecting the diff.`
22
+
23
+ ## DELEGATE-ISOLATION-001
24
+
25
+ Concurrent delegated writers MUST NOT share one working tree.
26
+
27
+ - Trigger: More than one delegated agent would edit files for the same task.
28
+ - Action: Run delegated edits one at a time, or give each writer its own Git worktree and merge before verification.
29
+ - Evidence: `agent-ops verify` returns a status other than `UNKNOWN` for the run.
30
+ - Positive: `Read-only scans run in parallel; the single edit runs in the coordinator worktree.`
31
+ - Negative: `Two subagents edit the same files while verification runs.`
@@ -93,9 +93,10 @@ before any reviewer invocation.
93
93
  - Trigger: The host declares disabled network or the loopback probe fails.
94
94
  - Action: Return `REVIEW_NOT_RUN / host-required` with the host restriction.
95
95
  - Evidence: `attempts` is empty and no target preflight or reviewer process ran.
96
- - Positive: A trusted outer host runner can retry the exact command once with both capabilities.
96
+ - Positive: A trusted outer host runner starts the exact command once with both capabilities before any reviewer invocation.
97
97
  - Negative: Treat a child login error as proof that an authenticated reviewer is unavailable.
98
98
 
99
+ The managed host instructions require this handoff before the first command.
99
100
  There is no repository-level permission bypass. An unavailable outer host runner
100
101
  MUST leave the result NOT_RUN rather than manufacture PASS.
101
102
 
@@ -82,9 +82,10 @@ agent-ops 刻意不傳會繞過權限邊界的 `--dangerously-skip-permissions`
82
82
  使 plan mode 失效的 `--disable-slash-commands`。
83
83
 
84
84
  Host 缺少 network 或 loopback 權限時,會在啟動任何 reviewer 前回傳
85
- `REVIEW_NOT_RUN`。可信任的外部 host runner 可以用兩項權限重跑同一個完整
86
- 指令一次;在原 sandbox 內重試不算升權,也不能產生 PASS。文字與 JSON 輸出
87
- 都會保留每次 attempt、preflight 與 diagnostic。
85
+ `REVIEW_NOT_RUN`。Managed 規則要求可信任的外部 host runner 在第一次呼叫時
86
+ 就用兩項權限啟動同一個完整指令;不要先在原 sandbox 執行再重試,因為那不算
87
+ 升權,也不能產生 PASS。文字與 JSON 輸出都會保留每次 attempt、preflight 與
88
+ diagnostic。
88
89
 
89
90
  Capability check 與模型啟動進度都寫到 stderr,包括 `--json` 模式;stdout
90
91
  仍只有最終 JSON envelope,且不會串流 reviewer 原始輸出。SIGINT 或 SIGTERM
@@ -21,3 +21,13 @@ English source version: 2026-07-23. Revalidate: when the English specification c
21
21
  - Evidence: 協調者記錄最終命令輸出。
22
22
  - Positive: `審查者回傳 PASS;協調者重新跑 typecheck 與測試。`
23
23
  - Negative: `不看 diff 就接受委派者的完成宣告。`
24
+
25
+ ## DELEGATE-ISOLATION-001
26
+
27
+ 並行的委派寫入者 MUST NOT 共用同一個工作區。
28
+
29
+ - Trigger: 同一任務中有超過一個委派 agent 會修改檔案。
30
+ - Action: 讓委派的修改依序進行,或為每個寫入者配置獨立 Git worktree,合併後再驗證。
31
+ - Evidence: `agent-ops verify` 該次執行回傳非 `UNKNOWN` 的狀態。
32
+ - Positive: `唯讀掃描並行執行;唯一的修改在協調者工作區進行。`
33
+ - Negative: `兩個 subagent 在驗證執行期間修改相同檔案。`
@@ -86,11 +86,12 @@ fail closed。
86
86
  - Trigger: host 宣告 network disabled 或 loopback probe 失敗。
87
87
  - Action: 回傳 `REVIEW_NOT_RUN / host-required` 與 host restriction。
88
88
  - Evidence: `attempts` 為空,沒有 target preflight 或 reviewer process 執行。
89
- - Positive: 可信任的外部 host runner 可在具兩項能力的主機重跑同一指令一次。
89
+ - Positive: 可信任的外部 host runner 在任何 reviewer invocation 前,以兩項能力啟動同一指令一次。
90
90
  - Negative: 把 child login error 當作 authenticated reviewer 不可用的證明。
91
91
 
92
- repository 不提供 permission bypass。外部 host runner 不可用時,結果 MUST 保持
93
- NOT_RUN,不得製造 PASS。
92
+ Managed host 規則要求在第一次呼叫前完成這個 handoff。repository 不提供
93
+ permission bypass。外部 host runner 不可用時,結果 MUST 保持 NOT_RUN,不得
94
+ 製造 PASS。
94
95
 
95
96
  ## REVIEW-EVIDENCE-001
96
97
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kylecheng3146/agent-ops",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Evidence-driven development loops for agy, Codex, Claude Code, and opencode",
5
5
  "type": "module",
6
6
  "license": "MIT",