@voltro/cli 0.60.0 → 0.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/apiBuild-Dl-djDc_.js +2 -0
  3. package/dist/{apiBuild-BU5cd-Fn.js → apiBuild-DwhySM-6.js} +2 -2
  4. package/dist/bin.js +1 -1
  5. package/dist/{build-BxAsLzyU.js → build-B43mm2g2.js} +7 -7
  6. package/dist/{checkCommand-C1CQc8lD.js → checkCommand-nB68vIo_.js} +1 -1
  7. package/dist/{checkCommand-DC7k1_hP.js → checkCommand-zGYZtIkJ.js} +3 -3
  8. package/dist/{codegenCommand-kS3Twuc9.js → codegenCommand-YvqhgQBj.js} +1 -1
  9. package/dist/{codemodRunner-ClUqkhvR.js → codemodRunner-D90bexh4.js} +233 -159
  10. package/dist/{commands-Ro4hYBHD.js → commands-Dd6Cp7qs.js} +21 -21
  11. package/dist/{dashboardCommand-t8Qsebjr.js → dashboardCommand-BsDfQa-g.js} +3 -3
  12. package/dist/{dataCommand-hNOGKz4K.js → dataCommand-Cgdcl5M0.js} +1 -1
  13. package/dist/{dev-Ce2gEziv.js → dev-BfUG0jrD.js} +32 -12
  14. package/dist/{dev-Dff_pdik.js → dev-BpMSAjMk.js} +1 -1
  15. package/dist/doctorCommand-PHcqxpnx.js +2 -0
  16. package/dist/{doctorCommand-CGjefPmk.js → doctorCommand-pxYq2bH5.js} +13 -13
  17. package/dist/{dormancyCommand-DYgI0Kf-.js → dormancyCommand-DZpSCWy9.js} +1 -1
  18. package/dist/{embeddingsCommand-yJivQSrI.js → embeddingsCommand-YR5Eif0k.js} +1 -1
  19. package/dist/{envCommand-ORJUf8r_.js → envCommand-Yl4TGM4h.js} +2 -2
  20. package/dist/{evolveCommand-CThb0EZZ.js → evolveCommand-B2iYAC9t.js} +2 -2
  21. package/dist/index.js +1 -1
  22. package/dist/{infoCommand-a0WkKcUY.js → infoCommand-DjtMWLZl.js} +1 -1
  23. package/dist/{probeCommand-BUYzc0CT.js → probeCommand-Dsu5if_4.js} +1 -1
  24. package/dist/{runtimeTrace-DDuKJgVi.js → runtimeTrace-CQcn26bI.js} +1 -1
  25. package/dist/{sdkgen-vq1fF9D_.js → sdkgen-DJvyVw7B.js} +1 -1
  26. package/dist/serveCommand-CZ0kgfIX.js +2 -0
  27. package/dist/{serveCommand-Dr4KXmTS.js → serveCommand-CaLTTh68.js} +3 -3
  28. package/dist/serveEntry.js +1 -1
  29. package/dist/{start-BhoDQ25C.js → start-DE4ixCTi.js} +1 -1
  30. package/dist/{start-CcdPRG8L.js → start-bqT4GRH0.js} +427 -418
  31. package/dist/startEntry.js +1 -1
  32. package/dist/updateCommand-DA4OMF7u.js +2 -0
  33. package/dist/{updateCommand-D9avpQFT.js → updateCommand-F6HFgz0i.js} +1 -1
  34. package/dist/{webDev-CBN9KkyQ.js → webDev-CYjhmOTZ.js} +1 -1
  35. package/dist/{webDev-Bzb8ZFus.js → webDev-CuG3Ged-.js} +1 -1
  36. package/dist/{webhooksCommand-BPJQOGTe.js → webhooksCommand-Bgdli8dI.js} +1 -1
  37. package/package.json +37 -19
  38. package/templates/AGENTS.md +2 -2
  39. package/templates/agent-docs/_index.md +2 -2
  40. package/templates/agent-docs/_manifest.json +1 -1
  41. package/templates/agent-docs/ai.md +32 -0
  42. package/templates/agent-docs/data.md +10 -2
  43. package/templates/agent-docs/observability.md +17 -2
  44. package/templates/agent-docs/plugins/sentry.md +29 -12
  45. package/templates/agent-docs/schema-driven-ui.md +38 -10
  46. package/templates/agent-docs/whats-new.md +5 -45
  47. package/templates/agent-docs/workflows.md +7 -2
  48. package/templates/apps/api-ai/package.json +6 -6
  49. package/templates/apps/api-auth/package.json +8 -8
  50. package/templates/apps/api-backend/package.json +7 -7
  51. package/templates/apps/api-backend-deactivation/package.json +7 -7
  52. package/templates/apps/api-backend-mail/package.json +8 -8
  53. package/templates/apps/api-backend-mariadb/package.json +9 -9
  54. package/templates/apps/api-backend-sqlite/package.json +8 -8
  55. package/templates/apps/api-backend-storage/package.json +8 -8
  56. package/templates/apps/api-cms/package.json +9 -9
  57. package/templates/apps/api-collab/package.json +8 -8
  58. package/templates/apps/api-data-advanced/package.json +8 -8
  59. package/templates/apps/api-durable/package.json +8 -8
  60. package/templates/apps/api-feature-flags/package.json +9 -9
  61. package/templates/apps/api-governance/package.json +8 -8
  62. package/templates/apps/api-kv/package.json +8 -8
  63. package/templates/apps/api-moderation/package.json +8 -8
  64. package/templates/apps/api-observability/package.json +8 -8
  65. package/templates/apps/api-ratelimit/package.json +8 -8
  66. package/templates/apps/api-rbac/package.json +8 -8
  67. package/templates/apps/api-rest/package.json +7 -7
  68. package/templates/apps/api-row-history/package.json +8 -8
  69. package/templates/apps/api-saas/package.json +11 -11
  70. package/templates/apps/api-saas-starter/package.json +10 -10
  71. package/templates/apps/api-search/package.json +8 -8
  72. package/templates/apps/api-status/package.json +8 -8
  73. package/templates/apps/api-webhooks/package.json +9 -9
  74. package/templates/apps/changelog/package.json +7 -7
  75. package/templates/apps/edge-functions/package.json +2 -2
  76. package/templates/apps/frontend-admin/package.json +7 -7
  77. package/templates/apps/frontend-app/package.json +8 -8
  78. package/templates/apps/frontend-auth/package.json +7 -7
  79. package/templates/apps/frontend-blank/package.json +6 -6
  80. package/templates/apps/frontend-cms/package.json +8 -8
  81. package/templates/apps/frontend-collab/package.json +9 -9
  82. package/templates/apps/frontend-contact/package.json +7 -7
  83. package/templates/apps/frontend-dashboard/package.json +6 -6
  84. package/templates/apps/frontend-docs/package.json +8 -8
  85. package/templates/apps/frontend-i18n/package.json +6 -6
  86. package/templates/apps/frontend-landing/package.json +7 -7
  87. package/templates/apps/frontend-portal/package.json +7 -7
  88. package/templates/apps/frontend-saas/package.json +7 -7
  89. package/templates/apps/frontend-spa/package.json +6 -6
  90. package/templates/apps/frontend-ssr/package.json +6 -6
  91. package/templates/apps/frontend-ssr-api/package.json +7 -7
  92. package/templates/apps/frontend-static-blog/package.json +8 -8
  93. package/templates/apps/frontend-status/package.json +7 -7
  94. package/templates/apps/mobile-app/package.json +4 -4
  95. package/dist/apiBuild-B9OvhITV.js +0 -2
  96. package/dist/doctorCommand-DXnNpKQT.js +0 -2
  97. package/dist/serveCommand-1R52mo6F.js +0 -2
  98. package/dist/updateCommand-QMOirvXC.js +0 -2
@@ -3,8 +3,8 @@ import { t as d } from "./pageConvention-CMpfDN6r.js";
3
3
  import { r as f } from "./tsconfigPaths-BWXBWgcl.js";
4
4
  import { a as p, i as m, t as h } from "./fileTaxonomy-CbyMQYx_.js";
5
5
  import { basename as g, dirname as _, join as v, relative as ee } from "node:path";
6
- import { existsSync as y, readFileSync as te, statSync as ne } from "node:fs";
7
- import { execFileSync as b } from "node:child_process";
6
+ import { existsSync as y, readFileSync as b, statSync as te } from "node:fs";
7
+ import { execFileSync as ne } from "node:child_process";
8
8
  import { Node as x, Project as re, QuoteKind as ie, SyntaxKind as S } from "ts-morph";
9
9
  import { globSync as ae } from "tinyglobby";
10
10
  //#region src/codemodHelpers.ts
@@ -504,20 +504,20 @@ var C = (e, t, n) => {
504
504
  "read it now rather than waiting: `sourceKey` is almost always what a",
505
505
  "\"parent\" relation means."
506
506
  ].join("\n")
507
- }), Oe = "@voltro/plugin-atlassian", ke = "atlassianPlugin", O = (e) => {
507
+ }), Oe = "@voltro/plugin-atlassian", ke = "atlassianPlugin", Ae = (e) => {
508
508
  let t = [];
509
509
  for (let n of e.getImportDeclarations()) if (n.getModuleSpecifierValue() === Oe) for (let e of n.getNamedImports()) e.getName() === ke && t.push(e.getAliasNode()?.getText() ?? e.getName());
510
510
  return t;
511
- }, Ae = T({
511
+ }, je = T({
512
512
  version: "0.6.0",
513
513
  id: "0.6.0/05_atlassian-avatar-mode",
514
514
  title: "atlassianPlugin's `avatar` config requires an explicit `mode: 'service' | 'perUser'`",
515
515
  kind: "transform",
516
- appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => O(e).length > 0),
516
+ appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => Ae(e).length > 0),
517
517
  transform: ({ project: e, log: t }) => {
518
518
  let n = 0;
519
519
  for (let t of e.getSourceFiles()) {
520
- let e = O(t);
520
+ let e = Ae(t);
521
521
  if (e.length !== 0) for (let r of t.getDescendantsOfKind(S.CallExpression)) {
522
522
  if (!e.includes(r.getExpression().getText())) continue;
523
523
  let t = r.getArguments()[0];
@@ -533,7 +533,7 @@ var C = (e, t, n) => {
533
533
  }
534
534
  n > 0 && (t(`atlassian avatar: added mode:'service' to ${n} config${n === 1 ? "" : "s"}`), t(" → to use the viewing user's own PAT instead, switch to mode:'perUser' and add resolveSubject"));
535
535
  }
536
- }), je = T({
536
+ }), Me = T({
537
537
  version: "0.6.0",
538
538
  id: "0.6.0/06_ui-strings-connect-account",
539
539
  title: "UiStrings gained a required `connectAccount` section",
@@ -577,14 +577,14 @@ var C = (e, t, n) => {
577
577
  "Alternatively, switch the annotation to `PartialUiStrings` if the object",
578
578
  "was only ever an override bag."
579
579
  ].join("\n")
580
- }), Me = E("setRowFilter"), Ne = /\bresolveRowFilterScope\b/, Pe = T({
580
+ }), Ne = E("setRowFilter"), Pe = /\bresolveRowFilterScope\b/, Fe = T({
581
581
  version: "0.7.0",
582
582
  id: "0.7.0/01_row-filter-load-failure",
583
583
  title: "A row filter that fails to load now errors instead of returning zero rows",
584
584
  kind: "manual",
585
585
  appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => {
586
586
  let t = e.getFullText();
587
- return Me.test(t) || Ne.test(t);
587
+ return Ne.test(t) || Pe.test(t);
588
588
  }),
589
589
  note: [
590
590
  "Row-level security: a `load` failure is now an ERROR, and is retried first.",
@@ -655,7 +655,7 @@ var C = (e, t, n) => {
655
655
  " \"every row you could see was just deleted\". Make sure your subscription",
656
656
  " error handling surfaces this rather than swallowing it."
657
657
  ].join("\n")
658
- }), Fe = T({
658
+ }), Ie = T({
659
659
  version: "0.7.0",
660
660
  id: "0.7.0/02_testing-invoke-effect-handlers",
661
661
  title: "@voltro/testing: invoke() runs Effect handlers; executor types widened",
@@ -710,14 +710,14 @@ var C = (e, t, n) => {
710
710
  "transaction, the deadlock replay, `afterCommit` and the plugin interceptor",
711
711
  "chain wrap an Effect handler exactly as they wrap an async one."
712
712
  ].join("\n")
713
- }), Ie = /\bpasswordHash\b/, Le = /\b(UserStore|UserRecord|memoryUserStore|postgresUserStore)\b/, Re = T({
713
+ }), Le = /\bpasswordHash\b/, Re = /\b(UserStore|UserRecord|memoryUserStore|postgresUserStore)\b/, ze = T({
714
714
  version: "0.8.0",
715
715
  id: "0.8.0/01_optional-password-hash",
716
716
  title: "`UserRecord.passwordHash` is optional — password-less identities are now first-class",
717
717
  kind: "manual",
718
718
  appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => {
719
719
  let t = e.getFullText();
720
- return Ie.test(t) || Le.test(t);
720
+ return Le.test(t) || Re.test(t);
721
721
  }),
722
722
  note: [
723
723
  "`UserRecord.passwordHash` is now `string | null | undefined`, not `string`.",
@@ -788,7 +788,7 @@ var C = (e, t, n) => {
788
788
  " to match and make sure your read path maps a NULL column to `null`/",
789
789
  " `undefined` rather than to `''`-by-coercion."
790
790
  ].join("\n")
791
- }), ze = T({
791
+ }), Be = T({
792
792
  version: "0.8.0",
793
793
  id: "0.8.0/02_ssr-streams-and-loaderdata",
794
794
  title: "`ssr` pages stream; `useLoaderData<T>()` returns `LoaderData<T>`",
@@ -840,13 +840,13 @@ var C = (e, t, n) => {
840
840
  "docs. `defer()` requires `renderMode: 'ssr'` and `interactive: 'full'`;",
841
841
  "every other combination is a hard error naming the page."
842
842
  ].join("\n")
843
- }), Be = /renderMode\s*[=:]\s*['"](spa|client)['"]/, Ve = /(^|[/\\])pages[/\\].*[/\\]?layout\.tsx$/, He = T({
843
+ }), Ve = /renderMode\s*[=:]\s*['"](spa|client)['"]/, He = /(^|[/\\])pages[/\\].*[/\\]?layout\.tsx$/, Ue = T({
844
844
  version: "0.9.0",
845
845
  id: "0.9.0/01_ssr-layout-shell-for-spa",
846
846
  title: "A `renderMode:'spa'` page under a layout now server-renders that layout",
847
847
  kind: "manual",
848
848
  appliesTo: ({ project: e }) => {
849
- let t = e.getSourceFiles(), n = t.some((e) => Be.test(e.getFullText())), r = t.some((e) => Ve.test(e.getFilePath()));
849
+ let t = e.getSourceFiles(), n = t.some((e) => Ve.test(e.getFullText())), r = t.some((e) => He.test(e.getFilePath()));
850
850
  return n && r;
851
851
  },
852
852
  note: [
@@ -885,35 +885,35 @@ var C = (e, t, n) => {
885
885
  "Nothing changes for `static` / `ssr` / `isr` pages, or for a spa page that",
886
886
  "has no layout (still a pure client mount)."
887
887
  ].join("\n")
888
- }), k = "client", Ue = "spa", We = (e) => {
888
+ }), O = "client", We = "spa", Ge = (e) => {
889
889
  if (!e) return null;
890
890
  let t = x.isAsExpression(e) ? e.getExpression() : e;
891
891
  return x.isStringLiteral(t) ? t : null;
892
- }, A = (e) => {
892
+ }, Ke = (e) => {
893
893
  let t = [];
894
894
  for (let n of e.getDescendantsOfKind(S.VariableDeclaration)) {
895
895
  if (n.getName() !== "renderMode") continue;
896
- let e = We(n.getInitializer());
896
+ let e = Ge(n.getInitializer());
897
897
  e && t.push(e);
898
898
  }
899
899
  for (let n of e.getDescendantsOfKind(S.PropertyAssignment)) {
900
900
  if (n.getName() !== "renderMode") continue;
901
- let e = We(n.getInitializer());
901
+ let e = Ge(n.getInitializer());
902
902
  e && t.push(e);
903
903
  }
904
904
  return t;
905
- }, Ge = T({
905
+ }, qe = T({
906
906
  version: "0.10.0",
907
907
  id: "0.10.0/01_render-mode-client-to-spa",
908
908
  title: "renderMode is a closed set — `'client'` becomes `'spa'`",
909
909
  kind: "transform",
910
- appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => A(e).some((e) => e.getLiteralValue() === k)),
910
+ appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => Ke(e).some((e) => e.getLiteralValue() === O)),
911
911
  transform: ({ project: e, log: t }) => {
912
912
  let n = 0, r = /* @__PURE__ */ new Set();
913
- for (let t of e.getSourceFiles()) for (let e of A(t)) e.getLiteralValue() === k && (e.setLiteralValue(Ue), n++, r.add(t.getFilePath()));
914
- n > 0 && (t(`renderMode: rewrote ${n} \`'${k}'\` → \`'${Ue}'\` in ${r.size} file${r.size === 1 ? "" : "s"}`), t(" → 'spa' is the mode those pages already behaved as: no prerender, client-rendered"), t(" → new in 0.9.0: if such a page sits under a layout, that layout now server-renders (see the note above)"));
913
+ for (let t of e.getSourceFiles()) for (let e of Ke(t)) e.getLiteralValue() === O && (e.setLiteralValue(We), n++, r.add(t.getFilePath()));
914
+ n > 0 && (t(`renderMode: rewrote ${n} \`'${O}'\` → \`'${We}'\` in ${r.size} file${r.size === 1 ? "" : "s"}`), t(" → 'spa' is the mode those pages already behaved as: no prerender, client-rendered"), t(" → new in 0.9.0: if such a page sits under a layout, that layout now server-renders (see the note above)"));
915
915
  }
916
- }), Ke = T({
916
+ }), Je = T({
917
917
  version: "0.10.0",
918
918
  id: "0.10.0/02_router-state-carries-its-path",
919
919
  title: "`renderRouterStateScript` now requires the `path` it rendered",
@@ -950,7 +950,7 @@ var C = (e, t, n) => {
950
950
  "Trailing slashes, a trailing `/index.html`, and percent-encoding are normalised",
951
951
  "before the comparison, so the usual static-host shapes still hydrate."
952
952
  ].join("\n")
953
- }), qe = T({
953
+ }), Ye = T({
954
954
  version: "0.10.0",
955
955
  id: "0.10.0/03_workflow-caller-context-resolved",
956
956
  title: "workflow `buildContext` receives a RESOLVED caller context",
@@ -996,7 +996,7 @@ var C = (e, t, n) => {
996
996
  "it receives the resolved context too, so `callerContext?.subject ?? …` there",
997
997
  "becomes `callerContext.subject`."
998
998
  ].join("\n")
999
- }), Je = T({
999
+ }), Xe = T({
1000
1000
  version: "0.10.0",
1001
1001
  id: "0.10.0/04_seed-run-status-skipped",
1002
1002
  title: "seed run status gained `skipped`",
@@ -1037,7 +1037,7 @@ var C = (e, t, n) => {
1037
1037
  "`Schema.Literal`, a zod enum, a DB check constraint), widen it there too — an",
1038
1038
  "unlisted third state is a DECODE failure, not a rendering oddity."
1039
1039
  ].join("\n")
1040
- }), Ye = T({
1040
+ }), Ze = T({
1041
1041
  version: "0.10.0",
1042
1042
  id: "0.10.0/05_subscription-idle-state",
1043
1043
  title: "`useSubscription` gained an idle state for `skip`",
@@ -1089,7 +1089,7 @@ var C = (e, t, n) => {
1089
1089
  "time's data), hold it in your own state — the subscription no longer claims to",
1090
1090
  "have data it was told to stop fetching."
1091
1091
  ].join("\n")
1092
- }), Xe = T({
1092
+ }), Qe = T({
1093
1093
  version: "0.11.0",
1094
1094
  id: "0.11.0/01_step-options-type-params",
1095
1095
  title: "`StepOptions` takes the context type first",
@@ -1117,7 +1117,7 @@ var C = (e, t, n) => {
1117
1117
  "If the step reads nothing from earlier steps, `StepOptions<Record<never, never>,",
1118
1118
  "Result>` is the honest spelling."
1119
1119
  ].join("\n")
1120
- }), Ze = T({
1120
+ }), $e = T({
1121
1121
  version: "0.12.0",
1122
1122
  id: "0.12.0/01_outbound-http-ssrf-guard",
1123
1123
  title: "Outbound HttpClient blocks internal targets by default (add `http.allowHosts` if you call one)",
@@ -1157,7 +1157,7 @@ var C = (e, t, n) => {
1157
1157
  "private address (DNS rebinding) still passes. Pair with network-layer egress",
1158
1158
  "control if that is in your threat model."
1159
1159
  ].join("\n")
1160
- }), Qe = T({
1160
+ }), et = T({
1161
1161
  version: "0.12.0",
1162
1162
  id: "0.12.0/02_api-key-revoke-tenant-scope",
1163
1163
  title: "apiKeyService.revoke/rotate now require the caller's tenantId",
@@ -1186,7 +1186,7 @@ var C = (e, t, n) => {
1186
1186
  "The framework's own `/v1/api-keys/revoke` route already passes the caller's",
1187
1187
  "tenant — no change needed if you only use the shipped routes."
1188
1188
  ].join("\n")
1189
- }), $e = T({
1189
+ }), tt = T({
1190
1190
  version: "0.12.0",
1191
1191
  id: "0.12.0/03_api-key-on-behalf-of",
1192
1192
  title: "API keys: createdBy is provenance, onBehalfOf is ownership",
@@ -1220,7 +1220,7 @@ var C = (e, t, n) => {
1220
1220
  "specific one against what the body asks for. Grant them in your role map. A key",
1221
1221
  "can never carry scopes its issuer does not hold."
1222
1222
  ].join("\n")
1223
- }), et = T({
1223
+ }), nt = T({
1224
1224
  version: "0.12.0",
1225
1225
  id: "0.12.0/04_inspect-fail-closed",
1226
1226
  title: "The inspect surface requires VOLTRO_INSPECT_TOKEN (previously open when unset)",
@@ -1249,7 +1249,7 @@ var C = (e, t, n) => {
1249
1249
  "",
1250
1250
  "To turn the surface off entirely instead, set `VOLTRO_INSPECT=off`."
1251
1251
  ].join("\n")
1252
- }), tt = T({
1252
+ }), rt = T({
1253
1253
  version: "0.13.0",
1254
1254
  id: "0.13.0/01_bearer-gates-fail-closed",
1255
1255
  title: "checkBearer is fail-closed; scimPlugin refuses an empty token",
@@ -1286,7 +1286,7 @@ var C = (e, t, n) => {
1286
1286
  " • `@voltro/plugin-prometheus` already passes `{ openWhenUnset: true }` — its",
1287
1287
  " `PROMETHEUS_TOKEN` is documented as optional. Nothing to do there."
1288
1288
  ].join("\n")
1289
- }), nt = T({
1289
+ }), it = T({
1290
1290
  version: "0.13.0",
1291
1291
  id: "0.13.0/02_storage-grants-owner-only",
1292
1292
  title: "storage.share / revoke / listGrants require ownership",
@@ -1317,7 +1317,7 @@ var C = (e, t, n) => {
1317
1317
  " returning the grant or null. `storage.revoke` is handed a grant id, so it has",
1318
1318
  " to resolve the object before it can check the owner."
1319
1319
  ].join("\n")
1320
- }), rt = T({
1320
+ }), at = T({
1321
1321
  version: "0.13.0",
1322
1322
  id: "0.13.0/03_apply-plan-convergence-proof",
1323
1323
  title: "applyPlan requires a `replan` convergence proof",
@@ -1350,7 +1350,7 @@ var C = (e, t, n) => {
1350
1350
  " • `AppliedMigration` gained `appliedOps` (operations actually EXECUTED, from",
1351
1351
  " the per-op results). If you construct that value in a test fixture, add it."
1352
1352
  ].join("\n")
1353
- }), it = T({
1353
+ }), ot = T({
1354
1354
  version: "0.14.0",
1355
1355
  id: "0.14.0/01_resolve-scopes-store",
1356
1356
  title: "auth.resolveScopes receives the app DataStore",
@@ -1388,19 +1388,19 @@ var C = (e, t, n) => {
1388
1388
  " deliberately does not, because only you know how fast a role change must",
1389
1389
  " take effect."
1390
1390
  ].join("\n")
1391
- }), j = (e) => {
1391
+ }), k = (e) => {
1392
1392
  if (!x.isCallExpression(e)) return !1;
1393
1393
  let t = e.getExpression();
1394
1394
  return x.isPropertyAccessExpression(t) && t.getName() === "reactive" && e.getArguments().length === 0;
1395
- }, at = (e) => e.getDescendantsOfKind(S.CallExpression).some(j), ot = (e) => {
1395
+ }, st = (e) => e.getDescendantsOfKind(S.CallExpression).some(k), ct = (e) => {
1396
1396
  let t = 0, n = e.getDescendantsOfKind(S.CallExpression);
1397
1397
  for (let e of n) {
1398
- if (e.wasForgotten() || !j(e)) continue;
1398
+ if (e.wasForgotten() || !k(e)) continue;
1399
1399
  let n = e.getExpression();
1400
1400
  x.isPropertyAccessExpression(n) && (e.replaceWithText(n.getExpression().getText()), t++);
1401
1401
  }
1402
1402
  return t;
1403
- }, st = T({
1403
+ }, lt = T({
1404
1404
  version: "0.14.0",
1405
1405
  id: "0.14.0/02_reactive-by-default",
1406
1406
  title: "Reactivity is the default; .reactive() is removed",
@@ -1418,16 +1418,16 @@ var C = (e, t, n) => {
1418
1418
  "real saving: REPLICA IDENTITY FULL widens every UPDATE/DELETE in the WAL.",
1419
1419
  "`voltro dev` warns if you opt out a table a query still reads."
1420
1420
  ].join("\n"),
1421
- appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => at(e)),
1421
+ appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => st(e)),
1422
1422
  transform: ({ project: e, log: t }) => {
1423
1423
  let n = 0, r = 0;
1424
1424
  for (let t of e.getSourceFiles()) {
1425
- let e = ot(t);
1425
+ let e = ct(t);
1426
1426
  e !== 0 && (n += e, r++);
1427
1427
  }
1428
1428
  return n > 0 && t(`removed ${n} .reactive() call(s) across ${r} file(s) — reactivity is the default`), n > 0;
1429
1429
  }
1430
- }), ct = T({
1430
+ }), ut = T({
1431
1431
  version: "0.14.0",
1432
1432
  id: "0.14.0/07_dev-remote-file-migrations",
1433
1433
  title: "voltro dev refuses unattended file migrations against a remote database",
@@ -1470,19 +1470,19 @@ var C = (e, t, n) => {
1470
1470
  "Unchanged: `voltro db files`, `voltro db apply` and `voltro serve`. This gates the",
1471
1471
  "AUTOMATIC boot path only; an explicit command is already an explicit decision."
1472
1472
  ].join("\n")
1473
- }), lt = (e) => [...e.getImportDeclarations(), ...e.getExportDeclarations()], M = (e) => g(e).replace(/\.tsx?$/, ""), ut = (e, t, n) => {
1474
- let r = M(t), i = M(n);
1473
+ }), dt = (e) => [...e.getImportDeclarations(), ...e.getExportDeclarations()], A = (e) => g(e).replace(/\.tsx?$/, ""), ft = (e, t, n) => {
1474
+ let r = A(t), i = A(n);
1475
1475
  if (r === i) return;
1476
1476
  let a = /\.tsx?$/.exec(e)?.[0] ?? "", o = a === "" ? e : e.slice(0, -a.length);
1477
1477
  if (!o.endsWith(`/${r}`) && o !== r) return;
1478
1478
  let s = a === "" ? "" : /\.tsx$/.test(n) ? ".tsx" : ".ts";
1479
1479
  return `${o.slice(0, o.length - r.length)}${i}${s}`;
1480
- }, N = (e, t) => {
1480
+ }, j = (e, t) => {
1481
1481
  let n = e.getFilePath(), r = [];
1482
- for (let i of e.getProject().getSourceFiles()) for (let e of lt(i)) {
1482
+ for (let i of e.getProject().getSourceFiles()) for (let e of dt(i)) {
1483
1483
  let i = e.getModuleSpecifierValue();
1484
1484
  if (i === void 0 || i.startsWith(".") || e.getModuleSpecifierSourceFile()?.getFilePath() !== n) continue;
1485
- let a = ut(i, n, t);
1485
+ let a = ft(i, n, t);
1486
1486
  a !== void 0 && r.push({
1487
1487
  decl: e,
1488
1488
  spec: a
@@ -1491,19 +1491,19 @@ var C = (e, t, n) => {
1491
1491
  e.move(t);
1492
1492
  for (let e of r) e.decl.setModuleSpecifier(e.spec);
1493
1493
  return r.length;
1494
- }, dt = (e) => {
1494
+ }, pt = (e) => {
1495
1495
  let t = e.getProject().getCompilerOptions().paths;
1496
1496
  if (t === void 0) return;
1497
- let n = M(e.getFilePath()), r = e.getFilePath().slice(0, e.getFilePath().lastIndexOf("/"));
1497
+ let n = A(e.getFilePath()), r = e.getFilePath().slice(0, e.getFilePath().lastIndexOf("/"));
1498
1498
  for (let [e, i] of Object.entries(t)) if (!e.endsWith("*")) for (let t of i ?? []) {
1499
1499
  if (!/\.tsx?$/.test(t)) continue;
1500
- let i = M(t), a = t.slice(0, t.lastIndexOf("/"));
1500
+ let i = A(t), a = t.slice(0, t.lastIndexOf("/"));
1501
1501
  if (i === n && r.endsWith(a.replace(/^\.\//, ""))) return e;
1502
1502
  }
1503
- }, ft = /\.page\.tsx$/, pt = (e) => {
1503
+ }, mt = /\.page\.tsx$/, M = (e) => {
1504
1504
  let t = e.includes("\\src\\pages\\") ? "\\src\\pages\\" : "/src/pages/", n = e.indexOf(t);
1505
1505
  return n === -1 ? null : e.slice(0, n);
1506
- }, mt = (e) => e.endsWith(".tsx") && !i.has(e) && !d(e) && !/\.island\.tsx$/.test(e) && !ft.test(e), ht = T({
1506
+ }, ht = (e) => e.endsWith(".tsx") && !i.has(e) && !d(e) && !/\.island\.tsx$/.test(e) && !mt.test(e), gt = T({
1507
1507
  version: "0.14.0",
1508
1508
  id: "0.14.0/03_pages-suffix",
1509
1509
  title: "Pages are declared with a .page.tsx suffix",
@@ -1518,8 +1518,8 @@ var C = (e, t, n) => {
1518
1518
  transform: ({ project: e, log: t }) => {
1519
1519
  let n = /* @__PURE__ */ new Map(), r = e.getSourceFiles().filter((t) => {
1520
1520
  let r = t.getFilePath();
1521
- if (!mt(g(r))) return !1;
1522
- let i = pt(r);
1521
+ if (!ht(g(r))) return !1;
1522
+ let i = M(r);
1523
1523
  if (i === null) return !1;
1524
1524
  let a = n.get(i);
1525
1525
  return a === void 0 && (a = e.getSourceFile(v(i, "app.config.ts")) !== void 0 || e.getSourceFile(v(i, "app.config.tsx")) !== void 0, n.set(i, a)), a;
@@ -1537,12 +1537,12 @@ var C = (e, t, n) => {
1537
1537
  let n = t.getFilePath(), r = g(n), s = _(n), c = r.slice(0, -4);
1538
1538
  for (let t of [".test.tsx", ".spec.tsx"]) {
1539
1539
  let n = v(s, `${c}${t}`), r = e.getSourceFile(n);
1540
- r !== void 0 && (N(r, v(s, `${c}.page${t}`)), o += 1);
1540
+ r !== void 0 && (j(r, v(s, `${c}.page${t}`)), o += 1);
1541
1541
  }
1542
- N(t, v(s, `${c}.page.tsx`));
1542
+ j(t, v(s, `${c}.page.tsx`));
1543
1543
  let l = i.get(n);
1544
1544
  if (l !== void 0 && l.length > 0 && !l.every((e) => d(g(e)))) {
1545
- let e = pt(n) ?? _(n), t = [...new Set(l)].map((t) => ee(e, t));
1545
+ let e = M(n) ?? _(n), t = [...new Set(l)].map((t) => ee(e, t));
1546
1546
  a.push(`${ee(e, n)} ← imported by ${t.join(", ")}`);
1547
1547
  }
1548
1548
  }
@@ -1551,7 +1551,7 @@ var C = (e, t, n) => {
1551
1551
  for (let e of a) t(` ${e}`);
1552
1552
  }
1553
1553
  }
1554
- }), gt = [
1554
+ }), _t = [
1555
1555
  /\.page\.tsx$/,
1556
1556
  c,
1557
1557
  s,
@@ -1562,10 +1562,10 @@ var C = (e, t, n) => {
1562
1562
  a,
1563
1563
  r,
1564
1564
  t
1565
- ], _t = (e) => {
1565
+ ], vt = (e) => {
1566
1566
  let t = g(e);
1567
- return !/\.tsx?$/.test(t) || i.has(t) || n(t) || t === "index.ts" || t === "index.tsx" || t === "app.config.ts" ? !1 : !gt.some((e) => e.test(t));
1568
- }, vt = (e) => {
1567
+ return !/\.tsx?$/.test(t) || i.has(t) || n(t) || t === "index.ts" || t === "index.tsx" || t === "app.config.ts" ? !1 : !_t.some((e) => e.test(t));
1568
+ }, yt = (e) => {
1569
1569
  let t = [], n = [], r = [], i = [];
1570
1570
  for (let [a, o] of e.getExportedDeclarations()) {
1571
1571
  let e = o[0];
@@ -1592,10 +1592,10 @@ var C = (e, t, n) => {
1592
1592
  others: r,
1593
1593
  types: i
1594
1594
  };
1595
- }, yt = (e, t) => {
1595
+ }, bt = (e, t) => {
1596
1596
  let { components: n, hooks: r, others: i, types: a } = e;
1597
1597
  return n.length + r.length + i.length === 0 ? a.length > 0 ? ".types" : null : t && h(n) && r.length === 0 && i.length === 0 ? ".component.tsx" : n.length === 0 && r.length === 1 && i.length === 0 ? ".hook" : null;
1598
- }, bt = T({
1598
+ }, xt = T({
1599
1599
  version: "0.14.0",
1600
1600
  id: "0.14.0/04_file-taxonomy",
1601
1601
  title: "Web files declare their contract (*.component.tsx / *.hook.ts / *.types.ts)",
@@ -1608,19 +1608,19 @@ var C = (e, t, n) => {
1608
1608
  if (s.length > 0) for (let e of s) t(` exempt (not ours): ${e.dir} — ${e.source}`);
1609
1609
  for (let t of e.getSourceFiles()) {
1610
1610
  let e = t.getFilePath();
1611
- if (!_t(e) || p(e, s)) continue;
1612
- let o = dt(t);
1611
+ if (!vt(e) || p(e, s)) continue;
1612
+ let o = pt(t);
1613
1613
  if (o !== void 0) {
1614
1614
  a.push(`${g(e)} (tsconfig paths: "${o}")`);
1615
1615
  continue;
1616
1616
  }
1617
- let c = e.endsWith(".tsx"), l = vt(t), u = yt(l, c);
1617
+ let c = e.endsWith(".tsx"), l = yt(t), u = bt(l, c);
1618
1618
  if (u === null) {
1619
1619
  l.components.length > 0 && l.hooks.length > 0 && r.push(`${g(e)} (component ${l.components.join("/")} + hook ${l.hooks.join("/")})`);
1620
1620
  continue;
1621
1621
  }
1622
1622
  let d = g(e).replace(/\.tsx?$/, ""), f = u === ".component.tsx" ? ".component.tsx" : `${u}${c ? ".tsx" : ".ts"}`;
1623
- i += N(t, v(_(e), `${d}${f}`)), n.push(`${d}${f}`);
1623
+ i += j(t, v(_(e), `${d}${f}`)), n.push(`${d}${f}`);
1624
1624
  }
1625
1625
  if (n.length > 0 && (t(`declared ${n.length} file(s): component / hook / types`), i > 0 && t(` rewrote ${i} aliased import specifier(s) (@/… and friends)`)), a.length > 0) {
1626
1626
  t(""), t(`left alone — a tsconfig \`paths\` entry names ${a.length} of these files directly:`);
@@ -1633,7 +1633,7 @@ var C = (e, t, n) => {
1633
1633
  r.length > 20 && t(` (+${r.length - 20} more)`);
1634
1634
  }
1635
1635
  }
1636
- }), xt = T({
1636
+ }), St = T({
1637
1637
  version: "0.14.0",
1638
1638
  id: "0.14.0/05_typed-tracking",
1639
1639
  title: "Tracking catalogues are typed against the component props",
@@ -1670,7 +1670,7 @@ var C = (e, t, n) => {
1670
1670
  "Read each one before changing it: a cast that no longer compiles is sometimes",
1671
1671
  "a real type disagreement the old signature was hiding."
1672
1672
  ].join("\n")
1673
- }), St = T({
1673
+ }), Ct = T({
1674
1674
  version: "0.14.0",
1675
1675
  id: "0.14.0/06_voltro-test-skips-e2e",
1676
1676
  title: "`voltro test` leaves `e2e/` to `voltro e2e`",
@@ -1692,13 +1692,13 @@ var C = (e, t, n) => {
1692
1692
  " code it tests, or",
1693
1693
  " • pass your own `--exclude`, which overrides the framework default outright."
1694
1694
  ].join("\n")
1695
- }), Ct = (e) => {
1695
+ }), wt = (e) => {
1696
1696
  let t = e.replace(/\.component(\.ui)?(\.tsx?)$/, "$2");
1697
1697
  return t === e ? null : n(t) ? t : null;
1698
- }, wt = (e) => {
1698
+ }, Tt = (e) => {
1699
1699
  for (let [, t] of e.getExportedDeclarations()) if (t[0] !== void 0) return !1;
1700
1700
  return e.getExportDeclarations().length === 0 && e.getExportAssignments().length === 0;
1701
- }, Tt = T({
1701
+ }, Et = T({
1702
1702
  version: "0.15.0",
1703
1703
  id: "0.15.0/01_undo-mistaken-taxonomy-renames",
1704
1704
  title: "Undo the two file renames 0.14.0 got wrong (framework primitives, side-effect modules)",
@@ -1715,14 +1715,14 @@ var C = (e, t, n) => {
1715
1715
  transform: ({ project: e, log: t }) => {
1716
1716
  let n = [], r = [];
1717
1717
  for (let t of e.getSourceFiles()) {
1718
- let e = t.getFilePath(), i = g(e), a = Ct(i);
1718
+ let e = t.getFilePath(), i = g(e), a = wt(i);
1719
1719
  if (a !== null) {
1720
- N(t, v(_(e), a)), n.push(`${i} → ${a}`);
1720
+ j(t, v(_(e), a)), n.push(`${i} → ${a}`);
1721
1721
  continue;
1722
1722
  }
1723
- if (/\.types\.tsx?$/.test(i) && wt(t)) {
1723
+ if (/\.types\.tsx?$/.test(i) && Tt(t)) {
1724
1724
  let n = i.replace(/\.types(\.tsx?)$/, "$1");
1725
- N(t, v(_(e), n)), r.push(`${i} → ${n}`);
1725
+ j(t, v(_(e), n)), r.push(`${i} → ${n}`);
1726
1726
  }
1727
1727
  }
1728
1728
  if (n.length > 0) {
@@ -1736,16 +1736,16 @@ var C = (e, t, n) => {
1736
1736
  }
1737
1737
  n.length === 0 && r.length === 0 && t("nothing to undo — 0.14.0 renamed neither a framework file nor a side-effect module here.");
1738
1738
  }
1739
- }), Et = ["@voltro/client", "@voltro/web"], P = "@voltro/protocol", Dt = T({
1739
+ }), N = ["@voltro/client", "@voltro/web"], P = "@voltro/protocol", Dt = T({
1740
1740
  version: "0.15.0",
1741
1741
  id: "0.15.0/02_error-tag-in-protocol",
1742
1742
  title: "`errorTag` is imported from @voltro/protocol",
1743
1743
  kind: "transform",
1744
- appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => e.getImportDeclarations().some((e) => Et.includes(e.getModuleSpecifierValue()) && e.getNamedImports().some((e) => e.getName() === "errorTag"))),
1744
+ appliesTo: ({ project: e }) => e.getSourceFiles().some((e) => e.getImportDeclarations().some((e) => N.includes(e.getModuleSpecifierValue()) && e.getNamedImports().some((e) => e.getName() === "errorTag"))),
1745
1745
  transform: ({ project: e, log: t }) => {
1746
1746
  let n = 0;
1747
1747
  for (let t of e.getSourceFiles()) for (let e of t.getImportDeclarations()) {
1748
- if (!Et.includes(e.getModuleSpecifierValue())) continue;
1748
+ if (!N.includes(e.getModuleSpecifierValue())) continue;
1749
1749
  let r = e.getNamedImports().find((e) => e.getName() === "errorTag");
1750
1750
  if (r === void 0) continue;
1751
1751
  let i = r.getAliasNode()?.getText(), a = e.isTypeOnly() || r.isTypeOnly();
@@ -1802,7 +1802,7 @@ var C = (e, t, n) => {
1802
1802
  }
1803
1803
  }
1804
1804
  let l = [], u = 0;
1805
- for (let e of r) s.has(e.from) || (u += N(e.sf, e.to), e.isTest || l.push(o(e.to)));
1805
+ for (let e of r) s.has(e.from) || (u += j(e.sf, e.to), e.isTest || l.push(o(e.to)));
1806
1806
  if (l.length > 0 && (t(`moved ${l.length} route(s) into their own directory`), u > 0 && t(` rewrote ${u} aliased import specifier(s)`)), c.length > 0) {
1807
1807
  t(""), t(`LEFT ALONE — ${c.length} case(s) where two files claim one route:`);
1808
1808
  for (let e of c) t(` ${e}`);
@@ -6550,12 +6550,41 @@ var C = (e, t, n) => {
6550
6550
  }
6551
6551
  n > 0 && (t?.(`sourcemaps: moved out of \`web:\` in ${n} config file(s)`), t?.(" → it now covers the SSR, start and serve bundles too, not only the browser bundle")), r > 0 && t?.(`sourcemaps: ${r} case(s) left for you — listed above`), n === 0 && r === 0 && t?.("sourcemaps: no `web.sourcemaps` found — nothing to move");
6552
6552
  }
6553
- }), pa = (e) => /\bsentryPlugin\b|@voltro\/plugin-sentry/.test(e.getFullText()), ma = T({
6553
+ }), pa = (e) => /\bcostSource\b|\bCostBreakdown\b|\bestimateCostUsd\b|\b_voltro_ai_usage\b|\bMeteredUsage\b/.test(e.getFullText()), ma = T({
6554
+ version: "0.59.0",
6555
+ id: "0.59.0/02_costsource_gained_unpriced",
6556
+ title: "`costSource` gained `unpriced`, and AI usage is counted in a unit",
6557
+ kind: "manual",
6558
+ appliesTo: ({ project: e }) => e.getSourceFiles().some(pa),
6559
+ note: [
6560
+ "AI COST NOW HAS A THIRD SOURCE, AND USAGE HAS A UNIT.",
6561
+ "",
6562
+ "WHAT CHANGED. `CostBreakdown[\"costSource\"]` gained `\"unpriced\"`, and",
6563
+ "`_voltro_ai_usage` gained a `unit` column. Speech vendors meter characters",
6564
+ "or seconds, never tokens, so a ledger that only knew tokens could not hold a",
6565
+ "speech call at all. A non-token unit with no supplied price is written with",
6566
+ "the REAL count and a zero cost, rather than a fabricated one.",
6567
+ "",
6568
+ "WHAT TO DO:",
6569
+ "",
6570
+ "1) IF YOU NARROWED `costSource` — a union of two members in your own type,",
6571
+ " or an exhaustive switch — add `\"unpriced\"`. The compiler points at it.",
6572
+ " Decide what it means for you: it is a real usage row whose price we do",
6573
+ " not know, not a free call.",
6574
+ "",
6575
+ "2) IF YOU READ `estimateCostUsd` POSITIONALLY, read it by name instead.",
6576
+ "",
6577
+ "3) CHECK YOUR USAGE QUERIES — this one does not fail, it answers wrongly.",
6578
+ " `sum(input_tokens)` over `_voltro_ai_usage` now adds character counts to",
6579
+ " token counts and returns a number that looks fine. Group by `unit`, and",
6580
+ " never sum across it."
6581
+ ].join("\n")
6582
+ }), ha = (e) => /\bsentryPlugin\b|@voltro\/plugin-sentry/.test(e.getFullText()), ga = T({
6554
6583
  version: "0.60.0",
6555
6584
  id: "0.60.0/01_declared_failures_are_not_incidents",
6556
6585
  title: "Sentry no longer reports declared failures by default",
6557
6586
  kind: "manual",
6558
- appliesTo: ({ project: e }) => e.getSourceFiles().some(pa),
6587
+ appliesTo: ({ project: e }) => e.getSourceFiles().some(ha),
6559
6588
  note: [
6560
6589
  "A DECLARED FAILURE IS NO LONGER A SENTRY ISSUE BY DEFAULT.",
6561
6590
  "",
@@ -6598,7 +6627,55 @@ var C = (e, t, n) => {
6598
6627
  "The boot line now names the setting — `sentry active … captureFailures=false`",
6599
6628
  "— so the choice is visible where the decision takes effect."
6600
6629
  ].join("\n")
6601
- }), ha = (e) => /\bcostSource\b|\bCostBreakdown\b|\bestimateCostUsd\b|\b_voltro_ai_usage\b|\bMeteredUsage\b/.test(e.getFullText()), ga = [
6630
+ }), _a = (e) => /\bRpcError(?:Bus|Listener|Kind)?\b/.test(e.getFullText()), va = T({
6631
+ version: "0.61.0",
6632
+ id: "0.61.0/01_rpc_errors_have_kinds",
6633
+ title: "`RpcError` now carries an explicit failure kind",
6634
+ kind: "manual",
6635
+ appliesTo: ({ project: e }) => e.getSourceFiles().some(_a),
6636
+ note: [
6637
+ "`RpcError` NOW REQUIRES `kind`.",
6638
+ "",
6639
+ "Events received from `useOnRpcError` are already populated. Branch on",
6640
+ "`event.kind === 'transport'` for connection-level UX instead of reading",
6641
+ "`useConnectionStatus` in the same callback or matching an error message.",
6642
+ "",
6643
+ "If your own test/helper calls `RpcErrorBus.emit(...)`, add the origin you",
6644
+ "can actually prove:",
6645
+ "",
6646
+ " bus.emit({ source: 'mutation', tag, error, kind: 'handler' })",
6647
+ "",
6648
+ "The values are 'transport' | 'handler' | 'client' | 'unknown'. Use",
6649
+ "'unknown' when the operation combines several stages and no single origin",
6650
+ "is provable. Do not infer whether the server ran from a transport failure:",
6651
+ "the request may have completed and only its response was lost.",
6652
+ "",
6653
+ "`traceId` identifies the client call span. It joins to server logs only",
6654
+ "when the server accepted the request; its presence is not delivery proof."
6655
+ ].join("\n")
6656
+ }), ya = (e) => /@voltro\/plugin-sentry(?:\/web)?|\bsentry\s*:/.test(e.getFullText()), ba = T({
6657
+ version: "0.61.0",
6658
+ id: "0.61.0/02_sentry_rpc_spans_join_page",
6659
+ title: "Sentry rpc spans now join the active browser transaction",
6660
+ kind: "manual",
6661
+ appliesTo: ({ project: e }) => e.getSourceFiles().some(ya),
6662
+ note: [
6663
+ "Browser rpc markers are now children of the active page/navigation",
6664
+ "transaction, with a span link to the Effect/server trace. They no longer",
6665
+ "create one root Sentry transaction and envelope per rpc call.",
6666
+ "",
6667
+ "`tracesSampleRate` now controls the page transaction and its rpc children.",
6668
+ "`browserTracing: false` also defaults the rpc bridge to off while browser",
6669
+ "error capture stays active. Set `rpcSpans: true` only if your app creates",
6670
+ "its own active Sentry transactions, or set `rpcSpans: false` to keep page",
6671
+ "performance traces without rpc child spans.",
6672
+ "",
6673
+ "`sentryTraceHeader` was removed. Delete direct imports and use the normal",
6674
+ "`initSentryBrowser` bridge. Custom instrumentation should create a",
6675
+ "parent-only child of Sentry's active transaction and attach the Effect",
6676
+ "trace context as a span link."
6677
+ ].join("\n")
6678
+ }), xa = (e) => /\b(?:AdmissionDrainDeps|makeFlowControlGate)\b/.test(e.getFullText()), J = [
6602
6679
  he,
6603
6680
  ge,
6604
6681
  ve,
@@ -6608,15 +6685,13 @@ var C = (e, t, n) => {
6608
6685
  Te,
6609
6686
  Ee,
6610
6687
  De,
6611
- Ae,
6612
6688
  je,
6613
- Pe,
6689
+ Me,
6614
6690
  Fe,
6615
- Re,
6691
+ Ie,
6616
6692
  ze,
6617
- He,
6618
- Ge,
6619
- Ke,
6693
+ Be,
6694
+ Ue,
6620
6695
  qe,
6621
6696
  Je,
6622
6697
  Ye,
@@ -6628,14 +6703,16 @@ var C = (e, t, n) => {
6628
6703
  tt,
6629
6704
  nt,
6630
6705
  rt,
6631
- ct,
6632
6706
  it,
6633
- st,
6634
- ht,
6635
- bt,
6707
+ at,
6708
+ ut,
6709
+ ot,
6710
+ lt,
6711
+ gt,
6636
6712
  xt,
6637
6713
  St,
6638
- Tt,
6714
+ Ct,
6715
+ Et,
6639
6716
  Dt,
6640
6717
  Mt,
6641
6718
  Pt,
@@ -6742,38 +6819,35 @@ var C = (e, t, n) => {
6742
6819
  oa,
6743
6820
  ca,
6744
6821
  fa,
6822
+ ga,
6745
6823
  ma,
6824
+ va,
6825
+ ba,
6746
6826
  T({
6747
- version: "0.59.0",
6748
- id: "0.59.0/02_costsource_gained_unpriced",
6749
- title: "`costSource` gained `unpriced`, and AI usage is counted in a unit",
6827
+ version: "0.62.0",
6828
+ id: "0.62.0/01_finish_timeout_uses_durable_cancellation",
6829
+ title: "Finish timeouts use durable, once-only cancellation",
6750
6830
  kind: "manual",
6751
- appliesTo: ({ project: e }) => e.getSourceFiles().some(ha),
6831
+ appliesTo: ({ project: e }) => e.getSourceFiles().some(xa),
6752
6832
  note: [
6753
- "AI COST NOW HAS A THIRD SOURCE, AND USAGE HAS A UNIT.",
6833
+ "`AdmissionDrainDeps.cancelRun` NOW RECEIVES one object:",
6754
6834
  "",
6755
- "WHAT CHANGED. `CostBreakdown[\"costSource\"]` gained `\"unpriced\"`, and",
6756
- "`_voltro_ai_usage` gained a `unit` column. Speech vendors meter characters",
6757
- "or seconds, never tokens, so a ledger that only knew tokens could not hold a",
6758
- "speech call at all. A non-token unit with no supplied price is written with",
6759
- "the REAL count and a zero cost, rather than a fabricated one.",
6835
+ " { workflowName, runId, executionId, reason, detail? }",
6760
6836
  "",
6761
- "WHAT TO DO:",
6837
+ "Return `true` only when this call changed the durable run from running to",
6838
+ "terminal; return `false` when it was already terminal or absent. The true",
6839
+ "result is the once-only claim that owns the `onFailure` signal.",
6762
6840
  "",
6763
- "1) IF YOU NARROWED `costSource` — a union of two members in your own type,",
6764
- " or an exhaustive switch — add `\"unpriced\"`. The compiler points at it.",
6765
- " Decide what it means for you: it is a real usage row whose price we do",
6766
- " not know, not a free call.",
6841
+ "`listRunningRuns(workflowName)` rows now include `runId`, `workflowName`,",
6842
+ "`executionId`, `payload`, and epoch-ms `startedAt`. Filter by the exact",
6843
+ "workflow and `running` status before returning them.",
6767
6844
  "",
6768
- "2) IF YOU READ `estimateCostUsd` POSITIONALLY, read it by name instead.",
6769
- "",
6770
- "3) CHECK YOUR USAGE QUERIES this one does not fail, it answers wrongly.",
6771
- " `sum(input_tokens)` over `_voltro_ai_usage` now adds character counts to",
6772
- " token counts and returns a number that looks fine. Group by `unit`, and",
6773
- " never sum across it."
6845
+ "`onAbandoned` may receive `runId` and `executionId`; forward them to the",
6846
+ "failure report. They are populated for `timeouts.finish` and remain absent",
6847
+ "for failures that happen before a run exists."
6774
6848
  ].join("\n")
6775
6849
  })
6776
- ], J = /* @__PURE__ */ new Set([
6850
+ ], Y = /* @__PURE__ */ new Set([
6777
6851
  "node_modules",
6778
6852
  ".git",
6779
6853
  "dist",
@@ -6785,42 +6859,42 @@ var C = (e, t, n) => {
6785
6859
  ".turbo",
6786
6860
  ".cache",
6787
6861
  ".output"
6788
- ]), _a = () => [...[...J].map((e) => `**/${e}/**`), "**/.voltro-*/**"], Y = /(?:from|import)\s*\(?\s*['"]([^'"]+)['"]|require\s*\(\s*['"]([^'"]+)['"]\s*\)/g, X = /\.(?:tsx?|jsx?|mjs|cjs)$/, va = (e) => g(e).replace(X, ""), ya = (e) => {
6862
+ ]), Sa = () => [...[...Y].map((e) => `**/${e}/**`), "**/.voltro-*/**"], X = /(?:from|import)\s*\(?\s*['"]([^'"]+)['"]|require\s*\(\s*['"]([^'"]+)['"]\s*\)/g, Ca = /\.(?:tsx?|jsx?|mjs|cjs)$/, wa = (e) => g(e).replace(Ca, ""), Ta = (e) => {
6789
6863
  let t = e.split("/").filter((e) => e.length > 0).pop();
6790
6864
  if (t === void 0 || t === "." || t === "..") return;
6791
- let n = t.replace(X, "");
6865
+ let n = t.replace(Ca, "");
6792
6866
  return n.length > 0 ? n : void 0;
6793
- }, ba = (e) => {
6867
+ }, Ea = (e) => {
6794
6868
  let t = /* @__PURE__ */ new Map();
6795
6869
  for (let n of e) {
6796
6870
  let e;
6797
6871
  try {
6798
- e = te(n, "utf8");
6872
+ e = b(n, "utf8");
6799
6873
  } catch {
6800
6874
  continue;
6801
6875
  }
6802
- Y.lastIndex = 0;
6803
- for (let r = Y.exec(e); r !== null; r = Y.exec(e)) {
6804
- let e = ya(r[1] ?? r[2] ?? "");
6876
+ X.lastIndex = 0;
6877
+ for (let r = X.exec(e); r !== null; r = X.exec(e)) {
6878
+ let e = Ta(r[1] ?? r[2] ?? "");
6805
6879
  if (e === void 0) continue;
6806
6880
  let i = t.get(e);
6807
6881
  i === void 0 ? t.set(e, /* @__PURE__ */ new Set([n])) : i.add(n);
6808
6882
  }
6809
6883
  }
6810
6884
  return t;
6811
- }, xa = (e, t) => {
6885
+ }, Da = (e, t) => {
6812
6886
  let n = new Set(e);
6813
- for (let r of e) for (let e of [va(r), g(_(r))]) {
6887
+ for (let r of e) for (let e of [wa(r), g(_(r))]) {
6814
6888
  let r = t.get(e);
6815
6889
  if (r !== void 0) for (let e of r) n.add(e);
6816
6890
  }
6817
6891
  return n;
6818
- }, Sa = /* @__PURE__ */ ".ts,.tsx,.mts,.cts,.js,.jsx,.mjs,.cjs,.yml,.yaml,.toml,.json,.jsonc,.ini,.cfg,.conf,.sh,.bash,.zsh,.fish,.ps1,.bat,.cmd,.md,.mdx,.rst,.txt,.adoc,Makefile,makefile,GNUmakefile,Justfile,justfile,Dockerfile,Containerfile,Procfile,Jenkinsfile,Rakefile,Taskfile".split(","), Ca = 2097152, wa = 4e4, Ta = (e) => {
6892
+ }, Oa = /* @__PURE__ */ ".ts,.tsx,.mts,.cts,.js,.jsx,.mjs,.cjs,.yml,.yaml,.toml,.json,.jsonc,.ini,.cfg,.conf,.sh,.bash,.zsh,.fish,.ps1,.bat,.cmd,.md,.mdx,.rst,.txt,.adoc,Makefile,makefile,GNUmakefile,Justfile,justfile,Dockerfile,Containerfile,Procfile,Jenkinsfile,Rakefile,Taskfile".split(","), ka = 2097152, Aa = 4e4, ja = (e) => {
6819
6893
  let t = e.slice(e.lastIndexOf("/") + 1);
6820
- return Sa.some((e) => e.startsWith(".") ? t.endsWith(e) : t === e);
6821
- }, Ea = (e) => {
6894
+ return Oa.some((e) => e.startsWith(".") ? t.endsWith(e) : t === e);
6895
+ }, Ma = (e) => {
6822
6896
  try {
6823
- let t = b("git", [
6897
+ let t = ne("git", [
6824
6898
  "ls-files",
6825
6899
  "--cached",
6826
6900
  "--others",
@@ -6839,23 +6913,23 @@ var C = (e, t, n) => {
6839
6913
  } catch {
6840
6914
  return;
6841
6915
  }
6842
- }, Z = (e, t = Ea) => {
6916
+ }, Z = (e, t = Ma) => {
6843
6917
  let n = t(e);
6844
- if (n === void 0) return Da;
6918
+ if (n === void 0) return Na;
6845
6919
  let r = /* @__PURE__ */ new Map(), i = [];
6846
6920
  for (let t of n) {
6847
- if (t.split("/").some((e) => J.has(e)) || !Ta(t)) continue;
6848
- if (r.size >= wa) {
6921
+ if (t.split("/").some((e) => Y.has(e)) || !ja(t)) continue;
6922
+ if (r.size >= Aa) {
6849
6923
  i.push(t);
6850
6924
  continue;
6851
6925
  }
6852
6926
  let n = v(e, t);
6853
6927
  try {
6854
- if (ne(n).size > Ca) {
6928
+ if (te(n).size > ka) {
6855
6929
  i.push(t);
6856
6930
  continue;
6857
6931
  }
6858
- let e = te(n, "utf8");
6932
+ let e = b(n, "utf8");
6859
6933
  if (e.includes("\0")) {
6860
6934
  i.push(t);
6861
6935
  continue;
@@ -6875,47 +6949,47 @@ var C = (e, t, n) => {
6875
6949
  scanned: r.size,
6876
6950
  skipped: i
6877
6951
  };
6878
- }, Da = {
6952
+ }, Na = {
6879
6953
  find: () => [],
6880
6954
  scanned: 0,
6881
6955
  skipped: []
6882
- }, Oa = [
6956
+ }, Pa = [
6883
6957
  "**/*.ts",
6884
6958
  "**/*.tsx",
6885
6959
  "!**/node_modules/**",
6886
6960
  "!**/dist/**",
6887
6961
  "!**/.framework/**",
6888
6962
  "!**/*.d.ts"
6889
- ], Q = (e, t, n = ja) => {
6963
+ ], Q = (e, t, n = La) => {
6890
6964
  let r = /* @__PURE__ */ new Set();
6891
- for (let e of t) for (let t of e.scope ?? Oa) r.add(t);
6965
+ for (let e of t) for (let t of e.scope ?? Pa) r.add(t);
6892
6966
  let i = n(e);
6893
6967
  if (i !== void 0) {
6894
- let t = [...r].filter((e) => !e.startsWith("!")).map((e) => Aa(e)), n = [...r].filter((e) => e.startsWith("!")).map((e) => Aa(e.slice(1))), a = [...J], o = [];
6968
+ let t = [...r].filter((e) => !e.startsWith("!")).map((e) => Ia(e)), n = [...r].filter((e) => e.startsWith("!")).map((e) => Ia(e.slice(1))), a = [...Y], o = [];
6895
6969
  for (let r of i) {
6896
6970
  if (a.some((e) => r === e || r.startsWith(`${e}/`) || r.includes(`/${e}/`)) || !t.some((e) => e(r)) || n.some((e) => e(r))) continue;
6897
6971
  let i = v(e, r);
6898
6972
  y(i) && o.push(i);
6899
6973
  }
6900
- return ka(o.length, e), o;
6974
+ return Fa(o.length, e), o;
6901
6975
  }
6902
6976
  let a = ae([...r], {
6903
6977
  cwd: e,
6904
6978
  absolute: !0,
6905
6979
  expandDirectories: !1,
6906
6980
  followSymbolicLinks: !1,
6907
- ignore: [..._a()]
6981
+ ignore: [...Sa()]
6908
6982
  });
6909
- return ka(a.length, e), a;
6910
- }, ka = (e, t) => {
6911
- let n = Ma();
6983
+ return Fa(a.length, e), a;
6984
+ }, Fa = (e, t) => {
6985
+ let n = Ra();
6912
6986
  if (!(e <= n)) throw Error(`voltro update: the codemod scan matched ${e} files under ${t}, past the ${n} ceiling.\n Every matched file is parsed into one ts-morph project, so the heap needed grows with\n this number — past the ceiling it runs out of memory, and V8 aborts without naming a\n limit, which is why this stops here instead. Three ways out, in order:\n • put non-source directories in .gitignore (inside a git repo the scan then never\n sees them at all — a build cache, a data dump, a virtualenv),\n • run \`voltro update\` from the app directory rather than the workspace root, or\n • take one codemod at a time: \`voltro update --dry-run\` lists the ids, then\n \`voltro update --codemods-only --only <id>\` runs a single one.\n If every one of those files really is source this pass must rewrite, raise the ceiling\n with VOLTRO_CODEMOD_MAX_FILES and give node room: NODE_OPTIONS=--max-old-space-size=8192.`);
6913
- }, Aa = (e) => {
6987
+ }, Ia = (e) => {
6914
6988
  let t = e.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*\//g, "\0").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\u0000/g, "(?:.*/)?").replace(/\\\{([^}]*)\\\}/g, (e, t) => `(?:${t.split(",").join("|")})`);
6915
6989
  return (e) => RegExp(`^${t}$`).test(e);
6916
- }, ja = (e) => {
6990
+ }, La = (e) => {
6917
6991
  try {
6918
- let t = b("git", [
6992
+ let t = ne("git", [
6919
6993
  "ls-files",
6920
6994
  "--cached",
6921
6995
  "--others",
@@ -6934,7 +7008,7 @@ var C = (e, t, n) => {
6934
7008
  } catch {
6935
7009
  return;
6936
7010
  }
6937
- }, Ma = () => {
7011
+ }, Ra = () => {
6938
7012
  let e = Number(process.env.VOLTRO_CODEMOD_MAX_FILES);
6939
7013
  return Number.isInteger(e) && e > 0 ? e : 2e4;
6940
7014
  }, $ = (e, t) => {
@@ -6944,7 +7018,7 @@ var C = (e, t, n) => {
6944
7018
  if (t !== 0) return t;
6945
7019
  }
6946
7020
  return 0;
6947
- }, Na = (e, t, n = ga) => n.filter((n) => $(e, n.version) < 0 && $(n.version, t) <= 0).slice().sort(me), Pa = (e, t, n = () => {}, r = Da) => {
7021
+ }, za = (e, t, n = J) => n.filter((n) => $(e, n.version) < 0 && $(n.version, t) <= 0).slice().sort(me), Ba = (e, t, n = () => {}, r = Na) => {
6948
7022
  let i = [], a = [], o = [];
6949
7023
  for (let s of t) {
6950
7024
  let t = !s.appliesTo || s.appliesTo({
@@ -6995,8 +7069,8 @@ var C = (e, t, n) => {
6995
7069
  manual: a,
6996
7070
  skipped: o
6997
7071
  };
6998
- }, Fa = async (e) => {
6999
- let t = e.log ?? (() => {}), n = Na(e.from, e.to, e.codemods ?? ga), r = e.only === void 0 || e.only.length === 0 ? n : (() => {
7072
+ }, Va = async (e) => {
7073
+ let t = e.log ?? (() => {}), n = za(e.from, e.to, e.codemods ?? J), r = e.only === void 0 || e.only.length === 0 ? n : (() => {
7000
7074
  let t = n.filter((t) => e.only.includes(t.id)), r = e.only.filter((e) => !n.some((t) => t.id === e));
7001
7075
  if (r.length > 0) throw Error(`voltro update --only: no codemod in ${e.from} → ${e.to} has id ${r.map((e) => `"${e}"`).join(", ")}.\n Available for this jump:\n${n.map((e) => ` ${e.id}`).join("\n")}`);
7002
7076
  return t;
@@ -7023,15 +7097,15 @@ var C = (e, t, n) => {
7023
7097
  get skipped() {
7024
7098
  return (p ??= Z(e.root)).skipped;
7025
7099
  }
7026
- }, h = c.length > 0 ? ba(Q(e.root, [{
7100
+ }, h = c.length > 0 ? Ea(Q(e.root, [{
7027
7101
  ...c[0],
7028
- scope: Oa
7102
+ scope: Pa
7029
7103
  }])) : void 0;
7030
7104
  for (let n of r) {
7031
7105
  if (c.includes(n)) {
7032
7106
  let r = a(), i = Q(e.root, [n]);
7033
- for (let e of xa(i, h)) y(e) && r.addSourceFileAtPath(e);
7034
- let s = Pa(r, [n], t, m);
7107
+ for (let e of Da(i, h)) y(e) && r.addSourceFileAtPath(e);
7108
+ let s = Ba(r, [n], t, m);
7035
7109
  e.dryRun || await r.save(), l.push(...s.applied), u.push(...s.manual), d.push(...s.skipped), o = void 0;
7036
7110
  continue;
7037
7111
  }
@@ -7040,7 +7114,7 @@ var C = (e, t, n) => {
7040
7114
  for (let t of s) y(t) && e.addSourceFileAtPath(t);
7041
7115
  return e;
7042
7116
  })();
7043
- let r = Pa(o, [n], t, m);
7117
+ let r = Ba(o, [n], t, m);
7044
7118
  e.dryRun || await o.save(), l.push(...r.applied), u.push(...r.manual), d.push(...r.skipped);
7045
7119
  }
7046
7120
  return {
@@ -7050,4 +7124,4 @@ var C = (e, t, n) => {
7050
7124
  };
7051
7125
  };
7052
7126
  //#endregion
7053
- export { T as i, Fa as n, J as r, $ as t };
7127
+ export { T as i, Va as n, Y as r, $ as t };