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

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 (37) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +1 -1
  3. package/package.json +9 -9
  4. package/src/cli.ts +120 -10
  5. package/src/command.ts +25 -5
  6. package/src/drift.ts +116 -7
  7. package/src/fix.ts +8 -2
  8. package/src/formatters.ts +3 -8
  9. package/src/index.ts +30 -2
  10. package/src/project-context.ts +255 -1
  11. package/src/rules/ast.ts +4 -0
  12. package/src/rules/duplicate-exported-symbol.ts +211 -0
  13. package/src/rules/duplicate-public-contract.ts +2 -1
  14. package/src/rules/governed-symbol-residue.ts +131 -0
  15. package/src/rules/index.ts +43 -3
  16. package/src/rules/metadata.ts +105 -11
  17. package/src/rules/no-legacy-cli-alias-export.ts +247 -0
  18. package/src/rules/no-retired-cross-vocabulary.ts +19 -9
  19. package/src/rules/public-export-example-coverage.ts +5 -0
  20. package/src/rules/registry-names.ts +12 -2
  21. package/src/rules/retired-vocabulary.ts +396 -0
  22. package/src/rules/signal-graph-coaching.ts +32 -3
  23. package/src/rules/surface-overlay-coherence.ts +262 -0
  24. package/src/rules/{surface-facet-coherence.ts → surface-trailhead-coherence.ts} +45 -41
  25. package/src/rules/trailhead-override-divergence.ts +356 -0
  26. package/src/rules/types.ts +58 -1
  27. package/src/rules/webhook-route-collision.ts +64 -1
  28. package/src/trails/duplicate-exported-symbol.trail.ts +48 -0
  29. package/src/trails/duplicate-public-contract.trail.ts +1 -1
  30. package/src/trails/governed-symbol-residue.trail.ts +24 -0
  31. package/src/trails/index.ts +6 -1
  32. package/src/trails/no-legacy-cli-alias-export.trail.ts +41 -0
  33. package/src/trails/schema.ts +39 -0
  34. package/src/trails/surface-overlay-coherence.trail.ts +24 -0
  35. package/src/trails/{surface-facet-coherence.trail.ts → surface-trailhead-coherence.trail.ts} +4 -4
  36. package/src/trails/trailhead-override-divergence.trail.ts +47 -0
  37. package/src/trails/wrap-rule.ts +10 -0
@@ -0,0 +1,41 @@
1
+ import { noLegacyCliAliasExport } from '../rules/no-legacy-cli-alias-export.js';
2
+ import { wrapRule } from './wrap-rule.js';
3
+
4
+ export const noLegacyCliAliasExportTrail = wrapRule({
5
+ examples: [
6
+ {
7
+ expected: { diagnostics: [] },
8
+ input: {
9
+ filePath: 'apps/example/src/app.ts',
10
+ sourceCode: `import { surfaceOverlay } from '@ontrails/core';\n\nexport const trailsOverlays = [surfaceOverlay({ cli: { ls: 'gear.list' } })];\n`,
11
+ },
12
+ name: 'App modules binding CLI through trailsOverlays are clean',
13
+ },
14
+ {
15
+ expected: {
16
+ diagnostics: [
17
+ {
18
+ filePath: 'apps/example/src/app.ts',
19
+ fix: {
20
+ class: 'export-restructure',
21
+ reason:
22
+ "Legacy CLI alias export 'trailsCliAliases' must be rewritten into a surfaceOverlay({ cli: { ... } }) entry inside the module's trailsOverlays array export; run the Regrade class export-restructure:cli-aliases (TRL-1210) to automate this restructure.",
23
+ safety: 'review',
24
+ },
25
+ line: 1,
26
+ message:
27
+ "Legacy CLI alias export 'trailsCliAliases' was removed in the TRL-1207 surfaces-overlay cutover. Wrap the alias map into surfaceOverlay({ cli: { ... } }) from @ontrails/core inside the module's trailsOverlays array export.",
28
+ rule: 'no-legacy-cli-alias-export',
29
+ severity: 'error',
30
+ },
31
+ ],
32
+ },
33
+ input: {
34
+ filePath: 'apps/example/src/app.ts',
35
+ sourceCode: `export const trailsCliAliases = { 'gear.ls': [['gear', 'ls']] };\n`,
36
+ },
37
+ name: 'Legacy CLI alias exports produce migration diagnostics',
38
+ },
39
+ ],
40
+ rule: noLegacyCliAliasExport,
41
+ });
@@ -85,13 +85,48 @@ export const publicWorkspaceSchema = z.object({
85
85
  rootDir: z.string(),
86
86
  });
87
87
 
88
+ export const exportedSymbolDefinitionSchema = z.object({
89
+ filePath: z.string(),
90
+ kind: z.enum([
91
+ 'class',
92
+ 'const',
93
+ 'enum',
94
+ 'export',
95
+ 'function',
96
+ 'interface',
97
+ 'type',
98
+ ]),
99
+ line: z.number(),
100
+ name: z.string(),
101
+ workspaceName: z.string(),
102
+ workspaceRoot: z.string(),
103
+ });
104
+
88
105
  /**
89
106
  * Extended input for project-aware warden rule trails.
90
107
  *
91
108
  * Adds `knownTrailIds` so the caller can supply compose-file context and avoid
92
109
  * false positives for `@see` references or compose-file contour relationships.
93
110
  */
111
+ export const authoredMcpSurfaceBindingSetSchema = z.object({
112
+ appName: z.string().describe('App/topo label the bindings were authored for'),
113
+ bindings: z
114
+ .record(z.string(), z.union([z.string(), z.array(z.string()).readonly()]))
115
+ .describe('Surfaces overlay mcp bindings: binding name to selector(s)'),
116
+ trailIds: z
117
+ .array(z.string())
118
+ .readonly()
119
+ .describe('Trail ids registered in the owning app topo'),
120
+ });
121
+
94
122
  export const projectAwareRuleInput = ruleInput.extend({
123
+ authoredMcpSurfaceBindingSets: z
124
+ .array(authoredMcpSurfaceBindingSetSchema)
125
+ .readonly()
126
+ .optional()
127
+ .describe(
128
+ 'Per-app authored surfaces overlay mcp bindings with owning-app trail ids'
129
+ ),
95
130
  composeTargetTrailIds: z
96
131
  .array(z.string())
97
132
  .optional()
@@ -114,6 +149,10 @@ export const projectAwareRuleInput = ruleInput.extend({
114
149
  .record(z.string(), z.array(importResolutionSchema))
115
150
  .optional()
116
151
  .describe('Resolved docs/specifier facts keyed by documentation file path'),
152
+ exportedSymbolDefinitionsByName: z
153
+ .record(z.string(), z.array(exportedSymbolDefinitionSchema))
154
+ .optional()
155
+ .describe('Public exported symbol definitions grouped by exported name'),
117
156
  importResolutionsByFile: z
118
157
  .record(z.string(), z.array(importResolutionSchema))
119
158
  .optional()
@@ -0,0 +1,24 @@
1
+ import { Result, topo, trail } from '@ontrails/core';
2
+ import { z } from 'zod';
3
+
4
+ import { surfaceOverlayCoherence } from '../rules/surface-overlay-coherence.js';
5
+ import { wrapTopoRule } from './wrap-rule.js';
6
+
7
+ const listTrail = trail('gear.list', {
8
+ blaze: () => Result.ok([]),
9
+ input: z.object({}),
10
+ output: z.array(z.string()),
11
+ });
12
+
13
+ export const surfaceOverlayCoherenceTrail = wrapTopoRule({
14
+ examples: [
15
+ {
16
+ expected: { diagnostics: [] },
17
+ input: {
18
+ topo: topo('surface-overlay-coherence', { listTrail }),
19
+ },
20
+ name: 'Topo without a serialized surfaces overlay stays quiet',
21
+ },
22
+ ],
23
+ rule: surfaceOverlayCoherence,
24
+ });
@@ -1,13 +1,13 @@
1
- import { surfaceFacetCoherence } from '../rules/surface-facet-coherence.js';
1
+ import { surfaceTrailheadCoherence } from '../rules/surface-trailhead-coherence.js';
2
2
  import { wrapRule } from './wrap-rule.js';
3
3
 
4
- export const surfaceFacetCoherenceTrail = wrapRule({
4
+ export const surfaceTrailheadCoherenceTrail = wrapRule({
5
5
  examples: [
6
6
  {
7
7
  expected: { diagnostics: [] },
8
8
  input: {
9
9
  filePath: 'mcp-options.ts',
10
- sourceCode: `export const facets = {
10
+ sourceCode: `export const trailheads = {
11
11
  inspect: {
12
12
  description: "Inspect topo state.",
13
13
  trails: ["survey", "survey.brief"],
@@ -21,5 +21,5 @@ export const surfaceFacetCoherenceTrail = wrapRule({
21
21
  name: 'Reviewable trailhead map',
22
22
  },
23
23
  ],
24
- rule: surfaceFacetCoherence,
24
+ rule: surfaceTrailheadCoherence,
25
25
  });
@@ -0,0 +1,47 @@
1
+ import { trailheadOverrideDivergence } from '../rules/trailhead-override-divergence.js';
2
+ import { wrapRule } from './wrap-rule.js';
3
+
4
+ export const trailheadOverrideDivergenceTrail = wrapRule({
5
+ examples: [
6
+ {
7
+ expected: { diagnostics: [] },
8
+ input: {
9
+ authoredMcpSurfaceBindingSets: [
10
+ {
11
+ appName: 'demo',
12
+ bindings: { inspect: ['survey', 'survey.brief'] },
13
+ trailIds: ['survey', 'survey.brief'],
14
+ },
15
+ ],
16
+ filePath: 'mcp-options.ts',
17
+ sourceCode: `export const trailheads = {
18
+ inspect: {
19
+ description: "Inspect topo state.",
20
+ trails: ["survey", "survey.brief"],
21
+ },
22
+ };`,
23
+ },
24
+ name: 'Aligned call-site override',
25
+ },
26
+ {
27
+ input: {
28
+ authoredMcpSurfaceBindingSets: [
29
+ {
30
+ appName: 'demo',
31
+ bindings: { inspect: ['survey', 'survey.brief'] },
32
+ trailIds: ['survey', 'survey.brief'],
33
+ },
34
+ ],
35
+ filePath: 'mcp-options.ts',
36
+ sourceCode: `export const trailheads = {
37
+ inspect: {
38
+ description: "Inspect topo state.",
39
+ trails: ["survey"],
40
+ },
41
+ };`,
42
+ },
43
+ name: 'Diverging member selectors are flagged',
44
+ },
45
+ ],
46
+ rule: trailheadOverrideDivergence,
47
+ });
@@ -51,6 +51,9 @@ const buildRuleMeta = (rule: WardenRule | TopoAwareWardenRule) => {
51
51
  };
52
52
 
53
53
  const buildProjectContext = (input: ProjectAwareRuleInput): ProjectContext => ({
54
+ ...(input.authoredMcpSurfaceBindingSets
55
+ ? { authoredMcpSurfaceBindingSets: input.authoredMcpSurfaceBindingSets }
56
+ : {}),
54
57
  ...(input.contourReferencesByName
55
58
  ? {
56
59
  contourReferencesByName: new Map(
@@ -88,6 +91,13 @@ const buildProjectContext = (input: ProjectAwareRuleInput): ProjectContext => ({
88
91
  ),
89
92
  }
90
93
  : {}),
94
+ ...(input.exportedSymbolDefinitionsByName
95
+ ? {
96
+ exportedSymbolDefinitionsByName: new Map(
97
+ Object.entries(input.exportedSymbolDefinitionsByName)
98
+ ),
99
+ }
100
+ : {}),
91
101
  ...(input.publicWorkspaces
92
102
  ? { publicWorkspaces: new Map(Object.entries(input.publicWorkspaces)) }
93
103
  : {}),