@pikku/core 0.12.84 → 0.12.86

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 (564) hide show
  1. package/CHANGELOG.md +424 -0
  2. package/dist/bootstrap-compat/root.d.ts +20 -0
  3. package/dist/classification/column-form.d.ts +32 -0
  4. package/dist/classification/column-form.js +42 -0
  5. package/dist/classification/data-classification.d.ts +64 -0
  6. package/dist/classification/index.d.ts +13 -0
  7. package/dist/classification/index.js +2 -0
  8. package/dist/classification/secret-value.d.ts +56 -0
  9. package/dist/classification/secret-value.js +46 -0
  10. package/dist/crypto-utils.d.ts +1 -1
  11. package/dist/ecosystem/agent-scorer.d.ts +1 -1
  12. package/dist/ecosystem/agent.d.ts +4 -1
  13. package/dist/ecosystem/channel/local.d.ts +2 -0
  14. package/dist/ecosystem/channel/local.js +2 -0
  15. package/dist/ecosystem/channel/serverless.d.ts +9 -0
  16. package/dist/ecosystem/channel/serverless.js +1 -0
  17. package/dist/ecosystem/channel.d.ts +3 -0
  18. package/dist/ecosystem/channel.js +1 -0
  19. package/dist/ecosystem/cli.d.ts +1 -1
  20. package/dist/ecosystem/cli.js +1 -1
  21. package/dist/ecosystem/credential.d.ts +1 -0
  22. package/dist/ecosystem/crypto-utils.d.ts +8 -0
  23. package/dist/ecosystem/crypto-utils.js +1 -0
  24. package/dist/ecosystem/dev.d.ts +1 -0
  25. package/dist/ecosystem/dev.js +1 -0
  26. package/{src/ecosystem/testing.ts → dist/ecosystem/errors.d.ts} +3 -3
  27. package/dist/ecosystem/errors.js +2 -0
  28. package/dist/ecosystem/function.d.ts +1 -1
  29. package/dist/ecosystem/function.js +1 -1
  30. package/dist/ecosystem/http.d.ts +3 -1
  31. package/dist/ecosystem/http.js +3 -1
  32. package/dist/ecosystem/mcp.d.ts +1 -1
  33. package/dist/ecosystem/mcp.js +1 -1
  34. package/dist/ecosystem/middleware.d.ts +2 -1
  35. package/dist/ecosystem/middleware.js +2 -1
  36. package/dist/ecosystem/persona.d.ts +4 -2
  37. package/dist/ecosystem/persona.js +2 -1
  38. package/dist/ecosystem/queue.d.ts +4 -2
  39. package/dist/ecosystem/queue.js +3 -1
  40. package/dist/ecosystem/role.d.ts +1 -0
  41. package/dist/ecosystem/rpc.d.ts +2 -0
  42. package/dist/ecosystem/rpc.js +1 -0
  43. package/dist/ecosystem/scenario.d.ts +8 -2
  44. package/dist/ecosystem/scenario.js +5 -1
  45. package/dist/ecosystem/scheduler.d.ts +2 -1
  46. package/dist/ecosystem/scheduler.js +2 -1
  47. package/dist/ecosystem/schema.d.ts +2 -1
  48. package/dist/ecosystem/schema.js +1 -1
  49. package/dist/ecosystem/scope.d.ts +2 -0
  50. package/dist/ecosystem/scope.js +1 -0
  51. package/dist/ecosystem/secret.d.ts +2 -0
  52. package/dist/ecosystem/secret.js +1 -0
  53. package/dist/ecosystem/services/local-content.d.ts +2 -1
  54. package/dist/ecosystem/services/local-content.js +1 -1
  55. package/dist/ecosystem/services/local-meta.d.ts +1 -0
  56. package/dist/ecosystem/services/local-meta.js +1 -0
  57. package/dist/ecosystem/services.d.ts +11 -3
  58. package/dist/ecosystem/services.js +7 -1
  59. package/dist/ecosystem/trigger.d.ts +1 -0
  60. package/dist/ecosystem/trigger.js +1 -1
  61. package/dist/ecosystem/types.d.ts +6 -3
  62. package/dist/ecosystem/types.js +3 -2
  63. package/dist/ecosystem/variable.d.ts +1 -0
  64. package/dist/ecosystem/virtual-user.d.ts +3 -0
  65. package/dist/ecosystem/virtual-user.js +3 -0
  66. package/dist/ecosystem/workflow.d.ts +2 -0
  67. package/dist/ecosystem/workflow.js +2 -0
  68. package/dist/errors/index.d.ts +8 -0
  69. package/dist/errors/index.js +1 -0
  70. package/dist/errors/serialized-error.d.ts +7 -0
  71. package/dist/function/function-meta.types.d.ts +139 -0
  72. package/dist/function/function-runner.d.ts +3 -2
  73. package/dist/function/function-runner.js +31 -11
  74. package/dist/function/functions.types.d.ts +10 -2
  75. package/dist/function/index.d.ts +8 -2
  76. package/dist/function/index.js +4 -1
  77. package/dist/function/pikku-request.d.ts +8 -0
  78. package/dist/function/pikku-request.js +15 -0
  79. package/dist/middleware/auth-apikey.d.ts +2 -10
  80. package/dist/middleware/auth-apikey.js +1 -1
  81. package/dist/middleware/auth-bearer.d.ts +2 -10
  82. package/dist/middleware/auth-bearer.js +1 -1
  83. package/dist/middleware/auth-cookie.d.ts +2 -10
  84. package/dist/middleware/auth-cookie.js +1 -1
  85. package/dist/middleware/cors.d.ts +5 -11
  86. package/dist/middleware/cors.js +13 -6
  87. package/dist/middleware/index.d.ts +3 -0
  88. package/dist/middleware/index.js +1 -0
  89. package/dist/middleware/middleware-factories.d.ts +9 -0
  90. package/dist/middleware/middleware-factories.js +19 -0
  91. package/dist/middleware/middleware.types.d.ts +27 -0
  92. package/dist/middleware/middleware.types.js +1 -0
  93. package/dist/middleware/remote-auth.d.ts +2 -2
  94. package/dist/middleware/remote-auth.js +1 -1
  95. package/dist/middleware/telemetry.d.ts +4 -20
  96. package/dist/middleware/telemetry.js +1 -1
  97. package/dist/middleware-runner.d.ts +2 -1
  98. package/dist/pikku-state.d.ts +2 -1
  99. package/dist/services/audit-service.d.ts +1 -1
  100. package/dist/services/credential-wire-service.js +1 -1
  101. package/dist/services/email-service.d.ts +1 -1
  102. package/dist/services/file-scenario-run-store.d.ts +58 -0
  103. package/dist/services/file-scenario-run-store.js +214 -0
  104. package/dist/services/in-memory-workflow-service.d.ts +1 -1
  105. package/dist/services/index.d.ts +5 -1
  106. package/dist/services/index.js +3 -0
  107. package/dist/services/local-secrets.d.ts +1 -1
  108. package/dist/services/local-secrets.js +1 -1
  109. package/dist/services/logger.d.ts +7 -7
  110. package/dist/services/meta-service.d.ts +2 -1
  111. package/dist/services/scoped-secret-service.d.ts +1 -1
  112. package/dist/services/secret-service.d.ts +1 -1
  113. package/dist/services/typed-secret-service.d.ts +16 -2
  114. package/dist/services/typed-secret-service.js +5 -0
  115. package/dist/services/webhook-service.d.ts +1 -1
  116. package/dist/services/workflow-service.d.ts +2 -1
  117. package/dist/testing/index.d.ts +1 -0
  118. package/dist/testing/index.js +1 -0
  119. package/dist/types/core.types.d.ts +30 -180
  120. package/dist/types/core.types.js +1 -19
  121. package/dist/types/index.d.ts +2 -0
  122. package/dist/types/index.js +1 -0
  123. package/dist/types/state.types.d.ts +3 -1
  124. package/dist/utils.d.ts +13 -0
  125. package/dist/utils.js +2 -0
  126. package/dist/wirings/addon/addon-runner.d.ts +17 -0
  127. package/dist/wirings/addon/addon-runner.js +150 -0
  128. package/dist/wirings/addon/index.d.ts +6 -0
  129. package/dist/wirings/addon/index.js +3 -0
  130. package/dist/wirings/addon/remote-addon-auth.d.ts +16 -0
  131. package/dist/wirings/addon/remote-addon-auth.js +39 -0
  132. package/dist/wirings/addon/wire-addon.d.ts +80 -0
  133. package/dist/wirings/addon/wire-addon.js +120 -0
  134. package/dist/wirings/addon/wire-remote-addon.d.ts +22 -0
  135. package/dist/wirings/addon/wire-remote-addon.js +11 -0
  136. package/dist/wirings/agent/agent-prepare.d.ts +3 -3
  137. package/dist/wirings/agent/agent-prepare.js +1 -1
  138. package/dist/wirings/agent/agent-runner.js +2 -3
  139. package/dist/wirings/agent/agent-stream.js +2 -2
  140. package/dist/wirings/agent/agent-utils.d.ts +13 -0
  141. package/dist/wirings/agent/agent-utils.js +16 -0
  142. package/dist/wirings/agent/agent.types.d.ts +3 -2
  143. package/dist/wirings/agent/index.d.ts +1 -1
  144. package/dist/wirings/agent/voice-input.js +1 -1
  145. package/dist/wirings/agent/voice-output.js +1 -1
  146. package/dist/wirings/agent-scorer/agent-scorer-judge.d.ts +13 -0
  147. package/dist/wirings/agent-scorer/agent-scorer-judge.js +52 -0
  148. package/dist/wirings/agent-scorer/agent-scorer.d.ts +7 -1
  149. package/dist/wirings/agent-scorer/agent-scorer.js +1 -0
  150. package/dist/wirings/agent-scorer/agent-scorer.types.d.ts +20 -0
  151. package/dist/wirings/agent-scorer/index.d.ts +1 -1
  152. package/dist/wirings/channel/channel-common.d.ts +2 -1
  153. package/dist/wirings/channel/channel-middleware-runner.d.ts +2 -1
  154. package/dist/wirings/channel/channel.types.d.ts +1 -1
  155. package/dist/wirings/channel/serverless/index.d.ts +1 -0
  156. package/dist/wirings/cli/channel/index.d.ts +1 -1
  157. package/dist/wirings/cli/cli-runner.d.ts +2 -1
  158. package/dist/wirings/cli/cli-runner.js +4 -1
  159. package/dist/wirings/cli/cli.types.d.ts +21 -2
  160. package/dist/wirings/cli/command-parser.js +157 -23
  161. package/dist/wirings/gateway/gateway.types.d.ts +2 -1
  162. package/dist/wirings/http/http-runner.d.ts +1 -1
  163. package/dist/wirings/http/http-runner.js +1 -1
  164. package/dist/wirings/http/http.types.d.ts +2 -2
  165. package/dist/wirings/http/index.d.ts +1 -0
  166. package/dist/wirings/http/index.js +1 -0
  167. package/dist/wirings/http/pikku-fetch-http-request.js +1 -1
  168. package/dist/wirings/http/pikku-fetch-http-response.js +2 -2
  169. package/dist/wirings/mcp/mcp.types.d.ts +1 -1
  170. package/dist/wirings/persona/index.d.ts +1 -1
  171. package/dist/wirings/persona/index.js +1 -1
  172. package/dist/wirings/persona/persona.types.d.ts +14 -0
  173. package/dist/wirings/queue/queue.types.d.ts +1 -1
  174. package/dist/wirings/queue/signed-queue-service.d.ts +1 -1
  175. package/dist/wirings/rpc/index.d.ts +0 -6
  176. package/dist/wirings/rpc/index.js +0 -3
  177. package/dist/wirings/rpc/remote-addon-auth.d.ts +1 -1
  178. package/dist/wirings/rpc/remote-addon-auth.js +1 -1
  179. package/dist/wirings/rpc/rpc-runner.js +2 -2
  180. package/dist/wirings/rpc/wire-addon.d.ts +1 -1
  181. package/dist/wirings/scheduler/scheduler.types.d.ts +2 -1
  182. package/dist/wirings/scope/index.d.ts +1 -0
  183. package/dist/wirings/scope/index.js +1 -0
  184. package/dist/wirings/secret/secret.types.d.ts +10 -0
  185. package/dist/wirings/secret/validate-secret-definitions.js +2 -0
  186. package/dist/wirings/variable/validate-variable-definitions.js +2 -0
  187. package/dist/wirings/variable/variable.types.d.ts +9 -0
  188. package/dist/wirings/virtual-user/index.d.ts +1 -1
  189. package/dist/wirings/virtual-user/index.js +1 -1
  190. package/dist/wirings/virtual-user/prepare-virtual-user-run.d.ts +1 -1
  191. package/dist/wirings/virtual-user/virtual-user-derive.d.ts +1 -1
  192. package/dist/wirings/workflow/graph/graph-node.d.ts +9 -2
  193. package/dist/wirings/workflow/graph/graph-node.js +2 -0
  194. package/dist/wirings/workflow/graph/graph-runner.d.ts +1 -0
  195. package/dist/wirings/workflow/graph/graph-runner.js +283 -31
  196. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +16 -1
  197. package/dist/wirings/workflow/index.d.ts +2 -0
  198. package/dist/wirings/workflow/index.js +1 -0
  199. package/dist/wirings/workflow/pikku-scenario-service.d.ts +14 -4
  200. package/dist/wirings/workflow/pikku-scenario-service.js +44 -16
  201. package/dist/wirings/workflow/pikku-workflow-service.d.ts +2 -1
  202. package/dist/wirings/workflow/pikku-workflow-service.js +3 -4
  203. package/dist/wirings/workflow/run-timeline.d.ts +1 -1
  204. package/dist/wirings/workflow/scenario-run.types.d.ts +171 -0
  205. package/dist/wirings/workflow/scenario-run.types.js +1 -0
  206. package/dist/wirings/workflow/scenario-step-guards.d.ts +1 -2
  207. package/dist/wirings/workflow/scenario-step-guards.js +0 -8
  208. package/dist/wirings/workflow/scenario-step.types.d.ts +27 -12
  209. package/dist/wirings/workflow/workflow-approval.js +2 -1
  210. package/dist/wirings/workflow/workflow-run-engine.types.d.ts +2 -1
  211. package/dist/wirings/workflow/workflow.types.d.ts +2 -1
  212. package/knowledge/decisions/index.md +2 -0
  213. package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +1 -1
  214. package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +1 -1
  215. package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-and-not-a-queued-job.md +2 -2
  216. package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +6 -6
  217. package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +1 -1
  218. package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +1 -1
  219. package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +1 -1
  220. package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +1 -1
  221. package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +1 -1
  222. package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +1 -1
  223. package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +1 -1
  224. package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +1 -1
  225. package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +1 -1
  226. package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +1 -1
  227. package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +4 -4
  228. package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +1 -1
  229. package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +3 -3
  230. package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +2 -2
  231. package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +2 -2
  232. package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +1 -1
  233. package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +1 -1
  234. package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +3 -3
  235. package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +1 -1
  236. package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +4 -4
  237. package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +1 -1
  238. package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +1 -1
  239. package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +1 -1
  240. package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +1 -1
  241. package/knowledge/decisions/internals/index.md +4 -2
  242. package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +1 -1
  243. package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +1 -1
  244. package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +1 -1
  245. package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +1 -1
  246. package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +1 -1
  247. package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +2 -2
  248. package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +5 -5
  249. package/knowledge/decisions/internals/the-actor-prompt-says-json-because-of-json-object-mode.md +1 -1
  250. package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +1 -1
  251. package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +43 -19
  252. package/knowledge/decisions/internals/the-persona-runtime-is-exported-from-the-persona-entry-point.md +1 -1
  253. package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +1 -1
  254. package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +3 -3
  255. package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +1 -1
  256. package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +1 -1
  257. package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +1 -1
  258. package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +1 -1
  259. package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +1 -1
  260. package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +1 -1
  261. package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +1 -1
  262. package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +1 -1
  263. package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +1 -1
  264. package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +9 -5
  265. package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +1 -1
  266. package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +2 -2
  267. package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +1 -1
  268. package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +1 -1
  269. package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +1 -1
  270. package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +2 -3
  271. package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +1 -1
  272. package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +1 -1
  273. package/knowledge/decisions/security/agent-gate-requires-a-session-only-when-auth-is-true.md +1 -1
  274. package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +3 -3
  275. package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +4 -3
  276. package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +1 -1
  277. package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +2 -2
  278. package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +1 -1
  279. package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +2 -2
  280. package/knowledge/decisions/security/index.md +2 -0
  281. package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +1 -1
  282. package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +3 -3
  283. package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +1 -1
  284. package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +2 -2
  285. package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +1 -1
  286. package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +2 -2
  287. package/knowledge/index.md +3 -1
  288. package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +1 -1
  289. package/knowledge/questions/index.md +2 -0
  290. package/package.json +14 -13
  291. package/run-tests.sh +0 -0
  292. package/scripts/generate-api-report.d.mts +1 -1
  293. package/scripts/generate-api-report.mjs +67 -60
  294. package/scripts/generate-api-report.mts +11 -45
  295. package/src/api-report.test.ts +70 -1
  296. package/src/app-alias-surface.test.ts +179 -0
  297. package/src/app-leaf-surface.test.ts +217 -0
  298. package/src/bootstrap-compat/root.ts +20 -0
  299. package/src/{column-form.test.ts → classification/column-form.test.ts} +2 -2
  300. package/src/{data-classification.ts → classification/data-classification.ts} +1 -5
  301. package/src/classification/index.ts +38 -0
  302. package/src/{secret-value.test.ts → classification/secret-value.test.ts} +2 -2
  303. package/src/{secret-value.ts → classification/secret-value.ts} +1 -6
  304. package/src/crypto-utils.ts +1 -1
  305. package/src/dev/reload-meta.test.ts +1 -1
  306. package/src/errors/index.ts +9 -0
  307. package/src/errors/serialized-error.ts +9 -0
  308. package/src/factory-functions.test.ts +4 -2
  309. package/src/function/function-meta.types.ts +151 -0
  310. package/src/function/function-runner.test.ts +4 -2
  311. package/src/function/function-runner.ts +47 -14
  312. package/src/function/functions.types.ts +11 -7
  313. package/src/function/index.ts +24 -5
  314. package/src/function/list.types.ts +1 -3
  315. package/src/middleware/auth-apikey.ts +4 -2
  316. package/src/middleware/auth-bearer.test.ts +1 -1
  317. package/src/middleware/auth-bearer.ts +4 -2
  318. package/src/middleware/auth-cookie.ts +4 -1
  319. package/src/middleware/cors.test.ts +126 -5
  320. package/src/middleware/cors.ts +19 -8
  321. package/src/middleware/index.ts +16 -0
  322. package/src/middleware/middleware-factories.ts +62 -0
  323. package/src/middleware/middleware.types.ts +61 -0
  324. package/src/middleware/remote-auth.test.ts +1 -1
  325. package/src/middleware/remote-auth.ts +1 -1
  326. package/src/middleware/telemetry.ts +4 -2
  327. package/src/middleware-runner.test.ts +2 -3
  328. package/src/middleware-runner.ts +2 -2
  329. package/src/no-root-barrel.test.ts +114 -0
  330. package/src/permissions.ts +2 -4
  331. package/src/pikku-state.ts +3 -1
  332. package/src/public-surface.json +56 -241
  333. package/src/public-surface.json.README +3 -3
  334. package/src/public-surface.test.ts +5 -5
  335. package/src/remote.test.ts +1 -1
  336. package/src/removed-legacy-exports.test.ts +5 -1
  337. package/src/services/audit-service.ts +1 -1
  338. package/src/services/credential-wire-service.ts +1 -1
  339. package/src/services/email-service.ts +2 -4
  340. package/src/services/file-scenario-run-store.test.ts +349 -0
  341. package/src/services/file-scenario-run-store.ts +282 -0
  342. package/src/services/in-memory-workflow-service.ts +1 -1
  343. package/src/services/index.ts +13 -1
  344. package/src/services/local-content-request-handler.ts +1 -2
  345. package/src/services/local-secrets.ts +1 -1
  346. package/src/services/logger.ts +7 -7
  347. package/src/services/meta-service.ts +2 -2
  348. package/src/services/queue-webhook-service.test.ts +1 -1
  349. package/src/services/scoped-secret-service.ts +1 -1
  350. package/src/services/secret-service.ts +1 -1
  351. package/src/services/typed-secret-service.test.ts +52 -0
  352. package/src/services/typed-secret-service.ts +26 -2
  353. package/src/services/webhook-service.ts +1 -1
  354. package/src/services/workflow-service.ts +2 -1
  355. package/src/template-alias-surface.test.ts +240 -0
  356. package/src/testing/index.ts +1 -0
  357. package/src/types/core.types.ts +33 -285
  358. package/src/types/index.ts +2 -0
  359. package/src/types/state.types.ts +6 -5
  360. package/src/types/typed-credentials.test.ts +72 -0
  361. package/src/utils.ts +34 -0
  362. package/src/wirings/{rpc → addon}/addon-scopes.test.ts +1 -1
  363. package/src/wirings/addon/index.ts +12 -0
  364. package/src/wirings/{rpc → addon}/remote-addon-auth.ts +4 -1
  365. package/src/wirings/{rpc → addon}/wire-addon.ts +37 -2
  366. package/src/wirings/agent/agent-prepare.ts +8 -5
  367. package/src/wirings/agent/agent-runner.ts +2 -3
  368. package/src/wirings/agent/agent-stream.ts +2 -3
  369. package/src/wirings/agent/agent-utils.ts +19 -0
  370. package/src/wirings/agent/agent.types.ts +3 -3
  371. package/src/wirings/agent/index.ts +1 -0
  372. package/src/wirings/agent/voice-input.ts +1 -1
  373. package/src/wirings/agent/voice-output.test.ts +2 -4
  374. package/src/wirings/agent/voice-output.ts +1 -1
  375. package/src/wirings/agent-scorer/agent-scorer-judge.test.ts +145 -0
  376. package/src/wirings/agent-scorer/agent-scorer-judge.ts +60 -0
  377. package/src/wirings/agent-scorer/agent-scorer.ts +8 -0
  378. package/src/wirings/agent-scorer/agent-scorer.types.ts +21 -0
  379. package/src/wirings/agent-scorer/index.ts +1 -0
  380. package/src/wirings/channel/channel-common.ts +4 -2
  381. package/src/wirings/channel/channel-handler.ts +2 -5
  382. package/src/wirings/channel/channel-middleware-runner.ts +1 -1
  383. package/src/wirings/channel/channel-rpc.types.ts +1 -5
  384. package/src/wirings/channel/channel.types.ts +1 -2
  385. package/src/wirings/channel/local/local-channel-runner.test.ts +1 -2
  386. package/src/wirings/channel/serverless/index.ts +1 -0
  387. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +2 -2
  388. package/src/wirings/cli/channel/index.ts +1 -3
  389. package/src/wirings/cli/cli-runner.test.ts +1 -1
  390. package/src/wirings/cli/cli-runner.ts +11 -7
  391. package/src/wirings/cli/cli.types.ts +24 -3
  392. package/src/wirings/cli/command-parser.test.ts +388 -1
  393. package/src/wirings/cli/command-parser.ts +189 -29
  394. package/src/wirings/gateway/gateway-runner.test.ts +1 -2
  395. package/src/wirings/gateway/gateway-runner.ts +3 -6
  396. package/src/wirings/gateway/gateway.types.ts +5 -4
  397. package/src/wirings/http/http-routes.test.ts +1 -2
  398. package/src/wirings/http/http-runner-addon-ref.test.ts +238 -0
  399. package/src/wirings/http/http-runner.test.ts +3 -8
  400. package/src/wirings/http/http-runner.ts +9 -3
  401. package/src/wirings/http/http.types.ts +3 -12
  402. package/src/wirings/http/index.ts +1 -0
  403. package/src/wirings/http/pikku-fetch-http-request.ts +1 -1
  404. package/src/wirings/http/pikku-fetch-http-response.ts +3 -2
  405. package/src/wirings/mcp/mcp-runner.test.ts +1 -1
  406. package/src/wirings/mcp/mcp.types.ts +1 -2
  407. package/src/wirings/persona/index.ts +1 -4
  408. package/src/wirings/persona/persona.types.ts +14 -0
  409. package/src/wirings/queue/queue-identity.test.ts +1 -1
  410. package/src/wirings/queue/queue.types.ts +2 -6
  411. package/src/wirings/queue/signed-queue-service.ts +1 -1
  412. package/src/wirings/rpc/index.ts +0 -12
  413. package/src/wirings/rpc/rpc-runner.test.ts +4 -4
  414. package/src/wirings/rpc/rpc-runner.ts +3 -3
  415. package/src/wirings/scheduler/scheduler.types.ts +2 -5
  416. package/src/wirings/scope/index.ts +1 -0
  417. package/src/wirings/secret/secret.types.ts +10 -0
  418. package/src/wirings/secret/validate-secret-definitions.test.ts +23 -0
  419. package/src/wirings/secret/validate-secret-definitions.ts +2 -0
  420. package/src/wirings/variable/validate-variable-definitions.test.ts +23 -0
  421. package/src/wirings/variable/validate-variable-definitions.ts +2 -0
  422. package/src/wirings/variable/variable.types.ts +9 -0
  423. package/src/wirings/virtual-user/index.ts +1 -4
  424. package/src/wirings/virtual-user/prepare-virtual-user-run.ts +1 -1
  425. package/src/wirings/virtual-user/virtual-user-derive.test.ts +1 -1
  426. package/src/wirings/virtual-user/virtual-user-derive.ts +1 -1
  427. package/src/wirings/virtual-user/virtual-user.types.ts +1 -5
  428. package/src/wirings/workflow/graph/graph-foreach-queued.test.ts +569 -0
  429. package/src/wirings/workflow/graph/graph-foreach.test.ts +626 -0
  430. package/src/wirings/workflow/graph/graph-node.ts +16 -1
  431. package/src/wirings/workflow/graph/graph-runner.ts +387 -61
  432. package/src/wirings/workflow/graph/workflow-graph.types.ts +28 -3
  433. package/src/wirings/workflow/index.ts +8 -0
  434. package/src/wirings/workflow/pikku-scenario-service.ts +59 -19
  435. package/src/wirings/workflow/pikku-workflow-service.ts +6 -8
  436. package/src/wirings/workflow/run-timeline.ts +1 -1
  437. package/src/wirings/workflow/scenario-expectations.test.ts +28 -13
  438. package/src/wirings/workflow/scenario-run.types.ts +186 -0
  439. package/src/wirings/workflow/scenario-step-guards.ts +1 -14
  440. package/src/wirings/workflow/scenario-step.test.ts +32 -7
  441. package/src/wirings/workflow/scenario-step.types.ts +27 -12
  442. package/src/wirings/workflow/workflow-approval-policy.test.ts +117 -47
  443. package/src/wirings/workflow/workflow-approval.ts +2 -1
  444. package/src/wirings/workflow/workflow-run-engine.types.ts +2 -1
  445. package/src/wirings/workflow/workflow.types.ts +4 -12
  446. package/src/wirings-stay-decoupled.test.ts +6 -3
  447. package/tsconfig.tsbuildinfo +1 -1
  448. package/tsconfig.type-tests.json +3 -2
  449. package/dist/ecosystem/ai-agent.d.ts +0 -18
  450. package/dist/ecosystem/ai-agent.js +0 -6
  451. package/dist/ecosystem/ai-scorer.d.ts +0 -12
  452. package/dist/ecosystem/ai-scorer.js +0 -5
  453. package/dist/services/ai-agent-runner-service.d.ts +0 -220
  454. package/dist/services/ai-run-state-service.d.ts +0 -29
  455. package/dist/services/ai-storage-service.d.ts +0 -18
  456. package/dist/services/in-memory-ai-run-state-service.d.ts +0 -19
  457. package/dist/services/in-memory-ai-run-state-service.js +0 -54
  458. package/dist/testing/service-tests/ai-storage-service-tests.d.ts +0 -3
  459. package/dist/testing/service-tests/ai-storage-service-tests.js +0 -302
  460. package/dist/wirings/ai-agent/agent-rpc.d.ts +0 -15
  461. package/dist/wirings/ai-agent/agent-rpc.js +0 -53
  462. package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -79
  463. package/dist/wirings/ai-agent/ai-agent-agui.js +0 -327
  464. package/dist/wirings/ai-agent/ai-agent-finalize.d.ts +0 -58
  465. package/dist/wirings/ai-agent/ai-agent-finalize.js +0 -138
  466. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +0 -35
  467. package/dist/wirings/ai-agent/ai-agent-helpers.js +0 -47
  468. package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +0 -153
  469. package/dist/wirings/ai-agent/ai-agent-interrupt.js +0 -257
  470. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +0 -42
  471. package/dist/wirings/ai-agent/ai-agent-memory.js +0 -333
  472. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -16
  473. package/dist/wirings/ai-agent/ai-agent-model-config.js +0 -51
  474. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +0 -117
  475. package/dist/wirings/ai-agent/ai-agent-prepare.js +0 -728
  476. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +0 -16
  477. package/dist/wirings/ai-agent/ai-agent-registry.js +0 -51
  478. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +0 -7
  479. package/dist/wirings/ai-agent/ai-agent-runner.js +0 -580
  480. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +0 -41
  481. package/dist/wirings/ai-agent/ai-agent-stream.js +0 -1029
  482. package/dist/wirings/ai-agent/ai-agent-turn.d.ts +0 -57
  483. package/dist/wirings/ai-agent/ai-agent-turn.js +0 -82
  484. package/dist/wirings/ai-agent/ai-agent-utils.d.ts +0 -1
  485. package/dist/wirings/ai-agent/ai-agent-utils.js +0 -1
  486. package/dist/wirings/ai-agent/ai-agent.types.d.ts +0 -625
  487. package/dist/wirings/ai-agent/index.d.ts +0 -12
  488. package/dist/wirings/ai-agent/index.js +0 -10
  489. package/dist/wirings/ai-agent/voice-input.d.ts +0 -69
  490. package/dist/wirings/ai-agent/voice-input.js +0 -150
  491. package/dist/wirings/ai-agent/voice-output.d.ts +0 -85
  492. package/dist/wirings/ai-agent/voice-output.js +0 -196
  493. package/dist/wirings/ai-scorer/ai-scorer-grade.d.ts +0 -26
  494. package/dist/wirings/ai-scorer/ai-scorer-grade.js +0 -33
  495. package/dist/wirings/ai-scorer/ai-scorer-judge.d.ts +0 -17
  496. package/dist/wirings/ai-scorer/ai-scorer-judge.js +0 -92
  497. package/dist/wirings/ai-scorer/ai-scorer-live.d.ts +0 -15
  498. package/dist/wirings/ai-scorer/ai-scorer-live.js +0 -38
  499. package/dist/wirings/ai-scorer/ai-scorer-registry.d.ts +0 -18
  500. package/dist/wirings/ai-scorer/ai-scorer-registry.js +0 -46
  501. package/dist/wirings/ai-scorer/ai-scorer-sampling.d.ts +0 -8
  502. package/dist/wirings/ai-scorer/ai-scorer-sampling.js +0 -31
  503. package/dist/wirings/ai-scorer/ai-scorer-snapshots.d.ts +0 -10
  504. package/dist/wirings/ai-scorer/ai-scorer-snapshots.js +0 -40
  505. package/dist/wirings/ai-scorer/ai-scorer-worker.d.ts +0 -15
  506. package/dist/wirings/ai-scorer/ai-scorer-worker.js +0 -58
  507. package/dist/wirings/ai-scorer/ai-scorer.d.ts +0 -39
  508. package/dist/wirings/ai-scorer/ai-scorer.js +0 -40
  509. package/dist/wirings/ai-scorer/ai-scorer.types.d.ts +0 -90
  510. package/dist/wirings/ai-scorer/ai-scorer.types.js +0 -4
  511. package/dist/wirings/ai-scorer/index.d.ts +0 -6
  512. package/dist/wirings/ai-scorer/index.js +0 -5
  513. package/src/ecosystem/agent-scorer.ts +0 -24
  514. package/src/ecosystem/agent.ts +0 -42
  515. package/src/ecosystem/channel/local.ts +0 -1
  516. package/src/ecosystem/channel.ts +0 -22
  517. package/src/ecosystem/cli/channel.ts +0 -25
  518. package/src/ecosystem/cli.ts +0 -21
  519. package/src/ecosystem/credential.ts +0 -10
  520. package/src/ecosystem/dev.ts +0 -12
  521. package/src/ecosystem/function.ts +0 -28
  522. package/src/ecosystem/gateway.ts +0 -4
  523. package/src/ecosystem/hmac.ts +0 -1
  524. package/src/ecosystem/http.ts +0 -22
  525. package/src/ecosystem/mcp.ts +0 -17
  526. package/src/ecosystem/middleware.ts +0 -27
  527. package/src/ecosystem/node-host-resolver.ts +0 -1
  528. package/src/ecosystem/node.ts +0 -5
  529. package/src/ecosystem/oauth2.ts +0 -4
  530. package/src/ecosystem/persona.ts +0 -30
  531. package/src/ecosystem/queue.ts +0 -23
  532. package/src/ecosystem/remote.ts +0 -9
  533. package/src/ecosystem/role.ts +0 -13
  534. package/src/ecosystem/rpc.ts +0 -7
  535. package/src/ecosystem/safe-fetch.ts +0 -8
  536. package/src/ecosystem/scenario.ts +0 -32
  537. package/src/ecosystem/scheduler.ts +0 -5
  538. package/src/ecosystem/schema.ts +0 -1
  539. package/src/ecosystem/scope.ts +0 -14
  540. package/src/ecosystem/secret.ts +0 -15
  541. package/src/ecosystem/services/istanbul-coverage.ts +0 -1
  542. package/src/ecosystem/services/local-content-request-handler.ts +0 -16
  543. package/src/ecosystem/services/local-content.ts +0 -1
  544. package/src/ecosystem/services/v8-coverage.ts +0 -1
  545. package/src/ecosystem/services.ts +0 -82
  546. package/src/ecosystem/trigger.ts +0 -7
  547. package/src/ecosystem/types.ts +0 -34
  548. package/src/ecosystem/variable.ts +0 -14
  549. package/src/ecosystem/virtual-user.ts +0 -48
  550. package/src/ecosystem/workflow.ts +0 -68
  551. package/src/ecosystem.ts +0 -40
  552. package/src/index.ts +0 -244
  553. /package/dist/{services/ai-agent-runner-service.js → bootstrap-compat/root.js} +0 -0
  554. /package/dist/{services/ai-run-state-service.js → classification/data-classification.js} +0 -0
  555. /package/dist/{services/ai-storage-service.js → errors/serialized-error.js} +0 -0
  556. /package/dist/{wirings/ai-agent/ai-agent.types.js → function/function-meta.types.js} +0 -0
  557. /package/src/{column-form.ts → classification/column-form.ts} +0 -0
  558. /package/src/{pikku-request.test.ts → function/pikku-request.test.ts} +0 -0
  559. /package/src/{pikku-request.ts → function/pikku-request.ts} +0 -0
  560. /package/src/wirings/{rpc → addon}/addon-auth-tags.test.ts +0 -0
  561. /package/src/wirings/{rpc → addon}/addon-runner.ts +0 -0
  562. /package/src/wirings/{rpc → addon}/addon-secrets.test.ts +0 -0
  563. /package/src/wirings/{rpc → addon}/wire-addon.test.ts +0 -0
  564. /package/src/wirings/{rpc → addon}/wire-remote-addon.ts +0 -0
@@ -1,4 +1,5 @@
1
- import type { CoreUserSession, SerializedError } from '../../types/core.types.js';
1
+ import type { CoreUserSession } from '../../types/core.types.js';
2
+ import type { SerializedError } from '../../errors/serialized-error.js';
2
3
  import type { GroupConcurrencyConfig, JobGroup, JobOptions } from '../queue/queue.types.js';
3
4
  import type { PikkuWorkflowWire, StepState, StepStatus, WorkflowPlannedStep, WorkflowRun, WorkflowRunMirror, WorkflowRunStatus, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, WorkflowQueueOptions, WorkflowStepOptions } from './workflow.types.js';
4
5
  import type { WorkflowService } from '../../services/workflow-service.js';
@@ -1,7 +1,7 @@
1
1
  import { runPikkuFunc } from '../../function/function-runner.js';
2
2
  import { getSingletonServices, getCreateWireServices, pikkuState, } from '../../pikku-state.js';
3
3
  import { getDurationInMilliseconds } from '../../time-utils.js';
4
- import { ChildWorkflowStartedException, continueGraph, executeGraphStep, runWorkflowGraph, runFromMeta, } from './graph/graph-runner.js';
4
+ import { ChildWorkflowStartedException, continueGraph, executeGraphStep, runWorkflowGraph, runFromMeta, stripInstanceOrdinal, } from './graph/graph-runner.js';
5
5
  import { isExpectedError } from '../../errors/error-handler.js';
6
6
  import { PikkuMissingMetaError } from '../../errors/errors.js';
7
7
  import { RPCNotFoundError } from '../rpc/rpc-runner.js';
@@ -735,9 +735,8 @@ export class PikkuWorkflowService {
735
735
  graphNodeId = stepName;
736
736
  }
737
737
  else {
738
- const hash = stepName.lastIndexOf('#');
739
- const base = hash > 0 ? stepName.slice(0, hash) : undefined;
740
- if (base && base in workflowMeta.nodes)
738
+ const base = stripInstanceOrdinal(stepName);
739
+ if (base !== stepName && base in workflowMeta.nodes)
741
740
  graphNodeId = base;
742
741
  }
743
742
  }
@@ -1,4 +1,4 @@
1
- import type { SerializedError } from '../../types/core.types.js';
1
+ import type { SerializedError } from '../../errors/serialized-error.js';
2
2
  import type { StepState, StepStatus } from './workflow.types.js';
3
3
  export interface RunTimelineEvent {
4
4
  seq: number;
@@ -0,0 +1,171 @@
1
+ /**
2
+ * What one `pikku scenario run` leaves behind.
3
+ *
4
+ * A run is history: the scenarios it selected, the sentences they were made of,
5
+ * and the images and footage they produced. The sentences are snapshotted into
6
+ * the record rather than looked up later, because a scenario is code and the
7
+ * code moves — a run from last week describes a suite that no longer exists,
8
+ * and re-deriving its ladder from today's source would quietly rewrite it.
9
+ *
10
+ * Everything here is plain serialisable data. That is what lets one record be
11
+ * a JSON file on disk in OSS and a row in Postgres on a hosted project, read
12
+ * back by the same console screen either way.
13
+ */
14
+ import type { ScenarioBrowserFailure } from './scenario-step.types.js';
15
+ /** What a run filed, in the order it filed it. */
16
+ export type ScenarioArtifactKind = 'screenshot' | 'failure' | 'video';
17
+ /**
18
+ * One image or recording a scenario produced.
19
+ *
20
+ * `path` is relative to the run's artifact root and always uses forward
21
+ * slashes: it is a content key, not a filesystem path. Locally it resolves
22
+ * under the run's directory; on a hosted project it is the object key in a
23
+ * bucket, and the same record works unchanged.
24
+ */
25
+ export interface ScenarioArtifact {
26
+ /** The scenario label this belongs to, as the report names it. */
27
+ scenario: string;
28
+ kind: ScenarioArtifactKind;
29
+ path: string;
30
+ /** Whose window it was — a two-actor scenario produces two of everything. */
31
+ actor?: string;
32
+ /** The caption the scenario author took a screenshot under. */
33
+ name?: string;
34
+ }
35
+ /** One step of a run, already joined to the prose that declared it. */
36
+ export interface ScenarioStepRow {
37
+ sentence: string;
38
+ status: string;
39
+ durationMs?: number;
40
+ error?: string;
41
+ }
42
+ /** Everything known about why one scenario failed. */
43
+ export interface ScenarioFailureDetail {
44
+ /** The rendered sentence of the failing step; absent if no step failed. */
45
+ sentence?: string;
46
+ message: string;
47
+ stack?: string;
48
+ /**
49
+ * True when the failure was a deliberate one (a PikkuError). Its message is
50
+ * the whole story, so the stack is noise.
51
+ */
52
+ expected?: boolean;
53
+ browser?: ScenarioBrowserFailure[];
54
+ }
55
+ export interface ScenarioResult {
56
+ name: string;
57
+ status: 'passed' | 'failed';
58
+ durationMs: number;
59
+ output?: unknown;
60
+ error?: string;
61
+ steps?: ScenarioStepRow[];
62
+ failure?: ScenarioFailureDetail;
63
+ /** The scenario registration this ran, which the label alone does not give. */
64
+ scenarioName?: string;
65
+ /** The feature that grouped it, when one did. */
66
+ feature?: string;
67
+ tags?: string[];
68
+ /** Images and footage this scenario produced, filed under the run. */
69
+ artifacts?: ScenarioArtifact[];
70
+ }
71
+ /** One scenario that was not run, and why. */
72
+ export interface ScenarioSkip {
73
+ name: string;
74
+ reason: string;
75
+ }
76
+ export interface ScenarioRunReport {
77
+ environment: string;
78
+ results: ScenarioResult[];
79
+ /**
80
+ * Scenarios not run at all, each carrying why. A skip is only useful if the
81
+ * reader can tell a browser scenario held back by `--no-browser` from one the
82
+ * project itself quarantined, so the reason travels with the name rather than
83
+ * being assumed by the formatter.
84
+ */
85
+ skipped: ScenarioSkip[];
86
+ /** Feature-level hook failures, which belong to no single scenario. */
87
+ hookFailures: string[];
88
+ }
89
+ export type ScenarioRunStatus = 'running' | 'passed' | 'failed';
90
+ /**
91
+ * A whole run, as it is stored and read back.
92
+ *
93
+ * `status` is `running` from the moment the run is created until it finishes,
94
+ * so a console watching a run in progress can tell "still going" from "nothing
95
+ * came back" — and a run killed halfway stays `running` forever, which is the
96
+ * honest record of what happened to it.
97
+ */
98
+ export interface ScenarioRunRecord extends ScenarioRunReport {
99
+ runId: string;
100
+ status: ScenarioRunStatus;
101
+ /** The surface the run targeted: `default`, `browser`, … */
102
+ surface: string;
103
+ startedAt: string;
104
+ finishedAt?: string;
105
+ }
106
+ /** Enough of a run to list it without loading its steps and stacks. */
107
+ export interface ScenarioRunSummary {
108
+ runId: string;
109
+ environment: string;
110
+ surface: string;
111
+ status: ScenarioRunStatus;
112
+ startedAt: string;
113
+ finishedAt?: string;
114
+ durationMs?: number;
115
+ passed: number;
116
+ failed: number;
117
+ skipped: number;
118
+ /** Whether anything is there to watch, so a list can say so without a second read. */
119
+ artifacts: number;
120
+ }
121
+ /**
122
+ * Where runs are kept.
123
+ *
124
+ * Deliberately not the workflow service: a scenario run is a workflow run under
125
+ * the hood, but its history has a different lifetime, a different audience, and
126
+ * a different home — a JSON file beside the project locally, a project-scoped
127
+ * table and an object store when hosted.
128
+ *
129
+ * Written progressively rather than at the end, so a suite that dies on its
130
+ * fortieth scenario still leaves the thirty-nine behind.
131
+ */
132
+ export interface ScenarioRunStore {
133
+ /** Open a run. Called before the first scenario, with `status: 'running'`. */
134
+ start(record: ScenarioRunRecord): Promise<void>;
135
+ /** Append one finished scenario to an open run. */
136
+ recordScenario(runId: string, result: ScenarioResult): Promise<void>;
137
+ /**
138
+ * File the run's artifacts against the scenarios that produced them.
139
+ *
140
+ * Separate from `recordScenario` because a scenario's video does not exist
141
+ * when the scenario ends — it is finalised by the next scenario's reset, and
142
+ * renamed again when the run closes. Artifacts are matched to a result by the
143
+ * label the report knows it under.
144
+ */
145
+ attachArtifacts(runId: string, artifacts: ScenarioArtifact[]): Promise<void>;
146
+ /** Close a run, settling everything only known once every scenario has run. */
147
+ finish(runId: string, outcome: Pick<ScenarioRunRecord, 'status' | 'finishedAt' | 'skipped' | 'hookFailures'>): Promise<void>;
148
+ /**
149
+ * The bytes of one artifact, by the `path` its record carries.
150
+ *
151
+ * Reading goes through the store because only the store knows where a run's
152
+ * files actually are — a directory beside the project, or an object store
153
+ * behind a bucket. Absent when the run or the path is unknown, which is also
154
+ * the answer for a path that tries to leave the run.
155
+ *
156
+ * The bytes are backed by their own `ArrayBuffer` so they can be handed
157
+ * straight to a `Response` — a view onto a pooled or shared buffer is not a
158
+ * valid body.
159
+ */
160
+ readArtifact(runId: string, path: string): Promise<{
161
+ body: Uint8Array<ArrayBuffer>;
162
+ contentType: string;
163
+ } | undefined>;
164
+ /** Most recent first. */
165
+ list(options?: {
166
+ limit?: number;
167
+ }): Promise<ScenarioRunSummary[]>;
168
+ get(runId: string): Promise<ScenarioRunRecord | undefined>;
169
+ /** Forget a run and everything it filed. */
170
+ remove(runId: string): Promise<void>;
171
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,2 @@
1
1
  import type { PikkuScenarioStepWire, ScenarioEnvironment } from './scenario-step.types.js';
2
- export declare const requireActor: <TActor>(scenarioStep: PikkuScenarioStepWire<TActor> | undefined) => TActor;
3
- export declare const requireScenarioEnv: (scenarioStep: PikkuScenarioStepWire<unknown> | undefined) => ScenarioEnvironment;
2
+ export declare const requireScenarioEnv: (scenarioStep: PikkuScenarioStepWire | undefined) => ScenarioEnvironment;
@@ -1,11 +1,3 @@
1
- export const requireActor = (scenarioStep) => {
2
- const actor = scenarioStep?.actor;
3
- if (!actor) {
4
- throw new Error(`[scenario] step '${scenarioStep?.name ?? 'unknown'}' was called without an actor. ` +
5
- `Pass { actor: actors.<name> } so it runs as that persona.`);
6
- }
7
- return actor;
8
- };
9
1
  export const requireScenarioEnv = (scenarioStep) => {
10
2
  const env = scenarioStep?.env;
11
3
  if (!env) {
@@ -1,4 +1,4 @@
1
- import type { ScenarioPersona } from '../../services/personas-service.js';
1
+ import type { ScenarioArtifact } from './scenario-run.types.js';
2
2
  /**
3
3
  * Scenario steps: named, typed units of scenario behaviour.
4
4
  *
@@ -86,7 +86,10 @@ export type ScenarioSurfaceResolution = {
86
86
  * default to no retries.
87
87
  */
88
88
  export interface ScenarioStepOptions {
89
- /** The actor this step runs as. Required for steps declaring a `browser` binding. */
89
+ /**
90
+ * The actor this step runs as. Required for a step that declares `actor: true`
91
+ * or a `browser` binding; the runner refuses to dispatch one without it.
92
+ */
90
93
  actor?: unknown;
91
94
  /** Overrides the step's own `description` for this call site only. */
92
95
  description?: string;
@@ -107,11 +110,12 @@ export interface ScenarioEnvironment {
107
110
  /**
108
111
  * The `scenarioStep` wire, present on every scenario step invocation.
109
112
  *
110
- * `TActor` is the project's own actor type, so a step reaches only the RPCs its
111
- * actors can actually call. It defaults to the open `ScenarioPersona` for a
112
- * project that declares no registry.
113
+ * The persona a step runs as is not here: it arrives as `wire.actor`, injected
114
+ * by the runner and typed as present exactly on the bindings that declared they
115
+ * need one. Keeping it off this interface is what makes that possible a wire
116
+ * member can be required per binding, a property of one cannot.
113
117
  */
114
- export interface PikkuScenarioStepWire<TActor = ScenarioPersona> {
118
+ export interface PikkuScenarioStepWire {
115
119
  /** Registered step name (also its pikkuFuncId) */
116
120
  name: string;
117
121
  /** Durable key within the run; may carry an `#ordinal` suffix when repeated */
@@ -123,12 +127,6 @@ export interface PikkuScenarioStepWire<TActor = ScenarioPersona> {
123
127
  * per witness, so its body sees this change between invocations.
124
128
  */
125
129
  surface: ScenarioSurface;
126
- /**
127
- * The actor this step runs as, when one was given. Call RPCs through it
128
- * (`actor.invoke(...)`) so they run against the target environment as that
129
- * persona.
130
- */
131
- actor?: TActor;
132
130
  /**
133
131
  * The environment this run targets. A step runs in the CLI process, where
134
132
  * there is no `variables` service — this is how a raw-HTTP step learns the
@@ -218,11 +216,28 @@ export interface ScenarioBrowserProvider {
218
216
  * folder — findable only by timestamp.
219
217
  */
220
218
  beginScenario?(scenario: string): void;
219
+ /**
220
+ * Report how the scenario that just ran finished.
221
+ *
222
+ * Called after each scenario, and separate from `reset()` because artifacts
223
+ * that only exist once a window closes — a video — are produced by the NEXT
224
+ * scenario's reset, long after the outcome that decides whether to keep them.
225
+ */
226
+ endScenario?(outcome: 'passed' | 'failed'): void;
221
227
  /**
222
228
  * Snapshot every open window for a failed scenario. `label` identifies the
223
229
  * scenario in artifact filenames. Never throws: a failure to capture must
224
230
  * not replace the failure being captured.
225
231
  */
226
232
  captureFailure?(label: string): Promise<ScenarioBrowserFailure[]>;
233
+ /**
234
+ * Everything the run filed, each entry naming the scenario it belongs to.
235
+ *
236
+ * Reported by the driver rather than discovered by scanning the directory:
237
+ * only the driver knows which window produced a file and under what caption,
238
+ * and a video's final name is not settled until the run closes. Read after
239
+ * `close()`, which is the first moment the answer is complete.
240
+ */
241
+ artifacts?(): ScenarioArtifact[];
227
242
  close(): Promise<void>;
228
243
  }
@@ -103,7 +103,8 @@ export const evaluateApprovalStep = async (store, runId, reason, approvalStepNam
103
103
  return stepState.result;
104
104
  }
105
105
  const stateKey = approvalStateKey(approvalStepName);
106
- let record = ((await store.getRunState(runId))[stateKey] ?? {});
106
+ let record = ((await store.getRunState(runId))[stateKey] ??
107
+ {});
107
108
  const policy = {
108
109
  approvers: options.approvers,
109
110
  approverScope: options.approverScope,
@@ -1,4 +1,5 @@
1
- import type { PikkuRawWire, SerializedError } from '../../types/core.types.js';
1
+ import type { PikkuRawWire } from '../../types/core.types.js';
2
+ import type { SerializedError } from '../../errors/serialized-error.js';
2
3
  import type { CoreWorkflow, PikkuWorkflowWire, StepState, WorkflowRun, WorkflowStatus, WorkflowStepOptions } from './workflow.types.js';
3
4
  export interface RunLifecycleContext {
4
5
  runId: string;
@@ -1,4 +1,5 @@
1
- import type { SerializedError, CommonWireMeta } from '../../types/core.types.js';
1
+ import type { CommonWireMeta } from '../../types/core.types.js';
2
+ import type { SerializedError } from '../../errors/serialized-error.js';
2
3
  import type { CorePikkuFunctionConfig } from '../../function/functions.types.js';
3
4
  import type { GroupConcurrencyConfig } from '../queue/queue.types.js';
4
5
  export type { WorkflowService } from '../../services/workflow-service.js';
@@ -14,6 +14,8 @@ here first — several of these exist because the obvious simplification was tri
14
14
  and broke something.
15
15
 
16
16
  <!-- pikku:knowledge-index -->
17
+
17
18
  - [internals](internals/index.md) — a rule about how it works under the hood, and why
18
19
  - [security](security/index.md) — a rule about who may do what
20
+
19
21
  <!-- /pikku:knowledge-index -->
@@ -14,7 +14,7 @@ A reporter fills those placeholders from a run that already happened. There is
14
14
  no run yet at derivation time, so there is nothing to fill them from. More
15
15
  importantly, filling them would answer the wrong question: "invites {email}"
16
16
  tells the user to choose someone, where "invites ada@example.com" tells it whom
17
- — and *whom* is the scenario author's answer, not something the virtual user
17
+ — and _whom_ is the scenario author's answer, not something the virtual user
18
18
  worked out.
19
19
 
20
20
  **What this rules out:** substituting example or fixture values to make the
@@ -37,7 +37,7 @@ that turn that into a one-line fix, and they are known at the catch site and
37
37
  nowhere after it.
38
38
 
39
39
  This matters most at exactly the moment it is least convenient: a change to
40
- `deriveKEK` makes *every* previously stored secret undecryptable at once. Loud
40
+ `deriveKEK` makes _every_ previously stored secret undecryptable at once. Loud
41
41
  failure names the first one; silence produces an empty map and a support ticket.
42
42
 
43
43
  **What this rules out:** a `getSecrets` that skips unreadable rows; returning
@@ -18,9 +18,9 @@ Both of the alternatives are the obvious ones, and both are wrong for this.
18
18
  resumed at the step it died on, and that the same input reaches the same step.
19
19
  A virtual user is the opposite by construction — it is an LLM deciding what to
20
20
  try next, so no two attempts take the same steps, and there is no step to resume
21
- *to*. Recording a run as a workflow puts entries in the workflow store that can
21
+ _to_. Recording a run as a workflow puts entries in the workflow store that can
22
22
  never be replayed, and gives every operator reading that store a row that lies
23
- about what it is. The seed makes a run *reproducible* — run it again and it
23
+ about what it is. The seed makes a run _reproducible_ — run it again and it
24
24
  explores the same way — which is a different property from resumable, and one
25
25
  the record already carries.
26
26
 
@@ -13,11 +13,11 @@ per secret turns a 10ms operation into a 4-second one.
13
13
 
14
14
  It guarded it with `assert.ok(elapsed < 50)`. Measured on this machine:
15
15
 
16
- | | |
17
- | --- | --- |
18
- | one `deriveKEK` | ~86ms |
19
- | 50 `envelopeDecrypt` | 10.8ms |
20
- | the old 50ms threshold | 4.6x headroom |
16
+ | | |
17
+ | ----------------------------- | ------------------------------- |
18
+ | one `deriveKEK` | ~86ms |
19
+ | 50 `envelopeDecrypt` | 10.8ms |
20
+ | the old 50ms threshold | 4.6x headroom |
21
21
  | the failure it guards against | ~4281ms — a **396x** separation |
22
22
 
23
23
  So the assertion had 4.6x of margin to detect a 396x regression. Everything
@@ -37,7 +37,7 @@ suite grows or CI moves to a noisier runner. Any assertion of the form
37
37
  ratio against something measured alongside it.
38
38
 
39
39
  Worth knowing: `envelopeDecrypt(kek: CryptoKey, …)` takes the derived key as a
40
- parameter, so it *cannot* derive one — the property is already enforced by the
40
+ parameter, so it _cannot_ derive one — the property is already enforced by the
41
41
  signature, and [[the-api-report-pins-members-not-just-names]] would catch a
42
42
  change to it. The test is defence in depth, which is a reason to make it cheap
43
43
  and quiet rather than to delete it.
@@ -18,7 +18,7 @@ pikkuUserId: rpcService.wire?.pikkuUserId,
18
18
  ```
19
19
 
20
20
  `PikkuRPC` has no `wire`. Neither does the object `getContextRPCService`
21
- actually returns — `ContextAwareRPCService` holds its wire *privately* and
21
+ actually returns — `ContextAwareRPCService` holds its wire _privately_ and
22
22
  exposes `invoke`, `remote`, `exposed`, `startWorkflow`, `agent` and
23
23
  `rpcWithWire`, and nothing else. Every one of those reads was `undefined`, and
24
24
  the `rpcService: any` parameter type is what kept the compiler quiet about it.
@@ -17,7 +17,7 @@ One package may be wired twice — the same payments addon against a live and a
17
17
  sandbox account, say — with different secret and variable names. Caching by
18
18
  package name would build the service graph once, from whichever instance called
19
19
  first, and silently hand the other instance the wrong credentials. Because the
20
- overrides have to be visible to the addon's *own* `createSingletonServices`, they
20
+ overrides have to be visible to the addon's _own_ `createSingletonServices`, they
21
21
  are applied by wrapping the parent `secrets` and `variables` services
22
22
  (`aliasSecretService`, `aliasVariablesService`) so that every logical name the
23
23
  addon reads is remapped to the real project name before resolution. A call with
@@ -15,7 +15,7 @@ instance namespace when known and otherwise the package's sole namespace via
15
15
  `findAddonNamespaceForPackage`.
16
16
 
17
17
  Workflows declared by an addon are registered under the addon's package scope,
18
- but the namespace they answer to is chosen by the *consumer* in `wireAddon`.
18
+ but the namespace they answer to is chosen by the _consumer_ in `wireAddon`.
19
19
  Without the proxy, `runToCompletion('myWorkflow')` written inside the addon
20
20
  resolves against root meta, misses, and throws `WorkflowNotFoundError` — leaving
21
21
  the addon author no option but to hardcode the consumer-defined namespace, which
@@ -24,7 +24,7 @@ permissions bug rather than a merge that dropped.
24
24
  This is a different rule from
25
25
  [scope roots may be co-declared by an addon and its host
26
26
  app](scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md): that one
27
- is about `flattenScopeDefinitions` deduping ids *within* a build where both
27
+ is about `flattenScopeDefinitions` deduping ids _within_ a build where both
28
28
  declarations are present and identical. This one is about the addon's copy never
29
29
  arriving. The consequence for addon authors is the same either way — own a root
30
30
  outright, named for the package or vendor, and nest everything under it. It is
@@ -14,7 +14,7 @@ things a caller may put on `onMessage` or inside `onMessageWiring`:
14
14
  - a direct function config, where `onMessage.func` is a plain `Function`;
15
15
  - a wrapper, where `onMessage.func` is itself a `CorePikkuFunctionConfig` and so
16
16
  has its own nested `.func`;
17
- - a simple wrapper, which carries a plain `Function` under `func` *and* a
17
+ - a simple wrapper, which carries a plain `Function` under `func` _and_ a
18
18
  sibling `middleware` array.
19
19
 
20
20
  The `isWrapper` check tests exactly that: an object with `func`, where either
@@ -19,7 +19,7 @@ user's stream and growing memory run over run. It is therefore appended fresh on
19
19
  every call, after the cached inherited slice.
20
20
 
21
21
  The `uid` matters as much as the cache split. `processMessageHandlers` in
22
- `channel-handler.ts` builds it from the channel name *plus* the routing property
22
+ `channel-handler.ts` builds it from the channel name _plus_ the routing property
23
23
  and router value (`${name}:${routingProperty}:${routerValue}`, or
24
24
  `${name}:default`), because several message routes on one channel may point at
25
25
  the same function — a key based on the function alone would serve one route's
@@ -10,7 +10,7 @@ tags: channel
10
10
  `runChannelConnect` in
11
11
  `packages/core/src/wirings/channel/serverless/serverless-channel-runner.ts`
12
12
  reads `userSession.getPikkuUserId()` and calls `channelStore.setPikkuUserId`
13
- *after* `runChannelLifecycleWithMiddleware` has executed the `onConnect`
13
+ _after_ `runChannelLifecycleWithMiddleware` has executed the `onConnect`
14
14
  lifecycle, not before.
15
15
 
16
16
  Auth middleware runs as part of that lifecycle — it is what inspects the upgrade
@@ -19,7 +19,7 @@ the conversion happens. The parser normalises every incoming `--from-plan` to
19
19
  `fromPlan` on the way in, and both `formatOptions` (help text) and the
20
20
  "Missing required option" / "Invalid value for" errors render back to kebab on
21
21
  the way out. `suggestOption` deliberately compares the typed string against
22
- *both* forms, so `--autoApply` and `--auto-apply` both find `autoApply`.
22
+ _both_ forms, so `--autoApply` and `--auto-apply` both find `autoApply`.
23
23
 
24
24
  **What this rules out:** storing option keys kebab-cased anywhere in CLI state or
25
25
  metadata — the schema pluck would then match nothing and every option would be
@@ -18,7 +18,7 @@ mistake (show the help text) or a value mistake (print the errors) by
18
18
  This is why the parser pushes `Missing subcommand: <path>` for a group command
19
19
  that has subcommands but no `pikkuFuncId` of its own, rather than simply
20
20
  returning the command meta and letting the runner discover it is unrunnable. The
21
- message *is* the routing signal. Rewording any of those three strings, or
21
+ message _is_ the routing signal. Rewording any of those three strings, or
22
22
  localising them, silently turns "show me the subcommands" into a raw error dump.
23
23
 
24
24
  **What this rules out:** editing those error message prefixes without updating
@@ -18,7 +18,7 @@ The reason is forward compatibility: a script or wrapper written against a newer
18
18
  command version may pass options an older installed binary does not know, and
19
19
  failing hard there turns a harmless extra flag into a broken pipeline.
20
20
  `RESERVED_OPTIONS` exempts flags the runner handles itself (`help`) from the
21
- warning. Unknown *short* flags are treated differently — they go to
21
+ warning. Unknown _short_ flags are treated differently — they go to
22
22
  `result.errors` and do fail — because a bundled short-flag cluster like `-abc`
23
23
  cannot be reliably attributed, and a typo'd short flag is far more likely than a
24
24
  version skew.
@@ -15,13 +15,13 @@ value leave the process?".
15
15
  The two axes were one field before this, with `security: 'encrypted'` sitting
16
16
  alongside `secret` as though they were alternatives. They are not, and the
17
17
  conflation made the field unanswerable: a token hash and a live bearer token are
18
- both `secret`, one must never be encrypted — the digest *is* the lookup key —
18
+ both `secret`, one must never be encrypted — the digest _is_ the lookup key —
19
19
  and the other must always be. Nothing in a single enum could tell them apart, so
20
20
  nothing could check either.
21
21
 
22
22
  ## Why `wrapped` and `sealed` rather than `encrypted`
23
23
 
24
- Sealed values *are* encrypted, so an `encrypted` member sitting beside `sealed`
24
+ Sealed values _are_ encrypted, so an `encrypted` member sitting beside `sealed`
25
25
  would be a supertype posing as a sibling, and every new column would be an
26
26
  even-odds guess. What actually separates them is who can read the value back:
27
27
  `wrapped` is symmetric and the application holds the key; `sealed` is asymmetric
@@ -64,7 +64,7 @@ it would buy nothing — feeding in the wrong string already fails at the AEAD t
64
64
  — while forcing a cast into every path that reads ciphertext out of a row or off
65
65
  the wire, which is where casts are least reviewable.
66
66
 
67
- The brand proves *provenance*, not correctness. It cannot know a value was
67
+ The brand proves _provenance_, not correctness. It cannot know a value was
68
68
  wrapped under the right key, and making it know would mean phantom-typing key
69
69
  ids per scope, which the multi-recipient path would fight constantly.
70
70
 
@@ -75,7 +75,7 @@ error. Every project predating the axis has such columns, and failing their next
75
75
  `db migrate` would be a breaking change for a diagnosis they have not had a
76
76
  chance to act on. `pikku db --fail-on-warn` is how a project opts into the
77
77
  ratchet. An explicit `form: 'plain'` silences it — that is the acknowledgement
78
- that reading the row is *meant* to yield a usable credential.
78
+ that reading the row is _meant_ to yield a usable credential.
79
79
 
80
80
  **What this rules out:** collapsing `wrapped` and `sealed` back into one
81
81
  `encrypted`; making the form brands optional (they would enforce nothing);
@@ -16,7 +16,7 @@ A required property would make a plain value unassignable to a branded column: a
16
16
  `string` could no longer be passed where `Private<string>` is expected, which
17
17
  breaks every ordinary Kysely query operand — `where('email', '=', someString)`,
18
18
  inserts, and `.set(...)`. Making it optional keeps the brand structurally present
19
- so static analysis still sees it, while letting plain values flow *in*. The
19
+ so static analysis still sees it, while letting plain values flow _in_. The
20
20
  asymmetry is the point: the brand constrains what comes out of a query, not what
21
21
  goes into one.
22
22
 
@@ -9,7 +9,7 @@ tags: core
9
9
 
10
10
  `runPikkuFunc` in `packages/core/src/function/function-runner.ts` does not build a
11
11
  fresh wire per call. Nested invocations — an RPC from inside a function, an addon
12
- sibling call, a workflow step — reuse the *same* wire object the outer transport
12
+ sibling call, a workflow step — reuse the _same_ wire object the outer transport
13
13
  created. So before it runs, the runner captures `functionId`, `audit`,
14
14
  `addonNamespace` and the property descriptor for `rpc`, overwrites them for the
15
15
  duration of this function, and restores or `delete`s them in a `finally`. Both
@@ -18,7 +18,7 @@ inner call would leave its identity on the wire and every subsequent outer step
18
18
  would be attributed to the wrong function.
19
19
 
20
20
  The same reuse is why the audit binding is re-gated inside `executeFunction`
21
- rather than trusted from `createWireServices`. The audit *gate* is per-function
21
+ rather than trusted from `createWireServices`. The audit _gate_ is per-function
22
22
  but the `auditLog` wire service is created per-transport-invocation. A nested or
23
23
  exposed-RPC call would otherwise inherit an `auditLog` built while the outer
24
24
  wire's audit config was unset (the generated `rpcCaller` declares none), and
@@ -32,7 +32,7 @@ then the auth/readonly checks, then `verifyScopes` — all of which depend only
32
32
  the session — and only then `await data()`, schema defaults, coercion, validation
33
33
  and `runPermissions`. A request denied by scope never pays to parse or validate
34
34
  its body. `rpc` is installed as a lazily-evaluating accessor that replaces itself
35
- with the resolved value on first read, capturing the *caller's* package name in
35
+ with the resolved value on first read, capturing the _caller's_ package name in
36
36
  the closure so an addon's RPCs resolve in its own namespace.
37
37
 
38
38
  **What this rules out:** dropping the save/restore blocks as duplicated
@@ -22,7 +22,7 @@ workflow job fails with `Function meta not found: pikkuWorkflowOrchestrator`.
22
22
  `dev/reload-meta.test.ts` pins this. Meta maps that only codegen ever writes
23
23
  (`http`, `rpc`, `agent`) are assigned outright.
24
24
 
25
- Two limits are inherent rather than incidental. Routes registered by a *new*
25
+ Two limits are inherent rather than incidental. Routes registered by a _new_
26
26
  `wireHTTP` file are not picked up here — those modules were never imported — which
27
27
  is why `hot-reload.ts` keeps a `postCodegenQueue` and exposes `reimportPending()`
28
28
  for the dev server to drain after codegen, so registrations that were skipped for
@@ -35,5 +35,5 @@ entry stranded until a restart.
35
35
  `pikkuState(null, 'function', 'meta', functionsMeta)` assignments on the grounds
36
36
  that codegen output is authoritative — it is authoritative only for what codegen
37
37
  emits. It also rules out folding `reimportPending()` back into the debounced
38
- reload (the whole point is that it runs *after* codegen), and dropping
38
+ reload (the whole point is that it runs _after_ codegen), and dropping
39
39
  `reconcileAddonRegistry` as dead code.
@@ -23,7 +23,7 @@ edits, and eventually OOMs a long editing session. `dev/module-runner.test.ts`
23
23
  asserts both the single-slot guarantee and bounded heap growth.
24
24
 
25
25
  Two details keep the mechanism honest. `import`s inside the user file are
26
- delegated to `createRequire`, whose resolution matches the native loader *and*
26
+ delegated to `createRequire`, whose resolution matches the native loader _and_
27
27
  returns the same live singletons (Node and Bun share the require/import cache) —
28
28
  that is what lets a reloaded file's top-level `wireHTTP` side effects mutate the
29
29
  services the running server is already using. And esbuild is invoked with no
@@ -37,6 +37,6 @@ code.
37
37
  import(url + '?t=' + Date.now())` or any fresh-URL variant, and turning
38
38
  sourcemaps back on for nicer stack traces (`filename` already anchors traces to
39
39
  the user file). It also rules out swapping `createRequire` for a fresh `import()`
40
- inside the compiled module — resolution would produce a *distinct* copy of every
40
+ inside the compiled module — resolution would produce a _distinct_ copy of every
41
41
  dependency, and the reloaded file would then wire itself into services nobody is
42
42
  serving from.
@@ -19,7 +19,7 @@ finally passed through `freezeDedupe` and cached in `middlewareCache` keyed by
19
19
  wire type and wire id.
20
20
 
21
21
  Two properties fall out of that and both are load-bearing. Because the sort is
22
- stable, priority is a coarse band and registration order breaks ties *within* a
22
+ stable, priority is a coarse band and registration order breaks ties _within_ a
23
23
  band, so declaration order still means something. And because the result is
24
24
  deduped by function identity, a middleware reachable through both a tag group and
25
25
  a direct wire registration runs exactly once — a fact several tests assert