@jaguilar87/gaia 5.0.0-rc.2

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 (621) hide show
  1. package/.claude-plugin/marketplace.json +33 -0
  2. package/.claude-plugin/plugin.json +26 -0
  3. package/ARCHITECTURE.md +335 -0
  4. package/CHANGELOG.md +1298 -0
  5. package/CODE_OF_CONDUCT.md +11 -0
  6. package/CONTRIBUTING.md +146 -0
  7. package/INSTALL.md +436 -0
  8. package/LICENSE +21 -0
  9. package/README.md +222 -0
  10. package/SECURITY.md +47 -0
  11. package/agents/README.md +78 -0
  12. package/agents/cloud-troubleshooter.md +73 -0
  13. package/agents/developer.md +65 -0
  14. package/agents/gaia-operator.md +64 -0
  15. package/agents/gaia-orchestrator.md +111 -0
  16. package/agents/gaia-planner.md +53 -0
  17. package/agents/gaia-system.md +71 -0
  18. package/agents/gitops-operator.md +61 -0
  19. package/agents/terraform-architect.md +63 -0
  20. package/bin/README.md +106 -0
  21. package/bin/cli/__init__.py +1 -0
  22. package/bin/cli/approvals.py +740 -0
  23. package/bin/cli/cleanup.py +562 -0
  24. package/bin/cli/context.py +283 -0
  25. package/bin/cli/doctor.py +651 -0
  26. package/bin/cli/history.py +305 -0
  27. package/bin/cli/memory.py +483 -0
  28. package/bin/cli/metrics.py +1068 -0
  29. package/bin/cli/plans.py +515 -0
  30. package/bin/cli/status.py +302 -0
  31. package/bin/cli/update.py +382 -0
  32. package/bin/gaia +112 -0
  33. package/bin/gaia-cleanup.js +531 -0
  34. package/bin/gaia-doctor.js +635 -0
  35. package/bin/gaia-evidence +126 -0
  36. package/bin/gaia-history.js +251 -0
  37. package/bin/gaia-metrics.js +1278 -0
  38. package/bin/gaia-review.js +269 -0
  39. package/bin/gaia-scan +44 -0
  40. package/bin/gaia-scan.py +589 -0
  41. package/bin/gaia-skills-diagnose.js +929 -0
  42. package/bin/gaia-status.js +278 -0
  43. package/bin/gaia-uninstall.js +111 -0
  44. package/bin/gaia-update.js +919 -0
  45. package/bin/pre-publish-validate.js +610 -0
  46. package/bin/python-detect.js +60 -0
  47. package/bin/validate-sandbox.sh +601 -0
  48. package/commands/README.md +64 -0
  49. package/commands/gaia.md +37 -0
  50. package/commands/scan-project.md +67 -0
  51. package/config/README.md +71 -0
  52. package/config/cloud/aws.json +134 -0
  53. package/config/cloud/gcp.json +139 -0
  54. package/config/context-contracts.json +158 -0
  55. package/config/crons-schema.md +81 -0
  56. package/config/git_standards.json +72 -0
  57. package/config/surface-routing.json +417 -0
  58. package/config/universal-rules.json +102 -0
  59. package/dist/gaia-ops/.claude-plugin/plugin.json +24 -0
  60. package/dist/gaia-ops/README.md +80 -0
  61. package/dist/gaia-ops/agents/cloud-troubleshooter.md +73 -0
  62. package/dist/gaia-ops/agents/developer.md +65 -0
  63. package/dist/gaia-ops/agents/gaia-operator.md +64 -0
  64. package/dist/gaia-ops/agents/gaia-orchestrator.md +111 -0
  65. package/dist/gaia-ops/agents/gaia-planner.md +53 -0
  66. package/dist/gaia-ops/agents/gaia-system.md +71 -0
  67. package/dist/gaia-ops/agents/gitops-operator.md +61 -0
  68. package/dist/gaia-ops/agents/terraform-architect.md +63 -0
  69. package/dist/gaia-ops/commands/gaia.md +37 -0
  70. package/dist/gaia-ops/config/README.md +71 -0
  71. package/dist/gaia-ops/config/cloud/aws.json +134 -0
  72. package/dist/gaia-ops/config/cloud/gcp.json +139 -0
  73. package/dist/gaia-ops/config/context-contracts.json +158 -0
  74. package/dist/gaia-ops/config/crons-schema.md +81 -0
  75. package/dist/gaia-ops/config/git_standards.json +72 -0
  76. package/dist/gaia-ops/config/surface-routing.json +417 -0
  77. package/dist/gaia-ops/config/universal-rules.json +102 -0
  78. package/dist/gaia-ops/hooks/adapters/__init__.py +52 -0
  79. package/dist/gaia-ops/hooks/adapters/base.py +219 -0
  80. package/dist/gaia-ops/hooks/adapters/channel.py +17 -0
  81. package/dist/gaia-ops/hooks/adapters/claude_code.py +1890 -0
  82. package/dist/gaia-ops/hooks/adapters/types.py +194 -0
  83. package/dist/gaia-ops/hooks/adapters/utils.py +25 -0
  84. package/dist/gaia-ops/hooks/hooks.json +192 -0
  85. package/dist/gaia-ops/hooks/modules/__init__.py +15 -0
  86. package/dist/gaia-ops/hooks/modules/agents/__init__.py +29 -0
  87. package/dist/gaia-ops/hooks/modules/agents/contract_validator.py +647 -0
  88. package/dist/gaia-ops/hooks/modules/agents/response_contract.py +496 -0
  89. package/dist/gaia-ops/hooks/modules/agents/skill_injection_verifier.py +120 -0
  90. package/dist/gaia-ops/hooks/modules/agents/state_tracker.py +267 -0
  91. package/dist/gaia-ops/hooks/modules/agents/task_info_builder.py +74 -0
  92. package/dist/gaia-ops/hooks/modules/agents/transcript_analyzer.py +458 -0
  93. package/dist/gaia-ops/hooks/modules/agents/transcript_reader.py +152 -0
  94. package/dist/gaia-ops/hooks/modules/audit/__init__.py +28 -0
  95. package/dist/gaia-ops/hooks/modules/audit/event_detector.py +168 -0
  96. package/dist/gaia-ops/hooks/modules/audit/logger.py +131 -0
  97. package/dist/gaia-ops/hooks/modules/audit/metrics.py +134 -0
  98. package/dist/gaia-ops/hooks/modules/audit/workflow_auditor.py +611 -0
  99. package/dist/gaia-ops/hooks/modules/audit/workflow_recorder.py +296 -0
  100. package/dist/gaia-ops/hooks/modules/context/__init__.py +11 -0
  101. package/dist/gaia-ops/hooks/modules/context/agentic_loop_detector.py +165 -0
  102. package/dist/gaia-ops/hooks/modules/context/anchor_tracker.py +317 -0
  103. package/dist/gaia-ops/hooks/modules/context/compact_context_builder.py +218 -0
  104. package/dist/gaia-ops/hooks/modules/context/context_freshness.py +145 -0
  105. package/dist/gaia-ops/hooks/modules/context/context_injector.py +558 -0
  106. package/dist/gaia-ops/hooks/modules/context/context_writer.py +530 -0
  107. package/dist/gaia-ops/hooks/modules/context/contracts_loader.py +161 -0
  108. package/dist/gaia-ops/hooks/modules/core/__init__.py +40 -0
  109. package/dist/gaia-ops/hooks/modules/core/hook_entry.py +78 -0
  110. package/dist/gaia-ops/hooks/modules/core/paths.py +160 -0
  111. package/dist/gaia-ops/hooks/modules/core/plugin_mode.py +149 -0
  112. package/dist/gaia-ops/hooks/modules/core/plugin_setup.py +577 -0
  113. package/dist/gaia-ops/hooks/modules/core/state.py +179 -0
  114. package/dist/gaia-ops/hooks/modules/core/stdin.py +24 -0
  115. package/dist/gaia-ops/hooks/modules/events/__init__.py +1 -0
  116. package/dist/gaia-ops/hooks/modules/events/event_writer.py +210 -0
  117. package/dist/gaia-ops/hooks/modules/memory/__init__.py +8 -0
  118. package/dist/gaia-ops/hooks/modules/memory/episode_writer.py +216 -0
  119. package/dist/gaia-ops/hooks/modules/orchestrator/__init__.py +1 -0
  120. package/dist/gaia-ops/hooks/modules/orchestrator/delegate_mode.py +122 -0
  121. package/dist/gaia-ops/hooks/modules/scanning/__init__.py +8 -0
  122. package/dist/gaia-ops/hooks/modules/scanning/scan_trigger.py +84 -0
  123. package/dist/gaia-ops/hooks/modules/security/__init__.py +120 -0
  124. package/dist/gaia-ops/hooks/modules/security/approval_cleanup.py +87 -0
  125. package/dist/gaia-ops/hooks/modules/security/approval_constants.py +23 -0
  126. package/dist/gaia-ops/hooks/modules/security/approval_grants.py +1638 -0
  127. package/dist/gaia-ops/hooks/modules/security/approval_messages.py +71 -0
  128. package/dist/gaia-ops/hooks/modules/security/approval_scopes.py +222 -0
  129. package/dist/gaia-ops/hooks/modules/security/blocked_commands.py +595 -0
  130. package/dist/gaia-ops/hooks/modules/security/blocked_message_formatter.py +87 -0
  131. package/dist/gaia-ops/hooks/modules/security/command_semantics.py +181 -0
  132. package/dist/gaia-ops/hooks/modules/security/composition_rules.py +547 -0
  133. package/dist/gaia-ops/hooks/modules/security/flag_classifiers.py +873 -0
  134. package/dist/gaia-ops/hooks/modules/security/gitops_validator.py +179 -0
  135. package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +1131 -0
  136. package/dist/gaia-ops/hooks/modules/security/network_hosts.py +481 -0
  137. package/dist/gaia-ops/hooks/modules/security/prompt_validator.py +40 -0
  138. package/dist/gaia-ops/hooks/modules/security/shell_unwrapper.py +165 -0
  139. package/dist/gaia-ops/hooks/modules/security/tiers.py +196 -0
  140. package/dist/gaia-ops/hooks/modules/session/__init__.py +10 -0
  141. package/dist/gaia-ops/hooks/modules/session/pending_scanner.py +174 -0
  142. package/dist/gaia-ops/hooks/modules/session/session_context_writer.py +100 -0
  143. package/dist/gaia-ops/hooks/modules/session/session_event_injector.py +160 -0
  144. package/dist/gaia-ops/hooks/modules/session/session_manager.py +31 -0
  145. package/dist/gaia-ops/hooks/modules/session/session_registry.py +333 -0
  146. package/dist/gaia-ops/hooks/modules/tools/__init__.py +29 -0
  147. package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +1008 -0
  148. package/dist/gaia-ops/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  149. package/dist/gaia-ops/hooks/modules/tools/hook_response.py +55 -0
  150. package/dist/gaia-ops/hooks/modules/tools/shell_parser.py +227 -0
  151. package/dist/gaia-ops/hooks/modules/tools/stage_decomposer.py +315 -0
  152. package/dist/gaia-ops/hooks/modules/tools/task_validator.py +294 -0
  153. package/dist/gaia-ops/hooks/modules/validation/__init__.py +23 -0
  154. package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +380 -0
  155. package/dist/gaia-ops/hooks/post_compact.py +43 -0
  156. package/dist/gaia-ops/hooks/post_tool_use.py +54 -0
  157. package/dist/gaia-ops/hooks/pre_compact.py +60 -0
  158. package/dist/gaia-ops/hooks/pre_tool_use.py +413 -0
  159. package/dist/gaia-ops/hooks/session_end_hook.py +77 -0
  160. package/dist/gaia-ops/hooks/session_start.py +81 -0
  161. package/dist/gaia-ops/hooks/stop_hook.py +70 -0
  162. package/dist/gaia-ops/hooks/subagent_start.py +71 -0
  163. package/dist/gaia-ops/hooks/subagent_stop.py +295 -0
  164. package/dist/gaia-ops/hooks/task_completed.py +70 -0
  165. package/dist/gaia-ops/hooks/user_prompt_submit.py +246 -0
  166. package/dist/gaia-ops/settings.json +72 -0
  167. package/dist/gaia-ops/skills/README.md +158 -0
  168. package/dist/gaia-ops/skills/agent-creation/SKILL.md +87 -0
  169. package/dist/gaia-ops/skills/agent-creation/examples.md +170 -0
  170. package/dist/gaia-ops/skills/agent-creation/reference.md +191 -0
  171. package/dist/gaia-ops/skills/agent-protocol/SKILL.md +93 -0
  172. package/dist/gaia-ops/skills/agent-protocol/examples.md +223 -0
  173. package/dist/gaia-ops/skills/agent-response/SKILL.md +69 -0
  174. package/dist/gaia-ops/skills/agentic-loop/SKILL.md +80 -0
  175. package/dist/gaia-ops/skills/agentic-loop/reference.md +378 -0
  176. package/dist/gaia-ops/skills/blog-writing/SKILL.md +98 -0
  177. package/dist/gaia-ops/skills/blog-writing/reference.md +130 -0
  178. package/dist/gaia-ops/skills/brief-spec/SKILL.md +185 -0
  179. package/dist/gaia-ops/skills/command-execution/SKILL.md +64 -0
  180. package/dist/gaia-ops/skills/command-execution/reference.md +83 -0
  181. package/dist/gaia-ops/skills/context-updater/SKILL.md +87 -0
  182. package/dist/gaia-ops/skills/context-updater/examples.md +71 -0
  183. package/dist/gaia-ops/skills/developer-patterns/SKILL.md +50 -0
  184. package/dist/gaia-ops/skills/developer-patterns/reference.md +112 -0
  185. package/dist/gaia-ops/skills/execution/SKILL.md +99 -0
  186. package/dist/gaia-ops/skills/fast-queries/SKILL.md +43 -0
  187. package/dist/gaia-ops/skills/gaia-compact/SKILL.md +74 -0
  188. package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +108 -0
  189. package/dist/gaia-ops/skills/gaia-patterns/reference.md +395 -0
  190. package/dist/gaia-ops/skills/gaia-planner/SKILL.md +37 -0
  191. package/dist/gaia-ops/skills/gaia-planner/reference.md +107 -0
  192. package/dist/gaia-ops/skills/gaia-release/SKILL.md +85 -0
  193. package/dist/gaia-ops/skills/gaia-release/reference.md +92 -0
  194. package/dist/gaia-ops/skills/gaia-self-check/SKILL.md +114 -0
  195. package/dist/gaia-ops/skills/gaia-self-check/reference.md +453 -0
  196. package/dist/gaia-ops/skills/gaia-verify/SKILL.md +77 -0
  197. package/dist/gaia-ops/skills/gaia-verify/reference.md +80 -0
  198. package/dist/gaia-ops/skills/git-conventions/SKILL.md +47 -0
  199. package/dist/gaia-ops/skills/gitops-patterns/SKILL.md +60 -0
  200. package/dist/gaia-ops/skills/gitops-patterns/reference.md +183 -0
  201. package/dist/gaia-ops/skills/gmail-policy/SKILL.md +200 -0
  202. package/dist/gaia-ops/skills/gmail-policy/reference.md +150 -0
  203. package/dist/gaia-ops/skills/gmail-triage/SKILL.md +100 -0
  204. package/dist/gaia-ops/skills/gws-setup/SKILL.md +99 -0
  205. package/dist/gaia-ops/skills/gws-setup/reference.md +73 -0
  206. package/dist/gaia-ops/skills/investigation/SKILL.md +100 -0
  207. package/dist/gaia-ops/skills/memory-curation/SKILL.md +83 -0
  208. package/dist/gaia-ops/skills/memory-search/SKILL.md +88 -0
  209. package/dist/gaia-ops/skills/orchestrator-approval/SKILL.md +160 -0
  210. package/dist/gaia-ops/skills/orchestrator-approval/reference.md +174 -0
  211. package/dist/gaia-ops/skills/pending-approvals/SKILL.md +72 -0
  212. package/dist/gaia-ops/skills/pending-approvals/reference.md +214 -0
  213. package/dist/gaia-ops/skills/readme-writing/SKILL.md +71 -0
  214. package/dist/gaia-ops/skills/readme-writing/reference.md +188 -0
  215. package/dist/gaia-ops/skills/reference.md +135 -0
  216. package/dist/gaia-ops/skills/request-approval/SKILL.md +140 -0
  217. package/dist/gaia-ops/skills/request-approval/examples.md +140 -0
  218. package/dist/gaia-ops/skills/request-approval/reference.md +57 -0
  219. package/dist/gaia-ops/skills/schedule-task/SKILL.md +64 -0
  220. package/dist/gaia-ops/skills/schedule-task/reference.md +233 -0
  221. package/dist/gaia-ops/skills/security-tiers/SKILL.md +141 -0
  222. package/dist/gaia-ops/skills/security-tiers/destructive-commands-reference.md +623 -0
  223. package/dist/gaia-ops/skills/security-tiers/reference.md +39 -0
  224. package/dist/gaia-ops/skills/session-reflection/SKILL.md +69 -0
  225. package/dist/gaia-ops/skills/skill-creation/SKILL.md +92 -0
  226. package/dist/gaia-ops/skills/skill-creation/reference.md +29 -0
  227. package/dist/gaia-ops/skills/terraform-patterns/SKILL.md +89 -0
  228. package/dist/gaia-ops/skills/terraform-patterns/reference.md +93 -0
  229. package/dist/gaia-ops/tools/__init__.py +9 -0
  230. package/dist/gaia-ops/tools/agentic-loop/decide-status.py +210 -0
  231. package/dist/gaia-ops/tools/agentic-loop/parse-metric.py +106 -0
  232. package/dist/gaia-ops/tools/agentic-loop/record-iteration.py +221 -0
  233. package/dist/gaia-ops/tools/context/README.md +132 -0
  234. package/dist/gaia-ops/tools/context/__init__.py +42 -0
  235. package/dist/gaia-ops/tools/context/_paths.py +20 -0
  236. package/dist/gaia-ops/tools/context/context_provider.py +721 -0
  237. package/dist/gaia-ops/tools/context/context_section_reader.py +342 -0
  238. package/dist/gaia-ops/tools/context/deep_merge.py +159 -0
  239. package/dist/gaia-ops/tools/context/pending_updates.py +760 -0
  240. package/dist/gaia-ops/tools/context/surface_router.py +278 -0
  241. package/dist/gaia-ops/tools/fast-queries/README.md +65 -0
  242. package/dist/gaia-ops/tools/fast-queries/__init__.py +30 -0
  243. package/dist/gaia-ops/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
  244. package/dist/gaia-ops/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
  245. package/dist/gaia-ops/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
  246. package/dist/gaia-ops/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
  247. package/dist/gaia-ops/tools/fast-queries/run_triage.sh +59 -0
  248. package/dist/gaia-ops/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
  249. package/dist/gaia-ops/tools/gaia_simulator/__init__.py +33 -0
  250. package/dist/gaia-ops/tools/gaia_simulator/cli.py +354 -0
  251. package/dist/gaia-ops/tools/gaia_simulator/extractor.py +457 -0
  252. package/dist/gaia-ops/tools/gaia_simulator/reporter.py +258 -0
  253. package/dist/gaia-ops/tools/gaia_simulator/routing_simulator.py +334 -0
  254. package/dist/gaia-ops/tools/gaia_simulator/runner.py +539 -0
  255. package/dist/gaia-ops/tools/gaia_simulator/skills_mapper.py +264 -0
  256. package/dist/gaia-ops/tools/memory/README.md +0 -0
  257. package/dist/gaia-ops/tools/memory/__init__.py +20 -0
  258. package/dist/gaia-ops/tools/memory/backfill_fts5.py +107 -0
  259. package/dist/gaia-ops/tools/memory/conflict_detector.py +295 -0
  260. package/dist/gaia-ops/tools/memory/episodic.py +1210 -0
  261. package/dist/gaia-ops/tools/memory/git_invalidator.py +262 -0
  262. package/dist/gaia-ops/tools/memory/paths.py +102 -0
  263. package/dist/gaia-ops/tools/memory/scoring.py +193 -0
  264. package/dist/gaia-ops/tools/memory/search_store.py +375 -0
  265. package/dist/gaia-ops/tools/persist_transcript_analysis.py +85 -0
  266. package/dist/gaia-ops/tools/review/__init__.py +1 -0
  267. package/dist/gaia-ops/tools/review/review_engine.py +157 -0
  268. package/dist/gaia-ops/tools/scan/__init__.py +35 -0
  269. package/dist/gaia-ops/tools/scan/config.py +247 -0
  270. package/dist/gaia-ops/tools/scan/merge.py +212 -0
  271. package/dist/gaia-ops/tools/scan/orchestrator.py +549 -0
  272. package/dist/gaia-ops/tools/scan/registry.py +127 -0
  273. package/dist/gaia-ops/tools/scan/scanners/__init__.py +18 -0
  274. package/dist/gaia-ops/tools/scan/scanners/base.py +137 -0
  275. package/dist/gaia-ops/tools/scan/scanners/environment.py +349 -0
  276. package/dist/gaia-ops/tools/scan/scanners/git.py +570 -0
  277. package/dist/gaia-ops/tools/scan/scanners/infrastructure.py +875 -0
  278. package/dist/gaia-ops/tools/scan/scanners/orchestration.py +600 -0
  279. package/dist/gaia-ops/tools/scan/scanners/stack.py +1085 -0
  280. package/dist/gaia-ops/tools/scan/scanners/tools.py +260 -0
  281. package/dist/gaia-ops/tools/scan/setup.py +686 -0
  282. package/dist/gaia-ops/tools/scan/tests/__init__.py +1 -0
  283. package/dist/gaia-ops/tools/scan/tests/conftest.py +796 -0
  284. package/dist/gaia-ops/tools/scan/tests/test_environment.py +323 -0
  285. package/dist/gaia-ops/tools/scan/tests/test_git.py +419 -0
  286. package/dist/gaia-ops/tools/scan/tests/test_infrastructure.py +382 -0
  287. package/dist/gaia-ops/tools/scan/tests/test_integration.py +920 -0
  288. package/dist/gaia-ops/tools/scan/tests/test_merge.py +269 -0
  289. package/dist/gaia-ops/tools/scan/tests/test_orchestration.py +304 -0
  290. package/dist/gaia-ops/tools/scan/tests/test_stack.py +604 -0
  291. package/dist/gaia-ops/tools/scan/tests/test_tools.py +349 -0
  292. package/dist/gaia-ops/tools/scan/ui.py +624 -0
  293. package/dist/gaia-ops/tools/scan/verify.py +270 -0
  294. package/dist/gaia-ops/tools/scan/walk.py +118 -0
  295. package/dist/gaia-ops/tools/scan/workspace.py +85 -0
  296. package/dist/gaia-ops/tools/validation/README.md +244 -0
  297. package/dist/gaia-ops/tools/validation/__init__.py +17 -0
  298. package/dist/gaia-ops/tools/validation/approval_gate.py +321 -0
  299. package/dist/gaia-ops/tools/validation/validate_skills.py +189 -0
  300. package/dist/gaia-security/.claude-plugin/plugin.json +24 -0
  301. package/dist/gaia-security/README.md +90 -0
  302. package/dist/gaia-security/config/universal-rules.json +102 -0
  303. package/dist/gaia-security/hooks/adapters/__init__.py +52 -0
  304. package/dist/gaia-security/hooks/adapters/base.py +219 -0
  305. package/dist/gaia-security/hooks/adapters/channel.py +17 -0
  306. package/dist/gaia-security/hooks/adapters/claude_code.py +1890 -0
  307. package/dist/gaia-security/hooks/adapters/types.py +194 -0
  308. package/dist/gaia-security/hooks/adapters/utils.py +25 -0
  309. package/dist/gaia-security/hooks/hooks.json +113 -0
  310. package/dist/gaia-security/hooks/modules/__init__.py +15 -0
  311. package/dist/gaia-security/hooks/modules/agents/__init__.py +29 -0
  312. package/dist/gaia-security/hooks/modules/agents/contract_validator.py +647 -0
  313. package/dist/gaia-security/hooks/modules/agents/response_contract.py +496 -0
  314. package/dist/gaia-security/hooks/modules/agents/skill_injection_verifier.py +120 -0
  315. package/dist/gaia-security/hooks/modules/agents/state_tracker.py +267 -0
  316. package/dist/gaia-security/hooks/modules/agents/task_info_builder.py +74 -0
  317. package/dist/gaia-security/hooks/modules/agents/transcript_analyzer.py +458 -0
  318. package/dist/gaia-security/hooks/modules/agents/transcript_reader.py +152 -0
  319. package/dist/gaia-security/hooks/modules/audit/__init__.py +28 -0
  320. package/dist/gaia-security/hooks/modules/audit/event_detector.py +168 -0
  321. package/dist/gaia-security/hooks/modules/audit/logger.py +131 -0
  322. package/dist/gaia-security/hooks/modules/audit/metrics.py +134 -0
  323. package/dist/gaia-security/hooks/modules/audit/workflow_auditor.py +611 -0
  324. package/dist/gaia-security/hooks/modules/audit/workflow_recorder.py +296 -0
  325. package/dist/gaia-security/hooks/modules/context/__init__.py +11 -0
  326. package/dist/gaia-security/hooks/modules/context/agentic_loop_detector.py +165 -0
  327. package/dist/gaia-security/hooks/modules/context/anchor_tracker.py +317 -0
  328. package/dist/gaia-security/hooks/modules/context/compact_context_builder.py +218 -0
  329. package/dist/gaia-security/hooks/modules/context/context_freshness.py +145 -0
  330. package/dist/gaia-security/hooks/modules/context/context_injector.py +558 -0
  331. package/dist/gaia-security/hooks/modules/context/context_writer.py +530 -0
  332. package/dist/gaia-security/hooks/modules/context/contracts_loader.py +161 -0
  333. package/dist/gaia-security/hooks/modules/core/__init__.py +40 -0
  334. package/dist/gaia-security/hooks/modules/core/hook_entry.py +78 -0
  335. package/dist/gaia-security/hooks/modules/core/paths.py +160 -0
  336. package/dist/gaia-security/hooks/modules/core/plugin_mode.py +149 -0
  337. package/dist/gaia-security/hooks/modules/core/plugin_setup.py +577 -0
  338. package/dist/gaia-security/hooks/modules/core/state.py +179 -0
  339. package/dist/gaia-security/hooks/modules/core/stdin.py +24 -0
  340. package/dist/gaia-security/hooks/modules/events/__init__.py +1 -0
  341. package/dist/gaia-security/hooks/modules/events/event_writer.py +210 -0
  342. package/dist/gaia-security/hooks/modules/memory/__init__.py +8 -0
  343. package/dist/gaia-security/hooks/modules/memory/episode_writer.py +216 -0
  344. package/dist/gaia-security/hooks/modules/orchestrator/__init__.py +1 -0
  345. package/dist/gaia-security/hooks/modules/orchestrator/delegate_mode.py +122 -0
  346. package/dist/gaia-security/hooks/modules/scanning/__init__.py +8 -0
  347. package/dist/gaia-security/hooks/modules/scanning/scan_trigger.py +84 -0
  348. package/dist/gaia-security/hooks/modules/security/__init__.py +120 -0
  349. package/dist/gaia-security/hooks/modules/security/approval_cleanup.py +87 -0
  350. package/dist/gaia-security/hooks/modules/security/approval_constants.py +23 -0
  351. package/dist/gaia-security/hooks/modules/security/approval_grants.py +1638 -0
  352. package/dist/gaia-security/hooks/modules/security/approval_messages.py +71 -0
  353. package/dist/gaia-security/hooks/modules/security/approval_scopes.py +222 -0
  354. package/dist/gaia-security/hooks/modules/security/blocked_commands.py +595 -0
  355. package/dist/gaia-security/hooks/modules/security/blocked_message_formatter.py +87 -0
  356. package/dist/gaia-security/hooks/modules/security/command_semantics.py +181 -0
  357. package/dist/gaia-security/hooks/modules/security/composition_rules.py +547 -0
  358. package/dist/gaia-security/hooks/modules/security/flag_classifiers.py +873 -0
  359. package/dist/gaia-security/hooks/modules/security/gitops_validator.py +179 -0
  360. package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +1131 -0
  361. package/dist/gaia-security/hooks/modules/security/network_hosts.py +481 -0
  362. package/dist/gaia-security/hooks/modules/security/prompt_validator.py +40 -0
  363. package/dist/gaia-security/hooks/modules/security/shell_unwrapper.py +165 -0
  364. package/dist/gaia-security/hooks/modules/security/tiers.py +196 -0
  365. package/dist/gaia-security/hooks/modules/session/__init__.py +10 -0
  366. package/dist/gaia-security/hooks/modules/session/pending_scanner.py +174 -0
  367. package/dist/gaia-security/hooks/modules/session/session_context_writer.py +100 -0
  368. package/dist/gaia-security/hooks/modules/session/session_event_injector.py +160 -0
  369. package/dist/gaia-security/hooks/modules/session/session_manager.py +31 -0
  370. package/dist/gaia-security/hooks/modules/session/session_registry.py +333 -0
  371. package/dist/gaia-security/hooks/modules/tools/__init__.py +29 -0
  372. package/dist/gaia-security/hooks/modules/tools/bash_validator.py +1008 -0
  373. package/dist/gaia-security/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  374. package/dist/gaia-security/hooks/modules/tools/hook_response.py +55 -0
  375. package/dist/gaia-security/hooks/modules/tools/shell_parser.py +227 -0
  376. package/dist/gaia-security/hooks/modules/tools/stage_decomposer.py +315 -0
  377. package/dist/gaia-security/hooks/modules/tools/task_validator.py +294 -0
  378. package/dist/gaia-security/hooks/modules/validation/__init__.py +23 -0
  379. package/dist/gaia-security/hooks/modules/validation/commit_validator.py +380 -0
  380. package/dist/gaia-security/hooks/post_tool_use.py +54 -0
  381. package/dist/gaia-security/hooks/pre_tool_use.py +413 -0
  382. package/dist/gaia-security/hooks/session_end_hook.py +77 -0
  383. package/dist/gaia-security/hooks/session_start.py +81 -0
  384. package/dist/gaia-security/hooks/stop_hook.py +70 -0
  385. package/dist/gaia-security/hooks/user_prompt_submit.py +246 -0
  386. package/dist/gaia-security/settings.json +58 -0
  387. package/git-hooks/commit-msg +41 -0
  388. package/hooks/README.md +100 -0
  389. package/hooks/adapters/__init__.py +52 -0
  390. package/hooks/adapters/base.py +219 -0
  391. package/hooks/adapters/channel.py +17 -0
  392. package/hooks/adapters/claude_code.py +1890 -0
  393. package/hooks/adapters/types.py +194 -0
  394. package/hooks/adapters/utils.py +25 -0
  395. package/hooks/elicitation_result.py +179 -0
  396. package/hooks/hooks.json +84 -0
  397. package/hooks/modules/README.md +189 -0
  398. package/hooks/modules/__init__.py +15 -0
  399. package/hooks/modules/agents/__init__.py +29 -0
  400. package/hooks/modules/agents/contract_validator.py +647 -0
  401. package/hooks/modules/agents/response_contract.py +496 -0
  402. package/hooks/modules/agents/skill_injection_verifier.py +120 -0
  403. package/hooks/modules/agents/state_tracker.py +267 -0
  404. package/hooks/modules/agents/task_info_builder.py +74 -0
  405. package/hooks/modules/agents/transcript_analyzer.py +458 -0
  406. package/hooks/modules/agents/transcript_reader.py +152 -0
  407. package/hooks/modules/audit/__init__.py +28 -0
  408. package/hooks/modules/audit/event_detector.py +168 -0
  409. package/hooks/modules/audit/logger.py +131 -0
  410. package/hooks/modules/audit/metrics.py +134 -0
  411. package/hooks/modules/audit/workflow_auditor.py +611 -0
  412. package/hooks/modules/audit/workflow_recorder.py +296 -0
  413. package/hooks/modules/context/__init__.py +11 -0
  414. package/hooks/modules/context/agentic_loop_detector.py +165 -0
  415. package/hooks/modules/context/anchor_tracker.py +317 -0
  416. package/hooks/modules/context/compact_context_builder.py +218 -0
  417. package/hooks/modules/context/context_freshness.py +145 -0
  418. package/hooks/modules/context/context_injector.py +558 -0
  419. package/hooks/modules/context/context_writer.py +530 -0
  420. package/hooks/modules/context/contracts_loader.py +161 -0
  421. package/hooks/modules/core/__init__.py +40 -0
  422. package/hooks/modules/core/hook_entry.py +78 -0
  423. package/hooks/modules/core/paths.py +160 -0
  424. package/hooks/modules/core/plugin_mode.py +149 -0
  425. package/hooks/modules/core/plugin_setup.py +577 -0
  426. package/hooks/modules/core/state.py +179 -0
  427. package/hooks/modules/core/stdin.py +24 -0
  428. package/hooks/modules/events/__init__.py +1 -0
  429. package/hooks/modules/events/event_writer.py +210 -0
  430. package/hooks/modules/evidence/__init__.py +34 -0
  431. package/hooks/modules/evidence/assertions.py +137 -0
  432. package/hooks/modules/evidence/index_writer.py +57 -0
  433. package/hooks/modules/evidence/loader.py +126 -0
  434. package/hooks/modules/evidence/runner.py +241 -0
  435. package/hooks/modules/memory/__init__.py +8 -0
  436. package/hooks/modules/memory/episode_writer.py +216 -0
  437. package/hooks/modules/orchestrator/__init__.py +1 -0
  438. package/hooks/modules/orchestrator/delegate_mode.py +122 -0
  439. package/hooks/modules/scanning/__init__.py +8 -0
  440. package/hooks/modules/scanning/scan_trigger.py +84 -0
  441. package/hooks/modules/security/__init__.py +120 -0
  442. package/hooks/modules/security/approval_cleanup.py +87 -0
  443. package/hooks/modules/security/approval_constants.py +23 -0
  444. package/hooks/modules/security/approval_grants.py +1638 -0
  445. package/hooks/modules/security/approval_messages.py +71 -0
  446. package/hooks/modules/security/approval_scopes.py +222 -0
  447. package/hooks/modules/security/blocked_commands.py +595 -0
  448. package/hooks/modules/security/blocked_message_formatter.py +87 -0
  449. package/hooks/modules/security/command_semantics.py +181 -0
  450. package/hooks/modules/security/composition_rules.py +547 -0
  451. package/hooks/modules/security/flag_classifiers.py +873 -0
  452. package/hooks/modules/security/gitops_validator.py +179 -0
  453. package/hooks/modules/security/mutative_verbs.py +1131 -0
  454. package/hooks/modules/security/network_hosts.py +481 -0
  455. package/hooks/modules/security/prompt_validator.py +40 -0
  456. package/hooks/modules/security/shell_unwrapper.py +165 -0
  457. package/hooks/modules/security/tiers.py +196 -0
  458. package/hooks/modules/session/__init__.py +10 -0
  459. package/hooks/modules/session/pending_scanner.py +174 -0
  460. package/hooks/modules/session/session_context_writer.py +100 -0
  461. package/hooks/modules/session/session_event_injector.py +160 -0
  462. package/hooks/modules/session/session_manager.py +31 -0
  463. package/hooks/modules/session/session_registry.py +333 -0
  464. package/hooks/modules/tools/__init__.py +29 -0
  465. package/hooks/modules/tools/bash_validator.py +1008 -0
  466. package/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  467. package/hooks/modules/tools/hook_response.py +55 -0
  468. package/hooks/modules/tools/shell_parser.py +227 -0
  469. package/hooks/modules/tools/stage_decomposer.py +315 -0
  470. package/hooks/modules/tools/task_validator.py +294 -0
  471. package/hooks/modules/validation/__init__.py +23 -0
  472. package/hooks/modules/validation/commit_validator.py +380 -0
  473. package/hooks/post_compact.py +43 -0
  474. package/hooks/post_tool_use.py +54 -0
  475. package/hooks/pre_compact.py +60 -0
  476. package/hooks/pre_tool_use.py +413 -0
  477. package/hooks/session_end_hook.py +77 -0
  478. package/hooks/session_start.py +81 -0
  479. package/hooks/stop_hook.py +70 -0
  480. package/hooks/subagent_start.py +71 -0
  481. package/hooks/subagent_stop.py +295 -0
  482. package/hooks/task_completed.py +70 -0
  483. package/hooks/user_prompt_submit.py +246 -0
  484. package/index.js +83 -0
  485. package/package.json +103 -0
  486. package/pyproject.toml +32 -0
  487. package/skills/README.md +158 -0
  488. package/skills/agent-creation/SKILL.md +87 -0
  489. package/skills/agent-creation/examples.md +170 -0
  490. package/skills/agent-creation/reference.md +191 -0
  491. package/skills/agent-protocol/SKILL.md +93 -0
  492. package/skills/agent-protocol/examples.md +223 -0
  493. package/skills/agent-response/SKILL.md +69 -0
  494. package/skills/agentic-loop/SKILL.md +80 -0
  495. package/skills/agentic-loop/reference.md +378 -0
  496. package/skills/blog-writing/SKILL.md +98 -0
  497. package/skills/blog-writing/reference.md +130 -0
  498. package/skills/brief-spec/SKILL.md +185 -0
  499. package/skills/command-execution/SKILL.md +64 -0
  500. package/skills/command-execution/reference.md +83 -0
  501. package/skills/context-updater/SKILL.md +87 -0
  502. package/skills/context-updater/examples.md +71 -0
  503. package/skills/developer-patterns/SKILL.md +50 -0
  504. package/skills/developer-patterns/reference.md +112 -0
  505. package/skills/execution/SKILL.md +99 -0
  506. package/skills/fast-queries/SKILL.md +43 -0
  507. package/skills/gaia-compact/SKILL.md +74 -0
  508. package/skills/gaia-patterns/SKILL.md +108 -0
  509. package/skills/gaia-patterns/reference.md +395 -0
  510. package/skills/gaia-planner/SKILL.md +37 -0
  511. package/skills/gaia-planner/reference.md +107 -0
  512. package/skills/gaia-release/SKILL.md +85 -0
  513. package/skills/gaia-release/reference.md +92 -0
  514. package/skills/gaia-self-check/SKILL.md +114 -0
  515. package/skills/gaia-self-check/reference.md +453 -0
  516. package/skills/gaia-verify/SKILL.md +77 -0
  517. package/skills/gaia-verify/reference.md +80 -0
  518. package/skills/git-conventions/SKILL.md +47 -0
  519. package/skills/gitops-patterns/SKILL.md +60 -0
  520. package/skills/gitops-patterns/reference.md +183 -0
  521. package/skills/gmail-policy/SKILL.md +200 -0
  522. package/skills/gmail-policy/reference.md +150 -0
  523. package/skills/gmail-triage/SKILL.md +100 -0
  524. package/skills/gws-setup/SKILL.md +99 -0
  525. package/skills/gws-setup/reference.md +73 -0
  526. package/skills/investigation/SKILL.md +100 -0
  527. package/skills/memory-curation/SKILL.md +83 -0
  528. package/skills/memory-search/SKILL.md +88 -0
  529. package/skills/orchestrator-approval/SKILL.md +160 -0
  530. package/skills/orchestrator-approval/reference.md +174 -0
  531. package/skills/pending-approvals/SKILL.md +72 -0
  532. package/skills/pending-approvals/reference.md +214 -0
  533. package/skills/readme-writing/SKILL.md +71 -0
  534. package/skills/readme-writing/reference.md +188 -0
  535. package/skills/reference.md +135 -0
  536. package/skills/request-approval/SKILL.md +140 -0
  537. package/skills/request-approval/examples.md +140 -0
  538. package/skills/request-approval/reference.md +57 -0
  539. package/skills/schedule-task/SKILL.md +64 -0
  540. package/skills/schedule-task/reference.md +233 -0
  541. package/skills/security-tiers/SKILL.md +141 -0
  542. package/skills/security-tiers/destructive-commands-reference.md +623 -0
  543. package/skills/security-tiers/reference.md +39 -0
  544. package/skills/session-reflection/SKILL.md +69 -0
  545. package/skills/skill-creation/SKILL.md +92 -0
  546. package/skills/skill-creation/reference.md +29 -0
  547. package/skills/terraform-patterns/SKILL.md +89 -0
  548. package/skills/terraform-patterns/reference.md +93 -0
  549. package/templates/README.md +69 -0
  550. package/templates/managed-settings.template.json +43 -0
  551. package/tools/__init__.py +9 -0
  552. package/tools/agentic-loop/decide-status.py +210 -0
  553. package/tools/agentic-loop/parse-metric.py +106 -0
  554. package/tools/agentic-loop/record-iteration.py +221 -0
  555. package/tools/context/README.md +132 -0
  556. package/tools/context/__init__.py +42 -0
  557. package/tools/context/_paths.py +20 -0
  558. package/tools/context/context_provider.py +721 -0
  559. package/tools/context/context_section_reader.py +342 -0
  560. package/tools/context/deep_merge.py +159 -0
  561. package/tools/context/pending_updates.py +760 -0
  562. package/tools/context/surface_router.py +278 -0
  563. package/tools/fast-queries/README.md +65 -0
  564. package/tools/fast-queries/__init__.py +30 -0
  565. package/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
  566. package/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
  567. package/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
  568. package/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
  569. package/tools/fast-queries/run_triage.sh +59 -0
  570. package/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
  571. package/tools/gaia_simulator/__init__.py +33 -0
  572. package/tools/gaia_simulator/cli.py +354 -0
  573. package/tools/gaia_simulator/extractor.py +457 -0
  574. package/tools/gaia_simulator/reporter.py +258 -0
  575. package/tools/gaia_simulator/routing_simulator.py +334 -0
  576. package/tools/gaia_simulator/runner.py +539 -0
  577. package/tools/gaia_simulator/skills_mapper.py +264 -0
  578. package/tools/memory/README.md +0 -0
  579. package/tools/memory/__init__.py +20 -0
  580. package/tools/memory/backfill_fts5.py +107 -0
  581. package/tools/memory/conflict_detector.py +295 -0
  582. package/tools/memory/episodic.py +1210 -0
  583. package/tools/memory/git_invalidator.py +262 -0
  584. package/tools/memory/paths.py +102 -0
  585. package/tools/memory/scoring.py +193 -0
  586. package/tools/memory/search_store.py +375 -0
  587. package/tools/persist_transcript_analysis.py +85 -0
  588. package/tools/review/__init__.py +1 -0
  589. package/tools/review/review_engine.py +157 -0
  590. package/tools/scan/__init__.py +35 -0
  591. package/tools/scan/config.py +247 -0
  592. package/tools/scan/merge.py +212 -0
  593. package/tools/scan/orchestrator.py +549 -0
  594. package/tools/scan/registry.py +127 -0
  595. package/tools/scan/scanners/__init__.py +18 -0
  596. package/tools/scan/scanners/base.py +137 -0
  597. package/tools/scan/scanners/environment.py +349 -0
  598. package/tools/scan/scanners/git.py +570 -0
  599. package/tools/scan/scanners/infrastructure.py +875 -0
  600. package/tools/scan/scanners/orchestration.py +600 -0
  601. package/tools/scan/scanners/stack.py +1085 -0
  602. package/tools/scan/scanners/tools.py +260 -0
  603. package/tools/scan/setup.py +686 -0
  604. package/tools/scan/tests/__init__.py +1 -0
  605. package/tools/scan/tests/conftest.py +796 -0
  606. package/tools/scan/tests/test_environment.py +323 -0
  607. package/tools/scan/tests/test_git.py +419 -0
  608. package/tools/scan/tests/test_infrastructure.py +382 -0
  609. package/tools/scan/tests/test_integration.py +920 -0
  610. package/tools/scan/tests/test_merge.py +269 -0
  611. package/tools/scan/tests/test_orchestration.py +304 -0
  612. package/tools/scan/tests/test_stack.py +604 -0
  613. package/tools/scan/tests/test_tools.py +349 -0
  614. package/tools/scan/ui.py +624 -0
  615. package/tools/scan/verify.py +270 -0
  616. package/tools/scan/walk.py +118 -0
  617. package/tools/scan/workspace.py +85 -0
  618. package/tools/validation/README.md +244 -0
  619. package/tools/validation/__init__.py +17 -0
  620. package/tools/validation/approval_gate.py +321 -0
  621. package/tools/validation/validate_skills.py +189 -0
@@ -0,0 +1,601 @@
1
+ #!/usr/bin/env bash
2
+ # validate-sandbox.sh -- end-to-end consumer-install verification harness.
3
+ #
4
+ # Two target modes:
5
+ #
6
+ # --target sandbox (default):
7
+ # Creates an ephemeral sandbox project populated from
8
+ # tests/fixtures/sandbox-project/, installs the target Gaia version, and
9
+ # exercises the install-time code paths (postinstall hook merge, FTS5
10
+ # backfill safety-net) plus read-side CLI surface (version, doctor,
11
+ # status, context show, memory stats/search, scan).
12
+ #
13
+ # --target local:
14
+ # Installs Gaia directly into a real workspace. If --workspace <path> is
15
+ # passed, that path is used as-is. Otherwise auto-detection walks up
16
+ # from cwd looking for a .claude/ with a Gaia instance marker
17
+ # (.claude/hooks/, .claude/agents/, or node_modules/@jaguilar87/gaia/),
18
+ # falling back to $HOME/ws/me/ if present. NO cleanup -- the install
19
+ # IS the installation. A fresh tarball install avoids per-path approval
20
+ # prompts for edited files during a session.
21
+ #
22
+ # Exit 0 when every check passes; 1 otherwise. `--stay` keeps the sandbox
23
+ # dir for post-mortem inspection (path printed on exit). Only meaningful
24
+ # with --target sandbox.
25
+
26
+ set -euo pipefail
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # Argparse
30
+ # ---------------------------------------------------------------------------
31
+
32
+ VERSION_SPEC=""
33
+ TARBALL_PATH=""
34
+ STAY=0
35
+ TARGET="sandbox"
36
+ WORKSPACE_OVERRIDE=""
37
+
38
+ usage() {
39
+ cat <<'EOF'
40
+ Usage:
41
+ bin/validate-sandbox.sh [--version <spec>] [--tarball <path>]
42
+ [--target sandbox|local] [--workspace <path>]
43
+ [--stay]
44
+
45
+ Options:
46
+ --version <spec> npm version specifier, e.g. "@rc", "@5.0.0-rc1",
47
+ "@jaguilar87/gaia@5.0.0-rc1". Default: "@rc".
48
+ --tarball <path> Install from a local tarball (from `npm pack`).
49
+ Takes precedence over --version.
50
+ --target <mode> sandbox (default): ephemeral /tmp/gaia-sandbox-<ts>/.
51
+ local: install over a real workspace (see --workspace
52
+ or auto-detect from cwd).
53
+ Local mode skips the settings-preservation check
54
+ (no pre-install snapshot of the real workspace).
55
+ --workspace <path> Explicit target directory for --target local.
56
+ Bypasses auto-detection. Ignored with --target sandbox.
57
+ --stay Do NOT clean up the sandbox dir on exit. Useful for
58
+ debugging; sandbox path is printed on exit.
59
+ Ignored with --target local.
60
+ --help, -h Print this help and exit.
61
+ EOF
62
+ }
63
+
64
+ while [[ $# -gt 0 ]]; do
65
+ case "$1" in
66
+ --version)
67
+ VERSION_SPEC="$2"
68
+ shift 2
69
+ ;;
70
+ --tarball)
71
+ TARBALL_PATH="$2"
72
+ shift 2
73
+ ;;
74
+ --target)
75
+ TARGET="$2"
76
+ shift 2
77
+ ;;
78
+ --workspace)
79
+ WORKSPACE_OVERRIDE="$2"
80
+ shift 2
81
+ ;;
82
+ --stay)
83
+ STAY=1
84
+ shift
85
+ ;;
86
+ --help|-h)
87
+ usage
88
+ exit 0
89
+ ;;
90
+ *)
91
+ echo "Unknown argument: $1" >&2
92
+ usage >&2
93
+ exit 2
94
+ ;;
95
+ esac
96
+ done
97
+
98
+ if [[ "${TARGET}" != "sandbox" && "${TARGET}" != "local" ]]; then
99
+ echo "FATAL: --target must be 'sandbox' or 'local', got '${TARGET}'" >&2
100
+ exit 2
101
+ fi
102
+
103
+ # Default to @rc when no install source given.
104
+ if [[ -z "${TARBALL_PATH}" && -z "${VERSION_SPEC}" ]]; then
105
+ VERSION_SPEC="@rc"
106
+ fi
107
+
108
+ # ---------------------------------------------------------------------------
109
+ # Paths
110
+ # ---------------------------------------------------------------------------
111
+
112
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
113
+ FIXTURE_DIR="${REPO_ROOT}/tests/fixtures/sandbox-project"
114
+
115
+ if [[ "${TARGET}" == "sandbox" && ! -d "${FIXTURE_DIR}" ]]; then
116
+ echo "FATAL: fixture dir not found at ${FIXTURE_DIR}" >&2
117
+ exit 1
118
+ fi
119
+
120
+ if [[ -n "${TARBALL_PATH}" ]]; then
121
+ # Resolve relative to cwd, then check existence
122
+ if [[ "${TARBALL_PATH}" != /* ]]; then
123
+ TARBALL_PATH="$(cd "$(dirname "${TARBALL_PATH}")" && pwd)/$(basename "${TARBALL_PATH}")"
124
+ fi
125
+ if [[ ! -f "${TARBALL_PATH}" ]]; then
126
+ echo "FATAL: tarball not found at ${TARBALL_PATH}" >&2
127
+ exit 1
128
+ fi
129
+ fi
130
+
131
+ # ---------------------------------------------------------------------------
132
+ # Determine working directory based on target
133
+ # ---------------------------------------------------------------------------
134
+
135
+ is_gaia_instance() {
136
+ # A directory is a Gaia instance if it has .claude/ with hook or agent
137
+ # content, or an already-installed Gaia package in node_modules.
138
+ local dir="$1"
139
+ [[ -d "${dir}/.claude/hooks" ]] && return 0
140
+ [[ -d "${dir}/.claude/agents" ]] && return 0
141
+ [[ -d "${dir}/node_modules/@jaguilar87/gaia" ]] && return 0
142
+ return 1
143
+ }
144
+
145
+ detect_local_workspace() {
146
+ # Priority 1: walk up from cwd looking for .claude/ with a Gaia marker.
147
+ # Preferring cwd means `cd project-X && npm run gaia:install-local`
148
+ # installs into project-X, not whatever comes first in $HOME.
149
+ local dir
150
+ dir="$(pwd)"
151
+ while [[ "${dir}" != "/" ]]; do
152
+ if [[ -d "${dir}/.claude" ]] && is_gaia_instance "${dir}"; then
153
+ echo "${dir}"
154
+ return 0
155
+ fi
156
+ dir="$(dirname "${dir}")"
157
+ done
158
+ # Priority 2: fallback to $HOME/ws/me if it exists and has .claude/.
159
+ if [[ -d "${HOME}/ws/me/.claude" ]]; then
160
+ echo "${HOME}/ws/me"
161
+ return 0
162
+ fi
163
+ return 1
164
+ }
165
+
166
+ is_noexec_mount() {
167
+ # Return 0 (true) if the directory's filesystem is mounted with noexec.
168
+ # Some WSL/Linux setups mount /tmp as tmpfs with noexec, which makes the
169
+ # installed bin shims unrunnable (rc=126 Permission denied) even though
170
+ # the exec bit is set. We detect that and pick a safe fallback.
171
+ local dir="$1"
172
+ [[ -d "${dir}" ]] || return 1
173
+ # findmnt is the most reliable; fall back to parsing /proc/mounts.
174
+ if command -v findmnt >/dev/null 2>&1; then
175
+ local opts
176
+ opts="$(findmnt -no OPTIONS --target "${dir}" 2>/dev/null || true)"
177
+ [[ "${opts}" == *noexec* ]] && return 0
178
+ return 1
179
+ fi
180
+ # Best-effort fallback: walk /proc/mounts for the longest matching mountpoint.
181
+ local resolved best_mp="" best_opts=""
182
+ resolved="$(cd "${dir}" 2>/dev/null && pwd -P)" || resolved="${dir}"
183
+ while IFS=' ' read -r _src mp _fs opts _rest; do
184
+ case "${resolved}/" in
185
+ "${mp}/"*)
186
+ if [[ ${#mp} -gt ${#best_mp} ]]; then
187
+ best_mp="${mp}"
188
+ best_opts="${opts}"
189
+ fi
190
+ ;;
191
+ esac
192
+ done < /proc/mounts
193
+ [[ "${best_opts}" == *noexec* ]] && return 0
194
+ return 1
195
+ }
196
+
197
+ select_sandbox_prefix() {
198
+ # Pick a parent directory for the ephemeral sandbox.
199
+ # Order: $TMPDIR (if set and exec-capable) -> /tmp (if exec-capable) ->
200
+ # $HOME/.cache/gaia-sandbox. Each candidate is rejected if its filesystem
201
+ # is mounted noexec, since npm bin shims must be directly executable.
202
+ local candidate
203
+ if [[ -n "${TMPDIR:-}" && -d "${TMPDIR}" ]]; then
204
+ if ! is_noexec_mount "${TMPDIR}"; then
205
+ echo "${TMPDIR%/}"
206
+ return 0
207
+ fi
208
+ echo "[sandbox] TMPDIR=${TMPDIR} is mounted noexec; falling back" >&2
209
+ fi
210
+ if [[ -d /tmp ]] && ! is_noexec_mount /tmp; then
211
+ echo "/tmp"
212
+ return 0
213
+ fi
214
+ if [[ -d /tmp ]]; then
215
+ echo "[sandbox] /tmp is mounted noexec; falling back to \$HOME/.cache" >&2
216
+ fi
217
+ candidate="${HOME}/.cache/gaia-sandbox"
218
+ mkdir -p "${candidate}"
219
+ if is_noexec_mount "${candidate}"; then
220
+ echo "FATAL: no exec-capable directory available for sandbox." >&2
221
+ echo " Tried: \$TMPDIR, /tmp, ${candidate} -- all noexec." >&2
222
+ echo " Set TMPDIR to an exec-capable path and retry." >&2
223
+ return 1
224
+ fi
225
+ echo "${candidate}"
226
+ }
227
+
228
+ if [[ "${TARGET}" == "sandbox" ]]; then
229
+ if ! SANDBOX_PREFIX="$(select_sandbox_prefix)"; then
230
+ exit 1
231
+ fi
232
+ WORKSPACE="${SANDBOX_PREFIX}/gaia-sandbox-$(date +%s)-$$"
233
+ echo "[sandbox] prefix: ${SANDBOX_PREFIX}"
234
+ mkdir -p "${WORKSPACE}"
235
+ else
236
+ if [[ -n "${WORKSPACE_OVERRIDE}" ]]; then
237
+ # Explicit override from --workspace flag. Resolve relative paths
238
+ # against cwd, then verify directory exists.
239
+ if [[ "${WORKSPACE_OVERRIDE}" != /* ]]; then
240
+ WORKSPACE_OVERRIDE="$(cd "$(dirname "${WORKSPACE_OVERRIDE}")" 2>/dev/null && pwd)/$(basename "${WORKSPACE_OVERRIDE}")"
241
+ fi
242
+ if [[ ! -d "${WORKSPACE_OVERRIDE}" ]]; then
243
+ echo "FATAL: --workspace path does not exist: ${WORKSPACE_OVERRIDE}" >&2
244
+ exit 1
245
+ fi
246
+ WORKSPACE="${WORKSPACE_OVERRIDE}"
247
+ echo "[local] target workspace (override): ${WORKSPACE}"
248
+ elif ! WORKSPACE="$(detect_local_workspace)"; then
249
+ echo "FATAL: --target local could not locate a workspace." >&2
250
+ echo " Walked up from cwd looking for a .claude/ with a Gaia marker" >&2
251
+ echo " (hooks/, agents/, or node_modules/@jaguilar87/gaia/)," >&2
252
+ echo " fallback \$HOME/ws/me/.claude/ also absent." >&2
253
+ echo " Pass --workspace <path> to override." >&2
254
+ exit 1
255
+ else
256
+ echo "[local] target workspace: ${WORKSPACE}"
257
+ fi
258
+ fi
259
+
260
+ # ---------------------------------------------------------------------------
261
+ # Cleanup trap (sandbox only)
262
+ # ---------------------------------------------------------------------------
263
+
264
+ cleanup() {
265
+ local rc=$?
266
+ if [[ "${TARGET}" == "sandbox" ]]; then
267
+ if [[ "${STAY}" -eq 1 ]]; then
268
+ echo
269
+ echo "Sandbox preserved at: ${WORKSPACE}"
270
+ echo "Remove manually when done: rm -rf '${WORKSPACE}'"
271
+ else
272
+ rm -rf "${WORKSPACE}" 2>/dev/null || true
273
+ fi
274
+ fi
275
+ exit "${rc}"
276
+ }
277
+ trap cleanup EXIT
278
+
279
+ # ---------------------------------------------------------------------------
280
+ # Check harness
281
+ # ---------------------------------------------------------------------------
282
+
283
+ CHECK_NAMES=()
284
+ CHECK_STATUS=()
285
+ CHECK_DETAILS=()
286
+ CHECK_MS=()
287
+ TOTAL_START_MS=$(date +%s%3N 2>/dev/null || python3 -c 'import time; print(int(time.time()*1000))')
288
+
289
+ record() {
290
+ local name="$1" status="$2" detail="$3" ms="$4"
291
+ CHECK_NAMES+=("${name}")
292
+ CHECK_STATUS+=("${status}")
293
+ CHECK_DETAILS+=("${detail}")
294
+ CHECK_MS+=("${ms}")
295
+ printf " [%-4s] %-36s %-50s (%sms)\n" "${status}" "${name}" "${detail}" "${ms}"
296
+ }
297
+
298
+ now_ms() {
299
+ date +%s%3N 2>/dev/null || python3 -c 'import time; print(int(time.time()*1000))'
300
+ }
301
+
302
+ # ---------------------------------------------------------------------------
303
+ # Prepare sandbox (fixture copy) — sandbox target only
304
+ # ---------------------------------------------------------------------------
305
+
306
+ prepare_sandbox() {
307
+ echo "[prepare] copying fixture -> ${WORKSPACE}"
308
+ # Copy tree, stripping .template and .fixture suffixes.
309
+ (
310
+ cd "${FIXTURE_DIR}"
311
+ find . -type f | while IFS= read -r src; do
312
+ local dest="${WORKSPACE}/${src#./}"
313
+ # Strip .template / .fixture suffix
314
+ case "${dest}" in
315
+ *.template)
316
+ dest="${dest%.template}"
317
+ ;;
318
+ *.fixture)
319
+ dest="${dest%.fixture}"
320
+ ;;
321
+ esac
322
+ # Rename sandbox-settings.local.json -> settings.local.json
323
+ dest="${dest//sandbox-settings.local.json/settings.local.json}"
324
+ mkdir -p "$(dirname "${dest}")"
325
+ cp "${src}" "${dest}"
326
+ done
327
+ )
328
+ echo "[prepare] fixture copied"
329
+ }
330
+
331
+ # ---------------------------------------------------------------------------
332
+ # Install
333
+ # ---------------------------------------------------------------------------
334
+
335
+ install_package() {
336
+ cd "${WORKSPACE}"
337
+
338
+ if [[ "${TARGET}" == "sandbox" && ! -f package.json ]]; then
339
+ echo "FATAL: package.json missing after prepare" >&2
340
+ return 1
341
+ fi
342
+
343
+ # In local mode, ensure a package.json exists so npm install has an anchor.
344
+ if [[ "${TARGET}" == "local" && ! -f package.json ]]; then
345
+ echo "[install] local mode: no package.json in ${WORKSPACE}, creating minimal one"
346
+ npm init -y --silent >/dev/null 2>&1 || npm init -y
347
+ fi
348
+
349
+ if [[ -n "${TARBALL_PATH}" ]]; then
350
+ echo "[install] installing tarball ${TARBALL_PATH}"
351
+ npm install --no-audit --no-fund "${TARBALL_PATH}"
352
+ else
353
+ # Accept forms: "@rc", "5.0.0-rc1", "@5.0.0-rc1",
354
+ # "@jaguilar87/gaia@5.0.0-rc1"
355
+ local spec="${VERSION_SPEC}"
356
+ if [[ "${spec}" == @* && "${spec}" != @jaguilar87/* ]]; then
357
+ # e.g. "@rc" or "@5.0.0-rc1"
358
+ spec="@jaguilar87/gaia${spec}"
359
+ elif [[ "${spec}" != @jaguilar87/* && "${spec}" != "" ]]; then
360
+ # Bare "5.0.0-rc1"
361
+ spec="@jaguilar87/gaia@${spec}"
362
+ fi
363
+ echo "[install] installing ${spec}"
364
+ npm install --no-audit --no-fund "${spec}"
365
+ fi
366
+ }
367
+
368
+ # ---------------------------------------------------------------------------
369
+ # Helpers
370
+ # ---------------------------------------------------------------------------
371
+
372
+ sha256() {
373
+ if command -v sha256sum >/dev/null 2>&1; then
374
+ sha256sum "$1" | awk '{print $1}'
375
+ elif command -v shasum >/dev/null 2>&1; then
376
+ shasum -a 256 "$1" | awk '{print $1}'
377
+ else
378
+ python3 -c "import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],'rb').read()).hexdigest())" "$1"
379
+ fi
380
+ }
381
+
382
+ # ---------------------------------------------------------------------------
383
+ # Execute
384
+ # ---------------------------------------------------------------------------
385
+
386
+ if [[ "${TARGET}" == "sandbox" ]]; then
387
+ prepare_sandbox
388
+ fi
389
+
390
+ SETTINGS_FILE="${WORKSPACE}/.claude/settings.local.json"
391
+ PRE_CHECKSUM=""
392
+ if [[ "${TARGET}" == "sandbox" && -f "${SETTINGS_FILE}" ]]; then
393
+ PRE_CHECKSUM="$(sha256 "${SETTINGS_FILE}")"
394
+ fi
395
+
396
+ install_package
397
+
398
+ # Put installed bin at head of PATH so we can call `gaia` directly
399
+ # (runtime check: node-independent invocation, no npx indirection).
400
+ export PATH="${WORKSPACE}/node_modules/.bin:${PATH}"
401
+
402
+ echo
403
+ echo "=== Running checks ==="
404
+
405
+ cd "${WORKSPACE}"
406
+
407
+ # 1. gaia --version
408
+ t0="$(now_ms)"
409
+ if out="$(gaia --version 2>&1)"; then
410
+ ms=$(( $(now_ms) - t0 ))
411
+ if grep -qE 'gaia [0-9]+\.[0-9]+\.[0-9]+' <<<"${out}"; then
412
+ record "gaia --version" "PASS" "$(echo "${out}" | head -1)" "${ms}"
413
+ else
414
+ record "gaia --version" "FAIL" "unexpected output: ${out:0:60}" "${ms}"
415
+ fi
416
+ else
417
+ ms=$(( $(now_ms) - t0 ))
418
+ record "gaia --version" "FAIL" "command failed: ${out:0:60}" "${ms}"
419
+ fi
420
+
421
+ # 2. gaia doctor --json (parse and check status)
422
+ t0="$(now_ms)"
423
+ if out="$(gaia doctor --json 2>&1)"; then
424
+ rc=0
425
+ else
426
+ rc=$?
427
+ fi
428
+ ms=$(( $(now_ms) - t0 ))
429
+ # doctor may exit 1 on warnings; allow rc=0 or rc=1 if json is parseable
430
+ if python3 -c "import json,sys; d=json.loads(sys.argv[1]); c=d['checks']; p=sum(1 for r in c if r['severity']=='pass'); t=len(c); sys.exit(0 if t>=5 and p>=max(1,t-3) else 1)" "${out}" 2>/dev/null; then
431
+ total=$(python3 -c "import json,sys; d=json.loads(sys.argv[1]); print(len(d['checks']))" "${out}")
432
+ passed=$(python3 -c "import json,sys; d=json.loads(sys.argv[1]); print(sum(1 for r in d['checks'] if r['severity']=='pass'))" "${out}")
433
+ record "gaia doctor --json" "PASS" "${passed}/${total} checks passed" "${ms}"
434
+ else
435
+ record "gaia doctor --json" "FAIL" "parse/threshold failure (rc=${rc})" "${ms}"
436
+ fi
437
+
438
+ # 3. gaia status --json
439
+ t0="$(now_ms)"
440
+ if out="$(gaia status --json 2>&1)"; then
441
+ ms=$(( $(now_ms) - t0 ))
442
+ if python3 -c "import json,sys; json.loads(sys.argv[1])" "${out}" 2>/dev/null; then
443
+ record "gaia status --json" "PASS" "json parsed" "${ms}"
444
+ else
445
+ record "gaia status --json" "FAIL" "invalid json: ${out:0:60}" "${ms}"
446
+ fi
447
+ else
448
+ ms=$(( $(now_ms) - t0 ))
449
+ record "gaia status --json" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
450
+ fi
451
+
452
+ # 4. gaia context show
453
+ t0="$(now_ms)"
454
+ if out="$(gaia context show 2>&1)"; then
455
+ ms=$(( $(now_ms) - t0 ))
456
+ record "gaia context show" "PASS" "exit 0" "${ms}"
457
+ else
458
+ ms=$(( $(now_ms) - t0 ))
459
+ record "gaia context show" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
460
+ fi
461
+
462
+ # 5. gaia memory stats --json (verify FTS5 backfill triggered)
463
+ t0="$(now_ms)"
464
+ if out="$(gaia memory stats --json 2>&1)"; then
465
+ ms=$(( $(now_ms) - t0 ))
466
+ indexed=$(python3 -c "import json,sys; d=json.loads(sys.argv[1]); print(d.get('indexed',0))" "${out}" 2>/dev/null || echo 0)
467
+ total=$(python3 -c "import json,sys; d=json.loads(sys.argv[1]); print(d.get('total_episodes',0))" "${out}" 2>/dev/null || echo 0)
468
+ if [[ "${TARGET}" == "sandbox" ]]; then
469
+ if [[ "${indexed}" -ge 9 ]]; then
470
+ record "memory stats (FTS5 backfill)" "PASS" "indexed=${indexed}/${total}" "${ms}"
471
+ else
472
+ record "memory stats (FTS5 backfill)" "FAIL" "indexed=${indexed}/${total} (need >=9)" "${ms}"
473
+ fi
474
+ else
475
+ # Local mode: workspace memory state is real and arbitrary. Assert
476
+ # indexed == total (backfill kept up) rather than a hardcoded floor.
477
+ if [[ "${indexed}" -eq "${total}" && "${total}" -ge 0 ]]; then
478
+ record "memory stats (FTS5 backfill)" "PASS" "indexed=${indexed}/${total}" "${ms}"
479
+ else
480
+ record "memory stats (FTS5 backfill)" "FAIL" "indexed=${indexed}/${total} (drift)" "${ms}"
481
+ fi
482
+ fi
483
+ else
484
+ ms=$(( $(now_ms) - t0 ))
485
+ record "memory stats (FTS5 backfill)" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
486
+ fi
487
+
488
+ # 6. gaia memory search "deploy" --limit 3 --json
489
+ t0="$(now_ms)"
490
+ if out="$(gaia memory search deploy --limit 3 --json 2>&1)"; then
491
+ ms=$(( $(now_ms) - t0 ))
492
+ hits=$(python3 -c "
493
+ import json,sys
494
+ try:
495
+ d=json.loads(sys.argv[1])
496
+ if isinstance(d,list):
497
+ print(len(d))
498
+ elif isinstance(d,dict):
499
+ for k in ('results','hits','matches'):
500
+ if k in d:
501
+ print(len(d[k])); sys.exit(0)
502
+ print(0)
503
+ else:
504
+ print(0)
505
+ except Exception:
506
+ print(0)
507
+ " "${out}" 2>/dev/null || echo 0)
508
+ if [[ "${TARGET}" == "sandbox" ]]; then
509
+ if [[ "${hits}" -ge 1 ]]; then
510
+ record "memory search deploy" "PASS" "${hits} hit(s)" "${ms}"
511
+ else
512
+ record "memory search deploy" "FAIL" "0 hits (expected >=1)" "${ms}"
513
+ fi
514
+ else
515
+ # Local mode: "deploy" is not guaranteed to appear in the real
516
+ # workspace memory. Only assert the command ran successfully.
517
+ record "memory search deploy" "PASS" "${hits} hit(s) (local)" "${ms}"
518
+ fi
519
+ else
520
+ ms=$(( $(now_ms) - t0 ))
521
+ record "memory search deploy" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
522
+ fi
523
+
524
+ # 7. gaia scan (exit 0)
525
+ # Use `gaia context scan --dry-run` (the higher-level CLI subcommand which
526
+ # supports --dry-run) rather than the bare `gaia-scan` binary, which wraps
527
+ # gaia-scan.py and does NOT accept --dry-run. --dry-run validates freshness
528
+ # without running the scanners or writing project-context.json.
529
+ t0="$(now_ms)"
530
+ if out="$(gaia context scan --dry-run 2>&1)"; then
531
+ ms=$(( $(now_ms) - t0 ))
532
+ record "gaia scan" "PASS" "scanner ran (dry-run)" "${ms}"
533
+ else
534
+ ms=$(( $(now_ms) - t0 ))
535
+ record "gaia scan" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
536
+ fi
537
+
538
+ # 8. Checksum preservation: settings.local.json unchanged by postinstall
539
+ # Sandbox only -- local mode has no meaningful "pre" snapshot.
540
+ if [[ "${TARGET}" == "sandbox" ]]; then
541
+ if [[ -n "${PRE_CHECKSUM}" && -f "${SETTINGS_FILE}" ]]; then
542
+ POST_CHECKSUM="$(sha256 "${SETTINGS_FILE}")"
543
+ t0="$(now_ms)"
544
+ if python3 -c "
545
+ import json,sys
546
+ p=json.load(open(sys.argv[1]))
547
+ assert p.get('_sandbox_sentinel')=='DO_NOT_TOUCH_ME', 'sentinel clobbered'
548
+ assert p.get('env',{}).get('SANDBOX_FIXTURE_MARKER')=='preserved-across-install', 'env marker clobbered'
549
+ " "${SETTINGS_FILE}" 2>/dev/null; then
550
+ ms=$(( $(now_ms) - t0 ))
551
+ record "settings preservation" "PASS" "sentinel + env markers intact" "${ms}"
552
+ else
553
+ ms=$(( $(now_ms) - t0 ))
554
+ record "settings preservation" "FAIL" "user keys clobbered by postinstall" "${ms}"
555
+ fi
556
+ else
557
+ record "settings preservation" "FAIL" "settings.local.json missing pre or post" "0"
558
+ fi
559
+ else
560
+ record "settings preservation" "SKIP" "local mode (no pre-snapshot)" "0"
561
+ fi
562
+
563
+ # ---------------------------------------------------------------------------
564
+ # Summary
565
+ # ---------------------------------------------------------------------------
566
+
567
+ TOTAL_END_MS="$(now_ms)"
568
+ TOTAL_MS=$((TOTAL_END_MS - TOTAL_START_MS))
569
+
570
+ echo
571
+ echo "=== Summary ==="
572
+ pass_count=0
573
+ fail_count=0
574
+ skip_count=0
575
+ for status in "${CHECK_STATUS[@]}"; do
576
+ case "${status}" in
577
+ PASS) pass_count=$((pass_count + 1)) ;;
578
+ SKIP) skip_count=$((skip_count + 1)) ;;
579
+ *) fail_count=$((fail_count + 1)) ;;
580
+ esac
581
+ done
582
+
583
+ echo " Passed: ${pass_count}"
584
+ echo " Failed: ${fail_count}"
585
+ echo " Skipped: ${skip_count}"
586
+ echo " Total time: ${TOTAL_MS}ms"
587
+ echo
588
+
589
+ if [[ "${fail_count}" -gt 0 ]]; then
590
+ echo "RESULT: FAIL"
591
+ exit 1
592
+ fi
593
+
594
+ echo "RESULT: PASS"
595
+
596
+ if [[ "${TARGET}" == "local" ]]; then
597
+ echo
598
+ echo "Gaia fresh install complete in ${WORKSPACE}. Restart Claude Code to reload skills/hooks/agents."
599
+ fi
600
+
601
+ exit 0
@@ -0,0 +1,64 @@
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 project-context.json
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)