stageflow 0.25.0 → 0.30.0

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 (681) hide show
  1. package/README.md +14 -3
  2. package/builtin-skills/browser/SKILL.md +42 -0
  3. package/dist/a2a/contracts.d.ts +1 -0
  4. package/dist/a2a/contracts.js +1 -0
  5. package/dist/a2a/registry.d.ts +2 -0
  6. package/dist/a2a/registry.js +20 -1
  7. package/dist/a2a/server.d.ts +7 -0
  8. package/dist/a2a/server.js +5 -2
  9. package/dist/a2a/service.d.ts +1 -1
  10. package/dist/a2a/service.js +57 -8
  11. package/dist/a2a/store.d.ts +8 -5
  12. package/dist/a2a/store.js +24 -67
  13. package/dist/agent/activity.d.ts +3 -0
  14. package/dist/agent/bootProviderConfig.d.ts +21 -0
  15. package/dist/agent/bootProviderConfig.js +74 -0
  16. package/dist/agent/claudeAdapter.js +2 -2
  17. package/dist/agent/cursorProvider.d.ts +2 -0
  18. package/dist/agent/cursorProvider.js +30 -5
  19. package/dist/agent/fakeAgent.d.ts +1 -0
  20. package/dist/agent/fakeAgent.js +13 -0
  21. package/dist/agent/piAdapter.d.ts +11 -24
  22. package/dist/agent/piAdapter.js +107 -50
  23. package/dist/agent/piIsolatedMcp.d.ts +2 -0
  24. package/dist/agent/piIsolatedMcp.js +10 -2
  25. package/dist/agent/piSessionFactory.d.ts +38 -0
  26. package/dist/agent/piSessionFactory.js +60 -0
  27. package/dist/agent/port.d.ts +8 -0
  28. package/dist/agent/streamLogRedact.d.ts +7 -1
  29. package/dist/agent/streamLogRedact.js +26 -11
  30. package/dist/browser/anchor.d.ts +27 -0
  31. package/dist/browser/anchor.js +127 -0
  32. package/dist/browser/auditSink.d.ts +38 -0
  33. package/dist/browser/auditSink.js +34 -0
  34. package/dist/browser/browserHost.d.ts +86 -0
  35. package/dist/browser/browserHost.js +7 -0
  36. package/dist/browser/browserSweep.d.ts +14 -0
  37. package/dist/browser/browserSweep.js +54 -0
  38. package/dist/browser/browserTeardown.d.ts +56 -0
  39. package/dist/browser/browserTeardown.js +235 -0
  40. package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -0
  41. package/dist/browser/fakeRemoteBrowserHost.js +34 -0
  42. package/dist/browser/gateHandoff.d.ts +25 -0
  43. package/dist/browser/gateHandoff.js +83 -0
  44. package/dist/browser/humanLogin.d.ts +18 -0
  45. package/dist/browser/humanLogin.js +34 -0
  46. package/dist/browser/keyProvider.d.ts +10 -0
  47. package/dist/browser/keyProvider.js +39 -0
  48. package/dist/browser/localBrowserHost.d.ts +10 -0
  49. package/dist/browser/localBrowserHost.js +152 -0
  50. package/dist/browser/localProfileLock.d.ts +2 -0
  51. package/dist/browser/localProfileLock.js +218 -0
  52. package/dist/browser/localProfileStore.d.ts +5 -0
  53. package/dist/browser/localProfileStore.js +91 -0
  54. package/dist/browser/loginCheck.d.ts +53 -0
  55. package/dist/browser/loginCheck.js +147 -0
  56. package/dist/browser/memoryProfileLock.d.ts +2 -0
  57. package/dist/browser/memoryProfileLock.js +53 -0
  58. package/dist/browser/memoryProfileStore.d.ts +2 -0
  59. package/dist/browser/memoryProfileStore.js +31 -0
  60. package/dist/browser/navigationAudit.d.ts +16 -0
  61. package/dist/browser/navigationAudit.js +53 -0
  62. package/dist/browser/persistedEnv.d.ts +3 -0
  63. package/dist/browser/persistedEnv.js +15 -0
  64. package/dist/browser/profileLock.d.ts +40 -0
  65. package/dist/browser/profileLock.js +10 -0
  66. package/dist/browser/profileStore.d.ts +23 -0
  67. package/dist/browser/profileStore.js +39 -0
  68. package/dist/browser/runLiveness.d.ts +13 -0
  69. package/dist/browser/runLiveness.js +39 -0
  70. package/dist/browser/sitePolicy.d.ts +10 -0
  71. package/dist/browser/sitePolicy.js +61 -0
  72. package/dist/browser/stageBrowserEnv.d.ts +22 -0
  73. package/dist/browser/stageBrowserEnv.js +147 -0
  74. package/dist/browser/stageProfileLock.d.ts +17 -0
  75. package/dist/browser/stageProfileLock.js +39 -0
  76. package/dist/cli/artifactCommand.js +9 -16
  77. package/dist/cli/backupCommand.d.ts +9 -0
  78. package/dist/cli/backupCommand.js +111 -0
  79. package/dist/cli/browserCommand.d.ts +44 -0
  80. package/dist/cli/browserCommand.js +472 -0
  81. package/dist/cli/debugRunCommand.d.ts +10 -0
  82. package/dist/cli/debugRunCommand.js +109 -0
  83. package/dist/cli/doctorCommand.d.ts +32 -0
  84. package/dist/cli/doctorCommand.js +453 -0
  85. package/dist/cli/envelopeCommand.js +9 -2
  86. package/dist/cli/exportAllCommand.d.ts +55 -0
  87. package/dist/cli/exportAllCommand.js +218 -0
  88. package/dist/cli/exportRunCommand.js +23 -21
  89. package/dist/cli/hostClient.d.ts +41 -3
  90. package/dist/cli/hostClient.js +129 -14
  91. package/dist/cli/initCommand.d.ts +1 -0
  92. package/dist/cli/initCommand.js +23 -7
  93. package/dist/cli/initTemplates.d.ts +5 -2
  94. package/dist/cli/initTemplates.js +32 -2
  95. package/dist/cli/resolveSafeOutPath.d.ts +2 -0
  96. package/dist/cli/resolveSafeOutPath.js +40 -0
  97. package/dist/cli/restoreCommand.d.ts +10 -0
  98. package/dist/cli/restoreCommand.js +90 -0
  99. package/dist/cli/runCommand.d.ts +3 -2
  100. package/dist/cli/runCommand.js +93 -11
  101. package/dist/cli/runOutput.d.ts +4 -0
  102. package/dist/cli/runOutput.js +33 -7
  103. package/dist/cli/runStageCommand.d.ts +1 -0
  104. package/dist/cli/runStageCommand.js +44 -25
  105. package/dist/cli/runsCommand.d.ts +1 -1
  106. package/dist/cli/runsCommand.js +168 -10
  107. package/dist/cli/triggerCommand.d.ts +12 -0
  108. package/dist/cli/triggerCommand.js +183 -0
  109. package/dist/cli/validateCommand.d.ts +1 -1
  110. package/dist/cli/validateCommand.js +23 -6
  111. package/dist/cli.js +202 -32
  112. package/dist/config/browseCatalog.d.ts +1 -0
  113. package/dist/config/browseCatalog.js +5 -4
  114. package/dist/config/builtinSkills.d.ts +4 -0
  115. package/dist/config/builtinSkills.js +23 -0
  116. package/dist/config/catalogRelativePath.d.ts +63 -0
  117. package/dist/config/catalogRelativePath.js +126 -0
  118. package/dist/config/configOrigin.d.ts +27 -0
  119. package/dist/config/configOrigin.js +59 -0
  120. package/dist/config/createTrigger.d.ts +27 -0
  121. package/dist/config/createTrigger.js +232 -0
  122. package/dist/config/draftPackage.d.ts +117 -0
  123. package/dist/config/draftPackage.js +550 -0
  124. package/dist/config/ensureCatalogScanRoot.d.ts +16 -0
  125. package/dist/config/ensureCatalogScanRoot.js +73 -0
  126. package/dist/config/hostConfig.d.ts +57 -0
  127. package/dist/config/hostConfig.js +360 -0
  128. package/dist/config/listSkills.d.ts +26 -0
  129. package/dist/config/listSkills.js +206 -5
  130. package/dist/config/loadOutcome.d.ts +7 -1
  131. package/dist/config/loadPipeline.js +39 -2
  132. package/dist/config/loadStage.js +25 -0
  133. package/dist/config/loadStageflowManifest.js +25 -0
  134. package/dist/config/loadTask.d.ts +2 -0
  135. package/dist/config/loadTask.js +57 -18
  136. package/dist/config/loadTrigger.d.ts +9 -0
  137. package/dist/config/loadTrigger.js +120 -0
  138. package/dist/config/materializeStageModels.js +5 -1
  139. package/dist/config/mergePipelineIncludes.d.ts +3 -0
  140. package/dist/config/mergePipelineIncludes.js +19 -0
  141. package/dist/config/migrateYaml.js +6 -11
  142. package/dist/config/multiProjectCatalog.d.ts +32 -0
  143. package/dist/config/multiProjectCatalog.js +150 -0
  144. package/dist/config/normalizePipelineStageEntry.js +27 -1
  145. package/dist/config/parseCompletionContract.js +6 -0
  146. package/dist/config/pipelineStageKeys.js +3 -0
  147. package/dist/config/publishDraftPackage.d.ts +7 -0
  148. package/dist/config/publishDraftPackage.js +25 -0
  149. package/dist/config/resolveCatalogContext.js +1 -1
  150. package/dist/config/resolveCatalogRoots.d.ts +27 -0
  151. package/dist/config/resolveCatalogRoots.js +76 -0
  152. package/dist/config/resolveModel.d.ts +7 -1
  153. package/dist/config/resolveModel.js +11 -1
  154. package/dist/config/resolvePipelineDag.js +1 -1
  155. package/dist/config/resolveStageMcpServers.d.ts +9 -1
  156. package/dist/config/resolveStageMcpServers.js +36 -9
  157. package/dist/config/scanCatalogPaths.d.ts +1 -1
  158. package/dist/config/scanCatalogPaths.js +6 -2
  159. package/dist/config/secretFromEnvOrFile.d.ts +9 -0
  160. package/dist/config/secretFromEnvOrFile.js +34 -0
  161. package/dist/config/seededCatalog.d.ts +11 -0
  162. package/dist/config/seededCatalog.js +29 -0
  163. package/dist/config/stageBrowser.d.ts +12 -0
  164. package/dist/config/stageBrowser.js +118 -0
  165. package/dist/config/toolRequires.d.ts +24 -0
  166. package/dist/config/toolRequires.js +115 -0
  167. package/dist/config/triggerCatalog.d.ts +10 -0
  168. package/dist/config/triggerCatalog.js +37 -0
  169. package/dist/config/validateCatalog.d.ts +17 -3
  170. package/dist/config/validateCatalog.js +223 -3
  171. package/dist/config/validateCompletionContract.js +8 -0
  172. package/dist/diagnostics/checks.d.ts +39 -0
  173. package/dist/diagnostics/checks.js +135 -0
  174. package/dist/envelope/preEmitChecks.d.ts +1 -1
  175. package/dist/envelope/preEmitChecks.js +8 -0
  176. package/dist/errors/codes.d.ts +14 -0
  177. package/dist/errors/codes.js +59 -0
  178. package/dist/git/cache.d.ts +14 -0
  179. package/dist/git/cache.js +150 -0
  180. package/dist/git/credentials.d.ts +9 -0
  181. package/dist/git/credentials.js +88 -0
  182. package/dist/git/errors.d.ts +20 -0
  183. package/dist/git/errors.js +94 -0
  184. package/dist/git/exec.d.ts +16 -0
  185. package/dist/git/exec.js +135 -0
  186. package/dist/git/operations.d.ts +29 -0
  187. package/dist/git/operations.js +153 -0
  188. package/dist/git/version.d.ts +1 -0
  189. package/dist/git/version.js +10 -0
  190. package/dist/logging/audit.d.ts +16 -0
  191. package/dist/logging/audit.js +19 -0
  192. package/dist/logging/commonWords.d.ts +2 -0
  193. package/dist/logging/commonWords.js +13 -0
  194. package/dist/logging/logger.d.ts +49 -0
  195. package/dist/logging/logger.js +193 -0
  196. package/dist/logging/namedSecrets.d.ts +6 -0
  197. package/dist/logging/namedSecrets.js +58 -0
  198. package/dist/logging/redact.d.ts +17 -0
  199. package/dist/logging/redact.js +105 -0
  200. package/dist/mcp/catalogTools.js +492 -81
  201. package/dist/mcp/checkoutTools.d.ts +52 -0
  202. package/dist/mcp/checkoutTools.js +332 -0
  203. package/dist/mcp/controlTools.js +182 -6
  204. package/dist/mcp/deps.d.ts +3 -0
  205. package/dist/mcp/getStartedTool.d.ts +3 -0
  206. package/dist/mcp/getStartedTool.js +62 -0
  207. package/dist/mcp/readArtifact.d.ts +11 -0
  208. package/dist/mcp/readArtifact.js +46 -30
  209. package/dist/mcp/server.js +2 -0
  210. package/dist/mcp/tools.js +6 -0
  211. package/dist/mcp/triggerTools.d.ts +3 -0
  212. package/dist/mcp/triggerTools.js +176 -0
  213. package/dist/net/proxy.d.ts +14 -0
  214. package/dist/net/proxy.js +78 -0
  215. package/dist/operatorAgent/docsRetrieval.d.ts +40 -0
  216. package/dist/operatorAgent/docsRetrieval.js +269 -0
  217. package/dist/operatorAgent/draftContext.d.ts +16 -0
  218. package/dist/operatorAgent/draftContext.js +68 -0
  219. package/dist/operatorAgent/fakeHost.d.ts +39 -0
  220. package/dist/operatorAgent/fakeHost.js +92 -0
  221. package/dist/operatorAgent/host.d.ts +40 -0
  222. package/dist/operatorAgent/host.js +179 -0
  223. package/dist/operatorAgent/index.d.ts +9 -0
  224. package/dist/operatorAgent/index.js +8 -0
  225. package/dist/operatorAgent/piModel.d.ts +80 -0
  226. package/dist/operatorAgent/piModel.js +528 -0
  227. package/dist/operatorAgent/profiles/workshopAuthor.d.ts +23 -0
  228. package/dist/operatorAgent/profiles/workshopAuthor.js +338 -0
  229. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +6 -0
  230. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +103 -0
  231. package/dist/operatorAgent/profiles/workshopAuthorTools.d.ts +57 -0
  232. package/dist/operatorAgent/profiles/workshopAuthorTools.js +623 -0
  233. package/dist/operatorAgent/proposals.d.ts +32 -0
  234. package/dist/operatorAgent/proposals.js +144 -0
  235. package/dist/operatorAgent/types.d.ts +128 -0
  236. package/dist/operatorAgent/types.js +1 -0
  237. package/dist/package-meta.d.ts +2 -1
  238. package/dist/package-meta.js +2 -1
  239. package/dist/preflight/bash.d.ts +8 -0
  240. package/dist/preflight/bash.js +34 -0
  241. package/dist/preflight/claudeRoot.d.ts +11 -0
  242. package/dist/preflight/claudeRoot.js +23 -0
  243. package/dist/preflight/mcpCommands.d.ts +8 -0
  244. package/dist/preflight/mcpCommands.js +36 -0
  245. package/dist/preflight/pipelinePreflight.d.ts +40 -0
  246. package/dist/preflight/pipelinePreflight.js +192 -0
  247. package/dist/preflight/tls.d.ts +6 -0
  248. package/dist/preflight/tls.js +18 -0
  249. package/dist/preflight/toolchain.d.ts +45 -0
  250. package/dist/preflight/toolchain.js +219 -0
  251. package/dist/project/findManifestRoot.d.ts +3 -0
  252. package/dist/project/findManifestRoot.js +35 -0
  253. package/dist/project/findProjectRoot.js +3 -4
  254. package/dist/project/globalHome.d.ts +7 -0
  255. package/dist/project/globalHome.js +63 -2
  256. package/dist/project/resolveProjectContext.js +2 -2
  257. package/dist/project/resolveStageflowContext.d.ts +7 -0
  258. package/dist/project/resolveStageflowContext.js +46 -30
  259. package/dist/projection/projectRun.d.ts +2 -1
  260. package/dist/projection/projectRun.js +1 -0
  261. package/dist/runstore/assertTmpdir.d.ts +1 -0
  262. package/dist/runstore/assertTmpdir.js +25 -0
  263. package/dist/runstore/backup.d.ts +52 -0
  264. package/dist/runstore/backup.js +292 -0
  265. package/dist/runstore/createStore.d.ts +18 -1
  266. package/dist/runstore/createStore.js +64 -5
  267. package/dist/runstore/debugBundle.d.ts +60 -0
  268. package/dist/runstore/debugBundle.js +143 -0
  269. package/dist/runstore/diskUsage.d.ts +50 -0
  270. package/dist/runstore/diskUsage.js +214 -0
  271. package/dist/runstore/exportRunPayload.d.ts +8 -0
  272. package/dist/runstore/exportRunPayload.js +23 -0
  273. package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
  274. package/dist/runstore/normalizeCatalogPath.js +10 -0
  275. package/dist/runstore/paths.d.ts +5 -0
  276. package/dist/runstore/paths.js +145 -1
  277. package/dist/runstore/port.d.ts +139 -13
  278. package/dist/runstore/port.js +8 -1
  279. package/dist/runstore/restore.d.ts +81 -0
  280. package/dist/runstore/restore.js +355 -0
  281. package/dist/runstore/retention.d.ts +27 -0
  282. package/dist/runstore/retention.js +74 -0
  283. package/dist/runstore/runManifest.d.ts +146 -0
  284. package/dist/runstore/runManifest.js +288 -0
  285. package/dist/runstore/runProjection.d.ts +3 -1
  286. package/dist/runstore/runProjection.js +63 -1
  287. package/dist/runstore/sqlite/SqliteRunStore.d.ts +35 -3
  288. package/dist/runstore/sqlite/SqliteRunStore.js +442 -219
  289. package/dist/runstore/sqlite/applyStorePragmas.d.ts +39 -0
  290. package/dist/runstore/sqlite/applyStorePragmas.js +145 -0
  291. package/dist/runstore/sqlite/migrations/001-baseline.d.ts +7 -0
  292. package/dist/runstore/sqlite/migrations/001-baseline.js +10 -0
  293. package/dist/runstore/sqlite/migrations/002-repository-binding.d.ts +7 -0
  294. package/dist/runstore/sqlite/migrations/002-repository-binding.js +29 -0
  295. package/dist/runstore/sqlite/migrations/003-run-lifecycle.d.ts +7 -0
  296. package/dist/runstore/sqlite/migrations/003-run-lifecycle.js +28 -0
  297. package/dist/runstore/sqlite/migrations/004-auto-resume-count.d.ts +7 -0
  298. package/dist/runstore/sqlite/migrations/004-auto-resume-count.js +19 -0
  299. package/dist/runstore/sqlite/migrations/005-config-origins.d.ts +7 -0
  300. package/dist/runstore/sqlite/migrations/005-config-origins.js +19 -0
  301. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.d.ts +7 -0
  302. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.js +28 -0
  303. package/dist/runstore/sqlite/migrations/007-projects-registry.d.ts +7 -0
  304. package/dist/runstore/sqlite/migrations/007-projects-registry.js +31 -0
  305. package/dist/runstore/sqlite/migrations/008-triggers-table.d.ts +7 -0
  306. package/dist/runstore/sqlite/migrations/008-triggers-table.js +19 -0
  307. package/dist/runstore/sqlite/migrations/009-trigger-next-run.d.ts +7 -0
  308. package/dist/runstore/sqlite/migrations/009-trigger-next-run.js +19 -0
  309. package/dist/runstore/sqlite/migrations/010-trigger-adapter-state.d.ts +7 -0
  310. package/dist/runstore/sqlite/migrations/010-trigger-adapter-state.js +17 -0
  311. package/dist/runstore/sqlite/migrations/index.d.ts +21 -0
  312. package/dist/runstore/sqlite/migrations/index.js +78 -0
  313. package/dist/runstore/sqlite/schema.d.ts +20 -1
  314. package/dist/runstore/sqlite/schema.js +277 -1
  315. package/dist/runstore/sqlite/storeOpenError.d.ts +6 -0
  316. package/dist/runstore/sqlite/storeOpenError.js +11 -0
  317. package/dist/runstore/sqlite/storeSchemaError.d.ts +5 -0
  318. package/dist/runstore/sqlite/storeSchemaError.js +8 -0
  319. package/dist/runstore/stageExecution.js +3 -0
  320. package/dist/runstore/storeFilesystem.d.ts +32 -0
  321. package/dist/runstore/storeFilesystem.js +148 -0
  322. package/dist/runstore/trackProjection.js +2 -0
  323. package/dist/runstore/workspaceLayout.d.ts +13 -0
  324. package/dist/runstore/workspaceLayout.js +76 -0
  325. package/dist/runtime/answerResume.d.ts +1 -0
  326. package/dist/runtime/answerResume.js +3 -1
  327. package/dist/runtime/completionCheckRunner.d.ts +15 -1
  328. package/dist/runtime/completionCheckRunner.js +67 -7
  329. package/dist/runtime/containerLimits.d.ts +16 -0
  330. package/dist/runtime/containerLimits.js +84 -0
  331. package/dist/runtime/credentialBinding.d.ts +2 -0
  332. package/dist/runtime/credentialBinding.js +3 -0
  333. package/dist/runtime/credentialMaterialisation.d.ts +28 -0
  334. package/dist/runtime/credentialMaterialisation.js +128 -0
  335. package/dist/runtime/emailSource.d.ts +72 -0
  336. package/dist/runtime/emailSource.js +304 -0
  337. package/dist/runtime/gitCheckoutCapability.js +7 -13
  338. package/dist/runtime/githubPollSource.d.ts +86 -0
  339. package/dist/runtime/githubPollSource.js +284 -0
  340. package/dist/runtime/pipelineRunner.d.ts +40 -1
  341. package/dist/runtime/pipelineRunner.js +181 -17
  342. package/dist/runtime/pipelineScheduler.d.ts +17 -0
  343. package/dist/runtime/pipelineScheduler.js +220 -28
  344. package/dist/runtime/reloadRunCatalog.js +6 -1
  345. package/dist/runtime/repositoryMaterialize.d.ts +47 -0
  346. package/dist/runtime/repositoryMaterialize.js +235 -0
  347. package/dist/runtime/resumeTimedOut.d.ts +1 -1
  348. package/dist/runtime/resumeTimedOut.js +5 -2
  349. package/dist/runtime/runChangeBus.js +9 -0
  350. package/dist/runtime/runDeletion.d.ts +7 -0
  351. package/dist/runtime/runDeletion.js +37 -0
  352. package/dist/runtime/runManager.d.ts +169 -4
  353. package/dist/runtime/runManager.js +1748 -83
  354. package/dist/runtime/runRetentionSweep.d.ts +31 -0
  355. package/dist/runtime/runRetentionSweep.js +328 -0
  356. package/dist/runtime/runRetryCoordinator.d.ts +4 -0
  357. package/dist/runtime/runRetryCoordinator.js +20 -2
  358. package/dist/runtime/runSkills.d.ts +40 -0
  359. package/dist/runtime/runSkills.js +173 -0
  360. package/dist/runtime/scheduleSource.d.ts +38 -0
  361. package/dist/runtime/scheduleSource.js +119 -0
  362. package/dist/runtime/settingsFile.d.ts +5 -0
  363. package/dist/runtime/settingsFile.js +61 -54
  364. package/dist/runtime/stageAttemptBootstrap.d.ts +5 -1
  365. package/dist/runtime/stageAttemptBootstrap.js +250 -27
  366. package/dist/runtime/stageCacheEnv.d.ts +6 -0
  367. package/dist/runtime/stageCacheEnv.js +34 -0
  368. package/dist/runtime/stageConcurrency.d.ts +2 -1
  369. package/dist/runtime/stageConcurrency.js +4 -2
  370. package/dist/runtime/stageEnvironment.d.ts +38 -0
  371. package/dist/runtime/stageEnvironment.js +194 -0
  372. package/dist/runtime/stageHitl.d.ts +1 -0
  373. package/dist/runtime/stageHitl.js +5 -1
  374. package/dist/runtime/stageProcessLauncher.d.ts +20 -0
  375. package/dist/runtime/stageProcessLauncher.js +236 -41
  376. package/dist/runtime/stageRecovery.d.ts +3 -1
  377. package/dist/runtime/stageRecovery.js +19 -4
  378. package/dist/runtime/stageRoots.d.ts +38 -1
  379. package/dist/runtime/stageRoots.js +118 -0
  380. package/dist/runtime/stageRunner.d.ts +6 -0
  381. package/dist/runtime/stageRunner.js +32 -6
  382. package/dist/runtime/stageSecretDecl.d.ts +9 -0
  383. package/dist/runtime/stageSecretDecl.js +102 -0
  384. package/dist/runtime/stageSecrets.d.ts +40 -0
  385. package/dist/runtime/stageSecrets.js +181 -0
  386. package/dist/runtime/stageStreamLog.d.ts +1 -0
  387. package/dist/runtime/stageStreamLog.js +2 -1
  388. package/dist/runtime/stageWorker.d.ts +3 -2
  389. package/dist/runtime/stageWorker.js +58 -10
  390. package/dist/runtime/stageWorkerProtocol.d.ts +5 -0
  391. package/dist/runtime/stageWorkerProtocol.js +8 -0
  392. package/dist/runtime/startPayload.d.ts +32 -0
  393. package/dist/runtime/startPayload.js +59 -0
  394. package/dist/runtime/taskInput.js +14 -5
  395. package/dist/runtime/triggerCatalog.d.ts +6 -0
  396. package/dist/runtime/triggerCatalog.js +24 -0
  397. package/dist/runtime/triggerEventMatch.d.ts +2 -0
  398. package/dist/runtime/triggerEventMatch.js +6 -0
  399. package/dist/runtime/triggerPort.d.ts +14 -0
  400. package/dist/runtime/triggerPort.js +1 -0
  401. package/dist/runtime/triggerRunner.d.ts +17 -0
  402. package/dist/runtime/triggerRunner.js +89 -0
  403. package/dist/runtime/verifiedStageExecution.d.ts +8 -0
  404. package/dist/runtime/verifiedStageExecution.js +16 -1
  405. package/dist/runtime/webhookSignature.d.ts +1 -0
  406. package/dist/runtime/webhookSignature.js +12 -0
  407. package/dist/runtime/workspaceBinding.d.ts +20 -0
  408. package/dist/runtime/workspaceBinding.js +60 -0
  409. package/dist/server/allowedHosts.d.ts +19 -0
  410. package/dist/server/allowedHosts.js +179 -0
  411. package/dist/server/bootstrap.d.ts +42 -2
  412. package/dist/server/bootstrap.js +273 -5
  413. package/dist/server/controlToken.d.ts +47 -0
  414. package/dist/server/controlToken.js +254 -0
  415. package/dist/server/createHttpHost.d.ts +11 -2
  416. package/dist/server/createHttpHost.js +106 -10
  417. package/dist/server/ensureGlobalService.d.ts +5 -1
  418. package/dist/server/ensureGlobalService.js +35 -1
  419. package/dist/server/healthSurfaces.d.ts +6 -0
  420. package/dist/server/healthSurfaces.js +123 -0
  421. package/dist/server/http.d.ts +27 -1
  422. package/dist/server/http.js +2254 -477
  423. package/dist/server/listenHost.d.ts +5 -0
  424. package/dist/server/listenHost.js +56 -0
  425. package/dist/server/mcpHost.d.ts +10 -1
  426. package/dist/server/mcpHost.js +36 -6
  427. package/dist/server/operatorResults.d.ts +2 -2
  428. package/dist/server/operatorResults.js +40 -29
  429. package/dist/server/requestAuthContext.d.ts +12 -0
  430. package/dist/server/requestAuthContext.js +21 -0
  431. package/dist/server/shutdown.d.ts +69 -0
  432. package/dist/server/shutdown.js +219 -0
  433. package/dist/server/triggerRoutes.d.ts +15 -0
  434. package/dist/server/triggerRoutes.js +268 -0
  435. package/dist/tools/askOperator.d.ts +3 -2
  436. package/dist/types/completion.d.ts +3 -0
  437. package/dist/types/pipeline.d.ts +10 -1
  438. package/dist/types/preEmitCheck.d.ts +7 -0
  439. package/dist/types/stage.d.ts +22 -0
  440. package/dist/types/stageflowManifest.d.ts +3 -0
  441. package/dist/types/task.d.ts +8 -0
  442. package/dist/types/trigger.d.ts +18 -0
  443. package/dist/types/trigger.js +1 -0
  444. package/dist/ui/assets/{index-CSsDued1.css → index-Bv4p1aPK.css} +1 -1
  445. package/dist/ui/assets/index-CntB4bZR.js +133 -0
  446. package/dist/ui/index.html +2 -2
  447. package/dist/workshop/autosave.d.ts +58 -0
  448. package/dist/workshop/autosave.js +222 -0
  449. package/dist/workshop/buildStore.d.ts +79 -0
  450. package/dist/workshop/buildStore.js +326 -0
  451. package/dist/workshop/chatTurn.d.ts +232 -0
  452. package/dist/workshop/chatTurn.js +475 -0
  453. package/dist/workshop/modelSettings.d.ts +18 -0
  454. package/dist/workshop/modelSettings.js +44 -0
  455. package/dist/workshop/sessionStore.d.ts +61 -0
  456. package/dist/workshop/sessionStore.js +254 -0
  457. package/dist/workshop/workshopPin.d.ts +72 -0
  458. package/dist/workshop/workshopPin.js +193 -0
  459. package/examples/README.md +99 -0
  460. package/examples/archify-on-pr/README.md +213 -0
  461. package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +19 -0
  462. package/examples/archify-on-pr/archify-on-pr.task.yaml +19 -0
  463. package/examples/archify-on-pr/author-diagrams.yaml +106 -0
  464. package/examples/archify-on-pr/detect-changes.yaml +89 -0
  465. package/examples/browser-session/README.md +77 -0
  466. package/examples/browser-session/browser-session.pipeline.yaml +50 -0
  467. package/examples/browser-session/browser-session.task.yaml +6 -0
  468. package/examples/browser-session/check-login.yaml +22 -0
  469. package/examples/browser-session/fixture-server.mjs +64 -0
  470. package/examples/browser-session/human-login.yaml +31 -0
  471. package/examples/browser-session/merge.yaml +36 -0
  472. package/examples/browser-session/work-a.yaml +41 -0
  473. package/examples/browser-session/work-b.yaml +41 -0
  474. package/examples/ci-validate/README.md +35 -0
  475. package/examples/ci-validate/check.yaml +13 -0
  476. package/examples/ci-validate/ci-demo.pipeline.yaml +4 -0
  477. package/examples/ci-validate/validate.sh +5 -0
  478. package/examples/compliance-review-demo/README.md +125 -0
  479. package/examples/compliance-review-demo/compliance-review-demo.pipeline.yaml +29 -0
  480. package/examples/compliance-review-demo/connect-account.yaml +47 -0
  481. package/examples/compliance-review-demo/map-to-control.yaml +123 -0
  482. package/examples/compliance-review-demo/poll-bucket-config.yaml +103 -0
  483. package/examples/compliance-review-demo/publish-report.yaml +79 -0
  484. package/examples/compliance-review-demo/review-verdict.yaml +122 -0
  485. package/examples/compliance-review-demo/run-compliance-check.yaml +96 -0
  486. package/examples/compliance-review-demo/store-evidence.yaml +143 -0
  487. package/examples/conditional-fork/README.md +89 -0
  488. package/examples/conditional-fork/branch-a.yaml +13 -0
  489. package/examples/conditional-fork/branch-b.yaml +13 -0
  490. package/examples/conditional-fork/decide.yaml +35 -0
  491. package/examples/conditional-fork/fork-demo.pipeline.yaml +20 -0
  492. package/examples/conditional-fork/fork-demo.task.yaml +8 -0
  493. package/examples/context7-mcp/README.md +42 -0
  494. package/examples/context7-mcp/context7-mcp.pipeline.yaml +15 -0
  495. package/examples/context7-mcp/context7-mcp.task.yaml +4 -0
  496. package/examples/context7-mcp/fetch-docs.yaml +52 -0
  497. package/examples/context7-mcp/resolve-library.yaml +31 -0
  498. package/examples/context7-mcp/write-brief.yaml +52 -0
  499. package/examples/feature-loop/README.md +104 -0
  500. package/examples/feature-loop/address-feedback.yaml +148 -0
  501. package/examples/feature-loop/align.yaml +116 -0
  502. package/examples/feature-loop/decompose.yaml +86 -0
  503. package/examples/feature-loop/default-model-hierarchy.task.yaml +58 -0
  504. package/examples/feature-loop/feature-loop.pipeline.yaml +140 -0
  505. package/examples/feature-loop/feature-loop.task.yaml +25 -0
  506. package/examples/feature-loop/implement.yaml +128 -0
  507. package/examples/feature-loop/plan.yaml +111 -0
  508. package/examples/feature-loop/publish.yaml +167 -0
  509. package/examples/feature-loop/review.yaml +146 -0
  510. package/examples/feature-loop/verify.yaml +106 -0
  511. package/examples/feedback-loop/README.md +72 -0
  512. package/examples/feedback-loop/VERIFY.md +208 -0
  513. package/examples/feedback-loop/continue-only.task.yaml +4 -0
  514. package/examples/feedback-loop/exhaust-require-continue.task.yaml +6 -0
  515. package/examples/feedback-loop/exhaust-wait-human.task.yaml +11 -0
  516. package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +23 -0
  517. package/examples/feedback-loop/feedback-loop.pipeline.yaml +23 -0
  518. package/examples/feedback-loop/feedback-loop.task.yaml +4 -0
  519. package/examples/feedback-loop/implement.yaml +14 -0
  520. package/examples/feedback-loop/plan.yaml +14 -0
  521. package/examples/feedback-loop/review.yaml +15 -0
  522. package/examples/feedback-loop/send-back-once.task.yaml +6 -0
  523. package/examples/feedback-loop/submit.yaml +12 -0
  524. package/examples/generic-fan-in/README.md +151 -0
  525. package/examples/generic-fan-in/clarify.yaml +18 -0
  526. package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +19 -0
  527. package/examples/generic-fan-in/generic-fan-in-accepted.task.yaml +8 -0
  528. package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +18 -0
  529. package/examples/generic-fan-in/generic-fan-in.task.yaml +9 -0
  530. package/examples/generic-fan-in/research.yaml +45 -0
  531. package/examples/generic-fan-in/synthesize.yaml +66 -0
  532. package/examples/generic-fan-in/validation.yaml +45 -0
  533. package/examples/github-release/README.md +78 -0
  534. package/examples/github-release/draft-release-notes.yaml +64 -0
  535. package/examples/github-release/github-release.pipeline.yaml +11 -0
  536. package/examples/github-release/github-release.task.yaml +13 -0
  537. package/examples/github-release/publish-github-release.yaml +64 -0
  538. package/examples/hello-world/README.md +28 -0
  539. package/examples/hello-world/hello.pipeline.yaml +4 -0
  540. package/examples/hello-world/my-task.task.yaml +6 -0
  541. package/examples/hello-world/research.yaml +18 -0
  542. package/examples/mcp-hitl-tour/README.md +113 -0
  543. package/examples/mcp-hitl-tour/draft-angle.yaml +33 -0
  544. package/examples/mcp-hitl-tour/draft-short.yaml +32 -0
  545. package/examples/mcp-hitl-tour/emit-angles.yaml +45 -0
  546. package/examples/mcp-hitl-tour/gather.yaml +31 -0
  547. package/examples/mcp-hitl-tour/intake.yaml +62 -0
  548. package/examples/mcp-hitl-tour/mcp-hitl-tour-exhaust.task.yaml +13 -0
  549. package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +54 -0
  550. package/examples/mcp-hitl-tour/mcp-hitl-tour.task.yaml +16 -0
  551. package/examples/mcp-hitl-tour/polish.yaml +33 -0
  552. package/examples/mcp-hitl-tour/review.yaml +17 -0
  553. package/examples/mcp-hitl-tour/ship.yaml +25 -0
  554. package/examples/oss-issue-contribution/README.md +218 -0
  555. package/examples/oss-issue-contribution/oss-address-review-feedback.yaml +117 -0
  556. package/examples/oss-issue-contribution/oss-approve-contribution.yaml +181 -0
  557. package/examples/oss-issue-contribution/oss-approve-plan.yaml +111 -0
  558. package/examples/oss-issue-contribution/oss-explain-fix.yaml +108 -0
  559. package/examples/oss-issue-contribution/oss-explain-issue.yaml +114 -0
  560. package/examples/oss-issue-contribution/oss-implement-source-fix.yaml +171 -0
  561. package/examples/oss-issue-contribution/oss-investigate-area.yaml +116 -0
  562. package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +125 -0
  563. package/examples/oss-issue-contribution/oss-issue-intake.yaml +106 -0
  564. package/examples/oss-issue-contribution/oss-plan-investigation.yaml +112 -0
  565. package/examples/oss-issue-contribution/oss-plan-review.yaml +109 -0
  566. package/examples/oss-issue-contribution/oss-reproduce-issue.yaml +140 -0
  567. package/examples/oss-issue-contribution/oss-review-change.yaml +107 -0
  568. package/examples/oss-issue-contribution/oss-verify-fix.yaml +130 -0
  569. package/examples/oss-issue-contribution/oss-write-regression-test.yaml +135 -0
  570. package/examples/oss-issue-contribution/pi-7629.task.yaml +79 -0
  571. package/examples/oss-issue-contribution/pi-8919.task.yaml +75 -0
  572. package/examples/oss-issue-contribution/pydantic-ai-7971.task.yaml +53 -0
  573. package/examples/oss-quick-fix/README.md +65 -0
  574. package/examples/oss-quick-fix/implement-fix.yaml +84 -0
  575. package/examples/oss-quick-fix/oss-quick-fix.pipeline.yaml +35 -0
  576. package/examples/oss-quick-fix/oss-quick-fix.task.yaml +19 -0
  577. package/examples/oss-quick-fix/ship-fix.yaml +81 -0
  578. package/examples/oss-quick-fix/understand-issue.yaml +67 -0
  579. package/examples/oss-quick-fix/verify-fix.yaml +73 -0
  580. package/examples/plan-review/README.md +37 -0
  581. package/examples/plan-review/plan-review-followup.yaml +13 -0
  582. package/examples/plan-review/plan-review.pipeline.yaml +9 -0
  583. package/examples/plan-review/plan-review.task.yaml +9 -0
  584. package/examples/plan-review/plan-review.yaml +25 -0
  585. package/examples/playwright-mcp/README.md +39 -0
  586. package/examples/playwright-mcp/playwright-mcp.pipeline.yaml +5 -0
  587. package/examples/playwright-mcp/playwright-mcp.task.yaml +4 -0
  588. package/examples/playwright-mcp/screenshot.yaml +40 -0
  589. package/examples/retry-tour/README.md +75 -0
  590. package/examples/retry-tour/retry-tour.pipeline.yaml +122 -0
  591. package/examples/retry-tour/retry-tour.task.yaml +9 -0
  592. package/examples/route-if-tour/README.md +202 -0
  593. package/examples/route-if-tour/route-if-tour.pipeline.yaml +950 -0
  594. package/examples/route-if-tour/route-if-tour.task.yaml +4 -0
  595. package/examples/route-wiring-smoke-test/01-core-routing.pipeline.yaml +168 -0
  596. package/examples/route-wiring-smoke-test/02-on-gating.pipeline.yaml +44 -0
  597. package/examples/route-wiring-smoke-test/03-two-entry-points.pipeline.yaml +28 -0
  598. package/examples/route-wiring-smoke-test/04-entry-false-equivalent-to-omitted.pipeline.yaml +27 -0
  599. package/examples/route-wiring-smoke-test/05-fork-choice.pipeline.yaml +110 -0
  600. package/examples/route-wiring-smoke-test/06-fan-out-fan-in.pipeline.yaml +82 -0
  601. package/examples/route-wiring-smoke-test/07-loop-human-decision.pipeline.yaml +82 -0
  602. package/examples/route-wiring-smoke-test/08-skip-fallback-and-multi-on-gate.pipeline.yaml +77 -0
  603. package/examples/route-wiring-smoke-test/09-multi-loop-targets.pipeline.yaml +102 -0
  604. package/examples/route-wiring-smoke-test/10-uses-dialect-fork.pipeline.yaml +23 -0
  605. package/examples/route-wiring-smoke-test/11-sequential-io-handoff.pipeline.yaml +37 -0
  606. package/examples/route-wiring-smoke-test/12-complex-io-schemas.pipeline.yaml +138 -0
  607. package/examples/route-wiring-smoke-test/13-ref-io-handoff.pipeline.yaml +84 -0
  608. package/examples/route-wiring-smoke-test/14-if-eq-gating.pipeline.yaml +50 -0
  609. package/examples/route-wiring-smoke-test/15-if-all-gated.pipeline.yaml +37 -0
  610. package/examples/route-wiring-smoke-test/16-if-composition.pipeline.yaml +65 -0
  611. package/examples/route-wiring-smoke-test/17-if-join.pipeline.yaml +80 -0
  612. package/examples/route-wiring-smoke-test/README.md +377 -0
  613. package/examples/route-wiring-smoke-test/rejected/01-reject-legacy-needs.pipeline.yaml +26 -0
  614. package/examples/route-wiring-smoke-test/rejected/02-reject-legacy-fork.pipeline.yaml +25 -0
  615. package/examples/route-wiring-smoke-test/rejected/03-reject-legacy-feedback-loop.pipeline.yaml +30 -0
  616. package/examples/route-wiring-smoke-test/rejected/04-reject-missing-entry.pipeline.yaml +24 -0
  617. package/examples/route-wiring-smoke-test/rejected/05-reject-unreachable.pipeline.yaml +35 -0
  618. package/examples/route-wiring-smoke-test/rejected/06-reject-allow-none-without-route-select.pipeline.yaml +37 -0
  619. package/examples/route-wiring-smoke-test/rejected/07-reject-cycle.pipeline.yaml +27 -0
  620. package/examples/route-wiring-smoke-test/rejected/08-reject-loop-non-ancestor.pipeline.yaml +42 -0
  621. package/examples/route-wiring-smoke-test/rejected/09-reject-route-select-leaf.pipeline.yaml +26 -0
  622. package/examples/route-wiring-smoke-test/rejected/12-reject-loop-replay-unsafe.pipeline.yaml +55 -0
  623. package/examples/route-wiring-smoke-test/rejected/13-reject-multiple-loop-entries.pipeline.yaml +51 -0
  624. package/examples/route-wiring-smoke-test/rejected/14-reject-duplicate-stage-id.pipeline.yaml +35 -0
  625. package/examples/route-wiring-smoke-test/rejected/15-reject-unknown-route-target.pipeline.yaml +15 -0
  626. package/examples/route-wiring-smoke-test/rejected/16-reject-malformed-route-item.pipeline.yaml +15 -0
  627. package/examples/route-wiring-smoke-test/rejected/17-reject-io-incompatible.pipeline.yaml +33 -0
  628. package/examples/route-wiring-smoke-test/rejected/18-reject-nested-io.pipeline.yaml +51 -0
  629. package/examples/route-wiring-smoke-test/rejected/19-reject-array-item-io.pipeline.yaml +55 -0
  630. package/examples/route-wiring-smoke-test/rejected/20-reject-closed-io.pipeline.yaml +36 -0
  631. package/examples/route-wiring-smoke-test/rejected/21-reject-ref-io.pipeline.yaml +42 -0
  632. package/examples/route-wiring-smoke-test/rejected/22-reject-if-unknown-field.pipeline.yaml +33 -0
  633. package/examples/route-wiring-smoke-test/rejected/23-reject-if-optional-field.pipeline.yaml +32 -0
  634. package/examples/route-wiring-smoke-test/rejected/24-reject-if-empty-all.pipeline.yaml +31 -0
  635. package/examples/route-wiring-smoke-test/rejected/25-reject-if-gt-on-string.pipeline.yaml +33 -0
  636. package/examples/route-wiring-smoke-test/rejected/26-reject-if-optional-nested.pipeline.yaml +36 -0
  637. package/examples/route-wiring-smoke-test/rejected/27-reject-if-on-loop.pipeline.yaml +63 -0
  638. package/examples/route-wiring-smoke-test/rejected/29-reject-if-on-failed.pipeline.yaml +46 -0
  639. package/examples/route-wiring-smoke-test/smoke-test.task.yaml +4 -0
  640. package/examples/route-wiring-smoke-test/stages/branch-a.yaml +12 -0
  641. package/examples/route-wiring-smoke-test/stages/branch-b.yaml +12 -0
  642. package/examples/route-wiring-smoke-test/stages/decide.yaml +12 -0
  643. package/examples/route-wiring-smoke-test/stages/finish.yaml +12 -0
  644. package/examples/ship-feature/README.md +190 -0
  645. package/examples/ship-feature/feat-address-feedback.yaml +119 -0
  646. package/examples/ship-feature/feat-implement.yaml +180 -0
  647. package/examples/ship-feature/feat-plan.yaml +120 -0
  648. package/examples/ship-feature/feat-review.yaml +109 -0
  649. package/examples/ship-feature/feat-ship.yaml +203 -0
  650. package/examples/ship-feature/ship-feature.pipeline.yaml +44 -0
  651. package/examples/ship-feature/ship-feature.task.yaml +78 -0
  652. package/examples/stage-mcp/README.md +145 -0
  653. package/examples/stage-mcp/echo-mcp.mjs +20 -0
  654. package/examples/stage-mcp/stage-mcp-dead.pipeline.yaml +5 -0
  655. package/examples/stage-mcp/stage-mcp-dead.task.yaml +3 -0
  656. package/examples/stage-mcp/stage-mcp-missing-var.pipeline.yaml +5 -0
  657. package/examples/stage-mcp/stage-mcp-missing-var.task.yaml +3 -0
  658. package/examples/stage-mcp/stage-mcp.pipeline.yaml +5 -0
  659. package/examples/stage-mcp/stage-mcp.task.yaml +4 -0
  660. package/examples/stage-mcp/use-echo.yaml +20 -0
  661. package/examples/stageflow.yaml +51 -0
  662. package/examples/verify-tour/README.md +80 -0
  663. package/examples/verify-tour/verify-tour.pipeline.yaml +162 -0
  664. package/examples/verify-tour/verify-tour.task.yaml +11 -0
  665. package/package.json +9 -1
  666. package/skills/stageflow/SKILL.md +6 -6
  667. package/skills/stageflow/references/control-surface.md +13 -5
  668. package/skills/stageflow/scripts/detect-host.mjs +14 -1
  669. package/skills/stageflow/scripts/detect-host.test.mjs +29 -1
  670. package/skills/stageflow-author/SKILL.md +4 -3
  671. package/skills/stageflow-author/references/catalog-mapping.md +16 -0
  672. package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
  673. package/skills/stageflow-author/references/stage-prompt-template.md +4 -4
  674. package/skills/stageflow-run/SKILL.md +22 -12
  675. package/skills/stageflow-run/references/mcp-call.md +9 -1
  676. package/skills/stageflow-run/references/task-and-pipeline-selection.md +19 -6
  677. package/skills/stageflow-run/scripts/mcp-call.mjs +46 -6
  678. package/skills/stageflow-run/scripts/mcp-call.test.mjs +64 -0
  679. package/skills/stageflow-session-capture/references/catalog-authoring.md +2 -0
  680. package/skills/stageflow-setup/SKILL.md +51 -8
  681. package/dist/ui/assets/index-Da5EHU6M.js +0 -119
@@ -0,0 +1,31 @@
1
+ import type { A2aStore } from "../a2a/store.js";
2
+ import { type RetentionWindows } from "../runstore/retention.js";
3
+ import type { RunStore } from "../runstore/port.js";
4
+ export type RetentionSweepReport = {
5
+ slimmed: string[];
6
+ purged: string[];
7
+ bareCachesEvicted: string[];
8
+ };
9
+ export type RunRetentionSweepOptions = {
10
+ now?: Date;
11
+ /** When false (default), compute candidates but skip mutating calls. */
12
+ execute?: boolean;
13
+ windows?: RetentionWindows;
14
+ env?: NodeJS.ProcessEnv;
15
+ artifactMaxBytes?: number;
16
+ bareCacheTtlMs?: number;
17
+ };
18
+ export declare function getSlimWalkCallCount(): number;
19
+ export declare function resetSlimWalkCallCount(): void;
20
+ /**
21
+ * Walk attempt + legacy artifact trees and remove SLIM-eligible paths.
22
+ * Never removes envelope.json, log.jsonl, or under-threshold artifacts.
23
+ */
24
+ export declare function slimRunWorkspaceArtifacts(workspaceDir: string, maxBytes: number): Promise<void>;
25
+ /**
26
+ * Two-stage retention: SLIM then PURGE, then bare-cache eviction.
27
+ * Dry-run (`execute: false`) computes the same candidates and skips mutations.
28
+ */
29
+ export declare function runRetentionSweep(store: RunStore, a2aStore: A2aStore | undefined, options?: RunRetentionSweepOptions): Promise<RetentionSweepReport>;
30
+ /** Test helper: expose bare-cache path resolution used by the eviction pass. */
31
+ export declare function bareCachePathForRepository(repository: string): string;
@@ -0,0 +1,328 @@
1
+ import { readdir, rm, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { bareCachePath } from "../git/cache.js";
4
+ import { globalStageflowHome } from "../project/globalHome.js";
5
+ import { bareCacheTtlFromEnv, isTerminalRunStatus, retentionDecision, retentionWindowsFromEnv, slimArtifactMaxBytesFromEnv, } from "../runstore/retention.js";
6
+ import { reclaimWorkspaceBinding, worktreePathForRun, } from "./repositoryMaterialize.js";
7
+ import { deleteRunEverywhere } from "./runDeletion.js";
8
+ const SLIM_ATTEMPT_FILES = ["pi-session.jsonl", "stream.log"];
9
+ const SLIM_ATTEMPT_DIRS = [".pi-agent"];
10
+ let slimWalkCallCount = 0;
11
+ export function getSlimWalkCallCount() {
12
+ return slimWalkCallCount;
13
+ }
14
+ export function resetSlimWalkCallCount() {
15
+ slimWalkCallCount = 0;
16
+ }
17
+ async function pathExists(target) {
18
+ try {
19
+ await stat(target);
20
+ return true;
21
+ }
22
+ catch (err) {
23
+ if (err.code === "ENOENT")
24
+ return false;
25
+ throw err;
26
+ }
27
+ }
28
+ async function rmForce(target) {
29
+ try {
30
+ await rm(target, { recursive: true, force: true });
31
+ }
32
+ catch (err) {
33
+ console.error(`runRetentionSweep: rm failed for ${target}: ${err instanceof Error ? err.message : String(err)}`);
34
+ }
35
+ }
36
+ async function removeOversizedArtifacts(artifactsDir, maxBytes) {
37
+ if (!(await pathExists(artifactsDir)))
38
+ return;
39
+ async function walk(current) {
40
+ let entries;
41
+ try {
42
+ entries = await readdir(current, { withFileTypes: true });
43
+ }
44
+ catch (err) {
45
+ if (err.code === "ENOENT")
46
+ return;
47
+ throw err;
48
+ }
49
+ for (const entry of entries) {
50
+ const full = path.join(current, entry.name);
51
+ if (entry.isDirectory()) {
52
+ await walk(full);
53
+ continue;
54
+ }
55
+ if (!entry.isFile())
56
+ continue;
57
+ let st;
58
+ try {
59
+ st = await stat(full);
60
+ }
61
+ catch (err) {
62
+ if (err.code === "ENOENT")
63
+ continue;
64
+ throw err;
65
+ }
66
+ if (st.size > maxBytes) {
67
+ await rmForce(full);
68
+ }
69
+ }
70
+ }
71
+ await walk(artifactsDir);
72
+ }
73
+ async function slimAttemptDir(attemptDir, maxBytes) {
74
+ for (const name of SLIM_ATTEMPT_DIRS) {
75
+ await rmForce(path.join(attemptDir, name));
76
+ }
77
+ for (const name of SLIM_ATTEMPT_FILES) {
78
+ await rmForce(path.join(attemptDir, name));
79
+ }
80
+ await removeOversizedArtifacts(path.join(attemptDir, "artifacts"), maxBytes);
81
+ }
82
+ /**
83
+ * Walk attempt + legacy artifact trees and remove SLIM-eligible paths.
84
+ * Never removes envelope.json, log.jsonl, or under-threshold artifacts.
85
+ */
86
+ export async function slimRunWorkspaceArtifacts(workspaceDir, maxBytes) {
87
+ slimWalkCallCount += 1;
88
+ const stagesRoot = path.join(workspaceDir, "stages");
89
+ if (!(await pathExists(stagesRoot)))
90
+ return;
91
+ let stageEntries;
92
+ try {
93
+ stageEntries = await readdir(stagesRoot, { withFileTypes: true });
94
+ }
95
+ catch (err) {
96
+ if (err.code === "ENOENT")
97
+ return;
98
+ throw err;
99
+ }
100
+ for (const stageEntry of stageEntries) {
101
+ if (!stageEntry.isDirectory())
102
+ continue;
103
+ const stageDir = path.join(stagesRoot, stageEntry.name);
104
+ const attemptsRoot = path.join(stageDir, "attempts");
105
+ if (await pathExists(attemptsRoot)) {
106
+ let attemptEntries;
107
+ try {
108
+ attemptEntries = await readdir(attemptsRoot, { withFileTypes: true });
109
+ }
110
+ catch (err) {
111
+ if (err.code === "ENOENT")
112
+ continue;
113
+ throw err;
114
+ }
115
+ for (const attemptEntry of attemptEntries) {
116
+ if (!attemptEntry.isDirectory())
117
+ continue;
118
+ await slimAttemptDir(path.join(attemptsRoot, attemptEntry.name), maxBytes);
119
+ }
120
+ }
121
+ await removeOversizedArtifacts(path.join(stageDir, "artifacts"), maxBytes);
122
+ }
123
+ }
124
+ async function slimOneRun(store, meta, now, artifactMaxBytes) {
125
+ try {
126
+ await reclaimWorkspaceBinding(meta, { keepRunBranch: true });
127
+ }
128
+ catch (err) {
129
+ console.error(`runRetentionSweep: worktree reclaim failed for ${meta.run_id}: ${err instanceof Error ? err.message : String(err)}`);
130
+ return false;
131
+ }
132
+ const workspaceDir = store.getWorkspaceDir(meta.run_id);
133
+ try {
134
+ await slimRunWorkspaceArtifacts(workspaceDir, artifactMaxBytes);
135
+ }
136
+ catch (err) {
137
+ console.error(`runRetentionSweep: artifact slim failed for ${meta.run_id}: ${err instanceof Error ? err.message : String(err)}`);
138
+ return false;
139
+ }
140
+ await store.setSlimmedAt(meta.run_id, now.toISOString());
141
+ return true;
142
+ }
143
+ async function listBareCachePaths(reposRoot) {
144
+ if (!(await pathExists(reposRoot)))
145
+ return [];
146
+ const out = [];
147
+ async function walk(current) {
148
+ let entries;
149
+ try {
150
+ entries = await readdir(current, { withFileTypes: true });
151
+ }
152
+ catch (err) {
153
+ if (err.code === "ENOENT")
154
+ return;
155
+ throw err;
156
+ }
157
+ for (const entry of entries) {
158
+ if (!entry.isDirectory())
159
+ continue;
160
+ const full = path.join(current, entry.name);
161
+ if (entry.name.endsWith(".git")) {
162
+ out.push(full);
163
+ }
164
+ else {
165
+ await walk(full);
166
+ }
167
+ }
168
+ }
169
+ await walk(reposRoot);
170
+ return out;
171
+ }
172
+ function repositoryForCachePath(cachePath) {
173
+ const reposRoot = path.join(globalStageflowHome(), "repos");
174
+ const rel = path.relative(reposRoot, cachePath);
175
+ if (rel.startsWith("..") || path.isAbsolute(rel))
176
+ return undefined;
177
+ const parts = rel.split(path.sep);
178
+ if (parts.length < 3)
179
+ return undefined;
180
+ const owner = parts[parts.length - 2];
181
+ const repoGit = parts[parts.length - 1];
182
+ if (!repoGit.endsWith(".git"))
183
+ return undefined;
184
+ return `${owner}/${repoGit.slice(0, -".git".length)}`;
185
+ }
186
+ function repositoryOf(run) {
187
+ if ("binding" in run && run.binding?.repository) {
188
+ return run.binding.repository;
189
+ }
190
+ if ("repository" in run && run.repository) {
191
+ return run.repository;
192
+ }
193
+ return undefined;
194
+ }
195
+ function runsForRepository(runs, repository) {
196
+ return runs.filter((r) => repositoryOf(r) === repository);
197
+ }
198
+ async function hasLiveWorktree(runs) {
199
+ for (const run of runs) {
200
+ const checkout = "checkout_root" in run && typeof run.checkout_root === "string"
201
+ ? run.checkout_root
202
+ : undefined;
203
+ const candidates = [
204
+ ...(checkout ? [checkout] : []),
205
+ worktreePathForRun(run.run_id),
206
+ ];
207
+ for (const candidate of candidates) {
208
+ if (candidate !== "" && (await pathExists(candidate)))
209
+ return true;
210
+ }
211
+ }
212
+ return false;
213
+ }
214
+ function allReferencingRunsPastBareTtl(runs, now, ttlMs) {
215
+ if (runs.length === 0)
216
+ return true;
217
+ for (const run of runs) {
218
+ if (!isTerminalRunStatus(run.status))
219
+ return false;
220
+ if (run.finished_at === undefined || run.finished_at === "")
221
+ return false;
222
+ const finishedMs = Date.parse(run.finished_at);
223
+ if (!Number.isFinite(finishedMs))
224
+ return false;
225
+ if (now.getTime() - finishedMs < ttlMs)
226
+ return false;
227
+ }
228
+ return true;
229
+ }
230
+ async function evictBareCaches(options) {
231
+ const reposRoot = path.join(globalStageflowHome(), "repos");
232
+ const caches = await listBareCachePaths(reposRoot);
233
+ const evicted = [];
234
+ for (const cachePath of caches) {
235
+ const repository = repositoryForCachePath(cachePath);
236
+ if (repository === undefined)
237
+ continue;
238
+ // Prefer store-based live-worktree check (cheaper than `git worktree list`).
239
+ const referencing = runsForRepository(options.runs, repository);
240
+ if (await hasLiveWorktree(referencing))
241
+ continue;
242
+ if (!allReferencingRunsPastBareTtl(referencing, options.now, options.ttlMs)) {
243
+ continue;
244
+ }
245
+ evicted.push(cachePath);
246
+ if (options.execute) {
247
+ await rmForce(cachePath);
248
+ }
249
+ }
250
+ return evicted;
251
+ }
252
+ /**
253
+ * Two-stage retention: SLIM then PURGE, then bare-cache eviction.
254
+ * Dry-run (`execute: false`) computes the same candidates and skips mutations.
255
+ */
256
+ export async function runRetentionSweep(store, a2aStore, options = {}) {
257
+ const now = options.now ?? new Date();
258
+ const execute = options.execute === true;
259
+ const env = options.env ?? process.env;
260
+ const windows = options.windows ?? retentionWindowsFromEnv(env);
261
+ const artifactMaxBytes = options.artifactMaxBytes ?? slimArtifactMaxBytesFromEnv(env);
262
+ const bareCacheTtlMs = options.bareCacheTtlMs ?? bareCacheTtlFromEnv(env);
263
+ const runs = await store.listRuns();
264
+ const slimmed = [];
265
+ const purged = [];
266
+ const metas = new Map();
267
+ async function metaFor(runId) {
268
+ let meta = metas.get(runId);
269
+ if (meta === undefined) {
270
+ meta = await store.readRunMeta(runId);
271
+ metas.set(runId, meta);
272
+ }
273
+ return meta;
274
+ }
275
+ // Decide from durable meta (status/finished_at/slimmed_at), not listRuns'
276
+ // derived status — stage rows can make a terminal run look "running".
277
+ const decisions = [];
278
+ for (const summary of runs) {
279
+ const meta = await metaFor(summary.run_id);
280
+ const decision = retentionDecision(meta, now, windows);
281
+ if (decision === "slim" || decision === "purge") {
282
+ decisions.push({ runId: summary.run_id, decision });
283
+ }
284
+ }
285
+ const purgeCandidates = decisions.filter((d) => d.decision === "purge");
286
+ if (execute && a2aStore === undefined && purgeCandidates.length > 0) {
287
+ throw new Error("runRetentionSweep: a2aStore is required when execute is true and PURGE candidates exist");
288
+ }
289
+ for (const { runId, decision } of decisions) {
290
+ if (decision !== "slim")
291
+ continue;
292
+ const meta = await metaFor(runId);
293
+ if (execute) {
294
+ const ok = await slimOneRun(store, meta, now, artifactMaxBytes);
295
+ if (!ok)
296
+ continue;
297
+ slimmed.push(runId);
298
+ metas.set(runId, {
299
+ ...meta,
300
+ slimmed_at: now.toISOString(),
301
+ });
302
+ }
303
+ else {
304
+ slimmed.push(runId);
305
+ }
306
+ }
307
+ for (const { runId, decision } of decisions) {
308
+ if (decision !== "purge")
309
+ continue;
310
+ purged.push(runId);
311
+ if (execute) {
312
+ await deleteRunEverywhere(store, a2aStore, runId);
313
+ }
314
+ }
315
+ // Re-list for bare-cache decisions after PURGE removed rows when execute.
316
+ const runsForBare = execute ? await store.listRuns() : runs;
317
+ const bareCachesEvicted = await evictBareCaches({
318
+ runs: runsForBare,
319
+ now,
320
+ ttlMs: bareCacheTtlMs,
321
+ execute,
322
+ });
323
+ return { slimmed, purged, bareCachesEvicted };
324
+ }
325
+ /** Test helper: expose bare-cache path resolution used by the eviction pass. */
326
+ export function bareCachePathForRepository(repository) {
327
+ return bareCachePath(repository);
328
+ }
@@ -3,6 +3,7 @@ import { type RunDetail, type RunPipelineDagSnapshot, type RunStatus, type RunSt
3
3
  import type { PipelineRunResult } from "./pipelineRunner.js";
4
4
  import { type SchedulerPreparedPipeline } from "./pipelineScheduler.js";
5
5
  import type { StageExecutionMode } from "./stageConcurrency.js";
6
+ import type { StageBrowserSupport } from "../browser/browserHost.js";
6
7
  import type { StageProcessLauncher } from "./stageProcessLauncher.js";
7
8
  import type { StageHitlController } from "./stageHitl.js";
8
9
  import type { OperatorCatalog } from "./stageAttemptBootstrap.js";
@@ -34,6 +35,7 @@ export type RetryStageResult = {
34
35
  ok: false;
35
36
  reason: string;
36
37
  status?: number;
38
+ code?: string;
37
39
  };
38
40
  export type RetryTrackingPort = {
39
41
  ensureResumeTracked(runId: string): Promise<{
@@ -57,6 +59,7 @@ export type RetryStageRequest = {
57
59
  agent: AgentPort;
58
60
  cwd: string;
59
61
  operatorCatalog?: OperatorCatalog;
62
+ browser?: StageBrowserSupport;
60
63
  maxActiveStagesPerRun: number;
61
64
  executionMode: StageExecutionMode;
62
65
  stageProcessLauncher?: StageProcessLauncher;
@@ -77,6 +80,7 @@ export declare function assertStageRetryEligible(detail: RunDetail, stageId: str
77
80
  ok: false;
78
81
  reason: string;
79
82
  status: number;
83
+ code: string;
80
84
  };
81
85
  export declare function readRetryRootWaitTimeoutMs(): number;
82
86
  export declare class RunRetryCoordinator {
@@ -37,6 +37,7 @@ export function assertStageRetryEligible(detail, stageId, opts) {
37
37
  ok: false,
38
38
  reason: `Stage not found: ${stageId}`,
39
39
  status: 404,
40
+ code: "stage_not_found",
40
41
  };
41
42
  }
42
43
  if (stageSnap.status === "waiting_for_input") {
@@ -44,6 +45,7 @@ export function assertStageRetryEligible(detail, stageId, opts) {
44
45
  ok: false,
45
46
  reason: `Stage is waiting for input and cannot be retried`,
46
47
  status: 409,
48
+ code: "hitl_not_retriable",
47
49
  };
48
50
  }
49
51
  const runStatus = opts?.persistedStatus ?? detail.status;
@@ -58,6 +60,7 @@ export function assertStageRetryEligible(detail, stageId, opts) {
58
60
  ok: false,
59
61
  reason: `Run is not failed or succeeded (status=${runStatus})`,
60
62
  status: 409,
63
+ code: "run_not_retryable",
61
64
  };
62
65
  }
63
66
  }
@@ -66,12 +69,18 @@ export function assertStageRetryEligible(detail, stageId, opts) {
66
69
  ok: false,
67
70
  reason: `Stage is not failed or succeeded (status=${stageSnap.status})`,
68
71
  status: 409,
72
+ code: "stage_not_failed",
69
73
  };
70
74
  }
71
75
  if (stageSnap.status === "succeeded") {
72
76
  const blocker = succeededStageRetryBlocker(stageSnap);
73
77
  if (blocker !== undefined) {
74
- return { ok: false, reason: blocker, status: 409 };
78
+ return {
79
+ ok: false,
80
+ reason: blocker,
81
+ status: 409,
82
+ code: "run_not_retryable",
83
+ };
75
84
  }
76
85
  }
77
86
  return { ok: true };
@@ -256,7 +265,12 @@ export class RunRetryCoordinator {
256
265
  dag = meta.pipeline_dag;
257
266
  }
258
267
  catch {
259
- return { ok: false, reason: `Run not found: ${runId}`, status: 404 };
268
+ return {
269
+ ok: false,
270
+ reason: `Run not found: ${runId}`,
271
+ status: 404,
272
+ code: "run_not_found",
273
+ };
260
274
  }
261
275
  const recoveryActive = this.isActive(runId);
262
276
  const eligibility = assertStageRetryEligible(detail, stageId, {
@@ -269,6 +283,7 @@ export class RunRetryCoordinator {
269
283
  ok: false,
270
284
  reason: eligibility.reason,
271
285
  status: eligibility.status,
286
+ code: eligibility.code,
272
287
  };
273
288
  }
274
289
  if (recoveryActive) {
@@ -277,6 +292,7 @@ export class RunRetryCoordinator {
277
292
  ok: false,
278
293
  reason: `Retry already in progress for run ${runId} stage ${stageId}`,
279
294
  status: 409,
295
+ code: "retry_in_progress",
280
296
  };
281
297
  }
282
298
  }
@@ -285,6 +301,7 @@ export class RunRetryCoordinator {
285
301
  ok: false,
286
302
  reason: `Run ${runId} already has active orchestration`,
287
303
  status: 409,
304
+ code: "run_not_retryable",
288
305
  };
289
306
  }
290
307
  const priorRunStatus = metaStatus;
@@ -327,6 +344,7 @@ export class RunRetryCoordinator {
327
344
  checkoutRoot: meta.checkout_root,
328
345
  hitl: req.hitl,
329
346
  operatorCatalog: req.operatorCatalog,
347
+ ...(req.browser !== undefined ? { browser: req.browser } : {}),
330
348
  };
331
349
  if (this.isActive(runId)) {
332
350
  await this.addRoot(runId, stageId, execution.attempt);
@@ -0,0 +1,40 @@
1
+ export declare const SKILLS_INVALID_NAME: "skills_invalid_name";
2
+ export declare const SKILLS_INVALID_PATH: "skills_invalid_path";
3
+ export declare const SKILLS_MISSING_SKILL_MD: "skills_missing_skill_md";
4
+ export declare const SKILLS_PAYLOAD_TOO_LARGE: "skills_payload_too_large";
5
+ export type SkillsPayloadErrorCode = typeof SKILLS_INVALID_NAME | typeof SKILLS_INVALID_PATH | typeof SKILLS_MISSING_SKILL_MD | typeof SKILLS_PAYLOAD_TOO_LARGE;
6
+ /** name → relativePath → utf-8 file contents */
7
+ export type SkillsPayload = Record<string, Record<string, string>>;
8
+ export type SkillsValidationOk = {
9
+ ok: true;
10
+ skills: SkillsPayload;
11
+ bytes: number;
12
+ };
13
+ export type SkillsValidationErr = {
14
+ ok: false;
15
+ code: SkillsPayloadErrorCode;
16
+ reason: string;
17
+ bytes?: number;
18
+ maxBytes?: number;
19
+ };
20
+ export type SkillsValidationResult = SkillsValidationOk | SkillsValidationErr;
21
+ export declare function runSkillsDir(workspaceDir: string): string;
22
+ export declare function skillPackDir(workspaceDir: string, skillName: string): string;
23
+ export declare function assertValidSkillName(name: string): {
24
+ ok: true;
25
+ } | {
26
+ ok: false;
27
+ reason: string;
28
+ };
29
+ export declare function assertValidSkillRelativePath(relPath: string): {
30
+ ok: true;
31
+ } | {
32
+ ok: false;
33
+ reason: string;
34
+ };
35
+ export declare function measureSkillsPayloadBytes(skills: SkillsPayload): number;
36
+ export declare function validateSkillsPayload(skills: unknown, options?: {
37
+ pipelineBytes?: number;
38
+ maxBytes?: number;
39
+ }): SkillsValidationResult;
40
+ export declare function materializeRunSkills(workspaceDir: string, skills: SkillsPayload): Promise<void>;
@@ -0,0 +1,173 @@
1
+ import { mkdir, realpath, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { START_PAYLOAD_MAX_BYTES } from "./startPayload.js";
4
+ import { isInsideDir } from "../runstore/workspaceLayout.js";
5
+ export const SKILLS_INVALID_NAME = "skills_invalid_name";
6
+ export const SKILLS_INVALID_PATH = "skills_invalid_path";
7
+ export const SKILLS_MISSING_SKILL_MD = "skills_missing_skill_md";
8
+ export const SKILLS_PAYLOAD_TOO_LARGE = "skills_payload_too_large";
9
+ const SKILL_MD = "SKILL.md";
10
+ export function runSkillsDir(workspaceDir) {
11
+ return path.join(workspaceDir, "skills");
12
+ }
13
+ export function skillPackDir(workspaceDir, skillName) {
14
+ return path.join(runSkillsDir(workspaceDir), skillName);
15
+ }
16
+ function hasForbiddenNameChars(name) {
17
+ return (name.includes("/") ||
18
+ name.includes("\\") ||
19
+ name.includes("\0") ||
20
+ name.includes("\u0000"));
21
+ }
22
+ function hasDotDotSegment(rel) {
23
+ const normalized = rel.replace(/\\/g, "/");
24
+ return normalized.split("/").some((segment) => segment === "..");
25
+ }
26
+ export function assertValidSkillName(name) {
27
+ if (typeof name !== "string" || name.length === 0) {
28
+ return { ok: false, reason: "Skill name must be a non-empty string" };
29
+ }
30
+ if (hasForbiddenNameChars(name)) {
31
+ return {
32
+ ok: false,
33
+ reason: `Skill name "${name}" must not contain "/", "\\\\", or NUL`,
34
+ };
35
+ }
36
+ if (path.isAbsolute(name) || hasDotDotSegment(name) || name === "..") {
37
+ return {
38
+ ok: false,
39
+ reason: `Skill name "${name}" must not be absolute or contain ".."`,
40
+ };
41
+ }
42
+ return { ok: true };
43
+ }
44
+ export function assertValidSkillRelativePath(relPath) {
45
+ if (typeof relPath !== "string" || relPath.length === 0) {
46
+ return { ok: false, reason: "Skill file path must be a non-empty string" };
47
+ }
48
+ if (path.isAbsolute(relPath) || hasDotDotSegment(relPath)) {
49
+ return {
50
+ ok: false,
51
+ reason: `Skill file path "${relPath}" must be relative and must not contain ".."`,
52
+ };
53
+ }
54
+ return { ok: true };
55
+ }
56
+ export function measureSkillsPayloadBytes(skills) {
57
+ let bytes = 0;
58
+ for (const files of Object.values(skills)) {
59
+ for (const content of Object.values(files)) {
60
+ bytes += Buffer.byteLength(content, "utf8");
61
+ }
62
+ }
63
+ return bytes;
64
+ }
65
+ export function validateSkillsPayload(skills, options) {
66
+ if (skills === undefined || skills === null) {
67
+ return { ok: true, skills: {}, bytes: 0 };
68
+ }
69
+ if (typeof skills !== "object" || Array.isArray(skills)) {
70
+ return {
71
+ ok: false,
72
+ code: SKILLS_INVALID_NAME,
73
+ reason: "skills must be a map of name → { relativePath: contents }",
74
+ };
75
+ }
76
+ const maxBytes = options?.maxBytes ?? START_PAYLOAD_MAX_BYTES;
77
+ const pipelineBytes = options?.pipelineBytes ?? 0;
78
+ const out = {};
79
+ for (const [name, files] of Object.entries(skills)) {
80
+ const nameCheck = assertValidSkillName(name);
81
+ if (!nameCheck.ok) {
82
+ return { ok: false, code: SKILLS_INVALID_NAME, reason: nameCheck.reason };
83
+ }
84
+ if (files === null || typeof files !== "object" || Array.isArray(files)) {
85
+ return {
86
+ ok: false,
87
+ code: SKILLS_MISSING_SKILL_MD,
88
+ reason: `Skill "${name}" must map to a files object including ${SKILL_MD}`,
89
+ };
90
+ }
91
+ const fileMap = {};
92
+ let hasSkillMd = false;
93
+ for (const [relPath, content] of Object.entries(files)) {
94
+ const pathCheck = assertValidSkillRelativePath(relPath);
95
+ if (!pathCheck.ok) {
96
+ return {
97
+ ok: false,
98
+ code: SKILLS_INVALID_PATH,
99
+ reason: pathCheck.reason,
100
+ };
101
+ }
102
+ if (typeof content !== "string") {
103
+ return {
104
+ ok: false,
105
+ code: SKILLS_INVALID_PATH,
106
+ reason: `Skill "${name}" file "${relPath}" content must be a UTF-8 string`,
107
+ };
108
+ }
109
+ if (relPath === SKILL_MD || relPath.replace(/\\/g, "/") === SKILL_MD) {
110
+ hasSkillMd = true;
111
+ }
112
+ fileMap[relPath] = content;
113
+ }
114
+ if (!hasSkillMd) {
115
+ return {
116
+ ok: false,
117
+ code: SKILLS_MISSING_SKILL_MD,
118
+ reason: `Skill "${name}" requires ${SKILL_MD}`,
119
+ };
120
+ }
121
+ out[name] = fileMap;
122
+ }
123
+ const bytes = measureSkillsPayloadBytes(out);
124
+ if (pipelineBytes + bytes > maxBytes) {
125
+ return {
126
+ ok: false,
127
+ code: SKILLS_PAYLOAD_TOO_LARGE,
128
+ reason: `Start payload (pipeline + skills) is ${pipelineBytes + bytes} bytes; max is ${maxBytes}`,
129
+ bytes: pipelineBytes + bytes,
130
+ maxBytes,
131
+ };
132
+ }
133
+ return { ok: true, skills: out, bytes };
134
+ }
135
+ export async function materializeRunSkills(workspaceDir, skills) {
136
+ if (Object.keys(skills).length === 0)
137
+ return;
138
+ const skillsRoot = runSkillsDir(workspaceDir);
139
+ await mkdir(skillsRoot, { recursive: true });
140
+ const skillsRootReal = await realpath(skillsRoot);
141
+ for (const [name, files] of Object.entries(skills)) {
142
+ const nameCheck = assertValidSkillName(name);
143
+ if (!nameCheck.ok) {
144
+ throw new Error(nameCheck.reason);
145
+ }
146
+ const destDir = skillPackDir(workspaceDir, name);
147
+ await mkdir(destDir, { recursive: true });
148
+ const destDirResolved = path.resolve(destDir);
149
+ if (!isInsideDir(destDirResolved, path.resolve(skillsRoot))) {
150
+ throw new Error(`Skill "${name}" destination escapes run skills directory`);
151
+ }
152
+ const destDirReal = await realpath(destDir);
153
+ if (!isInsideDir(destDirReal, skillsRootReal)) {
154
+ throw new Error(`Skill "${name}" destination realpath escapes run skills directory`);
155
+ }
156
+ for (const [relPath, content] of Object.entries(files)) {
157
+ const pathCheck = assertValidSkillRelativePath(relPath);
158
+ if (!pathCheck.ok) {
159
+ throw new Error(pathCheck.reason);
160
+ }
161
+ const dest = path.resolve(destDir, relPath);
162
+ if (!isInsideDir(dest, destDirResolved)) {
163
+ throw new Error(`Skill "${name}" file "${relPath}" escapes skill pack directory`);
164
+ }
165
+ await mkdir(path.dirname(dest), { recursive: true });
166
+ await writeFile(dest, content, "utf8");
167
+ const fileReal = await realpath(dest);
168
+ if (!isInsideDir(fileReal, destDirReal)) {
169
+ throw new Error(`Skill "${name}" file "${relPath}" realpath escapes skill pack directory`);
170
+ }
171
+ }
172
+ }
173
+ }