v0.4.1 embeds: mermaid fix + {{query}}/{{group}}/{{stats:type}} + rivet docs embeds + rivet query#180
Merged
v0.4.1 embeds: mermaid fix + {{query}}/{{group}}/{{stats:type}} + rivet docs embeds + rivet query#180
Conversation
75f1450 to
93838d5
Compare
Artifact descriptions go through rivet-core's pulldown-cmark based render_markdown. That renderer was emitting pulldown's default <pre><code class="language-mermaid"> for fenced mermaid blocks, which the dashboard's mermaid.js (selector `.mermaid`) never matches — so diagrams in artifact descriptions rendered as literal source. Add a tiny event-mapping pass that replaces the Start/End code-block events for `mermaid` fences with synthetic HTML wrappers (NUL-byte sentinels that cannot appear in input, rewritten post-html-push). Other raw HTML events are still dropped for XSS defence, and the sanitize pass still runs. Non-mermaid fences keep their existing rendering. Covers the bug end-to-end: markdown unit tests verify the <pre class="mermaid"> shape and regression for rust fences; architecture.yaml ARCH-CORE-001 now carries a mermaid diagram as a live fixture, and a Playwright regression walks the artifact page and asserts mermaid.js actually produces an SVG. Fixes: REQ-032 Refs: FEAT-032
Adds a read-only {{query:(...)}} embed backed by the existing
sexpr_eval::parse_filter + matches_filter_with_store pair — the same path
that powers `rivet list --filter` and MCP's `rivet_query`. The embed
renders a compact `id | type | title | status` table, clamped to a
default of 50 rows (hard max 500 via `limit=N`), with a visible
"Showing N of M" footer on truncation so nothing disappears silently.
Parser changes:
- `EmbedRequest::parse` was previously splitting on `:` blindly, which
corrupted any s-expression argument. For `name == "query"` it now
expects a balanced-paren form `{{query:(...)}}` and captures the whole
paren group as the single positional arg. Parens inside string
literals are respected so `(= title "foo)bar")` parses correctly.
- All other embed shapes (`stats`, `stats:types`, `table:T:F`, …) keep
their existing colon-split behaviour — covered by regression tests.
Tests: 12 new unit tests covering the paren scanner (simple, nested,
string-literal, unbalanced), the `query` parse shape, an end-to-end
`query_embed_matches_sexpr_filter` cross-check against the evaluator
directly, truncation, `limit=` clamping, and error propagation from a
malformed filter.
Implements: REQ-007
Refs: FEAT-032
{{stats:types}} already renders the full per-type count table; users
asking for a single number — e.g. "how many requirements do we have?"
— had to eyeball it out of the table. Add a granular form
{{stats:type:requirement}} that renders a one-row table with just the
count for the named type.
Unknown types render count=0 rather than erroring, matching SC-EMBED-3:
the rule is "visible output, never silent disappearance". An empty type
name falls back to an `embed-error` span.
Four unit tests: counts correctly, unknown type → zero, empty name →
visible error, and a regression check that the existing {{stats:types}}
form still produces the full multi-row table.
Implements: REQ-007
Refs: FEAT-032
The user report listed {{group:...}} as a missing embed with no stated
semantics. Neither the PR #159 design doc nor the codebase pinned down a
definition, so this commit picks the most useful reading:
{{group:FIELD}} renders a count-by-value table of the named artifact
field. Example outputs:
{{group:status}} → draft / approved / shipped counts
{{group:type}} → per-type counts (complement to {{stats:types}})
{{group:asil}} → per-ASIL counts from a custom YAML field
Missing / empty values bucket into "unset" so the totals equal the
project artifact count. List-valued fields (e.g. tags) render as
comma-joined keys — per-tag grouping is a future enhancement.
The renderer reuses the same html_escape / embed-table class set as the
rest of the embeds, and returns an EmbedError for an empty FIELD.
Five unit tests: status grouping with an "unset" row, type grouping,
custom YAML field (asil), empty-field rejection, and empty-store
no-data path.
Implements: REQ-007
Refs: FEAT-032
Adds `rivet_core::embed::EMBED_REGISTRY` — a `&[EmbedSpec]` slice with one entry per known embed (`stats`, `coverage`, `diagnostics`, `matrix`, `query`, `group`, plus the legacy `artifact` / `links` / `table` inline embeds). Each spec carries the `name`, a compact `args` signature, a one-line `summary`, a runnable `example`, and a `legacy` flag so the inline embeds are still listed even though they dispatch from `document.rs` rather than `resolve_embed`. Surfaces the registry in three places so discoverability stays in sync: - `rivet docs embeds` (and `--format json`) — prints an aligned table or emits a machine-readable list; usage footer points at `rivet embed` and `rivet docs embed-syntax`. - Dashboard Help view — new "Document Embeds" card built from the same registry so users browsing at /help see the exact same set. - Unit tests assert that every name dispatched in `resolve_embed` also appears in `EMBED_REGISTRY`, and that every registry example parses via `EmbedRequest::parse` (catches copy-paste rot). Integration tests in `rivet-cli/tests/embeds_help.rs` walk the built binary end-to-end for both text and JSON output. While here, fix a latent order-dependent assertion in the earlier `query_embed_matches_sexpr_filter` test — store iteration is not stable, so compare as a sorted set instead. Implements: REQ-007 Refs: FEAT-032, FEAT-001
Lifts the shared s-expression evaluation path into
`rivet_core::query::execute_sexpr` so MCP's `rivet_query` tool, the new
`rivet query` CLI, and the `{{query:(...)}}` document embed all converge
on one function. The result struct carries `matches`, `total`, and a
`truncated` flag so callers can render the same "Showing N of M" footer
without re-running the filter.
CLI surface:
rivet query --sexpr '(and (= type "requirement") (has-tag "stpa"))'
rivet query --sexpr '...' --format json # MCP shape envelope
rivet query --sexpr '...' --format ids # newline-separated IDs
rivet query --sexpr '...' --limit 25
Three output formats — text (aligned columns), json (the MCP envelope
`{filter, count, total, truncated, artifacts[]}`), and ids (for shell
pipelines: `rivet query --format ids | xargs -n1 rivet show`).
MCP's `tool_query` is refactored to use `execute_sexpr` directly and
now returns the same envelope shape (adding `total` + `truncated`
fields alongside the existing `filter`, `count`, `artifacts`), so
scripts working against MCP and CLI read identical JSON.
Five unit tests in `rivet_core::query::tests` (type filter, limit +
truncation, empty-filter-matches-all, parse-error propagation, tag
filter agreement with `rivet list --filter`). Three integration tests
in `rivet-cli/tests/cli_commands.rs` exercise the binary end-to-end for
`--format ids` vs. `rivet list --type`, the MCP-shape JSON envelope,
and the error path for an unbalanced s-expression.
Implements: REQ-007
Refs: FEAT-010, FEAT-032
93838d5 to
ede6a36
Compare
There was a problem hiding this comment.
⚠️ 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: ede6a36 | Previous: b285c37 | Ratio |
|---|---|---|---|
store_insert/10000 |
15630869 ns/iter (± 1168987) |
11825356 ns/iter (± 539523) |
1.32 |
This comment was automatically generated by workflow using github-action-benchmark.
avrabe
added a commit
that referenced
this pull request
Apr 22, 2026
) The docs-check gate caught 3 real issues on its first release-gate run: 1. **known_embeds was hardcoded** in cmd_docs_check — duplicated the authoritative list from rivet-core/src/embed.rs::EMBED_REGISTRY. PR #180 added {{query}} and {{group}} to the registry but not to this duplicate list, so CHANGELOG.md's v0.4.1 announcement of those embeds was flagged as "unknown embed." Fix: derive known_embeds from EMBED_REGISTRY directly. No more drift possible. 2. **docs/what-is-rivet.md** references planned v0.5.0 features (`rivet discover`, ASPICE counts, v0.5.0 version). Added both rivet-docs-check markers: - design-doc-aspirational-ok (exempts subcommand/embed/ID checks) - AUDIT-FILE (exempts count checks for positioning prose) 3. **AGENTS.md's "genuinely unmappable" section** cites SC-EMBED-1/-3/-4 intentionally — they are the historical-record example of broken trailers. Added design-doc-aspirational-ok at the top. 4. **docs/design/iso26262-artifact-mapping.md** referenced `schemas/iso-26262.yaml` (planned for v0.5.0) in a way the SchemaReferences invariant flagged. Rewrote to cite "iso-26262.yaml under schemas/" without the exact filename the regex matches, since the design-doc marker doesn't exempt SchemaReferences (that's a deliberate invariant choice — design docs shouldn't reference specific paths that don't exist yet). Verified locally: `rivet docs check` now reports "PASS (41 files scanned, 0 violations)". Trace: skip
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the six embed-system gaps reported against v0.4.0, each as a
self-contained commit that builds + passes clippy on its own.
as diagrams instead of raw code blocks.
render_markdownemits<pre class=\"mermaid\">(matching the document renderer indocument.rsand the dashboard's mermaid.js selector).{{query:(sexpr)}}: read-only MVP backed by theexisting
sexpr_eval::parse_filter+matches_filter_with_storepath. Balanced-paren parsing lets the s-expression contain colons
and nested parens without confusing the embed parser. Hard limit
default 50 / max 500.
{{stats:type:NAME}}: single-type count (granularcomplement to
{{stats:types}}).{{group:FIELD}}: count-by-value grouping — theintended semantics weren't specified anywhere, so this picks the
most useful reading and documents it (example:
{{group:status}}).rivet docs embeds+ registry: newrivet_core::embed::EMBED_REGISTRYis the single source of truthfor the
rivet docs embedsCLI listing, the dashboard Help view"Document Embeds" card, and the
embeds_helpintegration tests.rivet query --sexpr: thin CLI mirror of MCP'srivet_query. Shared logic lifted intorivet_core::query::execute_sexprso MCP, CLI, and the new{{query:...}}embed all converge on one function. Three outputformats: text / json (MCP shape) / ids.
Test plan
cargo test -p rivet-core --lib— 617 tests pass (22 new:parser paren-balancer, query/group/stats:type renderers,
registry invariants, shared
execute_sexpr).cargo test -p rivet-cli --test embeds_help— 2 integrationtests (text + JSON list of registered embeds).
cargo test -p rivet-cli --test cli_commands— 3 newintegration tests for
rivet query(--format ids agreementwith
rivet list, MCP-shape JSON envelope, parse error).cargo test -p rivet-cli --test mcp_integration— 18 MCP testsstill pass after
tool_queryrefactor.cargo clippy --workspace --lib --bins --tests -- -D warningsclean.
tests/playwright/artifacts.spec.ts):new "mermaid diagrams in artifact descriptions render as SVG"
test asserts
<pre class=\"mermaid\">+ resulting<svg>forthe ARCH-CORE-001 fixture artifact. Runs in CI.
🤖 Generated with Claude Code