@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
@@ -36,20 +36,20 @@ Every response MUST end with a single fenced `json:contract` block.
36
36
 
37
37
  ### agent_status (always required)
38
38
 
39
- - `plan_status` one of the 6 valid states below
40
- - `agent_id` generate once, reuse across responses
41
- - `pending_steps` remaining work (`[]` when done)
42
- - `next_action` `"done"` or what happens next
39
+ - `plan_status` -- one of the 5 valid states below
40
+ - `agent_id` -- generate once, reuse across responses
41
+ - `pending_steps` -- remaining work (`[]` when done)
42
+ - `next_action` -- `"done"` or what happens next
43
43
 
44
44
  ### evidence_report (always required)
45
45
 
46
46
  All 7 fields validated by runtime. Use `[]` when not applicable.
47
47
  Keep each to 1-3 items unless the task genuinely needs more.
48
48
 
49
- - `key_outputs` actionable findings, not descriptions of what you ran. Highlight what matters: what is wrong, what changed, what needs attention.
50
- - `verbatim_outputs` literal command output; truncate at ~100 lines
51
- - `cross_layer_impacts` adjacent surfaces affected
52
- - `open_gaps` what remains unverified; never imply certainty
49
+ - `key_outputs` -- actionable findings, not descriptions of what you ran. Highlight what matters: what is wrong, what changed, what needs attention.
50
+ - `verbatim_outputs` -- literal command output; truncate at ~100 lines
51
+ - `cross_layer_impacts` -- adjacent surfaces affected
52
+ - `open_gaps` -- what remains unverified; never imply certainty
53
53
 
54
54
  ### consolidation_report (when multi-surface)
55
55
 
@@ -61,30 +61,31 @@ Fields: `ownership_assessment`, `confirmed_findings`,
61
61
 
62
62
  For examples, read `examples.md` in this skill directory.
63
63
 
64
- ### approval_request (when REVIEW or AWAITING_APPROVAL)
64
+ ### approval_request (when REVIEW)
65
65
 
66
- Required when `plan_status` is `REVIEW` or `AWAITING_APPROVAL`. Otherwise `null`.
66
+ Required when `plan_status` is `REVIEW`. Otherwise `null`.
67
67
 
68
68
  Fields: `operation`, `exact_content`, `scope`, `risk_level`, `rollback`, `verification`.
69
- For `AWAITING_APPROVAL`, also include `nonce`.
69
+ When a hook blocked a T3 command with `[T3_BLOCKED]` and an `approval_id`:
70
+ - Do NOT retry the command -- retrying generates new nonces in a loop
71
+ - Set `plan_status` to `REVIEW` and include `approval_id` in `approval_request`
72
+ - The orchestrator will resume you after user approval; only then retry
70
73
 
71
74
  ## State Machine
72
75
 
73
76
  | Status | Meaning |
74
77
  |--------|---------|
75
78
  | `IN_PROGRESS` | Active work: investigating, planning, executing, retrying (max 2 cycles) |
76
- | `REVIEW` | Presenting plan or analysis for user feedback. No nonce. |
77
- | `AWAITING_APPROVAL` | Hook blocked a T3 command. Nonce present. |
79
+ | `REVIEW` | Presenting plan or analysis for user feedback. May include `approval_id` when hook-blocked. |
78
80
  | `COMPLETE` | Task finished |
79
- | `BLOCKED` | Cannot proceed escalated |
81
+ | `BLOCKED` | Cannot proceed -- escalated |
80
82
  | `NEEDS_INPUT` | Missing information from user |
81
83
 
82
84
  ### Transitions
83
85
 
84
86
  ```
85
87
  IN_PROGRESS -> COMPLETE (T0/T1/T2)
86
- IN_PROGRESS -> REVIEW -> IN_PROGRESS -> COMPLETE (plan-first)
87
- IN_PROGRESS -> AWAITING_APPROVAL -> IN_PROGRESS -> COMPLETE (hook-blocked T3)
88
+ IN_PROGRESS -> REVIEW -> IN_PROGRESS -> COMPLETE (plan-first or hook-blocked T3)
88
89
  IN_PROGRESS -> BLOCKED | NEEDS_INPUT (any point)
89
90
  IN_PROGRESS -> IN_PROGRESS (retry, max 2)
90
91
  ```
@@ -106,22 +106,22 @@ See `SKILL.md` for the schema definition and field rules.
106
106
  }
107
107
  ```
108
108
 
109
- ## AWAITING_APPROVAL (hook blocked T3 command, nonce present)
109
+ ## REVIEW with approval_id (hook blocked T3 command)
110
110
 
111
111
  ```json:contract
112
112
  {
113
113
  "agent_status": {
114
- "plan_status": "AWAITING_APPROVAL",
114
+ "plan_status": "REVIEW",
115
115
  "agent_id": "af1d9b7",
116
116
  "pending_steps": ["execute git push", "verify Flux reconciliation"],
117
- "next_action": "Hook blocked git push -- awaiting nonce-based approval"
117
+ "next_action": "Hook blocked git push -- awaiting user approval"
118
118
  },
119
119
  "evidence_report": {
120
120
  "patterns_checked": ["git branch naming in flux/clusters/"],
121
121
  "files_checked": ["flux/apps/qxo-api/helmrelease.yaml"],
122
122
  "commands_run": ["git diff HEAD -> 1 file changed", "git push origin main -> BLOCKED by hook"],
123
- "key_outputs": ["Push blocked by mutative_verbs hook, nonce issued"],
124
- "verbatim_outputs": ["APPROVAL REQUIRED. Present your plan to the user and include this approval code: NONCE:a1b2c3..."],
123
+ "key_outputs": ["Push blocked by security hook, approval_id issued"],
124
+ "verbatim_outputs": ["[T3_BLOCKED] MUTATIVE operation requires user approval. approval_id: a1b2c3..."],
125
125
  "cross_layer_impacts": ["Flux will reconcile HelmRelease on push"],
126
126
  "open_gaps": []
127
127
  },
@@ -133,7 +133,7 @@ See `SKILL.md` for the schema definition and field rules.
133
133
  "risk_level": "MEDIUM",
134
134
  "rollback": "git revert HEAD && git push",
135
135
  "verification": "flux get hr -n qxo -> reconciled",
136
- "nonce": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
136
+ "approval_id": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
137
137
  }
138
138
  }
139
139
  ```
@@ -12,12 +12,12 @@ metadata:
12
12
 
13
13
  ```
14
14
  Agent returns json:contract
15
- ├─ COMPLETE Summarize key_outputs (3-5 bullets)
16
- ├─ NEEDS_INPUT AskUserQuestion, then SendMessage answer back
17
- ├─ REVIEW AskUserQuestion (execute/modify/cancel), then SendMessage decision
18
- ├─ AWAITING_APPROVAL → Load Skill("orchestrator-approval")
19
- ├─ BLOCKED Present open_gaps via AskUserQuestion
20
- └─ IN_PROGRESS SendMessage to resume agent
15
+ |- COMPLETE -> Summarize key_outputs (3-5 bullets)
16
+ |- NEEDS_INPUT -> AskUserQuestion, then SendMessage answer back
17
+ |- REVIEW -> Load Skill("orchestrator-approval") if approval_id present,
18
+ | otherwise AskUserQuestion (execute/modify/cancel)
19
+ |- BLOCKED -> Present open_gaps via AskUserQuestion
20
+ +- IN_PROGRESS -> SendMessage to resume agent
21
21
  ```
22
22
 
23
23
  ## Mandatory Actions per Status
@@ -25,9 +25,8 @@ Agent returns json:contract
25
25
  | Status | Action | Tool |
26
26
  |---|---|---|
27
27
  | `COMPLETE` | Summarize `key_outputs` in 3-5 bullets. Mention `cross_layer_impacts` and `open_gaps` if non-empty. Say "ask for details" if `verbatim_outputs` exists. | Direct response |
28
- | `NEEDS_INPUT` | Present the agent's question with options | `AskUserQuestion` `SendMessage` |
29
- | `REVIEW` | Present plan with options: execute / modify / cancel | `AskUserQuestion` `SendMessage` |
30
- | `AWAITING_APPROVAL` | Do not handle directly | `Skill("orchestrator-approval")` |
28
+ | `NEEDS_INPUT` | Present the agent's question with options | `AskUserQuestion` -> `SendMessage` |
29
+ | `REVIEW` | If `approval_request.approval_id` is present: load `Skill("orchestrator-approval")`. Otherwise: present plan with options execute / modify / cancel. | `AskUserQuestion` -> `SendMessage` |
31
30
  | `BLOCKED` | Present alternatives from `open_gaps` | `AskUserQuestion` |
32
31
  | `IN_PROGRESS` | Agent was interrupted, let it continue | `SendMessage` |
33
32
 
@@ -35,10 +34,10 @@ Agent returns json:contract
35
34
 
36
35
  | Field | When to surface |
37
36
  |---|---|
38
- | `key_outputs` | Always base your summary on these |
39
- | `verbatim_outputs` | Only when user asks for details relay in code blocks |
37
+ | `key_outputs` | Always -- base your summary on these |
38
+ | `verbatim_outputs` | Only when user asks for details -- relay in code blocks |
40
39
  | `cross_layer_impacts` | Always mention if non-empty |
41
- | `open_gaps` | Always mention never imply certainty |
40
+ | `open_gaps` | Always mention -- never imply certainty |
42
41
  | `consolidation_report` | Check for `conflicts` and `next_best_agent` |
43
42
  | `next_best_agent` | Ask user if they want to dispatch |
44
43
 
@@ -51,6 +50,4 @@ If agents conflict, present both sides and ask user to decide.
51
50
 
52
51
  | Situation | Action |
53
52
  |---|---|
54
- | Hook blocks a command | Relay message verbatim. Do not try alternatives. |
55
- | Agent contradicts another | Show both findings, flag conflict, ask user. |
56
53
  | Malformed contract | Resume agent with repair instructions (max 2 retries). |
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  ## Overview
12
12
 
13
- The plan is a contract. The user approves the exact contract
13
+ The plan is a contract. The user approves the exact contract --
14
14
  not a vague intent. Structure your plan in the `approval_request`
15
15
  field of your `json:contract` so the orchestrator can present it
16
16
  directly to the user.
@@ -31,9 +31,9 @@ with these 6 fields:
31
31
  }
32
32
  ```
33
33
 
34
- For `AWAITING_APPROVAL` (hook-blocked), also include:
34
+ When a hook blocked your command with an `approval_id`, also include:
35
35
  ```json
36
- "nonce": "hex from hook block response"
36
+ "approval_id": "hex from hook deny response"
37
37
  ```
38
38
 
39
39
  ### Risk Levels
@@ -47,24 +47,39 @@ For `AWAITING_APPROVAL` (hook-blocked), also include:
47
47
 
48
48
  ## Which Status to Emit
49
49
 
50
- - `REVIEW` presenting a plan before executing (no hook block)
51
- - `AWAITING_APPROVAL` hook blocked your command with `NONCE:<hex>`
50
+ - `REVIEW` -- presenting a plan before executing (no hook block)
51
+ - `REVIEW` with `approval_id` -- hook blocked your command with an approval_id
52
52
 
53
- ## Nonce Flow
53
+ Both use `REVIEW` as the plan_status. The presence or absence of
54
+ `approval_id` in `approval_request` tells the orchestrator which
55
+ handling path to take.
54
56
 
55
- When a hook blocks your command, it returns a nonce:
57
+ ## Hook Block Flow
58
+
59
+ When a hook blocks your command with `[T3_BLOCKED]` and an `approval_id`:
60
+
61
+ 1. **STOP** -- do NOT retry the command. Retrying generates a new nonce
62
+ each time, creating an infinite loop.
63
+ 2. **Report REVIEW** -- set `plan_status` to `REVIEW` in your `json:contract`.
64
+ 3. **Include the approval_id** -- copy the hex identifier from the hook deny
65
+ response into `approval_request.approval_id`.
66
+ 4. **Wait** -- the orchestrator presents your plan to the user. When the user
67
+ approves, the orchestrator resumes you with the grant activated.
68
+ 5. **Then retry** -- only after the orchestrator resumes you, retry the command.
69
+
70
+ The hook deny message looks like:
56
71
  ```
57
- APPROVAL REQUIRED. ... NONCE:<hex>
72
+ [T3_BLOCKED] This command requires user approval.
73
+ Do NOT retry this command. Report REVIEW with this approval_id in your json:contract.
74
+ approval_id: <hex>
58
75
  ```
59
76
 
60
- Include this nonce in your `approval_request`. It is machine-readable
61
- the orchestrator extracts it silently.
62
-
63
- If you lose the nonce, re-attempt the command for a fresh one.
77
+ If you lose the approval_id, re-attempt the command once for a fresh one.
64
78
 
65
79
  ## Anti-Patterns
66
80
 
81
+ - **Retrying after T3_BLOCKED** -- generates a new nonce, causes infinite loop
67
82
  - Presenting approval without all 6 fields in `approval_request`
68
83
  - Putting approval fields in text only without the JSON object
69
84
  - Treating prior approvals as valid for new operations
70
- - Fabricating or paraphrasing the nonce token
85
+ - Fabricating or paraphrasing the approval_id token
@@ -43,10 +43,10 @@ These 6 fields MUST appear in the `approval_request` object of your `json:contra
43
43
  | `rollback` | `"terraform -chdir=/infra/dev apply -target=module.vpc -var='cidr=10.0.0.0/16'"` |
44
44
  | `verification` | `"terraform -chdir=/infra/dev output vpc_id -- expect vpc-xxx"` |
45
45
 
46
- For `AWAITING_APPROVAL`, also include:
46
+ When a hook blocked the command, also include:
47
47
  | Field | Example value |
48
48
  |-------|---------------|
49
- | `nonce` | `"a1b2c3d4e5f6..."` (hex from hook block response) |
49
+ | `approval_id` | `"a1b2c3d4e5f6..."` (hex from hook deny response) |
50
50
 
51
51
  ### Files Affected
52
52
 
@@ -24,7 +24,7 @@ system in a broken state.
24
24
 
25
25
  Before executing ANY approved operation:
26
26
 
27
- - [ ] Prompt contains canonical token: `APPROVE:<nonce>`
27
+ - [ ] User approved via AskUserQuestion and ElicitationResult hook activated the grant
28
28
  - [ ] Capture current state — know what you can roll back to
29
29
  - [ ] Plan still valid — re-run dry-run if time has passed
30
30
  - [ ] Commands will not prompt for interactive input
@@ -27,8 +27,7 @@ Domain knowledge for the gaia-ops meta-system. For the Component Map details, se
27
27
  5. Post-Tool Hook — audit + metrics
28
28
 
29
29
  6. Orchestrator processes `json:contract` block (plan_status)
30
- ├─ REVIEW → present plan, get feedback → resume
31
- ├─ AWAITING_APPROVAL → present plan + nonce relay → resume
30
+ ├─ REVIEW → present plan, get feedback → resume (with approval_id if hook-blocked)
32
31
  ├─ NEEDS_INPUT → ask user → resume
33
32
  └─ COMPLETE → respond to user
34
33
  ```
@@ -38,7 +37,7 @@ Domain knowledge for the gaia-ops meta-system. For the Component Map details, se
38
37
  - **Binary Delegation:** The orchestrator always delegates. Its only tools are Agent and AskUserQuestion.
39
38
  - **Agent Instantiation:** identity (.md) + skills (injected) + project-context (contracts) + orchestrator request.
40
39
  - **Security Tiers:** T0 (read) → T1 (validate) → T2 (simulate) → T3 (realize, requires approval).
41
- - **T3 Flow:** IN_PROGRESS → REVIEW → IN_PROGRESS → COMPLETE (plan-first) or IN_PROGRESS → AWAITING_APPROVAL → IN_PROGRESS → COMPLETE (hook-blocked).
40
+ - **T3 Flow:** IN_PROGRESS → REVIEW → IN_PROGRESS → COMPLETE (plan-first or hook-blocked with approval_id).
42
41
  - **Consolidation Loop:** for multi-surface work, Gaia may dispatch more than one round of agents, but only while gaps are actionable and evidence is still improving.
43
42
  - **Principle:** Skills teach process. Agents teach identity and domain knowledge. Runtime enforces deterministic contracts. Never duplicate.
44
43
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: orchestrator-approval
3
- description: Use when processing AWAITING_APPROVAL from a subagent -- enforces showing values before asking for user consent (not for REVIEW)
3
+ description: Use when processing REVIEW with approval_id from a subagent -- enforces showing values before asking for user consent
4
4
  metadata:
5
5
  user-invocable: false
6
6
  type: discipline
@@ -9,9 +9,9 @@ metadata:
9
9
  # Orchestrator Approval
10
10
 
11
11
  ```
12
- THIS SKILL HANDLES ONLY AWAITING_APPROVAL (hook-blocked T3 with nonce).
13
- REVIEW states are handled directly by the orchestrator -- this skill does not apply.
14
- NEVER RELAY APPROVE:<nonce> WITHOUT SHOWING THE USER
12
+ THIS SKILL HANDLES REVIEW WITH approval_id (hook-blocked T3).
13
+ Plain REVIEW (plan-first, no approval_id) is handled directly by the orchestrator.
14
+ NEVER PRESENT AN APPROVAL WITHOUT SHOWING THE USER
15
15
  (1) WHAT WILL HAPPEN, (2) EXACT CONTENT/COMMAND, (3) WHAT IT MODIFIES.
16
16
  ```
17
17
 
@@ -19,13 +19,13 @@ NEVER RELAY APPROVE:<nonce> WITHOUT SHOWING THE USER
19
19
 
20
20
  The orchestrator sits between the subagent and the user. The subagent presents a plan; the user decides. But the user cannot decide on information they have not seen. Every approval prompt must contain enough detail for informed consent -- not a summary, not a reference to "the plan above", not an offer to show details on request. The values go in the prompt, every time, before the question is asked.
21
21
 
22
- The agent-facing approval skill (`skills/approval/SKILL.md`) ensures the subagent builds a complete plan. This skill ensures the orchestrator presents that plan faithfully before asking for consent.
22
+ When a hook blocks a T3 command, it writes a pending approval and returns an `approval_id` in the deny response. The subagent includes this `approval_id` in its `approval_request`. The orchestrator presents the plan via AskUserQuestion with structured options (Approve / Modify / Reject). When the user selects "Approve", the PostToolUse hook for AskUserQuestion fires and activates the pending grant. No nonce or approval_id is relayed through SendMessage -- grant activation is handled entirely by the hook.
23
23
 
24
- **Scope:** This skill applies ONLY when a subagent emits `AWAITING_APPROVAL` (a hook blocked a T3 command and a nonce is present). When a subagent emits `REVIEW` (plan-first, no nonce), the orchestrator handles it directly by summarizing and asking the user -- no nonce relay is involved.
24
+ **Scope:** This skill applies ONLY when a subagent emits `REVIEW` with an `approval_id` in its `approval_request`. Without `approval_id`, the orchestrator handles REVIEW directly.
25
25
 
26
26
  ## Mandatory Presentation Block
27
27
 
28
- Every `AWAITING_APPROVAL` presented to the user MUST include these 5 fields.
28
+ Every hook-blocked `REVIEW` presented to the user MUST include these 5 fields.
29
29
  Read them from the `approval_request` object in the agent's `json:contract` block:
30
30
 
31
31
  | Field | Source in `approval_request` | Content |
@@ -36,57 +36,29 @@ Read them from the `approval_request` object in the agent's `json:contract` bloc
36
36
  | **RISK_LEVEL** | `approval_request.risk_level` | LOW / MEDIUM / HIGH / CRITICAL |
37
37
  | **ROLLBACK** | `approval_request.rollback` | How to undo if wrong |
38
38
 
39
- The nonce comes from `approval_request.nonce` (present only for `AWAITING_APPROVAL`).
40
-
41
- Present these fields, then use AskUserQuestion with labeled options: **Approve / Modify / Reject**.
42
-
43
39
  ## Rules
44
40
 
45
- **1. Human approval is not a hook nonce.**
46
- Human approval = semantic consent for an operation. Hook nonce = machine token for one blocked T3 command. They are different things with different lifecycles.
47
-
48
- **2. Never synthesize a nonce.**
49
- Only use `APPROVE:<nonce>` with a real hex nonce from the subagent's latest blocked command output. Never construct tokens like `APPROVE:commit`, `APPROVE:git push`, or `APPROVE:terraform apply prod`.
50
-
51
- **3. Approval intent vs nonce relay.**
52
- If the user approves but no nonce exists yet, store that as intent only. Resume the subagent with natural language and let it continue until the hook generates a real nonce.
53
-
54
- **4. Scope guard.**
55
- When a nonce arrives, compare the blocked command's scope to what the user originally approved. If the command expands scope, changes operation, or targets something materially different -- present the new scope and ask again.
56
-
57
- **5. Fresh presentation every time.**
58
- Each `AWAITING_APPROVAL` requires its own presentation with all mandatory fields. Prior approvals do not carry forward.
59
-
60
- ## Nonce Relay Procedure
61
-
62
- 1. Extract the 5 mandatory fields from `approval_request` in the subagent's `json:contract` block. Extract the nonce from `approval_request.nonce` (present only for `AWAITING_APPROVAL`).
63
- 2. Present to the user via AskUserQuestion with all mandatory fields populated. Options: **Approve / Modify / Reject**. Never include the nonce in user-facing text.
64
- 3. On user approval:
65
- - If nonce exists: resume the subagent via SendMessage(to: agentId) with `APPROVE:<nonce>` as the message.
66
- - If no nonce yet: store approval intent. Resume subagent via SendMessage with natural language describing the approved direction.
67
- 4. On scope change: if the eventual blocked command differs materially from what the user approved, present the new scope with all mandatory fields and ask again.
41
+ **1. Grant activates through the PostToolUse hook for AskUserQuestion -- not SendMessage.**
42
+ Resume the subagent via SendMessage with natural language only (e.g., "Proceed with the approved operation"). Never include any nonce, approval_id, or APPROVE: token.
68
43
 
69
- **Note:** After relaying the nonce, Claude Code will show a native confirmation
70
- dialog to the user for the first execution. This is the double-barrier security
71
- gate -- the user approved the plan through the orchestrator, and now confirms the
72
- actual command execution through the native dialog. Subsequent commands within the
73
- approval TTL window proceed without the native dialog.
44
+ **2. Scope guard.**
45
+ Compare the blocked command's scope to what the user originally approved. If the command expands scope, changes operation, or targets something materially different -- present the new scope and ask again.
74
46
 
75
- ## Red Flags -- Stop Before Relaying
47
+ **3. Fresh presentation every time.**
48
+ Each hook-blocked REVIEW requires its own presentation with all mandatory fields. Prior approvals do not carry forward.
76
49
 
77
- If you are forming any of these thoughts, stop. You are about to violate the presentation contract:
50
+ ## Approval Procedure
78
51
 
79
- - *"The change is obvious from the operation name"* -- Show exact content anyway.
80
- - *"The subagent already showed the user the plan"* -- Show it again in the approval prompt.
81
- - *"It's just a git commit / small edit"* -- Size does not change the contract.
82
- - *"I'll show details if they ask"* -- Show BEFORE asking, not after.
83
- - *"The user already approved this type of operation"* -- Each AWAITING_APPROVAL requires fresh presentation.
84
- - *"I can construct the nonce from the operation description"* -- Nonces are hex tokens from the hook, never synthesized.
52
+ 1. Extract the 5 mandatory fields from `approval_request` in the subagent's `json:contract` block.
53
+ 2. Present to the user via AskUserQuestion with all mandatory fields populated. Use exactly these options: **Approve / Modify / Reject**. Never include the approval_id in user-facing text.
54
+ 3. On "Approve": resume the subagent via SendMessage with natural language describing the approved direction.
55
+ 4. On scope change: present the new scope with all mandatory fields and ask again.
85
56
 
86
57
  ## Anti-Patterns
87
58
 
88
59
  - **Summary-only approval** -- presenting "Deploy to dev?" without the exact command, files, or rollback.
89
- - **Stale nonce** -- relaying a nonce from a previous blocked command instead of the latest one.
90
- - **Nonce in user text** -- showing the hex token to the user. The nonce is a machine handshake, never user-facing.
91
- - **Implicit carry-forward** -- treating a prior approval as valid for a new AWAITING_APPROVAL.
60
+ - **Token relay in SendMessage** -- including approval_id or nonce in the resume message.
61
+ - **Implicit carry-forward** -- treating a prior approval as valid for a new hook-blocked REVIEW.
92
62
  - **Details on demand** -- offering to show the plan instead of showing it upfront.
63
+ - **"It's just a small change"** -- size does not change the contract. Show exact content regardless.
64
+ - **"The subagent already showed it"** -- show it again in the approval prompt.
@@ -54,7 +54,7 @@ Conditional commands like `git branch` are safe for listing but T3 with mutative
54
54
 
55
55
  ## T3 Workflow
56
56
 
57
- For T3 operations, follow the state flow in `agent-protocol`: IN_PROGRESS -- REVIEW -- IN_PROGRESS -- COMPLETE (plan-first) or IN_PROGRESS -- AWAITING_APPROVAL -- IN_PROGRESS -- COMPLETE (hook-blocked).
57
+ For T3 operations, follow the state flow in `agent-protocol`: IN_PROGRESS -- REVIEW -- IN_PROGRESS -- COMPLETE (plan-first or hook-blocked with approval_id).
58
58
 
59
59
  On-demand workflow skills (read from disk when needed):
60
60
  - `.claude/skills/approval/SKILL.md` -- informed-consent plan quality and approval presentation
@@ -16,12 +16,12 @@ Generates final file in project
16
16
 
17
17
  ## Available Templates
18
18
 
19
- ### `settings.template.json`
19
+ ### `managed-settings.template.json`
20
20
 
21
- Template for permissions and security configuration. Replaced on every update -- the template is the source of truth.
21
+ Reference template for enterprise deployment via Claude.ai Admin Console or `/etc/claude-code/managed-settings.json`. Contains wildcard deny rules with highest precedence (cannot be overridden by user/project settings). Includes `disableBypassPermissionsMode` to prevent `--dangerously-skip-permissions`.
22
22
 
23
- **Generated by:** `bin/gaia-scan.py`, `bin/gaia-update.js`
24
- **Output file:** `./.claude/settings.json`
23
+ **Deployed by:** Organization admin (not automated)
24
+ **Output:** `/etc/claude-code/managed-settings.json` (Linux) or Admin Console
25
25
 
26
26
  ---
27
27
 
@@ -40,7 +40,7 @@ Template for the project governance document. Placeholders are filled with value
40
40
 
41
41
  ## Note on CLAUDE.md
42
42
 
43
- Orchestrator identity is no longer generated from a template. It is injected dynamically by the UserPromptSubmit hook via `ops_identity.py` and on-demand skills (`project-dispatch`, `agent-response`).
43
+ Orchestrator identity is no longer generated from a template. It is injected dynamically by the UserPromptSubmit hook via `ops_identity.py` with deterministic surface routing and on-demand skills (`agent-response`).
44
44
 
45
45
  ## Usage
46
46
 
@@ -56,15 +56,15 @@ node node_modules/@jaguilar87/gaia-ops/bin/gaia-update.js
56
56
 
57
57
  ```
58
58
  templates/
59
- ├── settings.template.json
60
- ├── governance.template.md
59
+ ├── managed-settings.template.json # Enterprise deny rules (manual deploy)
60
+ ├── governance.template.md # Project governance (interpolated)
61
61
  └── README.md
62
62
  ```
63
63
 
64
64
  **Scripts using templates:**
65
65
  - `bin/gaia-scan.py` - Installer
66
- - `bin/gaia-update.js` - Updater
66
+ - `bin/gaia-update.js` - Updater (permissions merge into settings.local.json)
67
67
 
68
68
  ---
69
69
 
70
- **Updated:** 2026-03-19 | **Templates:** 2
70
+ **Updated:** 2026-03-26 | **Templates:** 2
@@ -0,0 +1,43 @@
1
+ {
2
+ "_comment": [
3
+ "Managed settings template for enterprise/organization deployment.",
4
+ "Deploy to: /etc/claude-code/managed-settings.json (Linux/WSL)",
5
+ " /Library/Application Support/ClaudeCode/managed-settings.json (macOS)",
6
+ " Or via Claude.ai Admin > Claude Code > Managed Settings",
7
+ "",
8
+ "These rules have the HIGHEST precedence and CANNOT be overridden by",
9
+ "user, project, or local settings. They are the ultimate security gate."
10
+ ],
11
+ "permissions": {
12
+ "deny": [
13
+ "Bash(aws * delete-*:*)",
14
+ "Bash(aws * terminate-*:*)",
15
+ "Bash(az * delete:*)",
16
+ "Bash(gcloud * delete:*)",
17
+ "Bash(gsutil rb:*)",
18
+ "Bash(gsutil rm:*)",
19
+ "Bash(gcloud storage rm:*)",
20
+ "Bash(kubectl delete:*)",
21
+ "Bash(kubectl drain:*)",
22
+ "Bash(terraform destroy:*)",
23
+ "Bash(terragrunt destroy:*)",
24
+ "Bash(terragrunt run-all destroy:*)",
25
+ "Bash(helm uninstall:*)",
26
+ "Bash(helm delete:*)",
27
+ "Bash(flux uninstall:*)",
28
+ "Bash(docker system prune:*)",
29
+ "Bash(docker volume prune:*)",
30
+ "Bash(git push --force:*)",
31
+ "Bash(git push -f:*)",
32
+ "Bash(git reset --hard:*)",
33
+ "Bash(gh repo delete:*)",
34
+ "Bash(glab project delete:*)",
35
+ "Bash(dd:*)",
36
+ "Bash(fdisk:*)",
37
+ "Bash(mkfs:*)",
38
+ "Bash(mkfs.*:*)"
39
+ ]
40
+ },
41
+ "disableBypassPermissionsMode": "disable",
42
+ "allowManagedHooksOnly": false
43
+ }
@@ -352,6 +352,39 @@ class HookRunner:
352
352
 
353
353
  return base_dir
354
354
 
355
+ # Tools that the orchestrator is allowed to use directly.
356
+ # Payloads for these tools should NOT get agent_id injected, because
357
+ # they are orchestrator-level operations (dispatch, communication).
358
+ _ORCHESTRATOR_TOOLS = frozenset({
359
+ "agent", "task", "sendmessage", "skill",
360
+ "taskcreate", "taskupdate", "tasklist", "taskget",
361
+ "toolsearch", "websearch", "webfetch", "askuserquestion",
362
+ "stop", # stop_hook payloads are not subject to delegate mode
363
+ })
364
+
365
+ def _prepare_payload(self, event: ReplayEvent) -> str:
366
+ """Serialize the event payload for the hook subprocess.
367
+
368
+ Injects ``agent_id`` into tool-call payloads that lack one, so
369
+ delegate mode recognises them as subagent context instead of
370
+ blocking them as orchestrator calls. Agent/SendMessage/Task
371
+ payloads are left untouched since the orchestrator context is
372
+ correct for those.
373
+
374
+ Args:
375
+ event: The ReplayEvent being replayed.
376
+
377
+ Returns:
378
+ JSON string to feed to the hook subprocess via stdin.
379
+ """
380
+ payload = event.stdin_payload
381
+ tool_name = (payload.get("tool_name") or event.tool_name or "").lower()
382
+
383
+ if not payload.get("agent_id") and tool_name not in self._ORCHESTRATOR_TOOLS:
384
+ payload = {**payload, "agent_id": "replay-simulator"}
385
+
386
+ return json.dumps(payload)
387
+
355
388
  def _resolve_hook_script(self, hook_name: str) -> Path:
356
389
  """Resolve hook name to script path.
357
390
 
@@ -403,7 +436,7 @@ class HookRunner:
403
436
  try:
404
437
  result = subprocess.run(
405
438
  [sys.executable, str(script_path)],
406
- input=json.dumps(event.stdin_payload),
439
+ input=self._prepare_payload(event),
407
440
  capture_output=True,
408
441
  text=True,
409
442
  env=env,
@@ -37,6 +37,7 @@ from tools.scan.merge import (
37
37
  )
38
38
  from tools.scan.registry import ScannerRegistry
39
39
  from tools.scan.scanners.base import BaseScanner, ScanResult
40
+ from tools.scan.workspace import WorkspaceInfo, detect_workspace_type
40
41
 
41
42
  logger = logging.getLogger(__name__)
42
43
 
@@ -267,12 +268,24 @@ class ScanOrchestrator:
267
268
  existing_sections = existing_full.get("sections", {})
268
269
  existing_metadata = existing_full.get("metadata", {})
269
270
 
271
+ # Step 1.5: Detect workspace type BEFORE running scanners
272
+ workspace_info = detect_workspace_type(root)
273
+ if workspace_info.is_multi_repo:
274
+ logger.info(
275
+ "Multi-repo workspace: %d repos detected",
276
+ len(workspace_info.repo_dirs),
277
+ )
278
+
270
279
  # Step 2: Run all scanners
271
280
  scanners = self.registry.get_all()
272
281
  if self.config.scanners:
273
282
  requested = set(self.config.scanners)
274
283
  scanners = [s for s in scanners if s.SCANNER_NAME in requested]
275
284
 
285
+ # Pass workspace info to each scanner instance
286
+ for scanner in scanners:
287
+ scanner.workspace_info = workspace_info
288
+
276
289
  scanner_results: Dict[str, ScanResult] = {}
277
290
  all_warnings: List[str] = []
278
291
  all_errors: List[str] = []
@@ -53,8 +53,16 @@ class BaseScanner(ABC):
53
53
  Performance:
54
54
  - SHOULD complete in under 3 seconds for typical projects
55
55
  - MUST respect 2-second timeout for --version calls
56
+
57
+ Optional workspace_info attribute:
58
+ - Set by the orchestrator before scan() when workspace type has been
59
+ pre-detected. Scanners can check self.workspace_info for multi-repo
60
+ awareness. Defaults to None (single-repo assumed).
56
61
  """
57
62
 
63
+ def __init__(self) -> None:
64
+ self.workspace_info = None # Set by orchestrator if available
65
+
58
66
  @property
59
67
  @abstractmethod
60
68
  def SCANNER_NAME(self) -> str: