spawnfile 0.1.17 → 0.1.19

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 (490) hide show
  1. package/README.md +1 -1
  2. package/dist/auth/importers.js +21 -5
  3. package/dist/auth/index.d.ts +1 -0
  4. package/dist/auth/index.js +1 -0
  5. package/dist/auth/profileStore.js +4 -1
  6. package/dist/auth/trainingGrokWriteback.d.ts +4 -0
  7. package/dist/auth/trainingGrokWriteback.js +119 -0
  8. package/dist/auth/trainingGrokWritebackLock.d.ts +5 -0
  9. package/dist/auth/trainingGrokWritebackLock.js +56 -0
  10. package/dist/cli/authCommands.js +9 -5
  11. package/dist/cli/compileBuildCommands.js +4 -0
  12. package/dist/cli/devCommands.js +4 -2
  13. package/dist/cli/downCommand.d.ts +2 -0
  14. package/dist/cli/downCommand.js +3 -0
  15. package/dist/cli/envFileOption.d.ts +18 -0
  16. package/dist/cli/envFileOption.js +20 -0
  17. package/dist/cli/lifecycleCommands.d.ts +1 -1
  18. package/dist/cli/lifecycleCommands.js +3 -1
  19. package/dist/cli/lifecyclePlan.d.ts +1 -0
  20. package/dist/cli/lifecyclePlan.js +2 -0
  21. package/dist/cli/paideiaDelegation.d.ts +2 -1
  22. package/dist/cli/paideiaDelegation.js +5 -4
  23. package/dist/cli/recordCommands.d.ts +17 -0
  24. package/dist/cli/recordCommands.js +43 -0
  25. package/dist/cli/releaseCommand.d.ts +6 -0
  26. package/dist/cli/releaseCommand.js +91 -0
  27. package/dist/cli/runCli.d.ts +7 -1
  28. package/dist/cli/runCli.js +11 -6
  29. package/dist/cli/runPublishCommands.js +5 -3
  30. package/dist/cli/trainCommand.js +73 -20
  31. package/dist/cli/upCommand.js +5 -1
  32. package/dist/cli/volumeCommands.d.ts +8 -0
  33. package/dist/cli/volumeCommands.js +53 -0
  34. package/dist/compiler/agentNodeMerge.js +3 -2
  35. package/dist/compiler/buildCompilePlan.js +4 -0
  36. package/dist/compiler/buildCompilePlanAgent.js +3 -1
  37. package/dist/compiler/buildCompilePlanTraversal.js +2 -0
  38. package/dist/compiler/buildCompilePlanTraversalHelpers.d.ts +2 -2
  39. package/dist/compiler/buildCompilePlanTraversalHelpers.js +4 -3
  40. package/dist/compiler/buildProject.d.ts +10 -0
  41. package/dist/compiler/buildProject.js +14 -2
  42. package/dist/compiler/cleanCompileOutput.d.ts +2 -0
  43. package/dist/compiler/cleanCompileOutput.js +14 -0
  44. package/dist/compiler/compilePlanHelpers.js +2 -0
  45. package/dist/compiler/compileProject.d.ts +10 -0
  46. package/dist/compiler/compileProject.js +29 -3
  47. package/dist/compiler/containerArtifactSummaries.js +1 -0
  48. package/dist/compiler/containerArtifacts.d.ts +4 -4
  49. package/dist/compiler/containerArtifacts.js +18 -34
  50. package/dist/compiler/containerArtifactsPlans.js +7 -0
  51. package/dist/compiler/containerArtifactsTypes.d.ts +7 -0
  52. package/dist/compiler/containerDaimonBrokerRender.d.ts +3 -1
  53. package/dist/compiler/containerDaimonBrokerRender.js +6 -3
  54. package/dist/compiler/containerDaimonGrokTaskClock.d.ts +5 -0
  55. package/dist/compiler/containerDaimonGrokTaskClock.js +29 -0
  56. package/dist/compiler/containerDaimonGrokWorkerProvisioning.d.ts +1 -1
  57. package/dist/compiler/containerDaimonGrokWorkerProvisioning.js +38 -16
  58. package/dist/compiler/containerDaimonGrokWorkerRender.d.ts +33 -8
  59. package/dist/compiler/containerDaimonGrokWorkerRender.js +18 -5
  60. package/dist/compiler/containerDaimonOwnershipGuardRender.d.ts +14 -1
  61. package/dist/compiler/containerDaimonOwnershipGuardRender.js +15 -2
  62. package/dist/compiler/containerDaimonUidEntrypointRender.js +6 -12
  63. package/dist/compiler/containerTargetResources.d.ts +10 -0
  64. package/dist/compiler/containerTargetResources.js +21 -13
  65. package/dist/compiler/containerWorkspaceResourceRender.js +4 -1
  66. package/dist/compiler/index.d.ts +2 -0
  67. package/dist/compiler/index.js +2 -0
  68. package/dist/compiler/mcpPlaceholders.d.ts +11 -0
  69. package/dist/compiler/mcpPlaceholders.js +58 -0
  70. package/dist/compiler/mcpServerInheritance.d.ts +18 -0
  71. package/dist/compiler/mcpServerInheritance.js +43 -0
  72. package/dist/compiler/moltnetArtifactTypes.d.ts +1 -0
  73. package/dist/compiler/moltnetArtifacts.js +1 -0
  74. package/dist/compiler/preflightCompilePlan.d.ts +9 -0
  75. package/dist/compiler/preflightCompilePlan.js +38 -0
  76. package/dist/compiler/recordingAgentFacts.d.ts +4 -0
  77. package/dist/compiler/recordingAgentFacts.js +35 -0
  78. package/dist/compiler/recordingCapability.d.ts +4 -0
  79. package/dist/compiler/recordingCapability.js +22 -0
  80. package/dist/compiler/recordingReport.d.ts +4 -0
  81. package/dist/compiler/recordingReport.js +18 -0
  82. package/dist/compiler/runProject.d.ts +2 -1
  83. package/dist/compiler/runProject.js +2 -0
  84. package/dist/compiler/surfaces.d.ts +1 -2
  85. package/dist/compiler/surfaces.js +0 -1
  86. package/dist/compiler/syncProjectAuth.js +2 -1
  87. package/dist/compiler/training/broker/clockProbe.d.ts +6 -0
  88. package/dist/compiler/training/broker/clockProbe.js +27 -0
  89. package/dist/compiler/training/broker/declaration.d.ts +4 -2
  90. package/dist/compiler/training/broker/declaration.js +4 -2
  91. package/dist/compiler/training/broker/entrypoint.js +33 -18
  92. package/dist/compiler/training/broker/evaluatorSecrets.d.ts +2 -0
  93. package/dist/compiler/training/broker/evaluatorSecrets.js +60 -0
  94. package/dist/compiler/training/broker/index.d.ts +3 -2
  95. package/dist/compiler/training/broker/index.js +3 -2
  96. package/dist/compiler/training/broker/main.js +1 -1
  97. package/dist/compiler/training/broker/paths.d.ts +96 -56
  98. package/dist/compiler/training/broker/paths.js +97 -89
  99. package/dist/compiler/training/broker/processes.d.ts +9 -0
  100. package/dist/compiler/training/broker/processes.js +4 -1
  101. package/dist/compiler/training/broker/projection.d.ts +3 -2
  102. package/dist/compiler/training/broker/projection.js +21 -9
  103. package/dist/compiler/training/broker/provisioning.d.ts +6 -15
  104. package/dist/compiler/training/broker/provisioning.js +71 -53
  105. package/dist/compiler/training/broker/registration.d.ts +3 -1
  106. package/dist/compiler/training/broker/registration.js +29 -21
  107. package/dist/compiler/training/broker/reset.d.ts +9 -0
  108. package/dist/compiler/training/broker/reset.js +71 -0
  109. package/dist/compiler/training/broker/runtime.d.ts +10 -13
  110. package/dist/compiler/training/broker/runtime.js +69 -115
  111. package/dist/compiler/training/broker/supervisor.d.ts +10 -11
  112. package/dist/compiler/training/broker/supervisor.js +22 -23
  113. package/dist/compiler/training/broker/taskClock.d.ts +5 -0
  114. package/dist/compiler/training/broker/taskClock.js +41 -0
  115. package/dist/compiler/training/compiledAgent.d.ts +21 -0
  116. package/dist/compiler/training/compiledAgent.js +62 -0
  117. package/dist/compiler/training/container/contract.d.ts +23 -0
  118. package/dist/compiler/training/container/contract.js +23 -5
  119. package/dist/compiler/training/container/evaluators.d.ts +48 -0
  120. package/dist/compiler/training/container/evaluators.js +50 -0
  121. package/dist/compiler/training/container/grokWriteback.d.ts +8 -0
  122. package/dist/compiler/training/container/grokWriteback.js +26 -0
  123. package/dist/compiler/training/container/index.d.ts +2 -1
  124. package/dist/compiler/training/container/index.js +2 -1
  125. package/dist/compiler/training/container/launch.d.ts +3 -0
  126. package/dist/compiler/training/container/launch.js +119 -28
  127. package/dist/compiler/training/container/nativeSlots.d.ts +14 -0
  128. package/dist/compiler/training/container/nativeSlots.js +13 -0
  129. package/dist/compiler/training/container/outputCopy.d.ts +2 -0
  130. package/dist/compiler/training/container/outputCopy.js +72 -0
  131. package/dist/compiler/training/container/outputVolume.d.ts +27 -0
  132. package/dist/compiler/training/container/outputVolume.js +161 -0
  133. package/dist/compiler/training/container/prepare.d.ts +3 -1
  134. package/dist/compiler/training/container/prepare.js +57 -12
  135. package/dist/compiler/training/container/security.d.ts +5 -3
  136. package/dist/compiler/training/container/security.js +15 -5
  137. package/dist/compiler/training/container/subjectIsolation.d.ts +5 -0
  138. package/dist/compiler/training/container/subjectIsolation.js +15 -0
  139. package/dist/compiler/training/context.d.ts +8 -0
  140. package/dist/compiler/training/context.js +12 -12
  141. package/dist/compiler/training/contract.d.ts +2 -0
  142. package/dist/compiler/training/contract.js +2 -0
  143. package/dist/compiler/training/execution.d.ts +417 -0
  144. package/dist/compiler/training/execution.js +160 -0
  145. package/dist/compiler/training/index.d.ts +8 -0
  146. package/dist/compiler/training/index.js +7 -0
  147. package/dist/compiler/training/moments.d.ts +80 -0
  148. package/dist/compiler/training/moments.js +118 -0
  149. package/dist/compiler/training/output.d.ts +2 -0
  150. package/dist/compiler/training/output.js +20 -0
  151. package/dist/compiler/training/plan/contract.d.ts +287 -0
  152. package/dist/compiler/training/plan/contract.js +49 -0
  153. package/dist/compiler/training/plan/index.d.ts +5 -0
  154. package/dist/compiler/training/plan/index.js +4 -0
  155. package/dist/compiler/training/plan/load.d.ts +9 -0
  156. package/dist/compiler/training/plan/load.js +153 -0
  157. package/dist/compiler/training/plan/references.d.ts +19 -0
  158. package/dist/compiler/training/plan/references.js +57 -0
  159. package/dist/compiler/training/plan/resolve.d.ts +4 -0
  160. package/dist/compiler/training/plan/resolve.js +73 -0
  161. package/dist/compiler/training/plan/targets.d.ts +11 -0
  162. package/dist/compiler/training/plan/targets.js +71 -0
  163. package/dist/compiler/training/plan/types.d.ts +36 -0
  164. package/dist/compiler/training/plan/types.js +1 -0
  165. package/dist/compiler/training/preparation/assets/Dockerfile +13 -2
  166. package/dist/compiler/training/preparation/assets/package-lock.json +2 -2
  167. package/dist/compiler/training/preparation/broker.d.ts +3 -3
  168. package/dist/compiler/training/preparation/broker.js +6 -4
  169. package/dist/compiler/training/preparation/contract.d.ts +27 -2
  170. package/dist/compiler/training/preparation/contract.js +23 -4
  171. package/dist/compiler/training/preparation/files.d.ts +5 -1
  172. package/dist/compiler/training/preparation/files.js +76 -15
  173. package/dist/compiler/training/preparation/image.js +9 -4
  174. package/dist/compiler/training/preparation/inputs.d.ts +1 -0
  175. package/dist/compiler/training/preparation/inputs.js +18 -10
  176. package/dist/compiler/training/preparation/prepare.d.ts +5 -0
  177. package/dist/compiler/training/preparation/prepare.js +66 -29
  178. package/dist/compiler/training/preparation/scratch.d.ts +6 -17
  179. package/dist/compiler/training/preparation/scratch.js +89 -23
  180. package/dist/compiler/training/repair/contract.d.ts +338 -4
  181. package/dist/compiler/training/repair/contract.js +2 -0
  182. package/dist/compiler/training/repair/index.d.ts +1 -1
  183. package/dist/compiler/training/repair/index.js +1 -1
  184. package/dist/compiler/training/repair/prepare.d.ts +155 -3
  185. package/dist/compiler/training/repair/prepare.js +6 -2
  186. package/dist/compiler/training/repair/witness.d.ts +152 -3
  187. package/dist/compiler/training/repair/witness.js +8 -2
  188. package/dist/compiler/training/resolution.d.ts +25 -0
  189. package/dist/compiler/training/resolution.js +69 -0
  190. package/dist/compiler/training/rewind/contract.d.ts +321 -0
  191. package/dist/compiler/training/rewind/contract.js +39 -0
  192. package/dist/compiler/training/rewind/deployedResource.d.ts +22 -0
  193. package/dist/compiler/training/rewind/deployedResource.js +19 -0
  194. package/dist/compiler/training/rewind/feed.d.ts +12 -0
  195. package/dist/compiler/training/rewind/feed.js +182 -0
  196. package/dist/compiler/training/rewind/feedContent.d.ts +6 -0
  197. package/dist/compiler/training/rewind/feedContent.js +38 -0
  198. package/dist/compiler/training/rewind/git.d.ts +8 -0
  199. package/dist/compiler/training/rewind/git.js +159 -0
  200. package/dist/compiler/training/rewind/gitArchive.d.ts +2 -0
  201. package/dist/compiler/training/rewind/gitArchive.js +7 -0
  202. package/dist/compiler/training/rewind/gitHistory.d.ts +3 -0
  203. package/dist/compiler/training/rewind/gitHistory.js +55 -0
  204. package/dist/compiler/training/rewind/gitProcess.d.ts +19 -0
  205. package/dist/compiler/training/rewind/gitProcess.js +81 -0
  206. package/dist/compiler/training/rewind/gitTree.d.ts +14 -0
  207. package/dist/compiler/training/rewind/gitTree.js +90 -0
  208. package/dist/compiler/training/rewind/history.d.ts +28 -0
  209. package/dist/compiler/training/rewind/history.js +239 -0
  210. package/dist/compiler/training/rewind/index.d.ts +18 -0
  211. package/dist/compiler/training/rewind/index.js +15 -0
  212. package/dist/compiler/training/rewind/inputs.d.ts +9 -0
  213. package/dist/compiler/training/rewind/inputs.js +67 -0
  214. package/dist/compiler/training/rewind/instant.d.ts +4 -0
  215. package/dist/compiler/training/rewind/instant.js +24 -0
  216. package/dist/compiler/training/rewind/leakCheck.d.ts +10 -0
  217. package/dist/compiler/training/rewind/leakCheck.js +56 -0
  218. package/dist/compiler/training/rewind/leakFeed.d.ts +5 -0
  219. package/dist/compiler/training/rewind/leakFeed.js +25 -0
  220. package/dist/compiler/training/rewind/leakFiles.d.ts +10 -0
  221. package/dist/compiler/training/rewind/leakFiles.js +106 -0
  222. package/dist/compiler/training/rewind/leakGit.d.ts +3 -0
  223. package/dist/compiler/training/rewind/leakGit.js +78 -0
  224. package/dist/compiler/training/rewind/leakGitPayload.d.ts +4 -0
  225. package/dist/compiler/training/rewind/leakGitPayload.js +57 -0
  226. package/dist/compiler/training/rewind/leakInputs.d.ts +7 -0
  227. package/dist/compiler/training/rewind/leakInputs.js +135 -0
  228. package/dist/compiler/training/rewind/leakLayout.d.ts +2 -0
  229. package/dist/compiler/training/rewind/leakLayout.js +17 -0
  230. package/dist/compiler/training/rewind/leakProvenance.d.ts +3 -0
  231. package/dist/compiler/training/rewind/leakProvenance.js +88 -0
  232. package/dist/compiler/training/rewind/materialize.d.ts +136 -0
  233. package/dist/compiler/training/rewind/materialize.js +212 -0
  234. package/dist/compiler/training/rewind/memory.d.ts +10 -0
  235. package/dist/compiler/training/rewind/memory.js +84 -0
  236. package/dist/compiler/training/rewind/memorySchemas.d.ts +87 -0
  237. package/dist/compiler/training/rewind/memorySchemas.js +50 -0
  238. package/dist/compiler/training/rewind/moltnet.d.ts +2 -0
  239. package/dist/compiler/training/rewind/moltnet.js +54 -0
  240. package/dist/compiler/training/rewind/moltnetJson.d.ts +13 -0
  241. package/dist/compiler/training/rewind/moltnetJson.js +180 -0
  242. package/dist/compiler/training/rewind/moltnetSchemas.d.ts +1226 -0
  243. package/dist/compiler/training/rewind/moltnetSchemas.js +75 -0
  244. package/dist/compiler/training/rewind/moltnetSqlite.d.ts +31 -0
  245. package/dist/compiler/training/rewind/moltnetSqlite.js +192 -0
  246. package/dist/compiler/training/rewind/moltnetSqliteData.d.ts +10 -0
  247. package/dist/compiler/training/rewind/moltnetSqliteData.js +113 -0
  248. package/dist/compiler/training/rewind/recordInput.d.ts +40 -0
  249. package/dist/compiler/training/rewind/recordInput.js +49 -0
  250. package/dist/compiler/training/rewind/recordedBundle.d.ts +4 -0
  251. package/dist/compiler/training/rewind/recordedBundle.js +58 -0
  252. package/dist/compiler/training/rewind/recordedCommit.d.ts +2 -0
  253. package/dist/compiler/training/rewind/recordedCommit.js +10 -0
  254. package/dist/compiler/training/rewind/select.d.ts +18 -0
  255. package/dist/compiler/training/rewind/select.js +64 -0
  256. package/dist/compiler/training/rewind/snapshotManifest.d.ts +42 -0
  257. package/dist/compiler/training/rewind/snapshotManifest.js +134 -0
  258. package/dist/compiler/training/rewind/taskClock.d.ts +12 -0
  259. package/dist/compiler/training/rewind/taskClock.js +40 -0
  260. package/dist/compiler/training/rewind/timestamps.d.ts +4 -0
  261. package/dist/compiler/training/rewind/timestamps.js +26 -0
  262. package/dist/compiler/training/rewind/types.d.ts +43 -0
  263. package/dist/compiler/training/rewind/types.js +1 -0
  264. package/dist/compiler/training/rewind/volumes.d.ts +12 -0
  265. package/dist/compiler/training/rewind/volumes.js +58 -0
  266. package/dist/compiler/training/selection.d.ts +7 -0
  267. package/dist/compiler/training/selection.js +15 -0
  268. package/dist/compiler/types.d.ts +6 -3
  269. package/dist/compiler/upProject.d.ts +1 -0
  270. package/dist/compiler/upProject.js +21 -5
  271. package/dist/compiler/workspaceBundleArtifacts.d.ts +16 -1
  272. package/dist/compiler/workspaceBundleArtifacts.js +69 -20
  273. package/dist/compiler/workspaceBundleCache.d.ts +23 -0
  274. package/dist/compiler/workspaceBundleCache.js +79 -0
  275. package/dist/compiler/workspaceBundleDependencies.d.ts +21 -0
  276. package/dist/compiler/workspaceBundleDependencies.js +122 -0
  277. package/dist/compiler/workspaceBundleFiles.d.ts +51 -0
  278. package/dist/compiler/workspaceBundleFiles.js +251 -0
  279. package/dist/compiler/workspaceBundleGenerated.d.ts +25 -0
  280. package/dist/compiler/workspaceBundleGenerated.js +103 -0
  281. package/dist/compiler/workspaceBundleGit.d.ts +64 -0
  282. package/dist/compiler/workspaceBundleGit.js +154 -0
  283. package/dist/compiler/workspaceBundleKey.d.ts +34 -0
  284. package/dist/compiler/workspaceBundleKey.js +17 -0
  285. package/dist/compiler/workspaceBundleResolve.d.ts +56 -0
  286. package/dist/compiler/workspaceBundleResolve.js +144 -0
  287. package/dist/compiler/workspaceBundleRun.d.ts +41 -0
  288. package/dist/compiler/workspaceBundleRun.js +79 -0
  289. package/dist/compiler/workspaceBundleTar.d.ts +47 -0
  290. package/dist/compiler/workspaceBundleTar.js +140 -0
  291. package/dist/compiler/workspaceBundleTree.d.ts +15 -0
  292. package/dist/compiler/workspaceBundleTree.js +58 -0
  293. package/dist/compiler/workspaceGitFetch.d.ts +41 -0
  294. package/dist/compiler/workspaceGitFetch.js +155 -0
  295. package/dist/compiler/workspaceGitPins.d.ts +33 -0
  296. package/dist/compiler/workspaceGitPins.js +127 -0
  297. package/dist/compiler/workspaceResources.d.ts +5 -1
  298. package/dist/compiler/workspaceResources.js +32 -5
  299. package/dist/deployment/activation.d.ts +3 -0
  300. package/dist/deployment/activation.js +12 -0
  301. package/dist/deployment/canaryCutover.d.ts +1 -1
  302. package/dist/deployment/candidateRecording.d.ts +8 -0
  303. package/dist/deployment/candidateRecording.js +22 -0
  304. package/dist/deployment/dockerManager.d.ts +5 -3
  305. package/dist/deployment/dockerManager.js +12 -2
  306. package/dist/deployment/downDeployment.d.ts +2 -0
  307. package/dist/deployment/downDeployment.js +6 -2
  308. package/dist/deployment/homeStore.d.ts +9 -1
  309. package/dist/deployment/homeStore.js +16 -53
  310. package/dist/deployment/index.d.ts +6 -0
  311. package/dist/deployment/index.js +6 -0
  312. package/dist/deployment/pidLock.d.ts +25 -0
  313. package/dist/deployment/pidLock.js +81 -0
  314. package/dist/deployment/record.d.ts +85 -1
  315. package/dist/deployment/record.js +11 -5
  316. package/dist/deployment/recordPublication.d.ts +15 -0
  317. package/dist/deployment/recordPublication.js +76 -0
  318. package/dist/deployment/recordedMemoryRetention.d.ts +18 -0
  319. package/dist/deployment/recordedMemoryRetention.js +27 -0
  320. package/dist/deployment/resourceLog.d.ts +140 -0
  321. package/dist/deployment/resourceLog.js +78 -0
  322. package/dist/distribution/buildDistributionReport.d.ts +3 -0
  323. package/dist/distribution/buildDistributionReport.js +5 -0
  324. package/dist/distribution/consumeImage.d.ts +3 -0
  325. package/dist/distribution/consumeImage.js +23 -31
  326. package/dist/distribution/consumeImageLifecycle.d.ts +4 -1
  327. package/dist/distribution/consumeImageLifecycle.js +14 -3
  328. package/dist/distribution/consumeImageSupport.d.ts +7 -0
  329. package/dist/distribution/consumeImageSupport.js +25 -0
  330. package/dist/distribution/distributionReportSchema.d.ts +47 -0
  331. package/dist/distribution/distributionReportSchema.js +20 -0
  332. package/dist/distribution/renderImageInterface.js +1 -1
  333. package/dist/distribution/types.d.ts +15 -0
  334. package/dist/filesystem/durableWrite.d.ts +10 -0
  335. package/dist/filesystem/durableWrite.js +87 -0
  336. package/dist/filesystem/index.d.ts +2 -0
  337. package/dist/filesystem/index.js +2 -0
  338. package/dist/filesystem/retainedJsonl.d.ts +23 -0
  339. package/dist/filesystem/retainedJsonl.js +123 -0
  340. package/dist/manifest/commandSchemas.d.ts +5 -0
  341. package/dist/manifest/commandSchemas.js +5 -0
  342. package/dist/manifest/executionSchemas.d.ts +20 -0
  343. package/dist/manifest/executionSchemas.js +13 -3
  344. package/dist/manifest/index.d.ts +2 -0
  345. package/dist/manifest/index.js +2 -0
  346. package/dist/manifest/loadManifest.js +3 -26
  347. package/dist/manifest/mcpSchemas.d.ts +61 -0
  348. package/dist/manifest/mcpSchemas.js +57 -11
  349. package/dist/manifest/memorySchemas.d.ts +1 -1
  350. package/dist/manifest/memorySchemas.js +1 -1
  351. package/dist/manifest/parseManifest.d.ts +7 -0
  352. package/dist/manifest/parseManifest.js +65 -0
  353. package/dist/manifest/renderSpawnfile.js +4 -1
  354. package/dist/manifest/renderSpawnfileWorkspace.js +6 -2
  355. package/dist/manifest/schemas.d.ts +1206 -132
  356. package/dist/manifest/schemas.js +14 -4
  357. package/dist/manifest/teamNetworkSchemas.d.ts +1 -1
  358. package/dist/manifest/trainingDataSchemas.d.ts +357 -0
  359. package/dist/manifest/trainingDataSchemas.js +31 -0
  360. package/dist/manifest/trainingSchemas.d.ts +49 -0
  361. package/dist/manifest/trainingSchemas.js +44 -0
  362. package/dist/manifest/volumeFeedSchemas.d.ts +52 -0
  363. package/dist/manifest/volumeFeedSchemas.js +104 -0
  364. package/dist/manifest/workspaceSchemas.d.ts +182 -5
  365. package/dist/manifest/workspaceSchemas.js +111 -7
  366. package/dist/recording/compose.d.ts +3 -0
  367. package/dist/recording/compose.js +93 -0
  368. package/dist/recording/deployment.d.ts +15 -0
  369. package/dist/recording/deployment.js +38 -0
  370. package/dist/recording/history.d.ts +16 -0
  371. package/dist/recording/history.js +47 -0
  372. package/dist/recording/index.d.ts +9 -0
  373. package/dist/recording/index.js +9 -0
  374. package/dist/recording/moment.d.ts +61 -0
  375. package/dist/recording/moment.js +36 -0
  376. package/dist/recording/parse.d.ts +15 -0
  377. package/dist/recording/parse.js +74 -0
  378. package/dist/recording/read.d.ts +8 -0
  379. package/dist/recording/read.js +61 -0
  380. package/dist/recording/store.d.ts +10 -0
  381. package/dist/recording/store.js +94 -0
  382. package/dist/recording/sync.d.ts +24 -0
  383. package/dist/recording/sync.js +126 -0
  384. package/dist/recording/types.d.ts +45 -0
  385. package/dist/recording/types.js +2 -0
  386. package/dist/release/drainControl.d.ts +54 -0
  387. package/dist/release/drainControl.js +137 -0
  388. package/dist/release/drainPhase.d.ts +37 -0
  389. package/dist/release/drainPhase.js +161 -0
  390. package/dist/release/index.d.ts +11 -0
  391. package/dist/release/index.js +11 -0
  392. package/dist/release/ledger.d.ts +75 -0
  393. package/dist/release/ledger.js +111 -0
  394. package/dist/release/notify.d.ts +58 -0
  395. package/dist/release/notify.js +126 -0
  396. package/dist/release/pending.d.ts +35 -0
  397. package/dist/release/pending.js +60 -0
  398. package/dist/release/postDeploy.d.ts +32 -0
  399. package/dist/release/postDeploy.js +62 -0
  400. package/dist/release/releaseDefaults.d.ts +9 -0
  401. package/dist/release/releaseDefaults.js +115 -0
  402. package/dist/release/releaseDocker.d.ts +38 -0
  403. package/dist/release/releaseDocker.js +94 -0
  404. package/dist/release/releaseTypes.d.ts +94 -0
  405. package/dist/release/releaseTypes.js +1 -0
  406. package/dist/release/runRelease.d.ts +9 -0
  407. package/dist/release/runRelease.js +218 -0
  408. package/dist/release/swap.d.ts +23 -0
  409. package/dist/release/swap.js +55 -0
  410. package/dist/release/types.d.ts +50 -0
  411. package/dist/release/types.js +29 -0
  412. package/dist/report/index.d.ts +1 -0
  413. package/dist/report/index.js +1 -0
  414. package/dist/report/recording.d.ts +57 -0
  415. package/dist/report/recording.js +26 -0
  416. package/dist/report/types.d.ts +58 -0
  417. package/dist/runtime/container.js +8 -13
  418. package/dist/runtime/daimon/adapter.js +15 -4
  419. package/dist/runtime/daimon/config.d.ts +4 -0
  420. package/dist/runtime/daimon/config.js +53 -4
  421. package/dist/runtime/daimon/contract-manifest.json +1 -0
  422. package/dist/runtime/daimon/contract-manifest.sha256 +1 -0
  423. package/dist/runtime/daimon/contractManifest.d.ts +59 -8
  424. package/dist/runtime/daimon/contractManifest.js +26 -10
  425. package/dist/runtime/daimon/grokTurnLimits.d.ts +25 -0
  426. package/dist/runtime/daimon/grokTurnLimits.js +51 -0
  427. package/dist/runtime/daimon/grokWorkerConfigBytes.d.ts +17 -0
  428. package/dist/runtime/daimon/grokWorkerConfigBytes.js +17 -0
  429. package/dist/runtime/daimon/grokWorkerContract.d.ts +5 -0
  430. package/dist/runtime/daimon/grokWorkerContract.js +13 -1
  431. package/dist/runtime/daimon/recording.d.ts +19 -0
  432. package/dist/runtime/daimon/recording.js +50 -0
  433. package/dist/runtime/daimon/scheduleAuthority.d.ts +8 -0
  434. package/dist/runtime/daimon/scheduleAuthority.js +19 -5
  435. package/dist/runtime/daimon/wakeMoments.d.ts +15 -0
  436. package/dist/runtime/daimon/wakeMoments.js +17 -0
  437. package/dist/runtime/daimonInstall.d.ts +3 -0
  438. package/dist/runtime/daimonInstall.js +25 -0
  439. package/dist/runtime/index.d.ts +1 -0
  440. package/dist/runtime/index.js +1 -0
  441. package/dist/runtime/install.d.ts +2 -0
  442. package/dist/runtime/install.js +1 -0
  443. package/dist/runtime/openclaw/adapter.js +3 -0
  444. package/dist/runtime/pi/adapter.js +3 -0
  445. package/dist/runtime/pi/containerTargets.js +6 -0
  446. package/dist/runtime/picoclaw/adapter.js +3 -0
  447. package/dist/runtime/registry.d.ts +3 -0
  448. package/dist/runtime/registry.js +13 -1
  449. package/dist/runtime/types.d.ts +15 -0
  450. package/dist/runtime/usageLedgerRead.d.ts +6 -0
  451. package/dist/runtime/usageLedgerRead.js +3 -3
  452. package/dist/shared/index.d.ts +1 -0
  453. package/dist/shared/index.js +1 -0
  454. package/dist/shared/recording.d.ts +8 -0
  455. package/dist/shared/recording.js +25 -0
  456. package/dist/target/dockerCommandExecutorCore.js +1 -1
  457. package/dist/target/dockerTargetBinding.js +2 -1
  458. package/dist/volume/feedLand.d.ts +31 -0
  459. package/dist/volume/feedLand.js +174 -0
  460. package/dist/volume/feedLandings.d.ts +45 -0
  461. package/dist/volume/feedLandings.js +111 -0
  462. package/dist/volume/feedLayout.d.ts +61 -0
  463. package/dist/volume/feedLayout.js +234 -0
  464. package/dist/volume/feedLock.d.ts +7 -0
  465. package/dist/volume/feedLock.js +131 -0
  466. package/dist/volume/feedManifest.d.ts +27 -0
  467. package/dist/volume/feedManifest.js +123 -0
  468. package/dist/volume/feedPrepare.d.ts +16 -0
  469. package/dist/volume/feedPrepare.js +228 -0
  470. package/dist/volume/feedProject.d.ts +39 -0
  471. package/dist/volume/feedProject.js +92 -0
  472. package/dist/volume/feedRecord.d.ts +55 -0
  473. package/dist/volume/feedRecord.js +148 -0
  474. package/dist/volume/feedRef.d.ts +43 -0
  475. package/dist/volume/feedRef.js +117 -0
  476. package/dist/volume/feedRefresh.d.ts +15 -0
  477. package/dist/volume/feedRefresh.js +187 -0
  478. package/dist/volume/feedSource.d.ts +66 -0
  479. package/dist/volume/feedSource.js +104 -0
  480. package/dist/volume/feedTarget.d.ts +70 -0
  481. package/dist/volume/feedTarget.js +9 -0
  482. package/dist/volume/feedTestKit.d.ts +11 -0
  483. package/dist/volume/feedTestKit.js +45 -0
  484. package/dist/volume/feedVerify.d.ts +18 -0
  485. package/dist/volume/feedVerify.js +104 -0
  486. package/dist/volume/index.d.ts +13 -0
  487. package/dist/volume/index.js +13 -0
  488. package/moltnet-releases.json +4 -4
  489. package/package.json +3 -3
  490. package/runtimes.yaml +8 -6
@@ -6,7 +6,7 @@ import { DAIMON_WORKER_ROOT } from "../../containerDaimonGrokWorkerRender.js";
6
6
  /**
7
7
  * Every container path the broker-capable training container fixes.
8
8
  *
9
- * They are fixed rather than derived because three parties must agree on them
9
+ * They are deterministic because three parties must agree on them
10
10
  * without talking to each other: the root entrypoint that provisions them, the
11
11
  * root slot supervisor that wipes and re-provisions them on recycle, and
12
12
  * Paideia's native adapter, which writes them into `paideia.daimon-native.launch.v2`
@@ -14,7 +14,7 @@ import { DAIMON_WORKER_ROOT } from "../../containerDaimonGrokWorkerRender.js";
14
14
  * resolves a path, so each one must also be canonical and never a symlink; the
15
15
  * provisioning program asserts that before a slot is used.
16
16
  *
17
- * Everything under `/run/training/slot` is per-trial state on tmpfs — never the
17
+ * Everything under `/run/training/slots/<i>` is per-trial state on tmpfs — never the
18
18
  * Grok realm volume (R2). The realm volume holds only `auth.json` and the
19
19
  * broker credential journal, so a recycle can wipe the slot without touching
20
20
  * the one durable rotating credential.
@@ -23,20 +23,8 @@ export const TRAINING_RUN_ROOT = "/run/training/output";
23
23
  export const TRAINING_SEALED_INPUTS_ROOT = "/run/training/inputs";
24
24
  export const TRAINING_PAIDEIA_ROOT = "/run/paideia";
25
25
  export const TRAINING_CONTEXT_FILE = `${TRAINING_PAIDEIA_ROOT}/context.json`;
26
- /** Host-written, read-only `spawnfile.training-broker.v1` declaration the root entrypoint reads. */
26
+ /** Host-written, read-only `spawnfile.training-broker.v2` declaration the root entrypoint reads. */
27
27
  export const TRAINING_BROKER_DECLARATION_FILE = `${TRAINING_PAIDEIA_ROOT}/training-broker.json`;
28
- export const TRAINING_SLOT_ROOT = "/run/training/slot";
29
- export const TRAINING_SLOT_WORKSPACE = `${TRAINING_SLOT_ROOT}/workspace`;
30
- export const TRAINING_SLOT_RUNTIME_HOME = `${TRAINING_SLOT_ROOT}/runtime-home`;
31
- export const TRAINING_SLOT_STATE_ROOT = `${TRAINING_SLOT_ROOT}/state`;
32
- export const TRAINING_SLOT_ACCEPTANCE_STORE = `${TRAINING_SLOT_STATE_ROOT}/wake-acceptance`;
33
- /** Per-slot turn store. On tmpfs on purpose: a replayed turn from trial N must never satisfy trial N+1 (R2). */
34
- export const TRAINING_SLOT_TURN_STORE = `${TRAINING_SLOT_ROOT}/turns`;
35
- export const TRAINING_SLOT_USAGE_DIRECTORY = `${TRAINING_SLOT_ROOT}/usage`;
36
- export const TRAINING_SLOT_USAGE_LEDGER = `${TRAINING_SLOT_USAGE_DIRECTORY}/usage.jsonl`;
37
- export const TRAINING_SLOT_PREFLIGHT_RECEIPT = `${TRAINING_SLOT_ROOT}/preflight.json`;
38
- /** Supervisor-owned monotonic generation counter; survives a recycle, never a container restart. */
39
- export const TRAINING_SLOT_GENERATION_FILE = `${TRAINING_SLOT_ROOT}/generation.json`;
40
28
  export const TRAINING_INFERENCE_DIRECTORY = "/run/training/inference";
41
29
  export const TRAINING_INFERENCE_LEDGER = `${TRAINING_INFERENCE_DIRECTORY}/inference.jsonl`;
42
30
  /** Judge grant homes: `2000:2000 0700`, denied to every worker uid. Paideia reads it as `PAIDEIA_GROK_GRANT_HOME_ROOT`. */
@@ -58,9 +46,6 @@ export const TRAINING_SUPERVISOR_DIRECTORY = "/run/training/supervisor";
58
46
  export const TRAINING_SUPERVISOR_SOCKET = `${TRAINING_SUPERVISOR_DIRECTORY}/control.sock`;
59
47
  export const TRAINING_SUPERVISOR_LOG = `${TRAINING_SUPERVISOR_DIRECTORY}/supervisor.log`;
60
48
  export const TRAINING_WORKER_ROOT = DAIMON_WORKER_ROOT;
61
- export const TRAINING_SLOT_INDEX = 0;
62
- export const TRAINING_WORKER_UID = DAIMON_FIRST_WORKER_UID + TRAINING_SLOT_INDEX;
63
- export const TRAINING_WORKER_HOME = path.posix.join(TRAINING_WORKER_ROOT, String(TRAINING_WORKER_UID));
64
49
  /**
65
50
  * Paideia's own fixed container paths (`containerPaths` in its native launch
66
51
  * schema). They are *not* individual deny entries: Grok 1.0.34 materializes
@@ -94,63 +79,93 @@ export const TRAINING_CALLER_PROTECTED_PATHS = [
94
79
  * tagged `context` — the caller-state role — since there is no other way to
95
80
  * carry a path through that contract.
96
81
  */
97
- export const TRAINING_EVALUATOR_PATHS = [
98
- { role: "run-root", path: TRAINING_RUN_ROOT },
99
- { role: "sealed-inputs", path: TRAINING_SEALED_INPUTS_ROOT },
100
- { role: "judge-home", path: TRAINING_GRANT_HOME_ROOT },
101
- { role: "slot-ledger", path: TRAINING_SLOT_USAGE_DIRECTORY },
102
- { role: "context", path: TRAINING_PAIDEIA_ROOT },
103
- { role: "context", path: TRAINING_BROKER_TMPDIR },
104
- { role: "context", path: TRAINING_INFERENCE_DIRECTORY },
105
- { role: "context", path: TRAINING_SLOT_TURN_STORE },
106
- { role: "context", path: TRAINING_SUPERVISOR_DIRECTORY },
107
- { role: "context", path: path.posix.dirname(DAIMON_GROK_ENGINE_BROKER.controlSocketPath) },
108
- { role: "context", path: path.posix.dirname(DAIMON_GROK_ENGINE_BROKER.registrationPath) },
109
- { role: "context", path: DAIMON_GROK_TURN_USAGE_LEDGER.directoryPath },
110
- { role: "context", path: DAIMON_WAKE_FUSE_DIRECTORY }
82
+ export const TRAINING_SLOTS_FILE = `${TRAINING_PAIDEIA_ROOT}/slots.json`;
83
+ export const TRAINING_SLOTS_VERSION = "spawnfile.training-slots.v1";
84
+ export const TRAINING_DEFAULT_SLOTS = 4;
85
+ export const TRAINING_MAX_SLOTS = 8;
86
+ /** 100 ports per slot: offsets 0=Moltnet, 1=worker control, 2=bridge; 3..99 reserved. */
87
+ export const TRAINING_PORT_BASE = 20_000;
88
+ export const TRAINING_PORT_STRIDE = 100;
89
+ export const TRAINING_BROKER_SOCKET_PATHS = [
90
+ DAIMON_GROK_ENGINE_BROKER.controlSocketPath, DAIMON_GROK_ENGINE_BROKER.backendSocketPath,
91
+ DAIMON_GROK_ENGINE_BROKER.launcherSocketPath
111
92
  ];
112
- /**
113
- * One entry per evaluator role, in declaration order: the launch receipt requires all five roles,
114
- * and several `context` paths share that role, so the first of each role is the role's root.
115
- */
116
- export const TRAINING_EVALUATOR_ROOTS = TRAINING_EVALUATOR_PATHS
117
- .filter((entry, index) => TRAINING_EVALUATOR_PATHS.findIndex((first) => first.role === entry.role) === index);
118
- /**
119
- * What `paideia.daimon-native.launch.v2`'s `controlRoot` must be.
120
- *
121
- * Paideia's worker passes it to Daimon as `acceptanceStorePath`, and Daimon adds
122
- * it to the projection's deny list, so it has to be the same path this
123
- * container masks as its slot state root. Its own default
124
- * (`/run/paideia/control`) would both change the digest and nest inside the
125
- * `/run/paideia` mask, which Grok refuses — Daimon renders a nested mask
126
- * without complaining, so the failure would only appear at the first turn.
127
- */
128
- export const TRAINING_CALLER_CONTROL_ROOT = TRAINING_SLOT_STATE_ROOT;
129
- /**
130
- * Everything this container provisions that the one training worker must not
131
- * read, beyond Daimon's own protected set (realm, bootstrap, acceptance store).
132
- * Each entry sits strictly below a Grok 1.0.34 base-profile grant — Grok
133
- * refuses a profile whose deny entry equals or contains `/run`, `/var`, `/etc`
134
- * or `/tmp` — and no entry covers another, because masks cannot nest.
135
- */
136
- /**
137
- * The added deny set is exactly the launch's `evaluatorPaths`, so Spawnfile and
138
- * Paideia hand Daimon's resolver the same list. `TRAINING_SLOT_STATE_ROOT` is
139
- * deliberately absent: Daimon adds it itself, from the control root above.
140
- */
141
- export const TRAINING_ADDED_DENY_PATHS = [...new Set(TRAINING_EVALUATOR_PATHS.map((entry) => entry.path))].sort();
142
- /** Paths the provisioning program creates root-owned `0700` when absent, so every deny entry always has a target inode. */
93
+ export const TRAINING_TURN_STORE_ROOT = "/run/training/turns";
94
+ /** Persistent, broker-only run counter; never part of a slot recycle. */
95
+ export const TRAINING_RUN_REQUEST_STORE = "/run/training/request-budget";
96
+ export const assertTrainingSlotCount = (slots) => {
97
+ if (!Number.isInteger(slots) || slots < 1 || slots > TRAINING_MAX_SLOTS)
98
+ throw Error("Training slots must be an integer from 1 to 8");
99
+ return slots;
100
+ };
101
+ export const trainingSlotPaths = (slot) => {
102
+ if (!Number.isInteger(slot) || slot < 0 || slot >= TRAINING_MAX_SLOTS)
103
+ throw Error("Training slot index must be an integer from 0 to 7");
104
+ const root = `/run/training/slots/${slot}`;
105
+ const workerUid = DAIMON_FIRST_WORKER_UID + slot;
106
+ const workerHome = `${TRAINING_WORKER_ROOT}/${workerUid}`;
107
+ const portBase = TRAINING_PORT_BASE + slot * TRAINING_PORT_STRIDE;
108
+ const clockDirectory = `/run/daimon-engine-broker/task-clock/slot-${slot}`;
109
+ return {
110
+ slot, workerUid, root, workerHome, workspace: `${root}/workspace`, runtimeHome: `${root}/runtime-home`,
111
+ state: `${root}/state`, acceptanceStore: `${root}/state/wake-acceptance`,
112
+ turns: `${TRAINING_TURN_STORE_ROOT}/slot-${slot}`, usageDirectory: `${root}/usage`, usageLedger: `${root}/usage/usage.jsonl`,
113
+ preflightReceipt: `${root}/preflight.json`, generationFile: `${root}/generation.json`,
114
+ sealedInputsAttestation: `${root}/sealed-inputs.json`, privateTmp: `${workerHome}/tmp`,
115
+ clockDirectory, clockFile: `${clockDirectory}/faketime`,
116
+ ports: { base: portBase, stride: TRAINING_PORT_STRIDE, moltnet: portBase, workerControl: portBase + 1, bridge: portBase + 2 }
117
+ };
118
+ };
119
+ /** The complete additional projection deny set. Sibling roots and homes never nest with own masks. */
120
+ export const trainingEvaluatorPaths = (slot, slots) => {
121
+ assertTrainingSlotCount(slots);
122
+ if (slot >= slots)
123
+ throw Error("Training slot is outside the declared pool");
124
+ const own = trainingSlotPaths(slot);
125
+ return [
126
+ { role: "run-root", path: TRAINING_RUN_ROOT },
127
+ { role: "sealed-inputs", path: TRAINING_SEALED_INPUTS_ROOT },
128
+ { role: "judge-home", path: TRAINING_GRANT_HOME_ROOT },
129
+ { role: "slot-ledger", path: own.usageDirectory },
130
+ ...[TRAINING_PAIDEIA_ROOT, TRAINING_BROKER_TMPDIR, TRAINING_INFERENCE_DIRECTORY,
131
+ TRAINING_TURN_STORE_ROOT, TRAINING_RUN_REQUEST_STORE, TRAINING_SUPERVISOR_DIRECTORY,
132
+ ...TRAINING_BROKER_SOCKET_PATHS,
133
+ path.posix.dirname(DAIMON_GROK_ENGINE_BROKER.registrationPath),
134
+ DAIMON_GROK_TURN_USAGE_LEDGER.directoryPath, DAIMON_WAKE_FUSE_DIRECTORY,
135
+ ...Array.from({ length: slots }, (_, i) => trainingSlotPaths(i)).filter(p => p.slot !== slot)
136
+ .flatMap(p => [p.root, p.workerHome, p.clockDirectory])
137
+ ].map(path => ({ role: "context", path }))
138
+ ];
139
+ };
140
+ export const trainingSlotDescriptors = (slots = TRAINING_DEFAULT_SLOTS) => Array.from({ length: assertTrainingSlotCount(slots) }, (_, slot) => ({
141
+ ...trainingSlotPaths(slot), evaluatorPaths: trainingEvaluatorPaths(slot, slots),
142
+ containerPaths: TRAINING_CALLER_PROTECTED_PATHS.map(path => ({ path })),
143
+ controlRoot: trainingSlotPaths(slot).state
144
+ }));
145
+ export const trainingSlotsDocument = (slots = TRAINING_DEFAULT_SLOTS) => ({
146
+ schema: TRAINING_SLOTS_VERSION,
147
+ slots: trainingSlotDescriptors(slots).map(p => ({
148
+ index: p.slot, workerUid: p.workerUid,
149
+ // Paideia owns a runtime-neutral lease pool: its strict descriptor carries opaque named paths.
150
+ roots: {
151
+ ...Object.fromEntries(Object.entries(p).filter((entry) => typeof entry[1] === "string")),
152
+ home: p.runtimeHome, control: p.state, context: TRAINING_PAIDEIA_ROOT,
153
+ ...Object.fromEntries(p.evaluatorPaths.map((entry, index) => [`evaluator:${entry.role}:${index}`, entry.path])),
154
+ ...Object.fromEntries(p.containerPaths.map((entry, index) => [`container:${index}`, entry.path]))
155
+ },
156
+ ports: { base: p.ports.base, count: p.ports.stride }
157
+ }))
158
+ });
159
+ /** Both sides derive the descriptor bytes; a stale or edited bind must never certify a different pool. */
160
+ export const assertTrainingSlotsDocument = (value, slots) => {
161
+ if (JSON.stringify(value) !== JSON.stringify(trainingSlotsDocument(slots)))
162
+ throw Error("Training slots manifest differs from the broker declaration");
163
+ };
164
+ /** Shared deny targets exist before worker attestation; no per-slot subtree is touched here. */
143
165
  export const TRAINING_OPTIONAL_DENY_DIRECTORIES = [
144
- TRAINING_BROKER_TMPDIR,
145
- TRAINING_INFERENCE_DIRECTORY,
146
- TRAINING_SLOT_STATE_ROOT,
147
- TRAINING_SLOT_TURN_STORE,
148
- TRAINING_SUPERVISOR_DIRECTORY,
149
- TRAINING_GRANT_HOME_ROOT,
150
- // Denied and unused here — training meters per slot — but the mask still needs an inode. The launch
151
- // mounts each as tmpfs, so this only creates them when a caller ran the entrypoint without them.
152
- DAIMON_GROK_TURN_USAGE_LEDGER.directoryPath,
153
- DAIMON_WAKE_FUSE_DIRECTORY
166
+ TRAINING_BROKER_TMPDIR, TRAINING_INFERENCE_DIRECTORY, TRAINING_TURN_STORE_ROOT,
167
+ TRAINING_SUPERVISOR_DIRECTORY, TRAINING_GRANT_HOME_ROOT,
168
+ DAIMON_GROK_TURN_USAGE_LEDGER.directoryPath, DAIMON_WAKE_FUSE_DIRECTORY
154
169
  ];
155
170
  /**
156
171
  * Deny entries a launch may legitimately not have mounted. Everything else must
@@ -207,7 +222,6 @@ export const TRAINING_HOST_BIND_DENY_PATHS = [TRAINING_RUN_ROOT, DAIMON_GROK_SUB
207
222
  */
208
223
  export const TRAINING_SEALED_DENY_PATHS = [TRAINING_SEALED_INPUTS_ROOT];
209
224
  /** Spawnfile-owned per-route seal attestation, written by provisioning beside the slot preflight receipt. */
210
- export const TRAINING_SEALED_INPUTS_ATTESTATION = `${TRAINING_SLOT_ROOT}/sealed-inputs.json`;
211
225
  /** The image-baked identity of the sealed inputs root, asserted before every slot and never writable at runtime. */
212
226
  export const TRAINING_SEALED_INPUTS_IDENTITY = { uid: 0, gid: DAIMON_ORGANIZATION_UID, mode: "750" };
213
227
  /**
@@ -221,21 +235,15 @@ export const TRAINING_SEALED_INPUTS_IDENTITY = { uid: 0, gid: DAIMON_ORGANIZATIO
221
235
  * anyway, so an undeclared one degrades to "left in place and reported" rather
222
236
  * than a failed provision.
223
237
  */
224
- export const TRAINING_WIPE_TARGETS = [
225
- TRAINING_WORKER_HOME,
226
- TRAINING_SLOT_RUNTIME_HOME,
227
- TRAINING_SLOT_TURN_STORE,
228
- TRAINING_SLOT_ACCEPTANCE_STORE,
229
- DAIMON_GROK_ENGINE_BROKER.serviceConfigPath,
230
- DAIMON_GROK_ENGINE_BROKER.registrationPath
231
- ];
232
- /** Emptied but kept: their paths are registered with Daimon and must stay canonical across a recycle. */
233
- export const TRAINING_CLEAR_TARGETS = [
234
- TRAINING_SLOT_WORKSPACE,
235
- TRAINING_SLOT_USAGE_DIRECTORY,
236
- path.posix.dirname(DAIMON_GROK_ENGINE_BROKER.controlSocketPath),
237
- path.posix.dirname(DAIMON_GROK_ENGINE_BROKER.registrationPath)
238
- ];
238
+ export const trainingWipeTargets = (slot) => {
239
+ const p = trainingSlotPaths(slot);
240
+ return [p.runtimeHome, p.state, p.preflightReceipt, p.sealedInputsAttestation];
241
+ };
242
+ /** Broker-owned turns and clocks are reset through its control seam, never by filesystem deletion. */
243
+ export const trainingClearTargets = (slot) => {
244
+ const p = trainingSlotPaths(slot);
245
+ return [p.workspace, p.usageDirectory];
246
+ };
239
247
  export const TRAINING_REALM_MOUNT = DAIMON_GROK_SUBSCRIPTION_REALM.durableMountPath;
240
248
  export const TRAINING_BOOTSTRAP_MOUNT = DAIMON_GROK_SUBSCRIPTION_REALM.bootstrapMountPath;
241
249
  export { DAIMON_BROKER_UID, DAIMON_ORGANIZATION_UID };
@@ -1,4 +1,12 @@
1
1
  import { type ChildProcess } from "node:child_process";
2
+ interface SocketIdentity {
3
+ dev: number;
4
+ ino: number;
5
+ ctimeMs: number;
6
+ isSocket(): boolean;
7
+ }
8
+ /** An existing placement socket is not readiness. Its inode (or reuse timestamp) must change. */
9
+ export declare const isStartedBrokerSocket: (current: SocketIdentity | undefined, previous: SocketIdentity | undefined) => boolean;
2
10
  export declare const DAIMON_RUNTIME_ROOT = "/opt/spawnfile/runtime-installs/daimon";
3
11
  /** `00000000000000c1` = CHOWN|SETGID|SETUID, the launcher's bounding set after `setpriv`. */
4
12
  export declare const LAUNCHER_CAPABILITY_BOUND = "00000000000000c1";
@@ -40,3 +48,4 @@ export interface StartBrokerOptions {
40
48
  export declare const startBrokerProcesses: (options: StartBrokerOptions) => Promise<BrokerChild[]>;
41
49
  /** Graceful stop in reverse start order: relay, backend, launcher. `SIGKILL` only after the grace window. */
42
50
  export declare const stopBrokerProcesses: (children: readonly BrokerChild[], log: (line: string) => void, graceMs?: number) => Promise<void>;
51
+ export {};
@@ -4,6 +4,8 @@ import { setTimeout as pause } from "node:timers/promises";
4
4
  import { SpawnfileError } from "../../../shared/index.js";
5
5
  import { DAIMON_GROK_ENGINE_BROKER } from "../../../runtime/daimon/contractManifest.js";
6
6
  import { DAIMON_BROKER_UID, TRAINING_BROKER_TMPDIR } from "./paths.js";
7
+ /** An existing placement socket is not readiness. Its inode (or reuse timestamp) must change. */
8
+ export const isStartedBrokerSocket = (current, previous) => current?.isSocket() === true && (!previous || current.dev !== previous.dev || current.ino !== previous.ino || current.ctimeMs !== previous.ctimeMs);
7
9
  export const DAIMON_RUNTIME_ROOT = "/opt/spawnfile/runtime-installs/daimon";
8
10
  /** `00000000000000c1` = CHOWN|SETGID|SETUID, the launcher's bounding set after `setpriv`. */
9
11
  export const LAUNCHER_CAPABILITY_BOUND = "00000000000000c1";
@@ -52,6 +54,7 @@ export const startBrokerProcesses = async (options) => {
52
54
  const deadline = Date.now() + timeoutMs;
53
55
  try {
54
56
  for (const entry of brokerProcessPlan()) {
57
+ const previousSocket = await stat(entry.socket).catch(() => undefined);
55
58
  const child = spawn(entry.argv[0], entry.argv.slice(1), { stdio: ["ignore", "inherit", "inherit"] });
56
59
  if (child.pid === undefined)
57
60
  throw new SpawnfileError("runtime_error", `${entry.name} did not start`);
@@ -64,7 +67,7 @@ export const startBrokerProcesses = async (options) => {
64
67
  if (Date.now() > deadline)
65
68
  throw new SpawnfileError("runtime_error", `${entry.name} readiness timed out`);
66
69
  const socket = await stat(entry.socket).catch(() => undefined);
67
- if (socket?.isSocket()) {
70
+ if (isStartedBrokerSocket(socket, previousSocket)) {
68
71
  const identity = await processIdentity(child.pid, procRoot);
69
72
  if (identity.uid === String(entry.uid) && identity.capBnd === entry.capBnd)
70
73
  break;
@@ -18,6 +18,7 @@ export interface DaimonProjectionModule {
18
18
  projectionVersion: string;
19
19
  slotPreflightVersion: string;
20
20
  nativeAbiVersion: number;
21
+ controlProtocolVersion: string;
21
22
  };
22
23
  }
23
24
  export declare const loadDaimonProjectionModule: (load?: () => Promise<unknown>) => Promise<DaimonProjectionModule>;
@@ -31,13 +32,13 @@ export declare const loadDaimonProjectionModule: (load?: () => Promise<unknown>)
31
32
  * of peers reach `resolveOrganizationGrokBrokerProjection`, so this minimal
32
33
  * config and Paideia's fuller one compute the same projection digest. A peer
33
34
  * agent would change Daimon's protected set and the digest with it, which is
34
- * exactly why training runs one slot.
35
+ * why each slot resolves its own one-agent projection with explicit sibling deny paths.
35
36
  */
36
37
  export declare const trainingOrganizationRuntimeConfig: (declaration: {
37
38
  agentId: string;
38
39
  model: DaimonGrokBrokerModel;
39
40
  reasoningEffort: DaimonGrokBrokerReasoningEffort;
40
- }) => Record<string, unknown>;
41
+ }, slot?: number) => Record<string, unknown>;
41
42
  export interface TrainingGrokProjection {
42
43
  projection: Record<string, unknown>;
43
44
  projectionSha256: string;
@@ -1,6 +1,6 @@
1
1
  import { SpawnfileError } from "../../../shared/index.js";
2
2
  import { DAIMON_GROK_ENGINE_BROKER } from "../../../runtime/daimon/contractManifest.js";
3
- import { TRAINING_SLOT_RUNTIME_HOME, TRAINING_SLOT_STATE_ROOT, TRAINING_SLOT_WORKSPACE, TRAINING_WORKER_HOME } from "./paths.js";
3
+ import { trainingSlotPaths } from "./paths.js";
4
4
  /** Indirect specifier: Daimon is an in-image runtime peer of the training container, never a Spawnfile source dependency. */
5
5
  const loadRuntime = async () => {
6
6
  const packageName = "@noopolis/daimon/runtime";
@@ -16,6 +16,7 @@ export const loadDaimonProjectionModule = async (load = loadRuntime) => {
16
16
  }
17
17
  if (typeof daimon.resolveOrganizationGrokBrokerProjection !== "function" || typeof daimon.grokBrokerProjectionSha256 !== "function"
18
18
  || daimon.GROK_ENGINE_BROKER?.projectionVersion !== DAIMON_GROK_ENGINE_BROKER.projectionVersion
19
+ || daimon.GROK_ENGINE_BROKER.controlProtocolVersion !== DAIMON_GROK_ENGINE_BROKER.controlProtocolVersion
19
20
  || daimon.GROK_ENGINE_BROKER.slotPreflightVersion !== DAIMON_GROK_ENGINE_BROKER.slotPreflightVersion
20
21
  || daimon.GROK_ENGINE_BROKER.nativeAbiVersion !== DAIMON_GROK_ENGINE_BROKER.nativeAbiVersion) {
21
22
  throw new SpawnfileError("runtime_error", "The installed Daimon Grok broker contract differs from this compiler's vendored manifest");
@@ -32,17 +33,17 @@ export const loadDaimonProjectionModule = async (load = loadRuntime) => {
32
33
  * of peers reach `resolveOrganizationGrokBrokerProjection`, so this minimal
33
34
  * config and Paideia's fuller one compute the same projection digest. A peer
34
35
  * agent would change Daimon's protected set and the digest with it, which is
35
- * exactly why training runs one slot.
36
+ * why each slot resolves its own one-agent projection with explicit sibling deny paths.
36
37
  */
37
- export const trainingOrganizationRuntimeConfig = (declaration) => ({
38
+ export const trainingOrganizationRuntimeConfig = (declaration, slot = 0) => ({
38
39
  version: "noopolis.daimon.organization-runtime.v1",
39
- host: { bindHost: "127.0.0.1", port: 19_700, controlTokenEnv: "SPAWNFILE_DAIMON_CONTROL_TOKEN" },
40
+ host: { bindHost: "127.0.0.1", port: trainingSlotPaths(slot).ports.workerControl, controlTokenEnv: "SPAWNFILE_DAIMON_CONTROL_TOKEN" },
40
41
  agents: [{
41
42
  id: declaration.agentId,
42
43
  name: declaration.agentId,
43
44
  instructions: "training subject",
44
- workspacePath: TRAINING_SLOT_WORKSPACE,
45
- runtimeHomePath: TRAINING_SLOT_RUNTIME_HOME,
45
+ workspacePath: trainingSlotPaths(slot).workspace,
46
+ runtimeHomePath: trainingSlotPaths(slot).runtimeHome,
46
47
  engine: { kind: "grok", model: declaration.model, reasoningEffort: declaration.reasoningEffort }
47
48
  }]
48
49
  });
@@ -53,21 +54,32 @@ export const trainingOrganizationRuntimeConfig = (declaration) => ({
53
54
  * list drifted from the bytes provisioning wrote.
54
55
  */
55
56
  export const resolveTrainingGrokProjection = async (declaration, registration, daimon) => {
56
- const projection = daimon.resolveOrganizationGrokBrokerProjection(trainingOrganizationRuntimeConfig(declaration), declaration.agentId, {
57
+ const projection = daimon.resolveOrganizationGrokBrokerProjection(trainingOrganizationRuntimeConfig(declaration, registration.slot), declaration.agentId, {
57
58
  slot: registration.slot,
59
+ workerConfigVariant: "clocked",
58
60
  workerUid: registration.uid,
59
- workerHomePath: TRAINING_WORKER_HOME,
61
+ workerHomePath: registration.home,
60
62
  architecture: declaration.architecture,
61
63
  usageLedgerPath: registration.usageLedgerPath,
62
64
  limits: declaration.limits,
63
65
  // The mask that protects the wake-acceptance store is the slot state root it lives in: the store's
64
66
  // own parent is `2000:2000 0700`, so bubblewrap could not materialize a deny target inside it as
65
67
  // the worker uid. Every party that recomputes this projection must pass the same value.
66
- acceptanceStorePath: TRAINING_SLOT_STATE_ROOT,
68
+ acceptanceStorePath: trainingSlotPaths(registration.slot).state,
67
69
  denyPaths: registration.denyPaths,
68
70
  seccompProfileSha256: declaration.seccompProfileSha256,
69
71
  profileSha256: registration.profileSha256
70
72
  });
73
+ const clock = DAIMON_GROK_ENGINE_BROKER.worker.taskClock;
74
+ const expectedClock = { ...clock, directoryPath: clock.slotDirectoryPattern.replace("{slot}", String(registration.slot)),
75
+ timestampFilePath: clock.slotFilePattern.replace("{slot}", String(registration.slot)) };
76
+ const actualClock = projection.taskClock;
77
+ if (registration.configVariant !== "clocked" || projection.version !== DAIMON_GROK_ENGINE_BROKER.projectionVersion
78
+ || projection.profileSha256 !== registration.profileSha256 || actualClock === undefined
79
+ || Object.entries(expectedClock).some(([key, value]) => actualClock[key] !== value)
80
+ || projection.workerConfigVariant !== "clocked" || projection.workerConfigSha256 !== registration.configSha256) {
81
+ throw new SpawnfileError("runtime_error", "Daimon's clocked worker config differs from the provisioned registration");
82
+ }
71
83
  const denied = [...projection.denyPaths];
72
84
  if (denied.length !== registration.denyPaths.length || denied.some((entry, index) => entry !== registration.denyPaths[index])) {
73
85
  throw new SpawnfileError("runtime_error", "Daimon's Grok broker projection deny list differs from the provisioned sandbox profile");
@@ -7,7 +7,7 @@ import type { DaimonGrokRegistration } from "../../containerDaimonGrokWorkerRend
7
7
  * `2100:2000 2750` uid 2000 — Paideia, DSPy and every judge — cannot read a
8
8
  * single subject usage row or inference row it paid for.
9
9
  */
10
- export declare const trainingSlotDirectories: () => readonly {
10
+ export declare const trainingSlotDirectories: (slot?: number) => readonly {
11
11
  path: string;
12
12
  mode: string;
13
13
  uid: number;
@@ -22,20 +22,11 @@ export declare const trainingSlotDirectories: () => readonly {
22
22
  * and the worker uid instead, and this refuses to provision a slot in an image
23
23
  * that did not.
24
24
  */
25
- export declare const renderTrainingIdentities: () => string[];
26
- /**
27
- * Root provisioning for the training container's one broker slot, as bash
28
- * lines run by the image's own root entrypoint and replayed verbatim by the
29
- * slot supervisor on every recycle.
30
- *
31
- * Everything below the slot skeleton is Daimon's audited production
32
- * provisioning: the same credential bootstrap and journal recovery, the same
33
- * `registrations.bin`, the same attested worker `GROK_HOME` layout, the same
34
- * P1b private worker temp, closed shared temp and setgid spill directory, and
35
- * the same `service.json` — here v2 with the per-slot usage ledger, the
36
- * per-slot tmpfs turn store and the evaluator `inferenceLedgerPath`.
37
- */
38
- export declare const renderTrainingBrokerProvisioning: (registration: DaimonGrokRegistration) => string[];
25
+ export declare const renderTrainingIdentities: (slots?: number) => string[];
26
+ /** Full container provisioning runs exactly once, before any broker process starts. */
27
+ export declare const renderTrainingBrokerProvisioning: (input: DaimonGrokRegistration | readonly DaimonGrokRegistration[], maxRunRequests?: number) => string[];
28
+ /** Reuse the audited worker renderer; never touch service config, credentials, shared temps or siblings. */
29
+ export declare const renderTrainingSlotProvisioning: (registration: DaimonGrokRegistration) => string[];
39
30
  /**
40
31
  * The sealed-inputs seal, asserted and then attacked before any slot is used.
41
32
  *
@@ -1,10 +1,11 @@
1
1
  import path from "node:path";
2
+ import { renderTrainingTaskClockReset } from "./taskClock.js";
2
3
  import { DAIMON_GROK_SECCOMP_PROFILE_SHA256 } from "../../../shared/daimonGrokSeccompProfile.js";
3
4
  import { DAIMON_GROK_ENGINE_BROKER, DAIMON_GROK_TURN_USAGE_LEDGER } from "../../../runtime/daimon/contractManifest.js";
4
5
  import { DAIMON_WAKE_FUSE_DIRECTORY } from "../../../runtime/daimon/config.js";
5
- import { renderDaimonBrokerProvisioningProgram } from "../../containerDaimonBrokerRender.js";
6
- import { renderDaimonGrokHostPreflight } from "../../containerDaimonGrokWorkerProvisioning.js";
7
- import { DAIMON_BROKER_UID, DAIMON_ORGANIZATION_UID, TRAINING_GRANT_HOME_ROOT, TRAINING_INFERENCE_DIRECTORY, TRAINING_INFERENCE_LEDGER, TRAINING_OPTIONAL_DENY_DIRECTORIES, TRAINING_PAIDEIA_ROOT, TRAINING_SLOT_ACCEPTANCE_STORE, TRAINING_SEALED_INPUTS_ATTESTATION, TRAINING_SEALED_INPUTS_IDENTITY, TRAINING_SEALED_INPUTS_ROOT, TRAINING_SLOT_ROOT, TRAINING_SLOT_STATE_ROOT, TRAINING_SLOT_TURN_STORE, TRAINING_SLOT_USAGE_DIRECTORY, TRAINING_SLOT_USAGE_LEDGER, TRAINING_SUPERVISOR_DIRECTORY, TRAINING_BROKER_TMPDIR, TRAINING_SLOT_WORKSPACE, TRAINING_WORKER_ROOT, TRAINING_WORKER_UID } from "./paths.js";
6
+ import { renderDaimonBrokerProvisioningProgram, renderDaimonWorkspaceResourceSecurity } from "../../containerDaimonBrokerRender.js";
7
+ import { renderDaimonGrokHostPreflight, renderDaimonGrokWorkerProvisioning } from "../../containerDaimonGrokWorkerProvisioning.js";
8
+ import { trainingSlotPaths, trainingSlotDescriptors, TRAINING_TURN_STORE_ROOT, TRAINING_RUN_REQUEST_STORE, DAIMON_BROKER_UID, DAIMON_ORGANIZATION_UID, TRAINING_GRANT_HOME_ROOT, TRAINING_INFERENCE_DIRECTORY, TRAINING_INFERENCE_LEDGER, TRAINING_OPTIONAL_DENY_DIRECTORIES, TRAINING_PAIDEIA_ROOT, TRAINING_SEALED_INPUTS_IDENTITY, TRAINING_SEALED_INPUTS_ROOT, TRAINING_SUPERVISOR_DIRECTORY, TRAINING_BROKER_TMPDIR, TRAINING_WORKER_ROOT, } from "./paths.js";
8
9
  import { trainingNamespaceDenialMechanism } from "./seccompRoutes.js";
9
10
  const quote = (value) => `'${value.replace(/'/g, `'"'"'`)}'`;
10
11
  /**
@@ -28,21 +29,22 @@ const PROVISION_DIRECTORY_HELPER = [
28
29
  * `2100:2000 2750` uid 2000 — Paideia, DSPy and every judge — cannot read a
29
30
  * single subject usage row or inference row it paid for.
30
31
  */
31
- export const trainingSlotDirectories = () => [
32
+ export const trainingSlotDirectories = (slot = 0) => [
32
33
  // `/run/training` itself is deliberately absent: it is a mount-point parent on the read-only
33
34
  // image root, and every writable child below it is its own tmpfs or bind.
34
- { path: TRAINING_SLOT_ROOT, mode: "0755", uid: 0, gid: 0 },
35
+ { path: trainingSlotPaths(slot).root, mode: "0711", uid: 0, gid: 0 },
35
36
  { path: TRAINING_PAIDEIA_ROOT, mode: "0750", uid: DAIMON_ORGANIZATION_UID, gid: DAIMON_ORGANIZATION_UID },
36
37
  { path: "/home/training", mode: "0700", uid: DAIMON_ORGANIZATION_UID, gid: DAIMON_ORGANIZATION_UID },
37
38
  { path: "/work", mode: "0700", uid: DAIMON_ORGANIZATION_UID, gid: DAIMON_ORGANIZATION_UID },
38
- { path: TRAINING_SLOT_WORKSPACE, mode: "0750", uid: DAIMON_ORGANIZATION_UID, gid: TRAINING_WORKER_UID },
39
+ { path: trainingSlotPaths(slot).workspace, mode: "0750", uid: DAIMON_ORGANIZATION_UID, gid: trainingSlotPaths(slot).workerUid },
39
40
  // The agent runtime home is deliberately absent: the shared broker provisioning creates it root-owned,
40
41
  // fills its setgid `tool-output/`, and only then narrows it to `2000:<worker> 0710`. Handing it over here
41
42
  // would leave root — which holds no `CAP_DAC_OVERRIDE` — unable to create the spill directory inside it.
42
- { path: TRAINING_SLOT_STATE_ROOT, mode: "0700", uid: DAIMON_ORGANIZATION_UID, gid: DAIMON_ORGANIZATION_UID },
43
- { path: TRAINING_SLOT_ACCEPTANCE_STORE, mode: "0700", uid: DAIMON_ORGANIZATION_UID, gid: DAIMON_ORGANIZATION_UID },
44
- { path: TRAINING_SLOT_TURN_STORE, mode: "0700", uid: DAIMON_BROKER_UID, gid: DAIMON_BROKER_UID },
45
- { path: TRAINING_SLOT_USAGE_DIRECTORY, mode: "2750", uid: DAIMON_BROKER_UID, gid: DAIMON_ORGANIZATION_UID },
43
+ { path: trainingSlotPaths(slot).state, mode: "0700", uid: DAIMON_ORGANIZATION_UID, gid: DAIMON_ORGANIZATION_UID },
44
+ { path: trainingSlotPaths(slot).acceptanceStore, mode: "0700", uid: DAIMON_ORGANIZATION_UID, gid: DAIMON_ORGANIZATION_UID },
45
+ { path: TRAINING_TURN_STORE_ROOT, mode: "0700", uid: DAIMON_BROKER_UID, gid: DAIMON_BROKER_UID },
46
+ { path: TRAINING_RUN_REQUEST_STORE, mode: "0700", uid: DAIMON_BROKER_UID, gid: DAIMON_BROKER_UID },
47
+ { path: trainingSlotPaths(slot).usageDirectory, mode: "2750", uid: DAIMON_BROKER_UID, gid: DAIMON_ORGANIZATION_UID },
46
48
  { path: TRAINING_INFERENCE_DIRECTORY, mode: "2750", uid: DAIMON_BROKER_UID, gid: DAIMON_ORGANIZATION_UID },
47
49
  { path: TRAINING_GRANT_HOME_ROOT, mode: "0700", uid: DAIMON_ORGANIZATION_UID, gid: DAIMON_ORGANIZATION_UID },
48
50
  // Traverse only: the supervisor socket inside it is the uid gate, and a directory nobody but root may
@@ -66,52 +68,68 @@ export const trainingSlotDirectories = () => [
66
68
  * and the worker uid instead, and this refuses to provision a slot in an image
67
69
  * that did not.
68
70
  */
69
- export const renderTrainingIdentities = () => [
70
- `for fixed_uid in ${DAIMON_ORGANIZATION_UID} ${DAIMON_BROKER_UID} ${TRAINING_WORKER_UID}; do`,
71
+ export const renderTrainingIdentities = (slots = 4) => [
72
+ `for fixed_uid in ${DAIMON_ORGANIZATION_UID} ${DAIMON_BROKER_UID} ${trainingSlotDescriptors(slots).map(p => p.workerUid).join(" ")}; do`,
71
73
  ' getent passwd "$fixed_uid" >/dev/null && getent group "$fixed_uid" >/dev/null || { echo "the training image must bake uid/gid $fixed_uid; the container root is read-only" >&2; exit 1; }',
72
74
  "done"
73
75
  ];
74
- /**
75
- * Root provisioning for the training container's one broker slot, as bash
76
- * lines run by the image's own root entrypoint and replayed verbatim by the
77
- * slot supervisor on every recycle.
78
- *
79
- * Everything below the slot skeleton is Daimon's audited production
80
- * provisioning: the same credential bootstrap and journal recovery, the same
81
- * `registrations.bin`, the same attested worker `GROK_HOME` layout, the same
82
- * P1b private worker temp, closed shared temp and setgid spill directory, and
83
- * the same `service.json` — here v2 with the per-slot usage ledger, the
84
- * per-slot tmpfs turn store and the evaluator `inferenceLedgerPath`.
85
- */
86
- export const renderTrainingBrokerProvisioning = (registration) => [
76
+ /** Slot-local skeleton, shared by initial provisioning and recycle. */
77
+ const slotDirectories = (slot) => trainingSlotDirectories(slot).filter(entry => entry.path === trainingSlotPaths(slot).root || entry.path.startsWith(`${trainingSlotPaths(slot).root}/`));
78
+ const renderDirectories = (entries, ledgers) => [
87
79
  ...PROVISION_DIRECTORY_HELPER,
88
- // Two passes, because root here holds neither `CAP_DAC_OVERRIDE` nor `CAP_FOWNER`: create every
89
- // directory while they are all still root-owned and traversable, then set ownership and mode from the
90
- // deepest path up, so tightening a parent to `0700` never strands a child that still has to be created.
91
- ...trainingSlotDirectories().map((entry) => `mkdir -p ${quote(entry.path)}`),
92
- // Every deny entry needs an inode to mask; a bind the host did not supply is created root-owned and unreadable.
93
- ...TRAINING_OPTIONAL_DENY_DIRECTORIES.map((target) => `if [ ! -e ${quote(target)} ]; then mkdir -p ${quote(target)}; provision_dir ${quote(target)} 0700 0 0; fi`),
94
- // Both ledgers exist before their directories are handed to the broker: the broker appends rows `0640` in
95
- // its own group, and the setgid directory below is what lets uid 2000 read a row it paid for.
96
- ...[TRAINING_SLOT_USAGE_LEDGER, TRAINING_INFERENCE_LEDGER].map((ledger) => `if [ ! -e ${quote(ledger)} ]; then : > ${quote(ledger)}; fi; chown 0:0 ${quote(ledger)}; chmod 0640 ${quote(ledger)}; chown ${DAIMON_BROKER_UID}:${DAIMON_ORGANIZATION_UID} ${quote(ledger)}`),
97
- ...[...trainingSlotDirectories()].sort((left, right) => right.path.split("/").length - left.path.split("/").length)
98
- .map((entry) => `provision_dir ${quote(entry.path)} ${entry.mode} ${entry.uid} ${entry.gid}`),
99
- ...renderDaimonGrokHostPreflight(),
100
- ...renderDaimonBrokerProvisioningProgram([registration], [], {
101
- turnStore: TRAINING_SLOT_TURN_STORE,
102
- inferenceLedgerPath: TRAINING_INFERENCE_LEDGER
103
- }, "clear", TRAINING_OPTIONAL_DENY_DIRECTORIES, TRAINING_BROKER_TMPDIR),
104
- // The shared program leaves the broker's `/etc` root `0555 root:root`, which every uid can list. Training
105
- // denies that directory to its worker, and a canary can only observe a denial the kernel actually enforces.
106
- `chmod 0550 /etc/daimon-engine-broker; chown 0:${DAIMON_BROKER_UID} /etc/daimon-engine-broker`,
107
- `test "$(stat -c '%u:%g %a' ${quote(TRAINING_SLOT_USAGE_DIRECTORY)})" = "${DAIMON_BROKER_UID}:${DAIMON_ORGANIZATION_UID} 2750"`,
80
+ ...entries.map(entry => `mkdir -p ${quote(entry.path)}`),
81
+ ...ledgers.map(ledger => `if [ ! -e ${quote(ledger)} ]; then : > ${quote(ledger)}; fi; chown 0:0 ${quote(ledger)}; chmod 0640 ${quote(ledger)}; chown ${DAIMON_BROKER_UID}:${DAIMON_ORGANIZATION_UID} ${quote(ledger)}`),
82
+ ...[...entries].sort((a, b) => b.path.split("/").length - a.path.split("/").length)
83
+ .map(entry => `provision_dir ${quote(entry.path)} ${entry.mode} ${entry.uid} ${entry.gid}`)
84
+ ];
85
+ const renderSlotAssertions = (r) => [
86
+ `test "$(stat -c '%u:%g %a' ${quote(trainingSlotPaths(r.slot).usageDirectory)})" = "${DAIMON_BROKER_UID}:${DAIMON_ORGANIZATION_UID} 2750"`,
108
87
  `test "$(stat -c '%u:%g %a' ${quote(TRAINING_INFERENCE_DIRECTORY)})" = "${DAIMON_BROKER_UID}:${DAIMON_ORGANIZATION_UID} 2750"`,
109
88
  `test "$(stat -c '%u:%g %a' ${quote(TRAINING_GRANT_HOME_ROOT)})" = "${DAIMON_ORGANIZATION_UID}:${DAIMON_ORGANIZATION_UID} 700"`,
110
- // The judge grant home root is the evaluator's alone: no worker uid may even traverse it.
111
- `setpriv --clear-groups --reuid ${TRAINING_WORKER_UID} --regid ${TRAINING_WORKER_UID} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu '! test -r ${quote(TRAINING_GRANT_HOME_ROOT)}'`,
112
- `setpriv --clear-groups --reuid ${DAIMON_ORGANIZATION_UID} --regid ${DAIMON_ORGANIZATION_UID} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu 'test -r ${quote(TRAINING_SLOT_USAGE_LEDGER)} && test -r ${quote(TRAINING_INFERENCE_LEDGER)}'`,
113
- // The sealed train and test datasets: the one boundary here that must hold against the subject's own
114
- // namespace, not only against an honest tool. Last, so it runs with every mode already final.
89
+ `setpriv --clear-groups --reuid ${r.uid} --regid ${r.uid} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu '! test -r ${quote(TRAINING_GRANT_HOME_ROOT)}'`,
90
+ `setpriv --clear-groups --reuid ${DAIMON_ORGANIZATION_UID} --regid ${DAIMON_ORGANIZATION_UID} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- bash -ceu 'test -r ${quote(r.usageLedgerPath)} && test -r ${quote(TRAINING_INFERENCE_LEDGER)}'`
91
+ ];
92
+ /** Full container provisioning runs exactly once, before any broker process starts. */
93
+ export const renderTrainingBrokerProvisioning = (input, maxRunRequests = 1000) => {
94
+ if (!Number.isSafeInteger(maxRunRequests) || maxRunRequests < 1)
95
+ throw new Error("Invalid run request cap");
96
+ const registrations = Array.isArray(input) ? input : [input];
97
+ const directories = [...new Map(registrations.flatMap(r => trainingSlotDirectories(r.slot)).map(d => [d.path, d])).values()];
98
+ return [
99
+ ...renderTrainingIdentities(registrations.length),
100
+ ...renderTrainingTaskClockReset(),
101
+ ...renderDirectories(directories, [...registrations.map(r => r.usageLedgerPath), TRAINING_INFERENCE_LEDGER]),
102
+ ...renderDaimonGrokHostPreflight(),
103
+ ...renderDaimonBrokerProvisioningProgram(registrations, [], {
104
+ version: "v3", maxRunRequests, runRequestStore: TRAINING_RUN_REQUEST_STORE,
105
+ turnStore: TRAINING_TURN_STORE_ROOT, inferenceLedgerPath: TRAINING_INFERENCE_LEDGER
106
+ }, "clear", TRAINING_OPTIONAL_DENY_DIRECTORIES, TRAINING_BROKER_TMPDIR, [
107
+ `mkdir -p ${quote(DAIMON_GROK_ENGINE_BROKER.worker.taskClock.rootDirectoryPath)}; chmod 0755 ${quote(DAIMON_GROK_ENGINE_BROKER.worker.taskClock.rootDirectoryPath)}`,
108
+ ...registrations.flatMap(r => {
109
+ const p = trainingSlotPaths(r.slot);
110
+ return [
111
+ `mkdir -p ${quote(p.clockDirectory)}; chown 0:0 ${quote(p.clockDirectory)}; chmod 0755 ${quote(p.clockDirectory)}`,
112
+ `printf '+0\\n' > ${quote(p.clockFile)}; chmod 0644 ${quote(p.clockFile)}; chown ${DAIMON_BROKER_UID}:${DAIMON_BROKER_UID} ${quote(p.clockFile)}`,
113
+ `chown ${DAIMON_BROKER_UID}:${DAIMON_BROKER_UID} ${quote(p.clockDirectory)}`
114
+ ];
115
+ })
116
+ ]),
117
+ `chmod 0550 /etc/daimon-engine-broker; chown 0:${DAIMON_BROKER_UID} /etc/daimon-engine-broker`,
118
+ ...registrations.flatMap(r => [...renderSlotAssertions(r), ...renderTrainingSealedInputsAssertions(r.uid, r.privateTmp)])
119
+ ];
120
+ };
121
+ /** Reuse the audited worker renderer; never touch service config, credentials, shared temps or siblings. */
122
+ export const renderTrainingSlotProvisioning = (registration) => [
123
+ ...renderDirectories(slotDirectories(registration.slot), [registration.usageLedgerPath]),
124
+ // Keep worker-home and private-tmp identities stable: sibling turns attest them concurrently.
125
+ `setpriv --clear-groups --reuid=${registration.uid} --regid=${registration.uid} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- mkdir -p ${quote(registration.grokHome)}`,
126
+ `chown 0:0 ${quote(registration.grokHome)}; chmod 0700 ${quote(registration.grokHome)}`,
127
+ "node <<'SPAWNFILE_TRAINING_SLOT_PROVISION'",
128
+ "const crypto = require('node:crypto'); const fs = require('node:fs');",
129
+ ...renderDaimonWorkspaceResourceSecurity([]),
130
+ ...renderDaimonGrokWorkerProvisioning([registration], {}, [], "slot"),
131
+ "SPAWNFILE_TRAINING_SLOT_PROVISION",
132
+ ...renderSlotAssertions(registration),
115
133
  ...renderTrainingSealedInputsAssertions(registration.uid, registration.privateTmp)
116
134
  ];
117
135
  /**
@@ -158,11 +176,11 @@ export const renderTrainingBrokerProvisioning = (registration) => [
158
176
  * every trial on `namespace-rebind reached no verdict` — the `mkdir` failed, not
159
177
  * the seal. The private tmp is also the workspace the subject itself has.
160
178
  */
161
- export const renderTrainingSealedInputsAssertions = (workerUid = TRAINING_WORKER_UID, privateTmp = path.posix.join(TRAINING_WORKER_ROOT, String(TRAINING_WORKER_UID), "tmp"), mechanism = trainingNamespaceDenialMechanism()) => [
179
+ export const renderTrainingSealedInputsAssertions = (workerUid = trainingSlotPaths(0).workerUid, privateTmp = trainingSlotPaths(0).privateTmp, mechanism = trainingNamespaceDenialMechanism()) => [
162
180
  // Diagnostics go to a file rather than into the verdict: a route's stderr is util-linux prose that
163
181
  // would turn every real verdict into "unknown", but a no-verdict refusal with no diagnostic is what
164
182
  // made the first live failure unreadable, so the unknown branch prints it back.
165
- `seal_diagnostic=${quote(`${TRAINING_SLOT_ROOT}/seal-probe.err`)}`,
183
+ `seal_diagnostic=${quote(`${trainingSlotPaths(workerUid - trainingSlotPaths(0).workerUid).root}/seal-probe.err`)}`,
166
184
  `seal_worker() { setpriv --clear-groups --reuid ${workerUid} --regid ${workerUid} --inh-caps=-all --ambient-caps=-all --bounding-set=-all -- /bin/sh -c "$1" 2>"$seal_diagnostic"; }`,
167
185
  "seal_rows=''",
168
186
  'seal_record() { if [ -n "$seal_rows" ]; then seal_rows="$seal_rows,"; fi; seal_rows="$seal_rows{\\"route\\":\\"$1\\",\\"verdict\\":\\"$2\\"}"; }',
@@ -198,7 +216,7 @@ export const renderTrainingSealedInputsAssertions = (workerUid = TRAINING_WORKER
198
216
  // cross-repo `noopolis.daimon.grok-slot-preflight.v2` canary shape is deliberately untouched — its
199
217
  // schema lives in Daimon and no consumer here can validate an added member — so the per-route
200
218
  // mechanism is recorded here rather than implied by a bare `result: "denied"` there.
201
- `seal_attestation=${quote(TRAINING_SEALED_INPUTS_ATTESTATION)}`,
219
+ `seal_attestation=${quote(trainingSlotPaths(workerUid - trainingSlotPaths(0).workerUid).sealedInputsAttestation)}`,
202
220
  `printf '{"version":"spawnfile.training-sealed-inputs.v1","root":"%s","worker_uid":%s,"identity":"%s","pinned_seccomp_profile_sha256":"%s","namespace_routes":"%s","routes":[%s]}\\n' `
203
221
  + `${quote(TRAINING_SEALED_INPUTS_ROOT)} ${workerUid} `
204
222
  + `"$(stat -c '%u:%g %a' ${quote(TRAINING_SEALED_INPUTS_ROOT)})" ${quote(DAIMON_GROK_SECCOMP_PROFILE_SHA256)} `