@eviano/tribunal 0.1.2 → 0.2.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.
Files changed (41) hide show
  1. package/README.md +177 -11
  2. package/dist/analyzers/claimReconciliation.js +43 -22
  3. package/dist/analyzers/claimReconciliation.js.map +1 -1
  4. package/dist/analyzers/commentCodeDrift.d.ts +37 -0
  5. package/dist/analyzers/commentCodeDrift.js +241 -0
  6. package/dist/analyzers/commentCodeDrift.js.map +1 -0
  7. package/dist/analyzers/hallucinatedSymbol.js +22 -0
  8. package/dist/analyzers/hallucinatedSymbol.js.map +1 -1
  9. package/dist/analyzers/index.d.ts +5 -1
  10. package/dist/analyzers/index.js +12 -2
  11. package/dist/analyzers/index.js.map +1 -1
  12. package/dist/analyzers/riskyDiffNoTest.d.ts +36 -0
  13. package/dist/analyzers/riskyDiffNoTest.js +221 -0
  14. package/dist/analyzers/riskyDiffNoTest.js.map +1 -0
  15. package/dist/cli.js +167 -24
  16. package/dist/cli.js.map +1 -1
  17. package/dist/config/loadConfig.d.ts +19 -0
  18. package/dist/config/loadConfig.js +89 -0
  19. package/dist/config/loadConfig.js.map +1 -0
  20. package/dist/config/parseYaml.d.ts +17 -0
  21. package/dist/config/parseYaml.js +131 -0
  22. package/dist/config/parseYaml.js.map +1 -0
  23. package/dist/config/types.d.ts +17 -0
  24. package/dist/config/types.js +2 -0
  25. package/dist/config/types.js.map +1 -0
  26. package/dist/diff/parseUnifiedDiff.d.ts +4 -0
  27. package/dist/diff/parseUnifiedDiff.js +45 -18
  28. package/dist/diff/parseUnifiedDiff.js.map +1 -1
  29. package/dist/index.d.ts +3 -2
  30. package/dist/index.js +3 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/paths.d.ts +27 -0
  33. package/dist/paths.js +112 -0
  34. package/dist/paths.js.map +1 -0
  35. package/dist/propose.d.ts +103 -0
  36. package/dist/propose.js +175 -0
  37. package/dist/propose.js.map +1 -0
  38. package/dist/report/render.d.ts +5 -0
  39. package/dist/report/render.js +78 -0
  40. package/dist/report/render.js.map +1 -1
  41. package/package.json +1 -1
package/README.md CHANGED
@@ -28,27 +28,30 @@ guarantees, not vibes:
28
28
  5. **Reporter-first.** Default mode is a non-blocking PR comment. Teams earn trust in the signal before
29
29
  it can break their build.
30
30
 
31
- ## Quickstart
31
+ ## Install
32
+
33
+ [![npm](https://img.shields.io/npm/v/@eviano/tribunal)](https://www.npmjs.com/package/@eviano/tribunal)
32
34
 
33
35
  ```bash
34
- npm install
35
- npm test # run the suite
36
- npm run check -- check --help
36
+ npm i -D @eviano/tribunal
37
37
  ```
38
38
 
39
- Run it against your working changes (report-only):
39
+ Run it against a PR range (report-only by default; gates only on 🔴 CONTRADICTED):
40
40
 
41
41
  ```bash
42
- npm run check -- check # diff working tree vs HEAD
43
- npm run check -- check --base main --head HEAD
44
- npm run check -- check --diff some.patch # analyze a unified diff file
45
- npm run check -- check --format json
42
+ npx @eviano/tribunal check --base main --head HEAD
43
+ npx @eviano/tribunal check # diff working tree vs HEAD
44
+ npx @eviano/tribunal check --diff some.patch # analyze a unified diff file
45
+ npx @eviano/tribunal check --format json
46
+ npx @eviano/tribunal check --base main --head HEAD --hard-fail # block the build
46
47
  ```
47
48
 
48
- Make it block a build (opt-in, gates only on 🔴 CONTRADICTED):
49
+ ## Develop from source
49
50
 
50
51
  ```bash
51
- npm run check -- check --base main --head HEAD --hard-fail
52
+ npm install
53
+ npm test # run the suite
54
+ npm run check -- check --help
52
55
  ```
53
56
 
54
57
  ## Use it in CI (GitHub Action)
@@ -78,6 +81,78 @@ jobs:
78
81
 
79
82
  This repo dogfoods its own action — see [.github/workflows/tribunal.yml](.github/workflows/tribunal.yml).
80
83
 
84
+ ## SARIF output (GitHub code-scanning alerts)
85
+
86
+ Tribunal can emit [SARIF](https://docs.oasis-open.org/sarif/) so findings appear as GitHub
87
+ code-scanning alerts with proper tracking, dismissal, and filter-by-severity across runs.
88
+
89
+ ```bash
90
+ tribunal check --diff pr.diff --format sarif > tribunal.sarif
91
+ ```
92
+
93
+ Level mapping (deliberate — matches "gate only on CONTRADICTED"):
94
+
95
+ | Tribunal verdict | SARIF level |
96
+ |---|---|
97
+ | 🔴 CONTRADICTED | `error` |
98
+ | 🟡 UNVERIFIED | `note` |
99
+ | 🟢 PASS | _omitted_ |
100
+
101
+ Only the blocking verdict becomes an `error` alert; UNVERIFIED is visible but non-noisy. Each finding
102
+ carries a stable `partialFingerprints` (derived from analyzer + file + line + claim, **not** from the
103
+ prose) so GitHub tracks the same alert across runs — rewording a finding's title won't fork a new one.
104
+
105
+ Upload it in a workflow (bring your own upload step; the bundled action stays markdown-only to keep its
106
+ permission footprint minimal):
107
+
108
+ ```yaml
109
+ jobs:
110
+ tribunal-sarif:
111
+ runs-on: ubuntu-latest
112
+ permissions:
113
+ contents: read
114
+ security-events: write # required by upload-sarif
115
+ steps:
116
+ - uses: actions/checkout@v4
117
+ with: { fetch-depth: 0 }
118
+ - run: npx @eviano/tribunal check \
119
+ --base ${{ github.event.pull_request.base.sha }} \
120
+ --head ${{ github.event.pull_request.head.sha }} \
121
+ --format sarif > tribunal.sarif
122
+ - uses: github/codeql-action/upload-sarif@v3
123
+ with:
124
+ sarif_file: tribunal.sarif
125
+ category: tribunal
126
+ ```
127
+
128
+ SARIF is data, never a gate — the `--hard-fail` exit code still comes from `exitCode()`. You can run
129
+ both: post the markdown comment (via the action) **and** upload SARIF in the same job.
130
+
131
+ ## Configuration (`tribunal.yml`)
132
+
133
+ Optionally configure Tribunal with a `tribunal.yml` at the repo root (override the path with `--config
134
+ <file>` or `TRIBUNAL_CONFIG`). With **no** file, all defaults apply — config is purely additive.
135
+
136
+ ```yaml
137
+ # tribunal.yml
138
+ analyzers:
139
+ risky-diff-no-test: false # disable an analyzer (default: all enabled)
140
+ generated-paths: # EXTRA generated paths, appended to the built-ins
141
+ - vendor-generated/
142
+ - "**/*.gen.ts"
143
+ ```
144
+
145
+ - **`analyzers`** — a map of analyzer id → boolean. Default: every analyzer enabled. Disabling
146
+ `claim-reconciliation` just stops claim checks; claim-independent analyzers still run. **Unknown ids are
147
+ rejected** (typo guard): a misspelled key fails loud rather than silently no-op'ing.
148
+ - **`generated-paths`** — extra generated/build-output patterns, **appended** to the built-ins
149
+ (`dist/`, `action-dist/`, `*.min.js`, …). Config can only *add* coverage — never replace — so a user
150
+ can't accidentally drop the `dist/` safety net. Patterns may be dir-prefixes (`vendor-generated/`),
151
+ suffixes (`.gen.ts`), or simple globs (`**/*.gen.ts`, `src/generated/*`).
152
+
153
+ A present-but-malformed file (bad key, unknown analyzer, bad YAML) **fails loud** with a clear error
154
+ pointing at the line — it never silently degrades to defaults.
155
+
81
156
  ## What M0 catches: `assertion-free-test`
82
157
 
83
158
  A test the PR added or changed that **can never fail** because it asserts nothing:
@@ -114,6 +189,57 @@ re-exports, and degrades to 🟡 UNVERIFIED whenever exports can't be statically
114
189
  unresolvable re-exports). Default imports are never flagged (interop synthesizes a default). Scope for
115
190
  M1 is imports; full identifier/call resolution is a later increment.
116
191
 
192
+ ## What it also ships: `risky-diff-no-test`
193
+
194
+ A **signal** analyzer (never a gate) that fires when a PR touches a security-relevant area but adds no
195
+ correlated asserting test — the "silence is not an escape hatch" check. An agent that changes auth,
196
+ crypto, or payment code and ships nothing to cover it gets a finding even when it wrote no PR body:
197
+
198
+ ```ts
199
+ // src/auth.ts — changed by the PR
200
+ export function login(user, pass) { return user === pass; } // 🟡 UNVERIFIED: risky area ('auth'),
201
+ // no correlated asserting test
202
+ ```
203
+
204
+ - 🟡 **UNVERIFIED** — a risky area (path segment *or* a changed-line identifier token: `auth`,
205
+ `crypto`, `payment`, `token`, `secret`, …) was touched but no correlated asserting test was detected.
206
+ **Never blocks** — "is this risky?" is semantic, and a semantic guess may never flip a build red.
207
+ - 🟢 **PASS** — risky area touched **and** a correlated asserting test was added (test basename stem
208
+ shares a token with the risky file, e.g. `auth.ts` ↔ `auth.test.ts`).
209
+
210
+ It tokenizes (camelCase / kebab / snake) and matches on whole tokens, not substrings, so `authors.ts`
211
+ and `tokenize.ts` are correctly *not* flagged. Because it can only ever emit PASS/UNVERIFIED, it is safe
212
+ to run under `--hard-fail`.
213
+
214
+ **Generated-path skip.** A bundled artifact (e.g. `action-dist/cli.cjs`, `dist/*.min.js`) carries the
215
+ project's own risky vocab but isn't human-authored source a reviewer can act on, so flagging it is
216
+ noisy. This analyzer **skips generated/build-output paths by default** (`dist/`, `action-dist/`,
217
+ `build/`, `out/`, `.next/`, `coverage/`, `node_modules/`, and `*.min.{js,cjs,mjs}` / `*.bundle.js`).
218
+ Pass `--no-skip-generated` (or set `TRIBUNAL_NO_SKIP_GENERATED=1`) to re-enable flagging them — an
219
+ opinionated default must never silently suppress a file you want checked.
220
+
221
+ ## `comment-code-drift`
222
+
223
+ A **signal** analyzer (never a gate) that flags a comment/docstring which references a symbol whose
224
+ **definition changed** in the diff (body edit, rename, or removal), where the comment itself wasn't
225
+ freshly added. Catches the classic agent failure: it edits a function's behavior or renames it, but
226
+ leaves the docstring describing the old behavior/name.
227
+
228
+ ```ts
229
+ // src/greet.ts
230
+ // greet: returns a friendly greeting ← pre-existing comment (not added this PR)
231
+ export function greet() { return 'hello'; } // ← body changed 'hi' → 'hello'
232
+ // → 🟡 UNVERIFIED: comment mentions 'greet', whose definition changed. Verify the wording is accurate.
233
+ ```
234
+
235
+ - 🟡 **UNVERIFIED** — a comment (in the changed file **or** another changed file) mentions a changed
236
+ symbol by its **exact identifier token**, and the comment line was **not added** in this diff (a
237
+ freshly-added comment is unlikely stale — the key false-positive cut).
238
+ - It only fires when a **base ref** is available (it compares base vs head ASTs to find changed
239
+ declarations). With no base ref, it's silent.
240
+ - Like the other signal analyzers it **never blocks**: comment staleness is semantic, so it emits
241
+ PASS/UNVERIFIED only and is safe under `--hard-fail`.
242
+
117
243
  ## What M3 adds: `claim-reconciliation`
118
244
 
119
245
  Verifies the agent's **own claims** against the diff — deterministically. Claims are declared in a
@@ -137,6 +263,46 @@ no-public-api-change
137
263
  Pass claims with `--claims <file>` (a claims file) or `--pr-body <file>` (reads only the fenced block).
138
264
  Adding a new claim is one entry in the verifier registry.
139
265
 
266
+ ## `tribunal propose` — let an LLM PROPOSE claims (it never adjudicates)
267
+
268
+ No agent emits the ` ```tribunal ` convention today, so `claim-reconciliation` (above) does nothing on a
269
+ normal agent PR. `propose` closes that gap: it asks an LLM to *suggest* which claims a reviewer should
270
+ ask the deterministic engine to check, then writes a ` ```tribunal ` block that `check` consumes.
271
+
272
+ This is the narrow, Trust-Contract-compliant use of an LLM: it **proposes**; deterministic code
273
+ **adjudicates**. The LLM is never in the verification path.
274
+
275
+ **The two-step loop:**
276
+
277
+ ```bash
278
+ # 1) propose — the LLM reads the diff and suggests claims (writes claims.md)
279
+ tribunal propose --diff pr.diff \
280
+ --endpoint https://api.openai.com/v1 --model gpt-4o-mini \
281
+ --allow-send-diff --out claims.md
282
+
283
+ # 2) check — deterministic engine verifies the proposed claims against the diff
284
+ tribunal check --diff pr.diff --pr-body claims.md --hard-fail
285
+ ```
286
+
287
+ `propose` is pluggable: point `--endpoint` at any OpenAI-compatible chat-completions URL (OpenAI,
288
+ OpenRouter, a local Ollama / LM Studio server). Configure via flags or `TRIBUNAL_ENDPOINT` /
289
+ `TRIBUNAL_MODEL` / `TRIBUNAL_API_KEY`.
290
+
291
+ **The send-guard.** The diff is your source code, and sending it to an LLM endpoint is an outward-facing
292
+ publish. So `propose` **refuses to send by default** — without `--allow-send-diff` it prints the prompt
293
+ for review and sends *nothing*. Add the flag (or `TRIBUNAL_ALLOW_SEND_DIFF=1`) only when you've chosen
294
+ the endpoint and accept that the diff leaves the machine.
295
+
296
+ **Why this can't break the gate.** Two architectural guarantees hold even if the model hallucinates or is
297
+ prompt-injected:
298
+
299
+ 1. `propose` is a separate command and code path. It never imports or calls any verifier, `runTribunal`,
300
+ or `exitCode`. It only reads a diff and writes a claims block.
301
+ 2. The model can only ever emit claim *keys*. Keys outside the recognized set are downgraded to
302
+ 🟡 UNVERIFIED by the verifier registry — never 🔴 CONTRADICTED. Since `--hard-fail` gates only on
303
+ CONTRADICTED, **the LLM path cannot manufacture a false red**, no matter what it returns. (A *legitimate*
304
+ CONTRADICTED can still appear — that's the deterministic checker doing its job, which is the point.)
305
+
140
306
  ## Benchmark — the moat-proof
141
307
 
142
308
  Tribunal is only safe as a hard-fail gate if it almost never false-fires. That's measured, not
@@ -42,7 +42,20 @@ function verifyAddedTest(ctx) {
42
42
  };
43
43
  }
44
44
  const EMPTY_EXPORTS = { names: new Set(), hasDefault: false, uncertain: false };
45
- /** "no public API change" → exported-symbol set is identical between base and head for changed files. */
45
+ /**
46
+ * "no public API change" → the AGGREGATE exported-symbol set across changed files is identical between
47
+ * base and head.
48
+ *
49
+ * Why aggregate, not per-file: a refactor that moves `export const foo` from a.ts to b.ts (both changed)
50
+ * leaves the package surface unchanged, yet a per-file diff reports `-foo` in one file and `+foo` in the
51
+ * other — a false CONTRADICTED. Unchanged files export the same set on both sides, so they cancel out of
52
+ * the diff; aggregating only over changed files is therefore sound and bounded, and fixes the move case.
53
+ *
54
+ * Residual limitation: a symbol moved from a changed file into an UNCHANGED file still looks removed,
55
+ * because unchanged files are outside this diff-local view. Resolving that needs entry-point scoping
56
+ * (api-extractor); until then such a case degrades to UNVERIFIED via the `uncertain` path only when an
57
+ * uncertain module is present. This is strictly tighter than the prior per-file behavior.
58
+ */
46
59
  function verifyNoPublicApiChange(ctx) {
47
60
  if (!ctx.base || !ctx.readBaseFile) {
48
61
  return {
@@ -51,7 +64,10 @@ function verifyNoPublicApiChange(ctx) {
51
64
  detail: 'Exported-symbol changes need a base ref to diff against; none was available.',
52
65
  };
53
66
  }
54
- const changes = [];
67
+ const baseNames = new Set();
68
+ const headNames = new Set();
69
+ let baseDefault = false;
70
+ let headDefault = false;
55
71
  let uncertain = false;
56
72
  for (const f of ctx.changedFiles) {
57
73
  if (!SOURCE_EXT_RE.test(f.path) || isTestPath(f.path))
@@ -62,29 +78,34 @@ function verifyNoPublicApiChange(ctx) {
62
78
  continue;
63
79
  const baseExp = baseContent ? directExports(baseContent, f.path) : EMPTY_EXPORTS;
64
80
  const headExp = headContent ? directExports(headContent, f.path) : EMPTY_EXPORTS;
65
- if (baseExp.uncertain || headExp.uncertain) {
81
+ if (baseExp.uncertain || headExp.uncertain)
66
82
  uncertain = true;
67
- continue;
68
- }
69
- const added = [...headExp.names].filter((n) => !baseExp.names.has(n));
70
- const removed = [...baseExp.names].filter((n) => !headExp.names.has(n));
71
- if (baseExp.hasDefault !== headExp.hasDefault) {
72
- (headExp.hasDefault ? added : removed).push('default');
73
- }
74
- if (added.length || removed.length) {
75
- const parts = [];
76
- if (added.length)
77
- parts.push(`+${added.join(', +')}`);
78
- if (removed.length)
79
- parts.push(`-${removed.join(', -')}`);
80
- changes.push(`${f.path} (${parts.join('; ')})`);
81
- }
83
+ for (const n of baseExp.names)
84
+ baseNames.add(n);
85
+ for (const n of headExp.names)
86
+ headNames.add(n);
87
+ if (baseExp.hasDefault)
88
+ baseDefault = true;
89
+ if (headExp.hasDefault)
90
+ headDefault = true;
82
91
  }
83
- if (changes.length) {
92
+ const added = [...headNames].filter((n) => !baseNames.has(n));
93
+ const removed = [...baseNames].filter((n) => !headNames.has(n));
94
+ if (baseDefault !== headDefault)
95
+ (headDefault ? added : removed).push('default');
96
+ // Only CONTRADICT when the net change is a certainty. If any changed module is non-enumerable
97
+ // (`export *`, CJS), a "removed" symbol may live there and an "added" one may have pre-existed — so
98
+ // degrade to UNVERIFIED rather than risk a false red (Trust Contract §3.4).
99
+ if ((added.length || removed.length) && !uncertain) {
100
+ const parts = [];
101
+ if (added.length)
102
+ parts.push(`+${added.join(', +')}`);
103
+ if (removed.length)
104
+ parts.push(`-${removed.join(', -')}`);
84
105
  return {
85
106
  verdict: 'CONTRADICTED',
86
- title: 'Claimed no public API change, but exports changed',
87
- detail: `Exported symbols changed in: ${changes.join(' | ')}.`,
107
+ title: 'Claimed no public API change, but the exported surface changed',
108
+ detail: `Net exported-symbol change across changed files: ${parts.join('; ')}.`,
88
109
  };
89
110
  }
90
111
  if (uncertain) {
@@ -97,7 +118,7 @@ function verifyNoPublicApiChange(ctx) {
97
118
  return {
98
119
  verdict: 'PASS',
99
120
  title: 'Claim confirmed: no public API change',
100
- detail: 'No exported symbols were added or removed in changed source files.',
121
+ detail: 'The aggregate exported-symbol set across changed files is unchanged.',
101
122
  };
102
123
  }
103
124
  /** "no default flip" → no literal default parameter value changed between base and head. */
@@ -1 +1 @@
1
- {"version":3,"file":"claimReconciliation.js","sourceRoot":"","sources":["../../src/analyzers/claimReconciliation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claimReconciliation.js","sourceRoot":"","sources":["../../src/analyzers/claimReconciliation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAsB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEpE;;;;;;;GAOG;AAEH,MAAM,aAAa,GAAG,kBAAkB,CAAC;AACzC,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAC7D,MAAM,WAAW,GAAG,mCAAmC,CAAC;AAExD,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC;AASD,qGAAqG;AACrG,SAAS,eAAe,CAAC,GAAoB;IAC3C,6FAA6F;IAC7F,MAAM,YAAY,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC;IACpC,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IAE1E,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO;YACL,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,6BAA6B;YACpC,MAAM,EAAE,iBAAiB,SAAS,uCAAuC;SAC1E,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,OAAO;YACL,OAAO,EAAE,cAAc;YACvB,KAAK,EAAE,mDAAmD;YAC1D,MAAM,EAAE,kFAAkF;SAC3F,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,YAAY;QACrB,KAAK,EAAE,qDAAqD;QAC5D,MAAM,EAAE,iBAAiB,OAAO,uHAAuH;KACxJ,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAkB,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAE/F;;;;;;;;;;;;;GAaG;AACH,SAAS,uBAAuB,CAAC,GAAoB;IACnD,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,uCAAuC;YAC9C,MAAM,EAAE,8EAA8E;SACvF,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,SAAS;QAEhE,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzE,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI;YAAE,SAAS;QAEzD,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QACjF,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QACjF,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS;YAAE,SAAS,GAAG,IAAI,CAAC;QAC7D,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK;YAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChD,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK;YAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAChD,IAAI,OAAO,CAAC,UAAU;YAAE,WAAW,GAAG,IAAI,CAAC;QAC3C,IAAI,OAAO,CAAC,UAAU;YAAE,WAAW,GAAG,IAAI,CAAC;IAC7C,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,WAAW,KAAK,WAAW;QAAE,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEjF,8FAA8F;IAC9F,oGAAoG;IACpG,4EAA4E;IAC5E,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACnD,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACtD,IAAI,OAAO,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1D,OAAO;YACL,OAAO,EAAE,cAAc;YACvB,KAAK,EAAE,gEAAgE;YACvE,MAAM,EAAE,oDAAoD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;SAChF,CAAC;IACJ,CAAC;IACD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO;YACL,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,+CAA+C;YACtD,MAAM,EAAE,yFAAyF;SAClG,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,uCAAuC;QAC9C,MAAM,EAAE,sEAAsE;KAC/E,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,SAAS,mBAAmB,CAAC,GAAoB,EAAE,KAAY;IAC7D,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACnC,OAAO;YACL,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,iCAAiC;YACxC,MAAM,EAAE,4EAA4E;SACrF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,SAAS;QAChE,MAAM,WAAW,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzE,IAAI,WAAW,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI;YAAE,SAAS;QAEzD,MAAM,YAAY,GAAG,oBAAoB,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/D,MAAM,YAAY,GAAG,oBAAoB,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/D,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,YAAY,EAAE,CAAC;YAC1C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS,CAAC,oCAAoC;YAC1E,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;YACvC,IAAI,OAAO,KAAK,OAAO;gBAAE,SAAS;YAClC,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC1D,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,KAAK,OAAO,MAAM,OAAO,GAAG,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO;YACL,OAAO,EAAE,cAAc;YACvB,KAAK,EAAE,gDAAgD;YACvD,MAAM,EAAE,2BAA2B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG;SACxD,CAAC;IACJ,CAAC;IACD,OAAO;QACL,OAAO,EAAE,MAAM;QACf,KAAK,EAAE,kCAAkC;QACzC,MAAM,EAAE,KAAK,CAAC,GAAG;YACf,CAAC,CAAC,2BAA2B,KAAK,CAAC,GAAG,oCAAoC;YAC1E,CAAC,CAAC,sEAAsE;KAC3E,CAAC;AACJ,CAAC;AAED,MAAM,SAAS,GAA6B;IAC1C,YAAY,EAAE,eAAe;IAC7B,aAAa,EAAE,eAAe;IAC9B,cAAc,EAAE,eAAe;IAC/B,sBAAsB,EAAE,uBAAuB;IAC/C,eAAe,EAAE,uBAAuB;IACxC,uBAAuB,EAAE,uBAAuB;IAChD,iBAAiB,EAAE,mBAAmB;IACtC,mBAAmB,EAAE,mBAAmB;IACxC,qBAAqB,EAAE,mBAAmB;CAC3C,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEvD,MAAM,CAAC,MAAM,mBAAmB,GAAa;IAC3C,EAAE,EAAE,sBAAsB;IAC1B,KAAK,EAAE,sBAAsB;IAC7B,WAAW,EACT,2FAA2F;IAC7F,IAAI,EAAE,sBAAsB;IAC5B,GAAG,CAAC,GAAoB;QACtB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACtC,MAAM,GAAG,GAAmB,QAAQ;gBAClC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;gBACtB,CAAC,CAAC;oBACE,OAAO,EAAE,YAAY;oBACrB,KAAK,EAAE,oBAAoB;oBAC3B,MAAM,EAAE,wCAAwC,KAAK,CAAC,GAAG,kBAAkB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;iBAC1G,CAAC;YAEN,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,sBAAsB;gBAChC,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,CAAC;gBACP,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,KAAK,CAAC,GAAG;aACjB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { Analyzer } from '../types.js';
2
+ interface DeclInfo {
3
+ /** Declaration name (e.g. function/class/const/type name). */
4
+ name: string;
5
+ /** 1-based start line of the declaration (the `function foo(...)` line). */
6
+ line: number;
7
+ }
8
+ /** Collect top-level + class-member declaration names with their declaration line. */
9
+ declare function collectDeclarations(content: string, path: string): DeclInfo[];
10
+ /**
11
+ * Identify identifiers whose declaration changed in the diff for one file. A declaration "changed" if:
12
+ * - its line in base differs from head (body edit / moved), OR
13
+ * - it exists in base but not head (removed/renamed).
14
+ * Returns the set of changed names plus the file's added-line set (for the "comment not freshly added"
15
+ * exclusion).
16
+ */
17
+ declare function changedSymbolNames(baseContent: string | null, headContent: string | null, path: string): {
18
+ names: Set<string>;
19
+ addedLines: Set<number>;
20
+ };
21
+ interface CommentMention {
22
+ /** File containing the comment. */
23
+ file: string;
24
+ /** 1-based line of the comment. */
25
+ line: number;
26
+ /** The symbol token it mentioned. */
27
+ symbol: string;
28
+ }
29
+ /** Find comments in `content` (lines NOT in `addedLines`) that mention any of `symbols` as a token. */
30
+ declare function findStaleCommentMentions(content: string, path: string, symbols: Set<string>, addedLines: Set<number>): CommentMention[];
31
+ export declare const commentCodeDrift: Analyzer;
32
+ export declare const __test__: {
33
+ collectDeclarations: typeof collectDeclarations;
34
+ changedSymbolNames: typeof changedSymbolNames;
35
+ findStaleCommentMentions: typeof findStaleCommentMentions;
36
+ };
37
+ export {};
@@ -0,0 +1,241 @@
1
+ import ts from 'typescript';
2
+ import { isGeneratedPath } from '../paths.js';
3
+ /**
4
+ * `comment-code-drift` — flags a comment/docstring that references a symbol whose **definition changed**
5
+ * in the diff, where the comment itself wasn't freshly added. Completes SPEC §5a (the last "later"
6
+ * analyzer). Catches the classic agent failure: it edits a function's behavior or renames it, but leaves
7
+ * the docstring describing the old behavior/name.
8
+ *
9
+ * The verdict is load-bearing, same as `risky-diff-no-test`: "does this comment describe stale code?" is
10
+ * a *semantic* judgement, and SPEC §3.4 forbids semantic CONTRADICTED. So this analyzer is
11
+ * **UNVERIFIED-only, never CONTRADICTED** — a signal, never a gate. Safe under `--hard-fail` by
12
+ * construction.
13
+ *
14
+ * Trigger (all must hold):
15
+ * 1. A source file in the diff has a CHANGED declaration for identifier `X` (body edit, rename, or
16
+ * removal — gathered from base+head ASTs).
17
+ * 2. A comment/docstring (same file OR another changed file) mentions `X` as a whole token.
18
+ * 3. The comment line was NOT added in this diff (a freshly-added comment is unlikely stale — this is
19
+ * the key false-positive cut).
20
+ *
21
+ * Cross-file: same-file + other changed files (per design). Generated paths and test files are excluded
22
+ * from the "changed symbol" source set (a test mentioning a renamed util is usually fine; a bundle's
23
+ * comments aren't authored).
24
+ */
25
+ const SOURCE_EXT_RE = /\.[cm]?[jt]sx?$/i;
26
+ const TEST_FILE_RE = /(^|[./\\])(test|spec)\.[cm]?[jt]sx?$/i;
27
+ const TEST_DIR_RE = /(^|[/\\])(__tests__|tests?)[/\\]/i;
28
+ function isTestPath(path) {
29
+ return TEST_FILE_RE.test(path) || (TEST_DIR_RE.test(path) && SOURCE_EXT_RE.test(path));
30
+ }
31
+ function scriptKindFor(path) {
32
+ if (/\.tsx$/i.test(path))
33
+ return ts.ScriptKind.TSX;
34
+ if (/\.jsx$/i.test(path))
35
+ return ts.ScriptKind.JSX;
36
+ if (/\.[cm]?ts$/i.test(path))
37
+ return ts.ScriptKind.TS;
38
+ return ts.ScriptKind.JS;
39
+ }
40
+ /** Collect top-level + class-member declaration names with their declaration line. */
41
+ function collectDeclarations(content, path) {
42
+ const sf = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true, scriptKindFor(path));
43
+ const out = [];
44
+ const visit = (node) => {
45
+ const name = declName(node);
46
+ if (name) {
47
+ const line = sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
48
+ out.push({ name, line });
49
+ }
50
+ // Don't descend into function bodies (locals aren't "documented" at module/class level), but DO
51
+ // descend into class bodies to catch method renames.
52
+ if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node)) {
53
+ return;
54
+ }
55
+ ts.forEachChild(node, visit);
56
+ };
57
+ visit(sf);
58
+ return out;
59
+ }
60
+ function declName(node) {
61
+ // Named declarations we care about. NOTE: we handle VariableDeclaration (not VariableStatement) so a
62
+ // `const x` is reported once — visit descends from the statement into its declarators.
63
+ if (ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
64
+ return node.name?.text ?? null;
65
+ }
66
+ if (ts.isVariableDeclaration(node)) {
67
+ return node.name && ts.isIdentifier(node.name) ? node.name.text : null;
68
+ }
69
+ if (ts.isInterfaceDeclaration(node) ||
70
+ ts.isTypeAliasDeclaration(node) ||
71
+ ts.isEnumDeclaration(node)) {
72
+ return node.name.text;
73
+ }
74
+ if (ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isPropertyDeclaration(node)) {
75
+ return ts.isIdentifier(node.name) ? node.name.text : null;
76
+ }
77
+ return null;
78
+ }
79
+ /**
80
+ * Identify identifiers whose declaration changed in the diff for one file. A declaration "changed" if:
81
+ * - its line in base differs from head (body edit / moved), OR
82
+ * - it exists in base but not head (removed/renamed).
83
+ * Returns the set of changed names plus the file's added-line set (for the "comment not freshly added"
84
+ * exclusion).
85
+ */
86
+ function changedSymbolNames(baseContent, headContent, path) {
87
+ const names = new Set();
88
+ const addedLines = new Set();
89
+ if (baseContent == null && headContent == null)
90
+ return { names, addedLines };
91
+ // Determine added/removed lines by a cheap line-set diff (the ChangedFile.addedLines only has ADDS;
92
+ // we also need REMOVED base lines to spot a renamed old name).
93
+ const baseLines = baseContent ? new Set(baseContent.split('\n')) : new Set();
94
+ const headLines = headContent ? headContent.split('\n') : [];
95
+ if (headContent) {
96
+ headLines.forEach((l, i) => {
97
+ if (!baseLines.has(l))
98
+ addedLines.add(i + 1);
99
+ });
100
+ }
101
+ // Removed = base lines absent from head.
102
+ const removedLines = new Set();
103
+ const headLineSet = new Set(headLines);
104
+ if (baseContent) {
105
+ baseContent.split('\n').forEach((l, i) => {
106
+ if (!headLineSet.has(l))
107
+ removedLines.add(i + 1);
108
+ });
109
+ }
110
+ const baseDecls = baseContent ? collectDeclarations(baseContent, path) : [];
111
+ const headDecls = headContent ? collectDeclarations(headContent, path) : [];
112
+ const headByName = new Map(headDecls.map((d) => [d.name, d.line]));
113
+ // 1) base declarations removed from head (rename/removal) → old name is "changed".
114
+ for (const d of baseDecls) {
115
+ if (!headByName.has(d.name))
116
+ names.add(d.name);
117
+ }
118
+ // 2) declarations present in both whose declaration line is on a removed line → body edit or moved.
119
+ for (const d of headDecls) {
120
+ const was = baseDecls.find((b) => b.name === d.name);
121
+ if (was && (removedLines.has(was.line) || addedLines.has(d.line))) {
122
+ names.add(d.name);
123
+ }
124
+ }
125
+ return { names, addedLines };
126
+ }
127
+ /** Find comments in `content` (lines NOT in `addedLines`) that mention any of `symbols` as a token. */
128
+ function findStaleCommentMentions(content, path, symbols, addedLines) {
129
+ if (symbols.size === 0 || !content)
130
+ return [];
131
+ const sf = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true, scriptKindFor(path));
132
+ const mentions = [];
133
+ const symbolSet = new Set([...symbols].filter((s) => s && s.length >= 2 && !COMMON_WORDS.has(s.toLowerCase())));
134
+ if (symbolSet.size === 0)
135
+ return [];
136
+ const isComment = (kind) => kind === ts.SyntaxKind.SingleLineCommentTrivia ||
137
+ kind === ts.SyntaxKind.MultiLineCommentTrivia;
138
+ // `forEachLeadingCommentRange` runs per-node, so the same comment is reported once per following
139
+ // node. Track positions we've already inspected to emit each comment at most once.
140
+ const seenCommentPos = new Set();
141
+ const fullText = sf.text;
142
+ const visit = (node) => {
143
+ const start = node.getFullStart();
144
+ ts.forEachLeadingCommentRange(fullText, start, (pos, _end, kind) => {
145
+ if (!isComment(kind) || seenCommentPos.has(pos))
146
+ return;
147
+ seenCommentPos.add(pos);
148
+ const line = sf.getLineAndCharacterOfPosition(pos).line + 1;
149
+ if (addedLines.has(line))
150
+ return; // freshly-added comment → unlikely stale
151
+ const text = fullText.slice(pos, _end);
152
+ const toks = new Set(text.toLowerCase().split(/[^a-z0-9_$]+/i).filter(Boolean));
153
+ for (const sym of symbolSet) {
154
+ if (toks.has(sym) || toks.has(sym.toLowerCase())) {
155
+ mentions.push({ file: path, line, symbol: sym });
156
+ }
157
+ }
158
+ });
159
+ ts.forEachChild(node, visit);
160
+ };
161
+ visit(sf);
162
+ return mentions;
163
+ }
164
+ // Words too common to treat as a "symbol reference" even if they happen to be a declaration name.
165
+ const COMMON_WORDS = new Set([
166
+ 'data', 'value', 'item', 'result', 'error', 'options', 'config', 'props', 'state', 'type',
167
+ ]);
168
+ export const commentCodeDrift = {
169
+ id: 'comment-code-drift',
170
+ title: 'Comment may describe changed code',
171
+ description: 'Signals a comment/docstring that references a symbol whose definition changed in the diff (body ' +
172
+ 'edit, rename, or removal), where the comment itself was not freshly added. Never blocks: comment ' +
173
+ 'staleness is semantic, so it emits UNVERIFIED only.',
174
+ kind: 'claim-independent',
175
+ run(ctx) {
176
+ // No base ref → can't compare; degrade to silence (no false signal).
177
+ if (!ctx.base || !ctx.readBaseFile)
178
+ return [];
179
+ // 1) Gather changed symbols per changed source file (excluding tests/generated).
180
+ const changedPerFile = new Map();
181
+ for (const f of ctx.changedFiles) {
182
+ if (f.status === 'deleted' || isTestPath(f.path) || !SOURCE_EXT_RE.test(f.path))
183
+ continue;
184
+ if (isGeneratedPath(f.path))
185
+ continue;
186
+ const baseContent = ctx.readBaseFile(f.path);
187
+ const headContent = ctx.readFile(f.path);
188
+ if (baseContent == null && headContent == null)
189
+ continue;
190
+ const info = changedSymbolNames(baseContent, headContent, f.path);
191
+ if (info.names.size > 0)
192
+ changedPerFile.set(f.path, info);
193
+ }
194
+ if (changedPerFile.size === 0)
195
+ return [];
196
+ // Union of all changed symbol names across changed files (for cross-file comment scan).
197
+ const allChangedNames = new Set();
198
+ for (const info of changedPerFile.values())
199
+ for (const n of info.names)
200
+ allChangedNames.add(n);
201
+ if (allChangedNames.size === 0)
202
+ return [];
203
+ // 2) Scan comments in each changed file (same-file + cross-file within the changed set).
204
+ const findings = [];
205
+ for (const f of ctx.changedFiles) {
206
+ if (f.status === 'deleted')
207
+ continue;
208
+ // Comments in test files still count (a test docstring can drift too), but generated paths don't.
209
+ if (!SOURCE_EXT_RE.test(f.path) || isGeneratedPath(f.path))
210
+ continue;
211
+ const content = ctx.readFile(f.path);
212
+ if (content == null)
213
+ continue;
214
+ const mentions = findStaleCommentMentions(content, f.path, allChangedNames, f.addedLines);
215
+ for (const m of mentions) {
216
+ findings.push({
217
+ analyzer: 'comment-code-drift',
218
+ verdict: 'UNVERIFIED',
219
+ file: m.file,
220
+ line: m.line,
221
+ title: 'Comment may describe code that changed',
222
+ detail: `A comment here mentions '${m.symbol}', whose definition changed in this PR. The comment ` +
223
+ `may now be stale. 'Stale' is a heuristic, so this never blocks — verify the wording is ` +
224
+ `still accurate.`,
225
+ });
226
+ }
227
+ }
228
+ // Dedupe by (file, line, symbol).
229
+ const seen = new Set();
230
+ return findings.filter((f) => {
231
+ const key = `${f.file}:${f.line}:${(f.detail.match(/'([^']+)'/) ?? ['', ''])[1]}`;
232
+ if (seen.has(key))
233
+ return false;
234
+ seen.add(key);
235
+ return true;
236
+ });
237
+ },
238
+ };
239
+ // Exposed for unit tests.
240
+ export const __test__ = { collectDeclarations, changedSymbolNames, findStaleCommentMentions };
241
+ //# sourceMappingURL=commentCodeDrift.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commentCodeDrift.js","sourceRoot":"","sources":["../../src/analyzers/commentCodeDrift.ts"],"names":[],"mappings":"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"}