Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 39 additions & 25 deletions .claude/skills/update-xmech-page/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,19 @@ Then, for each Mech in the refreshed `_fleet/data/manifest.json`:
`git -C "$SRC/<Mech>" fetch -q origin`, take `origin/main`, and cross-check it
against `gh api repos/CultureBotAI/<repo>/commits/main --jq .sha`. The
repository name is not always the Mech name (`proteintraitsmech`). Write the
pins and CLAW's to `$SNAP/revisions.json` with the pin time. Corpora move within
minutes, so pin once and do not re-pin mid-run.
pins and CLAW's to `$SNAP/revisions.json` with the pin time, in the layout
`build_site_audit.py` reads in step 7 (#269):

```json
{"pinned_at_utc": "2026-09-25T02:06:03+00:00",
"mechs": {"<Mech name>": {"repo": "<repository>", "sha": "<40-hex sha>",
"commit_date": "<committer date with offset: git log -1 --format=%cI <sha>>"}},
"claw": "<40-hex sha>"}
```

`pinned_at_utc` is an ISO time with its offset; the nightly card check reads it
from the audit and fails on one it cannot read. Corpora move within minutes, so
pin once and do not re-pin mid-run.

### 2. Snapshot at the pins

Expand Down Expand Up @@ -227,26 +238,29 @@ either being stale alone.

### 7. Provenance

Rewrite `_fleet/data/site_audit.json` for the run: per repository the pinned
`sha` from `$SNAP/revisions.json` (not from `mech_stats.json`, or the audit-pin
test compares a value with itself, #125) and its commit date, the URL each card figure is read from, the figure, the
sha256 of the fetched HTML and of any data file, merged PRs, and short notes on
how the site figure relates to the repo count. Set `checked_at_utc`,
`local_date`, `pinned_at_utc` (ISO, with its offset) and `scope`. Record
`figure_at_pin` for every source with a committed copy: read the copy at the pin
with `check_cards.figure()`, the nightly's own parser with `REGIONS` applied,
never from the template. The provenance tests require it to equal each card, so
a mistyped card fails on the PR, and the nightly reports WRONG from it (#231).
ProteinTraitsMech's data file is built in CI and has none. Derive the other
mechanical fields rather than typing them: the live figure through
`check_cards.read_source()`, merged PRs from
`mech_stats.json`, SHAs and commit dates from the pins, and assert that the
pins equal the stats' `source_revision` before writing. Hash the served page as
committed at the pin too (`git show <sha>:pages/index.html`, or `docs/`), record
it beside the live hash, and let the builder say whether the two match. Never
type "byte-identical" into a note: sites publish during the run, and a
hand-written claim of identity went stale for four Mechs in the first run (#155). The provenance tests require its SHAs to equal the
stats' `source_revision`.
Update the audited notes in `_fleet/audit_notes.json`, one per Mech plus CLAW
and the `scope`: how each site's figure relates to its records at the pin, as
re-checked in step 5. Then write the audit:

```bash
python3 scripts/fleet/build_site_audit.py --snapshot "$SNAP"
```

The builder derives every mechanical field (#238): the pinned `sha` and commit
date from `$SNAP/revisions.json` (not from `mech_stats.json`, or the audit-pin
test compares a value with itself, #125), merged PRs from `mech_stats.json`
after checking it was counted at the pins, the live figure and `figure_at_pin`
through `check_cards.figure()` on the served file and on its committed copy at
the pin, and the sha256 of both. It appends one sentence to each note saying
whether the live copy still matches the pin, so never type "byte-identical" into
a note: sites publish during the run, and a hand-written claim went stale for
four Mechs in the first run (#155). It refuses to write when a card differs from
its figure at the pin (a typo, #231) or when a site states fewer than its card,
and it records a site that grew as `site_figure_at_check`. A source with no
committed copy must be listed in `check_cards.NO_PIN_COPY` (ProteinTraitsMech,
built in CI). The provenance tests then require the audit's SHAs to equal the
stats' `source_revision`, each `figure_at_pin` to equal its card, and each note
to start with its text in `_fleet/audit_notes.json`.

`CLAUDE.md` at the repository root records when the page was last refreshed.
Update its "Last refreshed" sentence in the same PR, so the guidance and the
Expand All @@ -269,9 +283,9 @@ live site, so it is the only gate that sees that.
When a site has moved past its pin, do not re-pin that one Mech: the census and
overlaps are computed across Mechs, so a single re-pin is a partial rerun, and a
fast Mech moves again before the rerun finishes. Keep the page a consistent
snapshot at the pins, record the live figure as `site_figure_at_check` in that
Mech's `site_audit.json` entry, and say in the PR which cards the check reports
as grown. That stays a warning for `GRACE_DAYS` (14) after `pinned_at_utc` while
snapshot at the pins (the builder records the live figure as
`site_figure_at_check` in that Mech's `site_audit.json` entry), and say in the PR
which cards the check reports as grown. That stays a warning for `GRACE_DAYS` (14) after `pinned_at_utc` while
the site is at most half as large again as the card; past either limit the
check reports STALE and fails, and the page is due a full refresh. A card that
differs from its audit's `figure_at_pin` fails as WRONG however far the site has
Expand Down
31 changes: 23 additions & 8 deletions _fleet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
hand-curated at the top of the script.
- `data/manifest.json` — membership and all capability declarations from a pinned
commit of CLAW's canonical manifest, plus the canonical artifact count.
- Other `data/` files — derived numbers: `prefix_census.json`, `subsets_summary.json`, `fleet_data.json`, `mech_stats.json`; `site_audit.json` is the hand-written provenance record.
- Other `data/` files — derived numbers: `prefix_census.json`, `subsets_summary.json`, `fleet_data.json`, `mech_stats.json`; `site_audit.json` is the provenance record, written by `scripts/fleet/build_site_audit.py` from the snapshot, the live sites and the audited notes in `_fleet/audit_notes.json`.

## Membership and capability updates

Expand Down Expand Up @@ -59,16 +59,27 @@ remedy for each failing verdict (#235):

- STALE or SHRANK: the card figures in `mechs_template.md` and the `MECHS` block
in `fleet_fragment.html` need a full refresh, since the page is a snapshot.
- WRONG: a card, or the audit's `figure_at_pin`, was mistyped. Correct the card
- WRONG: a card differs from the figure its source stated at the pin. Correct the card
and every other occurrence of its figure, found by grepping the tree for it as
step 6 of the update skill does: the MECHS `records:` and `extra:` text in
`fleet_fragment.html`, cross-references, `card_records` in `site_audit.json`
and the pages that repeat it. Or correct `figure_at_pin` if that is what was
wrong. Then rerun `assemble_page.py`; no re-pin (#248, #258). The unit tests catch this on the
`fleet_fragment.html`, cross-references and the pages that repeat it, and
`card_records` in `site_audit.json`, the one audit field a WRONG fix edits, to
match the corrected card (a test requires the two to agree; #277). Then rerun `assemble_page.py`; no re-pin (#248,
#258). If `figure_at_pin` itself is wrong, re-derive it with
`build_site_audit.py` against a snapshot at the audit's pins (update skill
step 11); it is derived, never typed (#268). The unit tests catch this on the
PR and in the nightly, which still runs the card check after a failed test
step so its report prints (#239, #240).
- GONE or CHANGED: a `SOURCES` entry needs repointing.
- MARKUP, UNCARDED or AUDIT: fix the card markup, `SOURCES` or `site_audit.json`.
- MARKUP or UNCARDED: fix the card markup or `SOURCES`.
- AUDIT: never edit `site_audit.json` by hand, apart from `card_records` under
WRONG (#273, #276, #277). A missing or
non-integer `figure_at_pin`: regenerate it with `build_site_audit.py` against a
snapshot at its pins (update skill steps 7 and 11). A bad pin time, or a missing
or malformed audit: the builder copies the pin time from `revisions.json`, so
take the pins and pin time from the last audit the builder wrote (`git log -p --
_fleet/data/site_audit.json`), then regenerate. A Mech
with no entry, such as a new member, needs a full refresh with new pins.
- UNCHECKED: most sites could not be reached; rerun before changing anything.

A new card needs a `SOURCES` entry; a test enforces that. The cards
Expand Down Expand Up @@ -195,8 +206,12 @@ procedure.

`data/site_audit.json` records, per repository, the pinned revision, the URL each
card figure is read from (a Pages URL, except CultureMech's committed README on
`main`), the figure, response hashes and merged
pull-request totals. The three dedicated pages link their descriptions and
`main`), the figure, the figure its source stated at the pin (`figure_at_pin`),
response hashes and merged pull-request totals. `scripts/fleet/build_site_audit.py
--snapshot "$SNAP"` writes it: every mechanical field is derived, and only the
notes on how each site's figure relates to its records, kept in
`_fleet/audit_notes.json`, are written by hand. It refuses a card that differs
from its figure at the pin or exceeds its site (#238). The three dedicated pages link their descriptions and
commands to those same revisions.

Follow client-side meta refreshes from site roots to `pages/` or `app/`. Read
Expand Down
16 changes: 16 additions & 0 deletions _fleet/audit_notes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"scope": "Public main revisions pinned once for the whole refresh, and the deployed GitHub Pages responses, except CultureMech, whose figure is read from its committed README on main because no page it reliably serves states the count; the vocabulary census, subsets and card stats were regenerated at the same pins.",
"notes": {
"AntibioticMech": "2,939 data/antibiotics records at the pin (2,669 ontology-grounded, 270 minted; 80 REVIEWED, 30 PROPOSED, 2,829 SEEDED), equal to the stat tile.",
"CellStructureMech": "542 data/structures records at the pin, equal to the stat tile (13 categories, 475 GO-grounded, 196 membrane organelles). All 542 are PROPOSED, so none is reviewed.",
"CommunityMech": "The landing tile counts 422 kb/communities records, equal to the pin. data/isolates adds four more, so the census and mech_stats.json count 426. The landing's '16 categories' tile is hard-coded upstream; the schema enum, the records and the browser facet all have 15. No GitHub release has been published.",
"CultureMech": "The committed README's corpus snapshot states 15,878 normalized and 6,288 merged records, equal to data/merge_yaml/merged at the pin; no page CultureMech reliably serves states the canonical count. The app/ landing tile still reads 10,657, a legacy figure that matches no data layer. The pages/ media index is deployed by CultureMech's generate-pages workflow and replaced by the branch-based Pages build on other pushes to main, so it was live on 2026-09-24 and gone on 2026-09-25 (#175).",
"HabitatMech": "3,206 data/habitats records at the pin (686 REVIEWED, 2,520 SEEDED), equal to the stat tile. The 263 commits since the previous audit add only record-review reports.",
"MediaIngredientMech": "The landing tiles are computed from data/ingredients.json: 2,953 ingredients, 2,611 MAPPED (88%), 261 UNMAPPED, 80 REJECTED, 1 AMBIGUOUS. browser.html reads directory counts instead (2,680 under mapped/).",
"NaturalProductMech": "The landing prose states 3,115 natural product structures, equal to data/natural_products at the pin; all are SEEDED.",
"ProteinTraitsMech": "429,293 records and 34 source labels, computed at runtime from data/facets.json and equal to data/traits at the pin. The static HTML still carries a legacy fallback of 408,978 / 29.",
"TaxonMech": "625,960 data/taxa records at the pin, equal to the stat tile and including 14 retained DEPRECATED records; none is REVIEWED.",
"TraitMech": "763 data/traits records at the pin (427 REVIEWED, 248 PROPOSED, 50 DEPRECATED, 38 SEEDED; 519 with causal graphs), equal to the landing page, which shows 62.5% embedded (477 of 763).",
"culturebotai-claw": "10 fleet members and 16 governed artifacts. Projected membership and capabilities are unchanged from the previous snapshot; provenance advanced to the pinned main revision. Every Mech vendors claw at 44db08d, and fleet.yaml, README.md and vendored_artifacts.json are identical between 44db08d and this pin."
}
}
Loading
Loading