@kylecheng3146/agent-ops 0.2.4 → 0.2.6
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.
|
@@ -7,6 +7,9 @@ import { collectBaseChangePaths, collectChangeSurface } from "../verify/change-s
|
|
|
7
7
|
import { calculateSourceFingerprint } from "../verify/source-fingerprint.js";
|
|
8
8
|
const FINGERPRINT = /^[a-f0-9]{64}$/u;
|
|
9
9
|
const SESSION = /^[^\0\r\n]{1,256}$/u;
|
|
10
|
+
function shellQuote(value) {
|
|
11
|
+
return `'${value.replaceAll("'", "'\"'\"'")}'`;
|
|
12
|
+
}
|
|
10
13
|
function gateResult(action, status, code, remedy) {
|
|
11
14
|
return { action, status, code, ...(remedy === undefined ? {} : { remedy }) };
|
|
12
15
|
}
|
|
@@ -142,7 +145,7 @@ export class CompletionGateService {
|
|
|
142
145
|
}
|
|
143
146
|
catch (error) {
|
|
144
147
|
return error instanceof AgentOpsError && error.code === "TASK_SESSION_UNATTACHED"
|
|
145
|
-
? gateResult("block", "FAIL", "COMPLETION_GATE_TASK_REQUIRED",
|
|
148
|
+
? gateResult("block", "FAIL", "COMPLETION_GATE_TASK_REQUIRED", `Attach this conversation to a formal task: agent-ops task create --title <title> --criterion <json> --criterion <json> (two to five criteria), then agent-ops task attach --task <task-id> --session ${shellQuote(sessionId)}.`)
|
|
146
149
|
: gateResult("block", "UNKNOWN", "COMPLETION_GATE_TASK_UNAVAILABLE", "Repair task state with agent-ops doctor before stopping.");
|
|
147
150
|
}
|
|
148
151
|
if (stored.status !== "complete") {
|
|
@@ -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",
|
|
@@ -299,7 +311,7 @@ export function managedRules(descriptor, context) {
|
|
|
299
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.", "");
|
|
@@ -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
|
-
|
|
191
|
-
|
|
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 };
|
|
@@ -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.`
|
|
@@ -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 在驗證執行期間修改相同檔案。`
|