@jaguilar87/gaia 5.0.0-rc1
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.
- package/.claude-plugin/marketplace.json +33 -0
- package/.claude-plugin/plugin.json +26 -0
- package/ARCHITECTURE.md +335 -0
- package/CHANGELOG.md +1212 -0
- package/CODE_OF_CONDUCT.md +11 -0
- package/CONTRIBUTING.md +146 -0
- package/INSTALL.md +436 -0
- package/LICENSE +21 -0
- package/README.md +222 -0
- package/SECURITY.md +47 -0
- package/agents/README.md +78 -0
- package/agents/cloud-troubleshooter.md +73 -0
- package/agents/developer.md +65 -0
- package/agents/gaia-operator.md +64 -0
- package/agents/gaia-orchestrator.md +237 -0
- package/agents/gaia-planner.md +53 -0
- package/agents/gaia-system.md +70 -0
- package/agents/gitops-operator.md +61 -0
- package/agents/terraform-architect.md +63 -0
- package/bin/README.md +106 -0
- package/bin/cli/__init__.py +1 -0
- package/bin/cli/approvals.py +740 -0
- package/bin/cli/cleanup.py +562 -0
- package/bin/cli/context.py +283 -0
- package/bin/cli/doctor.py +628 -0
- package/bin/cli/history.py +305 -0
- package/bin/cli/memory.py +464 -0
- package/bin/cli/metrics.py +1068 -0
- package/bin/cli/plans.py +515 -0
- package/bin/cli/status.py +302 -0
- package/bin/cli/update.py +382 -0
- package/bin/gaia +112 -0
- package/bin/gaia-cleanup.js +531 -0
- package/bin/gaia-doctor.js +635 -0
- package/bin/gaia-evidence +126 -0
- package/bin/gaia-history.js +251 -0
- package/bin/gaia-metrics.js +1278 -0
- package/bin/gaia-review.js +269 -0
- package/bin/gaia-scan +44 -0
- package/bin/gaia-scan.py +589 -0
- package/bin/gaia-skills-diagnose.js +929 -0
- package/bin/gaia-status.js +278 -0
- package/bin/gaia-uninstall.js +111 -0
- package/bin/gaia-update.js +816 -0
- package/bin/pre-publish-validate.js +610 -0
- package/bin/python-detect.js +60 -0
- package/commands/README.md +64 -0
- package/commands/gaia.md +37 -0
- package/commands/scan-project.md +67 -0
- package/config/README.md +71 -0
- package/config/cloud/aws.json +134 -0
- package/config/cloud/gcp.json +139 -0
- package/config/context-contracts.json +158 -0
- package/config/crons-schema.md +81 -0
- package/config/git_standards.json +72 -0
- package/config/surface-routing.json +421 -0
- package/config/universal-rules.json +102 -0
- package/dist/gaia-ops/.claude-plugin/plugin.json +24 -0
- package/dist/gaia-ops/README.md +80 -0
- package/dist/gaia-ops/agents/cloud-troubleshooter.md +73 -0
- package/dist/gaia-ops/agents/developer.md +65 -0
- package/dist/gaia-ops/agents/gaia-operator.md +64 -0
- package/dist/gaia-ops/agents/gaia-orchestrator.md +237 -0
- package/dist/gaia-ops/agents/gaia-planner.md +53 -0
- package/dist/gaia-ops/agents/gaia-system.md +70 -0
- package/dist/gaia-ops/agents/gitops-operator.md +61 -0
- package/dist/gaia-ops/agents/terraform-architect.md +63 -0
- package/dist/gaia-ops/commands/gaia.md +37 -0
- package/dist/gaia-ops/config/README.md +71 -0
- package/dist/gaia-ops/config/cloud/aws.json +134 -0
- package/dist/gaia-ops/config/cloud/gcp.json +139 -0
- package/dist/gaia-ops/config/context-contracts.json +158 -0
- package/dist/gaia-ops/config/crons-schema.md +81 -0
- package/dist/gaia-ops/config/git_standards.json +72 -0
- package/dist/gaia-ops/config/surface-routing.json +421 -0
- package/dist/gaia-ops/config/universal-rules.json +102 -0
- package/dist/gaia-ops/hooks/adapters/__init__.py +52 -0
- package/dist/gaia-ops/hooks/adapters/base.py +219 -0
- package/dist/gaia-ops/hooks/adapters/channel.py +17 -0
- package/dist/gaia-ops/hooks/adapters/claude_code.py +1890 -0
- package/dist/gaia-ops/hooks/adapters/types.py +194 -0
- package/dist/gaia-ops/hooks/adapters/utils.py +25 -0
- package/dist/gaia-ops/hooks/hooks.json +163 -0
- package/dist/gaia-ops/hooks/modules/__init__.py +15 -0
- package/dist/gaia-ops/hooks/modules/agents/__init__.py +29 -0
- package/dist/gaia-ops/hooks/modules/agents/contract_validator.py +647 -0
- package/dist/gaia-ops/hooks/modules/agents/response_contract.py +496 -0
- package/dist/gaia-ops/hooks/modules/agents/skill_injection_verifier.py +120 -0
- package/dist/gaia-ops/hooks/modules/agents/state_tracker.py +267 -0
- package/dist/gaia-ops/hooks/modules/agents/task_info_builder.py +74 -0
- package/dist/gaia-ops/hooks/modules/agents/transcript_analyzer.py +458 -0
- package/dist/gaia-ops/hooks/modules/agents/transcript_reader.py +152 -0
- package/dist/gaia-ops/hooks/modules/audit/__init__.py +28 -0
- package/dist/gaia-ops/hooks/modules/audit/event_detector.py +168 -0
- package/dist/gaia-ops/hooks/modules/audit/logger.py +131 -0
- package/dist/gaia-ops/hooks/modules/audit/metrics.py +134 -0
- package/dist/gaia-ops/hooks/modules/audit/workflow_auditor.py +611 -0
- package/dist/gaia-ops/hooks/modules/audit/workflow_recorder.py +296 -0
- package/dist/gaia-ops/hooks/modules/context/__init__.py +11 -0
- package/dist/gaia-ops/hooks/modules/context/agentic_loop_detector.py +165 -0
- package/dist/gaia-ops/hooks/modules/context/anchor_tracker.py +317 -0
- package/dist/gaia-ops/hooks/modules/context/compact_context_builder.py +218 -0
- package/dist/gaia-ops/hooks/modules/context/context_freshness.py +145 -0
- package/dist/gaia-ops/hooks/modules/context/context_injector.py +558 -0
- package/dist/gaia-ops/hooks/modules/context/context_writer.py +530 -0
- package/dist/gaia-ops/hooks/modules/context/contracts_loader.py +161 -0
- package/dist/gaia-ops/hooks/modules/core/__init__.py +40 -0
- package/dist/gaia-ops/hooks/modules/core/hook_entry.py +78 -0
- package/dist/gaia-ops/hooks/modules/core/paths.py +160 -0
- package/dist/gaia-ops/hooks/modules/core/plugin_mode.py +149 -0
- package/dist/gaia-ops/hooks/modules/core/plugin_setup.py +577 -0
- package/dist/gaia-ops/hooks/modules/core/state.py +179 -0
- package/dist/gaia-ops/hooks/modules/core/stdin.py +24 -0
- package/dist/gaia-ops/hooks/modules/events/__init__.py +1 -0
- package/dist/gaia-ops/hooks/modules/events/event_writer.py +210 -0
- package/dist/gaia-ops/hooks/modules/memory/__init__.py +8 -0
- package/dist/gaia-ops/hooks/modules/memory/episode_writer.py +216 -0
- package/dist/gaia-ops/hooks/modules/orchestrator/__init__.py +1 -0
- package/dist/gaia-ops/hooks/modules/orchestrator/delegate_mode.py +122 -0
- package/dist/gaia-ops/hooks/modules/scanning/__init__.py +8 -0
- package/dist/gaia-ops/hooks/modules/scanning/scan_trigger.py +84 -0
- package/dist/gaia-ops/hooks/modules/security/__init__.py +120 -0
- package/dist/gaia-ops/hooks/modules/security/approval_cleanup.py +87 -0
- package/dist/gaia-ops/hooks/modules/security/approval_constants.py +23 -0
- package/dist/gaia-ops/hooks/modules/security/approval_grants.py +1638 -0
- package/dist/gaia-ops/hooks/modules/security/approval_messages.py +71 -0
- package/dist/gaia-ops/hooks/modules/security/approval_scopes.py +222 -0
- package/dist/gaia-ops/hooks/modules/security/blocked_commands.py +595 -0
- package/dist/gaia-ops/hooks/modules/security/blocked_message_formatter.py +87 -0
- package/dist/gaia-ops/hooks/modules/security/command_semantics.py +181 -0
- package/dist/gaia-ops/hooks/modules/security/composition_rules.py +547 -0
- package/dist/gaia-ops/hooks/modules/security/flag_classifiers.py +873 -0
- package/dist/gaia-ops/hooks/modules/security/gitops_validator.py +179 -0
- package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +1131 -0
- package/dist/gaia-ops/hooks/modules/security/network_hosts.py +481 -0
- package/dist/gaia-ops/hooks/modules/security/prompt_validator.py +40 -0
- package/dist/gaia-ops/hooks/modules/security/shell_unwrapper.py +165 -0
- package/dist/gaia-ops/hooks/modules/security/tiers.py +196 -0
- package/dist/gaia-ops/hooks/modules/session/__init__.py +10 -0
- package/dist/gaia-ops/hooks/modules/session/pending_scanner.py +174 -0
- package/dist/gaia-ops/hooks/modules/session/session_context_writer.py +100 -0
- package/dist/gaia-ops/hooks/modules/session/session_event_injector.py +160 -0
- package/dist/gaia-ops/hooks/modules/session/session_manager.py +31 -0
- package/dist/gaia-ops/hooks/modules/session/session_registry.py +232 -0
- package/dist/gaia-ops/hooks/modules/tools/__init__.py +29 -0
- package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +1008 -0
- package/dist/gaia-ops/hooks/modules/tools/cloud_pipe_validator.py +231 -0
- package/dist/gaia-ops/hooks/modules/tools/hook_response.py +55 -0
- package/dist/gaia-ops/hooks/modules/tools/shell_parser.py +227 -0
- package/dist/gaia-ops/hooks/modules/tools/stage_decomposer.py +315 -0
- package/dist/gaia-ops/hooks/modules/tools/task_validator.py +294 -0
- package/dist/gaia-ops/hooks/modules/validation/__init__.py +23 -0
- package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +380 -0
- package/dist/gaia-ops/hooks/post_compact.py +43 -0
- package/dist/gaia-ops/hooks/post_tool_use.py +54 -0
- package/dist/gaia-ops/hooks/pre_compact.py +60 -0
- package/dist/gaia-ops/hooks/pre_tool_use.py +413 -0
- package/dist/gaia-ops/hooks/session_start.py +81 -0
- package/dist/gaia-ops/hooks/stop_hook.py +82 -0
- package/dist/gaia-ops/hooks/subagent_start.py +71 -0
- package/dist/gaia-ops/hooks/subagent_stop.py +295 -0
- package/dist/gaia-ops/hooks/task_completed.py +70 -0
- package/dist/gaia-ops/hooks/user_prompt_submit.py +246 -0
- package/dist/gaia-ops/settings.json +72 -0
- package/dist/gaia-ops/skills/README.md +154 -0
- package/dist/gaia-ops/skills/agent-protocol/SKILL.md +93 -0
- package/dist/gaia-ops/skills/agent-protocol/examples.md +223 -0
- package/dist/gaia-ops/skills/agent-response/SKILL.md +69 -0
- package/dist/gaia-ops/skills/agentic-loop/SKILL.md +80 -0
- package/dist/gaia-ops/skills/agentic-loop/reference.md +378 -0
- package/dist/gaia-ops/skills/blog-writing/SKILL.md +98 -0
- package/dist/gaia-ops/skills/blog-writing/reference.md +130 -0
- package/dist/gaia-ops/skills/brief-spec/SKILL.md +182 -0
- package/dist/gaia-ops/skills/command-execution/SKILL.md +64 -0
- package/dist/gaia-ops/skills/command-execution/reference.md +83 -0
- package/dist/gaia-ops/skills/context-updater/SKILL.md +87 -0
- package/dist/gaia-ops/skills/context-updater/examples.md +71 -0
- package/dist/gaia-ops/skills/developer-patterns/SKILL.md +50 -0
- package/dist/gaia-ops/skills/developer-patterns/reference.md +112 -0
- package/dist/gaia-ops/skills/execution/SKILL.md +99 -0
- package/dist/gaia-ops/skills/fast-queries/SKILL.md +43 -0
- package/dist/gaia-ops/skills/gaia-compact/SKILL.md +74 -0
- package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +108 -0
- package/dist/gaia-ops/skills/gaia-patterns/reference.md +395 -0
- package/dist/gaia-ops/skills/gaia-planner/SKILL.md +37 -0
- package/dist/gaia-ops/skills/gaia-planner/reference.md +107 -0
- package/dist/gaia-ops/skills/gaia-release/SKILL.md +82 -0
- package/dist/gaia-ops/skills/gaia-release/reference.md +102 -0
- package/dist/gaia-ops/skills/gaia-self-check/SKILL.md +114 -0
- package/dist/gaia-ops/skills/gaia-self-check/reference.md +453 -0
- package/dist/gaia-ops/skills/gaia-verify/SKILL.md +77 -0
- package/dist/gaia-ops/skills/gaia-verify/reference.md +80 -0
- package/dist/gaia-ops/skills/git-conventions/SKILL.md +47 -0
- package/dist/gaia-ops/skills/gitops-patterns/SKILL.md +60 -0
- package/dist/gaia-ops/skills/gitops-patterns/reference.md +183 -0
- package/dist/gaia-ops/skills/gmail-policy/SKILL.md +200 -0
- package/dist/gaia-ops/skills/gmail-policy/reference.md +150 -0
- package/dist/gaia-ops/skills/gmail-triage/SKILL.md +100 -0
- package/dist/gaia-ops/skills/gws-setup/SKILL.md +99 -0
- package/dist/gaia-ops/skills/gws-setup/reference.md +73 -0
- package/dist/gaia-ops/skills/investigation/SKILL.md +100 -0
- package/dist/gaia-ops/skills/memory-curation/SKILL.md +83 -0
- package/dist/gaia-ops/skills/memory-search/SKILL.md +88 -0
- package/dist/gaia-ops/skills/orchestrator-approval/SKILL.md +160 -0
- package/dist/gaia-ops/skills/orchestrator-approval/reference.md +174 -0
- package/dist/gaia-ops/skills/pending-approvals/SKILL.md +72 -0
- package/dist/gaia-ops/skills/pending-approvals/reference.md +214 -0
- package/dist/gaia-ops/skills/readme-writing/SKILL.md +71 -0
- package/dist/gaia-ops/skills/readme-writing/reference.md +188 -0
- package/dist/gaia-ops/skills/reference.md +135 -0
- package/dist/gaia-ops/skills/request-approval/SKILL.md +140 -0
- package/dist/gaia-ops/skills/request-approval/examples.md +140 -0
- package/dist/gaia-ops/skills/request-approval/reference.md +57 -0
- package/dist/gaia-ops/skills/schedule-task/SKILL.md +64 -0
- package/dist/gaia-ops/skills/schedule-task/reference.md +233 -0
- package/dist/gaia-ops/skills/security-tiers/SKILL.md +141 -0
- package/dist/gaia-ops/skills/security-tiers/destructive-commands-reference.md +623 -0
- package/dist/gaia-ops/skills/security-tiers/reference.md +39 -0
- package/dist/gaia-ops/skills/skill-creation/SKILL.md +92 -0
- package/dist/gaia-ops/skills/skill-creation/reference.md +29 -0
- package/dist/gaia-ops/skills/terraform-patterns/SKILL.md +89 -0
- package/dist/gaia-ops/skills/terraform-patterns/reference.md +93 -0
- package/dist/gaia-ops/tools/__init__.py +9 -0
- package/dist/gaia-ops/tools/agentic-loop/decide-status.py +210 -0
- package/dist/gaia-ops/tools/agentic-loop/parse-metric.py +106 -0
- package/dist/gaia-ops/tools/agentic-loop/record-iteration.py +221 -0
- package/dist/gaia-ops/tools/context/README.md +132 -0
- package/dist/gaia-ops/tools/context/__init__.py +42 -0
- package/dist/gaia-ops/tools/context/_paths.py +20 -0
- package/dist/gaia-ops/tools/context/context_provider.py +721 -0
- package/dist/gaia-ops/tools/context/context_section_reader.py +342 -0
- package/dist/gaia-ops/tools/context/deep_merge.py +159 -0
- package/dist/gaia-ops/tools/context/pending_updates.py +760 -0
- package/dist/gaia-ops/tools/context/surface_router.py +278 -0
- package/dist/gaia-ops/tools/fast-queries/README.md +65 -0
- package/dist/gaia-ops/tools/fast-queries/__init__.py +30 -0
- package/dist/gaia-ops/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
- package/dist/gaia-ops/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
- package/dist/gaia-ops/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
- package/dist/gaia-ops/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
- package/dist/gaia-ops/tools/fast-queries/run_triage.sh +59 -0
- package/dist/gaia-ops/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
- package/dist/gaia-ops/tools/gaia_simulator/__init__.py +33 -0
- package/dist/gaia-ops/tools/gaia_simulator/cli.py +354 -0
- package/dist/gaia-ops/tools/gaia_simulator/extractor.py +457 -0
- package/dist/gaia-ops/tools/gaia_simulator/reporter.py +258 -0
- package/dist/gaia-ops/tools/gaia_simulator/routing_simulator.py +334 -0
- package/dist/gaia-ops/tools/gaia_simulator/runner.py +539 -0
- package/dist/gaia-ops/tools/gaia_simulator/skills_mapper.py +264 -0
- package/dist/gaia-ops/tools/memory/README.md +0 -0
- package/dist/gaia-ops/tools/memory/__init__.py +20 -0
- package/dist/gaia-ops/tools/memory/backfill_fts5.py +107 -0
- package/dist/gaia-ops/tools/memory/conflict_detector.py +295 -0
- package/dist/gaia-ops/tools/memory/episodic.py +1210 -0
- package/dist/gaia-ops/tools/memory/git_invalidator.py +262 -0
- package/dist/gaia-ops/tools/memory/paths.py +102 -0
- package/dist/gaia-ops/tools/memory/scoring.py +193 -0
- package/dist/gaia-ops/tools/memory/search_store.py +360 -0
- package/dist/gaia-ops/tools/persist_transcript_analysis.py +85 -0
- package/dist/gaia-ops/tools/review/__init__.py +1 -0
- package/dist/gaia-ops/tools/review/review_engine.py +157 -0
- package/dist/gaia-ops/tools/scan/__init__.py +35 -0
- package/dist/gaia-ops/tools/scan/config.py +247 -0
- package/dist/gaia-ops/tools/scan/merge.py +212 -0
- package/dist/gaia-ops/tools/scan/orchestrator.py +549 -0
- package/dist/gaia-ops/tools/scan/registry.py +127 -0
- package/dist/gaia-ops/tools/scan/scanners/__init__.py +18 -0
- package/dist/gaia-ops/tools/scan/scanners/base.py +137 -0
- package/dist/gaia-ops/tools/scan/scanners/environment.py +349 -0
- package/dist/gaia-ops/tools/scan/scanners/git.py +570 -0
- package/dist/gaia-ops/tools/scan/scanners/infrastructure.py +875 -0
- package/dist/gaia-ops/tools/scan/scanners/orchestration.py +600 -0
- package/dist/gaia-ops/tools/scan/scanners/stack.py +1085 -0
- package/dist/gaia-ops/tools/scan/scanners/tools.py +260 -0
- package/dist/gaia-ops/tools/scan/setup.py +686 -0
- package/dist/gaia-ops/tools/scan/tests/__init__.py +1 -0
- package/dist/gaia-ops/tools/scan/tests/conftest.py +796 -0
- package/dist/gaia-ops/tools/scan/tests/test_environment.py +323 -0
- package/dist/gaia-ops/tools/scan/tests/test_git.py +419 -0
- package/dist/gaia-ops/tools/scan/tests/test_infrastructure.py +382 -0
- package/dist/gaia-ops/tools/scan/tests/test_integration.py +920 -0
- package/dist/gaia-ops/tools/scan/tests/test_merge.py +269 -0
- package/dist/gaia-ops/tools/scan/tests/test_orchestration.py +304 -0
- package/dist/gaia-ops/tools/scan/tests/test_stack.py +604 -0
- package/dist/gaia-ops/tools/scan/tests/test_tools.py +349 -0
- package/dist/gaia-ops/tools/scan/ui.py +624 -0
- package/dist/gaia-ops/tools/scan/verify.py +270 -0
- package/dist/gaia-ops/tools/scan/walk.py +118 -0
- package/dist/gaia-ops/tools/scan/workspace.py +85 -0
- package/dist/gaia-ops/tools/validation/README.md +244 -0
- package/dist/gaia-ops/tools/validation/__init__.py +17 -0
- package/dist/gaia-ops/tools/validation/approval_gate.py +321 -0
- package/dist/gaia-ops/tools/validation/validate_skills.py +189 -0
- package/dist/gaia-security/.claude-plugin/plugin.json +24 -0
- package/dist/gaia-security/README.md +90 -0
- package/dist/gaia-security/config/universal-rules.json +102 -0
- package/dist/gaia-security/hooks/adapters/__init__.py +52 -0
- package/dist/gaia-security/hooks/adapters/base.py +219 -0
- package/dist/gaia-security/hooks/adapters/channel.py +17 -0
- package/dist/gaia-security/hooks/adapters/claude_code.py +1890 -0
- package/dist/gaia-security/hooks/adapters/types.py +194 -0
- package/dist/gaia-security/hooks/adapters/utils.py +25 -0
- package/dist/gaia-security/hooks/hooks.json +84 -0
- package/dist/gaia-security/hooks/modules/__init__.py +15 -0
- package/dist/gaia-security/hooks/modules/agents/__init__.py +29 -0
- package/dist/gaia-security/hooks/modules/agents/contract_validator.py +647 -0
- package/dist/gaia-security/hooks/modules/agents/response_contract.py +496 -0
- package/dist/gaia-security/hooks/modules/agents/skill_injection_verifier.py +120 -0
- package/dist/gaia-security/hooks/modules/agents/state_tracker.py +267 -0
- package/dist/gaia-security/hooks/modules/agents/task_info_builder.py +74 -0
- package/dist/gaia-security/hooks/modules/agents/transcript_analyzer.py +458 -0
- package/dist/gaia-security/hooks/modules/agents/transcript_reader.py +152 -0
- package/dist/gaia-security/hooks/modules/audit/__init__.py +28 -0
- package/dist/gaia-security/hooks/modules/audit/event_detector.py +168 -0
- package/dist/gaia-security/hooks/modules/audit/logger.py +131 -0
- package/dist/gaia-security/hooks/modules/audit/metrics.py +134 -0
- package/dist/gaia-security/hooks/modules/audit/workflow_auditor.py +611 -0
- package/dist/gaia-security/hooks/modules/audit/workflow_recorder.py +296 -0
- package/dist/gaia-security/hooks/modules/context/__init__.py +11 -0
- package/dist/gaia-security/hooks/modules/context/agentic_loop_detector.py +165 -0
- package/dist/gaia-security/hooks/modules/context/anchor_tracker.py +317 -0
- package/dist/gaia-security/hooks/modules/context/compact_context_builder.py +218 -0
- package/dist/gaia-security/hooks/modules/context/context_freshness.py +145 -0
- package/dist/gaia-security/hooks/modules/context/context_injector.py +558 -0
- package/dist/gaia-security/hooks/modules/context/context_writer.py +530 -0
- package/dist/gaia-security/hooks/modules/context/contracts_loader.py +161 -0
- package/dist/gaia-security/hooks/modules/core/__init__.py +40 -0
- package/dist/gaia-security/hooks/modules/core/hook_entry.py +78 -0
- package/dist/gaia-security/hooks/modules/core/paths.py +160 -0
- package/dist/gaia-security/hooks/modules/core/plugin_mode.py +149 -0
- package/dist/gaia-security/hooks/modules/core/plugin_setup.py +577 -0
- package/dist/gaia-security/hooks/modules/core/state.py +179 -0
- package/dist/gaia-security/hooks/modules/core/stdin.py +24 -0
- package/dist/gaia-security/hooks/modules/events/__init__.py +1 -0
- package/dist/gaia-security/hooks/modules/events/event_writer.py +210 -0
- package/dist/gaia-security/hooks/modules/memory/__init__.py +8 -0
- package/dist/gaia-security/hooks/modules/memory/episode_writer.py +216 -0
- package/dist/gaia-security/hooks/modules/orchestrator/__init__.py +1 -0
- package/dist/gaia-security/hooks/modules/orchestrator/delegate_mode.py +122 -0
- package/dist/gaia-security/hooks/modules/scanning/__init__.py +8 -0
- package/dist/gaia-security/hooks/modules/scanning/scan_trigger.py +84 -0
- package/dist/gaia-security/hooks/modules/security/__init__.py +120 -0
- package/dist/gaia-security/hooks/modules/security/approval_cleanup.py +87 -0
- package/dist/gaia-security/hooks/modules/security/approval_constants.py +23 -0
- package/dist/gaia-security/hooks/modules/security/approval_grants.py +1638 -0
- package/dist/gaia-security/hooks/modules/security/approval_messages.py +71 -0
- package/dist/gaia-security/hooks/modules/security/approval_scopes.py +222 -0
- package/dist/gaia-security/hooks/modules/security/blocked_commands.py +595 -0
- package/dist/gaia-security/hooks/modules/security/blocked_message_formatter.py +87 -0
- package/dist/gaia-security/hooks/modules/security/command_semantics.py +181 -0
- package/dist/gaia-security/hooks/modules/security/composition_rules.py +547 -0
- package/dist/gaia-security/hooks/modules/security/flag_classifiers.py +873 -0
- package/dist/gaia-security/hooks/modules/security/gitops_validator.py +179 -0
- package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +1131 -0
- package/dist/gaia-security/hooks/modules/security/network_hosts.py +481 -0
- package/dist/gaia-security/hooks/modules/security/prompt_validator.py +40 -0
- package/dist/gaia-security/hooks/modules/security/shell_unwrapper.py +165 -0
- package/dist/gaia-security/hooks/modules/security/tiers.py +196 -0
- package/dist/gaia-security/hooks/modules/session/__init__.py +10 -0
- package/dist/gaia-security/hooks/modules/session/pending_scanner.py +174 -0
- package/dist/gaia-security/hooks/modules/session/session_context_writer.py +100 -0
- package/dist/gaia-security/hooks/modules/session/session_event_injector.py +160 -0
- package/dist/gaia-security/hooks/modules/session/session_manager.py +31 -0
- package/dist/gaia-security/hooks/modules/session/session_registry.py +232 -0
- package/dist/gaia-security/hooks/modules/tools/__init__.py +29 -0
- package/dist/gaia-security/hooks/modules/tools/bash_validator.py +1008 -0
- package/dist/gaia-security/hooks/modules/tools/cloud_pipe_validator.py +231 -0
- package/dist/gaia-security/hooks/modules/tools/hook_response.py +55 -0
- package/dist/gaia-security/hooks/modules/tools/shell_parser.py +227 -0
- package/dist/gaia-security/hooks/modules/tools/stage_decomposer.py +315 -0
- package/dist/gaia-security/hooks/modules/tools/task_validator.py +294 -0
- package/dist/gaia-security/hooks/modules/validation/__init__.py +23 -0
- package/dist/gaia-security/hooks/modules/validation/commit_validator.py +380 -0
- package/dist/gaia-security/hooks/post_tool_use.py +54 -0
- package/dist/gaia-security/hooks/pre_tool_use.py +413 -0
- package/dist/gaia-security/hooks/session_start.py +81 -0
- package/dist/gaia-security/hooks/stop_hook.py +82 -0
- package/dist/gaia-security/hooks/user_prompt_submit.py +246 -0
- package/dist/gaia-security/settings.json +58 -0
- package/git-hooks/commit-msg +41 -0
- package/hooks/README.md +100 -0
- package/hooks/adapters/__init__.py +52 -0
- package/hooks/adapters/base.py +219 -0
- package/hooks/adapters/channel.py +17 -0
- package/hooks/adapters/claude_code.py +1890 -0
- package/hooks/adapters/types.py +194 -0
- package/hooks/adapters/utils.py +25 -0
- package/hooks/elicitation_result.py +179 -0
- package/hooks/hooks.json +84 -0
- package/hooks/modules/README.md +189 -0
- package/hooks/modules/__init__.py +15 -0
- package/hooks/modules/agents/__init__.py +29 -0
- package/hooks/modules/agents/contract_validator.py +647 -0
- package/hooks/modules/agents/response_contract.py +496 -0
- package/hooks/modules/agents/skill_injection_verifier.py +120 -0
- package/hooks/modules/agents/state_tracker.py +267 -0
- package/hooks/modules/agents/task_info_builder.py +74 -0
- package/hooks/modules/agents/transcript_analyzer.py +458 -0
- package/hooks/modules/agents/transcript_reader.py +152 -0
- package/hooks/modules/audit/__init__.py +28 -0
- package/hooks/modules/audit/event_detector.py +168 -0
- package/hooks/modules/audit/logger.py +131 -0
- package/hooks/modules/audit/metrics.py +134 -0
- package/hooks/modules/audit/workflow_auditor.py +611 -0
- package/hooks/modules/audit/workflow_recorder.py +296 -0
- package/hooks/modules/context/__init__.py +11 -0
- package/hooks/modules/context/agentic_loop_detector.py +165 -0
- package/hooks/modules/context/anchor_tracker.py +317 -0
- package/hooks/modules/context/compact_context_builder.py +218 -0
- package/hooks/modules/context/context_freshness.py +145 -0
- package/hooks/modules/context/context_injector.py +558 -0
- package/hooks/modules/context/context_writer.py +530 -0
- package/hooks/modules/context/contracts_loader.py +161 -0
- package/hooks/modules/core/__init__.py +40 -0
- package/hooks/modules/core/hook_entry.py +78 -0
- package/hooks/modules/core/paths.py +160 -0
- package/hooks/modules/core/plugin_mode.py +149 -0
- package/hooks/modules/core/plugin_setup.py +577 -0
- package/hooks/modules/core/state.py +179 -0
- package/hooks/modules/core/stdin.py +24 -0
- package/hooks/modules/events/__init__.py +1 -0
- package/hooks/modules/events/event_writer.py +210 -0
- package/hooks/modules/evidence/__init__.py +34 -0
- package/hooks/modules/evidence/assertions.py +137 -0
- package/hooks/modules/evidence/index_writer.py +57 -0
- package/hooks/modules/evidence/loader.py +126 -0
- package/hooks/modules/evidence/runner.py +241 -0
- package/hooks/modules/memory/__init__.py +8 -0
- package/hooks/modules/memory/episode_writer.py +216 -0
- package/hooks/modules/orchestrator/__init__.py +1 -0
- package/hooks/modules/orchestrator/delegate_mode.py +122 -0
- package/hooks/modules/scanning/__init__.py +8 -0
- package/hooks/modules/scanning/scan_trigger.py +84 -0
- package/hooks/modules/security/__init__.py +120 -0
- package/hooks/modules/security/approval_cleanup.py +87 -0
- package/hooks/modules/security/approval_constants.py +23 -0
- package/hooks/modules/security/approval_grants.py +1638 -0
- package/hooks/modules/security/approval_messages.py +71 -0
- package/hooks/modules/security/approval_scopes.py +222 -0
- package/hooks/modules/security/blocked_commands.py +595 -0
- package/hooks/modules/security/blocked_message_formatter.py +87 -0
- package/hooks/modules/security/command_semantics.py +181 -0
- package/hooks/modules/security/composition_rules.py +547 -0
- package/hooks/modules/security/flag_classifiers.py +873 -0
- package/hooks/modules/security/gitops_validator.py +179 -0
- package/hooks/modules/security/mutative_verbs.py +1131 -0
- package/hooks/modules/security/network_hosts.py +481 -0
- package/hooks/modules/security/prompt_validator.py +40 -0
- package/hooks/modules/security/shell_unwrapper.py +165 -0
- package/hooks/modules/security/tiers.py +196 -0
- package/hooks/modules/session/__init__.py +10 -0
- package/hooks/modules/session/pending_scanner.py +174 -0
- package/hooks/modules/session/session_context_writer.py +100 -0
- package/hooks/modules/session/session_event_injector.py +160 -0
- package/hooks/modules/session/session_manager.py +31 -0
- package/hooks/modules/session/session_registry.py +232 -0
- package/hooks/modules/tools/__init__.py +29 -0
- package/hooks/modules/tools/bash_validator.py +1008 -0
- package/hooks/modules/tools/cloud_pipe_validator.py +231 -0
- package/hooks/modules/tools/hook_response.py +55 -0
- package/hooks/modules/tools/shell_parser.py +227 -0
- package/hooks/modules/tools/stage_decomposer.py +315 -0
- package/hooks/modules/tools/task_validator.py +294 -0
- package/hooks/modules/validation/__init__.py +23 -0
- package/hooks/modules/validation/commit_validator.py +380 -0
- package/hooks/post_compact.py +43 -0
- package/hooks/post_tool_use.py +54 -0
- package/hooks/pre_compact.py +60 -0
- package/hooks/pre_tool_use.py +413 -0
- package/hooks/session_start.py +81 -0
- package/hooks/stop_hook.py +82 -0
- package/hooks/subagent_start.py +71 -0
- package/hooks/subagent_stop.py +295 -0
- package/hooks/task_completed.py +70 -0
- package/hooks/user_prompt_submit.py +246 -0
- package/index.js +83 -0
- package/package.json +99 -0
- package/pyproject.toml +32 -0
- package/skills/README.md +154 -0
- package/skills/agent-protocol/SKILL.md +93 -0
- package/skills/agent-protocol/examples.md +223 -0
- package/skills/agent-response/SKILL.md +69 -0
- package/skills/agentic-loop/SKILL.md +80 -0
- package/skills/agentic-loop/reference.md +378 -0
- package/skills/blog-writing/SKILL.md +98 -0
- package/skills/blog-writing/reference.md +130 -0
- package/skills/brief-spec/SKILL.md +182 -0
- package/skills/command-execution/SKILL.md +64 -0
- package/skills/command-execution/reference.md +83 -0
- package/skills/context-updater/SKILL.md +87 -0
- package/skills/context-updater/examples.md +71 -0
- package/skills/developer-patterns/SKILL.md +50 -0
- package/skills/developer-patterns/reference.md +112 -0
- package/skills/execution/SKILL.md +99 -0
- package/skills/fast-queries/SKILL.md +43 -0
- package/skills/gaia-compact/SKILL.md +74 -0
- package/skills/gaia-patterns/SKILL.md +108 -0
- package/skills/gaia-patterns/reference.md +395 -0
- package/skills/gaia-planner/SKILL.md +37 -0
- package/skills/gaia-planner/reference.md +107 -0
- package/skills/gaia-release/SKILL.md +82 -0
- package/skills/gaia-release/reference.md +102 -0
- package/skills/gaia-self-check/SKILL.md +114 -0
- package/skills/gaia-self-check/reference.md +453 -0
- package/skills/gaia-verify/SKILL.md +77 -0
- package/skills/gaia-verify/reference.md +80 -0
- package/skills/git-conventions/SKILL.md +47 -0
- package/skills/gitops-patterns/SKILL.md +60 -0
- package/skills/gitops-patterns/reference.md +183 -0
- package/skills/gmail-policy/SKILL.md +200 -0
- package/skills/gmail-policy/reference.md +150 -0
- package/skills/gmail-triage/SKILL.md +100 -0
- package/skills/gws-setup/SKILL.md +99 -0
- package/skills/gws-setup/reference.md +73 -0
- package/skills/investigation/SKILL.md +100 -0
- package/skills/memory-curation/SKILL.md +83 -0
- package/skills/memory-search/SKILL.md +88 -0
- package/skills/orchestrator-approval/SKILL.md +160 -0
- package/skills/orchestrator-approval/reference.md +174 -0
- package/skills/pending-approvals/SKILL.md +72 -0
- package/skills/pending-approvals/reference.md +214 -0
- package/skills/readme-writing/SKILL.md +71 -0
- package/skills/readme-writing/reference.md +188 -0
- package/skills/reference.md +135 -0
- package/skills/request-approval/SKILL.md +140 -0
- package/skills/request-approval/examples.md +140 -0
- package/skills/request-approval/reference.md +57 -0
- package/skills/schedule-task/SKILL.md +64 -0
- package/skills/schedule-task/reference.md +233 -0
- package/skills/security-tiers/SKILL.md +141 -0
- package/skills/security-tiers/destructive-commands-reference.md +623 -0
- package/skills/security-tiers/reference.md +39 -0
- package/skills/skill-creation/SKILL.md +92 -0
- package/skills/skill-creation/reference.md +29 -0
- package/skills/terraform-patterns/SKILL.md +89 -0
- package/skills/terraform-patterns/reference.md +93 -0
- package/templates/README.md +69 -0
- package/templates/managed-settings.template.json +43 -0
- package/tools/__init__.py +9 -0
- package/tools/agentic-loop/decide-status.py +210 -0
- package/tools/agentic-loop/parse-metric.py +106 -0
- package/tools/agentic-loop/record-iteration.py +221 -0
- package/tools/context/README.md +132 -0
- package/tools/context/__init__.py +42 -0
- package/tools/context/_paths.py +20 -0
- package/tools/context/context_provider.py +721 -0
- package/tools/context/context_section_reader.py +342 -0
- package/tools/context/deep_merge.py +159 -0
- package/tools/context/pending_updates.py +760 -0
- package/tools/context/surface_router.py +278 -0
- package/tools/fast-queries/README.md +65 -0
- package/tools/fast-queries/__init__.py +30 -0
- package/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
- package/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
- package/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
- package/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
- package/tools/fast-queries/run_triage.sh +59 -0
- package/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
- package/tools/gaia_simulator/__init__.py +33 -0
- package/tools/gaia_simulator/cli.py +354 -0
- package/tools/gaia_simulator/extractor.py +457 -0
- package/tools/gaia_simulator/reporter.py +258 -0
- package/tools/gaia_simulator/routing_simulator.py +334 -0
- package/tools/gaia_simulator/runner.py +539 -0
- package/tools/gaia_simulator/skills_mapper.py +264 -0
- package/tools/memory/README.md +0 -0
- package/tools/memory/__init__.py +20 -0
- package/tools/memory/backfill_fts5.py +107 -0
- package/tools/memory/conflict_detector.py +295 -0
- package/tools/memory/episodic.py +1210 -0
- package/tools/memory/git_invalidator.py +262 -0
- package/tools/memory/paths.py +102 -0
- package/tools/memory/scoring.py +193 -0
- package/tools/memory/search_store.py +360 -0
- package/tools/persist_transcript_analysis.py +85 -0
- package/tools/review/__init__.py +1 -0
- package/tools/review/review_engine.py +157 -0
- package/tools/scan/__init__.py +35 -0
- package/tools/scan/config.py +247 -0
- package/tools/scan/merge.py +212 -0
- package/tools/scan/orchestrator.py +549 -0
- package/tools/scan/registry.py +127 -0
- package/tools/scan/scanners/__init__.py +18 -0
- package/tools/scan/scanners/base.py +137 -0
- package/tools/scan/scanners/environment.py +349 -0
- package/tools/scan/scanners/git.py +570 -0
- package/tools/scan/scanners/infrastructure.py +875 -0
- package/tools/scan/scanners/orchestration.py +600 -0
- package/tools/scan/scanners/stack.py +1085 -0
- package/tools/scan/scanners/tools.py +260 -0
- package/tools/scan/setup.py +686 -0
- package/tools/scan/tests/__init__.py +1 -0
- package/tools/scan/tests/conftest.py +796 -0
- package/tools/scan/tests/test_environment.py +323 -0
- package/tools/scan/tests/test_git.py +419 -0
- package/tools/scan/tests/test_infrastructure.py +382 -0
- package/tools/scan/tests/test_integration.py +920 -0
- package/tools/scan/tests/test_merge.py +269 -0
- package/tools/scan/tests/test_orchestration.py +304 -0
- package/tools/scan/tests/test_stack.py +604 -0
- package/tools/scan/tests/test_tools.py +349 -0
- package/tools/scan/ui.py +624 -0
- package/tools/scan/verify.py +270 -0
- package/tools/scan/walk.py +118 -0
- package/tools/scan/workspace.py +85 -0
- package/tools/validation/README.md +244 -0
- package/tools/validation/__init__.py +17 -0
- package/tools/validation/approval_gate.py +321 -0
- 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();
|