@fitlab-ai/agent-infra 0.9.6 → 0.9.8

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 (178) hide show
  1. package/dist/bin/internal-cli.js +10 -0
  2. package/dist/lib/agent-clients/adapters/claude-code.js +3 -3
  3. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +47 -5
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +162 -0
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +245 -0
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +398 -0
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +23 -6
  8. package/dist/lib/decide.js +68 -14
  9. package/dist/lib/defaults.json +10 -2
  10. package/dist/lib/git/workflow.js +30 -3
  11. package/dist/lib/init.js +1 -1
  12. package/dist/lib/internal/codex-lifecycle.js +69 -1
  13. package/dist/lib/internal/codex-sandbox-controller.js +106 -0
  14. package/dist/lib/internal/release-workflow.js +1 -3
  15. package/dist/lib/internal/task-activity.js +57 -7
  16. package/dist/lib/internal/task-event.js +57 -4
  17. package/dist/lib/internal/task-ledger.js +59 -5
  18. package/dist/lib/internal/task-lifecycle.js +59 -8
  19. package/dist/lib/internal/task-orchestration.js +48 -8
  20. package/dist/lib/internal/task-override.js +131 -0
  21. package/dist/lib/internal/task-review.js +64 -6
  22. package/dist/lib/internal/task-verify.js +65 -3
  23. package/dist/lib/internal/task-warning.js +57 -4
  24. package/dist/lib/platform/context.js +6 -4
  25. package/dist/lib/platform/github-client.js +55 -2
  26. package/dist/lib/platform/pr-summary.js +5 -3
  27. package/dist/lib/process-data/checkpoint.js +319 -0
  28. package/dist/lib/process-data/index.js +128 -60
  29. package/dist/lib/process-data/materialize.js +84 -0
  30. package/dist/lib/process-data/normalize.js +34 -1
  31. package/dist/lib/process-data/reconcile.js +55 -1
  32. package/dist/lib/process-data/sources.js +422 -1
  33. package/dist/lib/process-data/store.js +341 -11
  34. package/dist/lib/runtime/agent-runtime.js +56 -0
  35. package/dist/lib/sandbox/commands/create.js +394 -264
  36. package/dist/lib/sandbox/commands/rm.js +64 -15
  37. package/dist/lib/sandbox/commands/start.js +4 -3
  38. package/dist/lib/sandbox/control/container-identity.js +64 -0
  39. package/dist/lib/sandbox/control/executor.js +23 -9
  40. package/dist/lib/sandbox/control/lifecycle.js +590 -61
  41. package/dist/lib/sandbox/control/protocol.js +7 -0
  42. package/dist/lib/sandbox/control/server.js +202 -26
  43. package/dist/lib/sandbox/control/state.js +51 -25
  44. package/dist/lib/sandbox/control/timing.js +8 -0
  45. package/dist/lib/sandbox/engine.js +14 -7
  46. package/dist/lib/sandbox/mounts.js +7 -0
  47. package/dist/lib/sandbox/recovery.js +135 -50
  48. package/dist/lib/sandbox/workspace-view.js +59 -20
  49. package/dist/lib/server/daemon.js +1 -1
  50. package/dist/lib/server/process-control.js +11 -1
  51. package/dist/lib/server/process-state.js +107 -20
  52. package/dist/lib/task/activity-intent.js +4 -1
  53. package/dist/lib/task/artifact-lifecycle.js +82 -11
  54. package/dist/lib/task/artifact-receipts.js +128 -0
  55. package/dist/lib/task/codex-orchestration.js +81 -6
  56. package/dist/lib/task/commands/validate.js +1 -1
  57. package/dist/lib/task/create.js +10 -2
  58. package/dist/lib/task/decision-intents.js +4 -2
  59. package/dist/lib/task/delegation-receipts.js +120 -17
  60. package/dist/lib/task/events.js +148 -7
  61. package/dist/lib/task/guard-override.js +31 -0
  62. package/dist/lib/task/human-override.js +1240 -0
  63. package/dist/lib/task/ledger-intents.js +6 -3
  64. package/dist/lib/task/ledger.js +13 -1
  65. package/dist/lib/task/lifecycle.js +69 -14
  66. package/dist/lib/task/orchestration.js +293 -18
  67. package/dist/lib/task/review-finalization.js +3 -2
  68. package/dist/lib/task/sections.js +5 -1
  69. package/dist/lib/task/task-execution-lock.js +5 -4
  70. package/dist/lib/task/verification-engine.js +80 -22
  71. package/dist/lib/task/verification.js +13 -1
  72. package/dist/lib/task/workflow-warning-intents.js +4 -2
  73. package/dist/lib/task/write.js +2 -1
  74. package/dist/lifecycle-build-manifest.json +6 -0
  75. package/lib/agent-clients/adapters/claude-code.ts +3 -3
  76. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +62 -4
  77. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +227 -0
  78. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +322 -0
  79. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +26 -0
  80. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +480 -0
  81. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +35 -5
  82. package/lib/decide.ts +59 -14
  83. package/lib/defaults.json +10 -2
  84. package/lib/git/workflow.ts +25 -2
  85. package/lib/init.ts +1 -1
  86. package/lib/internal/codex-lifecycle.ts +68 -1
  87. package/lib/internal/codex-sandbox-controller.ts +109 -0
  88. package/lib/internal/release-workflow.ts +1 -3
  89. package/lib/internal/task-activity.ts +46 -6
  90. package/lib/internal/task-event.ts +53 -4
  91. package/lib/internal/task-ledger.ts +48 -4
  92. package/lib/internal/task-lifecycle.ts +56 -12
  93. package/lib/internal/task-orchestration.ts +43 -8
  94. package/lib/internal/task-override.ts +138 -0
  95. package/lib/internal/task-review.ts +51 -6
  96. package/lib/internal/task-verify.ts +52 -3
  97. package/lib/internal/task-warning.ts +44 -3
  98. package/lib/platform/context.ts +8 -5
  99. package/lib/platform/github-client.ts +61 -3
  100. package/lib/platform/pr-summary.ts +10 -3
  101. package/lib/process-data/checkpoint.ts +335 -0
  102. package/lib/process-data/index.ts +112 -60
  103. package/lib/process-data/materialize.ts +83 -0
  104. package/lib/process-data/normalize.ts +29 -1
  105. package/lib/process-data/reconcile.ts +64 -2
  106. package/lib/process-data/sources.ts +449 -2
  107. package/lib/process-data/store.ts +304 -11
  108. package/lib/process-data/types.ts +124 -2
  109. package/lib/runtime/agent-runtime.ts +76 -0
  110. package/lib/sandbox/commands/create.ts +139 -6
  111. package/lib/sandbox/commands/rm.ts +64 -14
  112. package/lib/sandbox/commands/start.ts +4 -3
  113. package/lib/sandbox/config.ts +2 -1
  114. package/lib/sandbox/control/container-identity.ts +93 -0
  115. package/lib/sandbox/control/executor.ts +24 -12
  116. package/lib/sandbox/control/lifecycle.ts +685 -67
  117. package/lib/sandbox/control/protocol.ts +35 -6
  118. package/lib/sandbox/control/server.ts +184 -24
  119. package/lib/sandbox/control/state.ts +67 -33
  120. package/lib/sandbox/control/timing.ts +12 -0
  121. package/lib/sandbox/engine.ts +20 -9
  122. package/lib/sandbox/mounts.ts +8 -0
  123. package/lib/sandbox/recovery.ts +159 -49
  124. package/lib/sandbox/workspace-view.ts +73 -22
  125. package/lib/server/daemon.ts +1 -1
  126. package/lib/server/process-control.ts +13 -3
  127. package/lib/server/process-state.ts +129 -27
  128. package/lib/task/activity-intent.ts +4 -2
  129. package/lib/task/artifact-lifecycle.ts +73 -10
  130. package/lib/task/artifact-receipts.ts +161 -0
  131. package/lib/task/codex-orchestration.ts +91 -5
  132. package/lib/task/commands/validate.ts +1 -1
  133. package/lib/task/create.ts +11 -2
  134. package/lib/task/decision-intents.ts +4 -2
  135. package/lib/task/delegation-receipts.ts +205 -25
  136. package/lib/task/events.ts +132 -6
  137. package/lib/task/guard-override.ts +50 -0
  138. package/lib/task/human-override.ts +1503 -0
  139. package/lib/task/ledger-intents.ts +6 -3
  140. package/lib/task/ledger.ts +16 -1
  141. package/lib/task/lifecycle.ts +71 -14
  142. package/lib/task/orchestration.ts +443 -22
  143. package/lib/task/review-finalization.ts +6 -2
  144. package/lib/task/sections.ts +6 -2
  145. package/lib/task/task-execution-lock.ts +11 -9
  146. package/lib/task/verification-engine.ts +93 -32
  147. package/lib/task/verification.ts +15 -1
  148. package/lib/task/workflow-warning-intents.ts +4 -2
  149. package/lib/task/write.ts +4 -1
  150. package/package.json +1 -1
  151. package/templates/.agents/README.en.md +7 -0
  152. package/templates/.agents/README.zh-CN.md +5 -0
  153. package/templates/.agents/hooks/lifecycle-delegation.js +33 -4
  154. package/templates/.agents/rules/lifecycle-orchestration.en.md +10 -3
  155. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +10 -3
  156. package/templates/.agents/rules/pr-checks-commands.github.en.md +1 -1
  157. package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +1 -1
  158. package/templates/.agents/rules/review-handshake.en.md +3 -1
  159. package/templates/.agents/rules/review-handshake.zh-CN.md +3 -1
  160. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +3 -1
  161. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +3 -1
  162. package/templates/.agents/skills/complete-task/SKILL.en.md +4 -0
  163. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +4 -0
  164. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +6 -6
  165. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +6 -6
  166. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +14 -3
  167. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +14 -3
  168. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +67 -0
  169. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +67 -0
  170. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +25 -0
  171. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +25 -0
  172. package/templates/.agents/skills/run-task/SKILL.en.md +9 -7
  173. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +9 -7
  174. package/templates/.agents/skills/run-task/reference/host-validation.en.md +5 -1
  175. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +5 -1
  176. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +75 -3
  177. package/templates/.agents/workspace/README.en.md +0 -26
  178. package/templates/.agents/workspace/README.zh-CN.md +0 -26
@@ -0,0 +1,322 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+
5
+ import { verifyLifecycleBuildIdentity } from './build-identity.ts';
6
+ import type { LifecycleBuildIdentity } from './build-identity.ts';
7
+ import { resolveAgentRuntimeStoreRoot } from '../../../runtime/agent-runtime.ts';
8
+
9
+ type CapabilityStatus = 'armed' | 'attested' | 'consumed' | 'expired';
10
+ type CodexControllerBinding = Readonly<{
11
+ instanceDigest: string;
12
+ controlGeneration: string;
13
+ }>;
14
+ type CodexCapabilityRecord = Readonly<{
15
+ schemaVersion: 1;
16
+ revision: number;
17
+ tokenDigest: string;
18
+ taskId: string;
19
+ status: CapabilityStatus;
20
+ buildIdentity: LifecycleBuildIdentity;
21
+ controller: CodexControllerBinding | null;
22
+ sessionId: string | null;
23
+ turnId: string | null;
24
+ toolUseId: string | null;
25
+ hookDefinitionHash: string | null;
26
+ armedAt: number;
27
+ expiresAt: number;
28
+ attestedAt: number | null;
29
+ consumedAt: number | null;
30
+ }>;
31
+
32
+ type CodexCapabilityStoreOptions = Readonly<{
33
+ root?: string;
34
+ now?: () => number;
35
+ token?: () => string;
36
+ ttlMs?: number;
37
+ tombstoneMs?: number;
38
+ maxRecords?: number;
39
+ beforeCompareAndSwap?: (input: Readonly<{ path: string; expectedRevision: number }>) => void;
40
+ }>;
41
+
42
+ const DEFAULT_TTL_MS = 30_000;
43
+ const DEFAULT_TOMBSTONE_MS = 86_400_000;
44
+ const DEFAULT_MAX_RECORDS = 128;
45
+ const LOCK_RETRY_MS = 10;
46
+ const LOCK_TIMEOUT_MS = 1_000;
47
+ const LOCK_STALE_MS = 30_000;
48
+
49
+ function digest(value: string): string {
50
+ return crypto.createHash('sha256').update(value).digest('hex');
51
+ }
52
+
53
+ function capabilityError(code: string, message: string): Error {
54
+ const error = new Error(`${code}: ${message}`);
55
+ error.name = code;
56
+ return error;
57
+ }
58
+
59
+ function sameController(
60
+ left: CodexControllerBinding | null,
61
+ right: CodexControllerBinding | null
62
+ ): boolean {
63
+ return left?.instanceDigest === right?.instanceDigest
64
+ && left?.controlGeneration === right?.controlGeneration;
65
+ }
66
+
67
+ function createCodexCapabilityStore(options: CodexCapabilityStoreOptions = {}) {
68
+ const root = options.root
69
+ ?? resolveAgentRuntimeStoreRoot({ store: 'capabilities' });
70
+ const now = options.now ?? Date.now;
71
+ const createToken = options.token ?? (() => crypto.randomBytes(32).toString('base64url'));
72
+ const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
73
+ const tombstoneMs = options.tombstoneMs ?? DEFAULT_TOMBSTONE_MS;
74
+ const maxRecords = options.maxRecords ?? DEFAULT_MAX_RECORDS;
75
+ fs.mkdirSync(root, { recursive: true, mode: 0o700 });
76
+ fs.chmodSync(root, 0o700);
77
+
78
+ function fileFor(token: string): string {
79
+ return path.join(root, `${digest(token)}.json`);
80
+ }
81
+
82
+ function read(file: string): CodexCapabilityRecord {
83
+ const value = JSON.parse(fs.readFileSync(file, 'utf8')) as CodexCapabilityRecord;
84
+ if (value.schemaVersion !== 1 || !Number.isSafeInteger(value.revision) || value.revision < 1) {
85
+ throw capabilityError('CODEX_CAPABILITY_STATE_INVALID', 'capability record schema is invalid');
86
+ }
87
+ return value;
88
+ }
89
+
90
+ function withWriteLock<T>(operation: () => T): T {
91
+ const lock = path.join(root, '.write.lock');
92
+ const deadline = Date.now() + LOCK_TIMEOUT_MS;
93
+ let descriptor: number | null = null;
94
+ while (descriptor === null) {
95
+ try {
96
+ descriptor = fs.openSync(lock, 'wx', 0o600);
97
+ } catch (error) {
98
+ if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
99
+ try {
100
+ if (Date.now() - fs.statSync(lock).mtimeMs > LOCK_STALE_MS) {
101
+ fs.unlinkSync(lock);
102
+ continue;
103
+ }
104
+ } catch (lockError) {
105
+ if ((lockError as NodeJS.ErrnoException).code === 'ENOENT') continue;
106
+ throw lockError;
107
+ }
108
+ if (Date.now() >= deadline) {
109
+ throw capabilityError('CODEX_CAPABILITY_STORE_BUSY', 'capability store is busy');
110
+ }
111
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, LOCK_RETRY_MS);
112
+ }
113
+ }
114
+ try {
115
+ return operation();
116
+ } finally {
117
+ fs.closeSync(descriptor);
118
+ fs.unlinkSync(lock);
119
+ }
120
+ }
121
+
122
+ function write(file: string, value: CodexCapabilityRecord, expectedRevision: number): void {
123
+ const temporary = `${file}.${process.pid}.${crypto.randomUUID()}.tmp`;
124
+ fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, {
125
+ encoding: 'utf8',
126
+ flag: 'wx',
127
+ mode: 0o600
128
+ });
129
+ try {
130
+ withWriteLock(() => {
131
+ options.beforeCompareAndSwap?.({ path: file, expectedRevision });
132
+ const actualRevision = fs.existsSync(file) ? read(file).revision : 0;
133
+ if (actualRevision !== expectedRevision) {
134
+ throw capabilityError(
135
+ 'CODEX_CAPABILITY_REVISION_CONFLICT',
136
+ `capability revision changed from ${expectedRevision} to ${actualRevision}`
137
+ );
138
+ }
139
+ fs.renameSync(temporary, file);
140
+ fs.chmodSync(file, 0o600);
141
+ });
142
+ } finally {
143
+ if (fs.existsSync(temporary)) fs.unlinkSync(temporary);
144
+ }
145
+ }
146
+
147
+ function files(): string[] {
148
+ return fs.readdirSync(root)
149
+ .filter((name) => /^[a-f0-9]{64}\.json$/u.test(name))
150
+ .map((name) => path.join(root, name));
151
+ }
152
+
153
+ function expire(record: CodexCapabilityRecord, file: string, timestamp: number): CodexCapabilityRecord {
154
+ if ((record.status === 'armed' || record.status === 'attested') && timestamp > record.expiresAt) {
155
+ const expired = Object.freeze({
156
+ ...record,
157
+ revision: record.revision + 1,
158
+ status: 'expired' as const
159
+ });
160
+ write(file, expired, record.revision);
161
+ return expired;
162
+ }
163
+ return record;
164
+ }
165
+
166
+ function sweep(): void {
167
+ const timestamp = now();
168
+ const records = files().map((file) => ({ file, record: expire(read(file), file, timestamp) }));
169
+ for (const entry of records) {
170
+ const terminalAt = entry.record.consumedAt ?? entry.record.expiresAt;
171
+ if (['consumed', 'expired'].includes(entry.record.status)
172
+ && timestamp - terminalAt > tombstoneMs) {
173
+ fs.unlinkSync(entry.file);
174
+ }
175
+ }
176
+ const remaining = files().map((file) => ({ file, record: read(file) }));
177
+ if (remaining.length <= maxRecords) return;
178
+ const removable = remaining
179
+ .filter(({ record }) => ['consumed', 'expired'].includes(record.status))
180
+ .sort((left, right) =>
181
+ (left.record.consumedAt ?? left.record.expiresAt)
182
+ - (right.record.consumedAt ?? right.record.expiresAt));
183
+ while (files().length > maxRecords && removable.length > 0) {
184
+ fs.unlinkSync(removable.shift()!.file);
185
+ }
186
+ if (files().length > maxRecords) {
187
+ throw capabilityError('CODEX_CAPABILITY_CAPACITY_EXCEEDED', 'capability store has too many active records');
188
+ }
189
+ }
190
+
191
+ function arm(input: Readonly<{
192
+ taskId: string;
193
+ buildIdentity: LifecycleBuildIdentity;
194
+ controller?: CodexControllerBinding;
195
+ }>): CodexCapabilityRecord & Readonly<{ token: string; path: string; marker: string }> {
196
+ sweep();
197
+ const token = createToken();
198
+ const file = fileFor(token);
199
+ if (fs.existsSync(file)) throw capabilityError('CODEX_CAPABILITY_TOKEN_COLLISION', 'capability token already exists');
200
+ const timestamp = now();
201
+ const record: CodexCapabilityRecord = Object.freeze({
202
+ schemaVersion: 1,
203
+ revision: 1,
204
+ tokenDigest: digest(token),
205
+ taskId: input.taskId,
206
+ status: 'armed',
207
+ buildIdentity: input.buildIdentity,
208
+ controller: input.controller ?? null,
209
+ sessionId: null,
210
+ turnId: null,
211
+ toolUseId: null,
212
+ hookDefinitionHash: null,
213
+ armedAt: timestamp,
214
+ expiresAt: timestamp + ttlMs,
215
+ attestedAt: null,
216
+ consumedAt: null
217
+ });
218
+ write(file, record, 0);
219
+ return Object.freeze({
220
+ ...record,
221
+ token,
222
+ path: file,
223
+ marker: `agent-infra-codex-capability:${token}`
224
+ });
225
+ }
226
+
227
+ function loadActive(token: string): Readonly<{ file: string; record: CodexCapabilityRecord }> {
228
+ const file = fileFor(token);
229
+ if (!fs.existsSync(file)) {
230
+ throw capabilityError('CODEX_CAPABILITY_MISSING', 'capability token was not found');
231
+ }
232
+ const record = expire(read(file), file, now());
233
+ if (record.status === 'expired') {
234
+ throw capabilityError('CODEX_CAPABILITY_EXPIRED', 'capability token expired');
235
+ }
236
+ return { file, record };
237
+ }
238
+
239
+ function attest(input: Readonly<{
240
+ token: string;
241
+ sessionId: string;
242
+ turnId: string;
243
+ toolUseId: string;
244
+ hookDefinitionHash: string;
245
+ buildIdentity: LifecycleBuildIdentity;
246
+ controller?: CodexControllerBinding;
247
+ }>): CodexCapabilityRecord {
248
+ const { file, record } = loadActive(input.token);
249
+ if (record.status !== 'armed') {
250
+ throw capabilityError(
251
+ record.status === 'consumed' ? 'CODEX_CAPABILITY_REPLAY' : 'CODEX_CAPABILITY_STATE_INVALID',
252
+ `capability is ${record.status}, expected armed`
253
+ );
254
+ }
255
+ const identity = verifyLifecycleBuildIdentity(record.buildIdentity, input.buildIdentity);
256
+ if (!identity.ok || !sameController(record.controller, input.controller ?? null)) {
257
+ throw capabilityError('CODEX_CAPABILITY_PROVENANCE_MISMATCH', 'capability build or controller identity does not match');
258
+ }
259
+ if (![input.sessionId, input.turnId, input.toolUseId, input.hookDefinitionHash]
260
+ .every((value) => value.trim().length > 0)) {
261
+ throw capabilityError('CODEX_CAPABILITY_IDENTITY_INVALID', 'hook identity is incomplete');
262
+ }
263
+ const timestamp = now();
264
+ const next: CodexCapabilityRecord = Object.freeze({
265
+ ...record,
266
+ revision: record.revision + 1,
267
+ status: 'attested',
268
+ sessionId: input.sessionId,
269
+ turnId: input.turnId,
270
+ toolUseId: input.toolUseId,
271
+ hookDefinitionHash: input.hookDefinitionHash,
272
+ attestedAt: timestamp
273
+ });
274
+ write(file, next, record.revision);
275
+ return next;
276
+ }
277
+
278
+ function consume(token: string, expected: Readonly<{
279
+ taskId: string;
280
+ hookDefinitionHash: string;
281
+ buildIdentity: LifecycleBuildIdentity;
282
+ controller?: CodexControllerBinding;
283
+ }>): CodexCapabilityRecord {
284
+ sweep();
285
+ const { file, record } = loadActive(token);
286
+ if (record.status === 'consumed') {
287
+ throw capabilityError('CODEX_CAPABILITY_REPLAY', 'capability token was already consumed');
288
+ }
289
+ if (record.status !== 'attested') {
290
+ throw capabilityError('CODEX_CAPABILITY_NOT_ATTESTED', 'capability token has no current-session hook attestation');
291
+ }
292
+ const identity = verifyLifecycleBuildIdentity(record.buildIdentity, expected.buildIdentity);
293
+ if (!identity.ok
294
+ || record.taskId !== expected.taskId
295
+ || record.hookDefinitionHash !== expected.hookDefinitionHash
296
+ || !sameController(record.controller, expected.controller ?? null)) {
297
+ throw capabilityError('CODEX_CAPABILITY_PROVENANCE_MISMATCH', 'capability consumption identity does not match');
298
+ }
299
+ const next: CodexCapabilityRecord = Object.freeze({
300
+ ...record,
301
+ revision: record.revision + 1,
302
+ status: 'consumed',
303
+ consumedAt: now()
304
+ });
305
+ write(file, next, record.revision);
306
+ return next;
307
+ }
308
+
309
+ function inspect(token: string): CodexCapabilityRecord {
310
+ return loadActive(token).record;
311
+ }
312
+
313
+ return Object.freeze({ arm, attest, consume, inspect, sweep });
314
+ }
315
+
316
+ export { createCodexCapabilityStore };
317
+ export type {
318
+ CapabilityStatus,
319
+ CodexCapabilityRecord,
320
+ CodexCapabilityStoreOptions,
321
+ CodexControllerBinding
322
+ };
@@ -0,0 +1,26 @@
1
+ {
2
+ "executableFiles": [
3
+ "bin/internal-cli.ts",
4
+ "lib/internal/codex-lifecycle.ts",
5
+ "lib/internal/codex-sandbox-controller.ts",
6
+ "lib/internal/task-orchestration.ts",
7
+ "lib/task/codex-orchestration.ts",
8
+ "lib/task/delegation-receipts.ts",
9
+ "lib/task/orchestration.ts",
10
+ "lib/agent-clients/adapters/codex-lifecycle/build-identity.ts",
11
+ "lib/agent-clients/adapters/codex-lifecycle/capability-store.ts",
12
+ "lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts",
13
+ "lib/agent-clients/adapters/codex-lifecycle/app-server.ts",
14
+ "lib/agent-clients/adapters/codex-lifecycle/evidence.ts",
15
+ "lib/agent-clients/adapters/codex-lifecycle/store.ts",
16
+ "lib/agent-clients/adapters/codex-lifecycle/manifest-files.json"
17
+ ],
18
+ "contractFiles": [
19
+ ".codex/hooks.json",
20
+ ".codex/agents/agent-infra-lifecycle-executor.toml",
21
+ ".codex/agents/agent-infra-lifecycle-reviewer.toml",
22
+ ".agents/hooks/lifecycle-delegation.js",
23
+ ".agents/skills/run-task/SKILL.md",
24
+ ".agents/rules/lifecycle-orchestration.md"
25
+ ]
26
+ }