@jaguilar87/gaia 5.0.2 → 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/ARCHITECTURE.md +0 -1
- package/CHANGELOG.md +110 -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/approvals.py +23 -21
- 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 -2
- 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 -2
- package/dist/gaia-ops/hooks/modules/agents/contract_validator.py +18 -0
- package/dist/gaia-ops/hooks/modules/agents/handoff_persister.py +214 -2
- package/dist/gaia-ops/hooks/modules/agents/response_contract.py +26 -0
- package/dist/gaia-ops/hooks/modules/agents/transcript_reader.py +15 -0
- package/dist/gaia-ops/hooks/modules/security/__init__.py +0 -5
- package/dist/gaia-ops/hooks/modules/security/approval_grants.py +124 -19
- package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +99 -7
- package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +127 -24
- 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/agent-contract-handoff/SKILL.md +3 -0
- package/dist/gaia-ops/skills/agent-response/SKILL.md +4 -2
- package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +1 -1
- package/dist/gaia-ops/skills/gaia-patterns/reference.md +2 -3
- 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 +30 -7
- package/dist/gaia-ops/skills/orchestrator-present-approval/reference.md +32 -15
- 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/skills/security-tiers/SKILL.md +5 -1
- package/dist/gaia-ops/skills/security-tiers/reference.md +3 -1
- package/dist/gaia-ops/skills/subagent-request-approval/SKILL.md +43 -6
- package/dist/gaia-ops/skills/subagent-request-approval/reference.md +66 -16
- package/dist/gaia-ops/tools/context/README.md +1 -1
- package/dist/gaia-ops/tools/gaia_simulator/extractor.py +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/contract_validator.py +18 -0
- package/dist/gaia-security/hooks/modules/agents/handoff_persister.py +214 -2
- package/dist/gaia-security/hooks/modules/agents/response_contract.py +26 -0
- package/dist/gaia-security/hooks/modules/agents/transcript_reader.py +15 -0
- package/dist/gaia-security/hooks/modules/security/__init__.py +0 -5
- package/dist/gaia-security/hooks/modules/security/approval_grants.py +124 -19
- package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +99 -7
- package/dist/gaia-security/hooks/modules/tools/bash_validator.py +127 -24
- package/dist/gaia-security/hooks/modules/validation/commit_validator.py +90 -55
- package/gaia/state/transitions.py +4 -4
- package/gaia/store/writer.py +56 -0
- package/hooks/modules/README.md +2 -4
- package/hooks/modules/agents/contract_validator.py +18 -0
- package/hooks/modules/agents/handoff_persister.py +214 -2
- package/hooks/modules/agents/response_contract.py +26 -0
- package/hooks/modules/agents/transcript_reader.py +15 -0
- package/hooks/modules/security/__init__.py +0 -5
- package/hooks/modules/security/approval_grants.py +124 -19
- package/hooks/modules/security/mutative_verbs.py +99 -7
- package/hooks/modules/tools/bash_validator.py +127 -24
- 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/agent-contract-handoff/SKILL.md +3 -0
- package/skills/agent-response/SKILL.md +4 -2
- package/skills/gaia-patterns/SKILL.md +1 -1
- package/skills/gaia-patterns/reference.md +2 -3
- 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 +30 -7
- package/skills/orchestrator-present-approval/reference.md +32 -15
- package/skills/readme-writing/SKILL.md +1 -1
- package/skills/readme-writing/reference.md +0 -1
- package/skills/security-tiers/SKILL.md +5 -1
- package/skills/security-tiers/reference.md +3 -1
- package/skills/subagent-request-approval/SKILL.md +43 -6
- package/skills/subagent-request-approval/reference.md +66 -16
- package/tools/context/README.md +1 -1
- package/tools/gaia_simulator/extractor.py +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/hooks/modules/security/gitops_validator.py +0 -179
- 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/dist/gaia-security/hooks/modules/security/gitops_validator.py +0 -179
- package/git-hooks/commit-msg +0 -41
- package/hooks/modules/security/gitops_validator.py +0 -179
- 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
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
{
|
|
9
9
|
"name": "gaia-ops",
|
|
10
10
|
"description": "Full DevOps orchestration for Claude Code. Eight specialized agents handle the complete development lifecycle — analysis, planning, execution, and deployment. Gaia-Ops scans your codebase to understand it and injects the right context into each sub-agent. Every command is classified by risk: read-only runs freely, state changes pause for your approval, and irreversible operations are permanently blocked.",
|
|
11
|
-
"version": "5.0.
|
|
11
|
+
"version": "5.0.5",
|
|
12
12
|
"category": "devops",
|
|
13
13
|
"author": {
|
|
14
14
|
"name": "jaguilar87",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
{
|
|
21
21
|
"name": "gaia-security",
|
|
22
22
|
"description": "Keeps you in the loop only when it matters. Gaia Security analyzes every command and classifies it into risk tiers: read-only queries run freely, simulations and validations pass through, and state-changing operations (create, delete, apply, push) pause for your explicit approval before executing. Irreversible commands like dropping databases or deleting cloud infrastructure are permanently blocked.",
|
|
23
|
-
"version": "5.0.
|
|
23
|
+
"version": "5.0.5",
|
|
24
24
|
"category": "security",
|
|
25
25
|
"author": {
|
|
26
26
|
"name": "jaguilar87",
|
package/ARCHITECTURE.md
CHANGED
|
@@ -72,7 +72,6 @@ Order is short-circuit -- first match wins:
|
|
|
72
72
|
| If mutative + no active grant -> generate nonce, block
|
|
73
73
|
| If mutative + active grant -> allow (T3)
|
|
74
74
|
| If not mutative -> safe by elimination (T0)
|
|
75
|
-
6. gitops_validator --> GitOps policy for kubectl/helm/flux
|
|
76
75
|
```
|
|
77
76
|
|
|
78
77
|
### Task/Agent Validation
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,116 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [5.0.5] - 2026-06-11
|
|
11
|
+
|
|
12
|
+
### Repository Hygiene, Python 3.11 Floor, v18 Schema Floor + Drift Guard, Release-Pipeline Hardening
|
|
13
|
+
|
|
14
|
+
Maintenance release focused on shrinking the surface area and hardening the release pipeline. Dead and redundant surfaces are removed, Python 3.9 support is dropped (minimum is now 3.11), the database migration history is collapsed to a v18 floor backed by a new build-time schema-drift guard, git-format rules are inlined into their single consumer, and several release-pipeline bugs that caused CI re-triggers and stale local installs are fixed.
|
|
15
|
+
|
|
16
|
+
#### Added
|
|
17
|
+
|
|
18
|
+
- **Schema-drift guard wired into pre-publish validation** — a new build/pre-publish
|
|
19
|
+
check (`scripts/check_schema_drift.py` + a recorded fingerprint in
|
|
20
|
+
`scripts/migrations/schema.checksum`, wired into pre-publish-validate **Step 5c**)
|
|
21
|
+
fails the build if `gaia/store/schema.sql` changes without a matching schema version
|
|
22
|
+
bump and migration. This makes silent schema drift impossible to ship: any edit to
|
|
23
|
+
the schema must be accompanied by a version bump, or the gate stops the release.
|
|
24
|
+
|
|
25
|
+
#### Changed
|
|
26
|
+
|
|
27
|
+
- **Python minimum is now 3.11 (Python 3.9 dropped)** — `pyproject.toml`
|
|
28
|
+
`requires-python`, the ruff target version, and the CI test matrix all move to 3.11
|
|
29
|
+
as the floor. The dead `scripts/check-py39-compat.py` compatibility checker and its
|
|
30
|
+
npm alias are removed along with the 3.9 support.
|
|
31
|
+
|
|
32
|
+
- **Database migration history collapsed to a v18 floor** — fresh installs now stamp
|
|
33
|
+
schema **v18** directly instead of replaying the full migration chain. Databases below
|
|
34
|
+
the v18 floor are rejected cleanly with guidance to recreate, rather than attempting an
|
|
35
|
+
unsupported incremental upgrade. The per-step `vN_to_vN+1` migration SQL and their
|
|
36
|
+
obsolete version-specific tests are removed.
|
|
37
|
+
|
|
38
|
+
- **Git commit-format rules inlined into their single consumer** — the commit-format
|
|
39
|
+
rules previously in `config/git_standards.json` are inlined directly into
|
|
40
|
+
`commit_validator.py` (its only reader), and the standalone config file is removed.
|
|
41
|
+
Forbidden-footer enforcement is consolidated into `bash_validator` (the duplicate dead
|
|
42
|
+
check is removed); runtime AI-attribution footer stripping continues to live in
|
|
43
|
+
`bash_validator`. The git-conventions skill is updated to match.
|
|
44
|
+
|
|
45
|
+
- **Release pipeline hardened** — `publish.yml` now runs on Python 3.11 and appends
|
|
46
|
+
`[skip ci]` to the dist commit-back, stopping the CI re-trigger / version-churn loop
|
|
47
|
+
that re-ran the pipeline on every published dist commit. `gaia:install-local` now
|
|
48
|
+
rebuilds plugins before packing so a local install can never carry a stale `dist/`.
|
|
49
|
+
`ci.yml` drops the obsolete `settings.json` build assertions, and the gaia-release
|
|
50
|
+
skill drift is corrected.
|
|
51
|
+
|
|
52
|
+
- **pytest tmp uses the default OS tmpdir** — the in-repo pytest `basetemp` that
|
|
53
|
+
polluted the working tree (and broke scanner project-identity isolation) is removed;
|
|
54
|
+
tests now use the default OS temporary directory. `config/README.md` is rewritten to
|
|
55
|
+
match the actual directory contents.
|
|
56
|
+
|
|
57
|
+
#### Removed
|
|
58
|
+
|
|
59
|
+
- **Dead and redundant surfaces and artifacts** — removed `evidence/`, `docs/`,
|
|
60
|
+
`git-hooks/` (the redundant `commit-msg` sed copy; runtime footer stripping stays in
|
|
61
|
+
`bash_validator`), `tools/agentic-loop/`, `tools/review/`, `logs/`, the `commands/`
|
|
62
|
+
slash-command surface (including `/gaia`), the `templates/` managed-settings surface,
|
|
63
|
+
and `config/crons-schema.md`. These were either unused, duplicated by an active code
|
|
64
|
+
path, or superseded surfaces with no remaining consumer.
|
|
65
|
+
|
|
66
|
+
## [5.0.4] - 2026-06-06
|
|
67
|
+
|
|
68
|
+
### COMMAND_SET Batch Approval, Consent-Reducing Approval Verbs, Contract Advisory Field, Version Source Sync
|
|
69
|
+
|
|
70
|
+
Patch release superseding 5.0.3 (which was never published to npm due to a pyproject.toml version drift that failed pre-publish validation). This release adds the version source sync fix on top of all 5.0.3 changes: COMMAND_SET batch-approval wired end-to-end, consent-reducing approval verbs reclassified out of T3, advisory contract field added, redundant `gitops_validator` removed, and all version sources (package.json, pyproject.toml, .claude-plugin/plugin.json, .claude-plugin/marketplace.json, CHANGELOG.md) aligned. Full suite green (4555 passed).
|
|
71
|
+
|
|
72
|
+
#### Added
|
|
73
|
+
|
|
74
|
+
- **COMMAND_SET batch approval, end-to-end** — a payload carrying a `command_set`
|
|
75
|
+
of more than one mutative command now activates into ONE `COMMAND_SET` grant
|
|
76
|
+
covering the whole batch instead of being degraded to a single command. The
|
|
77
|
+
create side (`activate_db_pending_by_prefix` Step 3b in `approval_grants.py`,
|
|
78
|
+
fed by `_intake_command_set_pending` in `handoff_persister.py` and persisted via
|
|
79
|
+
`gaia/store/writer.py`) was previously orphaned; it is now wired to the
|
|
80
|
+
byte-for-byte consume path in `bash_validator`. The batch is consumed
|
|
81
|
+
item-by-item under a single consent.
|
|
82
|
+
|
|
83
|
+
- **Advisory `user_facing_summary` field on the agent contract** — an additive,
|
|
84
|
+
optional field in the `agent_contract_handoff` envelope (`contract_validator.py`,
|
|
85
|
+
`response_contract.py`) carrying a human-readable summary for the orchestrator to
|
|
86
|
+
surface. Purely additive; absence does not affect validation.
|
|
87
|
+
|
|
88
|
+
#### Changed
|
|
89
|
+
|
|
90
|
+
- **Consent-reducing approval verbs are no longer T3** — `gaia approvals
|
|
91
|
+
revoke|reject|reject-all|clean` only revoke or discard grants Gaia itself issued
|
|
92
|
+
(they reduce capability, never reach remote state), so they are reclassified out
|
|
93
|
+
of T3 via `CONSENT_REDUCING_SUBCOMMAND_EXCEPTIONS` in `mutative_verbs.py`. `gaia
|
|
94
|
+
approvals approve` *grants* capability and remains T3.
|
|
95
|
+
|
|
96
|
+
- **`gaia approvals revoke` unified with auto-detect** — `revoke` now auto-detects
|
|
97
|
+
a pending approval (pending → grant) and the separate `revoke-v2` command was
|
|
98
|
+
removed. Behavior is otherwise unchanged.
|
|
99
|
+
|
|
100
|
+
- **Plan-first heuristic** — COMMAND_SET is now treated as a judgment call, not a
|
|
101
|
+
default, when deciding how to present batched mutative work.
|
|
102
|
+
|
|
103
|
+
#### Fixed
|
|
104
|
+
|
|
105
|
+
- **Guard empty/None `transcript_path`** — `transcript_reader.py` now guards against
|
|
106
|
+
an empty or `None` transcript path instead of failing downstream during nonce
|
|
107
|
+
extraction.
|
|
108
|
+
|
|
109
|
+
- **Harden AI-attribution footer stripping** — the attribution-footer stripping in
|
|
110
|
+
`bash_validator.py` is hardened against additional footer shapes.
|
|
111
|
+
|
|
112
|
+
#### Removed
|
|
113
|
+
|
|
114
|
+
- **Redundant `gitops_validator`** — `hooks/modules/security/gitops_validator.py` and
|
|
115
|
+
its test are removed; its responsibilities are covered by the unified bash
|
|
116
|
+
validation path. All references (security `__init__`, `bash_validator` import/call,
|
|
117
|
+
simulator extractor, surface-routing config, architecture docs, and skill/README
|
|
118
|
+
references) are cleaned up.
|
|
119
|
+
|
|
10
120
|
## [5.0.2] - 2026-06-03
|
|
11
121
|
|
|
12
122
|
### Approval-Flow Hardening, mkdir Reclassification, Jira Skill
|
package/INSTALL.md
CHANGED
|
@@ -172,7 +172,6 @@ your-project/
|
|
|
172
172
|
│ ├── hooks/ (symlink) → Security validations
|
|
173
173
|
│ ├── commands/ (symlink) → Slash commands
|
|
174
174
|
│ ├── config/ (symlink) → Configuration (contracts, rules)
|
|
175
|
-
│ ├── templates/ (symlink) → Installation templates
|
|
176
175
|
│ ├── logs/ ← Audit logs
|
|
177
176
|
│ ├── approvals/ ← Pending T3 approval files
|
|
178
177
|
│ ├── plugin-registry.json ← installed[].name = "gaia-ops"
|
|
@@ -204,7 +203,6 @@ Once installed, you have access to **complete documentation** in each directory:
|
|
|
204
203
|
├── config/README.md Contracts, git standards, surface routing
|
|
205
204
|
├── hooks/README.md 8 hook scripts (4 primary + 4 event handlers)
|
|
206
205
|
├── tools/ Context, memory, validation, review
|
|
207
|
-
├── templates/README.md Installation templates
|
|
208
206
|
└── bin/README.md CLI utilities
|
|
209
207
|
```
|
|
210
208
|
|
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ UserPromptSubmit -> routing -> PreToolUse -> agent -> PostToolUse -> S
|
|
|
21
21
|
injection
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
That pipeline is the spine. Everything else in this repo is either a component of that pipeline (`hooks/`, `agents/`, `skills/`, `config/`) or infrastructure that supports it (`build/`, `bin/`, `tests
|
|
24
|
+
That pipeline is the spine. Everything else in this repo is either a component of that pipeline (`hooks/`, `agents/`, `skills/`, `config/`) or infrastructure that supports it (`build/`, `bin/`, `tests/`). Start with the folder that matches the behavior you want to understand, and its README will tell you where it fits in the flow.
|
|
25
25
|
|
|
26
26
|
## Overview
|
|
27
27
|
|
|
@@ -150,10 +150,6 @@ Gaia enforces a 6-layer security pipeline:
|
|
|
150
150
|
| Mutative verb detection | `ask` dialog for state-changing ops | User approves via native dialog |
|
|
151
151
|
| Settings deny rules | 147 deny rules in `settings.local.json` | Self-healing (restored each session) |
|
|
152
152
|
|
|
153
|
-
### Enterprise Deployment
|
|
154
|
-
|
|
155
|
-
For organization-wide enforcement, deploy `templates/managed-settings.template.json` as a managed settings policy via Claude.ai Admin Console. Managed settings have the highest precedence and cannot be overridden.
|
|
156
|
-
|
|
157
153
|
## Project Structure
|
|
158
154
|
|
|
159
155
|
```
|
|
@@ -164,7 +160,6 @@ gaia-dev/
|
|
|
164
160
|
├── config/ # Configuration — routing, contracts, rules, git standards
|
|
165
161
|
├── commands/ # Slash commands — /gaia, /scan-project
|
|
166
162
|
├── build/ # Plugin manifests — hook + agent registration for Claude Code
|
|
167
|
-
├── templates/ # Installation templates — managed-settings for enterprise
|
|
168
163
|
├── bin/ # Single `gaia` CLI; subcommands discovered from bin/cli/
|
|
169
164
|
├── tests/ # Test suite — 3-layer pyramid (pytest, LLM eval, e2e)
|
|
170
165
|
└── tools/ # Context provisioning tools
|
package/bin/README.md
CHANGED
|
@@ -110,6 +110,5 @@ A single binary; subcommands are discovered, not registered.
|
|
|
110
110
|
|
|
111
111
|
- [`package.json`](../package.json) -- exposes `bin/gaia`; `scripts.postinstall` / `scripts.preuninstall` wire the lifecycle subcommands
|
|
112
112
|
- [`INSTALL.md`](../INSTALL.md) -- installation workflow that calls `gaia scan` and `gaia install`
|
|
113
|
-
- [`templates/README.md`](../templates/README.md) -- `gaia install` and `gaia scan` consume templates from here
|
|
114
113
|
- [`hooks/README.md`](../hooks/README.md) -- `gaia doctor` verifies the hook registrations are valid
|
|
115
114
|
- [`bin/validate-sandbox.sh`](./validate-sandbox.sh) -- end-to-end harness that drives `gaia` subcommands against a fresh tarball install
|
|
@@ -345,7 +345,7 @@ def merge_local_hooks(
|
|
|
345
345
|
# ---------------------------------------------------------------------------
|
|
346
346
|
|
|
347
347
|
# Directories the package exposes via .claude/<name> symlinks
|
|
348
|
-
_SYMLINK_NAMES = ["agents", "tools", "hooks", "commands", "
|
|
348
|
+
_SYMLINK_NAMES = ["agents", "tools", "hooks", "commands", "config", "skills"]
|
|
349
349
|
# Files (not dirs) we link or copy into .claude/
|
|
350
350
|
_SYMLINK_FILES = ["CHANGELOG.md"]
|
|
351
351
|
|
package/bin/cli/approvals.py
CHANGED
|
@@ -440,13 +440,17 @@ def cmd_show(args) -> int:
|
|
|
440
440
|
# Subcommand: revoke
|
|
441
441
|
# ---------------------------------------------------------------------------
|
|
442
442
|
|
|
443
|
-
def
|
|
444
|
-
"""Revoke an active command_set grant by its approval_id.
|
|
443
|
+
def _revoke_grant(args) -> int:
|
|
444
|
+
"""Revoke an active command_set grant by its approval_id (legacy path).
|
|
445
445
|
|
|
446
446
|
Calls ``writer.revoke_approval_grant(approval_id)`` to mark the grant
|
|
447
447
|
REVOKED in the DB. After revocation, any unconsumed commands in the
|
|
448
448
|
command_set will require fresh approval.
|
|
449
449
|
|
|
450
|
+
This is the legacy ``approval_grants``-table path. It is invoked as the
|
|
451
|
+
fallback by the unified :func:`cmd_revoke` when an id is not found in the
|
|
452
|
+
new ``approvals`` table.
|
|
453
|
+
|
|
450
454
|
Exits 0 on success, 1 if the grant is not found or already in a terminal
|
|
451
455
|
state.
|
|
452
456
|
"""
|
|
@@ -939,18 +943,14 @@ def cmd_pending(args) -> int:
|
|
|
939
943
|
# ---------------------------------------------------------------------------
|
|
940
944
|
|
|
941
945
|
def _resolve_approval_id(raw_id: str) -> str:
|
|
942
|
-
"""Normalize a raw approval_id input.
|
|
946
|
+
"""Normalize a raw approval_id input by trimming surrounding whitespace.
|
|
943
947
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
+
The input is passed through unchanged otherwise -- both the full
|
|
949
|
+
``P-{uuid4hex}`` form and the ``P-XXXX`` short form are returned as-is for
|
|
950
|
+
exact or prefix lookup downstream. (A bare hex string with no ``P-`` prefix
|
|
951
|
+
is also returned untouched; the lookup layer handles that case.)
|
|
948
952
|
"""
|
|
949
|
-
|
|
950
|
-
if stripped.upper().startswith("P-"):
|
|
951
|
-
return stripped
|
|
952
|
-
# Try to detect if it's a bare hex string missing the P- prefix.
|
|
953
|
-
return stripped
|
|
953
|
+
return raw_id.strip()
|
|
954
954
|
|
|
955
955
|
|
|
956
956
|
def cmd_show_v2(args) -> int:
|
|
@@ -1019,14 +1019,16 @@ def cmd_history_single(args) -> int:
|
|
|
1019
1019
|
|
|
1020
1020
|
|
|
1021
1021
|
# ---------------------------------------------------------------------------
|
|
1022
|
-
#
|
|
1022
|
+
# gaia approvals revoke <id> -- unified revoke (auto-detects pending vs grant)
|
|
1023
1023
|
# ---------------------------------------------------------------------------
|
|
1024
1024
|
|
|
1025
|
-
def
|
|
1026
|
-
"""Revoke
|
|
1025
|
+
def cmd_revoke(args) -> int:
|
|
1026
|
+
"""Revoke an approval, auto-detecting which store owns it.
|
|
1027
1027
|
|
|
1028
|
-
|
|
1029
|
-
|
|
1028
|
+
First looks the id up in the new ``approvals`` table. If found and
|
|
1029
|
+
``pending``, inserts a REVOKED event and updates status to 'revoked'.
|
|
1030
|
+
If the id is not present in the new table, falls back to the legacy
|
|
1031
|
+
command_set grant path (:func:`_revoke_grant`).
|
|
1030
1032
|
|
|
1031
1033
|
With ``--yes``, skips the interactive confirmation prompt.
|
|
1032
1034
|
Exits 0 on success, 1 on error.
|
|
@@ -1042,8 +1044,8 @@ def cmd_revoke_v2(args) -> int:
|
|
|
1042
1044
|
return 1
|
|
1043
1045
|
|
|
1044
1046
|
if approval is None:
|
|
1045
|
-
# Fall back to
|
|
1046
|
-
return
|
|
1047
|
+
# Fall back to legacy grant revoke if not found in new table.
|
|
1048
|
+
return _revoke_grant(args)
|
|
1047
1049
|
|
|
1048
1050
|
current_status = approval.get("status", "?")
|
|
1049
1051
|
if current_status != "pending":
|
|
@@ -1596,7 +1598,7 @@ def register(subparsers) -> None:
|
|
|
1596
1598
|
help="Full approval_id (P-{uuid4hex}) of the approval to revoke",
|
|
1597
1599
|
)
|
|
1598
1600
|
p_revoke.add_argument("--yes", action="store_true", help="Skip confirmation prompt")
|
|
1599
|
-
p_revoke.set_defaults(func=
|
|
1601
|
+
p_revoke.set_defaults(func=cmd_revoke)
|
|
1600
1602
|
|
|
1601
1603
|
# approve (T3.3) -- cross-session grant
|
|
1602
1604
|
p_approve = sub.add_parser(
|
|
@@ -1839,7 +1841,7 @@ def _build_standalone_parser() -> argparse.ArgumentParser:
|
|
|
1839
1841
|
p_revoke = subparsers.add_parser("revoke", help="Revoke a pending approval")
|
|
1840
1842
|
p_revoke.add_argument("approval_id", metavar="APPROVAL_ID")
|
|
1841
1843
|
p_revoke.add_argument("--yes", action="store_true")
|
|
1842
|
-
p_revoke.set_defaults(func=
|
|
1844
|
+
p_revoke.set_defaults(func=cmd_revoke)
|
|
1843
1845
|
|
|
1844
1846
|
p_history = subparsers.add_parser("history", help="Show approval history")
|
|
1845
1847
|
p_history.add_argument("approval_id", metavar="APPROVAL_ID", nargs="?")
|
package/bin/cli/cleanup.py
CHANGED
package/bin/cli/doctor.py
CHANGED
|
@@ -762,7 +762,7 @@ def _extract_check_values(
|
|
|
762
762
|
@register_check("Symlinks", order=50)
|
|
763
763
|
def check_symlinks(project_root: Path) -> dict:
|
|
764
764
|
"""Check .claude/ symlinks resolve to package content."""
|
|
765
|
-
names = ["agents", "tools", "hooks", "commands", "
|
|
765
|
+
names = ["agents", "tools", "hooks", "commands", "config", "skills", "CHANGELOG.md"]
|
|
766
766
|
critical = {"agents", "hooks", "skills"}
|
|
767
767
|
valid = 0
|
|
768
768
|
has_critical_missing = False
|
package/bin/cli/memory.py
CHANGED
|
@@ -19,6 +19,8 @@ Mutating subcommands operate on the curated ``memory`` table in
|
|
|
19
19
|
~/.claude/projects/.../memory/).
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
22
24
|
# Repo-root import bootstrap so ``from gaia.store.writer import ...`` resolves
|
|
23
25
|
# regardless of cwd (the CLI is launched from many places).
|
|
24
26
|
import sys as _sys
|
package/bin/cli/update.py
CHANGED
|
@@ -256,7 +256,7 @@ def _run_verification(claude_dir: Path) -> dict:
|
|
|
256
256
|
issues.append(f"project-context DB read error: {exc}")
|
|
257
257
|
|
|
258
258
|
# 4. Config files
|
|
259
|
-
config_files = ["
|
|
259
|
+
config_files = ["surface-routing.json"]
|
|
260
260
|
for cfg in config_files:
|
|
261
261
|
path = claude_dir / "config" / cfg
|
|
262
262
|
ok = path.exists()
|
|
@@ -324,12 +324,9 @@ class PrePublishValidator {
|
|
|
324
324
|
'hooks',
|
|
325
325
|
'agents',
|
|
326
326
|
'skills',
|
|
327
|
-
'commands',
|
|
328
327
|
'config',
|
|
329
|
-
'templates',
|
|
330
328
|
'tools',
|
|
331
329
|
'dist',
|
|
332
|
-
'git-hooks',
|
|
333
330
|
];
|
|
334
331
|
|
|
335
332
|
const missing = [];
|
|
@@ -385,6 +382,52 @@ class PrePublishValidator {
|
|
|
385
382
|
this.log('✓ All critical directories covered by package.json files', 'success');
|
|
386
383
|
}
|
|
387
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Schema-drift guard.
|
|
387
|
+
*
|
|
388
|
+
* Fails the publish if gaia/store/schema.sql changed without a corresponding
|
|
389
|
+
* EXPECTED_SCHEMA_VERSION bump + migration file. Without this guard, schema
|
|
390
|
+
* drift is only caught at runtime by `gaia doctor` (as a warning) -- here we
|
|
391
|
+
* make it a hard, non-zero build failure.
|
|
392
|
+
*
|
|
393
|
+
* The actual logic lives in scripts/check_schema_drift.py (fingerprint of
|
|
394
|
+
* schema.sql pinned to the version in scripts/migrations/schema.checksum).
|
|
395
|
+
* This method just invokes it and surfaces a non-zero exit as a failure.
|
|
396
|
+
*/
|
|
397
|
+
validateSchemaDrift() {
|
|
398
|
+
this.log('Step 5c: Schema-drift guard (schema.sql vs EXPECTED_SCHEMA_VERSION)...', 'info');
|
|
399
|
+
|
|
400
|
+
const guardPath = path.join(GAIA_OPS_ROOT, 'scripts', 'check_schema_drift.py');
|
|
401
|
+
if (!fs.existsSync(guardPath)) {
|
|
402
|
+
this.log(`✗ schema-drift guard missing: ${guardPath}`, 'error');
|
|
403
|
+
throw new Error('scripts/check_schema_drift.py not found -- cannot verify schema drift');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const pyCmd = findPython();
|
|
407
|
+
if (!pyCmd) {
|
|
408
|
+
// Python is required for the runtime; a publish that cannot run the
|
|
409
|
+
// guard cannot prove the schema is consistent, so fail rather than skip.
|
|
410
|
+
this.log('✗ Python not available -- cannot run schema-drift guard', 'error');
|
|
411
|
+
throw new Error('Python interpreter not found; schema-drift guard cannot run');
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
const out = this.execute(`${pyCmd} "${guardPath}"`, GAIA_OPS_ROOT, true);
|
|
416
|
+
out.trim().split('\n').filter(Boolean).forEach(line => this.log(` ${line}`, 'info'));
|
|
417
|
+
this.log('✓ No schema drift detected', 'success');
|
|
418
|
+
} catch (error) {
|
|
419
|
+
// execSync throws on non-zero exit; surface the guard's own stderr/stdout.
|
|
420
|
+
const detail = (error.stderr || error.stdout || error.message || '').toString().trim();
|
|
421
|
+
this.log('✗ Schema-drift guard failed:', 'error');
|
|
422
|
+
if (detail) detail.split('\n').forEach(line => console.error(` ${line}`));
|
|
423
|
+
throw new Error(
|
|
424
|
+
'Schema drift detected: gaia/store/schema.sql changed without a ' +
|
|
425
|
+
'version bump + migration. Bump EXPECTED_SCHEMA_VERSION in ' +
|
|
426
|
+
'bin/cli/doctor.py and add the migration, then re-run the guard.'
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
388
431
|
validatePluginManifest() {
|
|
389
432
|
this.log('Step 6: Validating plugin manifest (.claude-plugin/plugin.json)...', 'info');
|
|
390
433
|
|
|
@@ -440,8 +483,7 @@ class PrePublishValidator {
|
|
|
440
483
|
// Test 1: Validate JSON files
|
|
441
484
|
this.log('Test 1: Validating JSON configuration files...', 'info');
|
|
442
485
|
const jsonFiles = [
|
|
443
|
-
'config/clarification_rules.json'
|
|
444
|
-
'config/git_standards.json'
|
|
486
|
+
'config/clarification_rules.json'
|
|
445
487
|
];
|
|
446
488
|
|
|
447
489
|
jsonFiles.forEach(file => {
|
|
@@ -654,6 +696,7 @@ class PrePublishValidator {
|
|
|
654
696
|
this.validateFiles();
|
|
655
697
|
}
|
|
656
698
|
this.validateFilesCoverage();
|
|
699
|
+
this.validateSchemaDrift();
|
|
657
700
|
this.validatePluginManifest();
|
|
658
701
|
this.runTests();
|
|
659
702
|
|
package/config/README.md
CHANGED
|
@@ -1,68 +1,46 @@
|
|
|
1
1
|
# Config
|
|
2
2
|
|
|
3
|
-
Configuration lives here, separate from hooks, because these are data files — not code. Hooks are Python scripts that run at runtime; config files are JSON documents that those scripts read to make decisions. Keeping them apart means you can audit and change system behavior (
|
|
3
|
+
Configuration lives here, separate from hooks, because these are data files — not code. Hooks are Python scripts that run at runtime; config files are JSON documents that those scripts read to make decisions. Keeping them apart means you can audit and change system behavior (what git commit patterns are allowed, which surfaces route where) without touching executable code. It also makes the config files version-controllable and reviewable on their own terms.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The routing table is consumed at a well-defined point in the request lifecycle: on every user prompt. It is not loaded eagerly at startup — it is parsed exactly when `surface_router.py` is invoked. (Git commit standards used to live here too, in `git_standards.json`; they are now inlined as module-level constants in `hooks/modules/validation/commit_validator.py` — the single runtime consumer of those rules — so this folder no longer owns them.)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## When activated
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
This component does not activate as a runtime process. Each file is read on-demand by the module that needs it. The table below shows the read point for each file.
|
|
12
|
-
|
|
13
|
-
**Cuándo se lee cada archivo:**
|
|
14
|
-
|
|
15
|
-
| File | Read by | When |
|
|
16
|
-
|------|---------|------|
|
|
17
|
-
| `surface-routing.json` | `hooks/user_prompt_submit.py` | Every prompt — determines routing recommendation injected into orchestrator context |
|
|
18
|
-
| `context-contracts.json` | `gaia install` / `gaia update` | One-time at install; populates `~/.gaia/gaia.db` tables. Runtime reads come from DB. |
|
|
19
|
-
| `git_standards.json` | `hooks/modules/validation/commit_validator.py` | Every `git commit` call intercepted by PreToolUse |
|
|
20
|
-
| `cloud/gcp.json` | `tools/context/context_provider.py` | Agent dispatch when `cloud_provider = gcp` in workspace DB record |
|
|
21
|
-
| `cloud/aws.json` | `tools/context/context_provider.py` | Agent dispatch when `cloud_provider = aws` in workspace DB record |
|
|
22
|
-
|
|
23
|
-
**Base + cloud merge flow:**
|
|
9
|
+
This folder has no single activation event. Each file is read on-demand by the module that owns it.
|
|
24
10
|
|
|
25
11
|
```
|
|
26
|
-
|
|
12
|
+
User submits a prompt
|
|
27
13
|
|
|
|
28
|
-
hooks/
|
|
14
|
+
hooks/user_prompt_submit.py fires
|
|
29
15
|
|
|
|
30
|
-
|
|
16
|
+
tools/context/surface_router.py calls load_surface_routing_config()
|
|
31
17
|
|
|
|
32
|
-
Reads
|
|
18
|
+
Reads config/surface-routing.json
|
|
33
19
|
|
|
|
34
|
-
|
|
35
|
-
|
|
|
36
|
-
Result: complete contract for this agent on this cloud
|
|
37
|
-
|
|
|
38
|
-
Agent receives filtered project-context sections
|
|
20
|
+
Returns surface match + recommended agent injected into orchestrator context
|
|
39
21
|
```
|
|
40
22
|
|
|
41
|
-
|
|
23
|
+
If `surface-routing.json` is absent, `load_surface_routing_config()` returns a degraded config (`"version": "missing"`) and routing falls back to the `reconnaissance_agent` default.
|
|
24
|
+
|
|
25
|
+
## What's here
|
|
42
26
|
|
|
43
27
|
```
|
|
44
28
|
config/
|
|
45
|
-
├──
|
|
46
|
-
├── surface-routing.json # Intent classification and agent routing signals
|
|
47
|
-
├── git_standards.json # Commit type allowlist, footer rules, Conventional Commits config
|
|
48
|
-
├── cloud/
|
|
49
|
-
│ ├── gcp.json # GCP-specific context sections (extends base contracts)
|
|
50
|
-
│ └── aws.json # AWS-specific context sections (extends base contracts)
|
|
29
|
+
├── surface-routing.json # Surface→agent routing table; consumed by tools/context/surface_router.py on every prompt
|
|
51
30
|
└── README.md
|
|
52
31
|
```
|
|
53
32
|
|
|
54
|
-
##
|
|
33
|
+
## Conventions
|
|
55
34
|
|
|
56
|
-
**
|
|
35
|
+
**surface-routing.json schema:** Top-level keys are `version`, `reconnaissance_agent`, and `surfaces`. Each surface entry has `intent` (human description), `primary_agent` (agent id to dispatch), `adjacent_surfaces` (list of related surface names), `contract_sections` (context sections injected for that surface), `required_checks` (agent checklist), and `signals` with `keywords`, `commands`, and `artifacts` sub-lists. `surface_router.py` scores surfaces by matching task text against all signal lists; the highest-scoring surface wins.
|
|
57
36
|
|
|
58
|
-
**
|
|
37
|
+
**Git commit standards (no longer in this folder):** The Conventional Commits rules — allowed types, subject/body length limits, subject rules — are inlined as module-level constants (`TYPE_ALLOWED`, `SUBJECT_MAX_LENGTH`, `SUBJECT_RULES`, `BODY_MAX_LINE_LENGTH`, `ENFORCEMENT`) in `hooks/modules/validation/commit_validator.py`. Forbidden-footer detection lives, hardcoded, in `bash_validator`. To add a new commit type, edit `TYPE_ALLOWED` in `commit_validator.py`.
|
|
59
38
|
|
|
60
|
-
**
|
|
39
|
+
**Adding a new surface:** Add an entry to `surfaces` in `surface-routing.json` with all required sub-keys. Update L1 routing tests and the `gaia_system` signals if the new surface involves Gaia components.
|
|
61
40
|
|
|
62
|
-
##
|
|
41
|
+
## See also
|
|
63
42
|
|
|
64
|
-
- [
|
|
65
|
-
- [`hooks/user_prompt_submit.py`](../hooks/user_prompt_submit.py) —
|
|
66
|
-
- [`hooks/modules/validation
|
|
67
|
-
- [`
|
|
68
|
-
- [`agents/README.md`](../agents/README.md) — agent names that must match context-contracts.json keys
|
|
43
|
+
- [`tools/context/surface_router.py`](../tools/context/surface_router.py) — loads and scores `surface-routing.json`; the routing pillar source of truth
|
|
44
|
+
- [`hooks/user_prompt_submit.py`](../hooks/user_prompt_submit.py) — calls `classify_surfaces` from `surface_router` on every prompt
|
|
45
|
+
- [`hooks/modules/validation/commit_validator.py`](../hooks/modules/validation/commit_validator.py) — enforces Conventional Commits on every `git commit`; standards inlined as module-level constants
|
|
46
|
+
- [`skills/git-conventions/`](../skills/git-conventions/) — the agent-facing skill teaching the commit conventions
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"infrastructure",
|
|
18
18
|
"orchestration",
|
|
19
19
|
"cluster_details",
|
|
20
|
-
"monitoring_observability",
|
|
21
20
|
"application_services",
|
|
22
21
|
"infrastructure_topology",
|
|
23
22
|
"architecture_overview"
|
|
@@ -364,7 +363,6 @@
|
|
|
364
363
|
"hooks/",
|
|
365
364
|
"skills/",
|
|
366
365
|
"agents/",
|
|
367
|
-
"templates/",
|
|
368
366
|
"claude.md",
|
|
369
367
|
"project-context.json"
|
|
370
368
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gaia-ops",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.5",
|
|
4
4
|
"description": "Full DevOps orchestration for Claude Code. Eight specialized agents handle the complete development lifecycle \u2014 analysis, planning, execution, and deployment. Gaia-Ops scans your codebase to understand it and injects the right context into each sub-agent. Every command is classified by risk: read-only runs freely, state changes pause for your approval, and irreversible operations are permanently blocked.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "jaguilar87",
|