@jaguilar87/gaia-ops 4.4.0 → 4.7.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 (371) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +12 -3
  3. package/ARCHITECTURE.md +9 -8
  4. package/CHANGELOG.md +34 -0
  5. package/README.md +43 -11
  6. package/agents/terraform-architect.md +1 -1
  7. package/bin/README.md +2 -2
  8. package/bin/gaia-doctor.js +18 -5
  9. package/bin/gaia-history.js +0 -1
  10. package/bin/gaia-metrics.js +2 -2
  11. package/bin/gaia-scan.py +23 -1
  12. package/bin/gaia-update.js +346 -54
  13. package/bin/pre-publish-validate.js +33 -10
  14. package/commands/gaia.md +37 -0
  15. package/config/README.md +3 -9
  16. package/config/context-contracts.json +47 -15
  17. package/config/surface-routing.json +9 -1
  18. package/dist/gaia-ops/.claude-plugin/plugin.json +22 -0
  19. package/dist/gaia-ops/agents/cloud-troubleshooter.md +73 -0
  20. package/dist/gaia-ops/agents/devops-developer.md +57 -0
  21. package/dist/gaia-ops/agents/gaia-system.md +58 -0
  22. package/dist/gaia-ops/agents/gitops-operator.md +60 -0
  23. package/dist/gaia-ops/agents/speckit-planner.md +71 -0
  24. package/dist/gaia-ops/agents/terraform-architect.md +60 -0
  25. package/dist/gaia-ops/commands/gaia.md +37 -0
  26. package/dist/gaia-ops/config/README.md +58 -0
  27. package/dist/gaia-ops/config/cloud/aws.json +140 -0
  28. package/dist/gaia-ops/config/cloud/gcp.json +145 -0
  29. package/dist/gaia-ops/config/context-contracts.json +131 -0
  30. package/dist/gaia-ops/config/git_standards.json +72 -0
  31. package/dist/gaia-ops/config/surface-routing.json +197 -0
  32. package/dist/gaia-ops/config/universal-rules.json +10 -0
  33. package/dist/gaia-ops/hooks/adapters/__init__.py +52 -0
  34. package/dist/gaia-ops/hooks/adapters/base.py +219 -0
  35. package/dist/gaia-ops/hooks/adapters/channel.py +17 -0
  36. package/dist/gaia-ops/hooks/adapters/claude_code.py +1477 -0
  37. package/dist/gaia-ops/hooks/adapters/types.py +194 -0
  38. package/dist/gaia-ops/hooks/adapters/utils.py +25 -0
  39. package/dist/gaia-ops/hooks/hooks.json +126 -0
  40. package/dist/gaia-ops/hooks/modules/__init__.py +15 -0
  41. package/dist/gaia-ops/hooks/modules/agents/__init__.py +29 -0
  42. package/dist/gaia-ops/hooks/modules/agents/contract_validator.py +647 -0
  43. package/dist/gaia-ops/hooks/modules/agents/response_contract.py +496 -0
  44. package/dist/gaia-ops/hooks/modules/agents/skill_injection_verifier.py +124 -0
  45. package/dist/gaia-ops/hooks/modules/agents/task_info_builder.py +74 -0
  46. package/dist/gaia-ops/hooks/modules/agents/transcript_analyzer.py +458 -0
  47. package/dist/gaia-ops/hooks/modules/agents/transcript_reader.py +152 -0
  48. package/dist/gaia-ops/hooks/modules/audit/__init__.py +28 -0
  49. package/dist/gaia-ops/hooks/modules/audit/event_detector.py +168 -0
  50. package/dist/gaia-ops/hooks/modules/audit/logger.py +131 -0
  51. package/dist/gaia-ops/hooks/modules/audit/metrics.py +134 -0
  52. package/dist/gaia-ops/hooks/modules/audit/workflow_auditor.py +576 -0
  53. package/dist/gaia-ops/hooks/modules/audit/workflow_recorder.py +296 -0
  54. package/dist/gaia-ops/hooks/modules/context/__init__.py +11 -0
  55. package/dist/gaia-ops/hooks/modules/context/anchor_tracker.py +317 -0
  56. package/dist/gaia-ops/hooks/modules/context/compact_context_builder.py +215 -0
  57. package/dist/gaia-ops/hooks/modules/context/context_cache.py +129 -0
  58. package/dist/gaia-ops/hooks/modules/context/context_freshness.py +145 -0
  59. package/dist/gaia-ops/hooks/modules/context/context_injector.py +427 -0
  60. package/dist/gaia-ops/hooks/modules/context/context_writer.py +518 -0
  61. package/dist/gaia-ops/hooks/modules/context/contracts_loader.py +161 -0
  62. package/dist/gaia-ops/hooks/modules/core/__init__.py +40 -0
  63. package/dist/gaia-ops/hooks/modules/core/hook_entry.py +78 -0
  64. package/dist/gaia-ops/hooks/modules/core/paths.py +160 -0
  65. package/dist/gaia-ops/hooks/modules/core/plugin_mode.py +149 -0
  66. package/dist/gaia-ops/hooks/modules/core/plugin_setup.py +558 -0
  67. package/dist/gaia-ops/hooks/modules/core/state.py +179 -0
  68. package/dist/gaia-ops/hooks/modules/core/stdin.py +24 -0
  69. package/dist/gaia-ops/hooks/modules/events/__init__.py +1 -0
  70. package/dist/gaia-ops/hooks/modules/events/event_writer.py +210 -0
  71. package/dist/gaia-ops/hooks/modules/identity/__init__.py +0 -0
  72. package/dist/gaia-ops/hooks/modules/identity/identity_provider.py +21 -0
  73. package/dist/gaia-ops/hooks/modules/identity/ops_identity.py +34 -0
  74. package/dist/gaia-ops/hooks/modules/identity/security_identity.py +10 -0
  75. package/dist/gaia-ops/hooks/modules/memory/__init__.py +8 -0
  76. package/dist/gaia-ops/hooks/modules/memory/episode_writer.py +227 -0
  77. package/dist/gaia-ops/hooks/modules/orchestrator/__init__.py +1 -0
  78. package/dist/gaia-ops/hooks/modules/orchestrator/delegate_mode.py +128 -0
  79. package/dist/gaia-ops/hooks/modules/scanning/__init__.py +8 -0
  80. package/dist/gaia-ops/hooks/modules/scanning/scan_trigger.py +84 -0
  81. package/dist/gaia-ops/hooks/modules/security/__init__.py +89 -0
  82. package/dist/gaia-ops/hooks/modules/security/approval_cleanup.py +87 -0
  83. package/dist/gaia-ops/hooks/modules/security/approval_constants.py +23 -0
  84. package/dist/gaia-ops/hooks/modules/security/approval_grants.py +912 -0
  85. package/dist/gaia-ops/hooks/modules/security/approval_messages.py +71 -0
  86. package/dist/gaia-ops/hooks/modules/security/approval_scopes.py +153 -0
  87. package/dist/gaia-ops/hooks/modules/security/blocked_commands.py +584 -0
  88. package/dist/gaia-ops/hooks/modules/security/blocked_message_formatter.py +86 -0
  89. package/dist/gaia-ops/hooks/modules/security/command_semantics.py +130 -0
  90. package/dist/gaia-ops/hooks/modules/security/gitops_validator.py +179 -0
  91. package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +850 -0
  92. package/dist/gaia-ops/hooks/modules/security/prompt_validator.py +40 -0
  93. package/dist/gaia-ops/hooks/modules/security/tiers.py +196 -0
  94. package/dist/gaia-ops/hooks/modules/session/__init__.py +10 -0
  95. package/dist/gaia-ops/hooks/modules/session/session_context_writer.py +100 -0
  96. package/dist/gaia-ops/hooks/modules/session/session_event_injector.py +158 -0
  97. package/dist/gaia-ops/hooks/modules/session/session_manager.py +31 -0
  98. package/dist/gaia-ops/hooks/modules/tools/__init__.py +25 -0
  99. package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +708 -0
  100. package/dist/gaia-ops/hooks/modules/tools/cloud_pipe_validator.py +181 -0
  101. package/dist/gaia-ops/hooks/modules/tools/hook_response.py +55 -0
  102. package/dist/gaia-ops/hooks/modules/tools/shell_parser.py +227 -0
  103. package/dist/gaia-ops/hooks/modules/tools/task_validator.py +283 -0
  104. package/dist/gaia-ops/hooks/modules/validation/__init__.py +23 -0
  105. package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +380 -0
  106. package/dist/gaia-ops/hooks/post_compact.py +43 -0
  107. package/dist/gaia-ops/hooks/post_tool_use.py +54 -0
  108. package/dist/gaia-ops/hooks/pre_tool_use.py +383 -0
  109. package/dist/gaia-ops/hooks/session_start.py +69 -0
  110. package/dist/gaia-ops/hooks/stop_hook.py +69 -0
  111. package/dist/gaia-ops/hooks/subagent_start.py +71 -0
  112. package/dist/gaia-ops/hooks/subagent_stop.py +288 -0
  113. package/dist/gaia-ops/hooks/task_completed.py +70 -0
  114. package/dist/gaia-ops/hooks/user_prompt_submit.py +177 -0
  115. package/dist/gaia-ops/settings.json +72 -0
  116. package/dist/gaia-ops/skills/README.md +109 -0
  117. package/dist/gaia-ops/skills/agent-protocol/SKILL.md +105 -0
  118. package/dist/gaia-ops/skills/agent-protocol/examples.md +170 -0
  119. package/dist/gaia-ops/skills/agent-response/SKILL.md +53 -0
  120. package/dist/gaia-ops/skills/approval/SKILL.md +85 -0
  121. package/dist/gaia-ops/skills/approval/examples.md +140 -0
  122. package/dist/gaia-ops/skills/approval/reference.md +57 -0
  123. package/dist/gaia-ops/skills/command-execution/SKILL.md +64 -0
  124. package/dist/gaia-ops/skills/command-execution/reference.md +83 -0
  125. package/dist/gaia-ops/skills/context-updater/SKILL.md +76 -0
  126. package/dist/gaia-ops/skills/context-updater/examples.md +71 -0
  127. package/dist/gaia-ops/skills/developer-patterns/SKILL.md +93 -0
  128. package/dist/gaia-ops/skills/developer-patterns/reference.md +112 -0
  129. package/dist/gaia-ops/skills/execution/SKILL.md +66 -0
  130. package/dist/gaia-ops/skills/fast-queries/SKILL.md +47 -0
  131. package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +92 -0
  132. package/dist/gaia-ops/skills/gaia-patterns/reference.md +22 -0
  133. package/dist/gaia-ops/skills/git-conventions/SKILL.md +48 -0
  134. package/dist/gaia-ops/skills/gitops-patterns/SKILL.md +73 -0
  135. package/dist/gaia-ops/skills/gitops-patterns/reference.md +183 -0
  136. package/dist/gaia-ops/skills/investigation/SKILL.md +77 -0
  137. package/dist/gaia-ops/skills/orchestrator-approval/SKILL.md +64 -0
  138. package/dist/gaia-ops/skills/reference.md +134 -0
  139. package/dist/gaia-ops/skills/security-tiers/SKILL.md +61 -0
  140. package/dist/gaia-ops/skills/security-tiers/destructive-commands-reference.md +623 -0
  141. package/dist/gaia-ops/skills/security-tiers/reference.md +39 -0
  142. package/dist/gaia-ops/skills/skill-creation/SKILL.md +119 -0
  143. package/dist/gaia-ops/skills/specification/SKILL.md +186 -0
  144. package/dist/gaia-ops/skills/speckit-workflow/SKILL.md +165 -0
  145. package/dist/gaia-ops/skills/speckit-workflow/reference.md +117 -0
  146. package/dist/gaia-ops/skills/terraform-patterns/SKILL.md +63 -0
  147. package/dist/gaia-ops/skills/terraform-patterns/reference.md +93 -0
  148. package/dist/gaia-ops/speckit/README.md +516 -0
  149. package/dist/gaia-ops/speckit/scripts/.gitkeep +0 -0
  150. package/dist/gaia-ops/speckit/templates/adr-template.md +118 -0
  151. package/dist/gaia-ops/speckit/templates/agent-file-template.md +23 -0
  152. package/dist/gaia-ops/speckit/templates/plan-template.md +227 -0
  153. package/dist/gaia-ops/speckit/templates/spec-template.md +140 -0
  154. package/dist/gaia-ops/speckit/templates/tasks-template.md +257 -0
  155. package/dist/gaia-ops/tools/context/README.md +132 -0
  156. package/dist/gaia-ops/tools/context/__init__.py +42 -0
  157. package/dist/gaia-ops/tools/context/_paths.py +20 -0
  158. package/dist/gaia-ops/tools/context/context_provider.py +476 -0
  159. package/dist/gaia-ops/tools/context/context_section_reader.py +330 -0
  160. package/dist/gaia-ops/tools/context/deep_merge.py +159 -0
  161. package/dist/gaia-ops/tools/context/pending_updates.py +760 -0
  162. package/dist/gaia-ops/tools/context/surface_router.py +278 -0
  163. package/dist/gaia-ops/tools/fast-queries/README.md +65 -0
  164. package/dist/gaia-ops/tools/fast-queries/__init__.py +30 -0
  165. package/dist/gaia-ops/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
  166. package/dist/gaia-ops/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
  167. package/dist/gaia-ops/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
  168. package/dist/gaia-ops/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
  169. package/dist/gaia-ops/tools/fast-queries/run_triage.sh +59 -0
  170. package/dist/gaia-ops/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
  171. package/dist/gaia-ops/tools/gaia_simulator/__init__.py +33 -0
  172. package/dist/gaia-ops/tools/gaia_simulator/cli.py +354 -0
  173. package/dist/gaia-ops/tools/gaia_simulator/extractor.py +457 -0
  174. package/dist/gaia-ops/tools/gaia_simulator/reporter.py +258 -0
  175. package/dist/gaia-ops/tools/gaia_simulator/routing_simulator.py +334 -0
  176. package/dist/gaia-ops/tools/gaia_simulator/runner.py +539 -0
  177. package/dist/gaia-ops/tools/gaia_simulator/skills_mapper.py +262 -0
  178. package/dist/gaia-ops/tools/memory/README.md +0 -0
  179. package/dist/gaia-ops/tools/memory/__init__.py +20 -0
  180. package/dist/gaia-ops/tools/memory/episodic.py +1196 -0
  181. package/dist/gaia-ops/tools/persist_transcript_analysis.py +85 -0
  182. package/dist/gaia-ops/tools/review/__init__.py +1 -0
  183. package/dist/gaia-ops/tools/review/review_engine.py +157 -0
  184. package/dist/gaia-ops/tools/scan/__init__.py +35 -0
  185. package/dist/gaia-ops/tools/scan/config.py +247 -0
  186. package/dist/gaia-ops/tools/scan/merge.py +212 -0
  187. package/dist/gaia-ops/tools/scan/orchestrator.py +549 -0
  188. package/dist/gaia-ops/tools/scan/registry.py +127 -0
  189. package/dist/gaia-ops/tools/scan/scanners/__init__.py +18 -0
  190. package/dist/gaia-ops/tools/scan/scanners/base.py +137 -0
  191. package/dist/gaia-ops/tools/scan/scanners/environment.py +324 -0
  192. package/dist/gaia-ops/tools/scan/scanners/git.py +570 -0
  193. package/dist/gaia-ops/tools/scan/scanners/infrastructure.py +875 -0
  194. package/dist/gaia-ops/tools/scan/scanners/orchestration.py +600 -0
  195. package/dist/gaia-ops/tools/scan/scanners/stack.py +1085 -0
  196. package/dist/gaia-ops/tools/scan/scanners/tools.py +260 -0
  197. package/dist/gaia-ops/tools/scan/setup.py +753 -0
  198. package/dist/gaia-ops/tools/scan/tests/__init__.py +1 -0
  199. package/dist/gaia-ops/tools/scan/tests/conftest.py +796 -0
  200. package/dist/gaia-ops/tools/scan/tests/test_environment.py +323 -0
  201. package/dist/gaia-ops/tools/scan/tests/test_git.py +419 -0
  202. package/dist/gaia-ops/tools/scan/tests/test_infrastructure.py +382 -0
  203. package/dist/gaia-ops/tools/scan/tests/test_integration.py +920 -0
  204. package/dist/gaia-ops/tools/scan/tests/test_merge.py +269 -0
  205. package/dist/gaia-ops/tools/scan/tests/test_orchestration.py +304 -0
  206. package/dist/gaia-ops/tools/scan/tests/test_stack.py +604 -0
  207. package/dist/gaia-ops/tools/scan/tests/test_tools.py +349 -0
  208. package/dist/gaia-ops/tools/scan/ui.py +624 -0
  209. package/dist/gaia-ops/tools/scan/verify.py +266 -0
  210. package/dist/gaia-ops/tools/scan/walk.py +118 -0
  211. package/dist/gaia-ops/tools/scan/workspace.py +85 -0
  212. package/dist/gaia-ops/tools/validation/README.md +244 -0
  213. package/dist/gaia-ops/tools/validation/__init__.py +17 -0
  214. package/dist/gaia-ops/tools/validation/approval_gate.py +321 -0
  215. package/dist/gaia-ops/tools/validation/validate_skills.py +189 -0
  216. package/dist/gaia-security/.claude-plugin/plugin.json +22 -0
  217. package/dist/gaia-security/config/universal-rules.json +10 -0
  218. package/dist/gaia-security/hooks/adapters/__init__.py +52 -0
  219. package/dist/gaia-security/hooks/adapters/base.py +219 -0
  220. package/dist/gaia-security/hooks/adapters/channel.py +17 -0
  221. package/dist/gaia-security/hooks/adapters/claude_code.py +1477 -0
  222. package/dist/gaia-security/hooks/adapters/types.py +194 -0
  223. package/dist/gaia-security/hooks/adapters/utils.py +25 -0
  224. package/dist/gaia-security/hooks/hooks.json +57 -0
  225. package/dist/gaia-security/hooks/modules/__init__.py +15 -0
  226. package/dist/gaia-security/hooks/modules/agents/__init__.py +29 -0
  227. package/dist/gaia-security/hooks/modules/agents/contract_validator.py +647 -0
  228. package/dist/gaia-security/hooks/modules/agents/response_contract.py +496 -0
  229. package/dist/gaia-security/hooks/modules/agents/skill_injection_verifier.py +124 -0
  230. package/dist/gaia-security/hooks/modules/agents/task_info_builder.py +74 -0
  231. package/dist/gaia-security/hooks/modules/agents/transcript_analyzer.py +458 -0
  232. package/dist/gaia-security/hooks/modules/agents/transcript_reader.py +152 -0
  233. package/dist/gaia-security/hooks/modules/audit/__init__.py +28 -0
  234. package/dist/gaia-security/hooks/modules/audit/event_detector.py +168 -0
  235. package/dist/gaia-security/hooks/modules/audit/logger.py +131 -0
  236. package/dist/gaia-security/hooks/modules/audit/metrics.py +134 -0
  237. package/dist/gaia-security/hooks/modules/audit/workflow_auditor.py +576 -0
  238. package/dist/gaia-security/hooks/modules/audit/workflow_recorder.py +296 -0
  239. package/dist/gaia-security/hooks/modules/context/__init__.py +11 -0
  240. package/dist/gaia-security/hooks/modules/context/anchor_tracker.py +317 -0
  241. package/dist/gaia-security/hooks/modules/context/compact_context_builder.py +215 -0
  242. package/dist/gaia-security/hooks/modules/context/context_cache.py +129 -0
  243. package/dist/gaia-security/hooks/modules/context/context_freshness.py +145 -0
  244. package/dist/gaia-security/hooks/modules/context/context_injector.py +427 -0
  245. package/dist/gaia-security/hooks/modules/context/context_writer.py +518 -0
  246. package/dist/gaia-security/hooks/modules/context/contracts_loader.py +161 -0
  247. package/dist/gaia-security/hooks/modules/core/__init__.py +40 -0
  248. package/dist/gaia-security/hooks/modules/core/hook_entry.py +78 -0
  249. package/dist/gaia-security/hooks/modules/core/paths.py +160 -0
  250. package/dist/gaia-security/hooks/modules/core/plugin_mode.py +149 -0
  251. package/dist/gaia-security/hooks/modules/core/plugin_setup.py +558 -0
  252. package/dist/gaia-security/hooks/modules/core/state.py +179 -0
  253. package/dist/gaia-security/hooks/modules/core/stdin.py +24 -0
  254. package/dist/gaia-security/hooks/modules/events/__init__.py +1 -0
  255. package/dist/gaia-security/hooks/modules/events/event_writer.py +210 -0
  256. package/dist/gaia-security/hooks/modules/identity/__init__.py +0 -0
  257. package/dist/gaia-security/hooks/modules/identity/identity_provider.py +21 -0
  258. package/dist/gaia-security/hooks/modules/identity/ops_identity.py +34 -0
  259. package/dist/gaia-security/hooks/modules/identity/security_identity.py +10 -0
  260. package/dist/gaia-security/hooks/modules/memory/__init__.py +8 -0
  261. package/dist/gaia-security/hooks/modules/memory/episode_writer.py +227 -0
  262. package/dist/gaia-security/hooks/modules/orchestrator/__init__.py +1 -0
  263. package/dist/gaia-security/hooks/modules/orchestrator/delegate_mode.py +128 -0
  264. package/dist/gaia-security/hooks/modules/scanning/__init__.py +8 -0
  265. package/dist/gaia-security/hooks/modules/scanning/scan_trigger.py +84 -0
  266. package/dist/gaia-security/hooks/modules/security/__init__.py +89 -0
  267. package/dist/gaia-security/hooks/modules/security/approval_cleanup.py +87 -0
  268. package/dist/gaia-security/hooks/modules/security/approval_constants.py +23 -0
  269. package/dist/gaia-security/hooks/modules/security/approval_grants.py +912 -0
  270. package/dist/gaia-security/hooks/modules/security/approval_messages.py +71 -0
  271. package/dist/gaia-security/hooks/modules/security/approval_scopes.py +153 -0
  272. package/dist/gaia-security/hooks/modules/security/blocked_commands.py +584 -0
  273. package/dist/gaia-security/hooks/modules/security/blocked_message_formatter.py +86 -0
  274. package/dist/gaia-security/hooks/modules/security/command_semantics.py +130 -0
  275. package/dist/gaia-security/hooks/modules/security/gitops_validator.py +179 -0
  276. package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +850 -0
  277. package/dist/gaia-security/hooks/modules/security/prompt_validator.py +40 -0
  278. package/dist/gaia-security/hooks/modules/security/tiers.py +196 -0
  279. package/dist/gaia-security/hooks/modules/session/__init__.py +10 -0
  280. package/dist/gaia-security/hooks/modules/session/session_context_writer.py +100 -0
  281. package/dist/gaia-security/hooks/modules/session/session_event_injector.py +158 -0
  282. package/dist/gaia-security/hooks/modules/session/session_manager.py +31 -0
  283. package/dist/gaia-security/hooks/modules/tools/__init__.py +25 -0
  284. package/dist/gaia-security/hooks/modules/tools/bash_validator.py +708 -0
  285. package/dist/gaia-security/hooks/modules/tools/cloud_pipe_validator.py +181 -0
  286. package/dist/gaia-security/hooks/modules/tools/hook_response.py +55 -0
  287. package/dist/gaia-security/hooks/modules/tools/shell_parser.py +227 -0
  288. package/dist/gaia-security/hooks/modules/tools/task_validator.py +283 -0
  289. package/dist/gaia-security/hooks/modules/validation/__init__.py +23 -0
  290. package/dist/gaia-security/hooks/modules/validation/commit_validator.py +380 -0
  291. package/dist/gaia-security/hooks/post_tool_use.py +54 -0
  292. package/dist/gaia-security/hooks/pre_tool_use.py +383 -0
  293. package/dist/gaia-security/hooks/session_start.py +69 -0
  294. package/dist/gaia-security/hooks/stop_hook.py +69 -0
  295. package/dist/gaia-security/hooks/user_prompt_submit.py +177 -0
  296. package/dist/gaia-security/settings.json +58 -0
  297. package/git-hooks/commit-msg +41 -0
  298. package/hooks/README.md +8 -6
  299. package/hooks/adapters/channel.py +0 -25
  300. package/hooks/adapters/claude_code.py +364 -125
  301. package/hooks/elicitation_result.py +132 -0
  302. package/hooks/hooks.json +10 -1
  303. package/hooks/modules/README.md +3 -2
  304. package/hooks/modules/agents/contract_validator.py +3 -51
  305. package/hooks/modules/agents/response_contract.py +4 -8
  306. package/hooks/modules/agents/transcript_reader.py +4 -5
  307. package/hooks/modules/audit/__init__.py +4 -6
  308. package/hooks/modules/audit/event_detector.py +0 -2
  309. package/hooks/modules/audit/metrics.py +108 -187
  310. package/hooks/modules/audit/workflow_auditor.py +0 -4
  311. package/hooks/modules/audit/workflow_recorder.py +0 -5
  312. package/hooks/modules/context/compact_context_builder.py +1 -0
  313. package/hooks/modules/context/context_cache.py +129 -0
  314. package/hooks/modules/context/context_injector.py +18 -40
  315. package/hooks/modules/context/context_writer.py +1 -25
  316. package/hooks/modules/context/contracts_loader.py +7 -10
  317. package/hooks/modules/core/hook_entry.py +1 -0
  318. package/hooks/modules/core/paths.py +12 -13
  319. package/hooks/modules/core/plugin_mode.py +74 -4
  320. package/hooks/modules/core/plugin_setup.py +395 -23
  321. package/hooks/modules/events/__init__.py +1 -0
  322. package/hooks/modules/events/event_writer.py +210 -0
  323. package/hooks/modules/identity/ops_identity.py +18 -27
  324. package/hooks/modules/memory/episode_writer.py +1 -6
  325. package/hooks/modules/orchestrator/__init__.py +1 -0
  326. package/hooks/modules/orchestrator/delegate_mode.py +128 -0
  327. package/hooks/modules/security/__init__.py +2 -4
  328. package/hooks/modules/security/approval_constants.py +5 -1
  329. package/hooks/modules/security/approval_grants.py +189 -6
  330. package/hooks/modules/security/approval_messages.py +9 -21
  331. package/hooks/modules/security/blocked_commands.py +98 -34
  332. package/hooks/modules/security/command_semantics.py +0 -4
  333. package/hooks/modules/security/gitops_validator.py +1 -11
  334. package/hooks/modules/security/mutative_verbs.py +179 -38
  335. package/hooks/modules/security/tiers.py +1 -19
  336. package/hooks/modules/session/session_event_injector.py +1 -25
  337. package/hooks/modules/tools/bash_validator.py +310 -94
  338. package/hooks/modules/tools/shell_parser.py +0 -1
  339. package/hooks/modules/tools/task_validator.py +9 -29
  340. package/hooks/post_tool_use.py +0 -72
  341. package/hooks/pre_tool_use.py +42 -102
  342. package/hooks/session_start.py +4 -2
  343. package/hooks/subagent_start.py +6 -2
  344. package/hooks/subagent_stop.py +1 -13
  345. package/hooks/user_prompt_submit.py +119 -37
  346. package/index.js +1 -1
  347. package/package.json +5 -3
  348. package/skills/README.md +3 -5
  349. package/skills/agent-protocol/SKILL.md +17 -16
  350. package/skills/agent-protocol/examples.md +6 -6
  351. package/skills/agent-response/SKILL.md +11 -14
  352. package/skills/approval/SKILL.md +28 -13
  353. package/skills/approval/reference.md +2 -2
  354. package/skills/execution/SKILL.md +1 -1
  355. package/skills/gaia-patterns/SKILL.md +2 -3
  356. package/skills/orchestrator-approval/SKILL.md +22 -50
  357. package/skills/security-tiers/SKILL.md +1 -1
  358. package/templates/README.md +9 -9
  359. package/templates/managed-settings.template.json +43 -0
  360. package/tools/gaia_simulator/runner.py +34 -1
  361. package/tools/scan/orchestrator.py +13 -0
  362. package/tools/scan/scanners/base.py +8 -0
  363. package/tools/scan/scanners/git.py +78 -0
  364. package/tools/scan/scanners/infrastructure.py +65 -0
  365. package/tools/scan/scanners/stack.py +110 -0
  366. package/tools/scan/setup.py +120 -13
  367. package/tools/scan/workspace.py +85 -0
  368. package/config/context-contracts.aws.json +0 -42
  369. package/config/context-contracts.gcp.json +0 -39
  370. package/skills/project-dispatch/SKILL.md +0 -34
  371. package/templates/settings.template.json +0 -226
@@ -0,0 +1,40 @@
1
+ """
2
+ Core module - Shared utilities for all hook modules.
3
+
4
+ Provides:
5
+ - paths: Unified path resolution (find_claude_dir)
6
+ - plugin_mode: Plugin mode detection (security vs ops)
7
+ - state: Pre/post hook state sharing
8
+ - stdin: Stdin availability check (has_stdin_data)
9
+ """
10
+
11
+ from .paths import find_claude_dir, get_plugin_data_dir, get_logs_dir, get_metrics_dir, get_memory_dir
12
+ from .plugin_mode import get_plugin_mode, is_ops_mode, is_security_mode, has_plugin, clear_mode_cache
13
+ from .state import HookState, get_hook_state, save_hook_state, clear_hook_state, get_session_id
14
+ from .stdin import has_stdin_data
15
+ from .hook_entry import run_hook
16
+
17
+ __all__ = [
18
+ # Paths
19
+ "find_claude_dir",
20
+ "get_plugin_data_dir",
21
+ "get_logs_dir",
22
+ "get_metrics_dir",
23
+ "get_memory_dir",
24
+ # Plugin mode
25
+ "get_plugin_mode",
26
+ "is_ops_mode",
27
+ "is_security_mode",
28
+ "has_plugin",
29
+ "clear_mode_cache",
30
+ # State
31
+ "HookState",
32
+ "get_hook_state",
33
+ "save_hook_state",
34
+ "clear_hook_state",
35
+ "get_session_id",
36
+ # Stdin
37
+ "has_stdin_data",
38
+ # Hook entry
39
+ "run_hook",
40
+ ]
@@ -0,0 +1,78 @@
1
+ """
2
+ Common hook entrypoint boilerplate.
3
+
4
+ Provides ``run_hook()`` which encapsulates the repeated pattern found in
5
+ every hook entrypoint:
6
+
7
+ 1. Check ``has_stdin_data()``
8
+ 2. Read stdin
9
+ 3. Parse via the adapter
10
+ 4. Call a caller-provided handler with the parsed ``HookEvent``
11
+ 5. Catch and log exceptions, exiting appropriately
12
+
13
+ Usage in a hook entrypoint::
14
+
15
+ from modules.core.hook_entry import run_hook
16
+
17
+ def _handle(event: HookEvent) -> None:
18
+ ... # business logic, call sys.exit() / print as needed
19
+
20
+ if __name__ == "__main__":
21
+ run_hook(_handle, hook_name="stop_hook")
22
+ """
23
+ from __future__ import annotations
24
+
25
+ import json
26
+ import logging
27
+ import sys
28
+ from typing import Callable
29
+
30
+ from .stdin import has_stdin_data
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ def run_hook(
36
+ handler: Callable,
37
+ *,
38
+ hook_name: str = "hook",
39
+ usage_message: str | None = None,
40
+ ) -> None:
41
+ """Read stdin, parse via ClaudeCodeAdapter, and delegate to *handler*.
42
+
43
+ Args:
44
+ handler: Callable that receives an ``adapters.types.HookEvent``.
45
+ The handler is responsible for printing output and calling
46
+ ``sys.exit()`` with the appropriate code.
47
+ hook_name: Human-readable name used in log messages and the default
48
+ usage string.
49
+ usage_message: Custom usage text shown when stdin is absent. If
50
+ *None*, a sensible default is generated from *hook_name*.
51
+ """
52
+ if not has_stdin_data():
53
+ msg = usage_message or (
54
+ f"Usage: echo '{{...}}' | python {hook_name}.py (stdin mode)"
55
+ )
56
+ print(msg)
57
+ sys.exit(1)
58
+
59
+ try:
60
+ # Deferred adapter import avoids circular dependencies at module level;
61
+ # the adapter package is a sibling of modules/.
62
+ from adapters.claude_code import ClaudeCodeAdapter
63
+
64
+ adapter = ClaudeCodeAdapter()
65
+ stdin_data = sys.stdin.read()
66
+ event = adapter.parse_event(stdin_data)
67
+ handler(event)
68
+ except ValueError as e:
69
+ logger.error("Adapter parse failed in %s: %s", hook_name, e)
70
+ sys.exit(1)
71
+ except json.JSONDecodeError as e:
72
+ logger.error("Invalid JSON from stdin in %s: %s", hook_name, e)
73
+ sys.exit(1)
74
+ except SystemExit:
75
+ raise # Let explicit sys.exit() calls propagate
76
+ except Exception as e:
77
+ logger.error("Error processing %s hook: %s", hook_name, e)
78
+ sys.exit(1)
@@ -0,0 +1,160 @@
1
+ """
2
+ Unified path resolution for gaia-ops hooks.
3
+
4
+ Single source of truth for finding .claude directory and its subdirectories.
5
+
6
+ Path resolution follows two base directories:
7
+ - PLUGIN_ROOT (.claude/): Code, config, agents, skills, context providers
8
+ - PLUGIN_DATA (CLAUDE_PLUGIN_DATA or .claude/ fallback): Logs, sessions,
9
+ approval grants, workflow episodic memory — data that survives plugin updates
10
+ """
11
+
12
+ import os
13
+ import logging
14
+ from pathlib import Path
15
+ from functools import lru_cache
16
+ from typing import Optional
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ @lru_cache(maxsize=1)
22
+ def find_claude_dir() -> Path:
23
+ """
24
+ Find the .claude directory by searching upward from current location.
25
+
26
+ Search order:
27
+ 1. If currently in .claude, return it
28
+ 2. Check current directory for .claude/
29
+ 3. Search parent directories upward
30
+ 4. Fall back to current/.claude (without creating it)
31
+
32
+ Returns:
33
+ Path to the .claude directory
34
+
35
+ Note:
36
+ Result is cached for performance. Clear with find_claude_dir.cache_clear()
37
+ """
38
+ current = Path.cwd()
39
+
40
+ # If we're already in a .claude directory, return it
41
+ if current.name == ".claude":
42
+ return current
43
+
44
+ # Look for .claude in current directory
45
+ claude_dir = current / ".claude"
46
+ if claude_dir.exists():
47
+ return claude_dir
48
+
49
+ # Search upward through parent directories
50
+ for parent in current.parents:
51
+ claude_dir = parent / ".claude"
52
+ if claude_dir.exists():
53
+ return claude_dir
54
+
55
+ # Fallback - use current directory's .claude (but don't create it yet)
56
+ logger.warning(f"No .claude directory found, using {current}/.claude")
57
+ return current / ".claude"
58
+
59
+
60
+ @lru_cache(maxsize=1)
61
+ def get_plugin_data_dir() -> Path:
62
+ """
63
+ Get the base directory for persistent plugin data.
64
+
65
+ Resolution order:
66
+ 1. CLAUDE_PLUGIN_DATA env var (set by Claude Code >= 2.1.78)
67
+ 2. Fallback to find_claude_dir() for backward compatibility
68
+
69
+ Data stored here survives plugin updates. Code and config remain
70
+ under PLUGIN_ROOT (find_claude_dir()).
71
+
72
+ Returns:
73
+ Path to the plugin data directory (created if needed)
74
+
75
+ Note:
76
+ Result is cached for performance. Clear with clear_path_cache()
77
+ """
78
+ plugin_data = os.environ.get("CLAUDE_PLUGIN_DATA")
79
+ if plugin_data:
80
+ data_dir = Path(plugin_data)
81
+ data_dir.mkdir(parents=True, exist_ok=True)
82
+ return data_dir
83
+ # Fallback: data co-located with code in .claude/
84
+ return find_claude_dir()
85
+
86
+
87
+ def get_logs_dir() -> Path:
88
+ """
89
+ Get the logs directory, creating it if necessary.
90
+
91
+ Returns:
92
+ Path to .claude/logs/
93
+ """
94
+ logs_dir = get_plugin_data_dir() / "logs"
95
+ logs_dir.mkdir(parents=True, exist_ok=True)
96
+ return logs_dir
97
+
98
+
99
+ def get_metrics_dir() -> Path:
100
+ """
101
+ Get the metrics directory, creating it if necessary.
102
+
103
+ Returns:
104
+ Path to .claude/metrics/
105
+ """
106
+ metrics_dir = get_plugin_data_dir() / "metrics"
107
+ metrics_dir.mkdir(parents=True, exist_ok=True)
108
+ return metrics_dir
109
+
110
+
111
+ def get_memory_dir(subdir: Optional[str] = None) -> Path:
112
+ """
113
+ Get the memory directory, creating it if necessary.
114
+
115
+ Args:
116
+ subdir: Optional subdirectory (e.g., "workflow-episodic")
117
+
118
+ Returns:
119
+ Path to .claude/memory/ or .claude/memory/{subdir}/
120
+ """
121
+ memory_dir = get_plugin_data_dir() / "memory"
122
+ if subdir:
123
+ memory_dir = memory_dir / subdir
124
+ memory_dir.mkdir(parents=True, exist_ok=True)
125
+ return memory_dir
126
+
127
+
128
+ def get_events_dir() -> Path:
129
+ """
130
+ Get the events directory, creating it if necessary.
131
+
132
+ Returns:
133
+ Path to .claude/events/
134
+ """
135
+ events_dir = get_plugin_data_dir() / "events"
136
+ events_dir.mkdir(parents=True, exist_ok=True)
137
+ return events_dir
138
+
139
+
140
+ def get_session_dir() -> Path:
141
+ """
142
+ Get the active session directory, creating it if necessary.
143
+
144
+ Returns:
145
+ Path to .claude/session/active/
146
+ """
147
+ session_dir = get_plugin_data_dir() / "session" / "active"
148
+ session_dir.mkdir(parents=True, exist_ok=True)
149
+ return session_dir
150
+
151
+
152
+ def clear_path_cache():
153
+ """Clear all cached path results (useful for testing)."""
154
+ find_claude_dir.cache_clear()
155
+ get_plugin_data_dir.cache_clear()
156
+ try:
157
+ from .plugin_mode import clear_mode_cache
158
+ clear_mode_cache()
159
+ except ImportError:
160
+ pass
@@ -0,0 +1,149 @@
1
+ """Plugin mode detection for gaia hooks.
2
+
3
+ Determines whether the installation is security-only or ops (full orchestrator).
4
+ Security mode: T3 operations use native Claude Code approval dialog (permissionDecision: ask).
5
+ Ops mode: T3 operations block with nonce for orchestrator agent approval flow.
6
+
7
+ Detection order:
8
+ 1. plugin-registry.json in plugin data directory
9
+ 2. NPM package name detection (gaia-ops vs gaia-security)
10
+ 3. GAIA_PLUGIN_MODE env var fallback
11
+ 4. Default: "security" (most restrictive)
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ import logging
17
+ import os
18
+ from functools import lru_cache
19
+ from pathlib import Path
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ VALID_MODES = ("security", "ops")
24
+ DEFAULT_MODE = "security"
25
+
26
+ # Map NPM package names to plugin modes
27
+ _NPM_PACKAGE_MODE = {
28
+ "gaia-ops": "ops",
29
+ "gaia-security": "security",
30
+ }
31
+
32
+
33
+ def _detect_mode_from_npm_package() -> str | None:
34
+ """Detect plugin mode from the NPM package name.
35
+
36
+ When installed via npm, this module lives at a path like:
37
+ .../node_modules/@jaguilar87/gaia-ops/hooks/modules/core/plugin_mode.py
38
+
39
+ The package directory name (gaia-ops or gaia-security) determines the mode.
40
+ Also checks .claude/ symlinks as a secondary signal for npm installs.
41
+
42
+ Returns the mode string or None if not detectable.
43
+ """
44
+ # Primary: check our own file path for node_modules package name
45
+ module_path = Path(__file__).resolve()
46
+ parts = module_path.parts
47
+ for i, part in enumerate(parts):
48
+ if part == "node_modules" and i + 2 < len(parts):
49
+ # Could be @scope/package-name or just package-name
50
+ pkg_name = parts[i + 1]
51
+ if pkg_name.startswith("@") and i + 2 < len(parts):
52
+ pkg_name = parts[i + 2]
53
+ mode = _NPM_PACKAGE_MODE.get(pkg_name)
54
+ if mode:
55
+ logger.debug("Detected mode '%s' from npm package path: %s", mode, pkg_name)
56
+ return mode
57
+
58
+ # Secondary: check if .claude/agents symlink points to a gaia package
59
+ try:
60
+ from .paths import find_claude_dir
61
+ claude_dir = find_claude_dir()
62
+ agents_link = claude_dir / "agents"
63
+ if agents_link.is_symlink():
64
+ target = str(agents_link.resolve())
65
+ for pkg_name, mode in _NPM_PACKAGE_MODE.items():
66
+ if pkg_name in target:
67
+ logger.debug("Detected mode '%s' from .claude/agents symlink target", mode)
68
+ return mode
69
+ except Exception:
70
+ pass
71
+
72
+ return None
73
+
74
+
75
+ @lru_cache(maxsize=1)
76
+ def get_plugin_mode() -> str:
77
+ """Get the current plugin mode.
78
+
79
+ Returns "security" or "ops".
80
+ """
81
+ # 1. Check plugin registry
82
+ try:
83
+ from .paths import get_plugin_data_dir
84
+ registry_path = get_plugin_data_dir() / "plugin-registry.json"
85
+ if registry_path.exists():
86
+ registry = json.loads(registry_path.read_text())
87
+ installed = [p.get("name", "") for p in registry.get("installed", [])]
88
+ if "gaia-ops" in installed:
89
+ return "ops"
90
+ if "gaia-security" in installed:
91
+ return "security"
92
+ except Exception as e:
93
+ logger.debug("Registry check failed (non-fatal): %s", e)
94
+
95
+ # 2. CLAUDE_PLUGIN_ROOT + plugin.json (--plugin-dir mode)
96
+ plugin_root = os.environ.get("CLAUDE_PLUGIN_ROOT", "")
97
+ if plugin_root:
98
+ try:
99
+ pjson = Path(plugin_root) / ".claude-plugin" / "plugin.json"
100
+ if pjson.exists():
101
+ pdata = json.loads(pjson.read_text())
102
+ pname = pdata.get("name", "")
103
+ mode = _NPM_PACKAGE_MODE.get(pname)
104
+ if mode:
105
+ logger.debug("Detected mode '%s' from plugin.json name: %s", mode, pname)
106
+ return mode
107
+ except Exception as e:
108
+ logger.debug("Plugin.json check failed (non-fatal): %s", e)
109
+
110
+ # 3. NPM package name detection
111
+ npm_mode = _detect_mode_from_npm_package()
112
+ if npm_mode:
113
+ return npm_mode
114
+
115
+ # 4. Env var fallback
116
+ mode = os.environ.get("GAIA_PLUGIN_MODE", "").lower()
117
+ if mode in VALID_MODES:
118
+ return mode
119
+
120
+ # 5. Default: security (most restrictive)
121
+ return DEFAULT_MODE
122
+
123
+
124
+ def has_plugin(name: str) -> bool:
125
+ """Check if a specific plugin is installed."""
126
+ try:
127
+ from .paths import get_plugin_data_dir
128
+ registry_path = get_plugin_data_dir() / "plugin-registry.json"
129
+ if registry_path.exists():
130
+ registry = json.loads(registry_path.read_text())
131
+ return any(p.get("name") == name for p in registry.get("installed", []))
132
+ except Exception:
133
+ pass
134
+ return False
135
+
136
+
137
+ def is_ops_mode() -> bool:
138
+ """Convenience: check if running in ops mode."""
139
+ return get_plugin_mode() == "ops"
140
+
141
+
142
+ def is_security_mode() -> bool:
143
+ """Convenience: check if running in security-only mode."""
144
+ return get_plugin_mode() == "security"
145
+
146
+
147
+ def clear_mode_cache():
148
+ """Clear cached mode (for testing)."""
149
+ get_plugin_mode.cache_clear()