Skip to content

feat(validate): warn when prose names an artifact id without a typed link (#207)#234

Merged
avrabe merged 1 commit into
mainfrom
feat/issue-207-prose-mention-warn
Apr 29, 2026
Merged

feat(validate): warn when prose names an artifact id without a typed link (#207)#234
avrabe merged 1 commit into
mainfrom
feat/issue-207-prose-mention-warn

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented Apr 28, 2026

Closes #207.

Summary

rivet validate now scans each artifact's description (and every string-typed value in its fields map) for tokens matching \b[A-Z][A-Z0-9]*-[0-9]+\b. When such a mention resolves to an artifact in the corpus and the mentioning artifact has no typed link to it, validate emits a Warning diagnostic (prose-mention-without-typed-link).

This is the discipline analogue of Karpathy's [[wikilinks]] for the typed-graph world — see the issue body's link to the companion blog post.

Acceptance-criteria mapping (from #207)

The issue body's "Implementation sketch" enumerates testable bullets; mapped 1:1 here:

Sketch bullet Where it landed
New diagnostic kind in rivet-core/src/validate.rs prose-mention-without-typed-link, severity Warning, emitted from a new pass-10 in validate_structural
Pre-compile a regex \b[A-Z][A-Z0-9]*-[0-9]+\b (cached statically) static ID_MENTION_RE: LazyLock<Regex> at module scope, mirroring the pattern in rivet-core/src/markdown.rs
Apply to description + every value in fields that is a string if let Some(desc) = &artifact.description { scan(desc); } plus iteration over artifact.fields.values() filtering value.as_str()
Skip if it is the artifact's own id if mentioned == artifact.id { continue; }
Check if Store::get(mentioned_id) resolves; if yes and the artifact has no typed link to it, emit store.contains(mentioned) AND !linked_targets.contains(mentioned) (BTreeSet of all link targets, regardless of link type)
Tests: warning fires; typed link present → no warning; same-artifact-ID match suppressed All three covered, plus three more (unresolved id suppresses; string fields value is scanned; repeated mentions dedupe to one warning)

On --strict

The issue mentions a hypothetical rivet validate --strict to escalate this warning to an error. rivet already exposes rivet validate --fail-on warning (parsed in rivet-cli/src/main.rs::parse_fail_on), which fails the run on any warning; that subsumes the hypothetical flag without adding a new CLI surface. A literal severity-changing --strict is left for a follow-up if a separate warning-stays-warn-but-rule-becomes-error semantic is wanted.

Verification

  • cargo test -p rivet-core --lib822 passed, 0 failed (6 new tests for this rule, all green).
  • cargo test -p rivet-core --tests — all integration test binaries pass.
  • cargo clippy -p rivet-core --all-targets -- -D warnings — no new warnings (only the pre-existing MSRV-config mismatch warning).
  • rustfmt --check rivet-core/src/validate.rs — clean.
  • ./target/release/rivet validate on this repo:
    • Pristine main: FAIL (6 errors, 10 warnings, 0 broken cross-refs)
    • With this change: FAIL (6 errors, 68 warnings, 0 broken cross-refs)
    • Delta: +58 new prose-mention warnings on rivet's own artifacts — these are the real authoring-discipline gaps the rule is designed to surface (e.g. [TEST-027] prose mentions 'FEAT-061' but no typed link to it). They are not regressions; default --fail-on error is unaffected, so CI/release/compliance/pre-commit flows that rely on the default exit-code threshold see no behaviour change. A follow-up clean-up PR can decide which mentions deserve typed links and which should be reworded.

Tests added (all under rivet-core/src/validate.rs::tests, annotated // rivet: verifies REQ-004)

  • prose_mention_warns_when_no_typed_link — positive case: warn fires.
  • prose_mention_suppressed_when_typed_link_present — typed link to mentioned id suppresses.
  • prose_mention_suppressed_when_self_reference — self-id mention suppressed.
  • prose_mention_suppressed_when_id_does_not_resolve — unresolved id suppressed (broken-ref handling is a separate rule).
  • prose_mention_scans_string_field_values — string-typed fields values are scanned, not only description.
  • prose_mention_dedupes_per_id_per_artifact — three mentions of one id yield one warning.

Test plan

  • cargo fmt --check on the changed file is clean
  • cargo test -p rivet-core green (lib + integration)
  • cargo clippy -p rivet-core --all-targets -- -D warnings clean
  • rivet validate exit code unchanged on default --fail-on error
  • CI green
  • Maintainer confirms the pass-10 placement (after unknown-fields, before conditional rules) is the intended spot
  • Maintainer decides whether the 58 surfaced warnings warrant a follow-up clean-up PR or a temporary # rivet: ignore prose-mention mechanism

Trailers

Per CLAUDE.md:

Implements: REQ-004

Validation change → REQ-004.


Generated by Claude Code — issue-triage agent run 2026-04-28.


Generated by Claude Code

@temper-pulseengine
Copy link
Copy Markdown
Contributor

AI Code Review for PR #234

pulseengine/rivet:feat/issue-207-prose-mention-warn → pulseengine/rivet:main

Verdict: 💬 Comment

Summary: The code snippet provided is a Rust implementation for validating artifacts in a project using a typed graph. The validate_structural function checks for various issues such as broken links, unknown link types, and prose mentions without typed links. The code includes tests to verify the correctness of these validations.

Findings (1):

  1. src/lib.rs:513
    Severity::Warning
    
    The function validate_structural correctly identifies and reports warnings for prose mentions without typed links.

Generated by a local AI model and post-validated against a strict JSON contract. Each finding includes the verbatim line being criticised — verify by reading the file at the cited location.

Reviewed at 380e8fc

…ed link

Closes #207.

Add a structural-validation pass that scans each artifact's
`description` (and every string-typed value in its `fields` map) for
tokens matching `\b[A-Z][A-Z0-9]*-[0-9]+\b`. When a match resolves to
an artifact in the corpus and the mentioning artifact has no typed
link to it, emit a Warning-severity diagnostic
(`prose-mention-without-typed-link`).

Suppression cases (matching the issue body):
  * the mention is the artifact's own id (self-reference),
  * the mentioned id does not resolve in the corpus (broken refs are
    a separate concern),
  * the artifact already has any typed link to that id.

Per-(artifact, mentioned-id) dedup mirrors the unknown-link-type
pass's policy so repeated mentions of the same id yield one warning.

The regex is compiled once via `LazyLock<Regex>` (mirroring
`rivet-core/src/markdown.rs`).

Six unit tests cover every Tests-bullet from #207 plus dedup:
  * warn fires on bare mention,
  * typed link suppresses warn,
  * self-id mention suppresses warn,
  * unresolved id suppresses warn,
  * string-typed `fields` value is scanned,
  * three mentions of one id dedupe to one warning.

Note on escalation: the issue mentions a hypothetical
`rivet validate --strict` to escalate to Error. rivet already exposes
`rivet validate --fail-on warning` which fails the run on any
warning; that subsumes the hypothetical flag without a new surface.
A literal severity-changing `--strict` is left for a follow-up if
wanted.

Implements: REQ-004
@avrabe avrabe force-pushed the feat/issue-207-prose-mention-warn branch from 380e8fc to 86c2b02 Compare April 29, 2026 04:47
@github-actions
Copy link
Copy Markdown

📐 Rivet artifact delta

No artifact changes in this PR. Code-only changes (renderer, CLI wiring, tests) don't touch the artifact graph.

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: 86c2b02 Previous: 05c9400 Ratio
link_graph_build/10000 28575716 ns/iter (± 943005) 23408112 ns/iter (± 311314) 1.22
validate/10000 14694884 ns/iter (± 257550) 10596288 ns/iter (± 370139) 1.39

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

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 29, 2026

Codecov Report

❌ Patch coverage is 99.06542% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rivet-core/src/validate.rs 99.06% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@avrabe avrabe merged commit c47549b into main Apr 29, 2026
25 of 40 checks passed
@avrabe avrabe deleted the feat/issue-207-prose-mention-warn branch April 29, 2026 06:50
avrabe added a commit that referenced this pull request Apr 30, 2026
…246)

Workspace, vscode-rivet, and npm root package versions bumped to 0.7.0.
Platform packages stay on the release-npm.yml override path.

What's in 0.7.0:

- feat(schema): rivet schema migrate Phase 2 (#242) — full git-rebase
  conflict-resolution UX. Conflict markers in YAML, --continue,
  --skip, --edit. New MigrationConflict invariant in rivet docs check.
- feat(docs-check): subcommand-coverage gate (#241) — walks the live
  clap CLI tree and asserts each path has an embedded docs topic.
  Default warn-only; --strict makes it enforcing.
- feat(validate): prose-mention-without-typed-link warning (#234,
  closes #207).
- feat(schemas): vv-coverage repo-status type (#232, partial #188).
- feat(mutants): canonical cargo-mutants template (#229, closes #185).
- docs(pre-commit): canonical 21-hook template (#222, closes #186).
- fix(ci): Release workflow now idempotent on existing tag (#244).

Known issue: v0.5.0 / v0.5.1 / v0.6.0 release pages have no binary
assets attached because the workflow's Create Release step failed
on each (race with manual gh release create). The fix in #244 lands
in this release; v0.7.0 onward is unaffected. Older releases need
a manual gh release upload to backfill.

Verified: cargo check, cargo clippy --workspace -- -D warnings,
cargo test -p rivet-cli, rivet docs check (clean), rivet docs check
--coverage reports 48/81 paths covered (warn-only).

Trace: skip
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.

rivet validate: warn when description prose names an artifact ID with no typed link

2 participants