Every pull request in an estate repository carries one generated
Fork governance comment whose third lane is the Hypatia verdict grid
(metadatastician/standards: 3-practice/fork-governance/,
docs/VERDICT-GRID-SPEC.adoc). The grid has three permanent rows (Hypatia,
panic-attack, pons asinorum) and one row per gitbot-fleet member the repository
enrols in .gitbot-fleet/enrolment.json.
A fleet row leaves 🟠 indeterminate only when a file
.gitbot-fleet/report-backs/<member>.json is present in the scanned tree when
the grid renders. Until 2026-10-27 nothing in the estate produced one. Measured
on hyperpolymath/MetaManifold-WebUI#295: seven enrolled members, seven rows
reading "enrolled, but no report-back was received". The fleet was offering
nothing, and the grid said so honestly.
This document describes the producer that closes the gap and how a repository adopts it.
|
The driver. Reads the enrolment manifest, runs each enrolled adapter’s
existing local-directory JSON mode, translates the output into the grid’s
envelope, writes |
|
Builds the enrolled adapter crates ( |
|
48 checks over stubbed adapters whose JSON shapes were taken from live runs:
enrolment rules, every adapter’s translation, path relativisation, the
failure modes, envelope shape, |
|
|
|
This repository’s dogfood: runs the reusable on its own PRs, then renders the envelopes with the real standards renderer and fails if any enrolled member is still reported silent. |
|
This repository’s own manifest and the (deliberately empty) directory the lane fills at render time. |
One JSON object per member, key-sorted and compact with one final LF (the
I-JSON/JCS shape the estate asks of every .json it writes, as far as jq
produces it):
{ "findings": [ { "file": "src/a.jl", "line": 0, "message": "eval in src/a.jl",
"rule_id": "PA018", "severity": "warning" } ],
"reason": null,
"ref": "<gitbot-fleet commit>",
"reporter": "panicbot",
"status": "ran",
"title": "panicbot (panic recovery, error handling)" }status is ran, not_run or error; reason is required unless the member
ran. The driver never writes not_applicable: that is a statement about the
repository and belongs in the enrolment manifest ("enrolled": false with a
reason), where the grid renders it grey. severity is the fleet’s own word
(error, warning, info, suggestion) or a scanner word (critical,
high, medium, low); the renderer normalises both
(error → high, warning → medium, info/suggestion → minor). File paths
are repository-relative with no ./, so the grid’s change-scope (delta)
grading can match them against the diff.
| Member | Invocation | Translation and honesty notes |
|---|---|---|
rhodibot |
|
File-presence criteria against the vendored RSR canon. |
panicbot |
|
Wraps |
seambot |
|
Seam register completeness, drift and hidden channels. A repository with no
|
finishingbot |
|
Eight analyzers (license, placeholders, claims, release, SCM files, testing, tooling, v1 readiness) flattened to one list. Exits 1 when findings block a release; that is still a run. |
glambot |
|
Visual, accessibility, SEO, machine-readability and git-SEO analyzers, flattened. |
accessibilitybot |
|
WCAG 2.3 static analysis of HTML/CSS; absolute paths are relativised. Exits 1 when findings block a release; still a run. |
cipherbot |
|
Cryptographic hygiene and post-quantum readiness findings. |
echidnabot |
none |
echidnabot verifies proofs by dispatching to an ECHIDNA engine and has no
local mode. Without |
sustainabot |
none |
Reserved slot ( |
Adapter failures are never silent and never fatal to the run: a missing
binary, a crash without JSON, or a timeout each become error with the first
diagnostic line as the reason, and the grid renders that orange. Failing the
job would have turned every other member’s evidence into a missing artifact.
A repository needs three things.
-
An enrolment manifest at
.gitbot-fleet/enrolment.json, stating for every member whether it applies, with a reason when it does not. Enrol what is true of the repository, not what would look complete: a grey row with a reason is honest; an orange row forever is noise. -
The producer job, before the Hypatia lane in the fork-governance workflow. Where the repository’s Actions policy allows a reusable workflow from
hyperpolymath:jobs: fleet: name: Fleet report-backs uses: hyperpolymath/gitbot-fleet/.github/workflows/fleet-report-back-reusable.yml@<SHA> permissions: contents: read hypatia: needs: [fleet] if: ${{ always() }} uses: metadatastician/standards/.github/workflows/hypatia-scan-reusable.yml@<SHA> # the reusable downloads the `fleet-report-backs` artifact by default
Where it does not (a repository under another owner calling a reusable from
hyperpolymathfails at plan time with zero jobs), run the same steps inline: check outhyperpolymath/gitbot-fleetat a pinned SHA withactions/checkout, runscripts/fleet-report-back.sh, upload the artifact under the same name. The standards canon’s ownfork-governance.ymlis the worked example. -
A Hypatia lane that reads the artifact. The
report-backs-artifactinput (defaultfleet-report-backs;""opts out) and the download step before "Render the verdict grid" are in metadatastician/standardshypatia-scan-reusable.ymlfrom commitd253de273c5a6f688598fdd241b4c071159029b9(standards#1363, 2026-10-27) onward. A caller pinned to that commit or later gets the rows; a caller on an older pin produces the artifact and its lane does not read it, so bump the standards pin first. hyperpolymath/metamanifold-webui reads it through a fork-local copy of the reusable (its fork delta 4) and needs no bump.
The rows are not metamanifold-webui’s: every repository that runs the fork governance comment can have them. Two routes, chosen by the owner 2026-10-27:
-
New repositories inherit the manifest and the inline
fleetjob fromhyperpolymath/rsr-template-repo(its.gitbot-fleet/and.github/workflows/fork-governance.yml). -
Existing repositories get them from
scripts/fix-fleet-enrolment.sh, which rides the standards pin-propagation PR each repository already receives (standardsscripts/propagate-workflow-pins.sh): run both in the same branch, so the lane that reads the artifact and the job that produces it land together. Registered as reciperecipe-add-fleet-enrolmentand categoryMissingFleetEnrolmentinscripts/fix-script-registry.json; no Hypatia rule emits that finding yet, so today the fixer is run by hand or from a campaign manifest.
# in a consumer checkout, on the branch that bumps its standards pins
STANDARDS_DIR=~/standards FLEET_REF=<gitbot-fleet main sha> \
bash ~/gitbot-fleet/scripts/fix-fleet-enrolment.sh .
# exit 0: wired end to end. exit 3: written, with the MANUAL lines naming what
# is still missing (a lock to regenerate, a standards pin that does not read the
# artifact, a hypatia job to wire by hand). exit 2: refused, nothing changed.What the fixer writes, and what it refuses to:
| Item | Rule |
|---|---|
|
Written only when absent. rhodibot, finishingbot, glambot and cipherbot are enrolled everywhere; panicbot, seambot, accessibilitybot and echidnabot are enrolled when the tree shows what they read (a |
|
Written only when absent. |
|
Inserted before |
|
Gains |
|
Never edited. When one exists and a job was inserted the fixer exits 3 naming |
Standards pin |
Never bumped. The fixer reads the pinned |
The standards change in §5 step 3 is on main from d253de27, so the
campaign can run. Measured 2026-11-04 on a scratch repository: with the
standards pin at d253de27 and FLEET_REF at this repository’s
e44af814 the fixer exits 0 ("wired end to end"); on the earlier pin
9ae23875 it exits 3 and names the bump. A repository whose standards pin
predates d253de27 therefore takes the pin bump and the fixer in the same
branch.