@event4u/agent-config 1.9.1
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/.agent-src/README.md +64 -0
- package/.agent-src/commands/agent-handoff.md +64 -0
- package/.agent-src/commands/agent-status.md +83 -0
- package/.agent-src/commands/agents-audit.md +243 -0
- package/.agent-src/commands/agents-cleanup.md +169 -0
- package/.agent-src/commands/agents-prepare.md +137 -0
- package/.agent-src/commands/analyze-reference-repo.md +191 -0
- package/.agent-src/commands/bug-fix.md +181 -0
- package/.agent-src/commands/bug-investigate.md +175 -0
- package/.agent-src/commands/commit.md +121 -0
- package/.agent-src/commands/compress.md +177 -0
- package/.agent-src/commands/config-agent-settings.md +126 -0
- package/.agent-src/commands/context-create.md +167 -0
- package/.agent-src/commands/context-refactor.md +170 -0
- package/.agent-src/commands/copilot-agents-init.md +150 -0
- package/.agent-src/commands/copilot-agents-optimize.md +251 -0
- package/.agent-src/commands/create-pr-description.md +112 -0
- package/.agent-src/commands/create-pr.md +76 -0
- package/.agent-src/commands/do-and-judge.md +114 -0
- package/.agent-src/commands/do-in-steps.md +84 -0
- package/.agent-src/commands/e2e-heal.md +98 -0
- package/.agent-src/commands/e2e-plan.md +85 -0
- package/.agent-src/commands/estimate-ticket.md +80 -0
- package/.agent-src/commands/feature-dev.md +111 -0
- package/.agent-src/commands/feature-explore.md +180 -0
- package/.agent-src/commands/feature-plan.md +288 -0
- package/.agent-src/commands/feature-refactor.md +181 -0
- package/.agent-src/commands/feature-roadmap.md +184 -0
- package/.agent-src/commands/fix-ci.md +48 -0
- package/.agent-src/commands/fix-portability.md +97 -0
- package/.agent-src/commands/fix-pr-bot-comments.md +146 -0
- package/.agent-src/commands/fix-pr-comments.md +58 -0
- package/.agent-src/commands/fix-pr-developer-comments.md +152 -0
- package/.agent-src/commands/fix-references.md +94 -0
- package/.agent-src/commands/fix-seeder.md +146 -0
- package/.agent-src/commands/implement-ticket.md +133 -0
- package/.agent-src/commands/jira-ticket.md +71 -0
- package/.agent-src/commands/judge.md +86 -0
- package/.agent-src/commands/memory-add.md +130 -0
- package/.agent-src/commands/memory-full.md +97 -0
- package/.agent-src/commands/memory-promote.md +144 -0
- package/.agent-src/commands/mode.md +121 -0
- package/.agent-src/commands/module-create.md +132 -0
- package/.agent-src/commands/module-explore.md +157 -0
- package/.agent-src/commands/optimize-agents.md +139 -0
- package/.agent-src/commands/optimize-augmentignore.md +262 -0
- package/.agent-src/commands/optimize-rtk-filters.md +120 -0
- package/.agent-src/commands/optimize-skills.md +121 -0
- package/.agent-src/commands/override-create.md +97 -0
- package/.agent-src/commands/override-manage.md +96 -0
- package/.agent-src/commands/package-reset.md +154 -0
- package/.agent-src/commands/package-test.md +154 -0
- package/.agent-src/commands/prepare-for-review.md +91 -0
- package/.agent-src/commands/project-analyze.md +300 -0
- package/.agent-src/commands/project-health.md +95 -0
- package/.agent-src/commands/propose-memory.md +108 -0
- package/.agent-src/commands/quality-fix.md +106 -0
- package/.agent-src/commands/refine-ticket.md +81 -0
- package/.agent-src/commands/review-changes.md +130 -0
- package/.agent-src/commands/review-routing.md +111 -0
- package/.agent-src/commands/roadmap-create.md +110 -0
- package/.agent-src/commands/roadmap-execute.md +68 -0
- package/.agent-src/commands/rule-compliance-audit.md +139 -0
- package/.agent-src/commands/tests-create.md +73 -0
- package/.agent-src/commands/tests-execute.md +58 -0
- package/.agent-src/commands/threat-model.md +115 -0
- package/.agent-src/commands/update-form-request-messages.md +189 -0
- package/.agent-src/commands/upstream-contribute.md +171 -0
- package/.agent-src/contexts/augment-infrastructure.md +181 -0
- package/.agent-src/contexts/documentation-hierarchy.md +142 -0
- package/.agent-src/contexts/model-recommendations.md +142 -0
- package/.agent-src/contexts/override-system.md +187 -0
- package/.agent-src/contexts/skills-and-commands.md +154 -0
- package/.agent-src/contexts/subagent-configuration.md +62 -0
- package/.agent-src/guidelines/agent-infra/agent-interaction-and-decision-quality.md +110 -0
- package/.agent-src/guidelines/agent-infra/break-glass-usage.md +113 -0
- package/.agent-src/guidelines/agent-infra/developer-judgment.md +82 -0
- package/.agent-src/guidelines/agent-infra/engineering-memory-data-format.md +117 -0
- package/.agent-src/guidelines/agent-infra/layered-settings.md +158 -0
- package/.agent-src/guidelines/agent-infra/memory-access.md +121 -0
- package/.agent-src/guidelines/agent-infra/naming.md +69 -0
- package/.agent-src/guidelines/agent-infra/output-patterns.md +117 -0
- package/.agent-src/guidelines/agent-infra/review-routing-data-format.md +144 -0
- package/.agent-src/guidelines/agent-infra/role-contracts.md +211 -0
- package/.agent-src/guidelines/agent-infra/role-mode-router.md +89 -0
- package/.agent-src/guidelines/agent-infra/runtime-layer.md +89 -0
- package/.agent-src/guidelines/agent-infra/self-improvement-pipeline.md +135 -0
- package/.agent-src/guidelines/agent-infra/size-and-scope.md +189 -0
- package/.agent-src/guidelines/agent-infra/tool-integration.md +73 -0
- package/.agent-src/guidelines/docs/readme-size-and-splitting.md +153 -0
- package/.agent-src/guidelines/e2e/playwright.md +363 -0
- package/.agent-src/guidelines/php/api-design.md +115 -0
- package/.agent-src/guidelines/php/artisan-commands.md +81 -0
- package/.agent-src/guidelines/php/blade-ui.md +78 -0
- package/.agent-src/guidelines/php/controllers.md +90 -0
- package/.agent-src/guidelines/php/database.md +111 -0
- package/.agent-src/guidelines/php/eloquent.md +208 -0
- package/.agent-src/guidelines/php/flux.md +80 -0
- package/.agent-src/guidelines/php/general.md +191 -0
- package/.agent-src/guidelines/php/git.md +96 -0
- package/.agent-src/guidelines/php/jobs.md +111 -0
- package/.agent-src/guidelines/php/livewire.md +71 -0
- package/.agent-src/guidelines/php/logging.md +79 -0
- package/.agent-src/guidelines/php/naming.md +89 -0
- package/.agent-src/guidelines/php/patterns/dependency-injection.md +57 -0
- package/.agent-src/guidelines/php/patterns/dtos.md +199 -0
- package/.agent-src/guidelines/php/patterns/events.md +67 -0
- package/.agent-src/guidelines/php/patterns/factory.md +53 -0
- package/.agent-src/guidelines/php/patterns/pipelines.md +66 -0
- package/.agent-src/guidelines/php/patterns/policies.md +66 -0
- package/.agent-src/guidelines/php/patterns/repositories.md +122 -0
- package/.agent-src/guidelines/php/patterns/service-layer.md +64 -0
- package/.agent-src/guidelines/php/patterns/strategy.md +69 -0
- package/.agent-src/guidelines/php/patterns.md +28 -0
- package/.agent-src/guidelines/php/performance.md +92 -0
- package/.agent-src/guidelines/php/resources.md +100 -0
- package/.agent-src/guidelines/php/security.md +110 -0
- package/.agent-src/guidelines/php/sql.md +97 -0
- package/.agent-src/guidelines/php/validations.md +119 -0
- package/.agent-src/guidelines/php/websocket.md +100 -0
- package/.agent-src/personas/README.md +104 -0
- package/.agent-src/personas/ai-agent.md +77 -0
- package/.agent-src/personas/critical-challenger.md +73 -0
- package/.agent-src/personas/developer.md +73 -0
- package/.agent-src/personas/product-owner.md +78 -0
- package/.agent-src/personas/qa.md +67 -0
- package/.agent-src/personas/senior-engineer.md +77 -0
- package/.agent-src/personas/stakeholder.md +78 -0
- package/.agent-src/rules/agent-docs.md +61 -0
- package/.agent-src/rules/analysis-skill-routing.md +48 -0
- package/.agent-src/rules/architecture.md +62 -0
- package/.agent-src/rules/artifact-drafting-protocol.md +73 -0
- package/.agent-src/rules/ask-when-uncertain.md +52 -0
- package/.agent-src/rules/augment-portability.md +38 -0
- package/.agent-src/rules/augment-source-of-truth.md +128 -0
- package/.agent-src/rules/capture-learnings.md +89 -0
- package/.agent-src/rules/cli-output-handling.md +94 -0
- package/.agent-src/rules/commit-conventions.md +64 -0
- package/.agent-src/rules/context-hygiene.md +90 -0
- package/.agent-src/rules/docker-commands.md +55 -0
- package/.agent-src/rules/docs-sync.md +79 -0
- package/.agent-src/rules/downstream-changes.md +70 -0
- package/.agent-src/rules/e2e-testing.md +53 -0
- package/.agent-src/rules/guidelines.md +90 -0
- package/.agent-src/rules/improve-before-implement.md +94 -0
- package/.agent-src/rules/language-and-tone.md +104 -0
- package/.agent-src/rules/laravel-translations.md +48 -0
- package/.agent-src/rules/markdown-safe-codeblocks.md +18 -0
- package/.agent-src/rules/minimal-safe-diff.md +87 -0
- package/.agent-src/rules/missing-tool-handling.md +62 -0
- package/.agent-src/rules/model-recommendation.md +70 -0
- package/.agent-src/rules/package-ci-checks.md +80 -0
- package/.agent-src/rules/php-coding.md +63 -0
- package/.agent-src/rules/preservation-guard.md +29 -0
- package/.agent-src/rules/review-routing-awareness.md +125 -0
- package/.agent-src/rules/reviewer-awareness.md +92 -0
- package/.agent-src/rules/roadmap-progress-sync.md +56 -0
- package/.agent-src/rules/role-mode-adherence.md +54 -0
- package/.agent-src/rules/rule-type-governance.md +46 -0
- package/.agent-src/rules/runtime-safety.md +42 -0
- package/.agent-src/rules/scope-control.md +40 -0
- package/.agent-src/rules/security-sensitive-stop.md +77 -0
- package/.agent-src/rules/size-enforcement.md +29 -0
- package/.agent-src/rules/skill-improvement-trigger.md +58 -0
- package/.agent-src/rules/skill-quality.md +110 -0
- package/.agent-src/rules/slash-commands.md +30 -0
- package/.agent-src/rules/think-before-action.md +91 -0
- package/.agent-src/rules/token-efficiency.md +99 -0
- package/.agent-src/rules/tool-safety.md +36 -0
- package/.agent-src/rules/upstream-proposal.md +76 -0
- package/.agent-src/rules/user-interaction.md +79 -0
- package/.agent-src/rules/verify-before-complete.md +120 -0
- package/.agent-src/scripts/scan-seeder-violations.php +145 -0
- package/.agent-src/scripts/update_roadmap_progress.py +244 -0
- package/.agent-src/skills/adversarial-review/SKILL.md +149 -0
- package/.agent-src/skills/agent-docs-writing/SKILL.md +234 -0
- package/.agent-src/skills/analysis-autonomous-mode/SKILL.md +197 -0
- package/.agent-src/skills/analysis-skill-router/SKILL.md +134 -0
- package/.agent-src/skills/api-design/SKILL.md +104 -0
- package/.agent-src/skills/api-endpoint/SKILL.md +185 -0
- package/.agent-src/skills/api-testing/SKILL.md +206 -0
- package/.agent-src/skills/artisan-commands/SKILL.md +78 -0
- package/.agent-src/skills/authz-review/SKILL.md +171 -0
- package/.agent-src/skills/aws-infrastructure/SKILL.md +152 -0
- package/.agent-src/skills/blade-ui/SKILL.md +75 -0
- package/.agent-src/skills/blast-radius-analyzer/SKILL.md +185 -0
- package/.agent-src/skills/bug-analyzer/SKILL.md +256 -0
- package/.agent-src/skills/check-refs/SKILL.md +72 -0
- package/.agent-src/skills/code-refactoring/SKILL.md +200 -0
- package/.agent-src/skills/code-review/SKILL.md +214 -0
- package/.agent-src/skills/command-routing/SKILL.md +96 -0
- package/.agent-src/skills/command-writing/SKILL.md +143 -0
- package/.agent-src/skills/composer-packages/SKILL.md +172 -0
- package/.agent-src/skills/context-authoring/SKILL.md +157 -0
- package/.agent-src/skills/context-document/SKILL.md +153 -0
- package/.agent-src/skills/conventional-commits-writing/SKILL.md +70 -0
- package/.agent-src/skills/copilot-agents-optimization/SKILL.md +220 -0
- package/.agent-src/skills/copilot-config/SKILL.md +203 -0
- package/.agent-src/skills/dashboard-design/SKILL.md +116 -0
- package/.agent-src/skills/data-flow-mapper/SKILL.md +160 -0
- package/.agent-src/skills/database/SKILL.md +91 -0
- package/.agent-src/skills/dependency-upgrade/SKILL.md +204 -0
- package/.agent-src/skills/description-assist/SKILL.md +169 -0
- package/.agent-src/skills/design-review/SKILL.md +228 -0
- package/.agent-src/skills/devcontainer/SKILL.md +121 -0
- package/.agent-src/skills/developer-like-execution/SKILL.md +276 -0
- package/.agent-src/skills/docker/SKILL.md +245 -0
- package/.agent-src/skills/dto-creator/SKILL.md +117 -0
- package/.agent-src/skills/eloquent/SKILL.md +92 -0
- package/.agent-src/skills/eloquent/evals/last-run.json +99 -0
- package/.agent-src/skills/eloquent/evals/triggers.json +16 -0
- package/.agent-src/skills/estimate-ticket/SKILL.md +186 -0
- package/.agent-src/skills/estimate-ticket/evals/output-schema.yml +20 -0
- package/.agent-src/skills/estimate-ticket/evals/triggers.json +18 -0
- package/.agent-src/skills/fe-design/SKILL.md +223 -0
- package/.agent-src/skills/feature-planning/SKILL.md +226 -0
- package/.agent-src/skills/file-editor/SKILL.md +129 -0
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/.agent-src/skills/flux/SKILL.md +64 -0
- package/.agent-src/skills/git-workflow/SKILL.md +102 -0
- package/.agent-src/skills/github-ci/SKILL.md +122 -0
- package/.agent-src/skills/grafana/SKILL.md +168 -0
- package/.agent-src/skills/guideline-writing/SKILL.md +147 -0
- package/.agent-src/skills/jira-integration/SKILL.md +182 -0
- package/.agent-src/skills/jobs-events/SKILL.md +87 -0
- package/.agent-src/skills/judge-bug-hunter/SKILL.md +157 -0
- package/.agent-src/skills/judge-code-quality/SKILL.md +158 -0
- package/.agent-src/skills/judge-security-auditor/SKILL.md +167 -0
- package/.agent-src/skills/judge-test-coverage/SKILL.md +154 -0
- package/.agent-src/skills/laravel/SKILL.md +195 -0
- package/.agent-src/skills/laravel-horizon/SKILL.md +169 -0
- package/.agent-src/skills/laravel-mail/SKILL.md +193 -0
- package/.agent-src/skills/laravel-middleware/SKILL.md +185 -0
- package/.agent-src/skills/laravel-notifications/SKILL.md +168 -0
- package/.agent-src/skills/laravel-pennant/SKILL.md +188 -0
- package/.agent-src/skills/laravel-pulse/SKILL.md +160 -0
- package/.agent-src/skills/laravel-reverb/SKILL.md +205 -0
- package/.agent-src/skills/laravel-scheduling/SKILL.md +167 -0
- package/.agent-src/skills/laravel-validation/SKILL.md +71 -0
- package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +249 -0
- package/.agent-src/skills/lint-skills/SKILL.md +72 -0
- package/.agent-src/skills/livewire/SKILL.md +79 -0
- package/.agent-src/skills/logging-monitoring/SKILL.md +100 -0
- package/.agent-src/skills/mcp/SKILL.md +193 -0
- package/.agent-src/skills/merge-conflicts/SKILL.md +158 -0
- package/.agent-src/skills/migration-creator/SKILL.md +160 -0
- package/.agent-src/skills/module-management/SKILL.md +154 -0
- package/.agent-src/skills/multi-tenancy/SKILL.md +129 -0
- package/.agent-src/skills/openapi/SKILL.md +154 -0
- package/.agent-src/skills/override-management/SKILL.md +186 -0
- package/.agent-src/skills/performance/SKILL.md +69 -0
- package/.agent-src/skills/performance-analysis/SKILL.md +118 -0
- package/.agent-src/skills/pest-testing/SKILL.md +321 -0
- package/.agent-src/skills/php-coder/SKILL.md +78 -0
- package/.agent-src/skills/php-coder/evals/triggers.json +16 -0
- package/.agent-src/skills/php-debugging/SKILL.md +184 -0
- package/.agent-src/skills/php-service/SKILL.md +96 -0
- package/.agent-src/skills/playwright-testing/SKILL.md +244 -0
- package/.agent-src/skills/project-analysis-core/SKILL.md +138 -0
- package/.agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +130 -0
- package/.agent-src/skills/project-analysis-laravel/SKILL.md +119 -0
- package/.agent-src/skills/project-analysis-nextjs/SKILL.md +123 -0
- package/.agent-src/skills/project-analysis-node-express/SKILL.md +111 -0
- package/.agent-src/skills/project-analysis-react/SKILL.md +119 -0
- package/.agent-src/skills/project-analysis-symfony/SKILL.md +111 -0
- package/.agent-src/skills/project-analysis-zend-laminas/SKILL.md +108 -0
- package/.agent-src/skills/project-analyzer/SKILL.md +341 -0
- package/.agent-src/skills/project-docs/SKILL.md +137 -0
- package/.agent-src/skills/quality-tools/SKILL.md +411 -0
- package/.agent-src/skills/readme-reviewer/SKILL.md +187 -0
- package/.agent-src/skills/readme-writing/SKILL.md +142 -0
- package/.agent-src/skills/readme-writing-package/SKILL.md +185 -0
- package/.agent-src/skills/receiving-code-review/SKILL.md +190 -0
- package/.agent-src/skills/refine-ticket/SKILL.md +310 -0
- package/.agent-src/skills/refine-ticket/detection-map.yml +124 -0
- package/.agent-src/skills/refine-ticket/evals/output-schema.yml +16 -0
- package/.agent-src/skills/refine-ticket/evals/triggers.json +16 -0
- package/.agent-src/skills/requesting-code-review/SKILL.md +199 -0
- package/.agent-src/skills/review-routing/SKILL.md +195 -0
- package/.agent-src/skills/roadmap-management/SKILL.md +303 -0
- package/.agent-src/skills/rtk-output-filtering/SKILL.md +184 -0
- package/.agent-src/skills/rule-writing/SKILL.md +148 -0
- package/.agent-src/skills/security/SKILL.md +79 -0
- package/.agent-src/skills/security-audit/SKILL.md +123 -0
- package/.agent-src/skills/sentry-integration/SKILL.md +170 -0
- package/.agent-src/skills/sequential-thinking/SKILL.md +158 -0
- package/.agent-src/skills/skill-improvement-pipeline/SKILL.md +155 -0
- package/.agent-src/skills/skill-management/SKILL.md +121 -0
- package/.agent-src/skills/skill-reviewer/SKILL.md +218 -0
- package/.agent-src/skills/skill-writing/SKILL.md +291 -0
- package/.agent-src/skills/skill-writing/evals/triggers.json +16 -0
- package/.agent-src/skills/sql-writing/SKILL.md +74 -0
- package/.agent-src/skills/subagent-orchestration/SKILL.md +190 -0
- package/.agent-src/skills/systematic-debugging/SKILL.md +244 -0
- package/.agent-src/skills/technical-specification/SKILL.md +185 -0
- package/.agent-src/skills/terraform/SKILL.md +137 -0
- package/.agent-src/skills/terragrunt/SKILL.md +217 -0
- package/.agent-src/skills/test-driven-development/SKILL.md +252 -0
- package/.agent-src/skills/test-performance/SKILL.md +172 -0
- package/.agent-src/skills/threat-modeling/SKILL.md +189 -0
- package/.agent-src/skills/traefik/SKILL.md +319 -0
- package/.agent-src/skills/universal-project-analysis/SKILL.md +179 -0
- package/.agent-src/skills/upstream-contribute/SKILL.md +255 -0
- package/.agent-src/skills/using-git-worktrees/SKILL.md +148 -0
- package/.agent-src/skills/validate-feature-fit/SKILL.md +113 -0
- package/.agent-src/skills/verify-before-complete/SKILL.md +188 -0
- package/.agent-src/skills/websocket/SKILL.md +75 -0
- package/.agent-src/templates/AGENTS.md +146 -0
- package/.agent-src/templates/agent-settings.md +256 -0
- package/.agent-src/templates/agents/.gitattributes.fragment +16 -0
- package/.agent-src/templates/agents/agent-project-settings.example.yml +138 -0
- package/.agent-src/templates/agents/memory/architecture-decisions.example.yml +95 -0
- package/.agent-src/templates/agents/memory/domain-invariants.example.yml +80 -0
- package/.agent-src/templates/agents/memory/historical-patterns.example.yml +82 -0
- package/.agent-src/templates/agents/memory/incident-learnings.example.yml +113 -0
- package/.agent-src/templates/agents/memory/ownership.example.yml +75 -0
- package/.agent-src/templates/agents/memory/product-rules.example.yml +87 -0
- package/.agent-src/templates/agents/proposal.example.md +143 -0
- package/.agent-src/templates/command.md +84 -0
- package/.agent-src/templates/contexts/auth-model.md +59 -0
- package/.agent-src/templates/contexts/data-sensitivity.md +60 -0
- package/.agent-src/templates/contexts/deployment-order.md +72 -0
- package/.agent-src/templates/contexts/observability.md +64 -0
- package/.agent-src/templates/contexts/tenant-boundaries.md +68 -0
- package/.agent-src/templates/contexts.md +116 -0
- package/.agent-src/templates/copilot-instructions.md +115 -0
- package/.agent-src/templates/features.md +125 -0
- package/.agent-src/templates/github-workflows/memory-hygiene.yml +133 -0
- package/.agent-src/templates/github-workflows/pr-risk-review.yml +123 -0
- package/.agent-src/templates/github-workflows/proposal-drift.yml +118 -0
- package/.agent-src/templates/overrides/command.md +24 -0
- package/.agent-src/templates/overrides/guideline.md +21 -0
- package/.agent-src/templates/overrides/rule.md +19 -0
- package/.agent-src/templates/overrides/skill.md +24 -0
- package/.agent-src/templates/overrides/template.md +21 -0
- package/.agent-src/templates/persona.md +99 -0
- package/.agent-src/templates/roadmaps.md +109 -0
- package/.agent-src/templates/scripts/README.md +195 -0
- package/.agent-src/templates/scripts/check_memory.py +283 -0
- package/.agent-src/templates/scripts/check_memory_proposal.py +180 -0
- package/.agent-src/templates/scripts/historical-bug-patterns.example.yml +84 -0
- package/.agent-src/templates/scripts/implement_ticket/__init__.py +57 -0
- package/.agent-src/templates/scripts/implement_ticket/__main__.py +9 -0
- package/.agent-src/templates/scripts/implement_ticket/cli.py +171 -0
- package/.agent-src/templates/scripts/implement_ticket/delivery_state.py +130 -0
- package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +134 -0
- package/.agent-src/templates/scripts/implement_ticket/persona_policy.py +85 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +49 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/analyze.py +98 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/implement.py +145 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/memory.py +136 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/plan.py +175 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/refine.py +140 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/report.py +195 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/test.py +180 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/verify.py +170 -0
- package/.agent-src/templates/scripts/memory_hash.py +75 -0
- package/.agent-src/templates/scripts/memory_lookup.py +216 -0
- package/.agent-src/templates/scripts/memory_report.py +184 -0
- package/.agent-src/templates/scripts/memory_signal.py +167 -0
- package/.agent-src/templates/scripts/memory_status.py +156 -0
- package/.agent-src/templates/scripts/ownership-map.example.yml +87 -0
- package/.agent-src/templates/scripts/pr-risk-config.example.yml +76 -0
- package/.agent-src/templates/scripts/pr_review_routing.py +340 -0
- package/.agent-src/templates/scripts/pr_risk_review.py +211 -0
- package/.agent-src/templates/skill.md +136 -0
- package/.augment-plugin/marketplace.json +32 -0
- package/.augment-plugin/plugin.json +21 -0
- package/.claude-plugin/marketplace.json +119 -0
- package/AGENTS.md +121 -0
- package/CHANGELOG.md +279 -0
- package/CONTRIBUTING.md +176 -0
- package/LICENSE +21 -0
- package/README.md +357 -0
- package/bin/install.php +38 -0
- package/composer.json +29 -0
- package/config/agent-settings.template.yml +96 -0
- package/config/profiles/balanced.ini +10 -0
- package/config/profiles/full.ini +10 -0
- package/config/profiles/minimal.ini +10 -0
- package/docs/architecture.md +144 -0
- package/docs/customization.md +88 -0
- package/docs/development.md +171 -0
- package/docs/getting-started.md +130 -0
- package/docs/github-topics.md +84 -0
- package/docs/installation.md +376 -0
- package/docs/mcp.md +133 -0
- package/docs/quality.md +98 -0
- package/docs/skills-catalog.md +136 -0
- package/docs/troubleshooting.md +167 -0
- package/llms.txt +130 -0
- package/package.json +31 -0
- package/scripts/audit_skill_descriptions.py +168 -0
- package/scripts/check_compression.py +221 -0
- package/scripts/check_memory.py +341 -0
- package/scripts/check_memory_proposal.py +180 -0
- package/scripts/check_portability.py +320 -0
- package/scripts/check_proposal.py +269 -0
- package/scripts/check_references.py +400 -0
- package/scripts/ci_summary.py +131 -0
- package/scripts/compress.py +671 -0
- package/scripts/compress.sh +18 -0
- package/scripts/first-run.sh +109 -0
- package/scripts/generate_catalog.py +116 -0
- package/scripts/install +151 -0
- package/scripts/install-hooks.sh +29 -0
- package/scripts/install.py +487 -0
- package/scripts/install.sh +637 -0
- package/scripts/install_anthropic_key.sh +101 -0
- package/scripts/inventory_frontmatter.py +164 -0
- package/scripts/lint_marketplace.py +142 -0
- package/scripts/lint_regression.py +232 -0
- package/scripts/mcp_render.py +159 -0
- package/scripts/measure_patterns.py +376 -0
- package/scripts/memory_hash.py +75 -0
- package/scripts/memory_lookup.py +441 -0
- package/scripts/memory_report.py +336 -0
- package/scripts/memory_signal.py +210 -0
- package/scripts/memory_status.py +195 -0
- package/scripts/postinstall.sh +60 -0
- package/scripts/readme_linter.py +580 -0
- package/scripts/refine_ticket_detect.py +623 -0
- package/scripts/requirements-evals.txt +7 -0
- package/scripts/runtime_dispatcher.py +265 -0
- package/scripts/runtime_handler.py +148 -0
- package/scripts/runtime_registry.py +166 -0
- package/scripts/schemas/command.schema.json +32 -0
- package/scripts/schemas/persona.schema.json +42 -0
- package/scripts/schemas/rule.schema.json +28 -0
- package/scripts/schemas/skill.schema.json +73 -0
- package/scripts/setup.sh +230 -0
- package/scripts/setup_eval_venv.sh +58 -0
- package/scripts/skill_linter.py +2175 -0
- package/scripts/skill_trigger_eval.py +651 -0
- package/scripts/tool_registry.py +146 -0
- package/scripts/tools/__init__.py +1 -0
- package/scripts/tools/adapter_errors.py +63 -0
- package/scripts/tools/base_adapter.py +91 -0
- package/scripts/tools/github_adapter.py +128 -0
- package/scripts/tools/jira_adapter.py +115 -0
- package/scripts/update_counts.py +147 -0
- package/scripts/validate_frontmatter.py +424 -0
- package/templates/consumer-settings/README.md +46 -0
- package/templates/consumer-settings/augment-settings.json +12 -0
- package/templates/consumer-settings/claude-settings.json +9 -0
- package/templates/consumer-settings/copilot-settings.json +14 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""File-based retrieval for the `absent` path.
|
|
3
|
+
|
|
4
|
+
Implements the shared `retrieve(types, keys, limit)` abstraction used
|
|
5
|
+
by skills. Reads YAML under `agents/memory/<type>/` (curated, hand-
|
|
6
|
+
reviewed) and JSONL under `agents/memory/intake/*.jsonl` (agent-written,
|
|
7
|
+
append-only, supersede-chain aware).
|
|
8
|
+
|
|
9
|
+
The returned shape is identical to the `present`-path adapter over the
|
|
10
|
+
`@event4u/agent-memory` API, so skills stay backend-agnostic.
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
python3 scripts/memory_lookup.py --types domain-invariants,ownership \\
|
|
14
|
+
--key "app/Http/Controllers/Foo" --limit 5
|
|
15
|
+
python3 scripts/memory_lookup.py --types incident-learnings --format json
|
|
16
|
+
|
|
17
|
+
from scripts.memory_lookup import retrieve
|
|
18
|
+
hits = retrieve(types=["ownership"], keys=["app/Http"], limit=3)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import argparse
|
|
24
|
+
import fnmatch
|
|
25
|
+
import json
|
|
26
|
+
import sys
|
|
27
|
+
from dataclasses import dataclass, asdict, field
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
from typing import Any, Iterable
|
|
30
|
+
|
|
31
|
+
MEMORY_ROOT = Path("agents/memory")
|
|
32
|
+
INTAKE_ROOT = MEMORY_ROOT / "intake"
|
|
33
|
+
|
|
34
|
+
CURATED_TYPES = {
|
|
35
|
+
"ownership",
|
|
36
|
+
"historical-patterns",
|
|
37
|
+
"domain-invariants",
|
|
38
|
+
"architecture-decisions",
|
|
39
|
+
"incident-learnings",
|
|
40
|
+
"product-rules",
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class Hit:
|
|
46
|
+
id: str
|
|
47
|
+
type: str
|
|
48
|
+
source: str # "curated" or "intake"
|
|
49
|
+
path: str # file that produced the hit
|
|
50
|
+
score: float # naive, content-match based [0..1]
|
|
51
|
+
entry: dict = field(default_factory=dict)
|
|
52
|
+
|
|
53
|
+
def as_dict(self) -> dict:
|
|
54
|
+
return asdict(self)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _load_yaml(path: Path):
|
|
58
|
+
try:
|
|
59
|
+
import yaml
|
|
60
|
+
except ImportError:
|
|
61
|
+
print("error: PyYAML not installed. `pip install pyyaml`.",
|
|
62
|
+
file=sys.stderr)
|
|
63
|
+
sys.exit(2)
|
|
64
|
+
with path.open(encoding="utf-8") as fh:
|
|
65
|
+
return yaml.safe_load(fh) or {}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _iter_curated_entries(mtype: str) -> Iterable[tuple[Path, dict]]:
|
|
69
|
+
"""Yield (file, entry) pairs for curated files of `mtype`.
|
|
70
|
+
|
|
71
|
+
Supports both the content-addressed layout (`agents/memory/<type>/
|
|
72
|
+
<hash>.yml` — one entry per file) and the single-file layout
|
|
73
|
+
(`agents/memory/<type>.yml` or `<type>/entries.yml` with an
|
|
74
|
+
``entries:`` list), so consumers can adopt either.
|
|
75
|
+
"""
|
|
76
|
+
type_dir = MEMORY_ROOT / mtype
|
|
77
|
+
single_file = MEMORY_ROOT / f"{mtype}.yml"
|
|
78
|
+
if single_file.is_file():
|
|
79
|
+
data = _load_yaml(single_file)
|
|
80
|
+
for e in data.get("entries") or []:
|
|
81
|
+
if isinstance(e, dict):
|
|
82
|
+
yield single_file, e
|
|
83
|
+
if type_dir.is_dir():
|
|
84
|
+
for yml in sorted(type_dir.rglob("*.yml")):
|
|
85
|
+
data = _load_yaml(yml) or {}
|
|
86
|
+
entries = data.get("entries")
|
|
87
|
+
if isinstance(entries, list):
|
|
88
|
+
for e in entries:
|
|
89
|
+
if isinstance(e, dict):
|
|
90
|
+
yield yml, e
|
|
91
|
+
elif isinstance(data, dict) and data.get("id"):
|
|
92
|
+
# Flat, one-entry-per-file layout (content-addressed).
|
|
93
|
+
yield yml, data
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _iter_intake_entries(mtype: str) -> Iterable[tuple[Path, dict]]:
|
|
97
|
+
"""Yield (file, entry) from intake JSONL, applying supersede chains."""
|
|
98
|
+
if not INTAKE_ROOT.is_dir():
|
|
99
|
+
return
|
|
100
|
+
# Resolve supersede chains globally per file: later lines win.
|
|
101
|
+
for jsonl in sorted(INTAKE_ROOT.glob("*.jsonl")):
|
|
102
|
+
by_id: dict[str, dict] = {}
|
|
103
|
+
superseded: set[str] = set()
|
|
104
|
+
with jsonl.open(encoding="utf-8") as fh:
|
|
105
|
+
for line in fh:
|
|
106
|
+
line = line.strip()
|
|
107
|
+
if not line:
|
|
108
|
+
continue
|
|
109
|
+
try:
|
|
110
|
+
obj = json.loads(line)
|
|
111
|
+
except ValueError:
|
|
112
|
+
continue
|
|
113
|
+
if obj.get("type") == "supersede":
|
|
114
|
+
target = obj.get("supersedes")
|
|
115
|
+
if isinstance(target, str):
|
|
116
|
+
superseded.add(target)
|
|
117
|
+
continue
|
|
118
|
+
eid = obj.get("id")
|
|
119
|
+
if isinstance(eid, str):
|
|
120
|
+
by_id[eid] = obj
|
|
121
|
+
for eid, obj in by_id.items():
|
|
122
|
+
if eid in superseded:
|
|
123
|
+
continue
|
|
124
|
+
if mtype and obj.get("entry_type") and obj["entry_type"] != mtype:
|
|
125
|
+
continue
|
|
126
|
+
yield jsonl, obj
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _score(entry: dict, keys: list[str]) -> float:
|
|
130
|
+
"""Naive relevance score: max over keys of (glob-match | substring).
|
|
131
|
+
|
|
132
|
+
Good enough for the `absent` path where retrieval is best-effort.
|
|
133
|
+
The `present` path returns a real score from agent-memory.
|
|
134
|
+
"""
|
|
135
|
+
if not keys:
|
|
136
|
+
return 0.1 # any hit beats no hit when there is no key
|
|
137
|
+
hay_parts: list[str] = []
|
|
138
|
+
for field_name in ("path", "key", "symptom", "feature", "rule", "body"):
|
|
139
|
+
v = entry.get(field_name)
|
|
140
|
+
if isinstance(v, str):
|
|
141
|
+
hay_parts.append(v)
|
|
142
|
+
elif isinstance(v, list):
|
|
143
|
+
hay_parts.extend(str(x) for x in v)
|
|
144
|
+
hay = " | ".join(hay_parts).lower()
|
|
145
|
+
best = 0.0
|
|
146
|
+
for k in keys:
|
|
147
|
+
kl = k.lower()
|
|
148
|
+
if fnmatch.fnmatch(hay, f"*{kl}*"):
|
|
149
|
+
best = max(best, 0.8)
|
|
150
|
+
elif kl in hay:
|
|
151
|
+
best = max(best, 0.6)
|
|
152
|
+
return best
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def retrieve(types: list[str], keys: list[str], limit: int = 5) -> list[Hit]:
|
|
156
|
+
"""Return up to `limit` hits across the requested types, highest score first.
|
|
157
|
+
|
|
158
|
+
Curated entries are preferred on ties — they are hand-reviewed.
|
|
159
|
+
The shape (`Hit`) matches the `present` backend adapter so skills
|
|
160
|
+
can treat both sources identically.
|
|
161
|
+
"""
|
|
162
|
+
hits: list[Hit] = []
|
|
163
|
+
for mtype in types:
|
|
164
|
+
if mtype not in CURATED_TYPES:
|
|
165
|
+
continue
|
|
166
|
+
for path, entry in _iter_curated_entries(mtype):
|
|
167
|
+
hits.append(Hit(
|
|
168
|
+
id=str(entry.get("id", "")),
|
|
169
|
+
type=mtype,
|
|
170
|
+
source="curated",
|
|
171
|
+
path=str(path),
|
|
172
|
+
score=_score(entry, keys),
|
|
173
|
+
entry=entry,
|
|
174
|
+
))
|
|
175
|
+
for path, entry in _iter_intake_entries(mtype):
|
|
176
|
+
hits.append(Hit(
|
|
177
|
+
id=str(entry.get("id", "")),
|
|
178
|
+
type=mtype,
|
|
179
|
+
source="intake",
|
|
180
|
+
path=str(path),
|
|
181
|
+
score=_score(entry, keys) * 0.9, # slight discount vs curated
|
|
182
|
+
entry=entry,
|
|
183
|
+
))
|
|
184
|
+
hits.sort(key=lambda h: (h.score, h.source == "curated"), reverse=True)
|
|
185
|
+
# Drop zero-score hits unless no better option exists.
|
|
186
|
+
positives = [h for h in hits if h.score > 0]
|
|
187
|
+
return (positives or hits)[:limit]
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def main() -> int:
|
|
191
|
+
ap = argparse.ArgumentParser(description=__doc__)
|
|
192
|
+
ap.add_argument("--types", default="",
|
|
193
|
+
help="Comma-separated memory types (e.g., ownership,domain-invariants)")
|
|
194
|
+
ap.add_argument("--key", action="append", default=[],
|
|
195
|
+
help="Retrieval key (repeatable)")
|
|
196
|
+
ap.add_argument("--limit", type=int, default=5)
|
|
197
|
+
ap.add_argument("--format", choices=["text", "json"], default="text")
|
|
198
|
+
args = ap.parse_args()
|
|
199
|
+
types = [t.strip() for t in args.types.split(",") if t.strip()]
|
|
200
|
+
if not types:
|
|
201
|
+
print("error: --types is required", file=sys.stderr)
|
|
202
|
+
return 2
|
|
203
|
+
hits = retrieve(types, args.key, args.limit)
|
|
204
|
+
if args.format == "json":
|
|
205
|
+
print(json.dumps([h.as_dict() for h in hits], indent=2, default=str))
|
|
206
|
+
else:
|
|
207
|
+
if not hits:
|
|
208
|
+
print(" (no hits)")
|
|
209
|
+
for h in hits:
|
|
210
|
+
print(f" [{h.source}] {h.type} score={h.score:.2f} "
|
|
211
|
+
f"id={h.id or '-'} path={h.path}")
|
|
212
|
+
return 0
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
if __name__ == "__main__":
|
|
216
|
+
sys.exit(main())
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""One-shot memory observability report.
|
|
3
|
+
|
|
4
|
+
Shows:
|
|
5
|
+
- Backend status (via `memory_status.status()`)
|
|
6
|
+
- Intake counts per entry type and per month
|
|
7
|
+
- Curated file staleness (files with `last_validated` older than
|
|
8
|
+
`review_after_days` for any entry)
|
|
9
|
+
- Supersede-chain totals
|
|
10
|
+
|
|
11
|
+
Exit code: 0 = report printed (green or otherwise); 2 = PyYAML missing.
|
|
12
|
+
`task memory:status` is the expected entry point, but the script is
|
|
13
|
+
usable standalone.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
python3 scripts/memory_report.py
|
|
17
|
+
python3 scripts/memory_report.py --format json
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import argparse
|
|
23
|
+
import datetime as dt
|
|
24
|
+
import json
|
|
25
|
+
import sys
|
|
26
|
+
from collections import Counter, defaultdict
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any
|
|
29
|
+
|
|
30
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
31
|
+
import memory_status # noqa: E402
|
|
32
|
+
|
|
33
|
+
MEMORY_ROOT = Path("agents/memory")
|
|
34
|
+
INTAKE_ROOT = MEMORY_ROOT / "intake"
|
|
35
|
+
CURATED_TYPES = (
|
|
36
|
+
"ownership", "historical-patterns", "domain-invariants",
|
|
37
|
+
"architecture-decisions", "incident-learnings", "product-rules",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _load_yaml(path: Path) -> dict:
|
|
42
|
+
try:
|
|
43
|
+
import yaml
|
|
44
|
+
except ImportError:
|
|
45
|
+
print("error: PyYAML not installed. `pip install pyyaml`.",
|
|
46
|
+
file=sys.stderr)
|
|
47
|
+
sys.exit(2)
|
|
48
|
+
with path.open(encoding="utf-8") as fh:
|
|
49
|
+
return yaml.safe_load(fh) or {}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _iter_curated_entries() -> list[tuple[Path, str, dict]]:
|
|
53
|
+
"""Yield (file, type, entry) across both curated layouts."""
|
|
54
|
+
out: list[tuple[Path, str, dict]] = []
|
|
55
|
+
for mtype in CURATED_TYPES:
|
|
56
|
+
single = MEMORY_ROOT / f"{mtype}.yml"
|
|
57
|
+
if single.is_file():
|
|
58
|
+
data = _load_yaml(single)
|
|
59
|
+
for e in data.get("entries") or []:
|
|
60
|
+
if isinstance(e, dict):
|
|
61
|
+
out.append((single, mtype, e))
|
|
62
|
+
type_dir = MEMORY_ROOT / mtype
|
|
63
|
+
if type_dir.is_dir():
|
|
64
|
+
for yml in sorted(type_dir.rglob("*.yml")):
|
|
65
|
+
data = _load_yaml(yml) or {}
|
|
66
|
+
entries = data.get("entries")
|
|
67
|
+
if isinstance(entries, list):
|
|
68
|
+
for e in entries:
|
|
69
|
+
if isinstance(e, dict):
|
|
70
|
+
out.append((yml, mtype, e))
|
|
71
|
+
elif isinstance(data, dict) and data.get("id"):
|
|
72
|
+
out.append((yml, mtype, data))
|
|
73
|
+
return out
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _intake_stats() -> dict:
|
|
77
|
+
total = 0
|
|
78
|
+
by_type: Counter = Counter()
|
|
79
|
+
by_month: Counter = Counter()
|
|
80
|
+
superseded = 0
|
|
81
|
+
if INTAKE_ROOT.is_dir():
|
|
82
|
+
for jsonl in sorted(INTAKE_ROOT.glob("*.jsonl")):
|
|
83
|
+
month = jsonl.stem.replace("signals-", "")
|
|
84
|
+
with jsonl.open(encoding="utf-8") as fh:
|
|
85
|
+
for line in fh:
|
|
86
|
+
line = line.strip()
|
|
87
|
+
if not line:
|
|
88
|
+
continue
|
|
89
|
+
try:
|
|
90
|
+
obj = json.loads(line)
|
|
91
|
+
except ValueError:
|
|
92
|
+
continue
|
|
93
|
+
if obj.get("type") == "supersede":
|
|
94
|
+
superseded += 1
|
|
95
|
+
continue
|
|
96
|
+
total += 1
|
|
97
|
+
t = obj.get("entry_type")
|
|
98
|
+
if isinstance(t, str):
|
|
99
|
+
by_type[t] += 1
|
|
100
|
+
by_month[month] += 1
|
|
101
|
+
return {
|
|
102
|
+
"total_active": total,
|
|
103
|
+
"superseded": superseded,
|
|
104
|
+
"by_type": dict(by_type),
|
|
105
|
+
"by_month": dict(by_month),
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _staleness_report() -> list[dict]:
|
|
110
|
+
today = dt.date.today()
|
|
111
|
+
stale: list[dict] = []
|
|
112
|
+
for path, mtype, entry in _iter_curated_entries():
|
|
113
|
+
lv = entry.get("last_validated")
|
|
114
|
+
review_after = entry.get("review_after_days")
|
|
115
|
+
if not isinstance(lv, (str, dt.date)) \
|
|
116
|
+
or not isinstance(review_after, int):
|
|
117
|
+
continue
|
|
118
|
+
try:
|
|
119
|
+
last = lv if isinstance(lv, dt.date) \
|
|
120
|
+
else dt.date.fromisoformat(str(lv))
|
|
121
|
+
except ValueError:
|
|
122
|
+
continue
|
|
123
|
+
due = last + dt.timedelta(days=review_after)
|
|
124
|
+
if due < today:
|
|
125
|
+
stale.append({
|
|
126
|
+
"file": str(path),
|
|
127
|
+
"type": mtype,
|
|
128
|
+
"id": entry.get("id", "?"),
|
|
129
|
+
"overdue_days": (today - due).days,
|
|
130
|
+
})
|
|
131
|
+
stale.sort(key=lambda r: r["overdue_days"], reverse=True)
|
|
132
|
+
return stale
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def build_report() -> dict:
|
|
136
|
+
status = memory_status.status()
|
|
137
|
+
return {
|
|
138
|
+
"backend": {
|
|
139
|
+
"status": status.status,
|
|
140
|
+
"backend": status.backend,
|
|
141
|
+
"reason": status.reason,
|
|
142
|
+
"cli_path": status.cli_path,
|
|
143
|
+
},
|
|
144
|
+
"intake": _intake_stats(),
|
|
145
|
+
"staleness": _staleness_report(),
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _print_text(report: dict) -> None:
|
|
150
|
+
b = report["backend"]
|
|
151
|
+
print(f"Backend: {b['status']} (backend={b['backend']})")
|
|
152
|
+
if b["reason"]:
|
|
153
|
+
print(f" reason: {b['reason']}")
|
|
154
|
+
intake = report["intake"]
|
|
155
|
+
print(f"Intake: {intake['total_active']} active, "
|
|
156
|
+
f"{intake['superseded']} superseded")
|
|
157
|
+
for t, n in sorted(intake["by_type"].items()):
|
|
158
|
+
print(f" - {t}: {n}")
|
|
159
|
+
stale = report["staleness"]
|
|
160
|
+
if not stale:
|
|
161
|
+
print("Staleness: no curated entries past review_after_days")
|
|
162
|
+
else:
|
|
163
|
+
print(f"Staleness: {len(stale)} entrie(s) overdue")
|
|
164
|
+
for row in stale[:5]:
|
|
165
|
+
print(f" - {row['id']} ({row['type']}) "
|
|
166
|
+
f"+{row['overdue_days']}d {row['file']}")
|
|
167
|
+
if len(stale) > 5:
|
|
168
|
+
print(f" (+{len(stale) - 5} more)")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def main() -> int:
|
|
172
|
+
ap = argparse.ArgumentParser(description=__doc__)
|
|
173
|
+
ap.add_argument("--format", choices=["text", "json"], default="text")
|
|
174
|
+
args = ap.parse_args()
|
|
175
|
+
report = build_report()
|
|
176
|
+
if args.format == "json":
|
|
177
|
+
print(json.dumps(report, indent=2, default=str))
|
|
178
|
+
else:
|
|
179
|
+
_print_text(report)
|
|
180
|
+
return 0
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
sys.exit(main())
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Write-side helper: drop an engineering-memory signal.
|
|
3
|
+
|
|
4
|
+
Shared by producers (`/bug-fix`, `/do-and-judge`, `/propose-memory`,
|
|
5
|
+
incident role exit). Routes to the optional `agent-memory` package when
|
|
6
|
+
`memory_status.status() == "present"`; otherwise appends an intake
|
|
7
|
+
line under `agents/memory/intake/signals-YYYY-MM.jsonl` — append-only
|
|
8
|
+
JSONL with `merge=union` (see `road-to-memory-merge-safety.md`).
|
|
9
|
+
|
|
10
|
+
Rate limiting:
|
|
11
|
+
- Per-path, per-type, within a rolling window (default 7 days).
|
|
12
|
+
- Silent skip on duplicate — the producer's caller should not error,
|
|
13
|
+
since over-emission is a correctness bug, not a failure mode.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
python3 scripts/memory_signal.py \\
|
|
17
|
+
--type historical-patterns \\
|
|
18
|
+
--path "app/Http/Controllers/Billing/Checkout.php" \\
|
|
19
|
+
--body "Null deref when currency is missing — add guard."
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import datetime as dt
|
|
26
|
+
import json
|
|
27
|
+
import os
|
|
28
|
+
import secrets
|
|
29
|
+
import sys
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
from typing import Any
|
|
32
|
+
|
|
33
|
+
INTAKE_ROOT = Path("agents/memory/intake")
|
|
34
|
+
VALID_TYPES = {
|
|
35
|
+
"historical-patterns",
|
|
36
|
+
"incident-learnings",
|
|
37
|
+
"ownership",
|
|
38
|
+
"domain-invariants",
|
|
39
|
+
"architecture-decisions",
|
|
40
|
+
"product-rules",
|
|
41
|
+
}
|
|
42
|
+
RATE_LIMIT_WINDOW_DAYS = 7
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _now_iso() -> str:
|
|
46
|
+
return dt.datetime.now(dt.timezone.utc).isoformat(timespec="seconds")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _new_id() -> str:
|
|
50
|
+
# Short, URL-safe, stable enough for intake ids.
|
|
51
|
+
return f"sig-{secrets.token_hex(6)}"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _monthly_file() -> Path:
|
|
55
|
+
ym = dt.datetime.now(dt.timezone.utc).strftime("%Y-%m")
|
|
56
|
+
return INTAKE_ROOT / f"signals-{ym}.jsonl"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _recently_emitted(entry_type: str, path: str, body: str,
|
|
60
|
+
window_days: int = RATE_LIMIT_WINDOW_DAYS) -> bool:
|
|
61
|
+
"""True if an identical (type, path, body) was written within the window."""
|
|
62
|
+
if not INTAKE_ROOT.is_dir():
|
|
63
|
+
return False
|
|
64
|
+
cutoff = dt.datetime.now(dt.timezone.utc) - dt.timedelta(days=window_days)
|
|
65
|
+
for jsonl in sorted(INTAKE_ROOT.glob("signals-*.jsonl")):
|
|
66
|
+
try:
|
|
67
|
+
with jsonl.open(encoding="utf-8") as fh:
|
|
68
|
+
for line in fh:
|
|
69
|
+
line = line.strip()
|
|
70
|
+
if not line:
|
|
71
|
+
continue
|
|
72
|
+
try:
|
|
73
|
+
obj = json.loads(line)
|
|
74
|
+
except ValueError:
|
|
75
|
+
continue
|
|
76
|
+
if obj.get("entry_type") != entry_type:
|
|
77
|
+
continue
|
|
78
|
+
if obj.get("path") != path:
|
|
79
|
+
continue
|
|
80
|
+
if obj.get("body") != body:
|
|
81
|
+
continue
|
|
82
|
+
ts = obj.get("ts")
|
|
83
|
+
if not isinstance(ts, str):
|
|
84
|
+
continue
|
|
85
|
+
try:
|
|
86
|
+
emitted = dt.datetime.fromisoformat(ts)
|
|
87
|
+
except ValueError:
|
|
88
|
+
continue
|
|
89
|
+
if emitted >= cutoff:
|
|
90
|
+
return True
|
|
91
|
+
except OSError:
|
|
92
|
+
continue
|
|
93
|
+
return False
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def emit(entry_type: str, path: str, body: str,
|
|
97
|
+
extra: dict[str, Any] | None = None,
|
|
98
|
+
origin: str = "agent",
|
|
99
|
+
force: bool = False) -> dict[str, Any] | None:
|
|
100
|
+
"""Append a signal entry. Returns the written record, or None when skipped.
|
|
101
|
+
|
|
102
|
+
On `present` backend, routing to the package is a no-op here today —
|
|
103
|
+
the package adapter is wired in `road-to-agent-memory-integration.md`
|
|
104
|
+
Phase 3. For now, the file path is the single source of truth so
|
|
105
|
+
merge-safety is preserved in every mode.
|
|
106
|
+
"""
|
|
107
|
+
if entry_type not in VALID_TYPES:
|
|
108
|
+
raise ValueError(f"unknown memory type: {entry_type}")
|
|
109
|
+
if not path or not body:
|
|
110
|
+
raise ValueError("path and body are required")
|
|
111
|
+
if not force and _recently_emitted(entry_type, path, body):
|
|
112
|
+
return None
|
|
113
|
+
record: dict[str, Any] = {
|
|
114
|
+
"id": _new_id(),
|
|
115
|
+
"ts": _now_iso(),
|
|
116
|
+
"origin": origin,
|
|
117
|
+
"entry_type": entry_type,
|
|
118
|
+
"path": path,
|
|
119
|
+
"body": body,
|
|
120
|
+
}
|
|
121
|
+
if extra:
|
|
122
|
+
# Reserved keys stay intact; extras only fill unclaimed slots.
|
|
123
|
+
for k, v in extra.items():
|
|
124
|
+
record.setdefault(k, v)
|
|
125
|
+
INTAKE_ROOT.mkdir(parents=True, exist_ok=True)
|
|
126
|
+
target = _monthly_file()
|
|
127
|
+
with target.open("a", encoding="utf-8") as fh:
|
|
128
|
+
fh.write(json.dumps(record, ensure_ascii=False) + "\n")
|
|
129
|
+
return record
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def main() -> int:
|
|
133
|
+
ap = argparse.ArgumentParser(description=__doc__)
|
|
134
|
+
ap.add_argument("--type", dest="entry_type", required=True,
|
|
135
|
+
choices=sorted(VALID_TYPES))
|
|
136
|
+
ap.add_argument("--path", required=True,
|
|
137
|
+
help="Affected file/module path (e.g., app/Http/Foo.php)")
|
|
138
|
+
ap.add_argument("--body", required=True, help="One- to few-sentence finding")
|
|
139
|
+
ap.add_argument("--origin", default="agent",
|
|
140
|
+
help="Producer identifier, e.g., bug-fix, do-and-judge")
|
|
141
|
+
ap.add_argument("--extra", default="",
|
|
142
|
+
help="Optional JSON blob of extra keys (symptom, owner, ...)")
|
|
143
|
+
ap.add_argument("--force", action="store_true",
|
|
144
|
+
help="Bypass rate-limit dedupe")
|
|
145
|
+
args = ap.parse_args()
|
|
146
|
+
extra: dict[str, Any] = {}
|
|
147
|
+
if args.extra:
|
|
148
|
+
try:
|
|
149
|
+
extra = json.loads(args.extra)
|
|
150
|
+
if not isinstance(extra, dict):
|
|
151
|
+
raise ValueError
|
|
152
|
+
except ValueError:
|
|
153
|
+
print("error: --extra must be a JSON object", file=sys.stderr)
|
|
154
|
+
return 2
|
|
155
|
+
rec = emit(args.entry_type, args.path, args.body,
|
|
156
|
+
extra=extra, origin=args.origin, force=args.force)
|
|
157
|
+
if rec is None:
|
|
158
|
+
print(f" ℹ️ skipped (already emitted within "
|
|
159
|
+
f"{RATE_LIMIT_WINDOW_DAYS}d): {args.entry_type} @ {args.path}")
|
|
160
|
+
return 0
|
|
161
|
+
print(f" ✅ signal emitted: id={rec['id']} type={rec['entry_type']} "
|
|
162
|
+
f"path={rec['path']}")
|
|
163
|
+
return 0
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
sys.exit(main())
|