Skip to content

fix(source-view): match artifact ids as whole tokens, not substrings (REQ-144)#387

Merged
avrabe merged 1 commit into
mainfrom
fix/source-view-token-match
Jun 2, 2026
Merged

fix(source-view): match artifact ids as whole tokens, not substrings (REQ-144)#387
avrabe merged 1 commit into
mainfrom
fix/source-view-token-match

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented Jun 2, 2026

User report

in source view, the doc id can be wrongly interpreted if we have one req which is part of another requirement. e.g. SWR-001 and SDV-BCM-SWR-001.

Assessment

Confirmed. rivet-cli/src/render/source.rs matched artifact ids into source/doc lines with line.contains(id) (the highlight gate and the linkify filter). So when both SWR-001 and SDV-BCM-SWR-001 exist, a line mentioning SDV-BCM-SWR-001 also matched SWR-001 as a substring — a phantom trace edge, which for a traceability tool is a correctness bug (closes #385).

Fix

line_contains_id_token(line, id): the id matches only when bounded on both sides by a non-[A-Za-z0-9-] character (or a string boundary). Ids contain hyphens, so - is part of the token, not a delimiter — exactly what separates SWR-001 from SDV-BCM-SWR-001. Used at both call sites. Ids are ASCII so byte-boundary checks align with char boundaries; a non-ASCII neighbour counts as a boundary.

Verification

Regression test id_token_match_is_whole_token_not_substring:

  • SWR-001 does NOT match inside SDV-BCM-SWR-001; the longer id does.
  • exact/delimited occurrences (REQ-001 done, (SWR-001), bare SWR-001) match.
  • SWR-0011 and xSWR-001 do NOT match (longer token).

clippy --all-targets + fmt clean; rivet validate PASS.

Implements: REQ-144 · Closes #385

🤖 Generated with Claude Code

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

📐 Rivet artifact delta

Change Count
Added 0
Removed 0
Modified 1
Downstream impacted (depth ≤ 5) 0

Graph

graph LR
  REQ_144["REQ-144"]:::modified
  classDef added fill:#d4edda,stroke:#28a745,color:#155724
  classDef removed fill:#f8d7da,stroke:#dc3545,color:#721c24
  classDef modified fill:#fff3cd,stroke:#ffc107,color:#856404
  classDef overflow fill:#e2e3e5,stroke:#6c757d,color:#495057,stroke-dasharray: 3 3
Loading
Modified
ID Changes
REQ-144

📎 Full HTML dashboard attached as workflow artifact rivet-delta-pr-387download from the workflow run.

Posted by rivet-delta workflow. The graph shows only changed artifacts; open the HTML dashboard (above) for full context.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'Rivet Criterion Benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.

Benchmark suite Current: 4c2f7da Previous: 7965e6d Ratio
validate/10000 17350429 ns/iter (± 2532113) 12753787 ns/iter (± 400759) 1.36

This comment was automatically generated by workflow using github-action-benchmark.

…(REQ-144)

User-reported: in the source view, an id that is a SUBSTRING of a longer
id was wrongly linked — e.g. `SWR-001` linked inside `SDV-BCM-SWR-001`,
a phantom trace edge. The viewer gated and linkified ids with
`line.contains(id)`, a raw substring test.

Add `line_contains_id_token`: an id matches only when bounded on both
sides by a non-`[A-Za-z0-9-]` character (or a string boundary). Ids
contain hyphens, so a hyphen is part of the token, not a delimiter —
which is exactly what distinguishes `SWR-001` from `SDV-BCM-SWR-001`.
Used at both the highlight gate and the linkify filter. Ids are ASCII,
so byte-boundary checks align with char boundaries.

Regression test covers: substring NOT matched (`SWR-001` in
`SDV-BCM-SWR-001`), longer id matched, exact/delimited occurrences
matched, trailing-alnum (`SWR-0011`) and leading-alnum (`xSWR-001`) not
matched. `rivet validate` PASS.

Implements: REQ-144
Refs: REQ-092

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@avrabe avrabe force-pushed the fix/source-view-token-match branch from 23899f6 to 4c2f7da Compare June 2, 2026 06:27
@avrabe avrabe merged commit 78ae68e into main Jun 2, 2026
19 of 22 checks passed
@avrabe avrabe deleted the fix/source-view-token-match branch June 2, 2026 06:43
avrabe added a commit that referenced this pull request Jun 2, 2026
…ke (#389) (#390)

`graph_type_filter_renders_when_under_budget` fetched
`/graph?types=requirement` with the default 5s read timeout. That
endpoint does a BFS + layout over the dogfood corpus (~742 nodes / 1477
edges), which on a loaded CI runner can brush past 5s; `fetch_with_timeout`
parses a timed-out/empty response's status as 0, so the timeout surfaced
as `status == 0` and failed the `== 200` assertion. Same chronic flake
the focus-graph tests already fixed with a 15s budget — this one test
was missed. It falsely failed CI on #380, #387, and #388.

Switch it to `fetch_with_timeout(..., 15s)`, matching the other graph
endpoints. The test asserts on the response shape (SVG or budget
message), not a hard latency bound, so the wider timeout is safe.
Verified locally: passes 3/3 runs.

Trace: skip
Closes: #389

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

Source-view links artifact ids by substring: SWR-001 wrongly matched inside SDV-BCM-SWR-001

1 participant