Repository navigation
Rename runvil-parser to runvil-prompt and finish parser cleanup - #189
Merged
vinniefalco merged 14 commits intoNov 2, 2026
Merged
Conversation
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
temporarily deployed
to
github-pages
November 2, 2026 02:10 — with
GitHub Actions
Inactive
vinniefalco
temporarily deployed
to
github-pages
November 2, 2026 07:23 — with
GitHub Actions
Inactive
vinniefalco
temporarily deployed
to
github-pages
November 3, 2026 07:22 — with
GitHub Actions
Inactive
This branch was previously deployed
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
Thirteen commits that finish the parser cleanup and rename the crate to match what it does.
runvil-parsertorunvil-prompt. The crate loads a prompt and compiles every Lua fence at load time, so the name now matches that and matches therunvil::promptfacade module.positionmodule, so the fence splitter no longer depends on the section walker.ParseErrorcomputes its facts from the inner error instead of copying them at construction.ContractKeysstruct.Option<NonZeroU32>with one validatingdeserialize_withfunction. The range check still runs at parse time.prologue,prose,epilog) behindtest-support, since no production crate calls them.LuaProgramre-export from the parser surface.Notes for review
model role,arg name).public-api.txtis unchanged; the facade re-exports the same items under the same paths.Verification
cargo nextest run --locked --workspace --exclude workshop --exclude workshop-server --exclude workshop-server-api --all-featurescargo clippygate withCARGO_BUILD_WARNINGS=denycargo fmt --all --checkRUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --all-features(excluding workshop crates)cargo +<pinned nightly> xtask api --checkcargo test -p build-xtasknode --test crates/workshop/ui/test/docs-claims.mjs