Repository navigation
Add three stock prompt finders to the Harness - #18
Closed
vinniefalco wants to merge 2 commits into
Closed
vinniefalco wants to merge 2 commits into
vinniefalco wants to merge 2 commits into
Conversation
A run held the Packs that its prompt declared plus each `runvil` Pack whose Pack id no declaration took, so a prompt decided which Packs were in its run, and a registry held Packs of two vendors under one Pack id. `add` in `registry.rs` now refuses a Pack id that the registry holds, and `pick` in `packs.rs` takes every installed Pack. A `uses:` entry marks a Pack as required and installs its prelude, and it puts no Pack in a run and takes none out.
- `holder` is in the place of `reserves`, and the reason `pack_id_taken` in the place of `reserved_name`. The refusal names the Pack that holds the id, a built-in or any other, and a Pack that `insert_unavailable` added holds its id too.
- `pick` puts the declared Packs first, in declaration order, then every other installed Pack. It leaves out a Pack whose Pack id an `unresolved` entry names, because the roster lists that id as unavailable. The first step of such a run refuses it.
- `find` names the one other Pack in `write {other} to use that Pack`, where it had `others.join(" or ")`.
- A run makes its instance of every installed Pack and waits on the `ready` of each one, whether or not the prompt declares the Pack. A Pack whose `ready` never resolves holds each run of its Host until a cancel.
- A Pack of another vendor that the prompt does not declare is in the run: its tools are in the catalog, its roster entry has its vendor, and its prelude is not installed.
- The docs of `PackRegistry`, `insert`, `BUILTIN`, `Picked`, and `RUNVIL`, the module doc of `packs.rs`, and two invariants in the runner's `lib.rs` state the rule. The crate docs of `runvil-plugin` and `plugin-web` change by one sentence each.
- `packs-tests-pick.rs` is written over a Host that holds `runvil/web` and `acme/poop`, with `the_pick_is_every_installed_pack_with_the_declared_ones_first` among its tests. `a_pack_inserted_unavailable_holds_its_pack_id` is a test of the registry.
- `an_undeclared_third_party_pack_that_never_gets_ready_holds_no_run_up` is removed. In its place, one test waits for an undeclared Pack of another vendor that starts late, and one cancels a run during that wait.
- The diff changes no file of the Engine crates and neither `public-api.txt` listing.
Plan: /plan/2026-11-14-2-every-pack-in-every-run.plan.md
The change gives a Host three implementations of `PromptFinder`, so that it does not write its own. `prompt_finders.rs` in the runner adds `FindTextPrompt`, `FindFilePrompt`, and `PromptSet`, and the `harness` module of the `runvil` facade re-exports them. A file is read with `std::fs::read_to_string` at each find and no text is kept, and a `PromptSet` lists a directory at `insert_dir` and again at each `rescan`.
- `PromptSet` keeps one `Entry` for each insert in a `Vec`, and its `find` takes the newest entry that has the name. The three inserts take `&mut self`, and `rescan` and `names` take `&self`. The only state that changes in a shared set is the `names` of an `Entry::Dir`, behind a `Mutex`.
- `rescan` holds that lock while it lists the directory. A find holds it for the lookup only, and reads the file after it releases the lock.
- `list_prompts` takes the regular files of the directory whose extension is `md` and whose name is UTF-8. It does not enter a subdirectory, and it skips an entry whose `metadata` fails as `NotFound`. Any other failure of an entry fails the listing.
- `make_io_error` takes the code of a failed read or listing from the `io::ErrorKind`: `NotFound`, `NotUtf8` for `InvalidData`, and `Io` for the rest. The message names the prompt or the directory, then the path, then the cause.
- A find for a name that the finder does not have fails as `NotFound` with the message `no prompt named {name}` and the prose `No prompt has that name.`.
- `insert_dir` returns the failure of the listing and does not keep the directory. `rescan` returns one failure for each directory that it cannot list, clears the names of that directory, and lists the others.
- A find for a file that is removed from a listed directory fails with the failure of the read until the next `rescan`. It does not go to an older entry.
- The `run-prompt` example builds its `Host` with `FindTextPrompt::new(GREET_NAME, GREET)`, and its `find` function is removed.
- `public-api.txt` of `runvil` gains 20 lines: three structs, three `new` functions, five methods of `PromptSet`, and three impls of `PromptFinder`.
- `prompt_finders-tests.rs` has 23 tests. No test covers a link to a file, a file name that is not UTF-8, or an entry that is removed during a listing.
- The diff changes no manifest and no file of the Engine crates.
Plan: /plan/2026-11-14-3-stock-prompt-finders.plan.md
Member
Author
[High impact] The PR appears safe to merge.
|
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.
The Harness now has three ready-made
PromptFinderimplementations, so a Host no longer has to write its own closure to serve its prompts. They are inrunvil::harness.Why
Every Host hand-wrote a finder, and the
run-promptexample and the test suites each repeated the same one. A Host that keeps its prompts in one or more directories needs a little more than a closure: it has to pick up edits, notice new files, and say what it holds.What is added
FindTextPrompt. Serves one prompt, by name, from text given at construction.FindFilePrompt. Serves one prompt, by name, from a file. It reads the file withstd::fs::read_to_stringat each find, so an edit shows in the next find.PromptSet. Holds the prompts a Host inserts as text (insert), as a file (insert_file), or as every prompt file in a directory (insert_dir).rescanlists the directories again, andnameslists what the set serves.How
PromptSetbehavesArc, gives one handle to itsHostas the finder, and keeps the other to callrescanwhen it sees a directory change.rescankeeps going. A directory that cannot be listed holds no prompt until a later rescan lists it, the others are still listed, andrescanreturns one failure for each directory it could not list.insert_diris strict. A directory that cannot be listed is an error and is not kept.mdand whose name is UTF-8. Its name is its file name, such asgreet.md.&mut self, so the list of inserts never changes once the set is shared. Each directory's listing has its own lock. A rescan holds it while it lists, and a find holds it only to look a name up and reads the file after.Failures
Each is the universal
Error:NotFound, with the messageno prompt named {name}and theNamefact.NotFound,NotUtf8, orIo, with the messageprompt {name}: cannot read {path}then the system's reason, and theNameandPathfacts.NotFoundorIo, with the messagecannot list prompt directory {path}then the system's reason, and thePathfact.What else changes
runvil::harnessre-exports the three types.public-api.txtofrunvilgains 20 lines and loses none. Therunvil-enginelisting does not change.run-promptbuilds itsHostwithFindTextPrompt, and its hand-writtenfindfunction is gone.runvilname the stock finders, and the runner has one new invariant: a stock finder reads a file only inside a find, and the Harness calls a finder only fromHost::parse, before the run exists.Tests
prompt_finders-tests.rshas 23 tests:NotFound,NotUtf8, orIo.nameslists every insert, sorted, each name once, and follows a rescan.Hostparses a prompt that its application added to a shared set and rescanned.Three rules of a listing have no test: a link to a regular file counts as that file, a file name that is not UTF-8 is skipped, and an entry that vanishes during the listing is skipped. The first two need a setup for each platform, and the third needs a test seam.
Checks
Every command in
AGENTS.mdpasses on the final tree, with therun-promptexample, the doc build ofrunvilalone, and the private-items doc build ofrunvil-runtime. Nextest runs 3,818 tests, all passing, and skips 24.xtask api --checkpasses on the pinned nightly.Plan and findings:
plan/2026-11-14-3-stock-prompt-finders.plan.md(see "What the build found").