Skip to content

A word-character citation marker such as _ makes unqualified citations invisible, because citation_re requires a word boundary before the ID #483

Description

@vjovanov

What happens

A project that sets [reference] marker = "_" and [id] format = "{kind}_{slug}":

# grund.toml
grund_config_version = 1

[id]
format = "{kind}_{slug}"

[reference]
marker = "_"

[fmt.cross_refs]
enabled = false
# docs/functional-spec/FS-login.md
# FS_login: Login

Lead.
// src/lib.rs
//! _FS_login

grund FS_login resolves the declaration and prints Lead., but the citation in src/lib.rs is not seen anywhere. grund refs FS_login exits 0 and prints nothing, grund cover gives src/lib.rs no citations, and grund check warns declared but never cited: FS_login. The same fixture with the default marker § (//! §FS_login) works.

A reproducer builds grund and runs both fixtures side by side. On grund 0.16.2-dev at af9f6f5 it printed:

grund: grund 0.16.2-dev at af9f6f56d26721898b13c9a853a9044059a387ab
control, marker '§', src/lib.rs = '//! §FS_login':
  grund refs FS_login:
    src/lib.rs:1: §FS_login
  grund cover --format json:
    {"path":"docs/functional-spec/FS-login.md","citations":[]}
    {"path":"src/lib.rs","citations":[{"path":"src/lib.rs","line":1,"column":5,"id":"FS_login","section":null,"marker":true,"text":"§FS_login","enclosing_declaration":null,"enclosing_section":null}]}
subject, marker '_', src/lib.rs = '//! _FS_login':
  grund refs FS_login:
    
  grund cover --format json:
    {"path":"docs/functional-spec/FS-login.md","citations":[]}
    {"path":"src/lib.rs","citations":[]}
expected: refs=1 cover=1 (the configured marker cites the declared FS_login, as '§' does)
observed: refs=0 cover=0
defect stands: underscore-marked unqualified citation is invisible (citation_re's \b before the ID)

The same happens with the installed 0.15.1-dev, so it is not new. The LSP is affected as well: a textDocument/definition request inside //! 😀 _FS_login returns result: null, while § resolves. The reproducer above covers only the CLI.

The cause looks like crates/grund-core/src/grammar/compiled.rs:372:

let citation_re = Regex::new(&format!(r"\b{}{}{}", namespace_prefix, id_pat, sec_suffix))?;

The \b in front of the ID needs a word boundary before the F. When the marker is itself a word character, as _ is, the marker and the ID sit inside one word and there is no boundary, so the unqualified citation never matches. The marker fallback in the scanner handles qualified citations (_alias/FS_login), so only the unqualified spelling, which is the common one, is lost.

What should happen

_FS_login should be read as a marked citation of FS_login, exactly as §FS_login is under the default marker. It should show up in refs and cover, satisfy check, and resolve through LSP definition. A citation is the configured marker followed by an ID (§FS-check.1.1), and the marker can be configured (§FS-config.3.1). Config loading accepts _ without a complaint. The word boundary is there to keep an ID from matching inside a longer word, and the marker that ends right before the ID already does that job.

If a word-character marker is not meant to be supported, then grund.toml should reject it at load time, not accept it and then see nothing.

Why it matters

The failure is silent. refs comes back empty and cover lists the file with no citations. check raises no dangling-citation error, only a misleading declared but never cited warning on the declaration that is in fact cited. fmt reports nothing to normalize. A project on this marker loses every edge from code to spec, and nothing tells it so. Any rule that relies on those edges (grounding, chapter rules, refs before a rename) runs against a graph that is missing them.

What else was tried

  • The control with marker § in the same fixture finds the citation, so the fixture and the ID format are fine.
  • grund FS_login resolves the declaration, so declaration parsing under {kind}_{slug} works. Only citation scanning fails.
  • The LSP definition request fails the same way with or without a trailing newline and with or without prose after the citation.
  • This came up while reviewing Complete LSP citation authoring with ID completion and reliable trigger interaction #472. That issue's overlap tests were written so they don't depend on it, and the scanner fix was explicitly left out of its scope.

Workaround

Use a marker that is not a word character (the default §, for example). None found that keeps _.

Filed by grounded-ticket intake from grund.57 (kind: bug).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghigh-priorityWrong or misleading verdict a user can still catch, or an adoption blockerpath:simpleStraight to a spec-first fix, no planning round

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions