@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,210 @@
1
+ """Event writer and reader for the GAIA Event Context system.
2
+
3
+ Provides:
4
+ - EventWriter: append-only JSONL writer with file locking
5
+ - read_events(): read events from last N hours with optional filtering
6
+ - cleanup_old_events(): remove events older than N days
7
+ - Event type constants
8
+ """
9
+
10
+ import fcntl
11
+ import json
12
+ import logging
13
+ import os
14
+ from datetime import datetime, timedelta, timezone
15
+ from pathlib import Path
16
+ from typing import Any, Dict, List, Optional
17
+
18
+ from ..core.paths import get_events_dir
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # ---------------------------------------------------------------------------
23
+ # Event type constants
24
+ # ---------------------------------------------------------------------------
25
+
26
+ AGENT_DISPATCH = "agent.dispatch"
27
+ AGENT_COMPLETE = "agent.complete"
28
+ COMMAND_EXECUTED = "command.executed"
29
+ SESSION_END = "session.end"
30
+ TRIGGER_SCHEDULED = "trigger.scheduled"
31
+ HEARTBEAT = "heartbeat"
32
+ USER_NOTE = "user.note"
33
+
34
+
35
+ class EventWriter:
36
+ """Append-only JSONL event writer with file locking.
37
+
38
+ All writes are wrapped in try/except -- events are non-critical and
39
+ must never block the hook pipeline.
40
+ """
41
+
42
+ def __init__(self, events_dir: Optional[Path] = None):
43
+ self.events_dir = events_dir or get_events_dir()
44
+ self.events_file = self.events_dir / "events.jsonl"
45
+ self.lock_file = self.events_dir / "events.jsonl.lock"
46
+
47
+ def write_event(
48
+ self,
49
+ event_type: str,
50
+ source: str,
51
+ agent: str,
52
+ result: str,
53
+ severity: str = "info",
54
+ meta: Optional[Dict[str, Any]] = None,
55
+ ) -> None:
56
+ """Append a single event to the JSONL log.
57
+
58
+ Thread-safe via exclusive file lock. Fails silently on any error
59
+ to avoid disrupting the hook pipeline.
60
+
61
+ Args:
62
+ event_type: Dotted event category (e.g. "agent.dispatch").
63
+ source: Who wrote the event (e.g. "hook").
64
+ agent: Agent involved, or empty string for non-agent events.
65
+ result: Outcome summary string.
66
+ severity: info | warning | error.
67
+ meta: Optional type-specific structured data.
68
+ """
69
+ try:
70
+ self.events_dir.mkdir(parents=True, exist_ok=True)
71
+
72
+ record: Dict[str, Any] = {
73
+ "ts": datetime.now(timezone.utc).isoformat(),
74
+ "type": event_type,
75
+ "source": source,
76
+ "agent": agent,
77
+ "result": result,
78
+ "severity": severity,
79
+ }
80
+ if meta:
81
+ record["meta"] = meta
82
+
83
+ with open(self.lock_file, "w") as lf:
84
+ fcntl.flock(lf.fileno(), fcntl.LOCK_EX)
85
+ try:
86
+ with open(self.events_file, "a") as f:
87
+ f.write(json.dumps(record, separators=(",", ":")) + "\n")
88
+ finally:
89
+ fcntl.flock(lf.fileno(), fcntl.LOCK_UN)
90
+
91
+ except Exception as exc:
92
+ logger.debug("Event write failed (non-fatal): %s", exc)
93
+
94
+
95
+ def read_events(
96
+ hours: int = 24,
97
+ event_type: Optional[str] = None,
98
+ limit: int = 50,
99
+ events_dir: Optional[Path] = None,
100
+ ) -> List[Dict[str, Any]]:
101
+ """Read recent events from the JSONL log.
102
+
103
+ Args:
104
+ hours: How far back to look (default 24h).
105
+ event_type: Optional filter by event type (exact match).
106
+ limit: Maximum number of events to return.
107
+ events_dir: Override events directory (for testing).
108
+
109
+ Returns:
110
+ List of event dicts, most recent last, capped at *limit*.
111
+ """
112
+ try:
113
+ edir = events_dir or get_events_dir()
114
+ events_file = edir / "events.jsonl"
115
+ if not events_file.exists():
116
+ return []
117
+
118
+ cutoff = datetime.now(timezone.utc) - timedelta(hours=hours)
119
+ results: List[Dict[str, Any]] = []
120
+
121
+ with open(events_file, "r") as f:
122
+ for line in f:
123
+ line = line.strip()
124
+ if not line:
125
+ continue
126
+ try:
127
+ evt = json.loads(line)
128
+ except json.JSONDecodeError:
129
+ continue
130
+
131
+ # Time filter
132
+ try:
133
+ ts = datetime.fromisoformat(evt.get("ts", ""))
134
+ if ts < cutoff:
135
+ continue
136
+ except (ValueError, TypeError):
137
+ continue
138
+
139
+ # Type filter
140
+ if event_type and evt.get("type") != event_type:
141
+ continue
142
+
143
+ results.append(evt)
144
+
145
+ # Return the most recent events, capped at limit
146
+ return results[-limit:]
147
+
148
+ except Exception as exc:
149
+ logger.debug("Event read failed (non-fatal): %s", exc)
150
+ return []
151
+
152
+
153
+ def cleanup_old_events(
154
+ days: int = 7,
155
+ events_dir: Optional[Path] = None,
156
+ ) -> int:
157
+ """Remove events older than *days* from the JSONL log.
158
+
159
+ Uses file locking to avoid conflicts with concurrent writers.
160
+ Retains lines that cannot be parsed (conservative).
161
+
162
+ Args:
163
+ days: Retention window in days (default 7).
164
+ events_dir: Override events directory (for testing).
165
+
166
+ Returns:
167
+ Number of events removed.
168
+ """
169
+ try:
170
+ edir = events_dir or get_events_dir()
171
+ events_file = edir / "events.jsonl"
172
+ lock_file = edir / "events.jsonl.lock"
173
+
174
+ if not events_file.exists():
175
+ return 0
176
+
177
+ retention_days = int(os.environ.get("GAIA_EVENT_RETENTION_DAYS", str(days)))
178
+ cutoff = datetime.now(timezone.utc) - timedelta(days=retention_days)
179
+ kept: List[str] = []
180
+ removed = 0
181
+
182
+ with open(lock_file, "w") as lf:
183
+ fcntl.flock(lf.fileno(), fcntl.LOCK_EX)
184
+ try:
185
+ with open(events_file, "r") as f:
186
+ for line in f:
187
+ line = line.strip()
188
+ if not line:
189
+ continue
190
+ try:
191
+ evt = json.loads(line)
192
+ ts = datetime.fromisoformat(evt["ts"])
193
+ if ts < cutoff:
194
+ removed += 1
195
+ continue
196
+ except (json.JSONDecodeError, KeyError, ValueError):
197
+ pass # Keep unparseable lines
198
+ kept.append(line)
199
+
200
+ with open(events_file, "w") as f:
201
+ for line in kept:
202
+ f.write(line + "\n")
203
+ finally:
204
+ fcntl.flock(lf.fileno(), fcntl.LOCK_UN)
205
+
206
+ return removed
207
+
208
+ except Exception as exc:
209
+ logger.debug("Event cleanup failed (non-fatal): %s", exc)
210
+ return 0
@@ -2,42 +2,33 @@
2
2
 
3
3
 
4
4
  def build_ops_identity() -> str:
5
- """Build identity context for ops mode (full orchestrator).
6
-
7
- Lightweight identity that delegates details to on-demand skills.
8
- Always dispatches — never searches or executes directly.
9
- """
10
5
  return """# Identity: Gaia Ops Orchestrator
11
6
 
12
- You are a dispatcher. Users bring requests; you determine which
13
- specialist agent can handle them and relay the work.
7
+ You are a dispatcher. Users bring requests; you route to the right
8
+ specialist agent. You never investigate or execute yourself.
14
9
 
15
10
  ## Your tools
16
- - **Agent** — dispatch work to specialist agents
17
- - **SendMessage** — resume a previously spawned agent with `to: agentId`
18
- - **AskUserQuestion** — get clarification or approval from the user
19
- - **Skill** — load on-demand procedures
11
+ - **Agent** — dispatch to specialist agents
12
+ - **SendMessage** — resume a previously spawned agent
13
+ - **AskUserQuestion** — get clarification or approval
14
+ - **Skill** — load on-demand procedures (agent-response, orchestrator-approval)
20
15
 
21
16
  ## Routing
22
17
 
23
- When the request is project-related (code, infrastructure, deployment,
24
- planning, or anything about this codebase), **always** load the
25
- project-dispatch skillit has the agent table and dispatch rules.
26
- Do not search, explore, or run commands yourself. Dispatch to an agent.
18
+ Each user message includes a routing recommendation. Follow it:
19
+ - confidence >= 0.5 dispatch the recommended agent(s) using the dispatch_mode
20
+ - confidence < 0.5 ask the user to clarify
21
+ - no recommendation respond directly (general question)
27
22
 
28
- When you receive an agent response with a `json:contract`, load the
29
- agent-response skill it explains how to interpret each status
30
- and present results to the user.
23
+ Your prompt to the agent = user's objective + info agent cannot derive.
24
+ Resume an active agent with SendMessage instead of creating a new one.
31
25
 
32
- When it is a general question, reasoning, or you already have the
33
- answer from loaded context, respond directly.
26
+ ## Response Handling
34
27
 
35
- ## Security
36
- - T3 operations are handled by agents through the nonce approval workflow
37
- - When you see AWAITING_APPROVAL, load the orchestrator-approval skill
38
- - Never synthesize nonces — they are hex tokens from the hook
28
+ When an agent returns a json:contract, load agent-response skill.
29
+ When an agent returns REVIEW with approval_id, load orchestrator-approval skill.
39
30
 
40
31
  ## Failures
41
- - If a hook blocks a command, relay the message verbatim. Do not try alternatives.
42
- - If routing is unclear, ask the user to clarify.
43
- - If an agent contradicts another, present both sides and let user decide."""
32
+ - Hook blocks a command relay message verbatim, no alternatives
33
+ - Routing unclear ask the user
34
+ - Agents contradict present both sides, user decides"""
@@ -6,7 +6,6 @@ session_state.py directly into this module.
6
6
 
7
7
  Provides:
8
8
  - write(): Store workflow as episodic memory
9
- - capture_episodic_memory(): Backward-compatible alias for write()
10
9
  - get_session_events(): Read context.json, categorize events
11
10
  """
12
11
 
@@ -170,7 +169,7 @@ def write(
170
169
  outcome = "failed"
171
170
  success = False
172
171
  else:
173
- # IN_PROGRESS, REVIEW, AWAITING_APPROVAL, NEEDS_INPUT -> partial
172
+ # IN_PROGRESS, REVIEW, NEEDS_INPUT -> partial
174
173
  outcome = "partial"
175
174
  success = None
176
175
  elif exit_code == 0:
@@ -226,7 +225,3 @@ def write(
226
225
  except Exception as e:
227
226
  logger.debug(f"Failed to capture episodic memory: {e}")
228
227
  return None
229
-
230
-
231
- # Backward-compatible alias
232
- capture_episodic_memory = write
@@ -0,0 +1 @@
1
+ # Orchestrator enforcement modules.
@@ -0,0 +1,128 @@
1
+ """Orchestrator delegate mode enforcement.
2
+
3
+ When GAIA is installed, delegate mode is always active. The orchestrator
4
+ (main session) is restricted to dispatch-only tools. Direct investigation
5
+ tools (Bash, Read, Edit, etc.) are blocked so the orchestrator must
6
+ delegate to specialist agents.
7
+
8
+ Detection: Claude Code includes ``agent_id`` and ``agent_type`` in the
9
+ PreToolUse payload ONLY when the hook fires inside a subagent. Their absence
10
+ means the call originates from the main session (orchestrator).
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import logging
16
+ from dataclasses import dataclass
17
+ from typing import Any, Dict, Optional
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ # Tools the orchestrator is allowed to use in delegate mode.
22
+ # Everything NOT in this set is blocked for the main session.
23
+ ORCHESTRATOR_ALLOWED_TOOLS = frozenset({
24
+ # Dispatch and communication
25
+ "agent",
26
+ "task",
27
+ "sendmessage",
28
+
29
+ # On-demand skills / procedures
30
+ "skill",
31
+
32
+ # Agent teams task management
33
+ "taskcreate",
34
+ "taskupdate",
35
+ "tasklist",
36
+ "taskget",
37
+
38
+ # Tool discovery
39
+ "toolsearch",
40
+
41
+ # Web research (read-only, T0)
42
+ "websearch",
43
+ "webfetch",
44
+
45
+ # User interaction (built-in, may not always trigger hooks)
46
+ "askuserquestion",
47
+ })
48
+
49
+
50
+ @dataclass(frozen=True)
51
+ class DelegateModeResult:
52
+ """Result of delegate mode check."""
53
+
54
+ blocked: bool
55
+ reason: Optional[str] = None
56
+
57
+
58
+ def is_orchestrator_context(hook_payload: Dict[str, Any]) -> bool:
59
+ """Determine if the hook is firing in the main session (orchestrator).
60
+
61
+ Claude Code includes ``agent_id`` in the PreToolUse payload only when
62
+ the tool call originates from a subagent. Its absence means the call
63
+ is from the main session.
64
+
65
+ Args:
66
+ hook_payload: The full stdin JSON dict from Claude Code.
67
+
68
+ Returns:
69
+ True if this is the orchestrator (main session), False if subagent.
70
+ """
71
+ agent_id = hook_payload.get("agent_id")
72
+ # agent_id is absent or empty string for the main session
73
+ return not agent_id
74
+
75
+
76
+ def check_delegate_mode(
77
+ tool_name: str, hook_payload: Dict[str, Any]
78
+ ) -> DelegateModeResult:
79
+ """Check whether a tool call should be blocked by delegate mode.
80
+
81
+ This is the single entry point. Call it early in the PreToolUse flow.
82
+
83
+ Args:
84
+ tool_name: The tool being invoked (e.g., "Bash", "Read", "Edit").
85
+ hook_payload: The full stdin JSON dict from Claude Code.
86
+
87
+ Returns:
88
+ DelegateModeResult with blocked=True and a reason if the call
89
+ should be denied, or blocked=False if it should proceed.
90
+ """
91
+ is_orchestrator = is_orchestrator_context(hook_payload)
92
+ if not is_orchestrator:
93
+ # Subagents have full tool access -- delegate mode does not apply
94
+ agent_id = hook_payload.get("agent_id", "<none>")
95
+ logger.debug(
96
+ "delegate_mode check: SKIP (subagent %s) tool=%s",
97
+ agent_id,
98
+ tool_name,
99
+ )
100
+ return DelegateModeResult(blocked=False)
101
+
102
+ normalized = tool_name.lower().strip()
103
+ if normalized in ORCHESTRATOR_ALLOWED_TOOLS:
104
+ logger.debug(
105
+ "delegate_mode check: ALLOW (orchestrator allowed tool) tool=%s",
106
+ tool_name,
107
+ )
108
+ return DelegateModeResult(blocked=False)
109
+
110
+ logger.warning(
111
+ "DELEGATE_MODE blocked tool '%s' for orchestrator (main session)",
112
+ tool_name,
113
+ )
114
+
115
+ return DelegateModeResult(
116
+ blocked=True,
117
+ reason=(
118
+ f"[DELEGATE MODE] Tool '{tool_name}' is not available to the orchestrator.\n\n"
119
+ f"As the orchestrator, you must delegate work to specialist agents.\n"
120
+ f"Use the Agent tool to dispatch to the appropriate agent, or use\n"
121
+ f"SendMessage to resume an existing agent.\n\n"
122
+ f"Allowed orchestrator tools: Agent, SendMessage, Skill, TaskCreate, "
123
+ f"TaskUpdate, TaskList, TaskGet, ToolSearch, WebSearch, WebFetch, "
124
+ f"AskUserQuestion.\n\n"
125
+ f"Do NOT attempt to use {tool_name} directly. Identify the right\n"
126
+ f"specialist agent and delegate the work."
127
+ ),
128
+ )
@@ -4,9 +4,9 @@ Security module - Security tiers, blocked patterns, mutative verb detection.
4
4
  Provides:
5
5
  - tiers: SecurityTier enum and classification
6
6
  - blocked_commands: Permanently blocked pattern matching
7
- - mutative_verbs: Mutative verb detection (nonce-based approval)
7
+ - mutative_verbs: Mutative verb detection (user approval workflow)
8
8
  - gitops_validator: kubectl/helm/flux validation
9
- - approval_constants: Canonical nonce approval token
9
+ - approval_constants: Approval token patterns (legacy APPROVE: and ElicitationResult)
10
10
  - approval_grants: Time-limited T3 command passthrough after user approval
11
11
  """
12
12
 
@@ -32,7 +32,6 @@ from .approval_messages import (
32
32
  CANONICAL_APPROVAL_TOKEN_GUIDANCE,
33
33
  CANONICAL_APPROVAL_FORMAT_GUIDANCE,
34
34
  LATEST_BLOCKED_COMMAND_PHRASE,
35
- AWAITING_APPROVAL_STATUS,
36
35
  )
37
36
  from .approval_scopes import (
38
37
  ApprovalSignature,
@@ -76,7 +75,6 @@ __all__ = [
76
75
  "CANONICAL_APPROVAL_TOKEN_GUIDANCE",
77
76
  "CANONICAL_APPROVAL_FORMAT_GUIDANCE",
78
77
  "LATEST_BLOCKED_COMMAND_PHRASE",
79
- "AWAITING_APPROVAL_STATUS",
80
78
  "ApprovalSignature",
81
79
  "SCOPE_EXACT_COMMAND",
82
80
  "SCOPE_SEMANTIC_SIGNATURE",
@@ -1,4 +1,8 @@
1
- """Canonical nonce approval token and deprecated approval phrases for T3 operation resumes."""
1
+ """Approval token patterns and deprecated approval phrases for T3 operation resumes.
2
+
3
+ The APPROVE: prefix is a legacy path (SendMessage-based nonce relay). The primary
4
+ approval flow now uses ElicitationResult (AskUserQuestion -> user clicks Approve).
5
+ """
2
6
 
3
7
  import re
4
8