@jaguilar87/gaia 5.0.0-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +33 -0
- package/.claude-plugin/plugin.json +26 -0
- package/ARCHITECTURE.md +335 -0
- package/CHANGELOG.md +1212 -0
- package/CODE_OF_CONDUCT.md +11 -0
- package/CONTRIBUTING.md +146 -0
- package/INSTALL.md +436 -0
- package/LICENSE +21 -0
- package/README.md +222 -0
- package/SECURITY.md +47 -0
- package/agents/README.md +78 -0
- package/agents/cloud-troubleshooter.md +73 -0
- package/agents/developer.md +65 -0
- package/agents/gaia-operator.md +64 -0
- package/agents/gaia-orchestrator.md +237 -0
- package/agents/gaia-planner.md +53 -0
- package/agents/gaia-system.md +70 -0
- package/agents/gitops-operator.md +61 -0
- package/agents/terraform-architect.md +63 -0
- package/bin/README.md +106 -0
- package/bin/cli/__init__.py +1 -0
- package/bin/cli/approvals.py +740 -0
- package/bin/cli/cleanup.py +562 -0
- package/bin/cli/context.py +283 -0
- package/bin/cli/doctor.py +628 -0
- package/bin/cli/history.py +305 -0
- package/bin/cli/memory.py +464 -0
- package/bin/cli/metrics.py +1068 -0
- package/bin/cli/plans.py +515 -0
- package/bin/cli/status.py +302 -0
- package/bin/cli/update.py +382 -0
- package/bin/gaia +112 -0
- package/bin/gaia-cleanup.js +531 -0
- package/bin/gaia-doctor.js +635 -0
- package/bin/gaia-evidence +126 -0
- package/bin/gaia-history.js +251 -0
- package/bin/gaia-metrics.js +1278 -0
- package/bin/gaia-review.js +269 -0
- package/bin/gaia-scan +44 -0
- package/bin/gaia-scan.py +589 -0
- package/bin/gaia-skills-diagnose.js +929 -0
- package/bin/gaia-status.js +278 -0
- package/bin/gaia-uninstall.js +111 -0
- package/bin/gaia-update.js +816 -0
- package/bin/pre-publish-validate.js +610 -0
- package/bin/python-detect.js +60 -0
- package/commands/README.md +64 -0
- package/commands/gaia.md +37 -0
- package/commands/scan-project.md +67 -0
- package/config/README.md +71 -0
- package/config/cloud/aws.json +134 -0
- package/config/cloud/gcp.json +139 -0
- package/config/context-contracts.json +158 -0
- package/config/crons-schema.md +81 -0
- package/config/git_standards.json +72 -0
- package/config/surface-routing.json +421 -0
- package/config/universal-rules.json +102 -0
- package/dist/gaia-ops/.claude-plugin/plugin.json +24 -0
- package/dist/gaia-ops/README.md +80 -0
- package/dist/gaia-ops/agents/cloud-troubleshooter.md +73 -0
- package/dist/gaia-ops/agents/developer.md +65 -0
- package/dist/gaia-ops/agents/gaia-operator.md +64 -0
- package/dist/gaia-ops/agents/gaia-orchestrator.md +237 -0
- package/dist/gaia-ops/agents/gaia-planner.md +53 -0
- package/dist/gaia-ops/agents/gaia-system.md +70 -0
- package/dist/gaia-ops/agents/gitops-operator.md +61 -0
- package/dist/gaia-ops/agents/terraform-architect.md +63 -0
- package/dist/gaia-ops/commands/gaia.md +37 -0
- package/dist/gaia-ops/config/README.md +71 -0
- package/dist/gaia-ops/config/cloud/aws.json +134 -0
- package/dist/gaia-ops/config/cloud/gcp.json +139 -0
- package/dist/gaia-ops/config/context-contracts.json +158 -0
- package/dist/gaia-ops/config/crons-schema.md +81 -0
- package/dist/gaia-ops/config/git_standards.json +72 -0
- package/dist/gaia-ops/config/surface-routing.json +421 -0
- package/dist/gaia-ops/config/universal-rules.json +102 -0
- package/dist/gaia-ops/hooks/adapters/__init__.py +52 -0
- package/dist/gaia-ops/hooks/adapters/base.py +219 -0
- package/dist/gaia-ops/hooks/adapters/channel.py +17 -0
- package/dist/gaia-ops/hooks/adapters/claude_code.py +1890 -0
- package/dist/gaia-ops/hooks/adapters/types.py +194 -0
- package/dist/gaia-ops/hooks/adapters/utils.py +25 -0
- package/dist/gaia-ops/hooks/hooks.json +163 -0
- package/dist/gaia-ops/hooks/modules/__init__.py +15 -0
- package/dist/gaia-ops/hooks/modules/agents/__init__.py +29 -0
- package/dist/gaia-ops/hooks/modules/agents/contract_validator.py +647 -0
- package/dist/gaia-ops/hooks/modules/agents/response_contract.py +496 -0
- package/dist/gaia-ops/hooks/modules/agents/skill_injection_verifier.py +120 -0
- package/dist/gaia-ops/hooks/modules/agents/state_tracker.py +267 -0
- package/dist/gaia-ops/hooks/modules/agents/task_info_builder.py +74 -0
- package/dist/gaia-ops/hooks/modules/agents/transcript_analyzer.py +458 -0
- package/dist/gaia-ops/hooks/modules/agents/transcript_reader.py +152 -0
- package/dist/gaia-ops/hooks/modules/audit/__init__.py +28 -0
- package/dist/gaia-ops/hooks/modules/audit/event_detector.py +168 -0
- package/dist/gaia-ops/hooks/modules/audit/logger.py +131 -0
- package/dist/gaia-ops/hooks/modules/audit/metrics.py +134 -0
- package/dist/gaia-ops/hooks/modules/audit/workflow_auditor.py +611 -0
- package/dist/gaia-ops/hooks/modules/audit/workflow_recorder.py +296 -0
- package/dist/gaia-ops/hooks/modules/context/__init__.py +11 -0
- package/dist/gaia-ops/hooks/modules/context/agentic_loop_detector.py +165 -0
- package/dist/gaia-ops/hooks/modules/context/anchor_tracker.py +317 -0
- package/dist/gaia-ops/hooks/modules/context/compact_context_builder.py +218 -0
- package/dist/gaia-ops/hooks/modules/context/context_freshness.py +145 -0
- package/dist/gaia-ops/hooks/modules/context/context_injector.py +558 -0
- package/dist/gaia-ops/hooks/modules/context/context_writer.py +530 -0
- package/dist/gaia-ops/hooks/modules/context/contracts_loader.py +161 -0
- package/dist/gaia-ops/hooks/modules/core/__init__.py +40 -0
- package/dist/gaia-ops/hooks/modules/core/hook_entry.py +78 -0
- package/dist/gaia-ops/hooks/modules/core/paths.py +160 -0
- package/dist/gaia-ops/hooks/modules/core/plugin_mode.py +149 -0
- package/dist/gaia-ops/hooks/modules/core/plugin_setup.py +577 -0
- package/dist/gaia-ops/hooks/modules/core/state.py +179 -0
- package/dist/gaia-ops/hooks/modules/core/stdin.py +24 -0
- package/dist/gaia-ops/hooks/modules/events/__init__.py +1 -0
- package/dist/gaia-ops/hooks/modules/events/event_writer.py +210 -0
- package/dist/gaia-ops/hooks/modules/memory/__init__.py +8 -0
- package/dist/gaia-ops/hooks/modules/memory/episode_writer.py +216 -0
- package/dist/gaia-ops/hooks/modules/orchestrator/__init__.py +1 -0
- package/dist/gaia-ops/hooks/modules/orchestrator/delegate_mode.py +122 -0
- package/dist/gaia-ops/hooks/modules/scanning/__init__.py +8 -0
- package/dist/gaia-ops/hooks/modules/scanning/scan_trigger.py +84 -0
- package/dist/gaia-ops/hooks/modules/security/__init__.py +120 -0
- package/dist/gaia-ops/hooks/modules/security/approval_cleanup.py +87 -0
- package/dist/gaia-ops/hooks/modules/security/approval_constants.py +23 -0
- package/dist/gaia-ops/hooks/modules/security/approval_grants.py +1638 -0
- package/dist/gaia-ops/hooks/modules/security/approval_messages.py +71 -0
- package/dist/gaia-ops/hooks/modules/security/approval_scopes.py +222 -0
- package/dist/gaia-ops/hooks/modules/security/blocked_commands.py +595 -0
- package/dist/gaia-ops/hooks/modules/security/blocked_message_formatter.py +87 -0
- package/dist/gaia-ops/hooks/modules/security/command_semantics.py +181 -0
- package/dist/gaia-ops/hooks/modules/security/composition_rules.py +547 -0
- package/dist/gaia-ops/hooks/modules/security/flag_classifiers.py +873 -0
- package/dist/gaia-ops/hooks/modules/security/gitops_validator.py +179 -0
- package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +1131 -0
- package/dist/gaia-ops/hooks/modules/security/network_hosts.py +481 -0
- package/dist/gaia-ops/hooks/modules/security/prompt_validator.py +40 -0
- package/dist/gaia-ops/hooks/modules/security/shell_unwrapper.py +165 -0
- package/dist/gaia-ops/hooks/modules/security/tiers.py +196 -0
- package/dist/gaia-ops/hooks/modules/session/__init__.py +10 -0
- package/dist/gaia-ops/hooks/modules/session/pending_scanner.py +174 -0
- package/dist/gaia-ops/hooks/modules/session/session_context_writer.py +100 -0
- package/dist/gaia-ops/hooks/modules/session/session_event_injector.py +160 -0
- package/dist/gaia-ops/hooks/modules/session/session_manager.py +31 -0
- package/dist/gaia-ops/hooks/modules/session/session_registry.py +232 -0
- package/dist/gaia-ops/hooks/modules/tools/__init__.py +29 -0
- package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +1008 -0
- package/dist/gaia-ops/hooks/modules/tools/cloud_pipe_validator.py +231 -0
- package/dist/gaia-ops/hooks/modules/tools/hook_response.py +55 -0
- package/dist/gaia-ops/hooks/modules/tools/shell_parser.py +227 -0
- package/dist/gaia-ops/hooks/modules/tools/stage_decomposer.py +315 -0
- package/dist/gaia-ops/hooks/modules/tools/task_validator.py +294 -0
- package/dist/gaia-ops/hooks/modules/validation/__init__.py +23 -0
- package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +380 -0
- package/dist/gaia-ops/hooks/post_compact.py +43 -0
- package/dist/gaia-ops/hooks/post_tool_use.py +54 -0
- package/dist/gaia-ops/hooks/pre_compact.py +60 -0
- package/dist/gaia-ops/hooks/pre_tool_use.py +413 -0
- package/dist/gaia-ops/hooks/session_start.py +81 -0
- package/dist/gaia-ops/hooks/stop_hook.py +82 -0
- package/dist/gaia-ops/hooks/subagent_start.py +71 -0
- package/dist/gaia-ops/hooks/subagent_stop.py +295 -0
- package/dist/gaia-ops/hooks/task_completed.py +70 -0
- package/dist/gaia-ops/hooks/user_prompt_submit.py +246 -0
- package/dist/gaia-ops/settings.json +72 -0
- package/dist/gaia-ops/skills/README.md +154 -0
- package/dist/gaia-ops/skills/agent-protocol/SKILL.md +93 -0
- package/dist/gaia-ops/skills/agent-protocol/examples.md +223 -0
- package/dist/gaia-ops/skills/agent-response/SKILL.md +69 -0
- package/dist/gaia-ops/skills/agentic-loop/SKILL.md +80 -0
- package/dist/gaia-ops/skills/agentic-loop/reference.md +378 -0
- package/dist/gaia-ops/skills/blog-writing/SKILL.md +98 -0
- package/dist/gaia-ops/skills/blog-writing/reference.md +130 -0
- package/dist/gaia-ops/skills/brief-spec/SKILL.md +182 -0
- package/dist/gaia-ops/skills/command-execution/SKILL.md +64 -0
- package/dist/gaia-ops/skills/command-execution/reference.md +83 -0
- package/dist/gaia-ops/skills/context-updater/SKILL.md +87 -0
- package/dist/gaia-ops/skills/context-updater/examples.md +71 -0
- package/dist/gaia-ops/skills/developer-patterns/SKILL.md +50 -0
- package/dist/gaia-ops/skills/developer-patterns/reference.md +112 -0
- package/dist/gaia-ops/skills/execution/SKILL.md +99 -0
- package/dist/gaia-ops/skills/fast-queries/SKILL.md +43 -0
- package/dist/gaia-ops/skills/gaia-compact/SKILL.md +74 -0
- package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +108 -0
- package/dist/gaia-ops/skills/gaia-patterns/reference.md +395 -0
- package/dist/gaia-ops/skills/gaia-planner/SKILL.md +37 -0
- package/dist/gaia-ops/skills/gaia-planner/reference.md +107 -0
- package/dist/gaia-ops/skills/gaia-release/SKILL.md +82 -0
- package/dist/gaia-ops/skills/gaia-release/reference.md +102 -0
- package/dist/gaia-ops/skills/gaia-self-check/SKILL.md +114 -0
- package/dist/gaia-ops/skills/gaia-self-check/reference.md +453 -0
- package/dist/gaia-ops/skills/gaia-verify/SKILL.md +77 -0
- package/dist/gaia-ops/skills/gaia-verify/reference.md +80 -0
- package/dist/gaia-ops/skills/git-conventions/SKILL.md +47 -0
- package/dist/gaia-ops/skills/gitops-patterns/SKILL.md +60 -0
- package/dist/gaia-ops/skills/gitops-patterns/reference.md +183 -0
- package/dist/gaia-ops/skills/gmail-policy/SKILL.md +200 -0
- package/dist/gaia-ops/skills/gmail-policy/reference.md +150 -0
- package/dist/gaia-ops/skills/gmail-triage/SKILL.md +100 -0
- package/dist/gaia-ops/skills/gws-setup/SKILL.md +99 -0
- package/dist/gaia-ops/skills/gws-setup/reference.md +73 -0
- package/dist/gaia-ops/skills/investigation/SKILL.md +100 -0
- package/dist/gaia-ops/skills/memory-curation/SKILL.md +83 -0
- package/dist/gaia-ops/skills/memory-search/SKILL.md +88 -0
- package/dist/gaia-ops/skills/orchestrator-approval/SKILL.md +160 -0
- package/dist/gaia-ops/skills/orchestrator-approval/reference.md +174 -0
- package/dist/gaia-ops/skills/pending-approvals/SKILL.md +72 -0
- package/dist/gaia-ops/skills/pending-approvals/reference.md +214 -0
- package/dist/gaia-ops/skills/readme-writing/SKILL.md +71 -0
- package/dist/gaia-ops/skills/readme-writing/reference.md +188 -0
- package/dist/gaia-ops/skills/reference.md +135 -0
- package/dist/gaia-ops/skills/request-approval/SKILL.md +140 -0
- package/dist/gaia-ops/skills/request-approval/examples.md +140 -0
- package/dist/gaia-ops/skills/request-approval/reference.md +57 -0
- package/dist/gaia-ops/skills/schedule-task/SKILL.md +64 -0
- package/dist/gaia-ops/skills/schedule-task/reference.md +233 -0
- package/dist/gaia-ops/skills/security-tiers/SKILL.md +141 -0
- package/dist/gaia-ops/skills/security-tiers/destructive-commands-reference.md +623 -0
- package/dist/gaia-ops/skills/security-tiers/reference.md +39 -0
- package/dist/gaia-ops/skills/skill-creation/SKILL.md +92 -0
- package/dist/gaia-ops/skills/skill-creation/reference.md +29 -0
- package/dist/gaia-ops/skills/terraform-patterns/SKILL.md +89 -0
- package/dist/gaia-ops/skills/terraform-patterns/reference.md +93 -0
- package/dist/gaia-ops/tools/__init__.py +9 -0
- package/dist/gaia-ops/tools/agentic-loop/decide-status.py +210 -0
- package/dist/gaia-ops/tools/agentic-loop/parse-metric.py +106 -0
- package/dist/gaia-ops/tools/agentic-loop/record-iteration.py +221 -0
- package/dist/gaia-ops/tools/context/README.md +132 -0
- package/dist/gaia-ops/tools/context/__init__.py +42 -0
- package/dist/gaia-ops/tools/context/_paths.py +20 -0
- package/dist/gaia-ops/tools/context/context_provider.py +721 -0
- package/dist/gaia-ops/tools/context/context_section_reader.py +342 -0
- package/dist/gaia-ops/tools/context/deep_merge.py +159 -0
- package/dist/gaia-ops/tools/context/pending_updates.py +760 -0
- package/dist/gaia-ops/tools/context/surface_router.py +278 -0
- package/dist/gaia-ops/tools/fast-queries/README.md +65 -0
- package/dist/gaia-ops/tools/fast-queries/__init__.py +30 -0
- package/dist/gaia-ops/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
- package/dist/gaia-ops/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
- package/dist/gaia-ops/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
- package/dist/gaia-ops/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
- package/dist/gaia-ops/tools/fast-queries/run_triage.sh +59 -0
- package/dist/gaia-ops/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
- package/dist/gaia-ops/tools/gaia_simulator/__init__.py +33 -0
- package/dist/gaia-ops/tools/gaia_simulator/cli.py +354 -0
- package/dist/gaia-ops/tools/gaia_simulator/extractor.py +457 -0
- package/dist/gaia-ops/tools/gaia_simulator/reporter.py +258 -0
- package/dist/gaia-ops/tools/gaia_simulator/routing_simulator.py +334 -0
- package/dist/gaia-ops/tools/gaia_simulator/runner.py +539 -0
- package/dist/gaia-ops/tools/gaia_simulator/skills_mapper.py +264 -0
- package/dist/gaia-ops/tools/memory/README.md +0 -0
- package/dist/gaia-ops/tools/memory/__init__.py +20 -0
- package/dist/gaia-ops/tools/memory/backfill_fts5.py +107 -0
- package/dist/gaia-ops/tools/memory/conflict_detector.py +295 -0
- package/dist/gaia-ops/tools/memory/episodic.py +1210 -0
- package/dist/gaia-ops/tools/memory/git_invalidator.py +262 -0
- package/dist/gaia-ops/tools/memory/paths.py +102 -0
- package/dist/gaia-ops/tools/memory/scoring.py +193 -0
- package/dist/gaia-ops/tools/memory/search_store.py +360 -0
- package/dist/gaia-ops/tools/persist_transcript_analysis.py +85 -0
- package/dist/gaia-ops/tools/review/__init__.py +1 -0
- package/dist/gaia-ops/tools/review/review_engine.py +157 -0
- package/dist/gaia-ops/tools/scan/__init__.py +35 -0
- package/dist/gaia-ops/tools/scan/config.py +247 -0
- package/dist/gaia-ops/tools/scan/merge.py +212 -0
- package/dist/gaia-ops/tools/scan/orchestrator.py +549 -0
- package/dist/gaia-ops/tools/scan/registry.py +127 -0
- package/dist/gaia-ops/tools/scan/scanners/__init__.py +18 -0
- package/dist/gaia-ops/tools/scan/scanners/base.py +137 -0
- package/dist/gaia-ops/tools/scan/scanners/environment.py +349 -0
- package/dist/gaia-ops/tools/scan/scanners/git.py +570 -0
- package/dist/gaia-ops/tools/scan/scanners/infrastructure.py +875 -0
- package/dist/gaia-ops/tools/scan/scanners/orchestration.py +600 -0
- package/dist/gaia-ops/tools/scan/scanners/stack.py +1085 -0
- package/dist/gaia-ops/tools/scan/scanners/tools.py +260 -0
- package/dist/gaia-ops/tools/scan/setup.py +686 -0
- package/dist/gaia-ops/tools/scan/tests/__init__.py +1 -0
- package/dist/gaia-ops/tools/scan/tests/conftest.py +796 -0
- package/dist/gaia-ops/tools/scan/tests/test_environment.py +323 -0
- package/dist/gaia-ops/tools/scan/tests/test_git.py +419 -0
- package/dist/gaia-ops/tools/scan/tests/test_infrastructure.py +382 -0
- package/dist/gaia-ops/tools/scan/tests/test_integration.py +920 -0
- package/dist/gaia-ops/tools/scan/tests/test_merge.py +269 -0
- package/dist/gaia-ops/tools/scan/tests/test_orchestration.py +304 -0
- package/dist/gaia-ops/tools/scan/tests/test_stack.py +604 -0
- package/dist/gaia-ops/tools/scan/tests/test_tools.py +349 -0
- package/dist/gaia-ops/tools/scan/ui.py +624 -0
- package/dist/gaia-ops/tools/scan/verify.py +270 -0
- package/dist/gaia-ops/tools/scan/walk.py +118 -0
- package/dist/gaia-ops/tools/scan/workspace.py +85 -0
- package/dist/gaia-ops/tools/validation/README.md +244 -0
- package/dist/gaia-ops/tools/validation/__init__.py +17 -0
- package/dist/gaia-ops/tools/validation/approval_gate.py +321 -0
- package/dist/gaia-ops/tools/validation/validate_skills.py +189 -0
- package/dist/gaia-security/.claude-plugin/plugin.json +24 -0
- package/dist/gaia-security/README.md +90 -0
- package/dist/gaia-security/config/universal-rules.json +102 -0
- package/dist/gaia-security/hooks/adapters/__init__.py +52 -0
- package/dist/gaia-security/hooks/adapters/base.py +219 -0
- package/dist/gaia-security/hooks/adapters/channel.py +17 -0
- package/dist/gaia-security/hooks/adapters/claude_code.py +1890 -0
- package/dist/gaia-security/hooks/adapters/types.py +194 -0
- package/dist/gaia-security/hooks/adapters/utils.py +25 -0
- package/dist/gaia-security/hooks/hooks.json +84 -0
- package/dist/gaia-security/hooks/modules/__init__.py +15 -0
- package/dist/gaia-security/hooks/modules/agents/__init__.py +29 -0
- package/dist/gaia-security/hooks/modules/agents/contract_validator.py +647 -0
- package/dist/gaia-security/hooks/modules/agents/response_contract.py +496 -0
- package/dist/gaia-security/hooks/modules/agents/skill_injection_verifier.py +120 -0
- package/dist/gaia-security/hooks/modules/agents/state_tracker.py +267 -0
- package/dist/gaia-security/hooks/modules/agents/task_info_builder.py +74 -0
- package/dist/gaia-security/hooks/modules/agents/transcript_analyzer.py +458 -0
- package/dist/gaia-security/hooks/modules/agents/transcript_reader.py +152 -0
- package/dist/gaia-security/hooks/modules/audit/__init__.py +28 -0
- package/dist/gaia-security/hooks/modules/audit/event_detector.py +168 -0
- package/dist/gaia-security/hooks/modules/audit/logger.py +131 -0
- package/dist/gaia-security/hooks/modules/audit/metrics.py +134 -0
- package/dist/gaia-security/hooks/modules/audit/workflow_auditor.py +611 -0
- package/dist/gaia-security/hooks/modules/audit/workflow_recorder.py +296 -0
- package/dist/gaia-security/hooks/modules/context/__init__.py +11 -0
- package/dist/gaia-security/hooks/modules/context/agentic_loop_detector.py +165 -0
- package/dist/gaia-security/hooks/modules/context/anchor_tracker.py +317 -0
- package/dist/gaia-security/hooks/modules/context/compact_context_builder.py +218 -0
- package/dist/gaia-security/hooks/modules/context/context_freshness.py +145 -0
- package/dist/gaia-security/hooks/modules/context/context_injector.py +558 -0
- package/dist/gaia-security/hooks/modules/context/context_writer.py +530 -0
- package/dist/gaia-security/hooks/modules/context/contracts_loader.py +161 -0
- package/dist/gaia-security/hooks/modules/core/__init__.py +40 -0
- package/dist/gaia-security/hooks/modules/core/hook_entry.py +78 -0
- package/dist/gaia-security/hooks/modules/core/paths.py +160 -0
- package/dist/gaia-security/hooks/modules/core/plugin_mode.py +149 -0
- package/dist/gaia-security/hooks/modules/core/plugin_setup.py +577 -0
- package/dist/gaia-security/hooks/modules/core/state.py +179 -0
- package/dist/gaia-security/hooks/modules/core/stdin.py +24 -0
- package/dist/gaia-security/hooks/modules/events/__init__.py +1 -0
- package/dist/gaia-security/hooks/modules/events/event_writer.py +210 -0
- package/dist/gaia-security/hooks/modules/memory/__init__.py +8 -0
- package/dist/gaia-security/hooks/modules/memory/episode_writer.py +216 -0
- package/dist/gaia-security/hooks/modules/orchestrator/__init__.py +1 -0
- package/dist/gaia-security/hooks/modules/orchestrator/delegate_mode.py +122 -0
- package/dist/gaia-security/hooks/modules/scanning/__init__.py +8 -0
- package/dist/gaia-security/hooks/modules/scanning/scan_trigger.py +84 -0
- package/dist/gaia-security/hooks/modules/security/__init__.py +120 -0
- package/dist/gaia-security/hooks/modules/security/approval_cleanup.py +87 -0
- package/dist/gaia-security/hooks/modules/security/approval_constants.py +23 -0
- package/dist/gaia-security/hooks/modules/security/approval_grants.py +1638 -0
- package/dist/gaia-security/hooks/modules/security/approval_messages.py +71 -0
- package/dist/gaia-security/hooks/modules/security/approval_scopes.py +222 -0
- package/dist/gaia-security/hooks/modules/security/blocked_commands.py +595 -0
- package/dist/gaia-security/hooks/modules/security/blocked_message_formatter.py +87 -0
- package/dist/gaia-security/hooks/modules/security/command_semantics.py +181 -0
- package/dist/gaia-security/hooks/modules/security/composition_rules.py +547 -0
- package/dist/gaia-security/hooks/modules/security/flag_classifiers.py +873 -0
- package/dist/gaia-security/hooks/modules/security/gitops_validator.py +179 -0
- package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +1131 -0
- package/dist/gaia-security/hooks/modules/security/network_hosts.py +481 -0
- package/dist/gaia-security/hooks/modules/security/prompt_validator.py +40 -0
- package/dist/gaia-security/hooks/modules/security/shell_unwrapper.py +165 -0
- package/dist/gaia-security/hooks/modules/security/tiers.py +196 -0
- package/dist/gaia-security/hooks/modules/session/__init__.py +10 -0
- package/dist/gaia-security/hooks/modules/session/pending_scanner.py +174 -0
- package/dist/gaia-security/hooks/modules/session/session_context_writer.py +100 -0
- package/dist/gaia-security/hooks/modules/session/session_event_injector.py +160 -0
- package/dist/gaia-security/hooks/modules/session/session_manager.py +31 -0
- package/dist/gaia-security/hooks/modules/session/session_registry.py +232 -0
- package/dist/gaia-security/hooks/modules/tools/__init__.py +29 -0
- package/dist/gaia-security/hooks/modules/tools/bash_validator.py +1008 -0
- package/dist/gaia-security/hooks/modules/tools/cloud_pipe_validator.py +231 -0
- package/dist/gaia-security/hooks/modules/tools/hook_response.py +55 -0
- package/dist/gaia-security/hooks/modules/tools/shell_parser.py +227 -0
- package/dist/gaia-security/hooks/modules/tools/stage_decomposer.py +315 -0
- package/dist/gaia-security/hooks/modules/tools/task_validator.py +294 -0
- package/dist/gaia-security/hooks/modules/validation/__init__.py +23 -0
- package/dist/gaia-security/hooks/modules/validation/commit_validator.py +380 -0
- package/dist/gaia-security/hooks/post_tool_use.py +54 -0
- package/dist/gaia-security/hooks/pre_tool_use.py +413 -0
- package/dist/gaia-security/hooks/session_start.py +81 -0
- package/dist/gaia-security/hooks/stop_hook.py +82 -0
- package/dist/gaia-security/hooks/user_prompt_submit.py +246 -0
- package/dist/gaia-security/settings.json +58 -0
- package/git-hooks/commit-msg +41 -0
- package/hooks/README.md +100 -0
- package/hooks/adapters/__init__.py +52 -0
- package/hooks/adapters/base.py +219 -0
- package/hooks/adapters/channel.py +17 -0
- package/hooks/adapters/claude_code.py +1890 -0
- package/hooks/adapters/types.py +194 -0
- package/hooks/adapters/utils.py +25 -0
- package/hooks/elicitation_result.py +179 -0
- package/hooks/hooks.json +84 -0
- package/hooks/modules/README.md +189 -0
- package/hooks/modules/__init__.py +15 -0
- package/hooks/modules/agents/__init__.py +29 -0
- package/hooks/modules/agents/contract_validator.py +647 -0
- package/hooks/modules/agents/response_contract.py +496 -0
- package/hooks/modules/agents/skill_injection_verifier.py +120 -0
- package/hooks/modules/agents/state_tracker.py +267 -0
- package/hooks/modules/agents/task_info_builder.py +74 -0
- package/hooks/modules/agents/transcript_analyzer.py +458 -0
- package/hooks/modules/agents/transcript_reader.py +152 -0
- package/hooks/modules/audit/__init__.py +28 -0
- package/hooks/modules/audit/event_detector.py +168 -0
- package/hooks/modules/audit/logger.py +131 -0
- package/hooks/modules/audit/metrics.py +134 -0
- package/hooks/modules/audit/workflow_auditor.py +611 -0
- package/hooks/modules/audit/workflow_recorder.py +296 -0
- package/hooks/modules/context/__init__.py +11 -0
- package/hooks/modules/context/agentic_loop_detector.py +165 -0
- package/hooks/modules/context/anchor_tracker.py +317 -0
- package/hooks/modules/context/compact_context_builder.py +218 -0
- package/hooks/modules/context/context_freshness.py +145 -0
- package/hooks/modules/context/context_injector.py +558 -0
- package/hooks/modules/context/context_writer.py +530 -0
- package/hooks/modules/context/contracts_loader.py +161 -0
- package/hooks/modules/core/__init__.py +40 -0
- package/hooks/modules/core/hook_entry.py +78 -0
- package/hooks/modules/core/paths.py +160 -0
- package/hooks/modules/core/plugin_mode.py +149 -0
- package/hooks/modules/core/plugin_setup.py +577 -0
- package/hooks/modules/core/state.py +179 -0
- package/hooks/modules/core/stdin.py +24 -0
- package/hooks/modules/events/__init__.py +1 -0
- package/hooks/modules/events/event_writer.py +210 -0
- package/hooks/modules/evidence/__init__.py +34 -0
- package/hooks/modules/evidence/assertions.py +137 -0
- package/hooks/modules/evidence/index_writer.py +57 -0
- package/hooks/modules/evidence/loader.py +126 -0
- package/hooks/modules/evidence/runner.py +241 -0
- package/hooks/modules/memory/__init__.py +8 -0
- package/hooks/modules/memory/episode_writer.py +216 -0
- package/hooks/modules/orchestrator/__init__.py +1 -0
- package/hooks/modules/orchestrator/delegate_mode.py +122 -0
- package/hooks/modules/scanning/__init__.py +8 -0
- package/hooks/modules/scanning/scan_trigger.py +84 -0
- package/hooks/modules/security/__init__.py +120 -0
- package/hooks/modules/security/approval_cleanup.py +87 -0
- package/hooks/modules/security/approval_constants.py +23 -0
- package/hooks/modules/security/approval_grants.py +1638 -0
- package/hooks/modules/security/approval_messages.py +71 -0
- package/hooks/modules/security/approval_scopes.py +222 -0
- package/hooks/modules/security/blocked_commands.py +595 -0
- package/hooks/modules/security/blocked_message_formatter.py +87 -0
- package/hooks/modules/security/command_semantics.py +181 -0
- package/hooks/modules/security/composition_rules.py +547 -0
- package/hooks/modules/security/flag_classifiers.py +873 -0
- package/hooks/modules/security/gitops_validator.py +179 -0
- package/hooks/modules/security/mutative_verbs.py +1131 -0
- package/hooks/modules/security/network_hosts.py +481 -0
- package/hooks/modules/security/prompt_validator.py +40 -0
- package/hooks/modules/security/shell_unwrapper.py +165 -0
- package/hooks/modules/security/tiers.py +196 -0
- package/hooks/modules/session/__init__.py +10 -0
- package/hooks/modules/session/pending_scanner.py +174 -0
- package/hooks/modules/session/session_context_writer.py +100 -0
- package/hooks/modules/session/session_event_injector.py +160 -0
- package/hooks/modules/session/session_manager.py +31 -0
- package/hooks/modules/session/session_registry.py +232 -0
- package/hooks/modules/tools/__init__.py +29 -0
- package/hooks/modules/tools/bash_validator.py +1008 -0
- package/hooks/modules/tools/cloud_pipe_validator.py +231 -0
- package/hooks/modules/tools/hook_response.py +55 -0
- package/hooks/modules/tools/shell_parser.py +227 -0
- package/hooks/modules/tools/stage_decomposer.py +315 -0
- package/hooks/modules/tools/task_validator.py +294 -0
- package/hooks/modules/validation/__init__.py +23 -0
- package/hooks/modules/validation/commit_validator.py +380 -0
- package/hooks/post_compact.py +43 -0
- package/hooks/post_tool_use.py +54 -0
- package/hooks/pre_compact.py +60 -0
- package/hooks/pre_tool_use.py +413 -0
- package/hooks/session_start.py +81 -0
- package/hooks/stop_hook.py +82 -0
- package/hooks/subagent_start.py +71 -0
- package/hooks/subagent_stop.py +295 -0
- package/hooks/task_completed.py +70 -0
- package/hooks/user_prompt_submit.py +246 -0
- package/index.js +83 -0
- package/package.json +99 -0
- package/pyproject.toml +32 -0
- package/skills/README.md +154 -0
- package/skills/agent-protocol/SKILL.md +93 -0
- package/skills/agent-protocol/examples.md +223 -0
- package/skills/agent-response/SKILL.md +69 -0
- package/skills/agentic-loop/SKILL.md +80 -0
- package/skills/agentic-loop/reference.md +378 -0
- package/skills/blog-writing/SKILL.md +98 -0
- package/skills/blog-writing/reference.md +130 -0
- package/skills/brief-spec/SKILL.md +182 -0
- package/skills/command-execution/SKILL.md +64 -0
- package/skills/command-execution/reference.md +83 -0
- package/skills/context-updater/SKILL.md +87 -0
- package/skills/context-updater/examples.md +71 -0
- package/skills/developer-patterns/SKILL.md +50 -0
- package/skills/developer-patterns/reference.md +112 -0
- package/skills/execution/SKILL.md +99 -0
- package/skills/fast-queries/SKILL.md +43 -0
- package/skills/gaia-compact/SKILL.md +74 -0
- package/skills/gaia-patterns/SKILL.md +108 -0
- package/skills/gaia-patterns/reference.md +395 -0
- package/skills/gaia-planner/SKILL.md +37 -0
- package/skills/gaia-planner/reference.md +107 -0
- package/skills/gaia-release/SKILL.md +82 -0
- package/skills/gaia-release/reference.md +102 -0
- package/skills/gaia-self-check/SKILL.md +114 -0
- package/skills/gaia-self-check/reference.md +453 -0
- package/skills/gaia-verify/SKILL.md +77 -0
- package/skills/gaia-verify/reference.md +80 -0
- package/skills/git-conventions/SKILL.md +47 -0
- package/skills/gitops-patterns/SKILL.md +60 -0
- package/skills/gitops-patterns/reference.md +183 -0
- package/skills/gmail-policy/SKILL.md +200 -0
- package/skills/gmail-policy/reference.md +150 -0
- package/skills/gmail-triage/SKILL.md +100 -0
- package/skills/gws-setup/SKILL.md +99 -0
- package/skills/gws-setup/reference.md +73 -0
- package/skills/investigation/SKILL.md +100 -0
- package/skills/memory-curation/SKILL.md +83 -0
- package/skills/memory-search/SKILL.md +88 -0
- package/skills/orchestrator-approval/SKILL.md +160 -0
- package/skills/orchestrator-approval/reference.md +174 -0
- package/skills/pending-approvals/SKILL.md +72 -0
- package/skills/pending-approvals/reference.md +214 -0
- package/skills/readme-writing/SKILL.md +71 -0
- package/skills/readme-writing/reference.md +188 -0
- package/skills/reference.md +135 -0
- package/skills/request-approval/SKILL.md +140 -0
- package/skills/request-approval/examples.md +140 -0
- package/skills/request-approval/reference.md +57 -0
- package/skills/schedule-task/SKILL.md +64 -0
- package/skills/schedule-task/reference.md +233 -0
- package/skills/security-tiers/SKILL.md +141 -0
- package/skills/security-tiers/destructive-commands-reference.md +623 -0
- package/skills/security-tiers/reference.md +39 -0
- package/skills/skill-creation/SKILL.md +92 -0
- package/skills/skill-creation/reference.md +29 -0
- package/skills/terraform-patterns/SKILL.md +89 -0
- package/skills/terraform-patterns/reference.md +93 -0
- package/templates/README.md +69 -0
- package/templates/managed-settings.template.json +43 -0
- package/tools/__init__.py +9 -0
- package/tools/agentic-loop/decide-status.py +210 -0
- package/tools/agentic-loop/parse-metric.py +106 -0
- package/tools/agentic-loop/record-iteration.py +221 -0
- package/tools/context/README.md +132 -0
- package/tools/context/__init__.py +42 -0
- package/tools/context/_paths.py +20 -0
- package/tools/context/context_provider.py +721 -0
- package/tools/context/context_section_reader.py +342 -0
- package/tools/context/deep_merge.py +159 -0
- package/tools/context/pending_updates.py +760 -0
- package/tools/context/surface_router.py +278 -0
- package/tools/fast-queries/README.md +65 -0
- package/tools/fast-queries/__init__.py +30 -0
- package/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
- package/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
- package/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
- package/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
- package/tools/fast-queries/run_triage.sh +59 -0
- package/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
- package/tools/gaia_simulator/__init__.py +33 -0
- package/tools/gaia_simulator/cli.py +354 -0
- package/tools/gaia_simulator/extractor.py +457 -0
- package/tools/gaia_simulator/reporter.py +258 -0
- package/tools/gaia_simulator/routing_simulator.py +334 -0
- package/tools/gaia_simulator/runner.py +539 -0
- package/tools/gaia_simulator/skills_mapper.py +264 -0
- package/tools/memory/README.md +0 -0
- package/tools/memory/__init__.py +20 -0
- package/tools/memory/backfill_fts5.py +107 -0
- package/tools/memory/conflict_detector.py +295 -0
- package/tools/memory/episodic.py +1210 -0
- package/tools/memory/git_invalidator.py +262 -0
- package/tools/memory/paths.py +102 -0
- package/tools/memory/scoring.py +193 -0
- package/tools/memory/search_store.py +360 -0
- package/tools/persist_transcript_analysis.py +85 -0
- package/tools/review/__init__.py +1 -0
- package/tools/review/review_engine.py +157 -0
- package/tools/scan/__init__.py +35 -0
- package/tools/scan/config.py +247 -0
- package/tools/scan/merge.py +212 -0
- package/tools/scan/orchestrator.py +549 -0
- package/tools/scan/registry.py +127 -0
- package/tools/scan/scanners/__init__.py +18 -0
- package/tools/scan/scanners/base.py +137 -0
- package/tools/scan/scanners/environment.py +349 -0
- package/tools/scan/scanners/git.py +570 -0
- package/tools/scan/scanners/infrastructure.py +875 -0
- package/tools/scan/scanners/orchestration.py +600 -0
- package/tools/scan/scanners/stack.py +1085 -0
- package/tools/scan/scanners/tools.py +260 -0
- package/tools/scan/setup.py +686 -0
- package/tools/scan/tests/__init__.py +1 -0
- package/tools/scan/tests/conftest.py +796 -0
- package/tools/scan/tests/test_environment.py +323 -0
- package/tools/scan/tests/test_git.py +419 -0
- package/tools/scan/tests/test_infrastructure.py +382 -0
- package/tools/scan/tests/test_integration.py +920 -0
- package/tools/scan/tests/test_merge.py +269 -0
- package/tools/scan/tests/test_orchestration.py +304 -0
- package/tools/scan/tests/test_stack.py +604 -0
- package/tools/scan/tests/test_tools.py +349 -0
- package/tools/scan/ui.py +624 -0
- package/tools/scan/verify.py +270 -0
- package/tools/scan/walk.py +118 -0
- package/tools/scan/workspace.py +85 -0
- package/tools/validation/README.md +244 -0
- package/tools/validation/__init__.py +17 -0
- package/tools/validation/approval_gate.py +321 -0
- package/tools/validation/validate_skills.py +189 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Subagent stop hook for Claude Code Agent System.
|
|
4
|
+
|
|
5
|
+
Thin gate: parse stdin -> delegate to adapter -> format response -> exit.
|
|
6
|
+
|
|
7
|
+
Architecture:
|
|
8
|
+
- Uses adapter layer to parse and process the full SubagentStop lifecycle
|
|
9
|
+
- All business logic lives in ClaudeCodeAdapter.adapt_subagent_stop()
|
|
10
|
+
- This file is stdin/stdout glue only
|
|
11
|
+
|
|
12
|
+
Business logic modules (called by the adapter):
|
|
13
|
+
- modules.agents.contract_validator : Contract validation + evidence parsing
|
|
14
|
+
- modules.agents.transcript_reader : Transcript I/O
|
|
15
|
+
- modules.agents.task_info_builder : Hook payload -> task_info mapping
|
|
16
|
+
- modules.audit.workflow_recorder : Workflow metrics capture
|
|
17
|
+
- modules.audit.workflow_auditor : Anomaly detection + Gaia signaling
|
|
18
|
+
- modules.memory.episode_writer : Episodic memory storage + session events
|
|
19
|
+
- modules.context.context_writer : Progressive context enrichment
|
|
20
|
+
- modules.security.approval_cleanup : Approval file consumption
|
|
21
|
+
- modules.agents.response_contract : Response contract validation
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
import logging
|
|
26
|
+
import sys
|
|
27
|
+
from datetime import datetime
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Any, Dict
|
|
30
|
+
|
|
31
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
32
|
+
|
|
33
|
+
# Adapter layer
|
|
34
|
+
from adapters.claude_code import ClaudeCodeAdapter
|
|
35
|
+
from modules.core.hook_entry import run_hook
|
|
36
|
+
|
|
37
|
+
# Configure structured logging with file handler
|
|
38
|
+
try:
|
|
39
|
+
from modules.core.paths import get_logs_dir
|
|
40
|
+
_log_dir = get_logs_dir()
|
|
41
|
+
except ImportError:
|
|
42
|
+
_log_dir = Path.cwd() / ".claude" / "logs"
|
|
43
|
+
_log_dir.mkdir(parents=True, exist_ok=True)
|
|
44
|
+
|
|
45
|
+
_log_file = _log_dir / f"hooks-{datetime.now().strftime('%Y-%m-%d')}.log"
|
|
46
|
+
logging.basicConfig(
|
|
47
|
+
level=logging.INFO,
|
|
48
|
+
format='%(asctime)s [subagent_stop] %(name)s - %(levelname)s - %(message)s',
|
|
49
|
+
handlers=[
|
|
50
|
+
logging.FileHandler(_log_file),
|
|
51
|
+
]
|
|
52
|
+
)
|
|
53
|
+
logger = logging.getLogger(__name__)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ============================================================================
|
|
57
|
+
# Backward-compatible aliases (tests and e2e import these names)
|
|
58
|
+
# ============================================================================
|
|
59
|
+
|
|
60
|
+
from modules.agents.contract_validator import (
|
|
61
|
+
extract_commands_from_evidence,
|
|
62
|
+
extract_exit_code_from_output,
|
|
63
|
+
parse_contract,
|
|
64
|
+
requires_consolidation_report,
|
|
65
|
+
validate as validate_contract,
|
|
66
|
+
)
|
|
67
|
+
from modules.agents.response_contract import (
|
|
68
|
+
save_validation_result,
|
|
69
|
+
validate_response_contract,
|
|
70
|
+
resolve_agent_id,
|
|
71
|
+
)
|
|
72
|
+
from modules.agents.task_info_builder import build_task_info_from_hook_data
|
|
73
|
+
from modules.agents.transcript_reader import read_transcript
|
|
74
|
+
from modules.audit.workflow_auditor import audit as audit_workflow, signal_gaia_analysis
|
|
75
|
+
from modules.audit.workflow_recorder import record as record_workflow
|
|
76
|
+
from modules.context.context_writer import process_context_updates
|
|
77
|
+
from modules.memory.episode_writer import write as write_episode
|
|
78
|
+
from modules.security.approval_cleanup import cleanup as cleanup_approval
|
|
79
|
+
from modules.session.session_manager import get_or_create_session_id
|
|
80
|
+
|
|
81
|
+
_extract_commands_from_evidence = extract_commands_from_evidence
|
|
82
|
+
_extract_exit_code_from_output = extract_exit_code_from_output
|
|
83
|
+
_read_transcript = read_transcript
|
|
84
|
+
_process_context_updates = process_context_updates
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _build_task_info_from_hook_data(
|
|
88
|
+
hook_data: Dict[str, Any],
|
|
89
|
+
agent_output: str = "",
|
|
90
|
+
) -> Dict[str, Any]:
|
|
91
|
+
"""Backward-compatible wrapper for build_task_info_from_hook_data."""
|
|
92
|
+
return build_task_info_from_hook_data(hook_data, agent_output)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# ============================================================================
|
|
96
|
+
# Backward-compatible main processing chain (used by tests directly)
|
|
97
|
+
# ============================================================================
|
|
98
|
+
|
|
99
|
+
def subagent_stop_hook(task_info, agent_output):
|
|
100
|
+
"""
|
|
101
|
+
Main subagent stop hook - validates contracts, captures metrics, detects anomalies, stores episodes.
|
|
102
|
+
|
|
103
|
+
This is the backward-compatible entry point. The adapter calls the same
|
|
104
|
+
modules internally.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
task_info: Task information including ID, description, agent, etc.
|
|
108
|
+
agent_output: Complete output from agent execution
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Success confirmation with metrics info, or contract_rejected dict on validation failure.
|
|
112
|
+
"""
|
|
113
|
+
try:
|
|
114
|
+
from datetime import datetime as _dt
|
|
115
|
+
session_id = get_or_create_session_id()
|
|
116
|
+
agent_type = task_info.get("agent", "unknown")
|
|
117
|
+
|
|
118
|
+
parsed_contract = parse_contract(agent_output)
|
|
119
|
+
|
|
120
|
+
contract_result = validate_contract(agent_output, task_info)
|
|
121
|
+
if not contract_result.is_valid:
|
|
122
|
+
logger.warning(
|
|
123
|
+
"Contract validation failed for %s: %s",
|
|
124
|
+
agent_type, contract_result.error_message,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
cleanup_approval(agent_type)
|
|
128
|
+
|
|
129
|
+
# Consume all confirmed grants -- subagent session is over
|
|
130
|
+
try:
|
|
131
|
+
from modules.security.approval_grants import consume_session_grants
|
|
132
|
+
consume_session_grants(session_id)
|
|
133
|
+
except Exception:
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
commands_executed = extract_commands_from_evidence(agent_output)
|
|
137
|
+
context_update_result = process_context_updates(agent_output, task_info)
|
|
138
|
+
|
|
139
|
+
session_context = {
|
|
140
|
+
"timestamp": _dt.now().isoformat(),
|
|
141
|
+
"session_id": session_id,
|
|
142
|
+
"task_id": task_info.get("task_id", "unknown"),
|
|
143
|
+
"agent_id": task_info.get("agent_id", "unknown"),
|
|
144
|
+
"agent": agent_type,
|
|
145
|
+
}
|
|
146
|
+
workflow_metrics = record_workflow(
|
|
147
|
+
task_info,
|
|
148
|
+
agent_output,
|
|
149
|
+
session_context,
|
|
150
|
+
commands_executed=commands_executed,
|
|
151
|
+
context_update_result=context_update_result,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
response_contract = validate_response_contract(
|
|
155
|
+
agent_output,
|
|
156
|
+
task_agent_id=resolve_agent_id(task_info),
|
|
157
|
+
consolidation_required=requires_consolidation_report(task_info),
|
|
158
|
+
parsed_contract=parsed_contract,
|
|
159
|
+
)
|
|
160
|
+
save_validation_result(task_info, response_contract)
|
|
161
|
+
|
|
162
|
+
anomalies = audit_workflow(
|
|
163
|
+
workflow_metrics,
|
|
164
|
+
agent_output,
|
|
165
|
+
task_info,
|
|
166
|
+
rejected_sections=(context_update_result or {}).get("rejected", []),
|
|
167
|
+
)
|
|
168
|
+
if not response_contract.valid:
|
|
169
|
+
missing = ", ".join(response_contract.missing) or "none"
|
|
170
|
+
invalid = ", ".join(response_contract.invalid) or "none"
|
|
171
|
+
anomalies.append({
|
|
172
|
+
"type": "response_contract_violation",
|
|
173
|
+
"severity": "critical",
|
|
174
|
+
"message": (
|
|
175
|
+
f"Agent response contract invalid for {task_info.get('agent', 'unknown')}: "
|
|
176
|
+
f"missing=[{missing}] invalid=[{invalid}]"
|
|
177
|
+
),
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
if anomalies:
|
|
181
|
+
logger.warning(f"{len(anomalies)} anomalies detected in workflow")
|
|
182
|
+
signal_gaia_analysis(anomalies, workflow_metrics)
|
|
183
|
+
|
|
184
|
+
workflow_metrics["anomalies_detected"] = len(anomalies)
|
|
185
|
+
workflow_metrics["anomaly_types"] = [a.get("type", "") for a in anomalies]
|
|
186
|
+
|
|
187
|
+
episode_id = write_episode(
|
|
188
|
+
workflow_metrics,
|
|
189
|
+
anomalies=anomalies if anomalies else None,
|
|
190
|
+
commands_executed=commands_executed,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
contract_attempts = 0
|
|
194
|
+
if not response_contract.valid:
|
|
195
|
+
try:
|
|
196
|
+
repair_data = response_contract.to_dict()
|
|
197
|
+
contract_attempts = int(repair_data.get("repair_attempts", 0))
|
|
198
|
+
except Exception:
|
|
199
|
+
contract_attempts = 0
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
"success": True,
|
|
203
|
+
"session_id": session_id,
|
|
204
|
+
"status": "metrics_captured",
|
|
205
|
+
"metrics_captured": True,
|
|
206
|
+
"anomalies_detected": len(anomalies) if anomalies else 0,
|
|
207
|
+
"episode_id": episode_id,
|
|
208
|
+
"context_updated": context_update_result.get("updated", False) if context_update_result else False,
|
|
209
|
+
"response_contract": response_contract.to_dict(),
|
|
210
|
+
"contract_validated": contract_result.is_valid,
|
|
211
|
+
"contract_attempts": contract_attempts,
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
except Exception as e:
|
|
215
|
+
logger.error(f"Error in subagent_stop_hook: {e}", exc_info=True)
|
|
216
|
+
return {
|
|
217
|
+
"success": False,
|
|
218
|
+
"error": str(e),
|
|
219
|
+
"status": "partial_update"
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
# ============================================================================
|
|
224
|
+
# Thin gate handler (stdin mode)
|
|
225
|
+
# ============================================================================
|
|
226
|
+
|
|
227
|
+
def _handle_subagent_stop(event) -> None:
|
|
228
|
+
"""Process a SubagentStop event.
|
|
229
|
+
|
|
230
|
+
Delegates all business logic to the adapter.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
event: Parsed HookEvent from the adapter layer.
|
|
234
|
+
"""
|
|
235
|
+
adapter = ClaudeCodeAdapter()
|
|
236
|
+
response = adapter.adapt_subagent_stop(event)
|
|
237
|
+
|
|
238
|
+
if response.exit_code == 2:
|
|
239
|
+
error_msg = response.output.get("contract_rejection_reason", response.output.get("error", "unknown")) if isinstance(response.output, dict) else str(response.output)
|
|
240
|
+
print(
|
|
241
|
+
f"HOOK ERROR: Contract rejected: {error_msg}",
|
|
242
|
+
file=sys.stderr,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
print(json.dumps(response.output))
|
|
246
|
+
sys.exit(response.exit_code)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# ============================================================================
|
|
250
|
+
# CLI interface
|
|
251
|
+
# ============================================================================
|
|
252
|
+
|
|
253
|
+
def main():
|
|
254
|
+
"""CLI interface for testing metrics capture."""
|
|
255
|
+
if len(sys.argv) < 2:
|
|
256
|
+
print("Usage: python subagent_stop.py --test")
|
|
257
|
+
sys.exit(1)
|
|
258
|
+
|
|
259
|
+
if sys.argv[1] == "--test":
|
|
260
|
+
test_task_info = {
|
|
261
|
+
"task_id": "T006",
|
|
262
|
+
"description": "Terraform plan for infrastructure",
|
|
263
|
+
"agent": "terraform-architect",
|
|
264
|
+
"tier": "T1",
|
|
265
|
+
"tags": ["#terraform", "#infrastructure"],
|
|
266
|
+
}
|
|
267
|
+
test_output = (
|
|
268
|
+
"# Terraform Architect Execution Log\n\n"
|
|
269
|
+
"## Task: T006 - Terraform plan for infrastructure\n\n"
|
|
270
|
+
"### Results:\n"
|
|
271
|
+
"- Configuration validated successfully\n"
|
|
272
|
+
"- Plan generated with 12 resources\n"
|
|
273
|
+
"- Duration: 45000 ms\n"
|
|
274
|
+
)
|
|
275
|
+
result = subagent_stop_hook(test_task_info, test_output)
|
|
276
|
+
if result["success"]:
|
|
277
|
+
print("Test completed successfully!")
|
|
278
|
+
print(f"Session ID: {result['session_id']}")
|
|
279
|
+
print(f"Anomalies: {result['anomalies_detected']}")
|
|
280
|
+
print(f"Episode ID: {result.get('episode_id', 'none')}")
|
|
281
|
+
else:
|
|
282
|
+
print(f"Test failed: {result.get('error', 'Unknown error')}")
|
|
283
|
+
else:
|
|
284
|
+
print("Unknown command. Use --test to run test.")
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
# ============================================================================
|
|
288
|
+
# STDIN HANDLER (Claude Code integration)
|
|
289
|
+
# ============================================================================
|
|
290
|
+
|
|
291
|
+
if __name__ == "__main__":
|
|
292
|
+
if len(sys.argv) > 1:
|
|
293
|
+
main()
|
|
294
|
+
else:
|
|
295
|
+
run_hook(_handle_subagent_stop, hook_name="subagent_stop")
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
TaskCompleted hook for Claude Code Agent System.
|
|
4
|
+
|
|
5
|
+
Fires when a task is marked complete. Verifies that completion criteria are
|
|
6
|
+
met before allowing the task to close. For MVP: logs the event and allows
|
|
7
|
+
completion (passthrough). Quality checks will be wired in a future iteration.
|
|
8
|
+
|
|
9
|
+
Architecture:
|
|
10
|
+
- Uses adapter layer to parse TaskCompleted event
|
|
11
|
+
- Calls adapter.adapt_task_completed() for criteria verification
|
|
12
|
+
- Returns verification result via adapter format_verification_response()
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import sys
|
|
16
|
+
import json
|
|
17
|
+
import logging
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
22
|
+
|
|
23
|
+
from adapters.claude_code import ClaudeCodeAdapter
|
|
24
|
+
from modules.core.hook_entry import run_hook
|
|
25
|
+
from modules.core.paths import get_logs_dir
|
|
26
|
+
|
|
27
|
+
# Configure logging
|
|
28
|
+
_log_file = get_logs_dir() / f"hooks-{datetime.now().strftime('%Y-%m-%d')}.log"
|
|
29
|
+
logging.basicConfig(
|
|
30
|
+
level=logging.INFO,
|
|
31
|
+
format='%(asctime)s [task_completed] %(name)s - %(levelname)s - %(message)s',
|
|
32
|
+
handlers=[logging.FileHandler(_log_file)],
|
|
33
|
+
)
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _handle_task_completed(event) -> None:
|
|
38
|
+
"""Process a TaskCompleted event.
|
|
39
|
+
|
|
40
|
+
Checks whether task completion criteria are met.
|
|
41
|
+
For MVP, always allows completion.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
event: Parsed HookEvent from the adapter layer.
|
|
45
|
+
"""
|
|
46
|
+
adapter = ClaudeCodeAdapter()
|
|
47
|
+
|
|
48
|
+
# Parse task completed event via adapter
|
|
49
|
+
verification_result = adapter.adapt_task_completed(event.payload)
|
|
50
|
+
task_id = event.payload.get("task_id", "unknown")
|
|
51
|
+
|
|
52
|
+
logger.info(
|
|
53
|
+
"TaskCompleted: task_id=%s, criteria_met=%s, block=%s",
|
|
54
|
+
task_id,
|
|
55
|
+
verification_result.criteria_met,
|
|
56
|
+
verification_result.block_completion,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Format and output verification response
|
|
60
|
+
response = adapter.format_verification_response(verification_result)
|
|
61
|
+
print(json.dumps(response.output))
|
|
62
|
+
sys.exit(0)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# ============================================================================
|
|
66
|
+
# STDIN HANDLER (Claude Code integration)
|
|
67
|
+
# ============================================================================
|
|
68
|
+
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
run_hook(_handle_task_completed, hook_name="task_completed")
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""UserPromptSubmit hook — injects routing recommendations, first-run welcome, and agentic-loop resume context."""
|
|
3
|
+
|
|
4
|
+
import sys
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
11
|
+
|
|
12
|
+
from modules.core.paths import get_logs_dir
|
|
13
|
+
from modules.core.stdin import has_stdin_data
|
|
14
|
+
from modules.core.plugin_setup import run_first_time_setup
|
|
15
|
+
from modules.core.plugin_mode import get_plugin_mode
|
|
16
|
+
|
|
17
|
+
# Configure logging — file only, no stderr
|
|
18
|
+
_log_file = get_logs_dir() / f"hooks-{datetime.now().strftime('%Y-%m-%d')}.log"
|
|
19
|
+
logging.basicConfig(
|
|
20
|
+
level=logging.INFO,
|
|
21
|
+
format='%(asctime)s [user_prompt_submit] %(name)s - %(levelname)s - %(message)s',
|
|
22
|
+
handlers=[logging.FileHandler(_log_file)],
|
|
23
|
+
)
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _extract_user_prompt(raw_input: str) -> str:
|
|
28
|
+
"""Extract user prompt text from stdin event.
|
|
29
|
+
|
|
30
|
+
The UserPromptSubmit event is JSON with the user's message.
|
|
31
|
+
Try known field names; return empty string if extraction fails.
|
|
32
|
+
"""
|
|
33
|
+
try:
|
|
34
|
+
event = json.loads(raw_input)
|
|
35
|
+
# Try known field names from Claude Code hook events
|
|
36
|
+
for field in ("user_message", "prompt", "message", "content"):
|
|
37
|
+
if field in event and isinstance(event[field], str):
|
|
38
|
+
return event[field]
|
|
39
|
+
# Check nested hookEventInput
|
|
40
|
+
hook_input = event.get("hookEventInput", {})
|
|
41
|
+
if isinstance(hook_input, dict):
|
|
42
|
+
for field in ("user_message", "prompt", "message", "content"):
|
|
43
|
+
if field in hook_input and isinstance(hook_input[field], str):
|
|
44
|
+
return hook_input[field]
|
|
45
|
+
except (json.JSONDecodeError, TypeError, AttributeError):
|
|
46
|
+
pass
|
|
47
|
+
return ""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _build_routing_recommendation(prompt_text: str) -> str:
|
|
51
|
+
"""Run surface classification and format as a routing recommendation block.
|
|
52
|
+
|
|
53
|
+
Returns empty string if classification fails or produces no active surfaces.
|
|
54
|
+
This is advisory — never raises exceptions.
|
|
55
|
+
"""
|
|
56
|
+
try:
|
|
57
|
+
# Import surface_router from tools/context
|
|
58
|
+
tools_dir = Path(__file__).resolve().parent.parent / "tools" / "context"
|
|
59
|
+
if str(tools_dir) not in sys.path:
|
|
60
|
+
sys.path.insert(0, str(tools_dir))
|
|
61
|
+
|
|
62
|
+
from surface_router import classify_surfaces
|
|
63
|
+
|
|
64
|
+
routing = classify_surfaces(prompt_text)
|
|
65
|
+
|
|
66
|
+
active_surfaces = routing.get("active_surfaces", [])
|
|
67
|
+
if not active_surfaces:
|
|
68
|
+
logger.info("Surface routing: no active surfaces for prompt")
|
|
69
|
+
return ""
|
|
70
|
+
|
|
71
|
+
agents = routing.get("recommended_agents", [])
|
|
72
|
+
dispatch_mode = routing.get("dispatch_mode", "single_surface")
|
|
73
|
+
confidence = routing.get("confidence", 0.0)
|
|
74
|
+
matched_signals = routing.get("matched_signals", {})
|
|
75
|
+
|
|
76
|
+
# Flatten matched signals into a single list for display
|
|
77
|
+
all_signals = []
|
|
78
|
+
for surface_signals in matched_signals.values():
|
|
79
|
+
all_signals.extend(surface_signals)
|
|
80
|
+
|
|
81
|
+
lines = [
|
|
82
|
+
"\n\n## Surface Routing Recommendation",
|
|
83
|
+
f"- Recommended agents: {agents}",
|
|
84
|
+
f"- Dispatch mode: {dispatch_mode}",
|
|
85
|
+
f"- Confidence: {confidence}",
|
|
86
|
+
f"- Matched signals: {json.dumps(all_signals)}",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
logger.info(
|
|
90
|
+
"Surface routing: agents=%s mode=%s confidence=%.2f signals=%s",
|
|
91
|
+
agents, dispatch_mode, confidence, all_signals,
|
|
92
|
+
)
|
|
93
|
+
return "\n".join(lines)
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.warning("Surface routing failed (advisory, skipping): %s", e)
|
|
97
|
+
return ""
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _build_welcome(mode: str) -> str:
|
|
101
|
+
"""Build first-run welcome message for the user.
|
|
102
|
+
|
|
103
|
+
This message is injected as additionalContext so Claude receives it,
|
|
104
|
+
not the user directly. The framing explains WHY the user needs to
|
|
105
|
+
know — Claude should naturally relay it because it is actionable
|
|
106
|
+
and the user cannot use the plugin fully without restarting.
|
|
107
|
+
"""
|
|
108
|
+
plugin_name = f"GAIA {'Ops' if mode == 'ops' else 'Security'}"
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
f"{plugin_name} was just installed for the first time in this project. "
|
|
112
|
+
f"The plugin detected the installation and configured security permissions, "
|
|
113
|
+
f"but these permissions only take effect after restarting Claude Code. "
|
|
114
|
+
f"Until the user closes this session and reopens Claude Code, "
|
|
115
|
+
f"{plugin_name} cannot protect their commands — destructive operations "
|
|
116
|
+
f"will not be blocked and mutative operations will not require approval. "
|
|
117
|
+
f"The user needs to know this because they just installed {plugin_name} "
|
|
118
|
+
f"expecting it to work, but it will not be active until they restart. "
|
|
119
|
+
f"Tell the user that {plugin_name} is installed, that they need to close "
|
|
120
|
+
f"and reopen Claude Code to activate it, and that until they do, "
|
|
121
|
+
f"security protections are not active."
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _build_pending_context() -> str:
|
|
126
|
+
"""Scan for pending approvals and format as actionable context.
|
|
127
|
+
|
|
128
|
+
Returns an [ACTIONABLE]-framed summary if pending approvals exist,
|
|
129
|
+
or empty string if none found. Includes cross-session fallback:
|
|
130
|
+
scans current session first, then all sessions if empty.
|
|
131
|
+
|
|
132
|
+
Fully fail-safe — never raises exceptions.
|
|
133
|
+
"""
|
|
134
|
+
try:
|
|
135
|
+
from modules.session.pending_scanner import scan_pending_approvals, format_pending_summary
|
|
136
|
+
from modules.core.paths import get_plugin_data_dir
|
|
137
|
+
from modules.core.state import get_session_id
|
|
138
|
+
|
|
139
|
+
approvals_dir = get_plugin_data_dir() / "cache" / "approvals"
|
|
140
|
+
session_id = get_session_id()
|
|
141
|
+
|
|
142
|
+
# Current session first
|
|
143
|
+
pendings = scan_pending_approvals(
|
|
144
|
+
approvals_dir, session_id=session_id, current_session_id=session_id
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# Cross-session fallback: scan all sessions if current has none.
|
|
148
|
+
# exclude_live_sessions=True prevents pendings from parallel live
|
|
149
|
+
# sessions from appearing as "[session anterior]" injections.
|
|
150
|
+
if not pendings:
|
|
151
|
+
pendings = scan_pending_approvals(
|
|
152
|
+
approvals_dir,
|
|
153
|
+
current_session_id=session_id,
|
|
154
|
+
exclude_live_sessions=True,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
if not pendings:
|
|
158
|
+
return ""
|
|
159
|
+
|
|
160
|
+
summary = format_pending_summary(pendings)
|
|
161
|
+
logger.info("Pending context: %d approvals found", len(pendings))
|
|
162
|
+
return (
|
|
163
|
+
"[ACTIONABLE] Pending approvals require your attention before "
|
|
164
|
+
"routing this request.\n\n" + summary
|
|
165
|
+
)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
logger.debug("Pending context scan skipped (non-fatal): %s", e)
|
|
168
|
+
return ""
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
if __name__ == "__main__":
|
|
172
|
+
if not has_stdin_data():
|
|
173
|
+
sys.exit(0)
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
raw_input = sys.stdin.read()
|
|
177
|
+
|
|
178
|
+
# Check first-run BEFORE setup (SessionStart does setup with
|
|
179
|
+
# mark_done=False so the marker doesn't exist yet on first run).
|
|
180
|
+
from modules.core.plugin_setup import is_first_run, mark_initialized
|
|
181
|
+
first_run = is_first_run()
|
|
182
|
+
|
|
183
|
+
# Ensure registry + permissions exist (idempotent, no mark).
|
|
184
|
+
setup_msg = run_first_time_setup(mark_done=False)
|
|
185
|
+
mode = get_plugin_mode()
|
|
186
|
+
|
|
187
|
+
# Build additionalContext: welcome + agentic-loop + routing.
|
|
188
|
+
# Identity now lives in agents/gaia-orchestrator.md (agent definition).
|
|
189
|
+
context_parts = []
|
|
190
|
+
|
|
191
|
+
# First-time welcome: the marker does not exist yet because
|
|
192
|
+
# neither SessionStart nor this call marked it.
|
|
193
|
+
if first_run:
|
|
194
|
+
welcome = _build_welcome(mode)
|
|
195
|
+
context_parts.append(welcome)
|
|
196
|
+
mark_initialized() # Mark AFTER building the welcome
|
|
197
|
+
logger.info("First-run welcome prepended for %s mode", mode)
|
|
198
|
+
|
|
199
|
+
# Detect active agentic-loop and inject resume context (ops mode only).
|
|
200
|
+
# Lightweight: checks file existence + small JSON read, fully fail-safe.
|
|
201
|
+
if mode == "ops":
|
|
202
|
+
try:
|
|
203
|
+
from modules.context.agentic_loop_detector import build_resume_context
|
|
204
|
+
loop_context = build_resume_context()
|
|
205
|
+
if loop_context:
|
|
206
|
+
context_parts.append(loop_context)
|
|
207
|
+
logger.info("Agentic loop resume context injected")
|
|
208
|
+
except Exception as e:
|
|
209
|
+
logger.debug("Agentic loop detection skipped (non-fatal): %s", e)
|
|
210
|
+
|
|
211
|
+
# Inject pending approval context (ops mode only, before routing).
|
|
212
|
+
if mode == "ops":
|
|
213
|
+
pending_block = _build_pending_context()
|
|
214
|
+
if pending_block:
|
|
215
|
+
context_parts.append(pending_block)
|
|
216
|
+
logger.info("Pending approval context injected")
|
|
217
|
+
|
|
218
|
+
# Append deterministic surface routing recommendation (ops mode only)
|
|
219
|
+
if mode == "ops":
|
|
220
|
+
prompt_text = _extract_user_prompt(raw_input)
|
|
221
|
+
|
|
222
|
+
# NOTE: Approval activation moved to ElicitationResult hook.
|
|
223
|
+
# AskUserQuestion responses trigger ElicitationResult, not
|
|
224
|
+
# UserPromptSubmit, so approval detection lives there now.
|
|
225
|
+
|
|
226
|
+
if prompt_text:
|
|
227
|
+
routing_block = _build_routing_recommendation(prompt_text)
|
|
228
|
+
if routing_block:
|
|
229
|
+
context_parts.append(routing_block)
|
|
230
|
+
else:
|
|
231
|
+
logger.info("Could not extract user prompt from stdin, skipping routing")
|
|
232
|
+
|
|
233
|
+
additional_context = "\n\n".join(context_parts)
|
|
234
|
+
logger.info("Context injected: %s mode (%d chars)", mode, len(additional_context))
|
|
235
|
+
|
|
236
|
+
print(json.dumps({
|
|
237
|
+
"hookSpecificOutput": {
|
|
238
|
+
"hookEventName": "UserPromptSubmit",
|
|
239
|
+
"additionalContext": additional_context,
|
|
240
|
+
}
|
|
241
|
+
}))
|
|
242
|
+
sys.exit(0)
|
|
243
|
+
|
|
244
|
+
except Exception as e:
|
|
245
|
+
logger.error("Error in user_prompt_submit: %s", e, exc_info=True)
|
|
246
|
+
sys.exit(0)
|
package/index.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jaguilar87/gaia
|
|
3
|
+
*
|
|
4
|
+
* Multi-agent orchestration system for Claude Code - DevOps automation toolkit
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* import { getAgentPath, getToolPath, getConfigPath } from '@jaguilar87/gaia';
|
|
8
|
+
* const agentPath = getAgentPath('gitops-operator');
|
|
9
|
+
* const toolPath = getToolPath('context_provider.py');
|
|
10
|
+
* const configPath = getConfigPath('git_standards.json');
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { fileURLToPath } from 'url';
|
|
14
|
+
import { dirname, join } from 'path';
|
|
15
|
+
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = dirname(__filename);
|
|
18
|
+
|
|
19
|
+
export const PACKAGE_ROOT = __dirname;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get absolute path to an agent definition
|
|
23
|
+
* @param {string} agentName - Name of the agent (e.g., 'gitops-operator')
|
|
24
|
+
* @returns {string} Absolute path to agent file
|
|
25
|
+
*/
|
|
26
|
+
export function getAgentPath(agentName) {
|
|
27
|
+
return join(PACKAGE_ROOT, 'agents', `${agentName}.md`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get absolute path to a tool
|
|
32
|
+
* @param {string} toolName - Name of the tool (e.g., 'context_provider.py')
|
|
33
|
+
* @returns {string} Absolute path to tool file
|
|
34
|
+
*/
|
|
35
|
+
export function getToolPath(toolName) {
|
|
36
|
+
return join(PACKAGE_ROOT, 'tools', toolName);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get absolute path to a hook
|
|
41
|
+
* @param {string} hookName - Name of the hook (e.g., 'pre-commit')
|
|
42
|
+
* @returns {string} Absolute path to hook file
|
|
43
|
+
*/
|
|
44
|
+
export function getHookPath(hookName) {
|
|
45
|
+
return join(PACKAGE_ROOT, 'hooks', hookName);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get absolute path to a command
|
|
50
|
+
* @param {string} commandName - Name of the command (e.g., 'architect.md')
|
|
51
|
+
* @returns {string} Absolute path to command file
|
|
52
|
+
*/
|
|
53
|
+
export function getCommandPath(commandName) {
|
|
54
|
+
return join(PACKAGE_ROOT, 'commands', commandName);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get absolute path to a template
|
|
59
|
+
* @param {string} templateName - Name of the template (e.g., 'governance.template.md')
|
|
60
|
+
* @returns {string} Absolute path to template file
|
|
61
|
+
*/
|
|
62
|
+
export function getTemplatePath(templateName) {
|
|
63
|
+
return join(PACKAGE_ROOT, 'templates', templateName);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get absolute path to config file
|
|
68
|
+
* @param {string} configName - Name of the config (e.g., 'git_standards.json')
|
|
69
|
+
* @returns {string} Absolute path to config file
|
|
70
|
+
*/
|
|
71
|
+
export function getConfigPath(configName) {
|
|
72
|
+
return join(PACKAGE_ROOT, 'config', configName);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default {
|
|
76
|
+
PACKAGE_ROOT,
|
|
77
|
+
getAgentPath,
|
|
78
|
+
getToolPath,
|
|
79
|
+
getHookPath,
|
|
80
|
+
getCommandPath,
|
|
81
|
+
getTemplatePath,
|
|
82
|
+
getConfigPath
|
|
83
|
+
};
|