multica-ops
AGENTS.md11 starsChanged 49 days agoApache-2.0View on GitHub
This repository ships one skill: multica-ops — a Mops (Executive Advisor) that builds and runs an autonomous company of AI agents on Multica. Using the skill? Whatever harness you are (Claude Code, Codex, Cursor, Windsurf, Antigravity CLI, …): read SKILL.md and follow it. Slash commands are a Claude Code plugin convenience; every flow works from natural language in any agent — "set up my team", "join this project", "status", "add a feature: …". Requires the multica CLI on the machine,…
- Commits and pushes
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
The file
We split this AGENTS.md into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 207
Batch, don't drip: Commit small; tag on a coherent unit of value, not per commit.
- Very specific: line 250
Every new behaviour needs a scenario, or it has no regression test — evals go stale silently (2.3 shipped a release behind until caught by …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Agent entry point
This repository ships one skill: multica-ops — a Mops (Executive Advisor) that builds and runs an autonomous company of AI agents on Multica.
Using the skill? Whatever harness you are (Claude Code, Codex, Cursor, Windsurf, Antigravity CLI, …): read SKILL.md and follow it. Slash commands are a Claude Code plugin convenience; every flow works from natural language in any agent — "set up my team", "join this project", "status", "add a feature: …".
Requires the multica CLI on the machine, pointed at a workspace:
multica setup cloud, or multica setup self-host --server-url … for your own server.
Changing this repository? Read this part.
Two scripts guard it. Run them; they are fast and they have caught real defects:
bash scripts/preflight.sh # form: is the documentation well-made?
python3 scripts/verify.py --live # truth: do the commands and sources still exist?A file named in prose is a link, not a backticked name. The link is the edge GitHub, Obsidian's
graph and preflight §4 can all see; a name is an edge only a reader infers. scripts/link-names.py
--write makes the links and preflight §4d refuses the drift, with three kinds of name left as names.
The core — skills/mops/SKILL.md, loaded on every run, so a link there is paid every time.
A companion's name of another companion — a companion being any other root .md but README,
CHANGELOG, AGENTS and CLAUDE — because references stay one level deep from the core (preflight
§5c). And the files a project also carries — CLAUDE.md, LATER.md and the rest — which in
prose usually mean the project's own. A project's _ops/ has its own twin, scripts/link-ids.py
(BOOTSTRAP → Docs home).
What the automation cannot check — and what you must therefore read
The scripts verify shape and existence. They are blind to whether a paragraph is still correct, and every expensive defect this repo has shipped was of exactly that kind: a statement that parsed perfectly, linked correctly, and was false. So before you commit, read for these six things — as a human, or as an agent asked to review, but never assume a green hook covered them.
1 · Does this contradict another file? Rules live in several places on purpose (core, companion, guide template) and drift apart silently. The core once said squad leaders "never implement" while ROLES made working craft leads out of them; both files were internally consistent and the pair was wrong. If you change a rule, grep for it everywhere and fix every copy in the same commit.
2 · Is the framing still the current one? Text ages by being outrun, not by breaking. The docs-site introduction described version 1.x long after 2.1 shipped — every sentence true when written, the whole page misleading. When you add a capability, ask what page now describes an older product.
3 · Does a claim about the outside world still hold? verify.py checks commands, flags
and URLs. It cannot check that a command still means what we say it means: multica setup
exists and prints configuration, while our text implied it performs setup. If a sentence
explains what a tool does, run the tool.
4 · Are the numbers still measured? Any figure about ourselves rots — the guide template was quoted at ~1.7k tokens after it had grown. One such claim is now checked automatically; the rest are not. If you quote a size, a count or a share, re-measure it.
5 · Does the example still match the rule? EXAMPLES.md and the templates demonstrate the standard the prose describes. Change the standard and the demonstration quietly becomes the counter-example.
6 · Is this reachable? A capability that no command, use case, routing trigger or index points at does not exist for the agent who needs it. The hook checks command coherence; it cannot tell that a concept has no door.
Before building anything: does Multica already do it?
This skill is a methodology on top of a platform that keeps growing, so the first question
for any new capability is not how do we build it but does Multica already have it. Check
multica <group> --help for every group it might touch, and the docs, before designing.
Recording the answer costs a minute; missing it costs a home-grown mechanism that drifts from
the platform and confuses anyone reading both.
This has already bitten twice: agents were created with the legacy --visibility flag long
after Multica had a real per-agent permission model (and the legacy flag cannot express
"specific people" at all); and the workspace member roles — owner · admin · member, with
the invite and removal rules that follow from them — went undocumented here for versions.
Same rule when the platform lacks something: say so explicitly, and note the version checked,
so a later reader knows the wheel was deliberate. (workspace delete does not exist in the CLI
as of 0.4.8: Mops cannot remove a workspace it created, and must say so rather than promise.)
When a flow deserves a command — and how one appears
The scripts guard command coherence (every table row has a file, is reachable from SKILL and
the /multica-ops:mops dispatcher, and has a use case). They cannot judge whether a command should exist
at all, so decide it deliberately, every time you add capability.
A command is a shortcut for a flow the owner reaches for repeatedly, by name. Add one when all three hold: it is invoked as an action in its own right (not a phase inside another flow), it has a name in the owner's own language, and plain language alone reaches it unreliably. Do not add one for a one-off step, an internal stage of another flow, or a synonym — a synonym is an alias on an existing row. A quick job deliberately has none.
The command appears in the same commit as the capability — table row, commands/<name>.md,
a use case, and a mention in SKILL — or the commit message says plainly why the capability is
not getting one. A capability shipped now and given its door later is invisible in between,
which is the same failure as an unreachable one.
What a capability owes before it ships — four things, and why each one is here
A capability is not shipped when it is written. It is shipped when it is held, exercised and measured. Every item below is here because shipping without it was measured in this repository and produced a release that looked finished and was not. They land in the same commit as the capability, or the commit message says plainly which one is missing and why.
1 · If the rule can fail, a form — never a stronger sentence. Prose does not hold the weak
executor, and this is not an opinion: three rules of one release were measured at 0/5, 0/5 and
0/3 while stated clearly in the always-loaded core. Two were rebuilt as PreToolUse refusals
and went to 5/5 each. A refusal moves the rate; a note does not — the third was written
as a PostToolUse note and did not move it. Before writing the sentence, ask what artifact a
liar cannot fill cheaply, what template leaves a visible hole when omitted, what check refuses.
Where no form exists, say so and put the rule on the named prose-only list rather than
believing in it. And a form is not finished until you have watched it refuse, in the shape the
path it ships on honours — a flat permissionDecision is executed and ignored on the plugin
path while exit 2 holds, so check-structure.py fails the flat shape. The rule and its
measured matrix live in PLAYBOOKS → A gate is not enforced until you have watched it refuse,
because it is a company's problem before it is ours; what this section adds is that the same
rule binds the hooks this repository itself ships.
2 · A mutation test on the form, asserting what it refuses. A guard that cannot be wrong is
decoration, so each is shown speaking on the mutant and silent on its honest twin. The
load-bearing assertion is almost never what the holder does — it is what it declines to do: a
migration leaving the craft's own files alone, a gate whose retry also stops (the first
outward gate let the second attempt through, and three runs of five simply pushed again), a hook
staying quiet on a repository this skill does not operate. Two traps worth naming, both paid
for: a guard must not share its sweep's blind spot — the docs/ check read the same two
directories the sweep did and confirmed its silence while the always-loaded core kept sixteen
stale paths — and a suite must own its state directory, or markers survive between runs and
it passes less the more often you run it.
A third, paid for on 2026-08-28: a mutant that never applied is indistinguishable from a
toothless assertion. A wrong anchor makes the edit a no-op, the suite stays green, and the
green reads as the mutant survived — so the conclusion drawn is about the assertion when the
truth is about the patch. Every mutation asserts that it changed the file before the suite runs.
Two neighbours of the same shape, both measured the same day: restoring a fixture with
git checkout -- <file> restores from the INDEX, so state staged by an earlier assertion
survives and later ones pass on the leftover rather than on what they test (git checkout HEAD --
is the one that means it); and reusing a record id an earlier commit already took means a
gate scoped to added files never looks at the fixture at all. All three produce a green
assertion that is measuring nothing, which is worse than a red one — so a "must not fire"
assertion is paired with a "must fire" twin on the same fixture, and the pair is what proves the
subject was examined.
3 · A scenario, and the fixture that scenario needs. A behaviour with no scenario has no
regression test; a scenario with no fixture is unmeasured, not passing, and evals/COVERAGE.md
has a column that says which. Four things a fixture owes, each measured:
- Both halves. The repository half and the workspace half. With the board built and the ground missing, four runs of five answered "the working directory is empty, could you give me more context?" — correct about the room, nothing to do with the scenario.
- Rebuilt before every run. A scenario that acts on its own fixture invalidates every run after the first; runs 2–5 once arrived at a workspace the earlier runs had dismantled.
- A unique name per build for anything the teardown archives. Archived entities keep their names and block re-creation, so the second build silently produces less than the first — one scenario ran for three rounds with no agent to dispatch to, and scored the skill for it.
- A teardown that reports its own failure. The first one printed "0 issue(s) cancelled" over three live issues, because the verb was wrong and the error was swallowed. It exits nonzero and names what it left behind; a probe left in a workspace is indistinguishable from real work a month later.
4 · A door — the command rule above, unchanged: a capability nobody can reach does not exist for the agent who needs it.
And the measurement is only as good as the harness. A number taken through a broken rig is worse than no number, because it reads as behaviour. Before trusting a rate, confirm the player had its own working directory, its own config home, no other MCP servers, the corpus under test readable (the companions sit outside the working directory and were denied for a whole round), and no answer key in the box. When a defect is found in the rig, the numbers taken before the fix are withdrawn, not carried forward.
Writing the changelog
The changelog is the migration map /multica-ops:upgrade reads, and it is also what a stranger uses to
decide whether to adopt this. Both audiences want the same thing: what changed for me, and
what must I do differently.
- Lead with the capability or the consequence, not the discovery. "
/multica-ops:importbrings a backlog over from Linear" — not "we noticed imports were unhandled". - A fix is worth an entry when it changes what a reader should do: a recipe they may have copied, a behaviour they relied on. Say it plainly and briefly, including the remedy.
- The story of how a defect was found belongs in the commit message, where the next maintainer will look for it. It does not belong in the release notes, and a changelog full of self-audit reads as a product made of bugs rather than one kept honest.
- Never rewrite a released entry's substance. Versions are public; correct forward.
- Terse, and grouped. Compact technical language — the reader wants the delta, not an essay. Not every fix earns a paragraph; fold a handful of minor corrections into one line ("several doc and notation fixes") rather than a bullet each. Over-granular notes read as a product made of bugs.
When to cut a version
Two artifacts ship from this repo and they version differently. The docs site deploys
continuously — a wording, IA or typo fix is a deploy, never a version. The skill is what
users pull with /multica-ops:upgrade, so a bump is a whole upgrade cycle for them (a re-screen, a
restart, a changelog entry someone reads) — bump it only when a user has a reason to move.
SemVer picks the number: PATCH (x.y.Z) a bug fix or correction that changes what a reader should do · MINOR (x.Y.0) a new command, flow or capability · MAJOR (X.0.0) a breaking change (a removed or renamed command, a changed contract).
Batch, don't drip. Commit small; tag on a coherent unit of value, not per commit. Pool small fixes into one patch and let wording/notation/doc-only changes ride the next real release rather than minting a version each — the changelog is the upgrade map, so an entry must be something a user cares about; a release of "renamed a column" reads as a product made of noise. The one exception is an urgent fix — a real block, a security or data issue — which ships alone, immediately. (An earlier run of five patch releases in one week was exactly the drip this rule now prevents.)
Cutting a release
A version bump is not just a changelog entry. Before you tag:
[!CAUTION] A blanket version sweep does not touch a version that is part of a citation. Measured 2026-08-15: unifying the CLI pin with one
s/v0.4.23/v0.4.26/also rewroteMUL-5958 (v0.4.23)— a factual reference to the release that carries that change — into a release that does not. The pin is a claim about this repository; a ticket's version is a claim about theirs, and the two look identical to a regex. Sweep the pin by name, and re-read any line where a version sits beside a ticket id.And beside a measurement DATE, which this caution first missed. The same sweep also turned
Measured `2026-08-09` against CLI 0.4.12intoagainst CLI 0.4.26— a binary built on 2026-08-14, so the line claimed a measurement taken five days before the thing measured existed. It survived two repairs of its own class because this caution named only ticket citations. A version is swept only where it is this repository's pin; everywhere else — a ticket id, a measurement date, another project's release — it is somebody's fact, and a fact re-dated by a regex is worse than a stale one, because it reads as current.
- Refresh the evals, then run them and record the run. A round is driven by
evals/runsheet.tsv(what the player is told, and whether the situation is workspace state that must exist first) andbash scripts/eval-run.sh <id> <run> "<query>", which isolates three things or the number means nothing: a config home of its own (a shared one lets another installed skill answer — measured 2026-08-02), a copy of the corpus (the skill is frozen for the round), and the test workspace passed asMULTICA_WORKSPACE_IDrather than the profile default. The eval home needs its own login, once — credentials are keychain-scoped per home, so it never touches the main one, and the runner refuses to start without it rather than recording 125 "not logged in" transcripts as results. A scenario whose situation is workspace state gets it frompython3 scripts/eval-fixture.py <id> build|teardown, which builds from nothing every time rather than on top of a previous round, tags everythingEVAL-<id>-so a sweep finds its own litter and nothing else, and reports what it failed to clean — teardown verbs differ per entity (issues only cancel, agents archive, squads delete) and a teardown that cannot say it failed once printed "0 cancelled" over three live issues. Every new behaviour needs a scenario, or it has no regression test — evals go stale silently (2.3 shipped a release behind until caught by hand). preflight warns when the version bumped andevals/README.mddidn't. A minor or major is not tagged withoutevals/runs/<version>.md— date, player and judge tiers, a verdict per scenario with its evidence, andnot runlisted rather than omitted (evals/runs/TEMPLATE.md). The rubric says what should hold; the run record is the only place saying whether it did. - Run the four review lenses (deletion · adversarial · contradiction · cold-read) on the
changed skill — they find the class of defect no script can: a sentence that parses, links
and is false. This is not optional for a minor or major; a patch can skip it.
bash scripts/lens.sh <lens> <base-ref>runs one as an isolated headless session — its own config home, no connectors, no memory of the session that wrote the corpus, read-only — because the author cannot be the reader who did not write it. On 0.4.0 the four found sixteen defects with every script green, including the always-loaded core still pointing at the pre-release layout. State the limit with the result: this is independent of the session and not of the model, and the rule below still prefers a different provider. A lens that exhausts its turn budget reported nothing and is recorded as not completed — it is indistinguishable from one nobody ran, and the run record says so rather than quietly dropping it. Four rules about the reading itself, ported from the sibling 2026-09-18 and read out of working tools rather than invented. (a) The reader gets the artefact, not the author's case for it — no plan, no reasoning, no summary of intent, because those are exactly what make a reader agree; self-review confirms assumptions, it does not test them, and a reader handed the author's assumptions is doing self-review with an extra step. (b) An objection quotes the line it is about, as written — a paraphrase is where a lens's own reading hides, and the author then answers the paraphrase while the line stands. (c) A finding cites a verbatim excerpt and its line is derived from that: a quote matching nowhere, or matching twice, leaves the finding unlocated rather than placed, which is what makes a mislocated finding impossible instead of rare. (d) A verdict is a shape, and demoting one takes its fields away — a rejected finding still carrying a severity and a remediation reads, three weeks later, exactly like a real one somebody forgot to act on. And the re-round reads the repair, with the range reachable for context: nine round attempts across two releases, five lost whole to the session limit, and the sharpest finding of each re-round sat in the latest repair commit. A lens never runs an outward act — not against a stub, not to prove a hole — except throughscripts/test-gate-vs-bash.sh, which puts only stubs and harmless tools onPATH, checks every stub before each run, denies bash the network, and refuses to execute a real outward tool by any path. Measured 2026-09-24, and it published this repository: a lens wrote a script carryinggit pushfor a stubgit, the installed gate refused the command that would have made the stub,PATHfell through to the real binary, andmaintook eighteen commits of an untagged release. A gate reads commands, not the scripts they run, andlens.sh's read-only mode stops file edits, not a shell — a new shape to test goes into that suite's cases, where it runs closed. - Keep the guards current — they rot too. The shipped hooks are tested by mutation —
bash scripts/test-migration-hook.sh— each rule shown speaking on the mutant and silent on its honest twin, because a hook that cannot be wrong is decoration and this one only ever reports, so its whole value is being right about when it speaks. So is the layout migration —bash scripts/test-migrate-layout.sh— where the load-bearing assertions are about what it refuses to touch: a project's owndocs/files staying put, a collision named rather than overwritten, a second run doing nothing, a foreign repo left without an_ops/at all. And the twoPreToolUsegates —bash scripts/test-outward-gate.shandbash scripts/test-rule-home.sh. The outward gate's load-bearing assertion is that the retry does not pass: the first design stopped once and let the second attempt through, and three runs of five simply pushed again. The rule-home gate's is that it stays silent on a repository this skill does not operate and on a project's ownmemory/directory — a hook that fires on someone's own files is one they switch off. And the preflight's own checks —bash scripts/test-preflight-checks.sh: the typo'd date that used to silence the freshness gate, the count rephrase, the stale pin and the URL hidden in the exempt page — each mutant refused in a local clone of HEAD. And the dispatch note —bash scripts/test-dispatch-nudge.sh, whose four behaviours are silent-below-threshold, speaks-at-it, never-twice, and any real action resets the count. And the install inventory's route check —bash scripts/test-find-installs.sh: a plain copy is not flagged, a clean clone is not flagged, a stray untracked file is not flagged (git does not refuse a pull for one — measured, and the flag used to claim it did and prescribe a reset), a modified tracked file is flagged as AT RISK rather than broken (a fast-forward that does not touch it still succeeds), and the remedy is a command you can paste. It shipped with no test at all, under a commit titled a route nobody verifies is a route nobody has. And the skills this toolkit ships —skillspector scan ./skills --recursivebefore a tag (SkillSpector, Apache-2.0, NVIDIA, a third-party install and therefore never wired into preflight, which runs offline). We screen what we import and ship nineteen skills of our own; the rule that says imported is the one everybody reads as all.--no-llmreports itself as a partial scan, so a clean static run is evidence about patterns and not about intent. Read it as JSON (--format json --output <file>): a skill whose frontmatter a strict parser rejects shows only there, as amanifest_parse_errorin that skill's ownanalysis_completeness.ledger_exceptions— in a--recursivereport,skills[].analysis_completeness, while the report's top-levelanalysis_completenessstays clean — and the printed summary says successful with no findings (measured 2026-09-24).grep -c manifest_parse_error <file>must print0; anything else stops the tag, and the failing skill'sskill.sourcenames it. It is where the shapes preflight's frontmatter check names as its limits are caught. And the company guard —bash scripts/test-company-guard.sh: the four dependency-manifest shapes, the version bump that is not a new dependency, the word boundary that must not let a decision sayingupdatesatisfy a dependency calleddate, the register rung refusing and acceptingwe had none, and the guard noticing it is older than the guide it ships beside. It shipped with none of these — 101 lines of gate thatgrep -rlfound named only in prose, which is why it is named here. And so is the map generator —bash scripts/test-map-blocks.sh— where the assertion that matters is thatscripts/map-blocks.pyrewrites only between its markers: a generator that reformats a document it does not own is one nobody dares run. A new capability usually needs a new check, and this session's guards were mostly added reactively, after a defect shipped. Ask before: does this change need a guard, or break an existing one's assumption? The rot surfaces are the guards' own hardcoded lists —verify.py'sSTRUCTURAL/IGNOREobject sets andSMOKEcalls,check-structure.py's section-contiguity and command checks, the CLI pin. A guard that no longer matches reality passes silently, which is worse than no guard. - Every new capability has a door, or a stated reason it doesn't — see When a flow
deserves a command. Reachability is guarded; the decision to add a command is not.
Then regenerate the coverage map —
python3 scripts/coverage-map.pywritesevals/COVERAGE.mdfrom the tree itself: what the corpus says holds each rule, which validators, hooks and suites ship, how many scenarios exist and which versions have a run record. A hand-kept version of that table lies within a release, so it is generated and no rates are copied into it — a rate belongs where its date is. Read the output: a new holder with no test, or a version with no run, is visible there before it is visible to a user. bash scripts/preflight.sh,python3 scripts/verify.py --live, andpython3 scripts/fetch-source.py --verifythen--verify-citationsgreen (warnings named) — the last two walksources/SOURCES.mdin both directions: the register's live URLs are re-checked, and everycited-byis re-checked against the line it points at, since a rewrite moves the claim without touching the register.- Changelog leads with the capability or the consequence, not the archaeology of how a
defect was found (that goes in the commit message) — and ends with a
**Trio:**line saying what the release added, in wordsscripts/check-trio.pycan read and measure.
Two of those checks read what a summary hides, drawn — the skill scan of item 3 and the
changelog's **Trio:** line, which scripts/check-trio.py measures against the range since the
last tag (preflight §5j-bis):
flowchart LR
F["a skill's frontmatter"] --> P{"preflight —<br/>a strict reading"}
P -->|"a tab · a plain value holding ': ' ·<br/>' #' eating the rest of a line"| X(("refused on the commit,<br/>naming the skill"))
P -->|"passes, and so do the<br/>four shapes it names as limits"| S["before the tag:<br/>skillspector scan --format json"]
S --> J{"grep -c manifest_parse_error"}
J -->|"0"| T(["the tag may be cut"])
J -->|"1 or more"| W(("the tag waits —<br/>skills[].skill.source names it"))
S -.->|"the printed summary"| L["says 'successful' either way —<br/>so it is never what is read"]flowchart LR
E["the entry's Trio line"] --> R["read: diagrams ·<br/>situations · register entries"]
G["last tag .. the tree"] --> M["measured: mermaid blocks ·<br/>USE-CASES rows · new entries"]
R --> C{"the same?"}
M --> C
C -->|"yes"| OK(["§5j-bis passes"])
C -->|"no — or a kind the release added<br/>and the line does not name"| X(("§5j-bis fails,<br/>naming both numbers"))
E -.->|"no Trio line yet"| W["a warning — the entry<br/>is the last thing written"]Then the cut itself, in order — the last two steps were live misses on an earlier release:
- Bump both —
skills/mops/SKILL.mdfrontmatter and.claude-plugin/plugin.json; preflight fails on a mismatch. - Changelog + README roadmap — write the
## x.y.zsection (the map/multica-ops:upgradereads), and remove landed items from the README roadmap, refresh the rest — it is forward-only, so a shipped feature lives in the body and changelog, never as a checked box. - preflight green — the checklist above.
- Merge — a human merges the release branch (self-editing is locked; the loop adopts after the gate).
- Tag the merge commit — and the tag waits for the owner's word (the law and its
reasoning have one home:
CLAUDE.md→ Versioning). Everything above this line is preparation; nothing below it moves without an explicit yes. gh release createfrom that changelog section — a tag alone is not a Release, and a stranger deciding whether to adopt this reads the Releases page, not the tag list. (a previous version was tagged with no Release until the owner caught it; created retroactively.) The title isx.y.z — <the release's own line>, with no repository name in front of it. The Releases page is already scoped to this repo, so the prefix only eats the visible width and truncates the part that carries meaning — every title is a row read top to bottom, and the version plus its one line is what has to survive the truncation. (Both mistakes were made on 0.2.0 in one day: shipped bare as0.2.0, then renamed with the prefix, then renamed again without it.) The notes are the changelog entry whole, and its heading collapses to a bare italic date —*2026-08-02*, then the entry. The title already carries the version and the release's own line, so repeating the## x.y.z — dateheading inside the body says both a second time and pushes the first real sentence below the fold; the date is the only thing the title does not carry, so the date is what survives. Not a summary, not a subset: a reader on the Releases page gets what a reader ofCHANGELOG.mdgets. (All seven past releases were retro-fitted in place on 2026-08-07 — one of them had been published carrying the changelog's file header instead of its entry.)bash scripts/check-releases.sh— a published release's notes are a snapshot taken once, so a marked correction added to a frozen changelog entry afterwards reaches the file and never the page most people read. This compares every release against its entry and prints the one command each gap needs (--emit <dir>writes the files). It is a report, not a gate: it needs the network andgh, and preflight runs offline. Publishing stays the owner's hand.- Regenerate and push the docs site —
python3 scripts/generate.pyin theairepo, then push. The site deploys continuously, so a skipped regen silently ships the previous pages against the new tag. (a previous release's site lagged its tag the same way.)
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

