Skip to content

Sweep stale status claims and gate the spec - #114

Merged
djankov merged 1 commit into
mainfrom
wave32-docs-sweep-and-gate
Aug 17, 2026
Merged

Sweep stale status claims and gate the spec#114
djankov merged 1 commit into
mainfrom
wave32-docs-sweep-and-gate

Conversation

@djankov

@djankov djankov commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Wave 32, the docs half: the two sweeps and the gate, in one PR because the gate's acceptance criterion is that it is green on the tree after the sweeps land. Landing them separately would mean landing a red check.

Closes #110 · Closes #111 · Closes #112 · files astro-mine-cli#38


#110 — stale status claims

Ten sentences described shipped work as pending. The ones that mattered:

Where Said Is
architecture/README.md astro-mine-api "Not yet stood up" stood up
architecture/README.md ui "the pages land across Waves 29–30" every page ships
architecture/conventions.md §3.1 "astro-mine-api … is not built yet" built
architecture/system.md §11 distribution track "in progress" done, 2026-08-08
roadmap/README.md "in progress" — nine lines above "All five items are done" done
guide/tutorials/08 dependencies = ["astro-mine-allocate"] astro-mine-platform

The tutorial one was the worst of them: astro-mine-allocate is a distribution that never existed and was never published, so the instruction could not work. Verified by running the scaffoldastro-mine plugin new solver ./my_solver emits dependencies = ["astro-mine-platform"] at line 22, and has since astro-mine-cli#18 closed on 2026-07-30. The page told readers to patch it by hand for longer than the defect existed.

guide/reference/cli.md and guide/tutorials/07 needed care rather than a find-and-replace: both quote astro-mine studio serve, whose output is genuinely still stale. The quote is correct — it is what the command prints today — so the prose around it now explains that the conclusion survives while its premise does not (the API is stood up; nothing is on a package index during incubation, so there is still nothing to install), and points at astro-mine-cli#38, filed for the message itself.

#111 — counts, archival, composition roots

The count was wrong in eight places and wrong in two directions, because "eighteen" was doing duty for two different sets. Ground truth: seventeen Python component repositories, nineteen repositories deleted (the seventeen plus astro-mine-console and astro-mine-view). So this is not one number applied everywhere — each site now counts the set it actually means:

  • seventeen where it is the wheel's provenance and its merged dependency sets;
  • nineteen where it is what was deleted, what collapsed into four distributions, and how many release processes there used to be.

Three places still said "archived". Archival was the original decision, it was reversed, and roadmap/README.md §RM-DIST-05 — which is accurate and detailed — was the only place that said so. The summary at the top of the same file still called the history "kept readable rather than deleted", which is the reversed decision stated as fact.

conventions.md §3.3 named four svcs composition roots. There are two. Verified: svcs appears at exactly two call sites, both in the platform (cloud.submission.harness, studio.orchestrate.worker); neither the CLI nor the API imports it or declares it — the CLI constructs what a verb needs at the verb, the API uses FastAPI's own Depends.

That is not a defect to fix in the code, and the rewrite says so rather than quietly changing a number: the rule is where wiring happens, not which library does it, and a root free to use its own framework's idiom is the rule working. The paragraph's last sentence had also been patched into self-contradiction — "astro-mine-api is built, and naming an unbuilt thing as unbuilt is the honest form."

#112 — the gate

scripts/check_docs.pystandard library only, runnable under a bare python3. The repository has no dependencies and this adds none, so validating the spec is never harder than editing it.

python3 scripts/check_docs.py                        # links, anchors, status, format
python3 -m unittest discover -s scripts -t scripts   # 37 tests
Check Fails on
links a relative link that does not resolve
anchors a #fragment with no matching heading
status prose contradicting the declared status, or a corrected claim coming back
format trailing whitespace, CRLF, missing final newline, * list markers

The status check is the one this issue argued for, and its design is the interesting part. SUBJECT_STATUS is a table of what is built — the fact the prose is compared against. Ship something, move it there, and every sentence still calling it unbuilt fails on the next run. The table is small enough to keep true; the prose is not. RETIRED_CLAIMS locks in the corrections above so a finding stops being a recurring finding.

Two judgment calls in it:

  • Verbatim program output is exempt (fenced blocks). guide/reference/cli.md quotes a command that prints "not stood up yet", and a check that flagged it would be demanding the documentation misquote the software.
  • Inline code is not exempt. My first version stripped it — and the self-test caught that this made the check blind to the exact sentence that motivated it, since conventions.md wrote the defect as "astro-mine-api … is not built yet" with the subject in a code span.

A document quoting a false claim in order to correct it uses <!-- status-ok: why -->. The reason is required, and an unjustified marker excuses nothing.

On the check being trustworthy

The org has no Actions minutes until 2026-09-01 (.github#8), so neither workflow here can be watched running. A check nobody has seen fail is a check nobody should trust, so scripts/test_check_docs.py introduces one defect at a time and asserts each check reports it — then asserts the clean tree passes, which matters as much.

It found three bugs while being written: the slugger dropped _ from astro_mine.core, the inline-code blindness above, and an unjustified marker reported twice. There is also a test that the corpus is real — >1000 links, >20 fragments — so a green cannot mean "found nothing to look at". Verified end to end by injecting a broken link, a dead anchor and a false claim into system.md: all three reported with correct line numbers, exit 1, clean and exit 0 after reverting.

What the external-links lane actually covers

5 URLs. Of 29 unique external links, 24 point into the private org and 404 anonymously — checking them would report the whole organization as broken. They are skipped behind SKIP_WHILE_PRIVATE, and deleting that at the public flip turns this lane from marginal into near-total coverage. Weekly, never on PRs: a third-party outage must not fail somebody's edit.

What I did not build

#112's update suggested a second check — that a normative claim about another document's subject cites that document — which would have caught the VERSIONING.md / §3.1 contradiction. I did not build it. I could not find a formulation that was not either trivially evaded or noisy enough to get disabled, and the issue itself flags it as maybe not worth it. RETIRED_CLAIMS covers the regression half of that class; the detection half is still open, and worth a separate issue if a third instance shows up.


Verification

  • python3 scripts/check_docs.pyclean, 69 files, 4 checks
  • python3 -m unittest discover -s scripts -t scripts37 passed
  • python3 scripts/check_external_links.py5 checked, all resolve (24 skipped)
  • Both workflow YAMLs parse, with the intended triggers
  • astro-mine plugin new solver ./my_solver run against the real CLI to confirm the tutorial's corrected dependency line

Also adds a .gitignore — the repository had none, and scripts/ is the first thing in it that leaves bytecode behind.

Traceability: charter §9.4 · conventions.md §3.3, §7.1 · roadmap/README.md §RM-DIST-05 · audit F-12

Three Wave-32 findings, one change: the spec said things about the platform
that stopped being true, and it was the only tree in the organization with no
check that could have caught them.

**Status claims (#110).** Ten sentences still described shipped work as
pending. `astro-mine-api` was "not yet stood up" in the architecture index and
in conventions.md §3.3; the distribution track was "in progress" in
system.md's phase table and roadmap/README.md's summary, where it also
contradicted "All five items are done" nine lines later; the UI's pages were
"landing across Waves 29-30" after all 26 issues closed. Tutorial 08 told
readers to depend on `astro-mine-allocate`, a distribution that never existed
and was never published -- verified by running the scaffold, which emits
`astro-mine-platform`.

**Counts and archival (#111).** The repository count was wrong in eight places
and wrong in two directions, because "eighteen" was being used for two
different sets. Ground truth: seventeen Python component repositories,
nineteen repositories deleted (the seventeen plus `astro-mine-console` and
`astro-mine-view`). Each site now counts the set it actually means. Three
places still said the repositories were *archived*; archival was the original
decision and it was reversed, and §RM-DIST-05 -- which is accurate -- was the
only place that said so.

conventions.md §3.3 named four `svcs` composition roots. There are two, both
inside the wheel: neither the CLI nor the API imports `svcs` or declares it.
That is not a defect to fix in the code -- the CLI constructs at the verb and
the API uses FastAPI's `Depends` -- so §3.3 now says which two use the library
and why the other two need not.

**The gate (#112).** `scripts/check_docs.py`, standard library only, runnable
under a bare `python3`: relative links, `#fragment` anchors, a status
vocabulary, and mechanical formatting. Four of the five audit findings were of
a kind it catches.

The status check compares prose against `SUBJECT_STATUS`, a table of what is
built. Ship something, move it there, and every sentence still calling it
unbuilt fails -- the table is small enough to keep true and the prose is not.
`RETIRED_CLAIMS` locks in the corrections above so they cannot come back.
Verbatim program output is exempt, because guide/reference/cli.md correctly
quotes a command that prints a stale line (fixed in astro-mine-cli#38, filed);
inline code is *not* exempt, since the defect that motivated the check was
written as "`astro-mine-api` ... is not built yet". A document quoting a false
claim to correct it uses `<!-- status-ok: why -->`, and the reason is required.

`scripts/test_check_docs.py` -- 37 tests -- introduces one defect at a time and
asserts each check reports it, then asserts the clean tree passes. It found
three bugs while being written: the slugger dropped `_` from `astro_mine.core`,
stripping inline code made the status check blind to the exact sentence it
exists to catch, and an unjustified marker was reported twice. It also asserts
the corpus is real (>1000 links, >20 fragments), so a green cannot mean "found
nothing to look at".

External links run weekly, not on pull requests, so a third-party outage
cannot fail an edit. Note what that lane covers: 24 of 29 external URLs point
into the private org and 404 anonymously, so it checks 5 today and becomes real
coverage at the public flip, when `SKIP_WHILE_PRIVATE` comes out.

Both workflows are written but unobservable until the org has Actions minutes
again (2026-09-01, .github#8) -- which is why the gate runs on a workstation
first and in CI second.

Closes #110
Closes #111
Closes #112
@djankov

djankov commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

The red ✗ on Docs is the Actions billing block, not a code fault — and it is worth pinning down rather than assuming, because this PR is the one that adds the workflow.

The run finished in 4 seconds with zero steps executed:

$ gh api /repos/astro-mine/docs/actions/runs/32068416490/jobs
{"conclusion":"failure","name":"Links, anchors, status, format","steps":[]}

No step ran, so nothing in the workflow can have failed. That is the spending-limit signature (.github#8, resets 2026-09-01), the same one every other repo in the org has been showing. The one thing it does prove is that the workflow is registered and triggering — it was dispatched on the pull request as intended.

Which is exactly why the gate was written to run on a workstation first. Locally, on this branch:


checked 69 files, 4 check(s): clean

----------------------------------------------------------------------
Ran 37 tests in 12.390s

OK

skipping 24 link(s) into the private organization (they 404 anonymously; this lifts at the public flip)

checked 5 external link(s): all resolve

Both lanes will be observable in CI on 2026-09-01 without any change to this branch.

@djankov
djankov merged commit 6e31659 into main Aug 17, 2026
1 check failed
@djankov
djankov deleted the wave32-docs-sweep-and-gate branch August 17, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant