@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,132 @@
1
+ #!/usr/bin/env python3
2
+ """ElicitationResult hook -- activates T3 approval grants when user approves via AskUserQuestion.
3
+
4
+ This hook fires after the user responds to an AskUserQuestion elicitation.
5
+ It checks if the response indicates approval and, if so, activates all
6
+ pending approval grants for the current session.
7
+
8
+ The hook NEVER blocks (always exits 0). It is purely side-effectful:
9
+ reading the user's answer and activating grants when appropriate.
10
+ """
11
+
12
+ import sys
13
+ import json
14
+ import logging
15
+ import os
16
+ from datetime import datetime
17
+ from pathlib import Path
18
+
19
+ sys.path.insert(0, str(Path(__file__).parent))
20
+
21
+ from modules.core.paths import get_logs_dir
22
+ from modules.core.stdin import has_stdin_data
23
+
24
+ # Configure logging -- file only, no stderr
25
+ _log_file = get_logs_dir() / f"hooks-{datetime.now().strftime('%Y-%m-%d')}.log"
26
+ logging.basicConfig(
27
+ level=logging.INFO,
28
+ format='%(asctime)s [elicitation_result] %(name)s - %(levelname)s - %(message)s',
29
+ handlers=[logging.FileHandler(_log_file)],
30
+ )
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ def _extract_response(event: dict) -> str | None:
35
+ """Extract the user's answer from the ElicitationResult event.
36
+
37
+ The exact schema is not fully documented, so we probe multiple
38
+ possible field names defensively.
39
+ """
40
+ # Try top-level fields first
41
+ for field in ("result", "answer", "response", "selected", "value",
42
+ "hookEventInput", "elicitation_result"):
43
+ val = event.get(field)
44
+ if val is None:
45
+ continue
46
+ if isinstance(val, str) and val.strip():
47
+ return val
48
+ if isinstance(val, dict):
49
+ # Nested -- look for answer/selected inside
50
+ for inner in ("answer", "selected", "value", "result", "label"):
51
+ inner_val = val.get(inner)
52
+ if inner_val and isinstance(inner_val, str):
53
+ return inner_val
54
+ # Check for answers dict (AskUserQuestion structured format)
55
+ answers = val.get("answers", {})
56
+ if answers and isinstance(answers, dict):
57
+ first_val = next(iter(answers.values()), None)
58
+ if first_val:
59
+ return str(first_val)
60
+ # Check for options list selection
61
+ options = val.get("options", [])
62
+ if options and isinstance(options, list):
63
+ for opt in options:
64
+ if isinstance(opt, dict) and opt.get("selected"):
65
+ return str(opt.get("label", opt.get("value", "")))
66
+ return None
67
+
68
+
69
+ def _is_approval(response: str) -> bool:
70
+ """Check if the response indicates approval."""
71
+ normalized = response.lower().strip()
72
+ approval_words = ["approve", "approved", "yes", "accept", "confirm", "allow"]
73
+ return any(word in normalized for word in approval_words)
74
+
75
+
76
+ def _activate_grants(session_id: str) -> None:
77
+ """Activate all pending approval grants for this session."""
78
+ from modules.security.approval_grants import (
79
+ activate_grants_for_session,
80
+ get_pending_approvals_for_session,
81
+ )
82
+
83
+ pending = get_pending_approvals_for_session(session_id)
84
+ if not pending:
85
+ logger.info("No pending approvals to activate for session %s", session_id)
86
+ return
87
+
88
+ results = activate_grants_for_session(session_id)
89
+ activated = sum(1 for r in results if r.success)
90
+ logger.info(
91
+ "ElicitationResult activated %d/%d pending approvals for session %s",
92
+ activated, len(results), session_id,
93
+ )
94
+
95
+
96
+ if __name__ == "__main__":
97
+ if not has_stdin_data():
98
+ sys.exit(0)
99
+
100
+ try:
101
+ raw = sys.stdin.read()
102
+ if not raw.strip():
103
+ sys.exit(0)
104
+
105
+ event = json.loads(raw)
106
+
107
+ # Extract session_id from event or environment
108
+ session_id = event.get("session_id") or os.environ.get("CLAUDE_SESSION_ID", "")
109
+
110
+ # Extract user's response
111
+ response = _extract_response(event)
112
+
113
+ if not response:
114
+ logger.info("No extractable response in ElicitationResult event")
115
+ sys.exit(0)
116
+
117
+ logger.info("ElicitationResult response: %s", response[:80])
118
+
119
+ # Check if the response indicates approval
120
+ if _is_approval(response):
121
+ if session_id:
122
+ _activate_grants(session_id)
123
+ else:
124
+ logger.warning("Approval detected but no session_id available")
125
+ else:
126
+ logger.info("ElicitationResult response is not an approval: %s", response[:40])
127
+
128
+ except Exception as e:
129
+ logger.error("Error in elicitation_result hook: %s", e, exc_info=True)
130
+
131
+ # Never block -- always exit 0
132
+ sys.exit(0)
package/hooks/hooks.json CHANGED
@@ -16,12 +16,20 @@
16
16
  {
17
17
  "matcher": "SendMessage",
18
18
  "hooks": [{"type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/pre_tool_use.py"}]
19
+ },
20
+ {
21
+ "matcher": "Read|Edit|Write|Glob|Grep|WebSearch|WebFetch|NotebookEdit",
22
+ "hooks": [{"type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/pre_tool_use.py"}]
19
23
  }
20
24
  ],
21
25
  "PostToolUse": [
22
26
  {
23
27
  "matcher": "Bash",
24
28
  "hooks": [{"type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/post_tool_use.py"}]
29
+ },
30
+ {
31
+ "matcher": "AskUserQuestion",
32
+ "hooks": [{"type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/post_tool_use.py"}]
25
33
  }
26
34
  ],
27
35
  "SubagentStop": [
@@ -61,6 +69,7 @@
61
69
  {
62
70
  "hooks": [{"type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/post_compact.py"}]
63
71
  }
64
- ]
72
+ ],
73
+ "ElicitationResult": []
65
74
  }
66
75
  }
@@ -105,7 +105,7 @@ This enforces the principle: "Orchestrator delegates, agents execute."
105
105
  SendMessage is validated as a PreToolUse event (not a separate hook event):
106
106
  - Agent ID format check (must match `/^a[0-9a-f]{5,}$/`)
107
107
  - Non-empty message required
108
- - Nonce approval detection (APPROVE:{nonce} activates pending grants)
108
+ - Grant activation is handled by ElicitationResult hook (user approval via AskUserQuestion)
109
109
 
110
110
  ### Context Enforcement
111
111
  Task invocations for project agents inject project-context via `context_provider.py`.
@@ -173,11 +173,12 @@ All security rules (blocked patterns, mutative verbs, tiers) are hardcoded in th
173
173
 
174
174
  ### Validation Order (Defense-in-Depth)
175
175
  bash_validator checks commands in this order (short-circuit on first match):
176
+ 0. **Indirect execution detection** — `bash -c`, `eval`, `python -c` etc. → ask or block
176
177
  1. **Blocked commands** (blocked_commands.py) — permanently denied patterns, exit 2
177
178
  2. **Claude footer stripping** — transparent via updatedInput
178
179
  3. **Commit message validation** — conventional commits enforcement
179
180
  4. **Cloud pipe/redirect/chain check** (cloud_pipe_validator.py) — corrective deny
180
- 5. **Mutative verbs** (mutative_verbs.py) — CLI-agnostic verb detector, nonce-based deny
181
+ 5. **Mutative verbs** (mutative_verbs.py) — CLI-agnostic verb detector, native `ask` dialog
181
182
  6. **GitOps validation** (gitops_validator.py) — kubectl/helm/flux policy enforcement
182
183
  7. **Everything else** — SAFE by elimination (auto-approved)
183
184
 
@@ -118,7 +118,7 @@ def _validate_from_json_contract(contract: dict, task_info: Dict[str, Any]) -> V
118
118
  plan_status = str(agent_status.get("plan_status", "")).upper()
119
119
 
120
120
  statuses_requiring_evidence = {
121
- "IN_PROGRESS", "REVIEW", "AWAITING_APPROVAL",
121
+ "IN_PROGRESS", "REVIEW",
122
122
  "COMPLETE", "BLOCKED", "NEEDS_INPUT",
123
123
  }
124
124
 
@@ -568,48 +568,12 @@ def validate_verbatim_outputs_consistency(
568
568
  # False pending-approval detection
569
569
  # ============================================================================
570
570
 
571
- _NONCE_PATTERN = re.compile(r"NONCE:[a-f0-9]{32}")
572
-
573
-
574
- def validate_awaiting_approval_has_nonce(
575
- transcript_text: str,
576
- plan_status: str,
577
- ) -> Optional[Dict[str, Any]]:
578
- """Detect when an agent returns AWAITING_APPROVAL without a real hook nonce.
579
-
580
- If plan_status is AWAITING_APPROVAL, a hook should have blocked a T3 command
581
- and emitted a ``NONCE:<32-hex>`` token. If no such token appears in the
582
- agent's transcript/output, the agent likely over-escalated.
583
-
584
- Args:
585
- transcript_text: The full agent transcript or output text.
586
- plan_status: The agent's reported plan_status string.
587
-
588
- Returns:
589
- An anomaly dict (severity: info) when the check triggers, None otherwise.
590
- """
591
- if plan_status.upper() != "AWAITING_APPROVAL":
592
- return None
593
-
594
- if _NONCE_PATTERN.search(transcript_text):
595
- return None
596
-
597
- return {
598
- "type": "awaiting_approval_missing_nonce",
599
- "severity": "info",
600
- "detail": (
601
- "Agent returned AWAITING_APPROVAL without a hook nonce. "
602
- "This is normal for plan-first workflows; it becomes a concern "
603
- "only if the agent never proceeds to execution."
604
- ),
605
- }
606
-
607
571
 
608
572
  # ============================================================================
609
573
  # Approval request validation
610
574
  # ============================================================================
611
575
 
612
- _APPROVAL_STATUSES = {"REVIEW", "AWAITING_APPROVAL"}
576
+ _APPROVAL_STATUSES = {"REVIEW"}
613
577
 
614
578
  _APPROVAL_REQUIRED_FIELDS = [
615
579
  "operation", "exact_content", "scope", "risk_level", "rollback", "verification",
@@ -624,7 +588,7 @@ def validate_approval_request(
624
588
  contract: dict,
625
589
  plan_status: str,
626
590
  ) -> Optional[Dict[str, Any]]:
627
- """Validate the approval_request block when plan_status is REVIEW or AWAITING_APPROVAL.
591
+ """Validate the approval_request block when plan_status is REVIEW.
628
592
 
629
593
  Advisory only -- returns an anomaly dict if validation fails, None if OK
630
594
  or if the check does not apply.
@@ -659,14 +623,7 @@ def validate_approval_request(
659
623
  risk = str(approval_req.get("risk_level", "")).upper()
660
624
  invalid_risk = risk and risk not in _VALID_RISK_LEVELS
661
625
 
662
- # For AWAITING_APPROVAL, also check nonce
663
626
  nonce_issue = None
664
- if plan_status.upper() == "AWAITING_APPROVAL":
665
- nonce_val = str(approval_req.get("nonce", ""))
666
- if not nonce_val:
667
- nonce_issue = "nonce field missing"
668
- elif not _NONCE_HEX_RE.match(nonce_val):
669
- nonce_issue = f"nonce format invalid: {nonce_val}"
670
627
 
671
628
  issues: List[str] = []
672
629
  if missing_fields:
@@ -688,8 +645,3 @@ def validate_approval_request(
688
645
  ),
689
646
  "missing_fields": missing_fields,
690
647
  }
691
-
692
-
693
- # Aliases for shorter import names
694
- extract_plan_status = extract_plan_status_from_output
695
- extract_exit_code = extract_exit_code_from_output
@@ -29,7 +29,6 @@ from .contract_validator import parse_contract
29
29
  VALID_PLAN_STATUSES = {
30
30
  "IN_PROGRESS",
31
31
  "REVIEW",
32
- "AWAITING_APPROVAL",
33
32
  "COMPLETE",
34
33
  "BLOCKED",
35
34
  "NEEDS_INPUT",
@@ -64,7 +63,7 @@ CONSOLIDATION_FIELDS = [
64
63
  RECOMMENDED_ACTION_NONE = "none"
65
64
 
66
65
  # Statuses that should carry an approval_request block
67
- APPROVAL_REQUEST_STATUSES = {"REVIEW", "AWAITING_APPROVAL"}
66
+ APPROVAL_REQUEST_STATUSES = {"REVIEW"}
68
67
 
69
68
  APPROVAL_REQUEST_REQUIRED_FIELDS = [
70
69
  "operation",
@@ -386,12 +385,9 @@ def validate_response_contract(
386
385
  risk = str(approval_req.get("risk_level", "")).upper()
387
386
  if risk and risk not in VALID_RISK_LEVELS:
388
387
  warnings.append(f"APPROVAL_REQUEST_INVALID_RISK_LEVEL:{risk}")
389
- if status.plan_status == "AWAITING_APPROVAL":
390
- nonce_val = str(approval_req.get("nonce", ""))
391
- if not nonce_val:
392
- warnings.append("APPROVAL_REQUEST_NONCE_MISSING")
393
- elif not _NONCE_HEX_PATTERN.match(nonce_val):
394
- warnings.append(f"APPROVAL_REQUEST_NONCE_INVALID:{nonce_val}")
388
+ # Check for approval_id when status is REVIEW
389
+ if status.plan_status == "REVIEW":
390
+ pass # approval_id presence is advisory, not enforced
395
391
 
396
392
  valid = not missing and not invalid
397
393
  recommended_action = RECOMMENDED_ACTION_NONE if valid else "resume_same_agent_contract_repair"
@@ -117,8 +117,8 @@ def extract_task_description_from_transcript(transcript_path: str) -> str:
117
117
  The first ``role: "user"`` entry is the task prompt sent by the orchestrator --
118
118
  which is the most meaningful description of what the agent was asked to do.
119
119
 
120
- Since Phase 2, context is delivered via additionalContext (not prompt mutation),
121
- so the first user message IS the original prompt without any wrapping.
120
+ Context is delivered via additionalContext (not prompt mutation), so the
121
+ first user message IS the original prompt without any wrapping.
122
122
 
123
123
  Returns empty string on any error so the hook never crashes.
124
124
  """
@@ -134,9 +134,8 @@ def extract_injected_context_payload_from_transcript(
134
134
  ) -> Dict[str, Any]:
135
135
  """Extract the auto-injected context payload from disk cache.
136
136
 
137
- Since Phase 2, context is delivered via additionalContext and the payload
138
- is persisted to disk by context_injector. The legacy HTML comment parsing
139
- fallback has been removed as prompts no longer contain embedded payloads.
137
+ Context is delivered via additionalContext and the payload is persisted to
138
+ disk by context_injector. Prompts do not contain embedded payloads.
140
139
  """
141
140
  import os
142
141
 
@@ -1,14 +1,14 @@
1
1
  """
2
- Audit module - Logging, metrics, and event detection.
2
+ Audit module - Logging, metrics aggregation, and event detection.
3
3
 
4
4
  Provides:
5
- - logger: AuditLogger for tool executions
6
- - metrics: MetricsCollector with functional generate_summary
5
+ - logger: AuditLogger for tool executions (write path)
6
+ - metrics: generate_summary reads audit logs and aggregates (read path)
7
7
  - event_detector: CriticalEventDetector
8
8
  """
9
9
 
10
10
  from .logger import AuditLogger, log_execution
11
- from .metrics import MetricsCollector, record_metric, generate_summary
11
+ from .metrics import generate_summary
12
12
  from .event_detector import (
13
13
  CriticalEventDetector,
14
14
  detect_critical_event,
@@ -20,8 +20,6 @@ __all__ = [
20
20
  "AuditLogger",
21
21
  "log_execution",
22
22
  # Metrics
23
- "MetricsCollector",
24
- "record_metric",
25
23
  "generate_summary",
26
24
  # Event detector
27
25
  "CriticalEventDetector",
@@ -14,8 +14,6 @@ from typing import Dict, Any, Optional, List
14
14
  from dataclasses import dataclass
15
15
  from datetime import datetime
16
16
 
17
- from ..core.paths import get_session_dir
18
-
19
17
  logger = logging.getLogger(__name__)
20
18
 
21
19