@fitlab-ai/agent-infra 0.9.8 → 0.9.10

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 (182) 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/codex-lifecycle/app-server.js +58 -21
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +25 -11
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +173 -10
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +127 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +14 -0
  9. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +63 -92
  10. package/dist/lib/agent-clients/adapters/codex-sandbox.js +72 -11
  11. package/dist/lib/agent-clients/adapters/index.js +3 -1
  12. package/dist/lib/agent-clients/adapters/traecli.js +66 -0
  13. package/dist/lib/agent-clients/tokens.js +2 -2
  14. package/dist/lib/agent-clients/types.js +2 -1
  15. package/dist/lib/defaults.json +5 -0
  16. package/dist/lib/git/workflow.js +10 -1
  17. package/dist/lib/internal/codex-lifecycle.js +20 -6
  18. package/dist/lib/internal/codex-sandbox-controller.js +9 -15
  19. package/dist/lib/internal/git-workflow.js +5 -7
  20. package/dist/lib/internal/platform-pr.js +20 -7
  21. package/dist/lib/internal/release-workflow.js +2 -1
  22. package/dist/lib/internal/sandbox-control.js +79 -2
  23. package/dist/lib/internal/task-finalization.js +54 -0
  24. package/dist/lib/internal/task-orchestration.js +156 -291
  25. package/dist/lib/{task/commands/validate.js → internal/task-validate.js} +75 -42
  26. package/dist/lib/platform/pr-summary.js +48 -10
  27. package/dist/lib/platform/pull-requests.js +205 -41
  28. package/dist/lib/run/tui.js +5 -2
  29. package/dist/lib/sandbox/commands/rm.js +316 -55
  30. package/dist/lib/sandbox/control/client.js +190 -6
  31. package/dist/lib/sandbox/control/controller-registration.js +275 -0
  32. package/dist/lib/sandbox/control/executor.js +140 -5
  33. package/dist/lib/sandbox/control/lifecycle.js +3 -1
  34. package/dist/lib/sandbox/control/protocol.js +67 -6
  35. package/dist/lib/sandbox/index.js +5 -3
  36. package/dist/lib/sandbox/managed-fs.js +5 -0
  37. package/dist/lib/sandbox/task-resolver.js +50 -6
  38. package/dist/lib/sandbox/workspace-identity.js +27 -0
  39. package/dist/lib/sandbox/worktree-safety.js +215 -2
  40. package/dist/lib/task/codex-orchestration.js +161 -39
  41. package/dist/lib/task/commands/status.js +59 -1
  42. package/dist/lib/task/commit-operation.js +335 -0
  43. package/dist/lib/task/commit-policy.js +18 -0
  44. package/dist/lib/task/delegation-receipts.js +248 -6
  45. package/dist/lib/task/finalization.js +593 -0
  46. package/dist/lib/task/index.js +0 -9
  47. package/dist/lib/task/operation-outcome.js +33 -0
  48. package/dist/lib/task/orchestration.js +187 -761
  49. package/dist/lib/task/short-id.js +59 -1
  50. package/dist/lib/task/task-execution-lock.js +6 -1
  51. package/dist/lib/task/verification-engine.js +110 -60
  52. package/dist/lib/task/verification.js +2 -1
  53. package/dist/lib/task/workflow-warning-intents.js +50 -1
  54. package/dist/lifecycle-build-manifest.json +3 -3
  55. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +61 -19
  56. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +37 -10
  57. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +276 -12
  58. package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +163 -0
  59. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +19 -0
  60. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +9 -1
  61. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +91 -118
  62. package/lib/agent-clients/adapters/codex-sandbox.ts +89 -14
  63. package/lib/agent-clients/adapters/index.ts +3 -1
  64. package/lib/agent-clients/adapters/traecli.ts +67 -0
  65. package/lib/agent-clients/tokens.ts +2 -2
  66. package/lib/agent-clients/types.ts +2 -1
  67. package/lib/defaults.json +5 -0
  68. package/lib/git/workflow.ts +11 -2
  69. package/lib/internal/codex-lifecycle.ts +19 -6
  70. package/lib/internal/codex-sandbox-controller.ts +9 -14
  71. package/lib/internal/git-workflow.ts +5 -6
  72. package/lib/internal/platform-pr.ts +14 -7
  73. package/lib/internal/release-workflow.ts +2 -1
  74. package/lib/internal/sandbox-control.ts +92 -2
  75. package/lib/internal/task-finalization.ts +68 -0
  76. package/lib/internal/task-orchestration.ts +20 -103
  77. package/lib/{task/commands/validate.ts → internal/task-validate.ts} +75 -40
  78. package/lib/platform/pr-summary.ts +55 -11
  79. package/lib/platform/pull-requests.ts +211 -41
  80. package/lib/run/tui.ts +5 -3
  81. package/lib/sandbox/commands/rm.ts +413 -61
  82. package/lib/sandbox/control/client.ts +255 -6
  83. package/lib/sandbox/control/controller-registration.ts +352 -0
  84. package/lib/sandbox/control/executor.ts +169 -5
  85. package/lib/sandbox/control/lifecycle.ts +2 -1
  86. package/lib/sandbox/control/protocol.ts +80 -7
  87. package/lib/sandbox/index.ts +5 -3
  88. package/lib/sandbox/managed-fs.ts +5 -0
  89. package/lib/sandbox/task-resolver.ts +58 -7
  90. package/lib/sandbox/workspace-identity.ts +50 -2
  91. package/lib/sandbox/workspace-view.ts +3 -3
  92. package/lib/sandbox/worktree-safety.ts +236 -2
  93. package/lib/task/codex-orchestration.ts +168 -40
  94. package/lib/task/commands/status.ts +78 -1
  95. package/lib/task/commit-operation.ts +430 -0
  96. package/lib/task/commit-policy.ts +30 -0
  97. package/lib/task/delegation-receipts.ts +263 -4
  98. package/lib/task/finalization.ts +761 -0
  99. package/lib/task/index.ts +0 -8
  100. package/lib/task/operation-outcome.ts +48 -0
  101. package/lib/task/orchestration.ts +218 -982
  102. package/lib/task/short-id.ts +65 -1
  103. package/lib/task/task-execution-lock.ts +10 -1
  104. package/lib/task/verification-engine.ts +115 -63
  105. package/lib/task/verification.ts +3 -2
  106. package/lib/task/workflow-warning-intents.ts +57 -2
  107. package/package.json +2 -2
  108. package/templates/.agents/QUICKSTART.en.md +3 -4
  109. package/templates/.agents/QUICKSTART.zh-CN.md +3 -4
  110. package/templates/.agents/hooks/lifecycle-delegation.js +1 -21
  111. package/templates/.agents/rules/README.en.md +1 -0
  112. package/templates/.agents/rules/README.zh-CN.md +1 -0
  113. package/templates/.agents/rules/compatibility-policy.en.md +39 -0
  114. package/templates/.agents/rules/compatibility-policy.zh-CN.md +39 -0
  115. package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -4
  116. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -4
  117. package/templates/.agents/rules/pr-sync.en.md +1 -1
  118. package/templates/.agents/rules/pr-sync.github.en.md +2 -1
  119. package/templates/.agents/rules/pr-sync.github.zh-CN.md +2 -0
  120. package/templates/.agents/rules/pr-sync.zh-CN.md +1 -0
  121. package/templates/.agents/rules/review-method.en.md +1 -0
  122. package/templates/.agents/rules/review-method.zh-CN.md +1 -0
  123. package/templates/.agents/rules/task-management.en.md +2 -2
  124. package/templates/.agents/rules/task-management.zh-CN.md +2 -2
  125. package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -0
  126. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +1 -0
  127. package/templates/.agents/skills/block-task/SKILL.en.md +2 -4
  128. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -4
  129. package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
  130. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
  131. package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -2
  132. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -2
  133. package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -2
  134. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -2
  135. package/templates/.agents/skills/code-task/SKILL.en.md +1 -0
  136. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -0
  137. package/templates/.agents/skills/commit/SKILL.en.md +41 -125
  138. package/templates/.agents/skills/commit/SKILL.zh-CN.md +52 -123
  139. package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
  140. package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
  141. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +14 -43
  142. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +14 -49
  143. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  144. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  145. package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -35
  146. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -35
  147. package/templates/.agents/skills/complete-task/SKILL.en.md +31 -38
  148. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +31 -38
  149. package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
  150. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
  151. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
  152. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
  153. package/templates/.agents/skills/create-pr/SKILL.en.md +17 -9
  154. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +17 -9
  155. package/templates/.agents/skills/create-pr/reference/change-report.en.md +41 -0
  156. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +41 -0
  157. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
  158. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
  159. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -1
  160. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -1
  161. package/templates/.agents/skills/review-code/reference/migration-risks.en.md +8 -6
  162. package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +8 -6
  163. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +3 -3
  164. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +3 -3
  165. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +1 -1
  166. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +1 -1
  167. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
  168. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
  169. package/templates/.agents/skills/run-task/SKILL.en.md +6 -6
  170. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -6
  171. package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
  172. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
  173. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +24 -0
  174. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +1 -1
  175. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +1 -1
  176. package/templates/.codex/hooks.json +4 -4
  177. package/templates/.trae/skills/update-agent-infra.en.md +8 -0
  178. package/templates/.trae/skills/update-agent-infra.zh-CN.md +8 -0
  179. package/dist/lib/task/commit-finalization.js +0 -305
  180. package/dist/lib/task/commit-intent.js +0 -165
  181. package/lib/task/commit-finalization.ts +0 -419
  182. package/lib/task/commit-intent.ts +0 -230
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
 
3
+ import { isAgentClientId } from '../agent-clients/types.ts';
3
4
  import type { AgentClientId } from '../agent-clients/types.ts';
4
5
  import { normalizeAgentToken } from '../agent-clients/tokens.ts';
5
6
 
@@ -87,6 +88,265 @@ type ReceiptFailure = Readonly<{ ok: false; code: string; message: string; recei
87
88
  type ReceiptSuccess = Readonly<{ ok: true; receipt: DelegationReceipt; code?: never; message?: never }>;
88
89
  type ReceiptResult = ReceiptSuccess | ReceiptFailure;
89
90
 
91
+ function isRecord(value: unknown): value is Record<string, unknown> {
92
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
93
+ }
94
+
95
+ function hasExactKeys(
96
+ value: unknown,
97
+ required: readonly string[],
98
+ optional: readonly string[] = []
99
+ ): value is Record<string, unknown> {
100
+ if (!isRecord(value)) return false;
101
+ const keys = Object.keys(value);
102
+ const allowed = new Set([...required, ...optional]);
103
+ return required.every((key) => Object.prototype.hasOwnProperty.call(value, key))
104
+ && keys.every((key) => allowed.has(key));
105
+ }
106
+
107
+ function exactText(value: unknown): value is string {
108
+ return typeof value === 'string' && value.length > 0 && value.trim() === value;
109
+ }
110
+
111
+ function validCodexBuildMetadata(value: Readonly<Record<string, unknown>>): boolean {
112
+ return Number.isSafeInteger(value.protocolVersion) && (value.protocolVersion as number) > 0
113
+ && exactText(value.packageVersion)
114
+ && exactText(value.internalExecutableBuildHash)
115
+ && exactText(value.lifecycleContractHash);
116
+ }
117
+
118
+ function nullableText(value: unknown): value is string | null {
119
+ return value === null || exactText(value);
120
+ }
121
+
122
+ function nullableSafeInteger(value: unknown): value is number | null {
123
+ return value === null || (Number.isSafeInteger(value) && (value as number) >= 0);
124
+ }
125
+
126
+ const LIFECYCLE_PROVENANCE_KEYS = [
127
+ 'protocolVersion', 'packageVersion', 'internalExecutableBuildHash', 'lifecycleContractHash',
128
+ 'hookDefinitionHash', 'hookSource', 'hookSourcePathDigest', 'hookSourceHash',
129
+ 'capabilitySessionId', 'capabilityTurnId', 'capabilityToolUseId',
130
+ 'controllerInstanceDigest', 'controlGeneration'
131
+ ] as const;
132
+
133
+ function isDelegationLifecycleProvenance(value: unknown): value is DelegationLifecycleProvenance {
134
+ if (!hasExactKeys(value, LIFECYCLE_PROVENANCE_KEYS)) return false;
135
+ return Number.isSafeInteger(value.protocolVersion)
136
+ && (value.protocolVersion as number) > 0
137
+ && exactText(value.packageVersion)
138
+ && exactText(value.internalExecutableBuildHash)
139
+ && exactText(value.lifecycleContractHash)
140
+ && exactText(value.hookDefinitionHash)
141
+ && ['project', 'managed', 'isolated-user'].includes(value.hookSource as string)
142
+ && exactText(value.hookSourcePathDigest)
143
+ && exactText(value.hookSourceHash)
144
+ && exactText(value.capabilitySessionId)
145
+ && exactText(value.capabilityTurnId)
146
+ && exactText(value.capabilityToolUseId)
147
+ && nullableText(value.controllerInstanceDigest)
148
+ && nullableText(value.controlGeneration);
149
+ }
150
+
151
+ const HOST_EVIDENCE_REQUIRED_KEYS = [
152
+ 'kind', 'hookDefinitionHash', 'startRevision', 'stopRevision', 'consumer', 'consumedAt'
153
+ ] as const;
154
+ const HOST_EVIDENCE_OPTIONAL_KEYS = [
155
+ 'protocolVersion', 'packageVersion', 'internalExecutableBuildHash', 'lifecycleContractHash',
156
+ 'hookSource', 'hookSourcePathDigest', 'hookSourceHash', 'capabilitySessionId',
157
+ 'capabilityTurnId', 'capabilityToolUseId', 'spawnToolUseId', 'spawnObservedAt',
158
+ 'controllerInstanceDigest', 'controlGeneration'
159
+ ] as const;
160
+
161
+ function isDelegationHostEvidence(value: unknown): value is DelegationHostEvidence {
162
+ if (!hasExactKeys(value, HOST_EVIDENCE_REQUIRED_KEYS, HOST_EVIDENCE_OPTIONAL_KEYS)) return false;
163
+ if (!['codex-lifecycle-v1', 'codex-lifecycle-v2'].includes(value.kind as string)) return false;
164
+ if (!exactText(value.hookDefinitionHash)
165
+ || !Number.isSafeInteger(value.startRevision) || (value.startRevision as number) < 1
166
+ || !nullableSafeInteger(value.stopRevision)
167
+ || !nullableText(value.consumer)
168
+ || !nullableText(value.consumedAt)) return false;
169
+ if (value.kind === 'codex-lifecycle-v1') return true;
170
+ return Number.isSafeInteger(value.protocolVersion)
171
+ && (value.protocolVersion as number) > 0
172
+ && exactText(value.packageVersion)
173
+ && exactText(value.internalExecutableBuildHash)
174
+ && exactText(value.lifecycleContractHash)
175
+ && ['project', 'managed', 'isolated-user'].includes(value.hookSource as string)
176
+ && exactText(value.hookSourcePathDigest)
177
+ && exactText(value.hookSourceHash)
178
+ && exactText(value.capabilitySessionId)
179
+ && exactText(value.capabilityTurnId)
180
+ && exactText(value.spawnToolUseId)
181
+ && exactText(value.spawnObservedAt)
182
+ && nullableText(value.controllerInstanceDigest)
183
+ && nullableText(value.controlGeneration);
184
+ }
185
+
186
+ function hasCurrentCodexEvidence(receipt: DelegationReceipt): boolean {
187
+ const provenance = receipt.lifecycleProvenance;
188
+ if (!provenance) return false;
189
+ const activated = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status);
190
+ if (!activated) return receipt.hostEvidence === null;
191
+ const host = receipt.hostEvidence;
192
+ if (
193
+ host?.kind !== 'codex-lifecycle-v2'
194
+ || host.protocolVersion !== provenance.protocolVersion
195
+ || host.hookDefinitionHash !== provenance.hookDefinitionHash
196
+ || host.hookSource !== provenance.hookSource
197
+ || host.hookSourcePathDigest !== provenance.hookSourcePathDigest
198
+ || host.hookSourceHash !== provenance.hookSourceHash
199
+ || host.capabilitySessionId !== provenance.capabilitySessionId
200
+ || host.capabilityTurnId !== provenance.capabilityTurnId
201
+ || host.controllerInstanceDigest !== provenance.controllerInstanceDigest
202
+ || host.controlGeneration !== provenance.controlGeneration
203
+ || receipt.parentId !== provenance.capabilitySessionId
204
+ || host.spawnToolUseId === provenance.capabilityToolUseId
205
+ ) return false;
206
+ const spawnObservedAt = Date.parse(host.spawnObservedAt ?? '');
207
+ const spawnDispatchedAt = Date.parse(receipt.spawnDispatchedAt ?? '');
208
+ const activationDeadlineAt = Date.parse(receipt.activationDeadlineAt ?? '');
209
+ if (
210
+ !Number.isFinite(spawnObservedAt)
211
+ || !Number.isFinite(spawnDispatchedAt)
212
+ || !Number.isFinite(activationDeadlineAt)
213
+ || spawnObservedAt < spawnDispatchedAt
214
+ || spawnObservedAt > activationDeadlineAt
215
+ ) return false;
216
+ if (['sealed', 'consumed'].includes(receipt.status)) {
217
+ return Number.isSafeInteger(host.stopRevision)
218
+ && (host.stopRevision as number) > host.startRevision
219
+ && host.consumer === receipt.id
220
+ && exactText(host.consumedAt);
221
+ }
222
+ return host.stopRevision === null && host.consumer === null && host.consumedAt === null;
223
+ }
224
+
225
+ const RECEIPT_KEYS = [
226
+ 'id', 'taskId', 'runId', 'role', 'stage', 'round', 'artifact', 'client',
227
+ 'requestedModel', 'requestedReasoningEffort', 'actualModel', 'actualReasoningEffort',
228
+ 'modelFallbackReason', 'reasoningEffortFallbackReason', 'parentId', 'childId',
229
+ 'spawnMode', 'agent', 'status', 'workspaceSnapshotScope', 'lifecycleProvenance',
230
+ 'hostEvidence', 'beforeFingerprint', 'afterFingerprint', 'changedPaths', 'createdAt',
231
+ 'preparedMonotonicMs', 'spawnDispatchMonotonicMs', 'activationDeadlineMonotonicMs',
232
+ 'spawnDispatchedAt', 'activationDeadlineAt', 'startEvidenceMonotonicMs',
233
+ 'activatedMonotonicMs', 'activatedAt', 'sealedAt', 'consumedAt'
234
+ ] as const;
235
+
236
+ function hasStatusBoundEvidence(receipt: DelegationReceipt): boolean {
237
+ const dispatchFields = [
238
+ receipt.spawnDispatchMonotonicMs,
239
+ receipt.activationDeadlineMonotonicMs,
240
+ receipt.spawnDispatchedAt,
241
+ receipt.activationDeadlineAt
242
+ ];
243
+ const dispatchEmpty = dispatchFields.every((field) => field === null);
244
+ const dispatchComplete = dispatchFields.every((field) => field !== null);
245
+ if (!dispatchEmpty && !dispatchComplete) return false;
246
+
247
+ const beforeActivation = ['prepared', 'aborted', 'expired'].includes(receipt.status);
248
+ if (beforeActivation) {
249
+ return receipt.parentId === null
250
+ && receipt.childId === null
251
+ && receipt.spawnMode === null
252
+ && receipt.actualModel === null
253
+ && receipt.actualReasoningEffort === null
254
+ && receipt.modelFallbackReason === null
255
+ && receipt.reasoningEffortFallbackReason === null
256
+ && receipt.agent === null
257
+ && receipt.hostEvidence === null
258
+ && receipt.startEvidenceMonotonicMs === null
259
+ && receipt.activatedMonotonicMs === null
260
+ && receipt.activatedAt === null
261
+ && receipt.afterFingerprint === null
262
+ && receipt.changedPaths.length === 0
263
+ && receipt.sealedAt === null
264
+ && receipt.consumedAt === null;
265
+ }
266
+
267
+ if (
268
+ !dispatchComplete
269
+ || !exactText(receipt.parentId)
270
+ || !exactText(receipt.childId)
271
+ || receipt.parentId === receipt.childId
272
+ || receipt.startEvidenceMonotonicMs === null
273
+ || receipt.activatedMonotonicMs === null
274
+ || !exactText(receipt.activatedAt)
275
+ ) return false;
276
+
277
+ if (receipt.status === 'activated') {
278
+ return receipt.agent === null
279
+ && receipt.afterFingerprint === null
280
+ && receipt.changedPaths.length === 0
281
+ && receipt.sealedAt === null
282
+ && receipt.consumedAt === null;
283
+ }
284
+
285
+ if (
286
+ !exactText(receipt.agent)
287
+ || normalizeAgentToken(receipt.agent) !== normalizeAgentToken(receipt.client)
288
+ ) return false;
289
+
290
+ if (receipt.status === 'stage-completed') {
291
+ return receipt.afterFingerprint === null
292
+ && receipt.changedPaths.length === 0
293
+ && receipt.sealedAt === null
294
+ && receipt.consumedAt === null;
295
+ }
296
+
297
+ if (!exactText(receipt.afterFingerprint) || !exactText(receipt.sealedAt)) return false;
298
+ return receipt.status === 'sealed'
299
+ ? receipt.consumedAt === null
300
+ : receipt.status === 'consumed' && exactText(receipt.consumedAt);
301
+ }
302
+
303
+ function isDelegationReceipt(value: unknown): value is DelegationReceipt {
304
+ if (!hasExactKeys(value, RECEIPT_KEYS)) return false;
305
+ const structurallyValid = exactText(value.id)
306
+ && exactText(value.taskId)
307
+ && exactText(value.runId)
308
+ && ['executor', 'reviewer'].includes(value.role as string)
309
+ && ['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code', 'commit'].includes(value.stage as string)
310
+ && Number.isSafeInteger(value.round)
311
+ && (value.round as number) > 0
312
+ && exactText(value.artifact)
313
+ && isAgentClientId(value.client)
314
+ && exactText(value.requestedModel)
315
+ && exactText(value.requestedReasoningEffort)
316
+ && nullableText(value.actualModel)
317
+ && nullableText(value.actualReasoningEffort)
318
+ && nullableText(value.modelFallbackReason)
319
+ && nullableText(value.reasoningEffortFallbackReason)
320
+ && nullableText(value.parentId)
321
+ && nullableText(value.childId)
322
+ && nullableText(value.spawnMode)
323
+ && nullableText(value.agent)
324
+ && ['prepared', 'activated', 'stage-completed', 'sealed', 'consumed', 'aborted', 'expired'].includes(value.status as string)
325
+ && value.workspaceSnapshotScope === 'task'
326
+ && (value.lifecycleProvenance === null || isDelegationLifecycleProvenance(value.lifecycleProvenance))
327
+ && (value.hostEvidence === null || isDelegationHostEvidence(value.hostEvidence))
328
+ && exactText(value.beforeFingerprint)
329
+ && nullableText(value.afterFingerprint)
330
+ && Array.isArray(value.changedPaths)
331
+ && value.changedPaths.every(exactText)
332
+ && exactText(value.createdAt)
333
+ && nullableSafeInteger(value.preparedMonotonicMs)
334
+ && value.preparedMonotonicMs !== null
335
+ && nullableSafeInteger(value.spawnDispatchMonotonicMs)
336
+ && nullableSafeInteger(value.activationDeadlineMonotonicMs)
337
+ && nullableText(value.spawnDispatchedAt)
338
+ && nullableText(value.activationDeadlineAt)
339
+ && nullableSafeInteger(value.startEvidenceMonotonicMs)
340
+ && nullableSafeInteger(value.activatedMonotonicMs)
341
+ && nullableText(value.activatedAt)
342
+ && nullableText(value.sealedAt)
343
+ && nullableText(value.consumedAt);
344
+ if (!structurallyValid) return false;
345
+ const receipt = value as unknown as DelegationReceipt;
346
+ return hasStatusBoundEvidence(receipt)
347
+ && (receipt.client !== 'codex' || hasCurrentCodexEvidence(receipt));
348
+ }
349
+
90
350
  const MANAGED_AGENTS = {
91
351
  'agent-infra-lifecycle-executor': 'executor',
92
352
  'agent-infra-lifecycle-reviewer': 'reviewer'
@@ -151,7 +411,7 @@ function dispatchDelegation(
151
411
  }
152
412
  const monotonic = (options.monotonicNow ?? (() => Number(process.hrtime.bigint() / 1_000_000n)))();
153
413
  const dispatchedAt = (options.now ?? (() => new Date().toISOString()))();
154
- const window = options.activationWindowMs ?? 15_000;
414
+ const window = options.activationWindowMs ?? 60_000;
155
415
  return { ok: true, receipt: Object.freeze({
156
416
  ...receipt,
157
417
  spawnDispatchMonotonicMs: monotonic,
@@ -275,9 +535,6 @@ function activateDelegation(
275
535
  if (
276
536
  !expected
277
537
  || event.hostEvidence.protocolVersion !== expected.protocolVersion
278
- || event.hostEvidence.packageVersion !== expected.packageVersion
279
- || event.hostEvidence.internalExecutableBuildHash !== expected.internalExecutableBuildHash
280
- || event.hostEvidence.lifecycleContractHash !== expected.lifecycleContractHash
281
538
  || event.hostEvidence.hookDefinitionHash !== expected.hookDefinitionHash
282
539
  || event.hostEvidence.hookSource !== expected.hookSource
283
540
  || event.hostEvidence.hookSourcePathDigest !== expected.hookSourcePathDigest
@@ -292,6 +549,7 @@ function activateDelegation(
292
549
  || event.parentId !== expected.capabilitySessionId
293
550
  || (event.hostEvidence.controllerInstanceDigest ?? null) !== expected.controllerInstanceDigest
294
551
  || (event.hostEvidence.controlGeneration ?? null) !== expected.controlGeneration
552
+ || !validCodexBuildMetadata(event.hostEvidence)
295
553
  ) return fail('DELEGATION_HOST_EVIDENCE_INVALID', 'Codex lifecycle provenance does not match the prepared receipt');
296
554
  }
297
555
  return { ok: true, receipt: Object.freeze({
@@ -413,6 +671,7 @@ export {
413
671
  consumeDelegation,
414
672
  dispatchDelegation,
415
673
  foldBlankToNull,
674
+ isDelegationReceipt,
416
675
  managedDelegationRole,
417
676
  prepareDelegation,
418
677
  sealDelegation