@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,177 @@
1
+ #!/usr/bin/env python3
2
+ """UserPromptSubmit hook — injects dynamic identity based on installed plugins."""
3
+
4
+ import sys
5
+ import json
6
+ import logging
7
+ from datetime import datetime
8
+ from pathlib import Path
9
+
10
+ sys.path.insert(0, str(Path(__file__).parent))
11
+
12
+ from modules.core.paths import get_logs_dir
13
+ from modules.core.stdin import has_stdin_data
14
+ from modules.core.plugin_setup import run_first_time_setup
15
+ from modules.identity.identity_provider import build_identity
16
+
17
+ # Configure logging — file only, no stderr
18
+ _log_file = get_logs_dir() / f"hooks-{datetime.now().strftime('%Y-%m-%d')}.log"
19
+ logging.basicConfig(
20
+ level=logging.INFO,
21
+ format='%(asctime)s [user_prompt_submit] %(name)s - %(levelname)s - %(message)s',
22
+ handlers=[logging.FileHandler(_log_file)],
23
+ )
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ def _extract_user_prompt(raw_input: str) -> str:
28
+ """Extract user prompt text from stdin event.
29
+
30
+ The UserPromptSubmit event is JSON with the user's message.
31
+ Try known field names; return empty string if extraction fails.
32
+ """
33
+ try:
34
+ event = json.loads(raw_input)
35
+ # Try known field names from Claude Code hook events
36
+ for field in ("user_message", "prompt", "message", "content"):
37
+ if field in event and isinstance(event[field], str):
38
+ return event[field]
39
+ # Check nested hookEventInput
40
+ hook_input = event.get("hookEventInput", {})
41
+ if isinstance(hook_input, dict):
42
+ for field in ("user_message", "prompt", "message", "content"):
43
+ if field in hook_input and isinstance(hook_input[field], str):
44
+ return hook_input[field]
45
+ except (json.JSONDecodeError, TypeError, AttributeError):
46
+ pass
47
+ return ""
48
+
49
+
50
+ def _build_routing_recommendation(prompt_text: str) -> str:
51
+ """Run surface classification and format as a routing recommendation block.
52
+
53
+ Returns empty string if classification fails or produces no active surfaces.
54
+ This is advisory — never raises exceptions.
55
+ """
56
+ try:
57
+ # Import surface_router from tools/context
58
+ tools_dir = Path(__file__).resolve().parent.parent / "tools" / "context"
59
+ if str(tools_dir) not in sys.path:
60
+ sys.path.insert(0, str(tools_dir))
61
+
62
+ from surface_router import classify_surfaces
63
+
64
+ routing = classify_surfaces(prompt_text)
65
+
66
+ active_surfaces = routing.get("active_surfaces", [])
67
+ if not active_surfaces:
68
+ logger.info("Surface routing: no active surfaces for prompt")
69
+ return ""
70
+
71
+ agents = routing.get("recommended_agents", [])
72
+ dispatch_mode = routing.get("dispatch_mode", "single_surface")
73
+ confidence = routing.get("confidence", 0.0)
74
+ matched_signals = routing.get("matched_signals", {})
75
+
76
+ # Flatten matched signals into a single list for display
77
+ all_signals = []
78
+ for surface_signals in matched_signals.values():
79
+ all_signals.extend(surface_signals)
80
+
81
+ lines = [
82
+ "\n\n## Surface Routing Recommendation",
83
+ f"- Recommended agents: {agents}",
84
+ f"- Dispatch mode: {dispatch_mode}",
85
+ f"- Confidence: {confidence}",
86
+ f"- Matched signals: {json.dumps(all_signals)}",
87
+ ]
88
+
89
+ logger.info(
90
+ "Surface routing: agents=%s mode=%s confidence=%.2f signals=%s",
91
+ agents, dispatch_mode, confidence, all_signals,
92
+ )
93
+ return "\n".join(lines)
94
+
95
+ except Exception as e:
96
+ logger.warning("Surface routing failed (advisory, skipping): %s", e)
97
+ return ""
98
+
99
+
100
+ def _build_welcome(mode: str) -> str:
101
+ """Build first-run welcome message for the user.
102
+
103
+ This message is injected as additionalContext so Claude receives it,
104
+ not the user directly. The framing explains WHY the user needs to
105
+ know — Claude should naturally relay it because it is actionable
106
+ and the user cannot use the plugin fully without restarting.
107
+ """
108
+ plugin_name = f"GAIA {'Ops' if mode == 'ops' else 'Security'}"
109
+
110
+ return (
111
+ f"{plugin_name} was just installed for the first time in this project. "
112
+ f"The plugin detected the installation and configured security permissions, "
113
+ f"but these permissions only take effect after restarting Claude Code. "
114
+ f"Until the user closes this session and reopens Claude Code, "
115
+ f"{plugin_name} cannot protect their commands — destructive operations "
116
+ f"will not be blocked and mutative operations will not require approval. "
117
+ f"The user needs to know this because they just installed {plugin_name} "
118
+ f"expecting it to work, but it will not be active until they restart. "
119
+ f"Tell the user that {plugin_name} is installed, that they need to close "
120
+ f"and reopen Claude Code to activate it, and that until they do, "
121
+ f"security protections are not active."
122
+ )
123
+
124
+
125
+ if __name__ == "__main__":
126
+ if not has_stdin_data():
127
+ sys.exit(0)
128
+
129
+ try:
130
+ raw_input = sys.stdin.read()
131
+
132
+ # Check first-run BEFORE setup (SessionStart does setup with
133
+ # mark_done=False so the marker doesn't exist yet on first run).
134
+ from modules.core.plugin_setup import is_first_run, mark_initialized
135
+ first_run = is_first_run()
136
+
137
+ # Ensure registry + permissions exist (idempotent, no mark).
138
+ setup_msg = run_first_time_setup(mark_done=False)
139
+ identity = build_identity()
140
+ mode = "ops" if "Orchestrator" in identity else "security"
141
+
142
+ # First-time welcome: the marker does not exist yet because
143
+ # neither SessionStart nor this call marked it.
144
+ if first_run:
145
+ welcome = _build_welcome(mode)
146
+ identity = f"{welcome}\n\n{identity}"
147
+ mark_initialized() # Mark AFTER building the welcome
148
+ logger.info("First-run welcome prepended for %s mode", mode)
149
+
150
+ # Append deterministic surface routing recommendation (ops mode only)
151
+ if mode == "ops":
152
+ prompt_text = _extract_user_prompt(raw_input)
153
+
154
+ # NOTE: Approval activation moved to ElicitationResult hook.
155
+ # AskUserQuestion responses trigger ElicitationResult, not
156
+ # UserPromptSubmit, so approval detection lives there now.
157
+
158
+ if prompt_text:
159
+ routing_block = _build_routing_recommendation(prompt_text)
160
+ if routing_block:
161
+ identity = identity + routing_block
162
+ else:
163
+ logger.info("Could not extract user prompt from stdin, skipping routing")
164
+
165
+ logger.info("Identity injected: %s mode (%d chars)", mode, len(identity))
166
+
167
+ print(json.dumps({
168
+ "hookSpecificOutput": {
169
+ "hookEventName": "UserPromptSubmit",
170
+ "additionalContext": identity,
171
+ }
172
+ }))
173
+ sys.exit(0)
174
+
175
+ except Exception as e:
176
+ logger.error("Error in user_prompt_submit: %s", e, exc_info=True)
177
+ sys.exit(0)
@@ -0,0 +1,58 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(*)",
5
+ "Read",
6
+ "Glob",
7
+ "Grep",
8
+ "BashOutput",
9
+ "KillShell"
10
+ ],
11
+ "deny": [
12
+ "Bash(aws ec2 delete-vpc:*)",
13
+ "Bash(aws ec2 delete-subnet:*)",
14
+ "Bash(aws ec2 delete-internet-gateway:*)",
15
+ "Bash(aws ec2 delete-route-table:*)",
16
+ "Bash(aws ec2 delete-route:*)",
17
+ "Bash(aws rds delete-db-instance:*)",
18
+ "Bash(aws rds delete-db-cluster:*)",
19
+ "Bash(aws dynamodb delete-table:*)",
20
+ "Bash(aws s3 rb:*)",
21
+ "Bash(aws s3api delete-bucket:*)",
22
+ "Bash(aws elasticache delete-cache-cluster:*)",
23
+ "Bash(aws elasticache delete-replication-group:*)",
24
+ "Bash(aws eks delete-cluster:*)",
25
+ "Bash(gcloud projects delete:*)",
26
+ "Bash(gcloud container clusters delete:*)",
27
+ "Bash(gcloud sql instances delete:*)",
28
+ "Bash(gcloud sql databases delete:*)",
29
+ "Bash(gcloud services disable:*)",
30
+ "Bash(gsutil rb:*)",
31
+ "Bash(gsutil rm -r:*)",
32
+ "Bash(kubectl delete namespace:*)",
33
+ "Bash(kubectl delete node:*)",
34
+ "Bash(kubectl delete cluster:*)",
35
+ "Bash(kubectl delete pv:*)",
36
+ "Bash(kubectl delete persistentvolume:*)",
37
+ "Bash(kubectl delete pvc:*)",
38
+ "Bash(kubectl delete persistentvolumeclaim:*)",
39
+ "Bash(kubectl delete crd:*)",
40
+ "Bash(kubectl delete customresourcedefinition:*)",
41
+ "Bash(kubectl delete mutatingwebhookconfiguration:*)",
42
+ "Bash(kubectl delete validatingwebhookconfiguration:*)",
43
+ "Bash(kubectl drain:*)",
44
+ "Bash(git push --force:*)",
45
+ "Bash(git push -f:*)",
46
+ "Bash(git push origin --force:*)",
47
+ "Bash(git push origin -f:*)",
48
+ "Bash(dd:*)",
49
+ "Bash(fdisk:*)",
50
+ "Bash(mkfs:*)",
51
+ "Bash(mkfs.ext4:*)",
52
+ "Bash(mkfs.ext3:*)",
53
+ "Bash(mkfs.fat:*)",
54
+ "Bash(mkfs.ntfs:*)"
55
+ ],
56
+ "ask": []
57
+ }
58
+ }
@@ -0,0 +1,41 @@
1
+ #!/bin/sh
2
+ #
3
+ # commit-msg hook: strip Claude Code attribution footers from commit messages.
4
+ #
5
+ # This hook runs at the git level, catching ALL commits regardless of whether
6
+ # they originate from Claude Code's Bash tool, a subagent, or the user's terminal.
7
+ #
8
+ # Patterns match those in hooks/modules/tools/bash_validator.py _strip_claude_footers()
9
+ # to maintain a single source of truth for what constitutes a forbidden footer.
10
+ #
11
+ # Installation:
12
+ # cp git-hooks/commit-msg .git/hooks/commit-msg
13
+ # chmod +x .git/hooks/commit-msg
14
+ #
15
+ # Or via gaia-init (automatic).
16
+
17
+ COMMIT_MSG_FILE="$1"
18
+
19
+ if [ ! -f "${COMMIT_MSG_FILE}" ]; then
20
+ exit 0
21
+ fi
22
+
23
+ # Create a temp file for the cleaned message
24
+ TEMP_FILE=$(mktemp)
25
+ trap 'rm -f "${TEMP_FILE}"' EXIT
26
+
27
+ # Read the commit message and strip forbidden footer lines:
28
+ # - Co-Authored-By: containing "Claude" (any case)
29
+ # - "Generated with Claude Code" or "[Claude Code]" (any case)
30
+ # - Emoji-prefixed "Generated with" lines
31
+ sed -E \
32
+ -e '/^[[:space:]]*[Cc][Oo]-[Aa][Uu][Tt][Hh][Oo][Rr][Ee][Dd]-[Bb][Yy]:.*[Cc][Ll][Aa][Uu][Dd][Ee]/d' \
33
+ -e '/^[[:space:]]*[Gg][Ee][Nn][Ee][Rr][Aa][Tt][Ee][Dd] [Ww][Ii][Tt][Hh].*[Cc][Ll][Aa][Uu][Dd][Ee] [Cc][Oo][Dd][Ee]/d' \
34
+ -e '/^[[:space:]]*..?[[:space:]]*[Gg][Ee][Nn][Ee][Rr][Aa][Tt][Ee][Dd] [Ww][Ii][Tt][Hh]/d' \
35
+ "${COMMIT_MSG_FILE}" > "${TEMP_FILE}"
36
+
37
+ # Remove trailing blank lines (collapse to single trailing newline)
38
+ # This prevents empty trailers after stripping
39
+ sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' "${TEMP_FILE}" > "${COMMIT_MSG_FILE}"
40
+
41
+ exit 0
package/hooks/README.md CHANGED
@@ -9,14 +9,15 @@ User sends prompt
9
9
  |
10
10
  [user_prompt_submit.py] <- **injects orchestrator identity**
11
11
  | Builds identity via ops_identity.py
12
- | Skills loaded on-demand: project-dispatch, agent-response
12
+ | Inject surface routing recommendation (deterministic)
13
+ | Skills loaded on-demand: agent-response
13
14
  v
14
15
  Agent attempts to execute command
15
16
  |
16
17
  [pre_tool_use.py] <- intercepts BEFORE
17
18
  | Validates Bash commands (security gate)
18
19
  | Validates Task/Agent (context injection)
19
- | Validates SendMessage (agent resumption, nonce approval)
20
+ | Validates SendMessage (agent resumption)
20
21
  v
21
22
  ALLOWED / BLOCKED
22
23
  |
@@ -49,7 +50,8 @@ Command executes
49
50
  | **T0** | Read-only (get, list) | No | pre_tool_use |
50
51
  | **T1** | Local validation (validate, lint) | No | pre_tool_use |
51
52
  | **T2** | Simulation (plan, diff) | No | pre_tool_use |
52
- | **T3** | Execution (apply, delete) | **Yes** | pre_tool_use |
53
+ | **T3** | Execution (apply, delete) | **Yes** (native `ask` dialog) | pre_tool_use |
54
+ | **T3-blocked** | Irreversible (delete-vpc, drop db) | **Permanently blocked** | pre_tool_use (exit 2) |
53
55
 
54
56
  ## File Structure
55
57
 
@@ -70,6 +72,6 @@ hooks/
70
72
 
71
73
  ---
72
74
 
73
- **Version:** 4.4.0-rc.5
74
- **Last updated:** 2026-03-19
75
- **Total hooks:** 8 hook scripts (4 primary + 4 event handlers)
75
+ **Version:** 4.5.0
76
+ **Last updated:** 2026-03-24
77
+ **Total hooks:** 9 hook scripts (4 primary + 4 event handlers + post_compact)
@@ -9,31 +9,6 @@ logic to adapt behavior per channel.
9
9
  import os
10
10
  from pathlib import Path
11
11
 
12
- from .types import DistributionChannel
13
-
14
-
15
- def detect_distribution_channel() -> DistributionChannel:
16
- """Detect if running as Claude Code plugin or npm package."""
17
- # Plugin channel: CLAUDE_PLUGIN_ROOT env var is set
18
- if os.environ.get("CLAUDE_PLUGIN_ROOT"):
19
- return DistributionChannel.PLUGIN
20
- # npm channel: check if we're inside node_modules
21
- current = Path(__file__).resolve()
22
- if "node_modules" in current.parts:
23
- return DistributionChannel.NPM
24
- # Development: local source
25
- return DistributionChannel.NPM # default to npm behavior
26
-
27
-
28
- def get_plugin_root() -> str:
29
- """Get the plugin root path, works in both channels."""
30
- plugin_root = os.environ.get("CLAUDE_PLUGIN_ROOT")
31
- if plugin_root:
32
- return plugin_root
33
- # npm channel: walk up from this file to find the package root
34
- current = Path(__file__).resolve().parent.parent.parent
35
- return str(current)
36
-
37
12
 
38
13
  def is_dual_channel_active() -> bool:
39
14
  """Check if both plugin and npm installations exist simultaneously."""