@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.
Files changed (45) hide show
  1. package/README.md +19 -0
  2. package/dist/packages/cli/src/args.js +78 -3
  3. package/dist/packages/cli/src/bin.js +19 -1
  4. package/dist/packages/cli/src/cli.js +33 -0
  5. package/dist/packages/cli/src/commands/advance.js +3 -2
  6. package/dist/packages/cli/src/commands/followup.js +74 -0
  7. package/dist/packages/cli/src/commands/parallel.js +4 -0
  8. package/dist/packages/cli/src/commands/run.js +1 -1
  9. package/dist/packages/cli/src/commands/task.js +22 -5
  10. package/dist/packages/cli/src/context.js +13 -9
  11. package/dist/packages/cli/src/criteria-review.js +63 -0
  12. package/dist/packages/cli/src/followup-deps.js +56 -0
  13. package/dist/packages/cli/src/owned-run-step.js +1 -1
  14. package/dist/packages/cli/src/run-deps.js +16 -5
  15. package/dist/packages/cli/src/run-entry.js +283 -145
  16. package/dist/runtime/src/followup/intake.js +75 -0
  17. package/dist/runtime/src/followup/process.js +273 -0
  18. package/dist/runtime/src/followup/receipt.js +116 -0
  19. package/dist/runtime/src/followup/store.js +133 -0
  20. package/dist/runtime/src/install/harness.js +1 -1
  21. package/dist/runtime/src/install/preauth.js +11 -4
  22. package/dist/runtime/src/logging/local-log.js +12 -0
  23. package/dist/runtime/src/parallel/finish.js +10 -2
  24. package/dist/runtime/src/review/attestation.js +10 -0
  25. package/dist/runtime/src/review/criteria.js +252 -0
  26. package/dist/runtime/src/review/followup.js +233 -0
  27. package/dist/runtime/src/review/invocation.js +3 -3
  28. package/dist/runtime/src/review/runner.js +20 -0
  29. package/dist/runtime/src/run/service.js +59 -6
  30. package/dist/runtime/src/run/usage.js +5 -2
  31. package/dist/runtime/src/security/permissions.js +16 -1
  32. package/dist/runtime/src/verify/acceptance-coverage.js +2 -2
  33. package/dist/runtime/src/verify/service.js +62 -2
  34. package/dist/runtime/src/verify/spawn.js +67 -4
  35. package/docs/en/guides/configuration.md +5 -0
  36. package/docs/en/guides/task-debug.md +36 -0
  37. package/docs/en/spec/acceptance-and-evidence.md +54 -0
  38. package/docs/en/spec/loop-engineering.md +36 -0
  39. package/docs/en/spec/review.md +16 -0
  40. package/docs/zh-TW/guides/configuration.md +3 -0
  41. package/docs/zh-TW/guides/task-debug.md +31 -0
  42. package/docs/zh-TW/spec/acceptance-and-evidence.md +39 -0
  43. package/docs/zh-TW/spec/loop-engineering.md +21 -0
  44. package/docs/zh-TW/spec/review.md +17 -1
  45. 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: await readBootIdentity(), loginDomain: await readGuiLoginIdentity() });
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
- const result = await service.resume(runId, retryApprovalIds, upgradeBudget);
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);