@mmnto/totem 1.19.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compiler.d.ts +1 -1
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +1 -1
- package/dist/compiler.js.map +1 -1
- package/dist/config-schema.d.ts +132 -0
- package/dist/config-schema.d.ts.map +1 -1
- package/dist/config-schema.js +44 -0
- package/dist/config-schema.js.map +1 -1
- package/dist/config-schema.test.js +122 -0
- package/dist/config-schema.test.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/rule-engine.d.ts +11 -0
- package/dist/rule-engine.d.ts.map +1 -1
- package/dist/rule-engine.js +36 -4
- package/dist/rule-engine.js.map +1 -1
- package/dist/rule-engine.test.js +42 -0
- package/dist/rule-engine.test.js.map +1 -1
- package/dist/stage4-verifier.d.ts +94 -1
- package/dist/stage4-verifier.d.ts.map +1 -1
- package/dist/stage4-verifier.js +139 -71
- package/dist/stage4-verifier.js.map +1 -1
- package/dist/stage4-verifier.test.js +215 -4
- package/dist/stage4-verifier.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -50,7 +50,7 @@ export interface Stage4Baseline {
|
|
|
50
50
|
/**
|
|
51
51
|
* Glob patterns the rule MUST NOT fire on. Files matching any of these
|
|
52
52
|
* globs are part of the verification baseline — a match on one of them
|
|
53
|
-
* is evidence the pattern is over-broad. T1
|
|
53
|
+
* is evidence the pattern is over-broad. T1 shipped with `DEFAULT_BASELINE_GLOBS`
|
|
54
54
|
* (test + fixture patterns); T2 (mmnto-ai/totem#1683) layers consumer
|
|
55
55
|
* `extend` / `exclude` overrides via `review.stage4Baseline` config.
|
|
56
56
|
*
|
|
@@ -59,6 +59,25 @@ export interface Stage4Baseline {
|
|
|
59
59
|
* from `rule.fileGlobs` at evaluation time.
|
|
60
60
|
*/
|
|
61
61
|
readonly excludeFileGlobs: readonly string[];
|
|
62
|
+
/**
|
|
63
|
+
* Provenance: globs added via `# stage4-baseline:` directives in the
|
|
64
|
+
* consumer's `.totemignore` file. Empty when no such directives. Read
|
|
65
|
+
* by `totem doctor` (T4) and trace events; the verifier itself only
|
|
66
|
+
* reads `excludeFileGlobs`.
|
|
67
|
+
*/
|
|
68
|
+
readonly extendedFromIgnoreFile: readonly string[];
|
|
69
|
+
/**
|
|
70
|
+
* Provenance: globs added via `review.stage4Baseline.extend` in
|
|
71
|
+
* `totem.config.ts`. Empty when not configured.
|
|
72
|
+
*/
|
|
73
|
+
readonly extendedFromConfig: readonly string[];
|
|
74
|
+
/**
|
|
75
|
+
* Provenance: globs removed from the default baseline via
|
|
76
|
+
* `review.stage4Baseline.exclude` in `totem.config.ts`. Empty when not
|
|
77
|
+
* configured. Useful for diagnosing why a rule fires on a path the
|
|
78
|
+
* consumer expected to be in the baseline.
|
|
79
|
+
*/
|
|
80
|
+
readonly excludedFromConfig: readonly string[];
|
|
62
81
|
}
|
|
63
82
|
export type Stage4Outcome = 'no-matches' | 'out-of-scope' | 'in-scope-bad-example' | 'candidate-debt';
|
|
64
83
|
export interface Stage4VerificationResult {
|
|
@@ -110,7 +129,81 @@ export interface Stage4VerifierDeps {
|
|
|
110
129
|
* project legitimately treats `tests/` as production.
|
|
111
130
|
*/
|
|
112
131
|
export declare const DEFAULT_BASELINE_GLOBS: readonly string[];
|
|
132
|
+
/**
|
|
133
|
+
* Backwards-compatible shorthand for `resolveStage4Baseline({})`. Returns the
|
|
134
|
+
* default baseline (test + fixture globs) with empty provenance arrays. Kept
|
|
135
|
+
* because pre-T2 callers (early CLI integration sites, tests) pass no
|
|
136
|
+
* overrides; new callers should prefer `resolveStage4Baseline` directly so
|
|
137
|
+
* config + .totemignore overrides flow through.
|
|
138
|
+
*/
|
|
113
139
|
export declare function getDefaultBaseline(): Stage4Baseline;
|
|
140
|
+
/**
|
|
141
|
+
* Static manifest paths excluded from Stage 4 corpus to prevent rules with
|
|
142
|
+
* a `badExample` field from self-matching against their own entry in the
|
|
143
|
+
* compiled manifest. CLI integration (`packages/cli/src/commands/compile.ts`)
|
|
144
|
+
* additionally computes a `totemDir`-aware path at runtime
|
|
145
|
+
* (`path.join(config.totemDir, 'compiled-rules.json')` normalized to forward
|
|
146
|
+
* slashes) and adds it to the exclusion set so consumers who override
|
|
147
|
+
* `config.totemDir` are covered too.
|
|
148
|
+
*/
|
|
149
|
+
export declare const STAGE4_MANIFEST_EXCLUSIONS: readonly string[];
|
|
150
|
+
export interface ResolveStage4BaselineInput {
|
|
151
|
+
/** Globs parsed from `# stage4-baseline:` directives in `.totemignore`. */
|
|
152
|
+
readonly ignoreDirectives?: readonly string[];
|
|
153
|
+
/** Globs from `review.stage4Baseline.extend` in `totem.config.ts`. */
|
|
154
|
+
readonly configExtend?: readonly string[];
|
|
155
|
+
/** Globs from `review.stage4Baseline.exclude` in `totem.config.ts`. */
|
|
156
|
+
readonly configExclude?: readonly string[];
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Compute the effective Stage 4 baseline for a compile run.
|
|
160
|
+
*
|
|
161
|
+
* Composition: `defaults ∪ ignoreDirectives ∪ configExtend ∖ configExclude`.
|
|
162
|
+
* `configExclude` is set-difference (LAST), so a consumer can remove a
|
|
163
|
+
* default baseline glob like `**\/tests/**` when their project legitimately
|
|
164
|
+
* treats `tests/` as production. Set membership uses byte-equal comparison
|
|
165
|
+
* on the glob string, NOT path matching — `exclude: ['**\/tests/**']`
|
|
166
|
+
* removes that exact default entry, not every glob that happens to match
|
|
167
|
+
* a `tests/` path.
|
|
168
|
+
*
|
|
169
|
+
* Pure function. Does NOT read the filesystem; the CLI integration site
|
|
170
|
+
* reads `.totemignore` and parses it via `parseStage4BaselineDirectives`
|
|
171
|
+
* before passing the directives in.
|
|
172
|
+
*
|
|
173
|
+
* @param input - The three composition inputs (all optional / default to `[]`).
|
|
174
|
+
* @returns A `Stage4Baseline` whose `excludeFileGlobs` is consumed by the
|
|
175
|
+
* verifier and whose three provenance arrays are read by `totem doctor`
|
|
176
|
+
* (T4 / `mmnto-ai/totem#1685`) and trace events.
|
|
177
|
+
*/
|
|
178
|
+
export declare function resolveStage4Baseline(input: ResolveStage4BaselineInput): Stage4Baseline;
|
|
179
|
+
/**
|
|
180
|
+
* Extract `# stage4-baseline: <glob>` directives from `.totemignore` content
|
|
181
|
+
* (or any line-oriented text). The leading `#` is REQUIRED — the directive
|
|
182
|
+
* lives on a comment line so it doesn't interfere with the rest of
|
|
183
|
+
* `.totemignore`'s ignore semantics. Variable whitespace around the `#`,
|
|
184
|
+
* the colon, and the body is allowed; the regex collapses it.
|
|
185
|
+
*
|
|
186
|
+
* Returns the globs in source order. Empty / whitespace-only directive
|
|
187
|
+
* bodies are skipped silently (no throw). The directive name is
|
|
188
|
+
* case-sensitive to match `.totemignore`'s overall convention.
|
|
189
|
+
*
|
|
190
|
+
* Pure function (`string → string[]`) so it can be invoked from any core
|
|
191
|
+
* consumer. CLI reads the file and hands the content to this helper;
|
|
192
|
+
* MCP integrations may want the same surface in the future.
|
|
193
|
+
*
|
|
194
|
+
* @param content - Raw `.totemignore` text (or any line-oriented content).
|
|
195
|
+
* Empty or undefined returns `[]`. CRLF and LF line endings both work.
|
|
196
|
+
* @returns Glob strings extracted from `# stage4-baseline:` lines, in
|
|
197
|
+
* source order, excluding empty/whitespace-only directive bodies.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```ts
|
|
201
|
+
* parseStage4BaselineDirectives('# stage4-baseline: build/**\nsrc/temp/**');
|
|
202
|
+
* // → ['build/**'] (only the directive line; 'src/temp/**' is ordinary
|
|
203
|
+
* // .totemignore content, not a stage4 directive)
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
export declare function parseStage4BaselineDirectives(content: string): string[];
|
|
114
207
|
/**
|
|
115
208
|
* Run Stage 4 verification for a single compiled rule against the consumer's
|
|
116
209
|
* codebase. Caller decides what to do with the returned outcome:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage4-verifier.d.ts","sourceRoot":"","sources":["../src/stage4-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAc,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"stage4-verifier.d.ts","sourceRoot":"","sources":["../src/stage4-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAc,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAStE,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAE7C;;;;;OAKG;IACH,QAAQ,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAEnD;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAE/C;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD;AAED,MAAM,MAAM,aAAa,GACrB,YAAY,GACZ,cAAc,GACd,sBAAsB,GACtB,gBAAgB,CAAC;AAErB,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,aAAa,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAID;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAOnD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,cAAc,CAEnD;AAID;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAAmC,CAAC;AAI5F,MAAM,WAAW,0BAA0B;IACzC,2EAA2E;IAC3E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,sEAAsE;IACtE,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,uEAAuE;IACvE,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,GAAG,cAAc,CAgBvF;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAWvE;AA0KD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,wBAAwB,CAAC,CA2FnC"}
|
package/dist/stage4-verifier.js
CHANGED
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
* orchestration-only. CLI implementations back the callbacks with `git
|
|
45
45
|
* ls-files` and `fs.readFile`; tests stub them with synthetic file maps.
|
|
46
46
|
*/
|
|
47
|
-
import { applyAstRulesToAdditions, applyRulesToAdditions } from './rule-engine.js';
|
|
47
|
+
import { applyAstRulesToAdditions, applyRulesToAdditions, fileMatchesGlobs, } from './rule-engine.js';
|
|
48
48
|
// ─── Default baseline ───────────────────────────────
|
|
49
49
|
/**
|
|
50
50
|
* Glob shapes the test-contract scope classifier (mmnto-ai/totem#1626 /
|
|
@@ -62,74 +62,108 @@ export const DEFAULT_BASELINE_GLOBS = [
|
|
|
62
62
|
'**/__fixtures__/**',
|
|
63
63
|
'**/fixtures/**',
|
|
64
64
|
];
|
|
65
|
+
/**
|
|
66
|
+
* Backwards-compatible shorthand for `resolveStage4Baseline({})`. Returns the
|
|
67
|
+
* default baseline (test + fixture globs) with empty provenance arrays. Kept
|
|
68
|
+
* because pre-T2 callers (early CLI integration sites, tests) pass no
|
|
69
|
+
* overrides; new callers should prefer `resolveStage4Baseline` directly so
|
|
70
|
+
* config + .totemignore overrides flow through.
|
|
71
|
+
*/
|
|
65
72
|
export function getDefaultBaseline() {
|
|
66
|
-
|
|
67
|
-
// test/fixture exclusion). T2 (mmnto-ai/totem#1683) introduces per-config
|
|
68
|
-
// `extend`/`exclude` overrides; the function signature accepts a rule
|
|
69
|
-
// parameter then so per-rule baseline derivation can layer on top.
|
|
70
|
-
return { excludeFileGlobs: DEFAULT_BASELINE_GLOBS };
|
|
73
|
+
return resolveStage4Baseline({});
|
|
71
74
|
}
|
|
72
|
-
// ───
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
// ─── Manifest exclusions (mmnto-ai/totem#1765) ──────
|
|
76
|
+
/**
|
|
77
|
+
* Static manifest paths excluded from Stage 4 corpus to prevent rules with
|
|
78
|
+
* a `badExample` field from self-matching against their own entry in the
|
|
79
|
+
* compiled manifest. CLI integration (`packages/cli/src/commands/compile.ts`)
|
|
80
|
+
* additionally computes a `totemDir`-aware path at runtime
|
|
81
|
+
* (`path.join(config.totemDir, 'compiled-rules.json')` normalized to forward
|
|
82
|
+
* slashes) and adds it to the exclusion set so consumers who override
|
|
83
|
+
* `config.totemDir` are covered too.
|
|
84
|
+
*/
|
|
85
|
+
export const STAGE4_MANIFEST_EXCLUSIONS = ['.totem/compiled-rules.json'];
|
|
86
|
+
/**
|
|
87
|
+
* Compute the effective Stage 4 baseline for a compile run.
|
|
88
|
+
*
|
|
89
|
+
* Composition: `defaults ∪ ignoreDirectives ∪ configExtend ∖ configExclude`.
|
|
90
|
+
* `configExclude` is set-difference (LAST), so a consumer can remove a
|
|
91
|
+
* default baseline glob like `**\/tests/**` when their project legitimately
|
|
92
|
+
* treats `tests/` as production. Set membership uses byte-equal comparison
|
|
93
|
+
* on the glob string, NOT path matching — `exclude: ['**\/tests/**']`
|
|
94
|
+
* removes that exact default entry, not every glob that happens to match
|
|
95
|
+
* a `tests/` path.
|
|
96
|
+
*
|
|
97
|
+
* Pure function. Does NOT read the filesystem; the CLI integration site
|
|
98
|
+
* reads `.totemignore` and parses it via `parseStage4BaselineDirectives`
|
|
99
|
+
* before passing the directives in.
|
|
100
|
+
*
|
|
101
|
+
* @param input - The three composition inputs (all optional / default to `[]`).
|
|
102
|
+
* @returns A `Stage4Baseline` whose `excludeFileGlobs` is consumed by the
|
|
103
|
+
* verifier and whose three provenance arrays are read by `totem doctor`
|
|
104
|
+
* (T4 / `mmnto-ai/totem#1685`) and trace events.
|
|
105
|
+
*/
|
|
106
|
+
export function resolveStage4Baseline(input) {
|
|
107
|
+
const ignoreDirectives = input.ignoreDirectives ?? [];
|
|
108
|
+
const configExtend = input.configExtend ?? [];
|
|
109
|
+
const configExclude = input.configExclude ?? [];
|
|
110
|
+
const excludeSet = new Set(DEFAULT_BASELINE_GLOBS);
|
|
111
|
+
for (const g of ignoreDirectives)
|
|
112
|
+
excludeSet.add(g);
|
|
113
|
+
for (const g of configExtend)
|
|
114
|
+
excludeSet.add(g);
|
|
115
|
+
for (const g of configExclude)
|
|
116
|
+
excludeSet.delete(g);
|
|
117
|
+
return {
|
|
118
|
+
excludeFileGlobs: [...excludeSet],
|
|
119
|
+
extendedFromIgnoreFile: [...ignoreDirectives],
|
|
120
|
+
extendedFromConfig: [...configExtend],
|
|
121
|
+
excludedFromConfig: [...configExclude],
|
|
122
|
+
};
|
|
86
123
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
// ─── .totemignore directive parser (mmnto-ai/totem#1683) ─
|
|
125
|
+
const STAGE4_BASELINE_DIRECTIVE_RE = /^#\s*stage4-baseline:\s*(.+?)\s*$/;
|
|
126
|
+
/**
|
|
127
|
+
* Extract `# stage4-baseline: <glob>` directives from `.totemignore` content
|
|
128
|
+
* (or any line-oriented text). The leading `#` is REQUIRED — the directive
|
|
129
|
+
* lives on a comment line so it doesn't interfere with the rest of
|
|
130
|
+
* `.totemignore`'s ignore semantics. Variable whitespace around the `#`,
|
|
131
|
+
* the colon, and the body is allowed; the regex collapses it.
|
|
132
|
+
*
|
|
133
|
+
* Returns the globs in source order. Empty / whitespace-only directive
|
|
134
|
+
* bodies are skipped silently (no throw). The directive name is
|
|
135
|
+
* case-sensitive to match `.totemignore`'s overall convention.
|
|
136
|
+
*
|
|
137
|
+
* Pure function (`string → string[]`) so it can be invoked from any core
|
|
138
|
+
* consumer. CLI reads the file and hands the content to this helper;
|
|
139
|
+
* MCP integrations may want the same surface in the future.
|
|
140
|
+
*
|
|
141
|
+
* @param content - Raw `.totemignore` text (or any line-oriented content).
|
|
142
|
+
* Empty or undefined returns `[]`. CRLF and LF line endings both work.
|
|
143
|
+
* @returns Glob strings extracted from `# stage4-baseline:` lines, in
|
|
144
|
+
* source order, excluding empty/whitespace-only directive bodies.
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* parseStage4BaselineDirectives('# stage4-baseline: build/**\nsrc/temp/**');
|
|
149
|
+
* // → ['build/**'] (only the directive line; 'src/temp/**' is ordinary
|
|
150
|
+
* // .totemignore content, not a stage4 directive)
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export function parseStage4BaselineDirectives(content) {
|
|
154
|
+
if (!content)
|
|
155
|
+
return [];
|
|
156
|
+
const out = [];
|
|
157
|
+
for (const rawLine of content.split(/\r?\n/)) {
|
|
158
|
+
const match = STAGE4_BASELINE_DIRECTIVE_RE.exec(rawLine);
|
|
159
|
+
if (!match)
|
|
160
|
+
continue;
|
|
161
|
+
const body = match[1]?.trim() ?? '';
|
|
162
|
+
if (body.length === 0)
|
|
163
|
+
continue;
|
|
164
|
+
out.push(body);
|
|
125
165
|
}
|
|
126
|
-
return
|
|
127
|
-
}
|
|
128
|
-
function escapeRegex(s) {
|
|
129
|
-
return s.replace(/[.+()[\]^$|\\*?{}]/g, '\\$&');
|
|
130
|
-
}
|
|
131
|
-
function fileMatchesAnyGlob(filePath, globs) {
|
|
132
|
-
return globs.some((g) => matchesGlob(filePath, g));
|
|
166
|
+
return out;
|
|
133
167
|
}
|
|
134
168
|
/**
|
|
135
169
|
* A file is "in scope" for Stage 4 verification when it matches the rule's
|
|
@@ -138,19 +172,53 @@ function fileMatchesAnyGlob(filePath, globs) {
|
|
|
138
172
|
* inside `**\/*.ts` scope counts as baseline, not in-scope, because the
|
|
139
173
|
* verifier's job is to detect over-broad firing — including on tests the
|
|
140
174
|
* rule is supposed to skip.
|
|
175
|
+
*
|
|
176
|
+
* Glob matching delegates to `fileMatchesGlobs` from `rule-engine.ts`
|
|
177
|
+
* (mmnto-ai/totem#1758) — single source of truth for glob semantics
|
|
178
|
+
* across rule classification and Stage 4 baseline classification. The
|
|
179
|
+
* earlier local regex-conversion matcher had a substring hole
|
|
180
|
+
* (`**\/tests/**` would match `src/contests/foo.ts`) which the
|
|
181
|
+
* pattern-specific matcher in rule-engine fixes by construction.
|
|
141
182
|
*/
|
|
142
183
|
function classifyFile(filePath, ruleFileGlobs, baseline) {
|
|
143
184
|
// Rule has explicit fileGlobs and this file doesn't match → baseline (out-of-scope).
|
|
144
185
|
if (ruleFileGlobs && ruleFileGlobs.length > 0) {
|
|
145
|
-
|
|
146
|
-
const negative = ruleFileGlobs.filter((g) => g.startsWith('!')).map((g) => g.slice(1));
|
|
147
|
-
const matchesPositive = positive.length === 0 || fileMatchesAnyGlob(filePath, positive);
|
|
148
|
-
const matchesNegative = fileMatchesAnyGlob(filePath, negative);
|
|
149
|
-
if (!matchesPositive || matchesNegative)
|
|
186
|
+
if (!fileMatchesGlobs(filePath, ruleFileGlobs))
|
|
150
187
|
return 'baseline';
|
|
151
188
|
}
|
|
152
189
|
// File matches rule scope (or rule has no scope). Now check baseline overrides.
|
|
153
|
-
|
|
190
|
+
//
|
|
191
|
+
// Subtract rule-declared scope from the baseline first (CR mmnto-ai/totem#1766 R3).
|
|
192
|
+
// A rule that explicitly scopes itself to test or fixture files (e.g.
|
|
193
|
+
// `fileGlobs: ['**/*.test.*']` for a test-contract rule) needs to fire
|
|
194
|
+
// on those exact files. If the baseline contains the same glob (the
|
|
195
|
+
// default `DEFAULT_BASELINE_GLOBS` includes `**/*.test.*`), then without
|
|
196
|
+
// this subtraction every match the rule produces on its intended corpus
|
|
197
|
+
// is classified as baseline → the outcome flips to `out-of-scope` and
|
|
198
|
+
// the rule is archived on its own scope. Byte-equal subtraction is
|
|
199
|
+
// consistent with `resolveStage4Baseline`'s `exclude` semantics: an
|
|
200
|
+
// explicit `fileGlobs` entry that matches a baseline entry is the rule's
|
|
201
|
+
// way of claiming that part of the baseline as its own.
|
|
202
|
+
const effectiveBaselineGlobs = ruleFileGlobs && ruleFileGlobs.length > 0
|
|
203
|
+
? baseline.excludeFileGlobs.filter((g) => !ruleFileGlobs.includes(g))
|
|
204
|
+
: baseline.excludeFileGlobs;
|
|
205
|
+
// Guard against empty positive set explicitly. `fileMatchesGlobs` has
|
|
206
|
+
// default-allow semantics when its positive-glob set is empty (returns
|
|
207
|
+
// `true` so a rule with empty fileGlobs runs everywhere — that's the
|
|
208
|
+
// rule-engine's contract). Stage 4's baseline doesn't share that
|
|
209
|
+
// contract: an empty positive set means "nothing positively baseline-
|
|
210
|
+
// excluded", not "everything is baseline-excluded."
|
|
211
|
+
//
|
|
212
|
+
// Three empty-positive cases land here in practice:
|
|
213
|
+
// 1. Consumer `exclude`-s every default baseline glob → `excludeFileGlobs`
|
|
214
|
+
// is fully empty (Sonnet R0 catch).
|
|
215
|
+
// 2. Consumer `extend`-s with only `!`-prefixed entries AND `exclude`-s
|
|
216
|
+
// every default → `excludeFileGlobs` has only negatives, no positives
|
|
217
|
+
// (GCA mmnto-ai/totem#1766 R1 catch).
|
|
218
|
+
// 3. Rule `fileGlobs` covers every positive baseline entry → after the
|
|
219
|
+
// R3 subtraction above, `effectiveBaselineGlobs` has no positives.
|
|
220
|
+
const hasPositiveBaseline = effectiveBaselineGlobs.some((g) => !g.startsWith('!'));
|
|
221
|
+
if (hasPositiveBaseline && fileMatchesGlobs(filePath, effectiveBaselineGlobs))
|
|
154
222
|
return 'baseline';
|
|
155
223
|
return 'in-scope';
|
|
156
224
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage4-verifier.js","sourceRoot":"","sources":["../src/stage4-verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAIH,OAAO,
|
|
1
|
+
{"version":3,"file":"stage4-verifier.js","sourceRoot":"","sources":["../src/stage4-verifier.ts"],"names":[],"mappings":"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"}
|