@ontrails/warden 1.0.0-beta.13 → 1.0.0-beta.15
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.
- package/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +30 -0
- package/README.md +31 -20
- package/dist/cli.d.ts +19 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +261 -64
- package/dist/cli.js.map +1 -1
- package/dist/draft.d.ts +5 -0
- package/dist/draft.d.ts.map +1 -0
- package/dist/draft.js +16 -0
- package/dist/draft.js.map +1 -0
- package/dist/drift.d.ts +10 -7
- package/dist/drift.d.ts.map +1 -1
- package/dist/drift.js +50 -16
- package/dist/drift.js.map +1 -1
- package/dist/formatters.d.ts +2 -1
- package/dist/formatters.d.ts.map +1 -1
- package/dist/formatters.js +15 -4
- package/dist/formatters.js.map +1 -1
- package/dist/index.d.ts +9 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -17
- package/dist/index.js.map +1 -1
- package/dist/rules/ast.d.ts +412 -7
- package/dist/rules/ast.d.ts.map +1 -1
- package/dist/rules/ast.js +1847 -102
- package/dist/rules/ast.js.map +1 -1
- package/dist/rules/circular-refs.d.ts +6 -0
- package/dist/rules/circular-refs.d.ts.map +1 -0
- package/dist/rules/circular-refs.js +83 -0
- package/dist/rules/circular-refs.js.map +1 -0
- package/dist/rules/context-no-surface-types.d.ts.map +1 -1
- package/dist/rules/context-no-surface-types.js +59 -3
- package/dist/rules/context-no-surface-types.js.map +1 -1
- package/dist/rules/contour-exists.d.ts +7 -0
- package/dist/rules/contour-exists.d.ts.map +1 -0
- package/dist/rules/contour-exists.js +113 -0
- package/dist/rules/contour-exists.js.map +1 -0
- package/dist/rules/contour-ids.d.ts +10 -0
- package/dist/rules/contour-ids.d.ts.map +1 -0
- package/dist/rules/contour-ids.js +12 -0
- package/dist/rules/contour-ids.js.map +1 -0
- package/dist/rules/cross-declarations.d.ts.map +1 -1
- package/dist/rules/cross-declarations.js +171 -57
- package/dist/rules/cross-declarations.js.map +1 -1
- package/dist/rules/dead-internal-trail.d.ts +3 -0
- package/dist/rules/dead-internal-trail.d.ts.map +1 -0
- package/dist/rules/dead-internal-trail.js +80 -0
- package/dist/rules/dead-internal-trail.js.map +1 -0
- package/dist/rules/draft-file-marking.d.ts +6 -0
- package/dist/rules/draft-file-marking.d.ts.map +1 -0
- package/dist/rules/draft-file-marking.js +87 -0
- package/dist/rules/draft-file-marking.js.map +1 -0
- package/dist/rules/draft-visible-debt.d.ts +12 -0
- package/dist/rules/draft-visible-debt.d.ts.map +1 -0
- package/dist/rules/draft-visible-debt.js +50 -0
- package/dist/rules/draft-visible-debt.js.map +1 -0
- package/dist/rules/error-mapping-completeness.d.ts +13 -0
- package/dist/rules/error-mapping-completeness.d.ts.map +1 -0
- package/dist/rules/error-mapping-completeness.js +160 -0
- package/dist/rules/error-mapping-completeness.js.map +1 -0
- package/dist/rules/example-valid.d.ts +6 -0
- package/dist/rules/example-valid.d.ts.map +1 -0
- package/dist/rules/example-valid.js +203 -0
- package/dist/rules/example-valid.js.map +1 -0
- package/dist/rules/fires-declarations.d.ts +16 -0
- package/dist/rules/fires-declarations.d.ts.map +1 -0
- package/dist/rules/fires-declarations.js +444 -0
- package/dist/rules/fires-declarations.js.map +1 -0
- package/dist/rules/implementation-returns-result.d.ts +9 -0
- package/dist/rules/implementation-returns-result.d.ts.map +1 -1
- package/dist/rules/implementation-returns-result.js +638 -76
- package/dist/rules/implementation-returns-result.js.map +1 -1
- package/dist/rules/incomplete-accessor-for-standard-op.d.ts +30 -0
- package/dist/rules/incomplete-accessor-for-standard-op.d.ts.map +1 -0
- package/dist/rules/incomplete-accessor-for-standard-op.js +226 -0
- package/dist/rules/incomplete-accessor-for-standard-op.js.map +1 -0
- package/dist/rules/incomplete-crud.d.ts +21 -0
- package/dist/rules/incomplete-crud.d.ts.map +1 -0
- package/dist/rules/incomplete-crud.js +368 -0
- package/dist/rules/incomplete-crud.js.map +1 -0
- package/dist/rules/index.d.ts +40 -7
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +91 -15
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/intent-propagation.d.ts +3 -0
- package/dist/rules/intent-propagation.d.ts.map +1 -0
- package/dist/rules/intent-propagation.js +57 -0
- package/dist/rules/intent-propagation.js.map +1 -0
- package/dist/rules/missing-reconcile.d.ts +3 -0
- package/dist/rules/missing-reconcile.d.ts.map +1 -0
- package/dist/rules/missing-reconcile.js +44 -0
- package/dist/rules/missing-reconcile.js.map +1 -0
- package/dist/rules/missing-visibility.d.ts +3 -0
- package/dist/rules/missing-visibility.d.ts.map +1 -0
- package/dist/rules/missing-visibility.js +63 -0
- package/dist/rules/missing-visibility.js.map +1 -0
- package/dist/rules/no-direct-impl-in-route.d.ts.map +1 -1
- package/dist/rules/no-direct-impl-in-route.js +0 -3
- package/dist/rules/no-direct-impl-in-route.js.map +1 -1
- package/dist/rules/no-direct-implementation-call.js +1 -1
- package/dist/rules/no-direct-implementation-call.js.map +1 -1
- package/dist/rules/no-sync-result-assumption.d.ts.map +1 -1
- package/dist/rules/no-sync-result-assumption.js +870 -61
- package/dist/rules/no-sync-result-assumption.js.map +1 -1
- package/dist/rules/no-throw-in-detour-recover.d.ts +3 -0
- package/dist/rules/no-throw-in-detour-recover.d.ts.map +1 -0
- package/dist/rules/no-throw-in-detour-recover.js +147 -0
- package/dist/rules/no-throw-in-detour-recover.js.map +1 -0
- package/dist/rules/no-throw-in-detour-target.d.ts +4 -1
- package/dist/rules/no-throw-in-detour-target.d.ts.map +1 -1
- package/dist/rules/no-throw-in-detour-target.js +6 -3
- package/dist/rules/no-throw-in-detour-target.js.map +1 -1
- package/dist/rules/no-throw-in-implementation.d.ts +4 -2
- package/dist/rules/no-throw-in-implementation.d.ts.map +1 -1
- package/dist/rules/no-throw-in-implementation.js +6 -4
- package/dist/rules/no-throw-in-implementation.js.map +1 -1
- package/dist/rules/on-references-exist.d.ts +14 -0
- package/dist/rules/on-references-exist.d.ts.map +1 -0
- package/dist/rules/on-references-exist.js +109 -0
- package/dist/rules/on-references-exist.js.map +1 -0
- package/dist/rules/orphaned-signal.d.ts +3 -0
- package/dist/rules/orphaned-signal.d.ts.map +1 -0
- package/dist/rules/orphaned-signal.js +67 -0
- package/dist/rules/orphaned-signal.js.map +1 -0
- package/dist/rules/permit-governance.d.ts +3 -0
- package/dist/rules/permit-governance.d.ts.map +1 -0
- package/dist/rules/permit-governance.js +15 -0
- package/dist/rules/permit-governance.js.map +1 -0
- package/dist/rules/reference-exists.d.ts +6 -0
- package/dist/rules/reference-exists.d.ts.map +1 -0
- package/dist/rules/reference-exists.js +47 -0
- package/dist/rules/reference-exists.js.map +1 -0
- package/dist/rules/registry-names.d.ts +8 -0
- package/dist/rules/registry-names.d.ts.map +1 -0
- package/dist/rules/registry-names.js +83 -0
- package/dist/rules/registry-names.js.map +1 -0
- package/dist/rules/resource-declarations.d.ts +14 -0
- package/dist/rules/resource-declarations.d.ts.map +1 -0
- package/dist/rules/resource-declarations.js +413 -0
- package/dist/rules/resource-declarations.js.map +1 -0
- package/dist/rules/resource-exists.d.ts +6 -0
- package/dist/rules/resource-exists.d.ts.map +1 -0
- package/dist/rules/resource-exists.js +90 -0
- package/dist/rules/resource-exists.js.map +1 -0
- package/dist/rules/resource-id-grammar.d.ts +3 -0
- package/dist/rules/resource-id-grammar.d.ts.map +1 -0
- package/dist/rules/resource-id-grammar.js +39 -0
- package/dist/rules/resource-id-grammar.js.map +1 -0
- package/dist/rules/specs.d.ts.map +1 -1
- package/dist/rules/specs.js +5 -1
- package/dist/rules/specs.js.map +1 -1
- package/dist/rules/types.d.ts +53 -4
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/unreachable-detour-shadowing.d.ts +3 -0
- package/dist/rules/unreachable-detour-shadowing.d.ts.map +1 -0
- package/dist/rules/unreachable-detour-shadowing.js +202 -0
- package/dist/rules/unreachable-detour-shadowing.js.map +1 -0
- package/dist/rules/valid-describe-refs.d.ts.map +1 -1
- package/dist/rules/valid-describe-refs.js +132 -16
- package/dist/rules/valid-describe-refs.js.map +1 -1
- package/dist/rules/valid-detour-contract.d.ts +3 -0
- package/dist/rules/valid-detour-contract.d.ts.map +1 -0
- package/dist/rules/valid-detour-contract.js +47 -0
- package/dist/rules/valid-detour-contract.js.map +1 -0
- package/dist/rules/valid-detour-refs.d.ts.map +1 -1
- package/dist/rules/valid-detour-refs.js +73 -82
- package/dist/rules/valid-detour-refs.js.map +1 -1
- package/dist/rules/warden-export-symmetry.d.ts +7 -0
- package/dist/rules/warden-export-symmetry.d.ts.map +1 -0
- package/dist/rules/warden-export-symmetry.js +352 -0
- package/dist/rules/warden-export-symmetry.js.map +1 -0
- package/dist/rules/warden-rules-use-ast.d.ts +17 -0
- package/dist/rules/warden-rules-use-ast.d.ts.map +1 -0
- package/dist/rules/warden-rules-use-ast.js +778 -0
- package/dist/rules/warden-rules-use-ast.js.map +1 -0
- package/dist/trails/circular-refs.trail.d.ts +24 -0
- package/dist/trails/circular-refs.trail.d.ts.map +1 -0
- package/dist/trails/circular-refs.trail.js +29 -0
- package/dist/trails/circular-refs.trail.js.map +1 -0
- package/dist/trails/context-no-surface-types.trail.d.ts +2 -2
- package/dist/trails/context-no-surface-types.trail.d.ts.map +1 -1
- package/dist/trails/context-no-trailhead-types.trail.d.ts +2 -2
- package/dist/trails/context-no-trailhead-types.trail.d.ts.map +1 -1
- package/dist/trails/contour-exists.trail.d.ts +24 -0
- package/dist/trails/contour-exists.trail.d.ts.map +1 -0
- package/dist/trails/contour-exists.trail.js +21 -0
- package/dist/trails/contour-exists.trail.js.map +1 -0
- package/dist/trails/cross-declarations.trail.d.ts +2 -2
- package/dist/trails/cross-declarations.trail.d.ts.map +1 -1
- package/dist/trails/dead-internal-trail.trail.d.ts +24 -0
- package/dist/trails/dead-internal-trail.trail.d.ts.map +1 -0
- package/dist/trails/dead-internal-trail.trail.js +26 -0
- package/dist/trails/dead-internal-trail.trail.js.map +1 -0
- package/dist/trails/{provision-declarations.trail.d.ts → draft-file-marking.trail.d.ts} +3 -3
- package/dist/trails/draft-file-marking.trail.d.ts.map +1 -0
- package/dist/trails/draft-file-marking.trail.js +16 -0
- package/dist/trails/draft-file-marking.trail.js.map +1 -0
- package/dist/trails/draft-visible-debt.trail.d.ts +13 -0
- package/dist/trails/draft-visible-debt.trail.d.ts.map +1 -0
- package/dist/trails/draft-visible-debt.trail.js +16 -0
- package/dist/trails/draft-visible-debt.trail.js.map +1 -0
- package/dist/trails/error-mapping-completeness.trail.d.ts +13 -0
- package/dist/trails/error-mapping-completeness.trail.d.ts.map +1 -0
- package/dist/trails/error-mapping-completeness.trail.js +29 -0
- package/dist/trails/error-mapping-completeness.trail.js.map +1 -0
- package/dist/trails/{follow-declarations.trail.d.ts → example-valid.trail.d.ts} +3 -3
- package/dist/trails/example-valid.trail.d.ts.map +1 -0
- package/dist/trails/example-valid.trail.js +25 -0
- package/dist/trails/example-valid.trail.js.map +1 -0
- package/dist/trails/fires-declarations.trail.d.ts +13 -0
- package/dist/trails/fires-declarations.trail.d.ts.map +1 -0
- package/dist/trails/fires-declarations.trail.js +22 -0
- package/dist/trails/fires-declarations.trail.js.map +1 -0
- package/dist/trails/implementation-returns-result.trail.d.ts +2 -2
- package/dist/trails/implementation-returns-result.trail.d.ts.map +1 -1
- package/dist/trails/incomplete-accessor-for-standard-op.trail.d.ts +12 -0
- package/dist/trails/incomplete-accessor-for-standard-op.trail.d.ts.map +1 -0
- package/dist/trails/incomplete-accessor-for-standard-op.trail.js +60 -0
- package/dist/trails/incomplete-accessor-for-standard-op.trail.js.map +1 -0
- package/dist/trails/incomplete-crud.trail.d.ts +24 -0
- package/dist/trails/incomplete-crud.trail.d.ts.map +1 -0
- package/dist/trails/incomplete-crud.trail.js +39 -0
- package/dist/trails/incomplete-crud.trail.js.map +1 -0
- package/dist/trails/index.d.ts +29 -7
- package/dist/trails/index.d.ts.map +1 -1
- package/dist/trails/index.js +28 -6
- package/dist/trails/index.js.map +1 -1
- package/dist/trails/intent-propagation.trail.d.ts +24 -0
- package/dist/trails/intent-propagation.trail.d.ts.map +1 -0
- package/dist/trails/intent-propagation.trail.js +30 -0
- package/dist/trails/intent-propagation.trail.js.map +1 -0
- package/dist/trails/missing-reconcile.trail.d.ts +24 -0
- package/dist/trails/missing-reconcile.trail.d.ts.map +1 -0
- package/dist/trails/missing-reconcile.trail.js +33 -0
- package/dist/trails/missing-reconcile.trail.js.map +1 -0
- package/dist/trails/missing-visibility.trail.d.ts +24 -0
- package/dist/trails/missing-visibility.trail.d.ts.map +1 -0
- package/dist/trails/missing-visibility.trail.js +22 -0
- package/dist/trails/missing-visibility.trail.js.map +1 -0
- package/dist/trails/no-direct-impl-in-route.trail.d.ts +2 -2
- package/dist/trails/no-direct-impl-in-route.trail.d.ts.map +1 -1
- package/dist/trails/no-direct-implementation-call.trail.d.ts +2 -2
- package/dist/trails/no-direct-implementation-call.trail.d.ts.map +1 -1
- package/dist/trails/no-sync-result-assumption.trail.d.ts +2 -2
- package/dist/trails/no-sync-result-assumption.trail.d.ts.map +1 -1
- package/dist/trails/no-throw-in-detour-recover.trail.d.ts +13 -0
- package/dist/trails/no-throw-in-detour-recover.trail.d.ts.map +1 -0
- package/dist/trails/no-throw-in-detour-recover.trail.js +24 -0
- package/dist/trails/no-throw-in-detour-recover.trail.js.map +1 -0
- package/dist/trails/no-throw-in-detour-target.trail.d.ts +13 -3
- package/dist/trails/no-throw-in-detour-target.trail.d.ts.map +1 -1
- package/dist/trails/no-throw-in-implementation.trail.d.ts +2 -2
- package/dist/trails/no-throw-in-implementation.trail.d.ts.map +1 -1
- package/dist/trails/on-references-exist.trail.d.ts +24 -0
- package/dist/trails/on-references-exist.trail.d.ts.map +1 -0
- package/dist/trails/on-references-exist.trail.js +21 -0
- package/dist/trails/on-references-exist.trail.js.map +1 -0
- package/dist/trails/orphaned-signal.trail.d.ts +24 -0
- package/dist/trails/orphaned-signal.trail.d.ts.map +1 -0
- package/dist/trails/orphaned-signal.trail.js +36 -0
- package/dist/trails/orphaned-signal.trail.js.map +1 -0
- package/dist/trails/permit-governance.trail.d.ts +12 -0
- package/dist/trails/permit-governance.trail.d.ts.map +1 -0
- package/dist/trails/permit-governance.trail.js +47 -0
- package/dist/trails/permit-governance.trail.js.map +1 -0
- package/dist/trails/prefer-schema-inference.trail.d.ts +2 -2
- package/dist/trails/prefer-schema-inference.trail.d.ts.map +1 -1
- package/dist/trails/reference-exists.trail.d.ts +24 -0
- package/dist/trails/reference-exists.trail.d.ts.map +1 -0
- package/dist/trails/reference-exists.trail.js +25 -0
- package/dist/trails/reference-exists.trail.js.map +1 -0
- package/dist/trails/resource-declarations.trail.d.ts +13 -0
- package/dist/trails/resource-declarations.trail.d.ts.map +1 -0
- package/dist/trails/{provision-declarations.trail.js → resource-declarations.trail.js} +7 -7
- package/dist/trails/resource-declarations.trail.js.map +1 -0
- package/dist/trails/resource-exists.trail.d.ts +24 -0
- package/dist/trails/resource-exists.trail.d.ts.map +1 -0
- package/dist/trails/{provision-exists.trail.js → resource-exists.trail.js} +8 -8
- package/dist/trails/resource-exists.trail.js.map +1 -0
- package/dist/trails/resource-id-grammar.trail.d.ts +13 -0
- package/dist/trails/resource-id-grammar.trail.d.ts.map +1 -0
- package/dist/trails/resource-id-grammar.trail.js +38 -0
- package/dist/trails/resource-id-grammar.trail.js.map +1 -0
- package/dist/trails/run.d.ts +25 -9
- package/dist/trails/run.d.ts.map +1 -1
- package/dist/trails/run.js +63 -19
- package/dist/trails/run.js.map +1 -1
- package/dist/trails/schema.d.ts +28 -3
- package/dist/trails/schema.d.ts.map +1 -1
- package/dist/trails/schema.js +57 -4
- package/dist/trails/schema.js.map +1 -1
- package/dist/trails/unreachable-detour-shadowing.trail.d.ts +13 -0
- package/dist/trails/unreachable-detour-shadowing.trail.d.ts.map +1 -0
- package/dist/trails/unreachable-detour-shadowing.trail.js +44 -0
- package/dist/trails/unreachable-detour-shadowing.trail.js.map +1 -0
- package/dist/trails/valid-describe-refs.trail.d.ts +12 -3
- package/dist/trails/valid-describe-refs.trail.d.ts.map +1 -1
- package/dist/trails/valid-detour-contract.trail.d.ts +12 -0
- package/dist/trails/valid-detour-contract.trail.d.ts.map +1 -0
- package/dist/trails/valid-detour-contract.trail.js +66 -0
- package/dist/trails/valid-detour-contract.trail.js.map +1 -0
- package/dist/trails/valid-detour-refs.trail.d.ts +13 -3
- package/dist/trails/valid-detour-refs.trail.d.ts.map +1 -1
- package/dist/trails/warden-export-symmetry.trail.d.ts +13 -0
- package/dist/trails/warden-export-symmetry.trail.d.ts.map +1 -0
- package/dist/trails/warden-export-symmetry.trail.js +16 -0
- package/dist/trails/warden-export-symmetry.trail.js.map +1 -0
- package/dist/trails/warden-rules-use-ast.trail.d.ts +13 -0
- package/dist/trails/warden-rules-use-ast.trail.d.ts.map +1 -0
- package/dist/trails/warden-rules-use-ast.trail.js +41 -0
- package/dist/trails/warden-rules-use-ast.trail.js.map +1 -0
- package/dist/trails/wrap-rule.d.ts +16 -2
- package/dist/trails/wrap-rule.d.ts.map +1 -1
- package/dist/trails/wrap-rule.js +71 -11
- package/dist/trails/wrap-rule.js.map +1 -1
- package/package.json +7 -4
- package/src/__tests__/ast.test.ts +613 -0
- package/src/__tests__/circular-refs.test.ts +121 -0
- package/src/__tests__/cli.test.ts +360 -32
- package/src/__tests__/contour-exists.test.ts +203 -0
- package/src/__tests__/cross-declarations.test.ts +245 -0
- package/src/__tests__/dead-internal-trail.test.ts +81 -0
- package/src/__tests__/draft-rules-context.test.ts +150 -0
- package/src/__tests__/drift.test.ts +75 -5
- package/src/__tests__/error-mapping-completeness.test.ts +56 -0
- package/src/__tests__/example-valid.test.ts +101 -0
- package/src/__tests__/fires-declarations-param-destructure.test.ts +54 -0
- package/src/__tests__/fires-declarations.test.ts +652 -0
- package/src/__tests__/formatters.test.ts +2 -2
- package/src/__tests__/implementation-returns-result.test.ts +1016 -2
- package/src/__tests__/incomplete-accessor-for-standard-op.test.ts +337 -0
- package/src/__tests__/incomplete-crud.test.ts +498 -0
- package/src/__tests__/intent-propagation.test.ts +116 -0
- package/src/__tests__/missing-reconcile.test.ts +154 -0
- package/src/__tests__/missing-visibility.test.ts +108 -0
- package/src/__tests__/no-sync-result-assumption.test.ts +870 -39
- package/src/__tests__/no-throw-in-detour-recover.test.ts +93 -0
- package/src/__tests__/no-throw-in-implementation.test.ts +88 -0
- package/src/__tests__/on-references-exist.test.ts +151 -0
- package/src/__tests__/orphaned-signal.test.ts +137 -0
- package/src/__tests__/permit-governance.test.ts +66 -0
- package/src/__tests__/reference-exists.test.ts +281 -0
- package/src/__tests__/resource-declarations.test.ts +448 -0
- package/src/__tests__/resource-exists.test.ts +122 -0
- package/src/__tests__/resource-id-grammar.test.ts +50 -0
- package/src/__tests__/rules.test.ts +17 -77
- package/src/__tests__/topo-aware-rule.test.ts +257 -0
- package/src/__tests__/trails.test.ts +2 -2
- package/src/__tests__/unreachable-detour-shadowing.test.ts +128 -0
- package/src/__tests__/valid-describe-refs.test.ts +183 -0
- package/src/__tests__/valid-detour-contract.test.ts +86 -0
- package/src/__tests__/warden-export-symmetry.test.ts +251 -0
- package/src/__tests__/warden-rules-use-ast.test.ts +468 -0
- package/src/__tests__/wrap-rule.test.ts +3 -3
- package/src/cli.ts +458 -91
- package/src/draft.ts +22 -0
- package/src/drift.ts +63 -21
- package/src/formatters.ts +15 -4
- package/src/index.ts +62 -23
- package/src/rules/ast.ts +2715 -119
- package/src/rules/circular-refs.ts +154 -0
- package/src/rules/{context-no-trailhead-types.ts → context-no-surface-types.ts} +72 -12
- package/src/rules/contour-exists.ts +251 -0
- package/src/rules/contour-ids.ts +15 -0
- package/src/rules/cross-declarations.ts +277 -69
- package/src/rules/dead-internal-trail.ts +141 -0
- package/src/rules/draft-file-marking.ts +160 -0
- package/src/rules/draft-visible-debt.ts +87 -0
- package/src/rules/error-mapping-completeness.ts +273 -0
- package/src/rules/example-valid.ts +401 -0
- package/src/rules/fires-declarations.ts +609 -0
- package/src/rules/implementation-returns-result.ts +1042 -122
- package/src/rules/incomplete-accessor-for-standard-op.ts +315 -0
- package/src/rules/incomplete-crud.ts +579 -0
- package/src/rules/index.ts +95 -16
- package/src/rules/intent-propagation.ts +142 -0
- package/src/rules/missing-reconcile.ts +98 -0
- package/src/rules/missing-visibility.ts +110 -0
- package/src/rules/no-direct-impl-in-route.ts +0 -4
- package/src/rules/no-direct-implementation-call.ts +1 -1
- package/src/rules/no-sync-result-assumption.ts +1134 -96
- package/src/rules/no-throw-in-detour-recover.ts +225 -0
- package/src/rules/no-throw-in-implementation.ts +6 -4
- package/src/rules/on-references-exist.ts +194 -0
- package/src/rules/orphaned-signal.ts +150 -0
- package/src/rules/permit-governance.ts +25 -0
- package/src/rules/reference-exists.ts +98 -0
- package/src/rules/registry-names.ts +83 -0
- package/src/rules/{provision-declarations.ts → resource-declarations.ts} +208 -138
- package/src/rules/{provision-exists.ts → resource-exists.ts} +48 -51
- package/src/rules/resource-id-grammar.ts +65 -0
- package/src/rules/specs.ts +5 -1
- package/src/rules/types.ts +57 -4
- package/src/rules/unreachable-detour-shadowing.ts +375 -0
- package/src/rules/valid-describe-refs.ts +160 -32
- package/src/rules/valid-detour-contract.ts +78 -0
- package/src/rules/warden-export-symmetry.ts +533 -0
- package/src/rules/warden-rules-use-ast.ts +996 -0
- package/src/trails/circular-refs.trail.ts +29 -0
- package/src/trails/{context-no-trailhead-types.trail.ts → context-no-surface-types.trail.ts} +4 -4
- package/src/trails/contour-exists.trail.ts +21 -0
- package/src/trails/dead-internal-trail.trail.ts +26 -0
- package/src/trails/draft-file-marking.trail.ts +16 -0
- package/src/trails/draft-visible-debt.trail.ts +16 -0
- package/src/trails/error-mapping-completeness.trail.ts +29 -0
- package/src/trails/example-valid.trail.ts +25 -0
- package/src/trails/fires-declarations.trail.ts +22 -0
- package/src/trails/incomplete-accessor-for-standard-op.trail.ts +76 -0
- package/src/trails/incomplete-crud.trail.ts +39 -0
- package/src/trails/index.ts +40 -7
- package/src/trails/intent-propagation.trail.ts +30 -0
- package/src/trails/missing-reconcile.trail.ts +33 -0
- package/src/trails/missing-visibility.trail.ts +22 -0
- package/src/trails/no-throw-in-detour-recover.trail.ts +24 -0
- package/src/trails/on-references-exist.trail.ts +21 -0
- package/src/trails/orphaned-signal.trail.ts +36 -0
- package/src/trails/permit-governance.trail.ts +51 -0
- package/src/trails/reference-exists.trail.ts +25 -0
- package/src/trails/{provision-declarations.trail.ts → resource-declarations.trail.ts} +6 -6
- package/src/trails/{provision-exists.trail.ts → resource-exists.trail.ts} +7 -7
- package/src/trails/resource-id-grammar.trail.ts +39 -0
- package/src/trails/run.ts +121 -24
- package/src/trails/schema.ts +66 -4
- package/src/trails/unreachable-detour-shadowing.trail.ts +45 -0
- package/src/trails/valid-detour-contract.trail.ts +71 -0
- package/src/trails/warden-export-symmetry.trail.ts +16 -0
- package/src/trails/warden-rules-use-ast.trail.ts +45 -0
- package/src/trails/wrap-rule.ts +104 -12
- package/tsconfig.tests.json +10 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/rules/follow-declarations.d.ts +0 -13
- package/dist/rules/follow-declarations.d.ts.map +0 -1
- package/dist/rules/follow-declarations.js +0 -264
- package/dist/rules/follow-declarations.js.map +0 -1
- package/dist/rules/provision-declarations.d.ts +0 -14
- package/dist/rules/provision-declarations.d.ts.map +0 -1
- package/dist/rules/provision-declarations.js +0 -344
- package/dist/rules/provision-declarations.js.map +0 -1
- package/dist/rules/provision-exists.d.ts +0 -6
- package/dist/rules/provision-exists.d.ts.map +0 -1
- package/dist/rules/provision-exists.js +0 -89
- package/dist/rules/provision-exists.js.map +0 -1
- package/dist/rules/service-declarations.d.ts +0 -16
- package/dist/rules/service-declarations.d.ts.map +0 -1
- package/dist/rules/service-declarations.js +0 -346
- package/dist/rules/service-declarations.js.map +0 -1
- package/dist/rules/service-exists.d.ts +0 -8
- package/dist/rules/service-exists.d.ts.map +0 -1
- package/dist/rules/service-exists.js +0 -91
- package/dist/rules/service-exists.js.map +0 -1
- package/dist/trails/follow-declarations.trail.d.ts.map +0 -1
- package/dist/trails/follow-declarations.trail.js +0 -22
- package/dist/trails/follow-declarations.trail.js.map +0 -1
- package/dist/trails/provision-declarations.trail.d.ts.map +0 -1
- package/dist/trails/provision-declarations.trail.js.map +0 -1
- package/dist/trails/provision-exists.trail.d.ts +0 -15
- package/dist/trails/provision-exists.trail.d.ts.map +0 -1
- package/dist/trails/provision-exists.trail.js.map +0 -1
- package/dist/trails/service-declarations.trail.d.ts +0 -26
- package/dist/trails/service-declarations.trail.d.ts.map +0 -1
- package/dist/trails/service-declarations.trail.js +0 -27
- package/dist/trails/service-declarations.trail.js.map +0 -1
- package/dist/trails/service-exists.trail.d.ts +0 -32
- package/dist/trails/service-exists.trail.d.ts.map +0 -1
- package/dist/trails/service-exists.trail.js +0 -29
- package/dist/trails/service-exists.trail.js.map +0 -1
- package/src/__tests__/no-throw-in-detour-target.test.ts +0 -78
- package/src/__tests__/provision-declarations.test.ts +0 -318
- package/src/__tests__/provision-exists.test.ts +0 -122
- package/src/rules/no-throw-in-detour-target.ts +0 -150
- package/src/rules/valid-detour-refs.ts +0 -187
- package/src/trails/no-throw-in-detour-target.trail.ts +0 -20
- package/src/trails/valid-detour-refs.trail.ts +0 -24
package/.turbo/turbo-lint.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @ontrails/warden
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.15
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4ad6b25: Lexicon rename cleanup (ADR-0023). Breaking for `@ontrails/core`, `@ontrails/cli`, and `@ontrails/tracing` at the boundary; internal-only churn for `@ontrails/warden`.
|
|
8
|
+
|
|
9
|
+
- **core**: the topo store schema renames `topo_provisions` / `topo_trail_provisions` → `topo_resources` / `topo_trail_resources` and `provision_count` → `resource_count`. Schema version bumped v4→v5. Stores still carrying the legacy schema are detected on open, dropped, and recreated from the new DDL — previous topo saves are cleared. Stored-data helpers `listTopoStoreProvisions` / `getTopoStoreProvision` / `readProvisionUsage` / `mapProvisionRow` renamed to their `resource` counterparts. TS row types `TopoTrailProvisionRow` / `TopoProvisionRow` renamed to `TopoTrailResourceRow` / `TopoResourceRow`.
|
|
10
|
+
- **cli**: CLI output mode env vars are now derived from the topo name per ADR-0023. Legacy globals `TRAILS_JSON` / `TRAILS_JSONL` are no longer honored — a topo named `stash` reads `STASH_JSON` / `STASH_JSONL`. `ActionResultContext` gains a `topoName: string` field; `resolveOutputMode(flags, topoName)` takes a topo name argument.
|
|
11
|
+
- **tracing**: legacy `.trails/dev/tracker.db` migration path removed. Any user still running a pre-rename beta build with a `tracker.db` should delete it or migrate before upgrading.
|
|
12
|
+
- **warden**: internal-only rename of `provisionDeclarations` / `provisionExists` rules and their trails to `resourceDeclarations` / `resourceExists`. No behavior change.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [4ad6b25]
|
|
17
|
+
- @ontrails/core@1.0.0-beta.15
|
|
18
|
+
- @ontrails/permits@1.0.0-beta.15
|
|
19
|
+
- @ontrails/schema@1.0.0-beta.15
|
|
20
|
+
|
|
21
|
+
## 1.0.0-beta.14
|
|
22
|
+
|
|
23
|
+
### Minor Changes
|
|
24
|
+
|
|
25
|
+
- 69057e9: Add hierarchical CLI command trees and structured input, enforce established-only topo exports across trailheads, move developer topo and tracker state onto shared `trails.db` with pins and maintenance flows, and ship schema-derived stores through `@ontrails/store` and its Drizzle runtime.
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [69057e9]
|
|
30
|
+
- @ontrails/core@1.0.0-beta.14
|
|
31
|
+
- @ontrails/schema@1.0.0-beta.14
|
|
32
|
+
|
|
3
33
|
## 1.0.0-beta.13
|
|
4
34
|
|
|
5
35
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @ontrails/warden
|
|
2
2
|
|
|
3
|
-
AST-based code convention rules for Trails.
|
|
3
|
+
AST-based code convention rules for Trails. Built-in lint rules catch contract violations at development time, alongside lock drift detection and CI formatters.
|
|
4
4
|
|
|
5
|
-
Structural checks (cross target existence, declared
|
|
5
|
+
Structural checks (cross target existence, declared resource existence, recursive crossing, example schema validation) live in `validateTopo()` from `@ontrails/core`. Warden handles the code-level rules that need AST analysis.
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@ Or programmatically:
|
|
|
20
20
|
```typescript
|
|
21
21
|
import { runWarden, formatWardenReport } from '@ontrails/warden';
|
|
22
22
|
|
|
23
|
-
const report = await runWarden(
|
|
23
|
+
const report = await runWarden({ topo: graph });
|
|
24
24
|
console.log(formatWardenReport(report));
|
|
25
25
|
```
|
|
26
26
|
|
|
@@ -30,17 +30,20 @@ console.log(formatWardenReport(report));
|
|
|
30
30
|
| --- | --- | --- |
|
|
31
31
|
| `no-throw-in-implementation` | error | `throw` inside blaze bodies |
|
|
32
32
|
| `implementation-returns-result` | error | Blaze functions returning raw values instead of `Result` |
|
|
33
|
-
| `context-no-
|
|
34
|
-
| `no-sync-result-assumption` | error | Missing `await` on `.
|
|
35
|
-
| `valid-detour-
|
|
36
|
-
| `no-throw-in-detour-
|
|
37
|
-
| `
|
|
38
|
-
| `no-direct-
|
|
33
|
+
| `context-no-surface-types` | error | Surface type imports (`Request`, `McpSession`) in trail files |
|
|
34
|
+
| `no-sync-result-assumption` | error | Missing `await` on `.blaze()` results |
|
|
35
|
+
| `valid-detour-contract` | error | Detours with non-constructor `on` values or non-callable `recover` values |
|
|
36
|
+
| `no-throw-in-detour-recover` | error | `throw` inside detour `recover` functions |
|
|
37
|
+
| `unreachable-detour-shadowing` | error | Later detours made unreachable by earlier same-or-broader `on:` error types |
|
|
38
|
+
| `no-direct-implementation-call` | warn | Direct `.blaze()` calls bypassing `ctx.cross()` |
|
|
39
|
+
| `no-direct-impl-in-route` | warn | Direct `.blaze()` calls inside trail bodies with `crosses` |
|
|
39
40
|
| `prefer-schema-inference` | warn | Redundant field overrides already derivable from the schema |
|
|
40
41
|
| `cross-declarations` | error/warn | `ctx.cross()` calls that drift from declared `crosses: [...]` |
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
42
|
+
| `resource-declarations` | error/warn | `resource.from(ctx)` / `ctx.resource()` usage that drifts from declared `resources: [...]` |
|
|
43
|
+
| `resource-exists` | error | Declared or referenced resource IDs that do not resolve in project context |
|
|
43
44
|
| `valid-describe-refs` | warn | `@see` refs in `.describe()` that do not resolve |
|
|
45
|
+
| `draft-file-marking` | error | Draft-bearing files missing `_draft.*` or `*.draft.*` filename markers |
|
|
46
|
+
| `draft-visible-debt` | warn | Draft IDs remaining in source files that need promotion or removal |
|
|
44
47
|
|
|
45
48
|
## Drift detection
|
|
46
49
|
|
|
@@ -49,9 +52,9 @@ Warden integrates with `@ontrails/schema` to detect when the topo has changed wi
|
|
|
49
52
|
```typescript
|
|
50
53
|
import { checkDrift } from '@ontrails/warden';
|
|
51
54
|
|
|
52
|
-
const drift = await checkDrift(
|
|
55
|
+
const drift = await checkDrift(process.cwd(), graph);
|
|
53
56
|
if (drift.stale) {
|
|
54
|
-
console.log('lock file is stale -- regenerate with `trails
|
|
57
|
+
console.log('lock file is stale -- regenerate with `trails topo export`');
|
|
55
58
|
}
|
|
56
59
|
```
|
|
57
60
|
|
|
@@ -63,7 +66,7 @@ Add to lefthook for pre-push enforcement:
|
|
|
63
66
|
pre-push:
|
|
64
67
|
commands:
|
|
65
68
|
warden:
|
|
66
|
-
|
|
69
|
+
run: trails warden --exit-code
|
|
67
70
|
tags: governance
|
|
68
71
|
```
|
|
69
72
|
|
|
@@ -75,10 +78,14 @@ import { formatGitHubAnnotations, formatJson, formatSummary } from '@ontrails/wa
|
|
|
75
78
|
|
|
76
79
|
## Trail-based API
|
|
77
80
|
|
|
78
|
-
Every built-in warden rule is also available as a composable trail. This makes rules queryable, testable, and invocable through any Trails
|
|
81
|
+
Every built-in warden rule is also available as a composable trail. This makes rules queryable, testable, and invocable through any Trails surface.
|
|
79
82
|
|
|
80
83
|
```typescript
|
|
81
|
-
import {
|
|
84
|
+
import {
|
|
85
|
+
runTopoAwareWardenTrails,
|
|
86
|
+
runWardenTrails,
|
|
87
|
+
wardenTopo,
|
|
88
|
+
} from '@ontrails/warden';
|
|
82
89
|
|
|
83
90
|
// Inspect the warden rule trails
|
|
84
91
|
console.log(wardenTopo.ids()); // ['warden.rule.no-throw-in-implementation', ...]
|
|
@@ -86,8 +93,11 @@ console.log(wardenTopo.ids()); // ['warden.rule.no-throw-in-implementation', ...
|
|
|
86
93
|
// Run all rule trails against a source file
|
|
87
94
|
const diagnostics = await runWardenTrails(filePath, sourceCode, {
|
|
88
95
|
knownTrailIds: myApp.ids(),
|
|
89
|
-
|
|
96
|
+
knownResourceIds: myApp.resourceIds(),
|
|
90
97
|
});
|
|
98
|
+
|
|
99
|
+
// Run built-in topo-aware rule trails once against the resolved graph
|
|
100
|
+
const topoDiagnostics = await runTopoAwareWardenTrails(myApp);
|
|
91
101
|
```
|
|
92
102
|
|
|
93
103
|
To wrap a custom rule as a trail, use `wrapRule` (imported from `@ontrails/warden/trails/wrap-rule`). This is the same factory used internally to build all built-in rule trails.
|
|
@@ -96,12 +106,13 @@ To wrap a custom rule as a trail, use `wrapRule` (imported from `@ontrails/warde
|
|
|
96
106
|
|
|
97
107
|
| Export | What it does |
|
|
98
108
|
| --- | --- |
|
|
99
|
-
| `runWarden(
|
|
109
|
+
| `runWarden(options?)` | Run all rules and drift checks, return a report |
|
|
100
110
|
| `formatWardenReport(report)` | Human-readable report |
|
|
101
|
-
| `checkDrift(
|
|
111
|
+
| `checkDrift(rootDir, topo?)` | Check if the lock file matches the current topo |
|
|
102
112
|
| `wardenRules` | Registry of all built-in rules |
|
|
103
113
|
| `wardenTopo` | `Topo` of all built-in rule trails (one per rule) |
|
|
104
|
-
| `runWardenTrails(filePath, sourceCode, options?)` | Dispatch
|
|
114
|
+
| `runWardenTrails(filePath, sourceCode, options?)` | Dispatch file-scoped rule trails for a file, collect diagnostics |
|
|
115
|
+
| `runTopoAwareWardenTrails(topo)` | Dispatch built-in topo-aware rule trails once for a resolved topo |
|
|
105
116
|
| `formatGitHubAnnotations(report)` | GitHub Actions annotation format |
|
|
106
117
|
| `formatJson(report)` | Machine-readable JSON |
|
|
107
118
|
| `formatSummary(report)` | Compact summary line |
|
package/dist/cli.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { Topo } from '@ontrails/core';
|
|
8
8
|
import type { DriftResult } from './drift.js';
|
|
9
|
-
import type { WardenDiagnostic } from './rules/types.js';
|
|
9
|
+
import type { TopoAwareWardenRule, WardenDiagnostic } from './rules/types.js';
|
|
10
10
|
/**
|
|
11
11
|
* Options for the warden CLI runner.
|
|
12
12
|
*/
|
|
@@ -17,8 +17,25 @@ export interface WardenOptions {
|
|
|
17
17
|
readonly lintOnly?: boolean | undefined;
|
|
18
18
|
/** Only run drift detection, skip lint rules */
|
|
19
19
|
readonly driftOnly?: boolean | undefined;
|
|
20
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* App topology for drift detection. When provided, enables real trailhead
|
|
22
|
+
* lock comparison and unlocks the topo-aware rule dispatch path.
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* Topo-aware rules (both built-in `wardenTopoRules` and `extraTopoRules`)
|
|
26
|
+
* only fire when a `Topo` is supplied. Runs without a topo silently skip
|
|
27
|
+
* topo-aware dispatch — callers that depend on a topo-aware rule firing
|
|
28
|
+
* must pass `topo` explicitly.
|
|
29
|
+
*/
|
|
21
30
|
readonly topo?: Topo | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Extra topo-aware rules to run in addition to the built-in registry.
|
|
33
|
+
*
|
|
34
|
+
* Primarily a test hook — production callers should register rules via
|
|
35
|
+
* `wardenTopoRules` in `rules/index.ts`. These rules are only invoked
|
|
36
|
+
* when `topo` is also supplied (see `topo` remarks).
|
|
37
|
+
*/
|
|
38
|
+
readonly extraTopoRules?: readonly TopoAwareWardenRule[] | undefined;
|
|
22
39
|
}
|
|
23
40
|
/**
|
|
24
41
|
* Result of a warden run.
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiB9C,OAAO,KAAK,EAGV,mBAAmB,EACnB,gBAAgB,EAEjB,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,mBAAmB,EAAE,GAAG,SAAS,CAAC;CACtE;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAClD,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAqiBD;;GAEG;AACH,eAAO,MAAM,SAAS,GACpB,UAAS,aAAkB,KAC1B,OAAO,CAAC,YAAY,CAwBtB,CAAC;AA2DF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,YAAY,KAAG,MAmBzD,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
* and returns a structured report.
|
|
6
6
|
*/
|
|
7
7
|
import { resolve } from 'node:path';
|
|
8
|
+
import { getContourReferences } from '@ontrails/core';
|
|
8
9
|
import { checkDrift } from './drift.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
10
|
+
import { collectContourDefinitionIds, collectContourReferenceTargetsByName, collectCrudTableIds as collectCrudTableIdsFromAst, collectCrossTargetTrailIds, collectOnTargetSignalIds as collectOnTargetSignalIdsFromAst, collectReconcileTableIds as collectReconcileTableIdsFromAst, collectResourceDefinitionIds, collectSignalDefinitionIds, collectTrailIntentsById, findTrailDefinitions, parse, } from './rules/ast.js';
|
|
11
|
+
import { collectFileCrudCoverage } from './rules/incomplete-crud.js';
|
|
12
|
+
import { wardenRules, wardenTopoRules } from './rules/index.js';
|
|
11
13
|
/**
|
|
12
14
|
* Collect all .ts files under a directory, excluding node_modules, dist, and .git.
|
|
13
15
|
*/
|
|
@@ -36,6 +38,68 @@ const collectTsFiles = (dir) => {
|
|
|
36
38
|
}
|
|
37
39
|
return files;
|
|
38
40
|
};
|
|
41
|
+
const createMutableProjectContext = () => ({
|
|
42
|
+
contourReferencesByName: new Map(),
|
|
43
|
+
crossTargetTrailIds: new Set(),
|
|
44
|
+
crudCoverageByEntity: new Map(),
|
|
45
|
+
crudTableIds: new Set(),
|
|
46
|
+
knownContourIds: new Set(),
|
|
47
|
+
knownResourceIds: new Set(),
|
|
48
|
+
knownSignalIds: new Set(),
|
|
49
|
+
knownTrailIds: new Set(),
|
|
50
|
+
onTargetSignalIds: new Set(),
|
|
51
|
+
reconcileTableIds: new Set(),
|
|
52
|
+
trailIntentsById: new Map(),
|
|
53
|
+
});
|
|
54
|
+
const addContourReferenceTargets = (context, contourName, targets) => {
|
|
55
|
+
const existing = context.contourReferencesByName.get(contourName);
|
|
56
|
+
if (existing) {
|
|
57
|
+
for (const target of targets) {
|
|
58
|
+
existing.add(target);
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
context.contourReferencesByName.set(contourName, new Set(targets));
|
|
63
|
+
};
|
|
64
|
+
const toProjectContext = (context) => ({
|
|
65
|
+
...(context.contourReferencesByName.size > 0
|
|
66
|
+
? {
|
|
67
|
+
contourReferencesByName: new Map([...context.contourReferencesByName.entries()].map(([name, targets]) => [name, [...targets]])),
|
|
68
|
+
}
|
|
69
|
+
: {}),
|
|
70
|
+
...(context.crudTableIds.size > 0
|
|
71
|
+
? { crudTableIds: context.crudTableIds }
|
|
72
|
+
: {}),
|
|
73
|
+
...(context.crudCoverageByEntity.size > 0
|
|
74
|
+
? {
|
|
75
|
+
crudCoverageByEntity: new Map([...context.crudCoverageByEntity.entries()].map(([entityId, operations]) => [
|
|
76
|
+
entityId,
|
|
77
|
+
new Set(operations),
|
|
78
|
+
])),
|
|
79
|
+
}
|
|
80
|
+
: {}),
|
|
81
|
+
crossTargetTrailIds: context.crossTargetTrailIds,
|
|
82
|
+
knownContourIds: context.knownContourIds,
|
|
83
|
+
knownResourceIds: context.knownResourceIds,
|
|
84
|
+
knownSignalIds: context.knownSignalIds,
|
|
85
|
+
knownTrailIds: context.knownTrailIds,
|
|
86
|
+
...(context.onTargetSignalIds.size > 0
|
|
87
|
+
? { onTargetSignalIds: context.onTargetSignalIds }
|
|
88
|
+
: {}),
|
|
89
|
+
...(context.reconcileTableIds.size > 0
|
|
90
|
+
? { reconcileTableIds: context.reconcileTableIds }
|
|
91
|
+
: {}),
|
|
92
|
+
trailIntentsById: context.trailIntentsById,
|
|
93
|
+
});
|
|
94
|
+
const collectKnownContourIds = (sourceCode, filePath, knownContourIds) => {
|
|
95
|
+
const ast = parse(filePath, sourceCode);
|
|
96
|
+
if (!ast) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
for (const id of collectContourDefinitionIds(ast)) {
|
|
100
|
+
knownContourIds.add(id);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
39
103
|
const collectKnownTrailIds = (sourceCode, filePath, knownTrailIds) => {
|
|
40
104
|
const ast = parse(filePath, sourceCode);
|
|
41
105
|
if (!ast) {
|
|
@@ -45,35 +109,80 @@ const collectKnownTrailIds = (sourceCode, filePath, knownTrailIds) => {
|
|
|
45
109
|
knownTrailIds.add(def.id);
|
|
46
110
|
}
|
|
47
111
|
};
|
|
48
|
-
const
|
|
112
|
+
const collectCrossedTrailIds = (sourceCode, filePath, crossTargetTrailIds) => {
|
|
49
113
|
const ast = parse(filePath, sourceCode);
|
|
50
114
|
if (!ast) {
|
|
51
115
|
return;
|
|
52
116
|
}
|
|
53
|
-
for (const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
117
|
+
for (const id of collectCrossTargetTrailIds(ast, sourceCode)) {
|
|
118
|
+
crossTargetTrailIds.add(id);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const collectKnownResourceIds = (sourceCode, filePath, knownResourceIds) => {
|
|
122
|
+
const ast = parse(filePath, sourceCode);
|
|
123
|
+
if (!ast) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
for (const id of collectResourceDefinitionIds(ast)) {
|
|
127
|
+
knownResourceIds.add(id);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const collectKnownSignalIds = (sourceCode, filePath, knownSignalIds) => {
|
|
131
|
+
const ast = parse(filePath, sourceCode);
|
|
132
|
+
if (!ast) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
for (const id of collectSignalDefinitionIds(ast)) {
|
|
136
|
+
knownSignalIds.add(id);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
const collectTrailIntents = (sourceCode, filePath, trailIntentsById) => {
|
|
140
|
+
const ast = parse(filePath, sourceCode);
|
|
141
|
+
if (!ast) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
for (const [id, intent] of collectTrailIntentsById(ast)) {
|
|
145
|
+
trailIntentsById.set(id, intent);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const collectCrudTableIds = (sourceCode, filePath, crudTableIds) => {
|
|
149
|
+
const ast = parse(filePath, sourceCode);
|
|
150
|
+
if (!ast) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
for (const id of collectCrudTableIdsFromAst(ast)) {
|
|
154
|
+
crudTableIds.add(id);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const collectOnTargetSignalIds = (sourceCode, filePath, onTargetSignalIds) => {
|
|
158
|
+
const ast = parse(filePath, sourceCode);
|
|
159
|
+
if (!ast) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
for (const id of collectOnTargetSignalIdsFromAst(ast, sourceCode)) {
|
|
163
|
+
onTargetSignalIds.add(id);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const collectCrudCoverageByEntity = (sourceCode, filePath, coverageByEntity) => {
|
|
167
|
+
const ast = parse(filePath, sourceCode);
|
|
168
|
+
if (!ast) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
for (const [entityId, operations] of collectFileCrudCoverage(ast, sourceCode)) {
|
|
172
|
+
const bucket = coverageByEntity.get(entityId) ?? new Set();
|
|
173
|
+
for (const operation of operations) {
|
|
174
|
+
bucket.add(operation);
|
|
57
175
|
}
|
|
58
|
-
|
|
59
|
-
walk(detoursProp, (node) => {
|
|
60
|
-
if (node.type !== 'Literal') {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const val = node.value;
|
|
64
|
-
if (val && val.includes('.')) {
|
|
65
|
-
detourTargetTrailIds.add(val);
|
|
66
|
-
}
|
|
67
|
-
});
|
|
176
|
+
coverageByEntity.set(entityId, bucket);
|
|
68
177
|
}
|
|
69
178
|
};
|
|
70
|
-
const
|
|
179
|
+
const collectReconcileTableIds = (sourceCode, filePath, reconcileTableIds) => {
|
|
71
180
|
const ast = parse(filePath, sourceCode);
|
|
72
181
|
if (!ast) {
|
|
73
182
|
return;
|
|
74
183
|
}
|
|
75
|
-
for (const id of
|
|
76
|
-
|
|
184
|
+
for (const id of collectReconcileTableIdsFromAst(ast)) {
|
|
185
|
+
reconcileTableIds.add(id);
|
|
77
186
|
}
|
|
78
187
|
};
|
|
79
188
|
const loadSourceFiles = async (rootDir) => {
|
|
@@ -91,65 +200,145 @@ const loadSourceFiles = async (rootDir) => {
|
|
|
91
200
|
}
|
|
92
201
|
return sourceFiles;
|
|
93
202
|
};
|
|
94
|
-
const
|
|
95
|
-
const
|
|
203
|
+
const collectTopoKnownIds = (appTopo, context) => {
|
|
204
|
+
for (const name of appTopo.contours.keys()) {
|
|
205
|
+
context.knownContourIds.add(name);
|
|
206
|
+
}
|
|
207
|
+
for (const id of appTopo.trails.keys()) {
|
|
208
|
+
context.knownTrailIds.add(id);
|
|
209
|
+
}
|
|
210
|
+
for (const id of appTopo.resources.keys()) {
|
|
211
|
+
context.knownResourceIds.add(id);
|
|
212
|
+
}
|
|
213
|
+
for (const id of appTopo.signals.keys()) {
|
|
214
|
+
context.knownSignalIds.add(id);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
const collectTopoCrossesAndIntents = (appTopo, context) => {
|
|
96
218
|
for (const trail of appTopo.trails.values()) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
for (const targets of Object.values(detours)) {
|
|
102
|
-
for (const id of targets) {
|
|
103
|
-
detourTargetTrailIds.add(id);
|
|
104
|
-
}
|
|
219
|
+
context.trailIntentsById.set(trail.id, trail.intent);
|
|
220
|
+
for (const crossedTrailId of trail.crosses) {
|
|
221
|
+
context.crossTargetTrailIds.add(crossedTrailId);
|
|
105
222
|
}
|
|
106
223
|
}
|
|
107
|
-
return detourTargetTrailIds;
|
|
108
224
|
};
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
225
|
+
const collectTopoContourReferences = (appTopo, context) => {
|
|
226
|
+
for (const contour of appTopo.listContours()) {
|
|
227
|
+
addContourReferenceTargets(context, contour.name, getContourReferences(contour).map((reference) => reference.contour));
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
const collectTopoTrailContext = (appTopo, context) => {
|
|
231
|
+
collectTopoKnownIds(appTopo, context);
|
|
232
|
+
collectTopoCrossesAndIntents(appTopo, context);
|
|
233
|
+
collectTopoContourReferences(appTopo, context);
|
|
234
|
+
};
|
|
235
|
+
const collectFileKnownIds = (sourceFile, context) => {
|
|
236
|
+
collectKnownContourIds(sourceFile.sourceCode, sourceFile.filePath, context.knownContourIds);
|
|
237
|
+
collectKnownTrailIds(sourceFile.sourceCode, sourceFile.filePath, context.knownTrailIds);
|
|
238
|
+
collectKnownResourceIds(sourceFile.sourceCode, sourceFile.filePath, context.knownResourceIds);
|
|
239
|
+
collectKnownSignalIds(sourceFile.sourceCode, sourceFile.filePath, context.knownSignalIds);
|
|
240
|
+
};
|
|
241
|
+
const collectFileTrailRelationships = (sourceFile, context) => {
|
|
242
|
+
collectCrossedTrailIds(sourceFile.sourceCode, sourceFile.filePath, context.crossTargetTrailIds);
|
|
243
|
+
collectTrailIntents(sourceFile.sourceCode, sourceFile.filePath, context.trailIntentsById);
|
|
244
|
+
};
|
|
245
|
+
const collectFileSupplementalProjectContext = (sourceFile, context) => {
|
|
246
|
+
collectCrudTableIds(sourceFile.sourceCode, sourceFile.filePath, context.crudTableIds);
|
|
247
|
+
collectOnTargetSignalIds(sourceFile.sourceCode, sourceFile.filePath, context.onTargetSignalIds);
|
|
248
|
+
collectReconcileTableIds(sourceFile.sourceCode, sourceFile.filePath, context.reconcileTableIds);
|
|
249
|
+
collectCrudCoverageByEntity(sourceFile.sourceCode, sourceFile.filePath, context.crudCoverageByEntity);
|
|
250
|
+
};
|
|
251
|
+
const collectFileProjectContext = (sourceFile, context) => {
|
|
252
|
+
collectFileKnownIds(sourceFile, context);
|
|
253
|
+
collectFileTrailRelationships(sourceFile, context);
|
|
254
|
+
collectFileSupplementalProjectContext(sourceFile, context);
|
|
118
255
|
};
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
256
|
+
const collectFileContourReferences = (sourceFile, context) => {
|
|
257
|
+
const ast = parse(sourceFile.filePath, sourceFile.sourceCode);
|
|
258
|
+
if (!ast) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const referencesByName = collectContourReferenceTargetsByName(ast, context.knownContourIds);
|
|
262
|
+
for (const [contourName, targets] of referencesByName) {
|
|
263
|
+
addContourReferenceTargets(context, contourName, targets);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
const buildProjectContext = (sourceFiles, appTopo) => {
|
|
267
|
+
const context = createMutableProjectContext();
|
|
268
|
+
if (appTopo) {
|
|
269
|
+
collectTopoTrailContext(appTopo, context);
|
|
270
|
+
for (const sourceFile of sourceFiles) {
|
|
271
|
+
collectFileSupplementalProjectContext(sourceFile, context);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
for (const sourceFile of sourceFiles) {
|
|
276
|
+
collectFileProjectContext(sourceFile, context);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
123
279
|
for (const sourceFile of sourceFiles) {
|
|
124
|
-
|
|
125
|
-
collectKnownProvisionIds(sourceFile.sourceCode, sourceFile.filePath, knownProvisionIds);
|
|
126
|
-
collectDetourTargetTrailIds(sourceFile.sourceCode, sourceFile.filePath, detourTargetTrailIds);
|
|
280
|
+
collectFileContourReferences(sourceFile, context);
|
|
127
281
|
}
|
|
282
|
+
return toProjectContext(context);
|
|
283
|
+
};
|
|
284
|
+
const isProjectAwareRule = (rule) => 'checkWithContext' in rule;
|
|
285
|
+
const topoRuleFailureDiagnostic = (rule, error) => {
|
|
286
|
+
const cause = error instanceof Error ? error : new Error(String(error));
|
|
128
287
|
return {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
288
|
+
filePath: '<topo>',
|
|
289
|
+
line: 1,
|
|
290
|
+
message: `Topo-aware rule "${rule.name}" threw: ${cause.message}`,
|
|
291
|
+
rule: rule.name,
|
|
292
|
+
severity: 'error',
|
|
132
293
|
};
|
|
133
294
|
};
|
|
134
|
-
const isProjectAwareRule = (rule) => 'checkWithContext' in rule;
|
|
135
295
|
/**
|
|
136
|
-
*
|
|
296
|
+
* Run all registered topo-aware rules against the resolved topo.
|
|
297
|
+
*
|
|
298
|
+
* Topo-aware rules fire exactly once per run (not per file) because they
|
|
299
|
+
* inspect the compiled trail graph, not source text.
|
|
137
300
|
*/
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
301
|
+
const lintTopo = async (appTopo, extraTopoRules) => {
|
|
302
|
+
const diagnostics = [];
|
|
303
|
+
const rules = [
|
|
304
|
+
...wardenTopoRules.values(),
|
|
305
|
+
...extraTopoRules,
|
|
306
|
+
];
|
|
307
|
+
for (const rule of rules) {
|
|
308
|
+
try {
|
|
309
|
+
diagnostics.push(...(await rule.checkTopo(appTopo)));
|
|
310
|
+
}
|
|
311
|
+
catch (error) {
|
|
312
|
+
diagnostics.push(topoRuleFailureDiagnostic(rule, error));
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return diagnostics;
|
|
316
|
+
};
|
|
317
|
+
const lintSourceFiles = (sourceFiles, context) => {
|
|
318
|
+
const diagnostics = [];
|
|
144
319
|
for (const sourceFile of sourceFiles) {
|
|
145
320
|
for (const rule of wardenRules.values()) {
|
|
146
321
|
if (isProjectAwareRule(rule)) {
|
|
147
|
-
|
|
322
|
+
diagnostics.push(...rule.checkWithContext(sourceFile.sourceCode, sourceFile.filePath, context));
|
|
148
323
|
continue;
|
|
149
324
|
}
|
|
150
|
-
|
|
325
|
+
diagnostics.push(...rule.check(sourceFile.sourceCode, sourceFile.filePath));
|
|
151
326
|
}
|
|
152
327
|
}
|
|
328
|
+
return diagnostics;
|
|
329
|
+
};
|
|
330
|
+
/**
|
|
331
|
+
* Lint all files against all warden rules.
|
|
332
|
+
*/
|
|
333
|
+
const lintFiles = async (rootDir, appTopo, extraTopoRules = []) => {
|
|
334
|
+
const sourceFiles = await loadSourceFiles(rootDir);
|
|
335
|
+
const context = buildProjectContext(sourceFiles, appTopo);
|
|
336
|
+
const allDiagnostics = [
|
|
337
|
+
...lintSourceFiles(sourceFiles, context),
|
|
338
|
+
];
|
|
339
|
+
if (appTopo) {
|
|
340
|
+
allDiagnostics.push(...(await lintTopo(appTopo, extraTopoRules)));
|
|
341
|
+
}
|
|
153
342
|
return allDiagnostics;
|
|
154
343
|
};
|
|
155
344
|
/**
|
|
@@ -159,7 +348,7 @@ export const runWarden = async (options = {}) => {
|
|
|
159
348
|
const rootDir = resolve(options.rootDir ?? process.cwd());
|
|
160
349
|
const allDiagnostics = options.driftOnly
|
|
161
350
|
? []
|
|
162
|
-
: await lintFiles(rootDir, options.topo);
|
|
351
|
+
: await lintFiles(rootDir, options.topo, options.extraTopoRules ?? []);
|
|
163
352
|
const drift = options.lintOnly
|
|
164
353
|
? null
|
|
165
354
|
: await checkDrift(rootDir, options.topo);
|
|
@@ -169,7 +358,9 @@ export const runWarden = async (options = {}) => {
|
|
|
169
358
|
diagnostics: allDiagnostics,
|
|
170
359
|
drift,
|
|
171
360
|
errorCount,
|
|
172
|
-
passed: errorCount === 0 &&
|
|
361
|
+
passed: errorCount === 0 &&
|
|
362
|
+
!(drift?.stale ?? false) &&
|
|
363
|
+
drift?.blockedReason === undefined,
|
|
173
364
|
warnCount,
|
|
174
365
|
};
|
|
175
366
|
};
|
|
@@ -196,8 +387,11 @@ const formatDriftSection = (drift) => {
|
|
|
196
387
|
if (drift === null) {
|
|
197
388
|
return [];
|
|
198
389
|
}
|
|
390
|
+
if (drift.blockedReason !== undefined) {
|
|
391
|
+
return [`Drift: blocked (${drift.blockedReason})`, ''];
|
|
392
|
+
}
|
|
199
393
|
const label = drift.stale
|
|
200
|
-
? 'Drift:
|
|
394
|
+
? 'Drift: trails.lock is stale (regenerate with `trails topo export`)'
|
|
201
395
|
: 'Drift: clean';
|
|
202
396
|
return [label, ''];
|
|
203
397
|
};
|
|
@@ -212,7 +406,10 @@ const formatResultLine = (report) => {
|
|
|
212
406
|
if (report.errorCount > 0) {
|
|
213
407
|
parts.push(`${report.errorCount} errors`);
|
|
214
408
|
}
|
|
215
|
-
if (report.drift?.
|
|
409
|
+
if (report.drift?.blockedReason !== undefined) {
|
|
410
|
+
parts.push('established exports blocked');
|
|
411
|
+
}
|
|
412
|
+
else if (report.drift?.stale) {
|
|
216
413
|
parts.push('drift detected');
|
|
217
414
|
}
|
|
218
415
|
return `Result: FAIL (${parts.join(', ')})`;
|