@kylecheng3146/agent-ops 0.11.0 → 0.11.2
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 +19 -0
- package/dist/packages/cli/src/args.js +78 -3
- package/dist/packages/cli/src/bin.js +19 -1
- package/dist/packages/cli/src/cli.js +33 -0
- package/dist/packages/cli/src/commands/advance.js +3 -2
- package/dist/packages/cli/src/commands/followup.js +74 -0
- package/dist/packages/cli/src/commands/parallel.js +4 -0
- package/dist/packages/cli/src/commands/run.js +1 -1
- package/dist/packages/cli/src/commands/task.js +22 -5
- package/dist/packages/cli/src/context.js +13 -9
- package/dist/packages/cli/src/criteria-review.js +63 -0
- package/dist/packages/cli/src/followup-deps.js +56 -0
- package/dist/packages/cli/src/owned-run-step.js +1 -1
- package/dist/packages/cli/src/run-deps.js +16 -5
- package/dist/packages/cli/src/run-entry.js +283 -145
- package/dist/runtime/src/followup/intake.js +75 -0
- package/dist/runtime/src/followup/process.js +273 -0
- package/dist/runtime/src/followup/receipt.js +116 -0
- package/dist/runtime/src/followup/store.js +133 -0
- package/dist/runtime/src/install/harness.js +1 -1
- package/dist/runtime/src/install/preauth.js +11 -4
- package/dist/runtime/src/logging/local-log.js +12 -0
- package/dist/runtime/src/parallel/finish.js +10 -2
- package/dist/runtime/src/review/attestation.js +10 -0
- package/dist/runtime/src/review/criteria.js +252 -0
- package/dist/runtime/src/review/followup.js +233 -0
- package/dist/runtime/src/review/invocation.js +3 -3
- package/dist/runtime/src/review/runner.js +20 -0
- package/dist/runtime/src/run/service.js +59 -6
- package/dist/runtime/src/run/usage.js +5 -2
- package/dist/runtime/src/security/permissions.js +16 -1
- package/dist/runtime/src/verify/acceptance-coverage.js +2 -2
- package/dist/runtime/src/verify/service.js +62 -2
- package/dist/runtime/src/verify/spawn.js +67 -4
- package/docs/en/guides/configuration.md +5 -0
- package/docs/en/guides/task-debug.md +36 -0
- package/docs/en/spec/acceptance-and-evidence.md +54 -0
- package/docs/en/spec/loop-engineering.md +36 -0
- package/docs/en/spec/review.md +16 -0
- package/docs/zh-TW/guides/configuration.md +3 -0
- package/docs/zh-TW/guides/task-debug.md +31 -0
- package/docs/zh-TW/spec/acceptance-and-evidence.md +39 -0
- package/docs/zh-TW/spec/loop-engineering.md +21 -0
- package/docs/zh-TW/spec/review.md +17 -1
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { AgentOpsError } from "../../../runtime/src/fs/paths.js";
|
|
2
|
+
import { processFollowup, reconcileFollowupRepairs } from "../../../runtime/src/followup/process.js";
|
|
3
|
+
import { isFollowupAssessmentCurrent } from "../../../runtime/src/review/followup.js";
|
|
4
|
+
import { resolveReviewRole } from "../../../runtime/src/review/roles.js";
|
|
5
|
+
import { worktreeDependencies, gitRunner } from "./parallel-deps.js";
|
|
6
|
+
import { productionRunContext } from "./run-deps.js";
|
|
7
|
+
import { resolveCheckouts } from "../../../runtime/src/parallel/service.js";
|
|
8
|
+
import { reconcileFollowups } from "../../../runtime/src/followup/intake.js";
|
|
9
|
+
export async function followupRepositoryContext(cwd) {
|
|
10
|
+
const deps = worktreeDependencies(), checkouts = await resolveCheckouts(deps, cwd);
|
|
11
|
+
return { git: deps.git, mainRoot: checkouts.mainRoot, commonDir: checkouts.commonDir,
|
|
12
|
+
config: await deps.loadConfig(checkouts.mainRoot), loadConfig: async () => await deps.loadConfig(checkouts.mainRoot) };
|
|
13
|
+
}
|
|
14
|
+
/** Ordinary CLI reconciliation is advisory and never launches a provider or repair. */
|
|
15
|
+
export async function reconcileRepositoryFollowups(cwd) {
|
|
16
|
+
try {
|
|
17
|
+
return await reconcileFollowups(await followupRepositoryContext(cwd));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
const code = error instanceof AgentOpsError && /^[A-Z0-9_]{1,80}$/u.test(error.code) ? error.code : "FOLLOWUP_COLLECTION_FAILED";
|
|
21
|
+
return { added: 0, candidates: 0, observations: 0,
|
|
22
|
+
warnings: code === "WORKTREE_NOT_GIT" ? [] : [`followup: ${code}; retry with followup import.`] };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Uses the ordinary production authority, including its exact native/platform/trust refusals. */
|
|
26
|
+
export async function productionFollowupContext(cwd) {
|
|
27
|
+
const deps = worktreeDependencies(), checkouts = await resolveCheckouts(deps, cwd);
|
|
28
|
+
const branch = await deps.git(checkouts.currentRoot, ["symbolic-ref", "--short", "HEAD"]);
|
|
29
|
+
if (branch.exitCode !== 0)
|
|
30
|
+
throw new AgentOpsError("RUN_TARGET_REQUIRED", "Followup processing requires a checked-out target branch.");
|
|
31
|
+
const loadConfig = async () => await deps.loadConfig(checkouts.currentRoot);
|
|
32
|
+
const assessmentOptions = async (itemId, reviewOnlyReason) => {
|
|
33
|
+
const config = await loadConfig(), role = resolveReviewRole("independent-review", config.reviewRoles ?? []);
|
|
34
|
+
return {
|
|
35
|
+
root: checkouts.currentRoot, commonDir: checkouts.commonDir, itemId, targetBranch: branch.stdout.trim(),
|
|
36
|
+
gitRunner: gitRunner(checkouts.currentRoot), loadConfig,
|
|
37
|
+
review: { targets: role?.targets ?? [], ...(role?.timeoutMs === undefined ? {} : { timeoutMs: role.timeoutMs }) },
|
|
38
|
+
...(reviewOnlyReason === undefined ? {} : { reviewOnlyReason })
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
return { ...checkouts,
|
|
42
|
+
assessmentOptions,
|
|
43
|
+
process: async (itemId, host, reviewOnlyReason) => {
|
|
44
|
+
const options = await assessmentOptions(itemId, reviewOnlyReason);
|
|
45
|
+
return await processFollowup({ ...options, host, start: async (input, proof) => {
|
|
46
|
+
const run = await productionRunContext(cwd, { beforeStart: async () => {
|
|
47
|
+
if (!await isFollowupAssessmentCurrent(options, proof))
|
|
48
|
+
throw new AgentOpsError("FOLLOWUP_SOURCE_CHANGED", "The finding, target, source or config changed before repair startup.");
|
|
49
|
+
} });
|
|
50
|
+
return (await run.service.start({ ...input, root: run.mainRoot, commonDir: run.commonDir,
|
|
51
|
+
targetBranch: run.targetBranch, ownerSessionId: run.ownerSessionId })).state;
|
|
52
|
+
} });
|
|
53
|
+
},
|
|
54
|
+
reconcile: async () => await reconcileFollowupRepairs({ git: deps.git, mainRoot: checkouts.mainRoot,
|
|
55
|
+
commonDir: checkouts.commonDir, config: await loadConfig(), loadConfig }) };
|
|
56
|
+
}
|
|
@@ -22,7 +22,7 @@ export async function runOwnedLocalProof(argv) {
|
|
|
22
22
|
if (existing.processAlive)
|
|
23
23
|
throw new AgentOpsError("RUN_WORKER_PROOF_ACTIVE", "A registered proof command is already running for this worker.");
|
|
24
24
|
}
|
|
25
|
-
const remaining = remainingRunTimeMs(state);
|
|
25
|
+
const remaining = argv[0] === "review" && argv.includes("--criteria") ? Infinity : remainingRunTimeMs(state);
|
|
26
26
|
if (remaining <= 0)
|
|
27
27
|
throw new AgentOpsError("RUN_BUDGET_EXHAUSTED", "No active run time remains for local proof.");
|
|
28
28
|
const cli = fileURLToPath(new URL("./bin.js", import.meta.url));
|
|
@@ -7,9 +7,9 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { setTimeout as delay } from "node:timers/promises";
|
|
8
8
|
import { AgentOpsError } from "../../../runtime/src/fs/paths.js";
|
|
9
9
|
import { sha256 } from "../../../runtime/src/fs/hash.js";
|
|
10
|
-
import { resolveCheckouts, sessionWorktreeName } from "../../../runtime/src/parallel/service.js";
|
|
10
|
+
import { resolveCheckouts, readWorktreeRecord, sessionWorktreeName } from "../../../runtime/src/parallel/service.js";
|
|
11
11
|
import { createLaunchdDescriptor, LaunchdController, readBootIdentity, readGuiLoginIdentity } from "../../../runtime/src/run/macOS.js";
|
|
12
|
-
import { FileRunRepository, RunService } from "../../../runtime/src/run/service.js";
|
|
12
|
+
import { FileRunRepository, RunService, validateDeliveryRetry } from "../../../runtime/src/run/service.js";
|
|
13
13
|
import { readPrivateFile, writePrivateFile } from "../../../runtime/src/security/permissions.js";
|
|
14
14
|
import { collectChangeSurface } from "../../../runtime/src/verify/change-surface.js";
|
|
15
15
|
import { worktreeDependencies, gitRunner, trustStore } from "./parallel-deps.js";
|
|
@@ -182,8 +182,10 @@ export async function productionRunContext(cwd, options = {}) {
|
|
|
182
182
|
if (await deps.trust.status(checkouts.mainRoot, config) !== "TRUSTED")
|
|
183
183
|
throw new AgentOpsError("RUN_REPO_UNTRUSTED", "The run requires current repository verifier trust.");
|
|
184
184
|
const ownerSessionId = randomUUID();
|
|
185
|
+
const bootIdentity = await readBootIdentity(), loginDomain = await readGuiLoginIdentity();
|
|
186
|
+
await options.beforeStart?.();
|
|
185
187
|
const result = await service.start({ ...input, root: checkouts.mainRoot, commonDir: checkouts.commonDir,
|
|
186
|
-
targetBranch: target.stdout.trim(), ownerSessionId, bootIdentity
|
|
188
|
+
targetBranch: target.stdout.trim(), ownerSessionId, bootIdentity, loginDomain });
|
|
187
189
|
try {
|
|
188
190
|
await bindRunPolicy(repository, result.state.runId, { config,
|
|
189
191
|
baseTrustBinding: await repositoryTrustBinding(checkouts.mainRoot, config, CLI_VERSION), runtimeHash: await runRuntimeHash() });
|
|
@@ -209,8 +211,9 @@ export async function productionRunContext(cwd, options = {}) {
|
|
|
209
211
|
throw cause;
|
|
210
212
|
}
|
|
211
213
|
};
|
|
212
|
-
const resume = async (runId, retryApprovalIds = [], upgradeBudget = true) => {
|
|
214
|
+
const resume = async (runId, retryApprovalIds = [], upgradeBudget = true, retryDeliveryTaskId) => {
|
|
213
215
|
const before = await service.status(runId);
|
|
216
|
+
const retry = retryDeliveryTaskId === undefined ? null : validateDeliveryRetry(before, retryDeliveryTaskId);
|
|
214
217
|
const runtimeHash = await runRuntimeHash();
|
|
215
218
|
const policy = await readRunPolicy(before, before.policyBinding?.runtimeHash ?? runtimeHash, Date.now(), true);
|
|
216
219
|
if (policy !== null && await deps.trust.status(checkouts.mainRoot, policy.baseConfig) !== "TRUSTED")
|
|
@@ -236,7 +239,15 @@ export async function productionRunContext(cwd, options = {}) {
|
|
|
236
239
|
if (exists === null || (await collectChangeSurface(gitRunner(worker.worktree))).paths.length > 0)
|
|
237
240
|
throw new AgentOpsError("RUN_RECOVERY_DIRTY", "Commit or preserve every writer checkout before explicit resume.");
|
|
238
241
|
}
|
|
239
|
-
|
|
242
|
+
if (retry !== null) {
|
|
243
|
+
const record = retry.worktree === null ? null : await readWorktreeRecord(retry.worktree);
|
|
244
|
+
const head = retry.worktree === null ? null : await deps.git(retry.worktree, ["rev-parse", "HEAD"]);
|
|
245
|
+
if (record === null || record.runId !== runId || record.workerId !== retry.workerId ||
|
|
246
|
+
record.ownerSessionId !== retry.ownerSessionId || record.workerGeneration !== retry.generation ||
|
|
247
|
+
head?.exitCode !== 0 || head.stdout.trim() !== retry.stopIntent.sourceCommit)
|
|
248
|
+
throw new AgentOpsError("RUN_DELIVERY_RETRY_INVALID", "Interrupted checkout ownership or source changed; preserve it and reconcile before retrying.");
|
|
249
|
+
}
|
|
250
|
+
const result = await service.resume(runId, retryApprovalIds, upgradeBudget, retryDeliveryTaskId, retry?.lastFailure?.id);
|
|
240
251
|
try {
|
|
241
252
|
if (pending !== null)
|
|
242
253
|
await renewPendingRunPolicy(repository, runId, pending);
|