@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,85 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Retroactive transcript analysis: analyze .output files and persist metrics.
|
|
3
|
+
|
|
4
|
+
Reads all .output transcript files from a session's tasks directory,
|
|
5
|
+
runs analyze() and compute_compliance_score() from transcript_analyzer,
|
|
6
|
+
and appends non-empty results as JSON lines to the episodic-memory metrics file.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
from datetime import datetime, timezone
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
# Ensure the hooks package is importable
|
|
15
|
+
PLUGIN_ROOT = Path(__file__).resolve().parent.parent
|
|
16
|
+
sys.path.insert(0, str(PLUGIN_ROOT))
|
|
17
|
+
|
|
18
|
+
from hooks.modules.agents.transcript_analyzer import analyze, compute_compliance_score
|
|
19
|
+
|
|
20
|
+
SESSION_ID = "5da6ec0a-5471-4af9-b301-794748b21f62"
|
|
21
|
+
TASKS_DIR = Path(
|
|
22
|
+
f"/tmp/claude-1000/-home-jaguilar-aaxis-qxo/{SESSION_ID}/tasks"
|
|
23
|
+
)
|
|
24
|
+
METRICS_FILE = Path(
|
|
25
|
+
"/home/jaguilar/aaxis/qxo/.claude/project-context"
|
|
26
|
+
"/workflow-episodic-memory/metrics.jsonl"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def main() -> None:
|
|
31
|
+
if not TASKS_DIR.exists():
|
|
32
|
+
print(f"Tasks directory not found: {TASKS_DIR}")
|
|
33
|
+
sys.exit(1)
|
|
34
|
+
|
|
35
|
+
output_files = sorted(TASKS_DIR.glob("*.output"))
|
|
36
|
+
if not output_files:
|
|
37
|
+
print("No .output files found.")
|
|
38
|
+
sys.exit(0)
|
|
39
|
+
|
|
40
|
+
METRICS_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
41
|
+
|
|
42
|
+
persisted = 0
|
|
43
|
+
|
|
44
|
+
with open(METRICS_FILE, "a") as f:
|
|
45
|
+
for output_path in output_files:
|
|
46
|
+
task_id = output_path.stem # filename without .output
|
|
47
|
+
|
|
48
|
+
analysis = analyze(str(output_path))
|
|
49
|
+
|
|
50
|
+
if analysis.api_call_count == 0:
|
|
51
|
+
continue
|
|
52
|
+
|
|
53
|
+
score = compute_compliance_score(analysis, True, False, 0.5)
|
|
54
|
+
|
|
55
|
+
timestamp = analysis.first_timestamp or datetime.now(
|
|
56
|
+
timezone.utc
|
|
57
|
+
).isoformat()
|
|
58
|
+
|
|
59
|
+
entry = {
|
|
60
|
+
"timestamp": timestamp,
|
|
61
|
+
"session_id": SESSION_ID,
|
|
62
|
+
"task_id": task_id,
|
|
63
|
+
"agent": "retroactive-analysis",
|
|
64
|
+
"source": "transcript_analyzer_retroactive",
|
|
65
|
+
"input_tokens": analysis.input_tokens,
|
|
66
|
+
"cache_creation_tokens": analysis.cache_creation_tokens,
|
|
67
|
+
"cache_read_tokens": analysis.cache_read_tokens,
|
|
68
|
+
"output_tokens": analysis.output_tokens,
|
|
69
|
+
"duration_ms": analysis.duration_ms,
|
|
70
|
+
"tool_call_count": analysis.tool_call_count,
|
|
71
|
+
"skills_injected": analysis.skills_injected,
|
|
72
|
+
"model_used": analysis.model,
|
|
73
|
+
"compliance_score": score.total,
|
|
74
|
+
"compliance_grade": score.grade,
|
|
75
|
+
"api_call_count": analysis.api_call_count,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
f.write(json.dumps(entry, separators=(",", ":")) + "\n")
|
|
79
|
+
persisted += 1
|
|
80
|
+
|
|
81
|
+
print(f"Persisted {persisted} entries to {METRICS_FILE}")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Review tools for pending update management
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Review engine for managing pending context update suggestions.
|
|
2
|
+
|
|
3
|
+
This module provides the review logic for pending update suggestions,
|
|
4
|
+
including listing, approving, rejecting, and viewing statistics of
|
|
5
|
+
updates discovered by agents.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
# Import PendingUpdateStore from the context module
|
|
14
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
15
|
+
from context.pending_updates import PendingUpdateStore
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def review_pending(
|
|
19
|
+
action: str,
|
|
20
|
+
update_id: Optional[str] = None,
|
|
21
|
+
context_path: Optional[Path] = None,
|
|
22
|
+
store: Optional["PendingUpdateStore"] = None
|
|
23
|
+
) -> dict:
|
|
24
|
+
"""Execute a review action on pending updates.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
action: One of "list", "approve", "reject", "stats"
|
|
28
|
+
update_id: Required for approve/reject actions
|
|
29
|
+
context_path: Optional path to project-context.json (for apply)
|
|
30
|
+
store: Optional PendingUpdateStore instance (for testing)
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
dict: Action-specific results
|
|
34
|
+
|
|
35
|
+
Raises:
|
|
36
|
+
ValueError: If action is invalid or required parameters are missing
|
|
37
|
+
"""
|
|
38
|
+
valid_actions = {"list", "approve", "reject", "stats"}
|
|
39
|
+
|
|
40
|
+
if action not in valid_actions:
|
|
41
|
+
raise ValueError(
|
|
42
|
+
f"Invalid action: {action}. Must be one of: {', '.join(sorted(valid_actions))}"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Validate update_id requirement for approve/reject
|
|
46
|
+
if action in {"approve", "reject"} and not update_id:
|
|
47
|
+
raise ValueError(f"update_id is required for {action} action")
|
|
48
|
+
|
|
49
|
+
# Use provided store or create default
|
|
50
|
+
if store is None:
|
|
51
|
+
store = PendingUpdateStore()
|
|
52
|
+
|
|
53
|
+
# Execute action
|
|
54
|
+
if action == "list":
|
|
55
|
+
updates = store.list_pending()
|
|
56
|
+
# Convert dataclass instances to dicts for JSON serialization
|
|
57
|
+
updates_dict = [
|
|
58
|
+
{
|
|
59
|
+
"update_id": u.update_id,
|
|
60
|
+
"category": u.category,
|
|
61
|
+
"target_section": u.target_section,
|
|
62
|
+
"summary": u.summary,
|
|
63
|
+
"confidence": u.confidence,
|
|
64
|
+
"source_agent": u.source_agent,
|
|
65
|
+
"status": u.status,
|
|
66
|
+
"created_at": u.created_at,
|
|
67
|
+
"seen_count": u.seen_count,
|
|
68
|
+
}
|
|
69
|
+
for u in updates
|
|
70
|
+
]
|
|
71
|
+
return {
|
|
72
|
+
"action": "list",
|
|
73
|
+
"updates": updates_dict,
|
|
74
|
+
"count": len(updates_dict)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
elif action == "approve":
|
|
78
|
+
# Approve the update
|
|
79
|
+
store.approve(update_id)
|
|
80
|
+
|
|
81
|
+
# Apply the update to project-context.json
|
|
82
|
+
result = store.apply(update_id, context_path)
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
"action": "approve",
|
|
86
|
+
"update_id": update_id,
|
|
87
|
+
"applied": result.get("success", False),
|
|
88
|
+
"result": result
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
elif action == "reject":
|
|
92
|
+
store.reject(update_id)
|
|
93
|
+
return {
|
|
94
|
+
"action": "reject",
|
|
95
|
+
"update_id": update_id,
|
|
96
|
+
"success": True
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
elif action == "stats":
|
|
100
|
+
statistics = store.get_statistics()
|
|
101
|
+
return {
|
|
102
|
+
"action": "stats",
|
|
103
|
+
"statistics": statistics
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def main():
|
|
108
|
+
"""CLI entry point for review operations."""
|
|
109
|
+
import argparse
|
|
110
|
+
|
|
111
|
+
parser = argparse.ArgumentParser(
|
|
112
|
+
description="Review pending context updates"
|
|
113
|
+
)
|
|
114
|
+
parser.add_argument(
|
|
115
|
+
"action",
|
|
116
|
+
choices=["list", "approve", "reject", "stats"],
|
|
117
|
+
help="Action to perform"
|
|
118
|
+
)
|
|
119
|
+
parser.add_argument(
|
|
120
|
+
"--update-id",
|
|
121
|
+
help="Update ID (required for approve/reject)"
|
|
122
|
+
)
|
|
123
|
+
parser.add_argument(
|
|
124
|
+
"--context-path",
|
|
125
|
+
help="Path to project-context.json"
|
|
126
|
+
)
|
|
127
|
+
parser.add_argument(
|
|
128
|
+
"--json",
|
|
129
|
+
action="store_true",
|
|
130
|
+
help="Output as JSON (default behavior)"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
args = parser.parse_args()
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
# Execute review action
|
|
137
|
+
result = review_pending(
|
|
138
|
+
args.action,
|
|
139
|
+
args.update_id,
|
|
140
|
+
Path(args.context_path) if args.context_path else None
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Output result as JSON
|
|
144
|
+
print(json.dumps(result, indent=2))
|
|
145
|
+
|
|
146
|
+
except Exception as e:
|
|
147
|
+
# Output error as JSON
|
|
148
|
+
error_result = {
|
|
149
|
+
"error": str(e),
|
|
150
|
+
"action": args.action
|
|
151
|
+
}
|
|
152
|
+
print(json.dumps(error_result, indent=2))
|
|
153
|
+
sys.exit(1)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
if __name__ == "__main__":
|
|
157
|
+
main()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Scan Module: Modular project scanner for gaia-ops
|
|
3
|
+
|
|
4
|
+
This module provides a pluggable scanner system that detects project stack,
|
|
5
|
+
infrastructure, git configuration, tools, orchestration, and environment.
|
|
6
|
+
Each scanner is a pure function (filesystem path -> JSON sections) that runs
|
|
7
|
+
independently and in parallel. The system produces an agnostic project-context.json
|
|
8
|
+
schema that works for any project type.
|
|
9
|
+
|
|
10
|
+
Main components:
|
|
11
|
+
- BaseScanner: Abstract base class for scanner modules
|
|
12
|
+
- ScannerRegistry: Auto-discovery registry for scanner modules
|
|
13
|
+
- ScanOrchestrator: Parallel scanner execution and result aggregation
|
|
14
|
+
- ScanConfig: Scanner configuration and tool definitions
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import json as _json
|
|
18
|
+
from pathlib import Path as _Path
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _read_version() -> str:
|
|
22
|
+
"""Read version from package.json (single source of truth)."""
|
|
23
|
+
try:
|
|
24
|
+
pkg_path = _Path(__file__).resolve().parent.parent.parent / "package.json"
|
|
25
|
+
with open(pkg_path) as f:
|
|
26
|
+
return _json.load(f)["version"]
|
|
27
|
+
except Exception:
|
|
28
|
+
return "unknown"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
__version__ = _read_version()
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"__version__",
|
|
35
|
+
]
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Scanner Configuration Module
|
|
3
|
+
|
|
4
|
+
Provides ScanConfig for scanner orchestration settings, ToolCategory enum,
|
|
5
|
+
ToolDefinition dataclass, and the default tool definitions list.
|
|
6
|
+
|
|
7
|
+
Staleness threshold is overridable via GAIA_SCAN_STALENESS_HOURS env var.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import List, Optional
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ToolCategory(Enum):
|
|
19
|
+
"""Tool categories for classification during environment scanning."""
|
|
20
|
+
|
|
21
|
+
KUBERNETES = "kubernetes"
|
|
22
|
+
CLOUD = "cloud"
|
|
23
|
+
IAC = "iac"
|
|
24
|
+
CONTAINER = "container"
|
|
25
|
+
FILE_VIEWER = "file_viewer"
|
|
26
|
+
FILE_SEARCH = "file_search"
|
|
27
|
+
GIT = "git"
|
|
28
|
+
LANGUAGE_RUNTIME = "language_runtime"
|
|
29
|
+
BUILD = "build"
|
|
30
|
+
UTILITY = "utility"
|
|
31
|
+
AI_ASSISTANT = "ai_assistant"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class ToolDefinition:
|
|
36
|
+
"""Definition of a tool to scan for during environment detection.
|
|
37
|
+
|
|
38
|
+
Attributes:
|
|
39
|
+
name: Binary name (e.g., 'kubectl').
|
|
40
|
+
category: Tool category enum value.
|
|
41
|
+
version_flag: Flag to get version (default: '--version').
|
|
42
|
+
version_regex: Regex to extract version from output (None = first line).
|
|
43
|
+
preference_key: If this tool is a preferred alternative, the preference key.
|
|
44
|
+
preference_priority: Higher = more preferred (e.g., bat=10, cat=1).
|
|
45
|
+
extended: If True, only scanned with --full flag (low-value tools).
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
name: str
|
|
49
|
+
category: ToolCategory
|
|
50
|
+
version_flag: str = "--version"
|
|
51
|
+
version_regex: Optional[str] = None
|
|
52
|
+
preference_key: Optional[str] = None
|
|
53
|
+
preference_priority: int = 0
|
|
54
|
+
extended: bool = False
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class ScanConfig:
|
|
59
|
+
"""Configuration for the scan orchestrator.
|
|
60
|
+
|
|
61
|
+
Attributes:
|
|
62
|
+
project_root: Absolute path to the project root directory.
|
|
63
|
+
scanners: List of scanner names to run (empty = all).
|
|
64
|
+
timeout_per_scanner: Timeout in seconds per scanner (default 10).
|
|
65
|
+
parallel: Whether to run scanners in parallel (default True).
|
|
66
|
+
verbose: Print detailed output (default False).
|
|
67
|
+
output_path: Path to write project-context.json (None = default location).
|
|
68
|
+
staleness_hours: Hours before a scan is considered stale (default 24).
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
project_root: Path = field(default_factory=lambda: Path.cwd())
|
|
72
|
+
scanners: List[str] = field(default_factory=list)
|
|
73
|
+
timeout_per_scanner: int = 10
|
|
74
|
+
parallel: bool = True
|
|
75
|
+
verbose: bool = False
|
|
76
|
+
output_path: Optional[Path] = None
|
|
77
|
+
staleness_hours: int = 24
|
|
78
|
+
|
|
79
|
+
def __post_init__(self) -> None:
|
|
80
|
+
"""Apply environment variable overrides after init."""
|
|
81
|
+
env_staleness = os.environ.get("GAIA_SCAN_STALENESS_HOURS")
|
|
82
|
+
if env_staleness is not None:
|
|
83
|
+
try:
|
|
84
|
+
self.staleness_hours = int(env_staleness)
|
|
85
|
+
except ValueError:
|
|
86
|
+
pass # Keep default if env var is not a valid integer
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# Default tool definitions per data-model.md section 5.3
|
|
90
|
+
TOOL_DEFINITIONS: List[ToolDefinition] = [
|
|
91
|
+
# Kubernetes
|
|
92
|
+
ToolDefinition(
|
|
93
|
+
name="kubectl",
|
|
94
|
+
category=ToolCategory.KUBERNETES,
|
|
95
|
+
version_flag="version --client",
|
|
96
|
+
version_regex=r"Client Version:\s*(.+)",
|
|
97
|
+
),
|
|
98
|
+
ToolDefinition(
|
|
99
|
+
name="helm",
|
|
100
|
+
category=ToolCategory.KUBERNETES,
|
|
101
|
+
version_flag="version --short",
|
|
102
|
+
),
|
|
103
|
+
ToolDefinition(name="kustomize", category=ToolCategory.KUBERNETES, extended=True),
|
|
104
|
+
ToolDefinition(name="k9s", category=ToolCategory.KUBERNETES, extended=True),
|
|
105
|
+
ToolDefinition(
|
|
106
|
+
name="stern",
|
|
107
|
+
category=ToolCategory.KUBERNETES,
|
|
108
|
+
preference_key="log_viewer",
|
|
109
|
+
preference_priority=10,
|
|
110
|
+
extended=True,
|
|
111
|
+
),
|
|
112
|
+
ToolDefinition(name="kubens", category=ToolCategory.KUBERNETES, extended=True),
|
|
113
|
+
ToolDefinition(name="kubectx", category=ToolCategory.KUBERNETES, extended=True),
|
|
114
|
+
# Cloud
|
|
115
|
+
ToolDefinition(name="gcloud", category=ToolCategory.CLOUD),
|
|
116
|
+
ToolDefinition(name="aws", category=ToolCategory.CLOUD),
|
|
117
|
+
ToolDefinition(name="az", category=ToolCategory.CLOUD, extended=True),
|
|
118
|
+
# IaC
|
|
119
|
+
ToolDefinition(name="terraform", category=ToolCategory.IAC),
|
|
120
|
+
ToolDefinition(name="terragrunt", category=ToolCategory.IAC),
|
|
121
|
+
ToolDefinition(name="pulumi", category=ToolCategory.IAC, extended=True),
|
|
122
|
+
# Container
|
|
123
|
+
ToolDefinition(
|
|
124
|
+
name="docker",
|
|
125
|
+
category=ToolCategory.CONTAINER,
|
|
126
|
+
preference_key="container_runtime",
|
|
127
|
+
preference_priority=10,
|
|
128
|
+
),
|
|
129
|
+
ToolDefinition(
|
|
130
|
+
name="podman",
|
|
131
|
+
category=ToolCategory.CONTAINER,
|
|
132
|
+
preference_key="container_runtime",
|
|
133
|
+
preference_priority=5,
|
|
134
|
+
extended=True,
|
|
135
|
+
),
|
|
136
|
+
ToolDefinition(
|
|
137
|
+
name="nerdctl",
|
|
138
|
+
category=ToolCategory.CONTAINER,
|
|
139
|
+
preference_key="container_runtime",
|
|
140
|
+
preference_priority=3,
|
|
141
|
+
extended=True,
|
|
142
|
+
),
|
|
143
|
+
# File viewing
|
|
144
|
+
ToolDefinition(
|
|
145
|
+
name="bat",
|
|
146
|
+
category=ToolCategory.FILE_VIEWER,
|
|
147
|
+
preference_key="file_viewer",
|
|
148
|
+
preference_priority=10,
|
|
149
|
+
extended=True,
|
|
150
|
+
),
|
|
151
|
+
# File search
|
|
152
|
+
ToolDefinition(
|
|
153
|
+
name="fd",
|
|
154
|
+
category=ToolCategory.FILE_SEARCH,
|
|
155
|
+
preference_key="file_search",
|
|
156
|
+
preference_priority=10,
|
|
157
|
+
extended=True,
|
|
158
|
+
),
|
|
159
|
+
ToolDefinition(
|
|
160
|
+
name="rg",
|
|
161
|
+
category=ToolCategory.FILE_SEARCH,
|
|
162
|
+
preference_key="content_search",
|
|
163
|
+
preference_priority=10,
|
|
164
|
+
extended=True,
|
|
165
|
+
),
|
|
166
|
+
ToolDefinition(name="fzf", category=ToolCategory.FILE_SEARCH, extended=True),
|
|
167
|
+
# Git
|
|
168
|
+
ToolDefinition(
|
|
169
|
+
name="gh",
|
|
170
|
+
category=ToolCategory.GIT,
|
|
171
|
+
preference_key="git_cli",
|
|
172
|
+
preference_priority=10,
|
|
173
|
+
),
|
|
174
|
+
ToolDefinition(
|
|
175
|
+
name="glab",
|
|
176
|
+
category=ToolCategory.GIT,
|
|
177
|
+
preference_key="git_cli",
|
|
178
|
+
preference_priority=10,
|
|
179
|
+
),
|
|
180
|
+
ToolDefinition(name="git", category=ToolCategory.GIT),
|
|
181
|
+
# Language runtimes
|
|
182
|
+
ToolDefinition(name="python3", category=ToolCategory.LANGUAGE_RUNTIME),
|
|
183
|
+
ToolDefinition(name="node", category=ToolCategory.LANGUAGE_RUNTIME),
|
|
184
|
+
ToolDefinition(name="go", category=ToolCategory.LANGUAGE_RUNTIME),
|
|
185
|
+
ToolDefinition(name="cargo", category=ToolCategory.LANGUAGE_RUNTIME, extended=True),
|
|
186
|
+
ToolDefinition(name="rustc", category=ToolCategory.LANGUAGE_RUNTIME, extended=True),
|
|
187
|
+
ToolDefinition(name="java", category=ToolCategory.LANGUAGE_RUNTIME, extended=True),
|
|
188
|
+
ToolDefinition(name="ruby", category=ToolCategory.LANGUAGE_RUNTIME, extended=True),
|
|
189
|
+
ToolDefinition(name="php", category=ToolCategory.LANGUAGE_RUNTIME, extended=True),
|
|
190
|
+
# Build tools
|
|
191
|
+
ToolDefinition(name="make", category=ToolCategory.BUILD),
|
|
192
|
+
ToolDefinition(name="npm", category=ToolCategory.BUILD),
|
|
193
|
+
ToolDefinition(name="pnpm", category=ToolCategory.BUILD),
|
|
194
|
+
ToolDefinition(name="yarn", category=ToolCategory.BUILD),
|
|
195
|
+
ToolDefinition(name="pip", category=ToolCategory.BUILD),
|
|
196
|
+
ToolDefinition(name="poetry", category=ToolCategory.BUILD, extended=True),
|
|
197
|
+
ToolDefinition(name="gradle", category=ToolCategory.BUILD, extended=True),
|
|
198
|
+
ToolDefinition(
|
|
199
|
+
name="maven", category=ToolCategory.BUILD, version_flag="-version",
|
|
200
|
+
extended=True,
|
|
201
|
+
),
|
|
202
|
+
# Utilities
|
|
203
|
+
ToolDefinition(name="jq", category=ToolCategory.UTILITY),
|
|
204
|
+
ToolDefinition(name="yq", category=ToolCategory.UTILITY),
|
|
205
|
+
ToolDefinition(name="curl", category=ToolCategory.UTILITY, extended=True),
|
|
206
|
+
ToolDefinition(name="wget", category=ToolCategory.UTILITY, extended=True),
|
|
207
|
+
# AI assistants
|
|
208
|
+
ToolDefinition(name="claude", category=ToolCategory.AI_ASSISTANT),
|
|
209
|
+
]
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def load_scan_config(project_root: Path) -> ScanConfig:
|
|
213
|
+
"""Load scan configuration from project-context.json if it exists.
|
|
214
|
+
|
|
215
|
+
Reads metadata.scan_config from the project context file. Falls back
|
|
216
|
+
to defaults if the file does not exist or the section is missing.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
project_root: Absolute path to the project root directory.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
ScanConfig with values from file or defaults.
|
|
223
|
+
"""
|
|
224
|
+
context_path = project_root / ".claude" / "project-context" / "project-context.json"
|
|
225
|
+
|
|
226
|
+
config = ScanConfig(project_root=project_root)
|
|
227
|
+
|
|
228
|
+
if context_path.is_file():
|
|
229
|
+
try:
|
|
230
|
+
with open(context_path, "r") as f:
|
|
231
|
+
data = json.load(f)
|
|
232
|
+
|
|
233
|
+
scan_config = data.get("metadata", {}).get("scan_config", {})
|
|
234
|
+
|
|
235
|
+
if "staleness_hours" in scan_config:
|
|
236
|
+
config.staleness_hours = int(scan_config["staleness_hours"])
|
|
237
|
+
|
|
238
|
+
except (json.JSONDecodeError, ValueError, OSError):
|
|
239
|
+
pass # Use defaults on any error
|
|
240
|
+
|
|
241
|
+
return config
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
DEFAULT_SCAN_CONFIG = ScanConfig()
|
|
245
|
+
|
|
246
|
+
# Path to the context-contracts.json file (relative to the gaia-ops-plugin root)
|
|
247
|
+
CONTRACT_CONFIG_PATH = Path(__file__).parent.parent.parent / "config" / "context-contracts.json"
|