@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
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# validate-sandbox.sh -- end-to-end consumer-install verification harness.
|
|
3
|
+
#
|
|
4
|
+
# Two target modes:
|
|
5
|
+
#
|
|
6
|
+
# --target sandbox (default):
|
|
7
|
+
# Creates an ephemeral sandbox project populated from
|
|
8
|
+
# tests/fixtures/sandbox-project/, installs the target Gaia version, and
|
|
9
|
+
# exercises the install-time code paths (postinstall hook merge, FTS5
|
|
10
|
+
# backfill safety-net) plus read-side CLI surface (version, doctor,
|
|
11
|
+
# status, context show, memory stats/search, scan).
|
|
12
|
+
#
|
|
13
|
+
# --target local:
|
|
14
|
+
# Installs Gaia directly into a real workspace. If --workspace <path> is
|
|
15
|
+
# passed, that path is used as-is. Otherwise auto-detection walks up
|
|
16
|
+
# from cwd looking for a .claude/ with a Gaia instance marker
|
|
17
|
+
# (.claude/hooks/, .claude/agents/, or node_modules/@jaguilar87/gaia/),
|
|
18
|
+
# falling back to $HOME/ws/me/ if present. NO cleanup -- the install
|
|
19
|
+
# IS the installation. A fresh tarball install avoids per-path approval
|
|
20
|
+
# prompts for edited files during a session.
|
|
21
|
+
#
|
|
22
|
+
# Exit 0 when every check passes; 1 otherwise. `--stay` keeps the sandbox
|
|
23
|
+
# dir for post-mortem inspection (path printed on exit). Only meaningful
|
|
24
|
+
# with --target sandbox.
|
|
25
|
+
|
|
26
|
+
set -euo pipefail
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# Argparse
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
VERSION_SPEC=""
|
|
33
|
+
TARBALL_PATH=""
|
|
34
|
+
STAY=0
|
|
35
|
+
TARGET="sandbox"
|
|
36
|
+
WORKSPACE_OVERRIDE=""
|
|
37
|
+
|
|
38
|
+
usage() {
|
|
39
|
+
cat <<'EOF'
|
|
40
|
+
Usage:
|
|
41
|
+
bin/validate-sandbox.sh [--version <spec>] [--tarball <path>]
|
|
42
|
+
[--target sandbox|local] [--workspace <path>]
|
|
43
|
+
[--stay]
|
|
44
|
+
|
|
45
|
+
Options:
|
|
46
|
+
--version <spec> npm version specifier, e.g. "@rc", "@5.0.0-rc1",
|
|
47
|
+
"@jaguilar87/gaia@5.0.0-rc1". Default: "@rc".
|
|
48
|
+
--tarball <path> Install from a local tarball (from `npm pack`).
|
|
49
|
+
Takes precedence over --version.
|
|
50
|
+
--target <mode> sandbox (default): ephemeral /tmp/gaia-sandbox-<ts>/.
|
|
51
|
+
local: install over a real workspace (see --workspace
|
|
52
|
+
or auto-detect from cwd).
|
|
53
|
+
Local mode skips the settings-preservation check
|
|
54
|
+
(no pre-install snapshot of the real workspace).
|
|
55
|
+
--workspace <path> Explicit target directory for --target local.
|
|
56
|
+
Bypasses auto-detection. Ignored with --target sandbox.
|
|
57
|
+
--stay Do NOT clean up the sandbox dir on exit. Useful for
|
|
58
|
+
debugging; sandbox path is printed on exit.
|
|
59
|
+
Ignored with --target local.
|
|
60
|
+
--help, -h Print this help and exit.
|
|
61
|
+
EOF
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
while [[ $# -gt 0 ]]; do
|
|
65
|
+
case "$1" in
|
|
66
|
+
--version)
|
|
67
|
+
VERSION_SPEC="$2"
|
|
68
|
+
shift 2
|
|
69
|
+
;;
|
|
70
|
+
--tarball)
|
|
71
|
+
TARBALL_PATH="$2"
|
|
72
|
+
shift 2
|
|
73
|
+
;;
|
|
74
|
+
--target)
|
|
75
|
+
TARGET="$2"
|
|
76
|
+
shift 2
|
|
77
|
+
;;
|
|
78
|
+
--workspace)
|
|
79
|
+
WORKSPACE_OVERRIDE="$2"
|
|
80
|
+
shift 2
|
|
81
|
+
;;
|
|
82
|
+
--stay)
|
|
83
|
+
STAY=1
|
|
84
|
+
shift
|
|
85
|
+
;;
|
|
86
|
+
--help|-h)
|
|
87
|
+
usage
|
|
88
|
+
exit 0
|
|
89
|
+
;;
|
|
90
|
+
*)
|
|
91
|
+
echo "Unknown argument: $1" >&2
|
|
92
|
+
usage >&2
|
|
93
|
+
exit 2
|
|
94
|
+
;;
|
|
95
|
+
esac
|
|
96
|
+
done
|
|
97
|
+
|
|
98
|
+
if [[ "${TARGET}" != "sandbox" && "${TARGET}" != "local" ]]; then
|
|
99
|
+
echo "FATAL: --target must be 'sandbox' or 'local', got '${TARGET}'" >&2
|
|
100
|
+
exit 2
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# Default to @rc when no install source given.
|
|
104
|
+
if [[ -z "${TARBALL_PATH}" && -z "${VERSION_SPEC}" ]]; then
|
|
105
|
+
VERSION_SPEC="@rc"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# ---------------------------------------------------------------------------
|
|
109
|
+
# Paths
|
|
110
|
+
# ---------------------------------------------------------------------------
|
|
111
|
+
|
|
112
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
113
|
+
FIXTURE_DIR="${REPO_ROOT}/tests/fixtures/sandbox-project"
|
|
114
|
+
|
|
115
|
+
if [[ "${TARGET}" == "sandbox" && ! -d "${FIXTURE_DIR}" ]]; then
|
|
116
|
+
echo "FATAL: fixture dir not found at ${FIXTURE_DIR}" >&2
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if [[ -n "${TARBALL_PATH}" ]]; then
|
|
121
|
+
# Resolve relative to cwd, then check existence
|
|
122
|
+
if [[ "${TARBALL_PATH}" != /* ]]; then
|
|
123
|
+
TARBALL_PATH="$(cd "$(dirname "${TARBALL_PATH}")" && pwd)/$(basename "${TARBALL_PATH}")"
|
|
124
|
+
fi
|
|
125
|
+
if [[ ! -f "${TARBALL_PATH}" ]]; then
|
|
126
|
+
echo "FATAL: tarball not found at ${TARBALL_PATH}" >&2
|
|
127
|
+
exit 1
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
# ---------------------------------------------------------------------------
|
|
132
|
+
# Determine working directory based on target
|
|
133
|
+
# ---------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
is_gaia_instance() {
|
|
136
|
+
# A directory is a Gaia instance if it has .claude/ with hook or agent
|
|
137
|
+
# content, or an already-installed Gaia package in node_modules.
|
|
138
|
+
local dir="$1"
|
|
139
|
+
[[ -d "${dir}/.claude/hooks" ]] && return 0
|
|
140
|
+
[[ -d "${dir}/.claude/agents" ]] && return 0
|
|
141
|
+
[[ -d "${dir}/node_modules/@jaguilar87/gaia" ]] && return 0
|
|
142
|
+
return 1
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
detect_local_workspace() {
|
|
146
|
+
# Priority 1: walk up from cwd looking for .claude/ with a Gaia marker.
|
|
147
|
+
# Preferring cwd means `cd project-X && npm run gaia:install-local`
|
|
148
|
+
# installs into project-X, not whatever comes first in $HOME.
|
|
149
|
+
local dir
|
|
150
|
+
dir="$(pwd)"
|
|
151
|
+
while [[ "${dir}" != "/" ]]; do
|
|
152
|
+
if [[ -d "${dir}/.claude" ]] && is_gaia_instance "${dir}"; then
|
|
153
|
+
echo "${dir}"
|
|
154
|
+
return 0
|
|
155
|
+
fi
|
|
156
|
+
dir="$(dirname "${dir}")"
|
|
157
|
+
done
|
|
158
|
+
# Priority 2: fallback to $HOME/ws/me if it exists and has .claude/.
|
|
159
|
+
if [[ -d "${HOME}/ws/me/.claude" ]]; then
|
|
160
|
+
echo "${HOME}/ws/me"
|
|
161
|
+
return 0
|
|
162
|
+
fi
|
|
163
|
+
return 1
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
is_noexec_mount() {
|
|
167
|
+
# Return 0 (true) if the directory's filesystem is mounted with noexec.
|
|
168
|
+
# Some WSL/Linux setups mount /tmp as tmpfs with noexec, which makes the
|
|
169
|
+
# installed bin shims unrunnable (rc=126 Permission denied) even though
|
|
170
|
+
# the exec bit is set. We detect that and pick a safe fallback.
|
|
171
|
+
local dir="$1"
|
|
172
|
+
[[ -d "${dir}" ]] || return 1
|
|
173
|
+
# findmnt is the most reliable; fall back to parsing /proc/mounts.
|
|
174
|
+
if command -v findmnt >/dev/null 2>&1; then
|
|
175
|
+
local opts
|
|
176
|
+
opts="$(findmnt -no OPTIONS --target "${dir}" 2>/dev/null || true)"
|
|
177
|
+
[[ "${opts}" == *noexec* ]] && return 0
|
|
178
|
+
return 1
|
|
179
|
+
fi
|
|
180
|
+
# Best-effort fallback: walk /proc/mounts for the longest matching mountpoint.
|
|
181
|
+
local resolved best_mp="" best_opts=""
|
|
182
|
+
resolved="$(cd "${dir}" 2>/dev/null && pwd -P)" || resolved="${dir}"
|
|
183
|
+
while IFS=' ' read -r _src mp _fs opts _rest; do
|
|
184
|
+
case "${resolved}/" in
|
|
185
|
+
"${mp}/"*)
|
|
186
|
+
if [[ ${#mp} -gt ${#best_mp} ]]; then
|
|
187
|
+
best_mp="${mp}"
|
|
188
|
+
best_opts="${opts}"
|
|
189
|
+
fi
|
|
190
|
+
;;
|
|
191
|
+
esac
|
|
192
|
+
done < /proc/mounts
|
|
193
|
+
[[ "${best_opts}" == *noexec* ]] && return 0
|
|
194
|
+
return 1
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
select_sandbox_prefix() {
|
|
198
|
+
# Pick a parent directory for the ephemeral sandbox.
|
|
199
|
+
# Order: $TMPDIR (if set and exec-capable) -> /tmp (if exec-capable) ->
|
|
200
|
+
# $HOME/.cache/gaia-sandbox. Each candidate is rejected if its filesystem
|
|
201
|
+
# is mounted noexec, since npm bin shims must be directly executable.
|
|
202
|
+
local candidate
|
|
203
|
+
if [[ -n "${TMPDIR:-}" && -d "${TMPDIR}" ]]; then
|
|
204
|
+
if ! is_noexec_mount "${TMPDIR}"; then
|
|
205
|
+
echo "${TMPDIR%/}"
|
|
206
|
+
return 0
|
|
207
|
+
fi
|
|
208
|
+
echo "[sandbox] TMPDIR=${TMPDIR} is mounted noexec; falling back" >&2
|
|
209
|
+
fi
|
|
210
|
+
if [[ -d /tmp ]] && ! is_noexec_mount /tmp; then
|
|
211
|
+
echo "/tmp"
|
|
212
|
+
return 0
|
|
213
|
+
fi
|
|
214
|
+
if [[ -d /tmp ]]; then
|
|
215
|
+
echo "[sandbox] /tmp is mounted noexec; falling back to \$HOME/.cache" >&2
|
|
216
|
+
fi
|
|
217
|
+
candidate="${HOME}/.cache/gaia-sandbox"
|
|
218
|
+
mkdir -p "${candidate}"
|
|
219
|
+
if is_noexec_mount "${candidate}"; then
|
|
220
|
+
echo "FATAL: no exec-capable directory available for sandbox." >&2
|
|
221
|
+
echo " Tried: \$TMPDIR, /tmp, ${candidate} -- all noexec." >&2
|
|
222
|
+
echo " Set TMPDIR to an exec-capable path and retry." >&2
|
|
223
|
+
return 1
|
|
224
|
+
fi
|
|
225
|
+
echo "${candidate}"
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if [[ "${TARGET}" == "sandbox" ]]; then
|
|
229
|
+
if ! SANDBOX_PREFIX="$(select_sandbox_prefix)"; then
|
|
230
|
+
exit 1
|
|
231
|
+
fi
|
|
232
|
+
WORKSPACE="${SANDBOX_PREFIX}/gaia-sandbox-$(date +%s)-$$"
|
|
233
|
+
echo "[sandbox] prefix: ${SANDBOX_PREFIX}"
|
|
234
|
+
mkdir -p "${WORKSPACE}"
|
|
235
|
+
else
|
|
236
|
+
if [[ -n "${WORKSPACE_OVERRIDE}" ]]; then
|
|
237
|
+
# Explicit override from --workspace flag. Resolve relative paths
|
|
238
|
+
# against cwd, then verify directory exists.
|
|
239
|
+
if [[ "${WORKSPACE_OVERRIDE}" != /* ]]; then
|
|
240
|
+
WORKSPACE_OVERRIDE="$(cd "$(dirname "${WORKSPACE_OVERRIDE}")" 2>/dev/null && pwd)/$(basename "${WORKSPACE_OVERRIDE}")"
|
|
241
|
+
fi
|
|
242
|
+
if [[ ! -d "${WORKSPACE_OVERRIDE}" ]]; then
|
|
243
|
+
echo "FATAL: --workspace path does not exist: ${WORKSPACE_OVERRIDE}" >&2
|
|
244
|
+
exit 1
|
|
245
|
+
fi
|
|
246
|
+
WORKSPACE="${WORKSPACE_OVERRIDE}"
|
|
247
|
+
echo "[local] target workspace (override): ${WORKSPACE}"
|
|
248
|
+
elif ! WORKSPACE="$(detect_local_workspace)"; then
|
|
249
|
+
echo "FATAL: --target local could not locate a workspace." >&2
|
|
250
|
+
echo " Walked up from cwd looking for a .claude/ with a Gaia marker" >&2
|
|
251
|
+
echo " (hooks/, agents/, or node_modules/@jaguilar87/gaia/)," >&2
|
|
252
|
+
echo " fallback \$HOME/ws/me/.claude/ also absent." >&2
|
|
253
|
+
echo " Pass --workspace <path> to override." >&2
|
|
254
|
+
exit 1
|
|
255
|
+
else
|
|
256
|
+
echo "[local] target workspace: ${WORKSPACE}"
|
|
257
|
+
fi
|
|
258
|
+
fi
|
|
259
|
+
|
|
260
|
+
# ---------------------------------------------------------------------------
|
|
261
|
+
# Cleanup trap (sandbox only)
|
|
262
|
+
# ---------------------------------------------------------------------------
|
|
263
|
+
|
|
264
|
+
cleanup() {
|
|
265
|
+
local rc=$?
|
|
266
|
+
if [[ "${TARGET}" == "sandbox" ]]; then
|
|
267
|
+
if [[ "${STAY}" -eq 1 ]]; then
|
|
268
|
+
echo
|
|
269
|
+
echo "Sandbox preserved at: ${WORKSPACE}"
|
|
270
|
+
echo "Remove manually when done: rm -rf '${WORKSPACE}'"
|
|
271
|
+
else
|
|
272
|
+
rm -rf "${WORKSPACE}" 2>/dev/null || true
|
|
273
|
+
fi
|
|
274
|
+
fi
|
|
275
|
+
exit "${rc}"
|
|
276
|
+
}
|
|
277
|
+
trap cleanup EXIT
|
|
278
|
+
|
|
279
|
+
# ---------------------------------------------------------------------------
|
|
280
|
+
# Check harness
|
|
281
|
+
# ---------------------------------------------------------------------------
|
|
282
|
+
|
|
283
|
+
CHECK_NAMES=()
|
|
284
|
+
CHECK_STATUS=()
|
|
285
|
+
CHECK_DETAILS=()
|
|
286
|
+
CHECK_MS=()
|
|
287
|
+
TOTAL_START_MS=$(date +%s%3N 2>/dev/null || python3 -c 'import time; print(int(time.time()*1000))')
|
|
288
|
+
|
|
289
|
+
record() {
|
|
290
|
+
local name="$1" status="$2" detail="$3" ms="$4"
|
|
291
|
+
CHECK_NAMES+=("${name}")
|
|
292
|
+
CHECK_STATUS+=("${status}")
|
|
293
|
+
CHECK_DETAILS+=("${detail}")
|
|
294
|
+
CHECK_MS+=("${ms}")
|
|
295
|
+
printf " [%-4s] %-36s %-50s (%sms)\n" "${status}" "${name}" "${detail}" "${ms}"
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
now_ms() {
|
|
299
|
+
date +%s%3N 2>/dev/null || python3 -c 'import time; print(int(time.time()*1000))'
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
# ---------------------------------------------------------------------------
|
|
303
|
+
# Prepare sandbox (fixture copy) — sandbox target only
|
|
304
|
+
# ---------------------------------------------------------------------------
|
|
305
|
+
|
|
306
|
+
prepare_sandbox() {
|
|
307
|
+
echo "[prepare] copying fixture -> ${WORKSPACE}"
|
|
308
|
+
# Copy tree, stripping .template and .fixture suffixes.
|
|
309
|
+
(
|
|
310
|
+
cd "${FIXTURE_DIR}"
|
|
311
|
+
find . -type f | while IFS= read -r src; do
|
|
312
|
+
local dest="${WORKSPACE}/${src#./}"
|
|
313
|
+
# Strip .template / .fixture suffix
|
|
314
|
+
case "${dest}" in
|
|
315
|
+
*.template)
|
|
316
|
+
dest="${dest%.template}"
|
|
317
|
+
;;
|
|
318
|
+
*.fixture)
|
|
319
|
+
dest="${dest%.fixture}"
|
|
320
|
+
;;
|
|
321
|
+
esac
|
|
322
|
+
# Rename sandbox-settings.local.json -> settings.local.json
|
|
323
|
+
dest="${dest//sandbox-settings.local.json/settings.local.json}"
|
|
324
|
+
mkdir -p "$(dirname "${dest}")"
|
|
325
|
+
cp "${src}" "${dest}"
|
|
326
|
+
done
|
|
327
|
+
)
|
|
328
|
+
echo "[prepare] fixture copied"
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
# ---------------------------------------------------------------------------
|
|
332
|
+
# Install
|
|
333
|
+
# ---------------------------------------------------------------------------
|
|
334
|
+
|
|
335
|
+
install_package() {
|
|
336
|
+
cd "${WORKSPACE}"
|
|
337
|
+
|
|
338
|
+
if [[ "${TARGET}" == "sandbox" && ! -f package.json ]]; then
|
|
339
|
+
echo "FATAL: package.json missing after prepare" >&2
|
|
340
|
+
return 1
|
|
341
|
+
fi
|
|
342
|
+
|
|
343
|
+
# In local mode, ensure a package.json exists so npm install has an anchor.
|
|
344
|
+
if [[ "${TARGET}" == "local" && ! -f package.json ]]; then
|
|
345
|
+
echo "[install] local mode: no package.json in ${WORKSPACE}, creating minimal one"
|
|
346
|
+
npm init -y --silent >/dev/null 2>&1 || npm init -y
|
|
347
|
+
fi
|
|
348
|
+
|
|
349
|
+
if [[ -n "${TARBALL_PATH}" ]]; then
|
|
350
|
+
echo "[install] installing tarball ${TARBALL_PATH}"
|
|
351
|
+
npm install --no-audit --no-fund "${TARBALL_PATH}"
|
|
352
|
+
else
|
|
353
|
+
# Accept forms: "@rc", "5.0.0-rc1", "@5.0.0-rc1",
|
|
354
|
+
# "@jaguilar87/gaia@5.0.0-rc1"
|
|
355
|
+
local spec="${VERSION_SPEC}"
|
|
356
|
+
if [[ "${spec}" == @* && "${spec}" != @jaguilar87/* ]]; then
|
|
357
|
+
# e.g. "@rc" or "@5.0.0-rc1"
|
|
358
|
+
spec="@jaguilar87/gaia${spec}"
|
|
359
|
+
elif [[ "${spec}" != @jaguilar87/* && "${spec}" != "" ]]; then
|
|
360
|
+
# Bare "5.0.0-rc1"
|
|
361
|
+
spec="@jaguilar87/gaia@${spec}"
|
|
362
|
+
fi
|
|
363
|
+
echo "[install] installing ${spec}"
|
|
364
|
+
npm install --no-audit --no-fund "${spec}"
|
|
365
|
+
fi
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
# ---------------------------------------------------------------------------
|
|
369
|
+
# Helpers
|
|
370
|
+
# ---------------------------------------------------------------------------
|
|
371
|
+
|
|
372
|
+
sha256() {
|
|
373
|
+
if command -v sha256sum >/dev/null 2>&1; then
|
|
374
|
+
sha256sum "$1" | awk '{print $1}'
|
|
375
|
+
elif command -v shasum >/dev/null 2>&1; then
|
|
376
|
+
shasum -a 256 "$1" | awk '{print $1}'
|
|
377
|
+
else
|
|
378
|
+
python3 -c "import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],'rb').read()).hexdigest())" "$1"
|
|
379
|
+
fi
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
# ---------------------------------------------------------------------------
|
|
383
|
+
# Execute
|
|
384
|
+
# ---------------------------------------------------------------------------
|
|
385
|
+
|
|
386
|
+
if [[ "${TARGET}" == "sandbox" ]]; then
|
|
387
|
+
prepare_sandbox
|
|
388
|
+
fi
|
|
389
|
+
|
|
390
|
+
SETTINGS_FILE="${WORKSPACE}/.claude/settings.local.json"
|
|
391
|
+
PRE_CHECKSUM=""
|
|
392
|
+
if [[ "${TARGET}" == "sandbox" && -f "${SETTINGS_FILE}" ]]; then
|
|
393
|
+
PRE_CHECKSUM="$(sha256 "${SETTINGS_FILE}")"
|
|
394
|
+
fi
|
|
395
|
+
|
|
396
|
+
install_package
|
|
397
|
+
|
|
398
|
+
# Put installed bin at head of PATH so we can call `gaia` directly
|
|
399
|
+
# (runtime check: node-independent invocation, no npx indirection).
|
|
400
|
+
export PATH="${WORKSPACE}/node_modules/.bin:${PATH}"
|
|
401
|
+
|
|
402
|
+
echo
|
|
403
|
+
echo "=== Running checks ==="
|
|
404
|
+
|
|
405
|
+
cd "${WORKSPACE}"
|
|
406
|
+
|
|
407
|
+
# 1. gaia --version
|
|
408
|
+
t0="$(now_ms)"
|
|
409
|
+
if out="$(gaia --version 2>&1)"; then
|
|
410
|
+
ms=$(( $(now_ms) - t0 ))
|
|
411
|
+
if grep -qE 'gaia [0-9]+\.[0-9]+\.[0-9]+' <<<"${out}"; then
|
|
412
|
+
record "gaia --version" "PASS" "$(echo "${out}" | head -1)" "${ms}"
|
|
413
|
+
else
|
|
414
|
+
record "gaia --version" "FAIL" "unexpected output: ${out:0:60}" "${ms}"
|
|
415
|
+
fi
|
|
416
|
+
else
|
|
417
|
+
ms=$(( $(now_ms) - t0 ))
|
|
418
|
+
record "gaia --version" "FAIL" "command failed: ${out:0:60}" "${ms}"
|
|
419
|
+
fi
|
|
420
|
+
|
|
421
|
+
# 2. gaia doctor --json (parse and check status)
|
|
422
|
+
t0="$(now_ms)"
|
|
423
|
+
if out="$(gaia doctor --json 2>&1)"; then
|
|
424
|
+
rc=0
|
|
425
|
+
else
|
|
426
|
+
rc=$?
|
|
427
|
+
fi
|
|
428
|
+
ms=$(( $(now_ms) - t0 ))
|
|
429
|
+
# doctor may exit 1 on warnings; allow rc=0 or rc=1 if json is parseable
|
|
430
|
+
if python3 -c "import json,sys; d=json.loads(sys.argv[1]); c=d['checks']; p=sum(1 for r in c if r['severity']=='pass'); t=len(c); sys.exit(0 if t>=5 and p>=max(1,t-3) else 1)" "${out}" 2>/dev/null; then
|
|
431
|
+
total=$(python3 -c "import json,sys; d=json.loads(sys.argv[1]); print(len(d['checks']))" "${out}")
|
|
432
|
+
passed=$(python3 -c "import json,sys; d=json.loads(sys.argv[1]); print(sum(1 for r in d['checks'] if r['severity']=='pass'))" "${out}")
|
|
433
|
+
record "gaia doctor --json" "PASS" "${passed}/${total} checks passed" "${ms}"
|
|
434
|
+
else
|
|
435
|
+
record "gaia doctor --json" "FAIL" "parse/threshold failure (rc=${rc})" "${ms}"
|
|
436
|
+
fi
|
|
437
|
+
|
|
438
|
+
# 3. gaia status --json
|
|
439
|
+
t0="$(now_ms)"
|
|
440
|
+
if out="$(gaia status --json 2>&1)"; then
|
|
441
|
+
ms=$(( $(now_ms) - t0 ))
|
|
442
|
+
if python3 -c "import json,sys; json.loads(sys.argv[1])" "${out}" 2>/dev/null; then
|
|
443
|
+
record "gaia status --json" "PASS" "json parsed" "${ms}"
|
|
444
|
+
else
|
|
445
|
+
record "gaia status --json" "FAIL" "invalid json: ${out:0:60}" "${ms}"
|
|
446
|
+
fi
|
|
447
|
+
else
|
|
448
|
+
ms=$(( $(now_ms) - t0 ))
|
|
449
|
+
record "gaia status --json" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
|
|
450
|
+
fi
|
|
451
|
+
|
|
452
|
+
# 4. gaia context show
|
|
453
|
+
t0="$(now_ms)"
|
|
454
|
+
if out="$(gaia context show 2>&1)"; then
|
|
455
|
+
ms=$(( $(now_ms) - t0 ))
|
|
456
|
+
record "gaia context show" "PASS" "exit 0" "${ms}"
|
|
457
|
+
else
|
|
458
|
+
ms=$(( $(now_ms) - t0 ))
|
|
459
|
+
record "gaia context show" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
|
|
460
|
+
fi
|
|
461
|
+
|
|
462
|
+
# 5. gaia memory stats --json (verify FTS5 backfill triggered)
|
|
463
|
+
t0="$(now_ms)"
|
|
464
|
+
if out="$(gaia memory stats --json 2>&1)"; then
|
|
465
|
+
ms=$(( $(now_ms) - t0 ))
|
|
466
|
+
indexed=$(python3 -c "import json,sys; d=json.loads(sys.argv[1]); print(d.get('indexed',0))" "${out}" 2>/dev/null || echo 0)
|
|
467
|
+
total=$(python3 -c "import json,sys; d=json.loads(sys.argv[1]); print(d.get('total_episodes',0))" "${out}" 2>/dev/null || echo 0)
|
|
468
|
+
if [[ "${TARGET}" == "sandbox" ]]; then
|
|
469
|
+
if [[ "${indexed}" -ge 9 ]]; then
|
|
470
|
+
record "memory stats (FTS5 backfill)" "PASS" "indexed=${indexed}/${total}" "${ms}"
|
|
471
|
+
else
|
|
472
|
+
record "memory stats (FTS5 backfill)" "FAIL" "indexed=${indexed}/${total} (need >=9)" "${ms}"
|
|
473
|
+
fi
|
|
474
|
+
else
|
|
475
|
+
# Local mode: workspace memory state is real and arbitrary. Assert
|
|
476
|
+
# indexed == total (backfill kept up) rather than a hardcoded floor.
|
|
477
|
+
if [[ "${indexed}" -eq "${total}" && "${total}" -ge 0 ]]; then
|
|
478
|
+
record "memory stats (FTS5 backfill)" "PASS" "indexed=${indexed}/${total}" "${ms}"
|
|
479
|
+
else
|
|
480
|
+
record "memory stats (FTS5 backfill)" "FAIL" "indexed=${indexed}/${total} (drift)" "${ms}"
|
|
481
|
+
fi
|
|
482
|
+
fi
|
|
483
|
+
else
|
|
484
|
+
ms=$(( $(now_ms) - t0 ))
|
|
485
|
+
record "memory stats (FTS5 backfill)" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
|
|
486
|
+
fi
|
|
487
|
+
|
|
488
|
+
# 6. gaia memory search "deploy" --limit 3 --json
|
|
489
|
+
t0="$(now_ms)"
|
|
490
|
+
if out="$(gaia memory search deploy --limit 3 --json 2>&1)"; then
|
|
491
|
+
ms=$(( $(now_ms) - t0 ))
|
|
492
|
+
hits=$(python3 -c "
|
|
493
|
+
import json,sys
|
|
494
|
+
try:
|
|
495
|
+
d=json.loads(sys.argv[1])
|
|
496
|
+
if isinstance(d,list):
|
|
497
|
+
print(len(d))
|
|
498
|
+
elif isinstance(d,dict):
|
|
499
|
+
for k in ('results','hits','matches'):
|
|
500
|
+
if k in d:
|
|
501
|
+
print(len(d[k])); sys.exit(0)
|
|
502
|
+
print(0)
|
|
503
|
+
else:
|
|
504
|
+
print(0)
|
|
505
|
+
except Exception:
|
|
506
|
+
print(0)
|
|
507
|
+
" "${out}" 2>/dev/null || echo 0)
|
|
508
|
+
if [[ "${TARGET}" == "sandbox" ]]; then
|
|
509
|
+
if [[ "${hits}" -ge 1 ]]; then
|
|
510
|
+
record "memory search deploy" "PASS" "${hits} hit(s)" "${ms}"
|
|
511
|
+
else
|
|
512
|
+
record "memory search deploy" "FAIL" "0 hits (expected >=1)" "${ms}"
|
|
513
|
+
fi
|
|
514
|
+
else
|
|
515
|
+
# Local mode: "deploy" is not guaranteed to appear in the real
|
|
516
|
+
# workspace memory. Only assert the command ran successfully.
|
|
517
|
+
record "memory search deploy" "PASS" "${hits} hit(s) (local)" "${ms}"
|
|
518
|
+
fi
|
|
519
|
+
else
|
|
520
|
+
ms=$(( $(now_ms) - t0 ))
|
|
521
|
+
record "memory search deploy" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
|
|
522
|
+
fi
|
|
523
|
+
|
|
524
|
+
# 7. gaia scan (exit 0)
|
|
525
|
+
# Use `gaia context scan --dry-run` (the higher-level CLI subcommand which
|
|
526
|
+
# supports --dry-run) rather than the bare `gaia-scan` binary, which wraps
|
|
527
|
+
# gaia-scan.py and does NOT accept --dry-run. --dry-run validates freshness
|
|
528
|
+
# without running the scanners or writing project-context.json.
|
|
529
|
+
t0="$(now_ms)"
|
|
530
|
+
if out="$(gaia context scan --dry-run 2>&1)"; then
|
|
531
|
+
ms=$(( $(now_ms) - t0 ))
|
|
532
|
+
record "gaia scan" "PASS" "scanner ran (dry-run)" "${ms}"
|
|
533
|
+
else
|
|
534
|
+
ms=$(( $(now_ms) - t0 ))
|
|
535
|
+
record "gaia scan" "FAIL" "exit non-zero: ${out:0:60}" "${ms}"
|
|
536
|
+
fi
|
|
537
|
+
|
|
538
|
+
# 8. Checksum preservation: settings.local.json unchanged by postinstall
|
|
539
|
+
# Sandbox only -- local mode has no meaningful "pre" snapshot.
|
|
540
|
+
if [[ "${TARGET}" == "sandbox" ]]; then
|
|
541
|
+
if [[ -n "${PRE_CHECKSUM}" && -f "${SETTINGS_FILE}" ]]; then
|
|
542
|
+
POST_CHECKSUM="$(sha256 "${SETTINGS_FILE}")"
|
|
543
|
+
t0="$(now_ms)"
|
|
544
|
+
if python3 -c "
|
|
545
|
+
import json,sys
|
|
546
|
+
p=json.load(open(sys.argv[1]))
|
|
547
|
+
assert p.get('_sandbox_sentinel')=='DO_NOT_TOUCH_ME', 'sentinel clobbered'
|
|
548
|
+
assert p.get('env',{}).get('SANDBOX_FIXTURE_MARKER')=='preserved-across-install', 'env marker clobbered'
|
|
549
|
+
" "${SETTINGS_FILE}" 2>/dev/null; then
|
|
550
|
+
ms=$(( $(now_ms) - t0 ))
|
|
551
|
+
record "settings preservation" "PASS" "sentinel + env markers intact" "${ms}"
|
|
552
|
+
else
|
|
553
|
+
ms=$(( $(now_ms) - t0 ))
|
|
554
|
+
record "settings preservation" "FAIL" "user keys clobbered by postinstall" "${ms}"
|
|
555
|
+
fi
|
|
556
|
+
else
|
|
557
|
+
record "settings preservation" "FAIL" "settings.local.json missing pre or post" "0"
|
|
558
|
+
fi
|
|
559
|
+
else
|
|
560
|
+
record "settings preservation" "SKIP" "local mode (no pre-snapshot)" "0"
|
|
561
|
+
fi
|
|
562
|
+
|
|
563
|
+
# ---------------------------------------------------------------------------
|
|
564
|
+
# Summary
|
|
565
|
+
# ---------------------------------------------------------------------------
|
|
566
|
+
|
|
567
|
+
TOTAL_END_MS="$(now_ms)"
|
|
568
|
+
TOTAL_MS=$((TOTAL_END_MS - TOTAL_START_MS))
|
|
569
|
+
|
|
570
|
+
echo
|
|
571
|
+
echo "=== Summary ==="
|
|
572
|
+
pass_count=0
|
|
573
|
+
fail_count=0
|
|
574
|
+
skip_count=0
|
|
575
|
+
for status in "${CHECK_STATUS[@]}"; do
|
|
576
|
+
case "${status}" in
|
|
577
|
+
PASS) pass_count=$((pass_count + 1)) ;;
|
|
578
|
+
SKIP) skip_count=$((skip_count + 1)) ;;
|
|
579
|
+
*) fail_count=$((fail_count + 1)) ;;
|
|
580
|
+
esac
|
|
581
|
+
done
|
|
582
|
+
|
|
583
|
+
echo " Passed: ${pass_count}"
|
|
584
|
+
echo " Failed: ${fail_count}"
|
|
585
|
+
echo " Skipped: ${skip_count}"
|
|
586
|
+
echo " Total time: ${TOTAL_MS}ms"
|
|
587
|
+
echo
|
|
588
|
+
|
|
589
|
+
if [[ "${fail_count}" -gt 0 ]]; then
|
|
590
|
+
echo "RESULT: FAIL"
|
|
591
|
+
exit 1
|
|
592
|
+
fi
|
|
593
|
+
|
|
594
|
+
echo "RESULT: PASS"
|
|
595
|
+
|
|
596
|
+
if [[ "${TARGET}" == "local" ]]; then
|
|
597
|
+
echo
|
|
598
|
+
echo "Gaia fresh install complete in ${WORKSPACE}. Restart Claude Code to reload skills/hooks/agents."
|
|
599
|
+
fi
|
|
600
|
+
|
|
601
|
+
exit 0
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Commands
|
|
2
|
+
|
|
3
|
+
Slash commands are direct shortcuts into Gaia's orchestration layer. When you type `/gaia` or `/scan-project`, Claude Code detects the slash prefix, finds the matching `.md` file in this directory, and injects its contents as instructions to the currently active orchestrator. There is no subagent spawn — the orchestrator reads the command file and executes inline.
|
|
4
|
+
|
|
5
|
+
This makes slash commands different from agent dispatch. An agent dispatch creates a new Claude Code subprocess with its own identity, skills, and tool set. A slash command is a context injection into the orchestrator's current session. Think of it as a macro: the `.md` file says "when the user invokes this command, do the following." The orchestrator follows those instructions directly.
|
|
6
|
+
|
|
7
|
+
The practical implication is that slash commands are best suited for tasks that the orchestrator can complete by delegating to existing agents — not tasks that require a new agent identity. They are entry points, not agents.
|
|
8
|
+
|
|
9
|
+
## Cuándo se activa
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
User types /command-name [args]
|
|
13
|
+
|
|
|
14
|
+
Claude Code detects / prefix
|
|
15
|
+
|
|
|
16
|
+
Looks up commands/<command-name>.md
|
|
17
|
+
|
|
|
18
|
+
Injects the file's contents into the orchestrator's active context
|
|
19
|
+
|
|
|
20
|
+
Orchestrator reads the command instructions and executes them
|
|
21
|
+
(may dispatch agents, call tools, or respond directly)
|
|
22
|
+
|
|
|
23
|
+
Result returned to user in the current session
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
No subagent is spawned. No new identity is loaded. The orchestrator handles execution within its current session using its existing tool set and the instructions from the command file.
|
|
27
|
+
|
|
28
|
+
## Qué hay aquí
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
commands/
|
|
32
|
+
├── gaia.md # /gaia — invoke the Gaia meta-agent (gaia-system) for system work
|
|
33
|
+
└── scan-project.md # /scan-project — scan codebase, detect stack, update project-context.json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Note: a `/gaia-plan` command is referenced in some older documentation but the file does not exist here. Planning is handled conversationally through the orchestrator and the `gaia-planner` agent — not via a slash command.
|
|
37
|
+
|
|
38
|
+
## Convenciones
|
|
39
|
+
|
|
40
|
+
**File format:**
|
|
41
|
+
|
|
42
|
+
```markdown
|
|
43
|
+
---
|
|
44
|
+
name: command-name
|
|
45
|
+
description: One-line description shown in Claude Code autocomplete
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
# Command Name
|
|
49
|
+
|
|
50
|
+
[Instructions the orchestrator follows when this command is invoked]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Registration:** Each command file must also be listed in `build/gaia-ops.manifest.json` under the `commands` array. A file that exists here but is not in the manifest will not appear in Claude Code's slash command list.
|
|
54
|
+
|
|
55
|
+
**Scope:** Commands inject instructions into the orchestrator. If the task requires domain work (Terraform, code changes, cloud ops), the command's instructions should dispatch the appropriate agent — the command itself should not attempt domain execution.
|
|
56
|
+
|
|
57
|
+
**Arguments:** Slash commands can receive arguments after the command name (e.g., `/gaia-plan Add OAuth2 support`). The command's `.md` file can reference these as context, and the orchestrator receives them as part of the injected content.
|
|
58
|
+
|
|
59
|
+
## Ver también
|
|
60
|
+
|
|
61
|
+
- [`build/gaia-ops.manifest.json`](../build/gaia-ops.manifest.json) — command registration
|
|
62
|
+
- [`agents/gaia-system.md`](../agents/gaia-system.md) — the Gaia meta-agent invoked by `/gaia`
|
|
63
|
+
- [`agents/gaia-orchestrator.md`](../agents/gaia-orchestrator.md) — orchestrator that executes command instructions
|
|
64
|
+
- [`skills/gaia-planner/SKILL.md`](../skills/gaia-planner/SKILL.md) — planning workflow (used by gaia-planner agent, not a slash command)
|