@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,635 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @jaguilar87/gaia - Health Check CLI
5
+ *
6
+ * Verifies the complete Gaia-Ops installation is healthy.
7
+ * Run after install, update, or when things seem broken.
8
+ *
9
+ * Checks (in order):
10
+ * 1. Gaia-Ops version - package.json readable
11
+ * 2. Claude Code - CLI installed (prerequisite)
12
+ * 3. Python - Python 3.9+ available (hooks need it)
13
+ * 4. Plugin mode - ops vs security, registry valid
14
+ * 5. Symlinks - .claude/ symlinks resolve to package content
15
+ * 6. Identity - orchestrator agent configured in settings
16
+ * 7. Settings - hooks registered, permissions, deny rules
17
+ * 8. Hook files - all hook scripts present on disk
18
+ * 9. project-context - project-context.json valid and enriched
19
+ * 10. Project dirs - paths declared in context exist
20
+ * 11. Memory dirs - episodic memory dirs present
21
+ *
22
+ * Severity levels:
23
+ * pass - check passed
24
+ * info - informational, not an issue
25
+ * warning - degrades functionality
26
+ * error - critical, Gaia will not work
27
+ *
28
+ * Usage:
29
+ * npx gaia-doctor # Full health check
30
+ * npx gaia-doctor --fix # Attempt auto-fix for common issues
31
+ * npx gaia-doctor --json # Output as JSON (for CI)
32
+ */
33
+
34
+ import { fileURLToPath } from 'url';
35
+ import { dirname, join, relative } from 'path';
36
+ import fs from 'fs/promises';
37
+ import { existsSync } from 'fs';
38
+ import { exec } from 'child_process';
39
+ import { promisify } from 'util';
40
+ import { findPython } from './python-detect.js';
41
+ import chalk from 'chalk';
42
+ import yargs from 'yargs';
43
+ import { hideBin } from 'yargs/helpers';
44
+
45
+ const execAsync = promisify(exec);
46
+ const __filename = fileURLToPath(import.meta.url);
47
+ const __dirname = dirname(__filename);
48
+ const CWD = process.cwd();
49
+
50
+ // ============================================================================
51
+ // Severity helpers
52
+ // ============================================================================
53
+
54
+ /** Create a check result with explicit severity. */
55
+ function result(name, severity, detail, fix = null) {
56
+ // Backward-compatible `ok` field: pass and info are considered ok
57
+ const ok = severity === 'pass' || severity === 'info';
58
+ return { name, severity, ok, detail, ...(fix ? { fix } : {}) };
59
+ }
60
+
61
+ // ============================================================================
62
+ // Health Checks
63
+ // ============================================================================
64
+
65
+ async function checkGaiaVersion() {
66
+ try {
67
+ const pkg = JSON.parse(await fs.readFile(join(__dirname, '..', 'package.json'), 'utf-8'));
68
+ return result('Gaia-Ops', 'pass', `v${pkg.version}`);
69
+ } catch {
70
+ return result('Gaia-Ops', 'error', 'Version unknown', 'Reinstall @jaguilar87/gaia');
71
+ }
72
+ }
73
+
74
+ async function checkPluginMode() {
75
+ // Determine plugin mode (ops vs security) and verify the registry.
76
+ const registryPath = join(CWD, '.claude', 'plugin-registry.json');
77
+
78
+ if (!existsSync(registryPath)) {
79
+ return result('Plugin mode', 'warning', 'No plugin-registry.json', 'Run gaia-scan or restart Claude Code');
80
+ }
81
+
82
+ try {
83
+ const registry = JSON.parse(await fs.readFile(registryPath, 'utf-8'));
84
+ const installed = (registry.installed || []).map(p => p.name);
85
+ const source = registry.source || 'unknown';
86
+
87
+ if (installed.includes('gaia-ops')) {
88
+ return result('Plugin mode', 'pass', `ops (source: ${source})`);
89
+ } else if (installed.includes('gaia-security')) {
90
+ return result('Plugin mode', 'pass', `security (source: ${source})`);
91
+ } else {
92
+ return result('Plugin mode', 'warning', `Unknown plugin: ${installed.join(', ')}`, 'Verify installation');
93
+ }
94
+ } catch {
95
+ return result('Plugin mode', 'warning', 'Invalid plugin-registry.json', 'Delete and restart Claude Code');
96
+ }
97
+ }
98
+
99
+ async function checkSymlinks() {
100
+ const names = ['agents', 'tools', 'hooks', 'commands', 'templates', 'config', 'skills', 'CHANGELOG.md'];
101
+ // Critical symlinks that break core functionality if missing
102
+ const critical = new Set(['agents', 'hooks', 'skills']);
103
+ const sub = [];
104
+ let valid = 0;
105
+ let hasCriticalMissing = false;
106
+
107
+ for (const name of names) {
108
+ const linkPath = join(CWD, '.claude', name);
109
+ const exists = existsSync(linkPath);
110
+
111
+ if (exists) {
112
+ try {
113
+ await fs.realpath(linkPath);
114
+ valid++;
115
+ sub.push({ name, status: 'ok' });
116
+ } catch {
117
+ if (critical.has(name)) hasCriticalMissing = true;
118
+ sub.push({ name, status: 'broken', fix: `rm .claude/${name} && gaia-scan` });
119
+ }
120
+ } else {
121
+ if (critical.has(name)) hasCriticalMissing = true;
122
+ sub.push({ name, status: 'missing', fix: 'Run gaia-scan to recreate' });
123
+ }
124
+ }
125
+
126
+ if (valid === names.length) {
127
+ return { ...result('Symlinks', 'pass', `${valid}/${names.length} valid`), sub };
128
+ }
129
+
130
+ const severity = hasCriticalMissing ? 'error' : 'warning';
131
+ return {
132
+ ...result('Symlinks', severity, `${valid}/${names.length} valid`, 'Run gaia-scan to recreate symlinks'),
133
+ sub
134
+ };
135
+ }
136
+
137
+ async function checkIdentity() {
138
+ // Identity is defined in the orchestrator agent definition (.md file) and
139
+ // activated by the `agent` field in settings.local.json. CLAUDE.md is no
140
+ // longer used and should not be present.
141
+ const issues = [];
142
+ const infos = [];
143
+
144
+ // 1. Check that orchestrator agent definition exists
145
+ const agentPath = join(CWD, '.claude', 'agents', 'gaia-orchestrator.md');
146
+ if (!existsSync(agentPath)) {
147
+ issues.push('gaia-orchestrator.md not found');
148
+ }
149
+
150
+ // 2. Check that settings.local.json has `agent` field pointing to orchestrator
151
+ const localSettingsPath = join(CWD, '.claude', 'settings.local.json');
152
+ if (existsSync(localSettingsPath)) {
153
+ try {
154
+ const data = JSON.parse(await fs.readFile(localSettingsPath, 'utf-8'));
155
+ if (data.agent === 'gaia-orchestrator') {
156
+ // pass -- correct agent configured
157
+ } else if (data.agent) {
158
+ issues.push(`Agent set to "${data.agent}" (expected "gaia-orchestrator")`);
159
+ } else {
160
+ issues.push('No agent field in settings.local.json');
161
+ }
162
+ } catch { /* handled by settings check */ }
163
+ } else {
164
+ issues.push('settings.local.json missing');
165
+ }
166
+
167
+ // 3. Warn if legacy CLAUDE.md is still present
168
+ const claudeMdPath = join(CWD, 'CLAUDE.md');
169
+ if (existsSync(claudeMdPath)) {
170
+ infos.push('Legacy CLAUDE.md present (no longer used)');
171
+ }
172
+
173
+ if (issues.length > 0) {
174
+ return result('Identity', 'error', issues.join('; '), 'Run gaia-scan or npx gaia-update');
175
+ }
176
+
177
+ if (infos.length > 0) {
178
+ return result('Identity', 'info', `Orchestrator configured -- ${infos.join('; ')}`);
179
+ }
180
+
181
+ return result('Identity', 'pass', 'Orchestrator agent configured');
182
+ }
183
+
184
+ async function checkSettings() {
185
+ // Configuration lives in settings.local.json (hooks, permissions, agent, env).
186
+ // settings.json exists for Claude Code to detect the project but may be empty.
187
+ const localPath = join(CWD, '.claude', 'settings.local.json');
188
+
189
+ if (!existsSync(localPath)) {
190
+ return result('Settings', 'error', 'settings.local.json missing', 'Run gaia-scan or npx gaia-update');
191
+ }
192
+
193
+ try {
194
+ const data = JSON.parse(await fs.readFile(localPath, 'utf-8'));
195
+ const issues = [];
196
+ const infos = [];
197
+
198
+ // Check hooks configuration
199
+ const hooksConfig = data.hooks || null;
200
+ if (!hooksConfig) {
201
+ issues.push('No hooks configured');
202
+ } else {
203
+ const hookTypes = Object.keys(hooksConfig);
204
+ const required = ['PreToolUse', 'PostToolUse', 'UserPromptSubmit', 'SessionStart'];
205
+ const missing = required.filter(h => !hookTypes.includes(h));
206
+ if (missing.length > 0) {
207
+ issues.push(`Missing hooks: ${missing.join(', ')}`);
208
+ }
209
+ }
210
+
211
+ // Check permissions
212
+ const perms = data.permissions || {};
213
+ const allowCount = (perms.allow || []).length;
214
+ const denyCount = (perms.deny || []).length;
215
+ if (allowCount === 0) {
216
+ infos.push('No allow rules (tools will prompt for approval)');
217
+ }
218
+ if (denyCount === 0) {
219
+ issues.push('No deny rules (destructive commands not blocked)');
220
+ }
221
+
222
+ // Check env vars
223
+ const env = data.env || {};
224
+ if (!env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS) {
225
+ infos.push('AGENT_TEAMS env not set');
226
+ }
227
+
228
+ if (issues.length > 0) {
229
+ return result('Settings', 'error', issues.join('; '), 'Run gaia-scan or npx gaia-update');
230
+ }
231
+
232
+ const hookCount = hooksConfig ? Object.keys(hooksConfig).length : 0;
233
+ const permCount = allowCount + denyCount;
234
+
235
+ if (infos.length > 0) {
236
+ return result('Settings', 'info', `${hookCount} hook types, ${permCount} rules -- ${infos.join('; ')}`);
237
+ }
238
+
239
+ return result('Settings', 'pass', `${hookCount} hook types, ${permCount} rules`);
240
+ } catch {
241
+ return result('Settings', 'error', 'Invalid JSON in settings.local.json', 'Delete and run gaia-scan');
242
+ }
243
+ }
244
+
245
+ async function checkProjectContext() {
246
+ const path = join(CWD, '.claude', 'project-context', 'project-context.json');
247
+
248
+ if (!existsSync(path)) {
249
+ return result('project-context', 'warning', 'Missing', 'Run gaia-scan');
250
+ }
251
+
252
+ try {
253
+ const data = JSON.parse(await fs.readFile(path, 'utf-8'));
254
+ const warnings = [];
255
+ const infos = [];
256
+
257
+ if (!data.metadata) warnings.push('Missing metadata section');
258
+ if (!data.sections) warnings.push('Missing sections');
259
+
260
+ // Detect schema version: v2.0 uses metadata.version, v1.0 does not
261
+ const isV2 = data.metadata?.version === '2.0' || data.metadata?.created_by === 'gaia-scan';
262
+
263
+ // Check paths: v2.0 uses sections.infrastructure.paths, v1.0 uses top-level paths
264
+ const hasPaths = isV2
265
+ ? !!data.sections?.infrastructure?.paths
266
+ : !!data.paths;
267
+ if (!hasPaths) infos.push('No paths section');
268
+
269
+ // Cloud provider and region are informational -- not all projects use cloud
270
+ if (data.metadata) {
271
+ const cloudProvider = isV2
272
+ ? data.sections?.infrastructure?.cloud_providers?.[0]?.name
273
+ : data.metadata.cloud_provider;
274
+ if (!cloudProvider) infos.push('No cloud provider set');
275
+
276
+ const region = isV2
277
+ ? data.sections?.terraform_infrastructure?.provider_credentials?.gcp?.region
278
+ : data.metadata.primary_region;
279
+ if (!isV2 && !region) infos.push('No region set');
280
+ }
281
+
282
+ if (data.sections) {
283
+ const sectionCount = Object.keys(data.sections).length;
284
+ if (sectionCount < 3) infos.push(`Only ${sectionCount} sections (expected >=3)`);
285
+ }
286
+
287
+ // Warnings are real problems
288
+ if (warnings.length > 0) {
289
+ const detail = [...warnings, ...infos].join('; ');
290
+ return result('project-context', 'warning', detail, 'Run gaia-scan to enrich');
291
+ }
292
+
293
+ // Info-only items are not problems
294
+ if (infos.length > 0) {
295
+ const sectionCount = data.sections ? Object.keys(data.sections).length : 0;
296
+ return result('project-context', 'info', `${sectionCount} sections -- ${infos.join('; ')}`);
297
+ }
298
+
299
+ const sectionCount = Object.keys(data.sections).length;
300
+ const cloud = isV2
301
+ ? (data.sections?.infrastructure?.cloud_providers?.[0]?.name?.toUpperCase() || '?')
302
+ : (data.metadata.cloud_provider?.toUpperCase() || '?');
303
+ return result('project-context', 'pass', `${sectionCount} sections, ${cloud}`);
304
+ } catch {
305
+ return result('project-context', 'warning', 'Invalid JSON', 'Regenerate with gaia-scan');
306
+ }
307
+ }
308
+
309
+ async function checkPython() {
310
+ const pyCmd = findPython();
311
+ if (!pyCmd) {
312
+ return result('Python', 'error', 'Not found (hooks require Python)', 'Install Python 3.9+');
313
+ }
314
+
315
+ try {
316
+ const { stdout } = await execAsync(`${pyCmd} --version`);
317
+ const version = stdout.trim();
318
+ const match = version.match(/(\d+)\.(\d+)/);
319
+
320
+ if (match) {
321
+ const major = parseInt(match[1]);
322
+ const minor = parseInt(match[2]);
323
+ if (major < 3 || (major === 3 && minor < 9)) {
324
+ return result('Python', 'error', `${version} (need >=3.9)`, 'Upgrade Python to 3.9+');
325
+ }
326
+ }
327
+
328
+ return result('Python', 'pass', version);
329
+ } catch {
330
+ return result('Python', 'error', 'Not found (hooks require Python)', 'Install Python 3.9+');
331
+ }
332
+ }
333
+
334
+ async function checkClaudeCode() {
335
+ try {
336
+ const { stdout } = await execAsync('claude --version 2>/dev/null || claude-code --version 2>/dev/null');
337
+ return result('Claude Code', 'pass', stdout.trim().split('\n')[0]);
338
+ } catch {
339
+ // Claude Code is a prerequisite, not a Gaia issue -- informational only
340
+ return result('Claude Code', 'info', 'Not installed', 'npm install -g @anthropic-ai/claude-code');
341
+ }
342
+ }
343
+
344
+ async function checkHooks() {
345
+ // Hook files that must exist for Gaia to function.
346
+ // Required: break core functionality if missing.
347
+ // Expected: part of the standard pipeline but non-fatal if absent.
348
+ const hooks = [
349
+ { file: 'pre_tool_use.py', required: true },
350
+ { file: 'post_tool_use.py', required: true },
351
+ { file: 'user_prompt_submit.py', required: true },
352
+ { file: 'session_start.py', required: true },
353
+ { file: 'subagent_stop.py', expected: true },
354
+ { file: 'subagent_start.py', expected: true },
355
+ { file: 'stop_hook.py', expected: true },
356
+ { file: 'task_completed.py', expected: true },
357
+ { file: 'post_compact.py', expected: true },
358
+ { file: 'elicitation_result.py', expected: true }
359
+ ];
360
+
361
+ const errors = [];
362
+ const warnings = [];
363
+ let valid = 0;
364
+
365
+ for (const { file, required, expected } of hooks) {
366
+ const hookPath = join(CWD, '.claude', 'hooks', file);
367
+ if (existsSync(hookPath)) {
368
+ valid++;
369
+ } else if (required) {
370
+ errors.push(`${file} missing`);
371
+ } else if (expected) {
372
+ warnings.push(file);
373
+ }
374
+ }
375
+
376
+ if (errors.length > 0) {
377
+ return result('Hook files', 'error', errors.join('; '), 'Recreate symlinks: gaia-scan');
378
+ }
379
+
380
+ if (warnings.length > 0) {
381
+ return result('Hook files', 'warning', `${valid}/${hooks.length} found (missing: ${warnings.join(', ')})`, 'Run gaia-scan to recreate symlinks');
382
+ }
383
+
384
+ return result('Hook files', 'pass', `${valid}/${hooks.length} found`);
385
+ }
386
+
387
+ async function checkMemoryDirs() {
388
+ // Each memory dir has its own severity -- some are auto-created, some need manual setup
389
+ const checks = [
390
+ {
391
+ path: join(CWD, '.claude', 'project-context', 'workflow-episodic-memory'),
392
+ label: 'workflow-episodic-memory',
393
+ severity: 'warning',
394
+ fix: 'Run gaia-scan to create workflow memory directory'
395
+ },
396
+ {
397
+ path: join(CWD, '.claude', 'project-context', 'episodic-memory'),
398
+ label: 'episodic-memory',
399
+ severity: 'info', // Auto-created on first agent run
400
+ fix: 'Created automatically on first agent run'
401
+ },
402
+ ];
403
+
404
+ const warnings = [];
405
+ const infos = [];
406
+ let found = 0;
407
+
408
+ for (const { path, label, severity, fix } of checks) {
409
+ if (existsSync(path)) {
410
+ found++;
411
+ } else if (severity === 'info') {
412
+ infos.push({ label, fix });
413
+ } else {
414
+ warnings.push({ label, fix });
415
+ }
416
+ }
417
+
418
+ if (warnings.length > 0) {
419
+ const detail = warnings.map(i => `${i.label} missing`).join('; ');
420
+ return result('Memory dirs', 'warning', detail, warnings[0].fix);
421
+ }
422
+
423
+ if (infos.length > 0) {
424
+ const detail = `${found}/${checks.length} present (${infos.map(i => `${i.label}: ${i.fix}`).join('; ')})`;
425
+ return result('Memory dirs', 'info', detail);
426
+ }
427
+
428
+ return result('Memory dirs', 'pass', `${found}/${checks.length} present`);
429
+ }
430
+
431
+ async function checkProjectDirs() {
432
+ const contextPath = join(CWD, '.claude', 'project-context', 'project-context.json');
433
+ if (!existsSync(contextPath)) {
434
+ return result('Project dirs', 'pass', 'Skipped (no context)');
435
+ }
436
+
437
+ try {
438
+ const data = JSON.parse(await fs.readFile(contextPath, 'utf-8'));
439
+ // v2.0 stores paths in sections.infrastructure.paths; v1.0 uses top-level paths
440
+ const paths = data.sections?.infrastructure?.paths || data.paths || {};
441
+ const issues = [];
442
+
443
+ for (const [key, dirPath] of Object.entries(paths)) {
444
+ if (dirPath && !existsSync(join(CWD, dirPath))) {
445
+ issues.push(`${key}: ${dirPath} not found`);
446
+ }
447
+ }
448
+
449
+ if (issues.length > 0) {
450
+ return result('Project dirs', 'warning', issues.join('; '), 'Create missing directories or update paths');
451
+ }
452
+
453
+ return result('Project dirs', 'pass', `${Object.keys(paths).length} paths verified`);
454
+ } catch {
455
+ return result('Project dirs', 'pass', 'Skipped (parse error)');
456
+ }
457
+ }
458
+
459
+ // ============================================================================
460
+ // Auto-fix
461
+ // ============================================================================
462
+
463
+ async function autoFix() {
464
+ console.log(chalk.cyan('\n Attempting auto-fix...\n'));
465
+
466
+ let fixed = 0;
467
+
468
+ // Fix broken symlinks
469
+ const claudeDir = join(CWD, '.claude');
470
+ if (existsSync(claudeDir)) {
471
+ const packagePath = join(CWD, 'node_modules', '@jaguilar87', 'gaia-ops');
472
+ if (existsSync(packagePath)) {
473
+ const relPath = relative(claudeDir, packagePath);
474
+ const names = ['agents', 'tools', 'hooks', 'commands', 'templates', 'config', 'skills'];
475
+ // Use junctions on Windows (no admin required), regular symlinks elsewhere
476
+ const linkType = process.platform === 'win32' ? 'junction' : 'dir';
477
+
478
+ for (const name of names) {
479
+ const link = join(claudeDir, name);
480
+ if (!existsSync(link)) {
481
+ try {
482
+ // Junctions on Windows require absolute targets; symlinks on Unix use relative
483
+ const target = process.platform === 'win32'
484
+ ? join(packagePath, name)
485
+ : join(relPath, name);
486
+ await fs.symlink(target, link, linkType);
487
+ console.log(chalk.green(` Fixed: .claude/${name} symlink`));
488
+ fixed++;
489
+ } catch {
490
+ console.log(chalk.red(` Failed: .claude/${name}`));
491
+ }
492
+ }
493
+ }
494
+ }
495
+ }
496
+
497
+ // Create missing project dirs
498
+ const contextPath = join(CWD, '.claude', 'project-context', 'project-context.json');
499
+ if (existsSync(contextPath)) {
500
+ try {
501
+ const data = JSON.parse(await fs.readFile(contextPath, 'utf-8'));
502
+ const paths = data.sections?.infrastructure?.paths || data.paths || {};
503
+ for (const dirPath of Object.values(paths)) {
504
+ const abs = join(CWD, dirPath);
505
+ if (!existsSync(abs)) {
506
+ await fs.mkdir(abs, { recursive: true });
507
+ console.log(chalk.green(` Fixed: Created ${dirPath}`));
508
+ fixed++;
509
+ }
510
+ }
511
+ } catch {
512
+ // Skip
513
+ }
514
+ }
515
+
516
+ console.log(chalk.cyan(`\n ${fixed} issue(s) fixed\n`));
517
+ return fixed;
518
+ }
519
+
520
+ // ============================================================================
521
+ // Display helpers
522
+ // ============================================================================
523
+
524
+ const SEVERITY_ICONS = {
525
+ pass: { icon: '\u2713', color: chalk.green }, // check mark
526
+ info: { icon: '\u2139', color: chalk.cyan }, // info symbol
527
+ warning: { icon: '\u26A0', color: chalk.yellow }, // warning triangle
528
+ error: { icon: '\u2717', color: chalk.red }, // X mark
529
+ };
530
+
531
+ function severityIcon(severity) {
532
+ const entry = SEVERITY_ICONS[severity] || SEVERITY_ICONS.warning;
533
+ return entry.color(entry.icon);
534
+ }
535
+
536
+ function severityDetail(severity, detail) {
537
+ switch (severity) {
538
+ case 'pass': return chalk.gray(detail || '');
539
+ case 'info': return chalk.cyan(detail);
540
+ case 'warning': return chalk.yellow(detail);
541
+ case 'error': return chalk.red(detail);
542
+ default: return detail;
543
+ }
544
+ }
545
+
546
+ // ============================================================================
547
+ // Main
548
+ // ============================================================================
549
+
550
+ async function main() {
551
+ process.stderr.write('[DEPRECATED] gaia-doctor.js is deprecated. Use: python3 bin/gaia doctor\n[DEPRECATED] Migration guide: see CHANGELOG.md\n');
552
+
553
+ const args = yargs(hideBin(process.argv))
554
+ .usage('Usage: $0 [options]')
555
+ .option('fix', { type: 'boolean', description: 'Attempt auto-fix for common issues', default: false })
556
+ .option('json', { type: 'boolean', description: 'Output as JSON', default: false })
557
+ .help('h').alias('h', 'help')
558
+ .version(false)
559
+ .parse();
560
+
561
+ // Run all checks -- ordered from most fundamental to most specific.
562
+ // Core platform first, then Gaia configuration, then project-specific.
563
+ const checks = [
564
+ checkGaiaVersion,
565
+ checkClaudeCode,
566
+ checkPython,
567
+ checkPluginMode,
568
+ checkSymlinks,
569
+ checkIdentity,
570
+ checkSettings,
571
+ checkHooks,
572
+ checkProjectContext,
573
+ checkProjectDirs,
574
+ checkMemoryDirs
575
+ ];
576
+
577
+ const results = [];
578
+ for (const check of checks) {
579
+ try {
580
+ results.push(await check());
581
+ } catch (error) {
582
+ results.push(result(check.name, 'error', `Error: ${error.message}`));
583
+ }
584
+ }
585
+
586
+ // Compute overall status from severity levels
587
+ const hasErrors = results.some(r => r.severity === 'error');
588
+ const hasWarnings = results.some(r => r.severity === 'warning');
589
+
590
+ // JSON output mode
591
+ if (args.json) {
592
+ const status = hasErrors ? 'critical' : hasWarnings ? 'degraded' : 'healthy';
593
+ console.log(JSON.stringify({ healthy: !hasErrors && !hasWarnings, status, checks: results }, null, 2));
594
+ process.exit(hasErrors ? 2 : hasWarnings ? 1 : 0);
595
+ }
596
+
597
+ // Human-readable output
598
+ const gaiaCheck = results.find(r => r.name === 'Gaia-Ops');
599
+ const versionTag = gaiaCheck?.severity === 'pass' ? chalk.gray(` (${gaiaCheck.detail})`) : '';
600
+ console.log(chalk.cyan(`\n Gaia-Ops Health Check${versionTag}\n`));
601
+
602
+ for (const r of results) {
603
+ const icon = severityIcon(r.severity);
604
+ const detail = severityDetail(r.severity, r.detail || '');
605
+ console.log(` ${icon} ${r.name.padEnd(18)} ${detail}`);
606
+
607
+ if ((r.severity === 'warning' || r.severity === 'error') && r.fix) {
608
+ console.log(chalk.gray(` Fix: ${r.fix}`));
609
+ }
610
+ }
611
+
612
+ console.log('');
613
+
614
+ if (hasErrors) {
615
+ console.log(chalk.red.bold(' Status: CRITICAL\n'));
616
+ if (args.fix) {
617
+ await autoFix();
618
+ } else {
619
+ console.log(chalk.gray(' Run with --fix to attempt auto-repair\n'));
620
+ }
621
+ } else if (hasWarnings) {
622
+ console.log(chalk.yellow.bold(' Status: ISSUES FOUND\n'));
623
+ if (args.fix) {
624
+ await autoFix();
625
+ } else {
626
+ console.log(chalk.gray(' Run with --fix to attempt auto-repair\n'));
627
+ }
628
+ } else {
629
+ console.log(chalk.green.bold(' Status: HEALTHY\n'));
630
+ }
631
+
632
+ process.exit(hasErrors ? 2 : hasWarnings ? 1 : 0);
633
+ }
634
+
635
+ main();