@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,95 +1,43 @@
1
- import {
2
- inspectOrchestrationStage,
3
- pauseOrchestration,
4
- planOrchestrationStageCompletion
5
- } from './orchestration.ts';
6
- import type {
7
- OrchestrationStageCompletion,
8
- OrchestrationStageIdentity
9
- } from './orchestration.ts';
10
- import { resolveTaskRef } from './resolve-ref.ts';
1
+ import { parseTypedTaskFrontmatter } from './frontmatter.ts';
11
2
 
12
- type LifecycleExecutionMode = 'standalone' | 'orchestrated';
13
- type LifecycleExecutionRequest = Readonly<{
14
- mode: LifecycleExecutionMode;
15
- identity: OrchestrationStageIdentity;
16
- agent?: string;
17
- dryRun?: boolean;
18
- }>;
19
- type LifecycleExecutionResult = Readonly<{
20
- ok: boolean;
21
- mode: LifecycleExecutionMode;
22
- completionPlan: OrchestrationStageCompletion | null;
23
- error: Readonly<{ code: string; message: string }> | null;
24
- }>;
3
+ const labels = {
4
+ 'Analyze Task': 'analyze', 'Review Analysis': 'review-analysis', 'Plan Task': 'plan',
5
+ 'Review Plan': 'review-plan', 'Code Task': 'code', 'Review Code': 'review-code',
6
+ 'Run Manual Validation': 'validation-run'
7
+ } as const;
8
+ export type ExecutionFamily = typeof labels[keyof typeof labels] | 'manual-validation' | 'other';
9
+ export type LifecycleExecution = {
10
+ family: ExecutionFamily; agent: string; startedAt: string; round?: number;
11
+ fixFor?: string; implementationInput?: string; transactionId?: string;
12
+ };
25
13
 
26
- function failure(mode: LifecycleExecutionMode, code: string, message: string): LifecycleExecutionResult {
27
- return { ok: false, mode, completionPlan: null, error: { code, message } };
28
- }
29
-
30
- function inspectLifecycleExecution(
31
- taskRef: string,
32
- request: LifecycleExecutionRequest,
33
- options: Readonly<{
34
- repoRoot?: string;
35
- now?: () => string;
36
- }> = {}
37
- ): LifecycleExecutionResult {
38
- const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
39
- if (!resolved.ok) return failure(request.mode, resolved.code, resolved.message);
40
- if (request.mode === 'standalone') {
41
- return { ok: true, mode: request.mode, completionPlan: null, error: null };
42
- }
43
-
44
- if (request.agent) {
45
- const planned = planOrchestrationStageCompletion(taskRef, {
46
- ...request.identity,
47
- agent: request.agent
48
- }, options);
49
- if (planned.plan) {
50
- return { ok: true, mode: request.mode, completionPlan: planned.plan, error: null };
51
- }
52
- return failure(
53
- request.mode,
54
- planned.result.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH',
55
- planned.result.error?.message ?? 'orchestration provenance validation failed'
56
- );
14
+ export function lifecycleExecutions(content: string): LifecycleExecution[] {
15
+ const value = parseTypedTaskFrontmatter(content).lifecycle_execution;
16
+ if (value !== undefined) {
17
+ if (typeof value !== 'string') throw new Error('invalid lifecycle execution state');
18
+ const state: unknown = JSON.parse(value);
19
+ if (!state || typeof state !== 'object' || !('version' in state) || state.version !== 1 || !('open' in state) || !Array.isArray(state.open)) throw new Error('invalid lifecycle execution state');
20
+ return state.open.map((item: unknown) => {
21
+ if (!item || typeof item !== 'object' || !('family' in item) || typeof item.family !== 'string' || ![...Object.values(labels), 'manual-validation', 'other'].includes(item.family as ExecutionFamily) || !('agent' in item) || typeof item.agent !== 'string' || !('startedAt' in item) || typeof item.startedAt !== 'string') throw new Error('invalid lifecycle execution identity');
22
+ return item as LifecycleExecution;
23
+ });
57
24
  }
58
-
59
- const inspected = inspectOrchestrationStage(taskRef, request.identity, options);
60
- if (inspected.status !== 'failed') {
61
- return { ok: true, mode: request.mode, completionPlan: null, error: null };
62
- }
63
- return failure(
64
- request.mode,
65
- inspected.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH',
66
- inspected.error?.message ?? 'orchestration provenance validation failed'
67
- );
25
+ return [];
68
26
  }
69
27
 
70
- function validateLifecycleExecution(
71
- taskRef: string,
72
- request: LifecycleExecutionRequest,
73
- options: Readonly<{
74
- repoRoot?: string;
75
- now?: () => string;
76
- }> = {}
77
- ): LifecycleExecutionResult {
78
- const inspected = inspectLifecycleExecution(taskRef, request, options);
79
- if (inspected.ok || request.mode === 'standalone' || request.dryRun) return inspected;
80
- const paused = pauseOrchestration(
81
- taskRef,
82
- inspected.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH',
83
- inspected.error?.message ?? 'orchestration provenance validation failed',
84
- true,
85
- options
86
- );
87
- return failure(
88
- request.mode,
89
- paused.run?.pause?.code ?? inspected.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH',
90
- paused.run?.pause?.message ?? inspected.error?.message ?? 'orchestration provenance validation failed'
91
- );
28
+ export type PrReviewExecution = { open: { artifact: string; head: string; agent: string; startedAt: string } | null; terminals: Array<{ artifact: string; head: string; agent: string; note: string }> };
29
+ export function prReviewExecution(content: string): PrReviewExecution {
30
+ const value = parseTypedTaskFrontmatter(content).lifecycle_execution;
31
+ if (value === undefined) return { open: null, terminals: [] };
32
+ if (typeof value !== 'string') throw new Error('invalid lifecycle execution state');
33
+ const state = JSON.parse(value);
34
+ if (state.version !== 1 || !Array.isArray(state.open)) throw new Error('invalid lifecycle execution state');
35
+ const pr = state.prReview ?? { open: null, terminals: [] };
36
+ const valid = (item: any) => item && typeof item.artifact === 'string' && typeof item.head === 'string' && typeof item.agent === 'string';
37
+ if (!Array.isArray(pr.terminals) || (pr.open !== null && (!valid(pr.open) || typeof pr.open.startedAt !== 'string')) || !pr.terminals.every((item: any) => valid(item) && typeof item.note === 'string')) throw new Error('invalid PR review execution state');
38
+ return pr;
39
+ }
40
+ export function serializeLifecycleExecution(open: readonly LifecycleExecution[], content?: string, prReview?: PrReviewExecution): string {
41
+ const pr = prReview ?? (content ? prReviewExecution(content) : { open: null, terminals: [] });
42
+ return JSON.stringify({ version: 1, open, prReview: pr });
92
43
  }
93
-
94
- export { inspectLifecycleExecution, validateLifecycleExecution };
95
- export type { LifecycleExecutionMode, LifecycleExecutionRequest, LifecycleExecutionResult };
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
4
 
5
- import { appendActivityEntry, locateActivityLog } from './activity-log.ts';
5
+ import { activityWarnings, appendActivityEntry, locateActivityLog } from './activity-log.ts';
6
6
  import { artifactFamilyCatalog, inspectArtifactDirectory } from './artifact-lifecycle.ts';
7
7
  import { parseArtifactName } from './artifact-name.ts';
8
8
  import { parseTypedTaskFrontmatter, updateTaskFrontmatter } from './frontmatter.ts';
@@ -21,7 +21,7 @@ import { resourceIdentityEquals } from '../platform/resource-identity.ts';
21
21
  import { resolveProjectTaskWorkspaceRoot } from './workspace-root.ts';
22
22
 
23
23
  const lifecycleIntentCatalog = [
24
- 'block', 'activate', 'cancel', 'complete', 'close-codescan', 'close-dependabot', 'restore', 'recover-started'
24
+ 'block', 'activate', 'cancel', 'complete', 'close-codescan', 'close-dependabot', 'restore'
25
25
  ] as const;
26
26
  const lifecycleFailureCatalog = [
27
27
  'LIFECYCLE_DIRECTORY_TRANSFER_FAILED',
@@ -60,8 +60,7 @@ type TaskLifecycleRequest =
60
60
  | { taskRef: string; intent: 'complete'; agent: string; dryRun?: boolean }
61
61
  | { taskRef: string; intent: 'close-codescan'; agent: string; alertNumber: number; reason: string; dryRun?: boolean }
62
62
  | { taskRef: string; intent: 'close-dependabot'; agent: string; alertNumber: number; reason: string; dryRun?: boolean }
63
- | { taskRef: string; intent: 'restore'; agent: string; stagingDir: string; issueNumber: number; dryRun?: boolean }
64
- | { taskRef: string; intent: 'recover-started'; agent: string; auto: true; dryRun?: boolean };
63
+ | { taskRef: string; intent: 'restore'; agent: string; stagingDir: string; issueNumber: number; dryRun?: boolean };
65
64
 
66
65
  type HotState = 'active' | 'blocked' | 'completed';
67
66
  type SourceState = HotState | 'staging';
@@ -97,6 +96,7 @@ type TaskLifecycleResult = {
97
96
  completedSteps: readonly LifecycleStep[];
98
97
  pendingSteps: readonly LifecycleStep[];
99
98
  error: LifecycleError | null;
99
+ warnings?: readonly { code: string; message: string }[];
100
100
  };
101
101
  type LifecycleFileSystem = {
102
102
  renameSync: (source: string, target: string) => void;
@@ -160,14 +160,6 @@ function failed(request: Pick<TaskLifecycleRequest, 'taskRef' | 'intent'>, error
160
160
  };
161
161
  }
162
162
 
163
- export function taskLifecycleFailure(
164
- request: Pick<TaskLifecycleRequest, 'taskRef' | 'intent'>,
165
- error: LifecycleError,
166
- taskId: string | null = null
167
- ): TaskLifecycleResult {
168
- return failed(request, error, { taskId });
169
- }
170
-
171
163
  function normalizedRequest(request: TaskLifecycleRequest): TaskLifecycleRequest | LifecycleError {
172
164
  if (!request || typeof request !== 'object' || !lifecycleIntentCatalog.includes(request.intent as TaskLifecycleIntent)) {
173
165
  return { code: 'LIFECYCLE_PAYLOAD_INVALID', message: 'intent is not in the lifecycle catalog' };
@@ -368,32 +360,17 @@ function taskBoundControlMoveSafety(
368
360
  return null;
369
361
  }
370
362
 
371
- function orchestrationMoveSafety(sourcePath: string): LifecycleError | null {
372
- const orchestrationPath = path.join(sourcePath, '.runtime', 'orchestration.json');
373
- if (!pathExists(orchestrationPath)) return null;
374
- try {
375
- const run = JSON.parse(fs.readFileSync(orchestrationPath, 'utf8')) as { status?: unknown; pendingDelegation?: unknown };
376
- if (run.status === 'running' || run.pendingDelegation !== null && run.pendingDelegation !== undefined) {
377
- return { code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE', message: 'task orchestration has an active or pending delegation; settle it before moving the task directory' };
378
- }
379
- } catch {
380
- return { code: 'LIFECYCLE_RUNTIME_MOVE_UNSAFE', message: 'task orchestration state is unreadable; refusing to move the task directory' };
381
- }
382
- return null;
383
- }
384
-
385
363
  function runtimeMoveSafety(
386
364
  request: TaskLifecycleRequest,
387
365
  movingTaskDirectory: boolean,
388
366
  options: TaskLifecycleOptions,
389
367
  taskId: string,
390
368
  repoRoot: string,
391
- sourcePath: string,
392
369
  validateControlManifestIdentity: boolean
393
370
  ): LifecycleError | null {
394
371
  if (!movingTaskDirectory) return null;
395
372
  const controlSafety = taskBoundControlMoveSafety(request, options.controlRoot, options, taskId, repoRoot, validateControlManifestIdentity);
396
- return controlSafety ?? orchestrationMoveSafety(sourcePath);
373
+ return controlSafety;
397
374
  }
398
375
 
399
376
  function targetContainsTask(targetPath: string, taskId: string, request: TaskLifecycleRequest): boolean {
@@ -422,15 +399,26 @@ function actionAndNote(request: TaskLifecycleRequest, restoredFiles = 0): { acti
422
399
  if (request.intent === 'complete') return { action: 'Complete Task', note: 'Task moved to completed/' };
423
400
  if (request.intent === 'close-codescan') return { action: 'Close Codescan', note: `Code Scanning alert #${request.alertNumber} dismissed: ${request.reason}` };
424
401
  if (request.intent === 'close-dependabot') return { action: 'Close Dependabot', note: `Dependabot alert #${request.alertNumber} dismissed: ${request.reason}` };
425
- if (request.intent === 'recover-started') return { action: 'Recover Started', note: 'automatic recovery' };
426
402
  return { action: 'Restore Task', note: `Restored ${restoredFiles} files from Issue #${request.issueNumber}` };
427
403
  }
428
404
 
405
+ type LifecycleCompletionKey = { action: string; agent: string; note: string };
406
+
407
+ function completionKeys(content: string): LifecycleCompletionKey[] {
408
+ const value = parseTypedTaskFrontmatter(content).lifecycle_transition;
409
+ if (value === undefined) return [];
410
+ if (typeof value !== 'string') throw new Error('invalid lifecycle transition');
411
+ const state: unknown = JSON.parse(value);
412
+ if (!state || typeof state !== 'object' || !('completedKeys' in state) || !Array.isArray(state.completedKeys)) throw new Error('invalid lifecycle transition');
413
+ return state.completedKeys.map((key: unknown) => {
414
+ if (!key || typeof key !== 'object' || !('action' in key) || typeof key.action !== 'string' || !('agent' in key) || typeof key.agent !== 'string' || !('note' in key) || typeof key.note !== 'string') throw new Error('invalid lifecycle completion identity');
415
+ return key as LifecycleCompletionKey;
416
+ });
417
+ }
418
+
429
419
  function matchingCompletion(content: string, request: TaskLifecycleRequest, restoredFiles = 0): boolean {
430
- const section = locateActivityLog(content);
431
- if (!section) return false;
432
420
  const identity = actionAndNote(request, restoredFiles);
433
- return section.entries.some((entry) => entry.step === identity.action && entry.agent === request.agent && entry.note === identity.note);
421
+ return completionKeys(content).some((entry) => entry.action === identity.action && entry.agent === request.agent && entry.note === identity.note);
434
422
  }
435
423
 
436
424
  function validateRestoreStaging(request: Extract<TaskLifecycleRequest, { intent: 'restore' }>, repoRoot: string, taskId: string): LifecycleError | { stagingDir: string; fileCount: number } {
@@ -483,12 +471,17 @@ function validateRestoreStaging(request: Extract<TaskLifecycleRequest, { intent:
483
471
  return { stagingDir, fileCount: entries.filter((entry) => !entry.name.startsWith('.')).length };
484
472
  }
485
473
 
486
- function mutationsFor(request: TaskLifecycleRequest, content: string, metadata: TaskWriteMetadata, restoredFiles: number, allowMissingActivityLog = false): TaskMutation[] | LifecycleError {
487
- const section = locateActivityLog(content) ?? (allowMissingActivityLog ? { heading: 'Activity Log', body: '', entries: [] } : null);
488
- if (!section) return { code: 'LIFECYCLE_LOG_MISSING', message: 'task has no unique Activity Log section' };
489
- const identity = actionAndNote(request, restoredFiles);
474
+ function lifecycleActivityMutation(content: string, request: TaskLifecycleRequest, metadata: TaskWriteMetadata, identity: { action: string; note: string }, allowMissing: boolean): TaskMutation[] {
475
+ const section = locateActivityLog(content) ?? (allowMissing ? { heading: 'Activity Log', body: '', entries: [] } : null);
476
+ if (!section) return [];
490
477
  let body = appendActivityEntry(section, { time: metadata.timestamp, step: `${identity.action} [started]`, agent: request.agent, note: 'started' });
491
478
  body = appendActivityEntry({ ...section, body }, { time: metadata.timestamp, step: identity.action, agent: request.agent, note: identity.note });
479
+ return [{ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading, body }];
480
+ }
481
+
482
+ function mutationsFor(request: TaskLifecycleRequest, content: string, metadata: TaskWriteMetadata, restoredFiles: number, allowMissingActivityLog = false): TaskMutation[] | LifecycleError {
483
+ const identity = actionAndNote(request, restoredFiles);
484
+ const activityMutation = lifecycleActivityMutation(content, request, metadata, identity, allowMissingActivityLog);
492
485
  const set: Record<string, string> = {};
493
486
  const remove: string[] = [];
494
487
  if (request.intent === 'block') {
@@ -506,9 +499,12 @@ function mutationsFor(request: TaskLifecycleRequest, content: string, metadata:
506
499
  const frontmatter = parseTypedTaskFrontmatter(content);
507
500
  if (frontmatter.target_date === '') set.target_date = metadata.timestamp.slice(0, 10);
508
501
  }
502
+ const completedKeys = completionKeys(content);
503
+ if (!matchingCompletion(content, request, restoredFiles)) completedKeys.push({ ...identity, agent: request.agent });
504
+ set.lifecycle_transition = JSON.stringify({ completedKeys });
509
505
  const mutations: TaskMutation[] = [
510
506
  { kind: 'frontmatter', set, remove: [...new Set(remove)] },
511
- { kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading, body }
507
+ ...activityMutation
512
508
  ];
513
509
  if (request.intent === 'block') {
514
510
  mutations.splice(1, 0, {
@@ -630,9 +626,6 @@ export function inspectTaskLifecycleProgress(
630
626
  }
631
627
 
632
628
  function applyTaskLifecycle(requestInput: TaskLifecycleRequest, options: TaskLifecycleOptions = {}): TaskLifecycleResult {
633
- if (requestInput.intent === 'recover-started') {
634
- return failed(requestInput, { code: 'LIFECYCLE_RECOVERY_REQUIRES_AUTHORITY', message: 'recover-started must be dispatched through task control authority' });
635
- }
636
629
  const normalized = normalizedRequest(requestInput);
637
630
  if ('code' in normalized) return failed(requestInput, normalized);
638
631
  const request = normalized;
@@ -696,14 +689,13 @@ function applyTaskLifecycle(requestInput: TaskLifecycleRequest, options: TaskLif
696
689
  && !(request.intent === 'complete' && targetContainsTask(targetPath, taskId, request))) {
697
690
  return failed(request, { code: 'LIFECYCLE_TARGET_CONFLICT', message: `target directory already exists: ${targetPath}` }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
698
691
  }
699
- const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot, sourcePath, true);
692
+ const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot, true);
700
693
  if (moveSafety) return failed(request, moveSafety, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
701
694
  const content = io.readFileSync(currentTaskFile);
702
695
  let frontmatter;
703
696
  try { frontmatter = parseTypedTaskFrontmatter(content); }
704
697
  catch (error) { return failed(request, { code: 'LIFECYCLE_DOCUMENT_INVALID', message: error instanceof Error ? error.message : String(error) }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath }); }
705
698
  if (frontmatter.id !== taskId) return failed(request, { code: 'LIFECYCLE_IDENTITY_INVALID', message: 'task.md id does not match its lifecycle task id' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
706
- if (!locateActivityLog(content)) return failed(request, { code: 'LIFECYCLE_LOG_MISSING', message: 'task has no unique Activity Log section' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
707
699
  if (spec.target === 'active') {
708
700
  const contract = validateCurrentTaskContract(content);
709
701
  if (!contract.ok) return failed(request, { code: 'LIFECYCLE_DOCUMENT_INVALID', message: contract.message }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
@@ -823,7 +815,7 @@ function applyTaskLifecycle(requestInput: TaskLifecycleRequest, options: TaskLif
823
815
  }
824
816
  if (fs.existsSync(targetPath) && !fs.existsSync(path.join(sourcePath, 'task.md'))) completed.add('directory-moved');
825
817
  if (!completed.has('directory-moved')) {
826
- const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot, sourcePath, false);
818
+ const moveSafety = runtimeMoveSafety(request, movingTaskDirectory, options, taskId, repoRoot, false);
827
819
  if (moveSafety) return failed(request, moveSafety, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath, completedSteps: [...completed], changed: completed.size > 0, timestamp: journal.metadata.timestamp, agentInfraVersion: journal.metadata.agentInfraVersion });
828
820
  fs.mkdirSync(path.dirname(targetPath), { recursive: true });
829
821
  if (request.intent === 'complete') {
@@ -925,9 +917,21 @@ function applyTaskLifecycle(requestInput: TaskLifecycleRequest, options: TaskLif
925
917
  };
926
918
  }
927
919
 
920
+ function applyTaskLifecycleWithWarnings(request: TaskLifecycleRequest, options: TaskLifecycleOptions = {}): TaskLifecycleResult {
921
+ const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
922
+ const taskFile = resolved.ok ? resolved.taskMdPath : request.intent === 'restore' ? path.join(request.stagingDir, 'task.md') : null;
923
+ let warnings: ReturnType<typeof activityWarnings> = [];
924
+ if (taskFile) {
925
+ try { warnings = activityWarnings(fs.readFileSync(taskFile, 'utf8')); }
926
+ catch { /* The lifecycle operation reports its own read failure. */ }
927
+ }
928
+ const result = applyTaskLifecycle(request, options);
929
+ return result.status === 'failed' || !warnings.length ? result : { ...result, warnings };
930
+ }
931
+
928
932
  export {
929
933
  lifecycleIntentCatalog, lifecycleFailureCatalog, lifecycleProducerCatalog,
930
- applyTaskLifecycle, previewTaskCompletion
934
+ applyTaskLifecycleWithWarnings as applyTaskLifecycle, previewTaskCompletion
931
935
  };
932
936
  export type {
933
937
  TaskLifecycleIntent, TaskLifecycleRequest, TaskLifecycleResult, TaskLifecycleOptions,
@@ -183,12 +183,6 @@ function prepareLocalArtifact(
183
183
 
184
184
  }
185
185
 
186
- function commitLocalArtifactProvenance(
187
- prepared: LocalArtifactPreparation
188
- ): LocalArtifactFinalizationResult {
189
- return prepared.result;
190
- }
191
-
192
186
  function finalizeLocalArtifact(
193
187
  request: LocalArtifactFinalizationRequest
194
188
  ): LocalArtifactFinalizationResult {
@@ -208,7 +202,6 @@ export {
208
202
  finalizeLocalArtifact,
209
203
  preflightLocalArtifact,
210
204
  prepareLocalArtifact,
211
- commitLocalArtifactProvenance,
212
205
  canonicalSemanticDigest as semanticDigest,
213
206
  sha256Content,
214
207
  validateLocalArtifact
@@ -1,5 +1,3 @@
1
- import fs from 'node:fs';
2
- import { createHash } from 'node:crypto';
3
1
  import {
4
2
  MANUAL_VALIDATION_SHA40 as SHA40,
5
3
  MANUAL_VALIDATION_TASK_ID as TASK_ID,
@@ -47,11 +45,6 @@ type ManualValidationEvidenceInput = {
47
45
  signal: string | null;
48
46
  cleanup: ManualValidationCleanup;
49
47
  };
50
- type ManualValidationEvidenceIdentity = {
51
- taskId: string | null;
52
- branch: string;
53
- commit?: string;
54
- };
55
48
  type ManualValidationEvidenceErrorCode =
56
49
  | 'MANUAL_VALIDATION_EVIDENCE_MISSING'
57
50
  | 'MANUAL_VALIDATION_EVIDENCE_INVALID'
@@ -151,56 +144,17 @@ function manualValidationEvidenceSummary(evidence: ManualValidationEvidence): Ma
151
144
  };
152
145
  }
153
146
 
154
- function validateManualValidationEvidence(value: unknown, expected?: ManualValidationEvidenceIdentity): ManualValidationEvidenceResult {
155
- const shape = validateShape(value);
156
- if (!shape.ok) return shape;
157
- const evidence = shape.value;
158
- if (evidence.result.exitCode !== 0 || evidence.result.signal !== null || evidence.result.cleanup !== 'completed') {
159
- return { ok: false, error: { code: 'MANUAL_VALIDATION_EVIDENCE_UNSUCCESSFUL', message: 'validation must exit 0 without a signal and complete cleanup' } };
160
- }
161
- if (expected) {
162
- if (evidence.taskId !== expected.taskId || evidence.branch !== expected.branch) {
163
- return { ok: false, error: { code: 'MANUAL_VALIDATION_EVIDENCE_IDENTITY_MISMATCH', message: 'evidence task or branch does not match the expected identity' } };
164
- }
165
- if (expected.commit !== undefined && evidence.commit !== expected.commit) {
166
- return { ok: false, error: { code: 'MANUAL_VALIDATION_EVIDENCE_STALE', message: 'evidence commit does not match the current head' } };
167
- }
168
- }
169
- return shape;
170
- }
171
-
172
- function readManualValidationEvidence(file: string, expected?: ManualValidationEvidenceIdentity): ManualValidationEvidenceResult {
173
- let parsed: unknown;
174
- try {
175
- parsed = JSON.parse(fs.readFileSync(file, 'utf8')) as unknown;
176
- } catch (error) {
177
- const code = (error as NodeJS.ErrnoException).code === 'ENOENT'
178
- ? 'MANUAL_VALIDATION_EVIDENCE_MISSING'
179
- : 'MANUAL_VALIDATION_EVIDENCE_INVALID';
180
- return { ok: false, error: { code, message: error instanceof Error ? error.message : String(error) } };
181
- }
182
- return validateManualValidationEvidence(parsed, expected);
183
- }
184
-
185
- function manualValidationEvidenceDigest(evidence: ManualValidationEvidence): string {
186
- return createHash('sha256').update(JSON.stringify(evidence), 'utf8').digest('hex');
187
- }
188
-
189
147
  export {
190
148
  MANUAL_VALIDATION_EVIDENCE_SCHEMA,
191
149
  MANUAL_VALIDATION_EVIDENCE_VERSION,
192
150
  createManualValidationEvidence,
193
- manualValidationEvidenceSummary,
194
- manualValidationEvidenceDigest,
195
- readManualValidationEvidence,
196
- validateManualValidationEvidence
151
+ manualValidationEvidenceSummary
197
152
  };
198
153
  export type {
199
154
  ManualValidationCleanup,
200
155
  ManualValidationEvidence,
201
156
  ManualValidationEvidenceError,
202
157
  ManualValidationEvidenceErrorCode,
203
- ManualValidationEvidenceIdentity,
204
158
  ManualValidationEvidenceInput,
205
159
  ManualValidationEvidenceResult,
206
160
  ManualValidationEvidenceSummary,