@jaguilar87/gaia 5.0.4 → 5.0.6

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.
Files changed (113) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +65 -0
  4. package/INSTALL.md +0 -2
  5. package/README.md +1 -6
  6. package/bin/README.md +0 -1
  7. package/bin/cli/_install_helpers.py +1 -1
  8. package/bin/cli/cleanup.py +0 -1
  9. package/bin/cli/doctor.py +2 -2
  10. package/bin/cli/memory.py +2 -0
  11. package/bin/cli/update.py +1 -1
  12. package/bin/pre-publish-validate.js +48 -5
  13. package/config/README.md +22 -44
  14. package/config/surface-routing.json +0 -1
  15. package/dist/gaia-ops/.claude-plugin/plugin.json +1 -1
  16. package/dist/gaia-ops/config/README.md +22 -44
  17. package/dist/gaia-ops/config/surface-routing.json +0 -1
  18. package/dist/gaia-ops/hooks/modules/agents/handoff_persister.py +2 -0
  19. package/dist/gaia-ops/hooks/modules/security/approval_grants.py +2 -0
  20. package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +2 -0
  21. package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +90 -55
  22. package/dist/gaia-ops/skills/README.md +1 -1
  23. package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +1 -1
  24. package/dist/gaia-ops/skills/gaia-patterns/reference.md +0 -1
  25. package/dist/gaia-ops/skills/gaia-release/SKILL.md +60 -24
  26. package/dist/gaia-ops/skills/gaia-release/reference.md +35 -11
  27. package/dist/gaia-ops/skills/git-conventions/SKILL.md +6 -2
  28. package/dist/gaia-ops/skills/orchestrator-present-approval/SKILL.md +10 -2
  29. package/dist/gaia-ops/skills/readme-writing/SKILL.md +1 -1
  30. package/dist/gaia-ops/skills/readme-writing/reference.md +0 -1
  31. package/dist/gaia-ops/tools/scan/ui.py +20 -4
  32. package/dist/gaia-ops/tools/scan/verify.py +3 -3
  33. package/dist/gaia-ops/tools/validation/README.md +15 -24
  34. package/dist/gaia-security/.claude-plugin/plugin.json +1 -1
  35. package/dist/gaia-security/hooks/modules/agents/handoff_persister.py +2 -0
  36. package/dist/gaia-security/hooks/modules/security/approval_grants.py +2 -0
  37. package/dist/gaia-security/hooks/modules/tools/bash_validator.py +2 -0
  38. package/dist/gaia-security/hooks/modules/validation/commit_validator.py +90 -55
  39. package/hooks/modules/agents/handoff_persister.py +2 -0
  40. package/hooks/modules/security/approval_grants.py +2 -0
  41. package/hooks/modules/tools/bash_validator.py +2 -0
  42. package/hooks/modules/validation/commit_validator.py +90 -55
  43. package/index.js +2 -12
  44. package/package.json +4 -6
  45. package/pyproject.toml +3 -3
  46. package/scripts/bootstrap_database.sh +88 -439
  47. package/scripts/check_schema_drift.py +208 -0
  48. package/scripts/migrations/README.md +78 -28
  49. package/scripts/migrations/schema.checksum +8 -0
  50. package/scripts/release-prepare.mjs +199 -0
  51. package/skills/README.md +1 -1
  52. package/skills/gaia-patterns/SKILL.md +1 -1
  53. package/skills/gaia-patterns/reference.md +0 -1
  54. package/skills/gaia-release/SKILL.md +60 -24
  55. package/skills/gaia-release/reference.md +35 -11
  56. package/skills/git-conventions/SKILL.md +6 -2
  57. package/skills/orchestrator-present-approval/SKILL.md +10 -2
  58. package/skills/readme-writing/SKILL.md +1 -1
  59. package/skills/readme-writing/reference.md +0 -1
  60. package/tools/scan/ui.py +20 -4
  61. package/tools/scan/verify.py +3 -3
  62. package/tools/validation/README.md +15 -24
  63. package/commands/README.md +0 -64
  64. package/commands/gaia.md +0 -37
  65. package/commands/scan-project.md +0 -74
  66. package/config/crons-schema.md +0 -81
  67. package/config/git_standards.json +0 -72
  68. package/dist/gaia-ops/commands/gaia.md +0 -37
  69. package/dist/gaia-ops/config/crons-schema.md +0 -81
  70. package/dist/gaia-ops/config/git_standards.json +0 -72
  71. package/dist/gaia-ops/tools/agentic-loop/decide-status.py +0 -210
  72. package/dist/gaia-ops/tools/agentic-loop/parse-metric.py +0 -106
  73. package/dist/gaia-ops/tools/agentic-loop/record-iteration.py +0 -223
  74. package/git-hooks/commit-msg +0 -41
  75. package/scripts/migrations/v10_to_v11.sql +0 -170
  76. package/scripts/migrations/v10_to_v11_fresh.sql +0 -18
  77. package/scripts/migrations/v11_to_v12.sql +0 -195
  78. package/scripts/migrations/v11_to_v12_fresh.sql +0 -19
  79. package/scripts/migrations/v12_to_v13.sql +0 -48
  80. package/scripts/migrations/v12_to_v13_fresh.sql +0 -17
  81. package/scripts/migrations/v13_to_v14.sql +0 -44
  82. package/scripts/migrations/v13_to_v14_fresh.sql +0 -17
  83. package/scripts/migrations/v14_to_v15.sql +0 -71
  84. package/scripts/migrations/v14_to_v15_fresh.sql +0 -19
  85. package/scripts/migrations/v15_to_v16.sql +0 -57
  86. package/scripts/migrations/v15_to_v16_fresh.sql +0 -18
  87. package/scripts/migrations/v16_to_v17.sql +0 -51
  88. package/scripts/migrations/v16_to_v17_fresh.sql +0 -18
  89. package/scripts/migrations/v17_to_v18.sql +0 -66
  90. package/scripts/migrations/v17_to_v18_fresh.sql +0 -24
  91. package/scripts/migrations/v1_to_v2.sql +0 -97
  92. package/scripts/migrations/v2_to_v3.sql +0 -68
  93. package/scripts/migrations/v2_to_v3_merge.sql +0 -69
  94. package/scripts/migrations/v3_to_v4.sql +0 -67
  95. package/scripts/migrations/v3_to_v4_fresh.sql +0 -20
  96. package/scripts/migrations/v4_to_v5.sql +0 -55
  97. package/scripts/migrations/v4_to_v5_fresh.sql +0 -20
  98. package/scripts/migrations/v5_to_v6.sql +0 -48
  99. package/scripts/migrations/v5_to_v6_fresh.sql +0 -17
  100. package/scripts/migrations/v6_to_v7.sql +0 -26
  101. package/scripts/migrations/v6_to_v7_fresh.sql +0 -13
  102. package/scripts/migrations/v7_to_v8.sql +0 -44
  103. package/scripts/migrations/v7_to_v8_fresh.sql +0 -14
  104. package/scripts/migrations/v8_to_v9.sql +0 -87
  105. package/scripts/migrations/v8_to_v9_fresh.sql +0 -15
  106. package/scripts/migrations/v9_to_v10.sql +0 -109
  107. package/scripts/migrations/v9_to_v10_episodes_workspace.sql +0 -109
  108. package/scripts/migrations/v9_to_v10_fresh.sql +0 -18
  109. package/templates/README.md +0 -70
  110. package/templates/managed-settings.template.json +0 -43
  111. package/tools/agentic-loop/decide-status.py +0 -210
  112. package/tools/agentic-loop/parse-metric.py +0 -106
  113. 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.4",
11
+ "version": "5.0.6",
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.4",
23
+ "version": "5.0.6",
24
24
  "category": "security",
25
25
  "author": {
26
26
  "name": "jaguilar87",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gaia-ops",
3
- "version": "5.0.4",
3
+ "version": "5.0.6",
4
4
  "description": "Security-first orchestrator with specialized agents, hooks, and governance for AI coding",
5
5
  "author": {
6
6
  "name": "jaguilar87",
package/CHANGELOG.md CHANGED
@@ -7,6 +7,71 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [5.0.6] - 2026-06-12
11
+
12
+ ### Fixed
13
+
14
+ - **`gaia doctor` no longer reports a freshly-installed workspace as "degraded"
15
+ (rc=1)** — an empty project-context contracts table is now `info` (an advisory
16
+ to run `gaia scan`) instead of `warning`, so a clean install passes doctor with
17
+ rc=0. Fixes the post-publish sandbox-validation failure seen in 5.0.5.
18
+
19
+ ## [5.0.5] - 2026-06-11
20
+
21
+ ### Repository Hygiene, Python 3.11 Floor, v18 Schema Floor + Drift Guard, Release-Pipeline Hardening
22
+
23
+ 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.
24
+
25
+ #### Added
26
+
27
+ - **Schema-drift guard wired into pre-publish validation** — a new build/pre-publish
28
+ check (`scripts/check_schema_drift.py` + a recorded fingerprint in
29
+ `scripts/migrations/schema.checksum`, wired into pre-publish-validate **Step 5c**)
30
+ fails the build if `gaia/store/schema.sql` changes without a matching schema version
31
+ bump and migration. This makes silent schema drift impossible to ship: any edit to
32
+ the schema must be accompanied by a version bump, or the gate stops the release.
33
+
34
+ #### Changed
35
+
36
+ - **Python minimum is now 3.11 (Python 3.9 dropped)** — `pyproject.toml`
37
+ `requires-python`, the ruff target version, and the CI test matrix all move to 3.11
38
+ as the floor. The dead `scripts/check-py39-compat.py` compatibility checker and its
39
+ npm alias are removed along with the 3.9 support.
40
+
41
+ - **Database migration history collapsed to a v18 floor** — fresh installs now stamp
42
+ schema **v18** directly instead of replaying the full migration chain. Databases below
43
+ the v18 floor are rejected cleanly with guidance to recreate, rather than attempting an
44
+ unsupported incremental upgrade. The per-step `vN_to_vN+1` migration SQL and their
45
+ obsolete version-specific tests are removed.
46
+
47
+ - **Git commit-format rules inlined into their single consumer** — the commit-format
48
+ rules previously in `config/git_standards.json` are inlined directly into
49
+ `commit_validator.py` (its only reader), and the standalone config file is removed.
50
+ Forbidden-footer enforcement is consolidated into `bash_validator` (the duplicate dead
51
+ check is removed); runtime AI-attribution footer stripping continues to live in
52
+ `bash_validator`. The git-conventions skill is updated to match.
53
+
54
+ - **Release pipeline hardened** — `publish.yml` now runs on Python 3.11 and appends
55
+ `[skip ci]` to the dist commit-back, stopping the CI re-trigger / version-churn loop
56
+ that re-ran the pipeline on every published dist commit. `gaia:install-local` now
57
+ rebuilds plugins before packing so a local install can never carry a stale `dist/`.
58
+ `ci.yml` drops the obsolete `settings.json` build assertions, and the gaia-release
59
+ skill drift is corrected.
60
+
61
+ - **pytest tmp uses the default OS tmpdir** — the in-repo pytest `basetemp` that
62
+ polluted the working tree (and broke scanner project-identity isolation) is removed;
63
+ tests now use the default OS temporary directory. `config/README.md` is rewritten to
64
+ match the actual directory contents.
65
+
66
+ #### Removed
67
+
68
+ - **Dead and redundant surfaces and artifacts** — removed `evidence/`, `docs/`,
69
+ `git-hooks/` (the redundant `commit-msg` sed copy; runtime footer stripping stays in
70
+ `bash_validator`), `tools/agentic-loop/`, `tools/review/`, `logs/`, the `commands/`
71
+ slash-command surface (including `/gaia`), the `templates/` managed-settings surface,
72
+ and `config/crons-schema.md`. These were either unused, duplicated by an active code
73
+ path, or superseded surfaces with no remaining consumer.
74
+
10
75
  ## [5.0.4] - 2026-06-06
11
76
 
12
77
  ### COMMAND_SET Batch Approval, Consent-Reducing Approval Verbs, Contract Advisory Field, Version Source Sync
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/`, `templates/`). Start with the folder that matches the behavior you want to understand, and its README will tell you where it fits in the flow.
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", "templates", "config", "skills"]
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
 
@@ -333,7 +333,6 @@ SYMLINKS_TO_REMOVE = [
333
333
  ".claude/tools",
334
334
  ".claude/hooks",
335
335
  ".claude/commands",
336
- ".claude/templates",
337
336
  ".claude/config",
338
337
  ".claude/CHANGELOG.md",
339
338
  ".claude/README.en.md",
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", "templates", "config", "skills", "CHANGELOG.md"]
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
@@ -935,7 +935,7 @@ def check_project_context(project_root: Path) -> dict:
935
935
  return _result("project-context", "warning", f"DB read error: {exc}", "Run `gaia scan`")
936
936
 
937
937
  if count == 0:
938
- return _result("project-context", "warning", "No contracts in DB", "Run `gaia scan`")
938
+ return _result("project-context", "info", "No contracts in DB", "Run `gaia scan`")
939
939
 
940
940
  if count < 3:
941
941
  return _result(
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 = ["git_standards.json", "surface-routing.json"]
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 (which agents see which context sections, 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.
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
- `context-contracts.json` is the seeding source for agent contracts. During `gaia install`, its contents are loaded into the `project_context_contracts` and `agent_contract_permissions` tables in `~/.gaia/gaia.db`. At runtime, the DB is the SSOTthe hook layer reads contracts from the DB, not from this file. Editing `context-contracts.json` without re-running `gaia install` (or manually applying the SQL) has no effect. The cloud extension files in `cloud/` extend these contracts for cloud-specific sections without modifying the base file, so adding a new cloud provider is a new file, not an edit to the core.
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 startupit 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
- The other files — routing and git standards — are each consumed by a specific module and do exactly what their names say. There is no magic here: the files are loaded, parsed, and applied by the module that reads them.
7
+ ## When activated
8
8
 
9
- ## Cuándo se activa
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
- Agent dispatch triggered
12
+ User submits a prompt
27
13
  |
28
- hooks/modules/context/contracts_loader.py reads project_context_contracts from DB
14
+ hooks/user_prompt_submit.py fires
29
15
  |
30
- Detects cloud_provider from workspace record in ~/.gaia/gaia.db
16
+ tools/context/surface_router.py calls load_surface_routing_config()
31
17
  |
32
- Reads cloud/{provider}.json <- cloud extensions (still file-based)
18
+ Reads config/surface-routing.json
33
19
  |
34
- Merges: extends read/write lists per agent (no duplicates)
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
- ## Qué hay aquí
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
- ├── context-contracts.json # Seeding source for per-agent read/write contracts (applied on install to gaia.db)
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
- ## Convenciones
33
+ ## Conventions
55
34
 
56
- **context-contracts.json schema:** Each entry is keyed by agent name. Each agent has `read` (list of project-context section names the agent receives) and `write` (list of sections the agent can update via an `update_contracts` clause). `core_sections` is a top-level list of sections injected into every agent regardless of per-agent config. This schema is mirrored in the DB tables `project_context_contracts` (one row per agent) and `agent_contract_permissions` (permission grants).
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
- **Adding a new cloud:** Create `cloud/azure.json` following the same schema as `cloud/gcp.json`. Define agent-specific sections for that cloud. No code changes needed `context_provider.py` detects the file automatically by matching `cloud_provider` from project-context.
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
- **surface-routing.json format:** Each surface entry has `intent`, `primary_agent`, `adjacent_surfaces`, and `signals` (with `high` and `medium` confidence keyword lists). High-confidence signals are checked first; medium signals act as tie-breakers.
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
- ## Ver también
41
+ ## See also
63
42
 
64
- - [`~/.gaia/gaia.db`](../gaia/store/schema.sql) — `project_context_contracts` + `agent_contract_permissions` tables (runtime SSOT for contracts)
65
- - [`hooks/user_prompt_submit.py`](../hooks/user_prompt_submit.py) — reads `surface-routing.json` on every prompt
66
- - [`hooks/modules/validation/`](../hooks/modules/validation/) — reads `git_standards.json` on commit validation
67
- - [`tools/context/`](../tools/context/) — reads contracts (from DB) at agent dispatch time
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
@@ -363,7 +363,6 @@
363
363
  "hooks/",
364
364
  "skills/",
365
365
  "agents/",
366
- "templates/",
367
366
  "claude.md",
368
367
  "project-context.json"
369
368
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gaia-ops",
3
- "version": "5.0.4",
3
+ "version": "5.0.6",
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",
@@ -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 (which agents see which context sections, 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.
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
- `context-contracts.json` is the seeding source for agent contracts. During `gaia install`, its contents are loaded into the `project_context_contracts` and `agent_contract_permissions` tables in `~/.gaia/gaia.db`. At runtime, the DB is the SSOTthe hook layer reads contracts from the DB, not from this file. Editing `context-contracts.json` without re-running `gaia install` (or manually applying the SQL) has no effect. The cloud extension files in `cloud/` extend these contracts for cloud-specific sections without modifying the base file, so adding a new cloud provider is a new file, not an edit to the core.
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 startupit 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
- The other files — routing and git standards — are each consumed by a specific module and do exactly what their names say. There is no magic here: the files are loaded, parsed, and applied by the module that reads them.
7
+ ## When activated
8
8
 
9
- ## Cuándo se activa
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
- Agent dispatch triggered
12
+ User submits a prompt
27
13
  |
28
- hooks/modules/context/contracts_loader.py reads project_context_contracts from DB
14
+ hooks/user_prompt_submit.py fires
29
15
  |
30
- Detects cloud_provider from workspace record in ~/.gaia/gaia.db
16
+ tools/context/surface_router.py calls load_surface_routing_config()
31
17
  |
32
- Reads cloud/{provider}.json <- cloud extensions (still file-based)
18
+ Reads config/surface-routing.json
33
19
  |
34
- Merges: extends read/write lists per agent (no duplicates)
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
- ## Qué hay aquí
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
- ├── context-contracts.json # Seeding source for per-agent read/write contracts (applied on install to gaia.db)
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
- ## Convenciones
33
+ ## Conventions
55
34
 
56
- **context-contracts.json schema:** Each entry is keyed by agent name. Each agent has `read` (list of project-context section names the agent receives) and `write` (list of sections the agent can update via an `update_contracts` clause). `core_sections` is a top-level list of sections injected into every agent regardless of per-agent config. This schema is mirrored in the DB tables `project_context_contracts` (one row per agent) and `agent_contract_permissions` (permission grants).
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
- **Adding a new cloud:** Create `cloud/azure.json` following the same schema as `cloud/gcp.json`. Define agent-specific sections for that cloud. No code changes needed `context_provider.py` detects the file automatically by matching `cloud_provider` from project-context.
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
- **surface-routing.json format:** Each surface entry has `intent`, `primary_agent`, `adjacent_surfaces`, and `signals` (with `high` and `medium` confidence keyword lists). High-confidence signals are checked first; medium signals act as tie-breakers.
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
- ## Ver también
41
+ ## See also
63
42
 
64
- - [`~/.gaia/gaia.db`](../gaia/store/schema.sql) — `project_context_contracts` + `agent_contract_permissions` tables (runtime SSOT for contracts)
65
- - [`hooks/user_prompt_submit.py`](../hooks/user_prompt_submit.py) — reads `surface-routing.json` on every prompt
66
- - [`hooks/modules/validation/`](../hooks/modules/validation/) — reads `git_standards.json` on commit validation
67
- - [`tools/context/`](../tools/context/) — reads contracts (from DB) at agent dispatch time
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
@@ -363,7 +363,6 @@
363
363
  "hooks/",
364
364
  "skills/",
365
365
  "agents/",
366
- "templates/",
367
366
  "claude.md",
368
367
  "project-context.json"
369
368
  ]
@@ -10,6 +10,8 @@ arise if the adapter imported _persist_handoff directly from subagent_stop
10
10
  (which itself imports from the adapter's dependency tree).
11
11
  """
12
12
 
13
+ from __future__ import annotations
14
+
13
15
  import logging
14
16
 
15
17
  logger = logging.getLogger(__name__)
@@ -76,6 +76,8 @@ fallback plane retained for grants created before the DB cutover. The active
76
76
  flow runs through the DB plane in gaia.store.writer.
77
77
  """
78
78
 
79
+ from __future__ import annotations
80
+
79
81
  import json
80
82
  import logging
81
83
  import os
@@ -23,6 +23,8 @@ Earlier flat-pipeline order preserved within phases for backward compat:
23
23
  - Blocked commands run before cloud_pipe and mutative_verbs in phase 3
24
24
  """
25
25
 
26
+ from __future__ import annotations
27
+
26
28
  import os
27
29
  import re
28
30
  import json