@aiwg/cli 2026.10.5 → 2026.10.6

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 (212) hide show
  1. package/agentic/code/addons/composition-engine/lib/runtime.mjs +1401 -0
  2. package/agentic/code/addons/composition-engine/lib/validator.mjs +513 -0
  3. package/agentic/code/addons/composition-engine/schemas/flow-graph.schema.json +372 -0
  4. package/agentic/code/providers/model-capabilities.v1.json +74 -50
  5. package/bin/aiwg.mjs +3 -1
  6. package/dist/src/artifacts/browser-export.js +1 -0
  7. package/dist/src/artifacts/citation-parser.js +8 -1
  8. package/dist/src/artifacts/cli.js +57 -6
  9. package/dist/src/artifacts/fortemi-core-query-adapter.js +2 -0
  10. package/dist/src/artifacts/fortemi-core-sync.js +26 -8
  11. package/dist/src/artifacts/graph-query.js +18 -8
  12. package/dist/src/artifacts/index-adapters.js +339 -0
  13. package/dist/src/artifacts/index-builder.js +143 -14
  14. package/dist/src/artifacts/index-files.js +15 -4
  15. package/dist/src/artifacts/index-reader.js +44 -0
  16. package/dist/src/artifacts/index-refresh.js +114 -55
  17. package/dist/src/artifacts/index-status.js +20 -5
  18. package/dist/src/artifacts/memory-maintenance.js +503 -0
  19. package/dist/src/artifacts/prebuilt-relations.js +3 -1
  20. package/dist/src/artifacts/query-engine.js +263 -108
  21. package/dist/src/artifacts/relations-builder.js +2 -2
  22. package/dist/src/artifacts/source-graph.js +2 -2
  23. package/dist/src/artifacts/types.js +9 -1
  24. package/dist/src/cli/handlers/decision.js +19 -1
  25. package/dist/src/cli/handlers/guided-setup.js +470 -0
  26. package/dist/src/cli/handlers/help.js +2 -2
  27. package/dist/src/cli/handlers/housekeeper.js +1110 -0
  28. package/dist/src/cli/handlers/index.js +4 -2
  29. package/dist/src/cli/handlers/init.js +41 -6
  30. package/dist/src/cli/handlers/local-executor.js +5 -3
  31. package/dist/src/cli/handlers/mc.js +509 -53
  32. package/dist/src/cli/handlers/models.js +32 -2
  33. package/dist/src/cli/handlers/ralph-launcher.js +76 -4
  34. package/dist/src/cli/handlers/rules.js +1 -1
  35. package/dist/src/cli/handlers/script-runner.js +73 -2
  36. package/dist/src/cli/handlers/serve.js +5 -3
  37. package/dist/src/cli/handlers/sessions.js +1 -0
  38. package/dist/src/cli/handlers/setup.js +428 -1
  39. package/dist/src/cli/handlers/skill-lint.js +1 -1
  40. package/dist/src/cli/handlers/subcommands.js +118 -8
  41. package/dist/src/cli/handlers/use.js +279 -93
  42. package/dist/src/cli/handlers/workspace.js +3 -1
  43. package/dist/src/cli/prompt-utils.js +8 -0
  44. package/dist/src/cli/router.js +16 -1
  45. package/dist/src/config/aiwg-config.js +42 -0
  46. package/dist/src/config/cli.js +7 -3
  47. package/dist/src/config/decision-config.js +14 -1
  48. package/dist/src/config/native-sandbox-warnings.js +25 -0
  49. package/dist/src/contributors/validation.js +6 -5
  50. package/dist/src/decision/admission.js +7 -3
  51. package/dist/src/decision/benchmark.js +469 -0
  52. package/dist/src/decision/ledger.js +22 -3
  53. package/dist/src/decision/pricing.js +147 -0
  54. package/dist/src/decision/qualification/gate-evidence.js +18 -15
  55. package/dist/src/decision/qualification/load-staged.js +539 -0
  56. package/dist/src/decision/qualification/load.js +109 -33
  57. package/dist/src/decision/qualification/runner.js +5 -2
  58. package/dist/src/decision/review/service.js +6 -4
  59. package/dist/src/decision/review/validate.js +23 -2
  60. package/dist/src/decision/savings.js +8 -3
  61. package/dist/src/discovery/index.js +492 -0
  62. package/dist/src/discovery/interview.js +233 -0
  63. package/dist/src/discovery/plan-apply.js +571 -0
  64. package/dist/src/discovery/plan-store.js +171 -0
  65. package/dist/src/discovery/plan-types.js +2 -0
  66. package/dist/src/discovery/plan-validation.js +139 -0
  67. package/dist/src/discovery/types.js +2 -0
  68. package/dist/src/extensions/commands/definitions.js +49 -9
  69. package/dist/src/extensions/manifest.js +71 -44
  70. package/dist/src/extensions/project-local-discovery.js +1 -1
  71. package/dist/src/extensions/project-quickref.js +18 -17
  72. package/dist/src/extensions/validation.js +32 -29
  73. package/dist/src/housekeeper/daemon-config.js +148 -0
  74. package/dist/src/housekeeper/ipc.js +84 -0
  75. package/dist/src/housekeeper/lifecycle.js +148 -0
  76. package/dist/src/housekeeper/platform.js +35 -0
  77. package/dist/src/housekeeper/status.js +70 -0
  78. package/dist/src/housekeeper/units.js +114 -0
  79. package/dist/src/jobs/flow.js +22 -21
  80. package/dist/src/lint/rule-activation.js +20 -5
  81. package/dist/src/lint/runner.js +1 -1
  82. package/dist/src/mcp/cli.mjs +5 -6
  83. package/dist/src/mcp/config-file.mjs +6 -2
  84. package/dist/src/mcp/config-layers.mjs +23 -7
  85. package/dist/src/mcp/profiles.js +18 -31
  86. package/dist/src/mcp/profiles.mjs +18 -32
  87. package/dist/src/mcp/registry.js +7 -27
  88. package/dist/src/mcp/registry.mjs +7 -28
  89. package/dist/src/mcp/server.mjs +34 -1
  90. package/dist/src/mcp/tools/agentic-sandbox.mjs +8 -7
  91. package/dist/src/mcp/tools/command-run.mjs +3 -2
  92. package/dist/src/mcp/tools/decision.mjs +49 -48
  93. package/dist/src/mcp/tools/discovery.mjs +46 -21
  94. package/dist/src/mcp/tools/orchestration.mjs +22 -22
  95. package/dist/src/mcp/tools/subsystems.mjs +9 -8
  96. package/dist/src/mcp/tools/worker-invoke.mjs +17 -4
  97. package/dist/src/mcp/tools/writer-profiles.mjs +1 -1
  98. package/dist/src/memory/audit.js +719 -0
  99. package/dist/src/memory/canonical-context.js +392 -13
  100. package/dist/src/memory/canonical-maintenance.js +95 -0
  101. package/dist/src/memory/cli-result.js +22 -0
  102. package/dist/src/memory/cli.js +176 -0
  103. package/dist/src/memory/context-pack.js +57 -6
  104. package/dist/src/memory/cost.js +512 -0
  105. package/dist/src/memory/firewall-classification.d.mts +7 -0
  106. package/dist/src/memory/firewall-classification.mjs +32 -0
  107. package/dist/src/memory/index.js +8 -0
  108. package/dist/src/memory/line-maintenance.js +68 -0
  109. package/dist/src/memory/maintenance-cli.js +286 -0
  110. package/dist/src/memory/maintenance-contract.js +136 -0
  111. package/dist/src/memory/maintenance-index.js +18 -0
  112. package/dist/src/memory/maintenance-owner.js +2 -0
  113. package/dist/src/memory/maintenance-record.js +138 -0
  114. package/dist/src/memory/maintenance.js +254 -0
  115. package/dist/src/memory/provider-memory-adapter.js +154 -0
  116. package/dist/src/memory/recommend-cli.js +83 -0
  117. package/dist/src/memory/recommend.js +269 -0
  118. package/dist/src/memory/scheduled.js +81 -0
  119. package/dist/src/memory/taxonomy.js +44 -0
  120. package/dist/src/mission-protocol/codecs.js +19 -9
  121. package/dist/src/models/config-loader.js +11 -1
  122. package/dist/src/models/model-capabilities.v1.json +74 -50
  123. package/dist/src/models/provider-policy.js +125 -62
  124. package/dist/src/models/resolver.js +45 -8
  125. package/dist/src/models/worker-installation.d.mts +7 -0
  126. package/dist/src/models/worker-installation.mjs +169 -37
  127. package/dist/src/models/wrapper-route.js +1 -1
  128. package/dist/src/output-modes/registry.js +8 -7
  129. package/dist/src/plugin/metadata-validator.js +1 -1
  130. package/dist/src/providers/deploy-version.d.mts +1 -0
  131. package/dist/src/providers/deploy-version.mjs +17 -0
  132. package/dist/src/providers/provider-definitions.js +19 -16
  133. package/dist/src/providers/skill-ownership.d.mts +11 -2
  134. package/dist/src/providers/skill-ownership.mjs +35 -17
  135. package/dist/src/rules/activation.d.mts +11 -2
  136. package/dist/src/rules/activation.mjs +82 -6
  137. package/dist/src/rules/inventory.js +1 -1
  138. package/dist/src/rules/rule-frontmatter.schema.json +2 -0
  139. package/dist/src/schema/zod-validation.d.mts +6 -0
  140. package/dist/src/schema/zod-validation.mjs +50 -0
  141. package/dist/src/serve/executor-registry.js +297 -20
  142. package/dist/src/serve/executor-token.d.mts +1 -0
  143. package/dist/src/serve/executor-token.mjs +8 -0
  144. package/dist/src/serve/shared-host-scheduler.js +1102 -31
  145. package/dist/src/serve/worker-invocation.js +114 -15
  146. package/dist/src/sessions/adapters/claude.js +19 -18
  147. package/dist/src/sessions/adapters/codex.js +10 -9
  148. package/dist/src/sessions/adapters/copilot.js +14 -13
  149. package/dist/src/sessions/adapters/cursor.js +19 -18
  150. package/dist/src/sessions/adapters/deepseek-harness.js +9 -8
  151. package/dist/src/sessions/adapters/factory.js +11 -10
  152. package/dist/src/sessions/adapters/generic.js +32 -23
  153. package/dist/src/sessions/adapters/grokbot.js +35 -35
  154. package/dist/src/sessions/adapters/hermes.js +20 -19
  155. package/dist/src/sessions/adapters/muse.js +50 -49
  156. package/dist/src/sessions/adapters/omp.js +5 -4
  157. package/dist/src/sessions/adapters/openclaw.js +30 -29
  158. package/dist/src/sessions/adapters/opencode.js +26 -26
  159. package/dist/src/sessions/adapters/openhuman.js +24 -23
  160. package/dist/src/sessions/adapters/pi.js +5 -4
  161. package/dist/src/sessions/adapters/windsurf.js +8 -8
  162. package/dist/src/sessions/analytics.js +10 -9
  163. package/dist/src/sessions/candidates.js +7 -6
  164. package/dist/src/sessions/contracts.js +63 -53
  165. package/dist/src/sessions/output-registration.js +11 -10
  166. package/dist/src/sessions/workspace-discovery.js +3 -4
  167. package/dist/src/smiths/context-pipeline/aiwg-md.js +18 -1
  168. package/dist/src/smiths/context-pipeline/claude-hook.js +42 -6
  169. package/dist/src/smiths/context-pipeline/parallelism-section.js +72 -5
  170. package/dist/src/smiths/context-pipeline/workspace-context.js +106 -10
  171. package/dist/src/update/checker.d.mts +4 -0
  172. package/dist/src/update/checker.mjs +14 -0
  173. package/dist/src/writing/exemplar-selection.js +6 -6
  174. package/dist/src/writing/voice-evaluation.js +24 -23
  175. package/dist/src/writing/writer-migration.js +14 -13
  176. package/dist/src/writing/writer-profile.js +19 -18
  177. package/dist/src/writing/writing-brief.js +18 -17
  178. package/dist/src/writing/writing-receipt.js +47 -46
  179. package/package.json +5 -2
  180. package/schemas/decision/DecisionReview.schema.json +78 -1
  181. package/schemas/mission-v1.schema.json +3 -0
  182. package/tools/agents/deploy-agents.mjs +67 -39
  183. package/tools/agents/providers/antigravity.mjs +6 -1
  184. package/tools/agents/providers/base.mjs +19 -13
  185. package/tools/agents/providers/claude.mjs +1 -1
  186. package/tools/agents/providers/codex.mjs +50 -56
  187. package/tools/agents/providers/copilot.mjs +8 -2
  188. package/tools/agents/providers/cursor.mjs +1 -1
  189. package/tools/agents/providers/deepseek-harness.mjs +1 -1
  190. package/tools/agents/providers/factory.mjs +7 -1
  191. package/tools/agents/providers/grok-build.mjs +18 -2
  192. package/tools/agents/providers/grokbot.mjs +1 -1
  193. package/tools/agents/providers/hermes.mjs +7 -13
  194. package/tools/agents/providers/muse-hooks.mjs +21 -14
  195. package/tools/agents/providers/muse.mjs +7 -2
  196. package/tools/agents/providers/omp.mjs +28 -4
  197. package/tools/agents/providers/opencode.mjs +14 -5
  198. package/tools/agents/providers/openhuman.mjs +1 -1
  199. package/tools/agents/providers/pi.mjs +1 -1
  200. package/tools/agents/providers/provider-prepare-coordinator.mjs +29 -9
  201. package/tools/agents/providers/rule-delivery.mjs +263 -71
  202. package/tools/agents/providers/windsurf.mjs +7 -0
  203. package/tools/cli/workspace-status.mjs +5 -0
  204. package/tools/commands/deploy-prompts-codex.mjs +11 -8
  205. package/tools/ralph-external/lib/codex-adapter.mjs +6 -2
  206. package/tools/ralph-external/lib/muse-adapter.mjs +12 -2
  207. package/tools/ralph-external/lib/worker-health.mjs +1 -1
  208. package/tools/ralph-external/lib/worker-isolation.mjs +65 -9
  209. package/tools/ralph-external/process-monitor.mjs +7 -4
  210. package/tools/ralph-external/session-launcher.mjs +280 -32
  211. package/tools/skills/deploy-skills-codex.mjs +11 -7
  212. package/vscode-extension/schemas/aiwg.config.v1.json +11 -1
@@ -8,7 +8,7 @@ import { resolveWorkerPlan } from '../models/resolver.js';
8
8
  import { workerConfigDigest, validateWorkerHealthConfig } from '../config/aiwg-config.js';
9
9
  import { assertValidWorkerPayload } from '../mission-protocol/codecs.js';
10
10
  import { qualificationDigest } from '../models/qualification-digest.mjs';
11
- import { qualifyWorkerInvocationProfile, isOperatorQualifiedWorkerAdapter, assertOperatorWorkerNativeArgv, assertWorkerSelectionAllowed, requiredWorkerControls, requiresWorkerExternalBoundary, isCanonicalWorkerModelKey, assertWorkerHealthQualification, WorkerPolicyError, DEFAULT_WORKER_SELECTION } from '../models/provider-policy.js';
11
+ import { qualifyWorkerInvocationProfile, isOperatorQualifiedWorkerAdapter, assertOperatorWorkerNativeArgv, assertWorkerSelectionAllowed, assertWorkerLaunchMode, WorkerRoleEffortError, requiredWorkerControls, requiresWorkerExternalBoundary, isCanonicalWorkerModelKey, assertWorkerHealthQualification, WorkerPolicyError, DEFAULT_WORKER_SELECTION } from '../models/provider-policy.js';
12
12
  /** Frozen per-attempt windows; parent/transport ceilings include time already spent. */
13
13
  export function resolveWorkerEffectiveHealth(config, input) {
14
14
  const roleDefaults = { efficiency: 1, coding: 1, reasoning: 2 };
@@ -101,6 +101,10 @@ export async function prepareWorkerInvocation(invocation, qualification) {
101
101
  if (qualification.adapter.id !== qualification.adapterId) {
102
102
  throw new Error('Worker invocation adapter identity mismatch');
103
103
  }
104
+ assertWorkerLaunchMode(qualification.adapter, qualification.permissions);
105
+ if (result.isolation !== undefined && result.isolation !== (qualification.permissions?.launchMode ?? 'systemd-unit')) {
106
+ throw new WorkerPolicyError('OG_PIN_MISMATCH', 'Worker launch mode differs from the execution policy');
107
+ }
104
108
  for (const [key, value] of Object.entries(qualification.expectedDigests ?? {})) {
105
109
  if (result[key] !== value)
106
110
  throw new WorkerPolicyError('OG_PIN_MISMATCH', `Worker invocation ${key} changed`);
@@ -225,6 +229,56 @@ export async function prepareWorkerInvocation(invocation, qualification) {
225
229
  model: result.selected.model, effort: result.selected.effort.value });
226
230
  return result;
227
231
  }
232
+ const invocationChecks = {
233
+ invocation_build_failed: { pointer: '/invocation/buildInvocation',
234
+ message: 'Worker adapter could not build the invocation; check the selected model, effort, permissions and request paths.' },
235
+ native_argv_invalid: { pointer: '/invocation/argv',
236
+ message: 'Worker adapter arguments do not preserve the requested native controls; review the installed driver and qualify again.' },
237
+ invocation_prepare_failed: { pointer: '/invocation/prepareWorkerInvocation',
238
+ message: 'Worker invocation preparation failed; check installation evidence, policy, paths and environment, then qualify again.' },
239
+ installation_recheck_unavailable: { pointer: '/invocation/prepareWorkerInvocation',
240
+ message: 'The selected profile requires an installation recheck, but the installed driver has no preparation method. Restore the qualified driver and qualify again.' },
241
+ qualified_workspace_mismatch: { pointer: '/request/workdir',
242
+ message: 'Worker workdir differs from the qualified workspace. Use the qualified workspace or run aiwg doctor --probe-workers --qualify from the requested workdir.' },
243
+ };
244
+ /** Only fixed check identifiers, never adapter/filesystem error text, cross this boundary. */
245
+ export class WorkerInvocationCheckError extends WorkerPolicyError {
246
+ reason;
247
+ constructor(code, reason) {
248
+ super(code, invocationChecks[reason].message);
249
+ this.reason = reason;
250
+ }
251
+ }
252
+ /** Nonlaunching build and native-control check shared by resolution and doctor. */
253
+ export async function buildWorkerInvocationTransport(driver, input) {
254
+ assertWorkerLaunchMode(driver.qualification.adapter, input.permissions);
255
+ let transport;
256
+ try {
257
+ transport = await driver.buildInvocation(input);
258
+ }
259
+ catch (error) {
260
+ throw new WorkerInvocationCheckError(error instanceof WorkerPolicyError ? error.code : 'OG_ADAPTER_UNQUALIFIED', 'invocation_build_failed');
261
+ }
262
+ if (driver.qualification.adapter.invocationProfiles?.[input.selected.profileRef]?.transport === 'shell') {
263
+ try {
264
+ assertOperatorWorkerNativeArgv(driver.qualification.adapter, transport.argv, input.selected, input.permissions);
265
+ }
266
+ catch {
267
+ throw new WorkerInvocationCheckError('OG_ADAPTER_UNQUALIFIED', 'native_argv_invalid');
268
+ }
269
+ }
270
+ return transport;
271
+ }
272
+ /** Only fixed argument guidance is safe to expose in public request diagnostics. */
273
+ class WorkerRequestArgumentError extends WorkerPolicyError {
274
+ pointer;
275
+ constructor(key) {
276
+ super('OG_CONFIG_REFERENCE', key === 'task'
277
+ ? `Missing required --task. Valid task classes: ${Object.keys(DEFAULT_WORKER_SELECTION.taskClasses).join(', ')}, plus classes configured in defaults.workerSelection.taskClasses.`
278
+ : `--${key.replace('_', '-')} must be an absolute path; relative paths are not resolved against cwd or --workdir.`);
279
+ this.pointer = `/request/${key}`;
280
+ }
281
+ }
228
282
  /** Reject unsupported syntax before discovery or any path reads. */
229
283
  export function parseWorkerCommandArgs(args) {
230
284
  const names = { role: 'role', task: 'task', group: 'group', brief: 'brief',
@@ -254,6 +308,8 @@ export function parseWorkerCommandArgs(args) {
254
308
  throw new Error(`Duplicate --${match[1]}`);
255
309
  const value = match[2] ?? args[++i];
256
310
  if (!value || value.startsWith('--') && match[2] === undefined || value.includes('\0')) {
311
+ if (key === 'task' && !value?.includes('\0'))
312
+ throw new WorkerRequestArgumentError('task');
257
313
  throw new Error(`--${match[1]} requires a value`);
258
314
  }
259
315
  result[key] = value;
@@ -263,6 +319,8 @@ export function parseWorkerCommandArgs(args) {
263
319
  if (json)
264
320
  result.format = 'json';
265
321
  for (const key of ['role', 'task', 'group', 'brief', 'workdir', 'final_output']) {
322
+ if (key === 'task' && !result[key])
323
+ throw new WorkerRequestArgumentError('task');
266
324
  if (!result[key])
267
325
  throw new Error(`Missing ${key}`);
268
326
  }
@@ -342,7 +400,9 @@ export class WorkerPathScopeError extends WorkerPolicyError {
342
400
  }
343
401
  /** Re-resolve saved JSON through the same trusted owners; saved argv is never authority. */
344
402
  export async function revalidateWorkerInvocationPlan(saved, snapshot, drivers, now = new Date().toISOString()) {
345
- if (!saved.request || saved.mode !== 'direct' || saved.status !== 'eligible'
403
+ const managed = saved.mode === 'managed' && snapshot.config.parallelism?.worker_mode === 'managed';
404
+ if (!saved.request || (saved.mode !== 'direct' && !managed) || saved.mode !== (snapshot.config.parallelism?.worker_mode ?? 'direct') || saved.status !== 'eligible'
405
+ || (managed && saved.invocation?.mode !== 'managed')
346
406
  || saved.invocation?.readiness !== 'launchable' || Date.parse(saved.invocation.expiresAt) <= Date.parse(now)) {
347
407
  throw new Error('A fresh launchable models resolve JSON plan is required');
348
408
  }
@@ -366,8 +426,18 @@ export async function resolveWorkerInvocation(snapshot, request, drivers, now =
366
426
  let failureCode = 'OG_CONFIG_REFERENCE';
367
427
  let plan;
368
428
  try {
369
- if (!path.isAbsolute(request.brief))
370
- throw new WorkerPolicyError('OG_CONFIG_REFERENCE', '--brief must be an absolute path; relative paths are not resolved against cwd or --workdir.');
429
+ const managedIntent = request.managedIntent;
430
+ if (managedIntent) {
431
+ assertValidWorkerPayload('workerSelectionIntent', managedIntent);
432
+ if (snapshot.config.parallelism?.worker_mode !== 'managed'
433
+ || managedIntent.role !== request.role || managedIntent.taskClass !== request.task || managedIntent.group !== request.group) {
434
+ throw new Error('Managed task authority differs from the worker request');
435
+ }
436
+ }
437
+ for (const key of ['brief', 'workdir', 'final_output']) {
438
+ if (!path.isAbsolute(request[key]))
439
+ throw new WorkerRequestArgumentError(key);
440
+ }
371
441
  const bytes = await readBrief(request.brief);
372
442
  const briefDigest = bytes === null ? null : bytesDigest(bytes);
373
443
  if (expected && expected.briefDigest !== briefDigest)
@@ -375,7 +445,10 @@ export async function resolveWorkerInvocation(snapshot, request, drivers, now =
375
445
  let brief;
376
446
  if (bytes?.toString('utf8').trimStart().startsWith('{')) {
377
447
  brief = JSON.parse(bytes.toString('utf8'));
378
- assertValidWorkerPayload('workerDirectBrief', brief);
448
+ assertValidWorkerPayload(managedIntent ? 'workerBrief' : 'workerDirectBrief', brief);
449
+ if (managedIntent && workerConfigDigest(brief.intent) !== workerConfigDigest(managedIntent)) {
450
+ throw new Error('Managed brief differs from parent task authority');
451
+ }
379
452
  if (brief.intent.role !== request.role || brief.intent.taskClass !== request.task || brief.intent.group !== request.group
380
453
  || brief.workspace.path !== request.workdir || brief.output.resultPath !== request.final_output) {
381
454
  throw new WorkerPolicyError('OG_PIN_MISMATCH', 'Brief role/task/group/workspace/output differs from request');
@@ -387,6 +460,9 @@ export async function resolveWorkerInvocation(snapshot, request, drivers, now =
387
460
  model: brief.intent.pins.model, effort: brief.intent.pins.effort?.value, ceilings: {
388
461
  ...brief.intent.limits, costUsd: brief.intent.limits.costUsd ?? undefined
389
462
  } } : {}),
463
+ ...(managedIntent ? { dataClass: managedIntent.dataClass, member: managedIntent.pins.member,
464
+ model: managedIntent.pins.model, effort: managedIntent.pins.effort?.value,
465
+ ceilings: { ...managedIntent.limits, costUsd: managedIntent.limits.costUsd ?? undefined } } : {}),
390
466
  context: { estimator: 'utf8-byte-upper-bound-v1', briefTokens: bytes?.length ?? 0,
391
467
  inputTokens: 0, toolOutputAllowance: 1024, reservedOutput: 1024 },
392
468
  requiredControls: snapshot.config.parallelism?.health?.requireStepCap ? ['stepCap'] : [],
@@ -394,6 +470,11 @@ export async function resolveWorkerInvocation(snapshot, request, drivers, now =
394
470
  plan.request = structuredClone(request);
395
471
  if (!plan.selected)
396
472
  return plan;
473
+ if (plan.mode === 'managed' && !managedIntent) {
474
+ plan.diagnostics.push({ code: 'OG_CONFIG_REFERENCE', pointer: '/request/managedIntent',
475
+ message: 'Managed execution requires the parent task authority and shared admission.' });
476
+ return plan;
477
+ }
397
478
  const tuple = plan.selected;
398
479
  pointer = `/parallelism/clis/${tuple.cli}`;
399
480
  failureCode = 'OG_ADAPTER_UNQUALIFIED';
@@ -447,7 +528,7 @@ export async function resolveWorkerInvocation(snapshot, request, drivers, now =
447
528
  + (plan.policy?.freshness?.policyDays ?? DEFAULT_WORKER_SELECTION.freshness.policyDays) * 86400000)).toISOString();
448
529
  const healthConfig = snapshot.config.parallelism?.health;
449
530
  if (profile.installationQualification && !driver.prepareWorkerInvocation) {
450
- throw new Error('Installation-scoped profile requires the #2885 adapter preparation/recheck method');
531
+ throw new WorkerInvocationCheckError('OG_ADAPTER_UNQUALIFIED', 'installation_recheck_unavailable');
451
532
  }
452
533
  if (tuple.transport === 'mcp') {
453
534
  const serverRef = profile.mcp.serverRef;
@@ -462,23 +543,25 @@ export async function resolveWorkerInvocation(snapshot, request, drivers, now =
462
543
  }
463
544
  const controls = isOperatorQualifiedWorkerAdapter(adapter) ? (healthConfig?.requireStepCap ? ['stepCap'] : []) : requiredWorkerControls({ policy: plan.policy, permissions: tuple.permissions, effort: tuple.effort,
464
545
  requiredControls: healthConfig?.requireStepCap ? ['stepCap'] : [] });
465
- pointer = `/parallelism/clis/${tuple.cli}/invocationProfile`;
546
+ pointer = '/parallelism/health';
466
547
  failureCode = 'OG_ADAPTER_UNQUALIFIED';
467
548
  const healthInput = { role: request.role, effort: tuple.effort,
468
549
  modelKey: tuple.modelKey, profileRef: tuple.profile, wallSeconds: limits.wallSeconds,
469
550
  transportSeconds: adapter.invocation.kind === 'http' ? adapter.invocation.timeoutSeconds : undefined,
470
551
  stepEnforcement: controls.includes('stepCap') ? profile.controls.stepCap.support : 'unavailable' };
471
552
  let effectiveHealth = resolveWorkerEffectiveHealth(healthConfig, healthInput);
472
- const transport = await driver.buildInvocation({ selected: structuredClone(selected), permissions: structuredClone(tuple.permissions),
553
+ const transport = await buildWorkerInvocationTransport(driver, { selected: structuredClone(selected), permissions: structuredClone(tuple.permissions),
473
554
  cwd: request.workdir, briefPath: request.brief, brief: bytes?.toString('utf8') ?? '', finalPath, limits: structuredClone(limits),
474
555
  health: structuredClone(effectiveHealth) });
556
+ pointer = '/invocation/buildInvocation';
475
557
  if (transport.stdin === 'adapter-frame' && typeof driver.buildWorkerStdinFrame !== 'function')
476
558
  throw new Error('Installed adapter stdin framer is required');
477
559
  if (transport.mcp?.timeoutSeconds !== undefined)
478
560
  effectiveHealth = resolveWorkerEffectiveHealth(healthConfig, { ...healthInput, transportSeconds: Math.min(healthInput.transportSeconds ?? Infinity, transport.mcp.timeoutSeconds) });
479
561
  if (workerConfigDigest(driver.qualification) !== qualificationDigest)
480
562
  throw new WorkerPolicyError('OG_PIN_MISMATCH', 'Installation profile digest changed during resolution');
481
- const invocation = { version: 1, mode: 'direct', transport: tuple.transport, selected,
563
+ const invocation = { version: 1, mode: managedIntent ? 'managed' : 'direct', transport: tuple.transport, selected,
564
+ isolation: tuple.permissions.launchMode ?? 'systemd-unit',
482
565
  policyDigest, catalogDigest: plan.digests.catalogDigest, profileDigest: plan.digests.profileDigest,
483
566
  expiresAt, cwd: request.workdir, briefPath: request.brief, stdoutPath, stderrPath, finalPath,
484
567
  ...(transport.artifacts ? { artifacts: transport.artifacts } : {}),
@@ -493,13 +576,23 @@ export async function resolveWorkerInvocation(snapshot, request, drivers, now =
493
576
  policy: plan.policy, permissions: tuple.permissions, role: request.role, modelObservation: observation,
494
577
  expectedDigests: { policyDigest, catalogDigest: plan.digests.catalogDigest, profileDigest: plan.digests.profileDigest, briefDigest },
495
578
  requiredControls: controls };
496
- const prepared = await (driver.prepareWorkerInvocation
497
- ? driver.prepareWorkerInvocation(structuredClone(invocation), invocationQualification)
498
- : prepareWorkerInvocation(invocation, invocationQualification));
579
+ let prepared;
580
+ pointer = '/invocation/prepareWorkerInvocation';
581
+ try {
582
+ prepared = await (driver.prepareWorkerInvocation
583
+ ? driver.prepareWorkerInvocation(structuredClone(invocation), invocationQualification)
584
+ : prepareWorkerInvocation(invocation, invocationQualification));
585
+ }
586
+ catch (error) {
587
+ if (error instanceof WorkerPathScopeError || error instanceof WorkerInvocationCheckError)
588
+ throw error;
589
+ throw new WorkerInvocationCheckError(error instanceof WorkerPolicyError ? error.code : 'OG_ADAPTER_UNQUALIFIED', 'invocation_prepare_failed');
590
+ }
499
591
  if (workerConfigDigest({ ...prepared, shellCommand: invocation.shellCommand }) !== workerConfigDigest(invocation)) {
500
592
  throw new WorkerPolicyError('OG_PIN_MISMATCH', 'Installation preparation changed the resolved invocation');
501
593
  }
502
594
  if (tuple.transport === 'mcp' && profile.installationQualification) {
595
+ pointer = '/invocation/mcp';
503
596
  const installation = qualification.installation;
504
597
  if (!installation?.mcpServerDigest || !driver.mcpRegistry?.assertWorkerQualified) {
505
598
  throw new Error('MCP installation registration recheck is required');
@@ -539,10 +632,17 @@ export async function resolveWorkerInvocation(snapshot, request, drivers, now =
539
632
  }
540
633
  /** Public diagnostics contain fixed summaries or explicit typed request-path details. */
541
634
  export function workerInvocationDiagnostic(error, pointer, fallback = 'OG_CONFIG_REFERENCE') {
542
- if (error instanceof WorkerPathScopeError)
635
+ if (error instanceof WorkerRoleEffortError)
636
+ return { code: error.code, pointer: error.pointer, message: error.message };
637
+ if (error instanceof WorkerPathScopeError || error instanceof WorkerRequestArgumentError) {
543
638
  return { code: error.code, pointer: error.pointer, message: error.message };
639
+ }
640
+ if (error instanceof WorkerInvocationCheckError)
641
+ return { code: error.code, reason: error.reason, ...invocationChecks[error.reason] };
544
642
  const code = error instanceof WorkerPolicyError ? error.code : fallback;
545
643
  const messages = {
644
+ OG_SANDBOX_EXTERNAL: "The CLI's own sandbox is disabled by explicit external policy; isolation relies on the per-task worktree and launcher resource scope.",
645
+ OG_NATIVE_SANDBOX_UNAVAILABLE: 'Native sandbox unavailable inside systemd user units; select policy launchMode native-sandbox or allow unprivileged user namespaces through host AppArmor policy.',
546
646
  OG_CONFIG_REFERENCE: 'Invalid request or configuration reference; check the paths and settings.',
547
647
  OG_PIN_MISMATCH: 'Worker selection or pinned evidence changed; resolve again.',
548
648
  OG_MODEL_UNAPPROVED: 'The selected model lacks current approved observation evidence.',
@@ -552,7 +652,6 @@ export function workerInvocationDiagnostic(error, pointer, fallback = 'OG_CONFIG
552
652
  OG_POLICY_RELAXATION: 'The request would relax the resolved worker policy.',
553
653
  OG_BUDGET_UNMEASURABLE: 'The requested worker budget cannot be enforced.',
554
654
  };
555
- return { code, pointer, message: error instanceof WorkerPolicyError && error.message === '--brief must be an absolute path; relative paths are not resolved against cwd or --workdir.'
556
- ? error.message : messages[code] };
655
+ return { code, pointer, message: messages[code] };
557
656
  }
558
657
  //# sourceMappingURL=worker-invocation.js.map
@@ -1,6 +1,7 @@
1
1
  import { opendir } from 'node:fs/promises';
2
2
  import { basename, extname, resolve } from 'node:path';
3
3
  import { z } from 'zod';
4
+ import { dateTime, number } from '../../schema/zod-validation.mjs';
4
5
  import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, assertSupportedSchemaMajor, sha256, } from '../contracts.js';
5
6
  import { redactSourceLocator } from '../discovery.js';
6
7
  import { readBoundedJson, streamBoundedJsonLines, } from '../readers.js';
@@ -9,14 +10,14 @@ export const CLAUDE_TRANSCRIPT_SCHEMA_VERSION = '1.0.0';
9
10
  /** AIWG's own understanding of the layout it supports; Claude web/account
10
11
  * exports carry no in-band schema version to read instead. */
11
12
  export const CLAUDE_WEB_EXPORT_SCHEMA_VERSION = '1.0.0';
12
- const ClaudeRecordSchema = z.object({
13
+ const ClaudeRecordSchema = z.looseObject({
13
14
  type: z.string().min(1),
14
15
  subtype: z.string().optional(),
15
16
  uuid: z.string().min(1).optional(),
16
17
  parentUuid: z.string().min(1).nullable().optional(),
17
18
  sessionId: z.string().min(1).optional(),
18
19
  session_id: z.string().min(1).optional(),
19
- timestamp: z.string().datetime({ offset: true }).optional(),
20
+ timestamp: dateTime({ offset: true }).optional(),
20
21
  cwd: z.string().optional(),
21
22
  gitBranch: z.string().optional(),
22
23
  parentSessionId: z.string().min(1).optional(),
@@ -25,13 +26,13 @@ const ClaudeRecordSchema = z.object({
25
26
  slug: z.string().min(1).optional(),
26
27
  version: z.string().optional(),
27
28
  schemaVersion: z.string().optional(),
28
- message: z.object({
29
+ message: z.looseObject({
29
30
  id: z.string().min(1).optional(),
30
31
  role: z.string().min(1).optional(),
31
32
  content: z.union([z.string(), z.array(z.unknown())]).optional(),
32
- }).passthrough().optional(),
33
- }).passthrough();
34
- const ClaudeHookSchema = z.object({
33
+ }).optional(),
34
+ });
35
+ const ClaudeHookSchema = z.looseObject({
35
36
  session_id: z.string().min(1),
36
37
  transcript_path: z.string().min(1),
37
38
  cwd: z.string().min(1),
@@ -41,8 +42,8 @@ const ClaudeHookSchema = z.object({
41
42
  model: z.string().optional(),
42
43
  reason: z.string().optional(),
43
44
  schemaVersion: z.string().optional(),
44
- timestamp: z.string().datetime({ offset: true }).optional(),
45
- }).passthrough();
45
+ timestamp: dateTime({ offset: true }).optional(),
46
+ });
46
47
  /**
47
48
  * Claude.ai web/account data export (`conversations.json`): a JSON array of
48
49
  * conversations, each carrying its own `chat_messages`. This is a distinct
@@ -51,17 +52,17 @@ const ClaudeHookSchema = z.object({
51
52
  * rather than dropped, and content the export marks as an attachment/file is
52
53
  * recorded as a reference (bytes are not embedded in this export format).
53
54
  */
54
- const ClaudeWebExportAttachmentSchema = z.object({
55
+ const ClaudeWebExportAttachmentSchema = z.looseObject({
55
56
  file_name: z.string().optional(),
56
57
  file_type: z.string().optional(),
57
- file_size: z.number().optional(),
58
+ file_size: number().optional(),
58
59
  extracted_content: z.string().optional(),
59
- }).passthrough();
60
- const ClaudeWebExportContentBlockSchema = z.object({
60
+ });
61
+ const ClaudeWebExportContentBlockSchema = z.looseObject({
61
62
  type: z.string().optional(),
62
63
  text: z.string().optional(),
63
- }).passthrough();
64
- const ClaudeWebExportMessageSchema = z.object({
64
+ });
65
+ const ClaudeWebExportMessageSchema = z.looseObject({
65
66
  uuid: z.string().min(1),
66
67
  text: z.string().optional(),
67
68
  sender: z.enum(['human', 'assistant']),
@@ -70,15 +71,15 @@ const ClaudeWebExportMessageSchema = z.object({
70
71
  content: z.array(ClaudeWebExportContentBlockSchema).optional(),
71
72
  attachments: z.array(ClaudeWebExportAttachmentSchema).optional(),
72
73
  files: z.array(ClaudeWebExportAttachmentSchema).optional(),
73
- }).passthrough();
74
- const ClaudeWebExportConversationSchema = z.object({
74
+ });
75
+ const ClaudeWebExportConversationSchema = z.looseObject({
75
76
  uuid: z.string().min(1),
76
77
  name: z.string().optional(),
77
78
  created_at: z.string().optional(),
78
79
  updated_at: z.string().optional(),
79
- account: z.object({ uuid: z.string().optional() }).passthrough().optional(),
80
+ account: z.looseObject({ uuid: z.string().optional() }).optional(),
80
81
  chat_messages: z.array(ClaudeWebExportMessageSchema),
81
- }).passthrough();
82
+ });
82
83
  const ClaudeWebExportSchema = z.array(ClaudeWebExportConversationSchema);
83
84
  export class ClaudeSessionAdapter {
84
85
  limits;
@@ -1,18 +1,19 @@
1
1
  import { opendir } from 'node:fs/promises';
2
2
  import { basename, resolve } from 'node:path';
3
3
  import { z } from 'zod';
4
+ import { integer } from '../../schema/zod-validation.mjs';
4
5
  import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, assertSupportedSchemaMajor, } from '../contracts.js';
5
6
  import { streamBoundedJsonLines, } from '../readers.js';
6
7
  export const CODEX_ADAPTER_VERSION = '1.0.0';
7
8
  export const CODEX_SOURCE_SCHEMA_VERSION = '1.0.0';
8
- const AppServerEnvelopeSchema = z.object({
9
+ const AppServerEnvelopeSchema = z.looseObject({
9
10
  schemaVersion: z.string().optional(),
10
11
  productVersion: z.string().optional(),
11
12
  method: z.string().min(1),
12
13
  result: z.unknown().optional(),
13
14
  params: z.unknown().optional(),
14
- }).passthrough();
15
- const ThreadSchema = z.object({
15
+ });
16
+ const ThreadSchema = z.looseObject({
16
17
  id: z.string().min(1),
17
18
  sessionId: z.string().min(1).optional(),
18
19
  parentThreadId: z.string().nullable().optional(),
@@ -21,8 +22,8 @@ const ThreadSchema = z.object({
21
22
  preview: z.string().optional(),
22
23
  modelProvider: z.string().optional(),
23
24
  cliVersion: z.string().optional(),
24
- createdAt: z.number().int().optional(),
25
- updatedAt: z.number().int().optional(),
25
+ createdAt: integer().optional(),
26
+ updatedAt: integer().optional(),
26
27
  cwd: z.string().optional(),
27
28
  path: z.string().nullable().optional(),
28
29
  ephemeral: z.boolean().optional(),
@@ -30,13 +31,13 @@ const ThreadSchema = z.object({
30
31
  source: z.unknown().optional(),
31
32
  gitInfo: z.unknown().optional(),
32
33
  turns: z.array(z.unknown()).optional(),
33
- }).passthrough();
34
- const RolloutEnvelopeSchema = z.object({
34
+ });
35
+ const RolloutEnvelopeSchema = z.looseObject({
35
36
  schemaVersion: z.string().optional(),
36
37
  timestamp: z.string().optional(),
37
38
  type: z.string().min(1),
38
- payload: z.unknown(),
39
- }).passthrough();
39
+ payload: z.unknown().optional(),
40
+ });
40
41
  export class CodexSessionAdapter {
41
42
  limits;
42
43
  discoveryLimits;
@@ -1,43 +1,44 @@
1
1
  import { basename, extname } from 'node:path';
2
2
  import { z } from 'zod';
3
+ import { integer, number } from '../../schema/zod-validation.mjs';
3
4
  import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, assertSupportedSchemaMajor, } from '../contracts.js';
4
5
  import { readBoundedJson } from '../readers.js';
5
6
  export const COPILOT_ADAPTER_VERSION = '1.0.0';
6
7
  export const COPILOT_EXPORT_SCHEMA_VERSION = '1.0.0';
7
- const ResponsePartSchema = z.object({
8
+ const ResponsePartSchema = z.looseObject({
8
9
  value: z.string().optional(),
9
10
  kind: z.string().optional(),
10
- }).passthrough();
11
- const RequestSchema = z.object({
11
+ });
12
+ const RequestSchema = z.looseObject({
12
13
  requestId: z.string().min(1).optional(),
13
14
  message: z.union([
14
15
  z.string(),
15
- z.object({ text: z.string() }).passthrough(),
16
+ z.looseObject({ text: z.string() }),
16
17
  ]),
17
18
  response: z.union([
18
19
  z.string(),
19
20
  z.array(ResponsePartSchema),
20
21
  ]).optional(),
21
- timestamp: z.union([z.string(), z.number()]).optional(),
22
+ timestamp: z.union([z.string(), number()]).optional(),
22
23
  modelId: z.string().optional(),
23
- }).passthrough();
24
- const ExportSchema = z.object({
25
- version: z.union([z.number().int().positive(), z.string()]),
24
+ });
25
+ const ExportSchema = z.looseObject({
26
+ version: z.union([integer().positive(), z.string()]),
26
27
  schemaVersion: z.string().optional(),
27
28
  sessionId: z.string().min(1).optional(),
28
- creationDate: z.union([z.string(), z.number()]).optional(),
29
- lastMessageDate: z.union([z.string(), z.number()]).optional(),
29
+ creationDate: z.union([z.string(), number()]).optional(),
30
+ lastMessageDate: z.union([z.string(), number()]).optional(),
30
31
  requests: z.array(RequestSchema),
31
32
  requesterUsername: z.string().optional(),
32
33
  responderUsername: z.string().optional(),
33
34
  state: z.string().optional(),
34
35
  isArchived: z.boolean().optional(),
35
36
  syncStatus: z.string().optional(),
36
- workspace: z.object({
37
+ workspace: z.looseObject({
37
38
  id: z.string().optional(),
38
39
  repository: z.string().optional(),
39
- }).passthrough().optional(),
40
- }).passthrough();
40
+ }).optional(),
41
+ });
41
42
  export class CopilotSessionAdapter {
42
43
  limits;
43
44
  provider = 'copilot';
@@ -1,11 +1,12 @@
1
1
  import { opendir } from 'node:fs/promises';
2
2
  import { basename, dirname, extname, resolve, } from 'node:path';
3
3
  import { z } from 'zod';
4
+ import { dateTime } from '../../schema/zod-validation.mjs';
4
5
  import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, assertSupportedSchemaMajor, } from '../contracts.js';
5
6
  import { readBoundedText, streamBoundedJsonLines, } from '../readers.js';
6
7
  export const CURSOR_ADAPTER_VERSION = '1.0.0';
7
8
  export const CURSOR_SOURCE_SCHEMA_VERSION = '1.0.0';
8
- const CliEventSchema = z.object({
9
+ const CliEventSchema = z.looseObject({
9
10
  schemaVersion: z.string().optional(),
10
11
  cliVersion: z.string().optional(),
11
12
  version: z.string().optional(),
@@ -17,49 +18,49 @@ const CliEventSchema = z.object({
17
18
  cwd: z.string().optional(),
18
19
  model: z.string().optional(),
19
20
  permissionMode: z.string().optional(),
20
- message: z.object({
21
+ message: z.looseObject({
21
22
  role: z.string().optional(),
22
- content: z.array(z.object({
23
+ content: z.array(z.looseObject({
23
24
  type: z.string(),
24
25
  text: z.string().optional(),
25
- }).passthrough()).optional(),
26
- }).passthrough().optional(),
27
- tool_call: z.record(z.unknown()).optional(),
26
+ })).optional(),
27
+ }).optional(),
28
+ tool_call: z.record(z.string(), z.unknown()).optional(),
28
29
  result: z.string().optional(),
29
30
  is_error: z.boolean().optional(),
30
- }).passthrough();
31
- const CloudEventSchema = z.object({
31
+ });
32
+ const CloudEventSchema = z.looseObject({
32
33
  schemaVersion: z.string().optional(),
33
34
  id: z.string().optional(),
34
35
  event_id: z.string().optional(),
35
36
  type: z.string().min(1),
36
- agent: z.object({
37
+ agent: z.looseObject({
37
38
  id: z.string().min(1),
38
39
  status: z.string().optional(),
39
- }).passthrough().optional(),
40
- run: z.object({
40
+ }).optional(),
41
+ run: z.looseObject({
41
42
  id: z.string().min(1),
42
43
  status: z.string().optional(),
43
- }).passthrough().optional(),
44
+ }).optional(),
44
45
  data: z.unknown().optional(),
45
- }).passthrough().refine((value) => value.agent?.id || value.run?.id, {
46
+ }).refine((value) => value.agent?.id || value.run?.id, {
46
47
  message: 'cloud event requires an agent or run identity',
47
48
  });
48
- const AgentTranscriptEventSchema = z.object({
49
+ const AgentTranscriptEventSchema = z.looseObject({
49
50
  schemaVersion: z.string().optional(),
50
51
  id: z.string().optional(),
51
52
  event_id: z.string().optional(),
52
53
  request_id: z.string().optional(),
53
- timestamp: z.string().datetime({ offset: true }).optional(),
54
+ timestamp: dateTime({ offset: true }).optional(),
54
55
  type: z.string().min(1).optional(),
55
56
  status: z.string().min(1).optional(),
56
57
  role: z.string().min(1).optional(),
57
- message: z.object({
58
+ message: z.looseObject({
58
59
  id: z.string().optional(),
59
60
  role: z.string().optional(),
60
61
  content: z.union([z.string(), z.array(z.unknown())]).optional(),
61
- }).passthrough().optional(),
62
- }).passthrough().refine((value) => value.role || value.type, {
62
+ }).optional(),
63
+ }).refine((value) => value.role || value.type, {
63
64
  message: 'agent transcript event requires role or type',
64
65
  });
65
66
  export class CursorSessionAdapter {
@@ -1,20 +1,21 @@
1
1
  import { opendir } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
3
  import { z } from 'zod';
4
+ import { integer as integerSchema } from '../../schema/zod-validation.mjs';
4
5
  import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, } from '../contracts.js';
5
6
  import { streamBoundedJsonLines } from '../readers.js';
6
7
  export const DEEPSEEK_HARNESS_ADAPTER_VERSION = '1.0.0';
7
8
  export const DEEPSEEK_HARNESS_SOURCE_SCHEMA_VERSION = '2.0.0';
8
- const Header = z.object({
9
- type: z.literal('session'), version: z.number().int(), id: z.string().min(1),
9
+ const Header = z.looseObject({
10
+ type: z.literal('session'), version: integerSchema(), id: z.string().min(1),
10
11
  createdAt: z.number().finite(), cwd: z.string().optional(), parentSession: z.string().optional(),
11
12
  isSeeded: z.boolean(), origin: z.literal('subagent').optional(),
12
- delegationDepth: z.number().int().nonnegative(), agentPreset: z.string().optional(),
13
- }).passthrough();
14
- const Event = z.object({
15
- type: z.string().min(1), seq: z.number().int().nonnegative(), time: z.number().finite(),
16
- data: z.unknown(),
17
- }).passthrough();
13
+ delegationDepth: integerSchema().nonnegative(), agentPreset: z.string().optional(),
14
+ });
15
+ const Event = z.looseObject({
16
+ type: z.string().min(1), seq: integerSchema().nonnegative(), time: z.number().finite(),
17
+ data: z.unknown().optional(),
18
+ });
18
19
  const KNOWN = new Set([
19
20
  'turn/start', 'user/message', 'step/start', 'assistant/message', 'tool/call',
20
21
  'tool/result', 'request/header', 'request/context', 'session/end-seed',
@@ -1,11 +1,12 @@
1
1
  import { opendir } from 'node:fs/promises';
2
2
  import { basename, extname, resolve } from 'node:path';
3
3
  import { z } from 'zod';
4
+ import { number } from '../../schema/zod-validation.mjs';
4
5
  import { schemaRejectionDetail, schemaIssueDetail, SessionContractError, assertSupportedSchemaMajor, } from '../contracts.js';
5
6
  import { streamBoundedJsonLines, } from '../readers.js';
6
7
  export const FACTORY_ADAPTER_VERSION = '1.0.0';
7
8
  export const FACTORY_SOURCE_SCHEMA_VERSION = '1.0.0';
8
- const FactoryRecordSchema = z.object({
9
+ const FactoryRecordSchema = z.looseObject({
9
10
  schemaVersion: z.string().optional(),
10
11
  type: z.string().min(1),
11
12
  subtype: z.string().optional(),
@@ -14,21 +15,21 @@ const FactoryRecordSchema = z.object({
14
15
  parentUuid: z.string().nullable().optional(),
15
16
  sessionId: z.string().min(1).optional(),
16
17
  session_id: z.string().min(1).optional(),
17
- timestamp: z.union([z.string(), z.number()]).optional(),
18
- createdAt: z.number().optional(),
19
- updatedAt: z.number().optional(),
18
+ timestamp: z.union([z.string(), number()]).optional(),
19
+ createdAt: number().optional(),
20
+ updatedAt: number().optional(),
20
21
  cwd: z.string().optional(),
21
- version: z.union([z.string(), z.number()]).optional(),
22
- message: z.object({
22
+ version: z.union([z.string(), number()]).optional(),
23
+ message: z.looseObject({
23
24
  id: z.string().optional(),
24
25
  role: z.string().optional(),
25
26
  content: z.union([z.string(), z.array(z.unknown())]).optional(),
26
- }).passthrough().optional(),
27
+ }).optional(),
27
28
  content: z.union([z.string(), z.array(z.unknown())]).optional(),
28
- sessionSettings: z.record(z.unknown()).optional(),
29
- settings: z.record(z.unknown()).optional(),
29
+ sessionSettings: z.record(z.string(), z.unknown()).optional(),
30
+ settings: z.record(z.string(), z.unknown()).optional(),
30
31
  status: z.string().optional(),
31
- }).passthrough();
32
+ });
32
33
  export class FactorySessionAdapter {
33
34
  limits;
34
35
  transports;