gaia-cleanse
Cleanses memory, the wiki, and auto-loaded files of duplication, conflicting instructions,…
Maintainer-only. Classifies every file that would newly ship to adopters against the written distribution-boundary categories, withholds by default when none matches cleanly, and asks the maintainer only where the taxonomy does not settle it, so the release CLI can produce a
$ npx -y skills add gaia-react/gaia --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
/distribution-vetContext preview
What this command does when you run it.
Maintainer-only. Classifies every file that would newly ship to adopters against the written distribution-boundary categories, withholds by default when none matches cleanly, and asks the maintainer only where the taxonomy does not settle it, so the release CLI can produce a
name: distribution-vet description: Maintainer-only. Classifies every file that would newly ship to adopters against the written distribution-boundary categories, withholds by default when none matches cleanly, and asks the maintainer only where the taxonomy does not settle it, so the release CLI can produce a manifest. disable-model-invocation: true
Maintainer-only. Thin orchestrator over `.gaia/cli/gaia-maintainer`, which owns every deterministic step. This command supplies the one thing the CLI cannot: a classification of each newly-shipping file against the written distribution boundary, and a maintainer's answer on the few the taxonomy does not settle.
`.gaia/release-exclude` is the distribution boundary: a file ships to adopters if and only if git tracks it and no line in that file masks it. `.gaia/manifest.json` is the update policy `/update-gaia` consumes, and incidentally the ledger of which shipping files a maintainer has acknowledged. A file that git tracks, that no exclude line masks, and that the manifest does not yet list is "unanswered": it would ship, but nobody has said so on purpose.
.gaia/cli/gaia-maintainer release manifest --check --json
`--check` is read-only. It exits non-zero whenever it finds any of five conditions, so capture stdout and parse it as JSON regardless of the exit code; a non-zero exit here is not a failure, it is the normal signal that something needs attention. The payload shape is:
{"missing": [{"expected": "owned", "file": ".gaia/statusline/example.sh"}], "extra": [], "drift": [], "regionDrift": [], "versionDrift": null}`missing` is an array of objects, not of path strings: the path lives in `.file`, and `.expected` is the update class the classifier would assign. Extract paths with:
jq -r '.missing[].file'
Treating `missing`'s entries as if they were bare strings prints JSON blobs instead of paths and silently breaks Step 3's classification.
`missing` is not "everything that ships." The paths in `ADOPTER_OWNED_SENTINELS` (`.gaia/cli/src/release/manifest.ts`: `.gaia/manifest.json`, `.gaia/packages.json`, `.gaia/VERSION`, and `wiki/log.md`) are permanent adopter-owned fixtures that ship with baseline content but are never classified, so they never enter `missing` and this command never asks about them. That is correct, not a gap.
`.gaia/release-exclude` carries twelve numbered categories, each with a rationale paragraph, and is the single authoritative list of what stays maintainer-only. Most of `missing` is already answered there: category 3 settles a shipped script's verification rig in one line, category 4 settles everything under `.gaia/cli/src/`, category 1 settles the `/gaia-*` command split and names the adopter-useful exceptions.
So classify first and ask second. This is not "use judgment": it is matching each file against a written taxonomy and saying which entry it matched and why. A wrong decision then surfaces as a wrong **citation**, which a reader can check against the category's own text, instead of as a verdict they would have to re-derive from scratch.
Read the categories out of `.gaia/release-exclude`: the number, the title, and the rationale paragraph under each header. The rationale is what a path is matched against; the title alone is not enough to match on.
Then record three things for each path in `missing`:
Match on the rationale a category states, never on the shape of a path's neighbours. "Its siblings are excluded" is a guess that looks like a match.
The categories are **exclusion** categories, so a match is a withhold and a ship has to come from somewhere else. Three arms, and every path takes exactly one:
**A path in that third arm is recorded as a withhold**, and surfaced in 3b. It is never shipped on a silent default. The asymmetry is the whole reason:
Claude is raw power. GAIA is order and focus. The foundation that keeps Claude-shipped code production-grade as your team scales. The React frontend is handled. You build the rest of your app on top. Every convention enforced in code.
Repo: gaia-react/gaia
Cleanses memory, the wiki, and auto-loaded files of duplication, conflicting instructions,…
Drafts a guard (deterministic check, skill, or path-scoped rule) for a recurring code-audit…
Fixes the tech-debt backlog, a single issue or a recommended related batch, highest severity…
Health-checks and auto-heals this project's Claude integration (triage, heal, verify) and…
Turns a GAIA workflow misfire into a redacted, classified, filing-ready bug report in one…
Initializes a new project from the GAIA React template. Renames, strips GAIA branding,…