From 9005336e1f64d927a745361bac71260172d06b44 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Thu, 25 Jun 2026 21:58:54 +0900 Subject: [PATCH 01/25] docs: 1.7.0 release updates Document the 1.7.0 surface and reconcile drift: - spec: adversarial SPEC-audit step + silent merged-spec archiving - plan: decomposition audit (three lenses) - audit: clean zero-finding audits auto-apply, no gate - harden: efficacy lens; drop mentorship-naming guardrail line - agents: local-vs-CI audit mode + new worthiness-evaluator agent - hooks: wiki-cache recompaction pair + worthiness-presence merge gate; correct red-verify-commit-check for the emergent-test exemption - code skills: TDD determinism/worthiness + react-code platform-first ladder - scaffolders/cli: scaffold route --dry-run, complex --props - setup: audit-mode policy/choice steps; mute mentorship per docs voice - fix typos (create-gaia, "is keeps"); setup-cloned step renumbering Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/commands/audit.mdx | 6 ++++- src/content/docs/commands/harden.mdx | 6 +++-- src/content/docs/commands/plan.mdx | 17 +++++++++++++- src/content/docs/commands/spec.mdx | 18 ++++++++------- src/content/docs/commands/wiki.mdx | 2 +- src/content/docs/contributors/cli.mdx | 6 +++-- src/content/docs/contributors/index.mdx | 2 +- .../docs/getting-started/gaia-init.mdx | 4 ++-- .../setup-cloned-gaia-project.mdx | 13 +++++++++-- .../docs/getting-started/setup-gaia-ci.mdx | 12 +++++++--- src/content/docs/reference/agents.mdx | 23 +++++++++++++++++++ src/content/docs/reference/hooks.mdx | 10 +++++++- src/content/docs/skills/code.mdx | 10 +++++++- src/content/docs/skills/scaffolders.mdx | 8 +++++-- 14 files changed, 110 insertions(+), 27 deletions(-) diff --git a/src/content/docs/commands/audit.mdx b/src/content/docs/commands/audit.mdx index c21cadf..bf515ad 100644 --- a/src/content/docs/commands/audit.mdx +++ b/src/content/docs/commands/audit.mdx @@ -39,7 +39,11 @@ Use `--apply` to resume a report that was interrupted, or to retry after fixing ## The decision gate -Calling `/gaia-audit` is the intent to audit, not a commitment to apply. After the research stage writes its report, the main conversation summarizes the findings and asks one question with three options: +Calling `/gaia-audit` is the intent to audit, not a commitment to apply. What happens next depends on what the research stage found. + +If the audit comes back clean, with zero actions, there is nothing to approve: the command finalizes the report and clears the statusline nudge automatically, with no prompt. + +Otherwise, the main conversation summarizes the findings and asks one question with three options: - **Apply.** Run the apply stage now. This is the one-keystroke fast path. - **Discuss / refine.** Talk the report through. Edits happen in the report in place (it stays a `draft`), then the gate is asked again. diff --git a/src/content/docs/commands/harden.mdx b/src/content/docs/commands/harden.mdx index 138bbfa..507adba 100644 --- a/src/content/docs/commands/harden.mdx +++ b/src/content/docs/commands/harden.mdx @@ -50,7 +50,7 @@ The tally is recomputed from GitHub PR data via `gaia harden-tally` each time yo ## Judge-the-form logic -For each candidate, `/gaia-harden` judges two axes before recommending exactly one enforcement form. The bias is always to the lowest-context-weight form the pattern admits. +For each candidate, `/gaia-harden` weighs three things before recommending exactly one enforcement form. The bias is always to the lowest-context-weight form the pattern admits. **Edit vs new (checked first).** Before recommending a new artifact, the command checks whether an existing rule, skill, or hook already covers the finding's territory. If one does, the recommendation is to edit it, not create a new one. @@ -63,6 +63,8 @@ For each candidate, `/gaia-harden` judges two axes before recommending exactly o | Correct procedure (a sequence of steps) | A skill via `skill-creator`. v1 produces a scaffold only; nothing is activated. | | Judgment-based anti-pattern (no reliable mechanization) | A path-scoped prose rule. v1 owns this end to end. | +**Will it change behavior (checked last).** A recurring finding proves the anti-pattern is real. It does not prove the recommended form will stop it. Before presenting a recommendation, the command asks what cheap evidence would show the form actually changes behavior, and whether that evidence exists. The bar is low: a couple of before-and-after task replays, or a single case of the agent ignoring guidance of the same kind. This matters most for prose rules, which advise rather than enforce. When the recommended form is a prose rule and no such evidence is available, because the pattern is too judgment-laden to catch reliably or a capable agent already honors the principle, the command says so and frames the candidate as a defer or decline. The decision is always yours; it never auto-declines. + For each candidate, `/gaia-harden` presents the `finding_class`, its distinct-PR count and the PR numbers, the recommended form, and a one-line rationale. You then choose: **approve**, **decline**, **defer**, or **redirect** (override the form choice). ## What gets drafted on approve @@ -104,7 +106,7 @@ All approved work lands in the working tree only. It ships through your normal P - Every drafted prose rule has a mandatory `paths:` glob: no always-loaded frontmatter-less rules are ever produced. - A decline is machine-local only: it never vetoes the candidate for a teammate. - A defer persists nothing. -- The command never reads the privacy-sealed mentorship event store. The Policy-Memory Loop keys only on `finding_class` recurrence from the PR window. +- The Policy-Memory Loop keys only on recurring `finding_class` counts from the merged-PR window. ## Pruning promoted rules diff --git a/src/content/docs/commands/plan.mdx b/src/content/docs/commands/plan.mdx index 52fd12e..d62a7d1 100644 --- a/src/content/docs/commands/plan.mdx +++ b/src/content/docs/commands/plan.mdx @@ -54,7 +54,8 @@ Inside the directory: 3. **Plan directory resolution.** Slug is derived (or seeded from the SPEC id), suffixed on collision, then created under `.gaia/local/plans/`. 4. **Planner dispatch.** The skill spawns a `general-purpose` Agent restricted to writing inside the plan directory only. The planner reads `wiki/concepts/Task Orchestration.md` for the orchestration pattern, then writes the plan files directly to disk. 5. **Verification.** The skill confirms `README.md`, `ORCHESTRATOR.md`, `KICKOFF.md`, and at least one `task-*.md` exist. If anything is missing, the failure surfaces; no silent retry. -6. **Hand-off.** The skill prints the kickoff prompt as a fenced code block and tries to copy it to the system clipboard via `pbcopy`, `wl-copy`, `xclip`, `xsel`, `clip.exe`, or `clip` (whichever is available). The trailing line says whether the copy succeeded. +6. **Decomposition audit.** For non-trivial plans, the skill offers to stress-test the decomposition before hand-off, and running it is the recommended choice. See [Decomposition audit](#decomposition-audit). +7. **Hand-off.** The skill prints the kickoff prompt as a fenced code block and tries to copy it to the system clipboard via `pbcopy`, `wl-copy`, `xclip`, `xsel`, `clip.exe`, or `clip` (whichever is available). The trailing line says whether the copy succeeded. The kickoff prompt looks exactly like: @@ -64,6 +65,20 @@ Read /abs/path/.gaia/local/plans//KICKOFF.md and execute it. Paste it into a fresh Claude Code session, started cold, to run the plan. The orchestrator's behavior lives entirely in `KICKOFF.md`. +## Decomposition audit + +After the planner writes its files and verification confirms they exist, `/gaia-plan` offers to audit the decomposition itself before handing off. For non-trivial plans (parallel tasks, multiple phases, or shared frozen contracts), running it is the recommended choice; a trivial single-phase plan can skip it. + +Three auditors run in parallel, each targeting a different way a decomposition goes wrong: + +- **Decomposition & dependency soundness** checks that tasks placed in the same phase do not share state or edit the same files, that phase order respects real data and interface dependencies, and that every task reads the shared interface contracts the same way. +- **Contract grounding** checks every file path, export, type, and function signature a task names against the real repo. A contract that points at something that does not exist would send a sub-agent building on a false assumption. +- **SPEC coverage** runs only when the plan came from a SPEC. It maps each SPEC requirement to a covering task and flags anything left uncovered, contradicted, or scoped back in that the SPEC ruled out. + +Localized findings, like a wrong path or a missing acceptance criterion, are applied straight to the plan files. Structural findings, like a phase graph that needs reworking, re-spawn the planner with a correction directive and re-verify the regenerated plan before hand-off. + +The point is to catch a broken decomposition before hand-off, rather than mid-build after an orchestrator session has already started. + ## Orchestrator vs sub-agents The orchestrator owns coordination. It is spawned in a fresh context after you paste the kickoff prompt. It commits, pushes, opens the PR, runs quality gates between phases, dispatches sub-agents, and never edits source files itself. diff --git a/src/content/docs/commands/spec.mdx b/src/content/docs/commands/spec.mdx index 0614499..ee45579 100644 --- a/src/content/docs/commands/spec.mdx +++ b/src/content/docs/commands/spec.mdx @@ -49,7 +49,7 @@ Once saved, the SPEC artifact is immutable. Mutations require an explicit reopen A handful of mechanics are used by multiple steps: -- **Working-draft cache.** Every fold in the Socratic loop, every gate confirmation, every research result, every self-review apply persists the in-flight draft to `.gaia/local/cache/draft-.md`. A single `Write` per turn. No incremental `Edit` calls. Step 8's canonical save deletes the cache as its final action. Resumed sessions pick up the cache if it is newer than the canonical artifact. +- **Working-draft cache.** Every fold in the Socratic loop, every gate confirmation, every research result, every self-review apply persists the in-flight draft to `.gaia/local/cache/draft-.md`. A single `Write` per turn. No incremental `Edit` calls. Step 10's canonical save deletes the cache as its final action. Resumed sessions pick up the cache if it is newer than the canonical artifact. - **Per-topic revisit counter.** Tracks how many times the user has chosen "push deeper" on a given topic. On the third revisit, the prompt swaps to settle, defer, or push deeper anyway. Prevents one topic from consuming the whole session. - **Five-question cap.** Spec-kit's `/clarify` primitive caps the loop at five total questions per session. The wrapper inherits this cap and never invokes `/clarify` twice to extend it. - **Discuss-this escape.** Any closed-set question can drop into a plain Q&A discussion. On settlement, the outcome folds into `clarifications.answered[]` and the structured loop resumes on the next topic. @@ -59,15 +59,16 @@ A handful of mechanics are used by multiple steps: 1. **Description capture.** Open-ended prompt if not provided as arguments. 2. **GitHub issue mirror prompt.** Single `AskUserQuestion`: skip (recommended) or mirror to a GitHub issue on save. -3. **Resume-vs-start-new.** If an in-progress SPEC exists, the skill surfaces it (last touched, intent first line, UAT count) and asks: resume, start new, or discard the draft cache. +3. **Resume-vs-start-new.** If an in-progress SPEC exists, the skill surfaces it (last touched, intent first line, UAT count) and asks: resume, start new, or discard the draft cache. Before this prompt, two silent housekeeping passes run: any earlier SPEC whose implementing PR has since merged is advanced, then those merged folders are swept into `.gaia/local/specs/archived/`. Both are best-effort and never block the session, and only still-draft sessions surface for resume. 4. **Initial draft.** `/speckit-specify` runs the GAIA preset's body, allocates a SPEC id, lands the artifact at `.gaia/local/specs/SPEC-NNN/SPEC.md`. The `before_specify` hook (constitution check) fires automatically. 5. **Gate 1.** Plain prompt: confirm intent and UATs, or revise. 6. **Socratic clarify loop.** `/speckit-clarify` runs, capped at five questions. Closed-set questions go through `AskUserQuestion` with the recommended option first; open-ended questions are plain prompts. Per-topic exhaustion checkpoints fire when the natural well runs dry. Research subagents dispatch for any question requiring prior-art lookup. 7. **Self-review.** The `after_clarify` hook fires `/speckit-gaia-self-review` against the gate-1 snapshot. Findings come back classified low, medium, or high. Low and medium auto-apply; high surfaces to the user before applying. Pending clarifications block save until answered or deferred with rationale. -8. **Gate 2.** Plain prompt: confirm the full rendered artifact, or revise. -9. **Canonical save.** Writes `.gaia/local/specs/SPEC-NNN/SPEC.md` and deletes the working-draft cache. The `after_specify` hook fires `/speckit-gaia-lint` for immutability checks. Cycles 1 and 2 surface failures; cycle 3 prompts to step back to gate 2, defer remaining findings, or push another fix. -10. **Optional GitHub issue mirror.** If opted in at step 2, `gh-mirror.sh` creates the issue and stamps the URL into frontmatter. Skips silently when `gh` is not authenticated, Issues are disabled, or the viewer lacks write permission. -11. **Chain to `/gaia-plan`.** `AskUserQuestion`: trigger `/gaia-plan` now or defer. On yes, the skill enters a multi-plan dispatch loop. Each plan runs in its own `general-purpose` Agent so the wrapper context stays bounded across plan count. +8. **Adversarial SPEC-audit.** Before gate 2, the skill offers to audit the draft, and the recommended choice is always an intensity (standard or deep), never skip. A fan-out of specialist agents verifies the draft's claims against the actual repo and `node_modules`, attacks each UAT for testability, and hunts for coverage gaps, then a refutation pass filters what survives. Surviving findings split two ways: contract fixes fold into the draft before save, so gate 2 shows the already-hardened artifact; implementation directives land in `.gaia/local/specs/SPEC-NNN/AUDIT.md` for `/gaia-plan` to honor. +9. **Gate 2.** Plain prompt: confirm the full rendered artifact, or revise. +10. **Canonical save.** Writes `.gaia/local/specs/SPEC-NNN/SPEC.md` and deletes the working-draft cache. The `after_specify` hook fires `/speckit-gaia-lint` for immutability checks. Cycles 1 and 2 surface failures; cycle 3 prompts to step back to gate 2, defer remaining findings, or push another fix. +11. **Optional GitHub issue mirror.** If opted in at step 2, `gh-mirror.sh` creates the issue and stamps the URL into frontmatter. Skips silently when `gh` is not authenticated, Issues are disabled, or the viewer lacks write permission. +12. **Chain to `/gaia-plan`.** `AskUserQuestion`: trigger `/gaia-plan` now or defer. On yes, the skill enters a multi-plan dispatch loop. Each plan runs in its own `general-purpose` Agent so the wrapper context stays bounded across plan count. ## Auto mode @@ -77,6 +78,7 @@ A handful of mechanics are used by multiple steps: - Closed-set Socratic questions auto-pick the recommended option. - Open-ended questions get the agent's best-judgment answer. - Per-topic exhaustion auto-advances; the third-revisit prompt auto-settles. +- The adversarial SPEC-audit runs at the recommended intensity; it is never skipped. - Pending clarifications auto-defer with a static auto-mode rationale. - The GitHub issue mirror is forced on. - The chain to `/gaia-plan` is automatic and produces exactly one plan covering the full SPEC. @@ -102,8 +104,8 @@ Five GAIA hooks fire across the SPEC lifecycle. Never invoke them by hand. | `before_implement` | `/speckit-gaia-uat-write` | Renders frozen UATs into Playwright e2e specs at `.playwright/e2e//`, leaving a red-state harness before implementation begins. | | `after_implement` | `/speckit-gaia-wiki-promote` | Promotes merged-PR content into the project wiki under `wiki//`. Defers if the implementing PR has not merged yet. | -The chain-trigger to `/gaia-plan` lives inline at step 11 of the flow, not as a hook. Disposition of the SPEC artifact (archive, delete, or keep) happens through `/speckit-gaia-spec-close` after the implementing PR merges. It auto-fires from the `after_implement` wiki-promote step on the immediate-merge path, and is also invokable manually as `/gaia-spec close ` for the deferred path or retroactive cleanup. +The chain-trigger to `/gaia-plan` lives inline at step 12 of the flow, not as a hook. Disposition of the SPEC artifact (archive, delete, or keep) happens through `/speckit-gaia-spec-close` after the implementing PR merges. It auto-fires from the `after_implement` wiki-promote step on the immediate-merge path, and is also invokable manually as `/gaia-spec close ` for the deferred path or retroactive cleanup. ## Related -After save, [`/gaia-plan`](/commands/plan/) is the natural next step. The chain-trigger at step 11 dispatches it automatically when accepted. +After save, [`/gaia-plan`](/commands/plan/) is the natural next step. The chain-trigger at step 12 dispatches it automatically when accepted. diff --git a/src/content/docs/commands/wiki.mdx b/src/content/docs/commands/wiki.mdx index ccd0ba8..7d56eef 100644 --- a/src/content/docs/commands/wiki.mdx +++ b/src/content/docs/commands/wiki.mdx @@ -9,7 +9,7 @@ The wiki at `wiki/` exists for Claude, not for human reading (though it is used ## Why the wiki exists -The Obsidian wiki is keeps a current, structured project context Claude can read on demand instead of re-inferring the same facts from source code on every request. That re-inference is a token sink that the wiki eliminates. +The Obsidian wiki keeps a current, structured project context Claude can read on demand instead of re-inferring the same facts from source code on every request. That re-inference is a token sink that the wiki eliminates. Without it, every session that needs to reason about a service, a hook contract, or a past architectural decision pays for it twice: once when the source was written, and again when Claude reads the source to answer a question. The wiki captures the load-bearing facts once and stays current as commits land. Claude reads the wiki, not the source, for orientation, and only refers to the source code when more details are necessary. diff --git a/src/content/docs/contributors/cli.mdx b/src/content/docs/contributors/cli.mdx index 5c22d07..fba789d 100644 --- a/src/content/docs/contributors/cli.mdx +++ b/src/content/docs/contributors/cli.mdx @@ -44,12 +44,14 @@ Source: `.gaia/cli/src/scaffold/index.ts` Code generators invoked by the `new-component`, `new-hook`, `new-route`, and `new-service` skills. Each generator reads templates from `.gaia/cli/src/scaffold/templates/`. ``` -gaia scaffold component +gaia scaffold component [--props "a:string,..."] gaia scaffold hook -gaia scaffold route +gaia scaffold route [--dry-run] gaia scaffold service ``` +`scaffold route --dry-run` previews the files it would write without touching disk. `scaffold component --props` splits on depth-0 commas, so comma-bearing types (`Record`, tuples, multi-argument function types) are valid inside a single entry. + ### `gaia setup` Source: `.gaia/cli/src/setup/index.ts` diff --git a/src/content/docs/contributors/index.mdx b/src/content/docs/contributors/index.mdx index 8aa7b9b..79444b1 100644 --- a/src/content/docs/contributors/index.mdx +++ b/src/content/docs/contributors/index.mdx @@ -5,7 +5,7 @@ sidebar: order: 1 --- -This section covers GAIA surface that exists in the template repo but is not included in the `npx creata-gaia` bundle. +This section covers GAIA surface that exists in the template repo but is not included in the `npx create-gaia` bundle. Audience: Steven and any outside contributors working on the GAIA template itself. diff --git a/src/content/docs/getting-started/gaia-init.mdx b/src/content/docs/getting-started/gaia-init.mdx index 752ad5d..987e675 100644 --- a/src/content/docs/getting-started/gaia-init.mdx +++ b/src/content/docs/getting-started/gaia-init.mdx @@ -57,9 +57,9 @@ claude plugin marketplace add AgriciDaniel/claude-obsidian claude plugin install claude-obsidian@claude-obsidian-marketplace ``` -### 5. Mentorship opt-in +### 5. Adaptation feature opt-in -You can choose to opt-in to GAIA's experimental [mentorship](https://gaiareact.com/mentorship/) feature. +You can choose to opt into an optional adaptation feature. ### 6. Wiki initialization diff --git a/src/content/docs/getting-started/setup-cloned-gaia-project.mdx b/src/content/docs/getting-started/setup-cloned-gaia-project.mdx index c6d2f05..cadb21f 100644 --- a/src/content/docs/getting-started/setup-cloned-gaia-project.mdx +++ b/src/content/docs/getting-started/setup-cloned-gaia-project.mdx @@ -38,9 +38,18 @@ claude plugin install claude-obsidian@claude-obsidian-marketplace Already-installed plugins are no-ops. -### 4. Mentorship opt-in +### 3. Adaptation feature opt-in -You can choose to opt-in to GAIA's experimental [mentorship](https://gaiareact.com/mentorship/) feature. +You can choose to opt into an optional adaptation feature. + +### 4. Audit-mode choice + +If the project uses the pre-merge `code-review-audit` gate, you choose who runs it on your PRs: + +- **CI (default).** CI runs the audit on your PRs and you wait for the `GAIA-Audit` check before merging. +- **Locally.** The audit runs in your own session at merge time, streaming as it goes, and CI's audit step stands down for your PRs. + +Your choice adds a one-line entry to `.gaia/audit-ci.yml`, which the command helps you commit as a small PR. If `gh` is not authenticated, the step is skipped; re-run `/setup-cloned-gaia-project` after `gh auth login` to finish it. ## Resuming after a failure diff --git a/src/content/docs/getting-started/setup-gaia-ci.mdx b/src/content/docs/getting-started/setup-gaia-ci.mdx index 99de516..6f91b8d 100644 --- a/src/content/docs/getting-started/setup-gaia-ci.mdx +++ b/src/content/docs/getting-started/setup-gaia-ci.mdx @@ -50,7 +50,13 @@ Three options: If `delete_branch_on_merge` is disabled on the repo and you have admin access, the command offers to enable it. Enabling it makes the stale-branches workflow redundant. The command marks `stale_branches.mode = "off"` in `.gaia/automation.json` automatically. -### 5. Bot token +### 5. Audit-mode policy + +The pre-merge `code-review-audit` gate runs in CI by default: every PR waits for the `GAIA-Audit` check before it can merge. The command offers a different team default, where developers run the audit locally at merge time and CI's audit step stands down for them. Either way the gate holds; the choice is only where the audit runs. + +The decision is recorded as `default_mode` in `.gaia/audit-ci.yml`. Individual developers can override it for themselves during [`/setup-cloned-gaia-project`](/getting-started/setup-cloned-gaia-project/), and `--reconfigure` re-offers the policy. + +### 6. Bot token GAIA CI needs an Anthropic token or key to authenticate the workflow steps that call Claude. The command asks which token type to use: @@ -59,13 +65,13 @@ GAIA CI needs an Anthropic token or key to authenticate the workflow steps that Paste the token when prompted. It is piped directly to `gh secret set` and never written to any file, never echoed in chat, and never appears in the terminal scrollback. You can add it manually on GitHub instead, if you prefer. -### 6. Workflow generation +### 7. Workflow generation The command generates `.github/workflows/gaia-ci-*.yml` from `.gaia/automation.json` and installs `.github/workflows/code-review-audit.yml`, the pre-merge audit gate. The audit gate installs unconditionally, even when no cron tool runs in CI mode. The command then triggers one `workflow_dispatch` run on the first generated workflow to confirm it boots correctly. If the verification run fails, you can retry, abandon (deletes the generated files, leaves `setup_complete: false`), or commit anyway if you have confirmed the failure is a transient infrastructure issue. -### 7. Commit and push +### 8. Commit and push On a successful verification run, the command stages the generated workflow files and `.gaia/automation.json`, commits with a standard message, and pushes. diff --git a/src/content/docs/reference/agents.mdx b/src/content/docs/reference/agents.mdx index 8542de2..3c19605 100644 --- a/src/content/docs/reference/agents.mdx +++ b/src/content/docs/reference/agents.mdx @@ -51,3 +51,26 @@ The agent produces a structured report: When the report is clean (no Critical Issues, all Important Issues resolved in the working tree), the agent stamps HEAD with a `GAIA-Audit:` commit trailer and writes a marker file at `.gaia/local/audit/.ok`. The marker unblocks `gh pr merge` locally; the trailer travels with the commit through the network so CI can recognize an already-audited tree and skip its own audit run. If findings remain, the agent does not write the marker. Address findings, commit, and re-invoke the agent on the new HEAD. + +### Local vs CI audit mode + +By default the audit runs in CI on every PR, and you wait for the `GAIA-Audit` commit status to go green before merging. Teams can let individual developers run it locally instead. In local mode the audit runs at merge time in your own session, streaming as it goes, and CI's audit step stands down for that author while still running for everyone else. + +The team default and the per-developer enrollments live in `.gaia/audit-ci.yml`, which ships with the project and is meant to be edited. You set the team default during [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/); individual developers opt in during [`/setup-cloned-gaia-project`](/getting-started/setup-cloned-gaia-project/). Local mode relies on `GAIA-Audit` being registered as a required status check on the default branch; if it is not, the audit falls back to CI. + +## worthiness-evaluator + +Path: `.claude/agents/worthiness-evaluator.md`. Model: `opus`. + +An advisory reviewer for tests on the emergent surface (components and Playwright), where the failing-first RED gate does not apply. The `tdd` skill dispatches it after tests go green. It reads only the test files the phase changed plus their sibling suites, and it edits nothing. + +### What it judges + +Each test is scored on two axes: + +- **Honesty**: can the test fail for a real reason? It must assert through the public interface (roles, accessible names, visible text), not internal call signatures or implementation detail, and survive an internal refactor. +- **Worthiness**: is the test worth keeping? It should exercise your own code rather than a dependency or a platform formatter, and a composition test should not re-prove what a child's own suite already covers. + +### Output + +One verdict per test: `keep`, `fix`, or `delete`. A `fix` names the specific defect. A `delete` is always a proposal you confirm, never applied automatically, and it carries the evidence behind it. The verdicts surface in the end-of-task summary alongside the rest of the TDD roll-up. diff --git a/src/content/docs/reference/hooks.mdx b/src/content/docs/reference/hooks.mdx index 9b6aaa1..d600d5c 100644 --- a/src/content/docs/reference/hooks.mdx +++ b/src/content/docs/reference/hooks.mdx @@ -29,6 +29,13 @@ For Claude Code's own hook documentation, see [the Hooks reference on docs.claud | Hook | What it does | Path | |---|---|---| | `wiki-drift-check` | Detects drift between `wiki/.state.json` and HEAD; injects a once-per-session reminder when drifted. | `.claude/hooks/wiki-drift-check.sh` | +| `wiki-recompact-inject` | On the first prompt after a context compaction, restores the wiki hot cache into context, then clears the sentinel. No-op on every other prompt. Pairs with `wiki-recompact-sentinel`. | `.claude/hooks/wiki-recompact-inject.sh` | + +## PostCompact + +| Hook | What it does | Path | +|---|---|---| +| `wiki-recompact-sentinel` | After a context compaction, writes a sentinel file so the next `UserPromptSubmit` knows to restore the wiki hot cache. Pairs with `wiki-recompact-inject`. | `.claude/hooks/wiki-recompact-sentinel.sh` | ## UserPromptExpansion @@ -57,7 +64,8 @@ For Claude Code's own hook documentation, see [the Hooks reference on docs.claud | `block-no-verify` | Denies `git commit` / `git push` that carry a hook bypass (`--no-verify`, or commit-only `-n`), so the commit-time floor (typecheck, lint, test) cannot be skipped. | `.claude/hooks/block-no-verify.sh` | | `block-rm-rf` | Denies `rm -rf` against root, `$HOME`, cwd, unscoped globs, `.git`, `node_modules`, and any path outside a small whitelist of scratch dirs. | `.claude/hooks/block-rm-rf.sh` | | `pr-merge-audit-check` | Blocks `gh pr merge` until a code-review-audit marker file exists at `.gaia/local/audit/.ok`. | `.claude/hooks/pr-merge-audit-check.sh` | -| `red-verify-commit-check` | Blocks `git commit` when a new-at-HEAD test that now passes has no recorded failing (RED) run matching its current content. Enforces mechanical TDD: a new test must be observed failing before its passing version can land. Type-only tests (all assertions are type-level via `expectTypeOf`/`assertType`/`@ts-expect-error`, no runtime `expect`) are exempt: they have no runtime failure mode, so `tsc` enforces them instead. | `.claude/hooks/red-verify-commit-check.sh` | +| `red-verify-commit-check` | Blocks `git commit` when a new-at-HEAD test that now passes has no recorded failing (RED) run matching its current content. Enforces mechanical TDD: a new test must be observed failing before its passing version can land. Three kinds of test are exempt: type-only tests (all assertions are type-level via `expectTypeOf`/`assertType`/`@ts-expect-error`, no runtime `expect`), which `tsc` enforces instead; tests with dynamic or computed titles, which have no stable identity to key a RED to; and emergent-subject tests (component interaction, Playwright, or clock/IO-dependent), which have no stable failing-then-passing run to observe. The deterministic surface (pure utilities, service parsers, spec-derivable hooks) still demands a RED. | `.claude/hooks/red-verify-commit-check.sh` | +| `worthiness-presence-check` | Blocks `gh pr merge` when an emergent test the PR changed has no worthiness-ledger line matching its current content, so the worthiness audit has run over every changed emergent test before merge. It checks presence only, never the keep/fix/delete verdict, and is a no-op when no emergent tests changed. Sits alongside `pr-merge-audit-check`. | `.claude/hooks/worthiness-presence-check.sh` | ## PostToolUse (Bash) diff --git a/src/content/docs/skills/code.mdx b/src/content/docs/skills/code.mdx index 0d75df5..4c8f87b 100644 --- a/src/content/docs/skills/code.mdx +++ b/src/content/docs/skills/code.mdx @@ -21,7 +21,9 @@ Source: `.claude/skills/typescript/SKILL.md`. Conventions for React components, pages, routes, hooks, and forms. Includes pre-flight gates for `useEffect`, `useCallback`, and `useState`; a form-element check that swaps native `` for the project's `Form/*` components; and a translation gate that requires every user-visible string to come from `t()` (exception: approximate skeleton-loader placeholders standing in for dynamic runtime values stay hardcoded; static skeleton text that mirrors a real `t()` call must still use `t()`). Covers component extraction thresholds and route/page architecture (`app/routes/` thin shells, `app/pages/` for UI). -**Triggers** when writing or reviewing React components, hooks (`useEffect`, `useCallback`, `useState`), event handlers, or component extraction decisions. Also triggers when debugging stale closures, infinite re-renders, or unnecessary re-renders caused by memoization issues. +Before adding a dependency or hand-rolling a primitive, the skill walks a platform-first ladder: existing GAIA code, then browser-native APIs (`Intl`, `URL`, `crypto.randomUUID()`, `structuredClone()`, modern CSS), then an already-installed dependency, then a new dependency, then custom code as a last resort. It stops at the first rung that fits. The biggest practical savings come from `Intl` standing in for date and number formatting libraries and native collection methods standing in for utility libraries, both already enforced by lint. + +**Triggers** when writing or reviewing React components, hooks (`useEffect`, `useCallback`, `useState`), event handlers, or component extraction decisions. Also triggers when debugging stale closures, infinite re-renders, or unnecessary re-renders caused by memoization issues, or when deciding whether to add a dependency or reach for a web-platform API instead. **Example phrasing:** "this useEffect is firing twice", "extract this section into its own component", "wire up a Conform form for sign-up". @@ -59,6 +61,12 @@ Based on Matt Pocock's excellent [TDD Skill](https://www.aihero.dev/skill-test-d Test-driven development with a vertical-slice red-green-refactor loop. Treats horizontal slicing (write all tests first, then all code) as an antipattern. Tests verify behavior through public interfaces, not implementation details. Includes a per-cycle checklist and a planning step that asks for the public interface before writing the first red test. +After tests go green, a determinism classifier sorts each touched file and scopes the failing-first (RED) requirement to the deterministic surface only: pure utilities, service parsers, and spec-derivable hooks. Component and Playwright tests are treated as emergent and commit without a RED gate, since environment and DOM state make a stable failing run impossible to guarantee. + +For tests on that emergent surface, the skill dispatches a fresh-context evaluator that reviews each one for honesty and worthiness and returns a keep, fix, or delete verdict. Fixes for dishonest tests, like a test coupled to implementation detail or one asserting a tautology, apply automatically as ordinary edits for review. Delete proposals need your confirmation and show their evidence inline, so you decide without opening files. Everything lands in a single end-of-task summary. + +New components scaffolded with `new-component` start with a non-degenerate accessibility test that renders a real instance, so it can fail against an actual violation instead of passing against an empty DOM. + It is automatically used by Claude when working in GAIA projects. **Triggers** when building features or fixing bugs with TDD, mentioning "red-green-refactor", asking for integration tests, or asking for test-first development. diff --git a/src/content/docs/skills/scaffolders.mdx b/src/content/docs/skills/scaffolders.mdx index 2d4f64e..85a00a6 100644 --- a/src/content/docs/skills/scaffolders.mdx +++ b/src/content/docs/skills/scaffolders.mdx @@ -21,6 +21,8 @@ Scaffolds a React component as a folder under `app/components/` (or a sub-folder Underlying CLI: `gaia scaffold component [--no-story] [--parent ] [--props "a:string,b:number"]`. +`--props` takes comma-separated `name:type` pairs. Comma-bearing types like `Record`, tuples, and multi-argument function types work inside a single entry, for example `--props "label:string,data:Record"`. + Source: `.claude/skills/new-component/SKILL.md`. ## New Hook @@ -39,7 +41,7 @@ Source: `.claude/skills/new-hook/SKILL.md`. ## New Route -Scaffolds a new route with its page component, test, story, and optional i18n keys. Files land in `app/routes/+/.tsx` plus `app/pages///index.tsx`. The route file stays a thin shell (`loader`, `action`, `meta`, Zod schemas, one-line default export); UI lives in the page component. +Scaffolds a new route with its page component, test, story, and optional i18n keys. Files land in `app/routes/+/.tsx` plus `app/pages//Page/index.tsx` (for example `UserProfilePage`). The route file stays a thin shell (`loader`, `action`, `meta`, Zod schemas, one-line default export); UI lives in the page component. **Confirms:** name (kebab-case), group (`_public+` or `_session+`), and which of `--loader`, `--action`, `--i18n` to include. @@ -47,7 +49,9 @@ Scaffolds a new route with its page component, test, story, and optional i18n ke **Example phrasing:** "add a /pricing page in _public+", "scaffold /settings/profile under _session+ with a loader and action", "create a new route /forgot-password with i18n". -Underlying CLI: `gaia scaffold route --group <_public+|_session+> [--loader] [--action] [--i18n] [--json]`. +Underlying CLI: `gaia scaffold route --group <_public+|_session+> [--loader] [--action] [--i18n] [--dry-run] [--json]`. + +`--dry-run` prints the files it would write without touching disk, so you can confirm the output paths first. With `--i18n`, the new locale file is also wired into `app/languages/en/pages/index.ts`. If that barrel is missing, the command writes the locale file but stops with an actionable error instead of reporting success, so you can add the import by hand or re-run from the repo root. Source: `.claude/skills/new-route/SKILL.md`. From 6008823b20edd180149f70608cd9825ad47933cc Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Thu, 25 Jun 2026 23:04:46 +0900 Subject: [PATCH 02/25] docs: address pre-1.7.0 doc gaps - spec.mdx: fix spec-close manual invocation (/speckit-gaia-spec-close [SPEC-NNN], optional arg); /gaia-spec close never routed (spec.md parses only `auto`). - setup-cloned-gaia-project.mdx: surface the three automatic steps (spec-kit init, statusline permissions, env bootstrap). - hooks.mdx: add WorktreeCreate section (.gaia/scripts/create-worktree.sh). - gaia-init.mdx: add CI integration step (enable/skip; skip sets team audit default to local in .gaia/audit-ci.yml), cross-link /setup-gaia-ci and the agents reference; renumber subsequent steps. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/commands/spec.mdx | 2 +- src/content/docs/getting-started/gaia-init.mdx | 13 +++++++++++-- .../getting-started/setup-cloned-gaia-project.mdx | 8 ++++++++ src/content/docs/reference/hooks.mdx | 6 ++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/content/docs/commands/spec.mdx b/src/content/docs/commands/spec.mdx index ee45579..f66480a 100644 --- a/src/content/docs/commands/spec.mdx +++ b/src/content/docs/commands/spec.mdx @@ -104,7 +104,7 @@ Five GAIA hooks fire across the SPEC lifecycle. Never invoke them by hand. | `before_implement` | `/speckit-gaia-uat-write` | Renders frozen UATs into Playwright e2e specs at `.playwright/e2e//`, leaving a red-state harness before implementation begins. | | `after_implement` | `/speckit-gaia-wiki-promote` | Promotes merged-PR content into the project wiki under `wiki//`. Defers if the implementing PR has not merged yet. | -The chain-trigger to `/gaia-plan` lives inline at step 12 of the flow, not as a hook. Disposition of the SPEC artifact (archive, delete, or keep) happens through `/speckit-gaia-spec-close` after the implementing PR merges. It auto-fires from the `after_implement` wiki-promote step on the immediate-merge path, and is also invokable manually as `/gaia-spec close ` for the deferred path or retroactive cleanup. +The chain-trigger to `/gaia-plan` lives inline at step 12 of the flow, not as a hook. Disposition of the SPEC artifact (archive, delete, or keep) happens through `/speckit-gaia-spec-close` after the implementing PR merges. It auto-fires from the `after_implement` wiki-promote step on the immediate-merge path, and is also invokable manually as `/speckit-gaia-spec-close [SPEC-NNN]` for the deferred path or retroactive cleanup. The SPEC ID is optional; omit it and the command surfaces every eligible SPEC to choose from. ## Related diff --git a/src/content/docs/getting-started/gaia-init.mdx b/src/content/docs/getting-started/gaia-init.mdx index 987e675..11e5530 100644 --- a/src/content/docs/getting-started/gaia-init.mdx +++ b/src/content/docs/getting-started/gaia-init.mdx @@ -57,11 +57,20 @@ claude plugin marketplace add AgriciDaniel/claude-obsidian claude plugin install claude-obsidian@claude-obsidian-marketplace ``` -### 5. Adaptation feature opt-in +### 5. CI integration + +`/gaia-init` asks whether to enable GAIA's GitHub Actions CI now or defer it. GAIA's pre-merge audit gate can run in CI or locally. + +- **Enable now.** CI becomes the venue for the pre-merge `code-review-audit` gate. `/gaia-init` prints the `gh` commands you run yourself once the project is on GitHub: mint and store the bot token, then register the `GAIA-Audit` required check. After your first push, [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/) wires up the scheduled maintenance jobs and confirms CI is connected. +- **Skip.** Defers CI and sets the team audit default to `local` in `.gaia/audit-ci.yml`. The audit gate still holds, it just runs in your session at merge time instead of in CI. Re-enable anytime with [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/). + +Either way the audit gate is non-negotiable; the choice is only where it runs. See the [`code-review-audit` agent reference](/reference/agents/) for what the audit checks and how `default_mode` works. + +### 6. Adaptation feature opt-in You can choose to opt into an optional adaptation feature. -### 6. Wiki initialization +### 7. Wiki initialization GAIA comes with an Obsidian wiki built-in. Read more about it here. diff --git a/src/content/docs/getting-started/setup-cloned-gaia-project.mdx b/src/content/docs/getting-started/setup-cloned-gaia-project.mdx index cadb21f..058dfc2 100644 --- a/src/content/docs/getting-started/setup-cloned-gaia-project.mdx +++ b/src/content/docs/getting-started/setup-cloned-gaia-project.mdx @@ -38,6 +38,14 @@ claude plugin install claude-obsidian@claude-obsidian-marketplace Already-installed plugins are no-ops. +### Automatic steps + +Between plugin install and the prompts below, three steps run with no input from you: + +- **spec-kit init.** Registers the spec-kit runtime so `/gaia-spec` works in your clone. The repo already ships the GAIA extension and preset; this wires up spec-kit itself. +- **Statusline permissions.** Restores the executable bit on the statusline scripts, which can be lost on cross-platform clones. +- **Environment bootstrap.** If `.env.example` exists and `.env` does not, a copy is made for you. + ### 3. Adaptation feature opt-in You can choose to opt into an optional adaptation feature. diff --git a/src/content/docs/reference/hooks.mdx b/src/content/docs/reference/hooks.mdx index d600d5c..2d72c7c 100644 --- a/src/content/docs/reference/hooks.mdx +++ b/src/content/docs/reference/hooks.mdx @@ -43,6 +43,12 @@ For Claude Code's own hook documentation, see [the Hooks reference on docs.claud |---|---|---|---| | `intercept-init` | `init` | Redirects `/init` to `/gaia-init` so the built-in flow does not overwrite GAIA's curated `CLAUDE.md`. | `.claude/hooks/intercept-init.sh` | +## WorktreeCreate + +| Hook | What it does | Path | +|---|---|---| +| `create-worktree` | Creates a git worktree in the sibling `worktrees/` directory, branching from `base_ref` (default `main`), and sets up GAIA's shared-state symlinks inside it. Prints the worktree path on stdout, which Claude Code waits for before starting the agent there. | `.gaia/scripts/create-worktree.sh` | + ## PreToolUse (Edit / Write / MultiEdit) | Hook | What it does | Path | From 6011ccc3345042df8c7836fe48b89bfc919ded08 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Thu, 25 Jun 2026 23:22:38 +0900 Subject: [PATCH 03/25] docs: frame spec-close as automatic, manual as backstop (gaia#438) Lead with the automatic disposition path (wiki-promote chain on immediate merge + step-3 housekeeping sweep) and name the two manual backstop cases concretely: drain a deferred wiki-promote, or pick delete/keep over the default archive. Confirms the /speckit-gaia-spec-close [SPEC-NNN] form resolved in gaia PR #438; no stray /gaia-spec close references remain. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/commands/spec.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/commands/spec.mdx b/src/content/docs/commands/spec.mdx index f66480a..b5278d0 100644 --- a/src/content/docs/commands/spec.mdx +++ b/src/content/docs/commands/spec.mdx @@ -104,7 +104,7 @@ Five GAIA hooks fire across the SPEC lifecycle. Never invoke them by hand. | `before_implement` | `/speckit-gaia-uat-write` | Renders frozen UATs into Playwright e2e specs at `.playwright/e2e//`, leaving a red-state harness before implementation begins. | | `after_implement` | `/speckit-gaia-wiki-promote` | Promotes merged-PR content into the project wiki under `wiki//`. Defers if the implementing PR has not merged yet. | -The chain-trigger to `/gaia-plan` lives inline at step 12 of the flow, not as a hook. Disposition of the SPEC artifact (archive, delete, or keep) happens through `/speckit-gaia-spec-close` after the implementing PR merges. It auto-fires from the `after_implement` wiki-promote step on the immediate-merge path, and is also invokable manually as `/speckit-gaia-spec-close [SPEC-NNN]` for the deferred path or retroactive cleanup. The SPEC ID is optional; omit it and the command surfaces every eligible SPEC to choose from. +The chain-trigger to `/gaia-plan` lives inline at step 12 of the flow, not as a hook. Disposition of the SPEC artifact (archive, delete, or keep) is automatic after the implementing PR merges: on the immediate-merge path the `after_implement` wiki-promote step chains to `/speckit-gaia-spec-close`, and the step-3 housekeeping passes archive any SPEC whose PR has since merged. Running `/speckit-gaia-spec-close [SPEC-NNN]` by hand is a backstop, for draining a deferred wiki-promote when the PR merges after implementation, or for choosing delete or keep instead of the default archive. The SPEC ID is optional; omit it and the command surfaces every eligible SPEC to choose from. ## Related From c8dc8e3ba901da7498887b76f72a24bb7a647368 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Thu, 25 Jun 2026 23:42:06 +0900 Subject: [PATCH 04/25] docs: sync gaia-init/setup-gaia-ci CI flow with gaia#439 gaia-init's init CI step is now local-only: it records CI intent and writes default_mode: local to .gaia/audit-ci.yml regardless of the answer, never prints a token/required-check recipe, never creates a gaia-forensics label, and never names or moves a workflow file. - gaia-init.mdx: rewrite step 5 to the new option labels ("Yes, I'll enable CI after pushing" / "No, local only"), defer token + GAIA-Audit required check + workflow install to /setup-gaia-ci. - setup-gaia-ci.mdx: document that step 7 registers GAIA-Audit as the required status check (admin + branch-protection needed; falls back to ci mode until registered), completing the deferred-install handoff. Verified clean, no change needed: forensics.mdx (files to upstream gaia-react/gaia, no local label), contributors/ci.mdx (forensics-triage.yml documented as contributor-only), setup-cloned-gaia-project.mdx (no forensics). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/getting-started/gaia-init.mdx | 10 ++++++---- src/content/docs/getting-started/setup-gaia-ci.mdx | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/content/docs/getting-started/gaia-init.mdx b/src/content/docs/getting-started/gaia-init.mdx index 11e5530..ca8a496 100644 --- a/src/content/docs/getting-started/gaia-init.mdx +++ b/src/content/docs/getting-started/gaia-init.mdx @@ -59,12 +59,14 @@ claude plugin install claude-obsidian@claude-obsidian-marketplace ### 5. CI integration -`/gaia-init` asks whether to enable GAIA's GitHub Actions CI now or defer it. GAIA's pre-merge audit gate can run in CI or locally. +`/gaia-init` records whether you plan to run GAIA's GitHub Actions CI and sets the local audit baseline. Nothing is installed on GitHub at this stage and no workflow files are added to the project; the actual install happens later via [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/), after your first push. -- **Enable now.** CI becomes the venue for the pre-merge `code-review-audit` gate. `/gaia-init` prints the `gh` commands you run yourself once the project is on GitHub: mint and store the bot token, then register the `GAIA-Audit` required check. After your first push, [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/) wires up the scheduled maintenance jobs and confirms CI is connected. -- **Skip.** Defers CI and sets the team audit default to `local` in `.gaia/audit-ci.yml`. The audit gate still holds, it just runs in your session at merge time instead of in CI. Re-enable anytime with [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/). +You answer one question: -Either way the audit gate is non-negotiable; the choice is only where it runs. See the [`code-review-audit` agent reference](/reference/agents/) for what the audit checks and how `default_mode` works. +- **Yes, I'll enable CI after pushing (recommended).** Records the intent. After your first push, [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/) installs the `code-review-audit` PR gate and any cron maintenance workflows, stores the bot token as a repo secret, and registers the `GAIA-Audit` required check. +- **No, local only.** GAIA's audit and maintenance tools run only when you invoke them on this machine. + +Either way, `/gaia-init` writes `default_mode: local` to `.gaia/audit-ci.yml` as the audit baseline: until CI is wired up, the local `code-review-audit` agent is the only producer of the `GAIA-Audit` stamp. If you enable CI later, `/setup-gaia-ci` updates the team default. The audit gate is non-negotiable; this choice is only about where it runs. See the [`code-review-audit` agent reference](/reference/agents/) for what the audit checks. ### 6. Adaptation feature opt-in diff --git a/src/content/docs/getting-started/setup-gaia-ci.mdx b/src/content/docs/getting-started/setup-gaia-ci.mdx index 6f91b8d..796a93f 100644 --- a/src/content/docs/getting-started/setup-gaia-ci.mdx +++ b/src/content/docs/getting-started/setup-gaia-ci.mdx @@ -69,6 +69,8 @@ Paste the token when prompted. It is piped directly to `gh secret set` and never The command generates `.github/workflows/gaia-ci-*.yml` from `.gaia/automation.json` and installs `.github/workflows/code-review-audit.yml`, the pre-merge audit gate. The audit gate installs unconditionally, even when no cron tool runs in CI mode. The command then triggers one `workflow_dispatch` run on the first generated workflow to confirm it boots correctly. +It also registers `GAIA-Audit` as a required status check on the default branch, so no PR can merge until the audit clears for that commit. This needs repo-admin access and an existing branch-protection rule; if either is missing, the command prints the `gh api` call to run yourself once you have admin rights, and the merge gate falls back to CI mode for every author until the check is registered. + If the verification run fails, you can retry, abandon (deletes the generated files, leaves `setup_complete: false`), or commit anyway if you have confirmed the failure is a transient infrastructure issue. ### 8. Commit and push From 6eeda32877260e1f1d84022ba799aebf646f7001 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 00:08:54 +0900 Subject: [PATCH 05/25] chore: bump astro 6.3.0 -> 7.0.2, starlight 0.39.1 -> 0.41.1 Re-applies the upgrade that was rolled back in #3. The earlier break was version skew: Starlight bundled @astrojs/mdx 5.0.6 (pre-6.4 markdown API), so astro 6.4 silently dropped GFM and every table rendered as raw pipe text (0 in the build). Starlight 0.41.1 now bundles @astrojs/mdx 7.0.0, which peer-depends on astro ^7.0.0, so the mdx version tracks astro again and GFM survives. Build is clean and produces the same 28
elements across 13 pages as the known-good baseline; no raw pipe-table leakage. Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 4 +- pnpm-lock.yaml | 1162 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 775 insertions(+), 391 deletions(-) diff --git a/package.json b/package.json index 2cd0c4f..76b1c83 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "astro": "astro" }, "dependencies": { - "@astrojs/starlight": "^0.39.1", - "astro": "^6.2.2", + "@astrojs/starlight": "^0.41.1", + "astro": "^7.0.2", "sharp": "^0.34.5" }, "pnpm": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62fae17..c7979e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,43 +9,115 @@ importers: .: dependencies: '@astrojs/starlight': - specifier: ^0.39.1 - version: 0.39.1(astro@6.3.0(@types/node@24.12.2)(rollup@4.60.3)) + specifier: ^0.41.1 + version: 0.41.1(@astrojs/markdown-remark@7.2.0)(astro@7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2)) astro: - specifier: ^6.2.2 - version: 6.3.0(@types/node@24.12.2)(rollup@4.60.3) + specifier: ^7.0.2 + version: 7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2) sharp: specifier: ^0.34.5 version: 0.34.5 packages: - '@astrojs/compiler@4.0.0': - resolution: {integrity: sha512-eouss7G8ygdZqHuke033VMcVw5HTZUu+PXd/h06DGDUg/jt5btPYPqh66ENWw/mU78rBrf/oeC4oqoBwMtDMNA==} + '@astrojs/compiler-binding-darwin-arm64@0.2.3': + resolution: {integrity: sha512-sJIHeL1ONXEBLob8ZaXfmX6iCftUno08G/cMXj2FJnL0xNbHuELcEq1mjxHVFHNgUYu4P7xJNm2mpc0zUEPoKw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@astrojs/compiler-binding-darwin-x64@0.2.3': + resolution: {integrity: sha512-P0NYu6aaIeLCqFfszxxBHL0a5WRaYigNVbDoO654Gi5Q2au5duDb5xZBv5EqUg4qnQVC173FXNvGZu1M7nk+/w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@astrojs/compiler-binding-linux-arm64-gnu@0.2.3': + resolution: {integrity: sha512-PqVN5AqhuDqfx3ejaerwrC8codpV9jnyKV+IOel027qsJ1anFUJLdjUlY8VVys0xgd8lmqveX11OkcaQj/otTg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] - '@astrojs/internal-helpers@0.9.0': - resolution: {integrity: sha512-GdYkzR26re8izmyYlBqf4z2s7zNngmWLFuxw0UKiPNqHraZGS6GKWIwSHgS22RDlu2ePFJ8bzmpBcUszut/SDg==} + '@astrojs/compiler-binding-linux-arm64-musl@0.2.3': + resolution: {integrity: sha512-O3e2CbN4yTsRguWYNnRd0p5YQ0H3fb7KpcR0W4R319q/gq5B1pJ7eqNbiO3b8g2AuiEcRTiUz5jeGT9j69cxOQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] - '@astrojs/markdown-remark@7.1.1': - resolution: {integrity: sha512-C6e9BnLGlbdv6bV8MYGeHpHxsUHrCrB4OuRLqi5LI7oiBVcBcqfUN06zpwFQdHgV48QCCrMmLpyqBr7VqC+swA==} + '@astrojs/compiler-binding-linux-x64-gnu@0.2.3': + resolution: {integrity: sha512-hbLBjXVp+96psMe7/7uqyrquGiULXANrq6REVxxPK/I5VzebZ7LHmSfykmByUbLyR1u+K6CTBKgvdQsK2L+2Xw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] - '@astrojs/mdx@5.0.4': - resolution: {integrity: sha512-tSbuuYueNODiFAFaME7pjHY5lOLoxBYJi1cKd6scw9+a4ZO7C7UGdafEoVAQvOV2eO8a6RaHSAJYGVPL1w8BPA==} + '@astrojs/compiler-binding-linux-x64-musl@0.2.3': + resolution: {integrity: sha512-vIiEvOwrJfHZMaTmqUCrFTIwMYL0+PD3Rvy7kFDQgERyx3zhaw8CPa01MCCqa+/sj344BGrXKZ6ti37SgNLMhw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@astrojs/compiler-binding-wasm32-wasi@0.2.3': + resolution: {integrity: sha512-p9S2X8z/mUR2SMzAVJRFMCt8YaalKR+pjl2DgpdjzCQc6ww4bo8kiy54tgKqxZeNF5c+/2tCDTQIxVSm9V1FsA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@astrojs/compiler-binding-win32-arm64-msvc@0.2.3': + resolution: {integrity: sha512-vcCG6JttIb5vbSmcxO2O398hpVj7lQ349iS7cjgYP6ZuLVEnw+9qPAr2MM2kJkU5wEGZqJ2gyi/M7UJoPwH1iQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@astrojs/compiler-binding-win32-x64-msvc@0.2.3': + resolution: {integrity: sha512-hKssjNvC36e00Inb1GW1JsVyCFSCGnIjKem4S8q0VIW6cpWAUpvYB4qQU2HIDGD6SDX0ork4F5sWkNWkp2hrGQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@astrojs/compiler-binding@0.2.3': + resolution: {integrity: sha512-Xz3iBNse+hXXD25IXxsuXEt2ai8klAWE15CRm/EQBc9+aE3jXaF07DZx+iakk3HC6NHvWlEPzLPyxsLgPzOJsw==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@astrojs/compiler-rs@0.2.3': + resolution: {integrity: sha512-JRAtRcPxS4JeAZEIQFQ6GecBs/Wyp4m6/E8vBNxSgVfo1AtRVLUqRCl5oCGOZ0X/BSBB3Vef/7IlzyiGKi2ORA==} + + '@astrojs/internal-helpers@0.10.0': + resolution: {integrity: sha512-Ry2R3VPeIN4uPCSA4xQc+e+vsJXkalKpEbDc07hV+a/o5Bs2N/s/uDcPJH/05L19DKh9tAy7e6JM3YZ6Cxfezw==} + + '@astrojs/markdown-remark@7.2.0': + resolution: {integrity: sha512-+YxmVQu1Bd+MFfSzjq1rOJvD9+nIOJzz5YIIhdIH01RrxRkKbyKoEgyIqP3yv51MhzMDgd79QaPv+kCVPT8vHw==} + + '@astrojs/markdown-satteri@0.3.2': + resolution: {integrity: sha512-feXuUPy41gVfeM7EHT1ciUim8ozGr+YHXab9uUBc1Hk8y60DQosO8ldL+AoPXnCAoGj1OChwHfvXmmJ6XVnY9A==} + + '@astrojs/mdx@7.0.0': + resolution: {integrity: sha512-LKwNA8nnLtEM0auoP6OfH/UnlKe1Ub59qZjbcYkZjPBGw6PkJewWkA/1qwLpECvV6gMDd6TR6eqV9p/VYZrcrQ==} engines: {node: '>=22.12.0'} peerDependencies: - astro: ^6.0.0 + '@astrojs/markdown-satteri': ^0.3.1-alpha.0 + astro: ^7.0.0-alpha.0 + peerDependenciesMeta: + '@astrojs/markdown-satteri': + optional: true - '@astrojs/prism@4.0.1': - resolution: {integrity: sha512-nksZQVjlferuWzhPsBpQ1JE5XuKAf1id1/9Hj4a9KG4+ofrlzxUUwX4YGQF/SuDiuiGKEnzopGOt38F3AnVWsQ==} + '@astrojs/prism@4.0.2': + resolution: {integrity: sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==} engines: {node: '>=22.12.0'} '@astrojs/sitemap@3.7.2': resolution: {integrity: sha512-PqkzkcZTb5ICiyIR8VoKbIAP/laNRXi5tw616N1Ckk+40oNB8Can1AzVV56lrbC5GKSZFCyJYUVYqVivMisvpA==} - '@astrojs/starlight@0.39.1': - resolution: {integrity: sha512-9kIAXBwcqAuFQ7Ft419fr6rz6p0SPg7Yfgc28TfzoCcuOH9utZgIola9yOq5YIMDrR8rmm8kyl7pCsfrPVmLhQ==} + '@astrojs/starlight@0.41.1': + resolution: {integrity: sha512-avf2OmrVg6GdVU18juebjjIIuLa+uS3syHuJ/3yDaEFP/8it+YvcxRrYDSf7K6rC4v770UxIddba2hAqQyTeYA==} peerDependencies: - astro: ^6.0.0 + '@astrojs/markdown-remark': ^7.2.0 + astro: ^7.0.2 + peerDependenciesMeta: + '@astrojs/markdown-remark': + optional: true '@astrojs/telemetry@3.3.2': resolution: {integrity: sha512-j8DNruA8ors99Al39RYZPJK4DC1bKkoNm93mAMuBhY9TCNC4R8n1q7ovFnJ5qhGh5Lsh7pa1gpQVpYpsJPeTHQ==} @@ -68,6 +140,55 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@bruits/satteri-darwin-arm64@0.9.2': + resolution: {integrity: sha512-tRpKRsiWxyh+Q5cjLwqj+baqI9htIcKqpDcftygA08bB/4nocZsneq+CVLmqT1/njG2Gq+ET12JHECz52ybiPQ==} + cpu: [arm64] + os: [darwin] + + '@bruits/satteri-darwin-x64@0.9.2': + resolution: {integrity: sha512-oLSI0+Upq3Nd1brOdRSl044TMKgy7S6cF4sM7a9/Ms6/IADvuey+9yG3GBXxLGAzSYzR0/hh7PPSP1QBfsBKwA==} + cpu: [x64] + os: [darwin] + + '@bruits/satteri-linux-arm64-gnu@0.9.2': + resolution: {integrity: sha512-G+G6uYscRc4VUTNgZgS6SSfTHh04q/d5WiH66Jg39eftMzTAsT5cLSEHDTvDpleUT6BMNHdunx927WbddDgw7A==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@bruits/satteri-linux-arm64-musl@0.9.2': + resolution: {integrity: sha512-wRaKSHCRXwzAZwlieCiv3u8pWEE2t9FmhZ0X59YZvHCGin56YUBOTyEQqSOrRfXs6fhUb8ylprisGYJC6J8mFQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@bruits/satteri-linux-x64-gnu@0.9.2': + resolution: {integrity: sha512-hxEq3g/kS3tm3GKc2aRYnLMFI5IjxYzcd2sCwEH2C0V+m9TTAf+7Snt/+AZZklpxDOBrI+zthJHip9xnk9uM3g==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@bruits/satteri-linux-x64-musl@0.9.2': + resolution: {integrity: sha512-ZSu+a07Efn8sOeA1k9ZM9CO9J3sAeG37Sf2YYxi/unFGgkFe+Y8MHDQlUNtngpC8pkYIjkojkLFT6v1yiHNxOg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@bruits/satteri-wasm32-wasi@0.9.2': + resolution: {integrity: sha512-Q/d7OIwXb5UGaiKUuPp2E6Bm41xD3sW8ts5L6l2m0Wi9uu9WKsv7CDc1ge6AVd6OC6g4nlSKWECFfPa7MkJchg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@bruits/satteri-win32-arm64-msvc@0.9.2': + resolution: {integrity: sha512-QeaVjw+2IZeDRU7dU0KFlECTAwbL4fRUIXxZYQc4a16ejPzwizChEsKzoUBduyOJSDjyzvZxAmcdUYsSOUmR9A==} + cpu: [arm64] + os: [win32] + + '@bruits/satteri-win32-x64-msvc@0.9.2': + resolution: {integrity: sha512-+hVrOLFtGgXakKO38F6afcc9/uuWvRGghPmiA6/ez5XGnWaM9VjQxqvogam5aOa7Nvl4V65P8Vpj5RsLzYeO8g==} + cpu: [x64] + os: [win32] + '@capsizecss/unpack@4.0.0': resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==} engines: {node: '>=18'} @@ -84,176 +205,185 @@ packages: resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} engines: {node: '>=14'} + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@esbuild/aix-ppc64@0.27.7': - resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@esbuild/aix-ppc64@0.28.1': + resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.27.7': - resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + '@esbuild/android-arm64@0.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.27.7': - resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.27.7': - resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + '@esbuild/android-x64@0.28.1': + resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.27.7': - resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + '@esbuild/darwin-arm64@0.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.27.7': - resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.27.7': - resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + '@esbuild/freebsd-arm64@0.28.1': + resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.7': - resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + '@esbuild/freebsd-x64@0.28.1': + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.27.7': - resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.27.7': - resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + '@esbuild/linux-arm@0.28.1': + resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.27.7': - resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + '@esbuild/linux-ia32@0.28.1': + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.27.7': - resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + '@esbuild/linux-loong64@0.28.1': + resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.27.7': - resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + '@esbuild/linux-mips64el@0.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.27.7': - resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + '@esbuild/linux-ppc64@0.28.1': + resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.27.7': - resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + '@esbuild/linux-riscv64@0.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.27.7': - resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + '@esbuild/linux-s390x@0.28.1': + resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.27.7': - resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + '@esbuild/linux-x64@0.28.1': + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.27.7': - resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.7': - resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.27.7': - resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.7': - resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + '@esbuild/openbsd-x64@0.28.1': + resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.27.7': - resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + '@esbuild/openharmony-arm64@0.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.27.7': - resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.27.7': - resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.27.7': - resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + '@esbuild/win32-ia32@0.28.1': + resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.27.7': - resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + '@esbuild/win32-x64@0.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@expressive-code/core@0.42.0': - resolution: {integrity: sha512-MN11+9nfmaC7sYu2BZJXAXqwkBRt8t1xTSqP+Ti1NfTEskgl6xUnzDxoaiQkg0BMzpglA0pys4dpDKquP/cyIw==} + '@expressive-code/core@0.44.0': + resolution: {integrity: sha512-xgiF2P6tYUbrhi3+x0S8xHZWT1t3Bvb3U91tAtRbLb9HLejLvYc5GZUqKICKLaUN4iSGhhNJu2fM/aH8e5yCMg==} - '@expressive-code/plugin-frames@0.42.0': - resolution: {integrity: sha512-XtkPm+941Uta7Y+81Acv+OA/20F1NJmJhCX6UYGKpqEIGqplNh3PTOhcURp6tcruhlzJcWcvpWy6Oigz3SrjqA==} + '@expressive-code/plugin-frames@0.44.0': + resolution: {integrity: sha512-V6M6+zVc1GzqCvXkQHc2m5rcFOIVzJgMq5gnfrMnVf2gwtj/sg4H93c1f/mGeqHycubwkHFUDyParAOiGeDZeA==} - '@expressive-code/plugin-shiki@0.42.0': - resolution: {integrity: sha512-PMKey/kLmewttAHQezL+Y5Fx3vVssfDi3+FJOYQQS2mXP3tQspFELtKKAfsXfmSXdToZYgwoO69HJndqfE+09g==} + '@expressive-code/plugin-shiki@0.44.0': + resolution: {integrity: sha512-RZsdaqlbGqyAQKuoX4myQXxjmiE2l5KBpJ/gKPh62tCdIdpWyjbzVqSo8+5XsezZxkfi8AJ/J6EUaBTPROFX/Q==} - '@expressive-code/plugin-text-markers@0.42.0': - resolution: {integrity: sha512-l59lUx8fq1v5g6SpmbDjiU0+7IdfbiWnAyRmtTVSpfhyq+nZMN4UcmYyu2b9Mynhzt7Gr+O+cXyEPDNb2AVWVQ==} + '@expressive-code/plugin-text-markers@0.44.0': + resolution: {integrity: sha512-0/m3A5b+lz2upyNq+wzZ1S69HRoJmyFs5LsR42lVZ9pmGRlBiSBYQpvqlji4DBj1+Riamxc0AvcCr5kuzOQeWA==} '@img/colour@1.1.0': resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} @@ -414,9 +544,18 @@ packages: '@mdx-js/mdx@3.1.1': resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + '@oxc-project/types@0.137.0': + resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} + '@pagefind/darwin-arm64@1.5.2': resolution: {integrity: sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ==} cpu: [arm64] @@ -455,152 +594,112 @@ packages: cpu: [x64] os: [win32] - '@rollup/pluginutils@5.3.0': - resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/rollup-android-arm-eabi@4.60.3': - resolution: {integrity: sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.60.3': - resolution: {integrity: sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==} + '@rolldown/binding-android-arm64@1.1.3': + resolution: {integrity: sha512-DT6Z3PhvioeHMvxo+xHc3KtqggrI7CCTXCmC2h/5zUlp5jVitv7XEy+9q5/7v8IolhlioawpMo8Kg0EEBy7J0g==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.60.3': - resolution: {integrity: sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==} + '@rolldown/binding-darwin-arm64@1.1.3': + resolution: {integrity: sha512-0NwgwsjM7LrsuVnXMK3koTpagBNOhloc/BNjKqZjv4V5zI5r13qx69uVhRx+o5Z0yy4Hzq+lpy7TAgUG/ocvrw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.60.3': - resolution: {integrity: sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==} + '@rolldown/binding-darwin-x64@1.1.3': + resolution: {integrity: sha512-YtiBp4disu6V560loT6PjMdiRaWmVvDNrUunAalbiFx2ggeJwxdAsgZMcoGP17uyAsTwAj5V1niksxlHnVQ1Sw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.60.3': - resolution: {integrity: sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.60.3': - resolution: {integrity: sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==} + '@rolldown/binding-freebsd-x64@1.1.3': + resolution: {integrity: sha512-yD3EkEdXk2LypPxnf/kSZHirarsI8gcPzc62SukhR9VJTyvV+F9Q/GxWNuCojc7sXyuVC4DxRGhdDK4X8VSsbw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.60.3': - resolution: {integrity: sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.60.3': - resolution: {integrity: sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.3': + resolution: {integrity: sha512-c+8vieQbsD7HNAHKIA34w0GJ9FedFFuJGD+7E6vz7Q3uqAIugL5p45fhlsj4UaAsHpcmlqugBWMhA0/j7o0sIg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.60.3': - resolution: {integrity: sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==} + '@rolldown/binding-linux-arm64-gnu@1.1.3': + resolution: {integrity: sha512-50jD0uUwLvur7Zz9LHz17kaAdTPjn5wN93hEgjvmYFRZwiR7ZJYovTd5ipyWJDAnXKvZ+wgc+/Ika6dwSF5OcA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.60.3': - resolution: {integrity: sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==} + '@rolldown/binding-linux-arm64-musl@1.1.3': + resolution: {integrity: sha512-BO9+oPL8K9poZJBfYPsXNtYjPE5uM3qeehT3aFcW4LITOl+iSqhp0abzjR2nWBUNjIZeKXjAEWBZ64WjNoHd6w==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.60.3': - resolution: {integrity: sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.60.3': - resolution: {integrity: sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.60.3': - resolution: {integrity: sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.60.3': - resolution: {integrity: sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==} + '@rolldown/binding-linux-ppc64-gnu@1.1.3': + resolution: {integrity: sha512-f3VpLB1vQ0Eo6ecr/6cekLnvYMFF4YBFoVGkfkvPLq1bAkbAwHYQPZKoAmG6OJyTcxxoC+AvezGx/S1obNC0Mw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.60.3': - resolution: {integrity: sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==} - cpu: [riscv64] - os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.60.3': - resolution: {integrity: sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.60.3': - resolution: {integrity: sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==} + '@rolldown/binding-linux-s390x-gnu@1.1.3': + resolution: {integrity: sha512-AmurZ26Pqx/RI9N1gzEOCklkKXl927yjfXWUUS0O7Puh8ARM/Ob8qfrD3qnWksScdw6cSrW5PSHE9DyLu7+PtA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.60.3': - resolution: {integrity: sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==} + '@rolldown/binding-linux-x64-gnu@1.1.3': + resolution: {integrity: sha512-JJpqs8bRGITDOdbkNKnlojzBabbOHrqjSvDr0IVsZObE1lBcPjxItUEY9eWIDbxaJ3cGrXPWGfGkIxFijg/URg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.60.3': - resolution: {integrity: sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==} + '@rolldown/binding-linux-x64-musl@1.1.3': + resolution: {integrity: sha512-rSJcdjPxzA/by/6/rYs+v+bXU7UjvnbUWz8MJb6kh6+knqB1dCrtHg0uu7C/4haqJvqdkYHQ5IGn+tCH9GLW/g==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.60.3': - resolution: {integrity: sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.60.3': - resolution: {integrity: sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==} + '@rolldown/binding-openharmony-arm64@1.1.3': + resolution: {integrity: sha512-hQ3/PYkDJICgevvyNcVrihVeqq7k1Pp3VZ9lY+dauAYUJKO+auqApvANhvR1An9BhmqYKvW2Mu1F9u4DXSMLxQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.60.3': - resolution: {integrity: sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==} - cpu: [arm64] - os: [win32] + '@rolldown/binding-wasm32-wasi@1.1.3': + resolution: {integrity: sha512-Elcv/BtML9lXrV6JuKITc/grN2kYV9gjsQpW8Jfw4ioK0TOkjBjye0nnyqQNy9STNaI20lXNaQBRrD5gSgR0Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] - '@rollup/rollup-win32-ia32-msvc@4.60.3': - resolution: {integrity: sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==} - cpu: [ia32] + '@rolldown/binding-win32-arm64-msvc@1.1.3': + resolution: {integrity: sha512-2DrEfhluH9yhiaFApmsjsjwrSYbNcY1oFTzYSP1a535jDbV98zCFanA/96TBUd0iDFcxGmw9QRExwGCXz3U+/g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.60.3': - resolution: {integrity: sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==} + '@rolldown/binding-win32-x64-msvc@1.1.3': + resolution: {integrity: sha512-OL4OMk7UPXOeVGGd3qo5zJyPIljf4AFgk5QAkPPS+OoLuOOozhuaQGC18MxVTnw/06q93gShAJzlwnSCY9YtqA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.60.3': - resolution: {integrity: sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==} - cpu: [x64] - os: [win32] + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true '@shikijs/core@4.0.2': resolution: {integrity: sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw==} @@ -633,15 +732,15 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} @@ -688,6 +787,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + am-i-vibing@0.4.0: + resolution: {integrity: sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==} + hasBin: true + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -709,15 +812,20 @@ packages: resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} hasBin: true - astro-expressive-code@0.42.0: - resolution: {integrity: sha512-aiTePi2Cn0mJPYWZSzP1GcxCinX9mNtJyCCshVVPSg1yRwM7ADvFJOx0FnS440M9t65hp8JH//dc2qr22Bm4ag==} + astro-expressive-code@0.44.0: + resolution: {integrity: sha512-b1wN/ZvbJprzxlGKIpIes2kQrCY5KRLwys2tWbZAZyjGZcW5ZtgneZnBwzNRiBna9/48d4mQl19KLjcRuhO1hw==} peerDependencies: - astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta + astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta || ^7.0.0 - astro@6.3.0: - resolution: {integrity: sha512-yhDelVblNzQE4mjS0s27T9BZuAlfRCy+qHk6IlMgSr+ADG5QNpyPkroJAVCFRH08Nf2VhDM5dz6n4GWiTB9TlQ==} + astro@7.0.2: + resolution: {integrity: sha512-Rj31HS85pVSfiQTxKTwH6vTmF8y57iRfkgb1uiCTtdLIh3jlUKPAPXtEmHXRKp/PdTS00D4EXYlWXypY+AVVCA==} engines: {node: '>=22.12.0', npm: '>=9.6.5', pnpm: '>=7.1.0'} hasBin: true + peerDependencies: + '@astrojs/markdown-remark': 7.2.0 + peerDependenciesMeta: + '@astrojs/markdown-remark': + optional: true axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} @@ -839,8 +947,8 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - devalue@5.8.0: - resolution: {integrity: sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==} + devalue@5.8.1: + resolution: {integrity: sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==} devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -887,8 +995,8 @@ packages: esast-util-from-js@2.0.1: resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} - esbuild@0.27.7: - resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + esbuild@0.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} engines: {node: '>=18'} hasBin: true @@ -923,8 +1031,8 @@ packages: eventemitter3@5.0.4: resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} - expressive-code@0.42.0: - resolution: {integrity: sha512-V5DtJLEKuj4wf9O6IRtPtRObkMVy2ggR+S0MdjrTw6m58krZnDioyhW1si3Y04c5YPeooP4nd85Yq9NwEVHS4g==} + expressive-code@0.44.0: + resolution: {integrity: sha512-JXVWVNCKlLuZLMQH8cOiDUSosT0Bb+elwE/dbAkpwFwDFmyFyWlECoWZIohh2FkIF1iI67TQJ+Ts9k7oNDh2qA==} extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -1105,6 +1213,80 @@ packages: resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} engines: {node: '>= 8'} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -1396,10 +1578,18 @@ packages: resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + engines: {node: ^10 || ^12 || >=14} + prismjs@1.30.0: resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} engines: {node: '>=6'} + process-ancestry@0.1.0: + resolution: {integrity: sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==} + engines: {node: '>=18.0.0'} + property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} @@ -1433,8 +1623,8 @@ packages: regex@6.1.0: resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} - rehype-expressive-code@0.42.0: - resolution: {integrity: sha512-8rp/1YMEVVSYbtz+bFBx+uSx3vA4i4T8RwRm5Q/IWbucQnnQqQ0hDqtmKOr8tv+59Cik6cu5aH3WPo0I7csuTA==} + rehype-expressive-code@0.44.0: + resolution: {integrity: sha512-5r74C5F2sMR3X+QJH8OKWgZBO/cqRw5W1fLT6GVlSfLqepk+4j8tGFkyPqZYWjwntsBHzKPDH2zI68sZ7ScLfA==} rehype-format@5.0.1: resolution: {integrity: sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==} @@ -1491,11 +1681,14 @@ packages: retext@9.0.0: resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} - rollup@4.60.3: - resolution: {integrity: sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} + rolldown@1.1.3: + resolution: {integrity: sha512-1F1eEtUBtFvcGm1HQ9TiUIUHPQG7mSAODrhIzjxoUEFuo8OcbrGLiVLkevNgj84TE4lnHvnumwFjhJO5Eu135g==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + satteri@0.9.2: + resolution: {integrity: sha512-IDJTE5SzEg9PqtdZEToQ3bjlfQ/zM+/HNaBFrwPdZbtk9IL1RWVFvzR8EMIrC0JYybJNKZS8FL45GNSAMX/6Xg==} + sax@1.6.0: resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} engines: {node: '>=11.0.0'} @@ -1568,6 +1761,10 @@ packages: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -1687,6 +1884,10 @@ packages: uploadthing: optional: true + url-extras@0.1.0: + resolution: {integrity: sha512-8tzwTeXFPuX/5PHuCDQE5Dd9Ts4rwoq2t9aIT+HS4iAVpmj5l4Ao7Q+BuuFjvWRqrLswBhQDk8O96ZicgCqQqw==} + engines: {node: '>=20'} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1699,15 +1900,16 @@ packages: vfile@6.0.3: resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - vite@7.3.3: - resolution: {integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==} + vite@8.1.0: + resolution: {integrity: sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 - lightningcss: ^1.21.0 sass: ^1.70.0 sass-embedded: ^1.70.0 stylus: '>=0.54.8' @@ -1718,12 +1920,14 @@ packages: peerDependenciesMeta: '@types/node': optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true jiti: optional: true less: optional: true - lightningcss: - optional: true sass: optional: true sass-embedded: @@ -1773,20 +1977,78 @@ packages: snapshots: - '@astrojs/compiler@4.0.0': {} + '@astrojs/compiler-binding-darwin-arm64@0.2.3': + optional: true + + '@astrojs/compiler-binding-darwin-x64@0.2.3': + optional: true + + '@astrojs/compiler-binding-linux-arm64-gnu@0.2.3': + optional: true + + '@astrojs/compiler-binding-linux-arm64-musl@0.2.3': + optional: true + + '@astrojs/compiler-binding-linux-x64-gnu@0.2.3': + optional: true + + '@astrojs/compiler-binding-linux-x64-musl@0.2.3': + optional: true + + '@astrojs/compiler-binding-wasm32-wasi@0.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + + '@astrojs/compiler-binding-win32-arm64-msvc@0.2.3': + optional: true + + '@astrojs/compiler-binding-win32-x64-msvc@0.2.3': + optional: true + + '@astrojs/compiler-binding@0.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + optionalDependencies: + '@astrojs/compiler-binding-darwin-arm64': 0.2.3 + '@astrojs/compiler-binding-darwin-x64': 0.2.3 + '@astrojs/compiler-binding-linux-arm64-gnu': 0.2.3 + '@astrojs/compiler-binding-linux-arm64-musl': 0.2.3 + '@astrojs/compiler-binding-linux-x64-gnu': 0.2.3 + '@astrojs/compiler-binding-linux-x64-musl': 0.2.3 + '@astrojs/compiler-binding-wasm32-wasi': 0.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@astrojs/compiler-binding-win32-arm64-msvc': 0.2.3 + '@astrojs/compiler-binding-win32-x64-msvc': 0.2.3 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + '@astrojs/compiler-rs@0.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@astrojs/compiler-binding': 0.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' - '@astrojs/internal-helpers@0.9.0': + '@astrojs/internal-helpers@0.10.0': dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + js-yaml: 4.1.1 picomatch: 4.0.4 + retext-smartypants: 6.2.0 + shiki: 4.0.2 + smol-toml: 1.6.1 + unified: 11.0.5 - '@astrojs/markdown-remark@7.1.1': + '@astrojs/markdown-remark@7.2.0': dependencies: - '@astrojs/internal-helpers': 0.9.0 - '@astrojs/prism': 4.0.1 + '@astrojs/internal-helpers': 0.10.0 + '@astrojs/prism': 4.0.2 github-slugger: 2.0.0 hast-util-from-html: 2.0.3 hast-util-to-text: 4.0.2 - js-yaml: 4.1.1 mdast-util-definitions: 6.0.0 rehype-raw: 7.0.0 rehype-stringify: 10.0.1 @@ -1794,9 +2056,6 @@ snapshots: remark-parse: 11.0.0 remark-rehype: 11.1.2 remark-smartypants: 3.0.2 - retext-smartypants: 6.2.0 - shiki: 4.0.2 - smol-toml: 1.6.1 unified: 11.0.5 unist-util-remove-position: 5.0.0 unist-util-visit: 5.1.0 @@ -1805,12 +2064,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@5.0.4(astro@6.3.0(@types/node@24.12.2)(rollup@4.60.3))': + '@astrojs/markdown-satteri@0.3.2': + dependencies: + '@astrojs/internal-helpers': 0.10.0 + '@astrojs/prism': 4.0.2 + github-slugger: 2.0.0 + satteri: 0.9.2 + + '@astrojs/mdx@7.0.0(@astrojs/markdown-satteri@0.3.2)(astro@7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2))': dependencies: - '@astrojs/markdown-remark': 7.1.1 + '@astrojs/internal-helpers': 0.10.0 + '@astrojs/markdown-remark': 7.2.0 '@mdx-js/mdx': 3.1.1 acorn: 8.16.0 - astro: 6.3.0(@types/node@24.12.2)(rollup@4.60.3) + astro: 7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2) es-module-lexer: 2.1.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.5 @@ -1821,10 +2088,12 @@ snapshots: source-map: 0.7.6 unist-util-visit: 5.1.0 vfile: 6.0.3 + optionalDependencies: + '@astrojs/markdown-satteri': 0.3.2 transitivePeerDependencies: - supports-color - '@astrojs/prism@4.0.1': + '@astrojs/prism@4.0.2': dependencies: prismjs: 1.30.0 @@ -1834,17 +2103,17 @@ snapshots: stream-replace-string: 2.0.0 zod: 4.4.3 - '@astrojs/starlight@0.39.1(astro@6.3.0(@types/node@24.12.2)(rollup@4.60.3))': + '@astrojs/starlight@0.41.1(@astrojs/markdown-remark@7.2.0)(astro@7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2))': dependencies: - '@astrojs/markdown-remark': 7.1.1 - '@astrojs/mdx': 5.0.4(astro@6.3.0(@types/node@24.12.2)(rollup@4.60.3)) + '@astrojs/markdown-satteri': 0.3.2 + '@astrojs/mdx': 7.0.0(@astrojs/markdown-satteri@0.3.2)(astro@7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2)) '@astrojs/sitemap': 3.7.2 '@pagefind/default-ui': 1.5.2 '@types/hast': 3.0.4 '@types/js-yaml': 4.0.9 '@types/mdast': 4.0.4 - astro: 6.3.0(@types/node@24.12.2)(rollup@4.60.3) - astro-expressive-code: 0.42.0(astro@6.3.0(@types/node@24.12.2)(rollup@4.60.3)) + astro: 7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2) + astro-expressive-code: 0.44.0(astro@7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2)) bcp-47: 2.1.0 hast-util-from-html: 2.0.3 hast-util-select: 6.0.4 @@ -1861,10 +2130,13 @@ snapshots: rehype: 13.0.2 rehype-format: 5.0.1 remark-directive: 4.0.0 + satteri: 0.9.2 ultrahtml: 1.6.0 unified: 11.0.5 unist-util-visit: 5.1.0 vfile: 6.0.3 + optionalDependencies: + '@astrojs/markdown-remark': 7.2.0 transitivePeerDependencies: - supports-color - typescript @@ -1890,6 +2162,37 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@bruits/satteri-darwin-arm64@0.9.2': + optional: true + + '@bruits/satteri-darwin-x64@0.9.2': + optional: true + + '@bruits/satteri-linux-arm64-gnu@0.9.2': + optional: true + + '@bruits/satteri-linux-arm64-musl@0.9.2': + optional: true + + '@bruits/satteri-linux-x64-gnu@0.9.2': + optional: true + + '@bruits/satteri-linux-x64-musl@0.9.2': + optional: true + + '@bruits/satteri-wasm32-wasi@0.9.2': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@bruits/satteri-win32-arm64-msvc@0.9.2': + optional: true + + '@bruits/satteri-win32-x64-msvc@0.9.2': + optional: true + '@capsizecss/unpack@4.0.0': dependencies: fontkitten: 1.0.3 @@ -1908,90 +2211,106 @@ snapshots: '@ctrl/tinycolor@4.2.0': {} + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.27.7': + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/android-arm64@0.27.7': + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/android-arm@0.27.7': + '@esbuild/aix-ppc64@0.28.1': optional: true - '@esbuild/android-x64@0.27.7': + '@esbuild/android-arm64@0.28.1': optional: true - '@esbuild/darwin-arm64@0.27.7': + '@esbuild/android-arm@0.28.1': optional: true - '@esbuild/darwin-x64@0.27.7': + '@esbuild/android-x64@0.28.1': optional: true - '@esbuild/freebsd-arm64@0.27.7': + '@esbuild/darwin-arm64@0.28.1': optional: true - '@esbuild/freebsd-x64@0.27.7': + '@esbuild/darwin-x64@0.28.1': optional: true - '@esbuild/linux-arm64@0.27.7': + '@esbuild/freebsd-arm64@0.28.1': optional: true - '@esbuild/linux-arm@0.27.7': + '@esbuild/freebsd-x64@0.28.1': optional: true - '@esbuild/linux-ia32@0.27.7': + '@esbuild/linux-arm64@0.28.1': optional: true - '@esbuild/linux-loong64@0.27.7': + '@esbuild/linux-arm@0.28.1': optional: true - '@esbuild/linux-mips64el@0.27.7': + '@esbuild/linux-ia32@0.28.1': optional: true - '@esbuild/linux-ppc64@0.27.7': + '@esbuild/linux-loong64@0.28.1': optional: true - '@esbuild/linux-riscv64@0.27.7': + '@esbuild/linux-mips64el@0.28.1': optional: true - '@esbuild/linux-s390x@0.27.7': + '@esbuild/linux-ppc64@0.28.1': optional: true - '@esbuild/linux-x64@0.27.7': + '@esbuild/linux-riscv64@0.28.1': optional: true - '@esbuild/netbsd-arm64@0.27.7': + '@esbuild/linux-s390x@0.28.1': optional: true - '@esbuild/netbsd-x64@0.27.7': + '@esbuild/linux-x64@0.28.1': optional: true - '@esbuild/openbsd-arm64@0.27.7': + '@esbuild/netbsd-arm64@0.28.1': optional: true - '@esbuild/openbsd-x64@0.27.7': + '@esbuild/netbsd-x64@0.28.1': optional: true - '@esbuild/openharmony-arm64@0.27.7': + '@esbuild/openbsd-arm64@0.28.1': optional: true - '@esbuild/sunos-x64@0.27.7': + '@esbuild/openbsd-x64@0.28.1': optional: true - '@esbuild/win32-arm64@0.27.7': + '@esbuild/openharmony-arm64@0.28.1': optional: true - '@esbuild/win32-ia32@0.27.7': + '@esbuild/sunos-x64@0.28.1': optional: true - '@esbuild/win32-x64@0.27.7': + '@esbuild/win32-arm64@0.28.1': optional: true - '@expressive-code/core@0.42.0': + '@esbuild/win32-ia32@0.28.1': + optional: true + + '@esbuild/win32-x64@0.28.1': + optional: true + + '@expressive-code/core@0.44.0': dependencies: '@ctrl/tinycolor': 4.2.0 hast-util-select: 6.0.4 @@ -2003,18 +2322,18 @@ snapshots: unist-util-visit: 5.1.0 unist-util-visit-parents: 6.0.2 - '@expressive-code/plugin-frames@0.42.0': + '@expressive-code/plugin-frames@0.44.0': dependencies: - '@expressive-code/core': 0.42.0 + '@expressive-code/core': 0.44.0 - '@expressive-code/plugin-shiki@0.42.0': + '@expressive-code/plugin-shiki@0.44.0': dependencies: - '@expressive-code/core': 0.42.0 + '@expressive-code/core': 0.44.0 shiki: 4.0.2 - '@expressive-code/plugin-text-markers@0.42.0': + '@expressive-code/plugin-text-markers@0.44.0': dependencies: - '@expressive-code/core': 0.42.0 + '@expressive-code/core': 0.44.0 '@img/colour@1.1.0': {} @@ -2144,8 +2463,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + '@oslojs/encoding@1.1.0': {} + '@oxc-project/types@0.137.0': {} + '@pagefind/darwin-arm64@1.5.2': optional: true @@ -2169,88 +2497,62 @@ snapshots: '@pagefind/windows-x64@1.5.2': optional: true - '@rollup/pluginutils@5.3.0(rollup@4.60.3)': - dependencies: - '@types/estree': 1.0.9 - estree-walker: 2.0.2 - picomatch: 4.0.4 - optionalDependencies: - rollup: 4.60.3 - - '@rollup/rollup-android-arm-eabi@4.60.3': - optional: true - - '@rollup/rollup-android-arm64@4.60.3': - optional: true - - '@rollup/rollup-darwin-arm64@4.60.3': - optional: true - - '@rollup/rollup-darwin-x64@4.60.3': - optional: true - - '@rollup/rollup-freebsd-arm64@4.60.3': - optional: true - - '@rollup/rollup-freebsd-x64@4.60.3': + '@rolldown/binding-android-arm64@1.1.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.60.3': + '@rolldown/binding-darwin-arm64@1.1.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.60.3': + '@rolldown/binding-darwin-x64@1.1.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.60.3': + '@rolldown/binding-freebsd-x64@1.1.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.60.3': + '@rolldown/binding-linux-arm-gnueabihf@1.1.3': optional: true - '@rollup/rollup-linux-loong64-gnu@4.60.3': + '@rolldown/binding-linux-arm64-gnu@1.1.3': optional: true - '@rollup/rollup-linux-loong64-musl@4.60.3': + '@rolldown/binding-linux-arm64-musl@1.1.3': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.60.3': + '@rolldown/binding-linux-ppc64-gnu@1.1.3': optional: true - '@rollup/rollup-linux-ppc64-musl@4.60.3': + '@rolldown/binding-linux-s390x-gnu@1.1.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.60.3': + '@rolldown/binding-linux-x64-gnu@1.1.3': optional: true - '@rollup/rollup-linux-riscv64-musl@4.60.3': + '@rolldown/binding-linux-x64-musl@1.1.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.60.3': + '@rolldown/binding-openharmony-arm64@1.1.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.60.3': - optional: true - - '@rollup/rollup-linux-x64-musl@4.60.3': - optional: true - - '@rollup/rollup-openbsd-x64@4.60.3': - optional: true - - '@rollup/rollup-openharmony-arm64@4.60.3': + '@rolldown/binding-wasm32-wasi@1.1.3': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true - '@rollup/rollup-win32-arm64-msvc@4.60.3': + '@rolldown/binding-win32-arm64-msvc@1.1.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.60.3': + '@rolldown/binding-win32-x64-msvc@1.1.3': optional: true - '@rollup/rollup-win32-x64-gnu@4.60.3': - optional: true + '@rolldown/pluginutils@1.0.1': {} - '@rollup/rollup-win32-x64-msvc@4.60.3': - optional: true + '@rollup/pluginutils@5.3.0': + dependencies: + '@types/estree': 1.0.9 + estree-walker: 2.0.2 + picomatch: 4.0.4 '@shikijs/core@4.0.2': dependencies: @@ -2292,6 +2594,11 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 @@ -2300,8 +2607,6 @@ snapshots: dependencies: '@types/estree': 1.0.9 - '@types/estree@1.0.8': {} - '@types/estree@1.0.9': {} '@types/hast@3.0.4': @@ -2342,6 +2647,10 @@ snapshots: acorn@8.16.0: {} + am-i-vibing@0.4.0: + dependencies: + process-ancestry: 0.1.0 + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 @@ -2357,32 +2666,34 @@ snapshots: astring@1.9.0: {} - astro-expressive-code@0.42.0(astro@6.3.0(@types/node@24.12.2)(rollup@4.60.3)): + astro-expressive-code@0.44.0(astro@7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2)): dependencies: - astro: 6.3.0(@types/node@24.12.2)(rollup@4.60.3) - rehype-expressive-code: 0.42.0 + astro: 7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2) + rehype-expressive-code: 0.44.0 + url-extras: 0.1.0 - astro@6.3.0(@types/node@24.12.2)(rollup@4.60.3): + astro@7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2): dependencies: - '@astrojs/compiler': 4.0.0 - '@astrojs/internal-helpers': 0.9.0 - '@astrojs/markdown-remark': 7.1.1 + '@astrojs/compiler-rs': 0.2.3(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@astrojs/internal-helpers': 0.10.0 + '@astrojs/markdown-satteri': 0.3.2 '@astrojs/telemetry': 3.3.2 '@capsizecss/unpack': 4.0.0 '@clack/prompts': 1.3.0 '@oslojs/encoding': 1.1.0 - '@rollup/pluginutils': 5.3.0(rollup@4.60.3) + '@rollup/pluginutils': 5.3.0 + am-i-vibing: 0.4.0 aria-query: 5.3.2 axobject-query: 4.1.0 ci-info: 4.4.0 clsx: 2.1.1 common-ancestor-path: 2.0.0 cookie: 1.1.1 - devalue: 5.8.0 + devalue: 5.8.1 diff: 8.0.4 dset: 3.1.4 es-module-lexer: 2.1.0 - esbuild: 0.27.7 + esbuild: 0.28.1 flattie: 1.1.1 fontace: 0.4.1 get-tsconfig: 5.0.0-beta.4 @@ -2414,12 +2725,13 @@ snapshots: unist-util-visit: 5.1.0 unstorage: 1.17.5 vfile: 6.0.3 - vite: 7.3.3(@types/node@24.12.2) - vitefu: 1.1.3(vite@7.3.3(@types/node@24.12.2)) + vite: 8.1.0(@types/node@24.12.2)(esbuild@0.28.1) + vitefu: 1.1.3(vite@8.1.0(@types/node@24.12.2)(esbuild@0.28.1)) xxhash-wasm: 1.1.0 yargs-parser: 22.0.0 zod: 4.4.3 optionalDependencies: + '@astrojs/markdown-remark': 7.2.0 sharp: 0.34.5 transitivePeerDependencies: - '@azure/app-configuration' @@ -2430,6 +2742,8 @@ snapshots: - '@azure/storage-blob' - '@capacitor/preferences' - '@deno/kv' + - '@emnapi/core' + - '@emnapi/runtime' - '@netlify/blobs' - '@planetscale/database' - '@types/node' @@ -2437,19 +2751,18 @@ snapshots: - '@vercel/blob' - '@vercel/functions' - '@vercel/kv' + - '@vitejs/devtools' - aws4fetch - db0 - idb-keyval - ioredis - jiti - less - - lightningcss - rollup - sass - sass-embedded - stylus - sugarss - - supports-color - terser - tsx - uploadthing @@ -2547,7 +2860,7 @@ snapshots: detect-libc@2.1.2: {} - devalue@5.8.0: {} + devalue@5.8.1: {} devlop@1.1.0: dependencies: @@ -2597,34 +2910,34 @@ snapshots: esast-util-from-estree: 2.0.0 vfile-message: 4.0.3 - esbuild@0.27.7: + esbuild@0.28.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.7 - '@esbuild/android-arm': 0.27.7 - '@esbuild/android-arm64': 0.27.7 - '@esbuild/android-x64': 0.27.7 - '@esbuild/darwin-arm64': 0.27.7 - '@esbuild/darwin-x64': 0.27.7 - '@esbuild/freebsd-arm64': 0.27.7 - '@esbuild/freebsd-x64': 0.27.7 - '@esbuild/linux-arm': 0.27.7 - '@esbuild/linux-arm64': 0.27.7 - '@esbuild/linux-ia32': 0.27.7 - '@esbuild/linux-loong64': 0.27.7 - '@esbuild/linux-mips64el': 0.27.7 - '@esbuild/linux-ppc64': 0.27.7 - '@esbuild/linux-riscv64': 0.27.7 - '@esbuild/linux-s390x': 0.27.7 - '@esbuild/linux-x64': 0.27.7 - '@esbuild/netbsd-arm64': 0.27.7 - '@esbuild/netbsd-x64': 0.27.7 - '@esbuild/openbsd-arm64': 0.27.7 - '@esbuild/openbsd-x64': 0.27.7 - '@esbuild/openharmony-arm64': 0.27.7 - '@esbuild/sunos-x64': 0.27.7 - '@esbuild/win32-arm64': 0.27.7 - '@esbuild/win32-ia32': 0.27.7 - '@esbuild/win32-x64': 0.27.7 + '@esbuild/aix-ppc64': 0.28.1 + '@esbuild/android-arm': 0.28.1 + '@esbuild/android-arm64': 0.28.1 + '@esbuild/android-x64': 0.28.1 + '@esbuild/darwin-arm64': 0.28.1 + '@esbuild/darwin-x64': 0.28.1 + '@esbuild/freebsd-arm64': 0.28.1 + '@esbuild/freebsd-x64': 0.28.1 + '@esbuild/linux-arm': 0.28.1 + '@esbuild/linux-arm64': 0.28.1 + '@esbuild/linux-ia32': 0.28.1 + '@esbuild/linux-loong64': 0.28.1 + '@esbuild/linux-mips64el': 0.28.1 + '@esbuild/linux-ppc64': 0.28.1 + '@esbuild/linux-riscv64': 0.28.1 + '@esbuild/linux-s390x': 0.28.1 + '@esbuild/linux-x64': 0.28.1 + '@esbuild/netbsd-arm64': 0.28.1 + '@esbuild/netbsd-x64': 0.28.1 + '@esbuild/openbsd-arm64': 0.28.1 + '@esbuild/openbsd-x64': 0.28.1 + '@esbuild/openharmony-arm64': 0.28.1 + '@esbuild/sunos-x64': 0.28.1 + '@esbuild/win32-arm64': 0.28.1 + '@esbuild/win32-ia32': 0.28.1 + '@esbuild/win32-x64': 0.28.1 escape-string-regexp@5.0.0: {} @@ -2665,12 +2978,12 @@ snapshots: eventemitter3@5.0.4: {} - expressive-code@0.42.0: + expressive-code@0.44.0: dependencies: - '@expressive-code/core': 0.42.0 - '@expressive-code/plugin-frames': 0.42.0 - '@expressive-code/plugin-shiki': 0.42.0 - '@expressive-code/plugin-text-markers': 0.42.0 + '@expressive-code/core': 0.44.0 + '@expressive-code/plugin-frames': 0.44.0 + '@expressive-code/plugin-shiki': 0.44.0 + '@expressive-code/plugin-text-markers': 0.44.0 extend@3.0.2: {} @@ -2955,6 +3268,55 @@ snapshots: klona@2.0.6: {} + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + longest-streak@3.1.0: {} lru-cache@11.3.6: {} @@ -3544,8 +3906,16 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.15: + dependencies: + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prismjs@1.30.0: {} + process-ancestry@0.1.0: {} + property-information@7.1.0: {} radix3@1.1.2: {} @@ -3591,9 +3961,9 @@ snapshots: dependencies: regex-utilities: 2.3.0 - rehype-expressive-code@0.42.0: + rehype-expressive-code@0.44.0: dependencies: - expressive-code: 0.42.0 + expressive-code: 0.44.0 rehype-format@5.0.1: dependencies: @@ -3717,36 +4087,43 @@ snapshots: retext-stringify: 4.0.0 unified: 11.0.5 - rollup@4.60.3: + rolldown@1.1.3: dependencies: - '@types/estree': 1.0.8 + '@oxc-project/types': 0.137.0 + '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.60.3 - '@rollup/rollup-android-arm64': 4.60.3 - '@rollup/rollup-darwin-arm64': 4.60.3 - '@rollup/rollup-darwin-x64': 4.60.3 - '@rollup/rollup-freebsd-arm64': 4.60.3 - '@rollup/rollup-freebsd-x64': 4.60.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.60.3 - '@rollup/rollup-linux-arm-musleabihf': 4.60.3 - '@rollup/rollup-linux-arm64-gnu': 4.60.3 - '@rollup/rollup-linux-arm64-musl': 4.60.3 - '@rollup/rollup-linux-loong64-gnu': 4.60.3 - '@rollup/rollup-linux-loong64-musl': 4.60.3 - '@rollup/rollup-linux-ppc64-gnu': 4.60.3 - '@rollup/rollup-linux-ppc64-musl': 4.60.3 - '@rollup/rollup-linux-riscv64-gnu': 4.60.3 - '@rollup/rollup-linux-riscv64-musl': 4.60.3 - '@rollup/rollup-linux-s390x-gnu': 4.60.3 - '@rollup/rollup-linux-x64-gnu': 4.60.3 - '@rollup/rollup-linux-x64-musl': 4.60.3 - '@rollup/rollup-openbsd-x64': 4.60.3 - '@rollup/rollup-openharmony-arm64': 4.60.3 - '@rollup/rollup-win32-arm64-msvc': 4.60.3 - '@rollup/rollup-win32-ia32-msvc': 4.60.3 - '@rollup/rollup-win32-x64-gnu': 4.60.3 - '@rollup/rollup-win32-x64-msvc': 4.60.3 - fsevents: 2.3.3 + '@rolldown/binding-android-arm64': 1.1.3 + '@rolldown/binding-darwin-arm64': 1.1.3 + '@rolldown/binding-darwin-x64': 1.1.3 + '@rolldown/binding-freebsd-x64': 1.1.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.3 + '@rolldown/binding-linux-arm64-gnu': 1.1.3 + '@rolldown/binding-linux-arm64-musl': 1.1.3 + '@rolldown/binding-linux-ppc64-gnu': 1.1.3 + '@rolldown/binding-linux-s390x-gnu': 1.1.3 + '@rolldown/binding-linux-x64-gnu': 1.1.3 + '@rolldown/binding-linux-x64-musl': 1.1.3 + '@rolldown/binding-openharmony-arm64': 1.1.3 + '@rolldown/binding-wasm32-wasi': 1.1.3 + '@rolldown/binding-win32-arm64-msvc': 1.1.3 + '@rolldown/binding-win32-x64-msvc': 1.1.3 + + satteri@0.9.2: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + optionalDependencies: + '@bruits/satteri-darwin-arm64': 0.9.2 + '@bruits/satteri-darwin-x64': 0.9.2 + '@bruits/satteri-linux-arm64-gnu': 0.9.2 + '@bruits/satteri-linux-arm64-musl': 0.9.2 + '@bruits/satteri-linux-x64-gnu': 0.9.2 + '@bruits/satteri-linux-x64-musl': 0.9.2 + '@bruits/satteri-wasm32-wasi': 0.9.2 + '@bruits/satteri-win32-arm64-msvc': 0.9.2 + '@bruits/satteri-win32-x64-msvc': 0.9.2 sax@1.6.0: {} @@ -3847,6 +4224,11 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -3935,6 +4317,8 @@ snapshots: ofetch: 1.5.1 ufo: 1.6.4 + url-extras@0.1.0: {} + util-deprecate@1.0.2: {} vfile-location@5.0.3: @@ -3952,21 +4336,21 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@7.3.3(@types/node@24.12.2): + vite@8.1.0(@types/node@24.12.2)(esbuild@0.28.1): dependencies: - esbuild: 0.27.7 - fdir: 6.5.0(picomatch@4.0.4) + lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.14 - rollup: 4.60.3 - tinyglobby: 0.2.16 + postcss: 8.5.15 + rolldown: 1.1.3 + tinyglobby: 0.2.17 optionalDependencies: '@types/node': 24.12.2 + esbuild: 0.28.1 fsevents: 2.3.3 - vitefu@1.1.3(vite@7.3.3(@types/node@24.12.2)): + vitefu@1.1.3(vite@8.1.0(@types/node@24.12.2)(esbuild@0.28.1)): optionalDependencies: - vite: 7.3.3(@types/node@24.12.2) + vite: 8.1.0(@types/node@24.12.2)(esbuild@0.28.1) web-namespaces@2.0.1: {} From a6b4592f41b6e2b22a360b3503974faa406a3434 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 00:09:33 +0900 Subject: [PATCH 06/25] chore: bump sharp 0.34.5 -> 0.35.2 Image-optimization dep used by astro. Build is clean and table rendering is unaffected (28
across 13 pages). Co-Authored-By: Claude Opus 4.8 (1M context) --- package.json | 2 +- pnpm-lock.yaml | 310 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 309 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 76b1c83..b26c87a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/starlight": "^0.41.1", "astro": "^7.0.2", - "sharp": "^0.34.5" + "sharp": "^0.35.2" }, "pnpm": { "onlyBuiltDependencies": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c7979e8..9692775 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^7.0.2 version: 7.0.2(@astrojs/markdown-remark@7.2.0)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@24.12.2) sharp: - specifier: ^0.34.5 - version: 0.34.5 + specifier: ^0.35.2 + version: 0.35.2 packages: @@ -395,70 +395,145 @@ packages: cpu: [arm64] os: [darwin] + '@img/sharp-darwin-arm64@0.35.2': + resolution: {integrity: sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [darwin] + '@img/sharp-darwin-x64@0.34.5': resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] + '@img/sharp-darwin-x64@0.35.2': + resolution: {integrity: sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-freebsd-wasm32@0.35.2': + resolution: {integrity: sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw==} + engines: {node: '>=20.9.0'} + os: [freebsd] + '@img/sharp-libvips-darwin-arm64@1.2.4': resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} cpu: [arm64] os: [darwin] + '@img/sharp-libvips-darwin-arm64@1.3.1': + resolution: {integrity: sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g==} + cpu: [arm64] + os: [darwin] + '@img/sharp-libvips-darwin-x64@1.2.4': resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} cpu: [x64] os: [darwin] + '@img/sharp-libvips-darwin-x64@1.3.1': + resolution: {integrity: sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ==} + cpu: [x64] + os: [darwin] + '@img/sharp-libvips-linux-arm64@1.2.4': resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] libc: [glibc] + '@img/sharp-libvips-linux-arm64@1.3.1': + resolution: {integrity: sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] libc: [glibc] + '@img/sharp-libvips-linux-arm@1.3.1': + resolution: {integrity: sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg==} + cpu: [arm] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] libc: [glibc] + '@img/sharp-libvips-linux-ppc64@1.3.1': + resolution: {integrity: sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] libc: [glibc] + '@img/sharp-libvips-linux-riscv64@1.3.1': + resolution: {integrity: sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] libc: [glibc] + '@img/sharp-libvips-linux-s390x@1.3.1': + resolution: {integrity: sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew==} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] libc: [glibc] + '@img/sharp-libvips-linux-x64@1.3.1': + resolution: {integrity: sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A==} + cpu: [x64] + os: [linux] + libc: [glibc] + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] libc: [musl] + '@img/sharp-libvips-linuxmusl-arm64@1.3.1': + resolution: {integrity: sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw==} + cpu: [arm64] + os: [linux] + libc: [musl] + '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] libc: [musl] + '@img/sharp-libvips-linuxmusl-x64@1.3.1': + resolution: {integrity: sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg==} + cpu: [x64] + os: [linux] + libc: [musl] + '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -466,6 +541,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linux-arm64@0.35.2': + resolution: {integrity: sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -473,6 +555,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linux-arm@0.35.2': + resolution: {integrity: sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A==} + engines: {node: '>=20.9.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -480,6 +569,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linux-ppc64@0.35.2': + resolution: {integrity: sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg==} + engines: {node: '>=20.9.0'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -487,6 +583,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linux-riscv64@0.35.2': + resolution: {integrity: sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA==} + engines: {node: '>=20.9.0'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -494,6 +597,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linux-s390x@0.35.2': + resolution: {integrity: sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA==} + engines: {node: '>=20.9.0'} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -501,6 +611,13 @@ packages: os: [linux] libc: [glibc] + '@img/sharp-linux-x64@0.35.2': + resolution: {integrity: sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -508,6 +625,13 @@ packages: os: [linux] libc: [musl] + '@img/sharp-linuxmusl-arm64@0.35.2': + resolution: {integrity: sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -515,29 +639,63 @@ packages: os: [linux] libc: [musl] + '@img/sharp-linuxmusl-x64@0.35.2': + resolution: {integrity: sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [musl] + '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] + '@img/sharp-wasm32@0.35.2': + resolution: {integrity: sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw==} + engines: {node: '>=20.9.0'} + + '@img/sharp-webcontainers-wasm32@0.35.2': + resolution: {integrity: sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g==} + engines: {node: '>=20.9.0'} + cpu: [wasm32] + '@img/sharp-win32-arm64@0.34.5': resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [win32] + '@img/sharp-win32-arm64@0.35.2': + resolution: {integrity: sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [win32] + '@img/sharp-win32-ia32@0.34.5': resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] + '@img/sharp-win32-ia32@0.35.2': + resolution: {integrity: sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog==} + engines: {node: ^20.9.0} + cpu: [ia32] + os: [win32] + '@img/sharp-win32-x64@0.34.5': resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] + '@img/sharp-win32-x64@0.35.2': + resolution: {integrity: sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [win32] + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -1698,10 +1856,19 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + sharp@0.34.5: resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + sharp@0.35.2: + resolution: {integrity: sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w==} + engines: {node: '>=20.9.0'} + shiki@4.0.2: resolution: {integrity: sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ==} engines: {node: '>=20'} @@ -2342,95 +2509,199 @@ snapshots: '@img/sharp-libvips-darwin-arm64': 1.2.4 optional: true + '@img/sharp-darwin-arm64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.3.1 + optional: true + '@img/sharp-darwin-x64@0.34.5': optionalDependencies: '@img/sharp-libvips-darwin-x64': 1.2.4 optional: true + '@img/sharp-darwin-x64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.3.1 + optional: true + + '@img/sharp-freebsd-wasm32@0.35.2': + dependencies: + '@img/sharp-wasm32': 0.35.2 + optional: true + '@img/sharp-libvips-darwin-arm64@1.2.4': optional: true + '@img/sharp-libvips-darwin-arm64@1.3.1': + optional: true + '@img/sharp-libvips-darwin-x64@1.2.4': optional: true + '@img/sharp-libvips-darwin-x64@1.3.1': + optional: true + '@img/sharp-libvips-linux-arm64@1.2.4': optional: true + '@img/sharp-libvips-linux-arm64@1.3.1': + optional: true + '@img/sharp-libvips-linux-arm@1.2.4': optional: true + '@img/sharp-libvips-linux-arm@1.3.1': + optional: true + '@img/sharp-libvips-linux-ppc64@1.2.4': optional: true + '@img/sharp-libvips-linux-ppc64@1.3.1': + optional: true + '@img/sharp-libvips-linux-riscv64@1.2.4': optional: true + '@img/sharp-libvips-linux-riscv64@1.3.1': + optional: true + '@img/sharp-libvips-linux-s390x@1.2.4': optional: true + '@img/sharp-libvips-linux-s390x@1.3.1': + optional: true + '@img/sharp-libvips-linux-x64@1.2.4': optional: true + '@img/sharp-libvips-linux-x64@1.3.1': + optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': optional: true + '@img/sharp-libvips-linuxmusl-arm64@1.3.1': + optional: true + '@img/sharp-libvips-linuxmusl-x64@1.2.4': optional: true + '@img/sharp-libvips-linuxmusl-x64@1.3.1': + optional: true + '@img/sharp-linux-arm64@0.34.5': optionalDependencies: '@img/sharp-libvips-linux-arm64': 1.2.4 optional: true + '@img/sharp-linux-arm64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.3.1 + optional: true + '@img/sharp-linux-arm@0.34.5': optionalDependencies: '@img/sharp-libvips-linux-arm': 1.2.4 optional: true + '@img/sharp-linux-arm@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.3.1 + optional: true + '@img/sharp-linux-ppc64@0.34.5': optionalDependencies: '@img/sharp-libvips-linux-ppc64': 1.2.4 optional: true + '@img/sharp-linux-ppc64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.3.1 + optional: true + '@img/sharp-linux-riscv64@0.34.5': optionalDependencies: '@img/sharp-libvips-linux-riscv64': 1.2.4 optional: true + '@img/sharp-linux-riscv64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.3.1 + optional: true + '@img/sharp-linux-s390x@0.34.5': optionalDependencies: '@img/sharp-libvips-linux-s390x': 1.2.4 optional: true + '@img/sharp-linux-s390x@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.3.1 + optional: true + '@img/sharp-linux-x64@0.34.5': optionalDependencies: '@img/sharp-libvips-linux-x64': 1.2.4 optional: true + '@img/sharp-linux-x64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.3.1 + optional: true + '@img/sharp-linuxmusl-arm64@0.34.5': optionalDependencies: '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 optional: true + '@img/sharp-linuxmusl-arm64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.3.1 + optional: true + '@img/sharp-linuxmusl-x64@0.34.5': optionalDependencies: '@img/sharp-libvips-linuxmusl-x64': 1.2.4 optional: true + '@img/sharp-linuxmusl-x64@0.35.2': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.3.1 + optional: true + '@img/sharp-wasm32@0.34.5': dependencies: '@emnapi/runtime': 1.10.0 optional: true + '@img/sharp-wasm32@0.35.2': + dependencies: + '@emnapi/runtime': 1.11.1 + optional: true + + '@img/sharp-webcontainers-wasm32@0.35.2': + dependencies: + '@img/sharp-wasm32': 0.35.2 + optional: true + '@img/sharp-win32-arm64@0.34.5': optional: true + '@img/sharp-win32-arm64@0.35.2': + optional: true + '@img/sharp-win32-ia32@0.34.5': optional: true + '@img/sharp-win32-ia32@0.35.2': + optional: true + '@img/sharp-win32-x64@0.34.5': optional: true + '@img/sharp-win32-x64@0.35.2': + optional: true + '@jridgewell/sourcemap-codec@1.5.5': {} '@mdx-js/mdx@3.1.1': @@ -4129,6 +4400,8 @@ snapshots: semver@7.7.4: {} + semver@7.8.5: {} + sharp@0.34.5: dependencies: '@img/colour': 1.1.0 @@ -4159,6 +4432,39 @@ snapshots: '@img/sharp-win32-arm64': 0.34.5 '@img/sharp-win32-ia32': 0.34.5 '@img/sharp-win32-x64': 0.34.5 + optional: true + + sharp@0.35.2: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.8.5 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.35.2 + '@img/sharp-darwin-x64': 0.35.2 + '@img/sharp-freebsd-wasm32': 0.35.2 + '@img/sharp-libvips-darwin-arm64': 1.3.1 + '@img/sharp-libvips-darwin-x64': 1.3.1 + '@img/sharp-libvips-linux-arm': 1.3.1 + '@img/sharp-libvips-linux-arm64': 1.3.1 + '@img/sharp-libvips-linux-ppc64': 1.3.1 + '@img/sharp-libvips-linux-riscv64': 1.3.1 + '@img/sharp-libvips-linux-s390x': 1.3.1 + '@img/sharp-libvips-linux-x64': 1.3.1 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.1 + '@img/sharp-libvips-linuxmusl-x64': 1.3.1 + '@img/sharp-linux-arm': 0.35.2 + '@img/sharp-linux-arm64': 0.35.2 + '@img/sharp-linux-ppc64': 0.35.2 + '@img/sharp-linux-riscv64': 0.35.2 + '@img/sharp-linux-s390x': 0.35.2 + '@img/sharp-linux-x64': 0.35.2 + '@img/sharp-linuxmusl-arm64': 0.35.2 + '@img/sharp-linuxmusl-x64': 0.35.2 + '@img/sharp-webcontainers-wasm32': 0.35.2 + '@img/sharp-win32-arm64': 0.35.2 + '@img/sharp-win32-ia32': 0.35.2 + '@img/sharp-win32-x64': 0.35.2 shiki@4.0.2: dependencies: From 307d2dfa635ef93fb103ecac7ca7225bdd73dfb9 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 00:45:48 +0900 Subject: [PATCH 07/25] docs: add Working in GAIA workflow walkthrough New narrative page tying the /gaia-* commands into one day-to-day loop: mostly-just-prompt, a when-to-reach-for-each table, a feature start to finish (spec -> plan -> kickoff -> audit gate; handoff/pickup), and a permissions section explaining the first-run --dangerously-skip-permissions flag and the guardrail hooks that hold regardless. Wired into the Getting started sidebar (after Quick Start) and forward-linked from Quick Start. Co-Authored-By: Claude Opus 4.8 (1M context) --- astro.config.mjs | 1 + .../docs/getting-started/working-in-gaia.mdx | 79 +++++++++++++++++++ src/content/docs/index.mdx | 2 +- 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/content/docs/getting-started/working-in-gaia.mdx diff --git a/astro.config.mjs b/astro.config.mjs index d5331fb..309e371 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -33,6 +33,7 @@ export default defineConfig({ label: 'Getting started', items: [ { label: 'Quick Start', slug: 'index' }, + { label: 'Working in GAIA', slug: 'getting-started/working-in-gaia' }, { label: '/gaia-init', slug: 'getting-started/gaia-init' }, { label: '/setup-gaia-ci', slug: 'getting-started/setup-gaia-ci' }, { label: '/setup-cloned-gaia-project', slug: 'getting-started/setup-cloned-gaia-project' }, diff --git a/src/content/docs/getting-started/working-in-gaia.mdx b/src/content/docs/getting-started/working-in-gaia.mdx new file mode 100644 index 0000000..472ef0a --- /dev/null +++ b/src/content/docs/getting-started/working-in-gaia.mdx @@ -0,0 +1,79 @@ +--- +title: Working in GAIA +description: How a normal Claude Code session works once GAIA is installed, and when to reach for each /gaia-* command. +--- + +import { Aside } from '@astrojs/starlight/components'; + +Every other page here documents one command, hook, or skill on its own. This page is the opposite: it shows how the pieces fit together in normal use, so you know what to do once setup is done. + +## Mostly, you just prompt Claude + +Working in GAIA is the same as working in Claude Code: describe what you want in plain language. GAIA loads its rules, skills, and guardrails when the session starts, so an ordinary request already runs through them. You don't invoke them. + +Ask for a component, a fix, a refactor, a test: + +``` +> Add a date-range filter to the saved-search panel and cover it with a test. +``` + +The code skills (TypeScript, React, Tailwind, tests) and the scaffolders trigger on their own from how you phrase the request. You never call them by name. Before each commit, the quality gate runs typecheck, lint, and tests, and the hooks block risky actions in the background. Most sessions never touch a slash command. + + + +## When to reach for a command + +The `/gaia-*` commands are for specific moments, not everyday driving. + +| When you're... | Reach for | Why | +| --- | --- | --- | +| Starting a feature whose shape isn't settled | [`/gaia-spec`](/commands/spec/) | Pins down intent and acceptance tests, then saves a spec you can review before any code is written. | +| Turning a big feature into parallel work | [`/gaia-plan`](/commands/plan/) | Breaks it into phased workstreams with shared contracts and a ready-to-run kickoff. | +| Pausing, or your context is getting heavy | [`/gaia-handoff`](/commands/handoff-pickup/) | Writes down where you are so you can clear context without losing the thread. | +| Starting a fresh session | [`/gaia-pickup`](/commands/handoff-pickup/) | Reads the last handoff back and tells you what changed since. | +| A GAIA command or hook misbehaved | [`/gaia-forensics`](/commands/forensics/) | Diagnoses the misfire and, if it's a bug, drafts a filing-ready report. | +| The Claude integration feels off | [`/gaia-fitness`](/commands/fitness/) | Health-checks hooks, frontmatter, rules, and settings, then heals what it can. | +| Memory or rules have drifted | [`/gaia-audit`](/commands/audit/) | Finds duplication, contradictions, and stale guidance across your knowledge stores. | +| The wiki has fallen behind the code | [`/gaia-wiki`](/commands/wiki/) | Syncs, consolidates, and lints the project wiki Claude reads from. | +| Dependencies are stale | [`/update-deps`](/commands/update-deps/) | Walks outdated packages by group and runs major-version migrations. | +| A new GAIA release is out | [`/update-gaia`](/commands/update-gaia/) | Merges the release into your project without clobbering your changes. | + +The bottom half of that table is mostly nudged for you. The statusline surfaces when fitness, audit, wiki, or updates are due, so you don't have to track them yourself. + +**When to skip them.** Small, clear changes don't need a spec or a plan. "Fix the timezone bug in the invoice header" is just a prompt. Spec and plan earn their overhead on larger, fuzzier work, the kind where it's worth agreeing on what to build before building it. + +## A feature, start to finish + +Here is the full loop for a feature you can't fully describe yet: + +1. **Settle what to build.** Run `/gaia-spec add saved-search filters`. It asks a few questions, confirms the intent and the acceptance tests in plain English, and saves a spec. When discovery is done it offers to hand off to planning. +2. **Plan the work.** `/gaia-plan` reads the spec and breaks it into phased workstreams with shared contracts. It writes a plan folder with a ready-to-run kickoff prompt, then stops without writing code. +3. **Build it.** Open a fresh session and run the kickoff. The orchestrator builds each workstream, runs the quality gate after every phase, and sends the result through the [`code-review-audit`](/reference/agents/) agent before anything merges. +4. **Handle the small stuff directly.** Not every change is worth that. "Fix the date formatting in the invoice header" is a single prompt. Claude makes the change, and the quality gate runs at commit. +5. **Pause and resume cleanly.** When a session runs long, `/gaia-handoff` writes down where you are. Next time, `/gaia-pickup` reads it back and flags anything that changed since. + +You won't run every step for every task. Reach for as much of the loop as the work needs, and prompt directly for the rest. + +## Permissions on the first run + +When you scaffold a project, `npx create-gaia` launches Claude Code once with `--dangerously-skip-permissions` and runs `/gaia-init`. That single run rewrites files, registers tools, and wires the project end to end. The flag lets it finish without stopping to ask permission at every step. + +That flag applies to the setup run only. Nothing stores it. When `/gaia-init` finishes, it tells you to exit Claude and relaunch, because the new skills and plugins load only in a fresh session. How you relaunch is your call: plain `claude` if you'd rather approve actions as they happen, or `claude --dangerously-skip-permissions` if you don't want to be interrupted. + +Either way, GAIA's guardrails stay on. They run as hooks on every tool call, not as permission prompts, so skipping the prompts doesn't disable them. Every scaffolded project ships hooks that block actions like: + +- committing or force-pushing directly to `main` +- `rm -rf` on dangerous targets (`/`, `~`, `.git`, `node_modules`, the repo root) +- writing secrets or `.env` files into the repo +- committing with `--no-verify` to skip the typecheck, lint, and test gate + +These hold whether or not you pass the flag. See the [hooks reference](/reference/hooks/) for the full set. + +## Related + +- [Quick Start](/) scaffolds a new project. +- [Commands overview](/commands/) is the full catalog of `/gaia-*` commands. +- [Maintenance overview](/maintenance/) covers the upkeep commands (`/gaia-fitness`, `/gaia-audit`, `/gaia-wiki`). +- [Skills overview](/skills/) lists the code skills and scaffolders that trigger from plain prompts. diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index 399cd61..f2b0919 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -29,7 +29,7 @@ npx create-gaia@latest my-app 3. Installs the packages 4. Launches Claude Code in the project directory and runs `/gaia-init` automatically -Follow along with the `/gaia-init` [walkthrough](/getting-started/gaia-init/). +Follow along with the `/gaia-init` [walkthrough](/getting-started/gaia-init/). Once setup is done, [Working in GAIA](/getting-started/working-in-gaia/) shows how a normal session works. ## Cloning an existing GAIA project From 9955a51ff32197fa2d1882a4616ce583a985a89a Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 01:39:16 +0900 Subject: [PATCH 08/25] docs: add Working in GAIA walkthrough page New narrative page for the day-to-day GAIA loop: mostly-just-prompt plus test-first behavior, a two-group when-to-reach-for-each table (main commands vs statusline-nudged), a feature start to finish, and the first-run permissions and flag explanation. Adds it to the Getting started sidebar after Quick Start, forward-links from Quick Start, and reorders the Commands sidebar so /gaia-spec precedes /gaia-plan. Co-Authored-By: Claude Opus 4.8 (1M context) --- astro.config.mjs | 2 +- .../docs/getting-started/working-in-gaia.mdx | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index 309e371..9e15f08 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -43,8 +43,8 @@ export default defineConfig({ label: 'Commands', items: [ { label: 'Overview', slug: 'commands' }, - { label: '/gaia-plan', slug: 'commands/plan' }, { label: '/gaia-spec', slug: 'commands/spec' }, + { label: '/gaia-plan', slug: 'commands/plan' }, { label: '/gaia-handoff and pickup', slug: 'commands/handoff-pickup' }, { label: '/gaia-forensics', slug: 'commands/forensics' }, { label: '/update-deps', slug: 'commands/update-deps' }, diff --git a/src/content/docs/getting-started/working-in-gaia.mdx b/src/content/docs/getting-started/working-in-gaia.mdx index 472ef0a..9a216db 100644 --- a/src/content/docs/getting-started/working-in-gaia.mdx +++ b/src/content/docs/getting-started/working-in-gaia.mdx @@ -11,21 +11,23 @@ Every other page here documents one command, hook, or skill on its own. This pag Working in GAIA is the same as working in Claude Code: describe what you want in plain language. GAIA loads its rules, skills, and guardrails when the session starts, so an ordinary request already runs through them. You don't invoke them. -Ask for a component, a fix, a refactor, a test: +Ask for a component, a fix, a refactor: ``` -> Add a date-range filter to the saved-search panel and cover it with a test. +> Add a date-range filter to the saved-search panel. ``` The code skills (TypeScript, React, Tailwind, tests) and the scaffolders trigger on their own from how you phrase the request. You never call them by name. Before each commit, the quality gate runs typecheck, lint, and tests, and the hooks block risky actions in the background. Most sessions never touch a slash command. +Notice the prompt didn't ask for a test. GAIA works test-first: for a feature or a bug fix, Claude writes a failing test, then the code that makes it pass. A commit hook backs this up, refusing to commit a new test that was never seen to fail first. You get tests as part of the work, not as a separate request. + ## When to reach for a command -The `/gaia-*` commands are for specific moments, not everyday driving. +The `/gaia-*` commands are for specific moments, not everyday driving. These you reach for based on what you're doing: | When you're... | Reach for | Why | | --- | --- | --- | @@ -34,14 +36,19 @@ The `/gaia-*` commands are for specific moments, not everyday driving. | Pausing, or your context is getting heavy | [`/gaia-handoff`](/commands/handoff-pickup/) | Writes down where you are so you can clear context without losing the thread. | | Starting a fresh session | [`/gaia-pickup`](/commands/handoff-pickup/) | Reads the last handoff back and tells you what changed since. | | A GAIA command or hook misbehaved | [`/gaia-forensics`](/commands/forensics/) | Diagnoses the misfire and, if it's a bug, drafts a filing-ready report. | + +### Nudged by the statusline + +You rarely reach for these yourself. They surface on the statusline when they're due, so you don't have to track them: + +| When you're... | Reach for | Why | +| --- | --- | --- | | The Claude integration feels off | [`/gaia-fitness`](/commands/fitness/) | Health-checks hooks, frontmatter, rules, and settings, then heals what it can. | | Memory or rules have drifted | [`/gaia-audit`](/commands/audit/) | Finds duplication, contradictions, and stale guidance across your knowledge stores. | | The wiki has fallen behind the code | [`/gaia-wiki`](/commands/wiki/) | Syncs, consolidates, and lints the project wiki Claude reads from. | | Dependencies are stale | [`/update-deps`](/commands/update-deps/) | Walks outdated packages by group and runs major-version migrations. | | A new GAIA release is out | [`/update-gaia`](/commands/update-gaia/) | Merges the release into your project without clobbering your changes. | -The bottom half of that table is mostly nudged for you. The statusline surfaces when fitness, audit, wiki, or updates are due, so you don't have to track them yourself. - **When to skip them.** Small, clear changes don't need a spec or a plan. "Fix the timezone bug in the invoice header" is just a prompt. Spec and plan earn their overhead on larger, fuzzier work, the kind where it's worth agreeing on what to build before building it. ## A feature, start to finish From 721ad5b76c52dfe84f40a79348e97cdf184d16f6 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 01:39:16 +0900 Subject: [PATCH 09/25] docs: document running concurrent /gaia-spec and /gaia-plan Add a Running more than one at once section to each page: two specs draw distinct SPEC ids from a locked ledger with no coordination; parallel plans get isolated directories, and a second plan on a live branch triggers the worktree, continue, or defer prompt. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/commands/plan.mdx | 6 ++++++ src/content/docs/commands/spec.mdx | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/src/content/docs/commands/plan.mdx b/src/content/docs/commands/plan.mdx index d62a7d1..621d568 100644 --- a/src/content/docs/commands/plan.mdx +++ b/src/content/docs/commands/plan.mdx @@ -107,6 +107,12 @@ After all implementation phases pass and the final commit is pushed, the orchest After the user confirms the PR is ready to merge, the orchestrator deletes its own plan folder. If `.gaia/local/plans/` is gitignored (the GAIA default), the deletion is invisible to git and skipped from commit. Otherwise, the deletion lands as the final commit on the PR. +## Running more than one at once + +Parallel `/gaia-plan` invocations stay isolated on disk. Each plan gets its own directory, with the `-2`, `-3` suffix from [What gets produced](#what-gets-produced) resolving any slug collision, so building two plans at once never overwrites either. + +Execution is the part that can actually clash, since two orchestrators editing the same branch would step on each other. When you start a plan on a branch that already has a live orchestrator, GAIA detects the in-flight run and asks how to proceed: isolate the new work in a [git worktree](#worktree-mode-experimental) (recommended), continue on the shared branch and accept the conflict risk, or defer. Plans on different branches, or a plan running alongside a spec, need no coordination. + ## Worktree mode (experimental) If the orchestrator chose worktree mode at branch policy, the post-merge phase confirms the merge via `gh pr view --json state`, then calls `ExitWorktree({action: "remove", discard_changes: true})`. The merged-state confirmation is the primary signal that the work is preserved; `discard_changes: true` is correct because squash-merge produces unreachable commits on the worktree branch. diff --git a/src/content/docs/commands/spec.mdx b/src/content/docs/commands/spec.mdx index b5278d0..3f6523c 100644 --- a/src/content/docs/commands/spec.mdx +++ b/src/content/docs/commands/spec.mdx @@ -85,6 +85,14 @@ A handful of mechanics are used by multiple steps: Use auto mode when the description is well-formed and the cost of stopping for clarifications outweighs the cost of a reviewer auditing the deferred items afterward. +## Running more than one at once + +You can run `/gaia-spec` in two sessions at the same time. Each session draws its own SPEC number from a shared, locked ledger, so two concurrent specs never collide on an id or overwrite each other's artifact. There is no flag and nothing to coordinate: open a second session and start the second spec. + +If a session finds a SPEC that was allocated in another terminal but not yet saved, the resume-or-start-new prompt surfaces it, so you don't fork the same draft in two places. + +A spec only writes its own artifacts and never touches git, so it also runs cleanly alongside a `/gaia-plan` that is mid-execution. + ## Constraints during a spec session - **Write-surface allowlist.** Every write lands in `.gaia/local/specs/`, `.specify/`, or `.gaia/local/cache/`. No source files, no repo configs. From ff0110971d6f7bc09bd2bd0ad53fc90c11efa55f Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 01:39:16 +0900 Subject: [PATCH 10/25] docs: rewrite /gaia-init page for accuracy The prior page misdescribed the prompts (invented a statusline-mode question, wrong title default, missing the GitHub-username question), carried a stale React Doctor command and a truncated exit message, and omitted several real steps. Rewritten against the command source: corrected questions, build check, CODEOWNERS, .env bootstrap, spec-kit registration, maintenance-tool modes, finalize, and the verbatim exit message with the cd and setup-gaia-ci reminder. The adaptation opt-in stays muted. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../docs/getting-started/gaia-init.mdx | 78 ++++++++++++------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/src/content/docs/getting-started/gaia-init.mdx b/src/content/docs/getting-started/gaia-init.mdx index ca8a496..e28b18b 100644 --- a/src/content/docs/getting-started/gaia-init.mdx +++ b/src/content/docs/getting-started/gaia-init.mdx @@ -5,42 +5,46 @@ sidebar: order: 2 --- -`/gaia-init` is automatically run during `npx create-gaia`. It renames the project to your title, configures language support, replaces template branding, registers Claude tools and plugins, sets up the wiki, and hands you a project that compiles, lints, and tests cleanly. +`/gaia-init` runs automatically during `npx create-gaia`. It renames the project to your title, configures language support, strips the template's GAIA branding, sets up CODEOWNERS and your environment file, registers Claude tools and plugins, verifies the build, and hands you a project that compiles, lints, and tests cleanly. ## The flow -### 1. pnpm + dependencies +### 1. Dependencies -1. Enables pnpm via Corepack if available, otherwise installs it globally with npm. +1. Enables pnpm via Corepack, or installs it globally with npm if Corepack isn't available. 2. Runs `pnpm install` against the freshly extracted scaffold. -3. Runs `/update-deps` to update every dependency to its latest compatible version. If a package is held back, the reason is surfaced. +3. Runs `/update-deps` to bring every package to its latest compatible version. Anything held back is surfaced with a reason. -If install fails, the run halts with the underlying error. Address the cause and re-run `/gaia-init`. +If install fails, the run halts with the underlying error. Fix the cause and resume (see [Resuming after a failure](#resuming-after-a-failure)). -### 2. Project questions +### 2. Questions about your project -Three sets of prompts. +Up front, `/gaia-init` asks a few questions: -**Project title.** Name of your project (default: `GAIA React App`). +- **Primary language.** The main language for your app's UI. Defaults to the language you have been typing in. +- **Additional languages.** Any extra locales on top of the primary, as ISO 639-1 codes (for example `es, de, ar`). If you want none, you also choose whether to keep the i18n scaffolding (recommended, so you can localize later with no rework) or strip it out entirely. Stripping is hard to reverse, so pick it only if you are sure the app stays single-language. +- **Project identity.** Your GitHub username (used for CODEOWNERS), the project title (defaults to your folder name in title case, for example `my-cool-app` becomes `My Cool App`), and a kebab-case slug (defaults to the folder name). -**Languages.** Pick the primary UI language, and any additional locales. If the project is single-language, you also choose whether to keep the i18n scaffolding or not. Stripping i18n now is cheaper than removing it later, but adding it back later is harder than leaving it in place. +A few more questions come up later: CI intent and maintenance modes, and an optional adaptation opt-in. -**Statusline mode.** `global` writes the statusline command to `~/.claude/settings.json`, `project` writes to `.claude/settings.json` only, `skip` leaves your settings alone. +### 3. Branding, naming, and i18n -### 3. Locale scaffolding +With your answers, `/gaia-init` strips the template's GAIA branding (the funding file, the logo component and SVG, the Storybook brand), renames the project to your title and slug, configures i18n for your chosen locales, and wires the statusline into the project's `.claude/settings.json`. If you added locales, it scaffolds each non-English one. If you stripped i18n, it removes the framework cleanly. -If multiple locales were chosen, it wires up non-`en` locale(s). +### 4. Project files and build check -If the project is single-language with i18n stripped, `/gaia-init` follows `.claude/instructions/remove-i18n.md` to remove the framework cleanly. +- Creates `.github/CODEOWNERS` with your GitHub username as the repo-wide owner. +- Copies `.env.example` to `.env` if you do not already have one. +- Runs the full quality gate, `pnpm typecheck && pnpm lint && pnpm test:ci && pnpm build`, and stops if anything fails. This is the step that backs the "compiles, lints, and tests cleanly" promise, and the main reason init takes a few minutes. -### 4. Claude tooling +### 5. Claude tooling -`/gaia-init` configures three external tools and three Claude plugins. You don't need to call these manually. They're listed here for your reference. +`/gaia-init` configures the external tools, plugins, and spec-kit runtime GAIA relies on. The project-scoped skills (`react-code`, `typescript`, `tailwind`, `tdd`, `playwright-cli`, `eslint-fixes`, `skeleton-loaders`) already ship with the clone. You don't run any of this by hand; it is listed for reference. **Tools.** Per-machine, not tracked in the repo: -- [React Doctor](https://github.com/millionco/react-doctor): `curl -fsSL https://react.doctor/install-skill.sh | bash`. Installs the `react-doctor` skill to `~/.claude/skills/`. Auto-runs after code edits in a `CLAUDECODE` environment and is invoked by the `code-review-audit` agent pre-merge. -- [Playwright CLI](https://github.com/microsoft/playwright-cli) binary: `npm install -g @playwright/cli@latest`. Backs the bundled `playwright-cli` skill, which shells out to this binary. +- [React Doctor](https://github.com/millionco/react-doctor): `npx -y react-doctor@latest install --yes`. Installs the `react-doctor` skill. Auto-runs after code edits in a `CLAUDECODE` environment and is invoked by the `code-review-audit` agent pre-merge. +- [Playwright CLI](https://github.com/microsoft/playwright-cli) binary: `npm install -g @playwright/cli@latest`. Backs the bundled `playwright-cli` skill, which shells out to it. - [Serena](https://github.com/oraios/serena) MCP server, registered globally for your Claude Code: ```bash @@ -57,7 +61,11 @@ claude plugin marketplace add AgriciDaniel/claude-obsidian claude plugin install claude-obsidian@claude-obsidian-marketplace ``` -### 5. CI integration +**spec-kit.** `/gaia-spec` runs on top of [spec-kit](https://github.com/github/spec-kit). Init registers spec-kit's runtime along with the GAIA extension and preset that ship with the template, so `/gaia-spec` and the `/speckit.gaia.*` commands work. + +After installing, `/gaia-init` probes each component and reports `[ok]` or `[FAIL]` per item. A failure halts the run so you can retry before continuing. + +### 6. CI integration `/gaia-init` records whether you plan to run GAIA's GitHub Actions CI and sets the local audit baseline. Nothing is installed on GitHub at this stage and no workflow files are added to the project; the actual install happens later via [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/), after your first push. @@ -68,22 +76,40 @@ You answer one question: Either way, `/gaia-init` writes `default_mode: local` to `.gaia/audit-ci.yml` as the audit baseline: until CI is wired up, the local `code-review-audit` agent is the only producer of the `GAIA-Audit` stamp. If you enable CI later, `/setup-gaia-ci` updates the team default. The audit gate is non-negotiable; this choice is only about where it runs. See the [`code-review-audit` agent reference](/reference/agents/) for what the audit checks. -### 6. Adaptation feature opt-in +It then asks how four optional maintenance jobs should run, wiki sync, dependency refresh (`/update-deps`), `pnpm audit`, and stale-branch cleanup, and writes your choices to `.gaia/automation.json`: + +- **`ci`** runs the job in GitHub Actions on a schedule (offered only if you enabled CI above). +- **`local`** runs it only when you invoke it on this machine. +- **`off`** disables it. -You can choose to opt into an optional adaptation feature. +If you enabled CI, the recommended default is all four in `ci`. If you declined, they default to `local`. None of it activates until `/setup-gaia-ci` wires CI after your first push. -### 7. Wiki initialization +### 7. Adaptation feature opt-in -GAIA comes with an Obsidian wiki built-in. Read more about it here. +`/gaia-init` asks once whether to opt into an optional adaptation feature. It stays off unless you turn it on, and you can change the choice later. + +### 8. Wiki reset + +GAIA ships with a built-in [wiki](/commands/wiki/) that Claude maintains as it works. Init resets two of its files, the hot cache and the log, to a clean slate so your project starts with its own context instead of GAIA's development history. ## After gaia-init completes -You should see: ` is ready for development. Restart Claude to pick up the new plugin and skill state.` +Init marks per-machine setup complete, removes the one-time `/init` interceptor, prunes the matching entry from `.claude/settings.json`, and deletes its own command file. Then it prints: + +``` + is ready for development. To pick up the new plugin and skill state, exit Claude, then from your terminal: + +cd + +Then start Claude again. + +After you create your GitHub repo and push, run /setup-gaia-ci to wire up tokens and enable CI. +``` -Restart Claude Code and you're ready to start developing with GAIA. +Exit Claude and relaunch from inside the project folder. The `cd` matters: when you exit, your shell drops back to the directory you launched from, not the project folder. The new plugin and skill state only loads in a fresh session. -Run `pnpm dev` to run the app locally. You can ask Claude to run it for you, or run it yourself in a separate terminal. +From there you are ready to build. Run `pnpm dev` to start the app locally, or ask Claude to run it. After you push to GitHub, run [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/). ## Resuming after a failure -`/gaia-init` is idempotent. If something breaks mid-run, ask Claude to fix any issues and resume gaia-init. Already-completed steps are skipped. +`/gaia-init` is idempotent and records its progress. If something breaks mid-run, fix the cause and ask Claude to resume `/gaia-init`; already-completed steps are skipped. From dc6759a9c02e89841b45456c91442e76f13e57d3 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 01:39:16 +0900 Subject: [PATCH 11/25] style: theme callouts to the GAIA palette Re-theme Starlight asides off the stock purple and blue: tip becomes slate teal, note neutral warm gray, caution brand amber. danger keeps red until a GAIA danger color exists. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/styles/theme.css | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/styles/theme.css b/src/styles/theme.css index 7c8bfe2..b9c2708 100644 --- a/src/styles/theme.css +++ b/src/styles/theme.css @@ -9,6 +9,14 @@ --gaia-accent: #d97757; --gaia-accent-2: #c96442; --gaia-accent-soft: #efa58e; + --gaia-secondary: #5b8a8a; + --gaia-secondary-2: #436c6c; + --gaia-secondary-soft: #8eb4b4; + --gaia-secondary-low: #16231f; /* dark slate-teal tint for callout backgrounds */ + --gaia-warn: #d9a857; + --gaia-warn-2: #b88a3f; + --gaia-warn-soft: #ecc781; + --gaia-warn-low: #2a2010; /* dark amber tint for caution callout backgrounds */ --gaia-line: #3d3d3a; --gaia-line-soft: #2e2e2b; @@ -125,6 +133,30 @@ header.header, white-space: nowrap; } +/* Callouts (Asides) — Starlight ships stock purple/blue accents that aren't in + the GAIA palette. Re-theme each variant to its palette job: tip = slate teal + (secondary register), note = neutral warm gray, caution = brand amber + (semantic warning). danger keeps Starlight's red until a GAIA danger color + lands. customCss is unlayered, so these win over Starlight's layered defaults + without a specificity fight. */ +.starlight-aside--tip { + --sl-color-asides-text-accent: var(--gaia-secondary-soft); + --sl-color-asides-border: var(--gaia-secondary); + background-color: var(--gaia-secondary-low); +} + +.starlight-aside--note { + --sl-color-asides-text-accent: var(--gaia-ink); + --sl-color-asides-border: var(--gaia-muted); + background-color: var(--gaia-surface-raised); +} + +.starlight-aside--caution { + --sl-color-asides-text-accent: var(--gaia-warn-soft); + --sl-color-asides-border: var(--gaia-warn); + background-color: var(--gaia-warn-low); +} + /* Right TOC: fit the inner container to its parent so long entries wrap, and give the right edge breathing room. Full padding shorthand to ensure the override sticks against the layered default. */ From e5e3a2b4583a9f52325b0acb3e97e7a2a99dc5a2 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 15:00:50 +0900 Subject: [PATCH 12/25] chore: refresh source-state snapshot for docs accuracy pass Captured against gaia commit 0a4af7b via source-survey. Baseline for the top-down 1.7.0 docs accuracy pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/audit/source-state.json | 886 +++++++++++++++++++++----------- 1 file changed, 592 insertions(+), 294 deletions(-) diff --git a/.claude/audit/source-state.json b/.claude/audit/source-state.json index e469ecd..885424a 100644 --- a/.claude/audit/source-state.json +++ b/.claude/audit/source-state.json @@ -1,7 +1,7 @@ { "version": 1, - "captured_at": "2026-06-05T00:00:00Z", - "gaia_commit": "1984425dc43037b16ef43585b08f9180a9de5c08", + "captured_at": "2026-06-26T05:55:15Z", + "gaia_commit": "0a4af7b6d0559fde0c086ab7b942c6380388b92b", "items": [ { "kind": "agent", @@ -9,7 +9,16 @@ "name": "code-review-audit", "description": "Comprehensive code review, security audit, performance analysis, and architectural assessment. Goes beyond linting and type-checking to identify vulnerabilities, bottlenecks, code smells, anti-patterns, and refactoring opportunities. Mandatory before PR merge.", "audience": "adopter", - "content_hash": "f8213e8f533b507a57a863bf303029aead4df981bc2b658f4ebafa4c4f9631a2", + "content_hash": "639c0d869932a2a50ea3355bc15557c2033fe6b64e6f56224994cdf92d3e3b30", + "excluded_from_docs": false + }, + { + "kind": "agent", + "path": ".claude/agents/worthiness-evaluator.md", + "name": "worthiness-evaluator", + "description": "Advisory test-worthiness audit for the emergent surface. Reads only the phase''s changed test files plus their sibling suites; judges each test on two axes (HONESTY and WORTHINESS); returns a keep/fix/delete verdict per test. Proposes only, edits no files, every delete is human-gated.", + "audience": "adopter", + "content_hash": "79fb600ea423460f36e2fff01bfcec3c819324c5c74113e588d7a58384ee27ee", "excluded_from_docs": false }, { @@ -18,133 +27,133 @@ "name": "_internal-fetch-coaching", "description": null, "audience": "adopter", - "content_hash": "3886ec4d8870e4562bd9fa75e03d8d993248d20b638838c8bc5a414a26a4e9d7", + "content_hash": "a615d7e0dda12e74e2ef710d80ea80b669724124d560ee5d6ce3907ccf4d2eca", "excluded_from_docs": true }, { "kind": "cli-subcommand", "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation bump-state", + "name": "gaia automation cron-decide", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "c0fd25611b57dfade1adb558166b238f8fdb8533abbff0f96a9d468f1fc03a53", "excluded_from_docs": false }, { "kind": "cli-subcommand", "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation clear-overage", + "name": "gaia automation install-audit-workflow", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "c0fd25611b57dfade1adb558166b238f8fdb8533abbff0f96a9d468f1fc03a53", "excluded_from_docs": false }, { "kind": "cli-subcommand", "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation cron-decide", + "name": "gaia automation read-config", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "c0fd25611b57dfade1adb558166b238f8fdb8533abbff0f96a9d468f1fc03a53", "excluded_from_docs": false }, { "kind": "cli-subcommand", "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation init-state", + "name": "gaia automation render-workflows", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "c0fd25611b57dfade1adb558166b238f8fdb8533abbff0f96a9d468f1fc03a53", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation install-audit-workflow", + "path": ".gaia/cli/src/ci/revert.ts", + "name": "gaia ci-revert is-cap-reached", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "42e588da1d6ef836e45f1352ee19dc8a2ba6d5fd2f219fd67b97fce3d46c5213", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation read-config", + "path": ".gaia/cli/src/ci/revert.ts", + "name": "gaia ci-revert mark-failed", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "42e588da1d6ef836e45f1352ee19dc8a2ba6d5fd2f219fd67b97fce3d46c5213", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation read-state", + "path": ".gaia/cli/src/ci/revert.ts", + "name": "gaia ci-revert open", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "42e588da1d6ef836e45f1352ee19dc8a2ba6d5fd2f219fd67b97fce3d46c5213", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation record-overage", + "path": ".gaia/cli/src/ci/stale-check.ts", + "name": "gaia ci-stale-check", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "70f9b5e8e8748d20794c6ae8fbe07d50025f1a245755618630083922672413da", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation record-run", + "path": ".gaia/cli/src/fitness/index.ts", + "name": "gaia fitness render-card", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "d6761fc42b186ab8d639ea247b9c66e95acae329b2d85eb1e2481aa92d3eebec", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/automation/index.ts", - "name": "gaia automation render-workflows", + "path": ".gaia/cli/src/harden/ledger.ts", + "name": "gaia harden-ledger is-suppressed", "description": null, "audience": "adopter", - "content_hash": "857982b438a4a16fdcedcf7ae1b7bafccc61865115923357f6365235c402cb7f", + "content_hash": "ddcf25adb4721c12eb98625b5ab6e34429e124ac2b7f3064db62a13ba774ead6", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/ci/revert.ts", - "name": "gaia ci-revert is-cap-reached", + "path": ".gaia/cli/src/harden/ledger.ts", + "name": "gaia harden-ledger list", "description": null, "audience": "adopter", - "content_hash": "1b40e5de09233d2b24379eb7c88fc61c8e3a865a870e1cd04532185995ac2cf0", + "content_hash": "ddcf25adb4721c12eb98625b5ab6e34429e124ac2b7f3064db62a13ba774ead6", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/ci/revert.ts", - "name": "gaia ci-revert mark-failed", + "path": ".gaia/cli/src/harden/ledger.ts", + "name": "gaia harden-ledger prune", "description": null, "audience": "adopter", - "content_hash": "1b40e5de09233d2b24379eb7c88fc61c8e3a865a870e1cd04532185995ac2cf0", + "content_hash": "ddcf25adb4721c12eb98625b5ab6e34429e124ac2b7f3064db62a13ba774ead6", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/ci/revert.ts", - "name": "gaia ci-revert open", + "path": ".gaia/cli/src/harden/ledger.ts", + "name": "gaia harden-ledger record", "description": null, "audience": "adopter", - "content_hash": "1b40e5de09233d2b24379eb7c88fc61c8e3a865a870e1cd04532185995ac2cf0", + "content_hash": "ddcf25adb4721c12eb98625b5ab6e34429e124ac2b7f3064db62a13ba774ead6", "excluded_from_docs": false }, { "kind": "cli-subcommand", - "path": ".gaia/cli/src/ci/stale-check.ts", - "name": "gaia ci-stale-check", + "path": ".gaia/cli/src/harden/tally.ts", + "name": "gaia harden-tally", "description": null, "audience": "adopter", - "content_hash": "6b594dd06af11192d62c211f96ef329fa9a798b7ec71d6c4063694a533a5e38d", + "content_hash": "5a2ccfb6b1beeb7d0441d6a4bdd25b220e008bbb300cdb2c5b1a9930f1a69e5f", "excluded_from_docs": false }, { @@ -309,6 +318,15 @@ "content_hash": "d5236a4ddefbb75db80b44320ae640e238a52d8d4eaab61eaf29a00c9ff6d0d6", "excluded_from_docs": true }, + { + "kind": "cli-subcommand", + "path": ".gaia/cli/src/react-perf/index.ts", + "name": "gaia react-perf reduce", + "description": null, + "audience": "adopter", + "content_hash": "e8380258e8aa8ee7bdd44f138bc4389bad1d40485b0032b1a0469b184a748df0", + "excluded_from_docs": false + }, { "kind": "cli-subcommand", "path": ".gaia/cli/src/release/index.ts", @@ -459,7 +477,7 @@ "name": "gaia setup-ci check-admin", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -468,7 +486,7 @@ "name": "gaia setup-ci check-audit-drift", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -477,7 +495,7 @@ "name": "gaia setup-ci check-drift", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -486,7 +504,7 @@ "name": "gaia setup-ci detect-remote", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -495,7 +513,7 @@ "name": "gaia setup-ci dismiss-personal", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -504,7 +522,7 @@ "name": "gaia setup-ci enable-delete-branch", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -513,7 +531,7 @@ "name": "gaia setup-ci finalize", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -522,7 +540,7 @@ "name": "gaia setup-ci opt-out-team", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -531,7 +549,7 @@ "name": "gaia setup-ci set-secret", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -540,7 +558,7 @@ "name": "gaia setup-ci status", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -549,7 +567,7 @@ "name": "gaia setup-ci verify-run", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -558,7 +576,7 @@ "name": "gaia setup-ci warn-existing-tools", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -567,7 +585,7 @@ "name": "gaia setup-ci write-tool-mode", "description": null, "audience": "adopter", - "content_hash": "6d316819d5b5c695c6dfe12a861a6640a42bfb79f2b1910b52c9066a2133c892", + "content_hash": "6f3aee395ceeac815545026792bb7eb21f2be5919307720c5d8ae2f04ec0e3c2", "excluded_from_docs": false }, { @@ -600,10 +618,28 @@ { "kind": "cli-subcommand", "path": ".gaia/cli/src/update/index.ts", - "name": "gaia update merge", + "name": "gaia update merge-audit-ci", "description": null, "audience": "adopter", - "content_hash": "9d198d9321c2406822a6b7f1afc0b9c01b8ea84c0aba8745b3a8ae0e2b0cd40a", + "content_hash": "f0ff38cb3c96c643e506525914d55d2e090ccb2cadf1758b7bc0dd96ec05a7ba", + "excluded_from_docs": false + }, + { + "kind": "cli-subcommand", + "path": ".gaia/cli/src/update/index.ts", + "name": "gaia update merge-workspace", + "description": null, + "audience": "adopter", + "content_hash": "f0ff38cb3c96c643e506525914d55d2e090ccb2cadf1758b7bc0dd96ec05a7ba", + "excluded_from_docs": false + }, + { + "kind": "cli-subcommand", + "path": ".gaia/cli/src/update-deps/index.ts", + "name": "gaia update-deps decline", + "description": null, + "audience": "adopter", + "content_hash": "24758a6935f50fdd986462fa11b0a60939cbd18007f2f449a8d5dead776b958e", "excluded_from_docs": false }, { @@ -612,7 +648,16 @@ "name": "gaia update-deps run", "description": null, "audience": "adopter", - "content_hash": "69aa708eedc87b999fa9036020d8d02722f5ba203f441e7663f4de624c8ff2ec", + "content_hash": "24758a6935f50fdd986462fa11b0a60939cbd18007f2f449a8d5dead776b958e", + "excluded_from_docs": false + }, + { + "kind": "cli-subcommand", + "path": ".gaia/cli/src/wiki/index.ts", + "name": "gaia wiki chain", + "description": null, + "audience": "adopter", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -621,7 +666,7 @@ "name": "gaia wiki commit-classify", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -630,7 +675,7 @@ "name": "gaia wiki dead-paths", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -639,25 +684,25 @@ "name": "gaia wiki diff-size", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { "kind": "cli-subcommand", "path": ".gaia/cli/src/wiki/index.ts", "name": "gaia wiki empty-sections", - "description": "Headings with no content before the next heading.", + "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { "kind": "cli-subcommand", "path": ".gaia/cli/src/wiki/index.ts", "name": "gaia wiki frontmatter", - "description": "Pages missing required frontmatter (type, status).", + "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -666,7 +711,7 @@ "name": "gaia wiki log-prepend", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -675,7 +720,7 @@ "name": "gaia wiki near-collisions", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -684,7 +729,7 @@ "name": "gaia wiki orphans", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -693,7 +738,7 @@ "name": "gaia wiki page-index", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -702,7 +747,7 @@ "name": "gaia wiki state", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -711,7 +756,7 @@ "name": "gaia wiki state-bump", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -720,7 +765,7 @@ "name": "gaia wiki state-init", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { @@ -729,16 +774,16 @@ "name": "gaia wiki sync land", "description": null, "audience": "adopter", - "content_hash": "b4a4165ad2c28a7a80fa0b8eb47f38bb12832c09821c56739be27bba5555b27b", + "content_hash": "d2afb8af5610e8cf1fd4ff84575c32ac90a14a3ce573c5f07b93fa56c1af3aff", "excluded_from_docs": false }, { "kind": "command", "path": ".claude/commands/gaia-audit.md", "name": "gaia-audit", - "description": "Audit memory, wiki, and auto-loaded files for duplication, conflicting instructions, and stale content, then apply fixes. Pass --apply to re-run the apply stage against the most recent report.", + "description": "Audit memory, wiki, and auto-loaded files for duplication, conflicting instructions, and stale content. The default path researches, then asks you a single Apply / Discuss / Decline question before any change. Pass --apply to re-run the apply stage against the most recent report.", "audience": "adopter", - "content_hash": "a4646f13e799bd01c0c23b4dc5164d6c4d7f27d8495c6fd600105f60525d4e97", + "content_hash": "d94c7917c917851432d709f3d87260691c30165b4be0170b3578dc297db39c53", "excluded_from_docs": false }, { @@ -759,13 +804,22 @@ "content_hash": "5e1f8b2f81a0a152c753456d6ff5d979c422121d4a4edbe026aa56e1e9e2589c", "excluded_from_docs": false }, + { + "kind": "command", + "path": ".claude/commands/gaia-harden.md", + "name": "gaia-harden", + "description": "Judge-the-form, human-gated hardening. Reviews recurring code-review-audit findings and, with approval, drafts the lowest-context-weight form (deterministic check / skill / path-scoped prose rule) into the working tree. Pass `list` to see live candidates or `why ` to explain one.", + "audience": "adopter", + "content_hash": "a60e07393c994eb60ef41a8e63de92b5bfed764770dca0add9cc54323143aef2", + "excluded_from_docs": false + }, { "kind": "command", "path": ".claude/commands/gaia-init.md", "name": "gaia-init", "description": "Initialize a new project from the GAIA React template, renames, strips GAIA branding, configures i18n, installs Claude skills/plugins.", "audience": "adopter", - "content_hash": "3883456aaf563f83fa0651ae9e71390a9f6f95ad32c186624db08df080f2e0fc", + "content_hash": "fb81c89c41d64b496091595f002289c559acb95ff3f2d28b9cea164cc7018ae8", "excluded_from_docs": false }, { @@ -801,7 +855,7 @@ "name": "health-audit", "description": "Maintainer-only autonomous health audit + auto-heal loop. Runs N=3 fresh-team audit-fix-audit cycles with circuit breakers, reports an F-to-A+ verdict (folding in the shared Claude-integration fitness grade) or escalates.", "audience": "contributor", - "content_hash": "a8eabea49f36f803747e63a52f5504bc0899503f8d49699076668914b003b61c", + "content_hash": "a46ac6118ef3b94b354773989f90ac6e946be612aaf0172fec7c78914cc57528", "excluded_from_docs": false }, { @@ -810,7 +864,7 @@ "name": "setup-cloned-gaia-project", "description": "One-shot per-machine setup for a cloned GAIA project. Installs tools, plugins, spec-kit; bootstraps .env; opts into mentorship. Idempotent, safe to re-run.", "audience": "adopter", - "content_hash": "8f55331ad7893e3fa243ffb7042885ac8fd960b2177587b85c43a6faa5e37ee5", + "content_hash": "aed6325bbdfc19498172d1130de357df386874340a7ea88dc471d4787975c21b", "excluded_from_docs": false }, { @@ -826,25 +880,25 @@ "kind": "hook", "path": ".claude/hooks/audit-stamp-trailer.sh", "name": "audit-stamp-trailer.sh", - "description": null, + "description": "audit-stamp-trailer.sh, write the GAIA-Audit commit trailer on HEAD.", "audience": "adopter", - "content_hash": "baeae3b6e0007c555acb0d85aa28e6b13198dbcded47d454f72db594c4c4ad07", + "content_hash": "9bb3a31874f4b76bc14af6a556b92efab77e5adf16fda5f4b2e098c5e399440a", "excluded_from_docs": false }, { "kind": "hook", "path": ".claude/hooks/block-bare-test.sh", "name": "block-bare-test.sh", - "description": null, + "description": "Block bare `pnpm test` / `npm test` (and `run test` variants) without `--run`,", "audience": "adopter", - "content_hash": "bc63cfdf17bd8a7d6712e726dd8937e08a89823ba87d71af4ba3cddd9310dafd", + "content_hash": "679478ede41236df0dfb0fd0a180729911e44d268548dcea0a6b252ea444cf41", "excluded_from_docs": false }, { "kind": "hook", "path": ".claude/hooks/block-env-write.sh", "name": "block-env-write.sh", - "description": null, + "description": "PreToolUse Edit/Write hook: deny writes targeting `.env` files.", "audience": "adopter", "content_hash": "678a58957998a1e0c22c0e785bb9d933eb73f0712bcc5fc9f655d547aa3361b2", "excluded_from_docs": false @@ -853,7 +907,7 @@ "kind": "hook", "path": ".claude/hooks/block-eslint-config-edit.sh", "name": "block-eslint-config-edit.sh", - "description": null, + "description": "Block modifications to eslint.config.{js,cjs,mjs,ts} at any path.", "audience": "adopter", "content_hash": "e6675b7cb26af1cae095fe1b57991252887c3ea0a1a4fead77c80a015c27181f", "excluded_from_docs": false @@ -862,7 +916,7 @@ "kind": "hook", "path": ".claude/hooks/block-lockfile-edit.sh", "name": "block-lockfile-edit.sh", - "description": null, + "description": "PreToolUse Edit/Write hook: deny direct edits to package lockfiles.", "audience": "adopter", "content_hash": "5059a03ae4e3a362522703f8738b2b13aa5c45e49cce6b83362c6b88755d9570", "excluded_from_docs": false @@ -871,7 +925,7 @@ "kind": "hook", "path": ".claude/hooks/block-main-destructive-git.sh", "name": "block-main-destructive-git.sh", - "description": null, + "description": "PreToolUse Bash hook: block commits to main/master and force-push to main/master.", "audience": "adopter", "content_hash": "763dd1b32cfac206e54558e6bd00a4dd119513a5be182a9bba62e08d101d5f40", "excluded_from_docs": false @@ -880,7 +934,7 @@ "kind": "hook", "path": ".claude/hooks/block-no-verify.sh", "name": "block-no-verify.sh", - "description": null, + "description": "PreToolUse Bash hook: deny `git commit` / `git push` that carry a hook", "audience": "adopter", "content_hash": "8224cc4e2e7b8fd49846eebf4ffa075187704cbcbd8d1ec9b97c554e6f938d8d", "excluded_from_docs": false @@ -889,7 +943,7 @@ "kind": "hook", "path": ".claude/hooks/block-rm-rf.sh", "name": "block-rm-rf.sh", - "description": null, + "description": "PreToolUse Bash hook: deny dangerous `rm -rf` invocations.", "audience": "adopter", "content_hash": "876d755adf60c5659255f43cbcd9b872eb04a24f549c4a87357bfc1764fb5e3b", "excluded_from_docs": false @@ -898,7 +952,7 @@ "kind": "hook", "path": ".claude/hooks/block-secrets-write.sh", "name": "block-secrets-write.sh", - "description": null, + "description": "PreToolUse Edit/Write hook: deny writes that contain obvious secrets.", "audience": "adopter", "content_hash": "9cd17699fd43a9cd00d2d32f5f50e3c2b0b998bc17d515eddc082257ae1eaa08", "excluded_from_docs": false @@ -907,7 +961,7 @@ "kind": "hook", "path": ".claude/hooks/block-vitest-globals-tsconfig.sh", "name": "block-vitest-globals-tsconfig.sh", - "description": null, + "description": "Block adding vitest/globals to tsconfig.json", "audience": "adopter", "content_hash": "0a9e235b114393fbc49d35a775c4762dfeac7be56060f1083e0a3ec0a10e3672", "excluded_from_docs": false @@ -916,16 +970,16 @@ "kind": "hook", "path": ".claude/hooks/capture-red-observations.sh", "name": "capture-red-observations.sh", - "description": null, + "description": "PostToolUse Bash hook: OBSERVE-AND-RECORD half of the RED-verification gate.", "audience": "adopter", - "content_hash": "e2c33f23e9ac9a3c7f1dcb5d64ea32db7ba4904bb4d278a3e603b40f112f8f6f", + "content_hash": "52f6e19e7ad4c8a137509e6699a15d291d088833be40aa217793156b54b7699f", "excluded_from_docs": false }, { "kind": "hook", "path": ".claude/hooks/check-i18n-strings.sh", "name": "check-i18n-strings.sh", - "description": null, + "description": "Advisory check: warn about potential hardcoded strings in JSX.", "audience": "adopter", "content_hash": "7620e140933c8739ca56bbac111f3f9b4820a9bcdbc9e33696a1265da3824c72", "excluded_from_docs": false @@ -934,7 +988,7 @@ "kind": "hook", "path": ".claude/hooks/check-story-exists.sh", "name": "check-story-exists.sh", - "description": null, + "description": "Advisory check: remind to add Storybook story for new components", "audience": "adopter", "content_hash": "7e2dd46c8e8ccbb605e2064879a4893e71f442bb6f1149d98584bc8290f602cb", "excluded_from_docs": false @@ -943,34 +997,43 @@ "kind": "hook", "path": ".claude/hooks/intercept-init.sh", "name": "intercept-init.sh", - "description": null, + "description": "Redirect the built-in /init command to /gaia-init on this template.", "audience": "adopter", "content_hash": "91befea795ab9311a80c740f11af3ea69ae405ba75195ccda2ed1ad5b455b202", "excluded_from_docs": false }, + { + "kind": "hook", + "path": ".claude/hooks/post-audit-status.sh", + "name": "post-audit-status.sh", + "description": "post-audit-status.sh, post the GAIA-Audit success commit status on HEAD.", + "audience": "adopter", + "content_hash": "b517948c4ccd492d3e7031755711e8446d6a835ffc4cfe2026abe096eae44a5e", + "excluded_from_docs": false + }, { "kind": "hook", "path": ".claude/hooks/pr-merge-audit-check.sh", "name": "pr-merge-audit-check.sh", - "description": null, + "description": "PreToolUse Bash hook: BLOCK `gh pr merge` until proof of a passing", "audience": "adopter", - "content_hash": "ad83f3970d641f26c177511b85475cb0147febe767a6604c7ad219d655cc177a", + "content_hash": "2693d05ca41486c4ff28c6da7be80e01370a073c0a880a6ef7008f8ae1b7c821", "excluded_from_docs": false }, { "kind": "hook", "path": ".claude/hooks/red-verify-commit-check.sh", "name": "red-verify-commit-check.sh", - "description": null, + "description": "PreToolUse Bash hook: DENY `git commit` when a new-at-HEAD test that now", "audience": "adopter", - "content_hash": "45c18d0120d286d9557a67551c50ed621c8fca7cef6c4dde5dd83b5e517c05f3", + "content_hash": "39fe79c3e7f674deab66cbb9ad59ad0b39662a3b8f9d9c01d55faca68a3aa871", "excluded_from_docs": false }, { "kind": "hook", "path": ".claude/hooks/telemetry-task-postuse.sh", "name": "telemetry-task-postuse.sh", - "description": null, + "description": "PostToolUse Task hook: extract structured-trailer events from the agent's", "audience": "adopter", "content_hash": "12f64685fdfaf273b47d3dc96d4773faa922a661a84fbcdb15cb9f059e94645d", "excluded_from_docs": true @@ -979,7 +1042,7 @@ "kind": "hook", "path": ".claude/hooks/wiki-commit-nudge.sh", "name": "wiki-commit-nudge.sh", - "description": null, + "description": "PostToolUse hook on Bash matching `git commit`. Inject a one-line nudge", "audience": "adopter", "content_hash": "ae9b39f5b54a8cf5afd1c586c58b8494e793da84a6c7bf2375122caadbdb3b49", "excluded_from_docs": false @@ -988,16 +1051,34 @@ "kind": "hook", "path": ".claude/hooks/wiki-drift-check.sh", "name": "wiki-drift-check.sh", - "description": null, + "description": "UserPromptSubmit hook: detect drift between wiki/.state.json and HEAD,", "audience": "adopter", "content_hash": "bb0ed860b83522f74d599969cb7346ba349891139a1f7e5c41cfb6d6d0f22908", "excluded_from_docs": false }, + { + "kind": "hook", + "path": ".claude/hooks/wiki-recompact-inject.sh", + "name": "wiki-recompact-inject.sh", + "description": "GAIA-owned wiki hook. Pairs with wiki-recompact-sentinel.sh (PostCompact).", + "audience": "adopter", + "content_hash": "d131a6fbb89c34287355fe5275e7819027ad45aedc9b0edb1dec56b07ddd0ad7", + "excluded_from_docs": false + }, + { + "kind": "hook", + "path": ".claude/hooks/wiki-recompact-sentinel.sh", + "name": "wiki-recompact-sentinel.sh", + "description": "GAIA-owned wiki hook. Upstream contract: claude-obsidian/hooks/hooks.json::PostCompact", + "audience": "adopter", + "content_hash": "2d6364bbc987106aec39292256a6a6ec0835edd095e7b241b9fe7c4c2f154aac", + "excluded_from_docs": false + }, { "kind": "hook", "path": ".claude/hooks/wiki-session-start.sh", "name": "wiki-session-start.sh", - "description": null, + "description": "GAIA-owned wiki hook. Upstream contract: claude-obsidian/hooks/hooks.json::SessionStart", "audience": "adopter", "content_hash": "52d96a0714471784c50a71796f7729699b035df100ef00bc9cbe63f9358ecc63", "excluded_from_docs": false @@ -1006,7 +1087,7 @@ "kind": "hook", "path": ".claude/hooks/wiki-session-stop.sh", "name": "wiki-session-stop.sh", - "description": null, + "description": "GAIA-owned Stop hook (merged: session-stop + safety-net).", "audience": "adopter", "content_hash": "9118a931cd15ef635e5bff82baf83487b9dc9c70e313b859d1a63fd6fbf66436", "excluded_from_docs": false @@ -1015,11 +1096,20 @@ "kind": "hook", "path": ".claude/hooks/wiki-squash-autocommits.sh", "name": "wiki-squash-autocommits.sh", - "description": null, + "description": "GAIA-owned wiki hook. Upstream contract: claude-obsidian/hooks/hooks.json::PostToolUse (auto-commit per Write|Edit)", "audience": "adopter", "content_hash": "714323b380e18f2b72da97ae412b1e5dc06666148b5af325c05909d0448b44d3", "excluded_from_docs": false }, + { + "kind": "hook", + "path": ".claude/hooks/worthiness-presence-check.sh", + "name": "worthiness-presence-check.sh", + "description": "PreToolUse Bash hook: DENY `gh pr merge` when an emergent test the PR changed", + "audience": "adopter", + "content_hash": "2c2aee45cd71c49ef5b84bf2a1b5995e9531674d5215d8aef3fcbc891934008d", + "excluded_from_docs": false + }, { "kind": "rule", "path": ".claude/rules/accessibility.md", @@ -1044,25 +1134,25 @@ "name": "code-search", "description": "Code Search", "audience": "adopter", - "content_hash": "27006e808f53716a7cf07ef6e3b9bbda767b57735f826c90cced24686a764629", + "content_hash": "efeb58ae10f60e8c0a2ebff7b36a5f99b42b4c2eca6657169ccab357d1ab518e", "excluded_from_docs": false }, { "kind": "rule", "path": ".claude/rules/coding-guidelines.md", "name": "coding-guidelines", - "description": "Coding Guidelines", + "description": null, "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "a35c18ebcb7fc4f00f24d5a6b3151f096c0eeb0b96f839dc903bca86068dd599", "excluded_from_docs": false }, { "kind": "rule", "path": ".claude/rules/dep-audit.md", "name": "dep-audit", - "description": "Dependency-CVE Advisory, pnpm audit", + "description": null, "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "0219c0d013c0f4bd516a9a5e5b05852c36527f3bd7abdc05c9e9e5506210053e", "excluded_from_docs": false }, { @@ -1071,7 +1161,7 @@ "name": "i18n", "description": "Internationalization (i18n)", "audience": "adopter", - "content_hash": "44c79ba4d5fb3659eba0b3806b1c5493b90ce5efdc2f262af68674d2e437f448", + "content_hash": "017b5aa6e2f272912589fdc1cbc574204059370a0fb54af29b32d0e12c393d1b", "excluded_from_docs": false }, { @@ -1087,9 +1177,9 @@ "kind": "rule", "path": ".claude/rules/knip.md", "name": "knip", - "description": "Knip, Dead Code Detection", + "description": null, "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "5692324ef2966686d34e02b31601eb5c0137d632f531da43a1280d46d959cd15", "excluded_from_docs": false }, { @@ -1105,18 +1195,33 @@ "kind": "rule", "path": ".claude/rules/pr-merge.md", "name": "pr-merge", - "description": "PR Merge", - "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "excluded_from_docs": false + "description": null, + "audience": "mixed", + "content_hash": "6ab8f8ca1da2dc13bab0fc6fc66ead258eef1d313c49c25e2650dacc98027031", + "excluded_from_docs": false, + "marker_blocks": [ + [ + 5, + 7 + ] + ] }, { "kind": "rule", "path": ".claude/rules/quality-gate.md", "name": "quality-gate", - "description": "Quality Gate", + "description": null, + "audience": "adopter", + "content_hash": "9ef50cd3ba27504641fca9018ad8fea1ced7a6492b8e6a5a86f6691c06890d96", + "excluded_from_docs": false + }, + { + "kind": "rule", + "path": ".claude/rules/react-router-docs.md", + "name": "react-router-docs", + "description": "React Router Docs", "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "25827562af72388f2cdb54c259a1e55731696e64b0758b272e8cb9aa96677540", "excluded_from_docs": false }, { @@ -1132,9 +1237,9 @@ "kind": "rule", "path": ".claude/rules/shell-cwd.md", "name": "shell-cwd", - "description": "Shell CWD", + "description": null, "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "40128f142d1d7e34ad204c8d5dc5c47fdbd06fe29b1b8fbba56778a7d312949c", "excluded_from_docs": false }, { @@ -1143,7 +1248,7 @@ "name": "state-pattern", "description": "State Pattern", "audience": "adopter", - "content_hash": "467614e6c023147cedf77e183989f70c88d07bc4d168e4ad677f0cfdda466300", + "content_hash": "80faacf9f64e65ed5f366feb8f178934dcb58cec14d4cc6cf9e1e5a8528503f1", "excluded_from_docs": false }, { @@ -1169,17 +1274,23 @@ "path": ".claude/rules/wiki-style.md", "name": "wiki-style", "description": "Wiki & Comment Style", - "audience": "adopter", - "content_hash": "4e3158c571842b8765b0817d7e5bf92118599d149992896f9cf0bc1310bfa9bc", - "excluded_from_docs": false + "audience": "mixed", + "content_hash": "a66bc8986fd0413f5bdbb1fee631b6cb077875b41ddf6680d063b15b86bef870", + "excluded_from_docs": false, + "marker_blocks": [ + [ + 27, + 29 + ] + ] }, { "kind": "skill", "path": ".claude/skills/a11y-fixes/SKILL.md", "name": "a11y-fixes", - "description": "Resolve axe-core accessibility violations reported by Vitest (test/a11y.ts), Playwright (.playwright/a11y.ts), or the code-review-audit agent's a11y bucket. Use when fixing violations like color-contrast, label, label-title-only, image-alt, button-name, link-name, region, landmark-one-main, heading-order, aria-allowed-attr, aria-required-attr, aria-required-children, aria-required-parent, aria-valid-attr-value, focus-trap, tabindex, html-has-lang, document-title, duplicate-id, listitem, definition-list. Trigger on any axe rule id appearing in test output.", + "description": "Resolve axe-core accessibility violations reported by Vitest (test/a11y.ts), Playwright (.playwright/a11y.ts), or the code-review-audit agent's a11y bucket. Trigger on any axe rule id appearing in test output, not only the ones named here. Contains fix patterns for the most common violations (color-contrast, label, label-title-only, image-alt, button-name, link-name, region, landmark-one-main, heading-order, aria-allowed-attr, aria-required-attr, aria-required-children, aria-required-parent, aria-valid-attr-value, focus-trap, tabindex, html-has-lang, document-title, duplicate-id, listitem, definition-list); for any violation not listed, apply the general axe guidance and the same fix-then-verify loop.", "audience": "adopter", - "content_hash": "d68afa8fa14598fb1fee9194a280c0b76dbcfb17e2ce5d71ad5326630cfc5938", + "content_hash": "09c7fa8cc920643553f782f78a5a3b5e393e669a9e0707469dd6d5eef3a9d817", "excluded_from_docs": false }, { @@ -1209,6 +1320,15 @@ "content_hash": "7f5d86c8c16a0d86aa07dc9108cc4222013fab6f10ac6b91421b4214ba6cb946", "excluded_from_docs": false }, + { + "kind": "skill", + "path": ".claude/skills/gaia-react-perf/SKILL.md", + "name": "gaia-react-perf", + "description": "Diagnose React render performance by driving a micro-interaction, capturing real renders, and surfacing memo-defeating reference instability with a recommended structural fix. Measure-only: it emits a diagnosis, it does not auto-fix. Trigger on `/gaia-react-perf` or natural-language asks like \"profile renders\", \"measure renders\", \"why is X re-rendering\", or \"diagnose render performance\". Do NOT trigger on vague \"feels slow\", \"janky\", or \"optimize my app\".", + "audience": "adopter", + "content_hash": "6a825b1a8e72ce9c7a44acf4100491949ef65a949af6c64d9a004f2a4c195a90", + "excluded_from_docs": false + }, { "kind": "skill", "path": ".claude/skills/gaia-wiki/SKILL.md", @@ -1224,7 +1344,7 @@ "name": "new-component", "description": "Scaffold a new React component with optional Storybook story and Vitest test files. Use this skill whenever the user asks to \"create a component\", \"make a button\", \"scaffold a card\", \"add a new component\", or asks for a new file under `app/components/` following the project's component pattern (PascalCase folder, index.tsx, tests/).", "audience": "adopter", - "content_hash": "5575989b1bd84fa2a88a8ff28645c1e7aeb78f2915ed9a953bec893871776997", + "content_hash": "193e4dad08d5482d1727b2ae9dffbed92d658eebf4254e5af88a40330deb9a25", "excluded_from_docs": false }, { @@ -1240,9 +1360,9 @@ "kind": "skill", "path": ".claude/skills/new-route/SKILL.md", "name": "new-route", - "description": "Scaffold a new route with its page component, test, story, and optional i18n keys. Use this skill whenever the user asks to \"create a route\", \"add a new page\", \"scaffold /dashboard\", \"wire up a new route under _public+ or _session+\", or anything that implies adding a file under `app/routes/` with a matching `app/pages/{Group}/{PageName}/` folder.", + "description": "Scaffold a new route with its page component, test, story, and optional i18n keys. Use this skill whenever the user asks to \"create a route\", \"add a new page\", \"scaffold /dashboard\", \"wire up a new route under _public+ or _session+\", or anything that implies adding a file under `app/routes/` with a matching `app/pages/{Group}/{PascalName}Page/` folder.", "audience": "adopter", - "content_hash": "a7be8023411be4cf8146230aa5715e3967f99c5dc9e0229d69d02418d1a0e8e1", + "content_hash": "7a28123bd547be49e8a3340496cddc528bc48420d289459e59f2c901def34294", "excluded_from_docs": false }, { @@ -1267,9 +1387,9 @@ "kind": "skill", "path": ".claude/skills/react-code/SKILL.md", "name": "react-code", - "description": "Patterns and conventions for writing and editing React code, including components and hooks. Use this skill whenever writing or reviewing React components, hooks (useEffect, useCallback, useState), event handlers, or component extraction decisions. Also trigger when debugging stale closures, infinite re-renders, or unnecessary re-renders caused by memoization issues.", + "description": "Patterns and conventions for writing and editing React code, including components and hooks. Use this skill whenever writing or reviewing React components, hooks (useEffect, useCallback, useState), event handlers, or component extraction decisions. Also trigger when debugging stale closures, infinite re-renders, or unnecessary re-renders caused by memoization issues, or when deciding whether to add a dependency, reach for a web-platform API (Intl, URL, crypto.randomUUID), or hand-roll a primitive. Also trigger when choosing a React 19 idiom, deciding between forwardRef and ref-as-prop, useContext and use(), or Context.Provider and the Context shorthand; when conditional rendering risks the && numeric-0 leak; or when tempted to reach for React's form Actions (useActionState, useFormStatus, useOptimistic) instead of React Router's form handling.", "audience": "adopter", - "content_hash": "9847f31a309569a9dfa84c558e288a4ad06f29ed017f5056aae486e0ab7f822b", + "content_hash": "0c02706a5ba3b235211c461097f1f0ad08708e3749be67a32562145a2856216a", "excluded_from_docs": false }, { @@ -1287,7 +1407,7 @@ "name": "skeleton-loaders", "description": "For building skeleton loading states that are pixel-perfect matches of real content. Use this skill whenever adding loading states to components, building skeletons for async data, handling pending loader states in route transitions, or implementing the shimmer animation pattern. Also trigger when the user asks about preventing layout shift during data fetching.", "audience": "adopter", - "content_hash": "53d4021e2ec3b39a441900994726bc75df38adfaec2e7e328ab9471fe512044b", + "content_hash": "dcb705dcefaa30b8e41360dd75e60afe9002c6a7eda6d7759e6245fd447c4b79", "excluded_from_docs": false }, { @@ -1323,7 +1443,7 @@ "name": "update-deps", "description": "Autonomous Dependabot, auto-discover outdated packages, audit overrides, apply migrations for major bumps, resolve conflicts, run quality gate. Trigger when the user clicks the statusline `Run /update-deps` indicator or asks \"update dependencies\", \"bump deps\", \"run dependabot\".", "audience": "adopter", - "content_hash": "6c31163f5316748ff65805fcec88207ac4307dae1a9eb8c13824ff2a76677869", + "content_hash": "79bcaeb956ab5a7dd8155e0bab8507d8c02b6b1da913e8adb51345c3b10ad132", "excluded_from_docs": false }, { @@ -1339,25 +1459,25 @@ "kind": "spec-kit-cmd", "path": ".specify/extensions/gaia/commands/constitution-check.md", "name": "speckit.gaia.constitution-check", - "description": "GAIA before_specify hook: constitution placeholder check + spec-kit version-pin drift detection.", + "description": "Verify .specify/memory/constitution.md has no placeholder text before /speckit.specify runs.", "audience": "adopter", - "content_hash": "88ab004fc467cd49df1cd091a0b8701ac139dd5283e32f3b56d022fe90df36aa", + "content_hash": "8fb7e4d0da8600304f7aebdc275c68e3a5c3e57aa72c4efc4e0e3ff635338916", "excluded_from_docs": false }, { "kind": "spec-kit-cmd", "path": ".specify/extensions/gaia/commands/lint.md", "name": "speckit.gaia.lint", - "description": "GAIA after_specify hook: immutability lint over the just-written SPEC artifact.", + "description": "Immutability lint over a saved SPEC artifact: frontmatter, frozen UAT-NNN ids, no placeholders.", "audience": "adopter", - "content_hash": "05b8c2cee7097a38833e0ee7cf158c7cfb120026a46e72d9d6e3df00db2b94eb", + "content_hash": "7ce7755041d318a3819eb1e6988eeb510dbf8e21ab23e7e6f966b6d00efdd0d3", "excluded_from_docs": false }, { "kind": "spec-kit-cmd", "path": ".specify/extensions/gaia/commands/self-review.md", "name": "speckit.gaia.self-review", - "description": "GAIA after_clarify hook: pre-gate-2 self-review pass on the in-progress SPEC draft.", + "description": "Pre-gate-2 self-review pass; surfaces drift, ambiguity, and pending clarifications before save.", "audience": "adopter", "content_hash": "02973f87cbfc2375e4fa52e9be7d000e6096b359e3b9a46000d9fa7bbb9250f9", "excluded_from_docs": false @@ -1366,7 +1486,7 @@ "kind": "spec-kit-cmd", "path": ".specify/extensions/gaia/commands/spec.md", "name": "speckit.gaia.spec", - "description": "GAIA Socratic discovery wrapper around /speckit-specify and /speckit-clarify.", + "description": "GAIA Socratic discovery wrapper around /speckit.specify and /speckit.clarify.", "audience": "adopter", "content_hash": "41123447df9a84aedcef19e7a136674e6c1e85b86d37a2b4de3446f511a80ec4", "excluded_from_docs": false @@ -1375,18 +1495,18 @@ "kind": "spec-kit-cmd", "path": ".specify/extensions/gaia/commands/spec-close.md", "name": "speckit.gaia.spec-close", - "description": "Close a SPEC after implementation+merge. Optional drain of deferred wiki-promote, then disposition prompt (archive / delete / keep) for the local SPEC artifact.", + "description": "Close a SPEC after implementation+merge: optional drain of deferred wiki-promote, then archive/delete/keep prompt for the local SPEC artifact.", "audience": "adopter", - "content_hash": "501b1b27693e54369cab6339c39c102c2976012c9da7bd74c685ada5181ceacb", + "content_hash": "8d7ec1aa092a9e328c8592bb70767aea963d06ca17c85e56d4b03ec31e62fd4d", "excluded_from_docs": false }, { "kind": "spec-kit-cmd", "path": ".specify/extensions/gaia/commands/uat-write.md", "name": "speckit.gaia.uat-write", - "description": "GAIA before_implement hook: render PO-authored UATs into Playwright e2e specs at .playwright/e2e/spec-NNN/.", + "description": "before_implement hook: render PO-authored UATs into Playwright e2e specs at .playwright/e2e/spec-NNN/.", "audience": "adopter", - "content_hash": "73682b988bac6e56bcd49c45a36e4b7b14ad57dfe00c487dd57ce4a56f45e641", + "content_hash": "dbd6e30322a93d2fa62e74907982d24b19b54273407923816854abee9cfb4433", "excluded_from_docs": false }, { @@ -1395,106 +1515,115 @@ "name": "speckit.gaia.wiki-promote", "description": "Promote merged SPEC content into the GAIA wiki.", "audience": "adopter", - "content_hash": "0d813e6b39a7b96bfd0f902ee1bd7c42985c4c7e90ba95675bac5cf8669596fa", + "content_hash": "b5a0b4de826b5aacbfca1c7f3631859872785b5ae524c73e5e30a759c36f4499", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/audit.md", "name": "/gaia audit", - "description": "/gaia-audit", + "description": "**Do not execute the playbook yourself in the current conversation.** Dispatch the Stage 1 and Stage 2 subagents via the `Agent` tool. Each subagent runs in isolated context. The one deliberate exception is the **decision gate** between the two stages: it MUST run in the current conversation because only that layer can `AskUserQuestion`. Do not \"fix\" the gate back into a subagent.", "audience": "adopter", - "content_hash": "bf1ff5d5d44e0ae23c174a206cf8d7e7e48fc2d754d1ef55f2ae7d4f7c5be5c8", + "content_hash": "09f6f801c4fddff438cad7a1afce6433adf9f581c9cae76a1f4cfbee481f29d2", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/fitness.md", "name": "/gaia fitness", - "description": "/gaia-fitness", + "description": "`/gaia-fitness` is the Claude-integration health check + auto-heal. One invocation, no flag required, calling `/gaia-fitness` is the statement of intent to be fit. It runs three phases in sequence: triage \u2192 heal \u2192 verify.", "audience": "adopter", - "content_hash": "a3c17c54b41d52657d1e89630d42b70cbfda3e0a77fc883866d9375d8428d717", + "content_hash": "2c3fdd100a60bc7d8baabf8f1ba689a586c0832a78e88b94ee7bbd8b13fb796c", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/forensics.md", "name": "/gaia forensics", - "description": "/gaia-forensics", + "description": "Turn a GAIA workflow misfire into a redacted, classified, filing-ready bug report in one invocation. Read-only end-to-end: no remediation, no autofix, no state mutation.", "audience": "adopter", - "content_hash": "f234c2eebd9c07b7755963b4dfe8b5ec63320c411d76b923520e600ebf740260", + "content_hash": "757e60d1ca3e1b10f9b037878b6890388e99ebc8535d1e28519adb05bce9a19f", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/handoff.md", "name": "/gaia handoff", - "description": "/gaia-handoff", + "description": "Write a self-contained handoff doc so the next session can pick up cold without re-reading this conversation.", + "audience": "adopter", + "content_hash": "2d9e99f7df3d454a59e78e8ae347582e856d6ad6eb2f2562b739948dabdd638d", + "excluded_from_docs": false + }, + { + "kind": "sub-route", + "path": ".claude/skills/gaia/references/harden.md", + "name": "/gaia harden", + "description": "Human-gated hardening for the policy-memory loop. `/gaia-harden` is the ONLY code path that authors or activates anything in this loop, and it runs only under explicit human invocation. For each recurring finding it judges the lowest-context-weight form that fits, checks edit-vs-new first, recommends exactly one form with rationale, and presents an approve / decline / defer / redirect choice. Nothing is authored or activated unattended.", "audience": "adopter", - "content_hash": "6770dde315f94105a81bb0a7f0a751f806e7a40822b112a1374e7d170ab34910", + "content_hash": "cb5c47b7dd97cf7d51be9b8418505b4bf143ed256276b7093d64f8afe43d803a", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/pickup.md", "name": "/gaia pickup", - "description": "/gaia-pickup", + "description": "Rebuild \"where did we leave off\" at session start and suggest the next action.", "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "5669ee565ec1eea7d37203198a8113823277ecb6d2ad076a26b0d780c818185c", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/plan.md", "name": "/gaia plan", - "description": "/gaia-plan", + "description": "Plan a complex feature using the task orchestration pattern. Do not implement anything.", "audience": "adopter", - "content_hash": "6ca5e93bd38331dc979c8e2bc355b1b77557d90fc6ca68c1d436002ae9d9d2bb", + "content_hash": "765dc6a47bedd76f30f40547e7867f25794fb904b10b9f580f43dc0c29ecdf67", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/spec.md", "name": "/gaia spec", - "description": "/gaia-spec", + "description": "Socratic discovery wrapper around spec-kit. Produces an immutable SPEC artifact at `.gaia/local/specs/SPEC-NNN/SPEC.md` and prompts to chain into `/gaia-plan`. Do not implement anything, this skill produces an artifact and stops.", "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "2a8bb19b33d9f08d38fd35762c1c67e2a85c7641f2ab3046225848a26e01566e", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/wiki.md", "name": "/gaia wiki", - "description": "/gaia-wiki", + "description": "Wiki-maintenance router. Sub-commands run individually or chain end-to-end.", "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "6252229ca2476d2f9998c0fa89617bc8bbf151c6910657ec979e35e8f0a5da8f", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/wiki/consolidate.md", "name": "/gaia wiki consolidate", - "description": "wiki-consolidate playbook", + "description": "Dispatched by the `/gaia-wiki` router (`references/wiki.md` \u2192 \"Consolidate\"). Detection runs in a Sonnet subagent; apply/state/report run in the parent.", "audience": "adopter", - "content_hash": "22f078744907fd72456da8be2a44802b7446743bfdfa5fac5e07355ba658ffb9", + "content_hash": "a8d4b66e51675b1beafbfa3e2a134c9d0d0114e450841bd3dd07eab143be6caa", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/wiki/lint.md", "name": "/gaia wiki lint", - "description": "wiki-lint playbook", + "description": "Dispatched by the `/gaia-wiki` router (`references/wiki.md` \u2192 \"Lint\"). Runs in a Haiku subagent context.", "audience": "adopter", - "content_hash": "5d1ba52cf9420bc7a92cf27238281f3bc55cec25faf15a2fafa8f083c7dd4501", + "content_hash": "5990261d5b9b19e4cab948ba371f0755adc4fe95b4132288e2b6b68198960973", "excluded_from_docs": false }, { "kind": "sub-route", "path": ".claude/skills/gaia/references/wiki/sync.md", "name": "/gaia wiki sync", - "description": "wiki-sync playbook", + "description": "Dispatched by the `/gaia-wiki` router (`references/wiki.md` \u2192 \"Sync\"). Runs in a Sonnet subagent context.", "audience": "adopter", - "content_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "content_hash": "f8710c787676c9f726e43c32e3c08ceac9e76620f0f03451316b6535f1a5e600", "excluded_from_docs": false }, { @@ -1522,7 +1651,7 @@ "name": "wiki/components/Form Choices.md", "description": "Form Choices", "audience": "adopter", - "content_hash": "2fb7ac49ada39e573af47872a5617674013a26e85229688689c8e094fb3b792a", + "content_hash": "50a3c5fccae2a173a588ecd35a35541b63b3c137bb6881f5a206d79b857c2e27", "excluded_from_docs": false }, { @@ -1531,7 +1660,7 @@ "name": "wiki/components/Form Field.md", "description": "Form Field", "audience": "adopter", - "content_hash": "bb4bc8d2e73096ed14f9e8261ed6ad9cb52d1d4036c9fc3d201fe18b0045e4a6", + "content_hash": "2cdc69e2547f413b7ee546eaa163390f8ebee82d34717a63efacdfa51f828e13", "excluded_from_docs": false }, { @@ -1540,7 +1669,7 @@ "name": "wiki/components/Form Layout.md", "description": "Form Layout", "audience": "adopter", - "content_hash": "7657eb728be5e1441b96945618666fdc810a48b80ac499b5c2822595ed5d702f", + "content_hash": "ea945e02af4744c2877912294fbbacb23f82f1cc571075118bf2507328d9a8a3", "excluded_from_docs": false }, { @@ -1558,7 +1687,7 @@ "name": "wiki/components/Form Text Inputs.md", "description": "Form Text Inputs", "audience": "adopter", - "content_hash": "2e09a7c16350afae039a6f1a0f91821c4739ac5d5c5af880cbe2089bbace19d2", + "content_hash": "35737ae7afa41545d131c39ea22923a2b8a3718c6fded6c12f62b562953b2f59", "excluded_from_docs": false }, { @@ -1576,7 +1705,7 @@ "name": "wiki/concepts/API Service Pattern.md", "description": "API Service Pattern", "audience": "adopter", - "content_hash": "b1dff6ec95645fe5789119890a955bda6bbfdd7acd07bc4ce76672def211f782", + "content_hash": "b476892aaaaa53fb1326afd16c73dc75b99bed080b7a2bdcd6862b16dfaf97c8", "excluded_from_docs": false }, { @@ -1585,16 +1714,7 @@ "name": "wiki/concepts/Accessibility.md", "description": "Accessibility", "audience": "adopter", - "content_hash": "c7e49fdca13cefdedd430edcb28a8aa0873d32d14cf17b54dcad3a352145dfac", - "excluded_from_docs": false - }, - { - "kind": "wiki-page", - "path": "wiki/concepts/Agentic Design.md", - "name": "wiki/concepts/Agentic Design.md", - "description": "Agentic Design", - "audience": "adopter", - "content_hash": "5cbf27f3ac4b7d161259b99a6156340f90811f641fc4f134f14d17c4d059df87", + "content_hash": "6ffe1c6ea70370daa76ea93698a75f16bfa6468ac4292d33934431ee6bf75721", "excluded_from_docs": false }, { @@ -1603,7 +1723,7 @@ "name": "wiki/concepts/Chromatic Opt-Out.md", "description": "Chromatic Opt-Out", "audience": "adopter", - "content_hash": "eceb0c501eb60a2ccd88a9ee8eb9b151b2df19f71d1a6dc25741a29070f174b3", + "content_hash": "d731383464b37c19c36b2e092a5cb0921ce66bfd4d52f09f05c950ae7c2fd88b", "excluded_from_docs": false }, { @@ -1612,7 +1732,7 @@ "name": "wiki/concepts/Claude Hooks.md", "description": "Claude Hooks", "audience": "adopter", - "content_hash": "f4aee5f3b165dddc44ea4c18f66c4fd29a09789c8c3741cc9b80a3af473c5fed", + "content_hash": "1cfcb19751769ba6757ac4eff1733ad86afb442b158f0ff3bf8bd93bc3a89005", "excluded_from_docs": false }, { @@ -1621,7 +1741,7 @@ "name": "wiki/concepts/Claude Integration Conventions.md", "description": "Claude Integration Conventions", "audience": "adopter", - "content_hash": "baad4c0fb45f3917a1b80920219e23393b5e55e6015220dd26e868960b10e6e1", + "content_hash": "3c9ea00dd872728af5ca2420961abc49293b6dd4560221390ab87e33f24a86ff", "excluded_from_docs": false }, { @@ -1630,7 +1750,7 @@ "name": "wiki/concepts/Claude Skills.md", "description": "Claude Skills", "audience": "adopter", - "content_hash": "c4e3b933e8f6a8687c219e5ae95233aae6937b14ce3a6e032afea4173029f4ac", + "content_hash": "cdcae096d3d7545e0bb4137ef455f462518f0e5982a02ee0f3a1992cf51e4833", "excluded_from_docs": false }, { @@ -1639,7 +1759,7 @@ "name": "wiki/concepts/Code Review Audit Agent.md", "description": "Code Review Audit Agent", "audience": "adopter", - "content_hash": "10ea4793919e047b4e796e2b1b49b33b59ee87e1511fa1475be8bdc2d69e2214", + "content_hash": "69f04806b2460988f62755afe1ee4b3122c040b0441141a765df4fb470547545", "excluded_from_docs": false }, { @@ -1648,7 +1768,7 @@ "name": "wiki/concepts/Code Review Audit CI.md", "description": "Code Review Audit CI", "audience": "adopter", - "content_hash": "c5e252bee9f81b03defde0bed498192aac1dea2c950f2ef2a3a79f472729f6ee", + "content_hash": "04b24b6ccff23d8eeba0a138775265bb6fa208efb84e654fea39d8464652dedf", "excluded_from_docs": false }, { @@ -1666,7 +1786,7 @@ "name": "wiki/concepts/Component Testing.md", "description": "Component Testing", "audience": "adopter", - "content_hash": "ca035aeef658522533b498916580485edde7f38b0fe11cd63aeca65a8b49b358", + "content_hash": "d0deb4aee6184c685eabd3014ea99bcc5a5ee76f14f09b9ac274a01fb074596e", "excluded_from_docs": false }, { @@ -1675,7 +1795,7 @@ "name": "wiki/concepts/ESLint Fixes.md", "description": "ESLint Fixes", "audience": "adopter", - "content_hash": "af57b4f79fe5f66fed41c8be3b2850a19ea4d18cdaf0d0388bba6acfa7fbb778", + "content_hash": "78e6040d6ea481ab533c277eb0d126d4f14a06a3e034faf333cacf63909ff786", "excluded_from_docs": false }, { @@ -1684,7 +1804,7 @@ "name": "wiki/concepts/Forensics.md", "description": "Forensics", "audience": "adopter", - "content_hash": "779762f8075f188bb410cd0684d77b1212ca3d51be4e2ac4a89a082179a0189c", + "content_hash": "21cfad2dee3af04dadcd888008588147a80fdcfcfe86693d681b70f26bcfebbe", "excluded_from_docs": false }, { @@ -1693,7 +1813,7 @@ "name": "wiki/concepts/GAIA Audit.md", "description": "GAIA Audit", "audience": "adopter", - "content_hash": "42af1d0c9b2785d7bbb5874c205f02c705eb7c4599692622ab96ade9380eb135", + "content_hash": "070ffc0fb37d6071e63aa58c39d031341812428b8cf7de1b819a65e0eb14d7cf", "excluded_from_docs": false }, { @@ -1702,7 +1822,7 @@ "name": "wiki/concepts/GAIA Handoff.md", "description": "GAIA Handoff", "audience": "adopter", - "content_hash": "f14704285acc8d3dce637eba9c19a3e66b9857ae797bfce2a4b9dbfa81b66e4a", + "content_hash": "ea98300d1b1c032c543de4f1cfa2f463669a257eb19e354c5f1d7272ec0b0cc6", "excluded_from_docs": false }, { @@ -1711,7 +1831,7 @@ "name": "wiki/concepts/GAIA Init Workflow.md", "description": "GAIA Init Workflow", "audience": "adopter", - "content_hash": "400a5ef2ba17a7187994fe8859d6c28c08c6a88ea4eee44a597c0e75e99afd18", + "content_hash": "85d2c96a115c3b4d170f4b50e23b053069147d2ebc0264b05636cda79e76851c", "excluded_from_docs": false }, { @@ -1720,7 +1840,7 @@ "name": "wiki/concepts/GAIA Philosophy.md", "description": "GAIA Philosophy", "audience": "adopter", - "content_hash": "81b8d154ebc9417f407eedb7ba6859e411c78719fa2e39ebb6f8f52e0afe4400", + "content_hash": "e325e1b28cb2fed9919281a6b6316758b170bd626a8e6368fe6b068c991c3395", "excluded_from_docs": false }, { @@ -1729,7 +1849,7 @@ "name": "wiki/concepts/GAIA Pickup.md", "description": "GAIA Pickup", "audience": "adopter", - "content_hash": "d68a80267e35170b4ddd030af93c95599a8419b445113cd6739ac458139792af", + "content_hash": "ee34ca9dbb2c75fa1851d110bcb414cf1f0bac642af5136c7e72c3e95a32ae04", "excluded_from_docs": false }, { @@ -1738,7 +1858,7 @@ "name": "wiki/concepts/GAIA Plan.md", "description": "GAIA Plan", "audience": "adopter", - "content_hash": "cbb76f981b2329d3e0c27e53063c250e9fe39698a224f0827382a22933d67dab", + "content_hash": "ce1161a2898e60e0bb4560d464a601cffa0d11f3f2b05753e261dc6769801e49", "excluded_from_docs": false }, { @@ -1747,7 +1867,7 @@ "name": "wiki/concepts/GAIA Spec.md", "description": "GAIA Spec", "audience": "adopter", - "content_hash": "2a7382fdace509e4d832c43261a170c884ed65ae8d8a5e1f79e83ecbeb9dbfc0", + "content_hash": "894248492e5a48be0ce0cf777448c3569100ba7cd2fac4bf8ebc86327daacb65", "excluded_from_docs": false }, { @@ -1756,7 +1876,7 @@ "name": "wiki/concepts/Git Workflow.md", "description": "Git Workflow", "audience": "adopter", - "content_hash": "e7fbbafcb98835ceed26cdd0dddc515d9fca25af1c248cebed06708111c94ecf", + "content_hash": "741b330e33b2566565da6f7daf0c2552631a89703126acfa5ecb97a484b60ad6", "excluded_from_docs": false }, { @@ -1765,7 +1885,7 @@ "name": "wiki/concepts/Incremental CI Skipping.md", "description": "Incremental CI Skipping", "audience": "adopter", - "content_hash": "a5ef6cb2d62c93bbae5ff283a292f2557360f662a920cac2487285f290d607c0", + "content_hash": "e911d163e98c65522d6375ba65d716eff1f3ea03bc8736893c04cfb5a1dff6d1", "excluded_from_docs": false }, { @@ -1773,8 +1893,27 @@ "path": "wiki/concepts/PR Merge Workflow.md", "name": "wiki/concepts/PR Merge Workflow.md", "description": "PR Merge Workflow", + "audience": "mixed", + "content_hash": "8dbd0dfae7b968044c3e0a0884ba11ed7eab725bad54ab69840b588f32ed4cf5", + "excluded_from_docs": false, + "marker_blocks": [ + [ + 106, + 108 + ], + [ + 112, + 125 + ] + ] + }, + { + "kind": "wiki-page", + "path": "wiki/concepts/Policy-Memory Loop.md", + "name": "wiki/concepts/Policy-Memory Loop.md", + "description": "Policy-Memory Loop", "audience": "adopter", - "content_hash": "4eb0e06722813e1f04ebc2d660a43ac3a3f71653ccc1ec26766e1c408793f3d1", + "content_hash": "c72b4401f3ba6627833d1ecac771a38c507edcc1db08c33ed88e1cb879da6c9d", "excluded_from_docs": false }, { @@ -1786,13 +1925,28 @@ "content_hash": "202ae004f7cdb1180e85a8992ed4e529022cbba41d2c49c29047cc1acc11e178", "excluded_from_docs": false }, + { + "kind": "wiki-page", + "path": "wiki/concepts/React Perf Diagnostic.md", + "name": "wiki/concepts/React Perf Diagnostic.md", + "description": "React Perf Diagnostic", + "audience": "mixed", + "content_hash": "c87f3ae54562bb30fee190e245bd8ed0381df540352d2e33284efb0275b6bc33", + "excluded_from_docs": false, + "marker_blocks": [ + [ + 54, + 63 + ] + ] + }, { "kind": "wiki-page", "path": "wiki/concepts/Release Workflow.md", "name": "wiki/concepts/Release Workflow.md", "description": "Release Workflow", "audience": "contributor", - "content_hash": "138ac5082ab5138cc8b7e4ddf6f37b4dc4f4b8f5ec7202804735d9017a8f53cb", + "content_hash": "3d16f4dc8630653a5e68c4be66556b14f7b4f0951eceb9c45121a2b9969e2b70", "excluded_from_docs": false }, { @@ -1819,7 +1973,7 @@ "name": "wiki/concepts/Task Orchestration.md", "description": "Task Orchestration", "audience": "adopter", - "content_hash": "9f3a9b9099d86505ce28efad4df86a82f1aa3c191b4afb9f566a904f26618bff", + "content_hash": "8774176b364f264e8b02402b23e05653f1a71439ea4bfb686872119648271694", "excluded_from_docs": false }, { @@ -1828,7 +1982,7 @@ "name": "wiki/concepts/Telemetry.md", "description": "Telemetry", "audience": "adopter", - "content_hash": "c1237fdbc3ce5cb7358ffbb61826df815aa22f22688eae7165e22c8e17209e63", + "content_hash": "05b079c194ed9b224c3a0063b6c6caf57004801121984191dcf8b9b8b6b622cd", "excluded_from_docs": true }, { @@ -1837,16 +1991,7 @@ "name": "wiki/concepts/Test Runner.md", "description": "Test Runner Rule", "audience": "adopter", - "content_hash": "43c7c9cb9e6b5e76dab2167efb49c21bd6a504631f1b0b7969dab557e070ab8d", - "excluded_from_docs": false - }, - { - "kind": "wiki-page", - "path": "wiki/concepts/Update Merge.md", - "name": "wiki/concepts/Update Merge.md", - "description": "Update Merge", - "audience": "adopter", - "content_hash": "30ba211476547b67097560ae03909fe5302fa054b5a938b80f938df2c510c2ce", + "content_hash": "f2bf6ceb081c2ad818ca85773a429731666da086a049347c6fcb1d4e07146a07", "excluded_from_docs": false }, { @@ -1855,7 +2000,7 @@ "name": "wiki/concepts/Update Workflow.md", "description": "Update Workflow", "audience": "adopter", - "content_hash": "a7d7fb6b830933be6c0b7156f11d76530eb978701d6da7138e7a0d81b5355b16", + "content_hash": "3d8069623570e692e900610a69da45ea6c9d2e11f769bc7a272ef5017fd8e915", "excluded_from_docs": false }, { @@ -1873,7 +2018,7 @@ "name": "wiki/concepts/Wiki Sync.md", "description": "Wiki Sync", "audience": "adopter", - "content_hash": "f298134ed31e3e1d2b0148d55356c552391ca092511bdf0b8903d9add2cb95b0", + "content_hash": "f2053b3b734ffbb00b992720b2a7dd87bd7678f4aa998cf25aa0b10f53fda468", "excluded_from_docs": false }, { @@ -1882,7 +2027,7 @@ "name": "wiki/decisions/Bundle-time Scrub.md", "description": "Bundle-time Scrub", "audience": "contributor", - "content_hash": "79ec9426e6585875784171d6e3be6e01f0f0cd538f43dca795c3edb025bf1817", + "content_hash": "006cb30747dfcf5119ca63ff2789342f3f4053a1cbdddd687681c5a639e68eee", "excluded_from_docs": false }, { @@ -1891,7 +2036,7 @@ "name": "wiki/decisions/CLI-Binary-Split.md", "description": "CLI Binary Split", "audience": "contributor", - "content_hash": "ee85c6aa8799cce21ccc1a204b437c8f8322b852c16bff80a275b8d545e4e368", + "content_hash": "17e02dfe85409f7e159c8488499480ed93a0225ac06b9071ab35042e91552967", "excluded_from_docs": false }, { @@ -1900,7 +2045,7 @@ "name": "wiki/decisions/Claude Integration Fitness.md", "description": "Claude Integration Fitness", "audience": "adopter", - "content_hash": "fd2fefd702709abe5cb7f8800d21e719f073460abab6135c1787f17b8e1813af", + "content_hash": "f87b2a25df678eb5604d7b7f863c1ad52bd238858fcd1f9cb0cc1d5b33f3aa9b", "excluded_from_docs": false }, { @@ -1909,7 +2054,7 @@ "name": "wiki/decisions/Co-located Tests Folder.md", "description": "Decision: Co-located `tests/` Subfolder", "audience": "adopter", - "content_hash": "5e824ebbdf23874d4baeb6c65f94d43b4eca582d947c2d8408b2008b5cdc9df2", + "content_hash": "fc1a232006a42851220609a4e03e5e825fd3d16888334e0a5517fc882b95c24a", "excluded_from_docs": false }, { @@ -1925,9 +2070,18 @@ "kind": "wiki-page", "path": "wiki/decisions/Dark Mode Modernization.md", "name": "wiki/decisions/Dark Mode Modernization.md", - "description": "Decision: Modernize Dark Mode (Cookie + Client Hints)", + "description": "Decision: Modernize Dark Mode (Cookie + Optimistic UI)", + "audience": "adopter", + "content_hash": "ec7d666a6470c49cc385672cbdf0ed29bd7aed3af01495c9622310397f3d7811", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/decisions/Determinism Classifier.md", + "name": "wiki/decisions/Determinism Classifier.md", + "description": "Determinism Classifier", "audience": "adopter", - "content_hash": "f0b290117bd28f29db855d4baa50be7e7f4360d4220a495c4344f6e94be16893", + "content_hash": "215efb12c0b3f5d29070436acde0d53aa3a80d525ef14a95d726f0550ae04c04", "excluded_from_docs": false }, { @@ -1954,7 +2108,7 @@ "name": "wiki/decisions/Forensics Triage Workflow.md", "description": "Decision: Forensics Triage Workflow", "audience": "contributor", - "content_hash": "51eae953977cd7e1f7777e915be6e95b3909f828890c26c3ea188198f61f061b", + "content_hash": "1c353e60af79700948aab3827fdb8a3c3ae7cec9e29dbb09be1aef228cb5bbe1", "excluded_from_docs": false }, { @@ -1963,7 +2117,7 @@ "name": "wiki/decisions/No Component Library.md", "description": "Decision: No Component Library", "audience": "adopter", - "content_hash": "e3c7b7b04560feea35759eab2a25f63d09ff2715ddcb99f2cbd7b3122a46a63e", + "content_hash": "761c6fe115257b6e6607551db9e59bb7489fa055ba5de55a29c45d366e67d6d2", "excluded_from_docs": false }, { @@ -1972,7 +2126,7 @@ "name": "wiki/decisions/Quality Gate.md", "description": "Decision: Mandatory Quality Gate", "audience": "adopter", - "content_hash": "b8208a8106803aa58ce1a3a6f75598f5e5b7462ceee1b7b6fe90f98e6eb5184f", + "content_hash": "16c020703b0f428ea343859f7145959067a7105caef91f8bc52be9dfa464f774", "excluded_from_docs": false }, { @@ -1981,7 +2135,7 @@ "name": "wiki/decisions/TDD RED Verification.md", "description": "TDD RED Verification", "audience": "adopter", - "content_hash": "5b5f9f42a9c6ad8b2cf96dba34fc1dac9b4fd0de5acdf5a5e0da3927df1632bc", + "content_hash": "71d788caf90bf34b5d149b417783ece9c3b21eeca1cb434a70808c75e1c3364f", "excluded_from_docs": false }, { @@ -1990,7 +2144,16 @@ "name": "wiki/decisions/Thin Routes.md", "description": "Decision: Thin Routes, Fat Pages", "audience": "adopter", - "content_hash": "e2a91c2bb072098310a7862fbe35fea62b7f519b6180a1bae1a359044bd1dd46", + "content_hash": "9662215138fd8a79490783047c7f315da27a6fa12734d7f74fdfad2fa0b6182c", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/decisions/TypeScript 7 Readiness.md", + "name": "wiki/decisions/TypeScript 7 Readiness.md", + "description": "Decision: TypeScript 7 Readiness", + "audience": "adopter", + "content_hash": "ed7a02a5a90d798952e059bc74073b948b3d0a9889224b7aa4728dd3dbb0d01c", "excluded_from_docs": false }, { @@ -2008,7 +2171,25 @@ "name": "wiki/decisions/Wiki Management.md", "description": "Wiki Management", "audience": "adopter", - "content_hash": "81b7f13809f67bbff73fa29025069823ad1e1968b829527035a4974fbe6393c6", + "content_hash": "22c6d30ef1974c24e7ac1289e7b1266c0f23b03c1220d5dc4b11a2a844d4042a", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/decisions/Worthiness Audit.md", + "name": "wiki/decisions/Worthiness Audit.md", + "description": "Worthiness Audit", + "audience": "adopter", + "content_hash": "bb1b3d776c34c1e8461838fe837a0433d05c2f867faad1c94ea6d800a3074622", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/decisions/Worthiness Presence Gate.md", + "name": "wiki/decisions/Worthiness Presence Gate.md", + "description": "Worthiness Presence Gate", + "audience": "adopter", + "content_hash": "e7ee7eb6b4859a5443d4a0313c42fdde64d1970eda29387a5324ea2da4a8cc1b", "excluded_from_docs": false }, { @@ -2026,7 +2207,7 @@ "name": "wiki/decisions/pnpm.md", "description": "Decision: pnpm as the Package Manager", "audience": "adopter", - "content_hash": "a4154836d8633273c9553841227f99332232aad528d5c01fcd6e6d48424f0d67", + "content_hash": "88c0adc0552e32d5131bc15e797380f5bfcb68b42b44a4043d73c6d95237fb56", "excluded_from_docs": false }, { @@ -2035,7 +2216,7 @@ "name": "wiki/decisions/spec-kit Extension Strategy.md", "description": "spec-kit Extension Strategy", "audience": "adopter", - "content_hash": "72120546a17e1c57e5b707730d637cf112460e29019f0e6054bda246cdd2cbbf", + "content_hash": "7612d824db907c027548d920f3aa6c46903201477d4f7dccc38e94585ff079bf", "excluded_from_docs": false }, { @@ -2044,7 +2225,7 @@ "name": "wiki/dependencies/Chromatic.md", "description": "Chromatic", "audience": "adopter", - "content_hash": "6618978c8a00d2b93fe9e84762e4fbbeffe4be5f0d42a8ab150959e30a4c9167", + "content_hash": "6b2c541c05dc50755bf52ff141c5e06755ef41d5306928598265d302f3627a32", "excluded_from_docs": false }, { @@ -2053,7 +2234,7 @@ "name": "wiki/dependencies/Conform.md", "description": "Conform", "audience": "adopter", - "content_hash": "578a25bf6f3467c8c15df168478ddaf4447eb626a7c94cfd9db37673614c4258", + "content_hash": "f17f316d6c49b330633ea15783887c26f2ad7acea7660bc31ed96a4ca9611cf0", "excluded_from_docs": false }, { @@ -2062,7 +2243,7 @@ "name": "wiki/dependencies/Husky.md", "description": "Husky + lint-staged", "audience": "adopter", - "content_hash": "ab5b13ad0837dfbd409a4dac50637261154542a0652e4300e41fc1ba5d0c80a2", + "content_hash": "bd2aae88fa2c001a7f8191423034a13d6c1cbd280a095c2c8b682d716f5096c1", "excluded_from_docs": false }, { @@ -2071,7 +2252,7 @@ "name": "wiki/dependencies/Ky.md", "description": "Ky", "audience": "adopter", - "content_hash": "b6d69a77dee396b66db7056c1ccb6d37ac861d67b69405982ea3ff863680fa9e", + "content_hash": "15837df4134fc76be2fbae12294b318cf6992e8511b0a7c290c48cfc6812f6a6", "excluded_from_docs": false }, { @@ -2080,7 +2261,7 @@ "name": "wiki/dependencies/MSW.md", "description": "MSW", "audience": "adopter", - "content_hash": "4536d68cebaac10186967c1d9c25fc86a88bd00e5ef4abd0466f54602a0ed4d6", + "content_hash": "bb0fca54ffda32103e01a6cb595af68c811beefd58c1ccfa3d5db114b9189151", "excluded_from_docs": false }, { @@ -2089,7 +2270,7 @@ "name": "wiki/dependencies/Playwright.md", "description": "Playwright", "audience": "adopter", - "content_hash": "0eedc2e7aaab28d188dbeea52eeadb898eeb67983e6c09bdfa6ed221ed298ede", + "content_hash": "78bd0028aa21d7cceccf70eef2fd4a9de407b3f33bb677a1bd31b864f5b5eefc", "excluded_from_docs": false }, { @@ -2098,7 +2279,7 @@ "name": "wiki/dependencies/React Router 7.md", "description": "React Router 7", "audience": "adopter", - "content_hash": "01c20f7bb7a54eae1e0b050f3fec0e570e2816528d9a761fc006c52e3610c08c", + "content_hash": "abb4835d9cd495c71c2a06e3b60faac960b74366fe001e7f650bed53e28707f1", "excluded_from_docs": false }, { @@ -2107,7 +2288,7 @@ "name": "wiki/dependencies/React Testing Library.md", "description": "React Testing Library", "audience": "adopter", - "content_hash": "d15bf7edeb3390ef0aaac031afaaa41cf531620e25fd487ba484734a68b0e187", + "content_hash": "b72a664f89cde0cd49c2ed8479e6d425df84bcb624525707151ce3266a012c7e", "excluded_from_docs": false }, { @@ -2125,7 +2306,7 @@ "name": "wiki/dependencies/Storybook.md", "description": "Storybook", "audience": "adopter", - "content_hash": "fa283d281423dcb4bce94a36e3001104e391179a5a0a09c6b168540bbf4a4e79", + "content_hash": "f418eeb7833bee3c3282bac3fb336b53bd5c4352a884a67086ceb7ff241866e8", "excluded_from_docs": false }, { @@ -2134,7 +2315,7 @@ "name": "wiki/dependencies/Tailwind.md", "description": "Tailwind", "audience": "adopter", - "content_hash": "de698122e4b05c5fd89a2de1992043a6c3f5b11e4ddb26e0c36cd049d21184f6", + "content_hash": "93f7fe465378981d913feb109abeb271e640522646a051ea38eefd6ad9f8c2f4", "excluded_from_docs": false }, { @@ -2143,7 +2324,7 @@ "name": "wiki/dependencies/Vitest.md", "description": "Vitest", "audience": "adopter", - "content_hash": "efd21d864a47ae9e34ac1914f253b1f453ed971b93a10469254ee82a236ba8a3", + "content_hash": "1d91e0682de46c08b4470968e9376fcefe143ebbdd0727d1c7b98c9c6704e586", "excluded_from_docs": false }, { @@ -2152,7 +2333,7 @@ "name": "wiki/dependencies/Zod.md", "description": "Zod", "audience": "adopter", - "content_hash": "fa402a4fd91781e3adbcbeadba1fa3bedd010fbcc68e1f990e4d5b31baf4317d", + "content_hash": "635934c75d1654f1b1e0e5636d2aac7d3d2787c4c5919a1e01ca92f36f80cf5f", "excluded_from_docs": false }, { @@ -2161,7 +2342,7 @@ "name": "wiki/dependencies/gaia-lint.md", "description": "@gaia-react/lint", "audience": "adopter", - "content_hash": "e17e63fc38e37c5b2d53d3afad7430db1954a572b988c64266563f8c08034718", + "content_hash": "69befb7cdb4701981d52c2d411df9afcf247bdc1d0980b4f01cfa8ca76af15fa", "excluded_from_docs": false }, { @@ -2170,7 +2351,7 @@ "name": "wiki/dependencies/i18next.md", "description": "i18next", "audience": "adopter", - "content_hash": "a32db267e44f39343b0c702eb19a1ff3c817ac371f967dce20b50ced81ecca96", + "content_hash": "80d9cbcb1151f7f44ad7bda7fac788b16c53ac0d6258cc615fe15fb54abfd53f", "excluded_from_docs": false }, { @@ -2179,7 +2360,7 @@ "name": "wiki/dependencies/knip.md", "description": "knip", "audience": "adopter", - "content_hash": "7a9ac7c30cf8bd88b53afea19708095154d90e09e3bc337f397958298d9e709b", + "content_hash": "e250b8a3e3cf9308c0708f53b7ebbf9e98d24bb83ce2e9afeea4af7d21fe3c35", "excluded_from_docs": false }, { @@ -2188,7 +2369,25 @@ "name": "wiki/dependencies/pnpm-audit.md", "description": "pnpm-audit", "audience": "adopter", - "content_hash": "59594290dc0ae9e9fb6bebc4e01e0f8a90e083700609c54ce8f694d8ccf8f014", + "content_hash": "c2c42cc51f527b0fc53f391d6d82da3a7f3dc5e770ce1070f537648f50779d75", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/dependencies/pnpm-overrides.md", + "name": "wiki/dependencies/pnpm-overrides.md", + "description": "pnpm-overrides", + "audience": "adopter", + "content_hash": "ae2fa06c120b128b0ec13ffc4f619fbace9068ee9793bf2ad465abc77f8b6200", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/dependencies/react-doctor.md", + "name": "wiki/dependencies/react-doctor.md", + "description": "react-doctor", + "audience": "adopter", + "content_hash": "45df41c7be9ca12d99dc23cacac83ab81db508a3756ac2c57f3758cd0cda4b1d", "excluded_from_docs": false }, { @@ -2197,7 +2396,7 @@ "name": "wiki/dependencies/react-icons.md", "description": "react-icons", "audience": "adopter", - "content_hash": "e7419e61285cefd7d11ddd64380bcd5eacb612eab3511b7e459abe34fa9518af", + "content_hash": "16d885ea724117bddc996387438170923c62f7667dd13bd262b6d56560a62e7b", "excluded_from_docs": false }, { @@ -2215,7 +2414,7 @@ "name": "wiki/dependencies/remix-i18next.md", "description": "remix-i18next", "audience": "adopter", - "content_hash": "871acad1b44362e4f1eafb4a1391c9d752e4dff0d5c1c25c01ecfdcf7f64e114", + "content_hash": "cfc5ea80e8590b1839f2d69763def7284356decbaea939c18d1ed0eb8e615b34", "excluded_from_docs": false }, { @@ -2227,13 +2426,22 @@ "content_hash": "244213c3860e4f4ef65ab8eab6a1424415b0924708ebe74ca3a01a0f28b1599c", "excluded_from_docs": false }, + { + "kind": "wiki-page", + "path": "wiki/dependencies/remix-utils.md", + "name": "wiki/dependencies/remix-utils.md", + "description": "remix-utils", + "audience": "adopter", + "content_hash": "a8c0db0f578064c7781d165d4c7ff1cbb03bf1f269c4e2c647ee9173d72db0fc", + "excluded_from_docs": false + }, { "kind": "wiki-page", "path": "wiki/dependencies/spec-kit.md", "name": "wiki/dependencies/spec-kit.md", "description": "spec-kit", "audience": "adopter", - "content_hash": "9c6bfb947542130eb8e538a738c905a9f08d13cc45f95056620c5d6ba943edd3", + "content_hash": "e8575282d27b86a92fee9c26f6f67699d6a82f5cc135e1315024a3157928200d", "excluded_from_docs": false }, { @@ -2242,7 +2450,7 @@ "name": "wiki/entities/GAIA.md", "description": "GAIA", "audience": "contributor", - "content_hash": "8ac9ad6cf08aa85d7e0b98cc01226500bdca82527847456ca846d87e7dd3c330", + "content_hash": "d34ae40b9ca65c21b84fc0d06191bb1e1f5e23eacd2c43bccf4ac85c2ca9278c", "excluded_from_docs": false }, { @@ -2251,7 +2459,7 @@ "name": "wiki/entities/Steven Sacks.md", "description": "Steven Sacks", "audience": "contributor", - "content_hash": "3237fd76e69226ccd4f00a8ad74a15dd8e1c4c5ea0cf6562fc2a54650ff61654", + "content_hash": "e40e159a7f4dd9e773dc95ca844512fd383ab772058840e2f0325e5b788e66a3", "excluded_from_docs": false }, { @@ -2260,7 +2468,7 @@ "name": "wiki/flows/Form Submit Flow.md", "description": "Form Submit Flow", "audience": "adopter", - "content_hash": "4613494b8e7fe4b5f40fa7454bfc87ba101ab2b4bb102d92bc437e444201363a", + "content_hash": "c0e63b2702f0a0836c3d6f2db44e1adaa28ae301c6485b6844ffe1c725fbef80", "excluded_from_docs": false }, { @@ -2269,7 +2477,7 @@ "name": "wiki/flows/Language Flow.md", "description": "Language Flow", "audience": "adopter", - "content_hash": "7b7383a72c5ab7213acf00495e1cecb7e202dbada322f5e18bef21fa4defa928", + "content_hash": "11e3ae2b0b3d6bedc4d52dd9d668fe07f9f38bf4821d8a18dd880ea1b41e84d7", "excluded_from_docs": false }, { @@ -2278,7 +2486,7 @@ "name": "wiki/flows/Theme Flow.md", "description": "Theme Flow (Dark Mode)", "audience": "adopter", - "content_hash": "3978d8fdb65a5ef31e5f50b91be1d0f23c143a5bdd96030da1d40a1aa83a7922", + "content_hash": "04d5e0c16f037be48616893a4b88c5edf3652138f2333fa8e8a98c5ed61c1392", "excluded_from_docs": false }, { @@ -2287,7 +2495,7 @@ "name": "wiki/hot.md", "description": "Recent Context", "audience": "adopter", - "content_hash": "30ac1834dfca9c5f94989cd56178fb921a9b469d8968f301cbf93932c80c6e82", + "content_hash": "e4d0566d02e3480a1cd5526df81e447967349f61822a56a8281912d30649d108", "excluded_from_docs": false }, { @@ -2296,7 +2504,7 @@ "name": "wiki/index.md", "description": "Index", "audience": "mixed", - "content_hash": "0accb1bbb9a598df989131c3ae22dcbd5687550eb59c4bd437e778a1c142ac48", + "content_hash": "2b4ec920100ce2e3db7a1fda80219221cdd072f43bba8daaf7a06dc034a03bdd", "excluded_from_docs": false, "marker_blocks": [ [ @@ -2304,20 +2512,20 @@ 65 ], [ - 102, - 104 + 106, + 109 ], [ - 112, - 114 + 120, + 122 ], [ - 138, - 141 + 146, + 149 ], [ - 155, - 160 + 163, + 168 ] ] }, @@ -2327,7 +2535,7 @@ "name": "wiki/log.md", "description": "Log", "audience": "adopter", - "content_hash": "023f3d27adb1ce94ed598265f7d5136c447319e391c470271c2efe13a3a7a50f", + "content_hash": "97ba874f051f5dd4dd54410469a7d5b9a408d404f2dcf4c3075adc78ecf7970c", "excluded_from_docs": false }, { @@ -2366,13 +2574,40 @@ "content_hash": "4d348be73a7e10a317147f5a7e331ae79df14bb9939747ab2d61ba29c362fed2", "excluded_from_docs": false }, + { + "kind": "wiki-page", + "path": "wiki/meta/consolidate-report-2026-06-11.md", + "name": "wiki/meta/consolidate-report-2026-06-11.md", + "description": "Consolidate Report, 2026-06-11", + "audience": "contributor", + "content_hash": "f887dc5756e18e4279a7a72b08ea1bbeb98427cd2d45e223ee432b88953ad795", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/meta/consolidate-report-2026-06-23.md", + "name": "wiki/meta/consolidate-report-2026-06-23.md", + "description": "Consolidate Report, 2026-06-23", + "audience": "contributor", + "content_hash": "5972c12944cd39a1b523154bff54a4ec63b14459c031fdd62acfed9ec08fad1b", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/meta/consolidate-report-2026-06-24.md", + "name": "wiki/meta/consolidate-report-2026-06-24.md", + "description": "Consolidate Report, 2026-06-24", + "audience": "contributor", + "content_hash": "2806106a5c6c7d9a286bbe3ca2f85da373eff631aede87d55477f5e489cd1dc2", + "excluded_from_docs": false + }, { "kind": "wiki-page", "path": "wiki/meta/dashboard.md", "name": "wiki/meta/dashboard.md", "description": "Wiki Dashboard", "audience": "contributor", - "content_hash": "94d37e433ae24d5cfdf78afa1417361626f0915199343bdb026da507c41ccdea", + "content_hash": "0f61388be568ef1f56cf12549c386a671fc9c53c835ba72f2791a920c894cfbf", "excluded_from_docs": false }, { @@ -2381,7 +2616,7 @@ "name": "wiki/meta/lint-report-2026-04-21.md", "description": "Wiki Lint Report: 2026-04-21", "audience": "contributor", - "content_hash": "ff56226e95710344658306c3d58d3715969afc55941258198279f77ecab2387c", + "content_hash": "b1f93907876b432041a0937949dd247b3efdc3d4d58877e7cc00ea634fbf4ecc", "excluded_from_docs": false }, { @@ -2390,7 +2625,7 @@ "name": "wiki/meta/lint-report-2026-04-26.md", "description": "Wiki Lint Report: 2026-04-26", "audience": "contributor", - "content_hash": "fd107cab9cd059d3008bbbf979a274a6af3608431297394765f6ee291eb7fde0", + "content_hash": "fdcc2d3495b43a9b97d42579a09481c99194611ffec0877f2229879888d2d35e", "excluded_from_docs": false }, { @@ -2399,7 +2634,7 @@ "name": "wiki/meta/lint-report-2026-04-27.md", "description": "Wiki Lint Report: 2026-04-27", "audience": "contributor", - "content_hash": "aff9dead794561845f0143e0b01c69ae5fb29e375b420d58367a6bf583fe0526", + "content_hash": "aed76f8f834653a2ade3dc591c590372e6350163020ec0853e71d6da2eeebd2c", "excluded_from_docs": false }, { @@ -2408,7 +2643,7 @@ "name": "wiki/meta/lint-report-2026-05-01.md", "description": "Wiki Lint Report: 2026-05-01", "audience": "contributor", - "content_hash": "4bfa4110fd52166421929af67e7cfd785598a97c02491941cb7ffba5ddba2931", + "content_hash": "593e2b2f7b5869612227215a79fcd8d28b98f5b8d584acb9d7d859990ab96a3a", "excluded_from_docs": false }, { @@ -2435,7 +2670,7 @@ "name": "wiki/meta/lint-report-2026-05-06.md", "description": "Lint Report: 2026-05-06", "audience": "contributor", - "content_hash": "f2a853644dda5a093427abbe86825f00b3dabdb3b96051f55576589d1de5711b", + "content_hash": "9cc1ad09e5f73f27cb8e4860236a3fd4134d86286ca688fd18aaff8138669505", "excluded_from_docs": false }, { @@ -2444,7 +2679,7 @@ "name": "wiki/meta/lint-report-2026-05-07.md", "description": "Lint Report: 2026-05-07", "audience": "contributor", - "content_hash": "f5635e7f259b864449d049287c9ff5bf464206be648e5ae1a18fa3e261d7a4d9", + "content_hash": "8f8b07ffc9440b8e39e1b6388d4224e9a4af089e3c3c0f294f9c31b0de13dcd6", "excluded_from_docs": false }, { @@ -2483,13 +2718,76 @@ "content_hash": "ec027c7932e85eba42ba28b84e9f39ee1f0f24f5b39abfbdede91e9e4cc6c826", "excluded_from_docs": false }, + { + "kind": "wiki-page", + "path": "wiki/meta/lint-report-2026-06-09.md", + "name": "wiki/meta/lint-report-2026-06-09.md", + "description": "Lint Report: 2026-06-09", + "audience": "contributor", + "content_hash": "6bb8cd800627b942f9d85eda05a4eb063903dd4396b96e03d35f22c8b2fcedc1", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/meta/lint-report-2026-06-11.md", + "name": "wiki/meta/lint-report-2026-06-11.md", + "description": "Lint Report: 2026-06-11", + "audience": "contributor", + "content_hash": "329c4890ca8c8d8c5f5f4d3210cfc5249d0c3297acb00573969579be2e0f4761", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/meta/lint-report-2026-06-12.md", + "name": "wiki/meta/lint-report-2026-06-12.md", + "description": "Lint Report: 2026-06-12", + "audience": "contributor", + "content_hash": "ca2aed248ebb8f82d06db4bfa32405fc4322aecc8315ef87606297b985fd15e0", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/meta/lint-report-2026-06-23.md", + "name": "wiki/meta/lint-report-2026-06-23.md", + "description": "Lint Report: 2026-06-23", + "audience": "contributor", + "content_hash": "fc53ee56faa0b4cc8a036d84426b88881051cb6db1e3e30833a34b1ca912a4b0", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/meta/lint-report-2026-06-24.md", + "name": "wiki/meta/lint-report-2026-06-24.md", + "description": "Lint Report: 2026-06-24", + "audience": "contributor", + "content_hash": "bfd4d8eb698126db6fe15ac51e908a1af3604d1e2e6ec83fc96fea0cc1f68f12", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/meta/lint-report-2026-06-25.md", + "name": "wiki/meta/lint-report-2026-06-25.md", + "description": "Lint Report: 2026-06-25", + "audience": "contributor", + "content_hash": "ada120750dc829104c0e61c0f696a597100b412a71ab5b1ce00f7269a67f66bf", + "excluded_from_docs": false + }, + { + "kind": "wiki-page", + "path": "wiki/meta/staleness-audit-2026-06-24.md", + "name": "wiki/meta/staleness-audit-2026-06-24.md", + "description": null, + "audience": "contributor", + "content_hash": "a26d830825bf0cb1588d98101ad23fc223dd071db0d7e2b023f0bc8bfb38c464", + "excluded_from_docs": false + }, { "kind": "wiki-page", "path": "wiki/modules/CLI Scaffolding.md", "name": "wiki/modules/CLI Scaffolding.md", "description": "CLI Scaffolding", "audience": "adopter", - "content_hash": "1382aee50cb11ea0b5e7333909178ff46cd49eae244765c67520e1a1039740e8", + "content_hash": "f1d2f8df949916398262794028213bc69c28564546ddf8272a8d6359079f03df", "excluded_from_docs": false }, { @@ -2498,7 +2796,7 @@ "name": "wiki/modules/Claude Integration.md", "description": "Claude Integration", "audience": "adopter", - "content_hash": "865c384c90b183f02817ff3104b216174faef9748234063275923b1011703cc0", + "content_hash": "8109c525cfa5d9930a339fdac150d25767a021d25f7bafb7599609cfe1c17507", "excluded_from_docs": false }, { @@ -2507,7 +2805,7 @@ "name": "wiki/modules/Components.md", "description": "Components", "audience": "adopter", - "content_hash": "b1f6cda0ba5513d488169c304ddc767a7f4d8a4e095365cd12c9a617f8a1cfad", + "content_hash": "b935b345338f07969c39cdf6e30bcc762991142d330afb94da55b06609de44fd", "excluded_from_docs": false }, { @@ -2516,7 +2814,7 @@ "name": "wiki/modules/Folder Structure.md", "description": "Folder Structure", "audience": "adopter", - "content_hash": "4ed323c08bb2963e6891696a4c3c10bb84d4f4300cb89be11b9ccf1f25e9c741", + "content_hash": "e5b9b0e99c0c94887aa4666585819bf4312bd692769e1d2e5681ca617186cfbf", "excluded_from_docs": false }, { @@ -2525,7 +2823,7 @@ "name": "wiki/modules/Form Components.md", "description": "Form Components", "audience": "adopter", - "content_hash": "715397efea581a860c88361741f7333e08717ad0d25301b87e002e687a00bfe3", + "content_hash": "3abbe06d8b206d8e82a01b2a1110c1e29e8dadbfdce34d08704c84ec386f2b5f", "excluded_from_docs": false }, { @@ -2534,7 +2832,7 @@ "name": "wiki/modules/Hooks.md", "description": "Hooks", "audience": "adopter", - "content_hash": "86fe22d204f0185ac1f43ef6ba12dc6885df22462fadba26223bb450b35cff05", + "content_hash": "d7450d0f8549cd082320291f6b8893879fdd17c5d170d69d7ed14f1f5e8260c2", "excluded_from_docs": false }, { @@ -2543,7 +2841,7 @@ "name": "wiki/modules/MSW Handlers.md", "description": "MSW (Mock Service Worker)", "audience": "adopter", - "content_hash": "91fe9125355d95e0af2d3ce244adb52c80c350dcf7cc6037090624b2453423e5", + "content_hash": "810717c40dc01b615f23214a0b4e9433696217804286fcde86e0c4b9e6dd06c2", "excluded_from_docs": false }, { @@ -2561,7 +2859,7 @@ "name": "wiki/modules/Pages.md", "description": "Pages", "audience": "adopter", - "content_hash": "e834f49f6d0d478e8e1e668b299eebd88e3a9d635b136ce571914ee8a3580302", + "content_hash": "9962cb298352f39c0185855596bf2321a2b591b88f8780d18ad31c08e1082b0a", "excluded_from_docs": false }, { @@ -2570,7 +2868,7 @@ "name": "wiki/modules/Routing.md", "description": "Routing", "audience": "adopter", - "content_hash": "06f8bad26b51c6c8722ce7f432c6dbb6dae24315fcdc686a4b723d8af36d152c", + "content_hash": "6ff89351cc91658a48e6dab62a9d8475ac84ba8a652649db47d078d0b039dcfd", "excluded_from_docs": false }, { @@ -2579,7 +2877,7 @@ "name": "wiki/modules/Services.md", "description": "Services", "audience": "adopter", - "content_hash": "b5a7489efc5fb6a76b1f87261309533229750c62d2a6bb3f68b55dd0502282a5", + "content_hash": "4b6c3b992e6c283d3d264cf4c0d6ac218688fa858fd8e5ca84810f7b50a9399c", "excluded_from_docs": false }, { @@ -2588,7 +2886,7 @@ "name": "wiki/modules/Sessions.md", "description": "Sessions", "audience": "adopter", - "content_hash": "43accde9903553ceecc370467e5ba280e2cdac6cbc49cd49b287e376f58c1036", + "content_hash": "e54fcbade1074f66ee04e3ec84087112d6bc2755428b4ec96b472db81222c59b", "excluded_from_docs": false }, { @@ -2597,7 +2895,7 @@ "name": "wiki/modules/State.md", "description": "State", "audience": "adopter", - "content_hash": "25cd4b48f3cd935295104c5a4abce1c2b220cf81dd75fecaa0f777903d72e544", + "content_hash": "d362649124e4e4da9243eee4b36c424dbec60693f6567d8fdf44458ae01a58ad", "excluded_from_docs": false }, { @@ -2606,7 +2904,7 @@ "name": "wiki/modules/Storybook Stories.md", "description": "Storybook Stories", "audience": "adopter", - "content_hash": "d18b3810d894b22bce78aa48ae4ec1e9265641a86817df357524ecdbcb338619", + "content_hash": "4533eeea085c2b2977ffa650ee3bfcd8a90c950c7c449c970f94d3ae30a1ef7d", "excluded_from_docs": false }, { @@ -2615,7 +2913,7 @@ "name": "wiki/modules/Styles.md", "description": "Styles", "audience": "adopter", - "content_hash": "12d4ac101e39782e57709d58fb6781e87225a5e93df8b85be9f11dad1bfe4704", + "content_hash": "456e4a0b1de35bbedc9311390abf2be12bb39bbad72bb83ca098b2313054b211", "excluded_from_docs": false }, { @@ -2624,7 +2922,7 @@ "name": "wiki/modules/Testing.md", "description": "Testing", "audience": "adopter", - "content_hash": "cb64027bd758688a9acd3ee551c287d86ebc8b75ea62fb27720a874c31925edb", + "content_hash": "4fef4575d216597bc13d2847718e7a51d9359084f215d6f6f44994cbbe7ef30d", "excluded_from_docs": false }, { @@ -2633,7 +2931,7 @@ "name": "wiki/modules/Utils.md", "description": "Utils", "audience": "adopter", - "content_hash": "3f6186e791ddd61b8094b4f69a539e0dde4ff21b7befb7d7c4b49b32d966f373", + "content_hash": "f0671d5d35e2d804abb89db3d0c9b451573e075dffa17a53b11c6273e685d0c1", "excluded_from_docs": false }, { @@ -2642,7 +2940,7 @@ "name": "wiki/modules/i18n.md", "description": "i18n", "audience": "adopter", - "content_hash": "d308cf863ac114b8bb1c7343d6f0536fe23181764a62ae488f4033e1414c7657", + "content_hash": "1f5afd615fabc9b96b8c6f74c9f4c6afa64ffaa8c5f33bf2a1b78dcd54e3f89c", "excluded_from_docs": false }, { @@ -2651,7 +2949,7 @@ "name": "wiki/overview.md", "description": "GAIA React", "audience": "adopter", - "content_hash": "65f1150c22c55f7aee41fafd14c3388a19a996d48dbd80a6fced3c0cce54cc8f", + "content_hash": "00e7045b433f558afaf32fd2f6dcd74098106b246a2f8816f4a56090f6a0030f", "excluded_from_docs": false }, { @@ -2660,7 +2958,7 @@ "name": "audit-ci-tests.yml", "description": "Audit CI Tests", "audience": "contributor", - "content_hash": "161b7afee940342bcfcf5d6380dcfc6db06e08555cf2f864103ef7015bebf2aa", + "content_hash": "0d05869b07980d73f51ede30f2e43222e56fb140c9607a1b5954b24c177f47ec", "excluded_from_docs": false }, { @@ -2678,7 +2976,7 @@ "name": "cli-tests.yml", "description": "CLI Tests", "audience": "contributor", - "content_hash": "ae440887f984a78da0cef9a32742eac56aefd20834f714f28d7b25aea4583c50", + "content_hash": "99cf3d981ce1f5f78c40f69fc6f1efe4ef6c45436b4db4310892d78dec4c5c44", "excluded_from_docs": false }, { @@ -2687,7 +2985,7 @@ "name": "code-review-audit.yml", "description": "Code Review Audit", "audience": "contributor", - "content_hash": "7d6c488b0f6c0e0950eb17603f86b49d954ac2dc92ea040d4a8420ef505e8744", + "content_hash": "ca89b1f788f83368233d4ab53b20d0e1778f4ae6cf89246aefe27b848adc25b2", "excluded_from_docs": false }, { @@ -2723,7 +3021,7 @@ "name": "tests.yml", "description": "Tests", "audience": "adopter", - "content_hash": "a061a1fa4df06058657d3c6dc26b91c9eb6deb5559a7b49811db7fdde81fad93", + "content_hash": "4dce87c265d8d9305e03f480671e8c161b2f162db76c1c63927cdf0857ac0a1d", "excluded_from_docs": false } ] From 8517d0a2c5d3eb83d9b43666f0e0bb15c7b4212d Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 15:00:50 +0900 Subject: [PATCH 13/25] docs: accuracy pass on getting-started pages setup-gaia-ci: correct the four-workflow auto-merge claim (stale-branches deletes branches directly, no PR), full "already configured" output string, pnpm-audit issue+PR behavior, update-deps wave A/B PR split, wiki diff-size auto-merge holdout, and the "already configured" reconfigure note. setup-cloned-gaia-project: fix step-5 tooling cross-link, add finalize/ restart + worktree self-heal + GitHub CLI pre-check steps, remove the false audit-mode re-run promise, and correct the commit/PR wording (the command never auto-commits). Mentorship stays muted; forensics-triage.yml not leaked. index (Quick Start): verified against create-gaia + package.json, no changes. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../setup-cloned-gaia-project.mdx | 28 +++++++++++++++---- .../docs/getting-started/setup-gaia-ci.mdx | 28 +++++++++++-------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/content/docs/getting-started/setup-cloned-gaia-project.mdx b/src/content/docs/getting-started/setup-cloned-gaia-project.mdx index 058dfc2..6c4d9fc 100644 --- a/src/content/docs/getting-started/setup-cloned-gaia-project.mdx +++ b/src/content/docs/getting-started/setup-cloned-gaia-project.mdx @@ -9,18 +9,30 @@ sidebar: ## When to use this -- After `git clone`-ing an existing GAIA project -- Do not use after running `npx create-gaia`. +- After `git clone`-ing an existing GAIA project. +- Not after `npx create-gaia` (that path runs `/gaia-init` instead). + +GAIA's statusline prompts `Run /setup-cloned-gaia-project` until the per-machine setup is finished. + +The command is idempotent. Re-running it after a partial run picks up from the first step that has not completed yet, so it is safe to run more than once. ## The flow +### Pre-step: worktrees + +If you set up the clone from a git worktree created outside Claude Code, the command first restores the shared-state symlinks the worktree needs. In a normal checkout this does nothing. + ### Pre-step: pnpm and node_modules If `corepack` is available, pnpm is enabled at the version pinned in `package.json`. Otherwise pnpm is installed globally via npm. If `node_modules/` is missing, `pnpm install` runs. +### Pre-step: GitHub CLI check + +The command checks for the GitHub CLI before installing anything. If `gh` is not installed or not authenticated, it prints a warning and keeps going; setup never blocks on it. The PR merge gate and `/gaia-plan` rely on `gh`, so install it from https://cli.github.com/ and run `gh auth login` when you can. + ### 1. install-tools -Three external tools, identical to step 4 of [`/gaia-init`](/getting-started/gaia-init/#4-claude-tooling): +Three external tools, identical to step 5 of [`/gaia-init`](/getting-started/gaia-init/#5-claude-tooling): - React Doctor skill - Playwright CLI binary @@ -57,8 +69,14 @@ If the project uses the pre-merge `code-review-audit` gate, you choose who runs - **CI (default).** CI runs the audit on your PRs and you wait for the `GAIA-Audit` check before merging. - **Locally.** The audit runs in your own session at merge time, streaming as it goes, and CI's audit step stands down for your PRs. -Your choice adds a one-line entry to `.gaia/audit-ci.yml`, which the command helps you commit as a small PR. If `gh` is not authenticated, the step is skipped; re-run `/setup-cloned-gaia-project` after `gh auth login` to finish it. +Your choice adds a one-line entry to `.gaia/audit-ci.yml`. You commit and open the one-line PR yourself; the command prints the exact `git` and `gh` commands to run and never commits or opens the PR for you. + +If `gh` is not authenticated when this step runs, the choice is skipped and the step is recorded as done, so a later plain re-run will not prompt for it again. To set or change your audit mode afterward, add your `=` entry to `audit_authors` in `.gaia/audit-ci.yml`. + +### 5. Finish + +Once every step is recorded, setup finalizes and confirms it is complete. Restart Claude Code so the new plugin and skill state load. After that, the statusline surfaces `/update-deps` and `/update-gaia` indicators when updates are available. ## Resuming after a failure -If you encounter any issues while `/setup-cloned-gaia-project` runs, ask Claude to fix it and resume. +If a step fails, fix the underlying cause and re-run `/setup-cloned-gaia-project`. Completed steps are detected and skipped, so the run resumes from where it stopped. diff --git a/src/content/docs/getting-started/setup-gaia-ci.mdx b/src/content/docs/getting-started/setup-gaia-ci.mdx index 796a93f..50860be 100644 --- a/src/content/docs/getting-started/setup-gaia-ci.mdx +++ b/src/content/docs/getting-started/setup-gaia-ci.mdx @@ -5,22 +5,24 @@ sidebar: order: 3 --- -`/setup-gaia-ci` connects your GAIA project to GitHub Actions. Run it once after your first `git push origin main`. The command is idempotent: re-running on a configured repo prints `GAIA CI is already configured` and exits. Pass `--reconfigure` to rotate the bot token or re-select which tools run on cron. +`/setup-gaia-ci` connects your GAIA project to GitHub Actions. Run it once after your first `git push origin main`. The command is idempotent. Re-running on a configured repo that is already in sync prints `GAIA CI is already configured. Pass --reconfigure to rotate tokens or change tool selection.` and makes no changes. Pass `--reconfigure` to rotate the bot token or re-select which tools run on cron. ## What GAIA CI does -GAIA CI installs four maintenance workflows that run on a cron schedule, open labeled PRs, and auto-merge them when CI passes: +GAIA CI installs four maintenance workflows that run on a cron schedule. Three of them open labeled PRs and auto-merge on green CI. The stale-branches workflow deletes merged branches directly and opens no PR. | Workflow file | Default schedule | What it does | |---|---|---| -| `gaia-ci-wiki.yml` | Daily | Runs the `/gaia-wiki` chain: sync, consolidate, and lint | -| `gaia-ci-update-deps.yml` | Weekly | Runs `/update-deps` and opens a PR for any updates | -| `gaia-ci-pnpm-audit.yml` | Weekly | Runs `pnpm audit` and opens a security PR for high and critical findings | -| `gaia-ci-stale-branches.yml` | Monthly | Deletes branches merged more than 30 days ago | +| `gaia-ci-wiki.yml` | Daily | Runs the `/gaia-wiki` chain (sync, consolidate, lint) and opens one PR with the result | +| `gaia-ci-update-deps.yml` | Weekly | Runs `/update-deps`. Batches minor and patch bumps into one PR and opens a separate PR for each pending major-bump group | +| `gaia-ci-pnpm-audit.yml` | Daily | Runs `pnpm audit`. For each high or critical advisory, opens a security issue and a targeted single-package bump PR | +| `gaia-ci-stale-branches.yml` | Monthly | Deletes branches merged more than 30 days ago. No PR, no auto-merge | + +Two cases hold for human review instead of auto-merging, both tagged with the `needs-human-review` label: a wiki PR whose changed lines exceed 25% of the wiki's size at the base commit, and every major-bump PR from `gaia-ci-update-deps.yml`. Each cron workflow is generated from `.gaia/automation.json`. You can change the mode for any tool (`ci` / `local` / `off`) by running `/setup-gaia-ci --reconfigure`. -`/setup-gaia-ci` also installs `code-review-audit.yml`, the pre-merge audit gate. It is not one of the cron tools: it has no `ci` / `local` / `off` mode and installs unconditionally, even when no cron tool runs in CI. It reads its configuration from `.gaia/audit-ci.yml` at runtime, and the bot token you set below authenticates it (either token type works). See the [`code-review-audit` agent reference](/reference/agents/) for what it checks. +`/setup-gaia-ci` also installs `code-review-audit.yml`, the pre-merge audit gate. It is not one of the four cron tools and is not toggled on or off the way they are. It installs unconditionally, even when no cron tool runs in CI. It reads its configuration from `.gaia/audit-ci.yml` at runtime, and the bot token you set below authenticates it (either token type works). Where the audit runs at merge time, on CI or locally, is set by the audit-mode policy below. See the [`code-review-audit` agent reference](/reference/agents/) for what it checks. ## Prerequisites @@ -36,7 +38,7 @@ The command reads `origin` and confirms it points to `github.com`. Non-GitHub re ### 2. Duplicate tool detection -If Dependabot or Renovate is detected, the command warns that GAIA's update-deps workflow covers the same package ecosystems (npm, pnpm) and will open duplicate PRs if both run in parallel. You can disable the overlap before continuing or cancel and re-run later. The command does not disable either tool automatically. +If Dependabot or Renovate is detected, the command warns that GAIA's update-deps workflow (the warning calls it GAIA Sharpen) covers the same package ecosystems (npm, pnpm) and will open duplicate PRs if both run in parallel. You can disable the overlap before continuing or cancel and re-run later. The command does not disable either tool automatically. ### 3. Enable / defer / opt out @@ -63,7 +65,7 @@ GAIA CI needs an Anthropic token or key to authenticate the workflow steps that - **CLAUDE_CODE_OAUTH_TOKEN**: for Claude Code subscribers. - **ANTHROPIC_API_KEY**: for direct Anthropic API customers. -Paste the token when prompted. It is piped directly to `gh secret set` and never written to any file, never echoed in chat, and never appears in the terminal scrollback. You can add it manually on GitHub instead, if you prefer. +Paste the token when prompted. It is piped directly to `gh secret set` and never written to any file, never echoed in chat, and never appears in the terminal scrollback. A third option, **I don't know**, links to the docs and exits without setting anything. ### 7. Workflow generation @@ -75,7 +77,7 @@ If the verification run fails, you can retry, abandon (deletes the generated fil ### 8. Commit and push -On a successful verification run, the command stages the generated workflow files and `.gaia/automation.json`, commits with a standard message, and pushes. +On a successful verification run, the command stages the generated workflow files, `.gaia/automation.json`, and the audit-policy file `.gaia/audit-ci.yml`, commits with a standard message, and pushes. ## Reconfiguring @@ -83,7 +85,11 @@ On a successful verification run, the command stages the generated workflow file /setup-gaia-ci --reconfigure ``` -`--reconfigure` skips the idempotent short-circuit and re-runs the flow from Step 3. It lets you re-select which tools run in CI mode and always asks for a fresh token (the existing secret is silently overwritten). `setup_complete` stays `true`. +`--reconfigure` skips the idempotent short-circuit and re-runs the flow. In place of the enable / defer / opt out question, it asks which tools should run in CI mode, re-offers the audit-mode policy, and always asks for a fresh token (the existing secret is silently overwritten). `setup_complete` stays `true`. + +## Re-running after a GAIA update + +A GAIA update can change the bundled workflow templates. When you re-run `/setup-gaia-ci` on a configured repo whose `.github/workflows` files have drifted from the current templates, the command does not silently exit. It lists the affected workflows and offers to re-render them: it regenerates the drifted or missing files, re-installs `code-review-audit.yml`, commits on a new branch, and opens a PR for you to review and merge. Tool selection and the bot token stay unchanged. You can also skip, or run a full `--reconfigure` instead. ## On failure From c84fba142c84910b80734ffb43b935269ec37d6b Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 15:20:53 +0900 Subject: [PATCH 14/25] docs: accuracy pass on commands pages index: correct /gaia-audit, /gaia-fitness, /gaia-harden, /gaia-wiki, and /gaia-forensics descriptions against source frontmatter; fix the autocomplete prefix claim. spec: fix inline plan-dispatch model (no general-purpose wrapper), self-review timing (before gate 2), drop the wrong .specify/extensions.yml path, tighten spec-close SPEC-id optionality, add the audit-finding-apply draft-cache trigger. plan: correct the SPEC reference path (.gaia/local/specs/SPEC-NNN/SPEC.md), remove the fabricated clipboard auto-copy step, and note the non-main concurrent-orchestrator scan. handoff-pickup: label these as skills (not commands); replace invented context percentages with the sourced run-when guidance. forensics: drop the false single-write-dir claim, fix GH issue body scope (full body incl. frontmatter), reword the prune statement. update-deps: correct branch behavior (any non-main branch runs in place, no PR). update-gaia: add the merge-audit-ci / .gaia/audit-ci.yml field-aware merge surface. Telemetry and forensics-triage.yml stay unleaked; mentorship muted. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/commands/forensics.mdx | 6 +++--- src/content/docs/commands/handoff-pickup.mdx | 6 ++---- src/content/docs/commands/index.mdx | 14 +++++++------- src/content/docs/commands/plan.mdx | 6 +++--- src/content/docs/commands/spec.mdx | 10 +++++----- src/content/docs/commands/update-deps.mdx | 2 +- src/content/docs/commands/update-gaia.mdx | 14 ++++++++------ 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/content/docs/commands/forensics.mdx b/src/content/docs/commands/forensics.mdx index 4b9e9dd..24eb658 100644 --- a/src/content/docs/commands/forensics.mdx +++ b/src/content/docs/commands/forensics.mdx @@ -75,7 +75,7 @@ class_state_files: ``` -The body posted to a GitHub issue is the post-frontmatter portion (`## Symptom` through the end), byte-identical to the local file body. +The body posted to a GitHub issue is the full body, frontmatter and all four sections, byte-identical to the local file body at filing time. After filing, the local file gains the `gh_issue_url` value in its frontmatter. ## Hard constraints @@ -84,7 +84,7 @@ These four rules are non-negotiable. They apply to every code path. - **Read-only end-to-end.** Forensics inspects state. It never modifies, installs, fetches, or remediates. -- **Write surface allowlist.** Writes go to one user-visible directory: `.gaia/local/forensics/` for the report. No other path is writable. +- **Write surface allowlist.** Writes go to `.gaia/local/forensics/` for the report. - **Uniform redaction.** The local file body and the GitHub issue body pass through the same single redaction pass. The two bodies are byte-identical post-redaction. - **Strict body schema.** Frontmatter fields, section headers, and section order are fixed. Drift breaks downstream triage. @@ -112,4 +112,4 @@ If you say no, the report stays local and you can attach it to a manual issue la ## Storage -`.gaia/local/forensics/` is project-local and gitignored. Reports stay on your machine unless you explicitly file them. Old reports are not pruned automatically. +`.gaia/local/forensics/` is project-local and gitignored. Reports stay on your machine unless you explicitly file them. The workflow defines no automatic pruning, so reports accumulate under `.gaia/local/forensics/` until you remove them yourself. diff --git a/src/content/docs/commands/handoff-pickup.mdx b/src/content/docs/commands/handoff-pickup.mdx index abb06ec..110c52d 100644 --- a/src/content/docs/commands/handoff-pickup.mdx +++ b/src/content/docs/commands/handoff-pickup.mdx @@ -7,16 +7,14 @@ sidebar: import { Aside } from '@astrojs/starlight/components'; -| Command | What it does | +| Skill | What it does | | --- | --- | | `/gaia-handoff` | Writes a self-contained handoff document so you can clear context. | | `/gaia-pickup` | Reads the most recent handoff and reconstitutes context. | ## When to use them -Run `/gaia-handoff` when your context starts getting "heavy". A good rule of thumb is: -- **Opus 1M** - 20-25% -- **Sonnet/Haiku** - 40-60% +Run `/gaia-handoff` at the end of a session, before a context break, or when the current state is non-obvious. In practice that means when the context window is getting full and you are about to `/clear`, `/compact`, or restart Claude. Then `/clear` (or exit Claude and restart). diff --git a/src/content/docs/commands/index.mdx b/src/content/docs/commands/index.mdx index 8030456..f75e9df 100644 --- a/src/content/docs/commands/index.mdx +++ b/src/content/docs/commands/index.mdx @@ -5,7 +5,7 @@ sidebar: order: 1 --- -GAIA's day-to-day workflows are discrete slash entries that show up in autocomplete as you type `/gaia-`. Six are commands (`/gaia-plan`, `/gaia-spec`, `/gaia-audit`, `/gaia-fitness`, `/gaia-forensics`, `/gaia-harden`). Three are skills (`/gaia-wiki`, `/gaia-handoff`, `/gaia-pickup`) that also respond to plain-English requests, not just the slash form. +Most of GAIA's day-to-day workflows are discrete slash entries that show up in autocomplete as you type `/gaia-`. Six are commands (`/gaia-plan`, `/gaia-spec`, `/gaia-audit`, `/gaia-fitness`, `/gaia-forensics`, `/gaia-harden`). Three are skills (`/gaia-wiki`, `/gaia-handoff`, `/gaia-pickup`) that also respond to plain-English requests, not just the slash form. ## Workflow Commands @@ -20,10 +20,10 @@ GAIA's day-to-day workflows are discrete slash entries that show up in autocompl | Command | What it does | | --- | --- | -| [`/gaia-audit`](/commands/audit/) | Audit memory, rules, and wiki for duplication, contradictions, stale entries, and unnecessary base context overhead. | -| [`/gaia-fitness`](/commands/fitness/) | Health check and auto-heal for the Claude integration surface. Triage, heal, verify, with a letter grade. | -| [`/gaia-harden`](/commands/harden/) | Human-gated Policy-Memory Loop. Reviews recurring code-review-audit findings and drafts the lowest-context-weight enforcement form for your approval. | -| [`/gaia-wiki`](/commands/wiki/) | Wiki maintenance. With no arguments, runs the full chain. Each can also be invoked individually. | +| [`/gaia-audit`](/commands/audit/) | Audit memory, wiki, and auto-loaded files for duplication, conflicting instructions, and stale content. | +| [`/gaia-fitness`](/commands/fitness/) | Health check and auto-heal for the Claude integration surface. Triage, heal, verify, and report an F-to-A+ grade. | +| [`/gaia-harden`](/commands/harden/) | Human-gated hardening. Reviews recurring code-review-audit findings and, with approval, drafts the lowest-context-weight enforcement form (rule, skill, or deterministic check) into the working tree. | +| [`/gaia-wiki`](/commands/wiki/) | Wiki maintenance. With no arguments, runs the full sync, consolidate, and lint chain; each stage can also be invoked by name. | ## Update Commands @@ -36,8 +36,8 @@ GAIA's day-to-day workflows are discrete slash entries that show up in autocompl | Command | What it does | | --- | --- | -| [`/gaia-forensics`](/commands/forensics/) | If you encounter any issues with GAIA commands, this will triage the issue and submit a bug report. | +| [`/gaia-forensics`](/commands/forensics/) | Triage a GAIA workflow misfire into a redacted, classified bug report. Files upstream on confirmation. | ## No-argument behavior -Each entry has a sensible default when called with no arguments. `/gaia-wiki` runs the full chain (sync, consolidate, lint). `/gaia-audit` researches, then asks before it applies. `/gaia-harden` defaults to its interactive review mode. `/gaia-plan`, `/gaia-spec`, and `/gaia-forensics` prompt for or infer what they need before continuing. +Each entry has a sensible default when called with no arguments. `/gaia-wiki` runs the full chain (sync, consolidate, lint). `/gaia-audit` researches, then asks before it applies. `/gaia-harden` defaults to `review` mode. `/gaia-plan`, `/gaia-spec`, and `/gaia-forensics` prompt for or infer what they need before continuing. diff --git a/src/content/docs/commands/plan.mdx b/src/content/docs/commands/plan.mdx index 621d568..5341b1a 100644 --- a/src/content/docs/commands/plan.mdx +++ b/src/content/docs/commands/plan.mdx @@ -22,7 +22,7 @@ For feature work that has not been clarified yet, run [`/gaia-spec`](/commands/s Or, with a SPEC reference (typically passed automatically by `/gaia-spec`): ``` -/gaia-plan SPEC-005: rework auth, see .gaia/local/specs/SPEC-005.md +/gaia-plan SPEC-005: rework auth, see .gaia/local/specs/SPEC-005/SPEC.md ``` If you invoke `/gaia-plan` with no description, it asks for one before continuing. @@ -55,7 +55,7 @@ Inside the directory: 4. **Planner dispatch.** The skill spawns a `general-purpose` Agent restricted to writing inside the plan directory only. The planner reads `wiki/concepts/Task Orchestration.md` for the orchestration pattern, then writes the plan files directly to disk. 5. **Verification.** The skill confirms `README.md`, `ORCHESTRATOR.md`, `KICKOFF.md`, and at least one `task-*.md` exist. If anything is missing, the failure surfaces; no silent retry. 6. **Decomposition audit.** For non-trivial plans, the skill offers to stress-test the decomposition before hand-off, and running it is the recommended choice. See [Decomposition audit](#decomposition-audit). -7. **Hand-off.** The skill prints the kickoff prompt as a fenced code block and tries to copy it to the system clipboard via `pbcopy`, `wl-copy`, `xclip`, `xsel`, `clip.exe`, or `clip` (whichever is available). The trailing line says whether the copy succeeded. +7. **Hand-off.** The skill prints a short summary of the plan directory, then the kickoff prompt as a fenced code block you select and copy yourself. The trailing line reads `Type /clear and paste the prompt above.` The kickoff prompt looks exactly like: @@ -93,7 +93,7 @@ Before any `gh pr merge` invocation, the orchestrator spawns the `code-review-au ## Branch policy -If the orchestrator starts on `main`, it asks how to isolate the work: a feature branch in place (recommended) or a linked git worktree (experimental). On any other branch, it assumes the current branch is the work branch and proceeds. +If the orchestrator starts on `main`, it asks how to isolate the work: a feature branch in place (recommended) or a linked git worktree (experimental). On any other branch, it first scans for a live orchestrator already running on that branch. If none is found, it treats the current branch as the work branch and proceeds without prompting. If one is found, it surfaces the three-choice prompt covered in [Running more than one at once](#running-more-than-one-at-once). ## Stop conditions diff --git a/src/content/docs/commands/spec.mdx b/src/content/docs/commands/spec.mdx index 3f6523c..7a9ef7b 100644 --- a/src/content/docs/commands/spec.mdx +++ b/src/content/docs/commands/spec.mdx @@ -39,7 +39,7 @@ A description is required in auto mode. Without one, the skill aborts immediatel The SPEC has two gates and they are non-negotiable. -**Gate 1: shape confirmation.** Before any clarifying question fires, the skill presents the proposed `intent` paragraph and the proposed UATs in plain English. The user reads, confirms, or revises. On confirmation, the gate-1 shape is snapshotted to `.gaia/local/cache/gate1-.json` and treated as immutable for the remainder of the session. The self-review at gate 2 detects drift against this snapshot. +**Gate 1: shape confirmation.** Before any clarifying question fires, the skill presents the proposed `intent` paragraph and the proposed UATs in plain English. The user reads, confirms, or revises. On confirmation, the gate-1 shape is snapshotted to `.gaia/local/cache/gate1-.json` and treated as immutable for the remainder of the session. The self-review before gate 2 detects drift against this snapshot. **Gate 2: artifact confirmation.** After the Socratic loop and self-review apply, the full rendered SPEC is presented to the user one last time. Revisions loop until the user confirms. Only then does the canonical save fire. @@ -49,7 +49,7 @@ Once saved, the SPEC artifact is immutable. Mutations require an explicit reopen A handful of mechanics are used by multiple steps: -- **Working-draft cache.** Every fold in the Socratic loop, every gate confirmation, every research result, every self-review apply persists the in-flight draft to `.gaia/local/cache/draft-.md`. A single `Write` per turn. No incremental `Edit` calls. Step 10's canonical save deletes the cache as its final action. Resumed sessions pick up the cache if it is newer than the canonical artifact. +- **Working-draft cache.** Every fold in the Socratic loop, every gate confirmation, every research result, every self-review apply, and every audit-finding apply persists the in-flight draft to `.gaia/local/cache/draft-.md`. A single `Write` per turn. No incremental `Edit` calls. Step 10's canonical save deletes the cache as its final action. Resumed sessions pick up the cache if it is newer than the canonical artifact. - **Per-topic revisit counter.** Tracks how many times the user has chosen "push deeper" on a given topic. On the third revisit, the prompt swaps to settle, defer, or push deeper anyway. Prevents one topic from consuming the whole session. - **Five-question cap.** Spec-kit's `/clarify` primitive caps the loop at five total questions per session. The wrapper inherits this cap and never invokes `/clarify` twice to extend it. - **Discuss-this escape.** Any closed-set question can drop into a plain Q&A discussion. On settlement, the outcome folds into `clarifications.answered[]` and the structured loop resumes on the next topic. @@ -68,7 +68,7 @@ A handful of mechanics are used by multiple steps: 9. **Gate 2.** Plain prompt: confirm the full rendered artifact, or revise. 10. **Canonical save.** Writes `.gaia/local/specs/SPEC-NNN/SPEC.md` and deletes the working-draft cache. The `after_specify` hook fires `/speckit-gaia-lint` for immutability checks. Cycles 1 and 2 surface failures; cycle 3 prompts to step back to gate 2, defer remaining findings, or push another fix. 11. **Optional GitHub issue mirror.** If opted in at step 2, `gh-mirror.sh` creates the issue and stamps the URL into frontmatter. Skips silently when `gh` is not authenticated, Issues are disabled, or the viewer lacks write permission. -12. **Chain to `/gaia-plan`.** `AskUserQuestion`: trigger `/gaia-plan` now or defer. On yes, the skill enters a multi-plan dispatch loop. Each plan runs in its own `general-purpose` Agent so the wrapper context stays bounded across plan count. +12. **Chain to `/gaia-plan`.** `AskUserQuestion`: trigger `/gaia-plan` now or defer. On yes, the skill enters a multi-plan dispatch loop, running `/gaia-plan` inline for each slice you author. The heavy planning for each slice is isolated in a subagent that returns only a compact result, so the session's context stays bounded no matter how many plans you author. ## Auto mode @@ -100,7 +100,7 @@ A spec only writes its own artifacts and never touches git, so it also runs clea ## How spec-kit fires GAIA hooks -Spec-kit's hooks are not shell scripts. When core invokes `/speckit-specify` (or any other core skill), it reads `.specify/extensions.yml` for the relevant event and emits an `EXECUTE_COMMAND: ` markdown directive into the agent's reasoning context. The agent then invokes the rendered slash command as a normal Claude skill. +Spec-kit's hooks are not shell scripts. When core invokes `/speckit-specify` (or any other core skill), it reads the registered spec-kit extension configuration for the relevant event and emits an `EXECUTE_COMMAND: ` markdown directive into the agent's reasoning context. The agent then invokes the rendered slash command as a normal Claude skill. Five GAIA hooks fire across the SPEC lifecycle. Never invoke them by hand. @@ -112,7 +112,7 @@ Five GAIA hooks fire across the SPEC lifecycle. Never invoke them by hand. | `before_implement` | `/speckit-gaia-uat-write` | Renders frozen UATs into Playwright e2e specs at `.playwright/e2e//`, leaving a red-state harness before implementation begins. | | `after_implement` | `/speckit-gaia-wiki-promote` | Promotes merged-PR content into the project wiki under `wiki//`. Defers if the implementing PR has not merged yet. | -The chain-trigger to `/gaia-plan` lives inline at step 12 of the flow, not as a hook. Disposition of the SPEC artifact (archive, delete, or keep) is automatic after the implementing PR merges: on the immediate-merge path the `after_implement` wiki-promote step chains to `/speckit-gaia-spec-close`, and the step-3 housekeeping passes archive any SPEC whose PR has since merged. Running `/speckit-gaia-spec-close [SPEC-NNN]` by hand is a backstop, for draining a deferred wiki-promote when the PR merges after implementation, or for choosing delete or keep instead of the default archive. The SPEC ID is optional; omit it and the command surfaces every eligible SPEC to choose from. +The chain-trigger to `/gaia-plan` lives inline at step 12 of the flow, not as a hook. Disposition of the SPEC artifact (archive, delete, or keep) is automatic after the implementing PR merges: on the immediate-merge path the `after_implement` wiki-promote step chains to `/speckit-gaia-spec-close`, and the step-3 housekeeping passes archive any SPEC whose PR has since merged. Running `/speckit-gaia-spec-close [SPEC-NNN]` by hand is a backstop, for draining a deferred wiki-promote when the PR merges after implementation, or for choosing delete or keep instead of the default archive. The SPEC ID is optional; omit it and the command targets the single eligible SPEC, or prompts you to choose when more than one is eligible. ## Related diff --git a/src/content/docs/commands/update-deps.mdx b/src/content/docs/commands/update-deps.mdx index bf70024..728b47b 100644 --- a/src/content/docs/commands/update-deps.mdx +++ b/src/content/docs/commands/update-deps.mdx @@ -87,7 +87,7 @@ For major-version bumps, the skill makes one remediation pass if the quality gat ## Gotchas - Must run from the main checkout, not a linked worktree. The skill rejects worktree invocations early and surfaces the cached outdated count from main so you know whether action is even pending. -- Must run from `main` or `master`, or from an existing chore branch. If on `main`, the skill creates `chore/update-deps-`. +- On `main` or `master`, the skill creates `chore/update-deps-` and opens a PR after updates apply. On any other branch, it runs in place and pushes without opening a PR. - The final report is built from agent-returned data only. Anything filtered before installation (the ESLint cap) is silent on purpose. - `actionable_count` in the statusline already subtracts snoozed groups; the skill uses `total_count` internally for the actual apply set. diff --git a/src/content/docs/commands/update-gaia.mdx b/src/content/docs/commands/update-gaia.mdx index 23e4c76..71e5884 100644 --- a/src/content/docs/commands/update-gaia.mdx +++ b/src/content/docs/commands/update-gaia.mdx @@ -24,7 +24,7 @@ The three-way merge is governed by ownership classes defined in `.gaia/manifest. | Class | Who controls it | On drift | | --- | --- | --- | | `owned` | GAIA fully. Overwritten silently when unchanged from baseline. | Prompts if you have local changes. | -| `shared` | GAIA seeds, you customize. | Emits a `.gaia-merge/.patch` for manual resolution. Exception: `package.json` and `pnpm-workspace.yaml` get field-aware key-level merges instead of whole-file conflict patches (see below). | +| `shared` | GAIA seeds, you customize. | Emits a `.gaia-merge/.patch` for manual resolution. Exception: `package.json`, `pnpm-workspace.yaml`, and `.gaia/audit-ci.yml` get field-aware key-level merges instead of whole-file conflict patches (see below). | | `wiki-owned` | GAIA-seeded wiki pages (concepts, decisions, modules). Same as `shared`. | Emits a patch for manual resolution. | | adopter-owned (implicit) | Anything not in the manifest, plus sentinels like `wiki/hot.md`, `wiki/log.md`, `CHANGELOG.md`, `.gaia/VERSION`, `.gaia/manifest.json`. | Never touched. | @@ -34,9 +34,9 @@ The three-way merge is governed by ownership classes defined in `.gaia/manifest. 2. Resolves the latest release tag via `gh release list --repo gaia-react/gaia` (falls back to the GitHub API). 3. Shows the release notes and asks you to confirm. 4. Downloads the baseline and latest tarballs into `.gaia/cache/` (gitignored). -5. Runs the three-way merge per file directly (no CLI subcommand). Owned files are overwritten or conflict-patched; shared and wiki-owned files are merged or conflict-patched. `package.json` and `pnpm-workspace.yaml` are both classed `shared` but receive field-aware key-level merges rather than whole-file patches (see below). +5. Runs the three-way merge per file directly (no CLI subcommand). Owned files are overwritten or conflict-patched; shared and wiki-owned files are merged or conflict-patched. `package.json`, `pnpm-workspace.yaml`, and `.gaia/audit-ci.yml` are all classed `shared` but receive field-aware key-level merges rather than whole-file patches (see below). 6. Walks any conflicts with you one at a time; reads `.gaia-merge/.patch` for each. -7. For `pnpm-workspace.yaml`, uses `gaia update merge-workspace` to compute per-key verdicts. This is a field-aware merge of both the GAIA-managed settings keys and the `overrides` and `allowBuilds` maps. Overrides and build approvals live here (pnpm 11 no longer reads them from `package.json`); an adopter-only entry is never visited or clobbered. +7. For `pnpm-workspace.yaml`, uses `gaia update merge-workspace` to compute per-key verdicts. This is a field-aware merge of both the GAIA-managed settings keys and the `overrides` and `allowBuilds` maps. Overrides and build approvals live here (pnpm 11 no longer reads them from `package.json`); an adopter-only entry is never visited or clobbered. For `.gaia/audit-ci.yml`, uses `gaia update merge-audit-ci` to compute per-key and per-author-entry verdicts. 8. Prompts before deleting any file that the latest release removed. 9. Prints a summary with counts (overwritten, added, skipped, conflicts, deleted, backed up) and per-file counts for `package.json` and `pnpm-workspace.yaml` (applied, conflicts, suggestions). Then writes the new version to `.gaia/VERSION` and copies the latest manifest into `.gaia/manifest.json`. The VERSION bump is deferred to this point so an interrupted run stays resumable at the baseline version. @@ -44,17 +44,19 @@ Backups land in `.gaia-backup//`. Conflict patches land in `.gaia-mer ## Field-aware merges -`package.json` and `pnpm-workspace.yaml` are both classed `shared`, but a whole-file three-way merge produces noise for them (every project diverges `package.json` at init; every override addition drifts `pnpm-workspace.yaml`). Both get key-level merges instead. +`package.json`, `pnpm-workspace.yaml`, and `.gaia/audit-ci.yml` are all classed `shared`, but a whole-file three-way merge produces noise for them (every project diverges `package.json` at init; every override addition drifts `pnpm-workspace.yaml`; every developer's `audit_authors` entry drifts `.gaia/audit-ci.yml`). All three get key-level merges instead. **`package.json`** merges at JSON-key granularity across the managed sections: `dependencies`, `devDependencies`, `scripts`, `engines`, and `packageManager`. Identity keys (`name`, `version`, `description`, `author`, etc.) are never compared or patched. For each managed key, the outcome is one of: **apply** (GAIA changed it, you are still at the baseline pin), **conflict** (GAIA changed it, you re-pinned independently, left as yours with a note), or **suggestion** (GAIA added a key or changed one you removed, surfaced opt-in, never auto-inserted). Applied changes are written in place; conflicts and suggestions go to `.gaia-merge/package.json.notes`. **`pnpm-workspace.yaml`** merges at key/entry granularity using `gaia update merge-workspace`. The seven GAIA-managed settings keys (`minimumReleaseAge`, `trustPolicy`, etc.) are compared whole-value; the `overrides` and `allowBuilds` maps are compared per entry. An adopter-only override or build approval is never visited. Same apply/conflict/suggestion buckets as `package.json`; notes go to `.gaia-merge/pnpm-workspace.yaml.notes`. If the file is missing in the baseline (pre-pnpm 11 project) or unparseable, the skill falls back to a whole-file conflict patch. -A release that touches no managed keys in either file produces a clean skip with no notes file. +**`.gaia/audit-ci.yml`** merges at key/entry granularity using `gaia update merge-audit-ci`. The seven GAIA-managed scalar knobs (`gate_label`, `budget_seconds`, `max_turns`, `push_fixes`, `default_mode`, `override_label`, `retrigger_workflows`) are compared whole-value; `audit_authors`, a space-separated `login=mode` list each developer appends their own entry to, is compared per login. An adopter-only developer entry is never visited or clobbered. Same apply/conflict/suggestion buckets as `package.json`; notes go to `.gaia-merge/audit-ci.yml.notes`. If the file is absent from the baseline (projects that predate this file) or unparseable, the skill falls back to a whole-file conflict patch. + +A release that touches no managed keys in any of these files produces a clean skip with no notes file. ## After the run -Review patches in `.gaia-merge/`, reconcile any `.gaia-merge/package.json.notes` or `.gaia-merge/pnpm-workspace.yaml.notes` files, then run `pnpm install` if `package.json` or `pnpm-workspace.yaml` was changed. Run the quality gate and inspect `git diff` before committing. The skill does not auto-commit. When satisfied: +Review patches in `.gaia-merge/`, reconcile any `.gaia-merge/package.json.notes`, `.gaia-merge/pnpm-workspace.yaml.notes`, or `.gaia-merge/audit-ci.yml.notes` files, then run `pnpm install` if `package.json` or `pnpm-workspace.yaml` was changed. Run the quality gate and inspect `git diff` before committing. The skill does not auto-commit. When satisfied: ``` git commit -m "chore: update GAIA to " From 0871bff094be5d1a3591092bfc0173b0ab9c4b2a Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 15:40:30 +0900 Subject: [PATCH 15/25] docs: accuracy pass on maintenance pages maintenance overview: add the /gaia-harden row, fix /gaia-audit scope (memory, wiki, and auto-loaded files, not "rules"), quote the description to fix YAML frontmatter. fitness: correct the "what gets checked" categories against the integration fitness rubric, fix card header/sizing, ground the A-grade meaning, add grade count boundaries, fix default-branch detection wording. audit: fix statusline nudge reason strings, note the replace/shrink output label and ordering, complete the audited-stores table, add the gaia-harden provenance-rule exclusion. harden: add the redirect action to the intro action set. wiki: fix Cross-SPEC consolidate scope, the full-chain line-absent path, the sync state bootstrap, and remove the unverified wiki/meta auto-creation claim. Wiki framing preserved; mentorship/telemetry muted; no contributor leaks. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/commands/audit.mdx | 19 ++++++++++------ src/content/docs/commands/fitness.mdx | 30 ++++++++++++------------- src/content/docs/commands/harden.mdx | 2 +- src/content/docs/commands/wiki.mdx | 32 +++++++++++++++++---------- src/content/docs/maintenance.mdx | 11 +++++---- 5 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/content/docs/commands/audit.mdx b/src/content/docs/commands/audit.mdx index bf515ad..abc5492 100644 --- a/src/content/docs/commands/audit.mdx +++ b/src/content/docs/commands/audit.mdx @@ -55,13 +55,16 @@ Nothing in any knowledge store is touched until you choose **Apply**. | Store | Path | Auto-loaded? | | --- | --- | --- | -| Machine-local project memory | `~/.claude/projects//memory/` | `MEMORY.md` (first 200 lines) | +| Machine-local project memory | `~/.claude/projects//memory/` | `MEMORY.md` (first 200 lines), individual entries on demand | | Machine-local agent memory | `~/.claude/agent-memory/` | Per-agent, on demand | | Project agent memory | `.claude/agent-memory/` | Per-agent, on demand | | Project root `CLAUDE.md` | `CLAUDE.md` | Yes, every session | | Wiki hot cache | `wiki/hot.md` | Yes, every session | +| Wiki index | `wiki/index.md` | On demand | +| Wiki README | `wiki/README.md` | On demand | | Wiki domain pages | `wiki//` | On demand | | Project rules | `.claude/rules/*.md` | Yes when `paths:` frontmatter matches | +| Project commands | `.claude/commands/*.md` | On invocation only | | Nested `CLAUDE.md` | `**/CLAUDE.md` (e.g. monorepo packages) | Yes when cwd matches | The audit checks each entry against the other stores and classifies it as: @@ -74,6 +77,8 @@ The audit checks each entry against the other stores and classifies it as: Contradiction detection has two deliberate exclusions: a `paths:`-scoped rule that duplicates the wiki on purpose is sanctioned, not a conflict; and a wiki-page-vs-wiki-page disagreement is out of scope here. For that, use `/gaia-wiki consolidate`. +A rule that carries a `gaia-harden:` provenance marker (one [`/gaia-harden`](/commands/harden/) promoted from a recurring finding) falls under the same path-scoped exclusion. It always carries a `paths:` glob, so the audit inventories it, word-budgets it, and applies the same DUPLICATE and obsolescence prune rules as a hand-authored rule. The marker grants no exemption, and a rule is never marked STALE just because its pattern stopped recurring. + Then it computes auto-load budgets: | File | Budget | @@ -100,9 +105,9 @@ The two-stage split is technical (the stages carry different reasoning loads, wi | `delete` | Remove a memory or rules file whose facts are canonical in the wiki, gated on the file's SHA-256 matching what the report saw. | | `delete-entry` | Remove a specific block (e.g. a heading section in `MEMORY.md`) by verbatim match. | | `promote` | Move durable knowledge from memory to a named wiki page. Performs the target action (`append_section`, `insert_after_heading`, or `create_new`), prepends a log entry to `wiki/log.md`, appends an index entry to `wiki/index.md`, then deletes the source if the action says to. | -| `replace` | Shrink inline content in an autoloaded file to a wikilink, or swap a contradicting line for the canonical value. The current block must match byte-for-byte. | +| `replace` | Shrink inline content in an autoloaded file to a wikilink, or swap a contradicting line for the canonical value. The current block must match byte-for-byte. In report output and action IDs this type shows as `shrink` (for example `shrink-001`). | -The apply stage runs actions in order: `replace` → `delete-entry` → `promote` → `delete`. Earlier replaces never reference content that later actions touch; deletes come last so pointers do not go stale before they are used. Contradiction findings reuse `replace` and `delete`; there is no separate action type for them. +The apply stage runs actions in order: `shrink` → `delete-entry` → `promote` → `delete`. Earlier shrinks never reference content that later actions touch; deletes come last so pointers do not go stale before they are used. Contradiction findings reuse `replace` and `delete`; there is no separate action type for them. ## Report lifecycle and resume @@ -145,11 +150,11 @@ Reports live under `.gaia/local/audit/` and are gitignored. They are machine-loc ## Statusline nudge -GAIA surfaces `Run /gaia-audit ()` in the statusline when any of three conservative, debounced signals fires: +GAIA surfaces `Run /gaia-audit ()` in the statusline when any of three conservative, debounced signals fires. The `` is the literal string shown in parentheses. Only the highest-priority signal appears at a time, in this order: -- **Memory drift**: machine-local memory has grown by 10 or more entries, or 30 or more days have passed since the last applied audit. -- **Project drift**: an autoloaded file is over budget (`wiki/hot.md` over 200 words, root `CLAUDE.md` over 400 words, or any `.claude/rules/*.md` over 200 lines). -- **Pending draft**: a `draft` report is waiting to be resumed. +- `resume draft`: a `draft` report is waiting to be resumed. +- `machine drift`: machine-local memory has grown by 10 or more entries, or 30 or more days have passed since the last applied audit. +- `over budget`: an autoloaded file is over budget (`wiki/hot.md` over 200 words, root `CLAUDE.md` over 400 words, or any `.claude/rules/*.md` over 200 lines). The nudge is suppressed inside git worktrees and is computed in a cached background refresher, never on the statusline's render path. All thresholds are tunable. diff --git a/src/content/docs/commands/fitness.mdx b/src/content/docs/commands/fitness.mdx index c6e91a3..32904f1 100644 --- a/src/content/docs/commands/fitness.mdx +++ b/src/content/docs/commands/fitness.mdx @@ -27,13 +27,13 @@ Triage dispatches seven category checks in parallel. Each produces a set of find | Category | What it checks | | --- | --- | -| Hook integrity | `.claude/hooks/*` scripts and their wiring in `settings.json`. | -| Skill / command / agent frontmatter | `.claude/skills/**`, `.claude/commands/**`, `.claude/agents/**` frontmatter completeness and validity. | -| Rule hygiene | `.claude/rules/*.md` scope, `paths:` frontmatter, size. | -| `CLAUDE.md` hygiene | Root and nested `CLAUDE.md` files: size, structure, duplication. | -| Settings hygiene | `.claude/settings.json`: permission pairs, redundancy, malformed entries. | -| GAIA-install fitness | Whether the GAIA install is intact and consistent. | -| Wiki fitness | Wiki structure: state file, manifest, orphans, dead repo-relative paths. | +| Hook integrity | Hook commands wired in `.claude/settings.json` (and `settings.local.json`) exist and are executable, and every hook event name is valid. | +| Skill / command / agent frontmatter | `name` and `description` present and non-placeholder across `.claude/skills/**`, `.claude/commands/**`, `.claude/agents/**`, with no name collisions. | +| Rule hygiene | `.claude/rules/*.md`: valid `paths:` glob syntax, no skill `@`-imports, glob-versus-content coherence, and that rules cited in `CLAUDE.md` exist. | +| `CLAUDE.md` hygiene | Root and folder-map `CLAUDE.md` files: size against guidance, resolvable `@`-imports, existing folder-map targets, and no dead or machine-local path references. | +| Settings hygiene | `.claude/settings.json`: valid JSON, redundant permission entries, secret-shaped `env` values, and whether `.claude/settings.local.json` is gitignored. | +| GAIA-install fitness | Drift between GAIA-managed files and the contents the installed version shipped, plus whether a newer GAIA release is available. | +| Wiki fitness | Wiki state-file staleness, orphan pages, and dead path references in wiki prose. | The checks are recall-oriented and over-flag on purpose. Before grading, `/gaia-fitness` adjudicates each finding against the actual repo and drops the false positives (an unfamiliar-but-valid hook event, a permission pair that only looks redundant, and so on). What survives gets graded. @@ -41,14 +41,14 @@ The checks are recall-oriented and over-flag on purpose. Before grading, `/gaia- Each category gets a letter grade. A+ means zero findings. From there the grade keys off the worst severity present, then the count at that severity: -- All findings at `info`: stays in the A band (`A`, then `A-` as the count grows). -- A `warning` is the worst severity: B band. -- An `error` is the worst severity: C band, dropping through D as errors pile up. -- A structurally broken category: F. +- All findings at `info`: A band. `A` for one or two, `A-` for three or more. +- A `warning` is the worst severity: B band. `B+` for one, `B` for two, `B-` for three or more. +- An `error` is the worst severity: C and D bands. `C+` for one, `C` for two, `C-` for three, then `D+` for four, `D` for five, `D-` for six or more. +- A structurally broken category (an unparseable `settings.json`, a missing `CLAUDE.md`): F. The **overall grade is the floor of the seven category grades**. The integration is only as fit as its weakest surface. -An `A` should be considered a clean bill of health. +An `A` means only advisory `info` findings remain. They surface in the FINDINGS block with remediation text but signal no structural breakage. ## The three phases @@ -62,7 +62,7 @@ An `A` should be considered a clean bill of health. Where the fixes land depends on which branch you are on when you run it: -- **On the default branch** (`main`), with at least one fixable finding: `/gaia-fitness` creates and switches to a new branch named `chore/gaia-fitness-` before applying anything, so `main` stays untouched. +- **On your repo's default branch** (detected from the repo, typically `main`), with at least one fixable finding: `/gaia-fitness` creates and switches to a new branch named `chore/gaia-fitness-` before applying anything, so the default branch stays untouched. - **On any other branch**, with at least one fixable finding: it heals in place on your current branch. - **No fixable findings** (including a clean A+ run): no branch is created, `HEAD` stays put, nothing changes. @@ -76,13 +76,13 @@ Before any heal-phase change, `/gaia-fitness` checks whether the repo is safe to The card has three sections: -1. **Header row.** The command name (`/gaia-fitness`), the overall grade, and the `OVERALL` label right-aligned. +1. **Header row.** The command name (`/gaia-fitness`) on the left, with the `OVERALL` label and the overall grade right-aligned. 2. **Category rows.** One row per category, alphabetically sorted. Each row shows the category name, a compact severity note (for example, `2 errors, 1 warning`), and the category grade. A clean category shows no note. 3. **FINDINGS block** (omitted on a clean run). When there are adjudicated findings, a `FINDINGS` section follows the category rows. Findings are grouped by category, and each entry shows the severity tag (`[error]`, `[warning]`, or `[info]`), the file path, and the remediation text, word-wrapped to fit the terminal width. Unresolved or unfixable findings appear here with their recommended approach. On a clean run (zero adjudicated findings, overall A+), the FINDINGS block is omitted. The card shows only the header and category rows, all graded A+. -The card self-sizes: the box width is clamped to the longest content line, with a hard ceiling of 120 columns and a floor set by the widest category name. Remediation text wraps to fit. +The card self-sizes. The box width tracks the longest content line, capped at 120 columns or the terminal width (whichever is smaller) and floored wide enough to keep the category names and grades from colliding. Remediation text wraps to fit. Then, depending on what happened: diff --git a/src/content/docs/commands/harden.mdx b/src/content/docs/commands/harden.mdx index 507adba..9793dee 100644 --- a/src/content/docs/commands/harden.mdx +++ b/src/content/docs/commands/harden.mdx @@ -3,7 +3,7 @@ title: /gaia-harden description: Human-gated Policy-Memory Loop. Reviews recurring code-review-audit findings and, with your approval, drafts the lowest-context-weight enforcement form into the working tree. --- -`/gaia-harden` is the human gate on the Policy-Memory Loop. When the same anti-pattern recurs across three or more distinct merged PRs at `warning` or `error` severity within a rolling 90-day window, the statusline nudges you with `Run /gaia-harden (N recurring patterns)`. Calling `/gaia-harden` reads the live candidate queue, judges the lightest durable enforcement form for each finding, and presents a per-candidate approve / decline / defer choice. Nothing is authored or activated without your answer. +`/gaia-harden` is the human gate on the Policy-Memory Loop. When the same anti-pattern recurs across three or more distinct merged PRs at `warning` or `error` severity within a rolling 90-day window, the statusline nudges you with `Run /gaia-harden (N recurring patterns)`. Calling `/gaia-harden` reads the live candidate queue, judges the lightest durable enforcement form for each finding, and presents a per-candidate approve / decline / defer / redirect choice. Nothing is authored or activated without your answer. ## When to use it diff --git a/src/content/docs/commands/wiki.mdx b/src/content/docs/commands/wiki.mdx index 7d56eef..fb34b1a 100644 --- a/src/content/docs/commands/wiki.mdx +++ b/src/content/docs/commands/wiki.mdx @@ -31,15 +31,17 @@ chain single-writer, which is why CI is the recommended path. There are three main commands, plus a full-chain mode that runs them in sequence. Each command is described in detail below. ``` -/gaia-wiki [sync|consolidate|lint] +/gaia-wiki [--force] [sync|consolidate|lint] ``` | Argument | Behavior | | --- | --- | | `sync` | Evaluate commits since the last sync. Update wiki pages where warranted. No chaining. | -| `consolidate` | Cross-page redundancy and contradiction audit. Surfaces findings with action prompts. No chaining. | +| `consolidate` | Cross-SPEC redundancy and contradiction audit. Surfaces findings with action prompts. No chaining. | | `lint` | Health check: orphans, dead links, drift severity, narrative-reference scrub. No chaining. | -| (no argument) | Full chain: sync → consolidate → lint | +| (no argument) | Full chain: sync → consolidate (when the gate trips) → lint | + +`--force` is trailing and overrides the GAIA CI deferral. It is a no-op when CI does not manage the wiki for this repo. ## /gaia-wiki sync @@ -51,17 +53,21 @@ State lives in `wiki/.state.json`: - `last_evaluated_sha`: the commit sync most recently classified up to. - `last_evaluated_at`: when that classification ran. -- `last_consolidated_sha`: owned by consolidate. Sync preserves it. +- `last_consolidated_sha` and `last_consolidated_at`: owned by consolidate. Sync preserves them. + +On the very first sync, if `last_consolidated_sha` is absent, sync seeds it so the consolidate gate has a baseline to accumulate from. Consolidate owns every update after that. If drift exceeds 30 commits, sync asks before processing the full range. You can opt to sync the recent 20 only and re-anchor. +Run standalone, sync commits its own work. On `main` or `master` it cuts a `wiki-sync/-` branch and opens a pull request; on a feature branch it commits in place. In the full chain the branch is cut once up front and every stage commits onto it (see Full chain below). + Sync ends with a one-line trigger: `CONSOLIDATE_TRIGGERED: true|false`. Used by the full-chain mode to decide whether consolidate runs next. ## /gaia-wiki consolidate Detects redundancy and contradiction across the wiki. Four passes: -- **Same-subject across SPECs.** Pairs of pages in the same domain with matching titles or matching provenance gaps. The newer page is canonical; the older becomes a supersession candidate. +- **Same-subject across SPECs.** Pairs of pages in the same domain that share a title and were promoted from different SPECs at least 30 days apart. The newer page is canonical; the older becomes a supersession candidate. - **Reversed decisions.** Decision pages whose body negates an older decision page (`replaces`, `supersedes`, `deprecated in favor of`, etc.). The older page is flagged for retirement. - **Near-collision slugs.** Pairs within Levenshtein distance 2, or where one slug is a prefix of the other. - **Subject-orphaned pages.** Pages with zero inbound wikilinks, no body-title matches in `wiki/concepts/` or `wiki/modules/`, and no edits in 90 days. @@ -72,7 +78,7 @@ Consolidate does not commit. Applied edits stage; sync (or your manual commit) l ## /gaia-wiki lint -Standalone GAIA-native health check. Each check re-derives from a `gaia wiki` CLI primitive on every run, and the report is plain markdown GAIA owns end to end. The current checks: +Standalone GAIA-native health check. Each check re-derives on every run, most from a dedicated `gaia wiki` CLI primitive, and the report is plain markdown GAIA owns end to end. The current checks: - **#11 Wiki drift check.** Reports how many commits behind HEAD the wiki is. Severity: `none`, `low`, `medium`, `high`. High severity surfaces with a `WIKI DRIFT:` prefix. - **#12 Dead repo-relative paths.** Backticked paths in wiki body prose that no longer exist on disk (e.g. a hook removed in a refactor still cited in a concept page). @@ -81,7 +87,7 @@ Standalone GAIA-native health check. Each check re-derives from a `gaia wiki` CL - **#15 Frontmatter gaps.** Pages missing the required floor: `type` and `status`. - **#16 Empty sections.** Headings with no body content before the next heading. -Reports land at `wiki/meta/lint-report-YYYY-MM-DD.md`. The `wiki/meta/` directory is created locally on first lint run. +Reports land at `wiki/meta/lint-report-YYYY-MM-DD.md`. ## Full chain (no argument) @@ -89,16 +95,18 @@ Reports land at `wiki/meta/lint-report-YYYY-MM-DD.md`. The `wiki/meta/` director /gaia-wiki ``` -Runs sync. Reads the `CONSOLIDATE_TRIGGERED` line from sync's summary. If true, runs consolidate. Then runs lint. +The full chain lands every stage on one branch and opens a single pull request, not one PR per stage. On `main` or `master` it cuts a `wiki-sync/-` branch first, runs each stage so its commits land on that branch, then pushes, opens one PR, enables auto-merge, and returns to the base branch. On a feature branch it commits each stage in place and opens no PR. + +Sync runs first. The chain reads the `CONSOLIDATE_TRIGGERED` line from sync's summary: if `true`, consolidate runs; if `false`, consolidate is skipped. Lint always runs after. -The order matters: consolidate may move, rename, or archive pages, so lint runs last to check the true post-state. If sync exits on the re-anchor path or a partial-sync interruption, the chain stops; the wiki is in a known-incomplete state and consolidate against an unreachable past makes no sense. +The order matters: consolidate may move, rename, or archive pages, so lint runs last to check the true post-state. If sync exits on the re-anchor path or a partial-sync interruption, the `CONSOLIDATE_TRIGGERED` line is absent. The chain then skips both consolidate and lint, finishes the branch (landing any re-anchor commit, or removing the branch if sync produced nothing), and surfaces the incomplete state. Consolidating against an unreachable past makes no sense. ## Hooks that read state Three hooks consume `wiki/.state.json` in read-only mode: -- `wiki-drift-check`: surfaces drift severity on your first prompt of each session. -- `wiki-commit-nudge`: suggests a sync after commits that look wiki-relevant. -- `wiki-session-stop`: checks for uncommitted wiki changes and whether sync state advanced, then prompts accordingly. +- `wiki-drift-check`: on your first prompt of each session, reports how many commits the wiki is behind HEAD. +- `wiki-commit-nudge`: after a commit lands, reports the current drift count and suggests a sync. +- `wiki-session-stop`: at session end, if commits landed without the sync state advancing, prompts you to run sync. These never write the state file. Only sync and consolidate do. diff --git a/src/content/docs/maintenance.mdx b/src/content/docs/maintenance.mdx index 2d8dd0e..ecf924d 100644 --- a/src/content/docs/maintenance.mdx +++ b/src/content/docs/maintenance.mdx @@ -1,23 +1,25 @@ --- title: Maintenance -description: The GAIA commands that keep the GAIA setup itself in shape, the Claude integration surface, the loaded context, and the wiki. +description: 'The GAIA commands that keep the GAIA setup itself in shape: the integration surface, loaded context, wiki, and recurring review findings.' --- GAIA ships commands for doing work and commands for keeping the GAIA setup itself in shape. This page covers the second kind: the commands that check and repair GAIA's own setup as a project grows. -As a project accumulates work, three parts of that setup drift independently: +As a project accumulates work, four parts of that setup drift or accumulate independently: - the **Claude integration surface**: hooks, command and skill frontmatter, rule wiring, `.claude/settings.json`; - the **loaded context** Claude reads every session: machine-local memory, project rules, and autoloaded `CLAUDE.md` files; -- the **wiki** itself: pages that overlap or contradict each other, and broken wikilinks. +- the **wiki** itself: pages that overlap or contradict each other, and broken wikilinks; +- **recurring review findings**: patterns that code-review-audit flags repeatedly but that have not yet been codified as a rule, skill, or check. Each part has its own command. They run independently and do not call one another. | Command | What it checks | The question it answers | | --- | --- | --- | | [`/gaia-fitness`](/commands/fitness/) | The Claude integration surface: hooks, frontmatter, rules, `.claude/settings.json` | Does the machine run? | -| [`/gaia-audit`](/commands/audit/) | The loaded context: memory, rules, and autoloaded files, for duplication, contradictions against the source of truth, stale entries, and over-budget autoloads | Is the fuel clean? | +| [`/gaia-audit`](/commands/audit/) | Memory, wiki, and auto-loaded files for duplication, conflicting instructions, and stale content | Is the fuel clean? | | [`/gaia-wiki`](/commands/wiki/) | The wiki itself: redundant or conflicting pages, and broken wikilinks | Is the knowledge base internally consistent? | +| [`/gaia-harden`](/commands/harden/) | Recurring code-review-audit findings, for patterns worth codifying as a rule, skill, or deterministic check | Should this pattern become a rule? | ## Which one to run @@ -26,6 +28,7 @@ Pick by symptom: - The integration feels off, a hook is not firing, a rule is not loading, a command misbehaves: run [`/gaia-fitness`](/commands/fitness/). - The base context feels heavy, or machine-local memory has grown large: run [`/gaia-audit`](/commands/audit/). - The wiki has grown and pages overlap, or wikilinks break: run [`/gaia-wiki`](/commands/wiki/). +- Recurring findings from code-review-audit keep surfacing for the same class of issue: run [`/gaia-harden`](/commands/harden/). The boundary between `/gaia-audit` and `/gaia-wiki` is deliberate. `/gaia-audit` reconciles the loaded context against the wiki (the source of truth) and resolves disagreements between project files; it does not touch wiki-page-vs-wiki-page conflicts. Those belong to `/gaia-wiki consolidate`. From f06f592353725397863dce2153b20838f003b09e Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 16:00:40 +0900 Subject: [PATCH 16/25] docs: accuracy pass on skills pages overview: split the catalog into four categories (workflow, code, scaffolders, maintenance) and add the missing workflow + maintenance skills. code: add the a11y-fixes full axe-rule set and the react-code React 19 gate; add a gaia-react-perf catalog entry that cross-links to the new page. scaffolders: fix the route output path (group values already include +), add the --json flag to the component and hook invocations. new page: skills/react-performance documents the gaia-react-perf measure-only diagnostic (capture, gaia react-perf reduce, diagnose, verify), registered in the Skills sidebar. react-doctor is correctly described as a third-party scanner, not a GAIA skill; no contributor paths leaked. Co-Authored-By: Claude Opus 4.8 (1M context) --- astro.config.mjs | 1 + src/content/docs/skills/code.mdx | 20 +- src/content/docs/skills/index.mdx | 6 +- src/content/docs/skills/react-performance.mdx | 206 ++++++++++++++++++ src/content/docs/skills/scaffolders.mdx | 6 +- 5 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 src/content/docs/skills/react-performance.mdx diff --git a/astro.config.mjs b/astro.config.mjs index 9e15f08..0e6e577 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -67,6 +67,7 @@ export default defineConfig({ { label: 'Overview', slug: 'skills' }, { label: 'Code skills', slug: 'skills/code' }, { label: 'Scaffolders', slug: 'skills/scaffolders' }, + { label: 'React performance', slug: 'skills/react-performance' }, ], }, { diff --git a/src/content/docs/skills/code.mdx b/src/content/docs/skills/code.mdx index 4c8f87b..d8022e8 100644 --- a/src/content/docs/skills/code.mdx +++ b/src/content/docs/skills/code.mdx @@ -5,7 +5,7 @@ sidebar: order: 1 --- -Eight skills that govern code generation and review. Each one loads automatically when its trigger phrasing matches the conversation. You don't invoke them by name. +Nine skills that govern code generation and review. Each one loads automatically when its trigger phrasing matches the conversation. You don't invoke them by name. ## TypeScript @@ -19,16 +19,26 @@ Source: `.claude/skills/typescript/SKILL.md`. ### React Code -Conventions for React components, pages, routes, hooks, and forms. Includes pre-flight gates for `useEffect`, `useCallback`, and `useState`; a form-element check that swaps native `` for the project's `Form/*` components; and a translation gate that requires every user-visible string to come from `t()` (exception: approximate skeleton-loader placeholders standing in for dynamic runtime values stay hardcoded; static skeleton text that mirrors a real `t()` call must still use `t()`). Covers component extraction thresholds and route/page architecture (`app/routes/` thin shells, `app/pages/` for UI). +Conventions for React components, pages, routes, hooks, and forms. Includes pre-flight gates for `useEffect`, `useCallback`, and `useState`; a form-element check that swaps native `` for the project's `Form/*` components; a translation gate that requires every user-visible string to come from `t()` (exception: approximate skeleton-loader placeholders standing in for dynamic runtime values stay hardcoded; static skeleton text that mirrors a real `t()` call must still use `t()`); and a React 19 idiom check that enforces `ref` as an ordinary prop (no `forwardRef`), `use()` over `useContext`, `` shorthand over ``, guarding the `&&` numeric-0 leak in JSX, and staying in React Router's form handling instead of reaching for `useActionState`, `useFormStatus`, or `useOptimistic`. Covers component extraction thresholds and route/page architecture (`app/routes/` thin shells, `app/pages/` for UI). Before adding a dependency or hand-rolling a primitive, the skill walks a platform-first ladder: existing GAIA code, then browser-native APIs (`Intl`, `URL`, `crypto.randomUUID()`, `structuredClone()`, modern CSS), then an already-installed dependency, then a new dependency, then custom code as a last resort. It stops at the first rung that fits. The biggest practical savings come from `Intl` standing in for date and number formatting libraries and native collection methods standing in for utility libraries, both already enforced by lint. -**Triggers** when writing or reviewing React components, hooks (`useEffect`, `useCallback`, `useState`), event handlers, or component extraction decisions. Also triggers when debugging stale closures, infinite re-renders, or unnecessary re-renders caused by memoization issues, or when deciding whether to add a dependency or reach for a web-platform API instead. +**Triggers** when writing or reviewing React components, hooks (`useEffect`, `useCallback`, `useState`), event handlers, or component extraction decisions. Also triggers when debugging stale closures, infinite re-renders, or unnecessary re-renders caused by memoization issues; when deciding whether to add a dependency, reach for a web-platform API, or hand-roll a primitive; or when choosing a React 19 idiom: `ref` as a prop vs `forwardRef`, `use()` vs `useContext`, `` shorthand vs ``, guarding `&&` conditional rendering against the numeric-0 leak, or routing form handling to React Router instead of `useActionState` / `useFormStatus` / `useOptimistic`. **Example phrasing:** "this useEffect is firing twice", "extract this section into its own component", "wire up a Conform form for sign-up". Source: `.claude/skills/react-code/SKILL.md`. +## React Performance + +A measure-only diagnostic that drives a micro-interaction, captures real React renders, and surfaces memo-defeating reference instability with a recommended structural fix. It diagnoses, it does not auto-fix. See [React performance](/skills/react-performance/) for the full capture-reduce-diagnose-verify workflow. + +**Triggers** on explicit render-performance asks: "profile renders", "measure renders", "why is X re-rendering", or "diagnose render performance". Does NOT trigger on vague "feels slow" or "janky". Requires a concrete micro-interaction target (a button click or local state change on a specific page), not a page navigation or "the whole app". + +**Example phrasing:** "profile renders on the dashboard table", "why does the theme toggle re-render the header", "measure renders on the checkout form". + +Source: `.claude/skills/gaia-react-perf/SKILL.md`. + ## Styling ### `tailwind` @@ -99,9 +109,9 @@ Source: `.claude/skills/eslint-fixes/SKILL.md`. ## Accessibility Fixes -Resolve specific axe-core accessibility violations in your project. Covers the common rule failures: `color-contrast`, `label`, `image-alt`, `button-name`, `link-name`, `region`, `landmark-one-main`, `heading-order`, and the `aria-*` family. The fix patterns reach for the project's semantic Tailwind tokens and `Form/*` components, so corrections hold in both light and dark mode. General accessibility guidance lives in the `accessibility` rule; this skill handles the concrete fix once a violation is reported. +Resolve specific axe-core accessibility violations in your project. Covers common rule failures: `color-contrast`, `label`, `label-title-only`, `image-alt`, `button-name`, `link-name`, `region`, `landmark-one-main`, `heading-order`, `aria-allowed-attr`, `aria-required-attr`, `aria-required-children`, `aria-required-parent`, `aria-valid-attr-value`, `focus-trap`, `tabindex`, `html-has-lang`, `document-title`, `duplicate-id`, `listitem`, and `definition-list`. For any violation not in that list, apply the same fix-then-verify loop. The fix patterns reach for the project's semantic Tailwind tokens and `Form/*` components, so corrections hold in both light and dark mode. General accessibility guidance lives in the `accessibility` rule; this skill handles the concrete fix once a violation is reported. -**Triggers** when an axe rule id appears in test output from `test/a11y.ts` (Vitest), `.playwright/a11y.ts` (Playwright), or the `code-review-audit` agent's accessibility bucket. +**Triggers** when any axe rule id appears in test output from `test/a11y.ts` (Vitest), `.playwright/a11y.ts` (Playwright), or the `code-review-audit` agent's accessibility bucket. **Example phrasing:** "fix the color-contrast violation on the status badge", "axe says this button has no accessible name", "resolve the heading-order error". diff --git a/src/content/docs/skills/index.mdx b/src/content/docs/skills/index.mdx index 43441f3..b0a9544 100644 --- a/src/content/docs/skills/index.mdx +++ b/src/content/docs/skills/index.mdx @@ -9,12 +9,16 @@ GAIA ships its skills under `.claude/skills/` in your project. Each one is a dir ## Catalog -GAIA groups its skills into two categories: +GAIA groups its skills into four categories: + +**Workflow skills** handle session context and wiki maintenance. Trigger on `/gaia-handoff`, `/gaia-pickup`, `/gaia-wiki`, or natural-language asks like "hand off this session" or "sync the wiki". See [Handoff and pickup](/commands/handoff-pickup/) and [/gaia-wiki](/commands/wiki/). **Code skills** govern how code is written and reviewed. Trigger when you write or edit TypeScript, React, Tailwind, tests, or browser automation. See [Code skills](/skills/code/). **Scaffolders** generate new files from templates. Trigger when you ask to create a component, hook, route, or service. See [Scaffolders](/skills/scaffolders/). +**Maintenance skills** update project dependencies and pull new GAIA releases. See [/update-deps](/commands/update-deps/) and [/update-gaia](/commands/update-gaia/). + ## How triggering works Each `SKILL.md` has a `description:` field that lists the phrasings and situations that load the skill. The skills do not run on every prompt; they activate when the description matches what you said. You don't invoke them by name. Saying "scaffold a card called PriceCard" loads `new-component`. Saying "the typecheck is angry about a stale closure" loads `react-code`. diff --git a/src/content/docs/skills/react-performance.mdx b/src/content/docs/skills/react-performance.mdx new file mode 100644 index 0000000..c962ad8 --- /dev/null +++ b/src/content/docs/skills/react-performance.mdx @@ -0,0 +1,206 @@ +--- +title: React performance +description: A measure-only diagnostic that captures real React renders and surfaces the memo-defeating reference instability behind an over-render. +sidebar: + order: 3 +--- + +`react-performance` is a measure-only render-performance diagnostic. It drives one +concrete micro-interaction, captures the renders React actually performs, reduces +that capture to a small ranked summary, and reports the memo-defeating reference +instability behind an over-render along with a structural-first fix. + +It measures. It does not auto-fix. The diagnosis names the component, the unstable +input, and the recommended fix; you (or Claude, in normal conversation) apply it. + +## How to invoke + +The skill is gated to explicit render-performance intent. It loads on the +`/gaia-react-perf` handle or on a natural-language ask that names rendering. + +**Triggers** on phrasing like "profile renders", "measure renders", "why is X +re-rendering", or "diagnose render performance". It does **not** trigger on vague +"feels slow", "janky", or "optimize my app". + +**Example phrasing:** "profile renders on the dashboard table", "why does the +theme toggle re-render the header", "measure renders on the checkout form". + +It also requires a concrete micro-interaction target: a button click or a local +state change on a specific page. It refuses a page navigation or "the whole app", +because a navigation re-renders the entire tree and buries the signal in framework +noise. A local interaction re-renders only its own subtree, so the same memo +defeat reads as a single clean culprit instead of one row among hundreds. If you +don't name a target, the skill asks for one before proceeding. + +## The workflow + +The diagnostic separates a token-heavy raw capture from the small summary the +model reasons over. The raw dump (roughly 172 KB, about 43K tokens for a trivial +flow) never enters the conversation. Only the reduced summary is read. + +### 1. Capture + +The skill writes a short, temporary Playwright spec that drives your target +interaction using the committed capture helper at `.playwright/react-perf/capture.ts`. +The helper injects a render-instrumentation harness before React initializes, +collects each rendered fiber, and writes the raw dump to +`.gaia/local/cache//renders.json`. + +```ts +import {expect, test} from '@playwright/test'; +import {collectRenderDump, installRenderCapture} from '../react-perf/capture'; +import {hydration} from '../utils'; + +test('drive the target micro-interaction and capture renders', async ({page}) => { + // isStrictModeDisabled gives honest, non-doubled timings (see the caveat below). + await installRenderCapture(page, {isStrictModeDisabled: true}); + + await page.goto('/'); // the target route + await hydration(page); // wait for hydration before interacting + + // Drive the micro-interaction (a button click or local state change). + const toggle = page.locator('header').getByRole('button'); + await expect(toggle).toBeVisible(); + await toggle.click(); + + // keep: true is required, or the run dir auto-deletes on process exit before + // the reduce step can read it. + const result = await collectRenderDump(page, {keep: true}); + console.log(`RAW_DUMP_PATH=${result.rawPath}`); +}); +``` + +Run it. The Playwright config auto-starts the dev server, and the capture requires +a development build (a production build is rejected, because render timings are +zero in production). + +```sh +pnpm pw react-perf-drive +``` + +The spec logs `RAW_DUMP_PATH=...`; that absolute path is the input to the reduce +step. The temporary spec is removed once the diagnosis is done. + +### 2. Reduce + +The skill then runs the bundled CLI over the raw dump to produce a small ranked +summary: `gaia react-perf reduce `. The `gaia` binary resolves +through the project's package bin, so the skill runs it for you; you don't type it +into a separate terminal. + +The reduce filters framework noise, recomputes the signal, ranks findings, applies +a frame-budget timing gate, and prints a `ReducedSummary` as JSON on stdout. The +frame budget defaults to 16ms; pass `--frame-budget-ms ` to change the timing +gate. Malformed input prints a structured error and exits non-zero. That summary +is the only thing the skill ingests. + +### 3. Diagnose + +The signal is `memoDefeated`, not "this re-rendered". A render is memo-defeated +when a `memo`-wrapped component re-renders on an update and every changed input is +a referentially-new object or function (a fresh reference where `Object.is` fails +across commits). Plain "nothing meaningfully changed" renders are not surfaced, +because chasing them leads to memoize-everything over-optimization. Timing is a +gate, not a trigger: findings rank by blast radius times cost +(`memoDefeatedCount` times `maxTotalTime`), and a component is only flagged on +timing alone when its subtree crosses the frame budget. + +The top finding (`rank: 1`) reads as: a component re-rendered `renderCount` times +on the interaction, of which `memoDefeatedCount` were memo-defeated; +`unstableInputs` names what defeated the memo; and `maxTotalTime` plus +`exceedsFrameBudget` say whether the defeated subtree is actually expensive. + +### 4. Hand off the fix + +The fix is structural-first. Prefer hoisting a stable value to a module-level +constant before reaching for a hook, and only use a hook when the value genuinely +depends on render state. `unstableInputs` tells you which case you have. + +| Unstable input | Structural-first fix | Hook fallback | +|---|---|---| +| An inline object or array prop (`prop:`) | Hoist the literal to a module-level `const` | `useMemo` only when the value depends on render state | +| A callback prop (`prop:`) | Hoist the handler to module scope when it closes over nothing | `useCallback` with the right deps when it closes over render state | +| A freshly-constructed context value (`context`) | Move a static value to a module const, or split the context so unrelated consumers don't churn | `useMemo` the provider value when it depends on state | +| A child component defined inside another component's body | Lift the component to module scope | Not a hook fix | + +For that last row, `reactDoctorRule` is always `null`. The reduce works from flat +render records and cannot tell that a component was defined inside another, so it +never emits the nested-component label. Identify this case from the component name +and the unstable input, and lift the component to module scope. + +### 5. Verify + +After the fix, re-run the same drive spec and reduce. Confirm the targeted +finding's `memoDefeatedCount` drops to 0. A truly fixed memo skips its render +entirely, so the capture records no fiber for it and the component drops out of +`findings` altogether. That absence is the cleanest proof. + +## Reading the summary + +Each entry in `findings[]` carries these fields. Read them by name. + +| Field | What it tells you | +|---|---| +| `componentName`, `isMemo` | The app-owned component, and whether it is `memo`-wrapped | +| `renderCount` | Update renders on the interaction | +| `memoDefeatedCount` | How many of those were memo-defeated (the core signal) | +| `unstableInputs` | What defeated the memo: `prop:`, `state[]`, or `context` | +| `totalSelfTime`, `maxTotalTime` | Accumulated and peak subtree render time | +| `exceedsFrameBudget` | Whether the peak subtree time crosses the frame budget | +| `reactDoctorRule` | A conceptual static-cause label (see below) | +| `rank` | Position in the ranked list (1 is the top finding) | + +The summary also reports `totals` (records, updates, mounts, framework-filtered +renders, app components, and the overall memo-defeated count), `unknownNameCount` +(renders whose component name could not be resolved, a finding in itself), +`strictModeTimingCaveat`, `profilingAvailable`, and `rendererVersion`. + +The `reactDoctorRule` field is a conceptual static-cause label that names the +structural cause and points at the matching fix. The reduce emits +`jsx-no-new-object-as-prop` when an unstable prop dominates, +`jsx-no-constructed-context-values` when an unstable context dominates, or `null` +for state-only instability. These are guidance labels for reading the diagnosis, +not enforced ESLint rule ids, and the diagnostic never matches them against lint +output. + +## When to stop + +Stop when both stop-signal fields are true: + +> Stop when `stopSignal.zeroAppMemoDefeated` is true **and** +> `stopSignal.noAppFrameBudgetBreach` is true. + +The memo-defeat count catches cheap-but-wrong cases (a memo silently defeated); +the frame-budget gate catches the rarer expensive-subtree case that count alone +under-weights. Both, not either. + +Residual findings are called out as out of scope rather than chased: a +framework-level row (a router or library internal that the name heuristic did not +catch) is not app-fixable, and a sub-perceptible app finding well under the frame +budget is not worth fixing. + +## When to use it, and when not + +Use it to find the reference instability behind a specific over-render: a memo +that should skip but does not, on a concrete interaction. + +Be honest about cost. Render-count wins are often sub-perceptible. A cheap leaf +memo-defeat costs on the order of 0.038ms, roughly three orders of magnitude under +the 16ms frame budget. The diagnostic is primarily a memo-defeat and +reference-hygiene finder. It is most valuable when the defeated child is an +expensive subtree (`exceedsFrameBudget: true`). Don't let a finding that costs +nothing perceptible tempt a memoize-everything pass. + +Two more limits worth knowing: + +- **Timings need an honest baseline.** Components render twice under React's + StrictMode, which roughly doubles measured timings. The capture above runs with + StrictMode off for honest numbers. If a run leaves StrictMode on, the summary + sets `strictModeTimingCaveat: true`; treat those timings as relative, not + absolute. +- **The app/framework split is a name heuristic.** The reduce decides "framework + noise versus app code" by component name, not by where the component is defined. + An unusual component name can slip the filter, which is one more reason a human + stays in the loop on the fix. + +Source: `.claude/skills/gaia-react-perf/SKILL.md`. diff --git a/src/content/docs/skills/scaffolders.mdx b/src/content/docs/skills/scaffolders.mdx index 85a00a6..7aa46f2 100644 --- a/src/content/docs/skills/scaffolders.mdx +++ b/src/content/docs/skills/scaffolders.mdx @@ -19,7 +19,7 @@ Scaffolds a React component as a folder under `app/components/` (or a sub-folder **Example phrasing:** "create a PriceCard component", "scaffold a button under app/components/Form", "make a new component called UserAvatar with a name and url prop". -Underlying CLI: `gaia scaffold component [--no-story] [--parent ] [--props "a:string,b:number"]`. +Underlying CLI: `gaia scaffold component [--no-story] [--parent ] [--props "a:string,b:number"] [--json]`. `--props` takes comma-separated `name:type` pairs. Comma-bearing types like `Record`, tuples, and multi-argument function types work inside a single entry, for example `--props "label:string,data:Record"`. @@ -35,13 +35,13 @@ Scaffolds a custom React hook with a Vitest test file. **Example phrasing:** "make a useCountdown hook", "scaffold useDebouncedValue with a value and delay parameter", "extract this into a useFormSubmission hook". -Underlying CLI: `gaia scaffold hook [--params "a:string,b:number"] [--returns "ReturnType"]`. +Underlying CLI: `gaia scaffold hook [--params "a:string,b:number"] [--returns "ReturnType"] [--json]`. Source: `.claude/skills/new-hook/SKILL.md`. ## New Route -Scaffolds a new route with its page component, test, story, and optional i18n keys. Files land in `app/routes/+/.tsx` plus `app/pages//Page/index.tsx` (for example `UserProfilePage`). The route file stays a thin shell (`loader`, `action`, `meta`, Zod schemas, one-line default export); UI lives in the page component. +Scaffolds a new route with its page component, test, story, and optional i18n keys. Files land in `app/routes//.tsx` plus `app/pages//Page/index.tsx` (for example `UserProfilePage`). The route file stays a thin shell (`loader`, `action`, `meta`, Zod schemas, one-line default export); UI lives in the page component. **Confirms:** name (kebab-case), group (`_public+` or `_session+`), and which of `--loader`, `--action`, `--i18n` to include. From 9f6816cb2a20b1d6835e99ec988ec62ad17dfd2e Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 16:16:33 +0900 Subject: [PATCH 17/25] docs: accuracy pass on reference pages hooks: add post-audit-status; fix block-rm-rf (relative paths fall through), pr-merge-audit-check (multi-signal + /update-gaia self-mod exemption), block-main-destructive-git (plain push from main), block-no-verify (HUSKY=, hooksPath), audit-stamp-trailer (self-heal amend), check-story-exists (fires on edit too); mute the mentorship clause in wiki-session-start. telemetry hook stays undocumented. rules: add react-router-docs and dep-audit; fix coding-guidelines, knip, wiki-style entries; restore exact path globs on the path-scoped rules; correct the thin-routes description. pr-merge and wiki-style maintainer-only blocks stay omitted. agents: fix the Suggestions tier label (Must Fix or Escalate) and the audit marker conditions; worthiness-evaluator verified. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/reference/agents.mdx | 4 ++-- src/content/docs/reference/hooks.mdx | 15 ++++++++------- src/content/docs/reference/rules.mdx | 23 ++++++++++++----------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/content/docs/reference/agents.mdx b/src/content/docs/reference/agents.mdx index 3c19605..8f16740 100644 --- a/src/content/docs/reference/agents.mdx +++ b/src/content/docs/reference/agents.mdx @@ -43,12 +43,12 @@ The agent produces a structured report: - **Summary**: overview, overall quality, top findings. - **Critical Issues (Must Fix)**: security and bugs that block merge. Each finding gives `path:line`, the issue, and a concrete fix. - **Important Issues (Should Fix)**: performance and architectural concerns at scale. Same shape. -- **Suggestions (Consider Fixing)**: refactoring and minor improvements. +- **Suggestions (Must Fix or Escalate)**: refactoring and minor improvements. Every suggestion must be resolved before the audit passes. Auto-fix it in the working tree or explicitly escalate with documented rationale. Escalated suggestions block the marker. - **What's Done Well**: included only when there are concrete patterns worth reinforcing. ### Audit marker and trailer -When the report is clean (no Critical Issues, all Important Issues resolved in the working tree), the agent stamps HEAD with a `GAIA-Audit:` commit trailer and writes a marker file at `.gaia/local/audit/.ok`. The marker unblocks `gh pr merge` locally; the trailer travels with the commit through the network so CI can recognize an already-audited tree and skip its own audit run. +When the report is clean (no Critical Issues, all Important Issues resolved in the working tree, and the Suggestions section empty or every suggestion auto-fixed), the agent stamps HEAD with a `GAIA-Audit:` commit trailer and writes a marker file at `.gaia/local/audit/.ok`. The marker unblocks `gh pr merge` locally; the trailer travels with the commit through the network so CI can recognize an already-audited tree and skip its own audit run. If findings remain, the agent does not write the marker. Address findings, commit, and re-invoke the agent on the new HEAD. diff --git a/src/content/docs/reference/hooks.mdx b/src/content/docs/reference/hooks.mdx index 2d72c7c..e0a9fec 100644 --- a/src/content/docs/reference/hooks.mdx +++ b/src/content/docs/reference/hooks.mdx @@ -15,7 +15,7 @@ For Claude Code's own hook documentation, see [the Hooks reference on docs.claud | Hook | What it does | Path | |---|---|---| -| `wiki-session-start` | Records HEAD into `.git/claude-session-start` so the Stop hook can detect wiki commits during the session, and re-asserts per-machine memory contracts. | `.claude/hooks/wiki-session-start.sh` | +| `wiki-session-start` | Records HEAD into `.git/claude-session-start` so the Stop hook can detect wiki commits made during the session. | `.claude/hooks/wiki-session-start.sh` | ## Stop @@ -59,17 +59,17 @@ For Claude Code's own hook documentation, see [the Hooks reference on docs.claud | `block-secrets-write` | Denies writes that contain AWS keys, GitHub PATs, private-key headers, or non-placeholder `_TOKEN`/`_SECRET`/`_KEY`/`_PASSWORD` assignments. | `.claude/hooks/block-secrets-write.sh` | | `block-vitest-globals-tsconfig` | Blocks adding `vitest/globals` to `tsconfig.json`; tests must use explicit imports from `vitest`. | `.claude/hooks/block-vitest-globals-tsconfig.sh` | | `check-i18n-strings` | Advisory once-per-session reminder when a `.tsx` file under `app/pages/` or `app/components/` is edited; does not block. | `.claude/hooks/check-i18n-strings.sh` | -| `check-story-exists` | Advisory reminder to add a Storybook story when a new component `index.tsx` is written without a sibling `tests/index.stories.tsx`. | `.claude/hooks/check-story-exists.sh` | +| `check-story-exists` | Advisory reminder to add a Storybook story when a component `index.tsx` is written or edited without a sibling `tests/index.stories.tsx`. | `.claude/hooks/check-story-exists.sh` | ## PreToolUse (Bash) | Hook | What it does | Path | |---|---|---| | `block-bare-test` | Blocks bare `pnpm test` / `npm test` invocations; requires `--run` so vitest does not start watch mode. The block is anchored to command position: a `pnpm test` or `npm test` mention inside a commit message, `--body` string, or other quoted text is not an invocation and does not trigger the block. | `.claude/hooks/block-bare-test.sh` | -| `block-main-destructive-git` | Blocks commits to `main`/`master` and force-pushes to those branches. | `.claude/hooks/block-main-destructive-git.sh` | -| `block-no-verify` | Denies `git commit` / `git push` that carry a hook bypass (`--no-verify`, or commit-only `-n`), so the commit-time floor (typecheck, lint, test) cannot be skipped. | `.claude/hooks/block-no-verify.sh` | -| `block-rm-rf` | Denies `rm -rf` against root, `$HOME`, cwd, unscoped globs, `.git`, `node_modules`, and any path outside a small whitelist of scratch dirs. | `.claude/hooks/block-rm-rf.sh` | -| `pr-merge-audit-check` | Blocks `gh pr merge` until a code-review-audit marker file exists at `.gaia/local/audit/.ok`. | `.claude/hooks/pr-merge-audit-check.sh` | +| `block-main-destructive-git` | Blocks commits to `main`/`master`, force-pushes to those branches, and any plain `git push` originating from `main`/`master` (the flow is PR-only). | `.claude/hooks/block-main-destructive-git.sh` | +| `block-no-verify` | Denies `git commit` / `git push` that carry a hook bypass, so the commit-time floor (typecheck, lint, test) run by the Husky pre-commit hook cannot be skipped. Bypasses caught: `--no-verify`, commit-only `-n`, a falsy `HUSKY=` prefix, and `-c core.hooksPath=`. | `.claude/hooks/block-no-verify.sh` | +| `block-rm-rf` | Denies `rm -rf` of root, any absolute path, `$HOME`, cwd (`.`), an unscoped glob (`*`), `.git`, or `node_modules`, plus any command using `--no-preserve-root`. Other relative paths fall through; broader scoping lives in `settings.json` permissions. | `.claude/hooks/block-rm-rf.sh` | +| `pr-merge-audit-check` | Blocks `gh pr merge` until the current HEAD carries proof of a passing `code-review-audit`. Accepted signals: a local audit marker at `.gaia/local/audit/.ok`, a `GAIA-Audit` commit trailer whose tree-sha matches HEAD, or a `GAIA-Audit` GitHub commit status of `success`. PRs that change only out-of-scope surfaces (wiki, docs, `.gaia` metadata), `chore(deps)` PRs, and `/update-gaia` PRs whose only in-scope change is a verbatim refresh of the bundled `code-review-audit` workflow are exempt. | `.claude/hooks/pr-merge-audit-check.sh` | | `red-verify-commit-check` | Blocks `git commit` when a new-at-HEAD test that now passes has no recorded failing (RED) run matching its current content. Enforces mechanical TDD: a new test must be observed failing before its passing version can land. Three kinds of test are exempt: type-only tests (all assertions are type-level via `expectTypeOf`/`assertType`/`@ts-expect-error`, no runtime `expect`), which `tsc` enforces instead; tests with dynamic or computed titles, which have no stable identity to key a RED to; and emergent-subject tests (component interaction, Playwright, or clock/IO-dependent), which have no stable failing-then-passing run to observe. The deterministic surface (pure utilities, service parsers, spec-derivable hooks) still demands a RED. | `.claude/hooks/red-verify-commit-check.sh` | | `worthiness-presence-check` | Blocks `gh pr merge` when an emergent test the PR changed has no worthiness-ledger line matching its current content, so the worthiness audit has run over every changed emergent test before merge. It checks presence only, never the keep/fix/delete verdict, and is a no-op when no emergent tests changed. Sits alongside `pr-merge-audit-check`. | `.claude/hooks/worthiness-presence-check.sh` | @@ -84,4 +84,5 @@ For Claude Code's own hook documentation, see [the Hooks reference on docs.claud | Hook | What it does | Path | |---|---|---| -| `audit-stamp-trailer` | Writes the `GAIA-Audit:` commit trailer on HEAD so CI can recognize an already-audited tree. Called by the `code-review-audit` agent at the end of a clean review. | `.claude/hooks/audit-stamp-trailer.sh` | +| `audit-stamp-trailer` | Writes the `GAIA-Audit:` commit trailer on HEAD so CI can recognize an already-audited tree. Amends an un-pushed HEAD, adds an empty commit when HEAD is already published, or amends the audit's own fix-commit when the audit self-healed during the run. Called by the `code-review-audit` agent at the end of a clean review. | `.claude/hooks/audit-stamp-trailer.sh` | +| `post-audit-status` | Posts a `GAIA-Audit` commit status of `state=success` on HEAD after the audit marker is written, so a Claude-driven merge clears the same server-side check the CI path satisfies. Best-effort: skips silently when `gh` is absent or unauthenticated. Called by the `code-review-audit` agent. | `.claude/hooks/post-audit-status.sh` | diff --git a/src/content/docs/reference/rules.mdx b/src/content/docs/reference/rules.mdx index a829a40..9bf1242 100644 --- a/src/content/docs/reference/rules.mdx +++ b/src/content/docs/reference/rules.mdx @@ -13,9 +13,9 @@ A rule's frontmatter `paths:` field is the gate. When Claude edits or reads a fi | Rule | What it enforces | |---|---| -| `coding-guidelines` | File-naming conventions (PascalCase components, camelCase hooks, kebab-case other), simplicity-first (no speculative abstractions or impossible-scenario error handling; real failure modes such as non-zero exits, loop non-convergence, and network failures still get handled and bounded), surgical changes, goal-driven execution, mandatory TDD, mandatory quality-gate run before commit. | -| `dep-audit` | Dependency-CVE advisory. The audit agent runs `pnpm audit --json` pre-merge and reports high and critical findings for the operator to decide on. Read-only: never blocks the audit marker or `gh pr merge`. Distinct from the blocking CI `pnpm audit` pass. | -| `knip` | When and when not to run `pnpm knip`; the audit agent runs it pre-merge, manual runs only after a refactor, deletion, or dependency replacement. | +| `coding-guidelines` | File-naming conventions (PascalCase components, camelCase hooks, kebab-case other), think-before-coding (surface assumptions, push back when a simpler approach exists), simplicity-first (no speculative abstractions or impossible-scenario error handling; real failure modes such as non-zero exits, loop non-convergence, and network failures still get handled and bounded), surgical changes, goal-driven execution, mandatory TDD, mandatory quality-gate run before commit. | +| `dep-audit` | Dependency-CVE advisory. The audit agent runs `pnpm audit --json` pre-merge and reports high and critical findings for the operator to decide on. Read-only, so it never blocks the audit marker or `gh pr merge`. Distinct from the blocking CI `pnpm audit` pass. | +| `knip` | When and when not to run `pnpm knip`; the audit agent runs it pre-merge, manual runs only after a refactor, deletion, or dependency replacement, never mid-task or inside the Quality Gate. | | `pr-merge` | Before any `gh pr merge`, run the audit and marker handshake, then confirm the PR reports `MERGED` before any local branch cleanup; use `--auto` (not `--admin`) when branch protection blocks the merge. | | `quality-gate` | Run the steps in `wiki/decisions/Quality Gate.md` before any commit that touches source, unless nothing in the gate's scope is staged. | | `shell-cwd` | No `cd` in Bash tool calls; use absolute paths. A persistent `cd` breaks the relative-path hooks registered in `settings.json`. | @@ -24,14 +24,15 @@ A rule's frontmatter `paths:` field is the gate. When Claude edits or reads a fi | Rule | What it enforces | Paths | |---|---|---| -| `accessibility` | Keyboard reachability, alt text, focus management on modals, semantic HTML over ARIA roles, color never the sole indicator. | `app/components/**`, `app/pages/**` | -| `api-service` | Pointer to the API Service Pattern wiki page and the `new-service` skill; no inline rules. | `app/services/**`, `test/mocks/**` | +| `accessibility` | Keyboard reachability, alt text, focus management on modals, semantic HTML over ARIA roles, color never the sole indicator. | `app/components/**/*`, `app/pages/**/*` | +| `api-service` | Pointer to the API Service Pattern wiki page and the `new-service` skill; no inline rules. | `app/services/**/*`, `test/mocks/**/*` | | `code-search` | Prefer Serena's MCP tools for symbol-level queries on TS/TSX; fall back to Read+grep for prose, comments, and files outside `app/**`/`test/**`. | `app/**/*.ts`, `app/**/*.tsx`, `test/**/*.ts`, `test/**/*.tsx` | -| `i18n` | Every user-facing string comes from `t()`; one `useTranslation()` per component; namespace conventions and key file layout under `app/languages/en/`. | `app/pages/**`, `app/components/**`, `app/languages/**` | +| `i18n` | Every user-facing string comes from `t()`; one `useTranslation()` per component; namespace conventions and key file layout under `app/languages/en/`. | `app/pages/**/*`, `app/components/**/*`, `app/languages/**/*` | | `instruction-files` | All paths in template-distributed files under `.claude/` must be repo-relative; provides an audit grep for absolute-path leaks. | `.claude/**` | -| `playwright` | E2E spec layout, semantic selectors over CSS, web-first assertions only, hydration helper before interaction, MSW behavior in dev, parallelism and CI settings. | `.playwright/**`, `playwright.config.*` | -| `routes` | Pointer to thin-route conventions in the wiki and the `new-route` skill; route files stay loader/action-only. | `app/routes/**`, `app/pages/**` | -| `state-pattern` | Context creation lives in `app/state/`; naming conventions for Provider/`useX`/`useMaybeX`; never export the Context; provider composition via `app/state/index.tsx`. | `app/state/**` | -| `storybook` | Story file location and typing, slash-separated titles, decorator order, fullscreen layout with `wrap: 'p-4'` for padding, variant-name table, Chromatic dark-mode handling. | `app/**/*.stories.tsx`, `.storybook/**` | +| `playwright` | E2E spec layout, semantic selectors over CSS, web-first assertions only, hydration helper before interaction, MSW behavior in dev, parallelism and CI settings. | `.playwright/**/*`, `playwright.config.*` | +| `react-router-docs` | For React Router framework-mode work (routes, loaders, actions, middleware, navigation, error boundaries), read the docs shipped in `node_modules/react-router/docs`, which match the pinned version, rather than the web; check the remix-utils decision map before hand-rolling csrf, honeypot, or safe-redirect primitives. Covers React Router's own API; route/page structure conventions live in `routes`. | `app/routes/**/*`, `app/pages/**/*`, `app/root.tsx`, `app/middleware/**/*`, `react-router.config.ts` | +| `routes` | Pointer to thin-route conventions in the wiki and the `new-route` skill; route files hold only loader, action, meta, and a one-line page render. | `app/routes/**/*`, `app/pages/**/*` | +| `state-pattern` | Context creation lives in `app/state/`; naming conventions for Provider/`useX`/`useMaybeX`; never export the Context; provider composition via `app/state/index.tsx`. | `app/state/**/*` | +| `storybook` | Story file location and typing, slash-separated titles, decorator order, fullscreen layout with `wrap: 'p-4'` for padding, variant-name table, Chromatic dark-mode handling. | `app/**/*.stories.tsx`, `.storybook/**/*` | | `tailwind` | Tailwind v4 only (config in `app/styles/tailwind.css`, no `tailwind.config.ts`); semantic `@utility` tokens over raw paired classes; no arbitrary hex colors in `[]`. | `app/**/*.tsx`, `app/**/*.css` | -| `wiki-style` | Present-tense prose; no UAT/SPEC/PR/commit references in body prose; no historical phrasing; ships an audit grep for violations. | `wiki/**/*.md`, `app/**/*.{ts,tsx,js,jsx,css}`, `.claude/{skills,commands,agents,rules}/**/*.md`, `.claude/hooks/**/*.sh`, `.specify/extensions/gaia/{README.md,commands,lib,rules,templates}/**` | +| `wiki-style` | Present-tense prose; no UAT/SPEC/PR/commit references in body prose; no historical phrasing; no unreleased or speculative roadmap stated as current behavior; ships an audit grep for violations. | `wiki/**/*.md`, `app/**/*.{ts,tsx,js,jsx,css}`, `.claude/{skills,commands,agents,rules}/**/*.md`, `.claude/hooks/**/*.sh`, `.specify/extensions/gaia/README.md`, `.specify/extensions/gaia/commands/**/*.md`, `.specify/extensions/gaia/lib/**/*.sh`, `.specify/extensions/gaia/rules/**/*.md`, `.specify/extensions/gaia/templates/**/*.md` | From 7f3fc71d522f6a84b3e621bfb449adb071f60cd1 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 16:30:28 +0900 Subject: [PATCH 18/25] docs: accuracy pass on contributors pages index: name the maintainer generically (not by first name), add audit-ci-tests.yml to the contributor CI list. ci: fix cli-tests path filter, audit-ci-tests two-suite scope, and the pnpm-audit schedule (daily, not weekly). cli: add the setup-ci, automation, react-perf, ci-revert, and ci-stale-check namespaces plus new init/update/wiki subcommands; fix the scaffold route (--group required) and component (--no-story/--parent/--json) signatures. release/mentorship/telemetry/_internal stay absent per do-not-document. health-audit: rewrite to the five-bucket Orchestrator/Adjudicator model with correct clean-exit gates, circuit breakers, honest grading, escalation enum, and the /gaia-fitness distinction; archive is one-time init, not per cycle. release: correct the manifest-class claim, add the /gaia-release behavioral flow and the two-binary split, add the wiki-baseline reset step; no gaia release subcommands named. wiki: add the wiki/.state.json model, the gaia wiki CLI primitive table (incl. chain), and the report-path patterns. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/contributors/ci.mdx | 8 +- src/content/docs/contributors/cli.mdx | 98 +++++++++++++++++-- .../docs/contributors/health-audit.mdx | 76 ++++++++++---- src/content/docs/contributors/index.mdx | 4 +- src/content/docs/contributors/release.mdx | 23 ++++- src/content/docs/contributors/wiki.mdx | 54 +++++++++- 6 files changed, 224 insertions(+), 39 deletions(-) diff --git a/src/content/docs/contributors/ci.mdx b/src/content/docs/contributors/ci.mdx index b332e4c..a80c84d 100644 --- a/src/content/docs/contributors/ci.mdx +++ b/src/content/docs/contributors/ci.mdx @@ -31,7 +31,7 @@ The pre-publish distribution gate uses the org `CLAUDE_CODE_OAUTH_TOKEN` secret. Triggers on both `push` to `main` and `pull_request` against `main`. The job is gated to `pull_request` events via a job-level `if:` condition; push events keep the required status check green on merge commits without rerunning anything. Runs the Vitest suite under `.gaia/cli/`. -PRs that don't touch `.gaia/cli/**` or this workflow file report green without installing or running anything. The path filter is `dorny/paths-filter`. +PRs that don't touch `.gaia/cli/**`, this workflow file, or `.github/workflows/code-review-audit.yml` report green without installing or running anything. That third path is in the filter because a CLI test compares the in-tree audit workflow against its bundled template, so editing the workflow has to re-run the suite. The path filter is `dorny/paths-filter`. When the filter triggers, the job: @@ -45,9 +45,9 @@ The required-check posture is intentional: contributors who don't touch the CLI ## audit-ci-tests.yml -Triggers on both `push` to `main` and `pull_request` against `main`, with the job gated to `pull_request` events via a job-level `if:` condition. Runs the bats suites for the `.github/audit/` helpers that `code-review-audit.yml` consumes: `check-trailer.sh` (the skip-logic gate) and `resolve-audit-base.sh` (the incremental-review base). +Triggers on both `push` to `main` and `pull_request` against `main`, with the job gated to `pull_request` events via a job-level `if:` condition. It runs two bats suites. `bats .github/audit/tests/` covers the audit helpers that `code-review-audit.yml` consumes, including `check-trailer.sh` (the skip-logic gate), `resolve-audit-base.sh` (the incremental-review base), and `pr-merge-audit-check.sh` (the merge-status reader). `bats .gaia/scripts/tests/` covers the shipped GAIA-owned scripts under `.gaia/scripts/`. -PRs that don't touch `.github/audit/**`, this workflow file, or `.claude/hooks/lib/repo-scope.sh` report green without installing or running anything. The path filter is `dorny/paths-filter`, mirroring `cli-tests.yml`. +PRs that don't touch `.github/audit/**`, `.gaia/scripts/**`, this workflow file, or the audit hooks at `.claude/hooks/lib/repo-scope.sh`, `.claude/hooks/pr-merge-audit-check.sh`, and `.claude/hooks/post-audit-status.sh` report green without installing or running anything. The path filter is `dorny/paths-filter`, mirroring `cli-tests.yml`. Adopters receive the audit scripts as GAIA-controlled code they never edit, so the suite guards only maintainer changes. @@ -81,7 +81,7 @@ The installable set: - `gaia-ci-wiki.yml`: daily `/gaia-wiki` sync, consolidate, and lint chain - `gaia-ci-update-deps.yml`: weekly dependency updates -- `gaia-ci-pnpm-audit.yml`: weekly `pnpm audit` security pass +- `gaia-ci-pnpm-audit.yml`: daily `pnpm audit` security pass - `gaia-ci-stale-branches.yml`: monthly cleanup of long-merged branches - `code-review-audit.yml`: the pre-merge audit gate, installed unconditionally (not a cron tool) diff --git a/src/content/docs/contributors/cli.mdx b/src/content/docs/contributors/cli.mdx index fba789d..38210ee 100644 --- a/src/content/docs/contributors/cli.mdx +++ b/src/content/docs/contributors/cli.mdx @@ -33,10 +33,14 @@ gaia init strip-branding --title gaia init configure-i18n --locales --strip gaia init rename --title --kebab gaia init wire-statusline --mode +gaia init bootstrap-env +gaia init configure-automation --wiki --update-deps --pnpm-audit --stale-branches gaia init finalize gaia init resume [--from-step ] ``` +`bootstrap-env` copies `.env.example` to `.env` when `.env` is absent. `configure-automation` writes `.gaia/automation.json` with the four tool-mode selections and `setup_complete: false` (Phase A of GAIA CI). Each `` is one of `ci`, `local`, or `off`, and all four flags are required (no CLI-layer defaults). + ### `gaia scaffold` Source: `.gaia/cli/src/scaffold/index.ts` @@ -44,13 +48,13 @@ Source: `.gaia/cli/src/scaffold/index.ts` Code generators invoked by the `new-component`, `new-hook`, `new-route`, and `new-service` skills. Each generator reads templates from `.gaia/cli/src/scaffold/templates/`. ``` -gaia scaffold component [--props "a:string,..."] +gaia scaffold component [--props "a:string,..."] [--no-story] [--parent ] [--json] gaia scaffold hook -gaia scaffold route [--dry-run] +gaia scaffold route --group <_public+|_session+> [--loader] [--action] [--i18n] [--dry-run] [--json] gaia scaffold service ``` -`scaffold route --dry-run` previews the files it would write without touching disk. `scaffold component --props` splits on depth-0 commas, so comma-bearing types (`Record`, tuples, multi-argument function types) are valid inside a single entry. +`scaffold route` requires `--group`, one of `_public+` or `_session+` (the React Router flat-route group, mapped to `Public` / `Session` in the page tree). `--loader` and `--action` emit those stubs, `--i18n` writes a locale file and wires the locale barrel, and `--dry-run` previews the files it would write without touching disk. `scaffold component --props` splits on depth-0 commas, so comma-bearing types (`Record`, tuples, multi-argument function types) are valid inside a single entry. `--no-story` skips the stories file and rewires the test to be self-contained; `--parent ` overrides the parent directory under `app/components/`. ### `gaia setup` @@ -65,17 +69,57 @@ gaia setup finalize [--force] gaia setup link-worktree [--json] ``` +### `gaia setup-ci` + +Source: `.gaia/cli/src/setup-ci/index.ts` + +Phase B remote-integration primitives invoked by `/setup-gaia-ci`. The slash command shells out to these for remote detection, the admin permission probe, token piping (stdin only), `workflow_dispatch` verification, and the `setup_complete` flip. + +``` +gaia setup-ci status [--json] +gaia setup-ci check-drift [--workflows-dir

] [--json] +gaia setup-ci check-audit-drift [--workflows-dir

] [--baseline

[--latest

]] [--json] +gaia setup-ci detect-remote [--json] +gaia setup-ci warn-existing-tools [--json] +gaia setup-ci check-admin --owner --repo [--json] +gaia setup-ci dismiss-personal +gaia setup-ci opt-out-team +gaia setup-ci enable-delete-branch --owner --repo +gaia setup-ci set-secret +gaia setup-ci verify-run [--timeout-seconds N] [--json] +gaia setup-ci finalize +gaia setup-ci write-tool-mode +``` + +`check-drift` compares the rendered workflows against a fresh template render. `check-audit-drift` does the same for the installed audit workflow, two-way by default or a three-way classify when `--baseline` (and optional `--latest`) are passed. `detect-remote` reads `git remote get-url origin`. `warn-existing-tools` detects Dependabot or Renovate configs. `set-secret` reads the secret value from stdin and pipes it into `gh secret set `. `dismiss-personal` writes `nudge_dismissed=true` (per-machine); `opt-out-team` writes `setup_opted_out=true` (committed). `write-tool-mode` sets one tool's mode in `.gaia/automation.json`; `` is one of `wiki`, `update-deps`, `pnpm-audit`, `stale-branches` and `` is `ci`, `local`, or `off`. + +### `gaia automation` + +Source: `.gaia/cli/src/automation/index.ts` + +Local-side GAIA CI primitives that read the automation config and render the workflow YAML. + +``` +gaia automation read-config [--json] +gaia automation cron-decide [--json] +gaia automation render-workflows --out-dir [--tools ] [--dry-run] +gaia automation install-audit-workflow --out-dir [--dry-run] +``` + +`read-config` prints the resolved `.gaia/automation.json`. `cron-decide ` reports whether a given tool's scheduled run is due. `render-workflows` writes the workflow YAML for the enabled tools into `--out-dir`; `--tools` narrows the set to a comma-separated list and `--dry-run` previews without writing. `install-audit-workflow` writes the code-review-audit workflow into `--out-dir`. + ### `gaia update` Source: `.gaia/cli/src/update/index.ts` -Wired by the `/update-gaia` skill for the field-aware `pnpm-workspace.yaml` merge step (Step 7b). +Wired by the `/update-gaia` skill for the field-aware `pnpm-workspace.yaml` merge (Step 7b) and the field-aware `.gaia/audit-ci.yml` merge (Step 7c). ``` gaia update merge-workspace --baseline --latest --current [--json] +gaia update merge-audit-ci --baseline --latest --current [--json] ``` -A field-aware, read-only verdict oracle for `pnpm-workspace.yaml`. It parses three YAML files (baseline from the prior GAIA release, latest from the incoming tarball, current working-tree copy) and emits a JSON report of `{applied, conflicts, suggestions}`. It never writes the workspace file. The `/update-gaia` skill applies the `applied` entries with the Edit tool so comments, key order, and quote style survive. The `--json` flag switches output from the human summary to the raw JSON report. +Both are field-aware, read-only verdict oracles. They parse three files (baseline from the prior GAIA release, latest from the incoming tarball, current working-tree copy) and emit a JSON report of `{applied, conflicts, suggestions}`. Neither writes the target file. The `/update-gaia` skill applies the `applied` entries with the Edit tool so comments, key order, and quote style survive. `merge-workspace` targets `pnpm-workspace.yaml`; `merge-audit-ci` targets `.gaia/audit-ci.yml`. The `--json` flag switches output from the human summary to the raw JSON report. ### `gaia update-deps` @@ -103,6 +147,18 @@ gaia fitness render-card [--cols N] Reads a `/gaia-fitness` report JSON document on stdin and writes a width-aware ASCII report card to stdout. `--cols` sets the target terminal width (default: autodetect from `process.stdout.columns`, fallback 100). The box self-sizes to the longest content line, clamped to 120 columns and to the terminal width, wrapping remediation text to fit. Categories render alphabetically. The FINDINGS block is omitted when the `findings` array is empty (clean run). The skill pipes the assembled report JSON through this command and pastes the stdout verbatim into its chat reply. +### `gaia react-perf` + +Source: `.gaia/cli/src/react-perf/index.ts` + +The deterministic reduce layer of the `/gaia-react-perf` render-performance diagnostic skill. + +``` +gaia react-perf reduce [--frame-budget-ms ] +``` + +`reduce` reads a raw bippy render dump from the `` path argument and writes a small ranked JSON summary to stdout for the skill to consume. `--frame-budget-ms` sets the per-frame budget used to flag slow renders (default: 16). + ### `gaia harden-tally` Source: `.gaia/cli/src/harden/tally.ts` @@ -130,6 +186,32 @@ gaia harden-ledger prune --window-classes `list` prints the full ledger as JSON. `record` upserts one entry keyed by `finding_class`, snapshotting the current PR count at decline time (re-recording overwrites the timestamp and count). `is-suppressed` exits 0 (suppressed) when an entry exists and fewer than 3 distinct PRs carrying the class have merged since the decline; exits 1 (not suppressed) otherwise. `prune` removes entries whose `finding_class` is no longer in the active window, idempotently. Ledger file: `.gaia/local/harden/declines.json`. +### `gaia ci-revert` + +Source: `.gaia/cli/src/ci/revert.ts`. The `ci` prefix is a naming convention, not a sub-router; `ci-revert` and `ci-stale-check` register at the top level. + +Owns the GAIA CI hard cap of one revert attempt per merged PR. The Phase 2 composite action trusts these exit codes and never inspects the ledger directly. + +``` +gaia ci-revert open --pr --label [--reason ] [--json] +gaia ci-revert mark-failed --pr [--json] +gaia ci-revert is-cap-reached --pr [--json] +``` + +`open` opens one revert PR for merged PR `` and refuses with `revert_already_opened` when a ledger entry already exists. `mark-failed` flips the recorded attempt's status to `failed`. `is-cap-reached` prints `{cap_reached, status}` for the original PR. Ledger file: `.gaia/automation.state-revert-attempts.json` (committed). + +### `gaia ci-stale-check` + +Source: `.gaia/cli/src/ci/stale-check.ts` + +Pre-run skip primitive for the GAIA CI Phase 2 composite action. Decides whether a workflow run should skip because a matching GAIA CI PR is already open. + +``` +gaia ci-stale-check --label --base [--author ] [--json] +``` + +`--label` and `--base` are required. `--author` defaults to `github-actions[bot]`. The check delegates to `gh pr list` with the open state plus all three predicates and reports `proceed` or `skip`. Exit code is 0 on either decision and non-zero only on a `gh` invocation failure. + ### `gaia wiki` Source: `.gaia/cli/src/wiki/index.ts` @@ -143,15 +225,17 @@ gaia wiki state-init gaia wiki state-bump gaia wiki log-prepend --sha --decision --reason "..." gaia wiki page-index [--json] -gaia wiki orphans +gaia wiki orphans [--json] gaia wiki near-collisions [--max-distance N] gaia wiki dead-paths [--json] gaia wiki frontmatter [--json] gaia wiki empty-sections [--json] +gaia wiki diff-size --threshold-pct N [--base ] [--json] gaia wiki sync land [--branch-aware] +gaia wiki chain ``` -`state-init ` refuses if `wiki/.state.json` already exists. `state-bump` performs an atomic single-field update. `sync land` lands staged wiki changes via the correct branch strategy. +`state-init ` refuses if `wiki/.state.json` already exists. `state-bump` performs an atomic single-field update. `diff-size` gates auto-merge on the wiki byte-delta against a base ref. `sync land` lands staged wiki changes via the correct branch strategy. `chain` runs the one-branch, one-PR orchestration of the full `/gaia-wiki` chain: `begin [--branch-aware]` cuts the `wiki-sync/-` branch on main, `commit --label ""` commits a stage in place, and `finish [--branch-aware]` pushes the branch, opens one PR, enables auto-merge, and returns to the base branch. ## Where to find tests diff --git a/src/content/docs/contributors/health-audit.mdx b/src/content/docs/contributors/health-audit.mdx index 7ecdb93..a75176d 100644 --- a/src/content/docs/contributors/health-audit.mdx +++ b/src/content/docs/contributors/health-audit.mdx @@ -7,54 +7,92 @@ sidebar: `/health-audit` is the autonomous audit + auto-heal loop for the GAIA template repo. It is contributor-only. The slash command file (`.claude/commands/health-audit.md`) and the supporting infrastructure under `.gaia/cli/health/` are excluded from the tarball. -GAIA's Claude integration is graded for efficiency, safety, and correctness. +It grades the repo's Claude integration and distribution boundary, fixes what it safely can, re-audits, and reports an F-to-A+ verdict, or escalates to you when it cannot resolve a finding on its own. -The goal of `/health-audit` is to get an A+ score on the GAIA repo with 0 issues of any severity. +## How it differs from /gaia-fitness + +[`/gaia-fitness`](/commands/fitness/) is the adopter-facing Claude-integration health check. It ships in every GAIA project, runs one triage-heal-verify pass over seven categories, and reports a letter grade. + +`/health-audit` is contributor-only and wider. It runs `/gaia-fitness`'s seven-category protocol as one of five audit buckets (Bucket E) and adds buckets for static checks, distribution-boundary leaks, bundle simulation, and enforcement-primitive coverage. It loops up to three audit-fix-audit cycles, preserves per-cycle artifacts, and escalates on the conditions below. Use `/gaia-fitness` to grade a project's Claude surface. Use `/health-audit` to vet the GAIA template repo itself before a release. ## What it does -`/health-audit` runs up to three audit-fix-audit cycles. Each cycle: +`/health-audit` runs up to three audit-fix-audit cycles. The Orchestrator runs on the main thread and owns every spawn. A spawned subagent cannot spawn another, so the buckets, the Adjudicator, and the Fixers are all leaf subagents the Orchestrator dispatches directly. + +Before the loop, the Orchestrator initializes a fresh `.gaia/local/audit/` directory, archiving any stale prior run first. Then each cycle: + +1. The Orchestrator creates the cycle directory `.gaia/local/audit/c/` and its bucket subdirectories. +2. It spawns the five audit buckets (A–E) as parallel leaf subagents. Each writes its raw output to disk and returns a summary plus the artifact path. +3. It spawns a fresh Adjudicator, which reads the bucket artifacts, classifies findings, and writes `.gaia/local/audit/c/findings.json` (including Bucket E's shared-fitness grade and the cycle's overall grade). +4. If the cycle is clean (no open findings, Bucket D reports A+ readiness, and the effective shared-fitness grade is A+), the loop exits with the honest overall grade and removes the per-cycle directories. +5. Otherwise the Orchestrator compares this cycle's open-finding fingerprints against the previous cycle's to detect oscillation, then dispatches Fixers in lane-aware parallel. +6. The Fixers report post-fix state to the Orchestrator, and the next cycle starts. + +A fresh Adjudicator per cycle keeps prior-cycle findings from bleeding into this cycle's verification. The Adjudicator classifies findings and writes `findings.json`; it never dispatches Fixers and never runs the oscillation compare. Those belong to the Orchestrator, which stays mechanical (counters, directory creation, disk reads, the fingerprint compare, and dispatch) and never audits, adjudicates, or fixes in its own context, so session state it inherits cannot bias a grade. + +A clean cycle is not necessarily A+. The reported grade is the honest floor with no open work left, and non-blocking residual `info` findings (for example the post-sync `wiki/.state.json` drift) legitimately cap it at A. -1. Spawns a fresh Triager. -2. The Triager runs the Audit Team in parallel across buckets A-D. -3. Findings get written to `.gaia/local/audit/c/findings.json`. -4. If clean (zero findings + Bucket D reports A+ readiness), the cycle exits with grade A+. -5. Otherwise, the Triager classifies findings, compares fingerprints against the previous cycle to detect oscillation, and dispatches Fixers in lane-aware parallel. -6. Fixers complete; the Triager reports post-fix state; the team shuts down; the next cycle starts. +## What the buckets check -A fresh Triager per cycle prevents prior-cycle findings from bleeding into verification. +| Bucket | Checks | +| --- | --- | +| A | The bundled CLI's typecheck and test suite (`pnpm -C .gaia/cli typecheck` and `pnpm -C .gaia/cli test --run`). | +| B | Distribution-boundary leaks in adopter-shipped files: greps for contributor-only paths that must not appear in files that ship. | +| C | Bundle simulation: stages the would-be release tarball and confirms it carries no maintainer-only marker fragments and no wikilinks to excluded pages. | +| D | Cross-class enforcement walk: confirms every distribution-boundary class has an enforcing primitive, returning a verdict from A− up to A+ readiness. | +| E | The shared Claude-integration fitness protocol, the same seven-category check `/gaia-fitness` runs (hook integrity, skill/command/agent frontmatter, rule hygiene, `CLAUDE.md` hygiene, settings hygiene, GAIA-install fitness, wiki fitness). | + +Mechanical buckets (A, B, C, and the mechanical half of E) run on Haiku. Judgment-bearing work (Bucket D, the judgment half of E, the Adjudicator, and the Fixers) runs on Sonnet. A Fixer is promoted to Opus only when the Adjudicator flags a high-complexity fix. ## Where the runbook lives -The orchestrator reads `.gaia/cli/health/runbook.md` end-to-end before running. The runbook codifies role structure, bucket definitions, fixer lane mapping, model selection, circuit breakers, and escalation criteria. The taxonomy of findings lives at `.gaia/cli/health/taxonomy.md`. +The Orchestrator reads `.gaia/cli/health/runbook.md` end-to-end before running. The runbook codifies role structure, bucket definitions, fixer lane mapping, model selection, circuit breakers, and escalation criteria. The finding taxonomy lives at `.gaia/cli/health/taxonomy.md`. Bucket E runs the protocol defined in `wiki/decisions/Claude Integration Fitness.md`. -Both files are excluded from the adopter tarball via the `.gaia/cli/health/` directory rule in `.gaia/release-exclude`. +Both `runbook.md` and `taxonomy.md` are excluded from the adopter tarball via the `.gaia/cli/health/` directory rule in `.gaia/release-exclude`. ## Circuit breakers -A Fixer dispatch pauses for human-confirm if the proposed fix: +A Fixer dispatch pauses for your confirmation if the proposed fix: - Touches more than 100 lines. - Modifies `.gaia/release-exclude`. - Modifies `.claude/rules/`. - Removes a check from `.gaia/release-scrub.yml`. -- Edits `.gaia/cli/health/taxonomy.md` "Decided / not findings" entries. +- Edits the "Decided / not findings" entries in `.gaia/cli/health/taxonomy.md`. +- Edits the "Decided / not findings" section of `wiki/decisions/Claude Integration Fitness.md`. -If the human refuses the fix, the orchestrator escalates. +If you refuse the fix, the Orchestrator escalates. ## Reports -On a clean exit the orchestrator prints: +On a clean exit the Orchestrator prints: ``` -HEALTH AUDIT: A+ +HEALTH AUDIT: +Overall grade: +Shared-fitness grade: Cycles: Findings closed: (per cycle: ) +Non-blocking residuals: (e.g. wiki/.state.json post-sync drift, recorded not blocking) Artifacts: cleaned (.gaia/local/audit/c* removed) ``` -On escalation, it preserves all `c*/` directories and prints the outstanding findings with fingerprints and the escalation reason (max-loops hit, oscillation detected, circuit breaker tripped, unclassified finding, or fixer unable to fix). +On escalation it preserves all `c*/` directories and prints the grades, the escalation reason, the outstanding findings with fingerprints, and the preserved artifact paths: + +``` +HEALTH AUDIT: ESCALATED +Overall grade: +Shared-fitness grade: +Reason: +Outstanding findings: +Cycles run: +Artifacts: preserved at .gaia/local/audit/c1/, c2/, c3/ (see findings.json in each) +``` + +The overall grade is F-to-A+ and is never higher than the shared-fitness grade. Both grades appear in every report, on a clean exit and on escalation. ## When contributors run it -Run `/health-audit` against the template repo before cutting a release, after merging changes that touched the CLI source or shipped Claude surface, or when investigating drift between the template and its own internal rules. +Run `/health-audit` against the template repo before cutting a release, after merging changes that touched the CLI source or the shipped Claude surface, or when investigating drift between the template and its own internal rules. + +`/health-audit` does not commit. The Fixers leave the working tree dirty, and you review and commit their changes yourself. diff --git a/src/content/docs/contributors/index.mdx b/src/content/docs/contributors/index.mdx index 79444b1..1fe97e6 100644 --- a/src/content/docs/contributors/index.mdx +++ b/src/content/docs/contributors/index.mdx @@ -7,7 +7,7 @@ sidebar: This section covers GAIA surface that exists in the template repo but is not included in the `npx create-gaia` bundle. -Audience: Steven and any outside contributors working on the GAIA template itself. +Audience: the GAIA maintainer and any outside contributors working on the GAIA template itself. If you ran `npx create-gaia my-app` for a scaffolded project, this section is not for you. @@ -22,7 +22,7 @@ Both pass through the bundle-time scrub during release. The on-disk `.gaia/relea ## What's in this section -- [CI workflows](/contributors/ci/): `release.yml`, `cli-tests.yml`, `distribution.yml`, `forensics-triage.yml`. +- [CI workflows](/contributors/ci/): `release.yml`, `cli-tests.yml`, `audit-ci-tests.yml`, `distribution.yml`, `forensics-triage.yml`. - [CLI surface](/contributors/cli/): `gaia` binary subcommands that contributors invoke directly, plus where their source lives. - [`/health-audit`](/contributors/health-audit/): autonomous health audit and auto-heal loop with circuit breakers. - [`/gaia-release`](/contributors/release/): audience scope and what releases produce. The detailed runbook is internal to the maintainer. diff --git a/src/content/docs/contributors/release.mdx b/src/content/docs/contributors/release.mdx index 0cc2b37..d6f30d5 100644 --- a/src/content/docs/contributors/release.mdx +++ b/src/content/docs/contributors/release.mdx @@ -5,24 +5,41 @@ sidebar: order: 2 --- -`/gaia-release` cuts a new release of the GAIA template itself. It is invoked by **Steven only**. The slash command and its supporting `gaia-maintainer` binary are stripped from the tarball by `.gaia/release-exclude`, so installers never see this surface. +`/gaia-release` cuts a new release of the GAIA template itself. It is invoked by **Steven only**. The slash command and its supporting `gaia-maintainer` binary are stripped from the tarball by `.gaia/release-exclude`, so adopters never see this surface. ## Why contributors should know it exists Contributors who modify CLI source, hooks, rules, or shipped wiki content land in trees that a release will eventually package. The release flow validates those trees in three ways: -- **Manifest regeneration**. `.gaia/manifest.json` lists every file in the adopter tarball with a class (`owned`, `shared`, or `wiki-owned`). The classification rules live in `.gaia/cli/src/release/manifest.ts`. The on-disk manifest is the source of truth that `/update-gaia` consumers read. -- **Bundle-time scrub**. The release workflow stages a tree from `git ls-files`, subtracts `.gaia/release-exclude` patterns, then runs the scrub against the staging directory. The scrub strips `gaia:maintainer-only` blocks and runs leak checks before the tarball is built. +- **Manifest regeneration**. `.gaia/manifest.json` assigns each GAIA-managed file in the adopter tarball a class (`owned`, `shared`, or `wiki-owned`). The classification rules live in `.gaia/cli/src/release/manifest.ts`. The on-disk manifest is the source of truth that [`/update-gaia`](/commands/update-gaia/) reads to decide which files to overwrite, three-way merge, or leave alone. +- **Bundle-time scrub**. The release workflow stages a tree from `git ls-files`, subtracts `.gaia/release-exclude` patterns, then runs the scrub against the staging directory. The scrub strips `gaia:maintainer-only` blocks and runs leak checks before the tarball is built. Any leak fails the build. - **Distribution test gate**. The release workflow runs `.gaia/tests/distribution/run-all.sh` against an independently-staged tree before the tarball uploads. A broken release halts before `gh release create` runs. If a change touches surface the release flow validates, expect the next release to surface any drift. +## What /gaia-release does + +The command runs on a clean `main` and takes a `patch`, `minor`, or `major` argument. At a behavioral level it: + +- bumps the version in `.gaia/VERSION` and `package.json`, +- graduates the CHANGELOG's `## [Unreleased]` section into a dated `## [X.Y.Z]` entry, +- regenerates `.gaia/manifest.json`, +- resets `wiki/hot.md` and `wiki/log.md` to release-baseline content so adopters scaffold from a clean slate, +- commits on a `release/vX.Y.Z` branch and opens a PR, +- tags the merge commit after the PR lands, which triggers the release CI. + +The release PR is not exempt from the merge gate. It runs the same Vitest, Playwright, and Chromatic checks and the `code-review-audit` handshake as any other PR before it can merge. + ## What runs the release end-to-end The CI counterpart is [release.yml](/contributors/ci/#releaseyml). It runs on `v*.*.*` tags, re-stages the tree, re-validates the staged tree and verifies runtime dependencies, runs the distribution test gate, builds the tarball, and creates the GitHub Release. `main` is protected. The release commit lands on a `release/v` branch, goes through a PR, and the tag is created on the merge commit after it lands on `main`. +## The two CLI binaries + +The CLI bundles two binaries from two entry points. `.gaia/cli/gaia` is the adopter binary and ships in the tarball; `.gaia/cli/gaia-maintainer` carries the release surface and is excluded by `.gaia/release-exclude`. esbuild tree-shakes the release code out of the adopter binary, so the shipped `gaia` has no way to cut a release. The build layout is documented in the [CLI surface](/contributors/cli/#build-layout) reference. + ## Detailed runbook The end-to-end runbook lives in the template source at `.claude/commands/gaia-release.md`. It is not reproduced here. diff --git a/src/content/docs/contributors/wiki.mdx b/src/content/docs/contributors/wiki.mdx index bc2241a..54a5812 100644 --- a/src/content/docs/contributors/wiki.mdx +++ b/src/content/docs/contributors/wiki.mdx @@ -1,6 +1,6 @@ --- title: Contributor wiki content -description: wiki/entities and wiki/meta are excluded from the end user tarball. Contributor-only wiki content and the gaia:maintainer-only block convention. +description: "Contributor-only wiki directories, the gaia:maintainer-only block convention, the wiki/.state.json state model, and the gaia wiki CLI subcommands." sidebar: order: 6 --- @@ -10,7 +10,7 @@ Two directories under `gaia/wiki/` are excluded from the end user tarball by `.g - `wiki/entities/`: named systems, products, and people tracked across the codebase. - `wiki/meta/`: process and convention pages about the wiki itself. -Three individual concept and decision pages are also excluded: `wiki/concepts/Release Workflow.md`, `wiki/decisions/Bundle-time Scrub.md`, and `wiki/decisions/Forensics Triage Workflow.md`. +Five individual concept and decision pages are also excluded: `wiki/concepts/Release Workflow.md`, `wiki/concepts/Release-Notes.md`, `wiki/decisions/Bundle-time Scrub.md`, `wiki/decisions/CLI-Binary-Split.md`, and `wiki/decisions/Forensics Triage Workflow.md`. The user-facing wiki workflow (`/gaia-wiki sync`, `/gaia-wiki consolidate`, `/gaia-wiki lint`) lives in end user docs. This page covers content that contributors maintain on the template repo's own wiki. @@ -27,9 +27,55 @@ When to add: a new entity becomes worth tracking on its own page when it gets cr ## wiki/meta/ -Pages here describe the wiki's own process. The directory currently holds wiki lint reports and consolidate reports dated by run, plus a dashboard. The reports are generated artifacts of `/gaia-wiki lint` and `/gaia-wiki consolidate` runs. +Pages here describe the wiki's own process. The directory currently holds wiki lint reports and consolidate reports dated by run, plus a dashboard. Report naming: -When to add: a new meta page is appropriate when it documents how the wiki itself works (a new convention, a new dashboard, a new workflow). Generated lint and consolidate reports land here automatically; do not write them by hand. +- Lint: `wiki/meta/lint-report-.md` (generated by `/gaia-wiki lint`). +- Consolidate: `wiki/meta/consolidate-report-.md` (generated by `/gaia-wiki consolidate`). + +Both commands overwrite the same-day file on repeated runs; do not write these by hand. + +When to add: a new meta page is appropriate when it documents how the wiki itself works (a new convention, a new dashboard, a new workflow). + +## wiki/.state.json + +`wiki/sync` and `wiki/consolidate` share a single state file at `wiki/.state.json`. All fields are written atomically by CLI primitives; do not edit by hand while a workflow is running. + +| 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 ` creates the file on a fresh project (refuses if it already exists). `gaia wiki state-bump ` updates a single field and preserves all others. `gaia wiki state --json` reads the file and returns drift severity, head SHA, and per-domain page counts. + +## gaia wiki CLI primitives + +The `gaia wiki` namespace exposes these subcommands. The `/gaia-wiki` router and its subagents call them; they are rarely invoked manually outside of debugging. + +| Subcommand | Description | +|---|---| +| `state [--json]` | Drift report: commits ahead of `last_evaluated_sha`, severity, per-domain page counts. | +| `commit-classify --since [--json]` | Classify commits WORTHY/SKIP since ``. | +| `state-init ` | Create `wiki/.state.json` (refuses if the file already exists). | +| `state-bump ` | Atomic field update in `wiki/.state.json`; preserves all other fields. | +| `log-prepend --sha --decision --reason "..."` | Prepend a decision line to `wiki/log.md`. | +| `page-index [--json]` | Walk all wiki pages; return frontmatter and wikilinks per page. | +| `orphans [--json]` | Pages with zero inbound wikilinks. | +| `near-collisions [--max-distance N]` | Per-domain Levenshtein check over page slugs. | +| `dead-paths [--json]` | Backtick repo paths cited in wiki prose that no longer exist on disk. | +| `frontmatter [--json]` | Pages missing required frontmatter (`type`, `status`). Excludes `wiki/meta/`. | +| `empty-sections [--json]` | LEAF headings with no body content; parent headings are never flagged. Excludes `wiki/meta/`, `wiki/hot.md`, `wiki/log.md`. | +| `diff-size --threshold-pct N [--base ] [--json]` | Gate auto-merge on wiki byte-delta vs base. | +| `sync land [--branch-aware]` | Land staged wiki changes via the correct branch strategy. | +| `chain ` | Single-branch / single-PR orchestration of the full `/gaia-wiki` chain. | + +`chain` subcommands: + +- `begin [--branch-aware]` cuts a `wiki-sync/-` branch from `main`/`master` so every stage commits there; on a feature branch it is a no-op. +- `commit --label ""` commits staged `wiki/` changes in place; no-op when nothing changed; refuses when non-wiki changes are present. +- `finish [--branch-aware]` pushes the chain branch, opens one PR, enables auto-merge, and returns to the base branch; removes an empty chain branch; no-op for in-place runs. ## gaia:maintainer-only block convention From b35e6592fd7a6051e99f0cd143acbec83da66ef6 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 16:56:14 +0900 Subject: [PATCH 19/25] docs: promote React Code heading, fix spec concurrency wording React Code now a top-level skill heading instead of nested under TypeScript. Spec page no longer implies a two-session cap on concurrent specs; the locked ledger is collision-safe for any number of sessions. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/commands/spec.mdx | 2 +- src/content/docs/skills/code.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/commands/spec.mdx b/src/content/docs/commands/spec.mdx index 7a9ef7b..a4fc126 100644 --- a/src/content/docs/commands/spec.mdx +++ b/src/content/docs/commands/spec.mdx @@ -87,7 +87,7 @@ Use auto mode when the description is well-formed and the cost of stopping for c ## Running more than one at once -You can run `/gaia-spec` in two sessions at the same time. Each session draws its own SPEC number from a shared, locked ledger, so two concurrent specs never collide on an id or overwrite each other's artifact. There is no flag and nothing to coordinate: open a second session and start the second spec. +You can run `/gaia-spec` in more than one session at the same time. Each session draws its own SPEC number from a shared, locked ledger, so concurrent specs never collide on an id or overwrite each other's artifact, no matter how many run at once. There is no flag and nothing to coordinate: open another session and start the next spec. If a session finds a SPEC that was allocated in another terminal but not yet saved, the resume-or-start-new prompt surfaces it, so you don't fork the same draft in two places. diff --git a/src/content/docs/skills/code.mdx b/src/content/docs/skills/code.mdx index d8022e8..3e9a38b 100644 --- a/src/content/docs/skills/code.mdx +++ b/src/content/docs/skills/code.mdx @@ -17,7 +17,7 @@ Patterns and conventions for TypeScript across the project: camelCase identifier Source: `.claude/skills/typescript/SKILL.md`. -### React Code +## React Code Conventions for React components, pages, routes, hooks, and forms. Includes pre-flight gates for `useEffect`, `useCallback`, and `useState`; a form-element check that swaps native `` for the project's `Form/*` components; a translation gate that requires every user-visible string to come from `t()` (exception: approximate skeleton-loader placeholders standing in for dynamic runtime values stay hardcoded; static skeleton text that mirrors a real `t()` call must still use `t()`); and a React 19 idiom check that enforces `ref` as an ordinary prop (no `forwardRef`), `use()` over `useContext`, `` shorthand over ``, guarding the `&&` numeric-0 leak in JSX, and staying in React Router's form handling instead of reaching for `useActionState`, `useFormStatus`, or `useOptimistic`. Covers component extraction thresholds and route/page architecture (`app/routes/` thin shells, `app/pages/` for UI). From 5b0d05e09df4c483ccafdeb89fef28aafa875feb Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 17:51:32 +0900 Subject: [PATCH 20/25] docs: restructure command pages into Workflow and Maintenance groups - Split commands/ into workflow/ and maintenance/ with grouped URLs - Fold Working in GAIA into the Workflow overview page - Split handoff-pickup into separate /gaia-handoff and /gaia-pickup pages, cross-linked - Generalize the handoff/pickup example to a saved-search filters feature - Add Changelog link to the header to match gaiareact.com - Collapse the Contributors sidebar group by default and put the create-gaia notice in a callout Co-Authored-By: Claude Opus 4.8 (1M context) --- astro.config.mjs | 27 +++-- src/content/docs/commands/handoff-pickup.mdx | 111 ------------------ src/content/docs/commands/index.mdx | 43 ------- .../docs/contributors/health-audit.mdx | 2 +- src/content/docs/contributors/index.mdx | 6 +- src/content/docs/contributors/release.mdx | 2 +- .../docs/getting-started/gaia-init.mdx | 2 +- src/content/docs/index.mdx | 17 ++- .../docs/{commands => maintenance}/audit.mdx | 2 +- .../{commands => maintenance}/fitness.mdx | 6 +- .../docs/{commands => maintenance}/harden.mdx | 2 +- .../index.mdx} | 31 +++-- .../{commands => maintenance}/update-deps.mdx | 0 .../{commands => maintenance}/update-gaia.mdx | 0 .../docs/{commands => maintenance}/wiki.mdx | 0 src/content/docs/skills/index.mdx | 6 +- .../docs/{commands => workflow}/forensics.mdx | 0 src/content/docs/workflow/handoff.mdx | 63 ++++++++++ .../index.mdx} | 54 +++------ src/content/docs/workflow/pickup.mdx | 63 ++++++++++ .../docs/{commands => workflow}/plan.mdx | 4 +- .../docs/{commands => workflow}/spec.mdx | 6 +- src/overrides/Header.astro | 1 + 23 files changed, 216 insertions(+), 232 deletions(-) delete mode 100644 src/content/docs/commands/handoff-pickup.mdx delete mode 100644 src/content/docs/commands/index.mdx rename src/content/docs/{commands => maintenance}/audit.mdx (96%) rename src/content/docs/{commands => maintenance}/fitness.mdx (95%) rename src/content/docs/{commands => maintenance}/harden.mdx (98%) rename src/content/docs/{maintenance.mdx => maintenance/index.mdx} (51%) rename src/content/docs/{commands => maintenance}/update-deps.mdx (100%) rename src/content/docs/{commands => maintenance}/update-gaia.mdx (100%) rename src/content/docs/{commands => maintenance}/wiki.mdx (100%) rename src/content/docs/{commands => workflow}/forensics.mdx (100%) create mode 100644 src/content/docs/workflow/handoff.mdx rename src/content/docs/{getting-started/working-in-gaia.mdx => workflow/index.mdx} (52%) create mode 100644 src/content/docs/workflow/pickup.mdx rename src/content/docs/{commands => workflow}/plan.mdx (98%) rename src/content/docs/{commands => workflow}/spec.mdx (98%) diff --git a/astro.config.mjs b/astro.config.mjs index 0e6e577..162b168 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -33,32 +33,32 @@ export default defineConfig({ label: 'Getting started', items: [ { label: 'Quick Start', slug: 'index' }, - { label: 'Working in GAIA', slug: 'getting-started/working-in-gaia' }, { label: '/gaia-init', slug: 'getting-started/gaia-init' }, { label: '/setup-gaia-ci', slug: 'getting-started/setup-gaia-ci' }, { label: '/setup-cloned-gaia-project', slug: 'getting-started/setup-cloned-gaia-project' }, ], }, { - label: 'Commands', + label: 'Workflow', items: [ - { label: 'Overview', slug: 'commands' }, - { label: '/gaia-spec', slug: 'commands/spec' }, - { label: '/gaia-plan', slug: 'commands/plan' }, - { label: '/gaia-handoff and pickup', slug: 'commands/handoff-pickup' }, - { label: '/gaia-forensics', slug: 'commands/forensics' }, - { label: '/update-deps', slug: 'commands/update-deps' }, - { label: '/update-gaia', slug: 'commands/update-gaia' }, + { label: 'Overview', slug: 'workflow' }, + { label: '/gaia-spec', slug: 'workflow/spec' }, + { label: '/gaia-plan', slug: 'workflow/plan' }, + { label: '/gaia-handoff', slug: 'workflow/handoff' }, + { label: '/gaia-pickup', slug: 'workflow/pickup' }, + { label: '/gaia-forensics', slug: 'workflow/forensics' }, ], }, { label: 'Maintenance', items: [ { label: 'Overview', slug: 'maintenance' }, - { label: '/gaia-fitness', slug: 'commands/fitness' }, - { label: '/gaia-audit', slug: 'commands/audit' }, - { label: '/gaia-harden', slug: 'commands/harden' }, - { label: '/gaia-wiki', slug: 'commands/wiki' }, + { label: '/gaia-fitness', slug: 'maintenance/fitness' }, + { label: '/gaia-audit', slug: 'maintenance/audit' }, + { label: '/gaia-harden', slug: 'maintenance/harden' }, + { label: '/gaia-wiki', slug: 'maintenance/wiki' }, + { label: '/update-deps', slug: 'maintenance/update-deps' }, + { label: '/update-gaia', slug: 'maintenance/update-gaia' }, ], }, { @@ -80,6 +80,7 @@ export default defineConfig({ }, { label: 'Contributors', + collapsed: true, items: [ { label: 'Overview', slug: 'contributors' }, { label: 'CI workflows', slug: 'contributors/ci' }, diff --git a/src/content/docs/commands/handoff-pickup.mdx b/src/content/docs/commands/handoff-pickup.mdx deleted file mode 100644 index 110c52d..0000000 --- a/src/content/docs/commands/handoff-pickup.mdx +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: /gaia-handoff and /gaia-pickup -description: Pause a session and resume cold without re-reading the conversation. -sidebar: - order: 5 ---- - -import { Aside } from '@astrojs/starlight/components'; - -| Skill | What it does | -| --- | --- | -| `/gaia-handoff` | Writes a self-contained handoff document so you can clear context. | -| `/gaia-pickup` | Reads the most recent handoff and reconstitutes context. | - -## When to use them - -Run `/gaia-handoff` at the end of a session, before a context break, or when the current state is non-obvious. In practice that means when the context window is getting full and you are about to `/clear`, `/compact`, or restart Claude. - -Then `/clear` (or exit Claude and restart). - -Then call `/gaia-pickup` in the fresh session to continue. - -Both are skills, so they also run on plain-English asks like "write a handoff" or "pick up where we left off", not just the slash form. - -## /gaia-handoff - -``` -/gaia-handoff [optional inline notes] -``` - -Pulls from three sources: - -- The conversation transcript (accomplishments, decisions, gaps, open questions). -- Git state (`git rev-parse --abbrev-ref HEAD`, `git log -1 --oneline`, `git status --short`). -- You can optionally include notes inline after `handoff` to help "focus" on specific parts or the next step(s). - -The handoff document is written to: - -``` -.gaia/local/handoff/HANDOFF-{YYYY-MM-DD}-{slug}.md -``` - -The slug is derived from the session's main thread (e.g. `auth-refactor`, `route-cleanup`). - -### What the document contains - -Sections present only when there is real content. Empty sections are dropped, not stubbed. - -- **Accomplishments**: what shipped, with commit hashes when committed. -- **Decisions**: table of decision, rationale, impact. -- **Gaps and open questions**: each gap names a status (`FIXED` / `PARTIAL` / `UNKNOWN` / `DEFERRED` / `INTENTIONAL`), notes, a concrete next check, and a reference (`@path/to/file:line`). -- **Environment state**: branch, background processes, devices or simulators, test fixtures. -- **Reference files**: `@path` cross-references so the next session can jump straight in. -- **Next actions**: table of concrete, testable steps with rough effort estimates. - -## /gaia-pickup - -``` -/gaia-pickup -``` - -No arguments. Pickup runs through four steps: - -1. **Locate.** Find the most recent handoff: `ls -t .gaia/local/handoff/HANDOFF-*.md | head -1`. If no handoff exists, fall back to `wiki/hot.md` and report `No handoff found, resuming from hot cache.` -2. **Read.** Load the handoff in full. Run `git rev-parse --abbrev-ref HEAD`, `git status --short`, and `git log -1 --oneline` in parallel. -3. **Report.** Surface a tight status block: current branch (with drift from the handoff if any), handoff filename and date, one-line context, 1 to 3 bullets on what's done or in-flight, 1 to 3 bullets on gaps, and a suggested next action. -4. **Archive.** After you confirm a direction (pick an action, start editing, or say "go"), the consumed handoff moves to `.gaia/local/handoff/archive/`. - -

- -### Drift detection - -If the handoff says branch `feat/auth` at commit `abc1234`, and current state is `main` at `def5678` with a dirty tree, pickup flags the divergence before suggesting next actions. The handoff may be stale; pickup says so explicitly rather than reconstructing context against a different reality. - -## Example flow - -End of session: - -``` -> /gaia-handoff coach voice prompts still need fixture audit -``` - -Fresh session: - -``` -> /gaia-pickup -``` - -Pickup reports: - -``` -Branch: feat/coach-voice (clean, matches handoff) -Last handoff: HANDOFF-2026-05-08-coach-voice.md (2026-05-08) -Context: Wired coach voice prompts to /api/coach; fixtures pending. - -State: -- Coach prompt template extracted to lib/prompts/coach.ts -- Endpoint contract aligned with spec - -Open: -- Fixtures audit: voice cues for happy/sad/neutral are stubs -- Test for empty transcript edge case - -Suggested next: Audit fixture coverage at @lib/prompts/coach.fixtures.ts:1 -``` - -## Storage - -Handoffs are project-local: `.gaia/local/` is gitignored. They never enter version control, so private notes, dirty-tree details, and device IDs stay on the machine that wrote them. Archived handoffs are not pruned automatically. You should clean `.gaia/local/handoff/archive/` when it grows. diff --git a/src/content/docs/commands/index.mdx b/src/content/docs/commands/index.mdx deleted file mode 100644 index f75e9df..0000000 --- a/src/content/docs/commands/index.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Commands -description: GAIA's day-to-day workflows, each a discrete /gaia-* slash command or skill. -sidebar: - order: 1 ---- - -Most of GAIA's day-to-day workflows are discrete slash entries that show up in autocomplete as you type `/gaia-`. Six are commands (`/gaia-plan`, `/gaia-spec`, `/gaia-audit`, `/gaia-fitness`, `/gaia-forensics`, `/gaia-harden`). Three are skills (`/gaia-wiki`, `/gaia-handoff`, `/gaia-pickup`) that also respond to plain-English requests, not just the slash form. - -## Workflow Commands - -| Command | What it does | -| --- | --- | -| [`/gaia-spec`](/commands/spec/) | Run a Q&A to write and refine specifications. | -| [`/gaia-plan`](/commands/plan/) | Plan known features. | -| [`/gaia-handoff`](/commands/handoff-pickup/) | Generate a session handoff document so context can transfer to a fresh session. | -| [`/gaia-pickup`](/commands/handoff-pickup/) | Restore context from the most recent handoff. | - -## Maintenance Commands - -| Command | What it does | -| --- | --- | -| [`/gaia-audit`](/commands/audit/) | Audit memory, wiki, and auto-loaded files for duplication, conflicting instructions, and stale content. | -| [`/gaia-fitness`](/commands/fitness/) | Health check and auto-heal for the Claude integration surface. Triage, heal, verify, and report an F-to-A+ grade. | -| [`/gaia-harden`](/commands/harden/) | Human-gated hardening. Reviews recurring code-review-audit findings and, with approval, drafts the lowest-context-weight enforcement form (rule, skill, or deterministic check) into the working tree. | -| [`/gaia-wiki`](/commands/wiki/) | Wiki maintenance. With no arguments, runs the full sync, consolidate, and lint chain; each stage can also be invoked by name. | - -## Update Commands - -| Command | What it does | -| --- | --- | -| [`/update-deps`](/commands/update-deps/) | Bump outdated packages group-by-group, run migrations for major-version bumps, and validate the full quality gate. | -| [`/update-gaia`](/commands/update-gaia/) | Pull the latest GAIA release into your project without overwriting your customizations. | - -## GAIA Forensics - -| Command | What it does | -| --- | --- | -| [`/gaia-forensics`](/commands/forensics/) | Triage a GAIA workflow misfire into a redacted, classified bug report. Files upstream on confirmation. | - -## No-argument behavior - -Each entry has a sensible default when called with no arguments. `/gaia-wiki` runs the full chain (sync, consolidate, lint). `/gaia-audit` researches, then asks before it applies. `/gaia-harden` defaults to `review` mode. `/gaia-plan`, `/gaia-spec`, and `/gaia-forensics` prompt for or infer what they need before continuing. diff --git a/src/content/docs/contributors/health-audit.mdx b/src/content/docs/contributors/health-audit.mdx index a75176d..1283fef 100644 --- a/src/content/docs/contributors/health-audit.mdx +++ b/src/content/docs/contributors/health-audit.mdx @@ -11,7 +11,7 @@ It grades the repo's Claude integration and distribution boundary, fixes what it ## How it differs from /gaia-fitness -[`/gaia-fitness`](/commands/fitness/) is the adopter-facing Claude-integration health check. It ships in every GAIA project, runs one triage-heal-verify pass over seven categories, and reports a letter grade. +[`/gaia-fitness`](/maintenance/fitness/) is the adopter-facing Claude-integration health check. It ships in every GAIA project, runs one triage-heal-verify pass over seven categories, and reports a letter grade. `/health-audit` is contributor-only and wider. It runs `/gaia-fitness`'s seven-category protocol as one of five audit buckets (Bucket E) and adds buckets for static checks, distribution-boundary leaks, bundle simulation, and enforcement-primitive coverage. It loops up to three audit-fix-audit cycles, preserves per-cycle artifacts, and escalates on the conditions below. Use `/gaia-fitness` to grade a project's Claude surface. Use `/health-audit` to vet the GAIA template repo itself before a release. diff --git a/src/content/docs/contributors/index.mdx b/src/content/docs/contributors/index.mdx index 1fe97e6..1a1e2b7 100644 --- a/src/content/docs/contributors/index.mdx +++ b/src/content/docs/contributors/index.mdx @@ -5,11 +5,15 @@ sidebar: order: 1 --- +import { Aside } from '@astrojs/starlight/components'; + This section covers GAIA surface that exists in the template repo but is not included in the `npx create-gaia` bundle. Audience: the GAIA maintainer and any outside contributors working on the GAIA template itself. -If you ran `npx create-gaia my-app` for a scaffolded project, this section is not for you. + ## Adopter / contributor split diff --git a/src/content/docs/contributors/release.mdx b/src/content/docs/contributors/release.mdx index d6f30d5..814c4be 100644 --- a/src/content/docs/contributors/release.mdx +++ b/src/content/docs/contributors/release.mdx @@ -11,7 +11,7 @@ sidebar: Contributors who modify CLI source, hooks, rules, or shipped wiki content land in trees that a release will eventually package. The release flow validates those trees in three ways: -- **Manifest regeneration**. `.gaia/manifest.json` assigns each GAIA-managed file in the adopter tarball a class (`owned`, `shared`, or `wiki-owned`). The classification rules live in `.gaia/cli/src/release/manifest.ts`. The on-disk manifest is the source of truth that [`/update-gaia`](/commands/update-gaia/) reads to decide which files to overwrite, three-way merge, or leave alone. +- **Manifest regeneration**. `.gaia/manifest.json` assigns each GAIA-managed file in the adopter tarball a class (`owned`, `shared`, or `wiki-owned`). The classification rules live in `.gaia/cli/src/release/manifest.ts`. The on-disk manifest is the source of truth that [`/update-gaia`](/maintenance/update-gaia/) reads to decide which files to overwrite, three-way merge, or leave alone. - **Bundle-time scrub**. The release workflow stages a tree from `git ls-files`, subtracts `.gaia/release-exclude` patterns, then runs the scrub against the staging directory. The scrub strips `gaia:maintainer-only` blocks and runs leak checks before the tarball is built. Any leak fails the build. - **Distribution test gate**. The release workflow runs `.gaia/tests/distribution/run-all.sh` against an independently-staged tree before the tarball uploads. A broken release halts before `gh release create` runs. diff --git a/src/content/docs/getting-started/gaia-init.mdx b/src/content/docs/getting-started/gaia-init.mdx index e28b18b..729d4dc 100644 --- a/src/content/docs/getting-started/gaia-init.mdx +++ b/src/content/docs/getting-started/gaia-init.mdx @@ -90,7 +90,7 @@ If you enabled CI, the recommended default is all four in `ci`. If you declined, ### 8. Wiki reset -GAIA ships with a built-in [wiki](/commands/wiki/) that Claude maintains as it works. Init resets two of its files, the hot cache and the log, to a clean slate so your project starts with its own context instead of GAIA's development history. +GAIA ships with a built-in [wiki](/maintenance/wiki/) that Claude maintains as it works. Init resets two of its files, the hot cache and the log, to a clean slate so your project starts with its own context instead of GAIA's development history. ## After gaia-init completes diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index f2b0919..c0ec860 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -29,7 +29,22 @@ npx create-gaia@latest my-app 3. Installs the packages 4. Launches Claude Code in the project directory and runs `/gaia-init` automatically -Follow along with the `/gaia-init` [walkthrough](/getting-started/gaia-init/). Once setup is done, [Working in GAIA](/getting-started/working-in-gaia/) shows how a normal session works. +Follow along with the `/gaia-init` [walkthrough](/getting-started/gaia-init/). Once setup is done, the [Workflow overview](/workflow/) shows how a normal session works. + +### Permissions on the first run + +When you scaffold a project, `npx create-gaia` launches Claude Code once with `--dangerously-skip-permissions` and runs `/gaia-init`. That single run rewrites files, registers tools, and wires the project end to end. The flag lets it finish without stopping to ask permission at every step. + +That flag applies to the setup run only. Nothing stores it. When `/gaia-init` finishes, it tells you to exit Claude and relaunch, because the new skills and plugins load only in a fresh session. How you relaunch is your call: plain `claude` if you'd rather approve actions as they happen, or `claude --dangerously-skip-permissions` if you don't want to be interrupted. + +Either way, GAIA's guardrails stay on. They run as hooks on every tool call, not as permission prompts, so skipping the prompts doesn't disable them. Every scaffolded project ships hooks that block actions like: + +- committing or force-pushing directly to `main` +- `rm -rf` on dangerous targets (`/`, `~`, `.git`, `node_modules`, the repo root) +- writing secrets or `.env` files into the repo +- committing with `--no-verify` to skip the typecheck, lint, and test gate + +These hold whether or not you pass the flag. See the [hooks reference](/reference/hooks/) for the full set. ## Cloning an existing GAIA project diff --git a/src/content/docs/commands/audit.mdx b/src/content/docs/maintenance/audit.mdx similarity index 96% rename from src/content/docs/commands/audit.mdx rename to src/content/docs/maintenance/audit.mdx index abc5492..8ca58ad 100644 --- a/src/content/docs/commands/audit.mdx +++ b/src/content/docs/maintenance/audit.mdx @@ -77,7 +77,7 @@ The audit checks each entry against the other stores and classifies it as: Contradiction detection has two deliberate exclusions: a `paths:`-scoped rule that duplicates the wiki on purpose is sanctioned, not a conflict; and a wiki-page-vs-wiki-page disagreement is out of scope here. For that, use `/gaia-wiki consolidate`. -A rule that carries a `gaia-harden:` provenance marker (one [`/gaia-harden`](/commands/harden/) promoted from a recurring finding) falls under the same path-scoped exclusion. It always carries a `paths:` glob, so the audit inventories it, word-budgets it, and applies the same DUPLICATE and obsolescence prune rules as a hand-authored rule. The marker grants no exemption, and a rule is never marked STALE just because its pattern stopped recurring. +A rule that carries a `gaia-harden:` provenance marker (one [`/gaia-harden`](/maintenance/harden/) promoted from a recurring finding) falls under the same path-scoped exclusion. It always carries a `paths:` glob, so the audit inventories it, word-budgets it, and applies the same DUPLICATE and obsolescence prune rules as a hand-authored rule. The marker grants no exemption, and a rule is never marked STALE just because its pattern stopped recurring. Then it computes auto-load budgets: diff --git a/src/content/docs/commands/fitness.mdx b/src/content/docs/maintenance/fitness.mdx similarity index 95% rename from src/content/docs/commands/fitness.mdx rename to src/content/docs/maintenance/fitness.mdx index 32904f1..f7fc00f 100644 --- a/src/content/docs/commands/fitness.mdx +++ b/src/content/docs/maintenance/fitness.mdx @@ -5,13 +5,13 @@ description: Health check and auto-heal for your project's Claude integration. T `/gaia-fitness` checks the health of your project's Claude integration and repairs what it safely can. One invocation, no flags: calling `/gaia-fitness` is the statement of intent to be fit. It runs three phases in sequence: triage, heal, verify, and reports a per-category and overall grade from F up to A+. -It checks the Claude *surface* (hooks, skill/command/agent frontmatter, rule files, `CLAUDE.md`, `.claude/settings.json`, GAIA itself, and wiki structure), not your application code. For app code review before merge, use the `code-review-audit` agent. For knowledge-store bloat, duplication, and contradictions, use [`/gaia-audit`](/commands/audit/). +It checks the Claude *surface* (hooks, skill/command/agent frontmatter, rule files, `CLAUDE.md`, `.claude/settings.json`, GAIA itself, and wiki structure), not your application code. For app code review before merge, use the `code-review-audit` agent. For knowledge-store bloat, duplication, and contradictions, use [`/gaia-audit`](/maintenance/audit/). ## When to use it Run `/gaia-fitness` after editing under `.claude/`, such as modifying or adding new commands, skills, agents, hooks, etc. -You can also call it after pulling a GAIA update with [`/update-gaia`](/commands/update-gaia/) if you made any customizations to GAIA, or periodically as a routine check. +You can also call it after pulling a GAIA update with [`/update-gaia`](/maintenance/update-gaia/) if you made any customizations to GAIA, or periodically as a routine check. ## How to invoke @@ -93,4 +93,4 @@ Then, depending on what happened: ## Related -`/gaia-fitness` checks the Claude integration surface. For knowledge-store duplication, contradictions, and autoload budgets, use [`/gaia-audit`](/commands/audit/). For wiki-internal redundancy and broken wikilinks, use [`/gaia-wiki`](/commands/wiki/). For your application code on a branch before merge, use the [`code-review-audit` agent](/reference/agents/). +`/gaia-fitness` checks the Claude integration surface. For knowledge-store duplication, contradictions, and autoload budgets, use [`/gaia-audit`](/maintenance/audit/). For wiki-internal redundancy and broken wikilinks, use [`/gaia-wiki`](/maintenance/wiki/). For your application code on a branch before merge, use the [`code-review-audit` agent](/reference/agents/). diff --git a/src/content/docs/commands/harden.mdx b/src/content/docs/maintenance/harden.mdx similarity index 98% rename from src/content/docs/commands/harden.mdx rename to src/content/docs/maintenance/harden.mdx index 9793dee..7e9caa7 100644 --- a/src/content/docs/commands/harden.mdx +++ b/src/content/docs/maintenance/harden.mdx @@ -115,4 +115,4 @@ Promoted rules are not permanent in the "never touch" sense: `/gaia-audit` is th ## Related - [`code-review-audit` agent](/reference/agents/): the source of the `finding_class` emissions the loop counts. -- [`/gaia-audit`](/commands/audit/): the single pruner for promoted rules and all other knowledge-store hygiene. +- [`/gaia-audit`](/maintenance/audit/): the single pruner for promoted rules and all other knowledge-store hygiene. diff --git a/src/content/docs/maintenance.mdx b/src/content/docs/maintenance/index.mdx similarity index 51% rename from src/content/docs/maintenance.mdx rename to src/content/docs/maintenance/index.mdx index ecf924d..2131a21 100644 --- a/src/content/docs/maintenance.mdx +++ b/src/content/docs/maintenance/index.mdx @@ -14,24 +14,31 @@ As a project accumulates work, four parts of that setup drift or accumulate inde Each part has its own command. They run independently and do not call one another. -| Command | What it checks | The question it answers | -| --- | --- | --- | -| [`/gaia-fitness`](/commands/fitness/) | The Claude integration surface: hooks, frontmatter, rules, `.claude/settings.json` | Does the machine run? | -| [`/gaia-audit`](/commands/audit/) | Memory, wiki, and auto-loaded files for duplication, conflicting instructions, and stale content | Is the fuel clean? | -| [`/gaia-wiki`](/commands/wiki/) | The wiki itself: redundant or conflicting pages, and broken wikilinks | Is the knowledge base internally consistent? | -| [`/gaia-harden`](/commands/harden/) | Recurring code-review-audit findings, for patterns worth codifying as a rule, skill, or deterministic check | Should this pattern become a rule? | +## Maintenance Commands + +| Command | What it does | +| --- | --- | +| [`/gaia-fitness`](/maintenance/fitness/) | Health check and auto-heal for the Claude integration surface. Triage, heal, verify, and report an F-to-A+ grade. | +| [`/gaia-audit`](/maintenance/audit/) | Audit memory, wiki, and auto-loaded files for duplication, conflicting instructions, and stale content. Researches, then asks before it applies. | +| [`/gaia-harden`](/maintenance/harden/) | Human-gated hardening. Reviews recurring code-review-audit findings and, with approval, drafts the lowest-context-weight enforcement form (rule, skill, or deterministic check) into the working tree. Defaults to `review` mode. | +| [`/gaia-wiki`](/maintenance/wiki/) | Wiki maintenance. With no arguments, runs the full sync, consolidate, and lint chain; each stage can also be invoked by name. | ## Which one to run Pick by symptom: -- The integration feels off, a hook is not firing, a rule is not loading, a command misbehaves: run [`/gaia-fitness`](/commands/fitness/). -- The base context feels heavy, or machine-local memory has grown large: run [`/gaia-audit`](/commands/audit/). -- The wiki has grown and pages overlap, or wikilinks break: run [`/gaia-wiki`](/commands/wiki/). -- Recurring findings from code-review-audit keep surfacing for the same class of issue: run [`/gaia-harden`](/commands/harden/). +- The integration feels off, a hook is not firing, a rule is not loading, a command misbehaves: run [`/gaia-fitness`](/maintenance/fitness/). +- The base context feels heavy, or machine-local memory has grown large: run [`/gaia-audit`](/maintenance/audit/). +- The wiki has grown and pages overlap, or wikilinks break: run [`/gaia-wiki`](/maintenance/wiki/). +- Recurring findings from code-review-audit keep surfacing for the same class of issue: run [`/gaia-harden`](/maintenance/harden/). The boundary between `/gaia-audit` and `/gaia-wiki` is deliberate. `/gaia-audit` reconciles the loaded context against the wiki (the source of truth) and resolves disagreements between project files; it does not touch wiki-page-vs-wiki-page conflicts. Those belong to `/gaia-wiki consolidate`. -## Related +## Update Commands + +Keeping dependencies and GAIA itself current is a different kind of upkeep: -For keeping dependencies and GAIA itself current, a different kind of upkeep, see [`/update-deps`](/commands/update-deps/) and [`/update-gaia`](/commands/update-gaia/). +| Command | What it does | +| --- | --- | +| [`/update-deps`](/maintenance/update-deps/) | Bump outdated packages group-by-group, run migrations for major-version bumps, and validate the full quality gate. | +| [`/update-gaia`](/maintenance/update-gaia/) | Pull the latest GAIA release into your project without overwriting your customizations. | diff --git a/src/content/docs/commands/update-deps.mdx b/src/content/docs/maintenance/update-deps.mdx similarity index 100% rename from src/content/docs/commands/update-deps.mdx rename to src/content/docs/maintenance/update-deps.mdx diff --git a/src/content/docs/commands/update-gaia.mdx b/src/content/docs/maintenance/update-gaia.mdx similarity index 100% rename from src/content/docs/commands/update-gaia.mdx rename to src/content/docs/maintenance/update-gaia.mdx diff --git a/src/content/docs/commands/wiki.mdx b/src/content/docs/maintenance/wiki.mdx similarity index 100% rename from src/content/docs/commands/wiki.mdx rename to src/content/docs/maintenance/wiki.mdx diff --git a/src/content/docs/skills/index.mdx b/src/content/docs/skills/index.mdx index b0a9544..7d91603 100644 --- a/src/content/docs/skills/index.mdx +++ b/src/content/docs/skills/index.mdx @@ -11,19 +11,19 @@ GAIA ships its skills under `.claude/skills/` in your project. Each one is a dir GAIA groups its skills into four categories: -**Workflow skills** handle session context and wiki maintenance. Trigger on `/gaia-handoff`, `/gaia-pickup`, `/gaia-wiki`, or natural-language asks like "hand off this session" or "sync the wiki". See [Handoff and pickup](/commands/handoff-pickup/) and [/gaia-wiki](/commands/wiki/). +**Workflow skills** handle session context and wiki maintenance. Trigger on `/gaia-handoff`, `/gaia-pickup`, `/gaia-wiki`, or natural-language asks like "hand off this session" or "sync the wiki". See [/gaia-handoff](/workflow/handoff/), [/gaia-pickup](/workflow/pickup/), and [/gaia-wiki](/maintenance/wiki/). **Code skills** govern how code is written and reviewed. Trigger when you write or edit TypeScript, React, Tailwind, tests, or browser automation. See [Code skills](/skills/code/). **Scaffolders** generate new files from templates. Trigger when you ask to create a component, hook, route, or service. See [Scaffolders](/skills/scaffolders/). -**Maintenance skills** update project dependencies and pull new GAIA releases. See [/update-deps](/commands/update-deps/) and [/update-gaia](/commands/update-gaia/). +**Maintenance skills** update project dependencies and pull new GAIA releases. See [/update-deps](/maintenance/update-deps/) and [/update-gaia](/maintenance/update-gaia/). ## How triggering works Each `SKILL.md` has a `description:` field that lists the phrasings and situations that load the skill. The skills do not run on every prompt; they activate when the description matches what you said. You don't invoke them by name. Saying "scaffold a card called PriceCard" loads `new-component`. Saying "the typecheck is angry about a stale closure" loads `react-code`. -A few skills are also wired to the statusline. When [`/update-deps`](/commands/update-deps/) or [`/update-gaia`](/commands/update-gaia/) detect pending work, the statusline shows a `Run /update-deps` or `Run /update-gaia` indicator; clicking the indicator loads the skill. +A few skills are also wired to the statusline. When [`/update-deps`](/maintenance/update-deps/) or [`/update-gaia`](/maintenance/update-gaia/) detect pending work, the statusline shows a `Run /update-deps` or `Run /update-gaia` indicator; clicking the indicator loads the skill. ## Adding your own diff --git a/src/content/docs/commands/forensics.mdx b/src/content/docs/workflow/forensics.mdx similarity index 100% rename from src/content/docs/commands/forensics.mdx rename to src/content/docs/workflow/forensics.mdx diff --git a/src/content/docs/workflow/handoff.mdx b/src/content/docs/workflow/handoff.mdx new file mode 100644 index 0000000..a3ecfa9 --- /dev/null +++ b/src/content/docs/workflow/handoff.mdx @@ -0,0 +1,63 @@ +--- +title: /gaia-handoff +description: Write a self-contained handoff document so you can clear context without losing the thread. +sidebar: + order: 5 +--- + +import { Aside } from '@astrojs/starlight/components'; + +`/gaia-handoff` writes a self-contained handoff document so you can clear context. Its companion, [`/gaia-pickup`](/workflow/pickup/), reads that document back in a fresh session. + +## When to use it + +Run `/gaia-handoff` at the end of a session, before a context break, or when the current state is non-obvious. In practice that means when the context window is getting full and you are about to `/clear`, `/compact`, or restart Claude. + +Then `/clear` (or exit Claude and restart) and call [`/gaia-pickup`](/workflow/pickup/) in the fresh session to continue. + +It's a skill, so it also runs on plain-English asks like "write a handoff", not just the slash form. + +## Usage + +``` +/gaia-handoff [optional inline notes] +``` + +Pulls from three sources: + +- The conversation transcript (accomplishments, decisions, gaps, open questions). +- Git state (`git rev-parse --abbrev-ref HEAD`, `git log -1 --oneline`, `git status --short`). +- You can optionally include notes inline after `handoff` to help "focus" on specific parts or the next step(s). + +The handoff document is written to: + +``` +.gaia/local/handoff/HANDOFF-{YYYY-MM-DD}-{slug}.md +``` + +The slug is derived from the session's main thread (e.g. `auth-refactor`, `route-cleanup`). + +## What the document contains + +Sections present only when there is real content. Empty sections are dropped, not stubbed. + +- **Accomplishments**: what shipped, with commit hashes when committed. +- **Decisions**: table of decision, rationale, impact. +- **Gaps and open questions**: each gap names a status (`FIXED` / `PARTIAL` / `UNKNOWN` / `DEFERRED` / `INTENTIONAL`), notes, a concrete next check, and a reference (`@path/to/file:line`). +- **Environment state**: branch, background processes, devices or simulators, test fixtures. +- **Reference files**: `@path` cross-references so the next session can jump straight in. +- **Next actions**: table of concrete, testable steps with rough effort estimates. + +## Example + +End of session: + +``` +> /gaia-handoff saved-search filters still need empty-state handling +``` + +In the fresh session, [`/gaia-pickup`](/workflow/pickup/) reads this back. See that page for the resume side of the flow. + +## Storage + +Handoffs are project-local: `.gaia/local/` is gitignored. They never enter version control, so private notes, dirty-tree details, and device IDs stay on the machine that wrote them. Archived handoffs are not pruned automatically. You should clean `.gaia/local/handoff/archive/` when it grows. diff --git a/src/content/docs/getting-started/working-in-gaia.mdx b/src/content/docs/workflow/index.mdx similarity index 52% rename from src/content/docs/getting-started/working-in-gaia.mdx rename to src/content/docs/workflow/index.mdx index 9a216db..696dc34 100644 --- a/src/content/docs/getting-started/working-in-gaia.mdx +++ b/src/content/docs/workflow/index.mdx @@ -1,11 +1,13 @@ --- title: Working in GAIA description: How a normal Claude Code session works once GAIA is installed, and when to reach for each /gaia-* command. +sidebar: + order: 1 --- import { Aside } from '@astrojs/starlight/components'; -Every other page here documents one command, hook, or skill on its own. This page is the opposite: it shows how the pieces fit together in normal use, so you know what to do once setup is done. +This page shows how GAIA's pieces fit together in normal use, so you know what to do once setup is done. ## Mostly, you just prompt Claude @@ -21,33 +23,17 @@ The code skills (TypeScript, React, Tailwind, tests) and the scaffolders trigger Notice the prompt didn't ask for a test. GAIA works test-first: for a feature or a bug fix, Claude writes a failing test, then the code that makes it pass. A commit hook backs this up, refusing to commit a new test that was never seen to fail first. You get tests as part of the work, not as a separate request. - - ## When to reach for a command The `/gaia-*` commands are for specific moments, not everyday driving. These you reach for based on what you're doing: | When you're... | Reach for | Why | | --- | --- | --- | -| Starting a feature whose shape isn't settled | [`/gaia-spec`](/commands/spec/) | Pins down intent and acceptance tests, then saves a spec you can review before any code is written. | -| Turning a big feature into parallel work | [`/gaia-plan`](/commands/plan/) | Breaks it into phased workstreams with shared contracts and a ready-to-run kickoff. | -| Pausing, or your context is getting heavy | [`/gaia-handoff`](/commands/handoff-pickup/) | Writes down where you are so you can clear context without losing the thread. | -| Starting a fresh session | [`/gaia-pickup`](/commands/handoff-pickup/) | Reads the last handoff back and tells you what changed since. | -| A GAIA command or hook misbehaved | [`/gaia-forensics`](/commands/forensics/) | Diagnoses the misfire and, if it's a bug, drafts a filing-ready report. | - -### Nudged by the statusline - -You rarely reach for these yourself. They surface on the statusline when they're due, so you don't have to track them: - -| When you're... | Reach for | Why | -| --- | --- | --- | -| The Claude integration feels off | [`/gaia-fitness`](/commands/fitness/) | Health-checks hooks, frontmatter, rules, and settings, then heals what it can. | -| Memory or rules have drifted | [`/gaia-audit`](/commands/audit/) | Finds duplication, contradictions, and stale guidance across your knowledge stores. | -| The wiki has fallen behind the code | [`/gaia-wiki`](/commands/wiki/) | Syncs, consolidates, and lints the project wiki Claude reads from. | -| Dependencies are stale | [`/update-deps`](/commands/update-deps/) | Walks outdated packages by group and runs major-version migrations. | -| A new GAIA release is out | [`/update-gaia`](/commands/update-gaia/) | Merges the release into your project without clobbering your changes. | +| Starting a feature whose shape isn't settled | [`/gaia-spec`](/workflow/spec/) | Pins down intent and acceptance tests, then saves a spec you can review before any code is written. | +| Turning a big feature into parallel work | [`/gaia-plan`](/workflow/plan/) | Breaks it into phased workstreams with shared contracts and a ready-to-run kickoff. | +| Pausing, or your context is getting heavy | [`/gaia-handoff`](/workflow/handoff/) | Writes down where you are so you can clear context without losing the thread. | +| Starting a fresh session | [`/gaia-pickup`](/workflow/pickup/) | Reads the last handoff back and tells you what changed since. | +| A GAIA command or hook misbehaved | [`/gaia-forensics`](/workflow/forensics/) | Diagnoses the misfire and, if it's a bug, drafts a filing-ready report. | **When to skip them.** Small, clear changes don't need a spec or a plan. "Fix the timezone bug in the invoice header" is just a prompt. Spec and plan earn their overhead on larger, fuzzier work, the kind where it's worth agreeing on what to build before building it. @@ -63,24 +49,22 @@ Here is the full loop for a feature you can't fully describe yet: You won't run every step for every task. Reach for as much of the loop as the work needs, and prompt directly for the rest. -## Permissions on the first run +## Maintenance commands -When you scaffold a project, `npx create-gaia` launches Claude Code once with `--dangerously-skip-permissions` and runs `/gaia-init`. That single run rewrites files, registers tools, and wires the project end to end. The flag lets it finish without stopping to ask permission at every step. - -That flag applies to the setup run only. Nothing stores it. When `/gaia-init` finishes, it tells you to exit Claude and relaunch, because the new skills and plugins load only in a fresh session. How you relaunch is your call: plain `claude` if you'd rather approve actions as they happen, or `claude --dangerously-skip-permissions` if you don't want to be interrupted. - -Either way, GAIA's guardrails stay on. They run as hooks on every tool call, not as permission prompts, so skipping the prompts doesn't disable them. Every scaffolded project ships hooks that block actions like: - -- committing or force-pushing directly to `main` -- `rm -rf` on dangerous targets (`/`, `~`, `.git`, `node_modules`, the repo root) -- writing secrets or `.env` files into the repo -- committing with `--no-verify` to skip the typecheck, lint, and test gate + -These hold whether or not you pass the flag. See the [hooks reference](/reference/hooks/) for the full set. +| When you're... | Reach for | Why | +| --- | --- | --- | +| The Claude integration feels off | [`/gaia-fitness`](/maintenance/fitness/) | Health-checks hooks, frontmatter, rules, and settings, then heals what it can. | +| Memory or rules have drifted | [`/gaia-audit`](/maintenance/audit/) | Finds duplication, contradictions, and stale guidance across your knowledge stores. | +| The wiki has fallen behind the code | [`/gaia-wiki`](/maintenance/wiki/) | Syncs, consolidates, and lints the project wiki Claude reads from. | +| Dependencies are stale | [`/update-deps`](/maintenance/update-deps/) | Walks outdated packages by group and runs major-version migrations. | +| A new GAIA release is out | [`/update-gaia`](/maintenance/update-gaia/) | Merges the release into your project without clobbering your changes. | ## Related - [Quick Start](/) scaffolds a new project. -- [Commands overview](/commands/) is the full catalog of `/gaia-*` commands. - [Maintenance overview](/maintenance/) covers the upkeep commands (`/gaia-fitness`, `/gaia-audit`, `/gaia-wiki`). - [Skills overview](/skills/) lists the code skills and scaffolders that trigger from plain prompts. diff --git a/src/content/docs/workflow/pickup.mdx b/src/content/docs/workflow/pickup.mdx new file mode 100644 index 0000000..8a6e035 --- /dev/null +++ b/src/content/docs/workflow/pickup.mdx @@ -0,0 +1,63 @@ +--- +title: /gaia-pickup +description: Reconstitute context in a fresh session from the most recent handoff. +sidebar: + order: 6 +--- + +import { Aside } from '@astrojs/starlight/components'; + +`/gaia-pickup` reads the most recent handoff and reconstitutes context in a fresh session. It's the resume half of the pair; [`/gaia-handoff`](/workflow/handoff/) writes the document it reads. + +## When to use it + +Run `/gaia-pickup` at the start of a fresh session, after you've cleared or restarted Claude following a [`/gaia-handoff`](/workflow/handoff/). It reads the last handoff back and tells you what changed since. + +It's a skill, so it also runs on plain-English asks like "pick up where we left off", not just the slash form. + +## Usage + +``` +/gaia-pickup +``` + +No arguments. Pickup runs through four steps: + +1. **Locate.** Find the most recent handoff: `ls -t .gaia/local/handoff/HANDOFF-*.md | head -1`. If no handoff exists, fall back to `wiki/hot.md` and report `No handoff found, resuming from hot cache.` +2. **Read.** Load the handoff in full. Run `git rev-parse --abbrev-ref HEAD`, `git status --short`, and `git log -1 --oneline` in parallel. +3. **Report.** Surface a tight status block: current branch (with drift from the handoff if any), handoff filename and date, one-line context, 1 to 3 bullets on what's done or in-flight, 1 to 3 bullets on gaps, and a suggested next action. +4. **Archive.** After you confirm a direction (pick an action, start editing, or say "go"), the consumed handoff moves to `.gaia/local/handoff/archive/`. + + + +## Drift detection + +If the handoff says branch `feat/auth` at commit `abc1234`, and current state is `main` at `def5678` with a dirty tree, pickup flags the divergence before suggesting next actions. The handoff may be stale; pickup says so explicitly rather than reconstructing context against a different reality. + +## Example + +After a [`/gaia-handoff`](/workflow/handoff/), in the fresh session: + +``` +> /gaia-pickup +``` + +Pickup reports: + +``` +Branch: feat/saved-search-filters (clean, matches handoff) +Last handoff: HANDOFF-2026-06-12-saved-search-filters.md (2026-06-12) +Context: Wired the date-range filter into the saved-search panel; empty state and tests pending. + +State: +- Filter state lifted into the useSavedSearch hook +- Active filters synced to the URL query params + +Open: +- Empty state: no message when a filter set matches zero results +- Test for the inclusive date-range boundary (end date) + +Suggested next: Add empty-state handling at @components/SavedSearchPanel.tsx:42 +``` diff --git a/src/content/docs/commands/plan.mdx b/src/content/docs/workflow/plan.mdx similarity index 98% rename from src/content/docs/commands/plan.mdx rename to src/content/docs/workflow/plan.mdx index 5341b1a..2346e2e 100644 --- a/src/content/docs/commands/plan.mdx +++ b/src/content/docs/workflow/plan.mdx @@ -11,7 +11,7 @@ Reach for `/gaia-plan` when the work spans multiple files or modules, has identi For one-line bug fixes or single-file edits, skip the planning ceremony and just edit. -For feature work that has not been clarified yet, run [`/gaia-spec`](/commands/spec/) first. It chains into `/gaia-plan` after save. +For feature work that has not been clarified yet, run [`/gaia-spec`](/workflow/spec/) first. It chains into `/gaia-plan` after save. ## How to invoke @@ -121,4 +121,4 @@ If the orchestrator was itself dispatched into an isolated subagent context, it ## Related -- [`/gaia-spec`](/commands/spec/) is the upstream of `/gaia-plan`. The chain-trigger after spec save dispatches `/gaia-plan` automatically when accepted. +- [`/gaia-spec`](/workflow/spec/) is the upstream of `/gaia-plan`. The chain-trigger after spec save dispatches `/gaia-plan` automatically when accepted. diff --git a/src/content/docs/commands/spec.mdx b/src/content/docs/workflow/spec.mdx similarity index 98% rename from src/content/docs/commands/spec.mdx rename to src/content/docs/workflow/spec.mdx index a4fc126..12da94f 100644 --- a/src/content/docs/commands/spec.mdx +++ b/src/content/docs/workflow/spec.mdx @@ -3,7 +3,7 @@ title: /gaia-spec description: Run a Socratic discovery loop and save an immutable SPEC artifact. --- -`/gaia-spec` produces an immutable SPEC artifact through a guided Socratic conversation. The artifact lands at `.gaia/local/specs/SPEC-NNN/SPEC.md` and serves as the contract for [`/gaia-plan`](/commands/plan/) to decompose into work. The skill produces an artifact and stops. It does not implement anything. +`/gaia-spec` produces an immutable SPEC artifact through a guided Socratic conversation. The artifact lands at `.gaia/local/specs/SPEC-NNN/SPEC.md` and serves as the contract for [`/gaia-plan`](/workflow/plan/) to decompose into work. The skill produces an artifact and stops. It does not implement anything. This is for when you want to implement a large feature or change request with multiple parts, or you want to present an idea or concept and refine it before implementation. @@ -13,7 +13,7 @@ The flow runs on top of [spec-kit](https://github.com/github/spec-kit), with GAI Run `/gaia-spec` for any feature where the boundaries are not yet clear. It is the right entry point when the description has more questions than answers, or when multiple readings of the same prompt produce different intents. -For changes whose intent is already obvious (a bug fix, a refactor against a known interface, a copy edit), skip directly to [`/gaia-plan`](/commands/plan/). +For changes whose intent is already obvious (a bug fix, a refactor against a known interface, a copy edit), skip directly to [`/gaia-plan`](/workflow/plan/). ## How to invoke @@ -116,4 +116,4 @@ The chain-trigger to `/gaia-plan` lives inline at step 12 of the flow, not as a ## Related -After save, [`/gaia-plan`](/commands/plan/) is the natural next step. The chain-trigger at step 12 dispatches it automatically when accepted. +After save, [`/gaia-plan`](/workflow/plan/) is the natural next step. The chain-trigger at step 12 dispatches it automatically when accepted. diff --git a/src/overrides/Header.astro b/src/overrides/Header.astro index 3e99465..64cfa3a 100644 --- a/src/overrides/Header.astro +++ b/src/overrides/Header.astro @@ -9,6 +9,7 @@ const NAV = [ { href: `${WEB}/why/`, label: 'Why GAIA' }, { href: `${WEB}/features/`, label: 'Features' }, { href: `${WEB}/about/`, label: 'About' }, + { href: `${WEB}/changelog/`, label: 'Changelog' }, { href: '/', label: 'Docs', active: true }, ]; From 6c52e155872021a91dc263562c57aec8d26bf108 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 18:10:29 +0900 Subject: [PATCH 21/25] docs: clarify react-performance intro and workflow command lead-in - Lead the react-performance page with feature and benefit, credit bippy and react-scan, plain-language the second sentence - Reword the Workflow command table lead-in to a direct imperative Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/skills/react-performance.mdx | 12 ++++++++---- src/content/docs/workflow/index.mdx | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/content/docs/skills/react-performance.mdx b/src/content/docs/skills/react-performance.mdx index c962ad8..65628be 100644 --- a/src/content/docs/skills/react-performance.mdx +++ b/src/content/docs/skills/react-performance.mdx @@ -5,10 +5,14 @@ sidebar: order: 3 --- -`react-performance` is a measure-only render-performance diagnostic. It drives one -concrete micro-interaction, captures the renders React actually performs, reduces -that capture to a small ranked summary, and reports the memo-defeating reference -instability behind an over-render along with a structural-first fix. +GAIA includes a render-performance diagnostic that finds the wasted re-renders +behind a slow interaction and names exactly what to fix. You point it at one +specific interaction, like a button click, and it singles out the component that +re-renders when it shouldn't and explains what's forcing the extra work. + +The render capture is built on [bippy](https://github.com/aidenybai/bippy), the +same library that [react-scan](https://github.com/aidenybai/react-scan) uses to +read React's internal fiber tree. It measures. It does not auto-fix. The diagnosis names the component, the unstable input, and the recommended fix; you (or Claude, in normal conversation) apply it. diff --git a/src/content/docs/workflow/index.mdx b/src/content/docs/workflow/index.mdx index 696dc34..98777cc 100644 --- a/src/content/docs/workflow/index.mdx +++ b/src/content/docs/workflow/index.mdx @@ -25,7 +25,7 @@ Notice the prompt didn't ask for a test. GAIA works test-first: for a feature or ## When to reach for a command -The `/gaia-*` commands are for specific moments, not everyday driving. These you reach for based on what you're doing: +The `/gaia-*` commands are for specific moments, not everyday driving. Reach for these based on what you're doing: | When you're... | Reach for | Why | | --- | --- | --- | From 25feff0436bed12ce4dc3c44f924f5e0168b4bea Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 18:45:52 +0900 Subject: [PATCH 22/25] docs: cut over-technical detail from adopter pages Rewrite 53 passages and remove one internal CLI section across the adopter docs so pages explain what and why, not under-the-hood mechanism. Drops internal pipeline narration, jargon, and internal variable/path/signal references; retitles the update-deps CLI section after cutting the skill-internal decline flags. Contributor pages and the hooks reference table left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/getting-started/gaia-init.mdx | 6 +++--- .../getting-started/setup-cloned-gaia-project.mdx | 4 ++-- src/content/docs/getting-started/setup-gaia-ci.mdx | 2 +- src/content/docs/index.mdx | 2 +- src/content/docs/maintenance/audit.mdx | 14 +++++++------- src/content/docs/maintenance/fitness.mdx | 8 ++++---- src/content/docs/maintenance/harden.mdx | 2 +- src/content/docs/maintenance/update-deps.mdx | 13 ++++--------- src/content/docs/maintenance/update-gaia.mdx | 2 +- src/content/docs/maintenance/wiki.mdx | 10 +++++----- src/content/docs/reference/agents.mdx | 4 ++-- src/content/docs/skills/code.mdx | 10 +++++----- src/content/docs/skills/react-performance.mdx | 13 ++++++------- src/content/docs/workflow/forensics.mdx | 4 ++-- src/content/docs/workflow/plan.mdx | 12 ++++++------ src/content/docs/workflow/spec.mdx | 12 ++++++------ 16 files changed, 56 insertions(+), 62 deletions(-) diff --git a/src/content/docs/getting-started/gaia-init.mdx b/src/content/docs/getting-started/gaia-init.mdx index 729d4dc..5cf9ea9 100644 --- a/src/content/docs/getting-started/gaia-init.mdx +++ b/src/content/docs/getting-started/gaia-init.mdx @@ -43,8 +43,8 @@ With your answers, `/gaia-init` strips the template's GAIA branding (the funding **Tools.** Per-machine, not tracked in the repo: -- [React Doctor](https://github.com/millionco/react-doctor): `npx -y react-doctor@latest install --yes`. Installs the `react-doctor` skill. Auto-runs after code edits in a `CLAUDECODE` environment and is invoked by the `code-review-audit` agent pre-merge. -- [Playwright CLI](https://github.com/microsoft/playwright-cli) binary: `npm install -g @playwright/cli@latest`. Backs the bundled `playwright-cli` skill, which shells out to it. +- [React Doctor](https://github.com/millionco/react-doctor): `npx -y react-doctor@latest install --yes`. Installs the `react-doctor` skill. Runs automatically after Claude edits code, and again before a merge as part of the `code-review-audit` check. +- [Playwright CLI](https://github.com/microsoft/playwright-cli) binary: `npm install -g @playwright/cli@latest`. The bundled `playwright-cli` skill runs through it. - [Serena](https://github.com/oraios/serena) MCP server, registered globally for your Claude Code: ```bash @@ -94,7 +94,7 @@ GAIA ships with a built-in [wiki](/maintenance/wiki/) that Claude maintains as i ## After gaia-init completes -Init marks per-machine setup complete, removes the one-time `/init` interceptor, prunes the matching entry from `.claude/settings.json`, and deletes its own command file. Then it prints: +Init marks the per-machine setup complete and cleans up its own one-time setup files. Then it prints: ``` is ready for development. To pick up the new plugin and skill state, exit Claude, then from your terminal: diff --git a/src/content/docs/getting-started/setup-cloned-gaia-project.mdx b/src/content/docs/getting-started/setup-cloned-gaia-project.mdx index 6c4d9fc..01492c9 100644 --- a/src/content/docs/getting-started/setup-cloned-gaia-project.mdx +++ b/src/content/docs/getting-started/setup-cloned-gaia-project.mdx @@ -20,7 +20,7 @@ The command is idempotent. Re-running it after a partial run picks up from the f ### Pre-step: worktrees -If you set up the clone from a git worktree created outside Claude Code, the command first restores the shared-state symlinks the worktree needs. In a normal checkout this does nothing. +If you set up the clone from a git worktree created outside Claude Code, the command first reconnects the shared files the worktree needs. In a normal checkout this does nothing. ### Pre-step: pnpm and node_modules @@ -71,7 +71,7 @@ If the project uses the pre-merge `code-review-audit` gate, you choose who runs Your choice adds a one-line entry to `.gaia/audit-ci.yml`. You commit and open the one-line PR yourself; the command prints the exact `git` and `gh` commands to run and never commits or opens the PR for you. -If `gh` is not authenticated when this step runs, the choice is skipped and the step is recorded as done, so a later plain re-run will not prompt for it again. To set or change your audit mode afterward, add your `=` entry to `audit_authors` in `.gaia/audit-ci.yml`. +If `gh` is not authenticated when this step runs, the prompt is skipped and will not reappear on a plain re-run. To set or change your audit mode afterward, add your `=` entry to `audit_authors` in `.gaia/audit-ci.yml`. ### 5. Finish diff --git a/src/content/docs/getting-started/setup-gaia-ci.mdx b/src/content/docs/getting-started/setup-gaia-ci.mdx index 50860be..efefc4f 100644 --- a/src/content/docs/getting-started/setup-gaia-ci.mdx +++ b/src/content/docs/getting-started/setup-gaia-ci.mdx @@ -38,7 +38,7 @@ The command reads `origin` and confirms it points to `github.com`. Non-GitHub re ### 2. Duplicate tool detection -If Dependabot or Renovate is detected, the command warns that GAIA's update-deps workflow (the warning calls it GAIA Sharpen) covers the same package ecosystems (npm, pnpm) and will open duplicate PRs if both run in parallel. You can disable the overlap before continuing or cancel and re-run later. The command does not disable either tool automatically. +If Dependabot or Renovate is detected, the command warns that GAIA's update-deps workflow (the warning calls it GAIA Sharpen) covers the same packages (npm and pnpm) and will open duplicate PRs if both run in parallel. You can disable the overlap before continuing or cancel and re-run later. The command does not disable either tool automatically. ### 3. Enable / defer / opt out diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index c0ec860..9f17576 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -10,7 +10,7 @@ One command scaffolds the GAIA React framework and automatically launches Claude - Node 22.19 or later. Check with `node --version`. - Claude Code installed and reachable as `claude`. -`pnpm` is not required up front. When `pnpm install` runs (the default), `create-gaia` bootstraps pnpm via Corepack if missing, falling back to `npm install -g pnpm`. With `--no-install`, no bootstrap is attempted. +`pnpm` is not required up front. If `pnpm install` runs (the default) and pnpm is missing, `create-gaia` installs it for you. With `--no-install`, it installs nothing. `uv` is required for the Serena MCP server. GAIA will install it for you during setup if you don't already have it. diff --git a/src/content/docs/maintenance/audit.mdx b/src/content/docs/maintenance/audit.mdx index 8ca58ad..d6e060e 100644 --- a/src/content/docs/maintenance/audit.mdx +++ b/src/content/docs/maintenance/audit.mdx @@ -92,11 +92,11 @@ Anything over budget is flagged with a proposed fix: inline facts moved to the w ## The two-stage flow -**Stage 1: research (Sonnet).** Reads the stores, classifies entries, computes budgets, and writes a report to `.gaia/local/audit/KNOWLEDGE-{YYYY-MM-DD-HHMM}.md` with `status: draft`. It snapshots `git status --short` and `git rev-parse HEAD` into the report's frontmatter so the apply stage can detect drift. It mutates nothing outside `.gaia/local/audit/`. +**Stage 1: research (Sonnet).** Reads the stores, classifies entries, computes budgets, and writes a report to `.gaia/local/audit/KNOWLEDGE-{YYYY-MM-DD-HHMM}.md` with `status: draft`. It records the repo's current state so the apply stage can tell whether anything changed before it runs, and it writes nothing outside `.gaia/local/audit/`. -**Stage 2: apply (Sonnet).** Reads the most recent unfinished report, re-resolves the project root and memory directories, and stops with a clear error if they differ from the report's frontmatter (the report was generated on another machine or clone). It verifies each action's drift signal, applies the action verbatim or skips it with a recorded reason, then verifies the result landed. The apply stage runs on Sonnet because it makes coordinated multi-file edits where a wrong move can delete the only copy of an entry. +**Stage 2: apply.** Reads the most recent unfinished report and stops with a clear error if it was generated on another machine or clone. For each action it checks that the file still matches what the report saw, applies it or skips it with a recorded reason, then confirms the change landed. -The two-stage split is technical (the stages carry different reasoning loads, with a drift check between them). The user-confirmation checkpoint is the single decision gate, not the stage boundary. +The split into two stages is internal. The only point where you decide anything is the single gate above. ## Action types @@ -107,7 +107,7 @@ The two-stage split is technical (the stages carry different reasoning loads, wi | `promote` | Move durable knowledge from memory to a named wiki page. Performs the target action (`append_section`, `insert_after_heading`, or `create_new`), prepends a log entry to `wiki/log.md`, appends an index entry to `wiki/index.md`, then deletes the source if the action says to. | | `replace` | Shrink inline content in an autoloaded file to a wikilink, or swap a contradicting line for the canonical value. The current block must match byte-for-byte. In report output and action IDs this type shows as `shrink` (for example `shrink-001`). | -The apply stage runs actions in order: `shrink` → `delete-entry` → `promote` → `delete`. Earlier shrinks never reference content that later actions touch; deletes come last so pointers do not go stale before they are used. Contradiction findings reuse `replace` and `delete`; there is no separate action type for them. +The apply stage runs the actions in a safe order, so a delete never removes something another action still needs. ## Report lifecycle and resume @@ -127,7 +127,7 @@ When you run `/gaia-audit --apply`, the apply stage checks the report's age on a - 24 to 72 hours old: proceed with a warning that drift checks will catch any staleness. - Over 72 hours old: stop, and ask you to run a fresh audit. -The wall clock is a coarse guard. The real safety is the per-action drift check (SHA-256 plus verbatim snippets), which catches any file that changed since the report regardless of age. +The age check is only a rough guard. The real protection is the per-action check that compares each file against what the report saw, so any file that changed is caught regardless of age. ## Drift handling @@ -138,7 +138,7 @@ Each action ships with a drift signal: either `expect_sha256` (file-level) or a - Error during apply: flip to `[!]` with the error. - Target missing: `[!]` with `target missing`. -Files dirty in git that appear as targets are marked `SKIP (dirty)` before any action runs. Dirty-file protection is preventive, not diagnostic. +If a target file has uncommitted changes, the audit skips it and marks it `SKIP (dirty)` before any action runs. ## After the run @@ -156,7 +156,7 @@ GAIA surfaces `Run /gaia-audit ()` in the statusline when any of three c - `machine drift`: machine-local memory has grown by 10 or more entries, or 30 or more days have passed since the last applied audit. - `over budget`: an autoloaded file is over budget (`wiki/hot.md` over 200 words, root `CLAUDE.md` over 400 words, or any `.claude/rules/*.md` over 200 lines). -The nudge is suppressed inside git worktrees and is computed in a cached background refresher, never on the statusline's render path. All thresholds are tunable. +The nudge is suppressed inside git worktrees. All thresholds are tunable. ## Related diff --git a/src/content/docs/maintenance/fitness.mdx b/src/content/docs/maintenance/fitness.mdx index f7fc00f..158dd3e 100644 --- a/src/content/docs/maintenance/fitness.mdx +++ b/src/content/docs/maintenance/fitness.mdx @@ -35,7 +35,7 @@ Triage dispatches seven category checks in parallel. Each produces a set of find | GAIA-install fitness | Drift between GAIA-managed files and the contents the installed version shipped, plus whether a newer GAIA release is available. | | Wiki fitness | Wiki state-file staleness, orphan pages, and dead path references in wiki prose. | -The checks are recall-oriented and over-flag on purpose. Before grading, `/gaia-fitness` adjudicates each finding against the actual repo and drops the false positives (an unfamiliar-but-valid hook event, a permission pair that only looks redundant, and so on). What survives gets graded. +The checks over-flag on purpose. Before grading, `/gaia-fitness` adjudicates each finding against the actual repo and drops the false positives (an unfamiliar-but-valid hook event, a permission pair that only looks redundant, and so on). What survives gets graded. ## Grading @@ -54,7 +54,7 @@ An `A` means only advisory `info` findings remain. They surface in the FINDINGS **Triage.** Run the seven checks, adjudicate the findings, compute the grades. Each surviving finding is then classified as fixable (a mechanical edit a fixer can apply confidently without product context: a missing frontmatter field, a bad path, a `.gitignore` line) or unfixable (needs product context or invasive restructuring: splitting an oversized `CLAUDE.md`, rewriting a rule's scope, reworking hook logic). -**Heal.** Fixable findings get repaired by lane-aware fixers running in parallel, one lane per surface area (`.claude/` surface and `CLAUDE.md`; `.claude/settings.json`; `.gitignore`; `.gaia/manifest.json`). Healing runs inside a bounded loop, three cycles by default. After each cycle the affected checks re-run; if a finding survives a fix attempt unchanged, the loop stops chasing it and marks it unresolved. A fixer that judges a repair too invasive to apply without product context leaves it alone and surfaces it in the report with a recommended approach. **Nothing is ever committed.** The working tree is left for you to review. +**Heal.** Fixable findings get repaired automatically. GAIA retries each fix a few times, and if a finding does not clear, it stops and marks it unresolved. A fixer that judges a repair too invasive to apply without product context leaves it alone and surfaces it in the report with a recommended approach. **Nothing is ever committed.** The working tree is left for you to review. **Verify.** After each heal cycle the affected category checks re-run and the grades recompute. If the overall grade reaches A+, the loop exits clean. @@ -72,7 +72,7 @@ Before any heal-phase change, `/gaia-fitness` checks whether the repo is safe to ## After the run -`/gaia-fitness` renders the result as a deterministic width-aware ASCII card, produced by `gaia fitness render-card`. The card is pasted directly into the chat reply as a fenced code block. +`/gaia-fitness` shows the result as a text card right in the chat reply. The card has three sections: @@ -82,7 +82,7 @@ The card has three sections: On a clean run (zero adjudicated findings, overall A+), the FINDINGS block is omitted. The card shows only the header and category rows, all graded A+. -The card self-sizes. The box width tracks the longest content line, capped at 120 columns or the terminal width (whichever is smaller) and floored wide enough to keep the category names and grades from colliding. Remediation text wraps to fit. +The card sizes itself to fit your terminal, and long remediation text wraps. Then, depending on what happened: diff --git a/src/content/docs/maintenance/harden.mdx b/src/content/docs/maintenance/harden.mdx index 7e9caa7..3ce9dee 100644 --- a/src/content/docs/maintenance/harden.mdx +++ b/src/content/docs/maintenance/harden.mdx @@ -46,7 +46,7 @@ The `code-review-audit` agent tags each eligible finding with a stable `finding_ - within a rolling **90-day window**, and - no promoted rule already covers it, and the decline ledger does not suppress it. -The tally is recomputed from GitHub PR data via `gaia harden-tally` each time you invoke `/gaia-harden`. It is an ephemeral projection: an unacted pattern decays by ageing out of the window. +The list is recomputed from your merged PRs each time you run `/gaia-harden`. A pattern you never act on drops off once it ages past the 90-day window. ## Judge-the-form logic diff --git a/src/content/docs/maintenance/update-deps.mdx b/src/content/docs/maintenance/update-deps.mdx index 728b47b..239e7ba 100644 --- a/src/content/docs/maintenance/update-deps.mdx +++ b/src/content/docs/maintenance/update-deps.mdx @@ -46,14 +46,9 @@ After grouping, updates are classified into two waves: - **Wave A**: minor and patch bumps, bundled into one install. - **Wave B**: major-version bumps, each group processed individually with its own migration guide and code edits. -## The CLI primitives behind it +## Manual and scheduled runs agree -The deterministic parts (discovering outdated packages, applying the group rules, and classifying each group into Wave A or B) run through the bundled CLI: `gaia update-deps run --emit-updates ` writes the grouped, wave-classified set to a JSON file. The skill calls it for those steps and layers the preview, migrations, and quality gate on top. The same primitive backs the `gaia-ci-update-deps` workflow that [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/) can install, so scheduled and interactive runs agree on what is outdated. - -`gaia update-deps decline` manages the snooze ledger: - -- `--source --skip `: record the named groups as snoozed. Accepts either a group name (e.g. `react-router`) or any member package name; both resolve to the whole group. -- `--clear`: empty the ledger (used automatically when you choose "Update all"). +Discovering outdated packages, grouping them, and sorting them into waves work the same way whether you run `/update-deps` yourself or let the `gaia-ci-update-deps` workflow from [`/setup-gaia-ci`](/getting-started/setup-gaia-ci/) run it on a schedule, so both agree on what is outdated. ## Override audit @@ -88,7 +83,7 @@ For major-version bumps, the skill makes one remediation pass if the quality gat - Must run from the main checkout, not a linked worktree. The skill rejects worktree invocations early and surfaces the cached outdated count from main so you know whether action is even pending. - On `main` or `master`, the skill creates `chore/update-deps-` and opens a PR after updates apply. On any other branch, it runs in place and pushes without opening a PR. -- The final report is built from agent-returned data only. Anything filtered before installation (the ESLint cap) is silent on purpose. -- `actionable_count` in the statusline already subtracts snoozed groups; the skill uses `total_count` internally for the actual apply set. +- The final report only lists what was actually installed. Anything filtered out beforehand is left off on purpose. +- The statusline count already leaves out snoozed groups. Source: `.claude/skills/update-deps/SKILL.md`. diff --git a/src/content/docs/maintenance/update-gaia.mdx b/src/content/docs/maintenance/update-gaia.mdx index 71e5884..544e45b 100644 --- a/src/content/docs/maintenance/update-gaia.mdx +++ b/src/content/docs/maintenance/update-gaia.mdx @@ -34,7 +34,7 @@ The three-way merge is governed by ownership classes defined in `.gaia/manifest. 2. Resolves the latest release tag via `gh release list --repo gaia-react/gaia` (falls back to the GitHub API). 3. Shows the release notes and asks you to confirm. 4. Downloads the baseline and latest tarballs into `.gaia/cache/` (gitignored). -5. Runs the three-way merge per file directly (no CLI subcommand). Owned files are overwritten or conflict-patched; shared and wiki-owned files are merged or conflict-patched. `package.json`, `pnpm-workspace.yaml`, and `.gaia/audit-ci.yml` are all classed `shared` but receive field-aware key-level merges rather than whole-file patches (see below). +5. Runs the three-way merge per file directly. Owned files are overwritten or conflict-patched; shared and wiki-owned files are merged or conflict-patched. `package.json`, `pnpm-workspace.yaml`, and `.gaia/audit-ci.yml` are all classed `shared` but receive field-aware key-level merges rather than whole-file patches (see below). 6. Walks any conflicts with you one at a time; reads `.gaia-merge/.patch` for each. 7. For `pnpm-workspace.yaml`, uses `gaia update merge-workspace` to compute per-key verdicts. This is a field-aware merge of both the GAIA-managed settings keys and the `overrides` and `allowBuilds` maps. Overrides and build approvals live here (pnpm 11 no longer reads them from `package.json`); an adopter-only entry is never visited or clobbered. For `.gaia/audit-ci.yml`, uses `gaia update merge-audit-ci` to compute per-key and per-author-entry verdicts. 8. Prompts before deleting any file that the latest release removed. diff --git a/src/content/docs/maintenance/wiki.mdx b/src/content/docs/maintenance/wiki.mdx index fb34b1a..7d5cb46 100644 --- a/src/content/docs/maintenance/wiki.mdx +++ b/src/content/docs/maintenance/wiki.mdx @@ -47,7 +47,7 @@ There are three main commands, plus a full-chain mode that runs them in sequence Walks every commit between the wiki's last evaluated SHA and HEAD. For each commit, decides whether the wiki needs an update. Edits pages, logs decisions, advances state. -The classifier runs in two passes. The first pass classifies commits as `WORTHY` or `SKIP` deterministically (subject patterns, file patterns, file count). The second pass reads the diff for `WORTHY` commits only and edits the affected wiki pages. +It first decides which commits are worth recording, then reads the diffs of those commits and updates the affected wiki pages. State lives in `wiki/.state.json`: @@ -55,13 +55,13 @@ State lives in `wiki/.state.json`: - `last_evaluated_at`: when that classification ran. - `last_consolidated_sha` and `last_consolidated_at`: owned by consolidate. Sync preserves them. -On the very first sync, if `last_consolidated_sha` is absent, sync seeds it so the consolidate gate has a baseline to accumulate from. Consolidate owns every update after that. +On the first run, consolidate's starting point gets set up; after that, consolidate maintains it. If drift exceeds 30 commits, sync asks before processing the full range. You can opt to sync the recent 20 only and re-anchor. Run standalone, sync commits its own work. On `main` or `master` it cuts a `wiki-sync/-` branch and opens a pull request; on a feature branch it commits in place. In the full chain the branch is cut once up front and every stage commits onto it (see Full chain below). -Sync ends with a one-line trigger: `CONSOLIDATE_TRIGGERED: true|false`. Used by the full-chain mode to decide whether consolidate runs next. +When run as part of the full chain, sync signals whether consolidate needs to run next. ## /gaia-wiki consolidate @@ -69,7 +69,7 @@ Detects redundancy and contradiction across the wiki. Four passes: - **Same-subject across SPECs.** Pairs of pages in the same domain that share a title and were promoted from different SPECs at least 30 days apart. The newer page is canonical; the older becomes a supersession candidate. - **Reversed decisions.** Decision pages whose body negates an older decision page (`replaces`, `supersedes`, `deprecated in favor of`, etc.). The older page is flagged for retirement. -- **Near-collision slugs.** Pairs within Levenshtein distance 2, or where one slug is a prefix of the other. +- **Near-duplicate page names.** Names that differ by only a character or two, or where one name is the start of another. - **Subject-orphaned pages.** Pages with zero inbound wikilinks, no body-title matches in `wiki/concepts/` or `wiki/modules/`, and no edits in 90 days. For each finding, consolidate prompts you per finding: `Apply`, `Keep both`, or `Skip`. `Apply` performs the merge or retire action. `Keep both` writes a `consolidation_ack` flag on the canonical page so the finding does not re-surface. `Skip` defers to the next run. @@ -78,7 +78,7 @@ Consolidate does not commit. Applied edits stage; sync (or your manual commit) l ## /gaia-wiki lint -Standalone GAIA-native health check. Each check re-derives on every run, most from a dedicated `gaia wiki` CLI primitive, and the report is plain markdown GAIA owns end to end. The current checks: +A standalone health check. Every check recomputes from scratch on each run, and the report is plain markdown. The current checks: - **#11 Wiki drift check.** Reports how many commits behind HEAD the wiki is. Severity: `none`, `low`, `medium`, `high`. High severity surfaces with a `WIKI DRIFT:` prefix. - **#12 Dead repo-relative paths.** Backticked paths in wiki body prose that no longer exist on disk (e.g. a hook removed in a refactor still cited in a concept page). diff --git a/src/content/docs/reference/agents.mdx b/src/content/docs/reference/agents.mdx index 8f16740..2013388 100644 --- a/src/content/docs/reference/agents.mdx +++ b/src/content/docs/reference/agents.mdx @@ -30,9 +30,9 @@ Comprehensive code review, security audit, performance analysis, and architectur - **Accessibility**: keyboard reachability, semantic HTML, focus management, ARIA usage. - **Maintainability**: magic values, dead code, coupling, comment quality. -The review runs in two phases. In the first phase, the main agent surfaces every candidate finding tagged with severity and confidence (coverage-first: low-confidence candidates are surfaced, not silently dropped). In the second phase, each surviving Critical or Important holistic finding is handed to a fresh-context refuter subagent; the refuter overturns a finding only with concrete counter-evidence (a specific guard, a test, or a demonstration that the failure path is unreachable). The report is not written until the adversarial pass completes. +The review runs in two phases. First it surfaces every candidate finding tagged with severity and confidence, keeping low-confidence ones rather than dropping them. Then each Critical or Important finding is double-checked by a fresh subagent that overturns it only with concrete counter-evidence, like a specific guard, a test, or proof the failure path can't be reached. The report waits until that second pass finishes. -The main agent owns every spawn: specialist subagents (React patterns, TypeScript / architecture, translation), oracle tools (`react-doctor`, `pnpm knip --reporter json`, `pnpm audit --json`), and the per-finding refuters. None of these spawn further (depth-1 star topology). The `pnpm audit` pass is the Dependency-CVE advisory: it reports high and critical findings for you to decide on and never blocks the audit marker or `gh pr merge`. See the `dep-audit` rule. +The main agent runs the whole review: specialist subagents (React patterns, TypeScript / architecture, translation), supporting tools (`react-doctor`, `pnpm knip --reporter json`, `pnpm audit --json`), and the per-finding refuters. None of these spawn further subagents of their own. The `pnpm audit` pass is the Dependency-CVE advisory: it reports high and critical findings for you to decide on and never blocks the audit marker or `gh pr merge`. See the `dep-audit` rule. Per-phase progress breadcrumbs (scope resolved, oracles done, holistic review done, adversarial verify done, report stamped) are written to `.gaia/local/audit/progress.log` and surfaced in the GitHub Actions step summary. diff --git a/src/content/docs/skills/code.mdx b/src/content/docs/skills/code.mdx index 3e9a38b..462d05a 100644 --- a/src/content/docs/skills/code.mdx +++ b/src/content/docs/skills/code.mdx @@ -19,7 +19,7 @@ Source: `.claude/skills/typescript/SKILL.md`. ## React Code -Conventions for React components, pages, routes, hooks, and forms. Includes pre-flight gates for `useEffect`, `useCallback`, and `useState`; a form-element check that swaps native `` for the project's `Form/*` components; a translation gate that requires every user-visible string to come from `t()` (exception: approximate skeleton-loader placeholders standing in for dynamic runtime values stay hardcoded; static skeleton text that mirrors a real `t()` call must still use `t()`); and a React 19 idiom check that enforces `ref` as an ordinary prop (no `forwardRef`), `use()` over `useContext`, `` shorthand over ``, guarding the `&&` numeric-0 leak in JSX, and staying in React Router's form handling instead of reaching for `useActionState`, `useFormStatus`, or `useOptimistic`. Covers component extraction thresholds and route/page architecture (`app/routes/` thin shells, `app/pages/` for UI). +Conventions for React components, pages, routes, hooks, and forms. Includes checks for `useEffect`, `useCallback`, and `useState`; a form-element check that swaps native `` for the project's `Form/*` components; a translation check that requires every user-visible string to come from `t()`; and a React 19 idiom check that enforces `ref` as an ordinary prop (no `forwardRef`), `use()` over `useContext`, `` shorthand over ``, guarding the `&&` numeric-0 leak in JSX, and staying in React Router's form handling instead of reaching for `useActionState`, `useFormStatus`, or `useOptimistic`. Covers component extraction thresholds and route/page architecture (`app/routes/` thin shells, `app/pages/` for UI). Before adding a dependency or hand-rolling a primitive, the skill walks a platform-first ladder: existing GAIA code, then browser-native APIs (`Intl`, `URL`, `crypto.randomUUID()`, `structuredClone()`, modern CSS), then an already-installed dependency, then a new dependency, then custom code as a last resort. It stops at the first rung that fits. The biggest practical savings come from `Intl` standing in for date and number formatting libraries and native collection methods standing in for utility libraries, both already enforced by lint. @@ -31,7 +31,7 @@ Source: `.claude/skills/react-code/SKILL.md`. ## React Performance -A measure-only diagnostic that drives a micro-interaction, captures real React renders, and surfaces memo-defeating reference instability with a recommended structural fix. It diagnoses, it does not auto-fix. See [React performance](/skills/react-performance/) for the full capture-reduce-diagnose-verify workflow. +You point it at one specific interaction, like a button click, and it finds the component that re-renders when it shouldn't and explains what's forcing the extra work. It diagnoses, it does not auto-fix. See [React performance](/skills/react-performance/) for the full capture-reduce-diagnose-verify workflow. **Triggers** on explicit render-performance asks: "profile renders", "measure renders", "why is X re-rendering", or "diagnose render performance". Does NOT trigger on vague "feels slow" or "janky". Requires a concrete micro-interaction target (a button click or local state change on a specific page), not a page navigation or "the whole app". @@ -71,11 +71,11 @@ Based on Matt Pocock's excellent [TDD Skill](https://www.aihero.dev/skill-test-d Test-driven development with a vertical-slice red-green-refactor loop. Treats horizontal slicing (write all tests first, then all code) as an antipattern. Tests verify behavior through public interfaces, not implementation details. Includes a per-cycle checklist and a planning step that asks for the public interface before writing the first red test. -After tests go green, a determinism classifier sorts each touched file and scopes the failing-first (RED) requirement to the deterministic surface only: pure utilities, service parsers, and spec-derivable hooks. Component and Playwright tests are treated as emergent and commit without a RED gate, since environment and DOM state make a stable failing run impossible to guarantee. +The failing-test-first (RED) requirement applies only where a test can reliably fail first: pure utilities, service parsers, and hooks. Component and Playwright tests skip it, since their environment and DOM state can't guarantee a clean failing run. -For tests on that emergent surface, the skill dispatches a fresh-context evaluator that reviews each one for honesty and worthiness and returns a keep, fix, or delete verdict. Fixes for dishonest tests, like a test coupled to implementation detail or one asserting a tautology, apply automatically as ordinary edits for review. Delete proposals need your confirmation and show their evidence inline, so you decide without opening files. Everything lands in a single end-of-task summary. +For those component and Playwright tests, the skill reviews each one for honesty and worthiness and returns a keep, fix, or delete verdict. Fixes for dishonest tests, like a test coupled to implementation detail or one asserting a tautology, apply automatically as ordinary edits for review. Delete proposals need your confirmation and show their evidence inline, so you decide without opening files. Everything lands in a single end-of-task summary. -New components scaffolded with `new-component` start with a non-degenerate accessibility test that renders a real instance, so it can fail against an actual violation instead of passing against an empty DOM. +New components scaffolded with `new-component` start with an accessibility test that renders a real instance, so it can catch a real violation instead of passing against an empty DOM. It is automatically used by Claude when working in GAIA projects. diff --git a/src/content/docs/skills/react-performance.mdx b/src/content/docs/skills/react-performance.mdx index 65628be..1ed1085 100644 --- a/src/content/docs/skills/react-performance.mdx +++ b/src/content/docs/skills/react-performance.mdx @@ -38,17 +38,16 @@ don't name a target, the skill asks for one before proceeding. ## The workflow -The diagnostic separates a token-heavy raw capture from the small summary the -model reasons over. The raw dump (roughly 172 KB, about 43K tokens for a trivial +The diagnostic writes a large raw capture to disk, then reduces it to a small +summary. The raw dump (roughly 172 KB, about 43K tokens for a trivial flow) never enters the conversation. Only the reduced summary is read. ### 1. Capture The skill writes a short, temporary Playwright spec that drives your target interaction using the committed capture helper at `.playwright/react-perf/capture.ts`. -The helper injects a render-instrumentation harness before React initializes, -collects each rendered fiber, and writes the raw dump to -`.gaia/local/cache//renders.json`. +The helper records every render your interaction triggers and writes the raw data +to `.gaia/local/cache//renders.json`. ```ts import {expect, test} from '@playwright/test'; @@ -92,8 +91,8 @@ summary: `gaia react-perf reduce `. The `gaia` binary resolves through the project's package bin, so the skill runs it for you; you don't type it into a separate terminal. -The reduce filters framework noise, recomputes the signal, ranks findings, applies -a frame-budget timing gate, and prints a `ReducedSummary` as JSON on stdout. The +The reduce drops framework noise, ranks the findings, and prints a `ReducedSummary` +as JSON. The frame budget defaults to 16ms; pass `--frame-budget-ms ` to change the timing gate. Malformed input prints a structured error and exits non-zero. That summary is the only thing the skill ingests. diff --git a/src/content/docs/workflow/forensics.mdx b/src/content/docs/workflow/forensics.mdx index 24eb658..e5002d3 100644 --- a/src/content/docs/workflow/forensics.mdx +++ b/src/content/docs/workflow/forensics.mdx @@ -35,7 +35,7 @@ Forensics runs in nine read-only steps: 1. **Capture.** Reads a fixed set of state files: GAIA version, Node, pnpm, Claude Code version, branch, dirty status, plus class-specific state files (different per failure category). Bodies from `app/` and `wiki/` are never captured. `.env*` and `node_modules/` are excluded. Long files are truncated. 2. **Classify.** Walks a fixed taxonomy of eight classes (`init`, `update`, `wiki-sync`, `quality-gate`, `hook`, `scaffold`, `dev-server`, `other`) and matches signal phrases against your description. Cites the matched phrase and named state file as evidence. 3. **Diagnose.** Decides whether the failure is a user-config issue (wrong Node version, missing env var, dirty working tree blocking a workflow) or a probable bug. User-config wins when both signals fire: the environment is the more likely cause. -4. **Redact.** Runs the assembled report body through one redaction pass: project-root strip, machine-leak fallback, seven token-pattern sweeps, env-var value scrub, then a sanity recheck. If a credential-shaped string survives the recheck, forensics halts rather than emitting a partially redacted body. +4. **Redact.** Strips secrets and machine-specific paths out of the report, then double-checks the result. If anything that still looks like a credential gets through, forensics stops instead of writing a report that could leak it. 5. **Render.** Emits a strict-schema report with frontmatter (class, GAIA version, created date, optional issue URL) and four fixed sections: `## Symptom`, `## Classification`, `## Capture`, `## Reproduction context`. 6. **Save.** Writes to `.gaia/local/forensics/-.md`. The timestamp is ISO-8601 compact UTC. 7. **Branch on diagnosis.** User-config failures: prints remediation steps inline, exits. Probable bugs: continues to the issue-filing offer. @@ -44,7 +44,7 @@ Forensics runs in nine read-only steps: ## Strict body schema -The report body has fixed section headers and order. Phase-2 automation parses these without LLM fallback, so the schema is load-bearing: +The report body has fixed section headers and order. The fixed headers and order keep filed reports consistent and easy to triage: ```markdown --- diff --git a/src/content/docs/workflow/plan.mdx b/src/content/docs/workflow/plan.mdx index 2346e2e..58f3a9d 100644 --- a/src/content/docs/workflow/plan.mdx +++ b/src/content/docs/workflow/plan.mdx @@ -35,7 +35,7 @@ If you invoke `/gaia-plan` with no description, it asks for one before continuin .gaia/local/plans// ``` -The slug derives from the description. When invoked from a SPEC, the slug is prefixed with the SPEC id (e.g. `spec-005-cards-layout`) so plan-to-SPEC discovery is a one-line `ls .gaia/local/plans/ | grep ^spec-005-`. Slug collisions append `-2`, `-3`, and so on, so parallel invocations coexist without overwriting each other. +The slug derives from the description. When invoked from a SPEC, the slug is prefixed with the SPEC id (e.g. `spec-005-cards-layout`) so you can tell at a glance which plan came from which spec. If two plans would share a slug, GAIA appends `-2`, `-3`, and so on, so running several at once never overwrites either. Inside the directory: @@ -52,8 +52,8 @@ Inside the directory: 1. **Description capture.** If `$ARGUMENTS` is empty, the skill asks. If a SPEC reference is detected, the SPEC itself becomes the source of truth and the dispatch summary is just a label. 2. **Model check.** If the current session is not on Opus, the skill offers to spawn the planning agent on Opus. Plans benefit from the higher-capacity model. 3. **Plan directory resolution.** Slug is derived (or seeded from the SPEC id), suffixed on collision, then created under `.gaia/local/plans/`. -4. **Planner dispatch.** The skill spawns a `general-purpose` Agent restricted to writing inside the plan directory only. The planner reads `wiki/concepts/Task Orchestration.md` for the orchestration pattern, then writes the plan files directly to disk. -5. **Verification.** The skill confirms `README.md`, `ORCHESTRATOR.md`, `KICKOFF.md`, and at least one `task-*.md` exist. If anything is missing, the failure surfaces; no silent retry. +4. **Planner dispatch.** A planning agent writes the plan files, and only ever writes inside the plan directory. +5. **Verification.** The skill checks that the core plan files were written. If any are missing, it surfaces the problem instead of guessing. 6. **Decomposition audit.** For non-trivial plans, the skill offers to stress-test the decomposition before hand-off, and running it is the recommended choice. See [Decomposition audit](#decomposition-audit). 7. **Hand-off.** The skill prints a short summary of the plan directory, then the kickoff prompt as a fenced code block you select and copy yourself. The trailing line reads `Type /clear and paste the prompt above.` @@ -89,7 +89,7 @@ The orchestrator merges sub-agent notes into `SUMMARY.md` after every phase, so ## Pre-merge audit -Before any `gh pr merge` invocation, the orchestrator spawns the `code-review-audit` agent against the current branch. If the audit reports critical or unresolved important issues, the orchestrator stops and surfaces them. A clean pass writes a marker that a deny-hook reads to gate `gh pr merge`. The orchestrator does not wait for the deny-hook to fire; it spawns the agent proactively. +Before any `gh pr merge` invocation, the orchestrator spawns the `code-review-audit` agent against the current branch. If the audit reports critical or unresolved important issues, the orchestrator stops and surfaces them. The merge stays blocked until that audit passes clean. ## Branch policy @@ -115,9 +115,9 @@ Execution is the part that can actually clash, since two orchestrators editing t ## Worktree mode (experimental) -If the orchestrator chose worktree mode at branch policy, the post-merge phase confirms the merge via `gh pr view --json state`, then calls `ExitWorktree({action: "remove", discard_changes: true})`. The merged-state confirmation is the primary signal that the work is preserved; `discard_changes: true` is correct because squash-merge produces unreachable commits on the worktree branch. +If the orchestrator ran in worktree mode, it waits until the PR shows as merged, then removes the worktree. It confirms the merge first so your work is safely on the PR before the isolated copy goes away. -If the orchestrator was itself dispatched into an isolated subagent context, it cannot call `ExitWorktree` directly. It instead emits a copy-paste continuation prompt naming the absolute worktree path and the merged-state details, then stops. The user pastes that prompt into a fresh top-level session to complete the cleanup. +If the orchestrator was running inside an isolated subagent, it can't remove the worktree itself. Instead it stops and hands you a copy-paste prompt with the worktree path. Paste that into a fresh session to finish the cleanup. ## Related diff --git a/src/content/docs/workflow/spec.mdx b/src/content/docs/workflow/spec.mdx index 12da94f..41944f6 100644 --- a/src/content/docs/workflow/spec.mdx +++ b/src/content/docs/workflow/spec.mdx @@ -39,7 +39,7 @@ A description is required in auto mode. Without one, the skill aborts immediatel The SPEC has two gates and they are non-negotiable. -**Gate 1: shape confirmation.** Before any clarifying question fires, the skill presents the proposed `intent` paragraph and the proposed UATs in plain English. The user reads, confirms, or revises. On confirmation, the gate-1 shape is snapshotted to `.gaia/local/cache/gate1-.json` and treated as immutable for the remainder of the session. The self-review before gate 2 detects drift against this snapshot. +**Gate 1: shape confirmation.** Before any clarifying question fires, the skill presents the proposed `intent` paragraph and the proposed UATs in plain English. The user reads, confirms, or revises. Once you confirm, that shape is locked for the rest of the session, and a later self-review checks the spec hasn't drifted from what you agreed to. **Gate 2: artifact confirmation.** After the Socratic loop and self-review apply, the full rendered SPEC is presented to the user one last time. Revisions loop until the user confirms. Only then does the canonical save fire. @@ -49,9 +49,9 @@ Once saved, the SPEC artifact is immutable. Mutations require an explicit reopen A handful of mechanics are used by multiple steps: -- **Working-draft cache.** Every fold in the Socratic loop, every gate confirmation, every research result, every self-review apply, and every audit-finding apply persists the in-flight draft to `.gaia/local/cache/draft-.md`. A single `Write` per turn. No incremental `Edit` calls. Step 10's canonical save deletes the cache as its final action. Resumed sessions pick up the cache if it is newer than the canonical artifact. +- **Working-draft cache.** As you go, the in-progress spec is saved to `.gaia/local/cache/draft-.md` so nothing is lost if you stop partway. The final save deletes the cache. If you resume later, the spec picks up from that draft. - **Per-topic revisit counter.** Tracks how many times the user has chosen "push deeper" on a given topic. On the third revisit, the prompt swaps to settle, defer, or push deeper anyway. Prevents one topic from consuming the whole session. -- **Five-question cap.** Spec-kit's `/clarify` primitive caps the loop at five total questions per session. The wrapper inherits this cap and never invokes `/clarify` twice to extend it. +- **Five-question cap.** The clarify loop asks at most five questions per session, so a spec never turns into an endless interview. - **Discuss-this escape.** Any closed-set question can drop into a plain Q&A discussion. On settlement, the outcome folds into `clarifications.answered[]` and the structured loop resumes on the next topic. - **Save partial and resume later.** Every closed-set question offers this escape. It writes the draft cache and exits. Re-invoking `/gaia-spec` resumes from the right step. @@ -64,11 +64,11 @@ A handful of mechanics are used by multiple steps: 5. **Gate 1.** Plain prompt: confirm intent and UATs, or revise. 6. **Socratic clarify loop.** `/speckit-clarify` runs, capped at five questions. Closed-set questions go through `AskUserQuestion` with the recommended option first; open-ended questions are plain prompts. Per-topic exhaustion checkpoints fire when the natural well runs dry. Research subagents dispatch for any question requiring prior-art lookup. 7. **Self-review.** The `after_clarify` hook fires `/speckit-gaia-self-review` against the gate-1 snapshot. Findings come back classified low, medium, or high. Low and medium auto-apply; high surfaces to the user before applying. Pending clarifications block save until answered or deferred with rationale. -8. **Adversarial SPEC-audit.** Before gate 2, the skill offers to audit the draft, and the recommended choice is always an intensity (standard or deep), never skip. A fan-out of specialist agents verifies the draft's claims against the actual repo and `node_modules`, attacks each UAT for testability, and hunts for coverage gaps, then a refutation pass filters what survives. Surviving findings split two ways: contract fixes fold into the draft before save, so gate 2 shows the already-hardened artifact; implementation directives land in `.gaia/local/specs/SPEC-NNN/AUDIT.md` for `/gaia-plan` to honor. +8. **Adversarial SPEC-audit.** Before gate 2, the skill offers to audit the draft, and the recommended choice is always an intensity (standard or deep), never skip. The audit checks the draft's claims against your actual code, tests whether each UAT is really testable, and looks for gaps. Fixes to the spec itself are folded in before save, so gate 2 shows the hardened version. Notes meant for the build land in `.gaia/local/specs/SPEC-NNN/AUDIT.md` for `/gaia-plan` to honor. 9. **Gate 2.** Plain prompt: confirm the full rendered artifact, or revise. 10. **Canonical save.** Writes `.gaia/local/specs/SPEC-NNN/SPEC.md` and deletes the working-draft cache. The `after_specify` hook fires `/speckit-gaia-lint` for immutability checks. Cycles 1 and 2 surface failures; cycle 3 prompts to step back to gate 2, defer remaining findings, or push another fix. 11. **Optional GitHub issue mirror.** If opted in at step 2, `gh-mirror.sh` creates the issue and stamps the URL into frontmatter. Skips silently when `gh` is not authenticated, Issues are disabled, or the viewer lacks write permission. -12. **Chain to `/gaia-plan`.** `AskUserQuestion`: trigger `/gaia-plan` now or defer. On yes, the skill enters a multi-plan dispatch loop, running `/gaia-plan` inline for each slice you author. The heavy planning for each slice is isolated in a subagent that returns only a compact result, so the session's context stays bounded no matter how many plans you author. +12. **Chain to `/gaia-plan`.** `AskUserQuestion`: trigger `/gaia-plan` now or defer. On yes, you can author one or more plans, one per slice of the spec. The session stays light no matter how many you create. ## Auto mode @@ -100,7 +100,7 @@ A spec only writes its own artifacts and never touches git, so it also runs clea ## How spec-kit fires GAIA hooks -Spec-kit's hooks are not shell scripts. When core invokes `/speckit-specify` (or any other core skill), it reads the registered spec-kit extension configuration for the relevant event and emits an `EXECUTE_COMMAND: ` markdown directive into the agent's reasoning context. The agent then invokes the rendered slash command as a normal Claude skill. +GAIA adds its own checks to the spec-kit lifecycle. They fire on their own at set points in the flow, like before the first draft and after each clarify pass. Five GAIA hooks fire across the SPEC lifecycle. Never invoke them by hand. From 7d227135adc203565010d72e0f2ecf0121e70524 Mon Sep 17 00:00:00 2001 From: Steven Sacks Date: Fri, 26 Jun 2026 18:51:28 +0900 Subject: [PATCH 23/25] docs: update handoff/pickup to delete-on-done lifecycle Match GAIA #448: handoffs are transient with a single-handoff invariant, replacing the archive-on-pickup model. Add a Lifecycle section to handoff (one at a time, self-deletes when work lands, stays if interrupted) and retitle pickup's Archive step to Resolve. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/workflow/handoff.mdx | 8 +++++++- src/content/docs/workflow/pickup.mdx | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/content/docs/workflow/handoff.mdx b/src/content/docs/workflow/handoff.mdx index a3ecfa9..caeb765 100644 --- a/src/content/docs/workflow/handoff.mdx +++ b/src/content/docs/workflow/handoff.mdx @@ -58,6 +58,12 @@ End of session: In the fresh session, [`/gaia-pickup`](/workflow/pickup/) reads this back. See that page for the resume side of the flow. +## Lifecycle + +Only one handoff exists at a time. Running `/gaia-handoff` again replaces the previous one and carries forward anything still unfinished, so you never sort through a stack of stale files. + +A handoff is temporary. Once its Next Actions are done and verified, the session that finished the work deletes it. If you were interrupted before finishing, it stays in place so the next [`/gaia-pickup`](/workflow/pickup/) can resume from it. Handoffs are never archived; a finished one is deleted, not kept. + ## Storage -Handoffs are project-local: `.gaia/local/` is gitignored. They never enter version control, so private notes, dirty-tree details, and device IDs stay on the machine that wrote them. Archived handoffs are not pruned automatically. You should clean `.gaia/local/handoff/archive/` when it grows. +Handoffs are project-local: `.gaia/local/` is gitignored. They never enter version control, so private notes, dirty-tree details, and device IDs stay on the machine that wrote them. diff --git a/src/content/docs/workflow/pickup.mdx b/src/content/docs/workflow/pickup.mdx index 8a6e035..c169cfa 100644 --- a/src/content/docs/workflow/pickup.mdx +++ b/src/content/docs/workflow/pickup.mdx @@ -26,10 +26,10 @@ No arguments. Pickup runs through four steps: 1. **Locate.** Find the most recent handoff: `ls -t .gaia/local/handoff/HANDOFF-*.md | head -1`. If no handoff exists, fall back to `wiki/hot.md` and report `No handoff found, resuming from hot cache.` 2. **Read.** Load the handoff in full. Run `git rev-parse --abbrev-ref HEAD`, `git status --short`, and `git log -1 --oneline` in parallel. 3. **Report.** Surface a tight status block: current branch (with drift from the handoff if any), handoff filename and date, one-line context, 1 to 3 bullets on what's done or in-flight, 1 to 3 bullets on gaps, and a suggested next action. -4. **Archive.** After you confirm a direction (pick an action, start editing, or say "go"), the consumed handoff moves to `.gaia/local/handoff/archive/`. +4. **Resolve.** A handoff is never archived. Most of the time there's nothing to do here: the session that finishes the work deletes the handoff itself. If you pick up one whose work has already fully landed (its branch merged, its next actions already in `git log`), pickup clears it and resumes from the hot cache. If work is still outstanding, the handoff stays in place so an interruption stays recoverable. -