Skip to content

Ambiguous anchors fail the run, the editor understands reference blocks, and ADR 0016 has no open questions - #113

Merged
aslakhellesoy merged 3 commits into
mainfrom
reference-anchors-and-lsp
Sep 14, 2026
Merged

aslakhellesoy merged 3 commits into
mainfrom
reference-anchors-and-lsp

Conversation

@aslakhellesoy

@aslakhellesoy aslakhellesoy commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Closes #106, #107, #108, #109, #110. Stacked on #112 (which is stacked on #104) — the diff here is the three commits on top.

#106 — ambiguous anchors fail the run, in every port

ADR 0016 listed the error and nothing detected it. Two headings that slug identically (## Setup twice — GitHub's #setup and #setup-1) are indistinguishable to the scope-stack rule, so a reference to #setup spliced both sections in and stayed green.

Doc now carries headings (every heading block, in order), and plan() refuses a reference whose anchor names more than one of them: an ambiguous-anchor error on the reference block, like the other three reference errors, and nothing is spliced in until it is fixed. The rule is "the anchor a reference names belongs to one heading", not "unique headings in any referenced file" — a duplicate nobody links to is harmless.

  • The doc artifact pins the outline, so every bundle's doc.json gains headings (all 21 regenerated by the TypeScript reference; every port matches by content).
  • 22-reference-ambiguous-anchor gates the diagnostic across all seven ports.
  • TypeScript, Python, Ruby and .NET carry a message naming the target file and the headings' line numbers; Java, Rust and Go stay message-less, as their other reference diagnostics are.

(The first push of this PR had this as a TypeScript-only lint check. That was reversed after review; deviation 2 in the ADR records why and what moved.)

#107 — the editor at a reference block

  • Go to Definition lands on the heading the anchor names (top of file for a whole-file reference; one link per heading for an ambiguous anchor, so VS Code peeks both).

  • Hover shows the steps the reference splices in, nested references resolved, with a step from a third file saying which:

    **A stocked library** · `./shared/library.md#a-stocked-library`
    
    1. The library holds "Dune"
    2. Fees are enabled — from `billing.md`
    

    The section is consumed, so the index holds no plan for it; the hover plans the target as if nothing referenced it and keeps the section's examples, reusing the planner's own splice semantics.

  • Diagnostics already reached the editor; a test pins that they sit on the block.

Nothing changes in the VS Code extension — hoverProvider and definitionProvider were already on.

#108, #109, #110 — decided and documented

Recorded in the ADR (every open question is now resolved) and in reference/examples.mdx:

Gate

make check at the repo root exits 0: all seven ports built and tested (bundle 22 exercised in each), parity, commit lint, and every adapter smoke contract. Also green on their own: pnpm check (94 files, 682 tests), pnpm -r build, and the website build.

🤖 Generated with Claude Code

https://claude.ai/code/session_01RQVAKGfMEKPbT919FqAChP

@aslakhellesoy
aslakhellesoy force-pushed the reference-anchors-and-lsp branch from 180eee3 to 7e15c04 Compare September 14, 2026 09:56
@aslakhellesoy aslakhellesoy changed the title Ambiguous anchors are reported, and the editor understands reference blocks (closes #106, #107) Ambiguous anchors fail the run, the editor understands reference blocks, and ADR 0016 has no open questions Sep 14, 2026
@aslakhellesoy
aslakhellesoy requested a lite review from Copilot September 14, 2026 10:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds cross-port ambiguous-anchor diagnostics, LSP support for reference blocks, and documentation/conformance updates for ADR 0016 decisions.

Changes:

  • Records document headings and rejects duplicate reference anchors across all ports.
  • Adds reference hover and go-to-definition behavior in the LSP.
  • Resolves ADR questions and adds bundle 22 plus regenerated artifacts.
File summaries
File Description
typescript/packages/website/src/content/docs/reference/lint.md Updated as part of this pull request.
typescript/packages/website/src/content/docs/reference/examples.mdx Updated as part of this pull request.
typescript/packages/website/src/content/docs/reference/editor-support.mdx Updated as part of this pull request.
typescript/packages/website/src/content/docs/how-to/share-setup-between-examples.md Updated as part of this pull request.
typescript/packages/lsp/tests/handlers.test.ts Updated as part of this pull request.
typescript/packages/lsp/src/handlers.ts Updated as part of this pull request.
typescript/packages/language/tests/index-workspace.test.ts Updated as part of this pull request.
typescript/packages/core/tests/structurer.test.ts Updated as part of this pull request.
typescript/packages/core/tests/reference.test.ts Updated as part of this pull request.
typescript/packages/core/tests/conformance.test.ts Updated as part of this pull request.
typescript/packages/core/src/structurer.ts Updated as part of this pull request.
typescript/packages/core/src/plan.ts Updated as part of this pull request.
typescript/packages/core/src/index.ts Updated as part of this pull request.
typescript/packages/core/src/diagnostics.ts Updated as part of this pull request.
typescript/packages/core/src/conformance.ts Updated as part of this pull request.
typescript/packages/core/src/ast.ts Updated as part of this pull request.
typescript/packages/cli/tests/lint.test.ts Updated as part of this pull request.
typescript/packages/cli/src/lint.ts Updated as part of this pull request.
rust/varar/tests/conformance.rs Updated as part of this pull request.
rust/core/tests/ast_test.rs Updated as part of this pull request.
rust/core/src/structurer.rs Updated as part of this pull request.
rust/core/src/plan.rs Updated as part of this pull request.
rust/core/src/diagnostics.rs Updated as part of this pull request.
rust/core/src/conformance.rs Updated as part of this pull request.
rust/core/src/ast.rs Updated as part of this pull request.
ruby/packages/core/spec/varar/core/plan_spec.rb Updated as part of this pull request.
ruby/packages/core/lib/varar/core/structurer.rb Updated as part of this pull request.
ruby/packages/core/lib/varar/core/plan.rb Updated as part of this pull request.
ruby/packages/core/lib/varar/core/diagnostics.rb Updated as part of this pull request.
ruby/packages/core/lib/varar/core/conformance.rb Updated as part of this pull request.
ruby/packages/core/lib/varar/core/ast.rb Updated as part of this pull request.
python/packages/core/tests/test_structurer.py Updated as part of this pull request.
python/packages/core/tests/test_plan.py Updated as part of this pull request.
python/packages/core/tests/test_conformance.py Updated as part of this pull request.
python/packages/core/src/varar_core/structurer.py Updated as part of this pull request.
python/packages/core/src/varar_core/plan.py Updated as part of this pull request.
python/packages/core/src/varar_core/diagnostics.py Updated as part of this pull request.
python/packages/core/src/varar_core/conformance.py Updated as part of this pull request.
python/packages/core/src/varar_core/ast.py Updated as part of this pull request.
java/varar/src/test/java/dev/varar/ConformanceTest.java Updated as part of this pull request.
java/kotlin/src/test/kotlin/dev/varar/kotlin/ConformanceTest.kt Updated as part of this pull request.
java/core/src/test/java/dev/varar/core/StructurerTest.java Updated as part of this pull request.
java/core/src/test/java/dev/varar/core/AstTest.java Updated as part of this pull request.
java/core/src/main/java/dev/varar/core/Structurer.java Updated as part of this pull request.
java/core/src/main/java/dev/varar/core/Plan.java Updated as part of this pull request.
java/core/src/main/java/dev/varar/core/Diagnostics.java Updated as part of this pull request.
java/core/src/main/java/dev/varar/core/Conformance.java Updated as part of this pull request.
java/core/src/main/java/dev/varar/core/Ast.java Updated as part of this pull request.
go/core/structurer.go Updated as part of this pull request.
go/core/plan.go Updated as part of this pull request.
go/core/diagnostics.go Updated as part of this pull request.
go/core/conformance.go Updated as part of this pull request.
go/core/ast.go Updated as part of this pull request.
go/conformance/conformance_test.go Updated as part of this pull request.
go/conformance/b22/library.steps.go Updated as part of this pull request.
dotnet/Varar.Tests/ConformanceFixtures.cs Updated as part of this pull request.
dotnet/Varar.Core/Structurer.cs Updated as part of this pull request.
dotnet/Varar.Core/Plan.cs Updated as part of this pull request.
dotnet/Varar.Core/Diagnostics.cs Updated as part of this pull request.
dotnet/Varar.Core/Conformance.cs Updated as part of this pull request.
dotnet/Varar.Core/Ast.cs Updated as part of this pull request.
doc/adr/0016-reuse-is-a-link.md Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/shared.md Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/LibrarySteps.java Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/library.steps.ts Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/library.steps.rs Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/library.steps.rb Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/library.steps.py Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/library.steps.kt Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/library.steps.go Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/library.steps.cs Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/golden/trace.json Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/golden/registry.json Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/golden/plan.json Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/golden/doc.json Updated as part of this pull request.
conformance/bundles/22-reference-ambiguous-anchor/example.md Updated as part of this pull request.
conformance/bundles/21-reference-consumed/golden/doc.json Updated as part of this pull request.
conformance/bundles/20-reference-splice/golden/doc.json Updated as part of this pull request.
conformance/bundles/19-emphasis-parameter/golden/doc.json Updated as part of this pull request.
conformance/bundles/18-multi-table-example/golden/doc.json Updated as part of this pull request.
conformance/bundles/17-unexpected-pass/golden/doc.json Updated as part of this pull request.
conformance/bundles/16-stimulus-state-replacement/golden/doc.json Updated as part of this pull request.
conformance/bundles/15-custom-parameter-format/golden/doc.json Updated as part of this pull request.
conformance/bundles/14-stateless-steps/golden/doc.json Updated as part of this pull request.
conformance/bundles/13-custom-parameter-type/golden/doc.json Updated as part of this pull request.
conformance/bundles/12-combining-marks/golden/doc.json Updated as part of this pull request.
conformance/bundles/11-emoji-offsets/golden/doc.json Updated as part of this pull request.
conformance/bundles/10-error-fence-without-step/golden/doc.json Updated as part of this pull request.
conformance/bundles/09-expected-message-mismatch/golden/doc.json Updated as part of this pull request.
conformance/bundles/08-string-capture/golden/doc.json Updated as part of this pull request.
conformance/bundles/07-row-check-mismatch/golden/doc.json Updated as part of this pull request.
conformance/bundles/06-doc-string-mismatch/golden/doc.json Updated as part of this pull request.
conformance/bundles/05-ambiguous-match/golden/doc.json Updated as part of this pull request.
conformance/bundles/04-tables-and-docstrings/golden/doc.json Updated as part of this pull request.
conformance/bundles/03-expected-failure/golden/doc.json Updated as part of this pull request.
conformance/bundles/02-context-isolation/golden/doc.json Updated as part of this pull request.
conformance/bundles/01-roman-numerals/golden/doc.json Updated as part of this pull request.
Review details

Suppressed comments (3)

typescript/packages/core/src/plan.ts:221

  • When this check runs recursively, unit.span belongs to the nested target document, not necessarily the top-level from document. The resulting diagnostic carries only a span; the language index then labels every diagnostic from plan(doc, ...) with the host oath path, while the consumed target's own plan omits the section. An ambiguous anchor inside a nested shared section is therefore underlined at target offsets in the referring file instead of on the target reference block. Propagate the originating document path with diagnostics or retain nested diagnostics per oath.
    typescript/packages/lsp/src/handlers.ts:437
  • This test covers the new one-link-per-heading behavior only indirectly through the implementation; it does not exercise an ambiguous reference through buildHandlers().definition. Since returning both target links is the editor's promised behavior for the new diagnostic, add a duplicate-heading case that asserts both target ranges so a future change cannot silently choose one.
    typescript/packages/lsp/src/handlers.ts:486
  • Filtering the standalone plan by ex.scopeStack loses a valid nested-only section. If the referenced section contains only another reference, plan(target, ... referenced: new Set()) starts the merged example with the nested target's scope stack and never replaces it with the outer heading, so this predicate rejects it and hover reports _Contributes no steps._ even though the run resolver splices the nested steps. Select the target section before flattening, or retain the source section when planning, so nested-only references are included.
  • Files reviewed: 97/97 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

const heading = slug === '' ? undefined : sectionHeadings(target, slug)[0]
const title = slug === '' ? basenamePosix(target.path) : (heading?.text ?? `#${slug}`)
const lines = [`**${title}** · \`${linkTarget(at.written)}\``, '']
const steps = sectionSteps(index, target, slug)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 9789407: when the anchor names more than one heading the hover says so — _Ambiguous: 2 headings share this anchor (lines 3, 7), so nothing is spliced in._ — and previews nothing, since the reference contributes nothing until it is fixed. Go to Definition still offers every heading so the clash is visible, and the ambiguous-anchor diagnostic sits on the block. Pinned by a handler test.

Comment on lines +549 to +555
2. ~~Where is drift reported for a referenced section?~~ **Resolved** — it is
not drift at all. A consumed section plans no example in its own file, so
its paragraphs are not in the baseline; a step that stops matching one is
caught as `reference-empty` at the reference that depends on it — once,
loudly, where the fix goes. The consumed file's baseline entry means only
"this file was discovered". Consequence, accepted: delete every referrer and
the section reads as a new example, not a restored one. Documented under

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in eec87a8: the section is now ## Open questions, and how each was decided, with an intro saying every question is closed and kept in place with its decision beneath it; the two in-document links to it are updated to the new anchor.

@aslakhellesoy
aslakhellesoy force-pushed the run-results-document-identity branch from 0119df7 to b3f79ea Compare September 14, 2026 11:21
aslakhellesoy and others added 3 commits September 14, 2026 12:25
… as ambiguous-anchor

ADR 0016 listed the "ambiguous anchor" error and nothing detected it (#106).
Two headings that slug identically (`## Setup` twice — GitHub's `#setup` and
`#setup-1`) are indistinguishable to the scope-stack rule, so a reference to
`#setup` silently spliced BOTH sections in and the run stayed green.

Now `Doc` carries `headings` — every heading block, in order — and plan()
refuses a reference whose anchor names more than one of them: an
`ambiguous-anchor` error on the reference block, like the other three
reference errors, and nothing is spliced in until it is fixed. The rule is
"the anchor a reference names belongs to one heading", not "unique headings
in any referenced file": a duplicate nobody links to is harmless.

The doc artifact pins the outline, so every bundle's doc.json golden gains
`headings`, and `22-reference-ambiguous-anchor` gates the diagnostic in all
seven ports. Ports whose diagnostics carry messages (TypeScript, Python,
Ruby, .NET) name the target and the headings' lines; Java, Rust and Go stay
message-less as their other reference diagnostics are.

varar lint no longer goes through the runner's planOath, which re-parsed
every oath it had already parsed to build the workspace.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RQVAKGfMEKPbT919FqAChP
A reference block (ADR 0016) was inert in the editor beyond ordinary
Markdown link rendering (#107). Now:

- Go to Definition on the link lands on the heading the anchor names, in
  the oath that holds it — the top of the file for a whole-file reference,
  and one link per heading for an ambiguous anchor, so the editor peeks
  them all rather than picking one.
- Hover shows the steps the reference splices in, in order, with nested
  references resolved and a step from a third file saying which. The
  section is consumed, so the index holds no plan for it; the hover plans
  the target as if nothing referenced it and keeps the section's examples.
- The reference diagnostics already reached the editor through the
  ordinary rail; a test now pins that they sit on the block.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RQVAKGfMEKPbT919FqAChP
Ambiguous anchors fail the run in every port (the TypeScript-only lint
check was reversed; deviation 2 records why and what moved). The editor's
behaviour at a reference block is decided (question 8). And the decisions
on #108, #109 and #110: a consumed section's paragraphs are not in the
drift baseline and reference-empty is the intended signal; reports stay
flat, attributed by the run result's docPath; the same section twice runs
twice; whole-file references stay, hazard documented; a referenced
section's own heading chain is discarded; no opt-in depth lint. Nothing on
the ADR is open.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RQVAKGfMEKPbT919FqAChP
@aslakhellesoy
aslakhellesoy force-pushed the reference-anchors-and-lsp branch from 7e15c04 to eec87a8 Compare September 14, 2026 11:28
@aslakhellesoy
aslakhellesoy changed the base branch from run-results-document-identity to main September 14, 2026 11:57
@aslakhellesoy
aslakhellesoy merged commit d5fde84 into main Sep 14, 2026
11 checks passed
@aslakhellesoy
aslakhellesoy deleted the reference-anchors-and-lsp branch September 14, 2026 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ambiguous reference anchors are undetected (two headings that slug identically)

2 participants