@jaguilar87/gaia-ops 4.4.0 → 4.7.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 +1 -1
- package/.claude-plugin/plugin.json +12 -3
- package/ARCHITECTURE.md +9 -8
- package/CHANGELOG.md +34 -0
- package/README.md +43 -11
- package/agents/terraform-architect.md +1 -1
- package/bin/README.md +2 -2
- package/bin/gaia-doctor.js +18 -5
- package/bin/gaia-history.js +0 -1
- package/bin/gaia-metrics.js +2 -2
- package/bin/gaia-scan.py +23 -1
- package/bin/gaia-update.js +346 -54
- package/bin/pre-publish-validate.js +33 -10
- package/commands/gaia.md +37 -0
- package/config/README.md +3 -9
- package/config/context-contracts.json +47 -15
- package/config/surface-routing.json +9 -1
- package/dist/gaia-ops/.claude-plugin/plugin.json +22 -0
- package/dist/gaia-ops/agents/cloud-troubleshooter.md +73 -0
- package/dist/gaia-ops/agents/devops-developer.md +57 -0
- package/dist/gaia-ops/agents/gaia-system.md +58 -0
- package/dist/gaia-ops/agents/gitops-operator.md +60 -0
- package/dist/gaia-ops/agents/speckit-planner.md +71 -0
- package/dist/gaia-ops/agents/terraform-architect.md +60 -0
- package/dist/gaia-ops/commands/gaia.md +37 -0
- package/dist/gaia-ops/config/README.md +58 -0
- package/dist/gaia-ops/config/cloud/aws.json +140 -0
- package/dist/gaia-ops/config/cloud/gcp.json +145 -0
- package/dist/gaia-ops/config/context-contracts.json +131 -0
- package/dist/gaia-ops/config/git_standards.json +72 -0
- package/dist/gaia-ops/config/surface-routing.json +197 -0
- package/dist/gaia-ops/config/universal-rules.json +10 -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 +1477 -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 +126 -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 +124 -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 +576 -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/anchor_tracker.py +317 -0
- package/dist/gaia-ops/hooks/modules/context/compact_context_builder.py +215 -0
- package/dist/gaia-ops/hooks/modules/context/context_cache.py +129 -0
- package/dist/gaia-ops/hooks/modules/context/context_freshness.py +145 -0
- package/dist/gaia-ops/hooks/modules/context/context_injector.py +427 -0
- package/dist/gaia-ops/hooks/modules/context/context_writer.py +518 -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 +558 -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/identity/__init__.py +0 -0
- package/dist/gaia-ops/hooks/modules/identity/identity_provider.py +21 -0
- package/dist/gaia-ops/hooks/modules/identity/ops_identity.py +34 -0
- package/dist/gaia-ops/hooks/modules/identity/security_identity.py +10 -0
- package/dist/gaia-ops/hooks/modules/memory/__init__.py +8 -0
- package/dist/gaia-ops/hooks/modules/memory/episode_writer.py +227 -0
- package/dist/gaia-ops/hooks/modules/orchestrator/__init__.py +1 -0
- package/dist/gaia-ops/hooks/modules/orchestrator/delegate_mode.py +128 -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 +89 -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 +912 -0
- package/dist/gaia-ops/hooks/modules/security/approval_messages.py +71 -0
- package/dist/gaia-ops/hooks/modules/security/approval_scopes.py +153 -0
- package/dist/gaia-ops/hooks/modules/security/blocked_commands.py +584 -0
- package/dist/gaia-ops/hooks/modules/security/blocked_message_formatter.py +86 -0
- package/dist/gaia-ops/hooks/modules/security/command_semantics.py +130 -0
- package/dist/gaia-ops/hooks/modules/security/gitops_validator.py +179 -0
- package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +850 -0
- package/dist/gaia-ops/hooks/modules/security/prompt_validator.py +40 -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/session_context_writer.py +100 -0
- package/dist/gaia-ops/hooks/modules/session/session_event_injector.py +158 -0
- package/dist/gaia-ops/hooks/modules/session/session_manager.py +31 -0
- package/dist/gaia-ops/hooks/modules/tools/__init__.py +25 -0
- package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +708 -0
- package/dist/gaia-ops/hooks/modules/tools/cloud_pipe_validator.py +181 -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/task_validator.py +283 -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_tool_use.py +383 -0
- package/dist/gaia-ops/hooks/session_start.py +69 -0
- package/dist/gaia-ops/hooks/stop_hook.py +69 -0
- package/dist/gaia-ops/hooks/subagent_start.py +71 -0
- package/dist/gaia-ops/hooks/subagent_stop.py +288 -0
- package/dist/gaia-ops/hooks/task_completed.py +70 -0
- package/dist/gaia-ops/hooks/user_prompt_submit.py +177 -0
- package/dist/gaia-ops/settings.json +72 -0
- package/dist/gaia-ops/skills/README.md +109 -0
- package/dist/gaia-ops/skills/agent-protocol/SKILL.md +105 -0
- package/dist/gaia-ops/skills/agent-protocol/examples.md +170 -0
- package/dist/gaia-ops/skills/agent-response/SKILL.md +53 -0
- package/dist/gaia-ops/skills/approval/SKILL.md +85 -0
- package/dist/gaia-ops/skills/approval/examples.md +140 -0
- package/dist/gaia-ops/skills/approval/reference.md +57 -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 +76 -0
- package/dist/gaia-ops/skills/context-updater/examples.md +71 -0
- package/dist/gaia-ops/skills/developer-patterns/SKILL.md +93 -0
- package/dist/gaia-ops/skills/developer-patterns/reference.md +112 -0
- package/dist/gaia-ops/skills/execution/SKILL.md +66 -0
- package/dist/gaia-ops/skills/fast-queries/SKILL.md +47 -0
- package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +92 -0
- package/dist/gaia-ops/skills/gaia-patterns/reference.md +22 -0
- package/dist/gaia-ops/skills/git-conventions/SKILL.md +48 -0
- package/dist/gaia-ops/skills/gitops-patterns/SKILL.md +73 -0
- package/dist/gaia-ops/skills/gitops-patterns/reference.md +183 -0
- package/dist/gaia-ops/skills/investigation/SKILL.md +77 -0
- package/dist/gaia-ops/skills/orchestrator-approval/SKILL.md +64 -0
- package/dist/gaia-ops/skills/reference.md +134 -0
- package/dist/gaia-ops/skills/security-tiers/SKILL.md +61 -0
- package/dist/gaia-ops/skills/security-tiers/destructive-commands-reference.md +623 -0
- package/dist/gaia-ops/skills/security-tiers/reference.md +39 -0
- package/dist/gaia-ops/skills/skill-creation/SKILL.md +119 -0
- package/dist/gaia-ops/skills/specification/SKILL.md +186 -0
- package/dist/gaia-ops/skills/speckit-workflow/SKILL.md +165 -0
- package/dist/gaia-ops/skills/speckit-workflow/reference.md +117 -0
- package/dist/gaia-ops/skills/terraform-patterns/SKILL.md +63 -0
- package/dist/gaia-ops/skills/terraform-patterns/reference.md +93 -0
- package/dist/gaia-ops/speckit/README.md +516 -0
- package/dist/gaia-ops/speckit/scripts/.gitkeep +0 -0
- package/dist/gaia-ops/speckit/templates/adr-template.md +118 -0
- package/dist/gaia-ops/speckit/templates/agent-file-template.md +23 -0
- package/dist/gaia-ops/speckit/templates/plan-template.md +227 -0
- package/dist/gaia-ops/speckit/templates/spec-template.md +140 -0
- package/dist/gaia-ops/speckit/templates/tasks-template.md +257 -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 +476 -0
- package/dist/gaia-ops/tools/context/context_section_reader.py +330 -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 +262 -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/episodic.py +1196 -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 +324 -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 +753 -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 +266 -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 +22 -0
- package/dist/gaia-security/config/universal-rules.json +10 -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 +1477 -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 +57 -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 +124 -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 +576 -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/anchor_tracker.py +317 -0
- package/dist/gaia-security/hooks/modules/context/compact_context_builder.py +215 -0
- package/dist/gaia-security/hooks/modules/context/context_cache.py +129 -0
- package/dist/gaia-security/hooks/modules/context/context_freshness.py +145 -0
- package/dist/gaia-security/hooks/modules/context/context_injector.py +427 -0
- package/dist/gaia-security/hooks/modules/context/context_writer.py +518 -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 +558 -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/identity/__init__.py +0 -0
- package/dist/gaia-security/hooks/modules/identity/identity_provider.py +21 -0
- package/dist/gaia-security/hooks/modules/identity/ops_identity.py +34 -0
- package/dist/gaia-security/hooks/modules/identity/security_identity.py +10 -0
- package/dist/gaia-security/hooks/modules/memory/__init__.py +8 -0
- package/dist/gaia-security/hooks/modules/memory/episode_writer.py +227 -0
- package/dist/gaia-security/hooks/modules/orchestrator/__init__.py +1 -0
- package/dist/gaia-security/hooks/modules/orchestrator/delegate_mode.py +128 -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 +89 -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 +912 -0
- package/dist/gaia-security/hooks/modules/security/approval_messages.py +71 -0
- package/dist/gaia-security/hooks/modules/security/approval_scopes.py +153 -0
- package/dist/gaia-security/hooks/modules/security/blocked_commands.py +584 -0
- package/dist/gaia-security/hooks/modules/security/blocked_message_formatter.py +86 -0
- package/dist/gaia-security/hooks/modules/security/command_semantics.py +130 -0
- package/dist/gaia-security/hooks/modules/security/gitops_validator.py +179 -0
- package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +850 -0
- package/dist/gaia-security/hooks/modules/security/prompt_validator.py +40 -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/session_context_writer.py +100 -0
- package/dist/gaia-security/hooks/modules/session/session_event_injector.py +158 -0
- package/dist/gaia-security/hooks/modules/session/session_manager.py +31 -0
- package/dist/gaia-security/hooks/modules/tools/__init__.py +25 -0
- package/dist/gaia-security/hooks/modules/tools/bash_validator.py +708 -0
- package/dist/gaia-security/hooks/modules/tools/cloud_pipe_validator.py +181 -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/task_validator.py +283 -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 +383 -0
- package/dist/gaia-security/hooks/session_start.py +69 -0
- package/dist/gaia-security/hooks/stop_hook.py +69 -0
- package/dist/gaia-security/hooks/user_prompt_submit.py +177 -0
- package/dist/gaia-security/settings.json +58 -0
- package/git-hooks/commit-msg +41 -0
- package/hooks/README.md +8 -6
- package/hooks/adapters/channel.py +0 -25
- package/hooks/adapters/claude_code.py +364 -125
- package/hooks/elicitation_result.py +132 -0
- package/hooks/hooks.json +10 -1
- package/hooks/modules/README.md +3 -2
- package/hooks/modules/agents/contract_validator.py +3 -51
- package/hooks/modules/agents/response_contract.py +4 -8
- package/hooks/modules/agents/transcript_reader.py +4 -5
- package/hooks/modules/audit/__init__.py +4 -6
- package/hooks/modules/audit/event_detector.py +0 -2
- package/hooks/modules/audit/metrics.py +108 -187
- package/hooks/modules/audit/workflow_auditor.py +0 -4
- package/hooks/modules/audit/workflow_recorder.py +0 -5
- package/hooks/modules/context/compact_context_builder.py +1 -0
- package/hooks/modules/context/context_cache.py +129 -0
- package/hooks/modules/context/context_injector.py +18 -40
- package/hooks/modules/context/context_writer.py +1 -25
- package/hooks/modules/context/contracts_loader.py +7 -10
- package/hooks/modules/core/hook_entry.py +1 -0
- package/hooks/modules/core/paths.py +12 -13
- package/hooks/modules/core/plugin_mode.py +74 -4
- package/hooks/modules/core/plugin_setup.py +395 -23
- package/hooks/modules/events/__init__.py +1 -0
- package/hooks/modules/events/event_writer.py +210 -0
- package/hooks/modules/identity/ops_identity.py +18 -27
- package/hooks/modules/memory/episode_writer.py +1 -6
- package/hooks/modules/orchestrator/__init__.py +1 -0
- package/hooks/modules/orchestrator/delegate_mode.py +128 -0
- package/hooks/modules/security/__init__.py +2 -4
- package/hooks/modules/security/approval_constants.py +5 -1
- package/hooks/modules/security/approval_grants.py +189 -6
- package/hooks/modules/security/approval_messages.py +9 -21
- package/hooks/modules/security/blocked_commands.py +98 -34
- package/hooks/modules/security/command_semantics.py +0 -4
- package/hooks/modules/security/gitops_validator.py +1 -11
- package/hooks/modules/security/mutative_verbs.py +179 -38
- package/hooks/modules/security/tiers.py +1 -19
- package/hooks/modules/session/session_event_injector.py +1 -25
- package/hooks/modules/tools/bash_validator.py +310 -94
- package/hooks/modules/tools/shell_parser.py +0 -1
- package/hooks/modules/tools/task_validator.py +9 -29
- package/hooks/post_tool_use.py +0 -72
- package/hooks/pre_tool_use.py +42 -102
- package/hooks/session_start.py +4 -2
- package/hooks/subagent_start.py +6 -2
- package/hooks/subagent_stop.py +1 -13
- package/hooks/user_prompt_submit.py +119 -37
- package/index.js +1 -1
- package/package.json +5 -3
- package/skills/README.md +3 -5
- package/skills/agent-protocol/SKILL.md +17 -16
- package/skills/agent-protocol/examples.md +6 -6
- package/skills/agent-response/SKILL.md +11 -14
- package/skills/approval/SKILL.md +28 -13
- package/skills/approval/reference.md +2 -2
- package/skills/execution/SKILL.md +1 -1
- package/skills/gaia-patterns/SKILL.md +2 -3
- package/skills/orchestrator-approval/SKILL.md +22 -50
- package/skills/security-tiers/SKILL.md +1 -1
- package/templates/README.md +9 -9
- package/templates/managed-settings.template.json +43 -0
- package/tools/gaia_simulator/runner.py +34 -1
- package/tools/scan/orchestrator.py +13 -0
- package/tools/scan/scanners/base.py +8 -0
- package/tools/scan/scanners/git.py +78 -0
- package/tools/scan/scanners/infrastructure.py +65 -0
- package/tools/scan/scanners/stack.py +110 -0
- package/tools/scan/setup.py +120 -13
- package/tools/scan/workspace.py +85 -0
- package/config/context-contracts.aws.json +0 -42
- package/config/context-contracts.gcp.json +0 -39
- package/skills/project-dispatch/SKILL.md +0 -34
- package/templates/settings.template.json +0 -226
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# QuickTriage for Terraform - Optimized version
|
|
3
|
+
# Only shows validation results, not full output
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
TARGET_DIR="${1:-.}"
|
|
8
|
+
USE_TERRAGRUNT="${USE_TERRAGRUNT:-false}"
|
|
9
|
+
|
|
10
|
+
# Detect if should use terragrunt based on files present
|
|
11
|
+
if [ "$USE_TERRAGRUNT" != "true" ] && [ -f "$TARGET_DIR/terragrunt.hcl" ]; then
|
|
12
|
+
USE_TERRAGRUNT="true"
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
TOOL="terraform"
|
|
16
|
+
if [ "$USE_TERRAGRUNT" == "true" ]; then
|
|
17
|
+
TOOL="terragrunt"
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
echo "=== TERRAFORM CHECK: $TARGET_DIR ($TOOL) ==="
|
|
21
|
+
|
|
22
|
+
# Check if tool exists
|
|
23
|
+
if ! command -v "$TOOL" >/dev/null 2>&1; then
|
|
24
|
+
echo "❌ $TOOL not installed"
|
|
25
|
+
exit 2
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
cd "$TARGET_DIR" || exit 2
|
|
29
|
+
|
|
30
|
+
# 1. Format check (only show result, not diff)
|
|
31
|
+
if $TOOL fmt -check -diff=false > /dev/null 2>&1; then
|
|
32
|
+
echo "✅ Format OK"
|
|
33
|
+
else
|
|
34
|
+
echo "❌ Format issues (run: $TOOL fmt)"
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# 2. Init if needed (silent)
|
|
38
|
+
if [ ! -d ".terraform" ] && [ "$TOOL" == "terraform" ]; then
|
|
39
|
+
terraform init -backend=false -upgrade=false > /dev/null 2>&1 || true
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# 3. Validation (only show if fails)
|
|
43
|
+
VALIDATION_OUTPUT=$($TOOL validate 2>&1 || true)
|
|
44
|
+
if echo "$VALIDATION_OUTPUT" | grep -q "Success\|configuration is valid"; then
|
|
45
|
+
echo "✅ Valid configuration"
|
|
46
|
+
elif [ -z "$VALIDATION_OUTPUT" ]; then
|
|
47
|
+
echo "✅ Valid configuration"
|
|
48
|
+
else
|
|
49
|
+
echo "❌ Validation failed:"
|
|
50
|
+
echo "$VALIDATION_OUTPUT" | grep -E "Error:|Warning:" | head -3 | sed 's/^/ /'
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# 4. Plan summary (only count changes, don't show full plan)
|
|
54
|
+
if [ "$USE_TERRAGRUNT" == "true" ]; then
|
|
55
|
+
# Terragrunt doesn't support -detailed-exitcode well, just check for drift
|
|
56
|
+
PLAN_OUTPUT=$(terragrunt plan -lock=false 2>&1 | tail -20 || true)
|
|
57
|
+
else
|
|
58
|
+
# Terraform with detailed exit code
|
|
59
|
+
set +e
|
|
60
|
+
terraform plan -lock=false -refresh=false -detailed-exitcode -out=/dev/null > /tmp/tf-plan-$$.txt 2>&1
|
|
61
|
+
PLAN_EXIT=$?
|
|
62
|
+
set -e
|
|
63
|
+
|
|
64
|
+
if [ $PLAN_EXIT -eq 0 ]; then
|
|
65
|
+
echo "✅ No changes needed"
|
|
66
|
+
elif [ $PLAN_EXIT -eq 2 ]; then
|
|
67
|
+
# Changes detected, count them
|
|
68
|
+
PLAN_OUTPUT=$(cat /tmp/tf-plan-$$.txt)
|
|
69
|
+
ADD=$(echo "$PLAN_OUTPUT" | grep -c "will be created" || echo "0")
|
|
70
|
+
UPDATE=$(echo "$PLAN_OUTPUT" | grep -c "will be updated\|will be modified" || echo "0")
|
|
71
|
+
DELETE=$(echo "$PLAN_OUTPUT" | grep -c "will be destroyed" || echo "0")
|
|
72
|
+
echo "⚠️ Changes detected: +$ADD ~$UPDATE -$DELETE"
|
|
73
|
+
else
|
|
74
|
+
echo "❌ Plan failed"
|
|
75
|
+
fi
|
|
76
|
+
rm -f /tmp/tf-plan-$$.txt
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Exit code: 0 if all OK, 1 if issues found
|
|
80
|
+
[ -n "$(echo "$VALIDATION_OUTPUT" | grep -E "Error:")" ] && exit 1 || exit 0
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Gaia simulator module for gaia-ops hooks.
|
|
3
|
+
|
|
4
|
+
Extracts real hook events from production logs, replays them against the current
|
|
5
|
+
hooks, and detects regressions. Also provides routing simulation and skills mapping.
|
|
6
|
+
|
|
7
|
+
Modules:
|
|
8
|
+
extractor - Log parser: ReplayEvent + LogExtractor
|
|
9
|
+
runner - Hook executor: ReplayResult + HookRunner
|
|
10
|
+
reporter - Results formatter: ReplayReporter
|
|
11
|
+
routing_simulator - Surface routing simulation: RoutingSimulator
|
|
12
|
+
skills_mapper - Agent/skill/surface mapping: SkillsMapper
|
|
13
|
+
cli - Command-line entry point
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from gaia_simulator.extractor import LogExtractor, ReplayEvent
|
|
17
|
+
from gaia_simulator.runner import HookRunner, ReplayResult
|
|
18
|
+
from gaia_simulator.reporter import ReplayReporter
|
|
19
|
+
from gaia_simulator.routing_simulator import RoutingSimulator, RoutingResult
|
|
20
|
+
from gaia_simulator.skills_mapper import SkillsMapper, SkillMapping, AgentProfile
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"LogExtractor",
|
|
24
|
+
"ReplayEvent",
|
|
25
|
+
"HookRunner",
|
|
26
|
+
"ReplayResult",
|
|
27
|
+
"ReplayReporter",
|
|
28
|
+
"RoutingSimulator",
|
|
29
|
+
"RoutingResult",
|
|
30
|
+
"SkillsMapper",
|
|
31
|
+
"SkillMapping",
|
|
32
|
+
"AgentProfile",
|
|
33
|
+
]
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
CLI entry point for gaia-ops hook replay testing and routing analysis.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python3 tools/gaia_simulator/cli.py # replay all logs
|
|
7
|
+
python3 tools/gaia_simulator/cli.py --logs-dir /path/to/logs # custom log dir
|
|
8
|
+
python3 tools/gaia_simulator/cli.py --date 2026-03-11 # specific date
|
|
9
|
+
python3 tools/gaia_simulator/cli.py --hook pre_tool_use # specific hook only
|
|
10
|
+
python3 tools/gaia_simulator/cli.py --regressions-only # show only failures
|
|
11
|
+
python3 tools/gaia_simulator/cli.py --output results.json # save results
|
|
12
|
+
python3 tools/gaia_simulator/cli.py --extract-only # extract without running
|
|
13
|
+
python3 tools/gaia_simulator/cli.py --simulate "prompt" # simulate routing
|
|
14
|
+
python3 tools/gaia_simulator/cli.py --simulate-logs --date D # simulate from logs
|
|
15
|
+
python3 tools/gaia_simulator/cli.py --skills-map # show skills map
|
|
16
|
+
python3 tools/gaia_simulator/cli.py --agent-profiles # show agent profiles
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import argparse
|
|
22
|
+
import json
|
|
23
|
+
import sys
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
_TOOLS_DIR = Path(__file__).resolve().parent.parent
|
|
27
|
+
if str(_TOOLS_DIR) not in sys.path:
|
|
28
|
+
sys.path.insert(0, str(_TOOLS_DIR))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _find_defaults() -> tuple[Path, Path, Path]:
|
|
32
|
+
"""Find default paths relative to the plugin root.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
(hooks_dir, logs_dir, plugin_root) tuple.
|
|
36
|
+
"""
|
|
37
|
+
# tools/gaia_simulator/cli.py -> tools/gaia_simulator -> tools -> plugin_root
|
|
38
|
+
cli_path = Path(__file__).resolve()
|
|
39
|
+
plugin_root = cli_path.parent.parent.parent
|
|
40
|
+
hooks_dir = plugin_root / "hooks"
|
|
41
|
+
# Default logs location: two levels up from plugin root in .claude/logs
|
|
42
|
+
logs_dir = plugin_root.parent / ".claude" / "logs"
|
|
43
|
+
return hooks_dir, logs_dir, plugin_root
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _handle_simulate(prompt: str, plugin_root: Path) -> int:
|
|
47
|
+
"""Handle --simulate command: simulate routing for a prompt."""
|
|
48
|
+
from gaia_simulator.routing_simulator import RoutingSimulator, format_routing_result
|
|
49
|
+
|
|
50
|
+
config_dir = plugin_root / "config"
|
|
51
|
+
agents_dir = plugin_root / "agents"
|
|
52
|
+
simulator = RoutingSimulator(config_dir=config_dir, agents_dir=agents_dir)
|
|
53
|
+
result = simulator.simulate(prompt)
|
|
54
|
+
print(format_routing_result(result))
|
|
55
|
+
return 0
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _handle_simulate_logs(logs_dir: Path, date_filter: str, plugin_root: Path) -> int:
|
|
59
|
+
"""Handle --simulate-logs command: simulate routing for log events."""
|
|
60
|
+
from gaia_simulator.extractor import LogExtractor
|
|
61
|
+
from gaia_simulator.routing_simulator import RoutingSimulator, format_routing_result
|
|
62
|
+
|
|
63
|
+
config_dir = plugin_root / "config"
|
|
64
|
+
agents_dir = plugin_root / "agents"
|
|
65
|
+
|
|
66
|
+
extractor = LogExtractor()
|
|
67
|
+
events = extractor.extract_all(logs_dir, date_filter=date_filter)
|
|
68
|
+
|
|
69
|
+
if not events:
|
|
70
|
+
print("No events found matching the criteria.")
|
|
71
|
+
return 0
|
|
72
|
+
|
|
73
|
+
simulator = RoutingSimulator(config_dir=config_dir, agents_dir=agents_dir)
|
|
74
|
+
|
|
75
|
+
# Convert ReplayEvents to dicts for simulate_from_log
|
|
76
|
+
event_dicts = []
|
|
77
|
+
for ev in events:
|
|
78
|
+
tool_input = ev.stdin_payload.get("tool_input", {})
|
|
79
|
+
prompt = ""
|
|
80
|
+
if isinstance(tool_input, dict):
|
|
81
|
+
prompt = tool_input.get("command", tool_input.get("description", ""))
|
|
82
|
+
agent = ""
|
|
83
|
+
if ev.tool_name == "Agent" and isinstance(tool_input, dict):
|
|
84
|
+
agent = tool_input.get("subagent_type", "")
|
|
85
|
+
if prompt:
|
|
86
|
+
event_dicts.append({"prompt": prompt, "agent": agent})
|
|
87
|
+
|
|
88
|
+
results = simulator.simulate_from_log(event_dicts)
|
|
89
|
+
for result in results:
|
|
90
|
+
print(format_routing_result(result))
|
|
91
|
+
print()
|
|
92
|
+
|
|
93
|
+
print("Total events simulated: " + str(len(results)))
|
|
94
|
+
return 0
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _handle_skills_map(plugin_root: Path) -> int:
|
|
98
|
+
"""Handle --skills-map command: show skills mapping report."""
|
|
99
|
+
from gaia_simulator.skills_mapper import SkillsMapper
|
|
100
|
+
|
|
101
|
+
mapper = SkillsMapper(
|
|
102
|
+
agents_dir=plugin_root / "agents",
|
|
103
|
+
skills_dir=plugin_root / "skills",
|
|
104
|
+
config_dir=plugin_root / "config",
|
|
105
|
+
)
|
|
106
|
+
print(mapper.format_report())
|
|
107
|
+
return 0
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _handle_agent_profiles(plugin_root: Path) -> int:
|
|
111
|
+
"""Handle --agent-profiles command: show agent profiles."""
|
|
112
|
+
from gaia_simulator.skills_mapper import SkillsMapper
|
|
113
|
+
|
|
114
|
+
mapper = SkillsMapper(
|
|
115
|
+
agents_dir=plugin_root / "agents",
|
|
116
|
+
skills_dir=plugin_root / "skills",
|
|
117
|
+
config_dir=plugin_root / "config",
|
|
118
|
+
)
|
|
119
|
+
profiles = mapper.get_agent_profiles()
|
|
120
|
+
|
|
121
|
+
lines = []
|
|
122
|
+
lines.append("=" * 60)
|
|
123
|
+
lines.append("AGENT PROFILES")
|
|
124
|
+
lines.append("=" * 60)
|
|
125
|
+
|
|
126
|
+
for profile in profiles:
|
|
127
|
+
lines.append("")
|
|
128
|
+
lines.append(profile.agent_name + ":")
|
|
129
|
+
lines.append(" Skills: " + (", ".join(profile.skills) or "(none)"))
|
|
130
|
+
lines.append(" Surfaces: " + (", ".join(profile.surfaces) or "(none)"))
|
|
131
|
+
lines.append(" Read: " + (", ".join(profile.read_sections) or "(none)"))
|
|
132
|
+
lines.append(" Write: " + (", ".join(profile.write_sections) or "(none)"))
|
|
133
|
+
lines.append(" Invocations: " + str(profile.invocation_count))
|
|
134
|
+
|
|
135
|
+
lines.append("")
|
|
136
|
+
lines.append("=" * 60)
|
|
137
|
+
|
|
138
|
+
nl = chr(10)
|
|
139
|
+
print(nl.join(lines))
|
|
140
|
+
return 0
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def main(argv: list[str] | None = None) -> int:
|
|
144
|
+
"""Main entry point for the gaia simulator CLI.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
argv: Command-line arguments (defaults to sys.argv[1:]).
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Exit code: 0 if all matched, 1 if regressions found, 2 on error.
|
|
151
|
+
"""
|
|
152
|
+
hooks_dir_default, logs_dir_default, plugin_root = _find_defaults()
|
|
153
|
+
|
|
154
|
+
parser = argparse.ArgumentParser(
|
|
155
|
+
description="Replay gaia-ops hook events from production logs to detect regressions.",
|
|
156
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
157
|
+
)
|
|
158
|
+
parser.add_argument(
|
|
159
|
+
"--logs-dir",
|
|
160
|
+
type=Path,
|
|
161
|
+
default=logs_dir_default,
|
|
162
|
+
help="Directory containing log files (default: " + str(logs_dir_default) + ")",
|
|
163
|
+
)
|
|
164
|
+
parser.add_argument(
|
|
165
|
+
"--hooks-dir",
|
|
166
|
+
type=Path,
|
|
167
|
+
default=hooks_dir_default,
|
|
168
|
+
help="Directory containing hook scripts (default: " + str(hooks_dir_default) + ")",
|
|
169
|
+
)
|
|
170
|
+
parser.add_argument(
|
|
171
|
+
"--date",
|
|
172
|
+
type=str,
|
|
173
|
+
default=None,
|
|
174
|
+
help="Filter by date (YYYY-MM-DD format)",
|
|
175
|
+
)
|
|
176
|
+
parser.add_argument(
|
|
177
|
+
"--hook",
|
|
178
|
+
type=str,
|
|
179
|
+
default=None,
|
|
180
|
+
help="Filter by hook name (e.g. pre_tool_use)",
|
|
181
|
+
)
|
|
182
|
+
parser.add_argument(
|
|
183
|
+
"--regressions-only",
|
|
184
|
+
action="store_true",
|
|
185
|
+
help="Show only regression details",
|
|
186
|
+
)
|
|
187
|
+
parser.add_argument(
|
|
188
|
+
"--full",
|
|
189
|
+
action="store_true",
|
|
190
|
+
help="Show full report with breakdowns",
|
|
191
|
+
)
|
|
192
|
+
parser.add_argument(
|
|
193
|
+
"--output",
|
|
194
|
+
type=Path,
|
|
195
|
+
default=None,
|
|
196
|
+
help="Save results to JSON file",
|
|
197
|
+
)
|
|
198
|
+
parser.add_argument(
|
|
199
|
+
"--extract-only",
|
|
200
|
+
action="store_true",
|
|
201
|
+
help="Extract events from logs without running hooks",
|
|
202
|
+
)
|
|
203
|
+
parser.add_argument(
|
|
204
|
+
"--limit",
|
|
205
|
+
type=int,
|
|
206
|
+
default=0,
|
|
207
|
+
help="Limit number of events to replay (0 = all)",
|
|
208
|
+
)
|
|
209
|
+
parser.add_argument(
|
|
210
|
+
"--report-format",
|
|
211
|
+
choices=("text", "json"),
|
|
212
|
+
default="text",
|
|
213
|
+
help="Emit text for humans or JSON for machines",
|
|
214
|
+
)
|
|
215
|
+
# New routing/skills commands
|
|
216
|
+
parser.add_argument(
|
|
217
|
+
"--simulate",
|
|
218
|
+
type=str,
|
|
219
|
+
default=None,
|
|
220
|
+
metavar="PROMPT",
|
|
221
|
+
help="Simulate surface routing for a prompt",
|
|
222
|
+
)
|
|
223
|
+
parser.add_argument(
|
|
224
|
+
"--simulate-logs",
|
|
225
|
+
action="store_true",
|
|
226
|
+
help="Simulate routing for events extracted from logs",
|
|
227
|
+
)
|
|
228
|
+
parser.add_argument(
|
|
229
|
+
"--skills-map",
|
|
230
|
+
action="store_true",
|
|
231
|
+
help="Show agent/skill/surface mapping report",
|
|
232
|
+
)
|
|
233
|
+
parser.add_argument(
|
|
234
|
+
"--agent-profiles",
|
|
235
|
+
action="store_true",
|
|
236
|
+
help="Show detailed agent profiles",
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
args = parser.parse_args(argv)
|
|
240
|
+
|
|
241
|
+
# Handle routing/skills commands first (they don't need logs/hooks validation)
|
|
242
|
+
if args.simulate is not None:
|
|
243
|
+
return _handle_simulate(args.simulate, plugin_root)
|
|
244
|
+
|
|
245
|
+
if args.simulate_logs:
|
|
246
|
+
if not args.logs_dir.is_dir():
|
|
247
|
+
print("Error: Logs directory not found: " + str(args.logs_dir), file=sys.stderr)
|
|
248
|
+
return 2
|
|
249
|
+
return _handle_simulate_logs(args.logs_dir, args.date, plugin_root)
|
|
250
|
+
|
|
251
|
+
if args.skills_map:
|
|
252
|
+
return _handle_skills_map(plugin_root)
|
|
253
|
+
|
|
254
|
+
if args.agent_profiles:
|
|
255
|
+
return _handle_agent_profiles(plugin_root)
|
|
256
|
+
|
|
257
|
+
def status(message: str = "") -> None:
|
|
258
|
+
target = sys.stderr if args.report_format == "json" else sys.stdout
|
|
259
|
+
print(message, file=target)
|
|
260
|
+
|
|
261
|
+
# Validate paths
|
|
262
|
+
if not args.logs_dir.is_dir():
|
|
263
|
+
print("Error: Logs directory not found: " + str(args.logs_dir), file=sys.stderr)
|
|
264
|
+
return 2
|
|
265
|
+
|
|
266
|
+
if not args.extract_only and not args.hooks_dir.is_dir():
|
|
267
|
+
print("Error: Hooks directory not found: " + str(args.hooks_dir), file=sys.stderr)
|
|
268
|
+
return 2
|
|
269
|
+
|
|
270
|
+
# Lazy module loading to keep CLI fast for --help
|
|
271
|
+
from gaia_simulator.extractor import LogExtractor
|
|
272
|
+
from gaia_simulator.runner import HookRunner
|
|
273
|
+
from gaia_simulator.reporter import ReplayReporter
|
|
274
|
+
|
|
275
|
+
# Step 1: Extract events
|
|
276
|
+
extractor = LogExtractor()
|
|
277
|
+
reporter = ReplayReporter()
|
|
278
|
+
|
|
279
|
+
status("Extracting events from: " + str(args.logs_dir))
|
|
280
|
+
if args.date:
|
|
281
|
+
status("Date filter: " + args.date)
|
|
282
|
+
if args.hook:
|
|
283
|
+
status("Hook filter: " + args.hook)
|
|
284
|
+
|
|
285
|
+
events = extractor.extract_all(
|
|
286
|
+
args.logs_dir,
|
|
287
|
+
date_filter=args.date,
|
|
288
|
+
hook_filter=args.hook,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
if args.limit > 0:
|
|
292
|
+
events = events[: args.limit]
|
|
293
|
+
|
|
294
|
+
status("Extracted " + str(len(events)) + " events")
|
|
295
|
+
|
|
296
|
+
if not events:
|
|
297
|
+
if args.report_format == "json":
|
|
298
|
+
print("[]")
|
|
299
|
+
else:
|
|
300
|
+
status("No events found matching the criteria.")
|
|
301
|
+
return 0
|
|
302
|
+
|
|
303
|
+
# Extract-only mode
|
|
304
|
+
if args.extract_only:
|
|
305
|
+
if args.report_format == "json":
|
|
306
|
+
print(json.dumps(reporter.events_payload(events), indent=2, default=str))
|
|
307
|
+
else:
|
|
308
|
+
nl = chr(10)
|
|
309
|
+
print(nl + "--- Extracted Events ---")
|
|
310
|
+
for i, ev in enumerate(events, 1):
|
|
311
|
+
tool_input = ev.stdin_payload.get("tool_input", {})
|
|
312
|
+
if ev.tool_name == "Bash":
|
|
313
|
+
detail = tool_input.get("command", "")[:80]
|
|
314
|
+
elif ev.tool_name == "Agent":
|
|
315
|
+
detail = tool_input.get("subagent_type", tool_input.get("description", ""))[:80]
|
|
316
|
+
else:
|
|
317
|
+
detail = str(tool_input)[:80]
|
|
318
|
+
print(" [" + str(i) + "] " + ev.timestamp + " " + ev.hook_name + " " + ev.tool_name +
|
|
319
|
+
" -> " + ev.expected_decision + " (" + ev.expected_tier + ") | " + detail)
|
|
320
|
+
return 0
|
|
321
|
+
|
|
322
|
+
# Step 2: Run hooks
|
|
323
|
+
def progress(current: int, total: int) -> None:
|
|
324
|
+
if total > 10 and current % 10 == 0:
|
|
325
|
+
print(" Replayed " + str(current) + "/" + str(total) + " events...", file=sys.stderr)
|
|
326
|
+
|
|
327
|
+
nl = chr(10)
|
|
328
|
+
status(nl + "Replaying against hooks in: " + str(args.hooks_dir))
|
|
329
|
+
runner = HookRunner(hooks_dir=args.hooks_dir)
|
|
330
|
+
results = runner.run_batch(events, progress_callback=progress)
|
|
331
|
+
status("Replay complete: " + str(len(results)) + " results" + nl)
|
|
332
|
+
|
|
333
|
+
# Step 3: Report
|
|
334
|
+
if args.report_format == "json":
|
|
335
|
+
print(json.dumps(reporter.results_payload(results), indent=2, default=str))
|
|
336
|
+
elif args.regressions_only:
|
|
337
|
+
print(reporter.regressions_only(results))
|
|
338
|
+
elif args.full:
|
|
339
|
+
print(reporter.full_report(results))
|
|
340
|
+
else:
|
|
341
|
+
print(reporter.summary(results))
|
|
342
|
+
|
|
343
|
+
# Save JSON if requested
|
|
344
|
+
if args.output:
|
|
345
|
+
reporter.save_json(results, args.output)
|
|
346
|
+
status(nl + "Results saved to: " + str(args.output))
|
|
347
|
+
|
|
348
|
+
# Return exit code based on regressions
|
|
349
|
+
has_regressions = any(not r.matched for r in results)
|
|
350
|
+
return 1 if has_regressions else 0
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
if __name__ == "__main__":
|
|
354
|
+
sys.exit(main())
|