Skip to content

Rename runvil-parser to runvil-prompt and finish parser cleanup - #189

Merged
vinniefalco merged 14 commits into
cppalliance:masterfrom
vinniefalco:prompt-crate-cleanup
Nov 2, 2026
Merged

vinniefalco merged 14 commits into
cppalliance:masterfrom
vinniefalco:prompt-crate-cleanup

Conversation

@vinniefalco

Copy link
Copy Markdown
Member

Summary

Thirteen commits that finish the parser cleanup and rename the crate to match what it does.

  • Rename runvil-parser to runvil-prompt. The crate loads a prompt and compiles every Lua fence at load time, so the name now matches that and matches the runvil::prompt facade module.
  • Move the source position helpers into their own position module, so the fence splitter no longer depends on the section walker.
  • The fence splitter finds the closing fence with the same shape test the validator uses. A direct split that meets a malformed closing line now returns an internal error instead of skipping it.
  • ParseError computes its facts from the inner error instead of copying them at construction.
  • The map deserializer takes the key name directly instead of a one-field ContractKeys struct.
  • The tool-loop cap is stored as Option<NonZeroU32> with one validating deserialize_with function. The range check still runs at parse time.
  • Gate the classic-block accessors (prologue, prose, epilog) behind test-support, since no production crate calls them.
  • Drop the unused LuaProgram re-export from the parser surface.
  • Remove the Surfaces section from AGENTS.md, which restated the review principle as rules a scan cannot check. Also update the rest of AGENTS.md.

Notes for review

  • Error message wording is unchanged (model role, arg name).
  • public-api.txt is unchanged; the facade re-exports the same items under the same paths.
  • Behavior change: a direct split that meets an indented or four-backtick closing line now returns an internal error. A validated prompt refuses such lines before the split, so its blocks are unchanged.

Verification

  • cargo nextest run --locked --workspace --exclude workshop --exclude workshop-server --exclude workshop-server-api --all-features
  • cargo clippy gate with CARGO_BUILD_WARNINGS=deny
  • cargo fmt --all --check
  • RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --all-features (excluding workshop crates)
  • cargo +<pinned nightly> xtask api --check
  • cargo test -p build-xtask
  • node --test crates/workshop/ui/test/docs-claims.mjs

The parser's surface listed `LuaProgram`, but no crate outside the parser named it through that path. Delete the re-export and have the three modules and three test modules that name the type import `runvil_lua::LuaProgram` directly.
Delete the `MaxToolIterations` enum, its two methods, and its hand-written `Deserialize`; the frontmatter field now holds an `Option<NonZeroU32>` that one `deserialize_with` function validates. `Frontmatter::max_tool_iterations` returns the field, and each caller resolves its own default.

- The range check still runs at parse: `max_tool_iterations` rejects `0`, negatives, values above `MAX_TOOL_ITERATIONS`, and values above `u32`, so an invalid cap cannot reach execution.
- `detail::max_tool_iterations` is deleted; `ChainState::max_tool_iterations` and the `tool_loop` test now fold the `Option` with `map_or` at their own call sites.
No production crate calls `Section::prologue`, `Section::prose`, or `Section::epilog`; the parser's own tests and the Engine's suite are the only callers. Gate all three behind `test-support` so a production build cannot reach them.

- `tasks-spawn` dropped its `prologue` and `epilog` checks from the list-section guard. A section parses into `items` only when it holds no Lua block, so `items()` alone answers the question.
Remove the Surfaces section. Its rules restated the review principle as seven hard rules that a scan cannot check, and two of them collided on the same item.

- The principle stays in Principles: a reviewer reads one crate at a time, and its code, its surface, and the items it names stay small.
The crate loads a prompt and compiles every Lua fence at load time, so a loaded `Prompt` is ready to run. The name now matches that, and matches the `runvil::prompt` facade module it backs.

- The crate directory, package name, and `runvil_prompt` identifier change; the Engine's `crate::parser` import module becomes `crate::prompt`.
- Crate docs, the crate `README.md`, and four Engine doc lines that called this step "the parser" now describe loading rather than parsing.
- `public-api.txt` is unchanged: the facade re-exports the same items under the same paths.
The fence splitter imported four helpers from the section walker, and the walker imports the splitter. The helpers now live in `position`, and the splitter no longer names `sections`.

- `parse` takes `line_add` from `position` as well.
- The moved functions keep their bodies, signatures, and error messages.
`detail` lives in the same crate as `Prompt`, so `Prompt::h1_blocks` and `Prompt::sections` only repeated a field read. The two `detail` functions now read the fields, so each field has one access path.

- `Prompt::entry` stays, because the test suites call it.
- The `detail` signatures and the Engine's calls are unchanged.
`ContractKeys` held one string and was built at two call sites, so it carried no fact of its own. The map deserializer and its visitor now take the key name directly.

- Error messages keep their wording: `model role` for `models` and `arg name` for `args`.
`ParseError` copied its kind, span, line, and column out of the inner error at construction, so the same facts were stored twice. The accessors now compute them from the inner error on each call. `name` matches the inner error directly, because it returns a borrow.

- The inner error does not change after construction, so the computed values match the copied ones.
- `Classification` no longer carries the frontmatter name, since only `name` reads it and `name` no longer uses the classification.
- The public accessors keep their signatures.
The fence splitter searched for an exact closing line, while the validator used a shape test to find the closing line. The splitter now uses the same shape test, and it reports an internal error when the line it finds is not exactly three backticks.

- A validated prompt refuses any such line before a split, so its blocks are unchanged.
- A direct split that meets an indented or four-backtick closing line now returns an internal error at that line. It used to skip the line and keep reading.
- The test `a_fence_split_that_disagrees_with_the_markdown_parser_is_an_internal_error` passes without change.
The module comment said that none of the modules had to name another, which did not say what the dependency rule was. It now says that the fence splitter does not depend on the section walker.
The MSRV job named the crate runvil-parser. No package has that name, so cargo failed. The job now names runvil-prompt.
@vinniefalco
vinniefalco merged commit 3780eba into cppalliance:master Nov 2, 2026
11 checks passed
@vinniefalco
vinniefalco deleted the prompt-crate-cleanup branch November 2, 2026 02:08

This branch was previously deployed

1 inactive deployment
github-pages — 3780ebae Deployed Nov 3, 2026 by vinniefalco via deploy #158
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