Skip to content

Simplify toolpath format to single Graph root#63

Merged
eliothedeman merged 1 commit intomainfrom
eliot/sad-merkle-89deaa
Apr 28, 2026
Merged

Simplify toolpath format to single Graph root#63
eliothedeman merged 1 commit intomainfrom
eliot/sad-merkle-89deaa

Conversation

@eliothedeman
Copy link
Copy Markdown
Collaborator

Summary

  • Remove the Document enum and the {"Step":…} / {"Path":…} / {"Graph":…} envelope. Every .path.json file is a Graph at the root; every .path.jsonl file is a single-path Graph at the file boundary.
  • Single root type means uniform file shape — one schema, one parser path, no envelope detection across the workspace.

What changed

Core

  • toolpath 0.2.0 → 0.3.0: Document removed. New Graph helpers: from_json / to_json / to_json_pretty, from_path, single_path, into_single_path. JSONL helpers on Graph wrap a single inline Path (new JsonlError::NotSinglePathGraph).

Provider crates

  • toolpath-git 0.1.3 → 0.2.0: derive returns Graph (single branch → single-path graph; multi-branch → multi-path graph).
  • toolpath-pi 0.2.0 → 0.3.0: derive_project returns Graph.

Renderers

  • toolpath-dot 0.1.2 → 0.2.0: render(&Graph, …). Single-path graphs use the path layout, multi-path use clusters.
  • toolpath-md 0.2.0 → 0.3.0: render(&Graph, …). Same dispatch.

CLI (toolpath-cli 0.5.0 → 0.6.0)

  • validate, render, query, merge, import, export, track, cache all operate on Graph at file boundaries.
  • export claude / export gemini reject multi-path graphs with a clear error — projection requires exactly one inline path.

Format artifacts

  • examples/step-NN.json are now single-path single-step graphs.
  • examples/path-NN.path.json are single-path graphs (no envelope).
  • examples/graph-01-release.json drops its envelope. All .path.jsonl regenerated.
  • schema/toolpath.schema.json collapses the root oneOf of three envelopes into $ref: #/$defs/graph.
  • RFC.md, docs/RFC-jsonl.md, README.md, CHANGELOG.md, and per-crate READMEs updated.

Why

The three-variant root forced discriminator logic into every consumer (CLI commands, renderers, schema validators, fixture writers, docs). Collapsing to one root type removes that branching and gives every file a uniform shape — what used to be a bare Step or Path is now a degenerate single-path graph.

Reviewer notes

Mid-way through the change I made a tooling misstep: an early cp partially clobbered two large files. I restored both from HEAD and re-applied just the Document → Graph migration, but it's worth a focused look at:

Diff vs. main on those two files should show no behavior or feature changes beyond the format migration.

Test plan

  • cargo build --workspace clean
  • cargo test --workspace — all tests passing across every crate (no failures)
  • cargo clippy --workspace -- -D warnings clean
  • cargo run -p toolpath-cli -- validate --input <each> passes for all 16 example fixtures (12 JSON graphs + 4 JSONL streams)
  • Render-md snapshot tests regenerated under new single-path-graph rendering
  • Manual smoke test: path import git → cache → path render dot/mdpath validate flow
  • Manual smoke test: path import claude --no-cache | path export claude round-trip on a real session

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 27, 2026

🔍 Preview deployed: https://db8fdccf.toolpath.pages.dev

Copy link
Copy Markdown
Contributor

@akesling akesling left a comment

Choose a reason for hiding this comment

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

LGTM

Comment thread RFC.md Outdated
PascalCase variant names visually distinguish the type tag from the lowercase
structural fields inside (`step`, `path`, `graph`).
A "single PR" or "single conversation" is just a Graph that holds one inline
path in `paths`. A "release" is a Graph with several paths (or `$ref`s).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is a "release"? Did the LLM eat its tail here?

@@ -1,29 +1,31 @@
//! JSONL streaming format for `Path` documents.
//! JSONL streaming format for single-path Toolpath documents.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not necessary in this PR, but do we want to allow general graph streaming via the JSONL?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes absolutely

@od0
Copy link
Copy Markdown

od0 commented Apr 28, 2026

LGTM as well

Remove the `Document` enum and the `{"Step":…}` / `{"Path":…}` /
`{"Graph":…}` envelope. Every `.path.json` file is a `Graph` at the root;
every `.path.jsonl` file is a single-path `Graph` at the file boundary.
What was a bare Step or Path is now wrapped in a single-path Graph —
one schema, one parser path, no envelope to detect.

Why: the three-variant root pushed discriminator logic into every
consumer (CLI commands, renderers, schema, fixtures, docs). Collapsing
to a single root type makes file shape uniform and removes a class of
"which kind is this?" branching across the workspace.

Public API changes (pre-1.0 = potentially breaking):

- toolpath 0.2.0 → 0.3.0 — Document enum removed; new helpers on Graph
  (`from_json`/`to_json`/`to_json_pretty`, `from_path`, `single_path`,
  `into_single_path`) plus JSONL on Graph (`Graph::from_jsonl_*` /
  `to_jsonl_*` wrap a single inline Path; new `JsonlError::NotSinglePathGraph`)
- toolpath-git 0.1.3 → 0.2.0 — `derive` returns Graph
- toolpath-dot 0.1.2 → 0.2.0 — `render` takes &Graph (single-path graphs
  use the path layout, multi-path use the cluster layout)
- toolpath-md 0.2.0 → 0.3.0 — `render` takes &Graph (same dispatch)
- toolpath-pi 0.2.0 → 0.3.0 — `derive_project` returns Graph
- toolpath-cli 0.5.0 → 0.6.0 — file format change end-to-end

CLI: `validate`, `render`, `query`, `merge`, `import`, `export`, `track`,
`cache` all read/write Graph at file boundaries. `export claude` and
`export gemini` reject multi-path graphs with a clear error.

Examples: `step-NN.json` are now single-path single-step graphs;
`path-NN.path.json` are single-path graphs; `graph-01-release.json`
drops its envelope. JSONL fixtures regenerated.

Schema: `schema/toolpath.schema.json` collapses the root `oneOf` of
three envelopes into a direct `$ref` to the `graph` definition.

Docs: RFC.md, docs/RFC-jsonl.md, README.md, CHANGELOG.md, and per-crate
READMEs all updated.

Tests: workspace fully green (cargo build, cargo test --workspace,
cargo clippy --workspace -- -D warnings). Render-md snapshot tests for
step examples regenerated under the new single-path-graph rendering.
@eliothedeman eliothedeman force-pushed the eliot/sad-merkle-89deaa branch from 023a301 to 4c1ee8c Compare April 28, 2026 20:40
@eliothedeman eliothedeman merged commit 2f2fb1b into main Apr 28, 2026
2 checks passed
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.

3 participants