@ontrails/warden 1.0.0-beta.39 → 1.0.0-beta.41

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 (134) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/README.md +5 -5
  3. package/package.json +10 -12
  4. package/src/cli.ts +49 -44
  5. package/src/command.ts +2 -2
  6. package/src/drift.ts +4 -3
  7. package/src/index.ts +3 -2
  8. package/src/project-context.ts +3 -3
  9. package/src/resolve.ts +2 -2
  10. package/src/rules/captured-kernel.ts +375 -0
  11. package/src/rules/circular-refs.ts +12 -16
  12. package/src/rules/cli-command-route-coherence.ts +1 -1
  13. package/src/rules/composes-declarations.ts +15 -13
  14. package/src/rules/context-no-surface-types.ts +4 -3
  15. package/src/rules/dead-internal-trail.ts +3 -3
  16. package/src/rules/dead-public-trail.ts +3 -3
  17. package/src/rules/draft-file-marking.ts +4 -9
  18. package/src/rules/draft-visible-debt.ts +3 -8
  19. package/src/rules/duplicate-public-contract.ts +50 -5
  20. package/src/rules/{contour-exists.ts → entity-exists.ts} +67 -64
  21. package/src/rules/entity-ids.ts +15 -0
  22. package/src/rules/error-mapping-completeness.ts +2 -2
  23. package/src/rules/example-valid.ts +84 -84
  24. package/src/rules/fires-declarations.ts +27 -22
  25. package/src/rules/governed-symbol-residue.ts +339 -32
  26. package/src/rules/implementation-returns-result.ts +8 -8
  27. package/src/rules/incomplete-accessor-for-standard-op.ts +15 -15
  28. package/src/rules/incomplete-crud.ts +42 -40
  29. package/src/rules/index.ts +9 -6
  30. package/src/rules/intent-propagation.ts +3 -5
  31. package/src/rules/layer-field-name-drift.ts +2 -2
  32. package/src/rules/library-projection-coherence.ts +2 -2
  33. package/src/rules/metadata.ts +37 -15
  34. package/src/rules/missing-reconcile.ts +3 -4
  35. package/src/rules/missing-visibility.ts +2 -1
  36. package/src/rules/no-destructured-compose.ts +14 -12
  37. package/src/rules/no-direct-implementation-call.ts +12 -7
  38. package/src/rules/no-legacy-cli-alias-export.ts +2 -2
  39. package/src/rules/no-native-error-result.ts +2 -2
  40. package/src/rules/no-redundant-result-error-wrap.ts +10 -10
  41. package/src/rules/no-sync-result-assumption.ts +84 -78
  42. package/src/rules/no-throw-in-detour-recover.ts +2 -2
  43. package/src/rules/no-throw-in-implementation.ts +13 -7
  44. package/src/rules/no-top-level-surface.ts +2 -2
  45. package/src/rules/on-references-exist.ts +3 -3
  46. package/src/rules/orphaned-signal.ts +4 -5
  47. package/src/rules/owner-projection-parity.ts +2 -2
  48. package/src/rules/public-export-example-coverage.ts +10 -4
  49. package/src/rules/public-internal-deep-imports.ts +2 -3
  50. package/src/rules/read-intent-fires.ts +4 -3
  51. package/src/rules/reference-exists.ts +20 -21
  52. package/src/rules/registry-names.ts +6 -4
  53. package/src/rules/resolved-import-boundary.ts +1 -1
  54. package/src/rules/resource-declarations.ts +21 -17
  55. package/src/rules/resource-exists.ts +4 -2
  56. package/src/rules/resource-id-grammar.ts +2 -2
  57. package/src/rules/resource-mock-coverage.ts +2 -2
  58. package/src/rules/retired-vocabulary.ts +242 -5
  59. package/src/rules/source/composition.ts +165 -0
  60. package/src/rules/source/drafts.ts +164 -0
  61. package/src/rules/source/entities.ts +618 -0
  62. package/src/rules/source/pragmas.ts +45 -0
  63. package/src/rules/source/resources.ts +64 -0
  64. package/src/rules/source/signals.ts +397 -0
  65. package/src/rules/source/stores.ts +310 -0
  66. package/src/rules/static-resource-accessor-preference.ts +15 -11
  67. package/src/rules/surface-overlay-coherence.ts +1 -1
  68. package/src/rules/surface-trailhead-coherence.ts +2 -2
  69. package/src/rules/trail-fork-coaching.ts +27 -18
  70. package/src/rules/trail-versioning-source.ts +16 -12
  71. package/src/rules/trail-versioning-topo.ts +2 -2
  72. package/src/rules/trailhead-override-divergence.ts +2 -2
  73. package/src/rules/types.ts +7 -7
  74. package/src/rules/unmaterialized-activation-source.ts +1 -0
  75. package/src/rules/unreachable-detour-shadowing.ts +2 -2
  76. package/src/rules/valid-describe-refs.ts +2 -2
  77. package/src/rules/warden-export-symmetry.ts +3 -3
  78. package/src/rules/warden-rules-use-ast.ts +12 -17
  79. package/src/trails/activation-orphan.trail.ts +5 -5
  80. package/src/trails/captured-kernel.trail.ts +108 -0
  81. package/src/trails/circular-refs.trail.ts +6 -6
  82. package/src/trails/cli-command-route-coherence.trail.ts +2 -2
  83. package/src/trails/composes-declarations.trail.ts +1 -1
  84. package/src/trails/context-no-surface-types.trail.ts +1 -1
  85. package/src/trails/dead-internal-trail.trail.ts +2 -2
  86. package/src/trails/dead-public-trail.trail.ts +1 -1
  87. package/src/trails/deprecation-without-guidance.trail.ts +1 -1
  88. package/src/trails/duplicate-public-contract.trail.ts +3 -3
  89. package/src/trails/entity-exists.trail.ts +21 -0
  90. package/src/trails/example-valid.trail.ts +3 -3
  91. package/src/trails/fires-declarations.trail.ts +1 -1
  92. package/src/trails/{fork-without-preserved-blaze.trail.ts → fork-without-preserved-implementation.trail.ts} +4 -4
  93. package/src/trails/implementation-returns-result.trail.ts +1 -1
  94. package/src/trails/incomplete-accessor-for-standard-op.trail.ts +4 -4
  95. package/src/trails/index.ts +3 -2
  96. package/src/trails/intent-propagation.trail.ts +2 -2
  97. package/src/trails/library-projection-coherence.trail.ts +2 -2
  98. package/src/trails/marker-schema-unsupported.trail.ts +1 -1
  99. package/src/trails/missing-visibility.trail.ts +1 -1
  100. package/src/trails/no-destructured-compose.trail.ts +5 -5
  101. package/src/trails/no-direct-implementation-call.trail.ts +1 -1
  102. package/src/trails/no-redundant-result-error-wrap.trail.ts +2 -2
  103. package/src/trails/no-sync-result-assumption.trail.ts +2 -2
  104. package/src/trails/no-throw-in-detour-recover.trail.ts +1 -1
  105. package/src/trails/no-throw-in-implementation.trail.ts +1 -1
  106. package/src/trails/on-references-exist.trail.ts +1 -1
  107. package/src/trails/pending-force.trail.ts +1 -1
  108. package/src/trails/permit-governance.trail.ts +2 -2
  109. package/src/trails/prefer-schema-inference.trail.ts +1 -1
  110. package/src/trails/public-output-schema.trail.ts +2 -2
  111. package/src/trails/public-union-output-discriminants.trail.ts +1 -1
  112. package/src/trails/read-intent-fires.trail.ts +1 -1
  113. package/src/trails/reference-exists.trail.ts +5 -5
  114. package/src/trails/resource-declarations.trail.ts +1 -1
  115. package/src/trails/resource-exists.trail.ts +1 -1
  116. package/src/trails/run.ts +4 -6
  117. package/src/trails/scheduled-destroy-intent.trail.ts +2 -2
  118. package/src/trails/schema.ts +9 -9
  119. package/src/trails/signal-graph-coaching.trail.ts +2 -2
  120. package/src/trails/static-resource-accessor-preference.trail.ts +1 -1
  121. package/src/trails/surface-overlay-coherence.trail.ts +1 -1
  122. package/src/trails/trail-fork-coaching.trail.ts +1 -1
  123. package/src/trails/unmaterialized-activation-source.trail.ts +5 -5
  124. package/src/trails/valid-detour-contract.trail.ts +1 -1
  125. package/src/trails/version-gap.trail.ts +1 -1
  126. package/src/trails/version-pinned-compose.trail.ts +1 -1
  127. package/src/trails/version-without-examples.trail.ts +1 -1
  128. package/src/trails/warden-rules-use-ast.trail.ts +2 -2
  129. package/src/trails/webhook-route-collision.trail.ts +2 -2
  130. package/src/trails/wrap-rule.ts +17 -17
  131. package/src/ast.ts +0 -137
  132. package/src/rules/ast.ts +0 -4143
  133. package/src/rules/contour-ids.ts +0 -15
  134. package/src/trails/contour-exists.trail.ts +0 -21
@@ -1,10 +1,10 @@
1
+ import { getMemberExpression } from './source/stores.js';
1
2
  import {
2
3
  collectScopeFrameBindings,
3
- findBlazeBodies,
4
+ findImplementationBodies,
4
5
  findTrailDefinitions,
5
- getMemberExpression,
6
- getNodeArguments,
7
6
  getNodeArgument,
7
+ getNodeArguments,
8
8
  getNodeBodyNode,
9
9
  getNodeCallee,
10
10
  getNodeId,
@@ -19,7 +19,8 @@ import {
19
19
  parse,
20
20
  walkWithParents,
21
21
  walkWithScopes,
22
- } from './ast.js';
22
+ } from '@ontrails/source';
23
+ import type { AstNode, AstParentContext } from '@ontrails/source';
23
24
  import {
24
25
  collectAllResultHelperNames,
25
26
  collectNamespaceHelperImports,
@@ -30,7 +31,6 @@ import {
30
31
  trackScopedResultHelperDeclaration,
31
32
  } from './implementation-returns-result.js';
32
33
  import { isTestFile } from './scan.js';
33
- import type { AstNode, AstParentContext } from './ast.js';
34
34
  import type {
35
35
  MutableScopedHelperMap,
36
36
  NamespaceHelperMap,
@@ -344,12 +344,12 @@ export const noRedundantResultErrorWrap: WardenRule = {
344
344
  const helperNames = collectAllResultHelperNames(ast, sourceCode, filePath);
345
345
  const namespaceHelpers = collectNamespaceHelperImports(ast, filePath);
346
346
  const resultTypeNames = collectResultTypeNames(ast);
347
- const blazeStarts = new Set<number>();
347
+ const implementationStarts = new Set<number>();
348
348
  for (const def of findTrailDefinitions(ast)) {
349
- for (const blaze of findBlazeBodies(def.config)) {
350
- blazeStarts.add(blaze.start);
349
+ for (const implementation of findImplementationBodies(def.config)) {
350
+ implementationStarts.add(implementation.start);
351
351
  checkFunctionBody(
352
- blaze,
352
+ implementation,
353
353
  `Trail "${def.id}"`,
354
354
  filePath,
355
355
  sourceCode,
@@ -361,7 +361,7 @@ export const noRedundantResultErrorWrap: WardenRule = {
361
361
  }
362
362
  }
363
363
  walkWithParents(ast, (node, context) => {
364
- if (!isFunctionLike(node) || blazeStarts.has(node.start)) {
364
+ if (!isFunctionLike(node) || implementationStarts.has(node.start)) {
365
365
  return;
366
366
  }
367
367
  checkFunctionBody(
@@ -1,8 +1,8 @@
1
1
  import { resultAccessorNames } from '@ontrails/core';
2
2
 
3
3
  import {
4
- getNodeArgument,
5
4
  getNodeAlternate,
5
+ getNodeArgument,
6
6
  getNodeBodyNode,
7
7
  getNodeBodyStatements,
8
8
  getNodeConsequent,
@@ -24,11 +24,11 @@ import {
24
24
  getNodeRight,
25
25
  getNodeValueNode,
26
26
  identifierName,
27
- isBlazeCall,
27
+ isImplementationCall,
28
28
  offsetToLine,
29
29
  parse,
30
- } from './ast.js';
31
- import type { AstNode } from './ast.js';
30
+ } from '@ontrails/source';
31
+ import type { AstNode } from '@ontrails/source';
32
32
  import { isFrameworkInternalFile, isTestFile } from './scan.js';
33
33
  import type { WardenDiagnostic, WardenRule } from './types.js';
34
34
 
@@ -37,7 +37,7 @@ const RESULT_ACCESSOR_PROPERTIES: ReadonlySet<string> = new Set(
37
37
  );
38
38
 
39
39
  const MISSING_AWAIT_MESSAGE =
40
- 'Missing await: .blaze() returns Promise<Result> after normalization. Use `const result = await trail.blaze(input, ctx)`.';
40
+ 'Missing await: .implementation() returns Promise<Result> after normalization. Use `const result = await trail.implementation(input, ctx)`.';
41
41
 
42
42
  const createMissingAwaitDiagnostic = (
43
43
  filePath: string,
@@ -91,9 +91,9 @@ const buildParentMap = (ast: AstNode): WeakMap<AstNode, AstNode> => {
91
91
  * Walk up the parent chain and return true when the expression is awaited
92
92
  * before any result-accessing member access fires on it.
93
93
  *
94
- * `await x.blaze(...)` → awaited.
95
- * `(await x.blaze(...)).isOk()` → awaited (await wraps before member access).
96
- * `x.blaze(...).isOk()` → NOT awaited (member access on raw call).
94
+ * `await x.implementation(...)` → awaited.
95
+ * `(await x.implementation(...)).isOk()` → awaited (await wraps before member access).
96
+ * `x.implementation(...).isOk()` → NOT awaited (member access on raw call).
97
97
  */
98
98
  const TRANSPARENT_WRAPPER_TYPES = new Set([
99
99
  'ParenthesizedExpression',
@@ -123,8 +123,8 @@ const skipParens = (
123
123
  *
124
124
  * Conservative: we only hop across a conditional when the node is one of
125
125
  * its branches (not the `test` position). This lets us treat both
126
- * `const r = cond ? x.blaze(...) : fallback` and
127
- * `await (cond ? x.blaze(...) : fallback)` correctly without misattributing
126
+ * `const r = cond ? x.implementation(...) : fallback` and
127
+ * `await (cond ? x.implementation(...) : fallback)` correctly without misattributing
128
128
  * calls used as conditions.
129
129
  */
130
130
  const isBranchOfConditional = (outer: AstNode, parent: AstNode): boolean => {
@@ -137,9 +137,9 @@ const isBranchOfConditional = (outer: AstNode, parent: AstNode): boolean => {
137
137
  };
138
138
 
139
139
  /**
140
- * Logical expressions (`&&`, `||`, `??`) carry the blaze result through either
141
- * side. A `.blaze()` on either operand may be the value ultimately bound to a
142
- * declarator (e.g. `const r = cond && trail.blaze(...)`), so we treat both
140
+ * Logical expressions (`&&`, `||`, `??`) carry the implementation result through either
141
+ * side. A `.implementation()` on either operand may be the value ultimately bound to a
142
+ * declarator (e.g. `const r = cond && trail.implementation(...)`), so we treat both
143
143
  * operands as carriers.
144
144
  */
145
145
  const isOperandOfLogical = (outer: AstNode, parent: AstNode): boolean => {
@@ -175,9 +175,9 @@ const isAwaited = (
175
175
  node: AstNode,
176
176
  parents: WeakMap<AstNode, AstNode>
177
177
  ): boolean => {
178
- // Walk up through parens and any conditional whose branch is the blaze
179
- // call. `await (c ? x.blaze(...) : fallback)` awaits the conditional as a
180
- // whole, so the blaze call in a branch is effectively awaited.
178
+ // Walk up through parens and any conditional whose branch is the implementation
179
+ // call. `await (c ? x.implementation(...) : fallback)` awaits the conditional as a
180
+ // whole, so the implementation call in a branch is effectively awaited.
181
181
  const outer = skipParensAndBranchConditionals(node, parents);
182
182
  return parents.get(outer)?.type === 'AwaitExpression';
183
183
  };
@@ -197,19 +197,19 @@ const memberPropertyName = (node: AstNode): string | null => {
197
197
  };
198
198
 
199
199
  /**
200
- * Check if the blaze call is directly consumed by a result accessor
201
- * (e.g. `foo.blaze(...).isOk()` or `foo.blaze(...).value`).
200
+ * Check if the implementation call is directly consumed by a result accessor
201
+ * (e.g. `foo.implementation(...).isOk()` or `foo.implementation(...).value`).
202
202
  */
203
203
  const hasDirectResultAccess = (
204
- blazeCall: AstNode,
204
+ implementationCall: AstNode,
205
205
  parents: WeakMap<AstNode, AstNode>
206
206
  ): boolean => {
207
207
  // Unwrap wrapping parentheses, conditional branches, and logical-operator
208
- // operands so `(x.blaze(...)).isOk()`,
209
- // `(cond ? x.blaze(...) : fb).isOk()`, and
210
- // `(cond && x.blaze(...)).isOk()` are all detected the same way as the
211
- // bare `x.blaze(...).isOk()` shape.
212
- const outer = skipParensAndBranchConditionals(blazeCall, parents);
208
+ // operands so `(x.implementation(...)).isOk()`,
209
+ // `(cond ? x.implementation(...) : fb).isOk()`, and
210
+ // `(cond && x.implementation(...)).isOk()` are all detected the same way as the
211
+ // bare `x.implementation(...).isOk()` shape.
212
+ const outer = skipParensAndBranchConditionals(implementationCall, parents);
213
213
  const parent = parents.get(outer);
214
214
  if (!parent) {
215
215
  return false;
@@ -219,15 +219,15 @@ const hasDirectResultAccess = (
219
219
  };
220
220
 
221
221
  /**
222
- * If the blaze call is the init of a VariableDeclarator (directly, through
222
+ * If the implementation call is the init of a VariableDeclarator (directly, through
223
223
  * parens, or as a branch of a ConditionalExpression init), return the bound
224
224
  * identifier name. Otherwise null.
225
225
  */
226
226
  const extractAssignedBinding = (
227
- blazeCall: AstNode,
227
+ implementationCall: AstNode,
228
228
  parents: WeakMap<AstNode, AstNode>
229
229
  ): string | null => {
230
- const outer = skipParensAndBranchConditionals(blazeCall, parents);
230
+ const outer = skipParensAndBranchConditionals(implementationCall, parents);
231
231
  const parent = parents.get(outer);
232
232
  if (!parent || parent.type !== 'VariableDeclarator') {
233
233
  return null;
@@ -539,7 +539,7 @@ const collectBlockStatementBindings = (scope: AstNode): Set<string> => {
539
539
  // so `var` declarations inside them do not escape into the enclosing class
540
540
  // or function scope. `collectHoistedVarBindings` correctly refuses to compose
541
541
  // a `StaticBlock` boundary from the outside, which means nothing else will
542
- // register these bindings. Hoist them here so `var result = trail.blaze(...)`
542
+ // register these bindings. Hoist them here so `var result = trail.implementation(...)`
543
543
  // inside a `static { ... }` block is tracked against the block itself.
544
544
  if (scope.type === 'StaticBlock') {
545
545
  // `collectHoistedVarBindings` is called with the StaticBlock as the root,
@@ -586,7 +586,7 @@ interface ScopeFrame {
586
586
  * For function frames: names that came from parameters (not hoisted `var`s).
587
587
  * A `var` declaration with the same name as a parameter is redundant in JS —
588
588
  * the parameter is the real binding. We track params separately so we don't
589
- * register a pending `.blaze()` binding that is actually shadowed by a param.
589
+ * register a pending `.implementation()` binding that is actually shadowed by a param.
590
590
  */
591
591
  readonly paramBindings?: Set<string>;
592
592
  }
@@ -647,7 +647,7 @@ interface AnalyzeState {
647
647
  readonly diagnostics: WardenDiagnostic[];
648
648
  readonly sourceCode: string;
649
649
  readonly filePath: string;
650
- /** Pending `.blaze()` bindings seen so far, keyed by scope id + name. */
650
+ /** Pending `.implementation()` bindings seen so far, keyed by scope id + name. */
651
651
  readonly pendingByScopeAndName: Map<string, PendingBinding>;
652
652
  readonly scopeStack: ScopeFrame[];
653
653
  readonly reportedAt: Set<number>;
@@ -683,15 +683,15 @@ const resolveNearestScope = (
683
683
  };
684
684
 
685
685
  /**
686
- * Resolve the blaze call to a `{ name, declarator }` pair when it is the init
686
+ * Resolve the implementation call to a `{ name, declarator }` pair when it is the init
687
687
  * of a `VariableDeclarator` (directly, through parens, or as a branch of a
688
688
  * `ConditionalExpression` init). Returns null otherwise.
689
689
  */
690
- const resolveBlazeBinding = (
691
- blazeCall: AstNode,
690
+ const resolveImplementationBinding = (
691
+ implementationCall: AstNode,
692
692
  parents: WeakMap<AstNode, AstNode>
693
693
  ): { readonly name: string; readonly declarator: AstNode } | null => {
694
- const name = extractAssignedBinding(blazeCall, parents);
694
+ const name = extractAssignedBinding(implementationCall, parents);
695
695
  if (!name) {
696
696
  return null;
697
697
  }
@@ -699,22 +699,22 @@ const resolveBlazeBinding = (
699
699
  // conditionals so the stored declaration node points at the
700
700
  // `VariableDeclarator`, not at an intermediate `ParenthesizedExpression`
701
701
  // or `ConditionalExpression`.
702
- const outer = skipParensAndBranchConditionals(blazeCall, parents);
702
+ const outer = skipParensAndBranchConditionals(implementationCall, parents);
703
703
  const declarator = parents.get(outer);
704
704
  return declarator ? { declarator, name } : null;
705
705
  };
706
706
 
707
707
  /**
708
- * Resolve the blaze call to a `{ name, assignment }` pair when it is the RHS
708
+ * Resolve the implementation call to a `{ name, assignment }` pair when it is the RHS
709
709
  * of a plain `=` `AssignmentExpression` with an `Identifier` LHS (directly,
710
710
  * through parens, or as a branch of a conditional/logical expression).
711
711
  *
712
712
  * Covers patterns like:
713
713
  * let result;
714
- * result = trail.blaze(input, ctx);
714
+ * result = trail.implementation(input, ctx);
715
715
  * result.isOk();
716
716
  *
717
- * Member-expression LHS (`obj.result = blaze(...)`) is intentionally skipped —
717
+ * Member-expression LHS (`obj.result = implementation(...)`) is intentionally skipped —
718
718
  * those are property writes, not bare bindings we can track by name.
719
719
  */
720
720
  const extractPlainIdentifierAssignmentName = (
@@ -726,7 +726,7 @@ const extractPlainIdentifierAssignmentName = (
726
726
  const operator = getNodeOperator(parent);
727
727
  const left = getNodeLeft(parent);
728
728
  // Only plain `=` assignments to a bare identifier. Member-expression LHS
729
- // (`obj.result = blaze(...)`) is a property write, not a bare binding we
729
+ // (`obj.result = implementation(...)`) is a property write, not a bare binding we
730
730
  // can track by name.
731
731
  if (operator !== '=' || !left || left.type !== 'Identifier') {
732
732
  return null;
@@ -734,11 +734,11 @@ const extractPlainIdentifierAssignmentName = (
734
734
  return identifierName(left);
735
735
  };
736
736
 
737
- const resolveBlazeAssignment = (
738
- blazeCall: AstNode,
737
+ const resolveImplementationAssignment = (
738
+ implementationCall: AstNode,
739
739
  parents: WeakMap<AstNode, AstNode>
740
740
  ): { readonly name: string; readonly assignment: AstNode } | null => {
741
- const outer = skipParensAndBranchConditionals(blazeCall, parents);
741
+ const outer = skipParensAndBranchConditionals(implementationCall, parents);
742
742
  const parent = parents.get(outer);
743
743
  const name = extractPlainIdentifierAssignmentName(parent);
744
744
  return name && parent ? { assignment: parent, name } : null;
@@ -767,7 +767,7 @@ const isVarDeclaratorOfParamName = (
767
767
  * that name is a function parameter, the assignment re-initializes the
768
768
  * parameter's slot in the VariableEnvironment, just like `var <name> = ...`.
769
769
  * Compound assignments (`+=`, `??=`, etc.) are excluded because they do not
770
- * unconditionally replace the slot with the blaze result.
770
+ * unconditionally replace the slot with the implementation result.
771
771
  */
772
772
  const isAssignmentToParamName = (node: AstNode): boolean => {
773
773
  if (node.type !== 'AssignmentExpression') {
@@ -779,13 +779,16 @@ const isAssignmentToParamName = (node: AstNode): boolean => {
779
779
  };
780
780
 
781
781
  const recordPendingBinding = (
782
- blazeCall: AstNode,
782
+ implementationCall: AstNode,
783
783
  state: AnalyzeState
784
784
  ): void => {
785
785
  const binding =
786
- resolveBlazeBinding(blazeCall, state.parents) ??
786
+ resolveImplementationBinding(implementationCall, state.parents) ??
787
787
  (() => {
788
- const asn = resolveBlazeAssignment(blazeCall, state.parents);
788
+ const asn = resolveImplementationAssignment(
789
+ implementationCall,
790
+ state.parents
791
+ );
789
792
  return asn ? { declarator: asn.assignment, name: asn.name } : null;
790
793
  })();
791
794
  if (!binding) {
@@ -802,21 +805,21 @@ const recordPendingBinding = (
802
805
  }
803
806
  // If the name resolves to a function parameter, the `var` that visually
804
807
  // appears to declare it is redundant — the parameter is the real binding,
805
- // and parameters are not pending `.blaze()` results.
808
+ // and parameters are not pending `.implementation()` results.
806
809
  //
807
- // Carve-out: a `var <name> = blaze(...)` *initializer* inside the same
810
+ // Carve-out: a `var <name> = implementation(...)` *initializer* inside the same
808
811
  // function body legitimately re-binds the parameter at that point. `var`
809
812
  // and parameters share the function's VariableEnvironment, so the `var`
810
813
  // writes to the existing parameter slot and the subsequent use resolves
811
- // to the freshly-assigned `.blaze()` result. Treat that as a pending
814
+ // to the freshly-assigned `.implementation()` result. Treat that as a pending
812
815
  // binding.
813
816
  //
814
- // The same logic applies to a bare `result = blaze(...)` assignment: it
817
+ // The same logic applies to a bare `result = implementation(...)` assignment: it
815
818
  // writes to the parameter's existing slot in the same VariableEnvironment,
816
- // so the subsequent `result.isOk()` observes the blaze result. Only
819
+ // so the subsequent `result.isOk()` observes the implementation result. Only
817
820
  // compound assignments (`+=`, `??=`, etc.) and member-expression LHS fall
818
821
  // through the param-shadow suppression, because they do not
819
- // unconditionally replace the parameter slot with the blaze result.
822
+ // unconditionally replace the parameter slot with the implementation result.
820
823
  if (
821
824
  owningFrame.paramBindings?.has(name) &&
822
825
  !isVarDeclaratorOfParamName(declarator, state.parents) &&
@@ -833,12 +836,12 @@ const recordPendingBinding = (
833
836
 
834
837
  /**
835
838
  * True when `expr`, descended through wrapping parens, conditional branches,
836
- * and logical-operator operands, contains a `.blaze()` call that would be
839
+ * and logical-operator operands, contains a `.implementation()` call that would be
837
840
  * registered by `recordPendingBinding` for this assignment.
838
841
  *
839
842
  * This mirrors the *upward* carrier walk done by
840
- * `skipParensAndBranchConditionals` — if a blaze call is anywhere along a
841
- * carrier path descending from `expr`, then visiting that blaze call will
843
+ * `skipParensAndBranchConditionals` — if a implementation call is anywhere along a
844
+ * carrier path descending from `expr`, then visiting that implementation call will
842
845
  * re-register the pending binding, so we must not clear it on the way in.
843
846
  */
844
847
  type CarrierChildExtractor = (
@@ -862,23 +865,23 @@ const unwrapTransparentWrapper = (expr: AstNode): AstNode | undefined =>
862
865
 
863
866
  // biome-ignore lint/style/useConst: hoisted for recursive call
864
867
  // eslint-disable-next-line func-style
865
- function rhsCarriesBlazeReinit(expr: AstNode | undefined): boolean {
868
+ function rhsCarriesImplementationReinit(expr: AstNode | undefined): boolean {
866
869
  if (!expr) {
867
870
  return false;
868
871
  }
869
872
  if (TRANSPARENT_WRAPPER_TYPES.has(expr.type)) {
870
- return rhsCarriesBlazeReinit(unwrapTransparentWrapper(expr));
873
+ return rhsCarriesImplementationReinit(unwrapTransparentWrapper(expr));
871
874
  }
872
875
  const extractor = CARRIER_CHILDREN[expr.type];
873
876
  if (extractor) {
874
- return extractor(expr).some(rhsCarriesBlazeReinit);
877
+ return extractor(expr).some(rhsCarriesImplementationReinit);
875
878
  }
876
- return isBlazeCall(expr);
879
+ return isImplementationCall(expr);
877
880
  }
878
881
 
879
882
  /**
880
883
  * Nullish/falsy-skip compound assignments (`??=`, `||=`) only write to the slot
881
- * when the LHS is nullish or falsy. A pending `.blaze()` binding holds a
884
+ * when the LHS is nullish or falsy. A pending `.implementation()` binding holds a
882
885
  * truthy `Promise<Result>`, so the RHS never runs and the pending binding must
883
886
  * survive them.
884
887
  *
@@ -924,10 +927,10 @@ const resolvePendingKeyFor = (
924
927
 
925
928
  /**
926
929
  * Handle a plain `=` assignment (or clearing compound assignment) to a bare
927
- * identifier whose name currently has a pending `.blaze()` binding in scope.
930
+ * identifier whose name currently has a pending `.implementation()` binding in scope.
928
931
  *
929
- * A plain `=` whose RHS carries another blaze call leaves the pending entry
930
- * alone — `recordPendingBinding` will re-register it when the blaze call
932
+ * A plain `=` whose RHS carries another implementation call leaves the pending entry
933
+ * alone — `recordPendingBinding` will re-register it when the implementation call
931
934
  * itself is visited. Otherwise, clear the pending entry: the identifier has
932
935
  * been overwritten with a non-Result value, so the original
933
936
  * `result.isOk()`-style diagnostic no longer applies.
@@ -951,11 +954,14 @@ const handleAssignmentReassignment = (
951
954
  if (!key) {
952
955
  return;
953
956
  }
954
- // Plain `=` with a blaze-carrying RHS will re-register via
955
- // `recordPendingBinding` when the blaze call itself is visited. Other
957
+ // Plain `=` with a implementation-carrying RHS will re-register via
958
+ // `recordPendingBinding` when the implementation call itself is visited. Other
956
959
  // compound operators (`+=`, `-=`, `*=`, etc.) produce a primitive value
957
960
  // from the existing slot, so they always clear.
958
- if (assignment.operator === '=' && rhsCarriesBlazeReinit(assignment.right)) {
961
+ if (
962
+ assignment.operator === '=' &&
963
+ rhsCarriesImplementationReinit(assignment.right)
964
+ ) {
959
965
  return;
960
966
  }
961
967
  state.pendingByScopeAndName.delete(key);
@@ -1005,12 +1011,12 @@ const checkPendingAccess = (node: AstNode, state: AnalyzeState): void => {
1005
1011
  };
1006
1012
 
1007
1013
  /**
1008
- * If the blaze call is the init of a VariableDeclarator whose id is an
1014
+ * If the implementation call is the init of a VariableDeclarator whose id is an
1009
1015
  * ObjectPattern that destructures any known Result accessor property,
1010
1016
  * return the declarator node. Otherwise null.
1011
1017
  *
1012
1018
  * Catches the core missing-await shape when written as destructuring:
1013
- * `const { isOk } = entityShow.blaze(input, ctx)` — no await, immediate
1019
+ * `const { isOk } = entityShow.implementation(input, ctx)` — no await, immediate
1014
1020
  * access to a Result accessor, should fire.
1015
1021
  */
1016
1022
  const propertyDestructuresResultAccessor = (prop: AstNode): boolean => {
@@ -1027,14 +1033,14 @@ const objectPatternHasResultAccessorKey = (pattern: AstNode): boolean => {
1027
1033
  };
1028
1034
 
1029
1035
  const getDestructuredResultAccessorDeclarator = (
1030
- blazeCall: AstNode,
1036
+ implementationCall: AstNode,
1031
1037
  parents: WeakMap<AstNode, AstNode>
1032
1038
  ): AstNode | null => {
1033
1039
  // Unwrap any wrapping parentheses and branch-position conditionals so
1034
- // `const { isOk } = (trail.blaze(...));` and
1035
- // `const { isOk } = cond ? trail.blaze(...) : fallback;` are treated as
1036
- // `const { isOk } = trail.blaze(...);`.
1037
- const outer = skipParensAndBranchConditionals(blazeCall, parents);
1040
+ // `const { isOk } = (trail.implementation(...));` and
1041
+ // `const { isOk } = cond ? trail.implementation(...) : fallback;` are treated as
1042
+ // `const { isOk } = trail.implementation(...);`.
1043
+ const outer = skipParensAndBranchConditionals(implementationCall, parents);
1038
1044
  const parent = parents.get(outer);
1039
1045
  if (!parent || parent.type !== 'VariableDeclarator') {
1040
1046
  return null;
@@ -1046,8 +1052,8 @@ const getDestructuredResultAccessorDeclarator = (
1046
1052
  return objectPatternHasResultAccessorKey(id) ? parent : null;
1047
1053
  };
1048
1054
 
1049
- const visitBlazeCall = (node: AstNode, state: AnalyzeState): void => {
1050
- if (!isBlazeCall(node) || isAwaited(node, state.parents)) {
1055
+ const visitImplementationCall = (node: AstNode, state: AnalyzeState): void => {
1056
+ if (!isImplementationCall(node) || isAwaited(node, state.parents)) {
1051
1057
  return;
1052
1058
  }
1053
1059
  if (hasDirectResultAccess(node, state.parents)) {
@@ -1066,7 +1072,7 @@ const visitBlazeCall = (node: AstNode, state: AnalyzeState): void => {
1066
1072
  };
1067
1073
 
1068
1074
  const visitNode = (node: AstNode, state: AnalyzeState): void => {
1069
- visitBlazeCall(node, state);
1075
+ visitImplementationCall(node, state);
1070
1076
  checkPendingAccess(node, state);
1071
1077
  };
1072
1078
 
@@ -1173,7 +1179,7 @@ const analyze = (
1173
1179
  };
1174
1180
 
1175
1181
  /**
1176
- * Flags code that assumes `.blaze()` returns a synchronous result.
1182
+ * Flags code that assumes `.implementation()` returns a synchronous result.
1177
1183
  */
1178
1184
  export const noSyncResultAssumption: WardenRule = {
1179
1185
  check(sourceCode: string, filePath: string): readonly WardenDiagnostic[] {
@@ -1187,7 +1193,7 @@ export const noSyncResultAssumption: WardenRule = {
1187
1193
  return analyze(ast, sourceCode, filePath);
1188
1194
  },
1189
1195
  description:
1190
- 'Disallow treating .blaze() as synchronous after normalization. Always await the returned Promise<Result>.',
1196
+ 'Disallow treating .implementation() as synchronous after normalization. Always await the returned Promise<Result>.',
1191
1197
  name: 'no-sync-result-assumption',
1192
1198
  severity: 'error',
1193
1199
  };
@@ -6,8 +6,8 @@ import {
6
6
  parse,
7
7
  walk,
8
8
  walkScope,
9
- } from './ast.js';
10
- import type { AstNode } from './ast.js';
9
+ } from '@ontrails/source';
10
+ import type { AstNode } from '@ontrails/source';
11
11
  import { isTestFile } from './scan.js';
12
12
  import type { WardenDiagnostic, WardenRule } from './types.js';
13
13
 
@@ -1,13 +1,18 @@
1
1
  /**
2
- * Finds `throw` statements inside `blaze:` function bodies.
2
+ * Finds `throw` statements inside `implementation:` function bodies.
3
3
  *
4
4
  * Uses scope-aware AST walking so throws inside nested callbacks
5
5
  * (e.g. `.map()`, `.filter()`, inner helpers) are not attributed to
6
- * the blaze body itself. ADR-0007 requires this class of false positive
7
- * to be avoided — only throws in the blaze body scope should be flagged.
6
+ * the implementation body itself. ADR-0007 requires this class of false positive
7
+ * to be avoided — only throws in the implementation body scope should be flagged.
8
8
  */
9
9
 
10
- import { findBlazeBodies, offsetToLine, parse, walkScope } from './ast.js';
10
+ import {
11
+ findImplementationBodies,
12
+ offsetToLine,
13
+ parse,
14
+ walkScope,
15
+ } from '@ontrails/source';
11
16
  import type { WardenDiagnostic, WardenRule } from './types.js';
12
17
 
13
18
  export const noThrowInImplementation: WardenRule = {
@@ -19,13 +24,14 @@ export const noThrowInImplementation: WardenRule = {
19
24
 
20
25
  const diagnostics: WardenDiagnostic[] = [];
21
26
 
22
- for (const body of findBlazeBodies(ast)) {
27
+ for (const body of findImplementationBodies(ast)) {
23
28
  walkScope(body, (node) => {
24
29
  if (node.type === 'ThrowStatement') {
25
30
  diagnostics.push({
26
31
  filePath,
27
32
  line: offsetToLine(sourceCode, node.start),
28
- message: 'Do not throw inside the blaze. Use Result.err() instead.',
33
+ message:
34
+ 'Do not throw inside the implementation. Use Result.err() instead.',
29
35
  rule: 'no-throw-in-implementation',
30
36
  severity: 'error',
31
37
  });
@@ -36,7 +42,7 @@ export const noThrowInImplementation: WardenRule = {
36
42
  return diagnostics;
37
43
  },
38
44
  description:
39
- 'Disallow throw statements inside blaze bodies. Use Result.err() instead.',
45
+ 'Disallow throw statements inside implementation bodies. Use Result.err() instead.',
40
46
  name: 'no-throw-in-implementation',
41
47
  severity: 'error',
42
48
  };
@@ -21,8 +21,8 @@ import {
21
21
  isStringLiteral,
22
22
  offsetToLine,
23
23
  parse,
24
- } from './ast.js';
25
- import type { AstNode } from './ast.js';
24
+ } from '@ontrails/source';
25
+ import type { AstNode } from '@ontrails/source';
26
26
  import type { WardenDiagnostic, WardenRule } from './types.js';
27
27
 
28
28
  const RULE_NAME = 'no-top-level-surface';
@@ -9,8 +9,8 @@
9
9
 
10
10
  import { isDraftId } from '@ontrails/core';
11
11
 
12
+ import { collectSignalDefinitionIds } from './source/signals.js';
12
13
  import {
13
- collectSignalDefinitionIds,
14
14
  deriveConstString,
15
15
  findConfigProperty,
16
16
  findTrailDefinitions,
@@ -19,8 +19,8 @@ import {
19
19
  isStringLiteral,
20
20
  offsetToLine,
21
21
  parse,
22
- } from './ast.js';
23
- import type { AstNode } from './ast.js';
22
+ } from '@ontrails/source';
23
+ import type { AstNode } from '@ontrails/source';
24
24
  import { isTestFile } from './scan.js';
25
25
  import type {
26
26
  ProjectAwareWardenRule,
@@ -1,11 +1,10 @@
1
+ import { collectOnTargetSignalIds } from './source/signals.js';
1
2
  import {
2
3
  collectCrudTableIds,
3
- collectOnTargetSignalIds,
4
4
  findStoreTableDefinitions,
5
- offsetToLine,
6
- parse,
7
- } from './ast.js';
8
- import type { AstNode } from './ast.js';
5
+ } from './source/stores.js';
6
+ import { offsetToLine, parse } from '@ontrails/source';
7
+ import type { AstNode } from '@ontrails/source';
9
8
  import { isTestFile } from './scan.js';
10
9
  import type {
11
10
  ProjectAwareWardenRule,
@@ -14,8 +14,8 @@ import {
14
14
  offsetToLine,
15
15
  parse,
16
16
  walk,
17
- } from './ast.js';
18
- import type { AstNode } from './ast.js';
17
+ } from '@ontrails/source';
18
+ import type { AstNode } from '@ontrails/source';
19
19
  import type { WardenDiagnostic, WardenRule } from './types.js';
20
20
 
21
21
  const RULE_NAME = 'owner-projection-parity';
@@ -34,8 +34,8 @@ import {
34
34
  getNodeBodyStatements,
35
35
  getNodeDeclaration,
36
36
  getNodeDeclarations,
37
- getNodeExportKind,
38
37
  getNodeExported,
38
+ getNodeExportKind,
39
39
  getNodeId,
40
40
  getNodeLocal,
41
41
  getNodeName,
@@ -44,8 +44,8 @@ import {
44
44
  getNodeValue,
45
45
  offsetToLine,
46
46
  parse,
47
- } from './ast.js';
48
- import type { AstNode } from './ast.js';
47
+ } from '@ontrails/source';
48
+ import type { AstNode } from '@ontrails/source';
49
49
  import type { WardenDiagnostic, WardenRule } from './types.js';
50
50
 
51
51
  const RULE_NAME = 'public-export-example-coverage';
@@ -115,7 +115,13 @@ export const PUBLIC_API_EXAMPLE_TARGETS: readonly PublicApiPackageTarget[] = [
115
115
  },
116
116
  {
117
117
  indexPath: 'adapters/cloudflare/src/index.ts',
118
- minimumExports: ['createWorkersHandler', 'cloudflareKv'],
118
+ minimumExports: [
119
+ 'createWorkersHandler',
120
+ 'cloudflareKv',
121
+ 'cloudflareD1',
122
+ 'cloudflareQueue',
123
+ 'cloudflareR2',
124
+ ],
119
125
  packageName: '@ontrails/cloudflare',
120
126
  },
121
127
  ] as const;
@@ -2,15 +2,14 @@ import { existsSync, realpathSync } from 'node:fs';
2
2
  import { resolve, sep } from 'node:path';
3
3
  import { matchesPathGlob } from '@ontrails/core';
4
4
 
5
+ import { hasIgnoreCommentOnLine, splitSourceLines } from './source/pragmas.js';
5
6
  import {
6
7
  extractStringLiteral,
7
8
  getNodeSource,
8
- hasIgnoreCommentOnLine,
9
9
  offsetToLine,
10
10
  parse,
11
- splitSourceLines,
12
11
  walk,
13
- } from './ast.js';
12
+ } from '@ontrails/source';
14
13
  import type {
15
14
  ProjectAwareWardenRule,
16
15
  ProjectContext,