@jaguilar87/gaia 5.0.4 → 5.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +56 -0
- package/INSTALL.md +0 -2
- package/README.md +1 -6
- package/bin/README.md +0 -1
- package/bin/cli/_install_helpers.py +1 -1
- package/bin/cli/cleanup.py +0 -1
- package/bin/cli/doctor.py +1 -1
- package/bin/cli/memory.py +2 -0
- package/bin/cli/update.py +1 -1
- package/bin/pre-publish-validate.js +48 -5
- package/config/README.md +22 -44
- package/config/surface-routing.json +0 -1
- package/dist/gaia-ops/.claude-plugin/plugin.json +1 -1
- package/dist/gaia-ops/config/README.md +22 -44
- package/dist/gaia-ops/config/surface-routing.json +0 -1
- package/dist/gaia-ops/hooks/modules/agents/handoff_persister.py +2 -0
- package/dist/gaia-ops/hooks/modules/security/approval_grants.py +2 -0
- package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +2 -0
- package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +90 -55
- package/dist/gaia-ops/skills/README.md +1 -1
- package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +1 -1
- package/dist/gaia-ops/skills/gaia-patterns/reference.md +0 -1
- package/dist/gaia-ops/skills/gaia-release/SKILL.md +60 -24
- package/dist/gaia-ops/skills/gaia-release/reference.md +35 -11
- package/dist/gaia-ops/skills/git-conventions/SKILL.md +6 -2
- package/dist/gaia-ops/skills/orchestrator-present-approval/SKILL.md +10 -2
- package/dist/gaia-ops/skills/readme-writing/SKILL.md +1 -1
- package/dist/gaia-ops/skills/readme-writing/reference.md +0 -1
- package/dist/gaia-ops/tools/scan/ui.py +20 -4
- package/dist/gaia-ops/tools/scan/verify.py +3 -3
- package/dist/gaia-ops/tools/validation/README.md +15 -24
- package/dist/gaia-security/.claude-plugin/plugin.json +1 -1
- package/dist/gaia-security/hooks/modules/agents/handoff_persister.py +2 -0
- package/dist/gaia-security/hooks/modules/security/approval_grants.py +2 -0
- package/dist/gaia-security/hooks/modules/tools/bash_validator.py +2 -0
- package/dist/gaia-security/hooks/modules/validation/commit_validator.py +90 -55
- package/hooks/modules/agents/handoff_persister.py +2 -0
- package/hooks/modules/security/approval_grants.py +2 -0
- package/hooks/modules/tools/bash_validator.py +2 -0
- package/hooks/modules/validation/commit_validator.py +90 -55
- package/index.js +2 -12
- package/package.json +4 -6
- package/pyproject.toml +3 -3
- package/scripts/bootstrap_database.sh +88 -439
- package/scripts/check_schema_drift.py +208 -0
- package/scripts/migrations/README.md +78 -28
- package/scripts/migrations/schema.checksum +8 -0
- package/scripts/release-prepare.mjs +199 -0
- package/skills/README.md +1 -1
- package/skills/gaia-patterns/SKILL.md +1 -1
- package/skills/gaia-patterns/reference.md +0 -1
- package/skills/gaia-release/SKILL.md +60 -24
- package/skills/gaia-release/reference.md +35 -11
- package/skills/git-conventions/SKILL.md +6 -2
- package/skills/orchestrator-present-approval/SKILL.md +10 -2
- package/skills/readme-writing/SKILL.md +1 -1
- package/skills/readme-writing/reference.md +0 -1
- package/tools/scan/ui.py +20 -4
- package/tools/scan/verify.py +3 -3
- package/tools/validation/README.md +15 -24
- package/commands/README.md +0 -64
- package/commands/gaia.md +0 -37
- package/commands/scan-project.md +0 -74
- package/config/crons-schema.md +0 -81
- package/config/git_standards.json +0 -72
- package/dist/gaia-ops/commands/gaia.md +0 -37
- package/dist/gaia-ops/config/crons-schema.md +0 -81
- package/dist/gaia-ops/config/git_standards.json +0 -72
- package/dist/gaia-ops/tools/agentic-loop/decide-status.py +0 -210
- package/dist/gaia-ops/tools/agentic-loop/parse-metric.py +0 -106
- package/dist/gaia-ops/tools/agentic-loop/record-iteration.py +0 -223
- package/git-hooks/commit-msg +0 -41
- package/scripts/migrations/v10_to_v11.sql +0 -170
- package/scripts/migrations/v10_to_v11_fresh.sql +0 -18
- package/scripts/migrations/v11_to_v12.sql +0 -195
- package/scripts/migrations/v11_to_v12_fresh.sql +0 -19
- package/scripts/migrations/v12_to_v13.sql +0 -48
- package/scripts/migrations/v12_to_v13_fresh.sql +0 -17
- package/scripts/migrations/v13_to_v14.sql +0 -44
- package/scripts/migrations/v13_to_v14_fresh.sql +0 -17
- package/scripts/migrations/v14_to_v15.sql +0 -71
- package/scripts/migrations/v14_to_v15_fresh.sql +0 -19
- package/scripts/migrations/v15_to_v16.sql +0 -57
- package/scripts/migrations/v15_to_v16_fresh.sql +0 -18
- package/scripts/migrations/v16_to_v17.sql +0 -51
- package/scripts/migrations/v16_to_v17_fresh.sql +0 -18
- package/scripts/migrations/v17_to_v18.sql +0 -66
- package/scripts/migrations/v17_to_v18_fresh.sql +0 -24
- package/scripts/migrations/v1_to_v2.sql +0 -97
- package/scripts/migrations/v2_to_v3.sql +0 -68
- package/scripts/migrations/v2_to_v3_merge.sql +0 -69
- package/scripts/migrations/v3_to_v4.sql +0 -67
- package/scripts/migrations/v3_to_v4_fresh.sql +0 -20
- package/scripts/migrations/v4_to_v5.sql +0 -55
- package/scripts/migrations/v4_to_v5_fresh.sql +0 -20
- package/scripts/migrations/v5_to_v6.sql +0 -48
- package/scripts/migrations/v5_to_v6_fresh.sql +0 -17
- package/scripts/migrations/v6_to_v7.sql +0 -26
- package/scripts/migrations/v6_to_v7_fresh.sql +0 -13
- package/scripts/migrations/v7_to_v8.sql +0 -44
- package/scripts/migrations/v7_to_v8_fresh.sql +0 -14
- package/scripts/migrations/v8_to_v9.sql +0 -87
- package/scripts/migrations/v8_to_v9_fresh.sql +0 -15
- package/scripts/migrations/v9_to_v10.sql +0 -109
- package/scripts/migrations/v9_to_v10_episodes_workspace.sql +0 -109
- package/scripts/migrations/v9_to_v10_fresh.sql +0 -18
- package/templates/README.md +0 -70
- package/templates/managed-settings.template.json +0 -43
- package/tools/agentic-loop/decide-status.py +0 -210
- package/tools/agentic-loop/parse-metric.py +0 -106
- package/tools/agentic-loop/record-iteration.py +0 -223
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gaia-release
|
|
3
|
-
description: Use when testing, validating, or publishing Gaia releases --
|
|
3
|
+
description: Use when testing, validating, or publishing Gaia releases -- "install local", "dry-run", "release", live install, sandbox verify, RC, or stable
|
|
4
4
|
metadata:
|
|
5
5
|
user-invocable: false
|
|
6
6
|
type: technique
|
|
@@ -8,24 +8,52 @@ metadata:
|
|
|
8
8
|
|
|
9
9
|
# Gaia Release
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The norm for getting Gaia onto a machine and into the registry. The user expresses exactly one of three intentions -- **install local**, **dry-run**, or **release** -- and each maps to a complete, automated sequence the orchestrator runs end-to-end. The user never recalls a sub-step and never runs a release script by hand: the script is a tool the flow invokes, not a command the human must remember. This is the lesson of the sagas that shipped broken: a release failed because a version source was bumped one file at a time and a forgotten `pyproject.toml` drifted; another needed a force-push to reconcile a tag. Every one of those was a manual step a human was trusted to remember and didn't. The fix is to norm the sequence so the steps cannot be forgotten -- they are the flow, not a checklist beside it.
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## The three intentions
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|------|---------|-------------|
|
|
17
|
-
| **live self** | `cd /path/to/gaia && npm run gaia:install-local` | Re-install Gaia in the same workspace where Claude Code is running (e.g. `me/`). Validates working-tree changes against your dev environment. |
|
|
18
|
-
| **live external** | `cd /path/to/gaia && bash bin/validate-sandbox.sh --tarball ./jaguilar87-gaia-*.tgz --target local --workspace /path/to/target` | Install the working tree into a different workspace (e.g. `qxo/`). Validates consumer-real conditions without touching your dev environment. |
|
|
19
|
-
| **live fresh** | Add `--fresh` to either of the above | Wipes `node_modules/`, `package.json`, and `package-lock.json` from the target before install. Forces a clean postinstall run. |
|
|
20
|
-
| **dry-run** | `npm run gaia:verify-install:local` | Pack + install into `/tmp/gaia-sandbox-<ts>/` + run the 8-check harness. Validates exactly what `npm publish` would ship. |
|
|
21
|
-
| **RC** | Version bump to `X.Y.Z-rc.N` + GitHub Release | Pipeline publishes to npm with `--tag rc`. Consumers opt-in: `npm install @jaguilar87/gaia@rc`. |
|
|
22
|
-
| **stable** | Version bump to `X.Y.Z` + GitHub Release | Pipeline publishes to npm with `--tag latest`. Default install: `npm install @jaguilar87/gaia`. |
|
|
15
|
+
When the user says one of these, run the *whole* sequence. Do not stop after the first command and wait to be told the next one -- the sequence below IS the intention.
|
|
23
16
|
|
|
24
|
-
|
|
17
|
+
### "install local" -- put the working tree into a real workspace
|
|
25
18
|
|
|
26
|
-
|
|
19
|
+
```
|
|
20
|
+
npm run gaia:install-local
|
|
21
|
+
```
|
|
22
|
+
Then, without being asked:
|
|
23
|
+
1. Run the **Wire-up verification checklist** (below). If any check fails, jump to `reference.md` -> "Diagnostic guide".
|
|
24
|
+
2. **Remind the user to restart `claude`** -- skills, hooks, and agents cache at startup, so a fresh install is invisible until restart.
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
Installing into a *different* workspace (e.g. `qxo/`) or wiping install metadata first is the same intention with a different target -- see `reference.md` -> "Mode runbooks" for the `--workspace` and `--fresh` forms. Always pass `--workspace` explicitly when invoking from inside the gaia repo (the self-referencing `node_modules/@jaguilar87/gaia/` tricks auto-detect; guarded by `is_gaia_repo_root()` in `validate-sandbox.sh`).
|
|
27
|
+
|
|
28
|
+
### "dry-run" -- prove a clean install works, reproducing CI locally
|
|
29
|
+
|
|
30
|
+
This is not just the sandbox harness -- it is the **local stand-in for CI**, so it must run the same gates CI runs (see the pre-flight principle below). Run, in order:
|
|
31
|
+
1. `npm run pre-publish:validate` -- the version-drift gate (`validate-manifests` in `ci.yml`).
|
|
32
|
+
2. `npm run gaia:verify-install:local` -- packs, installs into `/tmp/gaia-sandbox-<ts>/`, runs the 8-check harness. Validates exactly what `npm publish` would ship.
|
|
33
|
+
3. `npm test` -- the L1 suite (the harness/tests CI runs that reasonably reproduce locally).
|
|
34
|
+
|
|
35
|
+
A green dry-run that skips step 1 is a *subset* of CI, not a stand-in for it -- the gap surfaces only after publish, when the fix costs another release.
|
|
36
|
+
|
|
37
|
+
### "release [version]" -- end-to-end publish, fully automated
|
|
38
|
+
|
|
39
|
+
The orchestrator runs every step below in order. The user supplies (or confirms) the version and approves the T3 operations; the orchestrator does the rest. **The user does not run `release:prepare` -- step (b) invokes it.**
|
|
40
|
+
|
|
41
|
+
| Step | Action | Notes |
|
|
42
|
+
|------|--------|-------|
|
|
43
|
+
| **(a)** | Determine the version | Default to the next **patch**. If the change is major/minor, **confirm with the user** (`NEEDS_INPUT`) before proceeding -- never silently pick major/minor. |
|
|
44
|
+
| **(b)** | `npm run release:prepare <version>` | The atomic core: bumps ALL version sources at once (`package.json`, `pyproject.toml`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `CHANGELOG.md`), runs `build:plugins`, then `pre-publish:validate`. Fails loud on any drift. This is `scripts/release-prepare.mjs` -- invoked by the flow, never by the user. |
|
|
45
|
+
| **(c)** | Pre-flight that reproduces CI | `pre-publish:validate` already ran inside (b). Now run `npm test` (plus any harness that applies) so the local gate matches CI before the tag exists. |
|
|
46
|
+
| **(d)** | Commit | `git add` + `git commit` -- local-only, not T3. |
|
|
47
|
+
| **(e)** | Tag, **force-free** | A *new* tag (`v<version>`); never move an existing one. If the remote diverged, reconcile with **merge, not rebase** (rebase forces a tag move, hard-denied locally). See `reference.md` -> "Reconciling a diverged remote". |
|
|
48
|
+
| **(f)** | Push | `git push` (T3). If diverged, the merge from (e) makes this force-free. |
|
|
49
|
+
| **(g)** | `gh release create v<version>` | Triggers `publish.yml`, which builds, validates, and publishes to npm with the auto-detected tag (`-rc.` -> rc, else latest). Mark RC as pre-release. |
|
|
50
|
+
| **(h)** | Monitor to the outcome | Watch the workflow run to its desenlace, then verify the package landed on npm (`npm run gaia:verify-install:rc` / `:latest`). The release is not done when the tag is pushed -- it is done when npm serves the new version. |
|
|
51
|
+
|
|
52
|
+
For the full command forms, the schema-migration lockstep, and the diverged-remote reconciliation, see `reference.md`.
|
|
53
|
+
|
|
54
|
+
## Wire-up verification checklist
|
|
55
|
+
|
|
56
|
+
After any install (install local, dry-run sandbox, RC, stable), the same checklist applies. If any check fails, jump to `reference.md` -> "Diagnostic guide".
|
|
29
57
|
|
|
30
58
|
1. `ls -la <workspace>/.claude/` -- 7 symlinks (agents, hooks, skills, commands, config, templates, tools) + `logs/`, `approvals/`, `plugin-registry.json`, `settings.local.json`.
|
|
31
59
|
2. `cat <workspace>/.claude/plugin-registry.json` -- `installed[].name` includes `gaia-ops` (or `gaia-security`) at the expected version.
|
|
@@ -36,25 +64,33 @@ After any install (live, dry-run, RC, stable), the same checklist applies. If an
|
|
|
36
64
|
|
|
37
65
|
These six checks are not redundant with `gaia doctor`. Steps 1-5 catch what doctor cannot reach when the wire-up is so broken that doctor itself walks up to the user `.claude/` instead of the workspace.
|
|
38
66
|
|
|
39
|
-
## Release Checklist
|
|
40
|
-
|
|
41
|
-
Pre-publish, publish, and post-publish steps -- plus the schema migration protocol when `EXPECTED_SCHEMA_VERSION` changes -- live in `reference.md` -> "Release checklist" and "Schema migration protocol". Both are read on-demand from the SKILL when actually doing a release; they are not in this file because they would dominate the line budget without informing the day-to-day mode decision.
|
|
42
|
-
|
|
43
67
|
## CI/CD
|
|
44
68
|
|
|
45
69
|
| Workflow | File | Triggers |
|
|
46
70
|
|----------|------|----------|
|
|
47
|
-
| CI | `.github/workflows/ci.yml` | Push / PR -- runs pytest (Python 3.
|
|
71
|
+
| CI | `.github/workflows/ci.yml` | Push / PR -- runs pytest (Python 3.11/3.12), Node tests, plugin build verification, and `validate-manifests` |
|
|
48
72
|
| Publish | `.github/workflows/publish.yml` | GitHub Release event -- builds plugins, validates artifacts, auto-detects npm tag from version (`-rc.` -> rc, `-beta.` -> beta, else -> latest), and publishes |
|
|
49
73
|
|
|
50
74
|
`NPM_TOKEN` lives in GitHub Secrets; local `npm publish` bypasses build verification and is not the supported path.
|
|
51
75
|
|
|
76
|
+
## Principles -- why the sequence is normed, not optional
|
|
77
|
+
|
|
78
|
+
- **The pre-flight reproduces what CI validates, not a subset of it.** When the local check skips a gate CI runs (`pre-publish:validate`), that gate's failures surface only *after* publishing, on the published tarball, where the only remedy is another release. That is exactly how a `pyproject.toml` drift shipped green-local and red-CI. The "dry-run" intention and step (c) of "release" close the gap -- `pre-publish:validate` for drift. See `reference.md` -> "The pre-flight reproduces what CI validates".
|
|
79
|
+
- **Bump every version source in one step, never one at a time.** `pre-publish:validate` requires `package.json`, `pyproject.toml`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, and the `CHANGELOG.md` top header to agree. A partial bump leaves the tree in a state the validator rejects and lets a stale source ship. `release:prepare` writes all of them from one target version, so a hand-desync is impossible. See `scripts/release-prepare.mjs`.
|
|
80
|
+
- **Tag force-free; reconcile with merge, never rebase.** `publish.yml` commits built artifacts back to `main`, so the remote leads after every release. Rebasing rewrites hashes and forces a tag move (`git tag -f` / `--force`), hard-denied by local hooks (`git_destructive` in `blocked_commands.py`, exit 2, not approvable). Merge preserves hashes and tags; a new release gets a *new* tag, never a moved one. See `reference.md` -> "Reconciling a diverged remote".
|
|
81
|
+
- **A release ends at npm, not at the tag.** Pushing the tag only starts `publish.yml`. The intention is not satisfied until the workflow reaches its outcome and npm serves the new version -- step (h) is part of the sequence, not a follow-up.
|
|
82
|
+
|
|
52
83
|
## Anti-Patterns
|
|
53
84
|
|
|
54
|
-
- **
|
|
85
|
+
- **Stopping after the first command of an intention** -- "install local" is not just `gaia:install-local`; "release" is not just `release:prepare`. Each intention is the *whole* sequence. Running one command and waiting to be told the next reintroduces the forgettable manual step the norm exists to remove.
|
|
86
|
+
- **Asking the user to run `release:prepare`** -- it is a tool the "release" flow invokes at step (b), not a command the human runs. Surfacing it as a manual step is the same failure mode (a step someone must remember) wearing a new script.
|
|
87
|
+
- **Pre-flight that is a subset of CI** -- skipping `pre-publish:validate` locally means the version drift surfaces after publish. Reproduce CI; do not approximate it.
|
|
88
|
+
- **Bumping version sources one at a time** -- desyncs a source by hand; `pre-publish:validate` rejects the tree and a forgotten file ships if the check is skipped. Always go through `release:prepare`.
|
|
89
|
+
- **Rebase to reconcile a diverged remote** -- forces a tag move, hard-denied locally. Merge instead.
|
|
90
|
+
- **Live-only testing** -- live install runs against accumulated workspace state; only dry-run proves a clean install works.
|
|
55
91
|
- **Local npm publish** -- bypasses the pipeline's build verification step.
|
|
56
92
|
- **Single-mode testing** -- `ops` and `security` load different skill sets and hook configurations; one can break while the other passes.
|
|
57
|
-
- **Stale dist/** -- forgetting `npm run build:plugins` before pack means validating old code.
|
|
58
|
-
- **Missing restart** -- the process caches skills, hooks, and agents at startup;
|
|
59
|
-
- **Ignoring `~/.gaia/last-install-error.json`** -- when postinstall fails silently, this is the marker
|
|
60
|
-
- **Relying on auto-detect when cwd is inside the gaia repo** -- the
|
|
93
|
+
- **Stale dist/** -- forgetting `npm run build:plugins` before pack means validating old code. `release:prepare` and `build:plugins` regenerate it; dry-run packs fresh.
|
|
94
|
+
- **Missing restart** -- the process caches skills, hooks, and agents at startup; installs and mode switches require restarting `claude`.
|
|
95
|
+
- **Ignoring `~/.gaia/last-install-error.json`** -- when postinstall fails silently, this is the marker. Treat its presence as a hard failure regardless of what `gaia doctor` reports.
|
|
96
|
+
- **Relying on auto-detect when cwd is inside the gaia repo** -- the self-referencing `node_modules/@jaguilar87/gaia/` entry tricks the workspace detector. Pass `--workspace /home/jorge/ws/me` explicitly; verify with `readlink /home/jorge/ws/me/.claude/hooks`.
|
|
@@ -44,7 +44,7 @@ Append `--fresh` to either form. The harness will delete `node_modules/`, `packa
|
|
|
44
44
|
**What postinstall does:**
|
|
45
45
|
1. Ships `scripts/` (bootstrap_database.sh) -- failed silently in pre-rc.4 builds; verified in `npm pack --dry-run`.
|
|
46
46
|
2. Creates `.claude/` if missing.
|
|
47
|
-
3. Runs `bootstrap_database.sh` -- seeds the schema (
|
|
47
|
+
3. Runs `bootstrap_database.sh` -- seeds the schema (current floor v18), agent rows, and `schema_version`. Fails loud on any error (writes `~/.gaia/last-install-error.json` and exits non-zero).
|
|
48
48
|
4. Merges hooks into `settings.local.json` via the consolidated `merge_hooks` step.
|
|
49
49
|
5. Creates 7 symlinks under `.claude/` to `node_modules/@jaguilar87/gaia/<dir>/`.
|
|
50
50
|
6. Writes `plugin-registry.json` with `installed[].name == "gaia-ops"`.
|
|
@@ -87,20 +87,32 @@ A change that works in one mode can break the other because they load different
|
|
|
87
87
|
|
|
88
88
|
### RC and stable (pipeline)
|
|
89
89
|
|
|
90
|
-
Both modes share the same pipeline. The pipeline auto-detects the npm tag from the version string.
|
|
90
|
+
Both modes share the same pipeline. The pipeline auto-detects the npm tag from the version string. These steps are the expansion of the "release" intention in `SKILL.md`; the orchestrator runs them, the user supplies/confirms the version.
|
|
91
91
|
|
|
92
92
|
1. Dry-run must pass locally first.
|
|
93
|
-
2.
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
5.
|
|
93
|
+
2. **`npm run release:prepare <version>`** -- the atomic bump. This is `scripts/release-prepare.mjs`, invoked by the flow, **never run by the user by hand**. In one command it:
|
|
94
|
+
- writes `<version>` to ALL sources at once -- `package.json`, `pyproject.toml`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json` (every plugin entry), and the `CHANGELOG.md` top header (inserts a dated stub above the current top if absent -- edit its body before release);
|
|
95
|
+
- runs `npm run build:plugins` to regenerate `dist/` (including the per-plugin manifests that carry the version);
|
|
96
|
+
- runs `npm run pre-publish:validate` and fails loud on any drift.
|
|
97
|
+
|
|
98
|
+
This replaces hand-bumping one file at a time. `pre-publish:validate` fails the release unless every version source agrees, and the two real escapes a hand-bump leaves are a `pyproject.toml` left behind on a prior version (caught only by `pre-publish:validate`) and a `marketplace.json` that still advertises the old tag. `release:prepare` makes the desync impossible because all sources are written from one target version. For a bare semver: `5.0.5` for stable, `5.1.0-rc.1` for RC (no leading `v` -- the tag adds it). The script is idempotent: re-running with the same version is a no-op bump that re-validates.
|
|
99
|
+
3. Pre-flight that reproduces CI (steps already partly done inside `release:prepare`): `npm test`. `pre-publish:validate` ran in step 2.
|
|
100
|
+
4. Commit (`git add` + `git commit` -- local-only, not T3). **If the remote diverged, reconcile with MERGE, never rebase** (see "Reconciling a diverged remote" below).
|
|
101
|
+
5. Tag (force-free -- a *new* `v<version>`, never moved) + push (`git push`, T3). The merge in step 4 keeps the push force-free.
|
|
99
102
|
6. Create a GitHub Release:
|
|
100
103
|
- Tag: the version from `package.json` (e.g., `v5.0.0-rc.4` or `v5.3.0`).
|
|
101
104
|
- Title: the version.
|
|
102
105
|
- Mark RC releases as pre-release.
|
|
103
106
|
7. `publish.yml` triggers automatically and publishes with `--tag <auto-detected>`.
|
|
107
|
+
8. Monitor the workflow run to its outcome, then verify npm serves the new version (`npm run gaia:verify-install:rc` / `:latest`). The release is done at npm, not at the tag.
|
|
108
|
+
|
|
109
|
+
### Reconciling a diverged remote -- merge, never rebase; never move a tag
|
|
110
|
+
|
|
111
|
+
`publish.yml` commits built artifacts back to `main` and pushes (the "Commit built plugins" step), so after a release the remote `main` is *ahead* of your local. When you next go to release and find the remote diverged, the reconciliation choice is forced by local policy:
|
|
112
|
+
|
|
113
|
+
- **Reconcile with merge, not rebase.** Rebase rewrites your local commit hashes. If a tag already pointed at one of those commits, you would have to re-point it -- which means `git tag -f` or a force-push of the tag. Both match the `git_destructive` pattern in `hooks/modules/security/blocked_commands.py` and are **hard-denied locally** (exit 2, not approvable) -- there is no `approval_id` that unblocks them. Merge preserves the existing hashes, so existing tags stay valid and no force is ever needed.
|
|
114
|
+
- **Tags are create-only -- never move one.** A published tag is immutable history; a new release gets a *new* tag (`-rc.N+1`, next patch/minor), it does not re-point an old one. Moving a tag requires the same force path that local hooks deny.
|
|
115
|
+
- **The force-deny is a local hooks policy, not a CI one.** `publish.yml` itself runs `git tag -f` and `git push --force` for the tag after committing `dist/` -- that is the pipeline operating under its own permissions, outside the local hook layer. Do not read the pipeline's force-push as license to force locally; the local deny stands regardless of what CI does.
|
|
104
116
|
|
|
105
117
|
**Verify from npm** (registry round-trip):
|
|
106
118
|
- RC: `npm run gaia:verify-install:rc`
|
|
@@ -134,17 +146,29 @@ When you bump `EXPECTED_SCHEMA_VERSION` in `bin/cli/doctor.py`, the four steps b
|
|
|
134
146
|
3. Add migration SQL (`UPDATE` / `ALTER TABLE`) when existing DBs need to upgrade in place; otherwise old workspaces stay below the expected version and `gaia doctor` fails.
|
|
135
147
|
4. Run `pytest tests/cli/test_schema_version_lockstep.py` -- it cross-references the constant, the bootstrap insert, and the migration SQL to confirm they all agree.
|
|
136
148
|
|
|
149
|
+
### Build/pre-publish Schema-Drift Guard
|
|
150
|
+
|
|
151
|
+
`bin/pre-publish-validate.js` Step 5c runs `scripts/check_schema_drift.py`, which sha256-fingerprints `gaia/store/schema.sql` and compares it against `scripts/migrations/schema.checksum` (pinned to `EXPECTED_SCHEMA_VERSION`). If the schema has changed but the version was not bumped and no migration file added, the guard fails the build.
|
|
152
|
+
|
|
153
|
+
**Consequence:** if you edit `schema.sql` you MUST either (a) bump `EXPECTED_SCHEMA_VERSION` + add the migration file (following the lockstep above), OR (b) re-pin the checksum with `python3 scripts/check_schema_drift.py --record` (the escape hatch for pure-comment or non-semantic edits). Without one of these, `npm run pre-publish:validate` — and therefore `release:prepare` — will FAIL.
|
|
154
|
+
|
|
137
155
|
## Release Checklist
|
|
138
156
|
|
|
157
|
+
### The pre-flight reproduces what CI validates, not a subset of it
|
|
158
|
+
|
|
159
|
+
A green pre-flight only protects the release if it runs the same gates CI runs. When the local check is a *subset* of CI, the gaps CI covers are discovered after publishing -- on the published tarball, where the only remedy is another release. `npm run gaia:verify-install:local` packs and installs into a sandbox, but it does **not** run `pre-publish:validate`. CI (`.github/workflows/ci.yml`) runs it separately. A real failure escaped exactly through that gap: a `pyproject.toml` version drift that only `pre-publish:validate` catches, which was green locally and red in CI *after* the tag was pushed.
|
|
160
|
+
|
|
161
|
+
So the pre-flight must close that gap before any tag or push:
|
|
162
|
+
|
|
139
163
|
**Pre-publish:**
|
|
140
164
|
- `pytest tests/` green (or `npm test` for the L1 subset).
|
|
165
|
+
- **`npm run pre-publish:validate` green locally** -- this is the version-drift gate (`validate-manifests` job in `ci.yml`). Run it before tag/push, not only in CI. It is what catches a `pyproject.toml` / `package.json` / `plugin.json` / `marketplace.json` desync before it ships.
|
|
141
166
|
- `npm pack --dry-run | grep scripts/` confirms `scripts/bootstrap_database.sh` is included in the tarball.
|
|
142
167
|
- `bash bin/validate-sandbox.sh --tarball ./jaguilar87-gaia-*.tgz --target sandbox --fresh` green (or `npm run gaia:verify-install:local`).
|
|
143
168
|
- Optional smoke: `npm run gaia:install-local -- --workspace /tmp/test-install --fresh`.
|
|
144
169
|
|
|
145
170
|
**Publish:**
|
|
146
|
-
-
|
|
147
|
-
- `npm run build:plugins` regenerates `dist/`.
|
|
171
|
+
- Run `npm run release:prepare <version>` -- atomically bumps all version sources (`package.json`, `pyproject.toml`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`), regenerates `dist/` via `build:plugins`, and runs `pre-publish:validate` (including the schema-drift guard). Nothing else should write a version.
|
|
148
172
|
- Commit + push.
|
|
149
173
|
- Create GitHub Release with the version tag.
|
|
150
174
|
- Pipeline publishes (`publish.yml` triggers on Release event):
|
|
@@ -165,7 +189,7 @@ The workflow at `.github/workflows/publish.yml` runs on every GitHub Release eve
|
|
|
165
189
|
- Installs deps with `npm ci`.
|
|
166
190
|
- Builds plugins with `npm run build:plugins`.
|
|
167
191
|
- Verifies all expected artifacts in `dist/`.
|
|
168
|
-
- Commits built artifacts back if changed.
|
|
192
|
+
- Commits built artifacts back if changed (commit message carries `[skip ci]` so the dist commit-back does not re-trigger CI).
|
|
169
193
|
- Runs `npm run pre-publish:validate`.
|
|
170
194
|
- Auto-detects npm tag from version string (see "Publish" above).
|
|
171
195
|
- Publishes with `npm publish --access public --tag <detected>`.
|
|
@@ -43,5 +43,9 @@ requires explicit user instruction.
|
|
|
43
43
|
|
|
44
44
|
## Hook Enforcement
|
|
45
45
|
|
|
46
|
-
The `commit_validator.py` hook validates against
|
|
47
|
-
|
|
46
|
+
The `commit_validator.py` hook validates against standards inlined as
|
|
47
|
+
module-level constants in that file (`TYPE_ALLOWED`, `SUBJECT_MAX_LENGTH`,
|
|
48
|
+
`SUBJECT_RULES`, `BODY_MAX_LINE_LENGTH`) -- it covers the conventional-commits
|
|
49
|
+
format, subject, and body rules. Forbidden-footer detection lives separately
|
|
50
|
+
in `bash_validator` (hardcoded there). Format violations block the commit.
|
|
51
|
+
Body line length triggers warnings only.
|
|
@@ -30,9 +30,16 @@ without the data needed to decide. The job is **verbatim relay, not
|
|
|
30
30
|
re-authoring**: rewriting any of the 7 sealed fields breaks the fingerprint and
|
|
31
31
|
`verify_fingerprint` (`gaia/approvals/chain.py`) raises `ChainTamperError`.
|
|
32
32
|
|
|
33
|
-
## Step 0 --
|
|
33
|
+
## Step 0 -- Verify the approval against the DB (mandatory before SHOWN)
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
A subagent's reported `approval_id` is an unverified claim, not a fact. The agent runs in its own context and can relay an id that is stale, from another session, or simply wrong -- and a stale id presented as a fresh block walks the user into consenting to nothing real (or to a grant that no longer exists). The DB is the source of truth; the agent's report is a pointer into it that you must resolve, never the authority itself.
|
|
36
|
+
|
|
37
|
+
So before AskUserQuestion, two checks against the DB, in order:
|
|
38
|
+
|
|
39
|
+
1. **The approval exists, is fresh, and is from the current session.** Query `gaia approvals pending --session "$CLAUDE_SESSION_ID"` (or `--json` for parsing). The reported `approval_id` MUST appear in that result. If it appears only under `--all-sessions` but not the current session, it is leakage from another session (a test session such as `e2e-sim`, a prior run) -- **do not present**. If it does not appear at all, it does not exist or was already consumed/rejected -- **do not present**. Freshness is the `created_at` of the pending row plus its presence as still-`pending`; an id the agent reports that is not currently pending in *this* session is not a fresh block, whatever the agent says.
|
|
40
|
+
2. **The payload is untampered.** Call `verify_fingerprint(approval_id, payload_json, con) -> bool` from `gaia/approvals/chain.py`. It raises `ChainTamperError` if the payload was modified between subagent emission and your relay (security boundary, do not present), and `ValueError` if no REQUESTED event exists for this `approval_id`. Either case: **do not present**, report the failure, stop.
|
|
41
|
+
|
|
42
|
+
**For a `command_set` (plan-first batch) the agent does not know the id at all.** The hook mints the `approval_id` at SubagentStop (`_intake_command_set_pending` -- see Rule 3); the subagent emits the `command_set` with **no** `approval_id`. So you do not have an agent-reported id to trust even if you wanted to -- you ALWAYS recover the freshly minted id from `gaia approvals pending` for the current session. This is the general shape made unavoidable: the DB mints, the orchestrator recovers, the agent never owns the id.
|
|
36
43
|
|
|
37
44
|
## Mandatory presentation -- 5 labeled fields + nonce-suffixed label
|
|
38
45
|
|
|
@@ -114,3 +121,4 @@ wording, see `reference.md` -> "GOOD vs BAD Examples", "Option Label Patterns",
|
|
|
114
121
|
| "The same command emitted a new approval_id" | Grants are single-use and consumed on the first retry. A second run is a new APPROVAL_REQUEST -- approve again. |
|
|
115
122
|
| "I'll set batch_scope to approve many at once" | `batch_scope` is ignored -- but a real batch path exists: a plan-first `command_set` (>= 2 items, no `approval_id`) is intaken into ONE pending `COMMAND_SET`. Present that single approval (N commands shown, one `[P-...]` nonce, one consent), not N separate approvals. |
|
|
116
123
|
| "I can paraphrase a field before relaying" | The fingerprint covers all 7 sealed fields; any modification raises `ChainTamperError` in Step 0 and the presentation is refused. |
|
|
124
|
+
| **"The agent reported an `approval_id`, so it's a real fresh block"** -- trusting a nonce relayed by the subagent | The agent's reported id is an unverified pointer, not a fact. It can be stale or belong to another session -- subagents have presented a STALE nonce from a test session (`e2e-sim`) as if it were a fresh block. Resolve every reported id against `gaia approvals pending --session "$CLAUDE_SESSION_ID"` (Step 0): it must be currently pending in *this* session. Visible only under `--all-sessions`, or absent entirely, means do not present. For `command_set` the hook mints the id and the agent never has one -- you always recover it from the DB. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: readme-writing
|
|
3
|
-
description: Use when writing or updating a README for a Gaia component folder (agents/, skills/, hooks/, commands/, config/, bin/, tests/, build/,
|
|
3
|
+
description: Use when writing or updating a README for a Gaia component folder (agents/, skills/, hooks/, commands/, config/, bin/, tests/, build/, or the repo root)
|
|
4
4
|
metadata:
|
|
5
5
|
user-invocable: false
|
|
6
6
|
type: technique
|
|
@@ -185,4 +185,3 @@ Copy this when writing a README from scratch. Fill every section -- do not delet
|
|
|
185
185
|
| `bin/` | Low -- CLI tools, user-invoked | No |
|
|
186
186
|
| `tests/` | Low -- run by CI or developer | No |
|
|
187
187
|
| `build/` | Medium -- triggered by npm run build | Optional |
|
|
188
|
-
| `templates/` | Low -- read by build scripts | No |
|
package/tools/scan/ui.py
CHANGED
|
@@ -16,6 +16,22 @@ import sys
|
|
|
16
16
|
from typing import Any, Dict, List, Optional
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
# Glyphs
|
|
21
|
+
#
|
|
22
|
+
# Hoisted to module-level constants so they are never written as escape
|
|
23
|
+
# sequences *inside* an f-string replacement field. A backslash within an
|
|
24
|
+
# f-string expression (e.g. f"{self._green('◇')}") is a SyntaxError on
|
|
25
|
+
# Python 3.11 (our declared minimum); it is only permitted on 3.12+ via PEP
|
|
26
|
+
# 701. Referencing a bare name inside the braces keeps the same rendered
|
|
27
|
+
# output while staying 3.11-compatible.
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
_GLYPH_DIAMOND_OUTLINE = "◇" # ◇
|
|
31
|
+
_GLYPH_WARNING = "⚠" # ⚠
|
|
32
|
+
_GLYPH_CORNER_BL = "└" # └
|
|
33
|
+
|
|
34
|
+
|
|
19
35
|
# ---------------------------------------------------------------------------
|
|
20
36
|
# ANSI color helpers
|
|
21
37
|
# ---------------------------------------------------------------------------
|
|
@@ -119,7 +135,7 @@ class RailUI:
|
|
|
119
135
|
name: Section title (e.g. "Stack", "Infrastructure").
|
|
120
136
|
lines: Detail lines to display under the section.
|
|
121
137
|
"""
|
|
122
|
-
self._write(f"{self._green(
|
|
138
|
+
self._write(f"{self._green(_GLYPH_DIAMOND_OUTLINE)} {self._cyan(name)}")
|
|
123
139
|
for line in lines:
|
|
124
140
|
self._write(f"{self._rail()} {line}")
|
|
125
141
|
self._write(self._rail())
|
|
@@ -131,7 +147,7 @@ class RailUI:
|
|
|
131
147
|
names: List of section names to join with middle-dot.
|
|
132
148
|
"""
|
|
133
149
|
joined = self._cyan(" \u00b7 ".join(names))
|
|
134
|
-
self._write(f"{self._green(
|
|
150
|
+
self._write(f"{self._green(_GLYPH_DIAMOND_OUTLINE)} {joined}")
|
|
135
151
|
self._write(self._rail())
|
|
136
152
|
|
|
137
153
|
def warning(self, count: int, messages: List[str]) -> None:
|
|
@@ -141,7 +157,7 @@ class RailUI:
|
|
|
141
157
|
count: Total number of warnings.
|
|
142
158
|
messages: Warning messages to display.
|
|
143
159
|
"""
|
|
144
|
-
self._write(f"{self._yellow(
|
|
160
|
+
self._write(f"{self._yellow(_GLYPH_WARNING)} {self._yellow(f'Warnings ({count})')}")
|
|
145
161
|
for msg in messages:
|
|
146
162
|
self._write(f"{self._rail()} {msg}")
|
|
147
163
|
self._write(self._rail())
|
|
@@ -193,7 +209,7 @@ class RailUI:
|
|
|
193
209
|
Args:
|
|
194
210
|
message: Footer message text.
|
|
195
211
|
"""
|
|
196
|
-
self._write(f"{self._dim(
|
|
212
|
+
self._write(f"{self._dim(_GLYPH_CORNER_BL)} {message}")
|
|
197
213
|
|
|
198
214
|
|
|
199
215
|
# ---------------------------------------------------------------------------
|
package/tools/scan/verify.py
CHANGED
|
@@ -45,8 +45,8 @@ class CheckResult:
|
|
|
45
45
|
def check_symlinks(project_root: Path) -> CheckResult:
|
|
46
46
|
"""Verify that all expected symlinks exist in .claude/.
|
|
47
47
|
|
|
48
|
-
Checks for: agents, tools, hooks, commands,
|
|
49
|
-
skills, CHANGELOG.md (
|
|
48
|
+
Checks for: agents, tools, hooks, commands, config,
|
|
49
|
+
skills, CHANGELOG.md (7 total).
|
|
50
50
|
|
|
51
51
|
Args:
|
|
52
52
|
project_root: Project root directory.
|
|
@@ -56,7 +56,7 @@ def check_symlinks(project_root: Path) -> CheckResult:
|
|
|
56
56
|
"""
|
|
57
57
|
names = [
|
|
58
58
|
"agents", "tools", "hooks", "commands",
|
|
59
|
-
"
|
|
59
|
+
"config", "skills",
|
|
60
60
|
"CHANGELOG.md",
|
|
61
61
|
]
|
|
62
62
|
valid = 0
|
|
@@ -25,7 +25,7 @@ without requiring explicit imports in agent code.
|
|
|
25
25
|
- ✅ Subject line rules (max 72 chars, no period at end)
|
|
26
26
|
- ✅ Forbidden footers (no "Generated with" footers)
|
|
27
27
|
|
|
28
|
-
**Configuration:**
|
|
28
|
+
**Configuration:** Standards are inlined as module-level constants in `hooks/modules/validation/commit_validator.py` (`TYPE_ALLOWED`, `SUBJECT_MAX_LENGTH`, `SUBJECT_RULES`, `BODY_MAX_LINE_LENGTH`, `ENFORCEMENT`). Forbidden-footer detection lives in `bash_validator`.
|
|
29
29
|
**Logs:** `.claude/logs/commit-violations.jsonl`
|
|
30
30
|
|
|
31
31
|
---
|
|
@@ -108,16 +108,11 @@ This validation module works with skills in a **hybrid model**:
|
|
|
108
108
|
|
|
109
109
|
```
|
|
110
110
|
┌──────────────────────────────────────────────────────────┐
|
|
111
|
-
│ config/git_standards.json (SSOT) │
|
|
112
|
-
│ - Conventional commit types │
|
|
113
|
-
│ - Forbidden footers │
|
|
114
|
-
│ - Max lengths │
|
|
115
|
-
└──────────────────────────────────────────────────────────┘
|
|
116
|
-
│
|
|
117
|
-
▼
|
|
118
|
-
┌──────────────────────────────────────────────────────────┐
|
|
119
111
|
│ hooks/modules/validation/ (Commit Validation) │
|
|
120
112
|
│ └─ commit_validator.py │
|
|
113
|
+
│ ├─ Standards inlined as module-level constants │
|
|
114
|
+
│ │ (types, subject/body max lengths, rules) │
|
|
115
|
+
│ ├─ Forbidden footers handled by bash_validator │
|
|
121
116
|
│ └─ Used by bash_validator.py only │
|
|
122
117
|
└──────────────────────────────────────────────────────────┘
|
|
123
118
|
│
|
|
@@ -178,24 +173,20 @@ Note: commit_validator.py moved to hooks/modules/validation/
|
|
|
178
173
|
|
|
179
174
|
## Configuration
|
|
180
175
|
|
|
181
|
-
**Git Standards:**
|
|
176
|
+
**Git Standards:** Inlined as module-level constants in `hooks/modules/validation/commit_validator.py`.
|
|
182
177
|
|
|
183
178
|
Example:
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
"enforcement": {
|
|
192
|
-
"enabled": true,
|
|
193
|
-
"block_on_failure": true,
|
|
194
|
-
"log_violations": true
|
|
195
|
-
}
|
|
196
|
-
}
|
|
179
|
+
```python
|
|
180
|
+
TYPE_ALLOWED = ("feat", "fix", "refactor", "docs", "test", "chore",
|
|
181
|
+
"ci", "perf", "style", "build")
|
|
182
|
+
SUBJECT_MAX_LENGTH = 72
|
|
183
|
+
SUBJECT_RULES = {"no_period_at_end": True, "no_emoji": True,
|
|
184
|
+
"imperative_mood": True, "capitalize_first_letter": False}
|
|
185
|
+
ENFORCEMENT = {"enabled": True, "block_on_failure": True, "log_violations": True}
|
|
197
186
|
```
|
|
198
187
|
|
|
188
|
+
Forbidden-footer detection lives, hardcoded, in `bash_validator`.
|
|
189
|
+
|
|
199
190
|
---
|
|
200
191
|
|
|
201
192
|
## Logs
|
|
@@ -232,7 +223,7 @@ Example entry:
|
|
|
232
223
|
|
|
233
224
|
## See Also
|
|
234
225
|
|
|
235
|
-
-
|
|
226
|
+
- `hooks/modules/validation/commit_validator.py` - Git standards (inlined constants)
|
|
236
227
|
- `.claude/skills/subagent-request-approval/SKILL.md` - Approval-request workflow patterns
|
|
237
228
|
- `.claude/skills/execution/SKILL.md` - Execution workflow patterns
|
|
238
229
|
- `CLAUDE.md` - Orchestrator protocol with T3 workflow
|
package/commands/README.md
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# Commands
|
|
2
|
-
|
|
3
|
-
Slash commands are direct shortcuts into Gaia's orchestration layer. When you type `/gaia` or `/scan-project`, Claude Code detects the slash prefix, finds the matching `.md` file in this directory, and injects its contents as instructions to the currently active orchestrator. There is no subagent spawn — the orchestrator reads the command file and executes inline.
|
|
4
|
-
|
|
5
|
-
This makes slash commands different from agent dispatch. An agent dispatch creates a new Claude Code subprocess with its own identity, skills, and tool set. A slash command is a context injection into the orchestrator's current session. Think of it as a macro: the `.md` file says "when the user invokes this command, do the following." The orchestrator follows those instructions directly.
|
|
6
|
-
|
|
7
|
-
The practical implication is that slash commands are best suited for tasks that the orchestrator can complete by delegating to existing agents — not tasks that require a new agent identity. They are entry points, not agents.
|
|
8
|
-
|
|
9
|
-
## Cuándo se activa
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
User types /command-name [args]
|
|
13
|
-
|
|
|
14
|
-
Claude Code detects / prefix
|
|
15
|
-
|
|
|
16
|
-
Looks up commands/<command-name>.md
|
|
17
|
-
|
|
|
18
|
-
Injects the file's contents into the orchestrator's active context
|
|
19
|
-
|
|
|
20
|
-
Orchestrator reads the command instructions and executes them
|
|
21
|
-
(may dispatch agents, call tools, or respond directly)
|
|
22
|
-
|
|
|
23
|
-
Result returned to user in the current session
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
No subagent is spawned. No new identity is loaded. The orchestrator handles execution within its current session using its existing tool set and the instructions from the command file.
|
|
27
|
-
|
|
28
|
-
## Qué hay aquí
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
commands/
|
|
32
|
-
├── gaia.md # /gaia — invoke the Gaia meta-agent (gaia-system) for system work
|
|
33
|
-
└── scan-project.md # /scan-project — scan codebase, detect stack, update ~/.gaia/gaia.db
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Note: a `/gaia-plan` command is referenced in some older documentation but the file does not exist here. Planning is handled conversationally through the orchestrator and the `gaia-planner` agent — not via a slash command.
|
|
37
|
-
|
|
38
|
-
## Convenciones
|
|
39
|
-
|
|
40
|
-
**File format:**
|
|
41
|
-
|
|
42
|
-
```markdown
|
|
43
|
-
---
|
|
44
|
-
name: command-name
|
|
45
|
-
description: One-line description shown in Claude Code autocomplete
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
# Command Name
|
|
49
|
-
|
|
50
|
-
[Instructions the orchestrator follows when this command is invoked]
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**Registration:** Each command file must also be listed in `build/gaia-ops.manifest.json` under the `commands` array. A file that exists here but is not in the manifest will not appear in Claude Code's slash command list.
|
|
54
|
-
|
|
55
|
-
**Scope:** Commands inject instructions into the orchestrator. If the task requires domain work (Terraform, code changes, cloud ops), the command's instructions should dispatch the appropriate agent — the command itself should not attempt domain execution.
|
|
56
|
-
|
|
57
|
-
**Arguments:** Slash commands can receive arguments after the command name (e.g., `/gaia-plan Add OAuth2 support`). The command's `.md` file can reference these as context, and the orchestrator receives them as part of the injected content.
|
|
58
|
-
|
|
59
|
-
## Ver también
|
|
60
|
-
|
|
61
|
-
- [`build/gaia-ops.manifest.json`](../build/gaia-ops.manifest.json) — command registration
|
|
62
|
-
- [`agents/gaia-system.md`](../agents/gaia-system.md) — the Gaia meta-agent invoked by `/gaia`
|
|
63
|
-
- [`agents/gaia-orchestrator.md`](../agents/gaia-orchestrator.md) — orchestrator that executes command instructions
|
|
64
|
-
- [`skills/gaia-planner/SKILL.md`](../skills/gaia-planner/SKILL.md) — planning workflow (used by gaia-planner agent, not a slash command)
|
package/commands/gaia.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: gaia
|
|
3
|
-
description: Invoke the Gaia meta-agent for system architecture analysis, agent design, skill creation, and orchestration debugging
|
|
4
|
-
allowed-tools:
|
|
5
|
-
- Bash(*)
|
|
6
|
-
- Read
|
|
7
|
-
- Edit
|
|
8
|
-
- Write
|
|
9
|
-
- Glob
|
|
10
|
-
- Grep
|
|
11
|
-
- WebSearch
|
|
12
|
-
- WebFetch
|
|
13
|
-
- Task
|
|
14
|
-
- Agent
|
|
15
|
-
- Skill
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
Invoke the Gaia meta-agent (`gaia-system`) to work on the gaia-ops orchestration
|
|
19
|
-
system itself. This is the entry point for tasks that modify or analyze agents,
|
|
20
|
-
skills, hooks, or system architecture.
|
|
21
|
-
|
|
22
|
-
## When to use
|
|
23
|
-
|
|
24
|
-
- Analyze or improve the gaia-ops architecture
|
|
25
|
-
- Create or update agent definitions (`.md` files)
|
|
26
|
-
- Create or update skills (`SKILL.md` files)
|
|
27
|
-
- Write or debug Python hooks and tools
|
|
28
|
-
- Update `CLAUDE.md` or system configuration
|
|
29
|
-
- Research best practices for agent orchestration
|
|
30
|
-
|
|
31
|
-
## How it works
|
|
32
|
-
|
|
33
|
-
This command delegates to the `gaia-system` agent, which is the meta-agent
|
|
34
|
-
specialized in the orchestration system. It follows the standard agent protocol
|
|
35
|
-
and returns a `agent_contract_handoff` block with findings and status.
|
|
36
|
-
|
|
37
|
-
$ARGUMENTS
|
package/commands/scan-project.md
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: scan-project
|
|
3
|
-
description: Scan the current project to detect stack, infrastructure, tools, and update the project context in ~/.gaia/gaia.db
|
|
4
|
-
allowed-tools:
|
|
5
|
-
- Bash(*)
|
|
6
|
-
- Read
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
Run the gaia modular project scanner to detect the project stack, infrastructure,
|
|
10
|
-
git setup, CLI tools, orchestration, and runtime environment. The scanner writes
|
|
11
|
-
structured, machine-readable context to `~/.gaia/gaia.db` that agents consume.
|
|
12
|
-
|
|
13
|
-
No `project-context.json` file is generated. The DB is the canonical source of
|
|
14
|
-
truth. Use `gaia context show` to inspect the stored context.
|
|
15
|
-
|
|
16
|
-
## What this does
|
|
17
|
-
|
|
18
|
-
The scanner runs 6 independent modules in parallel:
|
|
19
|
-
- **stack** -- languages, frameworks, package managers
|
|
20
|
-
- **git** -- platform, remotes, branching strategy, monorepo detection
|
|
21
|
-
- **infrastructure** -- cloud providers, IaC, CI/CD, containers
|
|
22
|
-
- **orchestration** -- Kubernetes, GitOps (Flux/Argo), Helm charts
|
|
23
|
-
- **tools** -- installed CLI tools (kubectl, terraform, gcloud, etc.)
|
|
24
|
-
- **environment** -- OS info, language runtimes, .env file patterns
|
|
25
|
-
|
|
26
|
-
It preserves agent-enriched sections (data added by agents via update_contracts)
|
|
27
|
-
and merges new scan data with existing context using section-ownership rules.
|
|
28
|
-
Projects that temporarily disappear are soft-deleted (`status='missing'`) and
|
|
29
|
-
reactivated when they reappear -- data is never purged.
|
|
30
|
-
|
|
31
|
-
## How to run
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
gaia scan
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Optional flags:
|
|
38
|
-
- `--verbose` -- show scanner-by-scanner progress
|
|
39
|
-
- `--scanners stack,git` -- run only specific scanners
|
|
40
|
-
- `--check-staleness` -- skip scan if context is already fresh (<24h old)
|
|
41
|
-
|
|
42
|
-
$ARGUMENTS
|
|
43
|
-
|
|
44
|
-
## Expected output
|
|
45
|
-
|
|
46
|
-
The CLI prints a JSON summary to stdout:
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
{
|
|
50
|
-
"status": "success",
|
|
51
|
-
"scanner_version": "0.1.0",
|
|
52
|
-
"sections_updated": ["project_identity", "stack", "git", ...],
|
|
53
|
-
"scanners_run": 6,
|
|
54
|
-
"warnings_count": 0,
|
|
55
|
-
"duration_ms": 2500.0
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
A human-readable summary is also printed to stderr showing scanner count,
|
|
60
|
-
section count, warnings, and elapsed time.
|
|
61
|
-
|
|
62
|
-
## After scanning
|
|
63
|
-
|
|
64
|
-
Inspect the stored context:
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
gaia context show
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Or query a specific section:
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
gaia context get stack
|
|
74
|
-
```
|