@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,296 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Workflow metrics capture and persistence.
|
|
3
|
+
|
|
4
|
+
Renamed from metrics_recorder.py for clarity.
|
|
5
|
+
|
|
6
|
+
Provides:
|
|
7
|
+
- get_workflow_memory_dir(): Resolve workflow memory directory
|
|
8
|
+
- record(): Build metrics dict, write to JSONL
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import logging
|
|
13
|
+
import os
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any, Dict, List, Optional
|
|
17
|
+
|
|
18
|
+
from ..context.context_injector import build_context_telemetry_snapshot
|
|
19
|
+
from ..core.paths import get_plugin_data_dir
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_workflow_memory_dir() -> Path:
|
|
25
|
+
"""
|
|
26
|
+
Get workflow memory directory path.
|
|
27
|
+
|
|
28
|
+
Resolution order:
|
|
29
|
+
1. WORKFLOW_MEMORY_BASE_PATH env var (testing override)
|
|
30
|
+
2. CLAUDE_PLUGIN_DATA / project-context / workflow-episodic-memory
|
|
31
|
+
3. .claude/project-context/workflow-episodic-memory (backward compat)
|
|
32
|
+
"""
|
|
33
|
+
base_path = os.environ.get("WORKFLOW_MEMORY_BASE_PATH")
|
|
34
|
+
if base_path:
|
|
35
|
+
return Path(base_path) / "project-context" / "workflow-episodic-memory"
|
|
36
|
+
return get_plugin_data_dir() / "project-context" / "workflow-episodic-memory"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _append_jsonl(path: Path, payload: Dict[str, Any]) -> None:
|
|
40
|
+
"""Append one JSON record per line."""
|
|
41
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
42
|
+
with open(path, "a") as f:
|
|
43
|
+
f.write(json.dumps(payload) + "\n")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _parse_frontmatter(text: str) -> Dict[str, Any]:
|
|
47
|
+
"""Parse simple markdown frontmatter without external dependencies."""
|
|
48
|
+
if not text.startswith("---"):
|
|
49
|
+
return {}
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
end = text.index("---", 3)
|
|
53
|
+
except ValueError:
|
|
54
|
+
return {}
|
|
55
|
+
|
|
56
|
+
frontmatter = text[3:end]
|
|
57
|
+
result: Dict[str, Any] = {}
|
|
58
|
+
current_key: Optional[str] = None
|
|
59
|
+
current_list: Optional[List[str]] = None
|
|
60
|
+
|
|
61
|
+
for line in frontmatter.splitlines():
|
|
62
|
+
stripped = line.strip()
|
|
63
|
+
if not stripped or stripped.startswith("#"):
|
|
64
|
+
continue
|
|
65
|
+
|
|
66
|
+
if stripped.startswith("- ") and current_key and current_list is not None:
|
|
67
|
+
current_list.append(stripped[2:].strip())
|
|
68
|
+
continue
|
|
69
|
+
|
|
70
|
+
if ":" in stripped:
|
|
71
|
+
if current_key and current_list is not None:
|
|
72
|
+
result[current_key] = current_list
|
|
73
|
+
|
|
74
|
+
key, _, value = stripped.partition(":")
|
|
75
|
+
key = key.strip()
|
|
76
|
+
value = value.strip()
|
|
77
|
+
|
|
78
|
+
if value:
|
|
79
|
+
result[key] = value
|
|
80
|
+
current_key = key
|
|
81
|
+
current_list = None
|
|
82
|
+
else:
|
|
83
|
+
current_key = key
|
|
84
|
+
current_list = []
|
|
85
|
+
|
|
86
|
+
if current_key and current_list is not None:
|
|
87
|
+
result[current_key] = current_list
|
|
88
|
+
|
|
89
|
+
return result
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _parse_tools_field(value: Any) -> List[str]:
|
|
93
|
+
"""Normalize frontmatter tools into a list."""
|
|
94
|
+
if isinstance(value, list):
|
|
95
|
+
return [item for item in value if isinstance(item, str) and item.strip()]
|
|
96
|
+
if isinstance(value, str):
|
|
97
|
+
return [item.strip() for item in value.split(",") if item.strip()]
|
|
98
|
+
return []
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _resolve_agent_file(agent_type: str) -> Optional[Path]:
|
|
102
|
+
"""Resolve the markdown definition for a project agent."""
|
|
103
|
+
if not agent_type:
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
candidates = [
|
|
107
|
+
Path(".claude/agents") / f"{agent_type}.md",
|
|
108
|
+
Path(__file__).resolve().parents[3] / "agents" / f"{agent_type}.md",
|
|
109
|
+
]
|
|
110
|
+
for candidate in candidates:
|
|
111
|
+
if candidate.exists():
|
|
112
|
+
return candidate
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def load_agent_runtime_profile(agent_type: str) -> Dict[str, Any]:
|
|
117
|
+
"""Load runtime-default metadata from an agent definition file."""
|
|
118
|
+
agent_file = _resolve_agent_file(agent_type)
|
|
119
|
+
if not agent_file:
|
|
120
|
+
return {
|
|
121
|
+
"agent": agent_type or "unknown",
|
|
122
|
+
"model": "",
|
|
123
|
+
"tools": [],
|
|
124
|
+
"skills": [],
|
|
125
|
+
"skills_count": 0,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
frontmatter = _parse_frontmatter(agent_file.read_text())
|
|
129
|
+
skills = frontmatter.get("skills", [])
|
|
130
|
+
if not isinstance(skills, list):
|
|
131
|
+
skills = []
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
"agent": agent_type or "unknown",
|
|
135
|
+
"model": frontmatter.get("model", ""),
|
|
136
|
+
"tools": _parse_tools_field(frontmatter.get("tools", [])),
|
|
137
|
+
"skills": skills,
|
|
138
|
+
"skills_count": len(skills),
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def record_agent_skill_snapshot(
|
|
143
|
+
agent_type: str,
|
|
144
|
+
session_context: Optional[Dict[str, Any]] = None,
|
|
145
|
+
task_description: str = "",
|
|
146
|
+
) -> Dict[str, Any]:
|
|
147
|
+
"""Persist a historical snapshot of an agent's runtime defaults."""
|
|
148
|
+
session_context = session_context or {}
|
|
149
|
+
profile = load_agent_runtime_profile(agent_type)
|
|
150
|
+
snapshot = {
|
|
151
|
+
"timestamp": session_context.get("timestamp", datetime.now().isoformat()),
|
|
152
|
+
"session_id": session_context.get("session_id", ""),
|
|
153
|
+
"agent": profile.get("agent", agent_type or "unknown"),
|
|
154
|
+
"task_description": task_description[:200],
|
|
155
|
+
"model": profile.get("model", ""),
|
|
156
|
+
"tools": profile.get("tools", []),
|
|
157
|
+
"skills": profile.get("skills", []),
|
|
158
|
+
"skills_count": profile.get("skills_count", 0),
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
_append_jsonl(get_workflow_memory_dir() / "agent-skills.jsonl", snapshot)
|
|
163
|
+
except Exception as exc:
|
|
164
|
+
logger.debug("Could not persist agent skill snapshot: %s", exc)
|
|
165
|
+
|
|
166
|
+
return snapshot
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def record(
|
|
170
|
+
task_info: Dict[str, Any],
|
|
171
|
+
agent_output: str,
|
|
172
|
+
session_context: Dict[str, Any],
|
|
173
|
+
commands_executed: Optional[List[str]] = None,
|
|
174
|
+
context_update_result: Optional[Dict[str, Any]] = None,
|
|
175
|
+
anchor_hits: Optional[Dict[str, Any]] = None,
|
|
176
|
+
transcript_analysis: Optional[Any] = None,
|
|
177
|
+
compliance_result: Optional[Any] = None,
|
|
178
|
+
) -> Dict[str, Any]:
|
|
179
|
+
"""
|
|
180
|
+
Capture workflow execution metrics for analysis.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
task_info: Task metadata
|
|
184
|
+
agent_output: Output from agent execution
|
|
185
|
+
session_context: Current session context
|
|
186
|
+
commands_executed: List of commands the agent executed.
|
|
187
|
+
context_update_result: Result of context update processing.
|
|
188
|
+
anchor_hits: Context anchor hit data.
|
|
189
|
+
transcript_analysis: Optional TranscriptAnalysis from transcript_analyzer.
|
|
190
|
+
When provided, real token counts and tool metrics are added to the
|
|
191
|
+
metrics dict alongside the existing output_tokens_approx.
|
|
192
|
+
compliance_result: Optional ComplianceScore from transcript_analyzer.
|
|
193
|
+
When provided, compliance_score and compliance_grade are added.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
Dict with duration, exit_code, agent, tier, etc.
|
|
197
|
+
"""
|
|
198
|
+
# Duration cannot be reliably measured from within this hook because
|
|
199
|
+
# it fires only at agent completion (no start timestamp available).
|
|
200
|
+
duration_ms = None
|
|
201
|
+
|
|
202
|
+
# Use exit_code from task_info (derived from AGENT_STATUS block) instead
|
|
203
|
+
# of naive text matching which gives false positives on "No errors found".
|
|
204
|
+
exit_code = task_info.get("exit_code", 0)
|
|
205
|
+
|
|
206
|
+
# Approximate token count: 4 chars per token is a reliable heuristic for LLM output
|
|
207
|
+
output_tokens_approx = len(agent_output) // 4
|
|
208
|
+
|
|
209
|
+
commands_executed = commands_executed or []
|
|
210
|
+
context_update_result = context_update_result or {}
|
|
211
|
+
context_snapshot = build_context_telemetry_snapshot(
|
|
212
|
+
task_info.get("injected_context") or {}
|
|
213
|
+
)
|
|
214
|
+
default_skills_snapshot = load_agent_runtime_profile(task_info.get("agent", "unknown"))
|
|
215
|
+
|
|
216
|
+
metrics = {
|
|
217
|
+
"timestamp": session_context["timestamp"],
|
|
218
|
+
"session_id": session_context["session_id"],
|
|
219
|
+
"task_id": task_info.get("task_id", "unknown"),
|
|
220
|
+
"agent_id": task_info.get("agent_id", "unknown"),
|
|
221
|
+
"agent": task_info.get("agent", "unknown"),
|
|
222
|
+
"tier": task_info.get("tier", "T0"),
|
|
223
|
+
"duration_ms": duration_ms,
|
|
224
|
+
"exit_code": exit_code,
|
|
225
|
+
"plan_status": task_info.get("plan_status", ""),
|
|
226
|
+
"output_length": len(agent_output),
|
|
227
|
+
"output_tokens_approx": output_tokens_approx,
|
|
228
|
+
"tags": task_info.get("tags", []),
|
|
229
|
+
"prompt": task_info.get("description", ""), # Store for episodic
|
|
230
|
+
"commands_executed": commands_executed,
|
|
231
|
+
"commands_executed_count": len(commands_executed),
|
|
232
|
+
"context_snapshot": context_snapshot,
|
|
233
|
+
"context_updated": bool(context_update_result.get("updated", False)),
|
|
234
|
+
"context_sections_updated": context_update_result.get("sections_updated", []),
|
|
235
|
+
"context_rejected_sections": context_update_result.get("rejected", []),
|
|
236
|
+
"default_skills_snapshot": default_skills_snapshot,
|
|
237
|
+
"context_anchor_hits": anchor_hits,
|
|
238
|
+
"context_anchor_hit_rate": anchor_hits.get("hit_rate") if anchor_hits else None,
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# --- Transcript-analysis enrichment (T010) ---
|
|
242
|
+
if transcript_analysis is not None:
|
|
243
|
+
metrics["input_tokens"] = transcript_analysis.input_tokens
|
|
244
|
+
metrics["cache_creation_tokens"] = transcript_analysis.cache_creation_tokens
|
|
245
|
+
metrics["cache_read_tokens"] = transcript_analysis.cache_read_tokens
|
|
246
|
+
metrics["output_tokens_real"] = transcript_analysis.output_tokens
|
|
247
|
+
metrics["duration_ms"] = transcript_analysis.duration_ms
|
|
248
|
+
metrics["tool_call_count"] = transcript_analysis.tool_call_count
|
|
249
|
+
metrics["skills_injected"] = transcript_analysis.skills_injected
|
|
250
|
+
metrics["model_used"] = transcript_analysis.model
|
|
251
|
+
metrics["api_call_count"] = transcript_analysis.api_call_count
|
|
252
|
+
|
|
253
|
+
# --- Compliance enrichment (T010) ---
|
|
254
|
+
if compliance_result is not None:
|
|
255
|
+
metrics["compliance_score"] = compliance_result.total
|
|
256
|
+
metrics["compliance_grade"] = compliance_result.grade
|
|
257
|
+
|
|
258
|
+
run_snapshot = {
|
|
259
|
+
"timestamp": metrics["timestamp"],
|
|
260
|
+
"session_id": metrics["session_id"],
|
|
261
|
+
"task_id": metrics["task_id"],
|
|
262
|
+
"agent_id": metrics["agent_id"],
|
|
263
|
+
"agent": metrics["agent"],
|
|
264
|
+
"tier": metrics["tier"],
|
|
265
|
+
"plan_status": metrics["plan_status"],
|
|
266
|
+
"context_snapshot": context_snapshot,
|
|
267
|
+
"context_updated": metrics["context_updated"],
|
|
268
|
+
"context_sections_updated": metrics["context_sections_updated"],
|
|
269
|
+
"context_rejected_sections": metrics["context_rejected_sections"],
|
|
270
|
+
"default_skills_snapshot": default_skills_snapshot,
|
|
271
|
+
"context_anchor_hits": anchor_hits,
|
|
272
|
+
"context_anchor_hit_rate": anchor_hits.get("hit_rate") if anchor_hits else None,
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
try:
|
|
276
|
+
workflow_memory_dir = get_workflow_memory_dir()
|
|
277
|
+
workflow_memory_dir.mkdir(parents=True, exist_ok=True)
|
|
278
|
+
_append_jsonl(workflow_memory_dir / "run-snapshots.jsonl", run_snapshot)
|
|
279
|
+
except Exception as exc:
|
|
280
|
+
logger.debug("Could not persist run telemetry snapshot: %s", exc)
|
|
281
|
+
|
|
282
|
+
# Save to workflow memory (gated behind env var; default: no write)
|
|
283
|
+
if os.environ.get("GAIA_WRITE_WORKFLOW_METRICS") == "1":
|
|
284
|
+
workflow_memory_dir = get_workflow_memory_dir()
|
|
285
|
+
workflow_memory_dir.mkdir(parents=True, exist_ok=True)
|
|
286
|
+
|
|
287
|
+
metrics_file = workflow_memory_dir / "metrics.jsonl"
|
|
288
|
+
with open(metrics_file, "a") as f:
|
|
289
|
+
f.write(json.dumps(metrics) + "\n")
|
|
290
|
+
|
|
291
|
+
logger.debug(
|
|
292
|
+
"Captured workflow metrics: %s (duration: %sms, exit: %s, commands: %s)",
|
|
293
|
+
metrics["agent"], duration_ms, exit_code, len(commands_executed),
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
return metrics
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Context Management Module
|
|
3
|
+
|
|
4
|
+
This module provides tools for managing context in agent conversations:
|
|
5
|
+
- context_writer: Progressive enrichment of project-context.json via CONTEXT_UPDATE blocks
|
|
6
|
+
- contracts_loader: Load context contracts, detect cloud provider, merge agent permissions
|
|
7
|
+
- context_injector: Core context injection subsystem for project agents
|
|
8
|
+
- context_freshness: Check staleness of project-context.json for SessionStart
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__all__ = []
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Agentic loop state detector.
|
|
2
|
+
|
|
3
|
+
Lightweight, fail-safe detection of an active agentic-loop session in the
|
|
4
|
+
current working directory. Used by UserPromptSubmit and PreCompact hooks to
|
|
5
|
+
inject recovery context when the loop is running.
|
|
6
|
+
|
|
7
|
+
Design constraints:
|
|
8
|
+
- Non-blocking: never raises, returns empty string on failure
|
|
9
|
+
- Lightweight: only file existence + small JSON reads
|
|
10
|
+
- Safe: malformed or missing files are silently skipped
|
|
11
|
+
- Staleness guard: states older than 24 hours are ignored
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import logging
|
|
17
|
+
from datetime import datetime, timezone
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Optional
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
# How old a state file can be before it's considered stale
|
|
24
|
+
STALE_HOURS = 24
|
|
25
|
+
|
|
26
|
+
# Candidate locations to search for loop state, relative to cwd
|
|
27
|
+
_STATE_CANDIDATES = [
|
|
28
|
+
"agentic_loop_state.json",
|
|
29
|
+
"state.json",
|
|
30
|
+
"tests/agentic_loop_state.json",
|
|
31
|
+
"tests/state.json",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _parse_state(path: Path) -> Optional[dict]:
|
|
36
|
+
"""Read and parse the JSON state file. Returns None on any error."""
|
|
37
|
+
try:
|
|
38
|
+
text = path.read_text(encoding="utf-8")
|
|
39
|
+
return json.loads(text)
|
|
40
|
+
except Exception:
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _is_stale(state: dict) -> bool:
|
|
45
|
+
"""Return True if the state's timestamp is older than STALE_HOURS."""
|
|
46
|
+
ts = state.get("timestamp")
|
|
47
|
+
if not ts:
|
|
48
|
+
# No timestamp -- treat as fresh so we don't silently skip real state
|
|
49
|
+
return False
|
|
50
|
+
try:
|
|
51
|
+
ts_clean = ts.replace("Z", "+00:00")
|
|
52
|
+
state_time = datetime.fromisoformat(ts_clean)
|
|
53
|
+
if state_time.tzinfo is None:
|
|
54
|
+
state_time = state_time.replace(tzinfo=timezone.utc)
|
|
55
|
+
now = datetime.now(tz=timezone.utc)
|
|
56
|
+
age_hours = (now - state_time).total_seconds() / 3600
|
|
57
|
+
return age_hours > STALE_HOURS
|
|
58
|
+
except Exception:
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _is_agentic_loop_state(state: dict) -> bool:
|
|
63
|
+
"""Return True if the state dict looks like an agentic-loop state file.
|
|
64
|
+
|
|
65
|
+
Checks for the presence of key fields that distinguish agentic-loop
|
|
66
|
+
state from unrelated state.json files (e.g., Node.js build state).
|
|
67
|
+
"""
|
|
68
|
+
loop_fields = {"eval_command", "metric", "threshold", "iteration"}
|
|
69
|
+
return bool(loop_fields & state.keys())
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def find_active_loop(cwd: Optional[Path] = None) -> Optional[dict]:
|
|
73
|
+
"""Search for an active agentic-loop state file.
|
|
74
|
+
|
|
75
|
+
Returns the parsed state dict if found, active (not terminal status),
|
|
76
|
+
and not stale. Returns None otherwise.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
cwd: Working directory to search. Defaults to Path.cwd().
|
|
80
|
+
"""
|
|
81
|
+
base = cwd or Path.cwd()
|
|
82
|
+
|
|
83
|
+
for candidate in _STATE_CANDIDATES:
|
|
84
|
+
path = base / candidate
|
|
85
|
+
if not path.exists():
|
|
86
|
+
continue
|
|
87
|
+
|
|
88
|
+
state = _parse_state(path)
|
|
89
|
+
if state is None:
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
if not _is_agentic_loop_state(state):
|
|
93
|
+
continue
|
|
94
|
+
|
|
95
|
+
status = state.get("status", "")
|
|
96
|
+
if status in ("complete", "threshold_reached", "max_iterations", "stopped"):
|
|
97
|
+
logger.debug("Agentic loop at %s is terminal (status=%s), skipping", path, status)
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
if _is_stale(state):
|
|
101
|
+
logger.debug("Agentic loop at %s is stale (>%dh), skipping", path, STALE_HOURS)
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
logger.info("Active agentic loop found: %s (status=%s, iter=%s)", path, status, state.get("iteration"))
|
|
105
|
+
return state
|
|
106
|
+
|
|
107
|
+
return None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def build_resume_context(cwd: Optional[Path] = None) -> str:
|
|
111
|
+
"""Build the additionalContext block for an active agentic loop.
|
|
112
|
+
|
|
113
|
+
Returns an empty string if no active loop is found.
|
|
114
|
+
Silently handles all errors.
|
|
115
|
+
"""
|
|
116
|
+
try:
|
|
117
|
+
state = find_active_loop(cwd)
|
|
118
|
+
if state is None:
|
|
119
|
+
return ""
|
|
120
|
+
|
|
121
|
+
iteration = state.get("iteration", "?")
|
|
122
|
+
current = state.get("current", state.get("best", "?"))
|
|
123
|
+
threshold = state.get("threshold", "?")
|
|
124
|
+
metric = state.get("metric", "metric")
|
|
125
|
+
goal = state.get("goal", "")
|
|
126
|
+
|
|
127
|
+
lines = [
|
|
128
|
+
"## Active Agentic Loop",
|
|
129
|
+
]
|
|
130
|
+
if goal:
|
|
131
|
+
lines.append(f"Goal: {goal}")
|
|
132
|
+
lines.extend([
|
|
133
|
+
"You are in an agentic-loop session. Read state.json for your objective and progress.",
|
|
134
|
+
f"Current iteration: {iteration}, {metric}: {current}, target: {threshold}. NEVER STOP until threshold or max_iterations.",
|
|
135
|
+
])
|
|
136
|
+
|
|
137
|
+
return "\n".join(lines)
|
|
138
|
+
|
|
139
|
+
except Exception as e:
|
|
140
|
+
logger.debug("build_resume_context failed (non-fatal): %s", e)
|
|
141
|
+
return ""
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def build_precompact_prompt(cwd: Optional[Path] = None) -> str:
|
|
145
|
+
"""Build the pre-compaction instruction block for an active agentic loop.
|
|
146
|
+
|
|
147
|
+
Returns an empty string if no active loop is found.
|
|
148
|
+
Silently handles all errors.
|
|
149
|
+
"""
|
|
150
|
+
try:
|
|
151
|
+
state = find_active_loop(cwd)
|
|
152
|
+
if state is None:
|
|
153
|
+
return ""
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
"IMPORTANT: You are in an agentic-loop. Before context compaction:\n"
|
|
157
|
+
"1. Write continue.md with: completed work, remaining steps, current iteration, decisions made, next action\n"
|
|
158
|
+
"2. Update state.json with current progress\n"
|
|
159
|
+
"3. Update worklog.md with latest run if not already logged\n"
|
|
160
|
+
"Do this NOW before your context is compacted."
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
except Exception as e:
|
|
164
|
+
logger.debug("build_precompact_prompt failed (non-fatal): %s", e)
|
|
165
|
+
return ""
|