@ontrails/warden 1.0.0-beta.42 → 1.0.0-beta.43
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/CHANGELOG.md +55 -0
- package/package.json +10 -10
- package/src/adapter-check.ts +1 -1
- package/src/cli.ts +81 -5
- package/src/index.ts +17 -4
- package/src/regrade-history.ts +599 -0
- package/src/rules/cli-command-route-coherence.ts +6 -6
- package/src/rules/draft-visible-debt.ts +1 -1
- package/src/rules/duplicate-exported-symbol.ts +4 -43
- package/src/rules/governed-symbol-residue.ts +146 -53
- package/src/rules/governed-vocabulary-permutation-watch.ts +76 -0
- package/src/rules/index.ts +17 -6
- package/src/rules/layer-field-name-drift.ts +2 -2
- package/src/rules/{library-projection-coherence.ts → library-render-coherence.ts} +11 -14
- package/src/rules/metadata.ts +51 -14
- package/src/rules/no-retired-cross-vocabulary.ts +0 -1
- package/src/rules/{owner-projection-parity.ts → owner-render-parity.ts} +18 -18
- package/src/rules/public-internal-deep-imports.ts +1 -3
- package/src/rules/public-output-schema.ts +1 -1
- package/src/rules/registry-names.ts +6 -4
- package/src/rules/retired-vocabulary.ts +775 -41
- package/src/rules/surface-overlay-coherence.ts +1 -1
- package/src/rules/trail-versioning-source.ts +1 -1
- package/src/rules/trailhead-override-divergence.ts +4 -4
- package/src/rules/types.ts +51 -5
- package/src/trails/governed-vocabulary-permutation-watch.trail.ts +16 -0
- package/src/trails/index.ts +3 -2
- package/src/trails/layer-field-name-drift.trail.ts +1 -1
- package/src/trails/{library-projection-coherence.trail.ts → library-render-coherence.trail.ts} +6 -6
- package/src/trails/{owner-projection-parity.trail.ts → owner-render-parity.trail.ts} +4 -4
- package/src/trails/public-output-schema.trail.ts +1 -1
- package/src/trails/run.ts +44 -2
- package/src/trails/schema.ts +41 -0
- package/src/trails/wrap-rule.ts +44 -2
|
@@ -39,7 +39,6 @@ const ALLOWED_PATH_SUFFIXES: readonly string[] = [
|
|
|
39
39
|
'/packages/warden/src/rules/retired-vocabulary.ts',
|
|
40
40
|
'/packages/warden/src/trails/governed-symbol-residue.trail.ts',
|
|
41
41
|
'/packages/warden/src/trails/no-retired-cross-vocabulary.trail.ts',
|
|
42
|
-
'/scripts/vocab-cutover-rewrite.ts',
|
|
43
42
|
];
|
|
44
43
|
|
|
45
44
|
interface SafeRewriteMatch {
|
|
@@ -18,14 +18,14 @@ import {
|
|
|
18
18
|
import type { AstNode } from '@ontrails/source';
|
|
19
19
|
import type { WardenDiagnostic, WardenRule } from './types.js';
|
|
20
20
|
|
|
21
|
-
const RULE_NAME = 'owner-
|
|
21
|
+
const RULE_NAME = 'owner-render-parity';
|
|
22
22
|
|
|
23
|
-
const
|
|
23
|
+
const HTTP_METHOD_DERIVATION_PATH = resolve(
|
|
24
24
|
fileURLToPath(new URL('../../../http/src/method.ts', import.meta.url))
|
|
25
25
|
);
|
|
26
26
|
|
|
27
27
|
const isTargetFile = (filePath: string): boolean =>
|
|
28
|
-
resolve(filePath) ===
|
|
28
|
+
resolve(filePath) === HTTP_METHOD_DERIVATION_PATH;
|
|
29
29
|
|
|
30
30
|
const unwrapExpression = (node: AstNode | undefined): AstNode | undefined => {
|
|
31
31
|
let current = node;
|
|
@@ -44,13 +44,13 @@ const unwrapExpression = (node: AstNode | undefined): AstNode | undefined => {
|
|
|
44
44
|
return current;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
interface
|
|
47
|
+
interface IntentKeyMap {
|
|
48
48
|
readonly keys: ReadonlySet<string>;
|
|
49
49
|
readonly node: AstNode;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const findHttpMethodByIntentMap = (ast: AstNode):
|
|
53
|
-
let found:
|
|
52
|
+
const findHttpMethodByIntentMap = (ast: AstNode): IntentKeyMap | null => {
|
|
53
|
+
let found: IntentKeyMap | null = null;
|
|
54
54
|
|
|
55
55
|
walk(ast, (node) => {
|
|
56
56
|
if (found || node.type !== 'VariableDeclarator') {
|
|
@@ -89,16 +89,16 @@ const findHttpMethodByIntentMap = (ast: AstNode): ProjectionMap | null => {
|
|
|
89
89
|
const buildMessage = (missing: string[], extra: string[]): string => {
|
|
90
90
|
const details = [
|
|
91
91
|
missing.length > 0 ? `missing owner intents: ${missing.join(', ')}` : '',
|
|
92
|
-
extra.length > 0 ? `unknown
|
|
92
|
+
extra.length > 0 ? `unknown intentKeyMap keys: ${extra.join(', ')}` : '',
|
|
93
93
|
].filter(Boolean);
|
|
94
94
|
|
|
95
95
|
return [
|
|
96
|
-
'owner-
|
|
96
|
+
'owner-render-parity: httpMethodByIntent must cover the core intentValues owner vocabulary.',
|
|
97
97
|
...details,
|
|
98
98
|
].join(' ');
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
-
export const
|
|
101
|
+
export const ownerRenderParity: WardenRule = {
|
|
102
102
|
check(sourceCode: string, filePath: string): readonly WardenDiagnostic[] {
|
|
103
103
|
if (!isTargetFile(filePath)) {
|
|
104
104
|
return [];
|
|
@@ -109,35 +109,35 @@ export const ownerProjectionParity: WardenRule = {
|
|
|
109
109
|
return [];
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
const
|
|
112
|
+
const intentKeyMap = findHttpMethodByIntentMap(ast);
|
|
113
113
|
const ownerKeys = new Set<string>(intentValues);
|
|
114
|
-
const
|
|
114
|
+
const derivedKeys = intentKeyMap?.keys ?? new Set<string>();
|
|
115
115
|
const missing = [...ownerKeys]
|
|
116
|
-
.filter((key) => !
|
|
116
|
+
.filter((key) => !derivedKeys.has(key))
|
|
117
117
|
.toSorted();
|
|
118
|
-
const extra = [...
|
|
118
|
+
const extra = [...derivedKeys]
|
|
119
119
|
.filter((key) => !ownerKeys.has(key))
|
|
120
120
|
.toSorted();
|
|
121
121
|
|
|
122
|
-
if (
|
|
122
|
+
if (intentKeyMap && missing.length === 0 && extra.length === 0) {
|
|
123
123
|
return [];
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
const node =
|
|
126
|
+
const node = intentKeyMap?.node ?? ast;
|
|
127
127
|
return [
|
|
128
128
|
{
|
|
129
129
|
filePath,
|
|
130
130
|
line: offsetToLine(sourceCode, node.start),
|
|
131
|
-
message:
|
|
131
|
+
message: intentKeyMap
|
|
132
132
|
? buildMessage(missing, extra)
|
|
133
|
-
: 'owner-
|
|
133
|
+
: 'owner-render-parity: expected httpMethodByIntent to render core intentValues.',
|
|
134
134
|
rule: RULE_NAME,
|
|
135
135
|
severity: 'error',
|
|
136
136
|
},
|
|
137
137
|
];
|
|
138
138
|
},
|
|
139
139
|
description:
|
|
140
|
-
'Require owner-derived
|
|
140
|
+
'Require owner-derived intentKeyMap maps to cover their authoritative owner vocabulary.',
|
|
141
141
|
name: RULE_NAME,
|
|
142
142
|
severity: 'error',
|
|
143
143
|
};
|
|
@@ -20,9 +20,7 @@ import type { WardenPublicWorkspace } from '../workspaces.js';
|
|
|
20
20
|
|
|
21
21
|
const RULE_NAME = 'public-internal-deep-imports';
|
|
22
22
|
const ONTRAILS_SPECIFIER_PATTERN = /^(@ontrails\/[^/]+)(?:\/(.+))?$/;
|
|
23
|
-
const ROOT_BARREL_INTERNAL_RE_EXPORT_ALLOWLIST = new Set(
|
|
24
|
-
'@ontrails/tracing:./internal/dev-state.js',
|
|
25
|
-
]);
|
|
23
|
+
const ROOT_BARREL_INTERNAL_RE_EXPORT_ALLOWLIST = new Set<string>();
|
|
26
24
|
|
|
27
25
|
interface ReExportSite {
|
|
28
26
|
readonly importSource: string;
|
|
@@ -10,7 +10,7 @@ const diagnosticForTrail = (trail: AnyTrail): WardenDiagnostic => ({
|
|
|
10
10
|
filePath: TOPO_FILE,
|
|
11
11
|
line: 1,
|
|
12
12
|
message:
|
|
13
|
-
`Trail "${trail.id}" is visible to public MCP/HTTP surface
|
|
13
|
+
`Trail "${trail.id}" is visible to public MCP/HTTP surface rendering but does not declare an output schema. ` +
|
|
14
14
|
'Add an explicit output schema, or mark the trail visibility as internal if it is composition-only.',
|
|
15
15
|
rule: RULE_NAME,
|
|
16
16
|
severity: 'error',
|
|
@@ -23,12 +23,13 @@ import { errorMappingCompleteness } from './error-mapping-completeness.js';
|
|
|
23
23
|
import { exampleValid } from './example-valid.js';
|
|
24
24
|
import { firesDeclarations } from './fires-declarations.js';
|
|
25
25
|
import { governedSymbolResidue } from './governed-symbol-residue.js';
|
|
26
|
+
import { governedVocabularyPermutationWatch } from './governed-vocabulary-permutation-watch.js';
|
|
26
27
|
import { implementationReturnsResult } from './implementation-returns-result.js';
|
|
27
28
|
import { incompleteAccessorForStandardOp } from './incomplete-accessor-for-standard-op.js';
|
|
28
29
|
import { incompleteCrud } from './incomplete-crud.js';
|
|
29
30
|
import { intentPropagation } from './intent-propagation.js';
|
|
30
31
|
import { layerFieldNameDrift } from './layer-field-name-drift.js';
|
|
31
|
-
import {
|
|
32
|
+
import { libraryRenderCoherence } from './library-render-coherence.js';
|
|
32
33
|
import { missingReconcile } from './missing-reconcile.js';
|
|
33
34
|
import { missingVisibility } from './missing-visibility.js';
|
|
34
35
|
import { noDevPermitInSource } from './no-dev-permit-in-source.js';
|
|
@@ -45,7 +46,7 @@ import { noThrowInImplementation } from './no-throw-in-implementation.js';
|
|
|
45
46
|
import { noTopLevelSurface } from './no-top-level-surface.js';
|
|
46
47
|
import { onReferencesExist } from './on-references-exist.js';
|
|
47
48
|
import { orphanedSignal } from './orphaned-signal.js';
|
|
48
|
-
import {
|
|
49
|
+
import { ownerRenderParity } from './owner-render-parity.js';
|
|
49
50
|
import { permitGovernance } from './permit-governance.js';
|
|
50
51
|
import { preferSchemaInference } from './prefer-schema-inference.js';
|
|
51
52
|
import { publicExportExampleCoverage } from './public-export-example-coverage.js';
|
|
@@ -109,13 +110,14 @@ export const registeredRuleNames: readonly string[] = [
|
|
|
109
110
|
exampleValid.name,
|
|
110
111
|
firesDeclarations.name,
|
|
111
112
|
governedSymbolResidue.name,
|
|
113
|
+
governedVocabularyPermutationWatch.name,
|
|
112
114
|
forkWithoutPreservedImplementation.name,
|
|
113
115
|
implementationReturnsResult.name,
|
|
114
116
|
incompleteAccessorForStandardOp.name,
|
|
115
117
|
incompleteCrud.name,
|
|
116
118
|
intentPropagation.name,
|
|
117
119
|
layerFieldNameDrift.name,
|
|
118
|
-
|
|
120
|
+
libraryRenderCoherence.name,
|
|
119
121
|
markerSchemaUnsupported.name,
|
|
120
122
|
missingReconcile.name,
|
|
121
123
|
missingVisibility.name,
|
|
@@ -133,7 +135,7 @@ export const registeredRuleNames: readonly string[] = [
|
|
|
133
135
|
noTopLevelSurface.name,
|
|
134
136
|
onReferencesExist.name,
|
|
135
137
|
orphanedSignal.name,
|
|
136
|
-
|
|
138
|
+
ownerRenderParity.name,
|
|
137
139
|
pendingForce.name,
|
|
138
140
|
permitGovernance.name,
|
|
139
141
|
preferSchemaInference.name,
|