@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
@@ -24,6 +24,15 @@ from typing import Dict, FrozenSet, List, Tuple
24
24
  from .approval_messages import build_t3_approval_instructions
25
25
  from .command_semantics import analyze_command
26
26
 
27
+ try:
28
+ from .blocked_commands import is_blocked_command as _is_blocked_command
29
+ except ImportError:
30
+ _is_blocked_command = None
31
+ logging.getLogger(__name__).warning(
32
+ "blocked_commands.is_blocked_command not importable; "
33
+ "inline code Layer 1 (shell extraction) disabled"
34
+ )
35
+
27
36
  logger = logging.getLogger(__name__)
28
37
 
29
38
 
@@ -157,34 +166,108 @@ VERB_FLAG_READ_ONLY_OVERRIDES: Dict[Tuple[str, str], FrozenSet[str]] = {
157
166
 
158
167
 
159
168
  # ============================================================================
160
- # Inline Code Dangerous Patterns (python3 -c, python -c)
169
+ # Inline Code Detection Language-Agnostic 3-Layer Approach
161
170
  # ============================================================================
162
- # When the base command is a runtime interpreter with inline code (-c flag),
163
- # scan the code string for dangerous patterns instead of verb-matching tokens.
171
+ # When the base command is a runtime interpreter with an inline code flag
172
+ # (e.g., python3 -c, node -e, ruby -e, perl -e), scan the code string
173
+ # using three layers instead of verb-matching tokens:
174
+ # Layer 1: Extract string literals → check against blocked_commands
175
+ # Layer 2: Universal dangerous API keyword patterns
176
+ # Layer 3: Heuristic safety classification (length, paths, encoding)
164
177
  import re as _re
165
178
 
166
- _DANGEROUS_INLINE_PATTERNS: Tuple[Tuple[_re.Pattern, str], ...] = (
167
- (_re.compile(r"os\.remove\b"), "os.remove"),
168
- (_re.compile(r"os\.unlink\b"), "os.unlink"),
169
- (_re.compile(r"os\.rmdir\b"), "os.rmdir"),
170
- (_re.compile(r"os\.rename\b"), "os.rename"),
171
- (_re.compile(r"os\.makedirs?\b"), "os.makedirs"),
172
- (_re.compile(r"os\.system\b"), "os.system"),
173
- (_re.compile(r"shutil\.rmtree\b"), "shutil.rmtree"),
174
- (_re.compile(r"shutil\.move\b"), "shutil.move"),
175
- (_re.compile(r"shutil\.copy\b"), "shutil.copy"),
176
- # NOTE: subprocess intentionally omitted -- commonly used for read-only
177
- # inspection (e.g., subprocess.run(["echo","hello"])). The actual command
178
- # inside the subprocess will be evaluated by the hook when it runs.
179
- (_re.compile(r"open\s*\([^)]*['\"][wWaA]['\"]"), "file write via open()"),
180
- (_re.compile(r"\.write\s*\("), "file write"),
181
- (_re.compile(r"pathlib\.Path\([^)]*\)\.(unlink|rmdir|rename|write_)"), "pathlib mutation"),
179
+ # ---------------------------------------------------------------------------
180
+ # CLI → inline-code flag mapping (Step 1a)
181
+ # ---------------------------------------------------------------------------
182
+ _INLINE_CODE_MAP: Dict[str, FrozenSet[str]] = {
183
+ "python": frozenset({"-c"}),
184
+ "python3": frozenset({"-c"}),
185
+ "python3.10": frozenset({"-c"}),
186
+ "python3.11": frozenset({"-c"}),
187
+ "python3.12": frozenset({"-c"}),
188
+ "python3.13": frozenset({"-c"}),
189
+ "node": frozenset({"-e", "--eval"}),
190
+ "ruby": frozenset({"-e"}),
191
+ "perl": frozenset({"-e", "-E"}),
192
+ "php": frozenset({"-r"}),
193
+ "lua": frozenset({"-e"}),
194
+ "rscript": frozenset({"-e"}),
195
+ }
196
+ _INLINE_CODE_CLIS: FrozenSet[str] = frozenset(_INLINE_CODE_MAP.keys())
197
+
198
+ # ---------------------------------------------------------------------------
199
+ # Layer 1: Shell command extraction from string literals
200
+ # ---------------------------------------------------------------------------
201
+ _STRING_LITERAL_RE = _re.compile(r"""(?:['"])((?:[^'"\\\n]|\\.){3,})(?:['"])""")
202
+
203
+
204
+ def _extract_embedded_shell_commands(code: str) -> List[str]:
205
+ """Extract string literals from inline code that may contain shell commands."""
206
+ return [m.group(1) for m in _STRING_LITERAL_RE.finditer(code)]
207
+
208
+
209
+ # ---------------------------------------------------------------------------
210
+ # Layer 2: Universal dangerous API keyword patterns (category-based)
211
+ # ---------------------------------------------------------------------------
212
+ _UNIVERSAL_DANGEROUS_PATTERNS: Tuple[Tuple[_re.Pattern, str, str], ...] = (
213
+ # Category: Process Execution
214
+ (_re.compile(r"\b(child_process|subprocess)\b"), "process-module", "PROCESS_EXECUTION"),
215
+ (_re.compile(r"\b(execSync|execFile|execFileSync)\s*\("), "exec-sync", "PROCESS_EXECUTION"),
216
+ (_re.compile(r"\bos\.(system|popen|exec[lv]?[pe]?)\s*\("), "os-exec", "PROCESS_EXECUTION"),
217
+ (_re.compile(r"\b(system|exec)\s*\("), "system-call", "PROCESS_EXECUTION"),
218
+ (_re.compile(r"\bspawn(Sync)?\s*\("), "spawn-call", "PROCESS_EXECUTION"),
219
+ (_re.compile(r"\bPopen\s*\("), "popen-call", "PROCESS_EXECUTION"),
220
+ (_re.compile(r"`[^`]{3,}`"), "backtick-exec", "PROCESS_EXECUTION"),
221
+
222
+ # Category: File Deletion
223
+ (_re.compile(r"\b(os\.remove|os\.unlink|os\.rmdir)\s*\("), "os-delete", "FILE_DELETION"),
224
+ (_re.compile(r"\b(shutil\.rmtree|shutil\.move)\s*\("), "shutil-delete", "FILE_DELETION"),
225
+ (_re.compile(r"\bfs\.(unlink|rmdir|rm)(Sync)?\s*\("), "fs-delete", "FILE_DELETION"),
226
+ # Also match .unlinkSync( / .rmSync( / .rmdirSync( as method calls (e.g., require('fs').unlinkSync())
227
+ (_re.compile(r"\.(unlink|rmdir|rm)(Sync)?\s*\("), "fs-delete", "FILE_DELETION"),
228
+ (_re.compile(r"\bFile\.(delete|unlink)\s*\("), "file-delete", "FILE_DELETION"),
229
+ (_re.compile(r"\bunlink\s*\("), "unlink-call", "FILE_DELETION"),
230
+ (_re.compile(r"\brmtree\s*\("), "rmtree-call", "FILE_DELETION"),
231
+ (_re.compile(r"\bFileUtils\.rm"), "fileutils-rm", "FILE_DELETION"),
232
+ (_re.compile(r"pathlib\.Path\([^)]*\)\.(unlink|rmdir)"), "pathlib-delete", "FILE_DELETION"),
233
+
234
+ # Category: File Write
235
+ (_re.compile(r"open\s*\([^)]*['\"][wWaA]"), "file-write-open", "FILE_WRITE"),
236
+ (_re.compile(r"\bfs\.writeFile(Sync)?\s*\("), "fs-write", "FILE_WRITE"),
237
+ # Also match .writeFileSync( / .appendFileSync( as method calls
238
+ (_re.compile(r"\.writeFile(Sync)?\s*\("), "fs-write", "FILE_WRITE"),
239
+ (_re.compile(r"\bfs\.appendFile(Sync)?\s*\("), "fs-append", "FILE_WRITE"),
240
+ (_re.compile(r"\.appendFile(Sync)?\s*\("), "fs-append", "FILE_WRITE"),
241
+ (_re.compile(r"\bFile\.(write|open)\b.*['\"][wWaA]"), "file-write-ruby", "FILE_WRITE"),
242
+ (_re.compile(r"\.write\s*\("), "file-write", "FILE_WRITE"),
243
+ (_re.compile(r"pathlib\.Path\([^)]*\)\.(rename|write_)"), "pathlib-write", "FILE_WRITE"),
244
+
245
+ # Category: File System Mutation (os.rename, os.makedirs, shutil.copy)
246
+ (_re.compile(r"\bos\.rename\s*\("), "os-rename", "FILE_MUTATION"),
247
+ (_re.compile(r"\bos\.makedirs?\s*\("), "os-makedirs", "FILE_MUTATION"),
248
+ (_re.compile(r"\bshutil\.copy\s*\("), "shutil-copy", "FILE_MUTATION"),
249
+
250
+ # Category: Network
251
+ (_re.compile(r"\bhttps?://\S+"), "url-literal", "NETWORK"),
252
+ (_re.compile(r"\b(fetch|axios|requests\.get|urllib)\s*\("), "http-call", "NETWORK"),
253
+ (_re.compile(r"\bNet::HTTP\b"), "net-http", "NETWORK"),
254
+
255
+ # Category: Permission Modification
256
+ (_re.compile(r"\bos\.chmod\s*\("), "os-chmod", "PERMISSION_MOD"),
257
+ (_re.compile(r"\bfs\.chmod(Sync)?\s*\("), "fs-chmod", "PERMISSION_MOD"),
182
258
  )
183
259
 
184
- # CLIs that accept -c for inline code execution
185
- _INLINE_CODE_CLIS: FrozenSet[str] = frozenset({
186
- "python", "python3", "python3.10", "python3.11", "python3.12", "python3.13",
187
- })
260
+ # ---------------------------------------------------------------------------
261
+ # Layer 3: Heuristic safety classification
262
+ # ---------------------------------------------------------------------------
263
+ _SUSPICIOUS_HEURISTICS: Tuple[Tuple[_re.Pattern, str], ...] = (
264
+ (_re.compile(r"(/etc/|/home/|~/\.ssh|/var/|/usr/|/root/)"), "sensitive-path"),
265
+ (_re.compile(r"\b(base64|b64encode|b64decode|atob|btoa)\b"), "encoding"),
266
+ (_re.compile(r"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"), "ip-address"),
267
+ )
268
+
269
+ MAX_SAFE_INLINE_LENGTH = 150
270
+ MAX_NORMAL_INLINE_LENGTH = 500
188
271
 
189
272
 
190
273
  # ============================================================================
@@ -458,11 +541,12 @@ def detect_mutative_command(command: str) -> MutativeResult:
458
541
  reason=f"Simulation flag detected (command has --dry-run or equivalent)",
459
542
  )
460
543
 
461
- # --- Step 3b: Inline code safety check (python3 -c "...") ---
462
- # For runtime interpreters with -c, scan the code string for dangerous
463
- # patterns instead of verb-matching tokens (which would false-positive on
464
- # generic keywords like "import", "create", etc.).
465
- if base_cmd in _INLINE_CODE_CLIS and "-c" in semantics.flag_tokens:
544
+ # --- Step 3b: Inline code safety check (python3 -c, node -e, etc.) ---
545
+ # For runtime interpreters with inline code flags, scan the code string
546
+ # using the 3-layer approach instead of verb-matching tokens (which would
547
+ # false-positive on generic keywords like "import", "create", etc.).
548
+ cli_flags = _INLINE_CODE_MAP.get(base_cmd, frozenset())
549
+ if base_cmd in _INLINE_CODE_CLIS and cli_flags & set(semantics.flag_tokens):
466
550
  return _check_inline_code(command, base_cmd, family)
467
551
 
468
552
  # --- Step 4: Scan semantic non-flag tokens near the command head ---
@@ -612,21 +696,41 @@ def detect_mutative_command(command: str) -> MutativeResult:
612
696
  # ============================================================================
613
697
 
614
698
  def _check_inline_code(command: str, base_cmd: str, family: str) -> MutativeResult:
615
- """Check inline code (python3 -c "...") for dangerous patterns.
699
+ """Check inline code for dangerous patterns using a 3-layer approach.
616
700
 
617
- Instead of verb-matching tokens (which false-positive on generic keywords
618
- like "import", "create"), scan the raw code string for known dangerous
619
- function calls.
701
+ Layer 1: Extract string literals from inline code and check them against
702
+ blocked_commands (catches embedded shell commands like 'rm -rf /').
703
+ Layer 2: Scan for universal dangerous API keywords (language-agnostic).
704
+ Layer 3: Heuristic safety classification (length, sensitive paths, encoding).
620
705
 
621
706
  Args:
622
707
  command: Full raw command string.
623
- base_cmd: The interpreter (e.g., "python3").
708
+ base_cmd: The interpreter (e.g., "python3", "node", "ruby").
624
709
  family: CLI family hint.
625
710
 
626
711
  Returns:
627
- MutativeResult -- MUTATIVE if dangerous patterns found, else safe.
712
+ MutativeResult -- MUTATIVE if any layer triggers, else safe.
628
713
  """
629
- for pattern, label in _DANGEROUS_INLINE_PATTERNS:
714
+ # ---- Layer 1: Extract string literals → check against blocked_commands ----
715
+ if _is_blocked_command is not None:
716
+ embedded_strings = _extract_embedded_shell_commands(command)
717
+ for literal in embedded_strings:
718
+ blocked = _is_blocked_command(literal)
719
+ if blocked.is_blocked:
720
+ return MutativeResult(
721
+ is_mutative=True,
722
+ category=CATEGORY_MUTATIVE,
723
+ verb="embedded-blocked-cmd",
724
+ cli_family=family,
725
+ confidence="high",
726
+ reason=(
727
+ f"Inline code contains blocked shell command in "
728
+ f"string literal: {blocked.category}"
729
+ ),
730
+ )
731
+
732
+ # ---- Layer 2: Universal dangerous API keyword patterns ----
733
+ for pattern, label, category in _UNIVERSAL_DANGEROUS_PATTERNS:
630
734
  if pattern.search(command):
631
735
  return MutativeResult(
632
736
  is_mutative=True,
@@ -634,17 +738,54 @@ def _check_inline_code(command: str, base_cmd: str, family: str) -> MutativeResu
634
738
  verb=label,
635
739
  cli_family=family,
636
740
  confidence="medium",
637
- reason=f"Inline code contains dangerous pattern: {label}",
741
+ reason=f"Inline code contains dangerous pattern: {label} ({category})",
638
742
  )
639
743
 
640
- # No dangerous patterns found -- safe inline code
744
+ # ---- Layer 3: Heuristic safety classification ----
745
+ # 3a: Check for suspicious indicators (sensitive paths, encoding, IPs)
746
+ for pattern, label in _SUSPICIOUS_HEURISTICS:
747
+ if pattern.search(command):
748
+ return MutativeResult(
749
+ is_mutative=True,
750
+ category=CATEGORY_MUTATIVE,
751
+ verb=f"heuristic-{label}",
752
+ cli_family=family,
753
+ confidence="low",
754
+ reason=f"Inline code flagged by heuristic: {label}",
755
+ )
756
+
757
+ # 3b: Unusually long inline code is suspicious
758
+ # Extract the code portion after the inline flag for length check.
759
+ # Use a rough extraction: everything after the first inline flag.
760
+ code_portion = command
761
+ cli_flag_tokens = _INLINE_CODE_MAP.get(base_cmd, frozenset())
762
+ for flag in cli_flag_tokens:
763
+ idx = command.find(f" {flag} ")
764
+ if idx != -1:
765
+ code_portion = command[idx + len(flag) + 2:]
766
+ break
767
+
768
+ if len(code_portion) > MAX_NORMAL_INLINE_LENGTH:
769
+ return MutativeResult(
770
+ is_mutative=True,
771
+ category=CATEGORY_MUTATIVE,
772
+ verb="heuristic-long-code",
773
+ cli_family=family,
774
+ confidence="low",
775
+ reason=(
776
+ f"Inline code is unusually long ({len(code_portion)} chars > "
777
+ f"{MAX_NORMAL_INLINE_LENGTH} limit)"
778
+ ),
779
+ )
780
+
781
+ # ---- No layers triggered -- safe inline code ----
641
782
  return MutativeResult(
642
783
  is_mutative=False,
643
784
  category=CATEGORY_READ_ONLY,
644
785
  verb="inline-code",
645
786
  cli_family=family,
646
787
  confidence="medium",
647
- reason=f"Inline code ({base_cmd} -c) with no dangerous patterns",
788
+ reason=f"Inline code ({base_cmd}) with no dangerous patterns",
648
789
  )
649
790
 
650
791
 
@@ -13,6 +13,7 @@ Tiers:
13
13
  - T3: State-modifying operations (mutative_verbs.py detection,
14
14
  nonce-based approval via approval_grants.py)
15
15
  """
16
+ from __future__ import annotations
16
17
 
17
18
  import re
18
19
  import logging
@@ -193,22 +194,3 @@ def classify_command_tier(
193
194
 
194
195
  # Use cached classification
195
196
  return _classify_command_tier_cached(command, has_blocked)
196
-
197
-
198
- def tier_from_string(tier_str: str) -> SecurityTier:
199
- """
200
- Convert string to SecurityTier.
201
-
202
- Args:
203
- tier_str: Tier string like "T0", "T1", "T2", "T3"
204
-
205
- Returns:
206
- SecurityTier enum value
207
- """
208
- tier_map = {
209
- "T0": SecurityTier.T0_READ_ONLY,
210
- "T1": SecurityTier.T1_VALIDATION,
211
- "T2": SecurityTier.T2_DRY_RUN,
212
- "T3": SecurityTier.T3_BLOCKED,
213
- }
214
- return tier_map.get(tier_str.upper(), SecurityTier.T3_BLOCKED)
@@ -5,6 +5,7 @@ Subsystem 4 of the pre_tool_use Task/Agent path.
5
5
  Filters events by agent domain and injects them into agent prompts.
6
6
  Includes the hardcoded agent-to-event mapping.
7
7
  """
8
+ from __future__ import annotations
8
9
 
9
10
  import json
10
11
  import logging
@@ -155,28 +156,3 @@ def build_session_events(
155
156
  return None
156
157
 
157
158
 
158
- def inject_session_events(
159
- parameters: dict,
160
- project_agents: list,
161
- ) -> dict:
162
- """
163
- Legacy wrapper: inject session events by mutating parameters["prompt"].
164
-
165
- Retained for backward compatibility (tests import this function).
166
- New code should use build_session_events() with additionalContext instead.
167
-
168
- Args:
169
- parameters: Task tool parameters (will be mutated).
170
- project_agents: List of valid project agent names.
171
-
172
- Returns:
173
- Modified parameters with events injected into prompt.
174
- """
175
- events_string = build_session_events(parameters, project_agents)
176
- if events_string is None:
177
- return parameters
178
-
179
- prompt = parameters.get("prompt", "")
180
- enriched_prompt = f"{prompt}\n\n{events_string}\n"
181
- parameters["prompt"] = enriched_prompt
182
- return parameters