@fitlab-ai/agent-infra 0.9.7 → 0.9.9

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 (195) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/bin/internal-cli.js +11 -1
  4. package/dist/lib/agent-clients/adapters/claude-code.js +3 -3
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +60 -22
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +8 -1
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +175 -11
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +147 -0
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +14 -0
  10. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +86 -69
  11. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +2 -1
  12. package/dist/lib/decide.js +68 -14
  13. package/dist/lib/git/workflow.js +10 -1
  14. package/dist/lib/init.js +1 -1
  15. package/dist/lib/internal/codex-lifecycle.js +19 -5
  16. package/dist/lib/internal/codex-sandbox-controller.js +6 -13
  17. package/dist/lib/internal/git-workflow.js +5 -7
  18. package/dist/lib/internal/platform-pr.js +20 -7
  19. package/dist/lib/internal/release-workflow.js +3 -4
  20. package/dist/lib/internal/sandbox-control.js +79 -2
  21. package/dist/lib/internal/task-activity.js +57 -7
  22. package/dist/lib/internal/task-event.js +57 -4
  23. package/dist/lib/internal/task-finalization.js +54 -0
  24. package/dist/lib/internal/task-ledger.js +59 -5
  25. package/dist/lib/internal/task-lifecycle.js +59 -8
  26. package/dist/lib/internal/task-orchestration.js +161 -288
  27. package/dist/lib/internal/task-override.js +131 -0
  28. package/dist/lib/internal/task-review.js +64 -6
  29. package/dist/lib/internal/task-verify.js +65 -3
  30. package/dist/lib/internal/task-warning.js +57 -4
  31. package/dist/lib/platform/pr-summary.js +53 -13
  32. package/dist/lib/platform/pull-requests.js +205 -41
  33. package/dist/lib/runtime/agent-runtime.js +56 -0
  34. package/dist/lib/sandbox/commands/create.js +389 -311
  35. package/dist/lib/sandbox/commands/rm.js +316 -55
  36. package/dist/lib/sandbox/control/client.js +190 -6
  37. package/dist/lib/sandbox/control/container-identity.js +1 -1
  38. package/dist/lib/sandbox/control/controller-registration.js +273 -0
  39. package/dist/lib/sandbox/control/executor.js +145 -5
  40. package/dist/lib/sandbox/control/lifecycle.js +395 -73
  41. package/dist/lib/sandbox/control/protocol.js +67 -6
  42. package/dist/lib/sandbox/control/state.js +27 -11
  43. package/dist/lib/sandbox/engine.js +14 -7
  44. package/dist/lib/sandbox/index.js +5 -3
  45. package/dist/lib/sandbox/managed-fs.js +5 -0
  46. package/dist/lib/sandbox/mounts.js +20 -5
  47. package/dist/lib/sandbox/recovery.js +78 -10
  48. package/dist/lib/sandbox/task-resolver.js +50 -6
  49. package/dist/lib/sandbox/workspace-identity.js +27 -0
  50. package/dist/lib/sandbox/workspace-view.js +62 -40
  51. package/dist/lib/sandbox/worktree-safety.js +215 -2
  52. package/dist/lib/server/process-state.js +51 -1
  53. package/dist/lib/task/activity-intent.js +4 -1
  54. package/dist/lib/task/codex-orchestration.js +158 -33
  55. package/dist/lib/task/commands/status.js +59 -1
  56. package/dist/lib/task/commit-operation.js +335 -0
  57. package/dist/lib/task/commit-policy.js +18 -0
  58. package/dist/lib/task/decision-intents.js +4 -2
  59. package/dist/lib/task/delegation-receipts.js +279 -17
  60. package/dist/lib/task/events.js +9 -5
  61. package/dist/lib/task/finalization.js +567 -0
  62. package/dist/lib/task/guard-override.js +31 -0
  63. package/dist/lib/task/human-override.js +1240 -0
  64. package/dist/lib/task/ledger-intents.js +6 -3
  65. package/dist/lib/task/lifecycle.js +69 -14
  66. package/dist/lib/task/operation-outcome.js +33 -0
  67. package/dist/lib/task/orchestration.js +199 -719
  68. package/dist/lib/task/review-finalization.js +3 -2
  69. package/dist/lib/task/short-id.js +59 -1
  70. package/dist/lib/task/task-execution-lock.js +6 -1
  71. package/dist/lib/task/verification-engine.js +138 -59
  72. package/dist/lib/task/verification.js +15 -2
  73. package/dist/lib/task/workflow-warning-intents.js +54 -3
  74. package/dist/lib/task/write.js +2 -1
  75. package/dist/lifecycle-build-manifest.json +3 -3
  76. package/lib/agent-clients/adapters/claude-code.ts +3 -3
  77. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +63 -20
  78. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +12 -0
  79. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +278 -13
  80. package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +180 -0
  81. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +19 -0
  82. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +9 -1
  83. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +112 -93
  84. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +2 -1
  85. package/lib/decide.ts +59 -14
  86. package/lib/git/workflow.ts +11 -2
  87. package/lib/init.ts +1 -1
  88. package/lib/internal/codex-lifecycle.ts +18 -5
  89. package/lib/internal/codex-sandbox-controller.ts +6 -12
  90. package/lib/internal/git-workflow.ts +5 -6
  91. package/lib/internal/platform-pr.ts +14 -7
  92. package/lib/internal/release-workflow.ts +3 -4
  93. package/lib/internal/sandbox-control.ts +92 -2
  94. package/lib/internal/task-activity.ts +46 -6
  95. package/lib/internal/task-event.ts +53 -4
  96. package/lib/internal/task-finalization.ts +68 -0
  97. package/lib/internal/task-ledger.ts +48 -4
  98. package/lib/internal/task-lifecycle.ts +56 -12
  99. package/lib/internal/task-orchestration.ts +32 -107
  100. package/lib/internal/task-override.ts +138 -0
  101. package/lib/internal/task-review.ts +51 -6
  102. package/lib/internal/task-verify.ts +52 -3
  103. package/lib/internal/task-warning.ts +44 -3
  104. package/lib/platform/pr-summary.ts +65 -14
  105. package/lib/platform/pull-requests.ts +211 -41
  106. package/lib/runtime/agent-runtime.ts +76 -0
  107. package/lib/sandbox/commands/create.ts +88 -4
  108. package/lib/sandbox/commands/rm.ts +413 -61
  109. package/lib/sandbox/config.ts +2 -1
  110. package/lib/sandbox/control/client.ts +255 -6
  111. package/lib/sandbox/control/container-identity.ts +3 -3
  112. package/lib/sandbox/control/controller-registration.ts +347 -0
  113. package/lib/sandbox/control/executor.ts +172 -6
  114. package/lib/sandbox/control/lifecycle.ts +465 -77
  115. package/lib/sandbox/control/protocol.ts +85 -9
  116. package/lib/sandbox/control/state.ts +35 -18
  117. package/lib/sandbox/engine.ts +20 -9
  118. package/lib/sandbox/index.ts +5 -3
  119. package/lib/sandbox/managed-fs.ts +5 -0
  120. package/lib/sandbox/mounts.ts +23 -5
  121. package/lib/sandbox/recovery.ts +90 -9
  122. package/lib/sandbox/task-resolver.ts +58 -7
  123. package/lib/sandbox/workspace-identity.ts +50 -2
  124. package/lib/sandbox/workspace-view.ts +73 -43
  125. package/lib/sandbox/worktree-safety.ts +236 -2
  126. package/lib/server/process-state.ts +48 -1
  127. package/lib/task/activity-intent.ts +4 -2
  128. package/lib/task/codex-orchestration.ts +167 -33
  129. package/lib/task/commands/status.ts +78 -1
  130. package/lib/task/commit-operation.ts +430 -0
  131. package/lib/task/commit-policy.ts +30 -0
  132. package/lib/task/decision-intents.ts +4 -2
  133. package/lib/task/delegation-receipts.ts +304 -19
  134. package/lib/task/events.ts +10 -5
  135. package/lib/task/finalization.ts +719 -0
  136. package/lib/task/guard-override.ts +50 -0
  137. package/lib/task/human-override.ts +1503 -0
  138. package/lib/task/ledger-intents.ts +6 -3
  139. package/lib/task/lifecycle.ts +71 -14
  140. package/lib/task/operation-outcome.ts +48 -0
  141. package/lib/task/orchestration.ts +239 -922
  142. package/lib/task/review-finalization.ts +6 -2
  143. package/lib/task/short-id.ts +65 -1
  144. package/lib/task/task-execution-lock.ts +10 -1
  145. package/lib/task/verification-engine.ts +145 -64
  146. package/lib/task/verification.ts +18 -3
  147. package/lib/task/workflow-warning-intents.ts +61 -4
  148. package/lib/task/write.ts +4 -1
  149. package/package.json +2 -2
  150. package/templates/.agents/QUICKSTART.en.md +2 -2
  151. package/templates/.agents/QUICKSTART.zh-CN.md +2 -2
  152. package/templates/.agents/hooks/lifecycle-delegation.js +9 -24
  153. package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -3
  154. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -3
  155. package/templates/.agents/rules/task-management.en.md +2 -2
  156. package/templates/.agents/rules/task-management.zh-CN.md +2 -2
  157. package/templates/.agents/skills/block-task/SKILL.en.md +2 -4
  158. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -4
  159. package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
  160. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
  161. package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -2
  162. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -2
  163. package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -2
  164. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -2
  165. package/templates/.agents/skills/commit/SKILL.en.md +41 -125
  166. package/templates/.agents/skills/commit/SKILL.zh-CN.md +52 -123
  167. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  168. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  169. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +14 -43
  170. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +14 -49
  171. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  172. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  173. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -35
  174. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -35
  175. package/templates/.agents/skills/complete-task/SKILL.en.md +31 -38
  176. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +31 -38
  177. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  178. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  179. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
  180. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
  181. package/templates/.agents/skills/create-pr/SKILL.en.md +6 -4
  182. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +6 -4
  183. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
  184. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
  185. package/templates/.agents/skills/run-task/SKILL.en.md +5 -5
  186. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +5 -5
  187. package/templates/.agents/skills/run-task/reference/host-validation.en.md +3 -1
  188. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +3 -1
  189. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +1 -1
  190. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +1 -1
  191. package/templates/.codex/hooks.json +4 -4
  192. package/dist/lib/task/commit-finalization.js +0 -305
  193. package/dist/lib/task/commit-intent.js +0 -165
  194. package/lib/task/commit-finalization.ts +0 -419
  195. package/lib/task/commit-intent.ts +0 -230
@@ -4,6 +4,7 @@ import { declareImplementationInput, IMPLEMENTATION_INPUT_ALIASES, parseImplemen
4
4
  import { LEDGER_COLUMNS, LEDGER_HEADINGS, nextHdId, parseLedger, validateLedgerRows } from './ledger.js';
5
5
  import { resolveTaskRef } from './resolve-ref.js';
6
6
  import { writeTask } from './write.js';
7
+ import { allowsManualOverride } from './guard-override.js';
7
8
  const PREFIX = { analysis: 'AN', plan: 'PL', code: 'CD' };
8
9
  const RESPONSE = new Set(['accepted', 'adjusted', 'refuted', 'cannot-judge']);
9
10
  const DISPOSITION = new Set(['confirmed', 'closed', 'open', 'needs-human-decision']);
@@ -84,7 +85,8 @@ function applyLedgerIntent(intent, options = {}) {
84
85
  const resolved = resolveTaskRef(intent.taskRef, { repoRoot: options.repoRoot });
85
86
  if (!resolved.ok)
86
87
  return failed(intent, resolved.code, resolved.message, resolved.taskId);
87
- if (resolved.state !== 'active')
88
+ const stateOverride = allowsManualOverride(options.manualOverride, 'ledger-intent', 'TASK_STATE_MISMATCH');
89
+ if (resolved.state !== 'active' && !stateOverride)
88
90
  return failed(intent, 'TASK_STATE_MISMATCH', `task ${resolved.taskId} is ${resolved.state}, expected active`, resolved.taskId);
89
91
  let content;
90
92
  let rows;
@@ -176,7 +178,8 @@ function applyLedgerIntent(intent, options = {}) {
176
178
  ? new Set(['confirmed', 'open', 'needs-human-decision'])
177
179
  : before.status === 'cannot-judge' ? new Set(['open', 'needs-human-decision']) : new Set();
178
180
  const sameRoundMinorClose = before.status === 'open' && before.severity === 'minor' && intent.status === 'closed';
179
- if ((!sameRoundMinorClose && !allowed.has(intent.status)) || (intent.status === 'open' && Number(before.round) >= maxHandshakeRounds(resolved.repoRoot))) {
181
+ if (((!sameRoundMinorClose && !allowed.has(intent.status)) || (intent.status === 'open' && Number(before.round) >= maxHandshakeRounds(resolved.repoRoot)))
182
+ && !allowsManualOverride(options.manualOverride, 'ledger-intent', 'LEDGER_TRANSITION_INVALID')) {
180
183
  return failed(intent, 'LEDGER_TRANSITION_INVALID', `finding '${intent.id}' cannot transition from ${before.status} to ${intent.status}`, resolved.taskId, intent.id);
181
184
  }
182
185
  after = { ...before, status: intent.status, evidence };
@@ -209,7 +212,7 @@ function applyLedgerIntent(intent, options = {}) {
209
212
  }
210
213
  }
211
214
  const result = writeTask({
212
- taskRef: intent.taskRef, expectedState: 'active',
215
+ taskRef: intent.taskRef, expectedState: stateOverride ? resolved.state : 'active',
213
216
  mutations: [...ledgerSectionMutation(content), rowMutation(after), ...(implementationMutation ? [implementationMutation] : [])],
214
217
  dryRun: 'dryRun' in intent ? intent.dryRun : false
215
218
  }, { ...options, taskLocation: { repoRoot: resolved.repoRoot, taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, state: resolved.state } });
@@ -10,6 +10,36 @@ import { captureTaskWriteMetadata, writeTask } from './write.js';
10
10
  const lifecycleIntentCatalog = [
11
11
  'block', 'activate', 'cancel', 'complete', 'close-codescan', 'close-dependabot', 'restore'
12
12
  ];
13
+ const lifecycleFailureCatalog = [
14
+ 'LIFECYCLE_DIRECTORY_RENAME_FAILED',
15
+ 'LIFECYCLE_DOCUMENT_INVALID',
16
+ 'LIFECYCLE_FINAL_STATE_INVALID',
17
+ 'LIFECYCLE_IDENTITY_CONFLICT',
18
+ 'LIFECYCLE_IDENTITY_INVALID',
19
+ 'LIFECYCLE_INTENT_CONFLICT',
20
+ 'LIFECYCLE_JOURNAL_CLEANUP_FAILED',
21
+ 'LIFECYCLE_JOURNAL_INVALID',
22
+ 'LIFECYCLE_JOURNAL_WRITE_FAILED',
23
+ 'LIFECYCLE_LOG_MISSING',
24
+ 'LIFECYCLE_METADATA_FAILED',
25
+ 'LIFECYCLE_PAYLOAD_INVALID',
26
+ 'LIFECYCLE_SHORT_ID_FAILED',
27
+ 'LIFECYCLE_SHORT_ID_PRECONDITION',
28
+ 'LIFECYCLE_SOURCE_INVALID',
29
+ 'LIFECYCLE_STAGING_IDENTITY_INVALID',
30
+ 'LIFECYCLE_STAGING_INVALID',
31
+ 'LIFECYCLE_TARGET_CONFLICT',
32
+ 'LIFECYCLE_TASK_NOT_FOUND',
33
+ 'SHORT_ID_CAPACITY_EXCEEDED'
34
+ ];
35
+ const lifecycleProducerCatalog = lifecycleFailureCatalog.map((code) => ({
36
+ producerId: 'lifecycle.apply',
37
+ guardId: 'G-03',
38
+ code
39
+ }));
40
+ function allowsManualOverride(options, code) {
41
+ return options.manualOverride?.failureId === `lifecycle.apply:${code}`;
42
+ }
13
43
  const STEPS = ['task-written', 'directory-moved', 'registry-committed'];
14
44
  const DEFAULT_IO = {
15
45
  renameSync: (source, target) => fs.renameSync(source, target),
@@ -121,10 +151,17 @@ function matchingCompletion(content, request, restoredFiles = 0) {
121
151
  return section.entries.some((entry) => entry.step === identity.action && entry.agent === request.agent && entry.note === identity.note);
122
152
  }
123
153
  function validateRestoreStaging(request, repoRoot, taskId) {
124
- const workspace = path.resolve(repoRoot, '.agents', 'workspace');
125
- const stagingDir = path.resolve(request.stagingDir);
154
+ let workspace;
155
+ let stagingDir;
156
+ try {
157
+ workspace = fs.realpathSync.native(path.resolve(repoRoot, '.agents', 'workspace'));
158
+ stagingDir = fs.realpathSync.native(path.resolve(request.stagingDir));
159
+ }
160
+ catch (error) {
161
+ return { code: 'LIFECYCLE_STAGING_INVALID', message: String(error) };
162
+ }
126
163
  const relative = path.relative(workspace, stagingDir);
127
- if (!relative || relative.startsWith('..') || path.isAbsolute(relative) || path.basename(stagingDir) === taskId) {
164
+ if (!relative || relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative) || path.basename(stagingDir) === taskId) {
128
165
  return { code: 'LIFECYCLE_STAGING_INVALID', message: 'restore staging must be a non-final directory inside .agents/workspace' };
129
166
  }
130
167
  let entries;
@@ -168,8 +205,8 @@ function validateRestoreStaging(request, repoRoot, taskId) {
168
205
  }
169
206
  return { stagingDir, fileCount: entries.filter((entry) => !entry.name.startsWith('.')).length };
170
207
  }
171
- function mutationsFor(request, content, metadata, restoredFiles) {
172
- const section = locateActivityLog(content);
208
+ function mutationsFor(request, content, metadata, restoredFiles, allowMissingActivityLog = false) {
209
+ const section = locateActivityLog(content) ?? (allowMissingActivityLog ? { heading: 'Activity Log', body: '', entries: [] } : null);
173
210
  if (!section)
174
211
  return { code: 'LIFECYCLE_LOG_MISSING', message: 'task has no unique Activity Log section' };
175
212
  const identity = actionAndNote(request, restoredFiles);
@@ -230,6 +267,14 @@ function writeJournal(file, journal, io, create = false) {
230
267
  throw error;
231
268
  }
232
269
  }
270
+ function rememberJournalFailure(file, journal, io, failure) {
271
+ try {
272
+ writeJournal(file, { ...journal, failure }, io);
273
+ }
274
+ catch {
275
+ // Preserve the original lifecycle failure when the diagnostic receipt cannot be updated.
276
+ }
277
+ }
233
278
  function parseJournal(content) {
234
279
  const value = JSON.parse(content);
235
280
  if (value.version !== 1 || typeof value.taskId !== 'string' ||
@@ -303,7 +348,7 @@ function applyTaskLifecycle(requestInput, options = {}) {
303
348
  }
304
349
  return failed(request, { code: 'LIFECYCLE_INTENT_CONFLICT', message: `task ${taskId} is already ${spec.target} with a different lifecycle intent` }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
305
350
  }
306
- if (!spec.sources.includes(sourceState) && !existingJournal) {
351
+ if (!spec.sources.includes(sourceState) && !existingJournal && !allowsManualOverride(options, 'LIFECYCLE_SOURCE_INVALID')) {
307
352
  return failed(request, { code: 'LIFECYCLE_SOURCE_INVALID', message: `${request.intent} is not allowed from ${sourceState}` }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
308
353
  }
309
354
  if (sourcePath !== targetPath && fs.existsSync(targetPath)) {
@@ -319,7 +364,7 @@ function applyTaskLifecycle(requestInput, options = {}) {
319
364
  }
320
365
  if (frontmatter.id !== taskId)
321
366
  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 });
322
- if (!locateActivityLog(content))
367
+ if (!locateActivityLog(content) && !allowsManualOverride(options, 'LIFECYCLE_LOG_MISSING'))
323
368
  return failed(request, { code: 'LIFECYCLE_LOG_MISSING', message: 'task has no unique Activity Log section' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
324
369
  const registryRequest = executeShortIdCommand({
325
370
  operation: 'list', activeDir: path.join(repoRoot, '.agents', 'workspace', 'active'),
@@ -330,10 +375,10 @@ function applyTaskLifecycle(requestInput, options = {}) {
330
375
  }
331
376
  const registry = JSON.parse(registryRequest.output || '{"version":1,"ids":{}}');
332
377
  const registeredKey = Object.entries(registry.ids).find(([, candidate]) => candidate === taskId)?.[0];
333
- if (spec.registry === 'release' && sourceState === 'active' && !registeredKey) {
378
+ if (spec.registry === 'release' && sourceState === 'active' && !registeredKey && !allowsManualOverride(options, 'LIFECYCLE_SHORT_ID_PRECONDITION')) {
334
379
  return failed(request, { code: 'LIFECYCLE_SHORT_ID_PRECONDITION', message: 'active source has no short-id registry entry' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
335
380
  }
336
- if (spec.registry === 'alloc' && !registeredKey && Object.keys(registry.ids).length >= 10 ** configuredShortIdLength(repoRoot) - 1) {
381
+ if (spec.registry === 'alloc' && !registeredKey && Object.keys(registry.ids).length >= 10 ** configuredShortIdLength(repoRoot) - 1 && !allowsManualOverride(options, 'SHORT_ID_CAPACITY_EXCEEDED')) {
337
382
  return failed(request, { code: 'SHORT_ID_CAPACITY_EXCEEDED', message: 'short-id registry has no free slot' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
338
383
  }
339
384
  const digest = intentIdentity(request, taskId);
@@ -347,7 +392,15 @@ function applyTaskLifecycle(requestInput, options = {}) {
347
392
  catch (error) {
348
393
  return failed(request, { code: 'LIFECYCLE_JOURNAL_INVALID', message: String(error) }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath: initialJournalPath });
349
394
  }
350
- if (journal.intentDigest !== digest || journal.taskId !== taskId)
395
+ if (journal.taskId !== taskId || journal.intent !== request.intent)
396
+ return failed(request, { code: 'LIFECYCLE_INTENT_CONFLICT', message: 'an in-progress lifecycle journal belongs to a different request' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath: initialJournalPath });
397
+ if (request.dryRun) {
398
+ if (!journal.failure)
399
+ return failed(request, { code: 'LIFECYCLE_JOURNAL_INVALID', message: 'existing lifecycle journal has no durable failure evidence for a read-only probe' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath: initialJournalPath });
400
+ return failed(request, journal.failure, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath: initialJournalPath, completedSteps: journal.completedSteps, pendingSteps: STEPS.filter((step) => !journal.completedSteps.includes(step)) });
401
+ }
402
+ const overrideResumesRecordedFailure = journal.failure && allowsManualOverride(options, journal.failure.code);
403
+ if (journal.intentDigest !== digest && !overrideResumesRecordedFailure)
351
404
  return failed(request, { code: 'LIFECYCLE_INTENT_CONFLICT', message: 'an in-progress lifecycle journal belongs to a different request' }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath: initialJournalPath });
352
405
  }
353
406
  else {
@@ -360,7 +413,7 @@ function applyTaskLifecycle(requestInput, options = {}) {
360
413
  }
361
414
  journal = { version: 1, taskId, intent: request.intent, intentDigest: digest, sourceState, targetState: spec.target, metadata, completedSteps: [] };
362
415
  if (request.dryRun) {
363
- const plannedMutations = mutationsFor(request, content, metadata, restoredFiles);
416
+ const plannedMutations = mutationsFor(request, content, metadata, restoredFiles, allowsManualOverride(options, 'LIFECYCLE_LOG_MISSING'));
364
417
  if ('code' in plannedMutations)
365
418
  return failed(request, plannedMutations, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath });
366
419
  const taskPlan = writeTask({ taskRef: taskId, expectedState: sourceState === 'blocked' ? 'blocked' : 'active', mutations: plannedMutations, dryRun: true }, {
@@ -402,7 +455,7 @@ function applyTaskLifecycle(requestInput, options = {}) {
402
455
  completed.add('task-written');
403
456
  if (!completed.has('task-written')) {
404
457
  const current = io.readFileSync(path.join(sourcePath, 'task.md'));
405
- const mutations = mutationsFor(request, current, journal.metadata, restoredFiles);
458
+ const mutations = mutationsFor(request, current, journal.metadata, restoredFiles, allowsManualOverride(options, 'LIFECYCLE_LOG_MISSING'));
406
459
  if ('code' in mutations)
407
460
  return failed(request, mutations, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath, completedSteps: [...completed], changed: completed.size > 0 });
408
461
  const writeResult = writeTask({ taskRef: taskId, expectedState: sourceState === 'blocked' ? 'blocked' : 'active', mutations }, {
@@ -432,7 +485,9 @@ function applyTaskLifecycle(requestInput, options = {}) {
432
485
  (options.directoryRenameSync ?? io.renameSync)(sourcePath, targetPath);
433
486
  }
434
487
  catch (error) {
435
- return failed(request, { code: 'LIFECYCLE_DIRECTORY_RENAME_FAILED', message: String(error) }, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath, task: { operations: taskOperations }, changed: true, completedSteps: [...completed], timestamp: journal.metadata.timestamp, agentInfraVersion: journal.metadata.agentInfraVersion });
488
+ const failure = { code: 'LIFECYCLE_DIRECTORY_RENAME_FAILED', message: String(error) };
489
+ rememberJournalFailure(journalPath, journal, io, failure);
490
+ return failed(request, failure, { taskId, sourceState, targetState: spec.target, sourcePath, targetPath, journalPath, task: { operations: taskOperations }, changed: true, completedSteps: [...completed], timestamp: journal.metadata.timestamp, agentInfraVersion: journal.metadata.agentInfraVersion });
436
491
  }
437
492
  completed.add('directory-moved');
438
493
  journal.completedSteps = [...completed];
@@ -480,5 +535,5 @@ function applyTaskLifecycle(requestInput, options = {}) {
480
535
  journalPath, completedSteps: [...completed], pendingSteps: []
481
536
  };
482
537
  }
483
- export { lifecycleIntentCatalog, applyTaskLifecycle };
538
+ export { lifecycleIntentCatalog, lifecycleFailureCatalog, lifecycleProducerCatalog, applyTaskLifecycle };
484
539
  //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1,33 @@
1
+ function warningKey(warning) {
2
+ return `${warning.step}\0${warning.code}\0${warning.target}`;
3
+ }
4
+ function mergeOperationWarnings(...groups) {
5
+ const merged = new Map();
6
+ for (const group of groups) {
7
+ for (const warning of group) {
8
+ const canonical = {
9
+ code: warning.code,
10
+ message: warning.message,
11
+ retryable: warning.retryable,
12
+ step: warning.step,
13
+ target: warning.target,
14
+ severity: warning.severity
15
+ };
16
+ merged.set(warningKey(canonical), canonical);
17
+ }
18
+ }
19
+ return [...merged.values()];
20
+ }
21
+ const RETRY_HINTS = {
22
+ COMMIT_AUTOPUSH_PROTECTED_BRANCH: 'Review the protected branch policy; push the local commit manually if delivery is intended.',
23
+ COMMIT_PUSH_FAILED: 'Retry the commit push-only path after fixing the remote push failure.',
24
+ PR_METADATA_SYNC_FAILED: 'Retry create-pr metadata synchronization; do not create another pull request.',
25
+ PR_SUMMARY_SYNC_FAILED: 'Retry create-pr summary synchronization; do not create another pull request.',
26
+ FINALIZATION_WARNING_PENDING: 'Retry complete-task to process the pending finalization step.'
27
+ };
28
+ function retryHintForWarning(warning) {
29
+ return RETRY_HINTS[warning.code]
30
+ ?? `Retry the ${warning.step} operation after resolving ${warning.code}.`;
31
+ }
32
+ export { mergeOperationWarnings, retryHintForWarning, warningKey };
33
+ //# sourceMappingURL=operation-outcome.js.map