Contributor wiki content
Two directories under wiki/ are excluded from the release bundle by .gaia/release-exclude:
wiki/entities/: named systems, products, and people tracked across the codebase.wiki/meta/: process and convention pages about the wiki itself.
Individual concept and decision pages are excluded too, each because its subject is maintainer-only: wiki/concepts/Release Workflow.md, wiki/concepts/Release-Notes.md, wiki/decisions/Bundle-time Scrub.md, wiki/decisions/CLI-Binary-Split.md, wiki/decisions/Folding Shell Scripts into the CLI Binary.md, wiki/decisions/Forensics Triage Workflow.md, wiki/decisions/Sharded CI Test Matrix.md, wiki/decisions/Shell Guard Fixture Discrimination.md, wiki/decisions/Local Test Runtime.md, and wiki/decisions/Dependabot as a Data Source.md. .gaia/release-exclude is the authoritative list.
The wiki workflow every project runs, /gaia-wiki, is in the main docs. This page covers content contributors maintain on the GAIA repo’s own wiki.
wiki/entities/
Section titled “wiki/entities/”Pages here describe named entities the GAIA team tracks. Current entries:
GAIA.md: the project itself, including history, naming convention, and supporting links.Steven Sacks.md: author and maintainer.
Entity pages use the entity type in their frontmatter, with an entity_type field saying what kind of entity it is (project, person, etc.).
An entity earns its own page once concept or decision pages link to it and a page of its own helps tell it apart from similar names. Generic concepts go under wiki/concepts/, not here. No /gaia-wiki stage writes entity pages, and outside contributors rarely need a new one. If you do, ask:
Draft a wiki/entities/ page for <name>, using the entity frontmatter (type: entity, entity_type: <kind>) and the layout of wiki/entities/GAIA.md. Link it from the concept or decision pages that mention it.wiki/meta/
Section titled “wiki/meta/”Pages here describe the wiki’s own process. /gaia-wiki writes two reports here, each overwritten on every run, with earlier runs in the commit history:
wiki/meta/lint-report.md, from the lint stage.wiki/meta/consolidate-report.md, from the consolidate stage.
Do not write these by hand. The directory is release-excluded, so a fresh project has no wiki/meta/ until its first /gaia-wiki run creates it.
A new meta page belongs here only when it documents how the wiki itself works, such as a new convention or a new workflow.
wiki/.state.json
Section titled “wiki/.state.json”The sync and consolidate stages of /gaia-wiki share one state file, wiki/.state.json. Each stage writes its own fields and keeps the other’s. Only gaia wiki subcommands write it, and each write replaces the file in one step. Never edit it by hand. If it looks wrong, ask:
wiki/.state.json looks wrong. Run gaia wiki state --json, explain what it shows, and fix the state through the gaia wiki CLI rather than editing the file.| Field | Written by | Value |
|---|---|---|
version | state-init | Always 1. |
last_evaluated_sha | sync | Full 40-char SHA of HEAD at the last sync evaluation. |
last_evaluated_at | sync | ISO-8601 timestamp of the last sync evaluation. |
last_consolidated_sha | sync (bootstrap) / consolidate | Full 40-char SHA at consolidate completion; bootstrapped by sync on first run. |
last_consolidated_at | consolidate | ISO-8601 timestamp at consolidate completion. |
gaia wiki state-init <sha> creates the file on a fresh project (refuses if it already exists). gaia wiki state-bump <field> <value> updates a single field and preserves all others. gaia wiki state --json reads the file and reports how far the wiki has fallen behind the code (drift severity), the head SHA, and page counts per domain.
gaia wiki CLI primitives
Section titled “gaia wiki CLI primitives”gaia wiki has these subcommands. /gaia-wiki and its subagents call them, so you do not run them yourself. To debug a /gaia-wiki run, ask Claude to use them:
Use the gaia wiki CLI to tell me why /gaia-wiki reports drift: run gaia wiki state --json and gaia wiki commit-classify since the last evaluated commit, and summarize.| Subcommand | Description |
|---|---|
state [--json] | Drift report: commits since last_evaluated_sha, severity, page counts per domain. |
commit-classify --since <sha> [--json] | Mark each commit since <sha> as WORTHY (worth a wiki update) or SKIP. |
state-init <sha> | Create wiki/.state.json (refuses if the file already exists). |
state-bump <field> <value> | Update one field in wiki/.state.json, keeping all the others. |
log-prepend --sha <h> --decision <D> --reason "..." | Prepend a decision line to wiki/log.md. |
page-index [--json] | List every wiki page with its frontmatter and wikilinks. |
orphans [--json] | Pages no other page links to. |
near-collisions [--max-distance N] | Page names in the same domain that differ by only a few characters (Levenshtein distance). |
dead-paths [--json] | Repo paths written in backticks in wiki text that no longer exist. |
frontmatter [--json] | Pages missing required frontmatter (type, status). Excludes wiki/meta/. |
empty-sections [--json] | Headings with no content and no subheadings; a heading with subheadings is never flagged. |
broken-links [--json] | Wikilinks whose target page does not exist. |
chain <begin|commit|finish|refresh-nudge> | Runs the full /gaia-wiki chain on one branch with one pull request. |
chain subcommands:
beginruns on the branch/gaia-wikialready created (awiki/<YYYY-MM-DD-HHMM>branch, in a worktree by default) and refusesmainandmaster.commitcommits every stage’swiki/edits as one commit titledwiki: <date> <time> UTC; a no-op when nothing changed; refuses when non-wiki changes are present.finishpushes the branch and opens one pull request as a draft (or ready, on a private repository that refuses drafts). If the branch rules require theGAIA-Auditcheck (the status the Code Audit Team posts when its audit passes), it posts that check itself, marking the wiki-only change as outside the audit’s scope. It then marks the pull request ready and queues auto-merge. If marking it ready fails, the pull request stays an open draft and auto-merge is not queued.- When nothing changed,
finishopens no pull request. In a normal checkout it deletes the empty branch. In a linked worktree it leaves the branch for the caller to remove, and with uncommitted changes it leaves everything in place for review. refresh-nudgeupdates the statusline’s wiki nudge after the merge, from the main checkout’s new drift.
gaia:maintainer-only block convention
Section titled “gaia:maintainer-only block convention”Some files that ship contain blocks that do not: pages under wiki/concepts/ and wiki/decisions/, files under .claude/ such as .claude/rules/pr-merge.md, the .gaia/audit-ci.yml roster, and .githooks/pre-commit. The marker syntax depends on the file type.
In Markdown files, use HTML comments:
<!-- gaia:maintainer-only:start -->This block is contributor-only. The bundle-time scrub removes itfrom the release tarball.<!-- gaia:maintainer-only:end -->In shell scripts, .gaia/audit-ci.yml, .githooks/pre-commit, and .prettierignore, use # comments:
# gaia:maintainer-only:startecho "contributor-only step"# gaia:maintainer-only:endThe wrong form breaks the file or ships the block. An HTML comment is a syntax error in a shell script, and a # marker in a Markdown file is not stripped.
Put each marker on a line of its own; indenting it is fine. The scrub drops the whole line a marker sits on, so any other text on that line would vanish from the release without a word. The release build therefore refuses a marker line that carries other text, just as it refuses a start marker without an end or an end without a start.
The shipped file is a subset of the source: the scrub removes the markers and everything between them before the tarball is built. The literal phrase is maintainer-only; this is the on-disk identifier and matches the comment text in .gaia/release-exclude. Public-facing references in the docs site use “Contributors.”
Where blocks work
Section titled “Where blocks work”Blocks are stripped only in the files .gaia/release-scrub.yml lists:
- HTML-comment markers in
wiki/**/*.mdand.claude/**/*.md. The paths are matched from the repo root, so.claude/**/*.mddoes not coverfrontend/.claude/. #markers in.prettierignore,.gaia/audit-ci.yml,.githooks/pre-commit, and every*.shfile.
A block in any other file ships as written, markers included. The marker check then catches it, in the verification runner, the pre-push hook, and the advisory checks on the pull request, because marker text survives in the shipped tree. Claude then moves the block or adds the file to the scrub list. To add a block somewhere new, ask:
I need a maintainer-only block in <file>. Check whether .gaia/release-scrub.yml strips markers in that file type; if not, add the path to the right marker-strip transform, then add the block with the comment syntax that file type uses.Blocks or path-level exclusion
Section titled “Blocks or path-level exclusion”Use a block when most of a file is relevant to every project but a section needs to stay internal. Use path-level exclusion when the entire file is contributor-only. .gaia/release-exclude is organized into numbered categories, each with the reason its paths are withheld, so a new entry belongs under the category that fits:
Withhold <path> from the release bundle: add it to .gaia/release-exclude under the category whose reason fits, and tell me which category you picked and why.Cross-references
Section titled “Cross-references”- The wiki workflow every project runs:
/gaia-wiki. - The
.gaia/release-excludemanifest is the authoritative path-level exclusion list. The maintainer’s release tooling also skips anything listed there, so the shipped manifest never lists a file a project cannot have.