firedrill-run 2.2.5 → 3.0.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 (392) hide show
  1. package/README.md +178 -22
  2. package/bin/firedrill.mjs +29 -5
  3. package/dist/assembly.json +13 -0
  4. package/dist/cli/runtime/candidate_copy.py +395 -0
  5. package/dist/cli/runtime/source_snapshot.py +391 -0
  6. package/dist/cli/src/administration.js +295 -0
  7. package/dist/cli/src/agent-changes.js +496 -0
  8. package/dist/cli/src/assessment-requests.js +67 -0
  9. package/dist/cli/src/auth.js +465 -0
  10. package/dist/cli/src/billing-commerce-contracts.js +1 -0
  11. package/dist/cli/src/billing-usage.js +227 -0
  12. package/dist/cli/src/billing-wallet-contracts.js +1 -0
  13. package/dist/cli/src/billing.js +170 -0
  14. package/dist/cli/src/bootstrap-process-lock.js +136 -0
  15. package/dist/cli/src/browser-links.js +14 -0
  16. package/dist/cli/src/campaign-controls.js +122 -0
  17. package/dist/cli/src/campaign-diagnoses.js +118 -0
  18. package/dist/cli/src/campaign-reports.js +1215 -0
  19. package/dist/cli/src/campaign-world.js +156 -0
  20. package/dist/cli/src/candidate-copy.js +376 -0
  21. package/dist/cli/src/catalog-contracts.js +1 -0
  22. package/dist/cli/src/ci-access-contracts.js +1 -0
  23. package/dist/cli/src/ci-configuration-contracts.js +1 -0
  24. package/dist/cli/src/ci-coverage.js +64 -0
  25. package/dist/cli/src/ci-delivery-contracts.js +1 -0
  26. package/dist/cli/src/ci-result-contracts.js +1 -0
  27. package/dist/cli/src/ci-run-contracts.js +1 -0
  28. package/dist/cli/src/ci-setup-proposals.js +52 -0
  29. package/dist/cli/src/company-policies.js +229 -0
  30. package/dist/cli/src/completion.js +79 -0
  31. package/dist/cli/src/configuration-intents.js +277 -0
  32. package/dist/cli/src/configuration.js +369 -0
  33. package/dist/cli/src/continuous-simulation.js +277 -0
  34. package/dist/cli/src/coordinated-checkpoints.js +133 -0
  35. package/dist/cli/src/credential-mode.js +139 -0
  36. package/dist/cli/src/credentials.js +331 -0
  37. package/dist/cli/src/credit-format.js +8 -0
  38. package/dist/cli/src/dataset-contracts.js +1 -0
  39. package/dist/cli/src/dataset-export.js +154 -0
  40. package/dist/cli/src/dataset-reads.js +37 -0
  41. package/dist/cli/src/dependency-preparation.js +239 -0
  42. package/dist/cli/src/director-tool-setup.js +104 -0
  43. package/dist/cli/src/driver-review.js +225 -0
  44. package/dist/cli/src/evaluation-authoring.js +315 -0
  45. package/dist/cli/src/evidence-bundles.js +367 -0
  46. package/dist/cli/src/execution-proposals.js +36 -0
  47. package/dist/cli/src/http.js +302 -0
  48. package/dist/cli/src/local-container-boundary.js +38 -0
  49. package/dist/cli/src/local-container-policy.js +201 -0
  50. package/dist/cli/src/local-execution-setup.js +81 -0
  51. package/dist/cli/src/local-source-basis.js +73 -0
  52. package/dist/cli/src/local-source.js +66 -0
  53. package/dist/cli/src/local-value-store.js +91 -0
  54. package/dist/cli/src/local-values.js +163 -0
  55. package/dist/cli/src/login-organizations.js +70 -0
  56. package/dist/cli/src/main.js +1622 -0
  57. package/dist/cli/src/mcp-connection.js +109 -0
  58. package/dist/cli/src/native/bindings.js +137 -0
  59. package/dist/cli/src/native/canonical.js +370 -0
  60. package/dist/cli/src/native/cloud-resources.js +942 -0
  61. package/dist/cli/src/native/companion-channel.js +421 -0
  62. package/dist/cli/src/native/companion-ipc.js +473 -0
  63. package/dist/cli/src/native/contracts.js +218 -0
  64. package/dist/cli/src/native/control-plane.js +1354 -0
  65. package/dist/cli/src/native/credit-approval.js +15 -0
  66. package/dist/cli/src/native/dependency-proxy.js +1006 -0
  67. package/dist/cli/src/native/drill-cleanup.js +115 -0
  68. package/dist/cli/src/native/drill-runner.js +1562 -0
  69. package/dist/cli/src/native/drivers/action-trace.js +210 -0
  70. package/dist/cli/src/native/drivers/function-wrapper.js +152 -0
  71. package/dist/cli/src/native/drivers/http.js +442 -0
  72. package/dist/cli/src/native/drivers/index.js +47 -0
  73. package/dist/cli/src/native/drivers/jsonl-process.js +538 -0
  74. package/dist/cli/src/native/drivers/playwright.js +600 -0
  75. package/dist/cli/src/native/drivers/signed-event.js +244 -0
  76. package/dist/cli/src/native/drivers/types.js +578 -0
  77. package/dist/cli/src/native/evidence-filter.js +255 -0
  78. package/dist/cli/src/native/isolated-access.js +241 -0
  79. package/dist/cli/src/native/library-sharing.js +220 -0
  80. package/dist/cli/src/native/local-run.js +667 -0
  81. package/dist/cli/src/native/local-secrets.js +19 -0
  82. package/dist/cli/src/native/mcp-config.js +123 -0
  83. package/dist/cli/src/native/metadata-requests.js +120 -0
  84. package/dist/cli/src/native/observations.js +1159 -0
  85. package/dist/cli/src/native/owned-groups.js +46 -0
  86. package/dist/cli/src/native/plan.js +594 -0
  87. package/dist/cli/src/native/png.js +159 -0
  88. package/dist/cli/src/native/ports.js +43 -0
  89. package/dist/cli/src/native/readiness.js +139 -0
  90. package/dist/cli/src/native/reassessments.js +206 -0
  91. package/dist/cli/src/native/redaction.js +235 -0
  92. package/dist/cli/src/native/registration.js +155 -0
  93. package/dist/cli/src/native/roots.js +110 -0
  94. package/dist/cli/src/native/run-cleanup.js +199 -0
  95. package/dist/cli/src/native/scratch.js +117 -0
  96. package/dist/cli/src/native/screenshots.js +60 -0
  97. package/dist/cli/src/native/session.js +556 -0
  98. package/dist/cli/src/native/standalone-proxy.js +580 -0
  99. package/dist/cli/src/native/standalone-renewals.js +183 -0
  100. package/dist/cli/src/native/standalone-state.js +193 -0
  101. package/dist/cli/src/native/standalone-tools.js +187 -0
  102. package/dist/cli/src/native/supervisor.js +831 -0
  103. package/dist/cli/src/native/target-auth.js +161 -0
  104. package/dist/cli/src/native/target-state.js +330 -0
  105. package/dist/cli/src/native/tool-reuse.js +364 -0
  106. package/dist/cli/src/native/tool-setups.js +336 -0
  107. package/dist/cli/src/native/world-reuse.js +288 -0
  108. package/dist/cli/src/onboarding.js +23 -0
  109. package/dist/cli/src/priority-requests.js +70 -0
  110. package/dist/cli/src/priority.js +223 -0
  111. package/dist/cli/src/prompts.js +184 -0
  112. package/dist/cli/src/real-operations.js +221 -0
  113. package/dist/cli/src/recipe-intents.js +58 -0
  114. package/dist/cli/src/recorded-context-intents.js +59 -0
  115. package/dist/cli/src/recorded-context.js +248 -0
  116. package/dist/cli/src/recordings.js +69 -0
  117. package/dist/cli/src/registration-guide.js +39 -0
  118. package/dist/cli/src/report-exports.js +213 -0
  119. package/dist/cli/src/request-input.js +47 -0
  120. package/dist/cli/src/resource-lifecycle.js +141 -0
  121. package/dist/cli/src/revision-requests.js +55 -0
  122. package/dist/cli/src/runner-abandon.js +53 -0
  123. package/dist/cli/src/runner-campaign-controls.js +262 -0
  124. package/dist/cli/src/runner-claim-reads.js +36 -0
  125. package/dist/cli/src/runner-completion.js +65 -0
  126. package/dist/cli/src/runner-configuration.js +546 -0
  127. package/dist/cli/src/runner-container.js +794 -0
  128. package/dist/cli/src/runner-evidence-erasure.js +351 -0
  129. package/dist/cli/src/runner-evidence-privacy.js +37 -0
  130. package/dist/cli/src/runner-evidence-retention.js +161 -0
  131. package/dist/cli/src/runner-evidence.js +326 -0
  132. package/dist/cli/src/runner-execute.js +92 -0
  133. package/dist/cli/src/runner-execution-deadline.js +25 -0
  134. package/dist/cli/src/runner-grants.js +307 -0
  135. package/dist/cli/src/runner-identity.js +615 -0
  136. package/dist/cli/src/runner-inputs.js +308 -0
  137. package/dist/cli/src/runner-jobs.js +49 -0
  138. package/dist/cli/src/runner-model-transport.js +392 -0
  139. package/dist/cli/src/runner-ownership.js +332 -0
  140. package/dist/cli/src/runner-process-lock.js +175 -0
  141. package/dist/cli/src/runner-runtime.js +396 -0
  142. package/dist/cli/src/runner-session-channel.js +377 -0
  143. package/dist/cli/src/runner-trial-completion.js +34 -0
  144. package/dist/cli/src/runner-trial-journal.js +358 -0
  145. package/dist/cli/src/runner-trial-live.js +393 -0
  146. package/dist/cli/src/runner-trial-protocol.js +289 -0
  147. package/dist/cli/src/runner-trial-sync.js +110 -0
  148. package/dist/cli/src/runner-trial-transfer.js +107 -0
  149. package/dist/cli/src/runner-voice.js +40 -0
  150. package/dist/cli/src/runner-world-claim.js +21 -0
  151. package/dist/cli/src/runner-world-collector.js +159 -0
  152. package/dist/cli/src/runner-world-command-evidence.js +487 -0
  153. package/dist/cli/src/runner-world-commands.js +268 -0
  154. package/dist/cli/src/runner-world-completion.js +76 -0
  155. package/dist/cli/src/runner-world-erasure.js +95 -0
  156. package/dist/cli/src/runner-world-evidence-sync.js +91 -0
  157. package/dist/cli/src/runner-world-journal.js +510 -0
  158. package/dist/cli/src/runner-world-native-filters.js +134 -0
  159. package/dist/cli/src/runner-world-observations.js +50 -0
  160. package/dist/cli/src/runner-world-session-protocol.js +134 -0
  161. package/dist/cli/src/saved-records.js +40 -0
  162. package/dist/cli/src/scenario-authoring.js +212 -0
  163. package/dist/cli/src/scenario-discovery.js +216 -0
  164. package/dist/cli/src/scenario-paths.js +68 -0
  165. package/dist/cli/src/scenario-requests.js +4 -0
  166. package/dist/cli/src/service-receipts.js +105 -0
  167. package/dist/cli/src/simple/authoring.js +270 -0
  168. package/dist/cli/src/simple/credit-approval.js +16 -0
  169. package/dist/cli/src/simple/help.js +98 -0
  170. package/dist/cli/src/simple/init.js +61 -0
  171. package/dist/cli/src/simple/library-sharing.js +414 -0
  172. package/dist/cli/src/simple/metadata-requests.js +46 -0
  173. package/dist/cli/src/simple/native-report.js +841 -0
  174. package/dist/cli/src/simple/native-tools.js +780 -0
  175. package/dist/cli/src/simple/plan-apply.js +506 -0
  176. package/dist/cli/src/simple/reassessment.js +323 -0
  177. package/dist/cli/src/simple/register.js +123 -0
  178. package/dist/cli/src/simple/run.js +122 -0
  179. package/dist/cli/src/simple/status.js +49 -0
  180. package/dist/cli/src/simple/tool-renewal.js +308 -0
  181. package/dist/cli/src/simple/tool-reuse.js +526 -0
  182. package/dist/cli/src/simple/tool-start-catalog.js +100 -0
  183. package/dist/cli/src/simple/tool-state.js +426 -0
  184. package/dist/cli/src/simple/tools-author.js +222 -0
  185. package/dist/cli/src/simple/watch.js +28 -0
  186. package/dist/cli/src/simple/world-reuse.js +586 -0
  187. package/dist/cli/src/simulation-intents.js +406 -0
  188. package/dist/cli/src/simulation-run.js +1058 -0
  189. package/dist/cli/src/source-batch.js +322 -0
  190. package/dist/cli/src/source-connection.js +451 -0
  191. package/dist/cli/src/source-runtime.js +346 -0
  192. package/dist/cli/src/source-selection-intents.js +75 -0
  193. package/dist/cli/src/source-sets.js +214 -0
  194. package/dist/cli/src/target-models.js +109 -0
  195. package/dist/cli/src/tool-catalog.js +224 -0
  196. package/dist/cli/src/tool-command-contracts.js +1 -0
  197. package/dist/cli/src/tool-command-export.js +245 -0
  198. package/dist/cli/src/tool-connection-contracts.js +1 -0
  199. package/dist/cli/src/tool-connection-reads.js +23 -0
  200. package/dist/cli/src/tool-contributions.js +58 -0
  201. package/dist/cli/src/tool-data.js +116 -0
  202. package/dist/cli/src/tool-datasets.js +176 -0
  203. package/dist/cli/src/tool-group-contracts.js +1 -0
  204. package/dist/cli/src/tool-group-reads.js +26 -0
  205. package/dist/cli/src/tool-group-state.js +147 -0
  206. package/dist/cli/src/tool-groups.js +311 -0
  207. package/dist/cli/src/tool-instances.js +186 -0
  208. package/dist/cli/src/tool-lifecycle-contracts.js +1 -0
  209. package/dist/cli/src/tool-lifecycle-reads.js +30 -0
  210. package/dist/cli/src/tool-lifecycle.js +323 -0
  211. package/dist/cli/src/tool-package-contracts.js +1 -0
  212. package/dist/cli/src/tool-package-reads.js +41 -0
  213. package/dist/cli/src/tool-records.js +53 -0
  214. package/dist/cli/src/tool-runtime.js +96 -0
  215. package/dist/cli/src/tool-state-contracts.js +1 -0
  216. package/dist/cli/src/tool-state-reads.js +31 -0
  217. package/dist/cli/src/tools.js +306 -0
  218. package/dist/cli/src/trial-actions.js +93 -0
  219. package/dist/cli/src/trial-checkpoints.js +133 -0
  220. package/dist/cli/src/trial-checks.js +70 -0
  221. package/dist/cli/src/trial-state.js +197 -0
  222. package/dist/cli/src/vault.js +266 -0
  223. package/dist/cli/src/workspace-registration.js +383 -0
  224. package/dist/cli/src/workspace-team-contracts.js +1 -0
  225. package/dist/cli/src/world-access.js +231 -0
  226. package/dist/cli/src/world-agent.js +4 -0
  227. package/dist/cli/src/world-checkpoint-scopes.js +15 -0
  228. package/dist/cli/src/world-contracts.js +6 -0
  229. package/dist/cli/src/world-creation.js +201 -0
  230. package/dist/cli/src/world-datasets.js +207 -0
  231. package/dist/cli/src/world-inspection.js +257 -0
  232. package/dist/cli/src/world-recipes.js +103 -0
  233. package/dist/cli/src/world-requests.js +241 -0
  234. package/dist/cli/src/world-session-checkpoints.js +196 -0
  235. package/dist/cli/src/world-session-lifecycle.js +207 -0
  236. package/dist/cli/src/world-session-requests.js +215 -0
  237. package/dist/cli/src/world-session-state.js +145 -0
  238. package/dist/cli/src/world-session-voice.js +66 -0
  239. package/dist/cli/src/world-sessions.js +288 -0
  240. package/dist/cli/src/world-stream.js +99 -0
  241. package/dist/cli/src/world-time-report.js +58 -0
  242. package/dist/contracts/agent-change-contracts.js +75 -0
  243. package/dist/contracts/agent-execution-contracts.js +38 -0
  244. package/dist/contracts/application-state-contracts.js +26 -0
  245. package/dist/contracts/assessment-aggregate-contracts.js +15 -0
  246. package/dist/contracts/assessment-contracts.js +74 -0
  247. package/dist/contracts/billing-commerce-contracts.js +107 -0
  248. package/dist/contracts/billing-wallet-contracts.js +43 -0
  249. package/dist/contracts/campaign-lifecycle.js +1 -0
  250. package/dist/contracts/campaign-world-contracts.js +80 -0
  251. package/dist/contracts/catalog-contracts.js +73 -0
  252. package/dist/contracts/ci-access-contracts.js +68 -0
  253. package/dist/contracts/ci-configuration-contracts.js +88 -0
  254. package/dist/contracts/ci-coverage-contracts.js +65 -0
  255. package/dist/contracts/ci-coverage-labels.js +25 -0
  256. package/dist/contracts/ci-delivery-contracts.js +61 -0
  257. package/dist/contracts/ci-result-contracts.js +103 -0
  258. package/dist/contracts/ci-run-contracts.js +51 -0
  259. package/dist/contracts/ci-setup-contracts.js +88 -0
  260. package/dist/contracts/clip-contracts.js +32 -0
  261. package/dist/contracts/comparison-contracts.js +53 -0
  262. package/dist/contracts/composite-contracts.js +34 -0
  263. package/dist/contracts/context-contracts.js +76 -0
  264. package/dist/contracts/continuation-report-contracts.js +1 -0
  265. package/dist/contracts/continuity-requirements.js +8 -0
  266. package/dist/contracts/coordinated-checkpoint-contracts.js +34 -0
  267. package/dist/contracts/dataset-contracts.js +88 -0
  268. package/dist/contracts/dependency-decision-contracts.js +36 -0
  269. package/dist/contracts/dependency-protocol-contracts.js +43 -0
  270. package/dist/contracts/director-execution.js +51 -0
  271. package/dist/contracts/driver-review-contracts.js +99 -0
  272. package/dist/contracts/evidence-contracts.js +65 -0
  273. package/dist/contracts/evidence-coverage-contracts.js +10 -0
  274. package/dist/contracts/export-contracts.js +44 -0
  275. package/dist/contracts/github-directory-contracts.js +96 -0
  276. package/dist/contracts/insight-contracts.js +11 -0
  277. package/dist/contracts/inspection-contracts.js +1 -0
  278. package/dist/contracts/local-claim-contracts.js +39 -0
  279. package/dist/contracts/local-configuration-contracts.js +7 -0
  280. package/dist/contracts/local-evidence-contracts.js +32 -0
  281. package/dist/contracts/local-grant-contracts.js +83 -0
  282. package/dist/contracts/local-input-contracts.js +19 -0
  283. package/dist/contracts/local-runner-contracts.js +42 -0
  284. package/dist/contracts/local-trial-live-contracts.js +16 -0
  285. package/dist/contracts/local-value-source-contracts.js +92 -0
  286. package/dist/contracts/local-world-native-contracts.js +8 -0
  287. package/dist/contracts/mcp-contracts.js +42 -0
  288. package/dist/contracts/media-contracts.js +28 -0
  289. package/dist/contracts/native-check-contracts.js +31 -0
  290. package/dist/contracts/native-identity-contracts.js +52 -0
  291. package/dist/contracts/onboarding-contracts.js +32 -0
  292. package/dist/contracts/performance-contracts.js +85 -0
  293. package/dist/contracts/planning-contracts.js +81 -0
  294. package/dist/contracts/real-operation-contracts.js +30 -0
  295. package/dist/contracts/recommendation-contracts.js +54 -0
  296. package/dist/contracts/report-contracts.js +1 -0
  297. package/dist/contracts/resource-lifecycle-contracts.js +57 -0
  298. package/dist/contracts/revision-contracts.js +12 -0
  299. package/dist/contracts/revision-request-contracts.js +39 -0
  300. package/dist/contracts/saved-record-contracts.js +76 -0
  301. package/dist/contracts/scenario-draft-comparison.js +91 -0
  302. package/dist/contracts/scenario-world-contracts.js +14 -0
  303. package/dist/contracts/service-contracts.js +1 -0
  304. package/dist/contracts/session-command-contracts.js +56 -0
  305. package/dist/contracts/session-contracts.js +65 -0
  306. package/dist/contracts/session-state-contracts.js +67 -0
  307. package/dist/contracts/session-voice-contracts.js +45 -0
  308. package/dist/contracts/source-set-contracts.js +26 -0
  309. package/dist/contracts/source-upload-contracts.js +22 -0
  310. package/dist/contracts/tool-command-contracts.js +57 -0
  311. package/dist/contracts/tool-connection-contracts.js +87 -0
  312. package/dist/contracts/tool-contribution-contracts.js +35 -0
  313. package/dist/contracts/tool-group-contracts.js +53 -0
  314. package/dist/contracts/tool-group-state-contracts.js +63 -0
  315. package/dist/contracts/tool-lifecycle-contracts.js +94 -0
  316. package/dist/contracts/tool-package-contracts.js +91 -0
  317. package/dist/contracts/tool-protocol-contracts.js +71 -0
  318. package/dist/contracts/tool-runtime-billing-contracts.js +28 -0
  319. package/dist/contracts/tool-setup-proposal.js +59 -0
  320. package/dist/contracts/tool-state-contracts.js +79 -0
  321. package/dist/contracts/trial-state-contracts.js +30 -0
  322. package/dist/contracts/typescript/agent-change.js +1 -0
  323. package/dist/contracts/typescript/assessment-aggregate.js +1 -0
  324. package/dist/contracts/typescript/assessment.js +1 -0
  325. package/dist/contracts/typescript/billing-commerce.js +1 -0
  326. package/dist/contracts/typescript/campaigns.js +1 -0
  327. package/dist/contracts/typescript/catalog.js +1 -0
  328. package/dist/contracts/typescript/ci-access.js +1 -0
  329. package/dist/contracts/typescript/ci-configuration.js +1 -0
  330. package/dist/contracts/typescript/ci-delivery.js +1 -0
  331. package/dist/contracts/typescript/ci-result.js +1 -0
  332. package/dist/contracts/typescript/ci-runs.js +1 -0
  333. package/dist/contracts/typescript/clips.js +1 -0
  334. package/dist/contracts/typescript/comparison.js +1 -0
  335. package/dist/contracts/typescript/composite.js +1 -0
  336. package/dist/contracts/typescript/connections.js +1 -0
  337. package/dist/contracts/typescript/context.js +1 -0
  338. package/dist/contracts/typescript/datasets.js +1 -0
  339. package/dist/contracts/typescript/evidence-coverage.js +1 -0
  340. package/dist/contracts/typescript/export.js +1 -0
  341. package/dist/contracts/typescript/github-directory.js +1 -0
  342. package/dist/contracts/typescript/insight.js +1 -0
  343. package/dist/contracts/typescript/inspection.js +1 -0
  344. package/dist/contracts/typescript/intake.js +1 -0
  345. package/dist/contracts/typescript/local-claim.js +1 -0
  346. package/dist/contracts/typescript/local-configuration.js +1 -0
  347. package/dist/contracts/typescript/local-evidence.js +1 -0
  348. package/dist/contracts/typescript/local-grant.js +1 -0
  349. package/dist/contracts/typescript/local-input.js +1 -0
  350. package/dist/contracts/typescript/local-runner.js +1 -0
  351. package/dist/contracts/typescript/local-trial-live.js +1 -0
  352. package/dist/contracts/typescript/local-value-source.js +1 -0
  353. package/dist/contracts/typescript/local-world-native.js +1 -0
  354. package/dist/contracts/typescript/mcp.js +1 -0
  355. package/dist/contracts/typescript/media.js +1 -0
  356. package/dist/contracts/typescript/native-check.js +1 -0
  357. package/dist/contracts/typescript/native-identity.js +1 -0
  358. package/dist/contracts/typescript/onboarding.js +1 -0
  359. package/dist/contracts/typescript/performance.js +1 -0
  360. package/dist/contracts/typescript/planning.js +1 -0
  361. package/dist/contracts/typescript/preparation.js +1 -0
  362. package/dist/contracts/typescript/real-operation.js +1 -0
  363. package/dist/contracts/typescript/recommendation.js +1 -0
  364. package/dist/contracts/typescript/reports.js +1 -0
  365. package/dist/contracts/typescript/resource-lifecycle.js +1 -0
  366. package/dist/contracts/typescript/saved-record.js +1 -0
  367. package/dist/contracts/typescript/scenarios.js +1 -0
  368. package/dist/contracts/typescript/services.js +1 -0
  369. package/dist/contracts/typescript/session-command.js +1 -0
  370. package/dist/contracts/typescript/session-state.js +1 -0
  371. package/dist/contracts/typescript/session-voice.js +1 -0
  372. package/dist/contracts/typescript/session.js +1 -0
  373. package/dist/contracts/typescript/tool-command.js +1 -0
  374. package/dist/contracts/typescript/tool-connection.js +1 -0
  375. package/dist/contracts/typescript/tool-contribution.js +1 -0
  376. package/dist/contracts/typescript/tool-groups.js +1 -0
  377. package/dist/contracts/typescript/tool-lifecycle.js +1 -0
  378. package/dist/contracts/typescript/tool-package.js +1 -0
  379. package/dist/contracts/typescript/tool-state.js +1 -0
  380. package/dist/contracts/typescript/trial-state.js +1 -0
  381. package/dist/contracts/typescript/vault.js +1 -0
  382. package/dist/contracts/typescript/workspace-team.js +1 -0
  383. package/dist/contracts/typescript/world-stream.js +1 -0
  384. package/dist/contracts/workspace-team-contracts.js +55 -0
  385. package/dist/contracts/world-command.js +65 -0
  386. package/dist/contracts/world-lifetime-contracts.js +74 -0
  387. package/dist/contracts/world-recipe-contracts.js +27 -0
  388. package/dist/contracts/world-stream-contracts.js +27 -0
  389. package/dist/package.json +1 -0
  390. package/package.json +16 -16
  391. package/LICENSE.md +0 -23
  392. package/PACKAGING.json +0 -50
@@ -0,0 +1,396 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { constants } from 'node:fs';
3
+ import { access, lstat, mkdir, open, readFile, realpath, rename, stat } from 'node:fs/promises';
4
+ import { homedir } from 'node:os';
5
+ import { isAbsolute, join, relative, sep } from 'node:path';
6
+ import { randomUUID } from 'node:crypto';
7
+ import { api } from './auth.js';
8
+ import { privateDirectory } from './credentials.js';
9
+ import { CliError } from './http.js';
10
+ import { selectOne } from './prompts.js';
11
+ import { selectedWorkspace } from './world-access.js';
12
+ import { identifier } from './world-contracts.js';
13
+ import { containerPolicy } from './local-container-policy.js';
14
+ import { boundaryArguments, requireContainerBoundary } from './local-container-boundary.js';
15
+ import { withProcessLifetimeLock } from './runner-process-lock.js';
16
+ import { localRuntimeCatalogMatches } from '../../contracts/local-runner-contracts.js';
17
+ const IMAGE = /^[a-z][a-z0-9-]{0,62}-docker\.pkg\.dev\/[a-z][a-z0-9-]{4,62}\/[a-z][a-z0-9-]{0,62}\/[a-z][a-z0-9-]{0,62}@sha256:[a-f0-9]{64}$/;
18
+ const PROFILE = 'firedrill.local-container.v1';
19
+ // Source-free guest readiness allows 60s for its child and 5s for teardown.
20
+ // Keep 25s for controller setup/observation without changing target budgets or
21
+ // user/ownership cancellation. Cleanup retains its separate fenced deadline.
22
+ const READINESS_ATTACH_SECONDS = 90;
23
+ export function hostArch() {
24
+ if (!['darwin', 'linux'].includes(process.platform) || !['arm64', 'x64'].includes(process.arch)) {
25
+ throw new CliError('runner_host_unsupported', 'Use macOS or Linux on arm64 or x64 for this local container path.', 2);
26
+ }
27
+ return process.arch === 'x64' ? 'amd64' : 'arm64';
28
+ }
29
+ async function privateSubdirectory(name) {
30
+ const directory = join(await privateDirectory(), name);
31
+ await mkdir(directory, { mode: 0o700 }).catch(error => { if (error.code !== 'EEXIST')
32
+ throw error; });
33
+ const value = await lstat(directory);
34
+ if (!value.isDirectory() || value.isSymbolicLink() || value.mode & 0o077 || process.getuid && value.uid !== process.getuid()) {
35
+ throw new CliError('runner_storage_unsafe', 'Use private runner storage owned by this OS user.');
36
+ }
37
+ return directory;
38
+ }
39
+ export async function docker() {
40
+ hostArch();
41
+ const home = await privateSubdirectory('docker-client');
42
+ const configuration = await privateSubdirectory('docker-configuration');
43
+ const config = join(configuration, 'config.json');
44
+ try {
45
+ const file = await open(config, 'wx', 0o600);
46
+ try {
47
+ await file.writeFile('{"auths":{}}\n');
48
+ await file.sync();
49
+ }
50
+ finally {
51
+ await file.close();
52
+ }
53
+ }
54
+ catch (error) {
55
+ if (error.code !== 'EEXIST')
56
+ throw error;
57
+ }
58
+ const configStat = await lstat(config);
59
+ if (!configStat.isFile() || configStat.isSymbolicLink() || configStat.mode & 0o077 || configStat.size > 32
60
+ || process.getuid && configStat.uid !== process.getuid() || await readFile(config, 'utf8') !== '{"auths":{}}\n') {
61
+ throw new CliError('runner_configuration_unsafe', 'The private container-client configuration changed. It was not used.');
62
+ }
63
+ const project = await realpath(process.cwd());
64
+ let binary;
65
+ for (const candidate of ['/usr/bin/docker', '/usr/local/bin/docker', '/opt/homebrew/bin/docker', '/Applications/Docker.app/Contents/Resources/bin/docker']) {
66
+ const path = await realpath(candidate).catch(() => null);
67
+ if (!path)
68
+ continue;
69
+ const within = relative(project, path);
70
+ if (within === '' || !within.startsWith('..' + sep) && within !== '..' && !isAbsolute(within))
71
+ continue;
72
+ const value = await stat(path);
73
+ if (!value.isFile() || value.mode & 0o022 || process.getuid && ![0, process.getuid()].includes(value.uid))
74
+ continue;
75
+ try {
76
+ await access(path, constants.X_OK);
77
+ binary = path;
78
+ break;
79
+ }
80
+ catch {
81
+ continue;
82
+ }
83
+ }
84
+ if (!binary)
85
+ throw new CliError('container_runtime_required', 'Install Docker Desktop or Docker Engine outside the project and start it. No host software was installed.', 2);
86
+ const sockets = [join(homedir(), '.docker/run/docker.sock'), ...(process.getuid ? [`/run/user/${process.getuid()}/docker.sock`] : []), '/var/run/docker.sock'];
87
+ let socket;
88
+ for (const candidate of sockets) {
89
+ const path = await realpath(candidate).catch(() => null);
90
+ if (!path)
91
+ continue;
92
+ const value = await stat(path);
93
+ if (value.isSocket() && !(value.mode & 0o002) && (!process.getuid || [0, process.getuid()].includes(value.uid))) {
94
+ socket = path;
95
+ break;
96
+ }
97
+ }
98
+ if (!socket)
99
+ throw new CliError('local_container_socket_required', 'Start a local Docker Engine. Remote contexts, SSH and TCP endpoints are not used.', 2);
100
+ return { binary, socket, configuration, home };
101
+ }
102
+ /** Internal fixed-command callers only. Never a target/model command executor. */
103
+ export function dockerProcess(context, args, signal) {
104
+ return spawn(context.binary, ['--config', context.configuration, '--host', `unix://${context.socket}`, ...args], { shell: false, cwd: context.home, env: { HOME: context.home, PATH: '/usr/bin:/bin', LANG: 'C.UTF-8', LC_ALL: 'C' },
105
+ stdio: ['pipe', 'pipe', 'pipe'], signal });
106
+ }
107
+ export async function command(context, args, options = {}) {
108
+ const signal = AbortSignal.any([...(options.signal ? [options.signal] : []), AbortSignal.timeout((options.seconds ?? 30) * 1000)]);
109
+ return new Promise((accept, refuse) => {
110
+ let bytes = 0, overflow = false;
111
+ const chunks = [];
112
+ const child = spawn(context.binary, ['--config', context.configuration, '--host', `unix://${context.socket}`, ...args], { shell: false, cwd: context.home, env: { HOME: context.home, PATH: '/usr/bin:/bin', LANG: 'C.UTF-8', LC_ALL: 'C' },
113
+ stdio: ['ignore', 'pipe', 'pipe'], signal });
114
+ child.stdout.on('data', (chunk) => {
115
+ bytes += chunk.length;
116
+ if (bytes > (options.maximum ?? 65536)) {
117
+ overflow = true;
118
+ child.kill('SIGTERM');
119
+ }
120
+ else if (!overflow)
121
+ chunks.push(chunk);
122
+ });
123
+ child.stderr.resume(); // No arbitrary daemon/registry/host text in output.
124
+ child.once('error', () => refuse(new CliError('container_operation_uncertain', 'The container operation was not confirmed. Inspect its exact saved request before continuing.')));
125
+ child.once('close', code => {
126
+ if (overflow || signal.aborted) {
127
+ refuse(new CliError('container_operation_uncertain', 'The container operation was not confirmed. Inspect its exact saved request before continuing.'));
128
+ return;
129
+ }
130
+ accept({ code, output: Buffer.concat(chunks).toString('utf8') });
131
+ });
132
+ });
133
+ }
134
+ function document(value) {
135
+ try {
136
+ return JSON.parse(value);
137
+ }
138
+ catch {
139
+ throw new CliError('container_response_invalid', 'The container response could not be read safely.');
140
+ }
141
+ }
142
+ export async function imagePresent(context, runtime, signal) {
143
+ const result = await command(context, ['image', 'inspect', runtime.image], { signal });
144
+ if (result.code !== 0)
145
+ return false;
146
+ const rows = document(result.output);
147
+ const row = Array.isArray(rows) && rows.length === 1 ? rows[0] : null;
148
+ if (!row || row.Os !== 'linux' || row.Architecture !== runtime.arch || !Array.isArray(row.RepoDigests)
149
+ || !row.RepoDigests.includes(runtime.image) || row.Config?.Labels?.['io.firedrill.engine-source-revision'] !== runtime.source_revision) {
150
+ throw new CliError('container_image_mismatch', 'The installed image does not match the selected engine and architecture. It was not started.');
151
+ }
152
+ return true;
153
+ }
154
+ const journalPath = async (value) => join(await privateDirectory(), `runtime-probe-${identifier(value.owner)}-${identifier(value.workspace)}-${identifier(value.key)}.json`);
155
+ async function persist(value) {
156
+ const path = await journalPath(value);
157
+ const temporary = path + '.' + randomUUID() + '.tmp';
158
+ const file = await open(temporary, 'wx', 0o600);
159
+ try {
160
+ await file.writeFile(JSON.stringify(value));
161
+ await file.sync();
162
+ }
163
+ finally {
164
+ await file.close();
165
+ }
166
+ await rename(temporary, path);
167
+ }
168
+ async function owned(value, signal, work) {
169
+ signal.throwIfAborted();
170
+ const path = join(await privateDirectory(), `runtime-probe-lock-${identifier(value.owner)}-${identifier(value.workspace)}-${identifier(value.key)}`);
171
+ return withProcessLifetimeLock(path, signal, work);
172
+ }
173
+ async function load(scope, key) {
174
+ const path = await journalPath({ ...scope, key });
175
+ const before = await lstat(path);
176
+ if (!before.isFile() || before.isSymbolicLink() || before.mode & 0o077 || before.size > 8192
177
+ || process.getuid && before.uid !== process.getuid())
178
+ throw new CliError('runner_journal_unsafe', 'The runtime request journal is not private. It was not used.');
179
+ const file = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
180
+ try {
181
+ const actual = await file.stat();
182
+ if (actual.ino !== before.ino || actual.dev !== before.dev || actual.size !== before.size)
183
+ throw new Error();
184
+ const value = document(await file.readFile('utf8'));
185
+ if (value.schema !== 'firedrill.local-runtime-probe.v1' || value.owner !== scope.owner || value.workspace !== scope.workspace || value.key !== identifier(key)
186
+ || value.name !== 'fd-readiness-' + key || !IMAGE.test(value.image) || !/^[a-f0-9]{40}$/.test(value.source_revision)
187
+ || !['create_dispatched', 'created', 'start_dispatched', 'observed', 'cleanup_confirmed'].includes(value.stage)
188
+ || value.container_id !== null && !/^[a-f0-9]{64}$/.test(value.container_id))
189
+ throw new Error();
190
+ return value;
191
+ }
192
+ catch {
193
+ throw new CliError('runner_journal_invalid', 'The runtime request journal changed. It was not replayed.');
194
+ }
195
+ finally {
196
+ await file.close();
197
+ }
198
+ }
199
+ async function inspected(context, value, signal) {
200
+ const response = await command(context, ['container', 'inspect', value.container_id ?? value.name], { signal });
201
+ if (response.code !== 0)
202
+ return null; // Absence is not proof a dispatched create cannot still arrive.
203
+ const rows = document(response.output);
204
+ const row = Array.isArray(rows) && rows.length === 1 ? rows[0] : null;
205
+ const labels = row?.Config?.Labels;
206
+ if (!row || !/^[a-f0-9]{64}$/.test(row.Id) || value.container_id && row.Id !== value.container_id
207
+ || row.Name !== '/' + value.name || row.Config?.Image !== value.image
208
+ || labels?.['io.firedrill.local-probe'] !== value.key || labels?.['io.firedrill.actor'] !== value.owner
209
+ || labels?.['io.firedrill.workspace'] !== value.workspace) {
210
+ throw new CliError('container_identity_mismatch', 'This container does not belong to the saved runtime request. It was not changed.');
211
+ }
212
+ return row;
213
+ }
214
+ const readinessArguments = (policy) => ['-m', 'runtime_support.guest_local_readiness',
215
+ ...(policy.requiredApparmor ? ['--apparmor-profile', policy.apparmor.name] : [])];
216
+ const readinessBoundary = (image, policy) => ({ image, arguments: readinessArguments(policy),
217
+ memoryBytes: 4 * 1024 ** 3, nanoCpus: 2 * 10 ** 9, interactive: false, tmpfs: {
218
+ '/work': 'rw,nosuid,nodev,size=64m,uid=2000,gid=2000,mode=0755',
219
+ '/run/simulation': 'rw,nosuid,nodev,noexec,size=16m,uid=2000,gid=2000,mode=0700',
220
+ '/tmp': 'rw,nosuid,nodev,noexec,size=64m,uid=2000,gid=2000,mode=1777'
221
+ } });
222
+ function sealed(row, policy) {
223
+ requireContainerBoundary(row, policy, readinessBoundary(row.Config?.Image, policy));
224
+ }
225
+ async function cleanup(context, value, signal) {
226
+ const row = await inspected(context, value, signal);
227
+ if (!row)
228
+ return false;
229
+ value.container_id = row.Id;
230
+ await persist(value);
231
+ const removed = await command(context, ['container', 'rm', '--force', row.Id], { signal });
232
+ if (removed.code !== 0)
233
+ return false;
234
+ value.stage = 'cleanup_confirmed';
235
+ await persist(value);
236
+ return true;
237
+ }
238
+ export async function runtimeCommand(action, key, options, output) {
239
+ const scope = await selectedWorkspace({ workspace: options.workspace, interactive: !options.json && !!process.stdin.isTTY && !!process.stderr.isTTY,
240
+ openBrowser: options.openBrowser, signal: options.signal });
241
+ return scopedRuntimeCommand(scope, action, key, options, output);
242
+ }
243
+ export async function scopedRuntimeCommand(scope, action, key, options, output) {
244
+ const arch = hostArch();
245
+ const context = await docker();
246
+ if (action === 'recover') {
247
+ if (!key)
248
+ throw new CliError('request_key_required', 'Use the exact runtime request key.', 2);
249
+ return owned({ ...scope, key: identifier(key) }, options.signal, async (active) => {
250
+ const value = await load(scope, identifier(key));
251
+ if (value.stage === 'cleanup_confirmed') {
252
+ output('runtime_cleanup', { request_key: value.key, state: value.stage }, 'Runtime readiness container cleanup was confirmed.');
253
+ return null;
254
+ }
255
+ const removed = await cleanup(context, value, active);
256
+ output('runtime_cleanup', { request_key: value.key, state: removed ? 'cleanup_confirmed' : 'not_visible' }, removed
257
+ ? 'Runtime readiness container removed.' : 'The container is not visible. Its pending create is not replayed; the journal remains for a later lookup.');
258
+ return null;
259
+ });
260
+ }
261
+ const info = await command(context, ['info', '--format', '{{json .}}'], { signal: options.signal, maximum: 128 * 1024 });
262
+ if (info.code !== 0)
263
+ throw new CliError('local_container_unavailable', 'The local Docker Engine is unavailable. Start it and try again.', 2);
264
+ const host = document(info.output);
265
+ const daemonArch = host.Architecture === 'x86_64' ? 'amd64' : host.Architecture === 'aarch64' ? 'arm64' : host.Architecture;
266
+ if (host.OSType !== 'linux' || daemonArch !== arch)
267
+ throw new CliError('local_container_architecture_required', 'Use a same-architecture Linux Docker Engine. No emulation was selected.', 2);
268
+ const policy = await containerPolicy(arch, host.SecurityOptions);
269
+ if (action === 'policy') {
270
+ const summary = { schema: policy.schema, seccomp: { path: policy.seccomp.path, sha256: policy.seccomp.sha256 },
271
+ apparmor: { ...policy.apparmor, required: policy.requiredApparmor }, installed_by_command: false };
272
+ output('runtime_policy', summary, `Local security policy exported. No host policy was installed or disabled.\nSeccomp: ${policy.seccomp.path}\n`
273
+ + (policy.requiredApparmor ? `AppArmor: ${policy.apparmor.path}\nA daemon-host administrator must load this exact named AppArmor 4 profile before execution. No daemon default is changed.`
274
+ : 'This daemon does not advertise AppArmor. Seccomp and strict namespace/role isolation are still required.'));
275
+ return null;
276
+ }
277
+ if (host.OSType !== 'linux' || daemonArch !== arch || !Number.isSafeInteger(host.NCPU) || host.NCPU < 2
278
+ || !Number.isSafeInteger(host.MemTotal) || host.MemTotal < 4 * 1024 ** 3) {
279
+ throw new CliError('local_container_capacity_required', 'Use a same-architecture Linux Docker Engine with at least 2 CPUs and 4 GiB of memory. No emulation or cloud fallback was selected.', 2);
280
+ }
281
+ const catalog = await api(`/api/workspaces/${scope.workspace}/local-runner-runtime`, { actor: scope.owner, workspace: scope.workspace, signal: options.signal });
282
+ const runtime = localRuntimeCatalogMatches(catalog, scope.owner, scope.workspace)
283
+ ? catalog.runtimes.find(item => item.arch === arch) : undefined;
284
+ if (!runtime || runtime.os !== 'linux' || runtime.profile !== PROFILE || !IMAGE.test(runtime.image) || !/^[a-f0-9]{40}$/.test(runtime.source_revision)) {
285
+ throw new CliError('local_runtime_configuration_required', 'A pinned local runtime for this architecture is not available. No image or project was run.');
286
+ }
287
+ let installed = await imagePresent(context, runtime, options.signal);
288
+ if (!installed && action === 'install') {
289
+ if (!options.install) {
290
+ if (options.json || !process.stdin.isTTY || !process.stderr.isTTY)
291
+ throw new CliError('runtime_install_consent_required', 'Pass --install-runtime to download the pinned execution image. No host software is installed.', 2);
292
+ const approved = await selectOne('Download the local execution image?', [{ value: true, label: 'Download', detail: 'Install only the selected digest-pinned image in your local Docker Engine.' }, { value: false, label: 'Cancel' }], options.signal);
293
+ if (!approved)
294
+ throw new CliError('canceled', 'No image was downloaded.', 130);
295
+ }
296
+ output('runtime_download', { image: runtime.image }, 'Downloading the pinned execution image.');
297
+ const pulled = await command(context, ['image', 'pull', '--quiet', '--platform', `linux/${arch}`, runtime.image], { signal: options.signal, seconds: 1800, maximum: 65536 });
298
+ if (pulled.code !== 0)
299
+ throw new CliError('runtime_download_unconfirmed', 'The execution image download was not confirmed. No container or project was started.');
300
+ installed = await imagePresent(context, runtime, options.signal);
301
+ }
302
+ const security = { schema: policy.schema, seccomp_sha256: policy.seccomp.sha256,
303
+ apparmor_profile: policy.requiredApparmor ? policy.apparmor.name : null };
304
+ const summary = { schema: 'firedrill.local-runtime-host.v1', runtime, installed, cpu_count: host.NCPU,
305
+ memory_bytes: host.MemTotal, connection: 'local_unix_socket', provenance: 'customer_device', security };
306
+ if (action !== 'check') {
307
+ output('runtime_host', summary, installed ? 'Pinned execution image installed. Container isolation has not been observed yet.' : 'The execution image is not installed. Use firedrill runner runtime install.');
308
+ return { runtime, installed, isolation_observed: false, cleanup_confirmed: false };
309
+ }
310
+ if (!installed)
311
+ throw new CliError('runtime_image_required', 'Use firedrill runner runtime install first. No container was started.', 2);
312
+ const value = { schema: 'firedrill.local-runtime-probe.v1', ...scope, key: randomUUID(), image: runtime.image,
313
+ source_revision: runtime.source_revision, name: '', container_id: null, stage: 'create_dispatched', security: summary.security };
314
+ value.name = 'fd-readiness-' + value.key;
315
+ await persist(value);
316
+ output('runtime_request', { request_key: value.key }, `Runtime readiness request ${value.key}. Recover cleanup with firedrill runner runtime recover ${value.key}.`);
317
+ return owned(value, options.signal, async (active, ownership) => {
318
+ let cleanupConfirmed = false;
319
+ try {
320
+ const created = await command(context, ['container', 'create', '--name', value.name, '--pull', 'never', '--platform', `linux/${arch}`,
321
+ '--label', `io.firedrill.local-probe=${value.key}`, '--label', `io.firedrill.actor=${scope.owner}`, '--label', `io.firedrill.workspace=${scope.workspace}`,
322
+ ...boundaryArguments(readinessBoundary(runtime.image, policy), policy)], { signal: active });
323
+ if (created.code !== 0 || !/^[a-f0-9]{64}$/.test(created.output.trim()))
324
+ throw new CliError('container_creation_unconfirmed', 'The readiness container was not confirmed. Recover this exact request; no second container was created.');
325
+ value.container_id = created.output.trim();
326
+ value.stage = 'created';
327
+ await persist(value);
328
+ const row = await inspected(context, value, active);
329
+ if (!row || row.State?.Status !== 'created' || row.State?.Running || row.State?.Restarting)
330
+ throw new CliError('container_start_ambiguous', 'The readiness container state changed. Its start was not repeated.');
331
+ sealed(row, policy);
332
+ value.stage = 'start_dispatched';
333
+ await persist(value);
334
+ const observed = await command(context, ['container', 'start', '--attach', value.container_id], { signal: active, seconds: READINESS_ATTACH_SECONDS, maximum: 8192 });
335
+ const result = document(observed.output);
336
+ const after = await inspected(context, value, active);
337
+ if (after)
338
+ sealed(after, policy);
339
+ const facts = result?.data;
340
+ const surface = facts?.inner?.surface;
341
+ const observedArch = facts?.container_arch === 'x86_64' ? 'amd64' : facts?.container_arch === 'aarch64' ? 'arm64' : facts?.container_arch;
342
+ if (observed.code !== 0 || result.ok !== true || !after || after.State?.Running || after.State?.ExitCode !== 0
343
+ || facts?.schema !== 'firedrill.local-runtime-observation.v1' || facts.container_os !== 'linux'
344
+ || observedArch !== runtime.arch
345
+ || facts.writable_storage !== true || facts.engine_import_available !== true || facts.parent_identity_ranges !== true
346
+ || facts.apparmor_enforced !== security.apparmor_profile || facts.inner?.kind !== 'rootless_user_namespace'
347
+ || facts.inner?.schema !== 'firedrill.local-inner-observation.v1'
348
+ || facts.inner?.separate_process_users !== true || facts.inner?.network !== 'isolated_loopback_only' || facts.inner?.role_identity_drop !== true
349
+ || !surface || typeof surface !== 'object' || Array.isArray(surface)
350
+ || Object.keys(surface).length !== 5
351
+ || surface.source_free !== true || surface.html_observed !== true || surface.frame_observed !== true
352
+ || surface.role_identity_drop !== true || surface.cleanup_confirmed !== true) {
353
+ throw new CliError(['local_namespace_policy_required', 'local_parent_mapping_required', 'local_lsm_policy_required', 'controller_bootstrap_unavailable',
354
+ 'local_namespace_syscall_denied', 'local_namespace_capability_unavailable', 'local_namespace_mount_unavailable',
355
+ 'local_uid_mapping_unavailable', 'local_gid_mapping_unavailable',
356
+ 'local_inner_identity_unavailable', 'local_role_namespace_unavailable', 'local_role_entry_unavailable',
357
+ 'local_surface_prerequisite_unavailable'].includes(result?.error?.code) ? result.error.code : 'local_runtime_not_ready', result?.error?.code === 'local_parent_mapping_required'
358
+ ? 'The container parent namespace cannot map the required isolated service identities. No host user-namespace setting was changed or bypassed.'
359
+ : result?.error?.code === 'controller_bootstrap_unavailable'
360
+ ? 'The fixed controller could not establish its required capability boundary. No privileged or weaker runtime was selected.'
361
+ : result?.error?.code === 'local_namespace_syscall_denied'
362
+ ? 'The runtime refused the required namespace syscall. No host setting, privileged mode or weaker runtime was selected.'
363
+ : ['local_namespace_capability_unavailable', 'local_namespace_mount_unavailable'].includes(result?.error?.code)
364
+ ? 'The fixed namespace helper could not establish its required inner capabilities or private mounts. No outer capability or host policy was broadened.'
365
+ : ['local_uid_mapping_unavailable', 'local_gid_mapping_unavailable'].includes(result?.error?.code)
366
+ ? 'The fixed identity-mapping helper could not establish the required service IDs. No mapping or host policy was bypassed.'
367
+ : ['local_inner_identity_unavailable', 'local_role_namespace_unavailable', 'local_role_entry_unavailable'].includes(result?.error?.code)
368
+ ? 'The inner runtime could not establish its required identity, role namespace or sealed process boundary. No project or weaker fallback was started.'
369
+ : result?.error?.code === 'local_surface_prerequisite_unavailable'
370
+ ? 'The isolated browser could not complete its startup, capture and cleanup check. No project was started. Keep this request for support; no weaker browser mode was selected.'
371
+ : 'The local runtime did not establish the required inner isolation. Inspect runner runtime policy and the daemon-host namespace policy. No project or weaker fallback was started.', 2);
372
+ }
373
+ value.stage = 'observed';
374
+ await persist(value);
375
+ output('runtime_observation', { ...summary, request_key: value.key, observation: facts }, 'Container isolation and isolated browser capture observed. No project, model call or simulation was started.');
376
+ }
377
+ finally {
378
+ if (value.container_id) {
379
+ const controller = new AbortController();
380
+ const timer = setTimeout(() => controller.abort(), 10000);
381
+ try {
382
+ cleanupConfirmed = await cleanup(context, value, AbortSignal.any([controller.signal, ownership]));
383
+ if (!cleanupConfirmed)
384
+ output('runtime_cleanup_pending', { request_key: value.key }, 'Readiness cleanup is pending. Use the exact recovery command shown above.');
385
+ }
386
+ catch {
387
+ output('runtime_cleanup_pending', { request_key: value.key }, 'Readiness cleanup is unconfirmed. Its journal was retained.');
388
+ }
389
+ finally {
390
+ clearTimeout(timer);
391
+ }
392
+ }
393
+ }
394
+ return { runtime, installed: true, isolation_observed: true, cleanup_confirmed: cleanupConfirmed, request_key: value.key };
395
+ });
396
+ }