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,216 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { api } from './auth.js';
3
+ import { CliError } from './http.js';
4
+ import { selectOne, terminalText } from './prompts.js';
5
+ import { selectedWorld } from './world-access.js';
6
+ import { identifier } from './world-contracts.js';
7
+ import { requestInput } from './request-input.js';
8
+ import { scenarioWorldEventsMatch } from '../../contracts/scenario-world-contracts.js';
9
+ import { revisionRequestMatches, revisionRequestPath } from '../../contracts/revision-request-contracts.js';
10
+ import { compareScenarioDrafts, scenarioDraftReviewMatches } from '../../contracts/scenario-draft-comparison.js';
11
+ const actions = new Set(['discover', 'discoveries', 'discovery', 'cancel-discovery', 'drafts', 'draft', 'edit-draft', 'accept-draft', 'coverage', 'world-events', 'revise-execution', 'draft-request', 'execution-request']);
12
+ const object = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
13
+ const invalid = () => new CliError('scenario_response_unconfirmed', 'The scenario response could not be confirmed. Inspect the original request; nothing was repeated.');
14
+ const positive = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
15
+ export const isScenarioDiscoveryAction = (action) => !!action && actions.has(action);
16
+ async function draftComparison(scope, row, options) {
17
+ if (!scenarioDraftReviewMatches(row))
18
+ throw invalid();
19
+ if (!row.parent_id)
20
+ return null;
21
+ const parent = await api(`${scope.prefix}/scenario-drafts/${row.parent_id}`, {
22
+ actor: scope.owner, workspace: scope.workspace, signal: options.signal
23
+ });
24
+ const result = compareScenarioDrafts(parent, row);
25
+ if (!result)
26
+ throw new CliError('scenario_draft_comparison_unavailable', 'The immediate previous draft does not match this saved revision. No comparison or approval was inferred. Reopen both exact drafts before continuing.', 2);
27
+ return result;
28
+ }
29
+ function comparisonText(row, scope) {
30
+ const text = (value) => {
31
+ const visible = value.text.slice(0, 600);
32
+ return visible.split('\n').map(terminalText).join('\n')
33
+ + (value.truncated || value.text.length > visible.length ? `\nShowing ${visible.length} of ${value.characters} characters. Inspect the full saved draft for the rest.` : '');
34
+ };
35
+ return `Changes from previous draft ${row.parent_id}\n${row.differences.length} changed fields.\n`
36
+ + (row.differences.length ? row.differences.map(one => `${terminalText(one.label)}\nBefore: ${text(one.before)}\nAfter: ${text(one.after)}`).join('\n\n') : 'No authored scenario fields changed.')
37
+ + `\nPrevious: firedrill scenarios draft ${row.parent_id} --world ${scope.world} --workspace ${scope.workspace}`
38
+ + `\nCurrent: firedrill scenarios draft ${row.draft_id} --world ${scope.world} --workspace ${scope.workspace}`;
39
+ }
40
+ async function confirm(message, options) {
41
+ if (options.approve)
42
+ return true;
43
+ if (options.json || !process.stdin.isTTY || !process.stderr.isTTY)
44
+ throw new CliError('approval_required', 'Review this exact change, then use --approve-change. No target is run by this action.', 2);
45
+ return selectOne(message, [{ value: false, label: 'Not now' }, { value: true, label: 'Apply this change' }], options.signal);
46
+ }
47
+ export async function scenarioDiscoveryCommand(args, options, output, selected) {
48
+ const action = args[0];
49
+ const directory = ['drafts', 'discoveries', 'coverage', 'world-events'].includes(action);
50
+ if (!isScenarioDiscoveryAction(action) || args.length > (action === 'discover' ? 100 : directory && action !== 'world-events' ? 1 : 2)
51
+ || (options.page !== undefined || options.search !== undefined) && !directory
52
+ || options.request !== undefined && !['discover', 'discoveries', 'edit-draft', 'revise-execution', 'draft-request', 'execution-request'].includes(action)
53
+ || options.file !== undefined && !['discover', 'edit-draft', 'revise-execution'].includes(action)
54
+ || options.file !== undefined && action === 'discover' && args.length > 1
55
+ || options.kind !== undefined && (action !== 'world-events' || !['record', 'operation', 'ingress', 'message'].includes(options.kind))
56
+ || options.approve && !['discover', 'edit-draft', 'accept-draft', 'cancel-discovery', 'revise-execution'].includes(action))
57
+ throw new CliError('arguments_invalid', 'Use scenarios discover [optional focus], drafts, draft <id>, edit-draft <id>, accept-draft <id>, coverage, world-events <scenario>, discoveries, discovery <id>, cancel-discovery <id>, revise-execution <id>, draft-request <parent> or execution-request <parent> --request-key <original UUID>.', 2);
58
+ const scope = selected ?? await selectedWorld({ ...options, interactive: !options.json && !!process.stdin.isTTY && !!process.stderr.isTTY });
59
+ const auth = { actor: scope.owner, workspace: scope.workspace, signal: options.signal };
60
+ const page = options.page ?? '1';
61
+ if (!/^[1-9][0-9]{0,8}$/.test(page) || (options.search ?? '').length > 200)
62
+ throw new CliError('arguments_invalid', 'Choose a positive page and a short search.', 2);
63
+ const params = new URLSearchParams({ page, q: options.search ?? '' });
64
+ if (action === 'draft-request' || action === 'execution-request') {
65
+ if (!options.request)
66
+ throw new CliError('request_key_required', 'Use --request-key <original UUID> with the original parent revision. This only reads its receipt.', 2);
67
+ const key = identifier(options.request);
68
+ const revisionScope = { actor: scope.owner, workspace: scope.workspace, world: scope.world,
69
+ parent: identifier(args[1]), kind: action === 'draft-request' ? 'scenario_draft' : 'execution_proposal' };
70
+ const row = await api(scope.prefix + revisionRequestPath(revisionScope, key), auth);
71
+ if (!revisionRequestMatches(row, revisionScope, key))
72
+ throw invalid();
73
+ output('revision_request', row, [`Original request: ${row.request_key}`,
74
+ row.state === 'not_received' ? 'No receipt is recorded yet. It may still arrive. Continue only with this same key and the exact original input.'
75
+ : row.state === 'unavailable' ? 'The original revision is recorded but is no longer readable. Do not replace it with another request.'
76
+ : `Original revision: ${row.resource_id}`,
77
+ ...(row.resource_id ? [action === 'draft-request' ? `Inspect: firedrill scenarios draft ${row.resource_id} --world ${scope.world} --workspace ${scope.workspace}`
78
+ : `Original proposal: ${row.resource_id}. New simulations use firedrill plan, apply and run.`] : [])].join('\n'));
79
+ return;
80
+ }
81
+ if (action === 'world-events') {
82
+ const id = identifier(args[1]);
83
+ const scenario = await api(`${scope.prefix}/scenarios/${id}`, auth);
84
+ if (scenario.id !== id || scenario.world_id !== scope.world || !/^[a-f0-9]{64}$/.test(scenario.definition_digest))
85
+ throw invalid();
86
+ if (scenario.world_timeline_problem)
87
+ throw new CliError('scenario_world_plan_invalid', 'This saved world progression needs review before the scenario can run.', 2);
88
+ if (!scenario.world_timeline) {
89
+ output('scenario_world_events', { scenario_id: id, world_timeline: null }, 'No continuous world events are declared for this scenario.');
90
+ return;
91
+ }
92
+ params.set('definition', scenario.definition_digest);
93
+ if (options.kind)
94
+ params.set('kind', options.kind);
95
+ const value = await api(`${scope.prefix}/scenarios/${id}/world-events?${params}`, auth);
96
+ if (!scenarioWorldEventsMatch(value, scenario.definition_digest) || value.page !== Number(page)
97
+ || options.kind && value.results.some(row => row.kind !== options.kind))
98
+ throw invalid();
99
+ output('scenario_world_events', value, [scenario.name, 'Saved scenario schedule, not observed execution. The agent clock is unchanged.',
100
+ ...value.results.map(row => `${row.id}\t${row.kind}\tafter ${row.after_ms}ms${row.repeat ? `; ${row.repeat.count} times every ${row.repeat.interval_ms}ms` : ''}\n${row.text_preview ?? row.operation ?? row.collection ?? 'Input to the configured agent event channel'}${row.text_shortened ? '…' : ''}${row.path ? '\n' + [row.method, row.path].filter(Boolean).join(' ') : ''}${row.conditional ? '\nRequires its declared condition.' : ''}${row.depends_on.length ? '\nAfter: ' + row.depends_on.join(', ') : ''}`),
101
+ `Page ${value.page}; ${value.count} declared event series.`, ...(value.next ? [`Next: firedrill scenarios world-events ${id} --world ${scope.world} --workspace ${scope.workspace} --page ${value.page + 1}${options.kind ? ' --kind ' + options.kind : ''}`] : [])].join('\n'));
102
+ return;
103
+ }
104
+ if (['drafts', 'discoveries', 'coverage'].includes(action)) {
105
+ const suffix = action === 'drafts' ? 'scenario-drafts' : action === 'discoveries' ? 'scenario-discovery' : 'scenario-coverage';
106
+ if (options.request)
107
+ params.set('request_key', identifier(options.request));
108
+ const raw = await api(`${scope.prefix}/${suffix}?${params}`, auth);
109
+ if (!object(raw) || !Array.isArray(raw.results) || raw.results.length > 100 || !positive(raw.count) || !positive(raw.page) || !positive(raw.page_size))
110
+ throw invalid();
111
+ const lines = raw.results.map(one => {
112
+ if (!object(one))
113
+ throw invalid();
114
+ if (action === 'drafts') {
115
+ if (!object(one.draft) || typeof one.draft.title !== 'string' || typeof one.accepted !== 'boolean')
116
+ throw invalid();
117
+ return `${identifier(String(one.id))} ${terminalText(one.draft.title)}${one.accepted ? ' (added)' : ''}`;
118
+ }
119
+ if (action === 'discoveries') {
120
+ if (typeof one.state !== 'string')
121
+ throw invalid();
122
+ return `${identifier(String(one.id))} ${terminalText(one.state)} request ${identifier(String(one.request_key))}`;
123
+ }
124
+ if (typeof one.name !== 'string' || !['covered', 'unexplored'].includes(String(one.state)))
125
+ throw invalid();
126
+ return `${terminalText(one.name)} ${one.state === 'covered' ? 'Has scenario' : 'Unexplored'}`;
127
+ });
128
+ output('scenario_' + action, raw, (lines.join('\n') || 'No matching records.') + `\nPage ${raw.page}, ${raw.count} records.`
129
+ + (action === 'coverage' ? '\nCoverage describes explicit scenario links, not execution success or complete behavioral coverage.' : ''));
130
+ return;
131
+ }
132
+ const id = action === 'discover' ? null : identifier(args[1]);
133
+ if (action === 'draft' || action === 'discovery') {
134
+ const row = await api(`${scope.prefix}/${action === 'draft' ? 'scenario-drafts' : 'scenario-discovery'}/${id}`, auth);
135
+ if (!object(row) || row.id !== id)
136
+ throw invalid();
137
+ output('scenario_' + action, row, JSON.stringify(row, null, 2).split('\n').map(terminalText).join('\n'));
138
+ if (action === 'draft') {
139
+ try {
140
+ const comparison = await draftComparison(scope, row, options);
141
+ if (comparison)
142
+ output('scenario_draft_comparison', comparison, comparisonText(comparison, scope));
143
+ }
144
+ catch (error) {
145
+ if (!options.signal.aborted)
146
+ output('scenario_draft_comparison_unavailable', { draft_id: id,
147
+ parent_id: typeof row.parent_id === 'string' && /^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/.test(row.parent_id) ? row.parent_id : null,
148
+ available: false }, 'The previous draft comparison is unavailable. This does not mean the definitions are unchanged; no scenario was added.');
149
+ throw error;
150
+ }
151
+ }
152
+ return;
153
+ }
154
+ if (action === 'cancel-discovery') {
155
+ const current = await api(`${scope.prefix}/scenario-discovery/${id}`, auth);
156
+ if (!object(current) || current.id !== id || typeof current.can_cancel !== 'boolean')
157
+ throw invalid();
158
+ if (!['queued', 'discovering'].includes(String(current.state))) {
159
+ output('scenario_discovery_finished', current, 'This discovery is already finished. Saved drafts remain available.');
160
+ return;
161
+ }
162
+ if (!current.can_cancel)
163
+ throw new CliError('scenario_discovery_access_required', 'Only the member who requested this discovery can cancel it. Saved drafts can still be inspected.', 2);
164
+ if (!await confirm('Cancel this discovery batch? Saved drafts remain available.', options))
165
+ return;
166
+ const row = await api(`${scope.prefix}/scenario-discovery/${id}`, { ...auth, method: 'DELETE' });
167
+ if (!object(row) || row.id !== id)
168
+ throw invalid();
169
+ output('scenario_discovery_canceled', row, row.state === 'canceled' ? 'Discovery canceled. Saved drafts remain available.' : 'Discovery already finished. Saved drafts remain available.');
170
+ return;
171
+ }
172
+ if (action === 'accept-draft') {
173
+ const row = await api(`${scope.prefix}/scenario-drafts/${id}`, auth);
174
+ if (!object(row) || row.id !== id || !object(row.draft) || typeof row.can_edit !== 'boolean')
175
+ throw invalid();
176
+ if (row.accepted === true) {
177
+ if (!object(row.scenario) || typeof row.scenario.id !== 'string')
178
+ throw new CliError('scenario_revision_unavailable', 'This draft was already accepted, but its original scenario is no longer available. No replacement was created.', 2);
179
+ output('scenario_already_added', row, `This draft is already linked to scenario ${identifier(row.scenario.id)}. No scenario or simulation was duplicated.`);
180
+ return;
181
+ }
182
+ if (!row.can_edit)
183
+ throw new CliError('scenario_draft_access_required', 'This draft is not editable by this account. Ask the original author or inspect its saved scenario.', 2);
184
+ const comparison = await draftComparison(scope, row, options);
185
+ output('scenario_draft_review', row, JSON.stringify(row.draft, null, 2).split('\n').map(terminalText).join('\n'));
186
+ if (comparison)
187
+ output('scenario_draft_comparison', comparison, comparisonText(comparison, scope));
188
+ if (!await confirm('Add this exact scenario draft? Startup validation will use the new scenario revision. No simulation starts.', options))
189
+ return;
190
+ const result = await api(`${scope.prefix}/scenario-drafts/${id}/accept`, { ...auth, method: 'POST', body: {} });
191
+ if (!object(result) || typeof result.id !== 'string')
192
+ throw invalid();
193
+ output('scenario_added', result, `Scenario added: ${identifier(result.id)}\nNo simulation started.`);
194
+ return;
195
+ }
196
+ if (['edit-draft', 'revise-execution'].includes(action) && !options.file)
197
+ throw new CliError('request_file_required', 'Use --file with the full reviewed draft or execution settings. Read the current draft/proposal first.', 2);
198
+ const raw = options.file ? await requestInput(options.file, options.signal, 512 * 1024) : JSON.stringify({ objective: args.slice(1).join(' ') });
199
+ const body = JSON.parse(raw);
200
+ if (!object(body))
201
+ throw new CliError('arguments_invalid', 'Use a JSON request object.', 2);
202
+ if (!await confirm(action === 'discover' ? 'Request a bounded batch of discovered scenarios? This does not run simulations or modify the agent.' : 'Save these settings as a new reviewable revision?', options))
203
+ return;
204
+ const key = options.request ? identifier(options.request) : randomUUID();
205
+ output('scenario_request', { request_key: key, world_id: scope.world, action }, `Original request: ${key}\nKeep this key if the response is interrupted. Use it with the same --request-key and input, not a replacement request.`);
206
+ if (action === 'edit-draft' || action === 'revise-execution')
207
+ output('revision_recovery', { parent_id: id, request_key: key }, `Read original receipt: firedrill scenarios ${action === 'edit-draft' ? 'draft-request' : 'execution-request'} ${id} --request-key ${key} --world ${scope.world} --workspace ${scope.workspace}`);
208
+ const route = action === 'discover' ? '/scenario-discovery' : action === 'edit-draft' ? `/scenario-drafts/${id}` : `/execution-proposals/${id}/revisions`;
209
+ const row = await api(scope.prefix + route, { ...auth, method: 'POST', bodyJson: raw, idempotencyKey: key });
210
+ if (!object(row) || typeof row.id !== 'string' || action === 'discover' && row.request_key !== key)
211
+ throw invalid();
212
+ identifier(row.id);
213
+ output('scenario_request_saved', row, action === 'discover' ? `Discovery requested: ${row.id}\nRead it with firedrill scenarios discovery ${row.id}. No target was invoked.`
214
+ : action === 'edit-draft' ? `Draft revision saved: ${row.id}\nInspect its previous-draft comparison before adding the scenario:\nfiredrill scenarios draft ${row.id} --world ${scope.world} --workspace ${scope.workspace}`
215
+ : `Execution proposal revised: ${row.id}\nReview execution access and the credit estimate again before running it.`);
216
+ }
@@ -0,0 +1,68 @@
1
+ import { api } from './auth.js';
2
+ import { CliError } from './http.js';
3
+ import { selectOne, terminalText } from './prompts.js';
4
+ import { selectedWorld } from './world-access.js';
5
+ import { identifier } from './world-contracts.js';
6
+ const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
7
+ export async function scenarioPaths(args, options, output) {
8
+ const page = options.page ?? '1', search = options.search ?? '';
9
+ if (args.length > 3 || !/^[1-9][0-9]{0,8}$/.test(page) || search.length > 200
10
+ || args.slice(1).some(value => !/^[1-9][0-9]{0,8}$/.test(value))
11
+ || options.definition !== undefined && !/^[a-f0-9]{64}$/.test(options.definition))
12
+ throw new CliError('arguments_invalid', 'Use scenarios paths [scenario-id] [path] [step], a positive page and a search of up to 200 characters. --basis-version pins the saved definition.', 2);
13
+ const interactive = !options.json && !!process.stdin.isTTY && !!process.stderr.isTTY;
14
+ const scope = await selectedWorld({ ...options, interactive });
15
+ const auth = { actor: scope.owner, workspace: scope.workspace, signal: options.signal };
16
+ let item = args[0] ? identifier(args[0]) : '';
17
+ let number = 1;
18
+ while (!item && interactive) {
19
+ const choices = await api(`${scope.prefix}/scenarios?page=${number}`, auth);
20
+ const values = choices.results.map(row => ({ value: identifier(row.id), label: row.name, detail: `Revision ${row.revision}` }));
21
+ if (number > 1)
22
+ values.unshift({ value: 'previous', label: 'Previous page', detail: '' });
23
+ if (choices.next)
24
+ values.push({ value: 'next', label: 'Next page', detail: '' });
25
+ if (!values.length)
26
+ throw new CliError('scenario_unavailable', 'No scenarios are available in this world.');
27
+ const chosen = await selectOne('Scenario', values, options.signal);
28
+ if (chosen === 'next')
29
+ number += 1;
30
+ else if (chosen === 'previous')
31
+ number -= 1;
32
+ else
33
+ item = identifier(chosen);
34
+ }
35
+ if (!item)
36
+ throw new CliError('scenario_required', 'Pass the scenario ID from firedrill scenarios. No simulation was started.', 2);
37
+ let definition = options.definition;
38
+ if (!definition) {
39
+ const original = await api(`${scope.prefix}/scenarios/${item}`, auth);
40
+ if (original.id !== item || original.world_id !== scope.world || !/^[a-f0-9]{64}$/.test(original.definition_digest))
41
+ throw new CliError('scenario_scope_changed', 'The original scenario could not be confirmed.');
42
+ definition = original.definition_digest;
43
+ }
44
+ const params = new URLSearchParams({ definition, page, q: search });
45
+ if (args[1])
46
+ params.set('path', args[1]);
47
+ if (args[2])
48
+ params.set('step', args[2]);
49
+ const result = await api(`${scope.prefix}/scenarios/${item}/reference-paths?${params}`, auth);
50
+ const expected = args[2] ? 'interfaces' : args[1] ? 'steps' : 'paths';
51
+ if (result.item_id !== item || result.world_id !== scope.world || result.definition_digest !== definition || result.view !== expected)
52
+ throw new CliError('scenario_scope_changed', 'The original reference path could not be confirmed.');
53
+ const lines = result.results.map(value => {
54
+ if ('step_count' in value)
55
+ return `${value.position}. ${value.kind === 'reference' ? 'Reference path' : `Alternative ${value.position - 1}`} · ${value.step_count} steps`;
56
+ if ('input_fields' in value)
57
+ return `${value.position}. ${value.tool || 'Operation not recorded'}\n${value.input_field_count} input fields: ${value.input_fields.join(', ')}${value.presentation_omitted ? '\nSome names are shortened, redacted or omitted.' : ''}`;
58
+ return `${value.service_name} · Revision ${value.service_revision}\n${value.protocol === 'http' && value.route ? `${value.method ?? ''} ${value.route}`.trim()
59
+ : value.protocol === 'mcp' ? `MCP: ${value.mcp_tool || value.operation}` : value.operation}\nService: ${value.service_id}`;
60
+ });
61
+ const follow = `firedrill scenarios paths ${item}${args[1] ? ' ' + args[1] : ''}${args[2] ? ' ' + args[2] : ''} --world ${scope.world} --workspace ${scope.workspace} --basis-version ${definition}`;
62
+ const readable = `${expected === 'interfaces' ? 'Exact declared operation-name matches, not recorded calls.' : 'Authored reference paths, not a required action sequence or observed execution.'}\n`
63
+ + (lines.join('\n\n') || (expected === 'interfaces' && !result.source_current ? 'Mappings are not shown for this previous world revision.' : 'No matching entries.'))
64
+ + `\nPage ${result.page}, ${result.count} entries.`
65
+ + (result.next ? `\nContinue: ${follow} --page ${result.page + 1}${search ? ' --search ' + quote(search) : ''}${options.json ? ' --json' : ''}` : '')
66
+ + (expected === 'paths' && result.count ? `\nInspect steps: ${follow} <path>` : expected === 'steps' && result.count ? `\nInspect interfaces: ${follow} <step>` : '');
67
+ output(result, readable.split('\n').map(terminalText).join('\n'));
68
+ }
@@ -0,0 +1,4 @@
1
+ import { revisionRequests } from './revision-requests.js';
2
+ export function scenarioRequests(args, options, output) {
3
+ return revisionRequests('scenario', args, options, output);
4
+ }
@@ -0,0 +1,105 @@
1
+ import { workspaceLink } from './browser-links.js';
2
+ import { api } from './auth.js';
3
+ import { CliError } from './http.js';
4
+ import { selectOne } from './prompts.js';
5
+ import { identifier } from './world-contracts.js';
6
+ import { trialActions } from './trial-actions.js';
7
+ const statusNames = { '': 'All responses', http_error: 'Response errors', unconfirmed: 'Response not confirmed' };
8
+ const receiptNames = { admitted: 'Request recorded', dispatching: 'Dispatch started', response: 'Response received',
9
+ not_sent: 'Not dispatched', uncertain: 'Outcome not confirmed' };
10
+ const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
11
+ export function validateReceiptOptions(options) {
12
+ if (options.page !== undefined && !/^[1-9][0-9]{0,8}$/.test(options.page)
13
+ || (options.search?.length ?? 0) > 200 || /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/.test(options.search ?? '')
14
+ || options.status !== undefined && !Object.hasOwn(statusNames, options.status)) {
15
+ throw new CliError('arguments_invalid', 'Use a positive page, a search up to 200 characters and --status http_error|unconfirmed for service receipts.', 2);
16
+ }
17
+ }
18
+ function responseLabel(row) {
19
+ const value = row.response;
20
+ if (!value || value.disposition === 'unknown')
21
+ return 'Response not confirmed';
22
+ if (value.rpc_error)
23
+ return 'MCP request error';
24
+ if (value.mcp_is_error)
25
+ return 'MCP tool error';
26
+ return value.http_status === null ? 'Response code not recorded' : `HTTP ${value.http_status}`;
27
+ }
28
+ function summary(row) {
29
+ return row.available === false ? `Receipt unavailable\n${row.problem.message}\n${row.id}`
30
+ : `${row.operation} · ${row.service.name} · Revision ${row.service.revision}\n${responseLabel(row)} · ${row.recorded_at}\n${row.id}`;
31
+ }
32
+ async function detail(path, scope, options, output, id, interactive) {
33
+ const row = await api(`${path}/${identifier(id)}`, { actor: scope.owner, workspace: scope.workspace, signal: options.signal });
34
+ if (!row.available || row.id !== identifier(id))
35
+ throw new CliError('service_receipt_unavailable', 'This service receipt could not be read. No operation was repeated.');
36
+ const campaign = identifier(row.trial.campaign_id), trial = identifier(row.trial.id);
37
+ output(row, [summary(row), row.protocol === 'mcp' ? `MCP ${row.mcp_tool}` : `${row.method} ${row.route}`,
38
+ row.mode === 'real' ? 'Real-account connection. Resetting the world does not undo external changes.' : 'Simulated-service connection.',
39
+ row.origin === 'customer_device' ? 'Reported from the local device.' : 'Reported from the cloud sandbox.',
40
+ `Request: ${row.request_bytes.toLocaleString()} bytes`,
41
+ ...(row.response ? [`Response size: ${row.response.response_bytes === null ? 'Not recorded' : row.response.response_bytes.toLocaleString() + ' bytes'}`,
42
+ `Elapsed: ${row.response.elapsed_ms}ms`, `Response recorded: ${row.response.recorded_at}`] : []),
43
+ ...(row.mode === 'real' ? [`Cloud receipt: ${row.real_operation ? receiptNames[row.real_operation.outcome] : 'No receipt retained'}`,
44
+ `Operation result: ${row.real_operation?.business_outcome === 'not_dispatched' ? 'Not dispatched' : 'Not assessed here'}`] : []),
45
+ `Drill ${row.trial.number}: ${row.trial.scenario_name}`,
46
+ `World revision ${row.trial.world_revision}; configuration revision ${row.trial.configuration_revision}`,
47
+ row.captured_actions.supported ? `Captured action records: ${row.captured_actions.count?.toLocaleString() ?? 'Unavailable'}` : 'Payload capture is not available for this connection or response.',
48
+ ...(row.captured_actions.count ? [`Inspect: firedrill report ${campaign} drill ${trial} actions --service-request ${row.id} --workspace ${scope.workspace}`] : []),
49
+ 'A transport response is not an evaluation score.',
50
+ workspaceLink(scope.workspace, `/campaigns/${campaign}/trials/${trial}?view=requests&request=${identifier(row.id)}`)].join('\n'));
51
+ if (interactive && row.captured_actions.count && await selectOne('Inspect receipt evidence', [
52
+ { value: true, label: 'Captured actions and payloads' }, { value: false, label: 'Done' }
53
+ ], options.signal)) {
54
+ await trialActions(`/api/workspaces/${scope.workspace}/campaigns/${campaign}/trials/${trial}`, scope, true, { signal: options.signal, serviceRequest: row.id }, output);
55
+ }
56
+ }
57
+ export async function serviceReceipts(path, scope, options, interactive, output, command, supplied) {
58
+ validateReceiptOptions(options);
59
+ if (supplied) {
60
+ if (options.page !== undefined || options.search !== undefined || options.status !== undefined)
61
+ throw new CliError('arguments_invalid', 'Page, search and response filters apply to receipt lists, not a single receipt.', 2);
62
+ await detail(path, scope, options, output, supplied, interactive);
63
+ return;
64
+ }
65
+ let page = Number(options.page ?? 1);
66
+ while (true) {
67
+ const params = new URLSearchParams({ page: String(page), q: options.search ?? '', status: options.status ?? '' });
68
+ const data = await api(`${path}${path.includes('?') ? '&' : '?'}${params}`, { actor: scope.owner, workspace: scope.workspace, signal: options.signal });
69
+ const continuation = `${command} --workspace ${scope.workspace}${options.search ? ' --search ' + quote(options.search) : ''}${options.status ? ' --status ' + options.status : ''}`;
70
+ output(data, [...data.results.map(summary), ...(!data.count ? ['No matching service receipts.'] : []),
71
+ ...(data.page_unavailable ? [`${data.page_unavailable.toLocaleString()} receipts unavailable on this page. Their outcomes are unknown.`] : []),
72
+ `Page ${data.page}; ${data.count.toLocaleString()} matching retained requests.`,
73
+ ...(data.next ? [`Continue: ${continuation} --page ${page + 1}`] : []),
74
+ 'Reading or refreshing receipts does not repeat a tool operation.'].join('\n\n'));
75
+ if (!interactive)
76
+ return;
77
+ const choices = data.results.flatMap(row => row.available === false ? []
78
+ : [{ value: { kind: 'receipt', row }, label: `${row.operation} · ${row.service.name}`, detail: `${responseLabel(row)} · ${row.recorded_at}` }]);
79
+ if (page > 1)
80
+ choices.push({ value: { kind: 'previous' }, label: 'Previous page' });
81
+ if (data.next)
82
+ choices.push({ value: { kind: 'next' }, label: 'Next page' });
83
+ if (data.page_unavailable)
84
+ choices.push({ value: { kind: 'refresh' }, label: 'Refresh retained receipts' });
85
+ choices.push({ value: { kind: 'done' }, label: 'Done' });
86
+ const selected = await selectOne('Service receipt', choices, options.signal);
87
+ if (selected.kind === 'done')
88
+ return;
89
+ if (selected.kind === 'next') {
90
+ page += 1;
91
+ continue;
92
+ }
93
+ if (selected.kind === 'previous') {
94
+ page -= 1;
95
+ continue;
96
+ }
97
+ if (selected.kind === 'refresh')
98
+ continue;
99
+ if (selected.kind !== 'receipt')
100
+ throw new CliError('selection_invalid', 'Choose a retained service receipt.', 2);
101
+ const row = selected.row;
102
+ const trialPath = `/api/workspaces/${scope.workspace}/campaigns/${identifier(row.trial.campaign_id)}/trials/${identifier(row.trial.id)}/requests`;
103
+ await detail(trialPath, scope, options, output, row.id, interactive);
104
+ }
105
+ }