-
Notifications
You must be signed in to change notification settings - Fork 1
Add a consumption test for the compiled wiki #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| # OKF consumption test — design | ||
|
|
||
| **Date:** 2026-07-31 | ||
| **Status:** approved, for implementation | ||
|
|
||
| ## Problem | ||
|
|
||
| `md2okf` is verified end to end as a *producer*: a 382 KB book compiles into a | ||
| 38-page OKF wiki that passes `okf-lint`. Nothing verifies the wiki is any | ||
| *use*. Completeness and well-formedness are not usefulness, and OKF's own goals | ||
| name consumption explicitly: | ||
|
|
||
| > Inform how **consumption agents** should read and traverse it. | ||
| > — `SPEC.md`, Goals §2 | ||
|
|
||
| So: can an agent holding only the compiled wiki apply the knowledge in it, and | ||
| can we tell the difference between it having done so and it having guessed? | ||
|
|
||
| ## The prior-knowledge problem | ||
|
|
||
| This is the crux. A capable model already knows roughly what Economist house | ||
| style is. Hand it a badly written paragraph and a wiki, and a good rewrite | ||
| proves nothing — it may never have opened a page. | ||
|
|
||
| Two mitigations, both required: | ||
|
|
||
| 1. **Arbitrary rulings.** Cases are built on house rulings a model cannot | ||
| derive from general knowledge, several of which invert the common | ||
| convention. The strongest is `%`: most style guides prefer spelling out | ||
| "per cent", and this one requires the sign. A model working from priors gets | ||
| it backwards. | ||
| 2. **Verified citations.** Every change must cite the page it came from, and | ||
| grading checks the cited page *actually says so*. A plausible citation to a | ||
| page that does not support the claim fails. | ||
|
|
||
| There is deliberately **no A/B control arm** (running each case again with the | ||
| wiki absent). It would be the cleanest evidence of contribution, but it doubles | ||
| the runs, and the counterintuitive rulings already give the test the ability to | ||
| fail when the wiki is unread. Recorded as a known limitation, not an oversight. | ||
|
|
||
| ## Isolation | ||
|
|
||
| A second Compose service, `pi-consume`, reusing the existing image: | ||
|
|
||
| | Mount | Compile run | Consumption run | | ||
| | --- | --- | --- | | ||
| | `md/` | read-only | **absent** | | ||
| | `okf/` | read-write | **read-only** | | ||
|
|
||
| `md/` is unmounted so the agent cannot reach the source book — only the compiled | ||
| wiki. `okf/` is read-only because consumption must not mutate the artefact under | ||
| test; it also means the run needs no writable mount at all. | ||
|
|
||
| The driver passes `--provider` and `--model` explicitly rather than editing | ||
| `settings.json`, so the test states which model it exercised and leaves repo | ||
| config untouched. | ||
|
|
||
| ## Output contract | ||
|
|
||
| The agent writes nothing. Its final message is the result, captured from | ||
| `pi -p` stdout, and must end with a fenced `json` block: | ||
|
|
||
| ```json | ||
| { | ||
| "rewrite": "the corrected paragraph", | ||
| "changes": [ | ||
| { | ||
| "before": "per cent", | ||
| "after": "%", | ||
| "ruling": "Use the sign % instead of per cent.", | ||
| "citation": "/part-2/7-sweating-the-small-stuff-punctuation-mechanics-and-conventions.md" | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| The grader reads the **last** fenced `json` block, so surrounding prose is | ||
| harmless. A missing or unparseable block fails the case explicitly rather than | ||
| scoring zero silently. | ||
|
|
||
| ## Grading | ||
|
|
||
| Three mechanical assertions per case. No LLM judge — every check is a string or | ||
| filesystem operation, so the result is deterministic and reproducible. | ||
|
|
||
| 1. **applied** — every `expect_present` string appears in `rewrite`, and every | ||
| `expect_absent` string does not. | ||
| 2. **cited** — at least one `changes[].citation` resolves to a file that exists | ||
| in the bundle. | ||
| 3. **grounded** — that cited file contains the case's `grounding` text. | ||
|
|
||
| A case passes only when all three hold. Assertion 3 is what makes hallucinated | ||
| citations fail: getting the edit right by luck and inventing a source still | ||
| fails the case. | ||
|
|
||
| ## Cases | ||
|
|
||
| All eight are verified present in the compiled wiki. `ch6` is | ||
| `/part-2/6-confusables-and-cuttables-individual-rulings.md`. | ||
|
|
||
| | # | Ruling | Page | Discriminates because | | ||
| | --- | --- | --- | --- | | ||
| | 1 | `%` not "per cent" | ch7 | inverts the usual convention | | ||
| | 2 | do not verb "impact" | ch9 | house prohibition, not grammar | | ||
| | 3 | "due to" modifies nouns only | ch6 | prefers *because of* / *owing to* | | ||
| | 4 | "decimate" = a significant proportion | ch6 | not total destruction | | ||
| | 5 | "fewer" for countables | ch6 | common error, explicit ruling | | ||
| | 6 | no sentence-initial "Hopefully," | ch6 | explicitly *not* a grammar rule | | ||
| | 7 | "alibi" ≠ excuse | ch6 | semantic ruling | | ||
| | 8 | "compared with" for evaluation | ch6 | fine distinction against *compared to* | | ||
|
|
||
| ## Failure taxonomy | ||
|
|
||
| Infrastructure failure must never read as "the wiki is bad". The driver exits: | ||
|
|
||
| - `0` — all cases passed | ||
| - `1` — at least one case failed on its assertions (a real result) | ||
| - `2` — infrastructure trouble: missing key, gateway error, no wiki, no cases | ||
|
|
||
| ## Components | ||
|
|
||
| | Path | Purpose | | ||
| | --- | --- | | ||
| | `pi/{container,sandbox}/…/skills/apply-house-style/SKILL.md` | the consumption task, one copy per runtime, aligned by hand | | ||
| | `tests/house-style/cases.yaml` | fixtures: input, assertions, expected page, grounding | | ||
| | `tests/house-style/grade.py` | the three assertions, table output, exit code | | ||
| | `scripts/test-house-style.sh` | driver: one Pi run per case, then grade | | ||
| | `pi/container/compose.yaml` | adds the `pi-consume` service | | ||
|
|
||
| ## Non-goals | ||
|
|
||
| - **Navigability.** The container ships `ripgrep` and `fd`, so the agent will | ||
| likely grep rather than traverse `index.md` files. This test says nothing | ||
| about whether the index structure works. | ||
| - **Prose quality.** Only the specific rulings are graded, not whether the | ||
| rewrite reads well. | ||
| - **The sandbox runtime.** Implemented for parity, exercised on the container | ||
| runtime only, matching how every other result in this repo was obtained. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| --- | ||
| name: apply-house-style | ||
| description: Rewrite a paragraph to follow the house style recorded in the OKF wiki under okf/, citing the page each change came from. Use when a run asks you to apply house style to a passage. | ||
| --- | ||
|
|
||
| # Apply house style from the wiki | ||
|
|
||
| You are given one paragraph. Rewrite it so it follows the house style recorded | ||
| in the OKF wiki under `okf/`, and say which page each change came from. | ||
|
|
||
| The wiki is **read-only** in this run and there is no source document to fall | ||
| back on — `okf/` is all you have, and it is the point. Answer from what the | ||
| pages actually say, not from what you already believe about house style. The | ||
| two often disagree, and here the wiki wins. | ||
|
|
||
| ## Procedure | ||
|
|
||
| 1. **Find the rulings.** Search `okf/` for the words and constructions used in | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Much of style guides are rules for specific words. In these cases, the CLI tools vale (active development, 5.7k stars) or qmd (active development, 28.5k stars) in addition to The harder problem are soft, less specific rules. Even if you can load thousands of lines of |
||
| the paragraph. A ruling is usually a short section named after the word it | ||
| governs. Read the page before relying on it. | ||
| 2. **Apply only what you found.** Make a change when a page supports it. Do not | ||
| make stylistic improvements the wiki does not ask for — an unsupported change | ||
| cannot be cited, and uncited changes are the failure this task looks for. | ||
| 3. **Leave the rest alone.** Preserve the paragraph's meaning, facts and | ||
| figures. You are correcting style, not rewriting the argument. | ||
| 4. **Report** in the format below. | ||
|
|
||
| ## Output format | ||
|
|
||
| End your reply with a fenced `json` block, and put nothing after it: | ||
|
|
||
| ````text | ||
| ```json | ||
| { | ||
| "rewrite": "the full corrected paragraph", | ||
| "changes": [ | ||
| { | ||
| "before": "the original wording", | ||
| "after": "the corrected wording", | ||
| "ruling": "a short quote of what the page says", | ||
| "citation": "/part-2/6-confusables-and-cuttables-individual-rulings.md" | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
| ```` | ||
|
|
||
| - `rewrite` — the whole paragraph, corrected. Not a diff, not a fragment. | ||
| - `changes` — one entry per change. An empty list is a valid answer if the | ||
| wiki genuinely supports no change. | ||
| - `ruling` — quote the page, briefly. Do not paraphrase it into something the | ||
| page does not say. | ||
| - `citation` — a **bundle-absolute** path to a page that exists, rooted at the | ||
| wiki root: `/part-2/….md`, not `okf/part-2/….md` and not a relative path. | ||
|
|
||
| Cite the page you actually read. A citation to a page that does not contain the | ||
| ruling is worse than making no change at all: it presents a guess as sourced. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| --- | ||
| name: apply-house-style | ||
| description: Rewrite a paragraph to follow the house style recorded in the OKF wiki under okf/, citing the page each change came from. Use when a run asks you to apply house style to a passage. | ||
| --- | ||
|
|
||
| # Apply house style from the wiki | ||
|
|
||
| You are given one paragraph. Rewrite it so it follows the house style recorded | ||
| in the OKF wiki under `okf/`, and say which page each change came from. | ||
|
|
||
| The wiki is **read-only** in this run and there is no source document to fall | ||
| back on — `okf/` is all you have, and it is the point. Answer from what the | ||
| pages actually say, not from what you already believe about house style. The | ||
| two often disagree, and here the wiki wins. | ||
|
|
||
| ## Procedure | ||
|
|
||
| 1. **Find the rulings.** Search `okf/` for the words and constructions used in | ||
| the paragraph. A ruling is usually a short section named after the word it | ||
| governs. Read the page before relying on it. | ||
| 2. **Apply only what you found.** Make a change when a page supports it. Do not | ||
| make stylistic improvements the wiki does not ask for — an unsupported change | ||
| cannot be cited, and uncited changes are the failure this task looks for. | ||
| 3. **Leave the rest alone.** Preserve the paragraph's meaning, facts and | ||
| figures. You are correcting style, not rewriting the argument. | ||
| 4. **Report** in the format below. | ||
|
|
||
| ## Output format | ||
|
|
||
| End your reply with a fenced `json` block, and put nothing after it: | ||
|
|
||
| ````text | ||
| ```json | ||
| { | ||
| "rewrite": "the full corrected paragraph", | ||
| "changes": [ | ||
| { | ||
| "before": "the original wording", | ||
| "after": "the corrected wording", | ||
| "ruling": "a short quote of what the page says", | ||
| "citation": "/part-2/6-confusables-and-cuttables-individual-rulings.md" | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
| ```` | ||
|
|
||
| - `rewrite` — the whole paragraph, corrected. Not a diff, not a fragment. | ||
| - `changes` — one entry per change. An empty list is a valid answer if the | ||
| wiki genuinely supports no change. | ||
| - `ruling` — quote the page, briefly. Do not paraphrase it into something the | ||
| page does not say. | ||
| - `citation` — a **bundle-absolute** path to a page that exists, rooted at the | ||
| wiki root: `/part-2/….md`, not `okf/part-2/….md` and not a relative path. | ||
|
|
||
| Cite the page you actually read. A citation to a page that does not contain the | ||
| ruling is worse than making no change at all: it presents a guess as sourced. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix stale fixture-file extension in the Components table.
Line 125 lists
tests/house-style/cases.yaml. The actual fixtures file added in this PR istests/house-style/cases.json. A reader following this table to find or edit fixtures looks for the wrong file.📝 Proposed fix
As per path instructions, "flag commands, paths, options, and examples that this change has made wrong or stale."
📝 Committable suggestion
🤖 Prompt for AI Agents
Source: Path instructions