@pikku/core 0.12.84 → 0.12.88

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 (577) hide show
  1. package/CHANGELOG.md +503 -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/dev/hot-reload.d.ts +1 -1
  12. package/dist/dev/hot-reload.js +1 -1
  13. package/dist/ecosystem/agent-scorer.d.ts +1 -1
  14. package/dist/ecosystem/agent.d.ts +4 -1
  15. package/dist/ecosystem/channel/local.d.ts +2 -0
  16. package/dist/ecosystem/channel/local.js +2 -0
  17. package/dist/ecosystem/channel/serverless.d.ts +9 -0
  18. package/dist/ecosystem/channel/serverless.js +1 -0
  19. package/dist/ecosystem/channel.d.ts +3 -0
  20. package/dist/ecosystem/channel.js +1 -0
  21. package/dist/ecosystem/cli.d.ts +1 -1
  22. package/dist/ecosystem/cli.js +1 -1
  23. package/dist/ecosystem/credential.d.ts +1 -0
  24. package/dist/ecosystem/crypto-utils.d.ts +8 -0
  25. package/dist/ecosystem/crypto-utils.js +1 -0
  26. package/dist/ecosystem/dev.d.ts +1 -0
  27. package/dist/ecosystem/dev.js +1 -0
  28. package/{src/ecosystem/testing.ts → dist/ecosystem/errors.d.ts} +3 -3
  29. package/dist/ecosystem/errors.js +2 -0
  30. package/dist/ecosystem/function.d.ts +1 -1
  31. package/dist/ecosystem/function.js +1 -1
  32. package/dist/ecosystem/http.d.ts +3 -1
  33. package/dist/ecosystem/http.js +3 -1
  34. package/dist/ecosystem/mcp.d.ts +1 -1
  35. package/dist/ecosystem/mcp.js +1 -1
  36. package/dist/ecosystem/middleware.d.ts +2 -1
  37. package/dist/ecosystem/middleware.js +2 -1
  38. package/dist/ecosystem/persona.d.ts +4 -2
  39. package/dist/ecosystem/persona.js +2 -1
  40. package/dist/ecosystem/queue.d.ts +4 -2
  41. package/dist/ecosystem/queue.js +3 -1
  42. package/dist/ecosystem/role.d.ts +1 -0
  43. package/dist/ecosystem/rpc.d.ts +2 -0
  44. package/dist/ecosystem/rpc.js +1 -0
  45. package/dist/ecosystem/scenario.d.ts +8 -2
  46. package/dist/ecosystem/scenario.js +5 -1
  47. package/dist/ecosystem/scheduler.d.ts +2 -1
  48. package/dist/ecosystem/scheduler.js +2 -1
  49. package/dist/ecosystem/schema.d.ts +2 -1
  50. package/dist/ecosystem/schema.js +1 -1
  51. package/dist/ecosystem/scope.d.ts +2 -0
  52. package/dist/ecosystem/scope.js +1 -0
  53. package/dist/ecosystem/secret.d.ts +2 -0
  54. package/dist/ecosystem/secret.js +1 -0
  55. package/dist/ecosystem/services/local-content.d.ts +2 -1
  56. package/dist/ecosystem/services/local-content.js +1 -1
  57. package/dist/ecosystem/services/local-meta.d.ts +1 -0
  58. package/dist/ecosystem/services/local-meta.js +1 -0
  59. package/dist/ecosystem/services.d.ts +11 -3
  60. package/dist/ecosystem/services.js +7 -1
  61. package/dist/ecosystem/trigger.d.ts +1 -0
  62. package/dist/ecosystem/trigger.js +1 -1
  63. package/dist/ecosystem/types.d.ts +6 -3
  64. package/dist/ecosystem/types.js +3 -2
  65. package/dist/ecosystem/variable.d.ts +1 -0
  66. package/dist/ecosystem/virtual-user.d.ts +3 -0
  67. package/dist/ecosystem/virtual-user.js +3 -0
  68. package/dist/ecosystem/workflow.d.ts +2 -0
  69. package/dist/ecosystem/workflow.js +2 -0
  70. package/dist/errors/index.d.ts +8 -0
  71. package/dist/errors/index.js +1 -0
  72. package/dist/errors/serialized-error.d.ts +7 -0
  73. package/dist/function/function-meta.types.d.ts +139 -0
  74. package/dist/function/function-runner.d.ts +3 -2
  75. package/dist/function/function-runner.js +31 -11
  76. package/dist/function/functions.types.d.ts +10 -2
  77. package/dist/function/index.d.ts +8 -2
  78. package/dist/function/index.js +4 -1
  79. package/dist/function/pikku-request.d.ts +8 -0
  80. package/dist/function/pikku-request.js +15 -0
  81. package/dist/middleware/auth-apikey.d.ts +2 -10
  82. package/dist/middleware/auth-apikey.js +1 -1
  83. package/dist/middleware/auth-bearer.d.ts +2 -10
  84. package/dist/middleware/auth-bearer.js +1 -1
  85. package/dist/middleware/auth-cookie.d.ts +2 -10
  86. package/dist/middleware/auth-cookie.js +1 -1
  87. package/dist/middleware/cors.d.ts +5 -11
  88. package/dist/middleware/cors.js +13 -6
  89. package/dist/middleware/index.d.ts +3 -0
  90. package/dist/middleware/index.js +1 -0
  91. package/dist/middleware/middleware-factories.d.ts +9 -0
  92. package/dist/middleware/middleware-factories.js +19 -0
  93. package/dist/middleware/middleware.types.d.ts +27 -0
  94. package/dist/middleware/middleware.types.js +1 -0
  95. package/dist/middleware/remote-auth.d.ts +2 -2
  96. package/dist/middleware/remote-auth.js +1 -1
  97. package/dist/middleware/telemetry.d.ts +4 -20
  98. package/dist/middleware/telemetry.js +1 -1
  99. package/dist/middleware-runner.d.ts +2 -1
  100. package/dist/pikku-state.d.ts +2 -1
  101. package/dist/services/audit-service.d.ts +1 -1
  102. package/dist/services/credential-wire-service.js +1 -1
  103. package/dist/services/email-service.d.ts +1 -1
  104. package/dist/services/file-scenario-run-store.d.ts +58 -0
  105. package/dist/services/file-scenario-run-store.js +214 -0
  106. package/dist/services/in-memory-workflow-service.d.ts +1 -1
  107. package/dist/services/index.d.ts +5 -1
  108. package/dist/services/index.js +3 -0
  109. package/dist/services/local-secrets.d.ts +1 -1
  110. package/dist/services/local-secrets.js +1 -1
  111. package/dist/services/logger.d.ts +7 -7
  112. package/dist/services/meta-service.d.ts +2 -1
  113. package/dist/services/scoped-secret-service.d.ts +1 -1
  114. package/dist/services/secret-service.d.ts +1 -1
  115. package/dist/services/typed-secret-service.d.ts +16 -2
  116. package/dist/services/typed-secret-service.js +5 -0
  117. package/dist/services/webhook-service.d.ts +1 -1
  118. package/dist/services/workflow-service.d.ts +2 -1
  119. package/dist/testing/index.d.ts +1 -0
  120. package/dist/testing/index.js +1 -0
  121. package/dist/types/core.types.d.ts +30 -180
  122. package/dist/types/core.types.js +1 -19
  123. package/dist/types/index.d.ts +2 -0
  124. package/dist/types/index.js +1 -0
  125. package/dist/types/state.types.d.ts +3 -1
  126. package/dist/utils.d.ts +13 -0
  127. package/dist/utils.js +2 -0
  128. package/dist/wirings/addon/addon-runner.d.ts +17 -0
  129. package/dist/wirings/addon/addon-runner.js +150 -0
  130. package/dist/wirings/addon/index.d.ts +6 -0
  131. package/dist/wirings/addon/index.js +3 -0
  132. package/dist/wirings/addon/remote-addon-auth.d.ts +16 -0
  133. package/dist/wirings/addon/remote-addon-auth.js +39 -0
  134. package/dist/wirings/addon/wire-addon.d.ts +80 -0
  135. package/dist/wirings/addon/wire-addon.js +120 -0
  136. package/dist/wirings/addon/wire-remote-addon.d.ts +22 -0
  137. package/dist/wirings/addon/wire-remote-addon.js +11 -0
  138. package/dist/wirings/agent/agent-memory.d.ts +11 -0
  139. package/dist/wirings/agent/agent-memory.js +17 -2
  140. package/dist/wirings/agent/agent-prepare.d.ts +3 -3
  141. package/dist/wirings/agent/agent-prepare.js +1 -1
  142. package/dist/wirings/agent/agent-runner.js +2 -3
  143. package/dist/wirings/agent/agent-stream.js +117 -93
  144. package/dist/wirings/agent/agent-utils.d.ts +13 -0
  145. package/dist/wirings/agent/agent-utils.js +16 -0
  146. package/dist/wirings/agent/agent.types.d.ts +12 -10
  147. package/dist/wirings/agent/index.d.ts +1 -1
  148. package/dist/wirings/agent/voice-input.js +1 -1
  149. package/dist/wirings/agent/voice-output.js +1 -1
  150. package/dist/wirings/agent-scorer/agent-scorer-judge.d.ts +13 -0
  151. package/dist/wirings/agent-scorer/agent-scorer-judge.js +52 -0
  152. package/dist/wirings/agent-scorer/agent-scorer.d.ts +7 -1
  153. package/dist/wirings/agent-scorer/agent-scorer.js +1 -0
  154. package/dist/wirings/agent-scorer/agent-scorer.types.d.ts +20 -0
  155. package/dist/wirings/agent-scorer/index.d.ts +1 -1
  156. package/dist/wirings/channel/channel-common.d.ts +2 -1
  157. package/dist/wirings/channel/channel-middleware-runner.d.ts +2 -1
  158. package/dist/wirings/channel/channel.types.d.ts +1 -1
  159. package/dist/wirings/channel/serverless/index.d.ts +1 -0
  160. package/dist/wirings/cli/channel/index.d.ts +1 -1
  161. package/dist/wirings/cli/cli-runner.d.ts +2 -1
  162. package/dist/wirings/cli/cli-runner.js +4 -1
  163. package/dist/wirings/cli/cli.types.d.ts +21 -2
  164. package/dist/wirings/cli/command-parser.js +157 -23
  165. package/dist/wirings/gateway/gateway.types.d.ts +2 -1
  166. package/dist/wirings/http/http-runner.d.ts +1 -1
  167. package/dist/wirings/http/http-runner.js +1 -1
  168. package/dist/wirings/http/http.types.d.ts +2 -2
  169. package/dist/wirings/http/index.d.ts +1 -0
  170. package/dist/wirings/http/index.js +1 -0
  171. package/dist/wirings/http/pikku-fetch-http-request.js +1 -1
  172. package/dist/wirings/http/pikku-fetch-http-response.js +2 -2
  173. package/dist/wirings/mcp/mcp.types.d.ts +1 -1
  174. package/dist/wirings/persona/index.d.ts +1 -1
  175. package/dist/wirings/persona/index.js +1 -1
  176. package/dist/wirings/persona/persona.types.d.ts +14 -0
  177. package/dist/wirings/queue/queue.types.d.ts +1 -1
  178. package/dist/wirings/queue/signed-queue-service.d.ts +1 -1
  179. package/dist/wirings/rpc/index.d.ts +0 -6
  180. package/dist/wirings/rpc/index.js +0 -3
  181. package/dist/wirings/rpc/remote-addon-auth.d.ts +1 -1
  182. package/dist/wirings/rpc/remote-addon-auth.js +1 -1
  183. package/dist/wirings/rpc/rpc-runner.js +2 -2
  184. package/dist/wirings/rpc/wire-addon.d.ts +1 -1
  185. package/dist/wirings/scheduler/scheduler.types.d.ts +2 -1
  186. package/dist/wirings/scope/index.d.ts +1 -0
  187. package/dist/wirings/scope/index.js +1 -0
  188. package/dist/wirings/secret/secret.types.d.ts +10 -0
  189. package/dist/wirings/secret/validate-secret-definitions.js +2 -0
  190. package/dist/wirings/variable/validate-variable-definitions.js +2 -0
  191. package/dist/wirings/variable/variable.types.d.ts +15 -0
  192. package/dist/wirings/virtual-user/index.d.ts +1 -1
  193. package/dist/wirings/virtual-user/index.js +1 -1
  194. package/dist/wirings/virtual-user/prepare-virtual-user-run.d.ts +1 -1
  195. package/dist/wirings/virtual-user/virtual-user-derive.d.ts +1 -1
  196. package/dist/wirings/workflow/graph/graph-node.d.ts +9 -2
  197. package/dist/wirings/workflow/graph/graph-node.js +2 -0
  198. package/dist/wirings/workflow/graph/graph-runner.d.ts +1 -0
  199. package/dist/wirings/workflow/graph/graph-runner.js +283 -31
  200. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +16 -1
  201. package/dist/wirings/workflow/index.d.ts +2 -0
  202. package/dist/wirings/workflow/index.js +1 -0
  203. package/dist/wirings/workflow/pikku-scenario-service.d.ts +15 -5
  204. package/dist/wirings/workflow/pikku-scenario-service.js +44 -16
  205. package/dist/wirings/workflow/pikku-workflow-service.d.ts +22 -7
  206. package/dist/wirings/workflow/pikku-workflow-service.js +28 -29
  207. package/dist/wirings/workflow/run-timeline.d.ts +1 -1
  208. package/dist/wirings/workflow/scenario-run.types.d.ts +171 -0
  209. package/dist/wirings/workflow/scenario-run.types.js +1 -0
  210. package/dist/wirings/workflow/scenario-step-guards.d.ts +1 -2
  211. package/dist/wirings/workflow/scenario-step-guards.js +0 -8
  212. package/dist/wirings/workflow/scenario-step.types.d.ts +27 -12
  213. package/dist/wirings/workflow/workflow-approval.js +2 -1
  214. package/dist/wirings/workflow/workflow-run-engine.types.d.ts +2 -1
  215. package/dist/wirings/workflow/workflow-step-claim.d.ts +16 -0
  216. package/dist/wirings/workflow/workflow-step-claim.js +27 -0
  217. package/dist/wirings/workflow/workflow.types.d.ts +2 -1
  218. package/knowledge/decisions/index.md +2 -0
  219. package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +1 -1
  220. package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +1 -1
  221. package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-and-not-a-queued-job.md +2 -2
  222. package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +6 -6
  223. package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +1 -1
  224. package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +1 -1
  225. package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +1 -1
  226. package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +1 -1
  227. package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +1 -1
  228. package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +1 -1
  229. package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +1 -1
  230. package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +1 -1
  231. package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +1 -1
  232. package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +1 -1
  233. package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +4 -4
  234. package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +1 -1
  235. package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +3 -3
  236. package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +2 -2
  237. package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +2 -2
  238. package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +1 -1
  239. package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +1 -1
  240. package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +3 -3
  241. package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +1 -1
  242. package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +4 -4
  243. package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +1 -1
  244. package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +1 -1
  245. package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +1 -1
  246. package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +1 -1
  247. package/knowledge/decisions/internals/index.md +4 -2
  248. package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +1 -1
  249. package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +1 -1
  250. package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +1 -1
  251. package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +1 -1
  252. package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +1 -1
  253. package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +2 -2
  254. package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +5 -5
  255. package/knowledge/decisions/internals/the-actor-prompt-says-json-because-of-json-object-mode.md +1 -1
  256. package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +1 -1
  257. package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +43 -19
  258. package/knowledge/decisions/internals/the-persona-runtime-is-exported-from-the-persona-entry-point.md +1 -1
  259. package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +1 -1
  260. package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +3 -3
  261. package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +1 -1
  262. package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +1 -1
  263. package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +1 -1
  264. package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +1 -1
  265. package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +1 -1
  266. package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +1 -1
  267. package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +1 -1
  268. package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +1 -1
  269. package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +1 -1
  270. package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +9 -5
  271. package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +1 -1
  272. package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +2 -2
  273. package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +1 -1
  274. package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +1 -1
  275. package/knowledge/decisions/security/a-scaffold-flag-says-a-surface-exists-not-who-may-call-it.md +47 -0
  276. package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +1 -1
  277. package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +2 -3
  278. package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +1 -1
  279. package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +1 -1
  280. package/knowledge/decisions/security/agent-gate-requires-a-session-only-when-auth-is-true.md +1 -1
  281. package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +3 -3
  282. package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +4 -3
  283. package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +1 -1
  284. package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +2 -2
  285. package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +1 -1
  286. package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +2 -2
  287. package/knowledge/decisions/security/index.md +4 -1
  288. package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +1 -1
  289. package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +3 -3
  290. package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +1 -1
  291. package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +8 -2
  292. package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +1 -1
  293. package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +2 -2
  294. package/knowledge/index.md +3 -1
  295. package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +1 -1
  296. package/knowledge/questions/index.md +2 -0
  297. package/package.json +14 -13
  298. package/run-tests.sh +0 -0
  299. package/scripts/generate-api-report.d.mts +1 -1
  300. package/scripts/generate-api-report.mjs +67 -60
  301. package/scripts/generate-api-report.mts +11 -45
  302. package/src/api-report.test.ts +70 -1
  303. package/src/app-alias-surface.test.ts +179 -0
  304. package/src/app-leaf-surface.test.ts +217 -0
  305. package/src/bootstrap-compat/root.ts +20 -0
  306. package/src/{column-form.test.ts → classification/column-form.test.ts} +2 -2
  307. package/src/{data-classification.ts → classification/data-classification.ts} +1 -5
  308. package/src/classification/index.ts +38 -0
  309. package/src/{secret-value.test.ts → classification/secret-value.test.ts} +2 -2
  310. package/src/{secret-value.ts → classification/secret-value.ts} +1 -6
  311. package/src/crypto-utils.ts +1 -1
  312. package/src/dev/hot-reload.ts +1 -1
  313. package/src/dev/reload-meta.test.ts +1 -1
  314. package/src/errors/index.ts +9 -0
  315. package/src/errors/serialized-error.ts +9 -0
  316. package/src/factory-functions.test.ts +4 -2
  317. package/src/function/function-meta.types.ts +151 -0
  318. package/src/function/function-runner.test.ts +4 -2
  319. package/src/function/function-runner.ts +47 -14
  320. package/src/function/functions.types.ts +11 -7
  321. package/src/function/index.ts +24 -5
  322. package/src/function/list.types.ts +1 -3
  323. package/src/middleware/auth-apikey.ts +4 -2
  324. package/src/middleware/auth-bearer.test.ts +1 -1
  325. package/src/middleware/auth-bearer.ts +4 -2
  326. package/src/middleware/auth-cookie.ts +4 -1
  327. package/src/middleware/cors.test.ts +126 -5
  328. package/src/middleware/cors.ts +19 -8
  329. package/src/middleware/index.ts +16 -0
  330. package/src/middleware/middleware-factories.ts +62 -0
  331. package/src/middleware/middleware.types.ts +61 -0
  332. package/src/middleware/remote-auth.test.ts +1 -1
  333. package/src/middleware/remote-auth.ts +1 -1
  334. package/src/middleware/telemetry.ts +4 -2
  335. package/src/middleware-runner.test.ts +2 -3
  336. package/src/middleware-runner.ts +2 -2
  337. package/src/no-root-barrel.test.ts +114 -0
  338. package/src/permissions.ts +2 -4
  339. package/src/pikku-state.ts +3 -1
  340. package/src/public-surface.json +56 -241
  341. package/src/public-surface.json.README +3 -3
  342. package/src/public-surface.test.ts +5 -5
  343. package/src/remote.test.ts +1 -1
  344. package/src/removed-legacy-exports.test.ts +5 -1
  345. package/src/services/audit-service.ts +1 -1
  346. package/src/services/credential-wire-service.ts +1 -1
  347. package/src/services/email-service.ts +2 -4
  348. package/src/services/file-scenario-run-store.test.ts +349 -0
  349. package/src/services/file-scenario-run-store.ts +282 -0
  350. package/src/services/in-memory-workflow-service.ts +1 -1
  351. package/src/services/index.ts +13 -1
  352. package/src/services/local-content-request-handler.ts +1 -2
  353. package/src/services/local-secrets.ts +1 -1
  354. package/src/services/logger.ts +7 -7
  355. package/src/services/meta-service.ts +2 -2
  356. package/src/services/queue-webhook-service.test.ts +1 -1
  357. package/src/services/scoped-secret-service.ts +1 -1
  358. package/src/services/secret-service.ts +1 -1
  359. package/src/services/typed-secret-service.test.ts +52 -0
  360. package/src/services/typed-secret-service.ts +26 -2
  361. package/src/services/webhook-service.ts +1 -1
  362. package/src/services/workflow-service.ts +2 -1
  363. package/src/template-alias-surface.test.ts +240 -0
  364. package/src/testing/index.ts +1 -0
  365. package/src/types/core.types.ts +33 -285
  366. package/src/types/index.ts +25 -0
  367. package/src/types/state.types.ts +6 -5
  368. package/src/types/typed-credentials.test.ts +72 -0
  369. package/src/utils.ts +34 -0
  370. package/src/wirings/{rpc → addon}/addon-scopes.test.ts +1 -1
  371. package/src/wirings/addon/index.ts +12 -0
  372. package/src/wirings/{rpc → addon}/remote-addon-auth.ts +4 -1
  373. package/src/wirings/{rpc → addon}/wire-addon.ts +37 -2
  374. package/src/wirings/agent/agent-memory.test.ts +73 -0
  375. package/src/wirings/agent/agent-memory.ts +16 -2
  376. package/src/wirings/agent/agent-middleware.types.test.ts +41 -0
  377. package/src/wirings/agent/agent-prepare.ts +8 -5
  378. package/src/wirings/agent/agent-runner.ts +2 -3
  379. package/src/wirings/agent/agent-stream-delegate.test.ts +381 -0
  380. package/src/wirings/agent/agent-stream.ts +160 -81
  381. package/src/wirings/agent/agent-utils.ts +19 -0
  382. package/src/wirings/agent/agent.types.ts +12 -11
  383. package/src/wirings/agent/index.ts +1 -0
  384. package/src/wirings/agent/voice-input.ts +1 -1
  385. package/src/wirings/agent/voice-output.test.ts +2 -4
  386. package/src/wirings/agent/voice-output.ts +1 -1
  387. package/src/wirings/agent-scorer/agent-scorer-judge.test.ts +145 -0
  388. package/src/wirings/agent-scorer/agent-scorer-judge.ts +60 -0
  389. package/src/wirings/agent-scorer/agent-scorer.ts +8 -0
  390. package/src/wirings/agent-scorer/agent-scorer.types.ts +21 -0
  391. package/src/wirings/agent-scorer/index.ts +1 -0
  392. package/src/wirings/channel/channel-common.ts +4 -2
  393. package/src/wirings/channel/channel-handler.ts +2 -5
  394. package/src/wirings/channel/channel-middleware-runner.ts +1 -1
  395. package/src/wirings/channel/channel-rpc.types.ts +1 -5
  396. package/src/wirings/channel/channel.types.ts +1 -2
  397. package/src/wirings/channel/local/local-channel-runner.test.ts +1 -2
  398. package/src/wirings/channel/serverless/index.ts +1 -0
  399. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +2 -2
  400. package/src/wirings/cli/channel/index.ts +1 -3
  401. package/src/wirings/cli/cli-runner.test.ts +1 -1
  402. package/src/wirings/cli/cli-runner.ts +11 -7
  403. package/src/wirings/cli/cli.types.ts +24 -3
  404. package/src/wirings/cli/command-parser.test.ts +388 -1
  405. package/src/wirings/cli/command-parser.ts +189 -29
  406. package/src/wirings/gateway/gateway-runner.test.ts +1 -2
  407. package/src/wirings/gateway/gateway-runner.ts +3 -6
  408. package/src/wirings/gateway/gateway.types.ts +5 -4
  409. package/src/wirings/http/http-routes.test.ts +1 -2
  410. package/src/wirings/http/http-runner-addon-ref.test.ts +238 -0
  411. package/src/wirings/http/http-runner.test.ts +3 -8
  412. package/src/wirings/http/http-runner.ts +9 -3
  413. package/src/wirings/http/http.types.ts +3 -12
  414. package/src/wirings/http/index.ts +1 -0
  415. package/src/wirings/http/pikku-fetch-http-request.ts +1 -1
  416. package/src/wirings/http/pikku-fetch-http-response.ts +3 -2
  417. package/src/wirings/mcp/mcp-runner.test.ts +1 -1
  418. package/src/wirings/mcp/mcp.types.ts +1 -2
  419. package/src/wirings/persona/index.ts +1 -4
  420. package/src/wirings/persona/persona.types.ts +14 -0
  421. package/src/wirings/queue/queue-identity.test.ts +1 -1
  422. package/src/wirings/queue/queue.types.ts +2 -6
  423. package/src/wirings/queue/signed-queue-service.ts +1 -1
  424. package/src/wirings/rpc/index.ts +0 -12
  425. package/src/wirings/rpc/rpc-runner.test.ts +4 -4
  426. package/src/wirings/rpc/rpc-runner.ts +3 -3
  427. package/src/wirings/scheduler/scheduler.types.ts +2 -5
  428. package/src/wirings/scope/index.ts +1 -0
  429. package/src/wirings/secret/secret.types.ts +10 -0
  430. package/src/wirings/secret/validate-secret-definitions.test.ts +23 -0
  431. package/src/wirings/secret/validate-secret-definitions.ts +2 -0
  432. package/src/wirings/variable/validate-variable-definitions.test.ts +24 -0
  433. package/src/wirings/variable/validate-variable-definitions.ts +2 -0
  434. package/src/wirings/variable/variable.types.ts +15 -0
  435. package/src/wirings/virtual-user/index.ts +1 -4
  436. package/src/wirings/virtual-user/prepare-virtual-user-run.ts +1 -1
  437. package/src/wirings/virtual-user/virtual-user-derive.test.ts +1 -1
  438. package/src/wirings/virtual-user/virtual-user-derive.ts +1 -1
  439. package/src/wirings/virtual-user/virtual-user.types.ts +1 -5
  440. package/src/wirings/workflow/graph/graph-foreach-queued.test.ts +569 -0
  441. package/src/wirings/workflow/graph/graph-foreach.test.ts +626 -0
  442. package/src/wirings/workflow/graph/graph-node.ts +16 -1
  443. package/src/wirings/workflow/graph/graph-runner.ts +387 -61
  444. package/src/wirings/workflow/graph/workflow-graph.types.ts +28 -3
  445. package/src/wirings/workflow/index.ts +8 -0
  446. package/src/wirings/workflow/pikku-scenario-service.ts +83 -20
  447. package/src/wirings/workflow/pikku-workflow-service.ts +37 -35
  448. package/src/wirings/workflow/run-timeline.ts +1 -1
  449. package/src/wirings/workflow/scenario-expectations.test.ts +28 -13
  450. package/src/wirings/workflow/scenario-run.types.ts +186 -0
  451. package/src/wirings/workflow/scenario-step-guards.ts +1 -14
  452. package/src/wirings/workflow/scenario-step.test.ts +32 -7
  453. package/src/wirings/workflow/scenario-step.types.ts +27 -12
  454. package/src/wirings/workflow/workflow-approval-policy.test.ts +117 -47
  455. package/src/wirings/workflow/workflow-approval.ts +2 -1
  456. package/src/wirings/workflow/workflow-run-engine.types.ts +2 -1
  457. package/src/wirings/workflow/workflow-step-claim.ts +46 -0
  458. package/src/wirings/workflow/workflow.types.ts +4 -12
  459. package/src/wirings-stay-decoupled.test.ts +6 -3
  460. package/tsconfig.tsbuildinfo +1 -1
  461. package/tsconfig.type-tests.json +4 -2
  462. package/dist/ecosystem/ai-agent.d.ts +0 -18
  463. package/dist/ecosystem/ai-agent.js +0 -6
  464. package/dist/ecosystem/ai-scorer.d.ts +0 -12
  465. package/dist/ecosystem/ai-scorer.js +0 -5
  466. package/dist/services/ai-agent-runner-service.d.ts +0 -220
  467. package/dist/services/ai-run-state-service.d.ts +0 -29
  468. package/dist/services/ai-storage-service.d.ts +0 -18
  469. package/dist/services/in-memory-ai-run-state-service.d.ts +0 -19
  470. package/dist/services/in-memory-ai-run-state-service.js +0 -54
  471. package/dist/testing/service-tests/ai-storage-service-tests.d.ts +0 -3
  472. package/dist/testing/service-tests/ai-storage-service-tests.js +0 -302
  473. package/dist/wirings/ai-agent/agent-rpc.d.ts +0 -15
  474. package/dist/wirings/ai-agent/agent-rpc.js +0 -53
  475. package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -79
  476. package/dist/wirings/ai-agent/ai-agent-agui.js +0 -327
  477. package/dist/wirings/ai-agent/ai-agent-finalize.d.ts +0 -58
  478. package/dist/wirings/ai-agent/ai-agent-finalize.js +0 -138
  479. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +0 -35
  480. package/dist/wirings/ai-agent/ai-agent-helpers.js +0 -47
  481. package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +0 -153
  482. package/dist/wirings/ai-agent/ai-agent-interrupt.js +0 -257
  483. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +0 -42
  484. package/dist/wirings/ai-agent/ai-agent-memory.js +0 -333
  485. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -16
  486. package/dist/wirings/ai-agent/ai-agent-model-config.js +0 -51
  487. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +0 -117
  488. package/dist/wirings/ai-agent/ai-agent-prepare.js +0 -728
  489. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +0 -16
  490. package/dist/wirings/ai-agent/ai-agent-registry.js +0 -51
  491. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +0 -7
  492. package/dist/wirings/ai-agent/ai-agent-runner.js +0 -580
  493. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +0 -41
  494. package/dist/wirings/ai-agent/ai-agent-stream.js +0 -1029
  495. package/dist/wirings/ai-agent/ai-agent-turn.d.ts +0 -57
  496. package/dist/wirings/ai-agent/ai-agent-turn.js +0 -82
  497. package/dist/wirings/ai-agent/ai-agent-utils.d.ts +0 -1
  498. package/dist/wirings/ai-agent/ai-agent-utils.js +0 -1
  499. package/dist/wirings/ai-agent/ai-agent.types.d.ts +0 -625
  500. package/dist/wirings/ai-agent/index.d.ts +0 -12
  501. package/dist/wirings/ai-agent/index.js +0 -10
  502. package/dist/wirings/ai-agent/voice-input.d.ts +0 -69
  503. package/dist/wirings/ai-agent/voice-input.js +0 -150
  504. package/dist/wirings/ai-agent/voice-output.d.ts +0 -85
  505. package/dist/wirings/ai-agent/voice-output.js +0 -196
  506. package/dist/wirings/ai-scorer/ai-scorer-grade.d.ts +0 -26
  507. package/dist/wirings/ai-scorer/ai-scorer-grade.js +0 -33
  508. package/dist/wirings/ai-scorer/ai-scorer-judge.d.ts +0 -17
  509. package/dist/wirings/ai-scorer/ai-scorer-judge.js +0 -92
  510. package/dist/wirings/ai-scorer/ai-scorer-live.d.ts +0 -15
  511. package/dist/wirings/ai-scorer/ai-scorer-live.js +0 -38
  512. package/dist/wirings/ai-scorer/ai-scorer-registry.d.ts +0 -18
  513. package/dist/wirings/ai-scorer/ai-scorer-registry.js +0 -46
  514. package/dist/wirings/ai-scorer/ai-scorer-sampling.d.ts +0 -8
  515. package/dist/wirings/ai-scorer/ai-scorer-sampling.js +0 -31
  516. package/dist/wirings/ai-scorer/ai-scorer-snapshots.d.ts +0 -10
  517. package/dist/wirings/ai-scorer/ai-scorer-snapshots.js +0 -40
  518. package/dist/wirings/ai-scorer/ai-scorer-worker.d.ts +0 -15
  519. package/dist/wirings/ai-scorer/ai-scorer-worker.js +0 -58
  520. package/dist/wirings/ai-scorer/ai-scorer.d.ts +0 -39
  521. package/dist/wirings/ai-scorer/ai-scorer.js +0 -40
  522. package/dist/wirings/ai-scorer/ai-scorer.types.d.ts +0 -90
  523. package/dist/wirings/ai-scorer/ai-scorer.types.js +0 -4
  524. package/dist/wirings/ai-scorer/index.d.ts +0 -6
  525. package/dist/wirings/ai-scorer/index.js +0 -5
  526. package/src/ecosystem/agent-scorer.ts +0 -24
  527. package/src/ecosystem/agent.ts +0 -42
  528. package/src/ecosystem/channel/local.ts +0 -1
  529. package/src/ecosystem/channel.ts +0 -22
  530. package/src/ecosystem/cli/channel.ts +0 -25
  531. package/src/ecosystem/cli.ts +0 -21
  532. package/src/ecosystem/credential.ts +0 -10
  533. package/src/ecosystem/dev.ts +0 -12
  534. package/src/ecosystem/function.ts +0 -28
  535. package/src/ecosystem/gateway.ts +0 -4
  536. package/src/ecosystem/hmac.ts +0 -1
  537. package/src/ecosystem/http.ts +0 -22
  538. package/src/ecosystem/mcp.ts +0 -17
  539. package/src/ecosystem/middleware.ts +0 -27
  540. package/src/ecosystem/node-host-resolver.ts +0 -1
  541. package/src/ecosystem/node.ts +0 -5
  542. package/src/ecosystem/oauth2.ts +0 -4
  543. package/src/ecosystem/persona.ts +0 -30
  544. package/src/ecosystem/queue.ts +0 -23
  545. package/src/ecosystem/remote.ts +0 -9
  546. package/src/ecosystem/role.ts +0 -13
  547. package/src/ecosystem/rpc.ts +0 -7
  548. package/src/ecosystem/safe-fetch.ts +0 -8
  549. package/src/ecosystem/scenario.ts +0 -32
  550. package/src/ecosystem/scheduler.ts +0 -5
  551. package/src/ecosystem/schema.ts +0 -1
  552. package/src/ecosystem/scope.ts +0 -14
  553. package/src/ecosystem/secret.ts +0 -15
  554. package/src/ecosystem/services/istanbul-coverage.ts +0 -1
  555. package/src/ecosystem/services/local-content-request-handler.ts +0 -16
  556. package/src/ecosystem/services/local-content.ts +0 -1
  557. package/src/ecosystem/services/v8-coverage.ts +0 -1
  558. package/src/ecosystem/services.ts +0 -82
  559. package/src/ecosystem/trigger.ts +0 -7
  560. package/src/ecosystem/types.ts +0 -34
  561. package/src/ecosystem/variable.ts +0 -14
  562. package/src/ecosystem/virtual-user.ts +0 -48
  563. package/src/ecosystem/workflow.ts +0 -68
  564. package/src/ecosystem.ts +0 -40
  565. package/src/index.ts +0 -244
  566. /package/dist/{services/ai-agent-runner-service.js → bootstrap-compat/root.js} +0 -0
  567. /package/dist/{services/ai-run-state-service.js → classification/data-classification.js} +0 -0
  568. /package/dist/{services/ai-storage-service.js → errors/serialized-error.js} +0 -0
  569. /package/dist/{wirings/ai-agent/ai-agent.types.js → function/function-meta.types.js} +0 -0
  570. /package/src/{column-form.ts → classification/column-form.ts} +0 -0
  571. /package/src/{pikku-request.test.ts → function/pikku-request.test.ts} +0 -0
  572. /package/src/{pikku-request.ts → function/pikku-request.ts} +0 -0
  573. /package/src/wirings/{rpc → addon}/addon-auth-tags.test.ts +0 -0
  574. /package/src/wirings/{rpc → addon}/addon-runner.ts +0 -0
  575. /package/src/wirings/{rpc → addon}/addon-secrets.test.ts +0 -0
  576. /package/src/wirings/{rpc → addon}/wire-addon.test.ts +0 -0
  577. /package/src/wirings/{rpc → addon}/wire-remote-addon.ts +0 -0
@@ -16,74 +16,81 @@
16
16
  *
17
17
  * Run: yarn api-report
18
18
  */
19
- import { readFileSync, writeFileSync } from 'node:fs';
20
- import { resolve, dirname } from 'node:path';
21
- import { fileURLToPath } from 'node:url';
22
- import ts from 'typescript';
23
- const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
24
- const pkg = JSON.parse(readFileSync(resolve(packageRoot, 'package.json'), 'utf-8'));
19
+ import { readFileSync, writeFileSync } from 'node:fs'
20
+ import { resolve, dirname } from 'node:path'
21
+ import { fileURLToPath } from 'node:url'
22
+ import ts from 'typescript'
23
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..')
24
+ const pkg = JSON.parse(
25
+ readFileSync(resolve(packageRoot, 'package.json'), 'utf-8')
26
+ )
25
27
  const entryPoints = Object.entries(pkg.exports).map(([subpath, dist]) => ({
26
- subpath,
27
- file: resolve(packageRoot, dist.replace('./dist/', './src/').replace(/\.js$/, '.ts')),
28
- }));
29
- const program = ts.createProgram(entryPoints.map((e) => e.file), {
28
+ subpath,
29
+ file: resolve(
30
+ packageRoot,
31
+ dist.replace('./dist/', './src/').replace(/\.js$/, '.ts')
32
+ ),
33
+ }))
34
+ const program = ts.createProgram(
35
+ entryPoints.map((e) => e.file),
36
+ {
30
37
  target: ts.ScriptTarget.ESNext,
31
38
  module: ts.ModuleKind.Node16,
32
39
  moduleResolution: ts.ModuleResolutionKind.Node16,
33
40
  strict: true,
34
41
  skipLibCheck: true,
35
- });
36
- const checker = program.getTypeChecker();
42
+ }
43
+ )
44
+ const checker = program.getTypeChecker()
37
45
  /** One line per symbol: how it is declared, flattened and stripped of noise. */
38
46
  const signature = (exported) => {
39
- // A re-export is an alias; the declaration that matters is the target's, so
40
- // an interface re-exported through a barrel still reports its members.
41
- const symbol = exported.flags & ts.SymbolFlags.Alias
42
- ? checker.getAliasedSymbol(exported)
43
- : exported;
44
- const declaration = symbol.declarations?.[0];
45
- if (!declaration)
46
- return exported.getName();
47
- if (ts.isInterfaceDeclaration(declaration) ||
48
- ts.isClassDeclaration(declaration) ||
49
- ts.isTypeAliasDeclaration(declaration) ||
50
- ts.isEnumDeclaration(declaration)) {
51
- // The declaration itself, so member changes show up in the diff.
52
- return declaration
53
- .getText()
54
- .replace(/\/\*\*[\s\S]*?\*\//g, '')
55
- .replace(/\/\/[^\n]*/g, '')
56
- .split('\n')
57
- .map((l) => l.trim())
58
- .filter(Boolean)
59
- .join(' ');
60
- }
61
- const type = checker.getTypeOfSymbolAtLocation(symbol, declaration);
62
- return `${exported.getName()}: ${checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation)}`;
63
- };
47
+ // A re-export is an alias; the declaration that matters is the target's, so
48
+ // an interface re-exported through a barrel still reports its members.
49
+ const symbol =
50
+ exported.flags & ts.SymbolFlags.Alias
51
+ ? checker.getAliasedSymbol(exported)
52
+ : exported
53
+ const declaration = symbol.declarations?.[0]
54
+ if (!declaration) return exported.getName()
55
+ if (
56
+ ts.isInterfaceDeclaration(declaration) ||
57
+ ts.isClassDeclaration(declaration) ||
58
+ ts.isTypeAliasDeclaration(declaration) ||
59
+ ts.isEnumDeclaration(declaration)
60
+ ) {
61
+ // The declaration itself, so member changes show up in the diff.
62
+ return declaration
63
+ .getText()
64
+ .replace(/\/\*\*[\s\S]*?\*\//g, '')
65
+ .replace(/\/\/[^\n]*/g, '')
66
+ .split('\n')
67
+ .map((l) => l.trim())
68
+ .filter(Boolean)
69
+ .join(' ')
70
+ }
71
+ const type = checker.getTypeOfSymbolAtLocation(symbol, declaration)
72
+ return `${exported.getName()}: ${checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation)}`
73
+ }
64
74
  const sections = [
65
- '# @pikku/core API report',
66
- '',
67
- 'Generated by `yarn api-report`. Every exported symbol with its full',
68
- 'signature, so a member-level change is a reviewable diff. Do not edit.',
69
- '',
70
- ];
75
+ '# @pikku/core API report',
76
+ '',
77
+ 'Generated by `yarn api-report`. Every exported symbol with its full',
78
+ 'signature, so a member-level change is a reviewable diff. Do not edit.',
79
+ '',
80
+ ]
71
81
  for (const { subpath, file } of entryPoints) {
72
- const source = program.getSourceFile(file);
73
- if (!source)
74
- continue;
75
- const moduleSymbol = checker.getSymbolAtLocation(source);
76
- if (!moduleSymbol)
77
- continue;
78
- const exports = checker
79
- .getExportsOfModule(moduleSymbol)
80
- .map((s) => [s.getName(), signature(s)])
81
- .sort(([a], [b]) => a.localeCompare(b));
82
- sections.push(`## ${subpath}`, '');
83
- sections.push('```ts');
84
- for (const [, sig] of exports)
85
- sections.push(sig);
86
- sections.push('```', '');
82
+ const source = program.getSourceFile(file)
83
+ if (!source) continue
84
+ const moduleSymbol = checker.getSymbolAtLocation(source)
85
+ if (!moduleSymbol) continue
86
+ const exports = checker
87
+ .getExportsOfModule(moduleSymbol)
88
+ .map((s) => [s.getName(), signature(s)])
89
+ .sort(([a], [b]) => a.localeCompare(b))
90
+ sections.push(`## ${subpath}`, '')
91
+ sections.push('```ts')
92
+ for (const [, sig] of exports) sections.push(sig)
93
+ sections.push('```', '')
87
94
  }
88
- writeFileSync(resolve(packageRoot, 'api-report.md'), sections.join('\n'));
89
- console.log(`api-report.md written for ${entryPoints.length} entry points`);
95
+ writeFileSync(resolve(packageRoot, 'api-report.md'), sections.join('\n'))
96
+ console.log(`api-report.md written for ${entryPoints.length} entry points`)
@@ -180,9 +180,7 @@ const isPublic = (member: ts.ClassElement | ts.TypeElement): boolean =>
180
180
  */
181
181
  const membered = (
182
182
  declaration:
183
- | ts.ClassDeclaration
184
- | ts.InterfaceDeclaration
185
- | ts.EnumDeclaration,
183
+ ts.ClassDeclaration | ts.InterfaceDeclaration | ts.EnumDeclaration,
186
184
  members: ts.NodeArray<ts.ClassElement | ts.TypeElement | ts.EnumMember>
187
185
  ): string => {
188
186
  if (members.length === 0) return oneLine(declaration.getText())
@@ -233,17 +231,6 @@ const signature = (exported: ts.Symbol): string => {
233
231
  return `${exported.getName()}: ${checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation)}`
234
232
  }
235
233
 
236
- /**
237
- * Entry points whose signatures move with the CLI's codegen. Everything else
238
- * is what an application imports, and is what a compatibility promise covers.
239
- *
240
- * knowledge: decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md
241
- */
242
- const isEcosystem = (subpath: string) =>
243
- subpath === './ecosystem' ||
244
- subpath === './internal' ||
245
- subpath.startsWith('./ecosystem/')
246
-
247
234
  type Exported = { name: string; members: number; signature: string }
248
235
 
249
236
  /** The members the report lists, which is what the tally is counting. */
@@ -282,33 +269,16 @@ for (const { subpath, file } of entryPoints) {
282
269
  )
283
270
  }
284
271
 
285
- // A name reachable from more than one entry point is counted once, against the
286
- // weaker promise reaching it through a stable subpath is what a consumer will
287
- // have done, whatever else also exports it.
288
- const tierOf = new Map<string, string>()
272
+ // A name reachable from more than one entry point is counted once: what a
273
+ // compatibility promise owes is the name, not each door onto it.
289
274
  const membersOf = new Map<string, number>()
290
- for (const [subpath, exports] of modules) {
291
- const tier = isEcosystem(subpath) ? 'ecosystem' : 'stable'
292
- for (const { name, members } of exports) {
293
- if (tier === 'stable' || !tierOf.has(name)) tierOf.set(name, tier)
275
+ for (const exports of modules.values())
276
+ for (const { name, members } of exports)
294
277
  membersOf.set(name, Math.max(membersOf.get(name) ?? 0, members))
295
- }
296
- }
297
278
 
298
- const tally = (tier: string) => {
299
- const names = [...tierOf].filter(([, t]) => t === tier).map(([n]) => n)
300
- return {
301
- entryPoints: [...modules.keys()].filter(
302
- (s) => (isEcosystem(s) ? 'ecosystem' : 'stable') === tier
303
- ).length,
304
- names: names.length,
305
- members: names.reduce((total, n) => total + (membersOf.get(n) ?? 0), 0),
306
- }
307
- }
308
- const stable = tally('stable')
309
- const ecosystem = tally('ecosystem')
310
- const observable =
311
- stable.names + stable.members + ecosystem.names + ecosystem.members
279
+ const names = membersOf.size
280
+ const members = [...membersOf.values()].reduce((total, n) => total + n, 0)
281
+ const observable = names + members
312
282
 
313
283
  const reachableFrom = new Map<string, number>()
314
284
  for (const exports of modules.values())
@@ -337,13 +307,9 @@ const sections: string[] = [
337
307
  '',
338
308
  '## What a compatibility promise covers',
339
309
  '',
340
- `**${observable} observable things**: ${stable.names + ecosystem.names} exported names, plus`,
341
- `${stable.members + ecosystem.members} members on the classes and interfaces among them.`,
342
- '',
343
- '| tier | entry points | names | members |',
344
- '| --- | ---: | ---: | ---: |',
345
- `| stable | ${stable.entryPoints} | ${stable.names} | ${stable.members} |`,
346
- `| ecosystem | ${ecosystem.entryPoints} | ${ecosystem.names} | ${ecosystem.members} |`,
310
+ `**${observable} observable things**: ${names} exported names, plus`,
311
+ `${members} members on the classes and interfaces among them, reachable`,
312
+ `through ${modules.size} entry points.`,
347
313
  '',
348
314
  'An entry point whose exports are mostly *exclusive* is a self-contained',
349
315
  'subsystem rather than shared machinery — which tends to mean a newer one.',
@@ -1,7 +1,8 @@
1
1
  import { describe, test } from 'node:test'
2
2
  import assert from 'node:assert/strict'
3
3
  import { execFileSync } from 'node:child_process'
4
- import { readFileSync, writeFileSync } from 'node:fs'
4
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
5
+ import { tmpdir } from 'node:os'
5
6
  import { fileURLToPath } from 'node:url'
6
7
  import { join, dirname } from 'node:path'
7
8
 
@@ -67,3 +68,71 @@ describe('the API report matches the code', () => {
67
68
  )
68
69
  })
69
70
  })
71
+
72
+ /**
73
+ * Every branch that touches the public surface rewrites the whole report, so
74
+ * two of them meeting is a ~9000-line conflict with no meaningful resolution
75
+ * in it. A merge driver takes the conflict away; the test above is what still
76
+ * insists on a report that matches the code.
77
+ *
78
+ * knowledge: decisions/internals/the-api-report-pins-members-not-just-names.md
79
+ */
80
+ describe('merging the API report is not hand work', () => {
81
+ const repoRoot = join(packageRoot, '..', '..')
82
+
83
+ test('.gitattributes routes the report through the driver', () => {
84
+ const attributes = readFileSync(join(repoRoot, '.gitattributes'), 'utf-8')
85
+
86
+ assert.match(
87
+ attributes,
88
+ /^packages\/core\/api-report\.md\s+merge=api-report\b/m,
89
+ 'the report must name the merge driver, or git conflicts on it as usual'
90
+ )
91
+ })
92
+
93
+ test('the setup script registers the driver as a plain take-one-side', () => {
94
+ // Against a throwaway repository rather than this one: a driver is written
95
+ // to `.git/config`, which every worktree of a checkout shares, so running
96
+ // this in place would reach into whatever else is checked out beside it.
97
+ const sandbox = mkdtempSync(join(tmpdir(), 'pikku-merge-driver-'))
98
+ try {
99
+ execFileSync('git', ['init', '--quiet', sandbox], { stdio: 'pipe' })
100
+ execFileSync(
101
+ 'node',
102
+ [join(repoRoot, 'scripts', 'setup-merge-drivers.mjs')],
103
+ { cwd: sandbox, stdio: 'pipe' }
104
+ )
105
+ const driver = execFileSync(
106
+ 'git',
107
+ ['config', '--local', 'merge.api-report.driver'],
108
+ { cwd: sandbox, stdio: 'pipe' }
109
+ )
110
+ .toString()
111
+ .trim()
112
+
113
+ // `true` writes nothing and succeeds, which is how a driver tells git to
114
+ // keep the side already in %A. Anything that regenerates the report is
115
+ // the trap this pins shut: git runs a driver while merging that one
116
+ // path, with the rest of the tree still unmerged, so the generator reads
117
+ // the old sources and resolves to a report missing exactly the API the
118
+ // incoming branch adds — conflict-free and wrong, which is worse than a
119
+ // conflict. The regeneration belongs to the guard above, which runs
120
+ // against a finished tree.
121
+ assert.equal(
122
+ driver,
123
+ 'true',
124
+ 'the driver must resolve to one side verbatim and run nothing'
125
+ )
126
+ } finally {
127
+ rmSync(sandbox, { recursive: true, force: true })
128
+ }
129
+ })
130
+
131
+ test('postinstall runs the setup, so a fresh clone is not left without it', () => {
132
+ const manifest = JSON.parse(
133
+ readFileSync(join(repoRoot, 'package.json'), 'utf-8')
134
+ )
135
+
136
+ assert.match(manifest.scripts.postinstall, /setup-merge-drivers\.mjs/)
137
+ })
138
+ })
@@ -0,0 +1,179 @@
1
+ import { test, describe } from 'node:test'
2
+ import * as assert from 'assert'
3
+ import ts from 'typescript'
4
+ import { readFileSync, readdirSync, statSync } from 'node:fs'
5
+ import { dirname, join, relative } from 'node:path'
6
+ import { fileURLToPath } from 'node:url'
7
+
8
+ /**
9
+ * The generated `#pikku` alias is the app developer's public API. An app
10
+ * reaching past it into `@pikku/core` is the smell this file measures: the
11
+ * alias is typed against that app's own functions, so a name pulled from core
12
+ * directly is one the app is holding untyped and one the CLI cannot evolve.
13
+ *
14
+ * The trees below are apps rather than packages, so they have no `src`
15
+ * convention to walk — bootstrap and test files sit wherever the runtime wants
16
+ * them. Walking each tree root means skipping what an app accumulates:
17
+ * installed dependencies, build output, and its own generated `.pikku`.
18
+ */
19
+ const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '../../..')
20
+ const appTrees = ['templates', 'e2e', 'verifiers']
21
+ const skipped = new Set(['node_modules', 'dist', '.next', 'build'])
22
+
23
+ /**
24
+ * `outDir` is a project's own setting, so the generated tree is not always
25
+ * `.pikku` — the treeshake verifier writes one output tree per scenario under
26
+ * `.pikku-shake`. Matching the prefix keeps a leaf's generated `index.ts`, which
27
+ * carries no `.gen.` in its name, from reading as hand-written app code.
28
+ */
29
+ const isGeneratedTree = (entry: string) => entry.startsWith('.pikku')
30
+
31
+ const walkApp = (dir: string, out: string[] = []): string[] => {
32
+ for (const entry of readdirSync(dir)) {
33
+ if (skipped.has(entry) || isGeneratedTree(entry)) continue
34
+ const path = join(dir, entry)
35
+ if (statSync(path).isDirectory()) walkApp(path, out)
36
+ else if (path.endsWith('.ts') || path.endsWith('.tsx')) out.push(path)
37
+ }
38
+ return out
39
+ }
40
+
41
+ /**
42
+ * `.gen.*` and `.d.ts` files are CLI output, not hand-written source: what they
43
+ * import is decided by the codegen templates, which are the thing that writes
44
+ * the alias in the first place.
45
+ */
46
+ const isGenerated = (path: string) =>
47
+ path.includes('.gen.') || path.endsWith('.d.ts')
48
+
49
+ const appSourceFiles = () =>
50
+ appTrees
51
+ .flatMap((tree) => walkApp(join(repoRoot, tree)))
52
+ .filter((file) => !isGenerated(file))
53
+
54
+ /**
55
+ * Parsed rather than grepped: a step body held as a template literal is fixture
56
+ * text describing a user's file, not an import the app itself makes.
57
+ */
58
+ const coreImports = (file: string) => {
59
+ const source = ts.createSourceFile(
60
+ file,
61
+ readFileSync(file, 'utf8'),
62
+ ts.ScriptTarget.Latest,
63
+ true
64
+ )
65
+ const found: { specifier: string; line: number; names: string[] }[] = []
66
+ for (const statement of source.statements) {
67
+ if (
68
+ !ts.isImportDeclaration(statement) &&
69
+ !ts.isExportDeclaration(statement)
70
+ ) {
71
+ continue
72
+ }
73
+ const moduleSpecifier = statement.moduleSpecifier
74
+ if (!moduleSpecifier || !ts.isStringLiteral(moduleSpecifier)) continue
75
+ const specifier = moduleSpecifier.text
76
+ if (specifier !== '@pikku/core' && !specifier.startsWith('@pikku/core/')) {
77
+ continue
78
+ }
79
+ const { line } = source.getLineAndCharacterOfPosition(
80
+ statement.getStart(source)
81
+ )
82
+ const clause = ts.isImportDeclaration(statement)
83
+ ? statement.importClause?.namedBindings
84
+ : statement.exportClause
85
+ const names =
86
+ clause && (ts.isNamedImports(clause) || ts.isNamedExports(clause))
87
+ ? clause.elements.map((element) => element.name.text)
88
+ : []
89
+ found.push({ specifier, line: line + 1, names })
90
+ }
91
+ return found
92
+ }
93
+
94
+ /**
95
+ * The scenario and persona surfaces are test-only names — actors, cookie jars,
96
+ * polling helpers, the typed personas an app declares. They are app code, but a
97
+ * distinct surface from wiring, so they reach the app through their own
98
+ * sub-entry rather than crowding the main hub.
99
+ */
100
+ const scenarioSubpaths = new Set(['@pikku/core/scenario', '@pikku/core/persona'])
101
+
102
+ /**
103
+ * A relative path into the generated scenario barrel reaches the same file the
104
+ * alias does, so it compiles — and then hard-codes how far the app file sits
105
+ * from `outDir`. Moving either end breaks it, and the CLI has no way to see
106
+ * that it is depended upon.
107
+ */
108
+ const relativeIntoScenarioBarrel = (file: string) => {
109
+ const source = ts.createSourceFile(
110
+ file,
111
+ readFileSync(file, 'utf8'),
112
+ ts.ScriptTarget.Latest,
113
+ true
114
+ )
115
+ const found: { specifier: string; line: number }[] = []
116
+ for (const statement of source.statements) {
117
+ if (
118
+ !ts.isImportDeclaration(statement) &&
119
+ !ts.isExportDeclaration(statement)
120
+ ) {
121
+ continue
122
+ }
123
+ const moduleSpecifier = statement.moduleSpecifier
124
+ if (!moduleSpecifier || !ts.isStringLiteral(moduleSpecifier)) continue
125
+ if (!moduleSpecifier.text.startsWith('.')) continue
126
+ if (!/\/pikku-scenario-types\.gen\.js$/.test(moduleSpecifier.text)) continue
127
+ const { line } = source.getLineAndCharacterOfPosition(
128
+ statement.getStart(source)
129
+ )
130
+ found.push({ specifier: moduleSpecifier.text, line: line + 1 })
131
+ }
132
+ return found
133
+ }
134
+
135
+ describe('the #pikku alias is the app surface', () => {
136
+ test('scenario code reaches the test surface through #pikku/scenario', () => {
137
+ const offenders: string[] = []
138
+
139
+ for (const file of appSourceFiles()) {
140
+ for (const { specifier, line, names } of coreImports(file)) {
141
+ if (!scenarioSubpaths.has(specifier)) continue
142
+ offenders.push(
143
+ `${relative(repoRoot, file)}:${line} ${names.join(', ')} from '${specifier}'`
144
+ )
145
+ }
146
+ }
147
+
148
+ assert.deepStrictEqual(
149
+ offenders,
150
+ [],
151
+ `Scenario and persona names come from the generated ` +
152
+ `'#pikku/scenario' entry, which is typed against this app's own ` +
153
+ `personas and steps.\n` +
154
+ `Reaching '@pikku/core/scenario' or '@pikku/core/persona' directly ` +
155
+ `gets the untyped shape, from a subpath scheduled for deletion.\n\n` +
156
+ offenders.join('\n')
157
+ )
158
+ })
159
+
160
+ test('the scenario barrel is reached through the alias, not a relative path', () => {
161
+ const offenders: string[] = []
162
+
163
+ for (const file of appSourceFiles()) {
164
+ for (const { specifier, line } of relativeIntoScenarioBarrel(file)) {
165
+ offenders.push(`${relative(repoRoot, file)}:${line} '${specifier}'`)
166
+ }
167
+ }
168
+
169
+ assert.deepStrictEqual(
170
+ offenders,
171
+ [],
172
+ `The generated scenario barrel is reached through '#pikku/scenario', ` +
173
+ `which the app's own 'imports' map points at.\n` +
174
+ `A relative path hard-codes the distance from the file to 'outDir', ` +
175
+ `so moving either end breaks it silently.\n\n` +
176
+ offenders.join('\n')
177
+ )
178
+ })
179
+ })