Skip to content

feat(bundle): rivet bundle <ID> --depth N --as {yaml,jsonl} (#206)#266

Merged
avrabe merged 2 commits into
mainfrom
fix/issue-206-rivet-bundle
May 11, 2026
Merged

feat(bundle): rivet bundle <ID> --depth N --as {yaml,jsonl} (#206)#266
avrabe merged 2 commits into
mainfrom
fix/issue-206-rivet-bundle

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 9, 2026

Summary

Closes #206 — implements the rivet bundle <ID> --depth N --as {yaml,jsonl} CLI command, the rivet_bundle MCP tool, and the rivet-core/src/bundle.rs module. An LLM agent reasoning about an artifact and its neighbours can now get the full link-graph closure in one round-trip instead of N — closing the gap the issue body identified after Karpathy's LLM Wiki.

What changed

  • rivet-core/src/bundle.rs (new). Breadth-first, visit-once traversal over Store::get + Artifact::links, returning a depth-stamped Vec<BundleEntry>. Cycles terminate via the visited set. Depth 0 = root only; depth 1 = root + direct neighbours. Dangling targets (links pointing outside the store) appear as target: references inside the parent's links: list but are not expanded.
  • BundleFormat::{Yaml, Jsonl} rendering. YAML is hand-rendered (not serde_yaml) because the # satisfies -> REQ-002 inline annotations are the whole point of the format and serde can't round-trip comments. JSONL is one serde_json record per line for tool consumers / streaming readers.
  • rivet-cli/src/main.rs — new Command::Bundle { id, depth, format } variant with --depth (default 1) and --as (default yaml). Handler cmd_bundle loads the project context, calls bundle::bundle, prints the rendered output. Invalid --as values produce a clear error listing the valid options.
  • rivet-cli/src/mcp.rs — new rivet_bundle MCP tool with BundleParams { id, depth, format }. Defaults match the CLI. Returns the rendered bundle as text content.

Acceptance — issue #206 (lifted from the 2026-04-26 + 2026-05-09 triage comments)

  • New module rivet-core/src/bundle.rs with closure traversal over Store + Link graph, depth-bounded — bundle::bundle(), lines 90–122.
  • rivet bundle <ID> --depth N --as {yaml,jsonl} CLI commandCommand::Bundle variant + cmd_bundle handler.
  • MCP tool rivet_bundle so agents call this without shelling — mcp.rs, decorated #[tool(...)] on rivet_bundle.
  • Output carries inline link annotations (# satisfies -> REQ-004 style) — proven by bundle_depth_one_yaml_with_annotations (CLI) and test_rivet_bundle_yaml_depth_one (MCP).
  • Snapshot/regression test fixture: depth-0 → only root; depth-1 → root + neighbours; depth-2 → two-hop closuredepth_zero_returns_root_only, depth_one_returns_root_plus_neighbours, depth_two_includes_two_hop_closure in bundle::tests.
  • Cycle handling tested (artifact A → B → A does not loop) — cycle_terminates.
  • Markdown rendering explicitly out of scope per the issue body.
  • Commit trailer Implements: REQ-007 (CLI) and Refs: FEAT-010 (MCP) — present.

Test plan

  • cargo test -p rivet-core --lib931 pass (920 prior + 11 new bundle::tests).
  • cargo test -p rivet-cli --test cli_commands66 pass (61 prior + 5 new bundle tests: depth-0 root only, depth-1 + annotations, jsonl shape, missing-root non-zero exit, invalid-format rejection).
  • cargo test -p rivet-cli --test mcp_integration24 pass (22 prior + 2 new bundle tests; tools-list count test bumped 15 → 16 to register rivet_bundle).
  • cargo clippy --workspace --all-targets -- -D warnings — clean.
  • cargo fmt --all -- --check — clean.
  • cargo run --release -p rivet-cli -- validate6 errors / 140 warnings / 0 broken cross-refs — byte-identical to pristine main. The 6 errors live in the spar: external fixture and are unaffected.
  • cargo run --release -p rivet-cli -- docs checkPASS (47 files scanned, 0 violations).
  • CI on this PR — verified by GHA.

Out of scope

  • Markdown rendering, per the issue body's "Out of scope" section. YAML preserves typed structure with zero information loss; markdown would re-introduce ambiguity rivet's typed model exists to remove.
  • docs/getting-started.md deep-dive on bundle — left for a docs-only follow-up so the surface lands first and stays focused (one-PR-per-issue rule).

🤖 Generated with Claude Code — issue-triage agent run 2026-05-09.


Generated by Claude Code

Implements the consumer surface proposed in #206 — emit the typed link-graph
closure of an artifact as a single, pasteable document so an LLM agent can
get root + neighbours in one round-trip instead of N. The MCP tool
counterpart (`rivet_bundle`) lets agents call this without shelling out.

What landed:

- `rivet-core/src/bundle.rs` — new module. Breadth-first, visit-once
  traversal over `Store::get` + `Artifact::links`, returning a
  depth-stamped `Vec<BundleEntry>`. Cycles terminate naturally via the
  visited set. Depth 0 = root only; depth 1 = root + direct neighbours;
  etc. Dangling targets (links pointing outside the store) appear as
  `target:` references inside the parent's `links:` list but are not
  expanded.
- `BundleFormat::{Yaml, Jsonl}` rendering. YAML is hand-rendered (not
  serde_yaml) because the inline `# satisfies -> REQ-002` annotations
  are the whole point of the format and serde can't round-trip
  comments. JSONL is one `serde_json` record per line for tool
  consumers / streaming readers.
- `rivet-cli/src/main.rs` — new `Command::Bundle { id, depth, format }`
  variant with `--depth` (default 1) and `--as` (default yaml). Handler
  `cmd_bundle` loads the project context, calls into `bundle::bundle`,
  prints the rendered output. Invalid `--as` values produce a clear
  error listing the valid options.
- `rivet-cli/src/mcp.rs` — new `rivet_bundle` MCP tool with
  `BundleParams { id, depth, format }`. Defaults match the CLI
  (depth=1, format=yaml). Returns the rendered bundle as text content.
- Tests: 11 unit tests in `bundle::tests` covering depth 0/1/2 closure,
  cycle termination, dangling targets, missing-root error, the
  `# linktype -> target` annotation, JSONL line-per-record, format
  parsing, and YAML scalar quoting. 5 CLI integration tests in
  `cli_commands.rs` (depth-0 root only, depth-1 + annotations,
  jsonl shape, missing-root non-zero exit, invalid-format rejection).
  2 MCP integration tests in `mcp_integration.rs` (yaml + jsonl).
  The tools-list count test was bumped from 15 to 16 to include
  `rivet_bundle`.

Out of scope per the issue body: markdown rendering ("the closest
Karpathy analogue is paste the wiki into the LLM context — for rivet,
YAML preserves typed structure with zero information loss").

Acceptance — issue #206 (lifted from the 2026-04-26 + 2026-05-09
triage comments):

- [x] New module `rivet-core/src/bundle.rs` with closure traversal
      over `Store` + `Link` graph, depth-bounded
- [x] `rivet bundle <ID> --depth N --as {yaml,jsonl}` CLI command
- [x] MCP tool `rivet_bundle` so agents can call it without shelling
- [x] Output carries inline link annotations
      (`# satisfies -> REQ-004` style)
- [x] Snapshot/regression test: depth-0 → only root; depth-1 → root +
      neighbours; depth-2 → two-hop closure
- [x] Cycle handling tested (artifact A → B → A does not loop)
- [x] Markdown rendering explicitly out of scope

Verification:

- `cargo test -p rivet-core --lib` — 931 pass (920 prior + 11 new)
- `cargo test -p rivet-cli --test cli_commands` — 66 pass (61 prior + 5 new)
- `cargo test -p rivet-cli --test mcp_integration` — 24 pass (22 prior + 2 new)
- `cargo clippy --workspace --all-targets -- -D warnings` — clean
- `cargo fmt --all -- --check` — clean
- `cargo run --release -p rivet-cli -- validate` — error count
  byte-identical to pristine main (6 errors / 140 warnings / 0 broken
  cross-refs; the 6 errors live in the `spar:` external fixture and
  are unaffected)
- `cargo run --release -p rivet-cli -- docs check` — PASS

Closes #206

Implements: REQ-007
Refs: FEAT-010
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 9, 2026

📐 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: 1cdcc18 Previous: 6dfdca6 Ratio
store_insert/10000 14314238 ns/iter (± 1141835) 10777546 ns/iter (± 201358) 1.33
link_graph_build/10000 32984738 ns/iter (± 2919346) 22905310 ns/iter (± 293676) 1.44
validate/10000 16249974 ns/iter (± 1401829) 12167984 ns/iter (± 144437) 1.34

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

@codecov
Copy link
Copy Markdown

codecov Bot commented May 9, 2026

Codecov Report

❌ Patch coverage is 97.65625% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rivet-core/src/bundle.rs 97.65% 6 Missing ⚠️

📢 Thoughts on this report? Let us know!

@avrabe avrabe merged commit c501467 into main May 11, 2026
62 of 65 checks passed
@avrabe avrabe deleted the fix/issue-206-rivet-bundle branch May 11, 2026 03:51
avrabe added a commit that referenced this pull request May 11, 2026
Three queued feature requests now land: rivet bundle (#266), rivet
coverage --matrix (#243), s-expr linked-via operator (#265). Plus
externals load their own schemas (#267) and STPA TCL numbering is
corrected to ISO 26262-8 (#257).

Infrastructure: CI concurrency control across all workflows (#258),
migration to self-hosted smithy runners (#262), release-npm trigger
fix that retroactively unblocked v0.7.0/v0.8.0 npm publication (#261),
weekly dependabot (#216), and the wasmtime 42→43 upgrade that retires
the RUSTSEC-2026-0114 suppression introduced in v0.8.0 (#260).

#125 (provenance-lifecycle) intentionally deferred — 5-week-old branch
with conflicts in heavily-churned files (CLAUDE.md, ci.yml, settings).
Needs its own attention session, not safe to autonomously rebase.

Refs: FEAT-001

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.

rivet bundle <ID> --depth N — context-window paste artifact

2 participants