@fitlab-ai/agent-infra 0.11.11 → 0.11.13

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 (154) hide show
  1. package/dist/bin/internal-cli.js +2 -2
  2. package/dist/lib/agent-clients/adapter.js +7 -1
  3. package/dist/lib/agent-clients/adapters/claude-code.js +5 -1
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +78 -63
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +114 -0
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +447 -0
  7. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-client.js +130 -0
  8. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-operation.js +131 -0
  9. package/dist/lib/{sandbox/control → agent-clients/adapters/codex-lifecycle}/controller-registration.js +2 -2
  10. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +48 -1
  11. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +124 -62
  12. package/dist/lib/{internal/codex-sandbox-controller.js → agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.js} +3 -3
  13. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -5
  14. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +211 -213
  15. package/dist/lib/agent-clients/adapters/codex-orchestration.js +468 -0
  16. package/dist/lib/agent-clients/adapters/codex.js +40 -1
  17. package/dist/lib/agent-clients/adapters/index.js +2 -10
  18. package/dist/lib/agent-clients/tokens.js +3 -2
  19. package/dist/lib/internal/agent-client.js +132 -72
  20. package/dist/lib/internal/cli-route-inventory.js +2 -2
  21. package/dist/lib/internal/sandbox-control.js +1 -81
  22. package/dist/lib/internal/task-finalization.js +26 -19
  23. package/dist/lib/internal/task-lifecycle.js +1 -1
  24. package/dist/lib/internal/task-operation-registry.js +1 -1
  25. package/dist/lib/internal/task-validate.js +1 -1
  26. package/dist/lib/platform/github-client.js +33 -3
  27. package/dist/lib/platform/issues.js +18 -6
  28. package/dist/lib/runtime/agent-runtime.js +6 -29
  29. package/dist/lib/sandbox/commands/control-status.js +1 -0
  30. package/dist/lib/sandbox/commands/create.js +7 -2
  31. package/dist/lib/sandbox/commands/ls.js +4 -5
  32. package/dist/lib/sandbox/commands/rm.js +1 -1
  33. package/dist/lib/sandbox/control/agent-operation.js +34 -0
  34. package/dist/lib/sandbox/control/client.js +14 -201
  35. package/dist/lib/sandbox/control/executor.js +12 -125
  36. package/dist/lib/sandbox/control/lifecycle.js +66 -4
  37. package/dist/lib/sandbox/control/protocol.js +15 -54
  38. package/dist/lib/sandbox/control/server.js +216 -281
  39. package/dist/lib/sandbox/control/task-view.js +0 -13
  40. package/dist/lib/sandbox/mounts.js +9 -1
  41. package/dist/lib/sandbox/recovery.js +31 -10
  42. package/dist/lib/sandbox/removal.js +28 -5
  43. package/dist/lib/sandbox/workspace-identity.js +18 -6
  44. package/dist/lib/sandbox/workspace-view.js +56 -19
  45. package/dist/lib/task/commands/ls.js +3 -3
  46. package/dist/lib/task/control-authority.js +56 -264
  47. package/dist/lib/task/control-recovery.js +2 -3
  48. package/dist/lib/task/create.js +2 -2
  49. package/dist/lib/task/delegation-receipts.js +74 -161
  50. package/dist/lib/task/events.js +88 -44
  51. package/dist/lib/task/finalization.js +35 -6
  52. package/dist/lib/task/lifecycle.js +274 -115
  53. package/dist/lib/task/orchestration.js +201 -194
  54. package/dist/lib/task/runtime-paths.js +10 -0
  55. package/dist/lib/task/short-id.js +37 -27
  56. package/dist/lib/task/verification-engine.js +32 -26
  57. package/dist/lib/task/workspace-snapshot.js +1 -1
  58. package/dist/lifecycle-build-manifest.json +3 -3
  59. package/lib/agent-clients/adapter.ts +39 -0
  60. package/lib/agent-clients/adapters/claude-code.ts +5 -1
  61. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +105 -80
  62. package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +147 -0
  63. package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +510 -0
  64. package/lib/agent-clients/adapters/codex-lifecycle/controller-client.ts +158 -0
  65. package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +1 -1
  66. package/lib/agent-clients/adapters/codex-lifecycle/controller-operation.ts +151 -0
  67. package/lib/{sandbox/control → agent-clients/adapters/codex-lifecycle}/controller-registration.ts +4 -4
  68. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +43 -0
  69. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +8 -5
  70. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +190 -65
  71. package/lib/{internal/codex-sandbox-controller.ts → agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.ts} +2 -2
  72. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -5
  73. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +270 -224
  74. package/lib/agent-clients/adapters/codex-orchestration.ts +632 -0
  75. package/lib/agent-clients/adapters/codex.ts +44 -1
  76. package/lib/agent-clients/adapters/index.ts +7 -20
  77. package/lib/agent-clients/tokens.ts +4 -3
  78. package/lib/internal/agent-client.ts +142 -73
  79. package/lib/internal/cli-route-inventory.ts +2 -2
  80. package/lib/internal/sandbox-control.ts +0 -97
  81. package/lib/internal/task-finalization.ts +30 -18
  82. package/lib/internal/task-lifecycle.ts +1 -1
  83. package/lib/internal/task-operation-registry.ts +1 -1
  84. package/lib/internal/task-validate.ts +1 -1
  85. package/lib/platform/github-client.ts +34 -3
  86. package/lib/platform/issues.ts +18 -6
  87. package/lib/runtime/agent-runtime.ts +6 -41
  88. package/lib/sandbox/commands/control-status.ts +1 -0
  89. package/lib/sandbox/commands/create.ts +7 -1
  90. package/lib/sandbox/commands/ls.ts +4 -5
  91. package/lib/sandbox/commands/rm.ts +1 -1
  92. package/lib/sandbox/control/agent-operation.ts +49 -0
  93. package/lib/sandbox/control/client.ts +20 -254
  94. package/lib/sandbox/control/executor.ts +13 -136
  95. package/lib/sandbox/control/lifecycle.ts +67 -4
  96. package/lib/sandbox/control/protocol.ts +22 -66
  97. package/lib/sandbox/control/server.ts +21 -95
  98. package/lib/sandbox/control/task-view.ts +0 -19
  99. package/lib/sandbox/mounts.ts +10 -1
  100. package/lib/sandbox/recovery.ts +38 -17
  101. package/lib/sandbox/removal.ts +33 -7
  102. package/lib/sandbox/workspace-identity.ts +16 -6
  103. package/lib/sandbox/workspace-view.ts +50 -18
  104. package/lib/task/commands/ls.ts +3 -3
  105. package/lib/task/control-authority.ts +66 -378
  106. package/lib/task/control-recovery.ts +3 -4
  107. package/lib/task/create.ts +3 -3
  108. package/lib/task/delegation-receipts.ts +87 -231
  109. package/lib/task/events.ts +100 -42
  110. package/lib/task/finalization.ts +37 -7
  111. package/lib/task/lifecycle.ts +257 -109
  112. package/lib/task/orchestration.ts +260 -237
  113. package/lib/task/runtime-paths.ts +12 -0
  114. package/lib/task/short-id.ts +33 -40
  115. package/lib/task/verification-engine.ts +30 -25
  116. package/lib/task/workspace-snapshot.ts +1 -1
  117. package/package.json +1 -1
  118. package/templates/.agents/hooks/lifecycle-delegation.js +1 -25
  119. package/templates/.agents/rules/README.en.md +2 -1
  120. package/templates/.agents/rules/README.zh-CN.md +2 -1
  121. package/templates/.agents/rules/next-step-output.en.md +6 -19
  122. package/templates/.agents/rules/next-step-output.zh-CN.md +6 -19
  123. package/templates/.agents/rules/strategy-pattern.en.md +25 -0
  124. package/templates/.agents/rules/strategy-pattern.zh-CN.md +25 -0
  125. package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -1
  126. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +1 -1
  127. package/templates/.agents/skills/check-task/SKILL.en.md +1 -1
  128. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +1 -1
  129. package/templates/.agents/skills/code-task/SKILL.en.md +1 -1
  130. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +1 -1
  131. package/templates/.agents/skills/code-task/reference/code-rules.en.md +4 -0
  132. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +4 -0
  133. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +0 -1
  134. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +0 -1
  135. package/templates/.agents/skills/complete-task/SKILL.en.md +5 -29
  136. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +5 -26
  137. package/templates/.agents/skills/plan-task/SKILL.en.md +7 -4
  138. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +7 -4
  139. package/templates/.agents/skills/review-analysis/SKILL.en.md +1 -1
  140. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +1 -1
  141. package/templates/.agents/skills/review-code/SKILL.en.md +1 -1
  142. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +1 -1
  143. package/templates/.agents/skills/review-plan/SKILL.en.md +1 -1
  144. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +1 -1
  145. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
  146. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
  147. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  148. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  149. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +0 -546
  150. package/dist/lib/internal/codex-lifecycle.js +0 -385
  151. package/dist/lib/task/codex-orchestration.js +0 -206
  152. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +0 -776
  153. package/lib/internal/codex-lifecycle.ts +0 -390
  154. package/lib/task/codex-orchestration.ts +0 -276
@@ -111,12 +111,12 @@ if (!controlRouted && !taskViewGuardFailed && internalRouteRegistered)
111
111
  break;
112
112
  }
113
113
  case 'codex-lifecycle': {
114
- const { codexLifecycle } = await import('../lib/internal/codex-lifecycle.js');
114
+ const { codexLifecycle } = await import('../lib/agent-clients/adapters/codex-lifecycle/cli.js');
115
115
  await codexLifecycle(process.argv.slice(3));
116
116
  break;
117
117
  }
118
118
  case 'codex-sandbox-controller': {
119
- const { codexSandboxController } = await import('../lib/internal/codex-sandbox-controller.js');
119
+ const { codexSandboxController } = await import('../lib/agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.js');
120
120
  await codexSandboxController(process.argv.slice(3));
121
121
  break;
122
122
  }
@@ -211,7 +211,10 @@ function defineAgentClientAdapter(candidate) {
211
211
  const evidence = candidate.delegationEvidence;
212
212
  if (!evidence
213
213
  || !['host-event', 'app-server', 'unavailable'].includes(evidence.actualModel)
214
- || !['host-event', 'app-server', 'spawn-ack', 'unavailable'].includes(evidence.actualReasoningEffort)) {
214
+ || !['host-event', 'app-server', 'spawn-ack', 'unavailable'].includes(evidence.actualReasoningEffort)
215
+ || ['spawnModeRequired', 'actualModelRequired', 'actualReasoningEffortRequired', 'fallbackReasonRequired']
216
+ .some((key) => evidence[key] !== undefined
217
+ && typeof evidence[key] !== 'boolean')) {
215
218
  throw new Error(`Agent Client '${candidate.id}' has invalid delegation evidence`);
216
219
  }
217
220
  if (typeof candidate.project !== 'object'
@@ -431,6 +434,9 @@ function defineAgentClientAdapter(candidate) {
431
434
  ...(candidate.orchestrationAdapter === undefined
432
435
  ? {}
433
436
  : { orchestrationAdapter: Object.freeze({ ...candidate.orchestrationAdapter }) }),
437
+ ...(candidate.sandboxControlOperation === undefined
438
+ ? {}
439
+ : { sandboxControlOperation: Object.freeze({ ...candidate.sandboxControlOperation }) }),
434
440
  project: Object.freeze({
435
441
  ownedPathPrefixes: Object.freeze(paths),
436
442
  ...projectAssets,
@@ -22,7 +22,11 @@ const claudeCodeAdapter = defineAgentClientAdapter({
22
22
  },
23
23
  delegationEvidence: {
24
24
  actualModel: 'host-event',
25
- actualReasoningEffort: 'spawn-ack'
25
+ actualReasoningEffort: 'spawn-ack',
26
+ spawnModeRequired: false,
27
+ actualModelRequired: false,
28
+ actualReasoningEffortRequired: false,
29
+ fallbackReasonRequired: false
26
30
  },
27
31
  project: {
28
32
  ownedPathPrefixes: ['.claude/'],
@@ -4,7 +4,9 @@ import fs from 'node:fs';
4
4
  import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import semver from 'semver';
7
- import { resolveAgentRuntimeStoreRoot } from '../../../runtime/agent-runtime.js';
7
+ import { parseCodexLifecycleBinding } from './binding.js';
8
+ import { hasActiveCodexLifecycleEvidence } from './store.js';
9
+ import { resolveTaskContext, resolveTaskRef } from '../../../task/resolve-ref.js';
8
10
  const LIFECYCLE_HOOKS = Object.freeze([
9
11
  Object.freeze({ event: 'PreToolUse', matcher: '^collaborationspawn_agent$', phase: 'pre-tool' }),
10
12
  Object.freeze({ event: 'PostToolUse', matcher: '', phase: 'post-tool' }),
@@ -25,16 +27,15 @@ function object(value) {
25
27
  function nonEmpty(value) {
26
28
  return typeof value === 'string' && value.trim() ? value : null;
27
29
  }
28
- function resolveCodexSpawnedChild(transcriptPath, expected) {
30
+ function readRolloutRecords(transcriptPath, sessionId) {
29
31
  const name = path.basename(transcriptPath);
30
- if (!transcriptPath || (!name.endsWith(`-${expected.sessionId}.jsonl`) && name !== `${expected.sessionId}.jsonl`)) {
32
+ if (!transcriptPath || (!name.endsWith(`-${sessionId}.jsonl`) && name !== `${sessionId}.jsonl`)) {
31
33
  throw new Error('Codex parent rollout path is invalid');
32
34
  }
33
35
  const stat = fs.lstatSync(transcriptPath);
34
36
  if (!stat.isFile() || stat.isSymbolicLink())
35
37
  throw new Error('Codex parent rollout is not a regular file');
36
- const maxBytes = 8 * 1024 * 1024;
37
- const offset = Math.max(0, stat.size - maxBytes);
38
+ const offset = Math.max(0, stat.size - 8 * 1024 * 1024);
38
39
  const buffer = Buffer.alloc(stat.size - offset);
39
40
  const descriptor = fs.openSync(transcriptPath, 'r');
40
41
  try {
@@ -46,37 +47,48 @@ function resolveCodexSpawnedChild(transcriptPath, expected) {
46
47
  let text = buffer.toString('utf8');
47
48
  if (offset)
48
49
  text = text.slice(text.indexOf('\n') + 1);
49
- const records = text.split(/\r?\n/).filter(Boolean).map((line) => object(JSON.parse(line))).filter(Boolean);
50
- const calls = records.filter((record) => {
51
- const payload = object(record?.payload);
52
- return record?.type === 'response_item'
53
- && payload?.type === 'function_call'
54
- && payload.call_id === expected.toolUseId
55
- && payload.namespace === 'collaboration'
56
- && payload.name === 'spawn_agent';
57
- });
50
+ return text.split(/\r?\n/u).filter(Boolean).map((line) => object(JSON.parse(line))).filter((record) => Boolean(record));
51
+ }
52
+ function isExpectedSpawnCall(record, expected) {
53
+ const payload = object(record.payload);
54
+ return record.type === 'response_item'
55
+ && payload?.type === 'function_call'
56
+ && payload.call_id === expected.toolUseId
57
+ && payload.namespace === 'collaboration'
58
+ && payload.name === 'spawn_agent';
59
+ }
60
+ function spawnArgsMatch(args, expected) {
61
+ return args?.agent_type === expected.nativeAgent
62
+ && args.task_name === expected.taskName
63
+ && (!expected.requestedModel || args.model === expected.requestedModel)
64
+ && (!expected.requestedReasoningEffort || args.reasoning_effort === expected.requestedReasoningEffort);
65
+ }
66
+ function isExpectedChildActivity(record, expected) {
67
+ const payload = object(record.payload);
68
+ const item = object(payload?.item);
69
+ return record.type === 'event_msg'
70
+ && payload?.type === 'item_completed'
71
+ && payload.thread_id === expected.sessionId
72
+ && payload.turn_id === expected.turnId
73
+ && item?.type === 'SubAgentActivity'
74
+ && item.id === expected.toolUseId
75
+ && item.kind === 'started'
76
+ && item.agent_path === `/root/${expected.taskName}`
77
+ && Boolean(nonEmpty(item.agent_thread_id));
78
+ }
79
+ function resolveCodexSpawnedChild(transcriptPath, expected) {
80
+ if (!parseCodexLifecycleBinding(expected.taskName)) {
81
+ throw new Error('Codex spawn task_name does not carry a valid lifecycle binding');
82
+ }
83
+ const records = readRolloutRecords(transcriptPath, expected.sessionId);
84
+ const calls = records.filter((record) => isExpectedSpawnCall(record, expected));
58
85
  if (calls.length !== 1)
59
86
  throw new Error('Codex parent rollout spawn call was not found uniquely');
60
87
  const call = object(calls[0]?.payload);
61
88
  const args = object(JSON.parse(nonEmpty(call?.arguments) ?? '{}'));
62
- if (args?.agent_type !== expected.nativeAgent
63
- || args.task_name !== expected.taskName
64
- || (expected.requestedModel && args.model !== expected.requestedModel)
65
- || (expected.requestedReasoningEffort && args.reasoning_effort !== expected.requestedReasoningEffort))
89
+ if (!spawnArgsMatch(args, expected))
66
90
  throw new Error('Codex parent rollout spawn identity does not match the hook event');
67
- const activities = records.filter((record) => {
68
- const payload = object(record?.payload);
69
- const item = object(payload?.item);
70
- return record?.type === 'event_msg'
71
- && payload?.type === 'item_completed'
72
- && payload.thread_id === expected.sessionId
73
- && payload.turn_id === expected.turnId
74
- && item?.type === 'SubAgentActivity'
75
- && item.id === expected.toolUseId
76
- && item.kind === 'started'
77
- && item.agent_path === `/root/${expected.taskName}`
78
- && nonEmpty(item.agent_thread_id);
79
- });
91
+ const activities = records.filter((record) => isExpectedChildActivity(record, expected));
80
92
  if (activities.length !== 1)
81
93
  throw new Error('Codex parent rollout child activity was not found uniquely');
82
94
  return nonEmpty(object(object(activities[0]?.payload)?.item)?.agent_thread_id);
@@ -141,27 +153,6 @@ function parseCodexHooksList(value, repoRoot, expectedSource = 'direct-host') {
141
153
  throw new Error('CODEX_PREFLIGHT_HOOKS_NOT_LOADED: lifecycle hooks are not loaded for this workspace');
142
154
  return Object.freeze(hooks);
143
155
  }
144
- function hasCodexRuntimeLiveness(runtimeRoot, hookDefinitionHash, identity) {
145
- if (!identity || !fs.existsSync(runtimeRoot))
146
- return false;
147
- return fs.readdirSync(runtimeRoot)
148
- .filter((name) => /^[a-f0-9]{64}\.json$/.test(name))
149
- .some((name) => {
150
- try {
151
- const record = object(JSON.parse(fs.readFileSync(path.join(runtimeRoot, name), 'utf8')));
152
- const state = object(record?.state);
153
- const spawnEvent = object(state?.spawn);
154
- return !['invalid', 'expired'].includes(String(state?.status))
155
- && spawnEvent?.hookDefinitionHash === hookDefinitionHash
156
- && spawnEvent.sessionId === identity.sessionId
157
- && spawnEvent.turnId === identity.turnId
158
- && spawnEvent.toolUseId === identity.toolUseId;
159
- }
160
- catch {
161
- return false;
162
- }
163
- });
164
- }
165
156
  function parseCodexThreadResolution(readValue, rolloutRecords) {
166
157
  const readRoot = object(readValue);
167
158
  const thread = object(readRoot?.thread);
@@ -215,6 +206,17 @@ function parseCodexThreadResolution(readValue, rolloutRecords) {
215
206
  })
216
207
  });
217
208
  }
209
+ function resolvePreflightTaskDir(repoRoot, taskId) {
210
+ try {
211
+ const context = taskId
212
+ ? resolveTaskRef(taskId, { repoRoot })
213
+ : resolveTaskContext(undefined, { repoRoot });
214
+ return context.ok ? context.taskDir : undefined;
215
+ }
216
+ catch {
217
+ return undefined;
218
+ }
219
+ }
218
220
  function readCodexRolloutRecords(readValue, childThreadId) {
219
221
  const thread = object(object(readValue)?.thread);
220
222
  const rolloutPath = nonEmpty(thread?.path);
@@ -491,7 +493,24 @@ async function resolveCodexTerminal(childThreadId, expectedTurnIdOrOptions = {},
491
493
  transport.close();
492
494
  }
493
495
  }
494
- async function preflightCodexLifecycleEvidence(repoRoot = process.cwd(), runtimeIdentity) {
496
+ async function preflightCodexLifecycleEvidence(repoRoot = process.cwd(), runtimeIdentity, taskId) {
497
+ const { cliVersion, hooksRaw } = validateStaticCodexPreflight(repoRoot);
498
+ const hookDefinitionHash = crypto.createHash('sha256').update(hooksRaw).digest('hex');
499
+ const taskDir = resolvePreflightTaskDir(repoRoot, taskId);
500
+ const runtimeLiveness = Boolean(taskDir && runtimeIdentity
501
+ && hasActiveCodexLifecycleEvidence(taskDir, { hookDefinitionHash, identity: runtimeIdentity }));
502
+ const host = await discoverLifecycleHooks(repoRoot);
503
+ return Object.freeze({
504
+ cliVersion,
505
+ hookDefinitionHash,
506
+ staticReady: true,
507
+ discoveredHooks: host.discoveredHooks,
508
+ hookProvenance: host.hookProvenance,
509
+ runtimeLiveness,
510
+ diagnostics: host.diagnostics
511
+ });
512
+ }
513
+ function validateStaticCodexPreflight(repoRoot) {
495
514
  const versionRun = spawnSync('codex', ['--version'], { encoding: 'utf8' });
496
515
  const match = /codex-cli\s+(\d+\.\d+\.\d+)/.exec(versionRun.stdout ?? '');
497
516
  if (versionRun.status !== 0 || !match?.[1] || !semver.gte(match[1], '0.147.0')) {
@@ -519,9 +538,9 @@ async function preflightCodexLifecycleEvidence(repoRoot = process.cwd(), runtime
519
538
  finally {
520
539
  fs.rmSync(schemaDir, { recursive: true, force: true });
521
540
  }
522
- const hookDefinitionHash = crypto.createHash('sha256').update(hooksRaw).digest('hex');
523
- const runtimeRoot = resolveAgentRuntimeStoreRoot({ repoRoot, store: 'lifecycle' });
524
- const runtimeLiveness = hasCodexRuntimeLiveness(runtimeRoot, hookDefinitionHash, runtimeIdentity);
541
+ return { cliVersion: match[1], hooksRaw };
542
+ }
543
+ async function discoverLifecycleHooks(repoRoot) {
525
544
  const transport = new CodexAppServerTransport();
526
545
  transport.start();
527
546
  let discoveredHooks;
@@ -548,10 +567,7 @@ async function preflightCodexLifecycleEvidence(repoRoot = process.cwd(), runtime
548
567
  const hookSource = process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT
549
568
  ? 'isolated-user'
550
569
  : source === 'managed' ? 'managed' : 'project';
551
- return Object.freeze({
552
- cliVersion: match[1],
553
- hookDefinitionHash,
554
- staticReady: true,
570
+ return {
555
571
  discoveredHooks,
556
572
  hookProvenance: Object.freeze({
557
573
  hookSource,
@@ -563,9 +579,8 @@ async function preflightCodexLifecycleEvidence(repoRoot = process.cwd(), runtime
563
579
  currentHash: hook.currentHash
564
580
  })))).digest('hex')
565
581
  }),
566
- runtimeLiveness,
567
582
  diagnostics: transport.diagnostics
568
- });
583
+ };
569
584
  }
570
- export { CodexAppServerTransport, hasCodexRuntimeLiveness, parseCodexModelReroute, parseCodexHooksList, parseCodexThreadResolution, parseCodexTurnCompleted, resolveCodexSpawnedChild, preflightCodexLifecycleEvidence, resolveCodexTerminal, resolveCodexThread, validateCodexLifecycleHookConfig };
585
+ export { CodexAppServerTransport, parseCodexModelReroute, parseCodexHooksList, parseCodexThreadResolution, parseCodexTurnCompleted, resolveCodexSpawnedChild, preflightCodexLifecycleEvidence, resolveCodexTerminal, resolveCodexThread, validateCodexLifecycleHookConfig };
571
586
  //# sourceMappingURL=app-server.js.map
@@ -0,0 +1,114 @@
1
+ import { managedDelegationRole } from '../../../task/delegation-receipts.js';
2
+ const MARKER_PREFIX = '__agent_infra_binding_';
3
+ const BASE32_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
4
+ const TASK_ID_PATTERN = /^TASK-[0-9]{8}-[0-9]{6}$/u;
5
+ const SAFE_LABEL_PATTERN = /^[a-z0-9_]{1,80}$/u;
6
+ const SAFE_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/u;
7
+ function assertSafeTaskName(taskName) {
8
+ if (Buffer.byteLength(taskName, 'utf8') > 255 || !/^[a-z0-9_]+$/u.test(taskName)) {
9
+ throw new Error('Codex task_name must use lowercase letters, digits, and underscores within 255 bytes');
10
+ }
11
+ }
12
+ function encodeTaskNamePayload(value) {
13
+ let buffer = 0;
14
+ let bits = 0;
15
+ let encoded = '';
16
+ for (const byte of Buffer.from(value, 'utf8')) {
17
+ buffer = (buffer << 8) | byte;
18
+ bits += 8;
19
+ while (bits >= 5) {
20
+ encoded += BASE32_ALPHABET[(buffer >>> (bits - 5)) & 31];
21
+ bits -= 5;
22
+ }
23
+ }
24
+ if (bits)
25
+ encoded += BASE32_ALPHABET[(buffer << (5 - bits)) & 31];
26
+ return encoded;
27
+ }
28
+ function decodeTaskNamePayload(encoded) {
29
+ let buffer = 0;
30
+ let bits = 0;
31
+ const bytes = [];
32
+ for (const character of encoded) {
33
+ const value = BASE32_ALPHABET.indexOf(character);
34
+ if (value < 0)
35
+ return null;
36
+ buffer = (buffer << 5) | value;
37
+ bits += 5;
38
+ if (bits >= 8) {
39
+ bytes.push((buffer >>> (bits - 8)) & 255);
40
+ bits -= 8;
41
+ }
42
+ }
43
+ if (bits && (buffer & ((1 << bits) - 1)) !== 0)
44
+ return null;
45
+ const decoded = Buffer.from(bytes).toString('utf8');
46
+ return encodeTaskNamePayload(decoded) === encoded ? decoded : null;
47
+ }
48
+ function encodeCodexLifecycleBinding(binding) {
49
+ if (!TASK_ID_PATTERN.test(binding.taskId)
50
+ || !SAFE_ID_PATTERN.test(binding.runId)
51
+ || !SAFE_ID_PATTERN.test(binding.receiptId)) {
52
+ throw new Error('Codex lifecycle task binding is invalid');
53
+ }
54
+ return `${MARKER_PREFIX}${encodeTaskNamePayload(JSON.stringify(binding))}`;
55
+ }
56
+ function appendCodexLifecycleBinding(label, binding) {
57
+ if (!SAFE_LABEL_PATTERN.test(label))
58
+ throw new Error('Codex task_name label is invalid');
59
+ const taskName = `${label}${encodeCodexLifecycleBinding(binding)}`;
60
+ assertSafeTaskName(taskName);
61
+ return taskName;
62
+ }
63
+ function parseCodexLifecycleBinding(taskName) {
64
+ assertSafeTaskName(taskName);
65
+ const markerIndex = taskName.lastIndexOf(MARKER_PREFIX);
66
+ if (markerIndex < 1)
67
+ return null;
68
+ const label = taskName.slice(0, markerIndex);
69
+ const encoded = taskName.slice(markerIndex + MARKER_PREFIX.length);
70
+ if (!SAFE_LABEL_PATTERN.test(label) || !/^[a-z2-7]+$/u.test(encoded))
71
+ return null;
72
+ try {
73
+ const decoded = decodeTaskNamePayload(encoded);
74
+ if (!decoded)
75
+ return null;
76
+ const value = JSON.parse(decoded);
77
+ if (Object.keys(value).sort().join(',') !== 'receiptId,runId,taskId'
78
+ || typeof value.taskId !== 'string' || !TASK_ID_PATTERN.test(value.taskId)
79
+ || typeof value.runId !== 'string' || !SAFE_ID_PATTERN.test(value.runId)
80
+ || typeof value.receiptId !== 'string' || !SAFE_ID_PATTERN.test(value.receiptId))
81
+ return null;
82
+ return Object.freeze({
83
+ taskName,
84
+ label,
85
+ binding: Object.freeze({ taskId: value.taskId, runId: value.runId, receiptId: value.receiptId })
86
+ });
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ function verifyCodexLifecycleTaskBinding(binding, run, nativeAgent, expected = {}) {
93
+ if (!codexReceiptMatchesBinding(binding, run, nativeAgent, expected)) {
94
+ throw new Error('Codex lifecycle task binding does not match the current pending receipt');
95
+ }
96
+ }
97
+ function codexReceiptMatchesBinding(binding, run, nativeAgent, expected) {
98
+ const receipt = run.pendingDelegation;
99
+ return Boolean(receipt)
100
+ && run.status === 'running'
101
+ && run.runId === binding.runId
102
+ && receipt.runId === binding.runId
103
+ && receipt.id === binding.receiptId
104
+ && receipt.client === 'codex'
105
+ && receipt.status === 'prepared'
106
+ && managedDelegationRole(nativeAgent) === receipt.role
107
+ && requestedBindingMatches(receipt, expected);
108
+ }
109
+ function requestedBindingMatches(receipt, expected) {
110
+ return (!expected.requestedModel || receipt.requestedModel === expected.requestedModel)
111
+ && (!expected.requestedReasoningEffort || receipt.requestedReasoningEffort === expected.requestedReasoningEffort);
112
+ }
113
+ export { appendCodexLifecycleBinding, encodeCodexLifecycleBinding, parseCodexLifecycleBinding, verifyCodexLifecycleTaskBinding };
114
+ //# sourceMappingURL=binding.js.map