@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,210 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ decide-status.py
4
+
5
+ Mechanically decide what to do based on numbers alone. No LLM judgment.
6
+
7
+ Usage:
8
+ python3 decide-status.py \
9
+ --current 94.5 \
10
+ --best 92.0 \
11
+ --threshold 98 \
12
+ --direction higher \
13
+ --consecutive-discards 2 \
14
+ --pivot-count 1
15
+
16
+ Output JSON:
17
+ {
18
+ "decision": "keep",
19
+ "reason": "Metric improved from 92.0 to 94.5",
20
+ "improved": true,
21
+ "gap_remaining": 3.5
22
+ }
23
+
24
+ Decision precedence (evaluated top-to-bottom, first match wins):
25
+ 1. pivot_count >= 3 → stop
26
+ 2. consecutive_discards >= 5 → pivot (also a discard)
27
+ 3. consecutive_discards >= 3 → refine (also a discard)
28
+ 4. current meets or passes threshold → threshold_reached
29
+ 5. current improved vs best (per direction) → keep
30
+ 6. current same or worse → discard
31
+
32
+ Exit codes:
33
+ 0 success (decision emitted as JSON)
34
+ 1 invalid input
35
+ """
36
+
37
+ import argparse
38
+ import json
39
+ import sys
40
+
41
+
42
+ Decision = str # type alias for readability
43
+
44
+
45
+ def _is_improved(current: float, best: float, direction: str) -> bool:
46
+ """Return True if *current* is strictly better than *best* per direction."""
47
+ if direction == "higher":
48
+ return current > best
49
+ return current < best # lower is better
50
+
51
+
52
+ def _threshold_reached(current: float, threshold: float, direction: str) -> bool:
53
+ """Return True if *current* has met or surpassed *threshold*."""
54
+ if direction == "higher":
55
+ return current >= threshold
56
+ return current <= threshold
57
+
58
+
59
+ def _gap_remaining(current: float, threshold: float, direction: str) -> float:
60
+ """Absolute gap between current value and threshold."""
61
+ if direction == "higher":
62
+ return max(0.0, threshold - current)
63
+ return max(0.0, current - threshold)
64
+
65
+
66
+ def decide(
67
+ current: float,
68
+ best: float,
69
+ threshold: float,
70
+ direction: str,
71
+ consecutive_discards: int,
72
+ pivot_count: int,
73
+ ) -> dict:
74
+ """Pure function: return decision dict from numeric inputs."""
75
+
76
+ gap = _gap_remaining(current, threshold, direction)
77
+ improved = _is_improved(current, best, direction)
78
+
79
+ # --- Precedence 1: hard stop on too many pivots ---
80
+ if pivot_count >= 3:
81
+ return {
82
+ "decision": "stop",
83
+ "reason": f"pivot_count={pivot_count} has reached the maximum of 3; halting loop",
84
+ "improved": improved,
85
+ "gap_remaining": gap,
86
+ }
87
+
88
+ # --- Precedence 2 & 3: discard streak escalations ---
89
+ # Evaluated before threshold/keep so an ongoing failing streak is flagged
90
+ # even if the current run happens to reach the threshold.
91
+ if consecutive_discards >= 5:
92
+ return {
93
+ "decision": "pivot",
94
+ "reason": (
95
+ f"consecutive_discards={consecutive_discards} >= 5; "
96
+ "strategy is not working, force a pivot"
97
+ ),
98
+ "improved": improved,
99
+ "gap_remaining": gap,
100
+ }
101
+
102
+ if consecutive_discards >= 3:
103
+ return {
104
+ "decision": "refine",
105
+ "reason": (
106
+ f"consecutive_discards={consecutive_discards} >= 3; "
107
+ "current approach needs refinement before continuing"
108
+ ),
109
+ "improved": improved,
110
+ "gap_remaining": gap,
111
+ }
112
+
113
+ # --- Precedence 4: threshold reached ---
114
+ if _threshold_reached(current, threshold, direction):
115
+ return {
116
+ "decision": "threshold_reached",
117
+ "reason": (
118
+ f"current={current} {'≥' if direction == 'higher' else '≤'} "
119
+ f"threshold={threshold}; goal achieved"
120
+ ),
121
+ "improved": improved,
122
+ "gap_remaining": 0.0,
123
+ }
124
+
125
+ # --- Precedence 5 & 6: standard keep/discard ---
126
+ if improved:
127
+ return {
128
+ "decision": "keep",
129
+ "reason": f"Metric improved from {best} to {current}",
130
+ "improved": True,
131
+ "gap_remaining": gap,
132
+ }
133
+
134
+ return {
135
+ "decision": "discard",
136
+ "reason": f"Metric did not improve (current={current}, best={best})",
137
+ "improved": False,
138
+ "gap_remaining": gap,
139
+ }
140
+
141
+
142
+ def main() -> None:
143
+ parser = argparse.ArgumentParser(
144
+ description="Compute the next agentic-loop decision from metric numbers only.",
145
+ formatter_class=argparse.RawDescriptionHelpFormatter,
146
+ epilog="""
147
+ Decisions:
148
+ keep current improved vs best
149
+ discard current same or worse
150
+ refine 3+ consecutive discards (improvement needed in approach)
151
+ pivot 5+ consecutive discards (strategy change required)
152
+ stop 3+ pivots already attempted
153
+ threshold_reached current meets or surpasses the goal threshold
154
+
155
+ Direction values:
156
+ higher larger numbers are better (e.g. accuracy, passing tests)
157
+ lower smaller numbers are better (e.g. error rate, latency ms)
158
+ """,
159
+ )
160
+ parser.add_argument("--current", required=True, type=float, help="Metric value for the current run")
161
+ parser.add_argument("--best", required=True, type=float, help="Best metric seen so far (from state.json)")
162
+ parser.add_argument("--threshold", required=True, type=float, help="Target threshold to reach")
163
+ parser.add_argument(
164
+ "--direction",
165
+ required=True,
166
+ choices=["higher", "lower"],
167
+ help="Whether higher or lower values are better",
168
+ )
169
+ parser.add_argument(
170
+ "--consecutive-discards",
171
+ required=True,
172
+ type=int,
173
+ metavar="N",
174
+ help="Number of consecutive discard outcomes so far (from state.json)",
175
+ )
176
+ parser.add_argument(
177
+ "--pivot-count",
178
+ required=True,
179
+ type=int,
180
+ metavar="N",
181
+ help="Number of pivots executed so far (from state.json)",
182
+ )
183
+ args = parser.parse_args()
184
+
185
+ # --- Input validation ---
186
+ errors = []
187
+ if args.consecutive_discards < 0:
188
+ errors.append("--consecutive-discards must be >= 0")
189
+ if args.pivot_count < 0:
190
+ errors.append("--pivot-count must be >= 0")
191
+
192
+ if errors:
193
+ for err in errors:
194
+ print(f"error: {err}", file=sys.stderr)
195
+ sys.exit(1)
196
+
197
+ result = decide(
198
+ current=args.current,
199
+ best=args.best,
200
+ threshold=args.threshold,
201
+ direction=args.direction,
202
+ consecutive_discards=args.consecutive_discards,
203
+ pivot_count=args.pivot_count,
204
+ )
205
+
206
+ print(json.dumps(result, indent=2))
207
+
208
+
209
+ if __name__ == "__main__":
210
+ main()
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ parse-metric.py
4
+
5
+ Read stdout from eval_command and extract METRIC lines.
6
+
7
+ Usage:
8
+ echo "output" | python3 parse-metric.py --metric accuracy
9
+ python3 parse-metric.py --metric accuracy --file /tmp/eval-output.txt
10
+
11
+ Input lines must match: METRIC {name}={number}
12
+ Output: JSON to stdout with metric name, numeric value, and raw line.
13
+ """
14
+
15
+ import argparse
16
+ import json
17
+ import re
18
+ import sys
19
+ from typing import Optional
20
+
21
+
22
+ METRIC_PATTERN = re.compile(r"^METRIC\s+(\w+)=([\d.]+)\s*$")
23
+
24
+
25
+ def parse_lines(lines: list[str]) -> list[dict]:
26
+ """Extract all METRIC entries from a sequence of lines."""
27
+ results = []
28
+ for line in lines:
29
+ stripped = line.rstrip("\n")
30
+ match = METRIC_PATTERN.match(stripped)
31
+ if match:
32
+ name = match.group(1)
33
+ raw_value = match.group(2)
34
+ # Preserve int vs float from the source text.
35
+ value: int | float
36
+ if "." in raw_value:
37
+ value = float(raw_value)
38
+ else:
39
+ value = int(raw_value)
40
+ results.append(
41
+ {
42
+ "metric": name,
43
+ "value": value,
44
+ "raw_line": stripped,
45
+ }
46
+ )
47
+ return results
48
+
49
+
50
+ def main() -> None:
51
+ parser = argparse.ArgumentParser(
52
+ description="Extract METRIC lines from eval_command output.",
53
+ formatter_class=argparse.RawDescriptionHelpFormatter,
54
+ epilog="""
55
+ Examples:
56
+ echo "METRIC accuracy=94.5" | python3 parse-metric.py --metric accuracy
57
+ python3 parse-metric.py --metric passing_tests --file /tmp/out.txt
58
+ python3 parse-metric.py --file /tmp/out.txt # returns all metrics
59
+ """,
60
+ )
61
+ parser.add_argument(
62
+ "--metric",
63
+ metavar="NAME",
64
+ help="Return only this named metric (case-sensitive). Exits 1 if not found.",
65
+ )
66
+ parser.add_argument(
67
+ "--file",
68
+ metavar="PATH",
69
+ help="Read from file instead of stdin.",
70
+ )
71
+ args = parser.parse_args()
72
+
73
+ # --- Read input ---
74
+ try:
75
+ if args.file:
76
+ with open(args.file, "r") as fh:
77
+ lines = fh.readlines()
78
+ else:
79
+ lines = sys.stdin.readlines()
80
+ except OSError as exc:
81
+ print(f"error: cannot read input: {exc}", file=sys.stderr)
82
+ sys.exit(1)
83
+
84
+ # --- Parse ---
85
+ all_metrics = parse_lines(lines)
86
+
87
+ if args.metric:
88
+ # Filter to the requested metric name.
89
+ matches = [m for m in all_metrics if m["metric"] == args.metric]
90
+ if not matches:
91
+ print(
92
+ f"error: metric '{args.metric}' not found in input",
93
+ file=sys.stderr,
94
+ )
95
+ sys.exit(1)
96
+ # Return the last occurrence if there are duplicates.
97
+ result = matches[-1]
98
+ else:
99
+ # Return all metrics as a list when no --metric filter is given.
100
+ result = all_metrics # type: ignore[assignment]
101
+
102
+ print(json.dumps(result, indent=2))
103
+
104
+
105
+ if __name__ == "__main__":
106
+ main()
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ record-iteration.py
4
+
5
+ Atomically update state.json and append to worklog.md after each iteration.
6
+ The LLM never writes state.json directly — this script is the only writer.
7
+
8
+ Usage:
9
+ python3 record-iteration.py \
10
+ --state-file state.json \
11
+ --worklog worklog.md \
12
+ --iteration 5 \
13
+ --metric-value 94.5 \
14
+ --status keep \
15
+ --description "Handle hyphenated verbs" \
16
+ --insight "delete-objects splits correctly" \
17
+ --next "Check camelCase+hyphen combined"
18
+
19
+ Optional flags:
20
+ --changed TEXT What was modified (default: same as description)
21
+ --metric-name TEXT Name of the metric recorded (default: "metric")
22
+
23
+ Atomic write guarantee: state.json is written to a .tmp sibling, fsynced,
24
+ then renamed over the original. Either the full write lands or the original
25
+ is untouched.
26
+ """
27
+
28
+ import argparse
29
+ import json
30
+ import os
31
+ import sys
32
+ import tempfile
33
+ from datetime import datetime, timezone
34
+
35
+
36
+ def load_state(path: str) -> dict:
37
+ """Load existing state.json or return an empty skeleton."""
38
+ if not os.path.exists(path):
39
+ return {
40
+ "iteration": 0,
41
+ "current_metric": None,
42
+ "best_metric": None,
43
+ "consecutive_discards": 0,
44
+ "pivot_count": 0,
45
+ "timestamp": None,
46
+ "status": None,
47
+ }
48
+ try:
49
+ with open(path, "r") as fh:
50
+ data = json.load(fh)
51
+ return data
52
+ except (OSError, json.JSONDecodeError) as exc:
53
+ print(f"error: cannot read state file '{path}': {exc}", file=sys.stderr)
54
+ sys.exit(1)
55
+
56
+
57
+ def atomic_write_json(path: str, data: dict) -> None:
58
+ """Write *data* to *path* atomically using write-fsync-rename."""
59
+ dir_name = os.path.dirname(os.path.abspath(path))
60
+ # Use a temp file in the same directory so rename is on the same filesystem.
61
+ try:
62
+ fd, tmp_path = tempfile.mkstemp(dir=dir_name, suffix=".tmp")
63
+ try:
64
+ with os.fdopen(fd, "w") as fh:
65
+ json.dump(data, fh, indent=2)
66
+ fh.write("\n")
67
+ fh.flush()
68
+ os.fsync(fh.fileno())
69
+ os.replace(tmp_path, path)
70
+ except Exception:
71
+ # Clean up orphaned temp file on failure.
72
+ try:
73
+ os.unlink(tmp_path)
74
+ except OSError:
75
+ pass
76
+ raise
77
+ except OSError as exc:
78
+ print(f"error: atomic write to '{path}' failed: {exc}", file=sys.stderr)
79
+ sys.exit(1)
80
+
81
+
82
+ def append_worklog(
83
+ path: str,
84
+ iteration: int,
85
+ description: str,
86
+ metric_name: str,
87
+ metric_value: float,
88
+ status: str,
89
+ changed: str,
90
+ insight: str,
91
+ next_step: str,
92
+ best_metric: float | None,
93
+ ) -> None:
94
+ """Append a structured run entry to worklog.md."""
95
+ status_upper = status.upper()
96
+
97
+ # Build result sentence
98
+ if best_metric is None:
99
+ result_text = f"{metric_name}={metric_value} (first run, no prior best)"
100
+ else:
101
+ comparison = (
102
+ f"improved from {best_metric}"
103
+ if metric_value > best_metric
104
+ else (
105
+ f"unchanged from {best_metric}"
106
+ if metric_value == best_metric
107
+ else f"regressed from {best_metric}"
108
+ )
109
+ )
110
+ result_text = f"{metric_name}={metric_value} ({comparison})"
111
+
112
+ entry = (
113
+ f"\n### Run {iteration}: {description} — {metric_name}={metric_value} ({status_upper})\n"
114
+ f"- **Changed:** {changed}\n"
115
+ f"- **Result:** {result_text}\n"
116
+ f"- **Insight:** {insight}\n"
117
+ f"- **Next:** {next_step}\n"
118
+ )
119
+
120
+ try:
121
+ with open(path, "a") as fh:
122
+ fh.write(entry)
123
+ except OSError as exc:
124
+ print(f"error: cannot append to worklog '{path}': {exc}", file=sys.stderr)
125
+ sys.exit(1)
126
+
127
+
128
+ def main() -> None:
129
+ parser = argparse.ArgumentParser(
130
+ description="Atomically record an agentic-loop iteration into state.json and worklog.md.",
131
+ formatter_class=argparse.RawDescriptionHelpFormatter,
132
+ epilog="""
133
+ Status values:
134
+ keep — metric improved; best is updated, consecutive_discards reset to 0
135
+ discard — metric did not improve; consecutive_discards incremented
136
+ pivot — forced strategy change (also increments pivot_count)
137
+ stop — terminal state; loop should halt
138
+
139
+ Exit codes:
140
+ 0 success
141
+ 1 error (message on stderr)
142
+ """,
143
+ )
144
+ parser.add_argument("--state-file", required=True, metavar="PATH", help="Path to state.json")
145
+ parser.add_argument("--worklog", required=True, metavar="PATH", help="Path to worklog.md (append-only)")
146
+ parser.add_argument("--iteration", required=True, type=int, help="Current iteration number (1-based)")
147
+ parser.add_argument("--metric-value", required=True, type=float, metavar="NUM", help="Numeric metric value this run")
148
+ parser.add_argument(
149
+ "--status",
150
+ required=True,
151
+ choices=["keep", "discard", "pivot", "stop"],
152
+ help="Outcome classification for this iteration",
153
+ )
154
+ parser.add_argument("--description", required=True, help="Short description of what changed this run")
155
+ parser.add_argument("--insight", required=True, help="What was learned from this run")
156
+ parser.add_argument("--next", required=True, dest="next_step", help="What to try in the next iteration")
157
+ parser.add_argument(
158
+ "--changed",
159
+ default=None,
160
+ metavar="TEXT",
161
+ help="What was specifically modified (defaults to --description)",
162
+ )
163
+ parser.add_argument(
164
+ "--metric-name",
165
+ default="metric",
166
+ metavar="NAME",
167
+ help="Name label for the metric (default: metric)",
168
+ )
169
+ args = parser.parse_args()
170
+
171
+ changed = args.changed if args.changed is not None else args.description
172
+
173
+ # --- Load current state ---
174
+ state = load_state(args.state_file)
175
+
176
+ prev_best: float | None = state.get("best_metric")
177
+
178
+ # --- Compute new state values ---
179
+ state["iteration"] = args.iteration
180
+ state["current_metric"] = args.metric_value
181
+ state["status"] = args.status
182
+ state["timestamp"] = datetime.now(tz=timezone.utc).isoformat()
183
+
184
+ if args.status == "keep":
185
+ # Keep: this run is better; promote to best.
186
+ state["best_metric"] = args.metric_value
187
+ state["consecutive_discards"] = 0
188
+ elif args.status == "discard":
189
+ # Do not update best; increment discard counter.
190
+ state["consecutive_discards"] = int(state.get("consecutive_discards") or 0) + 1
191
+ elif args.status == "pivot":
192
+ # Pivot: counts as a discard for streak purposes, but also advances pivot_count.
193
+ state["consecutive_discards"] = int(state.get("consecutive_discards") or 0) + 1
194
+ state["pivot_count"] = int(state.get("pivot_count") or 0) + 1
195
+ elif args.status == "stop":
196
+ # Terminal — no counter changes needed beyond recording.
197
+ pass
198
+
199
+ # --- Atomic write ---
200
+ atomic_write_json(args.state_file, state)
201
+
202
+ # --- Append worklog ---
203
+ append_worklog(
204
+ path=args.worklog,
205
+ iteration=args.iteration,
206
+ description=args.description,
207
+ metric_name=args.metric_name,
208
+ metric_value=args.metric_value,
209
+ status=args.status,
210
+ changed=changed,
211
+ insight=args.insight,
212
+ next_step=args.next_step,
213
+ best_metric=prev_best,
214
+ )
215
+
216
+ # Emit updated state summary for easy inspection.
217
+ print(json.dumps(state, indent=2))
218
+
219
+
220
+ if __name__ == "__main__":
221
+ main()
@@ -0,0 +1,132 @@
1
+ # Context Module
2
+
3
+ **Purpose:** Context provisioning and enrichment for agents
4
+
5
+ ## Overview
6
+
7
+ This module manages the SSOT (Single Source of Truth) context that agents receive. It loads project configuration, filters by agent contract (defined in `config/context-contracts.json` + cloud extensions), and provides context to agents.
8
+ It also classifies the task into generic Gaia surfaces, emits an `investigation_brief`, and injects `write_permissions` so agents receive deterministic cross-surface guidance and writable-section ownership, not just raw project data.
9
+
10
+ ## Core Functions
11
+
12
+ ### `load_project_context(path)`
13
+ Loads the project-context.json file.
14
+
15
+ ```python
16
+ from tools.context.context_provider import load_project_context
17
+ context = load_project_context(Path(".claude/project-context/project-context.json"))
18
+ ```
19
+
20
+ ### `get_contract_context(project_context, agent_name, provider_contracts)`
21
+ Gets the specific context needed for an agent based on its contract.
22
+
23
+ ```python
24
+ from tools.context.context_provider import get_contract_context
25
+ contract_context = get_contract_context(
26
+ project_context,
27
+ "terraform-architect",
28
+ provider_contracts
29
+ )
30
+ ```
31
+
32
+ ### `get_context_update_contract(agent_name, provider_contracts)`
33
+ Gets the readable/writable section contract that governs `CONTEXT_UPDATE`.
34
+
35
+ ```python
36
+ from tools.context.context_provider import get_context_update_contract
37
+ update_contract = get_context_update_contract("terraform-architect", provider_contracts)
38
+ ```
39
+
40
+ ### `load_provider_contracts(cloud_provider)`
41
+ Loads cloud provider-specific agent contracts (GCP, AWS).
42
+
43
+ ```python
44
+ from tools.context.context_provider import load_provider_contracts
45
+ contracts = load_provider_contracts("gcp")
46
+ ```
47
+
48
+ ### `classify_surfaces(task, current_agent=...)`
49
+ Classifies a task into one or more active Gaia surfaces using generic signals.
50
+
51
+ ```python
52
+ from tools.context.surface_router import classify_surfaces
53
+ routing = classify_surfaces("Investigate rollout failure after CI image change", current_agent="gitops-operator")
54
+ ```
55
+
56
+ ### `build_investigation_brief(task, agent_name, contract_context)`
57
+ Builds the deterministic investigation brief injected into project context.
58
+
59
+ ```python
60
+ from tools.context.surface_router import build_investigation_brief
61
+ brief = build_investigation_brief("Review hook/skill drift", "gaia-system", contract_context={})
62
+ ```
63
+
64
+ ## Core Classes
65
+
66
+ ### `ContextSectionReader`
67
+ Selective context loading for token optimization.
68
+
69
+ ```python
70
+ from tools.context.context_section_reader import ContextSectionReader
71
+ reader = ContextSectionReader(project_context)
72
+ sections = reader.get_sections_for_agent("gitops-operator")
73
+ ```
74
+
75
+ ## Agent Contracts
76
+
77
+ Each agent receives specific v2 context sections (defined in `config/context-contracts.json` v3):
78
+
79
+ **terraform-architect:**
80
+ - project_identity, stack, git, environment, infrastructure, orchestration
81
+ - terraform_infrastructure, infrastructure_topology
82
+ - operational_guidelines, cluster_details, application_services, architecture_overview
83
+
84
+ **gitops-operator:**
85
+ - project_identity, stack, git, environment, infrastructure, orchestration
86
+ - gitops_configuration, cluster_details
87
+ - operational_guidelines, application_services, architecture_overview
88
+
89
+ **cloud-troubleshooter:**
90
+ - project_identity, stack, git, environment, infrastructure, orchestration
91
+ - cluster_details, infrastructure_topology, terraform_infrastructure
92
+ - gitops_configuration, application_services, monitoring_observability, architecture_overview
93
+
94
+ The same contracts are also exposed under `write_permissions`:
95
+ - `readable_sections`
96
+ - `writable_sections`
97
+
98
+ Agents should use the injected `write_permissions`, not a hardcoded table in a skill,
99
+ when deciding whether a `CONTEXT_UPDATE` is allowed.
100
+
101
+ ## Command Line Usage
102
+
103
+ ```bash
104
+ python3 tools/context/context_provider.py terraform-architect "Create a VPC" \
105
+ --context-file .claude/project-context/project-context.json
106
+ ```
107
+
108
+ ## Files
109
+
110
+ ```
111
+ context/
112
+ ├── __init__.py # Public exports (re-exports from context_provider + surface_router)
113
+ ├── _paths.py # Shared config directory resolution (resolve_config_dir)
114
+ ├── context_provider.py # Main context provisioning logic
115
+ ├── surface_router.py # Surface classification + investigation brief
116
+ ├── context_section_reader.py # Token-optimized context extraction
117
+ ├── context_selector.py # Context selection logic
118
+ ├── context_compressor.py # Context compression for token optimization
119
+ ├── context_lazy_loader.py # Lazy loading for large contexts
120
+ ├── deep_merge.py # Deep merge utility for contract merging
121
+ ├── pending_updates.py # Pending context update management
122
+ ├── benchmark_context.py # Performance benchmarking
123
+ └── README.md
124
+ ```
125
+
126
+ ## See Also
127
+
128
+ - `config/context-contracts.json` - Agent contracts (SSOT)
129
+ - `config/cloud/gcp.json` - GCP-specific contract extensions
130
+ - `config/cloud/aws.json` - AWS-specific contract extensions
131
+ - `hooks/modules/context/context_writer.py` - Context write operations
132
+ - `tests/tools/test_context_provider.py` - Test suite