foundation(accuracy): B1 spans + B3 stable endpoint IDs + A4 AST↔regex parity - #90
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…issue #80) After T4 made AstCallMatch.span required, four detector test fixtures stopped compiling. They were also missing the pre-existing required `confidence` field on the base object — fixing both at once so the scanner-tests build clears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ures - ast-scanner: extend isInternalImport to filter node:* prefix and bare built-in module names so fs/path/assert don't surface as SDK matches - fingerprint-registry test: expect elevenlabs (11 providers) and derive count from ALL_PROVIDERS.length - compression test: loosen two estimatedMonthlyCost==null assertions — compressClusters now computes a real cost from local pricing - export test: add required costLeaks/providerSummary fields to two ExportedContext fixtures - tsconfig.scanner-tests: exclude src/test/fixtures (recost-mock-calls imports SDKs not installed in the test env)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…#82) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pure parity-runner library plus the human/machine-readable allowlist doc.
The runner walks a fixture corpus, runs AST and regex paths in isolation
(without core-scanner's AST-coverage masking), normalises both result sets
to {provider, method, line} tuples, and emits divergences.
parseAllowlist() reads the YAML block in PARITY.md so the markdown doc is
the single source of truth for documented intentional divergences.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Corpus for the AST↔regex parity runner. Seven fixtures total: Basic agreement (both paths should detect): - openai-basic.ts: direct OpenAI SDK call - anthropic-basic.ts: direct Anthropic SDK call - stripe-basic.ts: direct Stripe SDK call - fetch-known-host.ts: raw fetch() to a known host Documented divergence / regression guards: - wrapped-call.ts: AST follows wrapper back to SDK; regex sees only the wrapper invocation. Allowlisted as astOnly in PARITY.md. - object-literal-only.ts: pricing-table-style data — both paths should produce zero matches (A6 regression guard). - python-requests.py: requests.post() to a known host — both paths should attribute to openai via host lookup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First run surfaces two AST-only divergences (fetch-known-host.ts L2, python-requests.py L4) — both cases where AST does host-based provider attribution and regex does not. Triaged in follow-up commits. Fixture dir is resolved back to the source tree because fixtures are excluded from tsc compilation (tsconfig.scanner-tests.json) by design. The test is intentionally red on this commit; follow-up commits in Task 5 categorize and resolve each divergence. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…llback (issue #76) generic-http.ts previously hard-coded provider: "generic-http" for every fetch/axios/requests match, even when the URL had a known host. The AST scanner already attributes such calls via lookupHost(). Bring the regex path into parity by reusing the same host registry: when the URL host maps to a known provider, emit that provider id; otherwise fall back to "generic-http" as before. Also: the previous fetch fallback pattern matched fetch("url"...) without caring whether the call had an unparsed options object on subsequent lines, which produced wrong-method GET emits for multi-line POST/PUT calls. Tighten it to require a closing paren on the same line so the fallback only fires for actual no-options fetches; multi-line option objects are AST's job (separately documented in PARITY.md). Surfaces and resolves one of the two divergences flagged by the new parity test in src/test/parity.test.ts. The remaining multi-line cases are documented in docs/accuracy/PARITY.md in the next commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fetch-known-host.ts and python-requests.py both contain HTTP calls whose options object or URL argument spans multiple source lines. The regex matchers operate one line at a time by design, so they cannot stitch those constructs together; the AST scanner sees the full call expression structurally and attributes correctly. Documented in the YAML allowlist as astOnly with explicit reasons so future maintainers know why these divergences are accepted rather than introducing speculative multi-line regex passes. After this commit: PASS parity (2 documented divergences, 0 unannotated) Closes the iterative triage for issue #76. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Acceptance criteria in detection.md § A4 all check [x]:
- Parity test runs in CI on every PR (test.yml → npm test → test:scanner)
- Every divergence is fixed or annotated in PARITY.md
- Same line reported by both paths (enforced by the runner — same-line
disagreement always fails)
PROGRESS.md updated: A4 row, batch table, task checklist, activity log.
Final state: PASS parity (2 documented divergences, 0 unannotated).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ser-accuracy-2GYtd # Conflicts: # package.json # src/scanner/source-span.ts # src/webview-provider.ts
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR implements three interrelated roadmap items: span-based source locations (B1), stable endpoint IDs (B3), and AST↔regex parity validation (A4). It introduces source span infrastructure throughout the scanner and intelligence layers, adds deterministic endpoint ID hashing, includes comprehensive fixture-based parity testing with an allowlist, and updates the webview to support span-based file navigation. ChangesSpan Infrastructure and Source Location Tracking
Endpoint ID Generation and Integration
Span-Based Editor Navigation
AST↔Regex Parity Testing
Test Updates and New Suites
CI and Documentation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Flagged by github-code-quality bot. Runtime behavior unchanged — the parity harness uses console.error/process.exit, not assert.
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (4)
src/intelligence/__tests__/builder.test.ts (1)
230-230: ⚡ Quick winTighten the ID assertion to validate the full format.
Current regex is prefix-only, so malformed trailing characters still pass.
Proposed fix
- assert.ok(calls.every((apiCall) => /^ep_[a-z0-9]+/.test(apiCall.id))); + assert.ok(calls.every((apiCall) => /^ep_[a-z0-9]+(?:_L\d+)?$/.test(apiCall.id)));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/intelligence/__tests__/builder.test.ts` at line 230, The test is only asserting a prefix because the regex /^ep_[a-z0-9]+/ lacks an end anchor; update the assertion in the calls.every((apiCall) => /^ep_[a-z0-9]+/.test(apiCall.id)) to validate the entire id (e.g., use /^ep_[a-z0-9]+$/) so malformed trailing characters no longer pass.src/test/source-span.test.ts (1)
32-32: ⚡ Quick winAdd newline at end of file.
Line 32 is missing a trailing newline, which violates typical file formatting conventions and may cause issues with some tools.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/source-span.test.ts` at line 32, The file ends with the line containing the top-level IIFE catch handler "})().catch((err) => { console.error(err); process.exit(1); });" but is missing a trailing newline; simply add a single newline character at end-of-file so the file ends with a newline after that statement.src/scanner/core-scanner.ts (1)
177-182: 💤 Low valueConsider extracting duplicated span construction.
The line-wide span creation logic is duplicated in two locations (route matching and generic HTTP matching). While not a correctness issue, extracting this into a helper would improve maintainability.
♻️ Proposed extraction
+function lineWideSpan(lineNum: number, lineText: string): SourceSpan { + return { + startLine: lineNum, + startColumn: 0, + endLine: lineNum, + endColumn: lineText.length, + }; +} + for (const route of routeMatches) { if (!isHighConfidenceUrl(route.url)) continue; const key = `${entry.relativePath}:${lineNum}:${route.method}:${route.url}:${route.library}`; if (dedupe.has(key)) continue; dedupe.add(key); - const span: SourceSpan = { - startLine: lineNum, - startColumn: 0, - endLine: lineNum, - endColumn: line.length, - }; + const span = lineWideSpan(lineNum, line); allCalls.push({Also applies to: 208-213
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/scanner/core-scanner.ts` around lines 177 - 182, Extract the duplicated line-wide SourceSpan creation into a small helper (e.g. makeLineSpan or buildLineSpan) that accepts the line number and the line text/length and returns a SourceSpan with startLine=lineNum, startColumn=0, endLine=lineNum, endColumn=line.length; replace the two duplicated constructions used in the route-matching and generic-HTTP-matching code paths in core-scanner.ts with calls to this helper (references: SourceSpan, the span object creation block, and the variables lineNum and line) to improve maintainability.package.json (1)
199-199: ⚡ Quick winConsider refactoring the test script for maintainability.
The
test:scannerscript is now a single 1,500+ character line chaining 30+ test files. This makes it difficult to read, maintain, and debug. If any test fails, subsequent tests don't run.♻️ Alternative approaches
Option 1: Use a test runner script that discovers
dist-test/**/*.test.js:"test:scanner": "tsc -p tsconfig.scanner-tests.json && node scripts/run-tests.js"Option 2: Use
npm-run-allto run tests in parallel/series:"test:scanner": "tsc -p tsconfig.scanner-tests.json && npm-run-all test:scanner:*", "test:scanner:patterns": "node dist-test/test/scanner-patterns.test.js", "test:scanner:workspace": "node dist-test/test/workspace-scanner.test.js", ...Option 3: At minimum, break into multiple lines with
&&for readability:"test:scanner": "tsc -p tsconfig.scanner-tests.json && node dist-test/test/scanner-patterns.test.js && node dist-test/test/workspace-scanner.test.js && ..."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@package.json` at line 199, The "test:scanner" npm script is an overly long single-line command that chains many test files and is hard to maintain; split it into a maintainable approach by replacing the single "test:scanner" entry with one of the recommended patterns: (a) point "test:scanner" to a test runner script (e.g., "node scripts/run-tests.js") that discovers dist-test/**/*.test.js while still running tsc -p tsconfig.scanner-tests.json first, or (b) create per-file scripts like "test:scanner:patterns", "test:scanner:workspace", etc., and make "test:scanner" run them via npm-run-all (or with "&&" in series), or (c) at minimum break the long command into a readable chained command using multiple && lines; update package.json's "test:scanner" key and add the helper scripts (e.g., "test:scanner:patterns") accordingly and ensure the tsc invocation (tsc -p tsconfig.scanner-tests.json) remains before running tests so compiled files under dist-test are used.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/ast/ast-scanner.ts`:
- Line 601: The propagated match construction in matches.push is collapsing
multi-line spans by using pointSpan(line, column); update the span assignment in
the propagated objects (the matches.push call) to preserve the original full
call span (use m.span if present or merge m.span with the current node/span)
instead of replacing it with pointSpan; change each occurrence that sets span:
pointSpan(...) (the ones around matches.push) to carry forward m.span (or a
merged span) so wrapper/callback/middleware propagated detections keep their
full multi-line span and precise click-selection fidelity.
In `@src/ast/enclosing-function.ts`:
- Around line 37-44: The traversal currently stops and returns null for
anonymous arrow_function/function_expression when not bound to a
variable_declarator; instead, remove the early return so traversal continues up
the tree to find an enclosing named function. In the block handling current.type
=== "arrow_function" || "function_expression" (and after checking decl?.type ===
"variable_declarator" and possibly returning the lhs identifier), do not return
null — allow the function to advance current = current.parent (or fall through)
so outer function declarations or function_declaration names can still be
discovered.
In `@src/scanner/patterns/generic-http.ts`:
- Around line 22-27: The regex in the fetch pattern (sdk: "fetch", regex:
/fetch\(\s*['"`]([^'"`\n]+)['"`]\s*\)/gi) still matches calls that have a second
argument (options) when the first arg is a template/identifier form; update the
regex to ensure it only matches single-argument fetch calls by forbidding a
comma after the first argument—e.g., add a negative lookahead like (?!\s*,)
after the closing quote/backtick/identifier so fetch(..., options) is not
matched; modify the pattern used in generic-http.ts (the regex for sdk "fetch")
accordingly and keep flags consistent.
In `@src/test/url-template.test.ts`:
- Around line 4-7: The test helper run() currently calls fn() without awaiting
async results, so asynchronous rejections escape the try/catch; change the
signature of run to accept an async function (e.g., fn: () => Promise<void>) and
await its result inside the try block (await fn()) so any returned rejected
promise is caught and causes the test to fail as intended; update any callers if
needed to pass async functions/promises to run().
In `@src/webview-provider.ts`:
- Around line 749-756: The creation of the vscode.Range from the unvalidated
span can throw and silently fail; before constructing the Range in the code that
computes range (the span ? new vscode.Range(...) : ...) and the similar block at
lines 763–766, validate and clamp span.startLine, span.endLine,
span.startColumn, and span.endColumn to the document bounds (>=1 and <= total
lines/line length) and ensure end positions are not before start positions; if
the span is out-of-bounds or invalid, fall back to the line-based Range or
undefined and log or surface a small error so the click-open path does not
silently fail.
---
Nitpick comments:
In `@package.json`:
- Line 199: The "test:scanner" npm script is an overly long single-line command
that chains many test files and is hard to maintain; split it into a
maintainable approach by replacing the single "test:scanner" entry with one of
the recommended patterns: (a) point "test:scanner" to a test runner script
(e.g., "node scripts/run-tests.js") that discovers dist-test/**/*.test.js while
still running tsc -p tsconfig.scanner-tests.json first, or (b) create per-file
scripts like "test:scanner:patterns", "test:scanner:workspace", etc., and make
"test:scanner" run them via npm-run-all (or with "&&" in series), or (c) at
minimum break the long command into a readable chained command using multiple &&
lines; update package.json's "test:scanner" key and add the helper scripts
(e.g., "test:scanner:patterns") accordingly and ensure the tsc invocation (tsc
-p tsconfig.scanner-tests.json) remains before running tests so compiled files
under dist-test are used.
In `@src/intelligence/__tests__/builder.test.ts`:
- Line 230: The test is only asserting a prefix because the regex
/^ep_[a-z0-9]+/ lacks an end anchor; update the assertion in the
calls.every((apiCall) => /^ep_[a-z0-9]+/.test(apiCall.id)) to validate the
entire id (e.g., use /^ep_[a-z0-9]+$/) so malformed trailing characters no
longer pass.
In `@src/scanner/core-scanner.ts`:
- Around line 177-182: Extract the duplicated line-wide SourceSpan creation into
a small helper (e.g. makeLineSpan or buildLineSpan) that accepts the line number
and the line text/length and returns a SourceSpan with startLine=lineNum,
startColumn=0, endLine=lineNum, endColumn=line.length; replace the two
duplicated constructions used in the route-matching and generic-HTTP-matching
code paths in core-scanner.ts with calls to this helper (references: SourceSpan,
the span object creation block, and the variables lineNum and line) to improve
maintainability.
In `@src/test/source-span.test.ts`:
- Line 32: The file ends with the line containing the top-level IIFE catch
handler "})().catch((err) => { console.error(err); process.exit(1); });" but is
missing a trailing newline; simply add a single newline character at end-of-file
so the file ends with a newline after that statement.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f94fe3e7-fa60-40d3-8524-3259b7300c35
📒 Files selected for processing (47)
docs/accuracy/PARITY.mddocs/accuracy/detection.mddocs/accuracy/traceability.mddocs/superpowers/plans/PROGRESS.mdpackage.jsonsrc/analysis/types.tssrc/ast/ast-scanner.tssrc/ast/call-visitor.tssrc/ast/enclosing-function.tssrc/intelligence/__tests__/builder.test.tssrc/intelligence/__tests__/compression.test.tssrc/intelligence/builder.tssrc/intelligence/types.tssrc/messages.tssrc/scan-results.tssrc/scanner/core-scanner.tssrc/scanner/endpoint-id.tssrc/scanner/patterns/generic-http.tssrc/scanner/patterns/types.tssrc/scanner/source-span.tssrc/scanner/url-template.tssrc/test/ast-batch-detector.test.tssrc/test/ast-cache-detector.test.tssrc/test/ast-call-visitor.test.tssrc/test/ast-concurrency-detector.test.tssrc/test/ast-cross-file-resolver.test.tssrc/test/enclosing-function.test.tssrc/test/endpoint-id.test.tssrc/test/fingerprint-registry.test.tssrc/test/fixtures/parity/anthropic-basic.tssrc/test/fixtures/parity/fetch-known-host.tssrc/test/fixtures/parity/object-literal-only.tssrc/test/fixtures/parity/openai-basic.tssrc/test/fixtures/parity/python-requests.pysrc/test/fixtures/parity/stripe-basic.tssrc/test/fixtures/parity/wrapped-call.tssrc/test/parity.test.tssrc/test/parity.tssrc/test/python-waste-detector.test.tssrc/test/source-span.test.tssrc/test/url-template.test.tssrc/webview-provider.tssrc/webview/scan-publishing-handler.tssrc/webview/simulation-handler.tstsconfig.scanner-tests.jsonwebview/src/components/ResultsPage.tsxwebview/src/types.ts
Five actionable findings from the review on PR #90: - **B1 span fidelity** (`src/ast/ast-scanner.ts`): propagated matches in the wrapper/callback/middleware passes were collapsing multi-line spans to `pointSpan(line, column)`. Carry the original `callInfo.span` through so click-back selects the full call expression. - **B3 enclosing function** (`src/ast/enclosing-function.ts`): the walk returned `null` immediately for anonymous `arrow_function` / `function_expression` not bound to a `variable_declarator`, which swallowed common cases like `[].forEach(x => openai.create(x))` inside a named function. Let traversal continue so the named ancestor wins. Destructured bindings still return null (no single name to attribute the call to). - **Parity / generic-http** (`src/scanner/patterns/generic-http.ts`): the template-literal and identifier fetch patterns still matched the multi-arg form, so `fetch(\`url\`, { method: "POST" })` and `fetch(urlVar, { ... })` could emit a wrong-method GET fallback. Anchor both with `\s*\)` to keep them single-arg only — multi-line options are AST's job. - **url-template.test.ts**: `run()` invoked `fn()` without awaiting, so async rejections would silently pass. Await it and accept `() => void | Promise<void>`. - **webview-provider.ts handleOpenFile**: stale spans (e.g. from a re-scan after the file shrank) could throw inside `vscode.Range` and disappear into the silent catch. Clamp `startLine`, `endLine`, `startColumn`, `endColumn` to the document bounds so click-back always lands somewhere visible. Plus one nitpick: - `builder.test.ts` ID regex anchor: `/^ep_[a-z0-9]+/` was prefix-only; tighten to `/^ep_[a-z0-9]+(?:_L\d+)?$/` to also reject malformed trailing characters. Skipped: the EOF-newline nitpick on source-span.test.ts (the file already ends with `\n`), the package.json `test:scanner` length nitpick (style only, out of scope), and the core-scanner span helper extraction (low value per the reviewer's own classification). Full test suite still green: `PASS parity (2 documented divergences, 0 unannotated)`.
Flagged by github-code-quality (CodeQL). The previous fix removed all node consumers in the callback/iteration and middleware loops; the destructure was left over.
Summary
This branch lands the three foundation plans from the parser-accuracy
roadmap (see
docs/accuracy/README.md):carries a
SourceSpanfrom AST throughEndpointCallSiteto thewebview, so click-back can select the full multi-line call expression
instead of just the start line.
computeEndpointId()(URL-template masker + enclosing-function extractor) so an endpoint's
identity survives non-structural edits. Persisted simulator scenarios
now reattach across re-scans; orphaned records are pruned (guarded so
empty scans never destroy state).
(
src/test/parity.ts) walkssrc/test/fixtures/parity/, runs bothdetection paths in isolation (no AST-coverage masking), and fails CI
on any unannotated divergence in
(provider, method, line). Firstaudit fixed one regex bug (
generic-http.tsnow host-attributesknown hosts via
lookupHost()and drops the wrong-method GETfallback for multi-line fetch options) and documented two structural
multi-line cases in
docs/accuracy/PARITY.md.Closes #76. Closes #80. Closes #82.
Merge notes
origin/maininto this branch viagit merge(no rebase) sothe SHAs referenced in commit messages,
PROGRESS.md, and the A4handoff memory remain intact.
src/webview/scan-publishing-handler.ts::mergeRemoteAndLocalEndpoints(the function moved there during PR Audit remediation: full P0–P3 fix pass (2026-05-11 plan) #87).
pruneSavedScenariosAgainstmoved tosrc/webview/simulation-handler.ts::pruneAgainst(wheresavedScenariosnow lives) and is invoked from the scanpublishing flow via a new
pruneSavedScenariosAgainstcontextcallback.
webview-provider.tskept main's compact post-extraction shapeplus B1's
SourceSpanimport and theopenFilespan-awareselection logic.
package.jsontest:scannerscript combines main'sextension-activation.test.jsand this branch's parity /source-span / url-template / enclosing-function / endpoint-id
tests.
esbuild ^0.28andopenai ^4.104ranges from mainintact.
src/webview/simulation-handler.ts(added by PR Audit remediation: full P0–P3 fix pass (2026-05-11 plan) #87) survivedthe merge.
Notable design notes
core-scanner.scanFiles()masksregex output on AST-covered lines, which would silently hide most
parity gaps. The runner deliberately calls each path on raw source.
generic-httpmatches are filtered in parity normalisation:the regex layer's bare-HTTP detection without a host map produces
library: "generic-http", which has no provider. After the fix,known hosts elevate to the concrete provider id (e.g.
openai).multi-line
fetch("url", { method: "POST" })or a Pythonrequests.post(\n "url",\n ...)together. AST does thisstructurally. Two
astOnly: trueallowlist entries with concretereasons.
computeEndpointId(provider, urlTemplate, enclosingFunction, filePath)hashes the four inputs. URL templatemasker collapses numeric/uuid path segments so
…/users/42and…/users/99get the same ID. Enclosing-function extractor usesAST when available with a 7-day persistence override during the
rollout, documented in commit
b9e54be.Tests
src/test/parity.test.ts— new, runs the parity runner against thefixture corpus.
src/test/endpoint-id.test.ts— 13 cases covering hash determinism,refactor stability, file-path normalization, and end-to-end behaviour.
src/test/url-template.test.ts,src/test/enclosing-function.test.ts— extracted unit suites for the two ID components.
src/test/source-span.test.ts— span helper unit tests.required
spanfield onAstCallMatchandEndpointCallSite.Full suite is green locally.
test:scannerinvocation inpackage.jsonnow includes
parity.test.js. Final line isPASS parity (2 documented divergences, 0 unannotated).Pending manual verification (post-merge, before sign-off)
Two acceptance criteria require a manual run in the Extension
Development Host because they exercise UI selection / persistence
across editor sessions:
docs/accuracy/traceability.md§ B1)— F5 the dev host, scan a workspace containing a multi-line
await openai.chat.completions.create({ ... }), click thatendpoint row, confirm the selection covers from
awaitthroughthe closing
).docs/accuracy/traceability.md§ B3) — F5 the dev host, save a simulator scenario, edit any
unrelated file, re-scan, confirm the scenario still loads
(endpoint IDs survived the non-structural change).
These are gated checkboxes in
docs/accuracy/traceability.md; flipthem to
[x]and amend in a follow-up commit once green.Test plan
testsworkflow,npm testincludes parity).docs/accuracy/PARITY.md— confirm the twoastOnlyreasons read as honest structural limits, not as
"rubber-stamp every divergence".
src/webview/simulation-handler.tssurvived the merge(was added by PR Audit remediation: full P0–P3 fix pass (2026-05-11 plan) #87 — must not be deleted).
main.🤖 Generated with Claude Code
Generated by Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Documentation