Repository navigation
Remove debt from #172's review and rewrite the README as a storefront - #176
Merged
Merged
Conversation
The README now tells a new reader what Runvil does, how to get Workshop, and what a prompt looks like. One screenshot, `images/workshop-window.jpg`, replaces the five banner images and the portrait. Six sections follow: Workshop, a sample prompt, how the parts fit together, documentation, contributing, and the license. - The download link goes to the `nightly` release, because the `workshop-latest` tag has no release with installers. The text tells the reader that nightly builds do not update themselves. - The documentation link changes from `https://cppalliance.org/runvil/`, which returns 404, to `https://gh.cppalliance.org/runvil/`. The text also links the Language guide and the Gateway guide. - The Workshop text no longer says that a user can review every recorded run, because no screen reads the run log yet. It now describes agents in the chat panel and a local log that only grows. - The six images that the old text showed, `images/banner-02.png` to `images/banner-06.png` and `images/runvil-portrait.png`, stay in the repository. - The change adds no check that keeps the example equal to `prompts/greet.md`.
The documentation site is now at `https://gh.cppalliance.org/runvil/`, and `runvil.org` redirects to it. The root `README.md` shows `runvil.org` as the documentation site. `crates/gateway/app/README.md` links the gateway guide at `https://gh.cppalliance.org/runvil/gateway/` instead of `https://cppalliance.org/runvil/gateway/`. - The guide links in `README.md` keep their `https://gh.cppalliance.org/runvil/` paths, because `runvil.org` sends every path to the landing page.
vibelight writes a markdown outline and an HTML page for each workspace crate. The config chooses which crates a plain vibelight run outlines, and the output folder ignores its own outlines so they stay out of the history. - `vibelight.toml` outlines the whole workspace and follows every path dependency, but excludes the six `build-*` tooling crates and `crates/harness-internal/test-plugin`. It writes to `.vibelight`. - `.vibelight/.gitignore` ignores `*.md` and `*.html`, so the folder tracks only its ignore file.
The shipped research prompt told the model to use its web tools by their ids, but the model only knows tools by their wire names. The prompt now describes searching and fetching by what they do, so the text stays correct however the tools are named to the model. A new test checks that no user message the model reads names an offered tool's id. - `research_ada_lovelace` holds the scenario both shipped tests run and returns its `Trace`, which `support.rs` now re-exports to the suite. The existing end-to-end test keeps every assertion it had. - `the_shipped_research_prompt_names_no_tool_by_its_id_in_what_the_model_reads` serializes every user message in every `EffectRecord::Chat` and fails if one contains `web/search` or `web/fetch`. It checks only user messages, the text the prompt itself puts in front of the model, and it requires at least one so an empty run cannot pass. - `web/search` and `web/fetch` still appear in the section's Lua offer, which addresses tools by id. Only the prose sent to the model changes. Repairs: user messages name no offered tool id @ prompts/research-person.md - the research prose named the tool ids web/search and web/fetch Plan: vibe/2026-10-27-1-pr172-debt-removal.md
An admission pass that hit an internal error returned partway through, after it had already taken the queue it was working through and marked earlier admissions in the same pass as holding their slots. Those admissions never reached the scheduler, so a task that never started could read as admitted, and a parked chain waiting to take its slots back could be dropped and never resume. The pass now works on its own copies of both queues, the set of slot holders, and the map of given-back slots, and writes them back only when it succeeds. Which passes fail, their messages, and the order of admission stay the same; only the state left behind after a failure changes. - `plan` on `Admission` clones `holding` and `released`, builds the new resume and spawn queues locally, and assigns all four to `self` only just before it returns `Ok`. It checks each queued spawn by reference and moves the spawn records out of `self.spawned` only after the last check, so no error return can strand one. - `slot_holder` and `slots_in_use` move out of `Admission` into free functions that take the given-back map and the holder set as arguments, so the pass reads its working copies rather than `self`. - `plan` still checks only the entries it would admit instead of validating every queued entry up front, since that would make some passes fail that succeed today. - `is_queued` still reads the live spawn queue during the resumption checks. That queue stays untouched until the pass succeeds, so those checks see the same queue as before and the pass admits the same entries in the same order. - `self.holding.clone()` and `self.released.clone()` now run on every pass with something queued. A pass with both queues empty still returns before copying anything. - `admission-tests.rs` adds two regressions that fail a pass on a queued call chain, one after starting a task and one after admitting a parked call chain's resumption; between them they check that both queues, the holders, and the given-back map come through untouched. The second also checks the resumption is admitted once the stray spawn is forgotten, and the existing bad-resumption test now checks its resumption stays queued. - `plan` keeps its signature and both error messages, so its caller in the scheduler does not change. Design: new oversized-unit @ crates/runvil-internal/engine/src/execute/scheduler/admission.rs::Admission::plan Design: new pure-function @ crates/runvil-internal/engine/src/execute/scheduler/admission.rs::slot_holder deps: ChainIndex,HashMap Design: new pure-function @ crates/runvil-internal/engine/src/execute/scheduler/admission.rs::slots_in_use deps: ChainTree,HashSet Repairs: an unqueued task chain has been admitted @ crates/runvil-internal/engine/src/execute/scheduler/admission.rs::Admission::plan - a failed pass left a never-started spawn unqueued and holding its slots Repairs: a woken chain queued to take its slots back is admitted again @ crates/runvil-internal/engine/src/execute/scheduler/admission.rs::Admission::plan - a failed pass consumed a queued resumption that no later pass admitted Plan: vibe/2026-10-27-1-pr172-debt-removal.md
The engine kept its own two-variant enum for a section's Static Set and Dynamic Set beside the Lua crate's enum for which set an offer feeds, so two types modeled one concept and had to be kept in step. The module that defines the set errors also imported that enum from the scope module, which in turn imports the set errors, so the two modules depended on each other. The engine now uses the Lua crate's enum everywhere, and that enum renders the same Static Set and Dynamic Set text, so every merge error message reads exactly as before. - `OfferMode` gains a `Display` impl that writes `Static Set` and `Dynamic Set`, the same text the deleted engine enum wrote, so one enum now serves both offers and the engine's frozen sets. - `FrozenSet` is deleted with its `Display`, and `set_of`, `set_mut`, `check_set`, `lay_out`, and the set pairing in `refuse_clash` take or match `OfferMode` instead. The engine reaches it through the `crate::lua` import list it already used. - `SetTool` types its `set` field as `OfferMode`, imported straight from `runvil_lua`, so the set-error module no longer imports `execute::scope` and the import cycle between the two modules is gone. - `rule_five_fails_a_wire_name_used_twice_within_one_set_or_across_the_sets` now asserts the full message for a wire-name clash across the Static Set and Dynamic Set, which pins the set names the message interpolates. The other scope tests change only which enum names the set; their expected rules and messages stay as they were. - `OfferMode` keeps its name, variants, and derives; the `Display` impl is the only change to it. Design: removes parallel-abstraction @ crates/runvil-internal/engine/src/execute/scope.rs::FrozenSet Design: removes cyclic-dependency @ crates/runvil-internal/engine/src/error/sets.rs Plan: vibe/2026-10-27-1-pr172-debt-removal.md
Add a test that checks every discovery tool id parses as a tool id whose Pack is reserved. The discovery ids and the reserved Pack list are spelled out separately, so renaming one without the other would let a vendor Pack take the discovery namespace with nothing to catch it. Both ids already sit under a reserved Pack, so the test guards against a future rename rather than fixing a current failure. - `crates/runvil-internal/lua/src/scope.rs` changes only by a `#[cfg(test)]` module at its end, loaded from the sibling `scope-tests.rs` through `#[path = "scope-tests.rs"]`. The file had no test module before. - `every_discovery_tool_id_sits_under_a_reserved_pack` walks `DiscoveryTool::ALL`, parses each `tool.id()` with `ToolId::parse`, and asserts `id.pack().is_reserved()`, with a failure message naming the id. An id that stops parsing as a tool id fails the test through `expect` as well. Plan: vibe/2026-10-27-1-pr172-debt-removal.md
The two shared tool-dispatch functions took an optional call counter, but both engine call sites passed nothing because the engine had already counted the call at dispatch. This change removes the parameter, the increment it guarded, and the lint exemptions its long parameter list needed. The engine's dispatch path behaves as before, and the docs and tests stop describing a count taken here. - `prepare_dispatch` and `prepare_model_dispatch` no longer take `counts: Option<&ToolCallCounts>`, so `prepare_dispatch` drops its `if let Some(counts) = counts` increment and `prepare_model_dispatch` stops forwarding the argument. Both lose their `clippy::too_many_arguments` expectations, since seven parameters no longer trip that lint and an unfulfilled expectation would fail clippy. - `accept_tool_call` passed `None` for the counts at both of its dispatch calls, so dropping the argument leaves that path's behavior unchanged. Both functions keep their return types, so its error handling stays as it was. - `prepare_dispatch` now documents only `Error::Tool` under `# Errors`, dropping the error for a counter id that was never seeded. `prepare_model_dispatch` documents that it propagates every other `prepare_dispatch` error and turns the tool's own failure into the call's result. - `prepare_dispatch_wraps_a_canned_untrusted_output_and_reports_it` loses the `ToolCallCounts` local and the assertion that the tool's count reached 1, and keeps its other assertions. The other dispatch test calls only drop their `None` argument. - `ToolCallCounts` itself is untouched; the diff removes only its import and its uses in the dispatch module and its tests. Plan: vibe/2026-10-27-1-pr172-debt-removal.md
The error-chain renderer's doc gave an Engine error variant as its example of a variant that copies its source's text into its own message, and that variant no longer exists. The example clause is gone and the paragraph is rewrapped. The skip rule it documents and the code are unchanged. - `display_chain` The doc still says a cause is skipped when its text already appears in the text rendered so far, by a plain substring test. Only the doc paragraph changes, and the function body does not. - `LuaRuntime` The doc now names no example variant at all, rather than a substitute. Plan: vibe/2026-10-27-1-pr172-debt-removal.md
Plan: vibe/2026-10-27-1-pr172-debt-removal.md
This branch was successfully 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
This pull request carries two series. The first 3 commits rewrite
README.mdas a storefront, update the documentation links in two READMEs, and add the vibelight config. The next 7 commits remove debt that a review of #172 found in its 27 merged commits (951e4bb9b..1d6937459). Two of those fixes are real bugs, each with a regression test that failed before its fix. The rest are cleanups with no behavior change. The plan that drove the series,vibe/2026-10-27-1-pr172-debt-removal.md, comes with it and gives the evidence for each fix. The labels in parentheses below match its Debt Inventory.README and vibelight
README.mdnow tells a new reader what Runvil does, how to get Workshop, and what a prompt looks like. One screenshot,images/workshop-window.jpg, replaces the five banner images and the portrait, which stay in the repository.nightlyrelease, because theworkshop-latesttag has no release with installers, and the text says nightly builds don't update themselves. The Workshop text no longer says a user can review every recorded run, because no screen reads the run log yet.https://cppalliance.org/runvil/, which returns 404, tohttps://gh.cppalliance.org/runvil/, in the root README and incrates/gateway/app/README.md. The root README showsrunvil.org, which redirects there, as the documentation site.vibelight.tomlhas vibelight outline the whole workspace except the sixbuild-*tooling crates andcrates/harness-internal/test-plugin..vibelight/.gitignorekeeps the generated outlines out of the history.Bug fixes
prompts/research-person.md, told the model to useweb/searchandweb/fetch. Those are tool ids, but the model only knows tools by their wire names,web_searchandweb_fetchtoday. A model that followed the prose literally would call a tool outside its sets, and the section would fail. The prose now describes searching and fetching by what they do, so it stays correct however a Pack names the tools to the model. A new test checks that no user message the model reads names an offered tool's id, and it failed before the prose change. The prompt'stools.offerline still names the tools by id, which is correct for Lua. (C-1)Admission::plannow works on its own copies of both queues, the slot holders, and the given-back slots, and writes them back only when the pass succeeds. Which passes fail, their messages, and the order of admission stay the same. The only behavior change is the state admission keeps after an internal error, which only a scheduler bug can reach. The new regression tests inadmission-tests.rsfailed before the fix, and the existing bad-resumption test now also checks that its resumption stays queued. (D1-24)Cleanups with no behavior change
FrozenSetenum beside runvil-lua'sOfferMode, two types for one concept, and the engine'serror::setsandexecute::scopemodules imported each other because of it.FrozenSetis gone, andOfferModegains aDisplaythat writes the sameStatic SetandDynamic Settext, so every merge error message reads exactly as before and the import cycle is gone. One scope test now asserts the full message for a wire-name clash across the two sets. (D1-11, D1-19)dynamic/searchanddynamic/call, and the reserved Pack list were spelled out separately, so renaming one without the other would let a vendor Pack take the discovery namespace with nothing to catch it. A new runvil-lua test checks that every discovery tool id parses under a reserved Pack. It passes today and guards against a future rename. (D1-23)prepare_dispatchandprepare_model_dispatchtook an optional call counter, but the engine always passed nothing because it counts each call before dispatch. The parameter, its increment, and theclippy::too_many_argumentsexpectations it needed are gone, and the docs and tests stop describing a count taken there.ToolCallCountsitself is untouched. (D1-27)display_chain's doc gave the Engine'sLuaRuntimevariant as an example, and that variant no longer exists. The example clause is gone, and the code is unchanged. (D1-31)Breaking changes
None.
crates/runvil/public-api.txtis unchanged, and the one enum that gained an impl,OfferMode, lives in the internal runvil-lua crate. Every merge error message keeps its exact text.Guide
The guide change is on
cppalliance/runvil-docsmaster (d81228d..6727f22): cppalliance/runvil-docs@d81228d...6727f22It corrects one paragraph in the limits chapter that said the Harness can replace any default limit, so a run's limits could differ from the table. The Engine accepts other limits from the code that starts a run, but the Harness passes none today, so every run observes the defaults. (D1-34)
Test plan
Each step ran its own checks before its commit: nextest on the crates it touched, clippy with warnings denied on those crates, and fmt. The research prompt step also ran the docs-claims scan. The
OfferModestep also ran the engine's private-items rustdoc gate and a check that nothing in the engine still namesFrozenSet. The discovery-id step also rancargo test -p build-xtask, because it wires a new test file.The final step ran the full set over the whole series: workspace nextest, workspace clippy with warnings denied, fmt, both rustdoc gates,
cargo test -p build-xtask, the docs-claims scan, andxtask api --check, which confirms the public API listing didn't change.The research prompt and admission regression tests failed before their fixes and pass after them. The discovery-id guard passed at once, as expected.
Workshop nextest and clippy, the headless gateway check,
cargo deny, and the 1.95 build were not run locally for this series and are left to CI on this pull request. The README and vibelight commits change no Rust code.