@fitlab-ai/agent-infra 0.12.1 → 0.12.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 (303) hide show
  1. package/README.md +0 -2
  2. package/README.zh-CN.md +0 -2
  3. package/dist/bin/internal-cli.js +2 -17
  4. package/dist/lib/agent-clients/adapter.js +0 -13
  5. package/dist/lib/agent-clients/adapters/antigravity-cli.js +0 -5
  6. package/dist/lib/agent-clients/adapters/claude-code-credentials.js +0 -17
  7. package/dist/lib/agent-clients/adapters/claude-code.js +0 -9
  8. package/dist/lib/agent-clients/adapters/codex.js +0 -52
  9. package/dist/lib/agent-clients/adapters/opencode.js +0 -5
  10. package/dist/lib/agent-clients/adapters/traecli.js +0 -5
  11. package/dist/lib/agent-clients/config.js +19 -54
  12. package/dist/lib/agent-clients/registry.js +1 -12
  13. package/dist/lib/agent-clients/schema.js +0 -18
  14. package/dist/lib/agent-clients/tokens.js +1 -2
  15. package/dist/lib/agent-clients/types.js +0 -1
  16. package/dist/lib/decide.js +2 -0
  17. package/dist/lib/git/worktree-identity.js +1 -9
  18. package/dist/lib/internal/agent-client.js +2 -62
  19. package/dist/lib/internal/cli-route-inventory.js +1 -5
  20. package/dist/lib/internal/manual-validation.js +18 -10
  21. package/dist/lib/internal/task-create.js +1 -1
  22. package/dist/lib/internal/task-event.js +1 -8
  23. package/dist/lib/internal/task-finalization.js +0 -1
  24. package/dist/lib/internal/task-lifecycle.js +2 -2
  25. package/dist/lib/internal/task-operation-registry.js +4 -20
  26. package/dist/lib/internal/task-review.js +4 -4
  27. package/dist/lib/platform/comment-safety.js +1 -7
  28. package/dist/lib/platform/in-label-sync.js +1 -14
  29. package/dist/lib/platform/issue-comments.js +1 -16
  30. package/dist/lib/platform/issues.js +1 -1
  31. package/dist/lib/platform/operation-coordinator.js +4 -2
  32. package/dist/lib/platform/pr-change-report.js +1 -4
  33. package/dist/lib/platform/pr-checks.js +2 -8
  34. package/dist/lib/platform/provider-validation.js +0 -20
  35. package/dist/lib/platform/pull-requests.js +73 -84
  36. package/dist/lib/platform/releases.js +1 -43
  37. package/dist/lib/platform/verification-required.js +0 -2
  38. package/dist/lib/platform/verification-sync.js +1 -79
  39. package/dist/lib/process-data/normalize.js +1 -185
  40. package/dist/lib/process-data/privacy.js +1 -16
  41. package/dist/lib/process-data/sources.js +2 -279
  42. package/dist/lib/render.js +0 -12
  43. package/dist/lib/run/index.js +15 -10
  44. package/dist/lib/run/skills.js +0 -3
  45. package/dist/lib/sandbox/commands/create.js +40 -53
  46. package/dist/lib/sandbox/commands/list-running.js +0 -18
  47. package/dist/lib/sandbox/commands/start.js +7 -8
  48. package/dist/lib/sandbox/constants.js +0 -6
  49. package/dist/lib/sandbox/control/client.js +0 -1
  50. package/dist/lib/sandbox/control/container-identity.js +1 -16
  51. package/dist/lib/sandbox/control/executor.js +0 -4
  52. package/dist/lib/sandbox/control/identity-sentinel.js +0 -7
  53. package/dist/lib/sandbox/control/lifecycle.js +21 -37
  54. package/dist/lib/sandbox/control/native-file-lock.js +0 -3
  55. package/dist/lib/sandbox/control/server.js +18 -38
  56. package/dist/lib/sandbox/control/state.js +1 -9
  57. package/dist/lib/sandbox/dockerfile.js +0 -6
  58. package/dist/lib/sandbox/engine.js +0 -14
  59. package/dist/lib/sandbox/engines/docker-exact-discovery.js +1 -4
  60. package/dist/lib/sandbox/engines/wsl2-paths.js +0 -3
  61. package/dist/lib/sandbox/recovery.js +24 -26
  62. package/dist/lib/sandbox/removal.js +11 -519
  63. package/dist/lib/sandbox/task-resolver.js +0 -41
  64. package/dist/lib/sandbox/tools.js +1 -4
  65. package/dist/lib/sandbox/workspace-view.js +1 -2
  66. package/dist/lib/server/display.js +0 -6
  67. package/dist/lib/task/activity-intent.js +45 -40
  68. package/dist/lib/task/activity-log.js +9 -16
  69. package/dist/lib/task/artifact-command.js +1 -1
  70. package/dist/lib/task/artifact-lifecycle.js +61 -63
  71. package/dist/lib/task/artifact-name.js +0 -6
  72. package/dist/lib/task/artifact-operations.js +3 -3
  73. package/dist/lib/task/capabilities.js +4 -5
  74. package/dist/lib/task/commands/log.js +0 -6
  75. package/dist/lib/task/commands/status.js +17 -60
  76. package/dist/lib/task/commit-operation.js +28 -39
  77. package/dist/lib/task/completion-facts.js +56 -43
  78. package/dist/lib/task/control-authority.js +23 -256
  79. package/dist/lib/task/control-recovery.js +3 -5
  80. package/dist/lib/task/create.js +2 -4
  81. package/dist/lib/task/decision-intents.js +8 -9
  82. package/dist/lib/task/delivery-target.js +1 -40
  83. package/dist/lib/task/events.js +84 -107
  84. package/dist/lib/task/finalization.js +44 -8
  85. package/dist/lib/task/ledger-intents.js +1 -1
  86. package/dist/lib/task/lifecycle-execution.js +38 -33
  87. package/dist/lib/task/lifecycle.js +49 -41
  88. package/dist/lib/task/local-artifact-finalization.js +1 -4
  89. package/dist/lib/task/manual-validation-evidence.js +1 -37
  90. package/dist/lib/task/platform-operation-recovery.js +67 -24
  91. package/dist/lib/task/pr-delivery-fact.js +2 -5
  92. package/dist/lib/task/qualification-confirmation.js +5 -7
  93. package/dist/lib/task/resolve-ref.js +1 -25
  94. package/dist/lib/task/review-command.js +2 -2
  95. package/dist/lib/task/review-finalization.js +1 -21
  96. package/dist/lib/task/review-fingerprint.js +0 -4
  97. package/dist/lib/task/secure-fs.js +0 -56
  98. package/dist/lib/task/short-id.js +1 -39
  99. package/dist/lib/task/skill-scope.js +0 -1
  100. package/dist/lib/task/verification-engine.js +58 -282
  101. package/dist/lib/task/verification.js +6 -3
  102. package/dist/lib/task/write.js +11 -1
  103. package/lib/agent-clients/adapter.ts +0 -76
  104. package/lib/agent-clients/adapters/antigravity-cli.ts +0 -5
  105. package/lib/agent-clients/adapters/claude-code-credentials.ts +0 -19
  106. package/lib/agent-clients/adapters/claude-code.ts +0 -9
  107. package/lib/agent-clients/adapters/codex.ts +0 -56
  108. package/lib/agent-clients/adapters/opencode.ts +0 -5
  109. package/lib/agent-clients/adapters/traecli.ts +0 -5
  110. package/lib/agent-clients/config.ts +20 -61
  111. package/lib/agent-clients/registry.ts +1 -34
  112. package/lib/agent-clients/schema.ts +0 -18
  113. package/lib/agent-clients/tokens.ts +1 -2
  114. package/lib/agent-clients/types.ts +0 -15
  115. package/lib/decide.ts +1 -0
  116. package/lib/git/worktree-identity.ts +0 -10
  117. package/lib/internal/agent-client.ts +2 -70
  118. package/lib/internal/cli-route-inventory.ts +1 -4
  119. package/lib/internal/manual-validation.ts +16 -9
  120. package/lib/internal/task-create.ts +0 -1
  121. package/lib/internal/task-event.ts +1 -5
  122. package/lib/internal/task-finalization.ts +0 -1
  123. package/lib/internal/task-lifecycle.ts +3 -5
  124. package/lib/internal/task-operation-registry.ts +3 -19
  125. package/lib/internal/task-review.ts +4 -4
  126. package/lib/platform/comment-safety.ts +0 -10
  127. package/lib/platform/github-provider.ts +0 -2
  128. package/lib/platform/in-label-sync.ts +0 -16
  129. package/lib/platform/issue-comments.ts +0 -21
  130. package/lib/platform/issues.ts +0 -2
  131. package/lib/platform/operation-coordinator.ts +4 -2
  132. package/lib/platform/pr-change-report.ts +0 -5
  133. package/lib/platform/pr-checks.ts +1 -10
  134. package/lib/platform/pr-review.ts +1 -1
  135. package/lib/platform/provider-bridge.ts +0 -1
  136. package/lib/platform/provider-loader.ts +1 -5
  137. package/lib/platform/provider-validation.ts +1 -49
  138. package/lib/platform/pull-requests.ts +64 -99
  139. package/lib/platform/releases.ts +1 -40
  140. package/lib/platform/verification-required.ts +0 -2
  141. package/lib/platform/verification-sync.ts +0 -94
  142. package/lib/process-data/normalize.ts +1 -186
  143. package/lib/process-data/privacy.ts +2 -19
  144. package/lib/process-data/sources.ts +3 -283
  145. package/lib/render.ts +0 -15
  146. package/lib/run/index.ts +13 -7
  147. package/lib/run/skills.ts +0 -4
  148. package/lib/sandbox/commands/create.ts +37 -74
  149. package/lib/sandbox/commands/list-running.ts +0 -19
  150. package/lib/sandbox/commands/start.ts +7 -10
  151. package/lib/sandbox/constants.ts +0 -8
  152. package/lib/sandbox/control/client.ts +0 -1
  153. package/lib/sandbox/control/container-identity.ts +1 -16
  154. package/lib/sandbox/control/executor.ts +1 -5
  155. package/lib/sandbox/control/identity-sentinel.ts +0 -8
  156. package/lib/sandbox/control/lifecycle.ts +18 -51
  157. package/lib/sandbox/control/native-file-lock.ts +0 -8
  158. package/lib/sandbox/control/protocol.ts +0 -2
  159. package/lib/sandbox/control/server.ts +13 -39
  160. package/lib/sandbox/control/state.ts +1 -10
  161. package/lib/sandbox/dockerfile.ts +0 -11
  162. package/lib/sandbox/engine.ts +0 -17
  163. package/lib/sandbox/engines/docker-exact-discovery.ts +1 -5
  164. package/lib/sandbox/engines/wsl2-paths.ts +0 -4
  165. package/lib/sandbox/recovery.ts +24 -26
  166. package/lib/sandbox/removal.ts +11 -696
  167. package/lib/sandbox/shell.ts +1 -1
  168. package/lib/sandbox/task-resolver.ts +0 -48
  169. package/lib/sandbox/tools.ts +1 -5
  170. package/lib/sandbox/workspace-view.ts +2 -4
  171. package/lib/server/display.ts +0 -14
  172. package/lib/server/process-control.ts +1 -1
  173. package/lib/task/activity-intent.ts +36 -44
  174. package/lib/task/activity-log.ts +9 -22
  175. package/lib/task/artifact-command.ts +1 -1
  176. package/lib/task/artifact-lifecycle.ts +58 -67
  177. package/lib/task/artifact-name.ts +0 -7
  178. package/lib/task/artifact-operations.ts +3 -3
  179. package/lib/task/capabilities.ts +5 -6
  180. package/lib/task/commands/log.ts +0 -7
  181. package/lib/task/commands/status.ts +14 -79
  182. package/lib/task/commit-operation.ts +29 -51
  183. package/lib/task/completion-facts.ts +45 -42
  184. package/lib/task/control-authority.ts +27 -317
  185. package/lib/task/control-recovery.ts +2 -5
  186. package/lib/task/create.ts +2 -5
  187. package/lib/task/decision-intents.ts +5 -5
  188. package/lib/task/delivery-target.ts +0 -40
  189. package/lib/task/events.ts +89 -123
  190. package/lib/task/finalization.ts +41 -9
  191. package/lib/task/ledger-intents.ts +1 -1
  192. package/lib/task/lifecycle-execution.ts +37 -89
  193. package/lib/task/lifecycle.ts +48 -44
  194. package/lib/task/local-artifact-finalization.ts +0 -7
  195. package/lib/task/manual-validation-evidence.ts +1 -47
  196. package/lib/task/platform-operation-recovery.ts +50 -26
  197. package/lib/task/pr-delivery-fact.ts +2 -11
  198. package/lib/task/qualification-confirmation.ts +6 -6
  199. package/lib/task/resolve-ref.ts +0 -23
  200. package/lib/task/review-command.ts +2 -2
  201. package/lib/task/review-finalization.ts +1 -27
  202. package/lib/task/review-fingerprint.ts +0 -8
  203. package/lib/task/secure-fs.ts +0 -42
  204. package/lib/task/short-id.ts +0 -43
  205. package/lib/task/skill-scope.ts +0 -1
  206. package/lib/task/verification-engine.ts +56 -287
  207. package/lib/task/verification.ts +5 -5
  208. package/lib/task/write.ts +12 -1
  209. package/package.json +2 -2
  210. package/templates/.agents/README.en.md +1 -3
  211. package/templates/.agents/README.zh-CN.md +0 -2
  212. package/templates/.agents/rules/README.en.md +0 -1
  213. package/templates/.agents/rules/README.zh-CN.md +0 -1
  214. package/templates/.agents/rules/commit-and-pr.en.md +1 -1
  215. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -1
  216. package/templates/.agents/rules/no-mid-flow-questions.en.md +0 -10
  217. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +0 -10
  218. package/templates/.agents/rules/pr-sync.en.md +1 -1
  219. package/templates/.agents/rules/pr-sync.zh-CN.md +1 -1
  220. package/templates/.agents/rules/task-management.en.md +3 -3
  221. package/templates/.agents/rules/task-management.zh-CN.md +3 -3
  222. package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
  223. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
  224. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  225. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  226. package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
  227. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -4
  228. package/templates/.agents/skills/commit/SKILL.en.md +2 -2
  229. package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
  230. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +6 -6
  231. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +6 -6
  232. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
  233. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
  234. package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
  235. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
  236. package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
  237. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
  238. package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
  239. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
  240. package/templates/.agents/skills/review-pr/SKILL.en.md +4 -4
  241. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +4 -4
  242. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
  243. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
  244. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -75
  245. package/templates/.agents/templates/task.en.md +1 -0
  246. package/templates/.agents/templates/task.zh-CN.md +1 -0
  247. package/templates/.claude/settings.json +0 -24
  248. package/templates/.codex/hooks.json +0 -50
  249. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +0 -582
  250. package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +0 -114
  251. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +0 -237
  252. package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +0 -443
  253. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +0 -236
  254. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +0 -292
  255. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +0 -267
  256. package/dist/lib/agent-clients/adapters/codex-orchestration.js +0 -466
  257. package/dist/lib/internal/task-orchestration.js +0 -71
  258. package/dist/lib/platform/verification.js +0 -6
  259. package/dist/lib/run/prompt.js +0 -2
  260. package/dist/lib/sandbox/engines/authority.js +0 -289
  261. package/dist/lib/task/delegation-receipts.js +0 -410
  262. package/dist/lib/task/orchestration.js +0 -1233
  263. package/dist/lib/task/verification-checks.js +0 -9
  264. package/dist/lib/task/workspace-snapshot.js +0 -121
  265. package/dist/lifecycle-build-manifest.json +0 -6
  266. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +0 -688
  267. package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +0 -147
  268. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +0 -349
  269. package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +0 -506
  270. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +0 -385
  271. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -41
  272. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +0 -418
  273. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +0 -354
  274. package/lib/agent-clients/adapters/codex-orchestration.ts +0 -630
  275. package/lib/internal/task-orchestration.ts +0 -74
  276. package/lib/platform/verification.ts +0 -11
  277. package/lib/run/prompt.ts +0 -1
  278. package/lib/sandbox/engines/authority.ts +0 -365
  279. package/lib/task/delegation-receipts.ts +0 -547
  280. package/lib/task/orchestration.ts +0 -1651
  281. package/lib/task/verification-checks.ts +0 -10
  282. package/lib/task/workspace-snapshot.ts +0 -144
  283. package/templates/.agents/hooks/lifecycle-delegation.js +0 -140
  284. package/templates/.agents/rules/lifecycle-orchestration.en.md +0 -44
  285. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +0 -44
  286. package/templates/.agents/skills/run-task/SKILL.en.md +0 -29
  287. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +0 -29
  288. package/templates/.agents/skills/run-task/config/verify.en.json +0 -10
  289. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +0 -10
  290. package/templates/.agents/skills/run-task/reference/host-validation.en.md +0 -24
  291. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +0 -24
  292. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +0 -6
  293. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +0 -6
  294. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +0 -6
  295. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +0 -6
  296. package/templates/.claude/commands/run-task.en.md +0 -8
  297. package/templates/.claude/commands/run-task.zh-CN.md +0 -8
  298. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +0 -3
  299. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +0 -3
  300. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +0 -3
  301. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +0 -3
  302. package/templates/.opencode/commands/run-task.en.md +0 -11
  303. package/templates/.opencode/commands/run-task.zh-CN.md +0 -11
@@ -1,7 +1,6 @@
1
1
  // frontmatter, ledger, Git snapshot and platform domains are imported below.
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- import process from "node:process";
5
4
  import { execFileSync } from "node:child_process";
6
5
  import { fileURLToPath } from "node:url";
7
6
  import { extractReviewTargetHead, extractReviewedHead, extractReviewDiffBase, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from "./verification-review.js";
@@ -19,9 +18,8 @@ import { inspectDecisionDetailDuplicates } from "./decision-details.js";
19
18
  import { parseImplementationInputs } from "./implementation-inputs.js";
20
19
  import { scanVisibleMarkdown } from "./markdown.js";
21
20
  import { loadVerificationConfig } from "./verification-config.js";
22
- import { inspectActivityLog, pairEntries } from "./activity-log.js";
21
+ import { inspectActivityLog } from "./activity-log.js";
23
22
  import { parseWorkflowWarnings } from "./workflow-warnings.js";
24
- import { OrchestrationStateError, readRun } from "./orchestration.js";
25
23
  import { readPrDeliveryFact } from "./pr-delivery-fact.js";
26
24
  import { validateLocalArtifact } from "./local-artifact-finalization.js";
27
25
  import { getArtifactSchema } from "./artifact-schema.js";
@@ -29,13 +27,12 @@ import { inspectArtifactContract } from "./artifact-operations.js";
29
27
  import { normalizeVerificationRecord } from './gate-policy.js';
30
28
  import { manualValidationFinalSummaryProjectionMatches } from "./manual-validation-receipt.js";
31
29
  import { readManualValidationCompletion } from "./manual-validation-completion.js";
32
- import { sha256File } from "./artifact-receipts.js";
30
+ import { parseArtifactReceipts, receiptForOutput, sha256File } from "./artifact-receipts.js";
33
31
  import { inspectArtifactDirectory } from "./artifact-lifecycle.js";
34
- import { getAgentClientAdapter } from "../agent-clients/registry.js";
35
32
  import { parseArtifactName } from "./artifact-name.js";
36
33
  import { summaryCommentState } from "../platform/pr-summary.js";
37
34
  import { taskIssueIdentity } from "../platform/task-identities.js";
38
- import { hasArtifactCompletionFact, hasArtifactCompletionLog, parseCompletionFacts } from './completion-facts.js';
35
+ import { hasValidArtifactCompletion } from './completion-facts.js';
39
36
  import { inspectReviewIdentity } from './review-identity.js';
40
37
  const TASK_ENUMS = {
41
38
  type: ["feature", "bugfix", "refactor", "docs", "chore"],
@@ -55,10 +52,8 @@ const DEFAULT_REQUIRED_FIELDS = [
55
52
  ];
56
53
  const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
57
54
  // Started rows do not represent completed lifecycle actions.
58
- const ACTIVITY_LOG_STARTED_RE = /\s*\[started\]\s*$/;
59
55
  const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
60
56
  // Review disagreement ledger (see .agents/rules/review-handshake.md).
61
- const LEDGER_SECTION_NAMES = ["审查分歧账本", "Review Disagreement Ledger"];
62
57
  const POST_REVIEW_COMMIT_STAGE = "post-review-commit";
63
58
  const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
64
59
  const scriptPath = fileURLToPath(import.meta.url);
@@ -106,10 +101,6 @@ async function runCheck(type, context, shared) {
106
101
  return checkPostReviewCommit(context);
107
102
  case "required-pr-delivery":
108
103
  return checkRequiredPrDelivery(context);
109
- case "orchestration-state":
110
- return checkOrchestrationState(context);
111
- case "orchestration-evidence":
112
- return checkOrchestrationEvidence(context);
113
104
  default: {
114
105
  const adapter = PLATFORM_ADAPTERS[type];
115
106
  if (!adapter) {
@@ -122,159 +113,6 @@ async function runCheck(type, context, shared) {
122
113
  }
123
114
  }
124
115
  }
125
- function checkOrchestrationState({ taskDir }) {
126
- const file = path.join(taskDir, '.runtime', 'orchestration.json');
127
- const stat = safeStat(file);
128
- if (!stat?.isFile())
129
- return failResult('orchestration-state', 'orchestration.json is missing');
130
- let run;
131
- try {
132
- run = readRun(taskDir);
133
- }
134
- catch (error) {
135
- const message = error instanceof OrchestrationStateError ? error.message : String(error);
136
- return failResult('orchestration-state', `Invalid orchestration.json: ${message}`);
137
- }
138
- if (!run || !['paused', 'completed'].includes(run.status)) {
139
- return failResult('orchestration-state', `Expected paused or completed run, received '${run?.status ?? 'missing'}'`);
140
- }
141
- const adapterEvidenceError = validateAdapterReceiptEvidence(run);
142
- if (adapterEvidenceError)
143
- return failResult('orchestration-state', adapterEvidenceError);
144
- if (run.status === 'paused' && (!run.pause?.code || !run.pause?.message)) {
145
- return failResult('orchestration-state', 'Paused run requires a stable pause code and message');
146
- }
147
- if (run.status === 'completed') {
148
- const evidenceError = validateCleanCompletionEvidence(run);
149
- if (evidenceError)
150
- return failResult('orchestration-state', evidenceError);
151
- }
152
- else if (run.completionEvidence != null) {
153
- return failResult('orchestration-state', 'Clean completion evidence requires a completed run');
154
- }
155
- else if (run.pendingDelegation?.status === 'sealed') {
156
- return failResult('orchestration-state', 'Paused run has a sealed delegation that could still advance');
157
- }
158
- return passResult('orchestration-state', `Orchestration run is safely ${run.status}`);
159
- }
160
- function exactText(value) {
161
- return typeof value === 'string' && value.length > 0 && value.trim() === value;
162
- }
163
- function validateCleanCompletionEvidence(run) {
164
- const evidence = run.completionEvidence;
165
- const shaPattern = /^[0-9a-f]{40}$/i;
166
- if (!evidence
167
- || Number.isNaN(Date.parse(evidence.observedAt))
168
- || !shaPattern.test(evidence.head)
169
- || !shaPattern.test(evidence.headTree)
170
- || !shaPattern.test(evidence.worktreeTree)
171
- || !shaPattern.test(evidence.lastReviewedCommit)
172
- || !(evidence.prHead === null || shaPattern.test(evidence.prHead))) {
173
- return 'Clean completion evidence has an invalid structure';
174
- }
175
- if (evidence.head !== evidence.lastReviewedCommit
176
- || (evidence.prHead !== null && evidence.head !== evidence.prHead)
177
- || evidence.headTree !== evidence.worktreeTree) {
178
- return 'Clean completion evidence does not bind matching commit and tree identities';
179
- }
180
- if (run.status !== 'completed'
181
- || run.pendingDelegation !== null
182
- || run.receipts.some((receipt) => receipt.stage === 'commit')) {
183
- return 'Clean completion evidence conflicts with pending delegation or commit receipt state';
184
- }
185
- return null;
186
- }
187
- function validateAdapterReceiptEvidence(run) {
188
- const receipts = [...run.receipts, ...(run.pendingDelegation ? [run.pendingDelegation] : [])];
189
- for (const receipt of receipts) {
190
- const validate = getAgentClientAdapter(receipt.client).orchestrationAdapter?.validateReceiptEvidence;
191
- if (validate && !validate(receipt)) {
192
- return `Receipt '${receipt.id}' has invalid evidence from its agent adapter`;
193
- }
194
- }
195
- return null;
196
- }
197
- function checkOrchestrationEvidence({ taskDir }) {
198
- const file = path.join(taskDir, '.runtime', 'orchestration.json');
199
- const stat = safeStat(file);
200
- if (!stat?.isFile())
201
- return failResult('orchestration-evidence', 'orchestration.json is missing');
202
- let run;
203
- try {
204
- run = readRun(taskDir);
205
- }
206
- catch (error) {
207
- const message = error instanceof OrchestrationStateError ? error.message : String(error);
208
- return failResult('orchestration-evidence', `Invalid orchestration.json: ${message}`);
209
- }
210
- if (!run)
211
- return failResult('orchestration-evidence', 'orchestration.json is missing');
212
- const adapterEvidenceError = validateAdapterReceiptEvidence(run);
213
- if (adapterEvidenceError)
214
- return failResult('orchestration-evidence', adapterEvidenceError);
215
- // readRun validates the persisted schema, receipt identities and client provenance.
216
- const policy = run.modelPolicy;
217
- if (run.completionEvidence != null) {
218
- const evidenceError = validateCleanCompletionEvidence(run);
219
- if (evidenceError)
220
- return failResult('orchestration-evidence', evidenceError);
221
- }
222
- else if (run.status === 'completed') {
223
- return failResult('orchestration-evidence', 'Completed run requires reviewed-head-clean completion evidence');
224
- }
225
- if (run.pendingDelegation && !['prepared', 'activated', 'stage-completed'].includes(run.pendingDelegation.status)) {
226
- return failResult('orchestration-evidence', `Pending receipt has unsafe status '${run.pendingDelegation.status}'`);
227
- }
228
- const receipts = [...run.receipts, ...(run.pendingDelegation ? [run.pendingDelegation] : [])];
229
- for (const receipt of receipts) {
230
- const expectedPolicy = policy[receipt.role];
231
- if (!expectedPolicy || receipt.requestedModel !== expectedPolicy.model) {
232
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' requested model does not match its role policy`);
233
- }
234
- if (receipt.requestedReasoningEffort !== expectedPolicy.reasoningEffort) {
235
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' requested reasoning effort does not match its role policy`);
236
- }
237
- const activated = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status);
238
- if (activated) {
239
- const evidencePolicy = getAgentClientAdapter(receipt.client).delegationEvidence;
240
- if (evidencePolicy.actualModelRequired !== false) {
241
- if (!exactText(receipt.actualModel)) {
242
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has no host-observed actual model`);
243
- }
244
- }
245
- if (evidencePolicy.actualReasoningEffortRequired !== false) {
246
- if (!exactText(receipt.actualReasoningEffort)) {
247
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has no host-observed actual reasoning effort`);
248
- }
249
- }
250
- if (evidencePolicy.spawnModeRequired !== false && receipt.spawnMode !== 'fresh') {
251
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid fresh delegation identity`);
252
- }
253
- if (receipt.actualModel != null && receipt.actualModel !== receipt.requestedModel) {
254
- if (evidencePolicy.fallbackReasonRequired !== false && !exactText(receipt.modelFallbackReason)) {
255
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' model fallback is not justified`);
256
- }
257
- }
258
- if ((receipt.actualModel == null || receipt.actualModel === receipt.requestedModel)
259
- && receipt.modelFallbackReason !== null) {
260
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has an unrelated model fallback reason`);
261
- }
262
- if (receipt.actualReasoningEffort != null && receipt.actualReasoningEffort !== receipt.requestedReasoningEffort) {
263
- if (evidencePolicy.fallbackReasonRequired !== false && !exactText(receipt.reasoningEffortFallbackReason)) {
264
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' reasoning-effort fallback is not justified`);
265
- }
266
- }
267
- if ((receipt.actualReasoningEffort == null || receipt.actualReasoningEffort === receipt.requestedReasoningEffort)
268
- && receipt.reasoningEffortFallbackReason !== null) {
269
- return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has an unrelated reasoning-effort fallback reason`);
270
- }
271
- }
272
- }
273
- if (run.receipts.some((receipt) => receipt.status !== 'consumed')) {
274
- return failResult('orchestration-evidence', 'Historical receipts must be consumed');
275
- }
276
- return passResult('orchestration-evidence', 'Persisted orchestration model and delegation evidence is internally consistent');
277
- }
278
116
  // === Check Functions ===
279
117
  function checkTaskMeta({ taskDir, config, repositoryRoot, skillName, artifactFile }) {
280
118
  const task = loadTask(taskDir);
@@ -320,10 +158,7 @@ function checkTaskMeta({ taskDir, config, repositoryRoot, skillName, artifactFil
320
158
  if (expectedStep && metadata.current_step !== expectedStep) {
321
159
  let validLifecycleArtifact = false;
322
160
  if (currentTask) {
323
- const { section, invalidEntries } = inspectActivityLog(task.content);
324
- if (section && invalidEntries.length === 0) {
325
- validLifecycleArtifact = checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task, section.entries)?.status === "pass";
326
- }
161
+ validLifecycleArtifact = checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task)?.status === "pass";
327
162
  }
328
163
  if (!validLifecycleArtifact) {
329
164
  return failResult("task-meta", `Expected current_step '${expectedStep}', got '${metadata.current_step || "(empty)"}'`);
@@ -586,12 +421,6 @@ function checkImplementationInput({ taskDir, artifactFile }) {
586
421
  catch (error) {
587
422
  return failResult("implementation-input", `Invalid Implementation Inputs: ${error instanceof Error ? error.message : String(error)}`);
588
423
  }
589
- const doneActions = (inspectActivityLog(task.content).section?.entries ?? [])
590
- .filter((entry) => !ACTIVITY_LOG_STARTED_RE.test(entry.step))
591
- .map((entry) => entry.step)
592
- .filter((step) => /^(?:Code Task|Code) \(Round \d+/.test(step));
593
- const latestAction = doneActions.at(-1) || "";
594
- const actionDecision = /(?:Code Task|Code) \(Round \d+, decision (II-[1-9]\d*)\)/.exec(latestAction)?.[1] || null;
595
424
  const report = fs.readFileSync(artifactPath, "utf8");
596
425
  const reportSection = getSectionContent(report, ["实现输入", "Implementation Input"]);
597
426
  if (!reportSection)
@@ -604,36 +433,30 @@ function checkImplementationInput({ taskDir, artifactFile }) {
604
433
  const reportInput = field("裁决输入", "Decision Input");
605
434
  const reportLedger = field("账本 ID", "Ledger ID");
606
435
  const reportEvidence = field("裁决证据", "Decision Evidence");
607
- if (!actionDecision) {
608
- if (reportInput && reportInput !== "N/A") {
609
- return failResult("implementation-input", "Non-decision code action must report Decision Input as N/A");
610
- }
436
+ if (!reportInput || reportInput === "N/A") {
611
437
  return passResult("implementation-input", "Non-decision implementation input identity is consistent");
612
438
  }
613
- if (reportInput !== actionDecision) {
614
- return failResult("implementation-input", `Report decision input '${reportInput}' does not match Activity Log ${actionDecision}`);
615
- }
616
- const matches = rows.filter((row) => row.id === actionDecision);
439
+ const matches = rows.filter((row) => row.id === reportInput);
617
440
  if (matches.length !== 1)
618
- return failResult("implementation-input", `${actionDecision} is missing or duplicated in task table`);
441
+ return failResult("implementation-input", `${reportInput} is missing or duplicated in task table`);
619
442
  const row = matches[0];
620
443
  if (row.stage !== "code" || !row.needsImplementation || row.status !== "consumed" || row.consumedBy !== artifactFile || !row.decisionEvidence) {
621
- return failResult("implementation-input", `${actionDecision} is not a consumed input for ${artifactFile}`);
444
+ return failResult("implementation-input", `${reportInput} is not a consumed input for ${artifactFile}`);
622
445
  }
623
446
  if (reportLedger !== row.ledgerId || reportEvidence !== row.decisionEvidence) {
624
- return failResult("implementation-input", `${actionDecision} report identity does not match task table evidence`);
447
+ return failResult("implementation-input", `${reportInput} report identity does not match task table evidence`);
625
448
  }
626
- return passResult("implementation-input", `${actionDecision} matches Activity Log, report, and task table`);
449
+ return passResult("implementation-input", `${reportInput} matches report and task table`);
627
450
  }
628
451
  const ARTIFACT_ACTIVITY_STAGES = {
629
- "analyze-task": { family: "analysis", event: "analyze.completed", action: "Analyze Task" },
630
- "plan-task": { family: "plan", event: "plan.completed", action: "Plan Task" },
631
- "review-analysis": { family: "review-analysis", event: "review-analysis.completed", action: "Review Analysis" },
632
- "review-plan": { family: "review-plan", event: "review-plan.completed", action: "Review Plan" },
633
- "code-task": { family: "code", event: "code.completed", action: "Code Task" },
634
- "review-code": { family: "review-code", event: "review-code.completed", action: "Review Code" }
452
+ "analyze-task": { family: "analysis", event: "analyze.completed" },
453
+ "plan-task": { family: "plan", event: "plan.completed" },
454
+ "review-analysis": { family: "review-analysis", event: "review-analysis.completed" },
455
+ "review-plan": { family: "review-plan", event: "review-plan.completed" },
456
+ "code-task": { family: "code", event: "code.completed" },
457
+ "review-code": { family: "review-code", event: "review-code.completed" }
635
458
  };
636
- function checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task, entries) {
459
+ function checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task) {
637
460
  const stage = ARTIFACT_ACTIVITY_STAGES[skillName];
638
461
  if (!stage)
639
462
  return null;
@@ -649,38 +472,20 @@ function checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, tas
649
472
  if (!identity || identity.family !== stage.family) {
650
473
  return failResult("activity-log", `Artifact '${output}' does not belong to ${stage.family}`);
651
474
  }
652
- if (!hasArtifactCompletionFact(task.content, path.join(taskDir, output), stage.event)) {
475
+ if (!hasValidArtifactCompletion(task.content, taskDir, output, stage.event)) {
653
476
  return failResult("activity-log", `Completion fact for '${output}' is missing or stale; rerun ${skillName} to record a current completion`);
654
477
  }
655
- const frontmatter = parseTypedTaskFrontmatter(task.content);
656
- const fact = parseCompletionFacts(frontmatter.completion_facts).find((item) => item.event === stage.event && item.output === output);
657
- if (!fact)
658
- return failResult("activity-log", `Completion fact for '${output}' is missing; rerun ${skillName}`);
659
- if (!Array.isArray(fact.lifecycleInputs)) {
660
- return failResult("activity-log", `Completion fact for '${output}' has no input snapshot; rerun ${skillName}`);
661
- }
662
- for (const input of fact.lifecycleInputs) {
663
- if (!input || typeof input.name !== "string" || !/^[a-f0-9]{64}$/u.test(input.sha256)) {
664
- return failResult("activity-log", `Completion fact for '${output}' has an invalid input snapshot; rerun ${skillName}`);
665
- }
666
- const inputIdentity = parseArtifactName(input.name);
478
+ const receipts = parseArtifactReceipts(task.content).rows.filter((receipt) => receipt.output === output);
479
+ for (const receipt of receipts) {
480
+ const inputIdentity = parseArtifactName(receipt.input);
667
481
  if (!inputIdentity)
668
- return failResult("activity-log", `Completion fact for '${output}' has invalid input '${input.name}'; rerun ${skillName}`);
482
+ return failResult("activity-log", `Completion receipt for '${output}' has invalid input '${receipt.input}'; rerun ${skillName}`);
669
483
  const inputInventory = inspectArtifactDirectory(taskDir, inputIdentity.family);
670
- if (inputInventory.status !== "ready" || inputInventory.latest?.name !== input.name
671
- || sha256File(path.join(taskDir, input.name)) !== input.sha256) {
672
- return failResult("activity-log", `Input '${input.name}' changed or is no longer current; rerun ${skillName} to refresh '${output}'`);
484
+ if (inputInventory.status !== "ready" || inputInventory.latest?.name !== receipt.input
485
+ || sha256File(path.join(taskDir, receipt.input)) !== receipt.inputSha256) {
486
+ return failResult("activity-log", `Input '${receipt.input}' changed or is no longer current; rerun ${skillName} to refresh '${output}'`);
673
487
  }
674
488
  }
675
- const roundActionPattern = new RegExp(`^${stage.action} \\(Round ${identity.round}(?:, [^)]+)?\\)$`);
676
- const roundAction = entries.find((entry) => {
677
- return !ACTIVITY_LOG_STARTED_RE.test(entry.step)
678
- && roundActionPattern.test(entry.step)
679
- && entry.note.includes(`→ ${output}`);
680
- });
681
- if (!roundAction) {
682
- return failResult("activity-log", `No completed Activity Log row records '${output}' for ${skillName} Round ${identity.round}`);
683
- }
684
489
  return passResult("activity-log", `Current ${stage.family} completion '${output}' is valid for Round ${identity.round}`);
685
490
  }
686
491
  function checkActivityLog({ taskDir, skillName, artifactFile }) {
@@ -688,22 +493,22 @@ function checkActivityLog({ taskDir, skillName, artifactFile }) {
688
493
  if (!task.ok) {
689
494
  return failResult("activity-log", task.message);
690
495
  }
496
+ const artifactLifecycleResult = checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task);
497
+ if (artifactLifecycleResult && artifactLifecycleResult.status !== "pass")
498
+ return artifactLifecycleResult;
691
499
  const { section, invalidEntries } = inspectActivityLog(task.content);
500
+ const warnings = [];
692
501
  if (!section)
693
- return failResult("activity-log", "Activity Log section not found or ambiguous");
694
- if (invalidEntries.length)
695
- return failResult("activity-log", `Invalid Activity Log entry format: ${invalidEntries[0]}`);
696
- const entries = section.entries;
697
- if (entries.length === 0)
698
- return failResult("activity-log", "Activity Log has no entries");
699
- for (const entry of entries) {
700
- if (!entry.note.trim())
701
- return failResult("activity-log", "Activity Log entry note is required");
702
- }
703
- const artifactLifecycleResult = checkArtifactLifecycleActivityLog(taskDir, artifactFile, skillName, task, entries);
704
- if (artifactLifecycleResult)
705
- return artifactLifecycleResult;
706
- return passResult("activity-log", "Activity Log is valid");
502
+ warnings.push('Activity Log section is missing or ambiguous');
503
+ else {
504
+ if (invalidEntries.length)
505
+ warnings.push('Activity Log contains malformed entries');
506
+ if (!section.entries.length)
507
+ warnings.push('Activity Log has no entries');
508
+ if (section.entries.some((entry) => !entry.note.trim()))
509
+ warnings.push('Activity Log entry note is empty');
510
+ }
511
+ return passResult("activity-log", artifactLifecycleResult?.message ?? "Business checks are valid", warnings);
707
512
  }
708
513
  function checkCompletionChecklist({ taskDir, config }) {
709
514
  const task = loadTask(taskDir);
@@ -732,17 +537,7 @@ function checkCompletionChecklist({ taskDir, config }) {
732
537
  }
733
538
  return passResult("completion-checklist", `Completion Checklist valid (${items.length} items checked)`);
734
539
  }
735
- function resolveReviewSetting(config, key, fallback, repoRoot) {
736
- if (config && config[key] !== undefined && config[key] !== null) {
737
- return config[key];
738
- }
739
- const reviewConfig = loadPostReviewConfig(repoRoot);
740
- if (reviewConfig[key] !== undefined && reviewConfig[key] !== null) {
741
- return reviewConfig[key];
742
- }
743
- return fallback;
744
- }
745
- function checkReviewLedger({ taskDir, config, repositoryRoot }) {
540
+ function checkReviewLedger({ taskDir, config }) {
746
541
  const task = loadTask(taskDir);
747
542
  if (!task.ok) {
748
543
  return failResult("review-ledger", task.message);
@@ -818,8 +613,7 @@ async function checkManualValidation({ taskDir, repositoryRoot }) {
818
613
  if (!resolved.ok) {
819
614
  return failResult("manual-validation", `${parsed.summary.manualValidation} manual validation item(s) pending: run /complete-manual-validation`);
820
615
  }
821
- // 5. The Activity Log must record the matching completion entry; the file name
822
- // is derived with path.basename (resolveArtifactPath does not return fileName).
616
+ // 5. Validate the committed receipt, transaction, and artifact.
823
617
  const artifactName = path.basename(resolved.path);
824
618
  const task = loadTask(taskDir);
825
619
  if (!task.ok)
@@ -842,31 +636,22 @@ async function checkManualValidation({ taskDir, repositoryRoot }) {
842
636
  if (sha256File(resolved.path) !== receipt.artifactSha256) {
843
637
  return failResult("manual-validation", `Manual validation artifact digest does not match the receipt for ${artifactName}`);
844
638
  }
845
- // 6. Timing correlation (PL-3 fix, PL-4 corrected): the completion entry must
846
- // sit AFTER the latest review-code round's completion entry in the
847
- // append-only Activity Log. indexOf is a literal search, so the artifactName
848
- // must NOT be passed through escapeRegExp here (that escapes '.' to '\.',
849
- // which indexOf never matches). Not reusing completed.exec().index: exec
850
- // anchors to the first '**Complete Manual Validation**' heading, which can
851
- // belong to an earlier round's entry and misorder the standard path.
852
- const inspectedLog = inspectActivityLog(task.content);
853
- if (!inspectedLog.section)
854
- return failResult("manual-validation", "Activity Log is missing or invalid");
855
- const reviewRow = pairEntries(inspectedLog.section.entries).find((row) => row.step === `Review Code (Round ${review.round})` && row.started !== '' && row.done !== '');
856
- const reviewDoneIndex = reviewRow
857
- ? inspectedLog.section.entries.findIndex((entry) => entry.step === reviewRow.step && entry.time === reviewRow.done)
858
- : -1;
859
- const completedIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === "Complete Manual Validation"
860
- && entry.note.includes(`Manual validation passed → ${artifactName};`)
861
- && entry.note.includes(`transaction=${receipt.transactionId};`)
862
- && entry.note.includes(`receipt=${receipt.receiptDigest};`)
863
- && entry.note.includes(`head=${receipt.prHeadSha}`));
864
- if (reviewDoneIndex === -1)
865
- return failResult("manual-validation", `Latest review-code (round ${review.round}) completion entry is missing from the Activity Log`);
866
- if (completedIndex === -1)
867
- return failResult("manual-validation", `Committed manual validation completion is not recorded for ${artifactName}`);
868
- if (completedIndex < reviewDoneIndex)
869
- return failResult("manual-validation", `Latest review-code (round ${review.round}) came after the manual validation completion recorded for ${artifactName}`);
639
+ // 6. Compare the review completion and committed manual-validation times.
640
+ let reviewReceipt;
641
+ try {
642
+ reviewReceipt = receiptForOutput(task.content, review.fileName);
643
+ }
644
+ catch (error) {
645
+ return failResult("manual-validation", `Review-code receipt is invalid: ${error instanceof Error ? error.message : String(error)}`);
646
+ }
647
+ if (!reviewReceipt || reviewReceipt.event !== "review-code.completed") {
648
+ return failResult("manual-validation", `Review-code completion time is unavailable for ${review.fileName}`);
649
+ }
650
+ const reviewTime = Date.parse(reviewReceipt.completedAt.replace(' ', 'T'));
651
+ const validationTime = Date.parse(receipt.committedAt);
652
+ if (!Number.isFinite(reviewTime) || !Number.isFinite(validationTime) || validationTime <= reviewTime) {
653
+ return failResult("manual-validation", `Manual validation must be completed after review-code ${review.fileName}`);
654
+ }
870
655
  const fact = readPrDeliveryFact(task.metadata);
871
656
  if (fact.status === "invalid")
872
657
  return failResult("manual-validation", fact.error.message);
@@ -1069,12 +854,9 @@ function checkReviewFact({ taskDir, artifactFile, repositoryRoot }) {
1069
854
  return failResult("review-fact", task.message);
1070
855
  }
1071
856
  const content = fs.readFileSync(resolvedArtifact.path, "utf8");
1072
- if (!hasArtifactCompletionFact(task.content, resolvedArtifact.path, 'review-code.completed')) {
857
+ if (!hasValidArtifactCompletion(task.content, taskDir, path.basename(resolvedArtifact.path), 'review-code.completed')) {
1073
858
  return failResult("review-fact", `Review Code completion fact does not match ${path.basename(resolvedArtifact.path)}`);
1074
859
  }
1075
- if (!hasArtifactCompletionLog(task.content, path.basename(resolvedArtifact.path), 'review-code.completed')) {
1076
- return failResult("review-fact", `Review Code completion entry does not reference ${path.basename(resolvedArtifact.path)}`);
1077
- }
1078
860
  const verdict = parseReviewVerdict(content);
1079
861
  const reviewTargetHead = extractReviewTargetHead(content);
1080
862
  const reviewReviewedHead = extractReviewedHead(content);
@@ -1194,12 +976,6 @@ function normalizeContent(text) {
1194
976
  .replace(/\n{3,}/g, "\n\n")
1195
977
  .trim();
1196
978
  }
1197
- function interpolate(template, taskDir, artifactFile) {
1198
- const artifactStem = artifactFile ? path.basename(artifactFile, path.extname(artifactFile)) : "";
1199
- return template
1200
- .replace(/\{task-id\}/g, path.basename(taskDir))
1201
- .replace(/\{artifact-stem\}/g, artifactStem);
1202
- }
1203
979
  function summarizeGate(checks) {
1204
980
  if (checks.some((check) => check.effectiveStatus === "blocked")) {
1205
981
  return "blocked";
@@ -29,9 +29,7 @@ const VERIFICATION_CATALOG = {
29
29
  'import-dependabot.completed': gate('import-dependabot', 'active'),
30
30
  'import-issue.completed': gate('import-issue', 'active'),
31
31
  'watch-pr.completed': gate('watch-pr', 'active'),
32
- 'review-pr.completed': gate('review-pr', 'active', 'pr-review'),
33
- 'run-task.paused': { skill: 'run-task', expectedState: 'active', mode: 'checks', checks: ['orchestration-state', 'orchestration-evidence'] },
34
- 'run-task.completed': { skill: 'run-task', expectedState: 'active', mode: 'checks', checks: ['orchestration-state', 'orchestration-evidence'] }
32
+ 'review-pr.completed': gate('review-pr', 'active', 'pr-review')
35
33
  };
36
34
  function failure(request, code, message, extra = {}) {
37
35
  return {
@@ -117,6 +115,11 @@ function renderTaskVerification(result) {
117
115
  && typeof message === 'string'
118
116
  && /\bhuman-decided (?:post-review )?exemption\b/i.test(message)
119
117
  && /\bPRC-\d+\s*:/.test(message);
118
+ if (Array.isArray(check.warnings)) {
119
+ for (const warning of check.warnings)
120
+ if (typeof warning === 'string')
121
+ lines.push(`Warning: ${id} - ${warning}`);
122
+ }
120
123
  if (effectiveStatus === 'pass' && !isSoftWarning && !isHumanExemptionNotice)
121
124
  continue;
122
125
  lines.push(isSoftWarning
@@ -5,6 +5,7 @@ import { isValidAgentInfraVersion, VERSION } from '../version.js';
5
5
  import { parseTypedTaskFrontmatter, updateTaskFrontmatter } from './frontmatter.js';
6
6
  import { resolveTaskRef } from './resolve-ref.js';
7
7
  import { mutateTableRow, upsertSection } from './sections.js';
8
+ import { lifecycleExecutions, prReviewExecution, serializeLifecycleExecution } from './lifecycle-execution.js';
8
9
  import { validateCurrentTaskContract } from './current-contract.js';
9
10
  const DEFAULT_FILE_SYSTEM = {
10
11
  readFileSync: (file) => fs.readFileSync(file, 'utf8'),
@@ -104,7 +105,16 @@ function writeTaskCore(request, options = {}) {
104
105
  }
105
106
  const before = candidate;
106
107
  if (mutation.kind === 'frontmatter') {
107
- candidate = updateTaskFrontmatter(candidate, mutation.set, mutation.remove);
108
+ let set = mutation.set;
109
+ if (mutation.lifecycleExecutionDomain) {
110
+ const proposed = updateTaskFrontmatter(candidate, mutation.set);
111
+ const open = mutation.lifecycleExecutionDomain === 'ordinary'
112
+ ? lifecycleExecutions(proposed)
113
+ : lifecycleExecutions(candidate);
114
+ const pr = prReviewExecution(mutation.lifecycleExecutionDomain === 'pr-review' ? proposed : candidate);
115
+ set = { ...mutation.set, lifecycle_execution: serializeLifecycleExecution(open, undefined, pr) };
116
+ }
117
+ candidate = updateTaskFrontmatter(candidate, set, mutation.remove);
108
118
  operations.push({
109
119
  index,
110
120
  kind: 'frontmatter',
@@ -8,10 +8,6 @@ import type {
8
8
  AgentClientCapabilityMap,
9
9
  AgentClientId
10
10
  } from './types.ts';
11
- import type {
12
- OrchestrationOptions,
13
- OrchestrationResult
14
- } from '../task/orchestration.ts';
15
11
  import {
16
12
  SANDBOX_HOOK_PHASES
17
13
  } from '../sandbox/tool-types.ts';
@@ -42,56 +38,6 @@ type AgentClientModelSelectionContext =
42
38
  guidance: string;
43
39
  }>;
44
40
 
45
- type AgentClientDelegationEvidence = Readonly<{
46
- actualModel: 'host-event' | 'app-server' | 'unavailable';
47
- actualReasoningEffort: 'host-event' | 'app-server' | 'spawn-ack' | 'unavailable';
48
- spawnModeRequired?: boolean;
49
- actualModelRequired?: boolean;
50
- actualReasoningEffortRequired?: boolean;
51
- fallbackReasonRequired?: boolean;
52
- }>;
53
-
54
- type AgentClientLifecycleRecoveryRequest = Readonly<{
55
- taskRef: string;
56
- intent: 'recover-started';
57
- agent: string;
58
- auto: true;
59
- }>;
60
-
61
- type AgentClientLifecycleRecoveryResult = Readonly<{
62
- status: 'applied' | 'no-op' | 'owner-unknown' | 'conflict';
63
- changed: boolean;
64
- targetState: 'active';
65
- requestRef: string;
66
- intent: 'recover-started';
67
- taskId: string | null;
68
- receiptId: string | null;
69
- childId: string | null;
70
- error: Readonly<{ code: string; message: string }> | null;
71
- }>;
72
-
73
- type AgentClientOrchestrationAdapter = Readonly<{
74
- validateActivationEvidence?: (evidence: unknown, parentId: string) => boolean;
75
- validateReceiptEvidence?: (receipt: unknown) => boolean;
76
- createLaunchCarrier?: (
77
- adapterContext: string,
78
- identity: Readonly<{ stage: string; round: number; role: string }>
79
- ) => Readonly<Record<string, string>>;
80
- prepareDelegation?: (
81
- taskRef: string,
82
- input: Readonly<{
83
- client: AgentClientId;
84
- requestedModel?: string;
85
- requestedReasoningEffort?: string;
86
- }>,
87
- options?: Readonly<{ repoRoot?: string; orchestrationOptions?: OrchestrationOptions }>
88
- ) => Promise<OrchestrationResult>;
89
- recoverStarted?: (
90
- request: AgentClientLifecycleRecoveryRequest,
91
- options: Readonly<{ repoRoot: string }>
92
- ) => AgentClientLifecycleRecoveryResult | Promise<AgentClientLifecycleRecoveryResult>;
93
- }>;
94
-
95
41
  type AgentClientSeedCommand = Readonly<{
96
42
  templates: Readonly<{
97
43
  en: string;
@@ -123,8 +69,6 @@ type AgentClientAdapter = Readonly<{
123
69
  invocation: string;
124
70
  capabilities: AgentClientCapabilities;
125
71
  modelSelection: AgentClientModelSelectionContext;
126
- delegationEvidence: AgentClientDelegationEvidence;
127
- orchestrationAdapter?: AgentClientOrchestrationAdapter;
128
72
  project: AgentClientProjectDescriptor;
129
73
  sandbox: AgentClientSandboxDescriptor;
130
74
  }>;
@@ -399,18 +343,6 @@ function defineAgentClientAdapter(
399
343
  throw new Error(`Agent Client '${candidate.id}' has an invalid model-selection context`);
400
344
  }
401
345
 
402
- const evidence = candidate.delegationEvidence;
403
- if (
404
- !evidence
405
- || !['host-event', 'app-server', 'unavailable'].includes(evidence.actualModel)
406
- || !['host-event', 'app-server', 'spawn-ack', 'unavailable'].includes(evidence.actualReasoningEffort)
407
- || ['spawnModeRequired', 'actualModelRequired', 'actualReasoningEffortRequired', 'fallbackReasonRequired']
408
- .some((key) => evidence[key as keyof AgentClientDelegationEvidence] !== undefined
409
- && typeof evidence[key as keyof AgentClientDelegationEvidence] !== 'boolean')
410
- ) {
411
- throw new Error(`Agent Client '${candidate.id}' has invalid delegation evidence`);
412
- }
413
-
414
346
  if (
415
347
  typeof candidate.project !== 'object'
416
348
  || candidate.project === null
@@ -701,10 +633,6 @@ function defineAgentClientAdapter(
701
633
  invocation: candidate.invocation,
702
634
  capabilities: Object.freeze(capabilities),
703
635
  modelSelection: frozenModelSelection,
704
- delegationEvidence: Object.freeze({ ...evidence }),
705
- ...(candidate.orchestrationAdapter === undefined
706
- ? {}
707
- : { orchestrationAdapter: Object.freeze({ ...candidate.orchestrationAdapter }) }),
708
636
  project: Object.freeze({
709
637
  ownedPathPrefixes: Object.freeze(paths),
710
638
  ...projectAssets,
@@ -726,10 +654,6 @@ export type {
726
654
  AgentClientAdapter,
727
655
  AgentClientCapabilities,
728
656
  AgentClientCustomCommandDescriptor,
729
- AgentClientDelegationEvidence,
730
- AgentClientLifecycleRecoveryRequest,
731
- AgentClientLifecycleRecoveryResult,
732
- AgentClientOrchestrationAdapter,
733
657
  AgentClientManifestEntry,
734
658
  AgentClientModelSelectionContext,
735
659
  AgentClientProjectDescriptor,