@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,181 @@
1
+ """
2
+ Cloud pipe/redirect/chaining validator.
3
+
4
+ Detects pipe, redirect, and command-chaining violations in cloud/infra commands.
5
+ Cloud CLIs (gcloud, kubectl, aws, terraform, helm, flux) expose native flags
6
+ for filtering and formatting — there is never a valid reason to pipe their output.
7
+
8
+ This validator runs before tier classification so violations are caught early
9
+ and the agent receives a corrective response rather than a blocked execution.
10
+ """
11
+
12
+ import logging
13
+ import re
14
+ from dataclasses import dataclass
15
+ from typing import Optional
16
+
17
+ from .hook_response import build_hook_permission_response
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ # Cloud/infra CLIs covered by this policy
22
+ CLOUD_CLI_PATTERN = re.compile(
23
+ r'^\s*(gcloud|kubectl|aws|terraform|helm|flux)\b',
24
+ re.IGNORECASE
25
+ )
26
+
27
+ # Violation definitions: (name, regex, corrected_approach)
28
+ VIOLATIONS = [
29
+ (
30
+ "pipe",
31
+ # Match a single pipe `|` but NOT logical OR `||`.
32
+ # Negative lookbehind (?<!\|) skips the second `|` of `||`.
33
+ # Negative lookahead (?!\|) skips the first `|` of `||`.
34
+ re.compile(r'(?<!\|)\|(?!\|)'),
35
+ (
36
+ "Use native output flags instead of piping to shell utilities.\n"
37
+ " gcloud: --filter='...' --format='value(field)'\n"
38
+ " kubectl: -o jsonpath='{...}' or -o go-template='{{...}}'\n"
39
+ " aws: --query '...' --output text\n"
40
+ " terraform: use terraform output or -json flag"
41
+ ),
42
+ ),
43
+ (
44
+ "redirect",
45
+ # Match `>` or `>>` for file redirection, but NOT:
46
+ # - `>&` (file descriptor duplication, e.g. `2>&1`)
47
+ # - `--` prefixed flags or other non-redirect uses
48
+ # Negative lookbehind (?<![>&]) avoids matching the `>` in `>&1`.
49
+ # Negative lookahead (?![>&]) avoids matching `>` when followed by `&`.
50
+ re.compile(r'(?<![>&])>{1,2}(?![>&])'),
51
+ (
52
+ "Use the Write tool to write output to a file instead of shell redirection.\n"
53
+ " Write tool: creates or overwrites files cleanly without shell quoting issues.\n"
54
+ " For append patterns, use the Edit tool or Read + Write."
55
+ ),
56
+ ),
57
+ (
58
+ "chaining",
59
+ # Match `;` or `&&` but NOT `||` (which is now correctly handled
60
+ # by the pipe regex above via negative lookahead).
61
+ re.compile(r';|&&'),
62
+ (
63
+ "Run each command as a separate, atomic Bash call instead of chaining.\n"
64
+ " One command per step preserves exit-code isolation and avoids\n"
65
+ " interactive prompts mid-chain that block Claude Code execution."
66
+ ),
67
+ ),
68
+ ]
69
+
70
+
71
+ @dataclass
72
+ class PipeViolation:
73
+ """A detected pipe/redirect/chaining violation."""
74
+ rule: str # e.g. "pipe", "redirect", "chaining"
75
+ pattern: str # the literal character(s) that triggered it
76
+ correction: str # human-readable corrected approach
77
+
78
+
79
+ def _find_violation(command: str) -> Optional[PipeViolation]:
80
+ """
81
+ Return the first pipe/redirect/chaining violation found in command,
82
+ or None if the command is clean.
83
+
84
+ Only checks commands that start with a cloud/infra CLI.
85
+ Skips characters inside single or double quoted strings to avoid
86
+ false positives (e.g. --filter='status:RUNNING' contains no violation).
87
+ """
88
+ if not CLOUD_CLI_PATTERN.match(command):
89
+ return None
90
+
91
+ # Strip quoted substrings before scanning for operators.
92
+ # This prevents false positives from flag values like --filter='a|b'.
93
+ unquoted = _strip_quoted_sections(command)
94
+
95
+ for rule_name, pattern, correction in VIOLATIONS:
96
+ match = pattern.search(unquoted)
97
+ if match:
98
+ return PipeViolation(
99
+ rule=rule_name,
100
+ pattern=match.group(0),
101
+ correction=correction,
102
+ )
103
+
104
+ return None
105
+
106
+
107
+ def _strip_quoted_sections(text: str) -> str:
108
+ """
109
+ Replace content inside single and double quotes with spaces.
110
+ Handles simple quoting (no nested quotes, no escape sequences needed
111
+ for the operators we scan for).
112
+ """
113
+ result = []
114
+ in_single = False
115
+ in_double = False
116
+
117
+ for ch in text:
118
+ if ch == "'" and not in_double:
119
+ in_single = not in_single
120
+ result.append(ch)
121
+ elif ch == '"' and not in_single:
122
+ in_double = not in_double
123
+ result.append(ch)
124
+ elif in_single or in_double:
125
+ result.append(' ') # mask the character
126
+ else:
127
+ result.append(ch)
128
+
129
+ return ''.join(result)
130
+
131
+
132
+ def build_block_response(violation: PipeViolation, command: str) -> dict:
133
+ """
134
+ Build the structured JSON block that tells Claude Code to block the command
135
+ and return a corrective reason to the agent.
136
+
137
+ Uses permissionDecision: "deny" with exit 0 (NOT exit 2) so the agent
138
+ receives the correction message and adjusts rather than stopping entirely.
139
+
140
+ Args:
141
+ violation: The detected violation.
142
+ command: The original command string (truncated in reason for readability).
143
+
144
+ Returns:
145
+ Dict suitable for json.dumps() and print() in the hook entry point.
146
+ """
147
+ truncated = command[:120] + ('...' if len(command) > 120 else '')
148
+
149
+ reason = (
150
+ f"Command-execution rule violated: no {violation.rule}s in cloud/infra commands.\n\n"
151
+ f"Violating pattern: '{violation.pattern}' detected in:\n"
152
+ f" {truncated}\n\n"
153
+ f"Corrected approach:\n"
154
+ f"{violation.correction}"
155
+ )
156
+
157
+ return build_hook_permission_response("deny", reason)
158
+
159
+
160
+ def validate_cloud_pipe(command: str) -> Optional[dict]:
161
+ """
162
+ Check a command for cloud pipe/redirect/chaining violations.
163
+
164
+ Returns a block-response dict if a violation is found, None otherwise.
165
+ The caller should json.dumps() the result and exit(0).
166
+
167
+ Args:
168
+ command: The raw bash command string.
169
+
170
+ Returns:
171
+ Block response dict, or None if command is clean.
172
+ """
173
+ violation = _find_violation(command)
174
+ if violation is None:
175
+ return None
176
+
177
+ logger.warning(
178
+ f"Cloud pipe violation [{violation.rule}] pattern='{violation.pattern}' "
179
+ f"in: {command[:80]}"
180
+ )
181
+ return build_block_response(violation, command)
@@ -0,0 +1,55 @@
1
+ """
2
+ Shared builder for hookSpecificOutput responses.
3
+
4
+ Claude Code hooks communicate permission decisions via a standard JSON
5
+ structure. This module provides a single builder so the three call sites
6
+ (bash_validator allow, bash_validator deny, cloud_pipe_validator deny)
7
+ share the same shape and field names.
8
+
9
+ Internally delegates to the adapter layer's ``format_validation_response``
10
+ for structural consistency, while preserving the original function signature
11
+ so callers (bash_validator.py, cloud_pipe_validator) require zero changes.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import sys
17
+ from pathlib import Path
18
+
19
+ # Ensure the hooks directory is on sys.path so ``adapters`` resolves.
20
+ _hooks_dir = str(Path(__file__).resolve().parent.parent.parent)
21
+ if _hooks_dir not in sys.path:
22
+ sys.path.insert(0, _hooks_dir)
23
+
24
+ from adapters.claude_code import ClaudeCodeAdapter
25
+ from adapters.types import ValidationResult
26
+
27
+ # Module-level singleton -- lightweight, no I/O in __init__.
28
+ _adapter = ClaudeCodeAdapter()
29
+
30
+
31
+ def build_hook_permission_response(
32
+ decision: str, reason: str, updated_input: dict | None = None
33
+ ) -> dict:
34
+ """Build a hookSpecificOutput dict for a PreToolUse permission decision.
35
+
36
+ Args:
37
+ decision: "allow", "deny", or "ask".
38
+ reason: Human-readable explanation forwarded to the agent.
39
+ updated_input: Optional modified tool input to pass through for
40
+ "ask" decisions (e.g. footer-stripped command).
41
+
42
+ Returns:
43
+ Dict suitable for ``json.dumps()`` and ``print()`` in the hook
44
+ entry point.
45
+ """
46
+ if decision == "ask":
47
+ response = _adapter.format_ask_response(reason, updated_input=updated_input)
48
+ return response.output
49
+
50
+ vr = ValidationResult(
51
+ allowed=(decision == "allow"),
52
+ reason=reason,
53
+ )
54
+ response = _adapter.format_validation_response(vr)
55
+ return response.output
@@ -0,0 +1,227 @@
1
+ """
2
+ Shell Command Parser - Native Python Implementation
3
+
4
+ Parses bash commands into individual components for permission validation.
5
+ This is a workaround for Claude Code bug where settings.json permissions
6
+ are not respected (GitHub Issue #13340).
7
+
8
+ Features:
9
+ - Parse piped commands: "cmd1 | cmd2" -> ["cmd1", "cmd2"]
10
+ - Parse chained commands: "cmd1 && cmd2" -> ["cmd1", "cmd2"]
11
+ - Parse semicolon-separated: "cmd1; cmd2" -> ["cmd1", "cmd2"]
12
+ - Handle OR chains: "cmd1 || cmd2" -> ["cmd1", "cmd2"]
13
+ - Preserve quoted strings: echo 'a|b' -> ["echo 'a|b'"]
14
+
15
+ Dependencies: Python stdlib only (shlex, re)
16
+ """
17
+
18
+ from typing import List, Optional
19
+ from dataclasses import dataclass
20
+
21
+
22
+ @dataclass
23
+ class ParsedCommand:
24
+ """Represents a parsed shell command component."""
25
+ command: str # The actual command string
26
+ operator: Optional[str] = None # The operator that follows (|, &&, ||, ;)
27
+
28
+ def __str__(self) -> str:
29
+ return self.command
30
+
31
+
32
+ class ShellCommandParser:
33
+ """
34
+ Native Python shell command parser.
35
+
36
+ Parses bash commands into individual components while respecting:
37
+ - Single quotes (preserve everything inside)
38
+ - Double quotes (preserve with variable expansion awareness)
39
+ - Escape sequences
40
+ - Subshells
41
+ - Command substitution
42
+
43
+ Zero external dependencies - uses Python stdlib only.
44
+ """
45
+
46
+ # Shell operators that separate commands
47
+ OPERATORS = {
48
+ '|': 'pipe',
49
+ '&&': 'and',
50
+ '||': 'or',
51
+ ';': 'sequence',
52
+ '\n': 'newline'
53
+ }
54
+
55
+ def __init__(self):
56
+ """Initialize parser."""
57
+ pass
58
+
59
+ def parse(self, command: str) -> List[str]:
60
+ """
61
+ Parse shell command into individual components.
62
+
63
+ Args:
64
+ command: Full shell command string
65
+
66
+ Returns:
67
+ List of individual command strings
68
+
69
+ Example:
70
+ >>> parser = ShellCommandParser()
71
+ >>> parser.parse("ls | grep foo && wc -l")
72
+ ["ls", "grep foo", "wc -l"]
73
+
74
+ >>> parser.parse("echo 'test | grep' | cat")
75
+ ["echo 'test | grep'", "cat"]
76
+ """
77
+ if not command or not command.strip():
78
+ return []
79
+
80
+ # Normalize whitespace
81
+ command = command.strip()
82
+
83
+ # Split on operators while preserving quotes
84
+ components = self._split_on_operators(command)
85
+
86
+ # Clean and filter empty components
87
+ result = [comp.strip() for comp in components if comp.strip()]
88
+
89
+ return result
90
+
91
+ def _split_on_operators(self, command: str) -> List[str]:
92
+ """
93
+ Split command on operators (|, &&, ||, ;) while preserving quoted strings.
94
+
95
+ Uses state machine to track quote context.
96
+ """
97
+ components = []
98
+ current = []
99
+ i = 0
100
+
101
+ # Quote state
102
+ in_single_quote = False
103
+ in_double_quote = False
104
+
105
+ while i < len(command):
106
+ char = command[i]
107
+
108
+ # Handle escape sequences
109
+ if char == '\\' and i + 1 < len(command):
110
+ current.append(char)
111
+ current.append(command[i + 1])
112
+ i += 2
113
+ continue
114
+
115
+ # Handle single quotes
116
+ if char == "'" and not in_double_quote:
117
+ in_single_quote = not in_single_quote
118
+ current.append(char)
119
+ i += 1
120
+ continue
121
+
122
+ # Handle double quotes
123
+ if char == '"' and not in_single_quote:
124
+ in_double_quote = not in_double_quote
125
+ current.append(char)
126
+ i += 1
127
+ continue
128
+
129
+ # If inside quotes, add character and continue
130
+ if in_single_quote or in_double_quote:
131
+ current.append(char)
132
+ i += 1
133
+ continue
134
+
135
+ # Check for two-character operators (&&, ||)
136
+ if i + 1 < len(command):
137
+ two_char = command[i:i+2]
138
+ if two_char in ['&&', '||']:
139
+ # Found operator - save current component
140
+ if current:
141
+ components.append(''.join(current))
142
+ current = []
143
+ i += 2
144
+ continue
145
+
146
+ # Check for single-character operators (|, ;)
147
+ if char in ['|', ';', '\n']:
148
+ # Found operator - save current component
149
+ if current:
150
+ components.append(''.join(current))
151
+ current = []
152
+ i += 1
153
+ continue
154
+
155
+ # Regular character
156
+ current.append(char)
157
+ i += 1
158
+
159
+ # Add final component
160
+ if current:
161
+ components.append(''.join(current))
162
+
163
+ return components
164
+
165
+ def parse_with_operators(self, command: str) -> List[ParsedCommand]:
166
+ """
167
+ Parse command and preserve operator information.
168
+
169
+ Useful for understanding command flow (AND vs OR vs pipe).
170
+ """
171
+ if not command or not command.strip():
172
+ return []
173
+
174
+ commands = self.parse(command)
175
+ return [ParsedCommand(command=cmd) for cmd in commands]
176
+
177
+ def contains_operators(self, command: str) -> bool:
178
+ """Check if command contains shell operators (outside of quotes)."""
179
+ components = self.parse(command)
180
+ return len(components) > 1
181
+
182
+ def is_simple_command(self, command: str) -> bool:
183
+ """Check if command is a simple command (no operators)."""
184
+ return not self.contains_operators(command)
185
+
186
+
187
+ # Singleton instance for reuse
188
+ _shell_parser: Optional[ShellCommandParser] = None
189
+
190
+
191
+ def get_shell_parser() -> ShellCommandParser:
192
+ """
193
+ Get singleton ShellCommandParser instance.
194
+
195
+ Returns:
196
+ ShellCommandParser instance
197
+ """
198
+ global _shell_parser
199
+ if _shell_parser is None:
200
+ _shell_parser = ShellCommandParser()
201
+ return _shell_parser
202
+
203
+
204
+ def parse_command(command: str) -> List[str]:
205
+ """
206
+ Parse shell command into components (convenience function).
207
+
208
+ Args:
209
+ command: Shell command string
210
+
211
+ Returns:
212
+ List of command components
213
+ """
214
+ return get_shell_parser().parse(command)
215
+
216
+
217
+ def is_compound_command(command: str) -> bool:
218
+ """
219
+ Check if command is compound (contains operators).
220
+
221
+ Args:
222
+ command: Shell command string
223
+
224
+ Returns:
225
+ True if compound, False if simple
226
+ """
227
+ return get_shell_parser().contains_operators(command)