Skip to content

feat: AADL analysis panel, syntax highlighting, artifact embeds#6

Merged
avrabe merged 1 commit intomainfrom
feat/dashboard-analysis-panel
Mar 9, 2026
Merged

feat: AADL analysis panel, syntax highlighting, artifact embeds#6
avrabe merged 1 commit intomainfrom
feat/dashboard-analysis-panel

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented Mar 9, 2026

Summary

  • Add AADL analysis diagnostics panel below architecture diagrams — calls renderer.analyze(root) via WASM and displays errors/warnings/info with severity badges, component paths, and analysis names
  • Add Rust and TOML syntax highlighting to source code viewer
  • Add {{artifact:ID}} embedding syntax in documents for inline artifact cards
  • Improve AADL diagram rendering: standard component shapes, zoom-toward-cursor, fit-to-view
  • Add navigation integration tests and serve lint tests

Test plan

  • cargo test passes
  • WASM rebuilt with analyze function via build-wasm.sh
  • Dashboard shows analysis panel with sorted diagnostics below diagrams

🤖 Generated with Claude Code

…diagrams, navigation tests

Add Rust and TOML syntax highlighting to the source code viewer with
token-based colorization for keywords, types, strings, comments,
attributes, and macros. Refactor render_code_block to use string-based
language dispatch instead of boolean flags.

Add {{artifact:ID}} embedding syntax in documents that renders inline
cards with type/status badges, clickable IDs, and truncated descriptions.
Bridge document renderer to artifact store via ArtifactInfo callback.

Add diagram field support on artifacts — mermaid code renders as
interactive diagrams, "root:" prefix triggers AADL diagram containers.
Exclude diagram from regular fields display to avoid duplication.

Fix all 28 HTMX navigational links missing hx-push-url="true" so
browser URL bar stays in sync during SPA navigation. Add source-level
lint tests (serve_lint.rs) and HTTP integration tests
(serve_integration.rs) to prevent navigation regressions.

Add AADL SVG CSS overrides to match etch's clean visual style.
Add example content to SRS-001, architecture.yaml, and decisions.yaml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@avrabe avrabe merged commit 8542309 into main Mar 9, 2026
9 of 11 checks passed
@avrabe avrabe deleted the feat/dashboard-analysis-panel branch March 9, 2026 18:43
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 77.39130% with 26 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rivet-core/src/document.rs 77.39% 26 Missing ⚠️

📢 Thoughts on this report? Let us know!

avrabe added a commit that referenced this pull request Apr 22, 2026
* docs+feat(variant): feature-model schema reference + init scaffolder

Pain point: users reverse-engineer the feature-model YAML schema because
`rivet variant --help` has no field reference and `selects:` vs
`selected:` / group types / s-expression constraint syntax / bindings
file shape are undocumented.

Changes:
- Add docs/feature-model-schema.md: top-level reference for feature
  model YAML (root, features, group types, constraint syntax) with a
  worked example.
- Add docs/feature-model-bindings.md: dedicated binding file reference.
- Link both from docs/getting-started.md.
- Variant subcommand doc-comment now points at the schema reference so
  `rivet variant --help` surfaces it.
- Add `rivet variant init <name>` scaffolder that writes a starter
  feature-model.yaml + bindings/<name>.yaml with comments documenting
  every field.

Tests: 3 new integration tests in rivet-cli/tests/variant_init.rs
covering scaffolded file contents, overwrite protection, and that the
scaffolded template parses clean via `rivet variant list`.

Implements: REQ-042, REQ-043, REQ-044
Refs: REQ-046

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(hooks): pre-commit hook walks up to find rivet.yaml (marker discovery)

Pain point: `rivet init --hooks` emitted a pre-commit hook that ran
`rivet validate` at the git root. If the rivet project is relocated
inside the working tree (e.g. moved to subdir/), the hook either
silently validates the wrong directory or fails to find rivet.yaml.

Fix: the installed pre-commit hook now walks up from $PWD until it
finds a directory containing rivet.yaml, then cd's there before
invoking `rivet validate`. If no rivet.yaml exists in the ancestor
chain, the hook exits 0 silently so it does not block commits in
unrelated repositories.

Tests: rivet-cli/tests/hooks_install.rs adds 2 integration tests — one
verifies the hook body does not embed a hard-coded -p/--project flag and
uses the walk-up pattern; one stages a fresh project, moves rivet.yaml
into a subdirectory, and confirms the hook still discovers it when run
from a nested path.

Fixes: REQ-051

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(variant): check-all + optional --variant on validate (API ergonomics)

Pain point: variant-scoped validation required --model, --variant, and
--binding to be passed together — there was no way to validate just
model/binding consistency, and no single-invocation way to assert a
whole batch of variants is valid.

Changes:
- `rivet validate --model X --binding Y` (no --variant) now parses the
  model, parses the binding, and checks that every feature referenced
  in the binding exists in the model. Reports a clear diagnostic on
  unknown feature names instead of the old "must all be provided
  together" error. The full --model + --variant + --binding mode is
  unchanged.
- `rivet variant check-all --model M --binding B` iterates every
  variant declared under `variants:` in the binding file, prints a
  PASS/FAIL line per variant, and exits non-zero if any fail.
- `FeatureBinding` in rivet-core grows an optional `variants:` field
  (default empty) so the same file can carry bindings and declared
  variants without schema churn.

Tests: 5 new integration tests in rivet-cli/tests/variant_scoped_api.rs
cover the no-variant validate mode, the unknown-feature diagnostic,
check-all exit codes for mixed/all-pass fixtures, and JSON output shape.
Existing feature_model unit tests still pass (binding YAML is
backward-compatible — `variants:` defaults to empty).

Implements: REQ-044, REQ-045, REQ-046

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(sexpr): semantic notes on filter parse errors

Pain point: `[FilterError { offset: 14, message: "unexpected atom at
top level" }]` exposed parser internals. Users writing `A and B`,
`and A B`, or `(bogus A B)` got a positional offset with no hint that
they were using the wrong syntax.

Fix: extend `FilterError` with an optional `note` field, populated by a
classifier that inspects the source before parsing. Three common shapes
get a semantic nudge:
  - bare infix (`A and B`) → suggest `(and A B)`.
  - missing outer parens (`and A B`) → suggest wrapping it.
  - unknown head (`(bogus …)`) → reference the supported form list.
`FilterError::Display` renders the positional detail followed by the
note on a new line. Feature-model constraint errors now format via
Display instead of Debug, so the note bubbles out through
`rivet variant check` / `rivet validate --model` paths.

Tests: 4 new unit tests in sexpr_eval covering the three error shapes
plus a success case that must carry no note. All pre-existing tests
unchanged.

Fixes: REQ-043
Implements: REQ-042

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(variant-solve): per-feature origin tracking (selected vs mandatory vs implied)

Pain point: `rivet variant solve` output mixed user-picked features with
ones the solver added via mandatory-group propagation or constraint
implication. A flat list like `base, auth, oauth, token-cache, metrics`
didn't tell the user which features were their intent and which were
downstream effects.

Minimum-impact change per scope-limits brief (risk of conflict with
PR #156 cross-tree constraint work):
- Extend `ResolvedVariant` with a per-feature `origins: BTreeMap<String,
  FeatureOrigin>` where FeatureOrigin is UserSelected / Mandatory /
  ImpliedBy(name) / AllowedButUnbound.
- Populate origins alongside the existing selected-set fixpoint loop —
  no algorithmic changes. First-reason-wins on insertion so user
  selection beats later mandatory/implied discoveries.
- Text output of `rivet variant solve` prints one feature per line,
  prefixed with `+`, labeled (mandatory) / (selected) / (implied by X).
- JSON output is strictly additive: `effective_features` + `feature_count`
  preserved, new `origins` object keyed by feature name.

Tests:
- 4 new unit tests in rivet-core/src/feature_model.rs covering each
  origin variant.
- 2 new integration tests in rivet-cli/tests/variant_solve_origins.rs
  asserting text prefixes/labels and JSON backwards compatibility.
- All 15 pre-existing feature_model unit tests still pass; all 6
  proptest_feature_model properties still hold.

Implements: REQ-043, REQ-046
Refs: REQ-052

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
avrabe added a commit that referenced this pull request Apr 22, 2026
…f-life) (#189)

* fix(embed,docs,ui): v0.4.2 UX polish + 4 embed bugs

Surfacing existing-but-invisible data and fixing silent-accept in the
embed pipeline that the v0.4.1 Mythos pipeline would have flagged.

UI surfacing (data was always there, UI didn't show it):
- Artifact detail now lists documents that reference the artifact
  via [[ID]] links, with line numbers per occurrence.
- Mermaid/AADL diagrams on artifact detail and schema-show pages now
  wrap in .svg-viewer so they get the same zoom / fullscreen / popout
  toolbar as graph and doc-linkage views.

Embed correctness:
- {{group:TYPE:FIELD}} two-arg form — the second arg was silently
  discarded, causing every artifact to bucket into "unset" because
  the first arg was read as the field name. Now scopes by type and
  groups by field as the syntax suggests.
- {{query ...}} now honors fields= to customize table columns and
  rejects colon-prefixed option syntax (:limit 10) with a helpful
  error pointing to key=value form — previously silently dropped.
- Standalone {{artifact|links|table:...}} on its own line no longer
  wraps in <p>, which produced invalid HTML nesting. Block-level
  embeds emit directly.

Docs-check gate:
- rivet docs check now honors rivet.yaml's docs: list instead of
  only scanning the top-level docs/ directory. Projects with
  crates/*/docs or rivet/docs layouts are no longer silently missed.

Implements: REQ-004, REQ-008, REQ-010
Refs: FEAT-001

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(validate): count flow-style and named-field links for cardinality

Two silent-accept bugs in the link cardinality validator that let
"required: true, cardinality: one-or-many" link-fields appear absent
while rivet validate stayed PASS.

Flow-style: `links: [{type: X, target: Y}]`
  The rowan CST parser records flow sequences but does not emit nested
  flow-mapping nodes, so extract_links walked an empty Sequence and
  returned zero links. Added a serde_yaml fallback that re-parses the
  value text when the CST yields no Sequence — flow and block styles
  now produce byte-identical Link vectors.

Named-field form: schema `link-field.name: targets` + artifact
`targets: [SEC-AS-001]`
  shorthand_links was declared on ArtifactTypeDef but never populated,
  so the yaml_hir shorthand path never fired and `targets:` fell into
  custom-fields instead of becoming a threatens-link. Schema::merge
  now derives shorthand_links from each link-field automatically.

Both shapes were displayed correctly by `rivet get` (the parser saw
them for rendering) but the cardinality counter saw zero — the worst
kind of bug for safety tooling. Regression test pins the invariant
that flow-style and block-style yield identical Link vectors.

Fixes: REQ-004
Verifies: REQ-004

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(schema,validate): treat undeclared link types as ERROR + add schema-consistency check

Two changes that close a silent-accept loop in the schema layer:

1. validate.rs — `unknown-link-type` Severity bumped from Warning to
   Error. An undeclared link-type means the schema's cardinality and
   target-type guarantees silently don't apply to those links; that's
   not an advisory, it's an integrity failure. De-duplicates per
   (artifact, link_type) so a single typo doesn't drown the report.

2. schema.rs — new `Schema::validate_consistency()` returns a list of
   schema-internal issues:
   - link-fields referencing undeclared link types
   - link-fields with unknown target artifact types
   - traceability rules with unknown from/target types

   This mirrors what `rivet schema validate` already reported but is
   now a library function callable from any load path, so a downstream
   project can fail-fast on a broken schema instead of validating
   artifacts against silently-broken rules.

Two regression tests pin the invariants: undeclared link type emits
exactly one Error diagnostic per (artifact, link-type) pair, and
schema_consistency flags both dangling link-types and missing target
types.

Implements: REQ-010
Verifies: REQ-004, REQ-010

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(docs-check): external-namespace exemption + skip directives + AGENTS.md template fix

Three-layered escape hatch so the ArtifactIdValidity gate can run as a
required CI check on projects that legitimately reference external IDs
(Jira, Polarion, hazard catalogs, upstream stakeholder docs).

1. rivet.yaml `docs-check.external-namespaces: [GNV, GNR, HZO, UC, ...]`
   exempts every `<PREFIX>-NNN` matching one of those prefixes (case-
   insensitive). Most discoverable form — namespace-level allow-list.

2. rivet.yaml `docs-check.ignore-patterns: [<regex>, ...]` for cases
   where namespace matching isn't enough. Free-form regex escape hatch.

3. HTML-comment directives in any markdown:
   `<!-- rivet-docs-check: ignore GNV-396 FOO-1 -->` skips the named
       IDs anywhere in the doc.
   `<!-- rivet-docs-check: ignore-line -->` skips every ID on the same
       line as the directive.
   Most surgical — keeps the exemption visible right at the citation.

Bundled AGENTS.md template now embeds an `ignore SC-1 REQ-001 FEAT-042`
directive so a fresh `rivet init && rivet docs check` doesn't fail on
its own example IDs.

Two regression tests cover both the config and directive paths. The
24 existing doc_check tests still pass — the new context fields are
additive, all in-tree call sites updated.

Implements: REQ-004
Refs: REQ-008

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(stamp): batch filter flags --type, --changed-since, --missing-provenance

Three filter flags so provenance stamping no longer requires shell loops
like `rivet list | grep ... | xargs -I{} rivet stamp {} ...`. All
combinable with each other and with the existing `id "all"` form.

  --type PATTERN
    Glob (`SEC-*`) matches IDs by prefix; otherwise exact artifact-type
    name (`requirement`). Combine with `id "all"` or a wider glob.

  --changed-since REF
    Restrict to artifacts whose source YAML was touched relative to the
    given git ref — committed diff plus uncommitted modifications.
    Falls back to "no matches" on git error so the flag never panics.

  --missing-provenance
    Skip artifacts that already carry a `provenance:` block. Idempotent
    bulk stamping: rerun safely without overwriting human-reviewed
    provenance.

Glob support uses an in-tree minimal `*` / `?` matcher (5 unit tests)
to avoid pulling in the `glob` crate for one tiny need.

Implements: REQ-007
Refs: REQ-008

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: cover AUDIT marker, conditional-rules, rivet-managed contract; require --yes for --force-regen

Closes the documentation gaps the user flagged in Issue #5:

- AUDIT: marker syntax for the ArtifactCounts invariant — explains
  when to use it (manual override of "N items" claims) and that the
  date is not parsed (advisory only).
- conditional-rules: worked example showing when/then structure with
  `equals` condition and `required-fields` requirement.
- rivet-managed BEGIN/END markers contract — content outside the
  markers is preserved across `rivet init --agents` regeneration; only
  use --force-regen if markers were lost.
- rivet docs check escape hatches — three layered exemption
  mechanisms (config namespaces, ignore-patterns regex, HTML-comment
  directives) documented in one place.

CLI safety: `--force-regen` now requires `--yes` (clap requires=).
The destructive overwrite was previously one accidental flag away;
now it needs both `--force-regen --yes` to fire.

CLI clarity: error message for `rivet embed artifact:X` / `links:X` /
`table:T:F` now explains why those embeds only render inside markdown
documents, instead of the cryptic "handled inline" string. Saves
users an hour of debugging.

Refs: REQ-008, REQ-007

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(lsp,yaml): LSP resolves workspace schemas; YAML parser tolerates inline comments

Issue #6 — two LSP-noise sources that train users to ignore the LSP.

(a) LSP schema resolution
    The LSP previously called resolve_schemas_dir(cli) using cli.project,
    which is whatever directory the LSP process was launched from — often
    not the workspace root. So an LSP started from VS Code would look in
    `<cwd>/schemas/` and never find user schemas like
    `<workspace>/schemas/ulinc.yaml`. Result: every artifact-type defined
    in a project schema reported as "unknown artifact type" even though
    `rivet validate` accepted them.

    Now the LSP resolves the schemas directory from the workspace
    `project_dir` (derived from root_uri), with --schemas as the explicit
    override and the binary-relative location as a final fallback.

(b) YAML inline-comment handling
    The CST mapping parser fell to the generic error branch on any
    line whose first non-whitespace token was a Comment, producing
    "expected mapping key, found Some(Comment)" diagnostics on every
    `.github/workflows/*.yml` line with a leading `# ...` comment.
    serde_yaml and python yaml.safe_load both parse the same input fine.

    parse_block_mapping now eats Comment tokens at the key position and
    continues, treating them as trivia. Trailing inline comments and
    nested-mapping leading comments were already handled.

Three regression tests pin the YAML behaviour:
- mapping_with_comment_only_line
- mapping_with_indented_comment_line
- mapping_with_inline_trailing_comment_on_value

Implements: REQ-029, REQ-028
Verifies: REQ-029

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ui,docs,e2e): TOC anchors + variant dashboard docs + Playwright parity

Folds the items originally deferred to v0.4.3 back into v0.4.2 because
the customer needs them shipped together.

UI:
- Markdown headings now emit `id="..."` slugs so in-page TOC links and
  external `#anchor` URLs actually navigate. New `slugify_heading`
  strips embedded HTML (the inline embed resolver may have substituted
  artifact cards), lowercases, and collapses non-alnum runs to single
  hyphens. Two regression tests pin the slug shape and the heading id.

Docs:
- getting-started.md gains a "Variants in the dashboard" subsection
  documenting the auto-discovery convention, the sidebar+dropdown UI,
  and the `/variants` overview page. Closes the doc-reality drift the
  user flagged ("how would I even see the variant").
- what-is-rivet.md section 4.5 mentions the dashboard variant selector
  alongside the CLI workflow.

Playwright:
- New `diagram-viewer.spec.ts` codifies the architectural invariant:
  every dashboard view rendering a diagram (graph, doc-linkage,
  schema-linkage) wraps it in `.svg-viewer` with the same toolbar
  (zoom-fit, fullscreen, popout). Fullscreen toggle verified.
- `artifacts.spec.ts` extended with: (a) artifact mermaid diagram
  wrapped in svg-viewer, (b) "Referenced in Documents" reverse-index
  block visible (skips when fixture has no references).
- `documents.spec.ts` extended with: rendered headings carry `id`
  attributes — TOC navigation regression guard.

Implements: REQ-008
Refs: FEAT-001, REQ-007

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(embed,sexpr,yaml): close 6 silent-accept findings from project audit

Background audit (run after the v0.4.2 batch) flagged 6 more sites
where invalid input was silently swallowed instead of surfaced. All
close before v0.4.2 ships.

P1 — visible silent skips that masked typos as "no data":

- {{coverage:typo-rule}} now errors with a list of known rule names
  instead of rendering "No coverage rules defined" — previously a
  typo'd rule was indistinguishable from a project genuinely without
  rules.
- {{diagnostics:warnings}} (typo for `warning`) now errors with the
  three valid severities. Previously the unknown severity matched the
  `_ => true` arm and returned ALL diagnostics, hiding the typo.
- {{matrix:UnknownType:OtherType}} now errors before rendering. The
  blank table that used to appear was indistinguishable from "rule
  applies but nothing covered yet" — the user couldn't tell their
  typo from a real coverage gap.

P2 — narrower-scope clarity wins:

- sexpr_eval `links-count` now distinguishes "second arg isn't a
  symbol" from "operator literally empty" from "operator not in the
  allowed set", with a hint listing the six valid operators.
- yaml_hir `extract_string_list` now falls back to serde_yaml when the
  CST yields zero items from a non-empty FlowSequence — same defensive
  pattern that fixed `extract_links` for flow-style mappings.
- yaml_hir top-level mapping walk now emits a Warning diagnostic when
  an unknown key looks like a typo of a schema-defined section
  (singular vs plural, fuzzy match). Legitimate metadata keys still
  pass silently. Catches misspellings like `control-action:` (should
  be `control-actions:`) that previously dropped every nested item.

Three new regression tests pin the P1 invariants: matrix rejects
unknown types, diagnostics rejects unknown severities, coverage
rejects unknown filter rules. Each verifies the error message names
the bad input.

Pattern: every fix here returns Err with a hint listing valid values
or known names — the same shape we adopted in the v0.4.2 main batch
for `{{group}}` and `{{query}}` parameter validation.

Implements: REQ-004, REQ-029
Verifies: REQ-004

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(schema,parse): deny_unknown_fields on schema structs + fix docs-check UTF-8 boundary panic

Surfaces SCRC "deterministic parsing / strict schemas" requirement:
typo'd YAML keys in schema author files now error at load time
instead of silently dropping. Annotates every schema-author struct
with `#[serde(deny_unknown_fields)]`:

- SchemaFile, SchemaMetadata, ArtifactTypeDef, MistakeGuide,
  FieldDef, LinkFieldDef, LinkTypeDef, TraceabilityRule,
  ConditionalRule, AlternateBacklink (new) — schema authoring
- Link, Provenance — artifact-level

The strict deserialization immediately surfaced two missing fields the
bundled schemas were already using:
- LinkFieldDef.description — explanatory text per link-field
- TraceabilityRule.alternate_backlinks (new struct) — alternate
  backlink shapes used by safety-case schemas to express
  "supported-by OR decomposed-by OR has-sub-goal" without rule
  duplication

Both added as `#[serde(default)]` Optional/Vec to preserve back-compat;
14 in-tree TraceabilityRule constructors updated to pass `vec![]`.

Tangential bug found while landing this:
- doc_check.rs:557 panicked on multi-byte boundary when slicing the
  32-byte VersionConsistency context window if the cut landed inside
  a multi-byte char (e.g. an em-dash in a heading). Walks back to a
  char boundary first.

Also clarified the resolve_str function in sexpr_eval.rs with a
SAFETY-REVIEW-style comment explaining the intentional empty-string
semantics for missing fields in filter queries (NOT silent-accept;
it's the correct semantics for `(= asil "ASIL-D")` filters that
should naturally exclude artifacts without an `asil` field).

Hardened render_diagnostics severity match: the `_ => true` arm is now
unreachable after the upstream validation pass landed earlier in this
release; replaced with explicit `None` arm + `unreachable!()` for any
other Some(value), so a contract bug fails loudly instead of silently.

CHANGELOG.md gains a v0.4.2 entry covering all 18 silent-accept
findings and the v0.4.3 SCRC roadmap.

Implements: REQ-010, REQ-004
Verifies: REQ-010

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(ci): rivet-delta PR workflow with graphical artifact diff + Playwright coverage

New informational workflow (.github/workflows/rivet-delta.yml) that runs
on every PR touching artifacts/schemas/rivet.yaml/rivet-core/rivet-cli.
For each PR it:

  1. Checks out base (merge-base) and head side-by-side.
  2. Builds rivet-cli in release mode.
  3. Runs `rivet diff --base ... --head ... --format json`.
  4. Runs `rivet impact --since <base-sha> --depth 5 --format json`.
  5. Runs `rivet export --format html --offline` for the head tree.
  6. Generates a PR-comment markdown via scripts/diff-to-markdown.mjs.
  7. Uploads the full delta-out/ (HTML dashboard + JSON) as a workflow
     artifact retained for 14 days.
  8. Posts or updates a single PR comment (found via the hidden marker
     `<!-- rivet-delta-bot -->`) so the diff stays fresh across
     subsequent pushes without stacking.

Security:
  * All user-derived inputs (`pull_request.number`, `pull_request.base.sha`,
    `run_id`, `repository`) are captured at job-scope env and referenced
    from run: blocks via $VAR — follows GitHub's workflow-injection guide.
  * Every diff/impact/export step is `continue-on-error: true`; the script
    gracefully emits a warning comment if either JSON fails to load
    instead of crashing the workflow.
  * Never blocks merge — strictly informational.

Markdown format (scripts/diff-to-markdown.mjs):
  * Hidden `<!-- rivet-delta-bot -->` marker for comment-update lookup.
  * Counts table (added / removed / modified / impacted).
  * Mermaid link-graph diagram, capped at 30 nodes with an `overflow`
    sentinel node for the remainder; 3 classDef styles for
    added/removed/modified.
  * Collapsible `<details>` blocks per change class with 200-row cap
    plus `… +N more` overflow.
  * Workflow-artifact download link.
  * All user-controlled strings escaped (pipe, backtick, *, _, [, ],
    angle brackets) so hostile artifact IDs can't break out of the
    comment structure.

Playwright regression suite (tests/playwright/rivet-delta.spec.ts):
  * 6 tests pinning the "visible and usable" contract:
    - shipping summary renders end-to-end (counts table visible,
      "Modified" details expands, artifact link has correct href).
    - Empty-diff path emits the no-change sentinel (no mermaid block).
    - Malformed-JSON path produces a warning comment, not a crash.
    - Mermaid source parses with the real bundled mermaid.js parser
      (catches broken syntax before a reviewer sees a broken diagram).
    - 30-node cap produces the `overflow` sentinel.
    - Markdown metacharacters in artifact IDs (`*evil*`, `|pipe|`) are
      escaped, not interpreted.

Refs: FEAT-001, REQ-008

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: bump workspace + VSCode + npm to 0.4.2

Three surfaces kept in sync for the v0.4.2 release tag:
- workspace Cargo.toml
- vscode-rivet/package.json
- npm/package.json

Per-platform npm packages (darwin-x64, linux-arm64, etc.) are generated
with matching versions by the release-npm.yml workflow at publish time;
no hand-editing needed.

Trace: skip

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (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.

1 participant