@jaguilar87/gaia 5.0.0-rc.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 (621) hide show
  1. package/.claude-plugin/marketplace.json +33 -0
  2. package/.claude-plugin/plugin.json +26 -0
  3. package/ARCHITECTURE.md +335 -0
  4. package/CHANGELOG.md +1298 -0
  5. package/CODE_OF_CONDUCT.md +11 -0
  6. package/CONTRIBUTING.md +146 -0
  7. package/INSTALL.md +436 -0
  8. package/LICENSE +21 -0
  9. package/README.md +222 -0
  10. package/SECURITY.md +47 -0
  11. package/agents/README.md +78 -0
  12. package/agents/cloud-troubleshooter.md +73 -0
  13. package/agents/developer.md +65 -0
  14. package/agents/gaia-operator.md +64 -0
  15. package/agents/gaia-orchestrator.md +111 -0
  16. package/agents/gaia-planner.md +53 -0
  17. package/agents/gaia-system.md +71 -0
  18. package/agents/gitops-operator.md +61 -0
  19. package/agents/terraform-architect.md +63 -0
  20. package/bin/README.md +106 -0
  21. package/bin/cli/__init__.py +1 -0
  22. package/bin/cli/approvals.py +740 -0
  23. package/bin/cli/cleanup.py +562 -0
  24. package/bin/cli/context.py +283 -0
  25. package/bin/cli/doctor.py +651 -0
  26. package/bin/cli/history.py +305 -0
  27. package/bin/cli/memory.py +483 -0
  28. package/bin/cli/metrics.py +1068 -0
  29. package/bin/cli/plans.py +515 -0
  30. package/bin/cli/status.py +302 -0
  31. package/bin/cli/update.py +382 -0
  32. package/bin/gaia +112 -0
  33. package/bin/gaia-cleanup.js +531 -0
  34. package/bin/gaia-doctor.js +635 -0
  35. package/bin/gaia-evidence +126 -0
  36. package/bin/gaia-history.js +251 -0
  37. package/bin/gaia-metrics.js +1278 -0
  38. package/bin/gaia-review.js +269 -0
  39. package/bin/gaia-scan +44 -0
  40. package/bin/gaia-scan.py +589 -0
  41. package/bin/gaia-skills-diagnose.js +929 -0
  42. package/bin/gaia-status.js +278 -0
  43. package/bin/gaia-uninstall.js +111 -0
  44. package/bin/gaia-update.js +919 -0
  45. package/bin/pre-publish-validate.js +610 -0
  46. package/bin/python-detect.js +60 -0
  47. package/bin/validate-sandbox.sh +601 -0
  48. package/commands/README.md +64 -0
  49. package/commands/gaia.md +37 -0
  50. package/commands/scan-project.md +67 -0
  51. package/config/README.md +71 -0
  52. package/config/cloud/aws.json +134 -0
  53. package/config/cloud/gcp.json +139 -0
  54. package/config/context-contracts.json +158 -0
  55. package/config/crons-schema.md +81 -0
  56. package/config/git_standards.json +72 -0
  57. package/config/surface-routing.json +417 -0
  58. package/config/universal-rules.json +102 -0
  59. package/dist/gaia-ops/.claude-plugin/plugin.json +24 -0
  60. package/dist/gaia-ops/README.md +80 -0
  61. package/dist/gaia-ops/agents/cloud-troubleshooter.md +73 -0
  62. package/dist/gaia-ops/agents/developer.md +65 -0
  63. package/dist/gaia-ops/agents/gaia-operator.md +64 -0
  64. package/dist/gaia-ops/agents/gaia-orchestrator.md +111 -0
  65. package/dist/gaia-ops/agents/gaia-planner.md +53 -0
  66. package/dist/gaia-ops/agents/gaia-system.md +71 -0
  67. package/dist/gaia-ops/agents/gitops-operator.md +61 -0
  68. package/dist/gaia-ops/agents/terraform-architect.md +63 -0
  69. package/dist/gaia-ops/commands/gaia.md +37 -0
  70. package/dist/gaia-ops/config/README.md +71 -0
  71. package/dist/gaia-ops/config/cloud/aws.json +134 -0
  72. package/dist/gaia-ops/config/cloud/gcp.json +139 -0
  73. package/dist/gaia-ops/config/context-contracts.json +158 -0
  74. package/dist/gaia-ops/config/crons-schema.md +81 -0
  75. package/dist/gaia-ops/config/git_standards.json +72 -0
  76. package/dist/gaia-ops/config/surface-routing.json +417 -0
  77. package/dist/gaia-ops/config/universal-rules.json +102 -0
  78. package/dist/gaia-ops/hooks/adapters/__init__.py +52 -0
  79. package/dist/gaia-ops/hooks/adapters/base.py +219 -0
  80. package/dist/gaia-ops/hooks/adapters/channel.py +17 -0
  81. package/dist/gaia-ops/hooks/adapters/claude_code.py +1890 -0
  82. package/dist/gaia-ops/hooks/adapters/types.py +194 -0
  83. package/dist/gaia-ops/hooks/adapters/utils.py +25 -0
  84. package/dist/gaia-ops/hooks/hooks.json +192 -0
  85. package/dist/gaia-ops/hooks/modules/__init__.py +15 -0
  86. package/dist/gaia-ops/hooks/modules/agents/__init__.py +29 -0
  87. package/dist/gaia-ops/hooks/modules/agents/contract_validator.py +647 -0
  88. package/dist/gaia-ops/hooks/modules/agents/response_contract.py +496 -0
  89. package/dist/gaia-ops/hooks/modules/agents/skill_injection_verifier.py +120 -0
  90. package/dist/gaia-ops/hooks/modules/agents/state_tracker.py +267 -0
  91. package/dist/gaia-ops/hooks/modules/agents/task_info_builder.py +74 -0
  92. package/dist/gaia-ops/hooks/modules/agents/transcript_analyzer.py +458 -0
  93. package/dist/gaia-ops/hooks/modules/agents/transcript_reader.py +152 -0
  94. package/dist/gaia-ops/hooks/modules/audit/__init__.py +28 -0
  95. package/dist/gaia-ops/hooks/modules/audit/event_detector.py +168 -0
  96. package/dist/gaia-ops/hooks/modules/audit/logger.py +131 -0
  97. package/dist/gaia-ops/hooks/modules/audit/metrics.py +134 -0
  98. package/dist/gaia-ops/hooks/modules/audit/workflow_auditor.py +611 -0
  99. package/dist/gaia-ops/hooks/modules/audit/workflow_recorder.py +296 -0
  100. package/dist/gaia-ops/hooks/modules/context/__init__.py +11 -0
  101. package/dist/gaia-ops/hooks/modules/context/agentic_loop_detector.py +165 -0
  102. package/dist/gaia-ops/hooks/modules/context/anchor_tracker.py +317 -0
  103. package/dist/gaia-ops/hooks/modules/context/compact_context_builder.py +218 -0
  104. package/dist/gaia-ops/hooks/modules/context/context_freshness.py +145 -0
  105. package/dist/gaia-ops/hooks/modules/context/context_injector.py +558 -0
  106. package/dist/gaia-ops/hooks/modules/context/context_writer.py +530 -0
  107. package/dist/gaia-ops/hooks/modules/context/contracts_loader.py +161 -0
  108. package/dist/gaia-ops/hooks/modules/core/__init__.py +40 -0
  109. package/dist/gaia-ops/hooks/modules/core/hook_entry.py +78 -0
  110. package/dist/gaia-ops/hooks/modules/core/paths.py +160 -0
  111. package/dist/gaia-ops/hooks/modules/core/plugin_mode.py +149 -0
  112. package/dist/gaia-ops/hooks/modules/core/plugin_setup.py +577 -0
  113. package/dist/gaia-ops/hooks/modules/core/state.py +179 -0
  114. package/dist/gaia-ops/hooks/modules/core/stdin.py +24 -0
  115. package/dist/gaia-ops/hooks/modules/events/__init__.py +1 -0
  116. package/dist/gaia-ops/hooks/modules/events/event_writer.py +210 -0
  117. package/dist/gaia-ops/hooks/modules/memory/__init__.py +8 -0
  118. package/dist/gaia-ops/hooks/modules/memory/episode_writer.py +216 -0
  119. package/dist/gaia-ops/hooks/modules/orchestrator/__init__.py +1 -0
  120. package/dist/gaia-ops/hooks/modules/orchestrator/delegate_mode.py +122 -0
  121. package/dist/gaia-ops/hooks/modules/scanning/__init__.py +8 -0
  122. package/dist/gaia-ops/hooks/modules/scanning/scan_trigger.py +84 -0
  123. package/dist/gaia-ops/hooks/modules/security/__init__.py +120 -0
  124. package/dist/gaia-ops/hooks/modules/security/approval_cleanup.py +87 -0
  125. package/dist/gaia-ops/hooks/modules/security/approval_constants.py +23 -0
  126. package/dist/gaia-ops/hooks/modules/security/approval_grants.py +1638 -0
  127. package/dist/gaia-ops/hooks/modules/security/approval_messages.py +71 -0
  128. package/dist/gaia-ops/hooks/modules/security/approval_scopes.py +222 -0
  129. package/dist/gaia-ops/hooks/modules/security/blocked_commands.py +595 -0
  130. package/dist/gaia-ops/hooks/modules/security/blocked_message_formatter.py +87 -0
  131. package/dist/gaia-ops/hooks/modules/security/command_semantics.py +181 -0
  132. package/dist/gaia-ops/hooks/modules/security/composition_rules.py +547 -0
  133. package/dist/gaia-ops/hooks/modules/security/flag_classifiers.py +873 -0
  134. package/dist/gaia-ops/hooks/modules/security/gitops_validator.py +179 -0
  135. package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +1131 -0
  136. package/dist/gaia-ops/hooks/modules/security/network_hosts.py +481 -0
  137. package/dist/gaia-ops/hooks/modules/security/prompt_validator.py +40 -0
  138. package/dist/gaia-ops/hooks/modules/security/shell_unwrapper.py +165 -0
  139. package/dist/gaia-ops/hooks/modules/security/tiers.py +196 -0
  140. package/dist/gaia-ops/hooks/modules/session/__init__.py +10 -0
  141. package/dist/gaia-ops/hooks/modules/session/pending_scanner.py +174 -0
  142. package/dist/gaia-ops/hooks/modules/session/session_context_writer.py +100 -0
  143. package/dist/gaia-ops/hooks/modules/session/session_event_injector.py +160 -0
  144. package/dist/gaia-ops/hooks/modules/session/session_manager.py +31 -0
  145. package/dist/gaia-ops/hooks/modules/session/session_registry.py +333 -0
  146. package/dist/gaia-ops/hooks/modules/tools/__init__.py +29 -0
  147. package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +1008 -0
  148. package/dist/gaia-ops/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  149. package/dist/gaia-ops/hooks/modules/tools/hook_response.py +55 -0
  150. package/dist/gaia-ops/hooks/modules/tools/shell_parser.py +227 -0
  151. package/dist/gaia-ops/hooks/modules/tools/stage_decomposer.py +315 -0
  152. package/dist/gaia-ops/hooks/modules/tools/task_validator.py +294 -0
  153. package/dist/gaia-ops/hooks/modules/validation/__init__.py +23 -0
  154. package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +380 -0
  155. package/dist/gaia-ops/hooks/post_compact.py +43 -0
  156. package/dist/gaia-ops/hooks/post_tool_use.py +54 -0
  157. package/dist/gaia-ops/hooks/pre_compact.py +60 -0
  158. package/dist/gaia-ops/hooks/pre_tool_use.py +413 -0
  159. package/dist/gaia-ops/hooks/session_end_hook.py +77 -0
  160. package/dist/gaia-ops/hooks/session_start.py +81 -0
  161. package/dist/gaia-ops/hooks/stop_hook.py +70 -0
  162. package/dist/gaia-ops/hooks/subagent_start.py +71 -0
  163. package/dist/gaia-ops/hooks/subagent_stop.py +295 -0
  164. package/dist/gaia-ops/hooks/task_completed.py +70 -0
  165. package/dist/gaia-ops/hooks/user_prompt_submit.py +246 -0
  166. package/dist/gaia-ops/settings.json +72 -0
  167. package/dist/gaia-ops/skills/README.md +158 -0
  168. package/dist/gaia-ops/skills/agent-creation/SKILL.md +87 -0
  169. package/dist/gaia-ops/skills/agent-creation/examples.md +170 -0
  170. package/dist/gaia-ops/skills/agent-creation/reference.md +191 -0
  171. package/dist/gaia-ops/skills/agent-protocol/SKILL.md +93 -0
  172. package/dist/gaia-ops/skills/agent-protocol/examples.md +223 -0
  173. package/dist/gaia-ops/skills/agent-response/SKILL.md +69 -0
  174. package/dist/gaia-ops/skills/agentic-loop/SKILL.md +80 -0
  175. package/dist/gaia-ops/skills/agentic-loop/reference.md +378 -0
  176. package/dist/gaia-ops/skills/blog-writing/SKILL.md +98 -0
  177. package/dist/gaia-ops/skills/blog-writing/reference.md +130 -0
  178. package/dist/gaia-ops/skills/brief-spec/SKILL.md +185 -0
  179. package/dist/gaia-ops/skills/command-execution/SKILL.md +64 -0
  180. package/dist/gaia-ops/skills/command-execution/reference.md +83 -0
  181. package/dist/gaia-ops/skills/context-updater/SKILL.md +87 -0
  182. package/dist/gaia-ops/skills/context-updater/examples.md +71 -0
  183. package/dist/gaia-ops/skills/developer-patterns/SKILL.md +50 -0
  184. package/dist/gaia-ops/skills/developer-patterns/reference.md +112 -0
  185. package/dist/gaia-ops/skills/execution/SKILL.md +99 -0
  186. package/dist/gaia-ops/skills/fast-queries/SKILL.md +43 -0
  187. package/dist/gaia-ops/skills/gaia-compact/SKILL.md +74 -0
  188. package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +108 -0
  189. package/dist/gaia-ops/skills/gaia-patterns/reference.md +395 -0
  190. package/dist/gaia-ops/skills/gaia-planner/SKILL.md +37 -0
  191. package/dist/gaia-ops/skills/gaia-planner/reference.md +107 -0
  192. package/dist/gaia-ops/skills/gaia-release/SKILL.md +85 -0
  193. package/dist/gaia-ops/skills/gaia-release/reference.md +92 -0
  194. package/dist/gaia-ops/skills/gaia-self-check/SKILL.md +114 -0
  195. package/dist/gaia-ops/skills/gaia-self-check/reference.md +453 -0
  196. package/dist/gaia-ops/skills/gaia-verify/SKILL.md +77 -0
  197. package/dist/gaia-ops/skills/gaia-verify/reference.md +80 -0
  198. package/dist/gaia-ops/skills/git-conventions/SKILL.md +47 -0
  199. package/dist/gaia-ops/skills/gitops-patterns/SKILL.md +60 -0
  200. package/dist/gaia-ops/skills/gitops-patterns/reference.md +183 -0
  201. package/dist/gaia-ops/skills/gmail-policy/SKILL.md +200 -0
  202. package/dist/gaia-ops/skills/gmail-policy/reference.md +150 -0
  203. package/dist/gaia-ops/skills/gmail-triage/SKILL.md +100 -0
  204. package/dist/gaia-ops/skills/gws-setup/SKILL.md +99 -0
  205. package/dist/gaia-ops/skills/gws-setup/reference.md +73 -0
  206. package/dist/gaia-ops/skills/investigation/SKILL.md +100 -0
  207. package/dist/gaia-ops/skills/memory-curation/SKILL.md +83 -0
  208. package/dist/gaia-ops/skills/memory-search/SKILL.md +88 -0
  209. package/dist/gaia-ops/skills/orchestrator-approval/SKILL.md +160 -0
  210. package/dist/gaia-ops/skills/orchestrator-approval/reference.md +174 -0
  211. package/dist/gaia-ops/skills/pending-approvals/SKILL.md +72 -0
  212. package/dist/gaia-ops/skills/pending-approvals/reference.md +214 -0
  213. package/dist/gaia-ops/skills/readme-writing/SKILL.md +71 -0
  214. package/dist/gaia-ops/skills/readme-writing/reference.md +188 -0
  215. package/dist/gaia-ops/skills/reference.md +135 -0
  216. package/dist/gaia-ops/skills/request-approval/SKILL.md +140 -0
  217. package/dist/gaia-ops/skills/request-approval/examples.md +140 -0
  218. package/dist/gaia-ops/skills/request-approval/reference.md +57 -0
  219. package/dist/gaia-ops/skills/schedule-task/SKILL.md +64 -0
  220. package/dist/gaia-ops/skills/schedule-task/reference.md +233 -0
  221. package/dist/gaia-ops/skills/security-tiers/SKILL.md +141 -0
  222. package/dist/gaia-ops/skills/security-tiers/destructive-commands-reference.md +623 -0
  223. package/dist/gaia-ops/skills/security-tiers/reference.md +39 -0
  224. package/dist/gaia-ops/skills/session-reflection/SKILL.md +69 -0
  225. package/dist/gaia-ops/skills/skill-creation/SKILL.md +92 -0
  226. package/dist/gaia-ops/skills/skill-creation/reference.md +29 -0
  227. package/dist/gaia-ops/skills/terraform-patterns/SKILL.md +89 -0
  228. package/dist/gaia-ops/skills/terraform-patterns/reference.md +93 -0
  229. package/dist/gaia-ops/tools/__init__.py +9 -0
  230. package/dist/gaia-ops/tools/agentic-loop/decide-status.py +210 -0
  231. package/dist/gaia-ops/tools/agentic-loop/parse-metric.py +106 -0
  232. package/dist/gaia-ops/tools/agentic-loop/record-iteration.py +221 -0
  233. package/dist/gaia-ops/tools/context/README.md +132 -0
  234. package/dist/gaia-ops/tools/context/__init__.py +42 -0
  235. package/dist/gaia-ops/tools/context/_paths.py +20 -0
  236. package/dist/gaia-ops/tools/context/context_provider.py +721 -0
  237. package/dist/gaia-ops/tools/context/context_section_reader.py +342 -0
  238. package/dist/gaia-ops/tools/context/deep_merge.py +159 -0
  239. package/dist/gaia-ops/tools/context/pending_updates.py +760 -0
  240. package/dist/gaia-ops/tools/context/surface_router.py +278 -0
  241. package/dist/gaia-ops/tools/fast-queries/README.md +65 -0
  242. package/dist/gaia-ops/tools/fast-queries/__init__.py +30 -0
  243. package/dist/gaia-ops/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
  244. package/dist/gaia-ops/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
  245. package/dist/gaia-ops/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
  246. package/dist/gaia-ops/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
  247. package/dist/gaia-ops/tools/fast-queries/run_triage.sh +59 -0
  248. package/dist/gaia-ops/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
  249. package/dist/gaia-ops/tools/gaia_simulator/__init__.py +33 -0
  250. package/dist/gaia-ops/tools/gaia_simulator/cli.py +354 -0
  251. package/dist/gaia-ops/tools/gaia_simulator/extractor.py +457 -0
  252. package/dist/gaia-ops/tools/gaia_simulator/reporter.py +258 -0
  253. package/dist/gaia-ops/tools/gaia_simulator/routing_simulator.py +334 -0
  254. package/dist/gaia-ops/tools/gaia_simulator/runner.py +539 -0
  255. package/dist/gaia-ops/tools/gaia_simulator/skills_mapper.py +264 -0
  256. package/dist/gaia-ops/tools/memory/README.md +0 -0
  257. package/dist/gaia-ops/tools/memory/__init__.py +20 -0
  258. package/dist/gaia-ops/tools/memory/backfill_fts5.py +107 -0
  259. package/dist/gaia-ops/tools/memory/conflict_detector.py +295 -0
  260. package/dist/gaia-ops/tools/memory/episodic.py +1210 -0
  261. package/dist/gaia-ops/tools/memory/git_invalidator.py +262 -0
  262. package/dist/gaia-ops/tools/memory/paths.py +102 -0
  263. package/dist/gaia-ops/tools/memory/scoring.py +193 -0
  264. package/dist/gaia-ops/tools/memory/search_store.py +375 -0
  265. package/dist/gaia-ops/tools/persist_transcript_analysis.py +85 -0
  266. package/dist/gaia-ops/tools/review/__init__.py +1 -0
  267. package/dist/gaia-ops/tools/review/review_engine.py +157 -0
  268. package/dist/gaia-ops/tools/scan/__init__.py +35 -0
  269. package/dist/gaia-ops/tools/scan/config.py +247 -0
  270. package/dist/gaia-ops/tools/scan/merge.py +212 -0
  271. package/dist/gaia-ops/tools/scan/orchestrator.py +549 -0
  272. package/dist/gaia-ops/tools/scan/registry.py +127 -0
  273. package/dist/gaia-ops/tools/scan/scanners/__init__.py +18 -0
  274. package/dist/gaia-ops/tools/scan/scanners/base.py +137 -0
  275. package/dist/gaia-ops/tools/scan/scanners/environment.py +349 -0
  276. package/dist/gaia-ops/tools/scan/scanners/git.py +570 -0
  277. package/dist/gaia-ops/tools/scan/scanners/infrastructure.py +875 -0
  278. package/dist/gaia-ops/tools/scan/scanners/orchestration.py +600 -0
  279. package/dist/gaia-ops/tools/scan/scanners/stack.py +1085 -0
  280. package/dist/gaia-ops/tools/scan/scanners/tools.py +260 -0
  281. package/dist/gaia-ops/tools/scan/setup.py +686 -0
  282. package/dist/gaia-ops/tools/scan/tests/__init__.py +1 -0
  283. package/dist/gaia-ops/tools/scan/tests/conftest.py +796 -0
  284. package/dist/gaia-ops/tools/scan/tests/test_environment.py +323 -0
  285. package/dist/gaia-ops/tools/scan/tests/test_git.py +419 -0
  286. package/dist/gaia-ops/tools/scan/tests/test_infrastructure.py +382 -0
  287. package/dist/gaia-ops/tools/scan/tests/test_integration.py +920 -0
  288. package/dist/gaia-ops/tools/scan/tests/test_merge.py +269 -0
  289. package/dist/gaia-ops/tools/scan/tests/test_orchestration.py +304 -0
  290. package/dist/gaia-ops/tools/scan/tests/test_stack.py +604 -0
  291. package/dist/gaia-ops/tools/scan/tests/test_tools.py +349 -0
  292. package/dist/gaia-ops/tools/scan/ui.py +624 -0
  293. package/dist/gaia-ops/tools/scan/verify.py +270 -0
  294. package/dist/gaia-ops/tools/scan/walk.py +118 -0
  295. package/dist/gaia-ops/tools/scan/workspace.py +85 -0
  296. package/dist/gaia-ops/tools/validation/README.md +244 -0
  297. package/dist/gaia-ops/tools/validation/__init__.py +17 -0
  298. package/dist/gaia-ops/tools/validation/approval_gate.py +321 -0
  299. package/dist/gaia-ops/tools/validation/validate_skills.py +189 -0
  300. package/dist/gaia-security/.claude-plugin/plugin.json +24 -0
  301. package/dist/gaia-security/README.md +90 -0
  302. package/dist/gaia-security/config/universal-rules.json +102 -0
  303. package/dist/gaia-security/hooks/adapters/__init__.py +52 -0
  304. package/dist/gaia-security/hooks/adapters/base.py +219 -0
  305. package/dist/gaia-security/hooks/adapters/channel.py +17 -0
  306. package/dist/gaia-security/hooks/adapters/claude_code.py +1890 -0
  307. package/dist/gaia-security/hooks/adapters/types.py +194 -0
  308. package/dist/gaia-security/hooks/adapters/utils.py +25 -0
  309. package/dist/gaia-security/hooks/hooks.json +113 -0
  310. package/dist/gaia-security/hooks/modules/__init__.py +15 -0
  311. package/dist/gaia-security/hooks/modules/agents/__init__.py +29 -0
  312. package/dist/gaia-security/hooks/modules/agents/contract_validator.py +647 -0
  313. package/dist/gaia-security/hooks/modules/agents/response_contract.py +496 -0
  314. package/dist/gaia-security/hooks/modules/agents/skill_injection_verifier.py +120 -0
  315. package/dist/gaia-security/hooks/modules/agents/state_tracker.py +267 -0
  316. package/dist/gaia-security/hooks/modules/agents/task_info_builder.py +74 -0
  317. package/dist/gaia-security/hooks/modules/agents/transcript_analyzer.py +458 -0
  318. package/dist/gaia-security/hooks/modules/agents/transcript_reader.py +152 -0
  319. package/dist/gaia-security/hooks/modules/audit/__init__.py +28 -0
  320. package/dist/gaia-security/hooks/modules/audit/event_detector.py +168 -0
  321. package/dist/gaia-security/hooks/modules/audit/logger.py +131 -0
  322. package/dist/gaia-security/hooks/modules/audit/metrics.py +134 -0
  323. package/dist/gaia-security/hooks/modules/audit/workflow_auditor.py +611 -0
  324. package/dist/gaia-security/hooks/modules/audit/workflow_recorder.py +296 -0
  325. package/dist/gaia-security/hooks/modules/context/__init__.py +11 -0
  326. package/dist/gaia-security/hooks/modules/context/agentic_loop_detector.py +165 -0
  327. package/dist/gaia-security/hooks/modules/context/anchor_tracker.py +317 -0
  328. package/dist/gaia-security/hooks/modules/context/compact_context_builder.py +218 -0
  329. package/dist/gaia-security/hooks/modules/context/context_freshness.py +145 -0
  330. package/dist/gaia-security/hooks/modules/context/context_injector.py +558 -0
  331. package/dist/gaia-security/hooks/modules/context/context_writer.py +530 -0
  332. package/dist/gaia-security/hooks/modules/context/contracts_loader.py +161 -0
  333. package/dist/gaia-security/hooks/modules/core/__init__.py +40 -0
  334. package/dist/gaia-security/hooks/modules/core/hook_entry.py +78 -0
  335. package/dist/gaia-security/hooks/modules/core/paths.py +160 -0
  336. package/dist/gaia-security/hooks/modules/core/plugin_mode.py +149 -0
  337. package/dist/gaia-security/hooks/modules/core/plugin_setup.py +577 -0
  338. package/dist/gaia-security/hooks/modules/core/state.py +179 -0
  339. package/dist/gaia-security/hooks/modules/core/stdin.py +24 -0
  340. package/dist/gaia-security/hooks/modules/events/__init__.py +1 -0
  341. package/dist/gaia-security/hooks/modules/events/event_writer.py +210 -0
  342. package/dist/gaia-security/hooks/modules/memory/__init__.py +8 -0
  343. package/dist/gaia-security/hooks/modules/memory/episode_writer.py +216 -0
  344. package/dist/gaia-security/hooks/modules/orchestrator/__init__.py +1 -0
  345. package/dist/gaia-security/hooks/modules/orchestrator/delegate_mode.py +122 -0
  346. package/dist/gaia-security/hooks/modules/scanning/__init__.py +8 -0
  347. package/dist/gaia-security/hooks/modules/scanning/scan_trigger.py +84 -0
  348. package/dist/gaia-security/hooks/modules/security/__init__.py +120 -0
  349. package/dist/gaia-security/hooks/modules/security/approval_cleanup.py +87 -0
  350. package/dist/gaia-security/hooks/modules/security/approval_constants.py +23 -0
  351. package/dist/gaia-security/hooks/modules/security/approval_grants.py +1638 -0
  352. package/dist/gaia-security/hooks/modules/security/approval_messages.py +71 -0
  353. package/dist/gaia-security/hooks/modules/security/approval_scopes.py +222 -0
  354. package/dist/gaia-security/hooks/modules/security/blocked_commands.py +595 -0
  355. package/dist/gaia-security/hooks/modules/security/blocked_message_formatter.py +87 -0
  356. package/dist/gaia-security/hooks/modules/security/command_semantics.py +181 -0
  357. package/dist/gaia-security/hooks/modules/security/composition_rules.py +547 -0
  358. package/dist/gaia-security/hooks/modules/security/flag_classifiers.py +873 -0
  359. package/dist/gaia-security/hooks/modules/security/gitops_validator.py +179 -0
  360. package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +1131 -0
  361. package/dist/gaia-security/hooks/modules/security/network_hosts.py +481 -0
  362. package/dist/gaia-security/hooks/modules/security/prompt_validator.py +40 -0
  363. package/dist/gaia-security/hooks/modules/security/shell_unwrapper.py +165 -0
  364. package/dist/gaia-security/hooks/modules/security/tiers.py +196 -0
  365. package/dist/gaia-security/hooks/modules/session/__init__.py +10 -0
  366. package/dist/gaia-security/hooks/modules/session/pending_scanner.py +174 -0
  367. package/dist/gaia-security/hooks/modules/session/session_context_writer.py +100 -0
  368. package/dist/gaia-security/hooks/modules/session/session_event_injector.py +160 -0
  369. package/dist/gaia-security/hooks/modules/session/session_manager.py +31 -0
  370. package/dist/gaia-security/hooks/modules/session/session_registry.py +333 -0
  371. package/dist/gaia-security/hooks/modules/tools/__init__.py +29 -0
  372. package/dist/gaia-security/hooks/modules/tools/bash_validator.py +1008 -0
  373. package/dist/gaia-security/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  374. package/dist/gaia-security/hooks/modules/tools/hook_response.py +55 -0
  375. package/dist/gaia-security/hooks/modules/tools/shell_parser.py +227 -0
  376. package/dist/gaia-security/hooks/modules/tools/stage_decomposer.py +315 -0
  377. package/dist/gaia-security/hooks/modules/tools/task_validator.py +294 -0
  378. package/dist/gaia-security/hooks/modules/validation/__init__.py +23 -0
  379. package/dist/gaia-security/hooks/modules/validation/commit_validator.py +380 -0
  380. package/dist/gaia-security/hooks/post_tool_use.py +54 -0
  381. package/dist/gaia-security/hooks/pre_tool_use.py +413 -0
  382. package/dist/gaia-security/hooks/session_end_hook.py +77 -0
  383. package/dist/gaia-security/hooks/session_start.py +81 -0
  384. package/dist/gaia-security/hooks/stop_hook.py +70 -0
  385. package/dist/gaia-security/hooks/user_prompt_submit.py +246 -0
  386. package/dist/gaia-security/settings.json +58 -0
  387. package/git-hooks/commit-msg +41 -0
  388. package/hooks/README.md +100 -0
  389. package/hooks/adapters/__init__.py +52 -0
  390. package/hooks/adapters/base.py +219 -0
  391. package/hooks/adapters/channel.py +17 -0
  392. package/hooks/adapters/claude_code.py +1890 -0
  393. package/hooks/adapters/types.py +194 -0
  394. package/hooks/adapters/utils.py +25 -0
  395. package/hooks/elicitation_result.py +179 -0
  396. package/hooks/hooks.json +84 -0
  397. package/hooks/modules/README.md +189 -0
  398. package/hooks/modules/__init__.py +15 -0
  399. package/hooks/modules/agents/__init__.py +29 -0
  400. package/hooks/modules/agents/contract_validator.py +647 -0
  401. package/hooks/modules/agents/response_contract.py +496 -0
  402. package/hooks/modules/agents/skill_injection_verifier.py +120 -0
  403. package/hooks/modules/agents/state_tracker.py +267 -0
  404. package/hooks/modules/agents/task_info_builder.py +74 -0
  405. package/hooks/modules/agents/transcript_analyzer.py +458 -0
  406. package/hooks/modules/agents/transcript_reader.py +152 -0
  407. package/hooks/modules/audit/__init__.py +28 -0
  408. package/hooks/modules/audit/event_detector.py +168 -0
  409. package/hooks/modules/audit/logger.py +131 -0
  410. package/hooks/modules/audit/metrics.py +134 -0
  411. package/hooks/modules/audit/workflow_auditor.py +611 -0
  412. package/hooks/modules/audit/workflow_recorder.py +296 -0
  413. package/hooks/modules/context/__init__.py +11 -0
  414. package/hooks/modules/context/agentic_loop_detector.py +165 -0
  415. package/hooks/modules/context/anchor_tracker.py +317 -0
  416. package/hooks/modules/context/compact_context_builder.py +218 -0
  417. package/hooks/modules/context/context_freshness.py +145 -0
  418. package/hooks/modules/context/context_injector.py +558 -0
  419. package/hooks/modules/context/context_writer.py +530 -0
  420. package/hooks/modules/context/contracts_loader.py +161 -0
  421. package/hooks/modules/core/__init__.py +40 -0
  422. package/hooks/modules/core/hook_entry.py +78 -0
  423. package/hooks/modules/core/paths.py +160 -0
  424. package/hooks/modules/core/plugin_mode.py +149 -0
  425. package/hooks/modules/core/plugin_setup.py +577 -0
  426. package/hooks/modules/core/state.py +179 -0
  427. package/hooks/modules/core/stdin.py +24 -0
  428. package/hooks/modules/events/__init__.py +1 -0
  429. package/hooks/modules/events/event_writer.py +210 -0
  430. package/hooks/modules/evidence/__init__.py +34 -0
  431. package/hooks/modules/evidence/assertions.py +137 -0
  432. package/hooks/modules/evidence/index_writer.py +57 -0
  433. package/hooks/modules/evidence/loader.py +126 -0
  434. package/hooks/modules/evidence/runner.py +241 -0
  435. package/hooks/modules/memory/__init__.py +8 -0
  436. package/hooks/modules/memory/episode_writer.py +216 -0
  437. package/hooks/modules/orchestrator/__init__.py +1 -0
  438. package/hooks/modules/orchestrator/delegate_mode.py +122 -0
  439. package/hooks/modules/scanning/__init__.py +8 -0
  440. package/hooks/modules/scanning/scan_trigger.py +84 -0
  441. package/hooks/modules/security/__init__.py +120 -0
  442. package/hooks/modules/security/approval_cleanup.py +87 -0
  443. package/hooks/modules/security/approval_constants.py +23 -0
  444. package/hooks/modules/security/approval_grants.py +1638 -0
  445. package/hooks/modules/security/approval_messages.py +71 -0
  446. package/hooks/modules/security/approval_scopes.py +222 -0
  447. package/hooks/modules/security/blocked_commands.py +595 -0
  448. package/hooks/modules/security/blocked_message_formatter.py +87 -0
  449. package/hooks/modules/security/command_semantics.py +181 -0
  450. package/hooks/modules/security/composition_rules.py +547 -0
  451. package/hooks/modules/security/flag_classifiers.py +873 -0
  452. package/hooks/modules/security/gitops_validator.py +179 -0
  453. package/hooks/modules/security/mutative_verbs.py +1131 -0
  454. package/hooks/modules/security/network_hosts.py +481 -0
  455. package/hooks/modules/security/prompt_validator.py +40 -0
  456. package/hooks/modules/security/shell_unwrapper.py +165 -0
  457. package/hooks/modules/security/tiers.py +196 -0
  458. package/hooks/modules/session/__init__.py +10 -0
  459. package/hooks/modules/session/pending_scanner.py +174 -0
  460. package/hooks/modules/session/session_context_writer.py +100 -0
  461. package/hooks/modules/session/session_event_injector.py +160 -0
  462. package/hooks/modules/session/session_manager.py +31 -0
  463. package/hooks/modules/session/session_registry.py +333 -0
  464. package/hooks/modules/tools/__init__.py +29 -0
  465. package/hooks/modules/tools/bash_validator.py +1008 -0
  466. package/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  467. package/hooks/modules/tools/hook_response.py +55 -0
  468. package/hooks/modules/tools/shell_parser.py +227 -0
  469. package/hooks/modules/tools/stage_decomposer.py +315 -0
  470. package/hooks/modules/tools/task_validator.py +294 -0
  471. package/hooks/modules/validation/__init__.py +23 -0
  472. package/hooks/modules/validation/commit_validator.py +380 -0
  473. package/hooks/post_compact.py +43 -0
  474. package/hooks/post_tool_use.py +54 -0
  475. package/hooks/pre_compact.py +60 -0
  476. package/hooks/pre_tool_use.py +413 -0
  477. package/hooks/session_end_hook.py +77 -0
  478. package/hooks/session_start.py +81 -0
  479. package/hooks/stop_hook.py +70 -0
  480. package/hooks/subagent_start.py +71 -0
  481. package/hooks/subagent_stop.py +295 -0
  482. package/hooks/task_completed.py +70 -0
  483. package/hooks/user_prompt_submit.py +246 -0
  484. package/index.js +83 -0
  485. package/package.json +103 -0
  486. package/pyproject.toml +32 -0
  487. package/skills/README.md +158 -0
  488. package/skills/agent-creation/SKILL.md +87 -0
  489. package/skills/agent-creation/examples.md +170 -0
  490. package/skills/agent-creation/reference.md +191 -0
  491. package/skills/agent-protocol/SKILL.md +93 -0
  492. package/skills/agent-protocol/examples.md +223 -0
  493. package/skills/agent-response/SKILL.md +69 -0
  494. package/skills/agentic-loop/SKILL.md +80 -0
  495. package/skills/agentic-loop/reference.md +378 -0
  496. package/skills/blog-writing/SKILL.md +98 -0
  497. package/skills/blog-writing/reference.md +130 -0
  498. package/skills/brief-spec/SKILL.md +185 -0
  499. package/skills/command-execution/SKILL.md +64 -0
  500. package/skills/command-execution/reference.md +83 -0
  501. package/skills/context-updater/SKILL.md +87 -0
  502. package/skills/context-updater/examples.md +71 -0
  503. package/skills/developer-patterns/SKILL.md +50 -0
  504. package/skills/developer-patterns/reference.md +112 -0
  505. package/skills/execution/SKILL.md +99 -0
  506. package/skills/fast-queries/SKILL.md +43 -0
  507. package/skills/gaia-compact/SKILL.md +74 -0
  508. package/skills/gaia-patterns/SKILL.md +108 -0
  509. package/skills/gaia-patterns/reference.md +395 -0
  510. package/skills/gaia-planner/SKILL.md +37 -0
  511. package/skills/gaia-planner/reference.md +107 -0
  512. package/skills/gaia-release/SKILL.md +85 -0
  513. package/skills/gaia-release/reference.md +92 -0
  514. package/skills/gaia-self-check/SKILL.md +114 -0
  515. package/skills/gaia-self-check/reference.md +453 -0
  516. package/skills/gaia-verify/SKILL.md +77 -0
  517. package/skills/gaia-verify/reference.md +80 -0
  518. package/skills/git-conventions/SKILL.md +47 -0
  519. package/skills/gitops-patterns/SKILL.md +60 -0
  520. package/skills/gitops-patterns/reference.md +183 -0
  521. package/skills/gmail-policy/SKILL.md +200 -0
  522. package/skills/gmail-policy/reference.md +150 -0
  523. package/skills/gmail-triage/SKILL.md +100 -0
  524. package/skills/gws-setup/SKILL.md +99 -0
  525. package/skills/gws-setup/reference.md +73 -0
  526. package/skills/investigation/SKILL.md +100 -0
  527. package/skills/memory-curation/SKILL.md +83 -0
  528. package/skills/memory-search/SKILL.md +88 -0
  529. package/skills/orchestrator-approval/SKILL.md +160 -0
  530. package/skills/orchestrator-approval/reference.md +174 -0
  531. package/skills/pending-approvals/SKILL.md +72 -0
  532. package/skills/pending-approvals/reference.md +214 -0
  533. package/skills/readme-writing/SKILL.md +71 -0
  534. package/skills/readme-writing/reference.md +188 -0
  535. package/skills/reference.md +135 -0
  536. package/skills/request-approval/SKILL.md +140 -0
  537. package/skills/request-approval/examples.md +140 -0
  538. package/skills/request-approval/reference.md +57 -0
  539. package/skills/schedule-task/SKILL.md +64 -0
  540. package/skills/schedule-task/reference.md +233 -0
  541. package/skills/security-tiers/SKILL.md +141 -0
  542. package/skills/security-tiers/destructive-commands-reference.md +623 -0
  543. package/skills/security-tiers/reference.md +39 -0
  544. package/skills/session-reflection/SKILL.md +69 -0
  545. package/skills/skill-creation/SKILL.md +92 -0
  546. package/skills/skill-creation/reference.md +29 -0
  547. package/skills/terraform-patterns/SKILL.md +89 -0
  548. package/skills/terraform-patterns/reference.md +93 -0
  549. package/templates/README.md +69 -0
  550. package/templates/managed-settings.template.json +43 -0
  551. package/tools/__init__.py +9 -0
  552. package/tools/agentic-loop/decide-status.py +210 -0
  553. package/tools/agentic-loop/parse-metric.py +106 -0
  554. package/tools/agentic-loop/record-iteration.py +221 -0
  555. package/tools/context/README.md +132 -0
  556. package/tools/context/__init__.py +42 -0
  557. package/tools/context/_paths.py +20 -0
  558. package/tools/context/context_provider.py +721 -0
  559. package/tools/context/context_section_reader.py +342 -0
  560. package/tools/context/deep_merge.py +159 -0
  561. package/tools/context/pending_updates.py +760 -0
  562. package/tools/context/surface_router.py +278 -0
  563. package/tools/fast-queries/README.md +65 -0
  564. package/tools/fast-queries/__init__.py +30 -0
  565. package/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
  566. package/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
  567. package/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
  568. package/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
  569. package/tools/fast-queries/run_triage.sh +59 -0
  570. package/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
  571. package/tools/gaia_simulator/__init__.py +33 -0
  572. package/tools/gaia_simulator/cli.py +354 -0
  573. package/tools/gaia_simulator/extractor.py +457 -0
  574. package/tools/gaia_simulator/reporter.py +258 -0
  575. package/tools/gaia_simulator/routing_simulator.py +334 -0
  576. package/tools/gaia_simulator/runner.py +539 -0
  577. package/tools/gaia_simulator/skills_mapper.py +264 -0
  578. package/tools/memory/README.md +0 -0
  579. package/tools/memory/__init__.py +20 -0
  580. package/tools/memory/backfill_fts5.py +107 -0
  581. package/tools/memory/conflict_detector.py +295 -0
  582. package/tools/memory/episodic.py +1210 -0
  583. package/tools/memory/git_invalidator.py +262 -0
  584. package/tools/memory/paths.py +102 -0
  585. package/tools/memory/scoring.py +193 -0
  586. package/tools/memory/search_store.py +375 -0
  587. package/tools/persist_transcript_analysis.py +85 -0
  588. package/tools/review/__init__.py +1 -0
  589. package/tools/review/review_engine.py +157 -0
  590. package/tools/scan/__init__.py +35 -0
  591. package/tools/scan/config.py +247 -0
  592. package/tools/scan/merge.py +212 -0
  593. package/tools/scan/orchestrator.py +549 -0
  594. package/tools/scan/registry.py +127 -0
  595. package/tools/scan/scanners/__init__.py +18 -0
  596. package/tools/scan/scanners/base.py +137 -0
  597. package/tools/scan/scanners/environment.py +349 -0
  598. package/tools/scan/scanners/git.py +570 -0
  599. package/tools/scan/scanners/infrastructure.py +875 -0
  600. package/tools/scan/scanners/orchestration.py +600 -0
  601. package/tools/scan/scanners/stack.py +1085 -0
  602. package/tools/scan/scanners/tools.py +260 -0
  603. package/tools/scan/setup.py +686 -0
  604. package/tools/scan/tests/__init__.py +1 -0
  605. package/tools/scan/tests/conftest.py +796 -0
  606. package/tools/scan/tests/test_environment.py +323 -0
  607. package/tools/scan/tests/test_git.py +419 -0
  608. package/tools/scan/tests/test_infrastructure.py +382 -0
  609. package/tools/scan/tests/test_integration.py +920 -0
  610. package/tools/scan/tests/test_merge.py +269 -0
  611. package/tools/scan/tests/test_orchestration.py +304 -0
  612. package/tools/scan/tests/test_stack.py +604 -0
  613. package/tools/scan/tests/test_tools.py +349 -0
  614. package/tools/scan/ui.py +624 -0
  615. package/tools/scan/verify.py +270 -0
  616. package/tools/scan/walk.py +118 -0
  617. package/tools/scan/workspace.py +85 -0
  618. package/tools/validation/README.md +244 -0
  619. package/tools/validation/__init__.py +17 -0
  620. package/tools/validation/approval_gate.py +321 -0
  621. package/tools/validation/validate_skills.py +189 -0
@@ -0,0 +1,577 @@
1
+ """First-time plugin setup for SessionStart hook.
2
+
3
+ Detects first run via marker file in CLAUDE_PLUGIN_DATA.
4
+ On first run, merges gaia permissions into .claude/settings.local.json.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ import logging
10
+ from datetime import datetime
11
+ from pathlib import Path
12
+
13
+ from .paths import get_plugin_data_dir
14
+ from .plugin_mode import get_plugin_mode
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ MARKER_FILE = ".plugin-initialized"
19
+
20
+ # ---------------------------------------------------------------------------
21
+ # Deny list — shared across all modes. Aligned with blocked_commands.py
22
+ # (hook-level enforcement) for dual-barrier security. These rules are
23
+ # merged into settings.local.json so Claude Code's native permission system
24
+ # blocks the commands BEFORE they even reach the hook layer.
25
+ # ---------------------------------------------------------------------------
26
+ _DENY_RULES = [
27
+ # AWS — networking / data infrastructure (irreversible)
28
+ "Bash(aws ec2 delete-vpc:*)",
29
+ "Bash(aws ec2 delete-subnet:*)",
30
+ "Bash(aws ec2 delete-internet-gateway:*)",
31
+ "Bash(aws ec2 delete-route-table:*)",
32
+ "Bash(aws ec2 delete-route:*)",
33
+ "Bash(aws ec2 terminate-instances:*)",
34
+ "Bash(aws rds delete-db-instance:*)",
35
+ "Bash(aws rds delete-db-cluster:*)",
36
+ "Bash(aws dynamodb delete-table:*)",
37
+ "Bash(aws s3 rb:*)",
38
+ "Bash(aws s3api delete-bucket:*)",
39
+ "Bash(aws elasticache delete-cache-cluster:*)",
40
+ "Bash(aws elasticache delete-replication-group:*)",
41
+ "Bash(aws eks delete-cluster:*)",
42
+ # AWS — KMS / Organizations / Route53
43
+ "Bash(aws kms schedule-key-deletion:*)",
44
+ "Bash(aws organizations delete-organization:*)",
45
+ "Bash(aws route53 delete-hosted-zone:*)",
46
+ # AWS — IAM (mutative but denied at settings level too)
47
+ "Bash(aws iam delete-user:*)",
48
+ "Bash(aws iam delete-role:*)",
49
+ "Bash(aws iam delete-access-key:*)",
50
+ "Bash(aws iam delete-group:*)",
51
+ "Bash(aws iam delete-instance-profile:*)",
52
+ "Bash(aws iam delete-policy:*)",
53
+ "Bash(aws iam delete-role-policy:*)",
54
+ "Bash(aws iam delete-user-policy:*)",
55
+ "Bash(aws iam delete-group-policy:*)",
56
+ "Bash(aws iam detach-user-policy:*)",
57
+ "Bash(aws iam detach-role-policy:*)",
58
+ "Bash(aws iam detach-group-policy:*)",
59
+ "Bash(aws iam remove-user-from-group:*)",
60
+ # AWS — other destructive
61
+ "Bash(aws backup delete:*::*)",
62
+ "Bash(aws cloudformation delete-stack:*)",
63
+ "Bash(aws dynamodb delete-item:*)",
64
+ "Bash(aws ec2 delete-key-pair:*)",
65
+ "Bash(aws ec2 delete-snapshot:*)",
66
+ "Bash(aws ec2 delete-volume:*)",
67
+ "Bash(aws ec2 delete-security-group:*)",
68
+ "Bash(aws ec2 delete-network-interface:*)",
69
+ "Bash(aws lambda delete-function:*)",
70
+ "Bash(aws rds delete-db-cluster-parameter-group:*)",
71
+ "Bash(aws rds delete-db-parameter-group:*)",
72
+ "Bash(aws s3api delete-objects:*)",
73
+ "Bash(aws sns delete-topic:*)",
74
+ "Bash(aws sqs delete-queue:*)",
75
+ "Bash(aws eks delete-nodegroup:*)",
76
+ "Bash(aws eks delete-addon:*)",
77
+ # Azure — resource group / networking / data (irreversible)
78
+ "Bash(az group delete:*)",
79
+ "Bash(az network vnet delete:*)",
80
+ "Bash(az network vnet subnet delete:*)",
81
+ "Bash(az network nsg delete:*)",
82
+ "Bash(az network public-ip delete:*)",
83
+ "Bash(az network application-gateway delete:*)",
84
+ "Bash(az network lb delete:*)",
85
+ "Bash(az network dns zone delete:*)",
86
+ "Bash(az network private-dns zone delete:*)",
87
+ "Bash(az vm delete:*)",
88
+ "Bash(az vmss delete:*)",
89
+ "Bash(az disk delete:*)",
90
+ "Bash(az snapshot delete:*)",
91
+ "Bash(az image delete:*)",
92
+ # Azure — databases / storage
93
+ "Bash(az sql server delete:*)",
94
+ "Bash(az sql db delete:*)",
95
+ "Bash(az cosmosdb delete:*)",
96
+ "Bash(az redis delete:*)",
97
+ "Bash(az storage account delete:*)",
98
+ "Bash(az storage container delete:*)",
99
+ "Bash(az storage blob delete-batch:*)",
100
+ # Azure — AKS / container
101
+ "Bash(az aks delete:*)",
102
+ "Bash(az aks nodepool delete:*)",
103
+ "Bash(az acr delete:*)",
104
+ # Azure — IAM / key vault / functions
105
+ "Bash(az role assignment delete:*)",
106
+ "Bash(az role definition delete:*)",
107
+ "Bash(az ad app delete:*)",
108
+ "Bash(az ad sp delete:*)",
109
+ "Bash(az keyvault delete:*)",
110
+ "Bash(az keyvault key delete:*)",
111
+ "Bash(az keyvault secret delete:*)",
112
+ "Bash(az functionapp delete:*)",
113
+ "Bash(az webapp delete:*)",
114
+ # Azure — messaging / monitoring
115
+ "Bash(az servicebus namespace delete:*)",
116
+ "Bash(az servicebus queue delete:*)",
117
+ "Bash(az servicebus topic delete:*)",
118
+ "Bash(az eventhubs namespace delete:*)",
119
+ "Bash(az eventhubs eventhub delete:*)",
120
+ "Bash(az monitor action-group delete:*)",
121
+ # GCP — project / cluster / database (irreversible)
122
+ "Bash(gcloud projects delete:*)",
123
+ "Bash(gcloud container clusters delete:*)",
124
+ "Bash(gcloud container node-pools delete:*)",
125
+ "Bash(gcloud sql instances delete:*)",
126
+ "Bash(gcloud sql databases delete:*)",
127
+ "Bash(gcloud services disable:*)",
128
+ "Bash(gsutil rb:*)",
129
+ "Bash(gsutil rm -r:*)",
130
+ # GCP — compute / IAM / storage
131
+ "Bash(gcloud compute firewall-rules delete:*)",
132
+ "Bash(gcloud compute instances delete:*)",
133
+ "Bash(gcloud compute networks delete:*)",
134
+ "Bash(gcloud compute disks delete:*)",
135
+ "Bash(gcloud compute images delete:*)",
136
+ "Bash(gcloud compute snapshots delete:*)",
137
+ "Bash(gcloud iam roles delete:*)",
138
+ "Bash(gcloud storage rm:*)",
139
+ # Kubernetes — critical cluster operations
140
+ "Bash(kubectl delete namespace:*)",
141
+ "Bash(kubectl delete node:*)",
142
+ "Bash(kubectl delete cluster:*)",
143
+ "Bash(kubectl delete pv:*)",
144
+ "Bash(kubectl delete persistentvolume:*)",
145
+ "Bash(kubectl delete pvc:*)",
146
+ "Bash(kubectl delete persistentvolumeclaim:*)",
147
+ "Bash(kubectl delete crd:*)",
148
+ "Bash(kubectl delete customresourcedefinition:*)",
149
+ "Bash(kubectl delete mutatingwebhookconfiguration:*)",
150
+ "Bash(kubectl delete validatingwebhookconfiguration:*)",
151
+ "Bash(kubectl delete clusterrole:*)",
152
+ "Bash(kubectl delete clusterrolebinding:*)",
153
+ "Bash(kubectl drain:*)",
154
+ # Flux
155
+ "Bash(flux delete:*)",
156
+ # Git — force push (history rewrite)
157
+ "Bash(git push --force:*)",
158
+ "Bash(git push -f:*)",
159
+ "Bash(git push origin --force:*)",
160
+ "Bash(git push origin -f:*)",
161
+ # Disk / filesystem destruction
162
+ "Bash(dd:*)",
163
+ "Bash(fdisk:*)",
164
+ "Bash(mkfs:*)",
165
+ "Bash(mkfs.ext4:*)",
166
+ "Bash(mkfs.ext3:*)",
167
+ "Bash(mkfs.fat:*)",
168
+ "Bash(mkfs.ntfs:*)",
169
+ # -------------------------------------------------------------------
170
+ # Generic wildcard rules — catch ALL present and future services.
171
+ # These complement the granular rules above; if a new cloud service
172
+ # is added, these patterns block its delete operations automatically.
173
+ # -------------------------------------------------------------------
174
+ # AWS — any "delete-*" subcommand across all services
175
+ "Bash(aws * delete-*:*)",
176
+ "Bash(aws * terminate-*:*)",
177
+ # Azure — any "delete" subcommand across all services
178
+ "Bash(az * delete:*)",
179
+ # GCP — any "delete" subcommand across all services
180
+ "Bash(gcloud * delete:*)",
181
+ "Bash(gsutil rb:*)",
182
+ "Bash(gsutil rm:*)",
183
+ "Bash(gcloud storage rm:*)",
184
+ # Kubernetes — all delete and drain operations
185
+ "Bash(kubectl delete:*)",
186
+ "Bash(kubectl drain:*)",
187
+ # Terraform / Terragrunt — destroy
188
+ "Bash(terraform destroy:*)",
189
+ "Bash(terragrunt destroy:*)",
190
+ "Bash(terragrunt run-all destroy:*)",
191
+ # Helm — uninstall
192
+ "Bash(helm uninstall:*)",
193
+ "Bash(helm delete:*)",
194
+ # Flux — uninstall
195
+ "Bash(flux uninstall:*)",
196
+ # Docker — bulk prune
197
+ "Bash(docker system prune:*)",
198
+ "Bash(docker volume prune:*)",
199
+ # Git — destructive history operations
200
+ "Bash(git reset --hard:*)",
201
+ # Repo deletion
202
+ "Bash(gh repo delete:*)",
203
+ "Bash(glab project delete:*)",
204
+ ]
205
+
206
+ # Base permissions for security-only mode
207
+ SECURITY_PERMISSIONS = {
208
+ "permissions": {
209
+ "allow": [
210
+ "Bash(*)",
211
+ "Read",
212
+ "Glob",
213
+ "Grep",
214
+ "BashOutput",
215
+ "ExitPlanMode",
216
+ "KillShell",
217
+ "Skill",
218
+ "SlashCommand",
219
+ "TodoWrite",
220
+ "WebFetch",
221
+ "WebSearch",
222
+ "NotebookEdit",
223
+ ],
224
+ "deny": _DENY_RULES,
225
+ "ask": [],
226
+ }
227
+ }
228
+
229
+ # Extended permissions for ops mode (adds agent dispatch tools)
230
+ OPS_PERMISSIONS = {
231
+ "permissions": {
232
+ "allow": [
233
+ "Bash(*)",
234
+ "Read",
235
+ "Glob",
236
+ "Grep",
237
+ "BashOutput",
238
+ "ExitPlanMode",
239
+ "KillShell",
240
+ "Skill",
241
+ "SlashCommand",
242
+ "Task",
243
+ "Agent",
244
+ "SendMessage",
245
+ "AskUserQuestion",
246
+ "TodoWrite",
247
+ "WebFetch",
248
+ "WebSearch",
249
+ "NotebookEdit",
250
+ "Edit",
251
+ "Write",
252
+ ],
253
+ "deny": _DENY_RULES,
254
+ "ask": [],
255
+ }
256
+ }
257
+
258
+
259
+ def is_first_run() -> bool:
260
+ """Check if this is the first time the plugin runs."""
261
+ marker = get_plugin_data_dir() / MARKER_FILE
262
+ return not marker.exists()
263
+
264
+
265
+ def mark_initialized() -> None:
266
+ """Mark the plugin as initialized."""
267
+ marker = get_plugin_data_dir() / MARKER_FILE
268
+ marker.write_text(json.dumps({
269
+ "initialized_at": datetime.now().isoformat(),
270
+ "mode": get_plugin_mode(),
271
+ }))
272
+ logger.info("Plugin marked as initialized: %s", marker)
273
+
274
+
275
+ def _tool_name(entry: str) -> str:
276
+ """Extract the base tool name from a permission entry.
277
+
278
+ Examples:
279
+ "Edit" -> "Edit"
280
+ "Edit(/tmp/*)" -> "Edit"
281
+ "Bash(*)" -> "Bash"
282
+ "Bash(aws ec2 delete-vpc:*)" -> "Bash"
283
+ """
284
+ paren = entry.find("(")
285
+ return entry[:paren] if paren != -1 else entry
286
+
287
+
288
+ def _authoritative_merge(current: set[str], ours: set[str]) -> list[str]:
289
+ """Merge permissions so Gaia's entries are authoritative.
290
+
291
+ For every base tool name that Gaia defines, ALL existing entries for
292
+ that tool are replaced with Gaia's current values. User-added entries
293
+ for tool names Gaia does NOT manage are preserved.
294
+
295
+ This prevents stale scoped entries (e.g. ``Edit(/tmp/*)`` lingering
296
+ after Gaia changes to ``Edit``) while keeping user customizations
297
+ for tools outside Gaia's scope.
298
+ """
299
+ gaia_tool_names = {_tool_name(e) for e in ours}
300
+ # Keep only user entries whose tool name Gaia doesn't manage
301
+ user_entries = {e for e in current if _tool_name(e) not in gaia_tool_names}
302
+ return sorted(user_entries | ours)
303
+
304
+
305
+ def setup_project_permissions() -> bool:
306
+ """Merge gaia permissions into .claude/settings.local.json.
307
+
308
+ Uses settings.local.json (highest project-level precedence) so that
309
+ /reload-plugins picks up changes mid-session without restart.
310
+ Preserves enabledPlugins and any existing user configuration.
311
+
312
+ Returns True if settings were modified (reload needed).
313
+ """
314
+ claude_dir = Path.cwd() / ".claude"
315
+ settings_path = claude_dir / "settings.local.json"
316
+
317
+ mode = get_plugin_mode()
318
+ our_perms = OPS_PERMISSIONS if mode == "ops" else SECURITY_PERMISSIONS
319
+ our_allow = set(our_perms["permissions"]["allow"])
320
+ our_deny = set(our_perms["permissions"].get("deny", []))
321
+
322
+ # Load existing settings.local.json (has enabledPlugins from install)
323
+ existing = {}
324
+ if settings_path.exists():
325
+ try:
326
+ existing = json.loads(settings_path.read_text())
327
+ except (json.JSONDecodeError, OSError):
328
+ pass
329
+
330
+ # Authoritative merge: Gaia's entries replace any existing entries for the
331
+ # same base tool name (removes stale scoped variants like Edit(/tmp/*) when
332
+ # Gaia now says Edit). User entries for tools Gaia doesn't manage survive.
333
+ perms = existing.get("permissions", {})
334
+ current_allow = set(perms.get("allow", []))
335
+ current_deny = set(perms.get("deny", []))
336
+
337
+ merged_allow = _authoritative_merge(current_allow, our_allow)
338
+ merged_deny = _authoritative_merge(current_deny, our_deny)
339
+
340
+ if current_allow == set(merged_allow) and current_deny == set(merged_deny):
341
+ logger.info("Project permissions already include gaia rules, skipping")
342
+ return False
343
+
344
+ # Update only permissions, preserve everything else (enabledPlugins, etc.)
345
+ existing.setdefault("permissions", {})
346
+ existing["permissions"]["allow"] = merged_allow
347
+ existing["permissions"]["deny"] = merged_deny
348
+ existing["permissions"].setdefault("ask", [])
349
+
350
+ # Add env vars (smart merge: add if not present, don't overwrite)
351
+ env = existing.setdefault("env", {})
352
+ if "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS" not in env:
353
+ env["CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS"] = "1"
354
+
355
+ claude_dir.mkdir(parents=True, exist_ok=True)
356
+ settings_path.write_text(json.dumps(existing, indent=2) + "\n")
357
+ logger.info("Merged gaia %s permissions and env into %s", mode, settings_path)
358
+ return True
359
+
360
+
361
+ def ensure_plugin_registry() -> None:
362
+ """Create plugin-registry.json if missing.
363
+
364
+ Detection strategies (in order):
365
+ 1. CLAUDE_PLUGIN_ROOT env var (plugin marketplace mode):
366
+ Path looks like .../cache/marketplace/gaia-ops/4.4.0-rc.2
367
+ 2. NPM package detection: resolve package name and version from
368
+ node_modules path and package.json
369
+ """
370
+ import os
371
+ data_dir = get_plugin_data_dir()
372
+ registry_path = data_dir / "plugin-registry.json"
373
+ if registry_path.exists():
374
+ return
375
+
376
+ plugin_name = None
377
+ plugin_version = None
378
+ source = None
379
+
380
+ # Strategy 1: CLAUDE_PLUGIN_ROOT (plugin marketplace or --plugin-dir)
381
+ plugin_root = os.environ.get("CLAUDE_PLUGIN_ROOT", "")
382
+ if plugin_root:
383
+ root_path = Path(plugin_root)
384
+ # First, try to read .claude-plugin/plugin.json (most reliable)
385
+ plugin_json = root_path / ".claude-plugin" / "plugin.json"
386
+ if plugin_json.exists():
387
+ try:
388
+ pdata = json.loads(plugin_json.read_text())
389
+ plugin_name = pdata.get("name")
390
+ plugin_version = pdata.get("version")
391
+ source = "plugin-mode"
392
+ except (json.JSONDecodeError, OSError):
393
+ pass
394
+ # Fallback: parse path (marketplace layout: .../name/version)
395
+ if not plugin_name:
396
+ parts = root_path.parts
397
+ if len(parts) >= 2:
398
+ plugin_name = parts[-2]
399
+ plugin_version = parts[-1]
400
+ source = "plugin-mode"
401
+
402
+ # Strategy 2: NPM package detection
403
+ if not plugin_name:
404
+ npm_info = _detect_npm_package_info()
405
+ if npm_info:
406
+ plugin_name, plugin_version = npm_info
407
+ source = "npm-mode"
408
+
409
+ if not plugin_name:
410
+ return
411
+
412
+ registry = {
413
+ "installed": [{"name": plugin_name, "version": plugin_version or "unknown"}],
414
+ "source": source,
415
+ }
416
+ data_dir.mkdir(parents=True, exist_ok=True)
417
+ registry_path.write_text(json.dumps(registry, indent=2) + "\n")
418
+ logger.info("Created plugin-registry.json: %s@%s (source: %s)", plugin_name, plugin_version, source)
419
+
420
+
421
+ def _detect_npm_package_info() -> tuple[str, str | None] | None:
422
+ """Detect plugin name and version from NPM package path.
423
+
424
+ When installed via npm, this module lives at:
425
+ .../node_modules/@jaguilar87/gaia/hooks/modules/core/plugin_setup.py
426
+
427
+ Returns (plugin_name, version) or None.
428
+ """
429
+ module_path = Path(__file__).resolve()
430
+ parts = module_path.parts
431
+
432
+ # Find node_modules in path and extract package name
433
+ pkg_name = None
434
+ pkg_root = None
435
+ for i, part in enumerate(parts):
436
+ if part == "node_modules" and i + 1 < len(parts):
437
+ next_part = parts[i + 1]
438
+ if next_part.startswith("@") and i + 2 < len(parts):
439
+ # Scoped package: @scope/name
440
+ pkg_name = parts[i + 2]
441
+ pkg_root = Path(*parts[:i + 3])
442
+ else:
443
+ pkg_name = next_part
444
+ pkg_root = Path(*parts[:i + 2])
445
+ break
446
+
447
+ if not pkg_name or pkg_name not in ("gaia-ops", "gaia-security"):
448
+ return None
449
+
450
+ # Try to read version from package.json
451
+ version = None
452
+ if pkg_root:
453
+ pkg_json = Path("/") / pkg_root / "package.json"
454
+ try:
455
+ if pkg_json.exists():
456
+ data = json.loads(pkg_json.read_text())
457
+ version = data.get("version")
458
+ except Exception:
459
+ pass
460
+
461
+ return (pkg_name, version)
462
+
463
+
464
+ def setup_project_hooks() -> bool:
465
+ """Merge hooks from hooks.json into .claude/settings.local.json.
466
+
467
+ In npm mode, Claude Code reads hooks from settings files, not hooks.json.
468
+ This resolves hook script paths to absolute paths (via .claude/hooks symlink)
469
+ so hooks work regardless of CWD at execution time.
470
+
471
+ Returns True if settings were modified.
472
+ """
473
+ import re
474
+
475
+ claude_dir = Path.cwd() / ".claude"
476
+ settings_path = claude_dir / "settings.local.json"
477
+
478
+ # Find hooks.json — try package root (npm) or plugin root
479
+ hooks_json_path = None
480
+ # Strategy 1: relative to this module (npm layout)
481
+ module_dir = Path(__file__).resolve().parent.parent.parent
482
+ candidate = module_dir / "hooks.json"
483
+ if candidate.is_file():
484
+ hooks_json_path = candidate
485
+ else:
486
+ # Strategy 2: .claude/hooks/hooks.json (symlinked)
487
+ candidate2 = claude_dir / "hooks" / "hooks.json"
488
+ if candidate2.is_file():
489
+ hooks_json_path = candidate2
490
+
491
+ if not hooks_json_path:
492
+ logger.info("hooks.json not found, skipping hooks merge")
493
+ return False
494
+
495
+ try:
496
+ hooks_data = json.loads(hooks_json_path.read_text())
497
+ except (json.JSONDecodeError, OSError):
498
+ logger.warning("hooks.json is invalid, skipping hooks merge")
499
+ return False
500
+
501
+ # Unwrap outer "hooks" key if present
502
+ source_hooks = hooks_data.get("hooks", hooks_data)
503
+
504
+ # Resolve absolute path to hooks directory so hooks work regardless of
505
+ # CWD at execution time (Stop/PostCompact hooks may run from unknown CWD)
506
+ hooks_dir = claude_dir / "hooks"
507
+ if hooks_dir.exists():
508
+ hooks_abs = str(hooks_dir.resolve())
509
+ else:
510
+ # Fallback: use relative .claude/hooks/ if symlink not yet created
511
+ hooks_abs = str(claude_dir / "hooks")
512
+
513
+ def convert_command(cmd: str) -> str:
514
+ return re.sub(r'\$\{CLAUDE_PLUGIN_ROOT\}/hooks/', f'{hooks_abs}/', cmd)
515
+
516
+ converted_hooks: dict = {}
517
+ for event, entries in source_hooks.items():
518
+ converted_hooks[event] = []
519
+ for entry in entries:
520
+ new_entry = dict(entry)
521
+ if "hooks" in new_entry:
522
+ new_entry["hooks"] = [
523
+ {**h, "command": convert_command(h["command"])} if "command" in h else h
524
+ for h in new_entry["hooks"]
525
+ ]
526
+ converted_hooks[event].append(new_entry)
527
+
528
+ # Load existing settings.local.json
529
+ existing: dict = {}
530
+ if settings_path.exists():
531
+ try:
532
+ existing = json.loads(settings_path.read_text())
533
+ except (json.JSONDecodeError, OSError):
534
+ existing = {}
535
+
536
+ # Replace hooks entirely — gaia is the sole author of hook entries.
537
+ # Previous merge-append logic caused duplicates when setup ran twice
538
+ # per session (session_start + user_prompt_submit).
539
+ existing_hooks = existing.get("hooks", {})
540
+ if existing_hooks == converted_hooks:
541
+ logger.info("settings.local.json hooks already up to date")
542
+ return False
543
+
544
+ existing["hooks"] = converted_hooks
545
+ claude_dir.mkdir(parents=True, exist_ok=True)
546
+ settings_path.write_text(json.dumps(existing, indent=2) + "\n")
547
+ logger.info("Merged hooks into %s", settings_path)
548
+ return True
549
+
550
+
551
+ def run_first_time_setup(mark_done: bool = True) -> str | None:
552
+ """Run setup. Returns a reload message if permissions were written.
553
+
554
+ Args:
555
+ mark_done: If True, mark the plugin as initialized after setup.
556
+ Set to False when the caller wants to defer marking
557
+ (e.g., UserPromptSubmit marks after showing the welcome).
558
+ """
559
+ # Always ensure registry, permissions, and hooks exist (even on subsequent runs)
560
+ ensure_plugin_registry()
561
+ reload_needed = setup_project_permissions()
562
+ hooks_changed = setup_project_hooks()
563
+ reload_needed = reload_needed or hooks_changed
564
+
565
+ if not is_first_run():
566
+ if reload_needed:
567
+ return "Permissions updated. Run /reload-plugins to activate."
568
+ return None
569
+
570
+ if mark_done:
571
+ mark_initialized()
572
+
573
+ if reload_needed:
574
+ mode = get_plugin_mode()
575
+ return f"GAIA {mode} setup complete. Run /reload-plugins to activate permissions."
576
+
577
+ return None