Docs 6: the launch audit - #88
Merged
Merged
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
arpanghoshal
force-pushed
the
docs/8-audit-and-launch
branch
from
September 6, 2026 17:10
744dff5 to
ab14d0d
Compare
Session 6 of the docs milestone. What a machine can check is checked; what a person has to click is in `internal/LAUNCH-CHECKLIST.md`, which is local-only like the other `internal/` files. Three findings needed code. **The README said an unreleased version was on PyPI.** The readiness block read *"Version 0.6.0, on PyPI"* off `pyproject.toml` alone, while `CHANGELOG.md` still says `## [0.6.0] - unreleased` and PyPI holds 0.5.0 — a false sentence on the front page, produced by a generator, which is the one failure a generator exists to prevent. It now reads the changelog for the newest **dated** version and says *"Version 0.6.0 is in development; PyPI has 0.5.0"* until the release lands, at which point dating the entry flips all three copies on its own. Found by fetching the badges and reading what they said. **Every share card on the internet pointed at the wrong domain.** `og:image` and `twitter:image` were `/images/social-preview.png`, and Mintlify resolved that against the deployment origin rather than the custom domain, so the image URL was `ctrlrun.mintlify.app`. Absolute now, on `docs.ctrlrun.dev`. **The home page shared as "CTRLRun - CTRLRun".** Mintlify renders `<title> - <site name>`, and both were `CTRLRun`. It carries its own `og:title` and `twitter:title` now, and a test refuses one that is the site name again. **The three docs audits stop being advisory.** Runnable snippets, the forbidden-words lint and the link check carried `continue-on-error: true` from session 0, because a job that was red on arrival would have taught everyone to ignore it. The baseline is clear — 96 runnable blocks, 182 documents, 0 findings, 0 broken links — so the flags are gone. Adding `docs` to the required status checks is a settings click and is on the checklist; until it is required, a red docs job still merges. What the audit checked and found green: nine generators with `--check`; `CLAIMS.md` re-pointed with no drift and its line-number test passing; every one of the 62 public names has a reference page; `mint validate` and `mint broken-links` both clean; all six tags have a GitHub Release; all seven badges render; the community profile is at 100%; the recording still matches what the demo prints. And the new-user path, from a wheel built here into a fresh 3.12 virtualenv with no repository: `pip install` brings `click` and `pyyaml` and nothing else, `ctrlrun init` writes a policy, `ctrlrun demo` runs five scenarios in 0.12s with no network, `receipts` and `verify` both work, and the quickstart's five runnable blocks pass against that install. Two things the audit found that only a person can fix, both on the checklist: the social preview uploaded to the repository page is still the pre-branding grey image, and `docs` is not yet a required status check.
A session that had not written any of it read the site the way a site is read —
home, Why, the navigation, the links the pages themselves offer — as a backend
engineer with an agent that issues refunds and deploys services. It ran the
commands. Thirty-odd findings; every one below is fixed and most now have a guard.
**The three that would have cost the most trust.**
`reference/cli.mdx` said `Usage: main [OPTIONS] COMMAND [ARGS]...` **fourteen times**,
under a sentence promising each block is "the command's own `--help`, verbatim".
Click takes the program name from `sys.argv[0]`, which under the generator is
`main`. A reader who tried it got command-not-found from the reference page.
`guides/verify-in-ci.mdx` and `cookbook/verify-in-github-actions.mdx` presented
`ctrlrun verify` transcripts as real runs. They were **written, not captured**: every
PASS row named `stripe.refund` where the page's own policy makes verify exercise
`k8s.delete_namespace`, both dropped the stderr line G7's scenario logs, and one
misaligned a column. That is the false-green problem this project spends thousands
of words warning about, arriving in its own quoted evidence. Both are now compared
against a real run of the page's own policy, line by line.
**All seventy-one API reference pages had signatures that raise.** The renderer
emitted `name: annotation` and nothing else, so twenty-seven keyword-only signatures
read as positional and forty-four optional parameters read as required —
`protect('stripe.refund', 'refund:{id}')`, copied off the page, is a `TypeError`.
Protocols rendered as a bare `class X(Protocol)` with none of the members they ask
an implementer for. And not one page carried an import line or named the extra it
needs. A new test compares every rendered signature with `inspect.signature`.
**`docs/ARCHITECTURE.md` had a stray closing fence**, so everything from the module
map to the end of the file rendered inside a code block on the live site — and the
forbidden-words lint, which reads only outside fences, had stopped looking at 88
lines.
**Five pages said every call leaves a receipt, refused ones too.** A receipt is
written when an action reaches a terminal state and *waiting on a human* is not one:
three protected calls leave two receipts. Measured in the test rather than asserted.
**`canonical` and `og:url` were site-wide metatags**, so all 180 pages declared
themselves duplicates of the home page — an instruction to a search engine to index
one and drop the rest.
Wrong and now right: `--store-url`'s help text still said "Reserved; v0.4 accepts
'sqlite'" (the CLI reference rendered it faithfully); the Slack guide's answer body
omitted the two fields the endpoint requires and never gave the signature's wire
format, so the verifier it tells you to write could not be written; the conformance
suite was documented as `python -m ctrlrun.conformance.store`, which has no
`__main__`; `ctrlrun inspect` was passed an approval id; the exit-2 case was
described as a policy with no approve rule, which exits 0; a read-only Postgres role
was said to run `--verify-chain`, which it cannot, because opening the store
migrates it; `PendingApproval` was documented with `principal` and `hash` keys it
does not have; `Subject` was said to require `agent` and to refuse a wildcard, and
both are the opposite; five reserved condition subjects were named where there are
ten; a receipt's `action` field was called `name` and its approver `human:shell`,
a string in no source file; a policy `deny` was shown as `deny/blocked`; four pages
said ten guarantees where there are eleven; the roadmap quoted `10/10` and `5/5`;
`how-this-is-built.md` claimed 1,625 functions and 2,442 cases against 1,704 and
3,944; the threat model said it covers through v0.3 and named a `check` hook that
never shipped; the OWASP mapping listed `ASI06` as both covered and out of scope and
named four of the six chain-break names.
Also: four frontmatter descriptions were cut mid-clause, and they are the search
snippet; `mcp/use-the-docs-from-your-editor` published a production note to its own
author where a screenshot should be; two pages used `just` and `simply`.
**New guards, each mutation-tested:** rendered signatures against `inspect`; quoted
verify transcripts against a run; the receipt count against a measurement; a
guarantee count against the catalogue; the suite size as a floor; no site-wide
canonical; no truncated description; every API page names its import and its extra.
The lint allowlist records why `ROADMAP.md` stays excluded now that it is a site
page: every regulation it names is future work, and the packs section says in its
own words that no pack describes itself as compliant with anything.
arpanghoshal
force-pushed
the
docs/8-audit-and-launch
branch
from
September 6, 2026 17:17
ab14d0d to
72ed75d
Compare
arpanghoshal
enabled auto-merge (squash)
September 6, 2026 17:17
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.
Session 6: read the site as a stranger, run the full audit, write the human steps down. Two halves — what a machine can check, and what only a first read finds.
The fresh read
A session that had not written any of it read the site the way a site is read, as a backend engineer with an agent that issues refunds and deploys services, and ran the commands. Thirty-odd findings. The three that would have cost the most trust:
reference/cli.mdxsaidUsage: mainfourteen times, under a sentence promising each block is the command's own--helpverbatim. Click takes the program name fromsys.argv[0]. A reader who tried it got command-not-found from the reference page.ctrlrun verifytranscripts that were written, not captured. Every PASS row namedstripe.refundwhere the page's own policy makes verify exercisek8s.delete_namespace. That is the false-green problem this project warns about, in its own evidence.*and every default, soprotect('stripe.refund', 'refund:{id}')copied off the page is aTypeError. Protocols rendered with none of their members, and no page had an import line or named its extra.Also fixed: a stray fence in
ARCHITECTURE.mdthat rendered everything from the module map to the end of the file inside a code block on the live site, and hid 88 lines from the lint. Five pages claiming every call leaves a receipt, when a call waiting on a human has none. Site-widecanonicalandog:url, making all 180 pages declare themselves duplicates of the home page.And a long tail of statements that were wrong: the Slack answer body and signature format,
python -m ctrlrun.conformance.store,ctrlrun inspectgiven an approval id, the exit-2 case, a read-only Postgres role running--verify-chain,PendingApproval's keys,Subject's rule, five reserved subjects where there are ten, a receipt'sactionfield calledname,deny/blocked, ten guarantees where there are eleven,10/10and5/5in the roadmap, 1,625 test functions where there are 1,704.Three sentences that were not true yet
pyproject.tomlwhile the changelog says## [0.6.0] - unreleasedand PyPI holds 0.5.0. It reads the changelog for the newest dated version now, and dating the entry flips all three copies on its own.og:imagewas relative.New guards, each mutation-tested
inspect.signaturecanonicalThe three docs audits stop being advisory
Runnable snippets, the forbidden-words lint and the link check carried
continue-on-error: truefrom session 0, so a job red on arrival would not teach everyone to ignore it. The baseline is clear, so the flags are gone. Addingdocsto the required status checks is a settings click and is on the checklist.Checked and green
--checkmint validate·mint broken-linksThe new-user path, from a wheel built here into a fresh 3.12 virtualenv with no repository:
pip installbringsclickandpyyamland nothing else,ctrlrun initwrites a policy,ctrlrun demoruns five scenarios in 0.12s with no network,receiptsandverifywork, and the quickstart's five runnable blocks pass against that install.Left for a person
In
internal/LAUNCH-CHECKLIST.md, which stays local. The social preview on the repository page is still the pre-branding grey image;docsis not yet a required status check; the MCP screenshot needs taking.Not fixed, and listed rather than hidden
ctrlrun initwrites actrlrun.policy/v1policy with noeffect:key, so a reader who starts where the install page points gets no reservation and no one-effect-once — the guarantee the whole site is about. That is asrc/behaviour change and needs your word.ctrlrun>=0.5,<0.6, sopip install ctrlrun-langgraphon 0.6 downgrades the kernel. No site page states a supported kernel range.@protected function, what happens to an abandoned approval request.Verification