@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.
- package/.claude-plugin/marketplace.json +33 -0
- package/.claude-plugin/plugin.json +26 -0
- package/ARCHITECTURE.md +335 -0
- package/CHANGELOG.md +1298 -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 +111 -0
- package/agents/gaia-planner.md +53 -0
- package/agents/gaia-system.md +71 -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 +651 -0
- package/bin/cli/history.py +305 -0
- package/bin/cli/memory.py +483 -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 +919 -0
- package/bin/pre-publish-validate.js +610 -0
- package/bin/python-detect.js +60 -0
- package/bin/validate-sandbox.sh +601 -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 +417 -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 +111 -0
- package/dist/gaia-ops/agents/gaia-planner.md +53 -0
- package/dist/gaia-ops/agents/gaia-system.md +71 -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 +417 -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 +192 -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 +333 -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_end_hook.py +77 -0
- package/dist/gaia-ops/hooks/session_start.py +81 -0
- package/dist/gaia-ops/hooks/stop_hook.py +70 -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 +158 -0
- package/dist/gaia-ops/skills/agent-creation/SKILL.md +87 -0
- package/dist/gaia-ops/skills/agent-creation/examples.md +170 -0
- package/dist/gaia-ops/skills/agent-creation/reference.md +191 -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 +185 -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 +85 -0
- package/dist/gaia-ops/skills/gaia-release/reference.md +92 -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/session-reflection/SKILL.md +69 -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 +375 -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 +113 -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 +333 -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_end_hook.py +77 -0
- package/dist/gaia-security/hooks/session_start.py +81 -0
- package/dist/gaia-security/hooks/stop_hook.py +70 -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 +333 -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_end_hook.py +77 -0
- package/hooks/session_start.py +81 -0
- package/hooks/stop_hook.py +70 -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 +103 -0
- package/pyproject.toml +32 -0
- package/skills/README.md +158 -0
- package/skills/agent-creation/SKILL.md +87 -0
- package/skills/agent-creation/examples.md +170 -0
- package/skills/agent-creation/reference.md +191 -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 +185 -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 +85 -0
- package/skills/gaia-release/reference.md +92 -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/session-reflection/SKILL.md +69 -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 +375 -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
package/bin/gaia
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
gaia -- Unified Gaia-Ops CLI
|
|
4
|
+
|
|
5
|
+
Entry point that discovers subcommand plugins from bin/cli/ and dispatches
|
|
6
|
+
to the matching handler. Zero external dependencies (stdlib only).
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python bin/gaia <subcommand> [options]
|
|
10
|
+
python bin/gaia --help
|
|
11
|
+
python bin/gaia status [--json]
|
|
12
|
+
python bin/gaia doctor [--json] [--fix]
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import importlib
|
|
17
|
+
import importlib.util
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
# Ensure the package root is on sys.path so submodules resolve correctly.
|
|
22
|
+
_SCRIPT_DIR = Path(__file__).resolve().parent
|
|
23
|
+
_PACKAGE_ROOT = _SCRIPT_DIR.parent
|
|
24
|
+
if str(_PACKAGE_ROOT) not in sys.path:
|
|
25
|
+
sys.path.insert(0, str(_PACKAGE_ROOT))
|
|
26
|
+
# Also ensure bin/ is on the path so bin/cli/ resolves as a package.
|
|
27
|
+
if str(_SCRIPT_DIR) not in sys.path:
|
|
28
|
+
sys.path.insert(0, str(_SCRIPT_DIR))
|
|
29
|
+
|
|
30
|
+
_CLI_DIR = _SCRIPT_DIR / "cli"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _discover_plugins():
|
|
34
|
+
"""Return a sorted list of (module_name, module) for all bin/cli/*.py plugins."""
|
|
35
|
+
plugins = []
|
|
36
|
+
if not _CLI_DIR.is_dir():
|
|
37
|
+
return plugins
|
|
38
|
+
|
|
39
|
+
for path in sorted(_CLI_DIR.glob("*.py")):
|
|
40
|
+
if path.stem == "__init__":
|
|
41
|
+
continue
|
|
42
|
+
spec = importlib.util.spec_from_file_location(f"cli.{path.stem}", path)
|
|
43
|
+
if spec is None:
|
|
44
|
+
continue
|
|
45
|
+
try:
|
|
46
|
+
mod = importlib.util.module_from_spec(spec)
|
|
47
|
+
spec.loader.exec_module(mod)
|
|
48
|
+
plugins.append((path.stem, mod))
|
|
49
|
+
except Exception as exc: # noqa: BLE001
|
|
50
|
+
print(f"Warning: could not load plugin {path.name}: {exc}", file=sys.stderr)
|
|
51
|
+
|
|
52
|
+
return plugins
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def main(argv=None):
|
|
56
|
+
"""CLI entry point. Returns exit code."""
|
|
57
|
+
parser = argparse.ArgumentParser(
|
|
58
|
+
prog="gaia",
|
|
59
|
+
description="Gaia-Ops unified CLI -- manage and inspect your Gaia installation.",
|
|
60
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
61
|
+
)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"--json",
|
|
64
|
+
action="store_true",
|
|
65
|
+
default=False,
|
|
66
|
+
help="Output results as JSON (machine-readable)",
|
|
67
|
+
)
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
"--version",
|
|
70
|
+
action="store_true",
|
|
71
|
+
default=False,
|
|
72
|
+
help="Print version and exit",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
subparsers = parser.add_subparsers(dest="subcommand", metavar="<subcommand>")
|
|
76
|
+
|
|
77
|
+
# Discover and register plugins
|
|
78
|
+
plugins = _discover_plugins()
|
|
79
|
+
for _name, mod in plugins:
|
|
80
|
+
if hasattr(mod, "register"):
|
|
81
|
+
mod.register(subparsers)
|
|
82
|
+
|
|
83
|
+
args = parser.parse_args(argv)
|
|
84
|
+
|
|
85
|
+
if args.version:
|
|
86
|
+
# Print version from package.json
|
|
87
|
+
try:
|
|
88
|
+
import json
|
|
89
|
+
pkg = _PACKAGE_ROOT / "package.json"
|
|
90
|
+
version = json.loads(pkg.read_text())["version"]
|
|
91
|
+
print(f"gaia {version}")
|
|
92
|
+
except Exception:
|
|
93
|
+
print("gaia (version unknown)")
|
|
94
|
+
return 0
|
|
95
|
+
|
|
96
|
+
if args.subcommand is None:
|
|
97
|
+
parser.print_help()
|
|
98
|
+
return 0
|
|
99
|
+
|
|
100
|
+
# Dispatch to the matching plugin handler
|
|
101
|
+
for name, mod in plugins:
|
|
102
|
+
if name == args.subcommand and hasattr(mod, f"cmd_{name}"):
|
|
103
|
+
handler = getattr(mod, f"cmd_{name}")
|
|
104
|
+
return handler(args) or 0
|
|
105
|
+
|
|
106
|
+
# Subcommand registered but handler not found -- should not happen
|
|
107
|
+
print(f"gaia: unknown subcommand '{args.subcommand}'", file=sys.stderr)
|
|
108
|
+
return 1
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
if __name__ == "__main__":
|
|
112
|
+
sys.exit(main())
|
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @jaguilar87/gaia - Cleanup script
|
|
5
|
+
*
|
|
6
|
+
* Purpose:
|
|
7
|
+
* - Remove CLAUDE.md
|
|
8
|
+
* - Remove settings.json
|
|
9
|
+
* - Remove all symlinks (agents, tools, hooks, commands, config, templates, CHANGELOG.md)
|
|
10
|
+
* - Preserve project-specific data (logs, tests, project-context, session, metrics)
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* Manual: npx gaia-cleanup
|
|
14
|
+
* Automatic: Runs via preuninstall hook when uninstalling from npm registry
|
|
15
|
+
*
|
|
16
|
+
* IMPORTANT FOR LOCAL DEVELOPMENT:
|
|
17
|
+
* When testing with local installs (npm install ./gaia-ops), the preuninstall hook
|
|
18
|
+
* will NOT execute automatically due to npm's file: protocol behavior.
|
|
19
|
+
* You must run 'npx gaia-cleanup' manually before uninstalling:
|
|
20
|
+
*
|
|
21
|
+
* npx gaia-cleanup && npm uninstall @jaguilar87/gaia
|
|
22
|
+
*
|
|
23
|
+
* When installed from npm registry, cleanup happens automatically on uninstall.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { join, dirname, resolve } from 'path';
|
|
27
|
+
import fs from 'fs/promises';
|
|
28
|
+
import { existsSync, lstatSync, statSync, readdirSync } from 'fs';
|
|
29
|
+
import chalk from 'chalk';
|
|
30
|
+
import ora from 'ora';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Find the project root directory by looking for .claude/ directory
|
|
34
|
+
* Searches upward from the current working directory
|
|
35
|
+
*/
|
|
36
|
+
function findProjectRoot() {
|
|
37
|
+
// First try INIT_CWD (available during npm install/uninstall)
|
|
38
|
+
if (process.env.INIT_CWD) {
|
|
39
|
+
const claudeDir = join(process.env.INIT_CWD, '.claude');
|
|
40
|
+
if (existsSync(claudeDir)) {
|
|
41
|
+
return process.env.INIT_CWD;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Search upward from current directory
|
|
46
|
+
let currentDir = process.cwd();
|
|
47
|
+
const root = resolve('/');
|
|
48
|
+
|
|
49
|
+
while (currentDir !== root) {
|
|
50
|
+
const claudeDir = join(currentDir, '.claude');
|
|
51
|
+
if (existsSync(claudeDir)) {
|
|
52
|
+
return currentDir;
|
|
53
|
+
}
|
|
54
|
+
currentDir = dirname(currentDir);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Fallback to current directory
|
|
58
|
+
return process.env.INIT_CWD || process.cwd();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const CWD = findProjectRoot();
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Remove legacy CLAUDE.md if it exists (identity now injected by hook).
|
|
65
|
+
*/
|
|
66
|
+
async function removeClaudeMd() {
|
|
67
|
+
const spinner = ora('Removing CLAUDE.md...').start();
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const claudeMdPath = join(CWD, 'CLAUDE.md');
|
|
71
|
+
|
|
72
|
+
if (!existsSync(claudeMdPath)) {
|
|
73
|
+
spinner.info('CLAUDE.md not found, skipping');
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
await fs.unlink(claudeMdPath);
|
|
78
|
+
spinner.succeed('CLAUDE.md removed');
|
|
79
|
+
return true;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
spinner.fail(`Failed to remove CLAUDE.md: ${error.message}`);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Remove settings.json if it exists
|
|
88
|
+
*/
|
|
89
|
+
async function removeSettingsJson() {
|
|
90
|
+
const spinner = ora('Removing settings.json...').start();
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const settingsPath = join(CWD, '.claude', 'settings.json');
|
|
94
|
+
|
|
95
|
+
if (!existsSync(settingsPath)) {
|
|
96
|
+
spinner.info('settings.json not found, skipping');
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
await fs.unlink(settingsPath);
|
|
101
|
+
spinner.succeed('settings.json removed');
|
|
102
|
+
return true;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
spinner.fail(`Failed to remove settings.json: ${error.message}`);
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Remove all symlinks in .claude/ directory
|
|
111
|
+
*/
|
|
112
|
+
async function removeSymlinks() {
|
|
113
|
+
const spinner = ora('Removing symlinks...').start();
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const claudeDir = join(CWD, '.claude');
|
|
117
|
+
|
|
118
|
+
if (!existsSync(claudeDir)) {
|
|
119
|
+
spinner.info('.claude/ directory not found, skipping');
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Define all symlinks that should be removed
|
|
124
|
+
const symlinks = [
|
|
125
|
+
join(claudeDir, 'agents'),
|
|
126
|
+
join(claudeDir, 'tools'),
|
|
127
|
+
join(claudeDir, 'hooks'),
|
|
128
|
+
join(claudeDir, 'commands'),
|
|
129
|
+
join(claudeDir, 'templates'),
|
|
130
|
+
join(claudeDir, 'config'),
|
|
131
|
+
join(claudeDir, 'CHANGELOG.md'),
|
|
132
|
+
join(claudeDir, 'README.en.md'),
|
|
133
|
+
join(claudeDir, 'README.md')
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
// Also remove AGENTS.md at project root
|
|
137
|
+
const agentsMdPath = join(CWD, 'AGENTS.md');
|
|
138
|
+
|
|
139
|
+
let removed = 0;
|
|
140
|
+
|
|
141
|
+
// Remove known symlinks in .claude/
|
|
142
|
+
for (const symlinkPath of symlinks) {
|
|
143
|
+
try {
|
|
144
|
+
// Use lstat to check if path exists as a symlink (works for broken symlinks too)
|
|
145
|
+
const stats = lstatSync(symlinkPath);
|
|
146
|
+
if (stats.isSymbolicLink() || stats.isFile()) {
|
|
147
|
+
await fs.unlink(symlinkPath);
|
|
148
|
+
removed++;
|
|
149
|
+
}
|
|
150
|
+
} catch (error) {
|
|
151
|
+
// Path doesn't exist or other error, skip
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Remove AGENTS.md at project root (it's a symlink)
|
|
156
|
+
try {
|
|
157
|
+
const stats = lstatSync(agentsMdPath);
|
|
158
|
+
if (stats.isSymbolicLink() || stats.isFile()) {
|
|
159
|
+
await fs.unlink(agentsMdPath);
|
|
160
|
+
removed++;
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
// Path doesn't exist, skip
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Scan for ANY other broken symlinks in .claude/ directory
|
|
167
|
+
try {
|
|
168
|
+
const entries = await fs.readdir(claudeDir);
|
|
169
|
+
for (const entry of entries) {
|
|
170
|
+
const fullPath = join(claudeDir, entry);
|
|
171
|
+
try {
|
|
172
|
+
const stats = lstatSync(fullPath);
|
|
173
|
+
// Check if it's a symlink
|
|
174
|
+
if (stats.isSymbolicLink()) {
|
|
175
|
+
// Try to access the target to see if it's broken
|
|
176
|
+
try {
|
|
177
|
+
await fs.access(fullPath);
|
|
178
|
+
// Symlink is valid, skip
|
|
179
|
+
} catch {
|
|
180
|
+
// Symlink is broken, remove it
|
|
181
|
+
await fs.unlink(fullPath);
|
|
182
|
+
removed++;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
// Skip if can't check
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
} catch (error) {
|
|
190
|
+
// Can't read directory, skip scan
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (removed > 0) {
|
|
194
|
+
spinner.succeed(`Removed ${removed} symlink(s)`);
|
|
195
|
+
return true;
|
|
196
|
+
} else {
|
|
197
|
+
spinner.info('No symlinks found to remove');
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
} catch (error) {
|
|
201
|
+
spinner.fail(`Failed to remove symlinks: ${error.message}`);
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Data retention policy configuration
|
|
208
|
+
* Defines max age in days for each data category
|
|
209
|
+
*/
|
|
210
|
+
const RETENTION_POLICY = {
|
|
211
|
+
auditLogs: { pattern: 'audit-*.jsonl', dir: '.claude/logs', maxDays: 30, label: 'Audit logs' },
|
|
212
|
+
hookLogs: { pattern: 'hooks-*.log', dir: '.claude/logs', maxDays: 14, label: 'Hook logs' },
|
|
213
|
+
monthlyMetrics: { pattern: 'metrics-*.jsonl', dir: '.claude/metrics', maxDays: 90, label: 'Monthly metrics' },
|
|
214
|
+
responseContract: { type: 'dirs', dir: '.claude/session/active/response-contract', maxDays: 7, label: 'Response contract sessions' },
|
|
215
|
+
episodicEpisodes: { pattern: '*.json', dir: '.claude/project-context/episodic-memory/episodes', maxDays: 90, label: 'Episodic memory episodes' },
|
|
216
|
+
workflowMetrics: { type: 'truncate-jsonl', file: '.claude/project-context/workflow-episodic-memory/metrics.jsonl', maxDays: 90, label: 'Workflow metrics' },
|
|
217
|
+
anomalies: { type: 'truncate-jsonl', file: '.claude/project-context/workflow-episodic-memory/anomalies.jsonl', maxDays: 90, label: 'Anomalies' },
|
|
218
|
+
legacyLogs: { type: 'legacy', dir: '.claude/logs', patterns: ['pre_tool_use_v2-*.log', 'post_tool_use_v2-*.log', 'subagent_stop-*.log'], label: 'Legacy logs' },
|
|
219
|
+
anomalyFlag: { type: 'flag-ttl', file: '.claude/project-context/workflow-episodic-memory/signals/needs_analysis.flag', maxHours: 1, label: 'Anomaly signal flag' },
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Check if a filename matches a glob-like pattern (supports * wildcard)
|
|
224
|
+
*/
|
|
225
|
+
function matchesPattern(filename, pattern) {
|
|
226
|
+
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
|
|
227
|
+
return new RegExp(`^${escaped}$`).test(filename);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Delete files matching a pattern that are older than maxDays
|
|
232
|
+
*/
|
|
233
|
+
async function pruneOldFiles(dirPath, pattern, maxDays, label) {
|
|
234
|
+
const fullDir = join(CWD, dirPath);
|
|
235
|
+
if (!existsSync(fullDir)) return 0;
|
|
236
|
+
|
|
237
|
+
const cutoff = Date.now() - maxDays * 24 * 60 * 60 * 1000;
|
|
238
|
+
let removed = 0;
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
const entries = readdirSync(fullDir);
|
|
242
|
+
for (const entry of entries) {
|
|
243
|
+
if (!matchesPattern(entry, pattern)) continue;
|
|
244
|
+
const fullPath = join(fullDir, entry);
|
|
245
|
+
try {
|
|
246
|
+
const stats = statSync(fullPath);
|
|
247
|
+
if (stats.isFile() && stats.mtimeMs < cutoff) {
|
|
248
|
+
await fs.unlink(fullPath);
|
|
249
|
+
console.log(chalk.gray(` Pruned: ${dirPath}/${entry} (${label})`));
|
|
250
|
+
removed++;
|
|
251
|
+
}
|
|
252
|
+
} catch { /* skip unreadable files */ }
|
|
253
|
+
}
|
|
254
|
+
} catch { /* directory not readable */ }
|
|
255
|
+
|
|
256
|
+
return removed;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Delete directories older than maxDays (by modification time)
|
|
261
|
+
*/
|
|
262
|
+
async function pruneOldDirs(dirPath, maxDays, label) {
|
|
263
|
+
const fullDir = join(CWD, dirPath);
|
|
264
|
+
if (!existsSync(fullDir)) return 0;
|
|
265
|
+
|
|
266
|
+
const cutoff = Date.now() - maxDays * 24 * 60 * 60 * 1000;
|
|
267
|
+
let removed = 0;
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
const entries = readdirSync(fullDir);
|
|
271
|
+
for (const entry of entries) {
|
|
272
|
+
const fullPath = join(fullDir, entry);
|
|
273
|
+
try {
|
|
274
|
+
const stats = statSync(fullPath);
|
|
275
|
+
if (stats.isDirectory() && stats.mtimeMs < cutoff) {
|
|
276
|
+
await fs.rm(fullPath, { recursive: true, force: true });
|
|
277
|
+
console.log(chalk.gray(` Pruned dir: ${dirPath}/${entry} (${label})`));
|
|
278
|
+
removed++;
|
|
279
|
+
}
|
|
280
|
+
} catch { /* skip */ }
|
|
281
|
+
}
|
|
282
|
+
} catch { /* directory not readable */ }
|
|
283
|
+
|
|
284
|
+
return removed;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Truncate a JSONL file, keeping only entries newer than maxDays
|
|
289
|
+
* Entries must have a "timestamp" field (ISO 8601)
|
|
290
|
+
*/
|
|
291
|
+
async function truncateJsonl(filePath, maxDays, label) {
|
|
292
|
+
const fullPath = join(CWD, filePath);
|
|
293
|
+
if (!existsSync(fullPath)) return 0;
|
|
294
|
+
|
|
295
|
+
const cutoff = Date.now() - maxDays * 24 * 60 * 60 * 1000;
|
|
296
|
+
let removedCount = 0;
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
300
|
+
const lines = content.trim().split('\n').filter(l => l.trim());
|
|
301
|
+
const kept = [];
|
|
302
|
+
|
|
303
|
+
for (const line of lines) {
|
|
304
|
+
try {
|
|
305
|
+
const entry = JSON.parse(line);
|
|
306
|
+
const ts = entry.timestamp ? new Date(entry.timestamp).getTime() : Date.now();
|
|
307
|
+
if (ts >= cutoff) {
|
|
308
|
+
kept.push(line);
|
|
309
|
+
} else {
|
|
310
|
+
removedCount++;
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
// Unparseable line - keep it to be safe
|
|
314
|
+
kept.push(line);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (removedCount > 0) {
|
|
319
|
+
await fs.writeFile(fullPath, kept.join('\n') + (kept.length ? '\n' : ''));
|
|
320
|
+
console.log(chalk.gray(` Truncated: ${filePath} - removed ${removedCount} old entries (${label})`));
|
|
321
|
+
}
|
|
322
|
+
} catch { /* file not readable */ }
|
|
323
|
+
|
|
324
|
+
return removedCount;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Delete legacy log files that should no longer exist
|
|
329
|
+
*/
|
|
330
|
+
async function pruneLegacyLogs(dirPath, patterns, label) {
|
|
331
|
+
const fullDir = join(CWD, dirPath);
|
|
332
|
+
if (!existsSync(fullDir)) return 0;
|
|
333
|
+
|
|
334
|
+
let removed = 0;
|
|
335
|
+
|
|
336
|
+
try {
|
|
337
|
+
const entries = readdirSync(fullDir);
|
|
338
|
+
for (const entry of entries) {
|
|
339
|
+
const matches = patterns.some(p => matchesPattern(entry, p));
|
|
340
|
+
if (!matches) continue;
|
|
341
|
+
const fullPath = join(fullDir, entry);
|
|
342
|
+
try {
|
|
343
|
+
const stats = statSync(fullPath);
|
|
344
|
+
if (stats.isFile()) {
|
|
345
|
+
await fs.unlink(fullPath);
|
|
346
|
+
console.log(chalk.gray(` Deleted legacy: ${dirPath}/${entry} (${label})`));
|
|
347
|
+
removed++;
|
|
348
|
+
}
|
|
349
|
+
} catch { /* skip */ }
|
|
350
|
+
}
|
|
351
|
+
} catch { /* directory not readable */ }
|
|
352
|
+
|
|
353
|
+
return removed;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Delete a flag file if it is older than maxHours
|
|
358
|
+
*/
|
|
359
|
+
async function pruneFlagByTtl(filePath, maxHours, label) {
|
|
360
|
+
const fullPath = join(CWD, filePath);
|
|
361
|
+
if (!existsSync(fullPath)) return 0;
|
|
362
|
+
|
|
363
|
+
const cutoff = Date.now() - maxHours * 60 * 60 * 1000;
|
|
364
|
+
|
|
365
|
+
try {
|
|
366
|
+
const stats = statSync(fullPath);
|
|
367
|
+
if (stats.mtimeMs < cutoff) {
|
|
368
|
+
await fs.unlink(fullPath);
|
|
369
|
+
console.log(chalk.gray(` Expired flag: ${filePath} (${label})`));
|
|
370
|
+
return 1;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Also check created_at timestamp inside the JSON
|
|
374
|
+
try {
|
|
375
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
376
|
+
const data = JSON.parse(content);
|
|
377
|
+
const createdAt = data.created_at || data.timestamp;
|
|
378
|
+
if (createdAt) {
|
|
379
|
+
const createdMs = new Date(createdAt).getTime();
|
|
380
|
+
if (createdMs < cutoff) {
|
|
381
|
+
await fs.unlink(fullPath);
|
|
382
|
+
console.log(chalk.gray(` Expired flag (by created_at): ${filePath} (${label})`));
|
|
383
|
+
return 1;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
} catch { /* not valid JSON, use mtime check above */ }
|
|
387
|
+
} catch { /* file not accessible */ }
|
|
388
|
+
|
|
389
|
+
return 0;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Rebuild episodic memory index after pruning episodes
|
|
394
|
+
*/
|
|
395
|
+
async function rebuildEpisodicIndex() {
|
|
396
|
+
const episodesDir = join(CWD, '.claude/project-context/episodic-memory/episodes');
|
|
397
|
+
const indexPath = join(CWD, '.claude/project-context/episodic-memory/index.json');
|
|
398
|
+
|
|
399
|
+
if (!existsSync(episodesDir)) return;
|
|
400
|
+
|
|
401
|
+
try {
|
|
402
|
+
const entries = readdirSync(episodesDir).filter(e => e.endsWith('.json')).sort();
|
|
403
|
+
const index = [];
|
|
404
|
+
|
|
405
|
+
for (const entry of entries) {
|
|
406
|
+
try {
|
|
407
|
+
const content = await fs.readFile(join(episodesDir, entry), 'utf-8');
|
|
408
|
+
const episode = JSON.parse(content);
|
|
409
|
+
index.push({
|
|
410
|
+
id: episode.id || entry.replace('.json', ''),
|
|
411
|
+
timestamp: episode.timestamp || '',
|
|
412
|
+
prompt_summary: (episode.prompt || '').slice(0, 100),
|
|
413
|
+
outcome: episode.outcome || 'unknown',
|
|
414
|
+
tags: episode.tags || [],
|
|
415
|
+
});
|
|
416
|
+
} catch { /* skip unparseable */ }
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
await fs.writeFile(indexPath, JSON.stringify({ episodes: index, rebuilt_at: new Date().toISOString() }, null, 2));
|
|
420
|
+
console.log(chalk.gray(` Rebuilt episodic index: ${index.length} episodes`));
|
|
421
|
+
} catch (error) {
|
|
422
|
+
console.log(chalk.yellow(` Warning: could not rebuild episodic index: ${error.message}`));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Apply data retention policy - prune old data across all categories
|
|
428
|
+
*/
|
|
429
|
+
async function applyRetentionPolicy() {
|
|
430
|
+
const spinner = ora('Applying data retention policy...').start();
|
|
431
|
+
|
|
432
|
+
let totalPruned = 0;
|
|
433
|
+
|
|
434
|
+
try {
|
|
435
|
+
for (const [_key, policy] of Object.entries(RETENTION_POLICY)) {
|
|
436
|
+
if (policy.type === 'dirs') {
|
|
437
|
+
totalPruned += await pruneOldDirs(policy.dir, policy.maxDays, policy.label);
|
|
438
|
+
} else if (policy.type === 'truncate-jsonl') {
|
|
439
|
+
totalPruned += await truncateJsonl(policy.file, policy.maxDays, policy.label);
|
|
440
|
+
} else if (policy.type === 'legacy') {
|
|
441
|
+
totalPruned += await pruneLegacyLogs(policy.dir, policy.patterns, policy.label);
|
|
442
|
+
} else if (policy.type === 'flag-ttl') {
|
|
443
|
+
totalPruned += await pruneFlagByTtl(policy.file, policy.maxHours, policy.label);
|
|
444
|
+
} else if (policy.pattern) {
|
|
445
|
+
totalPruned += await pruneOldFiles(policy.dir, policy.pattern, policy.maxDays, policy.label);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Rebuild episodic index if any episodes were pruned
|
|
450
|
+
if (totalPruned > 0) {
|
|
451
|
+
await rebuildEpisodicIndex();
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (totalPruned > 0) {
|
|
455
|
+
spinner.succeed(`Data retention applied: ${totalPruned} item(s) pruned`);
|
|
456
|
+
} else {
|
|
457
|
+
spinner.info('Data retention: nothing to prune');
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return totalPruned > 0;
|
|
461
|
+
} catch (error) {
|
|
462
|
+
spinner.fail(`Data retention failed: ${error.message}`);
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Main function
|
|
469
|
+
*/
|
|
470
|
+
async function main() {
|
|
471
|
+
process.stderr.write('[DEPRECATED] gaia-cleanup.js is deprecated. Use: python3 bin/gaia cleanup\n[DEPRECATED] Migration guide: see CHANGELOG.md\n');
|
|
472
|
+
|
|
473
|
+
const args = process.argv.slice(2);
|
|
474
|
+
const pruneOnly = args.includes('--prune') || args.includes('--retain');
|
|
475
|
+
|
|
476
|
+
if (pruneOnly) {
|
|
477
|
+
console.log(chalk.cyan('\n🧹 @jaguilar87/gaia data retention\n'));
|
|
478
|
+
console.log(chalk.gray('Retention policy:'));
|
|
479
|
+
console.log(chalk.gray(' Audit logs: 30 days'));
|
|
480
|
+
console.log(chalk.gray(' Hook logs: 14 days'));
|
|
481
|
+
console.log(chalk.gray(' Monthly metrics: 90 days'));
|
|
482
|
+
console.log(chalk.gray(' Response contracts: 7 days'));
|
|
483
|
+
console.log(chalk.gray(' Episodic episodes: 90 days'));
|
|
484
|
+
console.log(chalk.gray(' Workflow metrics: 90 days'));
|
|
485
|
+
console.log(chalk.gray(' Anomalies: 90 days'));
|
|
486
|
+
console.log(chalk.gray(' Legacy logs: all removed'));
|
|
487
|
+
console.log(chalk.gray(' Anomaly flag: 1 hour TTL\n'));
|
|
488
|
+
|
|
489
|
+
try {
|
|
490
|
+
const pruned = await applyRetentionPolicy();
|
|
491
|
+
if (pruned) {
|
|
492
|
+
console.log(chalk.green('\n✅ Data retention completed\n'));
|
|
493
|
+
} else {
|
|
494
|
+
console.log(chalk.gray('\n✓ All data within retention limits\n'));
|
|
495
|
+
}
|
|
496
|
+
} catch (error) {
|
|
497
|
+
console.error(chalk.red(`\n❌ Data retention failed: ${error.message}\n`));
|
|
498
|
+
process.exit(1);
|
|
499
|
+
}
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
console.log(chalk.cyan('\n🧹 @jaguilar87/gaia cleanup\n'));
|
|
504
|
+
|
|
505
|
+
try {
|
|
506
|
+
const claudeRemoved = await removeClaudeMd();
|
|
507
|
+
const settingsRemoved = await removeSettingsJson();
|
|
508
|
+
const symlinksRemoved = await removeSymlinks();
|
|
509
|
+
|
|
510
|
+
// Always apply data retention as part of cleanup
|
|
511
|
+
const retentionApplied = await applyRetentionPolicy();
|
|
512
|
+
|
|
513
|
+
if (claudeRemoved || settingsRemoved || symlinksRemoved || retentionApplied) {
|
|
514
|
+
console.log(chalk.green('\n✅ Cleanup completed\n'));
|
|
515
|
+
console.log(chalk.gray('Preserved data:'));
|
|
516
|
+
console.log(chalk.gray(' • .claude/logs/'));
|
|
517
|
+
console.log(chalk.gray(' • .claude/tests/'));
|
|
518
|
+
console.log(chalk.gray(' • .claude/project-context/'));
|
|
519
|
+
console.log(chalk.gray(' • .claude/session/'));
|
|
520
|
+
console.log(chalk.gray(' • .claude/metrics/\n'));
|
|
521
|
+
} else {
|
|
522
|
+
console.log(chalk.gray('\n✓ Nothing to clean up\n'));
|
|
523
|
+
}
|
|
524
|
+
} catch (error) {
|
|
525
|
+
console.error(chalk.red(`\n❌ Cleanup failed: ${error.message}\n`));
|
|
526
|
+
// Don't fail npm uninstall, just warn
|
|
527
|
+
process.exit(0);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
main();
|