@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,320 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Portability checker for agent-config packages.
|
|
4
|
+
|
|
5
|
+
Scans .agent-src/ and .agent-src.uncompressed/ for project-specific references
|
|
6
|
+
that violate package portability (the package must work in ANY project).
|
|
7
|
+
|
|
8
|
+
Allowed: references to packages/libraries (laravel, pest, phpstan, etc.)
|
|
9
|
+
Forbidden: references to specific projects, repos, domains, teams, customers
|
|
10
|
+
|
|
11
|
+
Exit codes: 0 = clean, 1 = violations found, 3 = internal error
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
import json
|
|
18
|
+
import re
|
|
19
|
+
import sys
|
|
20
|
+
from dataclasses import dataclass, asdict
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import List, Literal
|
|
23
|
+
|
|
24
|
+
Severity = Literal["error", "warning"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Violation:
|
|
29
|
+
file: str
|
|
30
|
+
line: int
|
|
31
|
+
match: str
|
|
32
|
+
pattern_name: str
|
|
33
|
+
severity: Severity
|
|
34
|
+
context: str # the full line for review
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# ── Auto-detected project identifiers ────────────────────────────────────
|
|
38
|
+
# Instead of hardcoding project names, we auto-detect them from:
|
|
39
|
+
# 1. Git remote URL (org name, repo name)
|
|
40
|
+
# 2. composer.json / package.json (package name)
|
|
41
|
+
# 3. Directory name (workspace root)
|
|
42
|
+
# This makes the checker portable across ANY project.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _detect_project_identifiers(root: Path) -> set[str]:
|
|
46
|
+
"""Auto-detect project-specific identifiers from the project context."""
|
|
47
|
+
identifiers: set[str] = set()
|
|
48
|
+
|
|
49
|
+
# 1. Git remote URL
|
|
50
|
+
try:
|
|
51
|
+
import subprocess
|
|
52
|
+
result = subprocess.run(
|
|
53
|
+
["git", "remote", "get-url", "origin"],
|
|
54
|
+
capture_output=True, text=True, cwd=root, timeout=5,
|
|
55
|
+
)
|
|
56
|
+
if result.returncode == 0:
|
|
57
|
+
url = result.stdout.strip()
|
|
58
|
+
# Extract from SSH: git@github.com:org/repo.git
|
|
59
|
+
# Extract from HTTPS: https://github.com/org/repo.git
|
|
60
|
+
parts = re.split(r"[:/]", url.replace(".git", ""))
|
|
61
|
+
# Last 2 parts are typically org and repo
|
|
62
|
+
for part in parts[-2:]:
|
|
63
|
+
part = part.strip()
|
|
64
|
+
if part and part not in ("git", "github.com", "gitlab.com", "bitbucket.org", "com"):
|
|
65
|
+
identifiers.add(part)
|
|
66
|
+
# Also add sub-parts split by hyphen (e.g., "event4u-app" → "event4u")
|
|
67
|
+
for sub in part.split("-"):
|
|
68
|
+
if len(sub) >= 3:
|
|
69
|
+
identifiers.add(sub)
|
|
70
|
+
except (FileNotFoundError, subprocess.TimeoutExpired):
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
# 2. composer.json
|
|
74
|
+
composer = root / "composer.json"
|
|
75
|
+
if composer.exists():
|
|
76
|
+
try:
|
|
77
|
+
data = json.loads(composer.read_text(encoding="utf-8"))
|
|
78
|
+
name = data.get("name", "")
|
|
79
|
+
if "/" in name:
|
|
80
|
+
vendor, pkg = name.split("/", 1)
|
|
81
|
+
identifiers.add(vendor)
|
|
82
|
+
identifiers.add(pkg)
|
|
83
|
+
for sub in pkg.split("-"):
|
|
84
|
+
if len(sub) >= 3:
|
|
85
|
+
identifiers.add(sub)
|
|
86
|
+
except (json.JSONDecodeError, ValueError):
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
# 3. package.json
|
|
90
|
+
pkgjson = root / "package.json"
|
|
91
|
+
if pkgjson.exists():
|
|
92
|
+
try:
|
|
93
|
+
data = json.loads(pkgjson.read_text(encoding="utf-8"))
|
|
94
|
+
name = data.get("name", "").lstrip("@")
|
|
95
|
+
if "/" in name:
|
|
96
|
+
scope, pkg = name.split("/", 1)
|
|
97
|
+
identifiers.add(scope)
|
|
98
|
+
identifiers.add(pkg)
|
|
99
|
+
elif name:
|
|
100
|
+
identifiers.add(name)
|
|
101
|
+
except (json.JSONDecodeError, ValueError):
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
# 4. Directory name (parent directories of .agent-src/)
|
|
105
|
+
augment_dir = root / ".agent-src"
|
|
106
|
+
if augment_dir.exists():
|
|
107
|
+
dir_name = root.name
|
|
108
|
+
if len(dir_name) >= 3:
|
|
109
|
+
identifiers.add(dir_name)
|
|
110
|
+
# Also check parent (often the org/group directory)
|
|
111
|
+
parent_name = root.parent.name
|
|
112
|
+
if len(parent_name) >= 3 and parent_name not in ("projects", "src", "code", "repos", "home", "Users"):
|
|
113
|
+
identifiers.add(parent_name)
|
|
114
|
+
|
|
115
|
+
# Filter out generic terms that would cause false positives
|
|
116
|
+
generic = {"app", "api", "web", "src", "lib", "pkg", "core", "main", "test",
|
|
117
|
+
"config", "agent", "tools", "packages", "server", "client", "common"}
|
|
118
|
+
identifiers -= generic
|
|
119
|
+
|
|
120
|
+
return identifiers
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _build_patterns(root: Path) -> tuple[list[tuple[re.Pattern, str, Severity]], list[str]]:
|
|
124
|
+
"""Build regex patterns from auto-detected project identifiers."""
|
|
125
|
+
identifiers = _detect_project_identifiers(root)
|
|
126
|
+
patterns: list[tuple[re.Pattern, str, Severity]] = []
|
|
127
|
+
detected: list[str] = sorted(identifiers)
|
|
128
|
+
|
|
129
|
+
for ident in identifiers:
|
|
130
|
+
escaped = re.escape(ident)
|
|
131
|
+
# Word boundary match (case-insensitive)
|
|
132
|
+
patterns.append((re.compile(rf"\b{escaped}\b", re.IGNORECASE), "project-name", "error"))
|
|
133
|
+
# As prefix with separator (db names, container names, env vars)
|
|
134
|
+
patterns.append((re.compile(rf"\b{escaped}[-_]\w+", re.IGNORECASE), "project-derivative", "warning"))
|
|
135
|
+
# Domain patterns (name.tld)
|
|
136
|
+
patterns.append((re.compile(rf"\b{escaped}\.\w{{2,6}}\b", re.IGNORECASE), "project-domain", "error"))
|
|
137
|
+
# GitHub org/user patterns
|
|
138
|
+
patterns.append((re.compile(rf"@{escaped}\b", re.IGNORECASE), "project-org", "error"))
|
|
139
|
+
|
|
140
|
+
return patterns, detected
|
|
141
|
+
|
|
142
|
+
# ── Allowed patterns (NOT violations even if they match above) ──────────
|
|
143
|
+
# Generic Laravel/framework patterns that are NOT project-specific
|
|
144
|
+
ALLOWLIST = [
|
|
145
|
+
r"\.agent-settings\.yml", # config file reference (YAML)
|
|
146
|
+
r"\.agent-settings\b", # legacy reference (key=value, migration window)
|
|
147
|
+
r"agents/overrides/", # override system
|
|
148
|
+
r"app/Modules/", # generic Laravel module pattern
|
|
149
|
+
r"`App\\", # namespace pattern explanation
|
|
150
|
+
r"app/Http/Controllers/", # generic Laravel path pattern
|
|
151
|
+
r"app/Repositories/", # generic pattern in skills/guidelines
|
|
152
|
+
r"\.module-template", # module template
|
|
153
|
+
r"ModuleServiceProvider", # generic module concept
|
|
154
|
+
r"app/Services/MyService", # example placeholder
|
|
155
|
+
r"app/Models/\{", # template placeholder like {Model}
|
|
156
|
+
r"app/Services/\{", # template placeholder like {Service}
|
|
157
|
+
r"agent-config", # refers to the package concept, not a specific project
|
|
158
|
+
r"shared.*package", # "shared package" concept
|
|
159
|
+
r"package repository", # "package repository" concept
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
# Directories to scan (only package files, not project-specific agents/)
|
|
163
|
+
SCAN_DIRS = [".agent-src", ".agent-src.uncompressed"]
|
|
164
|
+
|
|
165
|
+
# Additional root-level files shipped by the package that must also stay
|
|
166
|
+
# portable. These are read by agents working on the package itself and —
|
|
167
|
+
# for AGENTS.md and copilot-instructions.md — serve as meta docs about
|
|
168
|
+
# the package. They must never leak consumer-project identifiers.
|
|
169
|
+
SCAN_ROOT_FILES = ["AGENTS.md", ".github/copilot-instructions.md"]
|
|
170
|
+
|
|
171
|
+
# Skip these subdirectories (they ARE allowed to be project-specific)
|
|
172
|
+
SKIP_PATTERNS = [
|
|
173
|
+
"agents/", # project-specific by design
|
|
174
|
+
".agent-settings.yml", # project config (YAML)
|
|
175
|
+
".agent-settings", # legacy project config (migration window)
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
# Optional blocklist of identifiers from past/adjacent projects that must
|
|
179
|
+
# never appear anywhere in the shared package, even when the auto-detector
|
|
180
|
+
# would not flag them (e.g. because the repo was renamed or split). The
|
|
181
|
+
# list is loaded from the environment variable AGENT_CONFIG_BLOCKLIST
|
|
182
|
+
# (comma-separated) so the package itself ships without hardcoding any
|
|
183
|
+
# consumer-specific names. Maintainers of a fork with legacy debt can set
|
|
184
|
+
# the variable in their CI to catch regressions.
|
|
185
|
+
def _load_forbidden_identifiers() -> list[str]:
|
|
186
|
+
raw = __import__("os").environ.get("AGENT_CONFIG_BLOCKLIST", "")
|
|
187
|
+
return [part.strip() for part in raw.split(",") if part.strip()]
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
FORBIDDEN_IDENTIFIERS: list[str] = _load_forbidden_identifiers()
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _compile_patterns(root: Path) -> tuple[list[tuple[re.Pattern, str, Severity]], list[str]]:
|
|
194
|
+
"""Build patterns from auto-detected project identifiers."""
|
|
195
|
+
return _build_patterns(root)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _compile_forbidden_patterns() -> list[tuple[re.Pattern, str, Severity]]:
|
|
199
|
+
"""Build regex patterns for hardcoded FORBIDDEN_IDENTIFIERS.
|
|
200
|
+
|
|
201
|
+
These apply to every scanned file regardless of auto-detection. They
|
|
202
|
+
catch leakage from renamed or adjacent projects.
|
|
203
|
+
"""
|
|
204
|
+
patterns: list[tuple[re.Pattern, str, Severity]] = []
|
|
205
|
+
for ident in FORBIDDEN_IDENTIFIERS:
|
|
206
|
+
escaped = re.escape(ident)
|
|
207
|
+
patterns.append((re.compile(rf"\b{escaped}\b", re.IGNORECASE), "forbidden-identifier", "error"))
|
|
208
|
+
return patterns
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _compile_allowlist() -> list[re.Pattern]:
|
|
212
|
+
return [re.compile(p) for p in ALLOWLIST]
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def check_file(filepath: Path, patterns: list, allowlist: list) -> List[Violation]:
|
|
216
|
+
violations: List[Violation] = []
|
|
217
|
+
try:
|
|
218
|
+
lines = filepath.read_text(encoding="utf-8").splitlines()
|
|
219
|
+
except Exception:
|
|
220
|
+
return violations
|
|
221
|
+
|
|
222
|
+
in_code_block = False
|
|
223
|
+
for i, line in enumerate(lines, 1):
|
|
224
|
+
stripped = line.strip()
|
|
225
|
+
|
|
226
|
+
# Skip YAML frontmatter
|
|
227
|
+
if i <= 10 and stripped == "---":
|
|
228
|
+
continue
|
|
229
|
+
|
|
230
|
+
# Track code blocks
|
|
231
|
+
if stripped.startswith("```"):
|
|
232
|
+
in_code_block = not in_code_block
|
|
233
|
+
continue
|
|
234
|
+
if in_code_block:
|
|
235
|
+
continue
|
|
236
|
+
|
|
237
|
+
# Check allowlist first
|
|
238
|
+
if any(a.search(line) for a in allowlist):
|
|
239
|
+
continue
|
|
240
|
+
|
|
241
|
+
for pattern, name, severity in patterns:
|
|
242
|
+
for m in pattern.finditer(line):
|
|
243
|
+
violations.append(Violation(
|
|
244
|
+
file=str(filepath), line=i, match=m.group(0),
|
|
245
|
+
pattern_name=name, severity=severity, context=stripped,
|
|
246
|
+
))
|
|
247
|
+
|
|
248
|
+
return violations
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def scan_all(root: Path) -> tuple[List[Violation], list[str]]:
|
|
252
|
+
"""Scan all package files for portability violations. Returns (violations, detected_identifiers).
|
|
253
|
+
|
|
254
|
+
Scanning has two layers:
|
|
255
|
+
1. Auto-detected identifiers — applied to `.agent-src/` and
|
|
256
|
+
`.agent-src.uncompressed/` only. The package's own root AGENTS.md and
|
|
257
|
+
copilot-instructions.md are meta docs ABOUT the package, so the
|
|
258
|
+
detector's own hits (e.g. "event4u", "agent-config") are expected.
|
|
259
|
+
2. Optional FORBIDDEN_IDENTIFIERS from AGENT_CONFIG_BLOCKLIST —
|
|
260
|
+
applied to every scanned file, including the root files. Catches
|
|
261
|
+
leakage from renamed or adjacent projects in downstream forks.
|
|
262
|
+
"""
|
|
263
|
+
patterns, detected = _compile_patterns(root)
|
|
264
|
+
forbidden = _compile_forbidden_patterns()
|
|
265
|
+
allowlist = _compile_allowlist()
|
|
266
|
+
violations: List[Violation] = []
|
|
267
|
+
|
|
268
|
+
# Layer 1 + 2: full package content
|
|
269
|
+
for scan_dir in SCAN_DIRS:
|
|
270
|
+
d = root / scan_dir
|
|
271
|
+
if not d.exists():
|
|
272
|
+
continue
|
|
273
|
+
for f in sorted(d.rglob("*.md")):
|
|
274
|
+
violations.extend(check_file(f, patterns + forbidden, allowlist))
|
|
275
|
+
|
|
276
|
+
# Layer 2 only: root files (auto-detected identifiers are expected here)
|
|
277
|
+
for rel in SCAN_ROOT_FILES:
|
|
278
|
+
f = root / rel
|
|
279
|
+
if f.is_file():
|
|
280
|
+
violations.extend(check_file(f, forbidden, allowlist))
|
|
281
|
+
|
|
282
|
+
return violations, detected
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def format_text(violations: List[Violation], detected: list[str]) -> str:
|
|
287
|
+
header = f"Auto-detected identifiers: {', '.join(detected)}\n" if detected else ""
|
|
288
|
+
if not violations:
|
|
289
|
+
return f"{header}✅ No portability violations found."
|
|
290
|
+
lines = [f"{header}❌ Found {len(violations)} portability violation(s):\n"]
|
|
291
|
+
for v in violations:
|
|
292
|
+
icon = "🔴" if v.severity == "error" else "🟡"
|
|
293
|
+
lines.append(f" {icon} {v.file}:{v.line} — [{v.pattern_name}] `{v.match}`")
|
|
294
|
+
lines.append(f" {v.context}")
|
|
295
|
+
return "\n".join(lines)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def main() -> int:
|
|
299
|
+
parser = argparse.ArgumentParser(description="Check agent-config package portability")
|
|
300
|
+
parser.add_argument("--format", choices=["text", "json"], default="text")
|
|
301
|
+
parser.add_argument("--root", type=Path, default=Path("."), help="Repository root")
|
|
302
|
+
args = parser.parse_args()
|
|
303
|
+
|
|
304
|
+
try:
|
|
305
|
+
violations, detected = scan_all(args.root)
|
|
306
|
+
except Exception as e:
|
|
307
|
+
print(f"Internal error: {e}", file=sys.stderr)
|
|
308
|
+
return 3
|
|
309
|
+
|
|
310
|
+
if args.format == "json":
|
|
311
|
+
payload = {"detected": detected, "violations": [asdict(v) for v in violations]}
|
|
312
|
+
print(json.dumps(payload, indent=2))
|
|
313
|
+
else:
|
|
314
|
+
print(format_text(violations, detected))
|
|
315
|
+
|
|
316
|
+
return 1 if violations else 0
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
if __name__ == "__main__":
|
|
320
|
+
sys.exit(main())
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Stage-4 gate for curated self-improvement proposals.
|
|
4
|
+
|
|
5
|
+
Validates a proposal doc produced by the pipeline documented in
|
|
6
|
+
`guidelines/agent-infra/self-improvement-pipeline.md`. A proposal is
|
|
7
|
+
only eligible to advance to `stage: gated` if every check here passes.
|
|
8
|
+
|
|
9
|
+
Gate checks (all hard):
|
|
10
|
+
1. Frontmatter complete — proposal_id, type, scope, stage, author,
|
|
11
|
+
created, last_updated.
|
|
12
|
+
2. Type / scope / stage values are from the documented vocabulary.
|
|
13
|
+
3. Evidence block — ≥2 entries under `evidence:`, each with distinct
|
|
14
|
+
`ref` value. At least two distinct hosts/repos/paths.
|
|
15
|
+
4. No "TODO" / "TBD" / "xxx" markers in the draft body.
|
|
16
|
+
5. Required sections all present (1..10 per template).
|
|
17
|
+
6. Success signal — Section 7 has a concrete metric, target, and
|
|
18
|
+
evaluation date.
|
|
19
|
+
|
|
20
|
+
Exit codes: 0 = pass, 1 = gate failure, 2 = PyYAML missing, 3 = internal error.
|
|
21
|
+
|
|
22
|
+
Usage:
|
|
23
|
+
python3 scripts/check_proposal.py agents/proposals/my-proposal.md
|
|
24
|
+
python3 scripts/check_proposal.py --format json path/to.md
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
import argparse
|
|
30
|
+
import json
|
|
31
|
+
import re
|
|
32
|
+
import sys
|
|
33
|
+
from dataclasses import dataclass, asdict
|
|
34
|
+
from pathlib import Path
|
|
35
|
+
from typing import List, Literal, Tuple
|
|
36
|
+
from urllib.parse import urlparse
|
|
37
|
+
|
|
38
|
+
Severity = Literal["error", "warning"]
|
|
39
|
+
|
|
40
|
+
REQUIRED_FRONTMATTER = {
|
|
41
|
+
"proposal_id", "type", "scope", "stage",
|
|
42
|
+
"author", "created", "last_updated",
|
|
43
|
+
}
|
|
44
|
+
VALID_TYPES = {"rule", "skill", "command", "guideline"}
|
|
45
|
+
VALID_SCOPES = {"project", "package"}
|
|
46
|
+
VALID_STAGES = {"captured", "classified", "proposed", "gated", "upstream"}
|
|
47
|
+
REQUIRED_SECTIONS: List[Tuple[str, str]] = [
|
|
48
|
+
(r"^##\s+1\.\s+Learning\b", "1. Learning"),
|
|
49
|
+
(r"^##\s+2\.\s+Classification\b", "2. Classification"),
|
|
50
|
+
(r"^##\s+3\.\s+Evidence\b", "3. Evidence"),
|
|
51
|
+
(r"^##\s+4\.\s+Proposed artefact\b", "4. Proposed artefact"),
|
|
52
|
+
(r"^##\s+5\.\s+Quality gate expectations\b", "5. Quality gate expectations"),
|
|
53
|
+
(r"^##\s+6\.\s+Replacement justification\b", "6. Replacement justification"),
|
|
54
|
+
(r"^##\s+7\.\s+Success signal\b", "7. Success signal"),
|
|
55
|
+
(r"^##\s+8\.\s+Risks and alternatives rejected\b", "8. Risks and alternatives rejected"),
|
|
56
|
+
(r"^##\s+9\.\s+Gate verdict\b", "9. Gate verdict"),
|
|
57
|
+
(r"^##\s+10\.\s+Upstream PR\b", "10. Upstream PR"),
|
|
58
|
+
]
|
|
59
|
+
BAD_MARKERS = re.compile(r"\b(TODO|TBD|FIXME|XXX)\b")
|
|
60
|
+
FRONTMATTER_PATTERN = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass
|
|
64
|
+
class Finding:
|
|
65
|
+
severity: Severity
|
|
66
|
+
section: str
|
|
67
|
+
message: str
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _load_frontmatter(text: str) -> dict:
|
|
71
|
+
match = FRONTMATTER_PATTERN.match(text)
|
|
72
|
+
if not match:
|
|
73
|
+
return {}
|
|
74
|
+
try:
|
|
75
|
+
import yaml
|
|
76
|
+
except ImportError:
|
|
77
|
+
print("error: PyYAML not installed. Run `pip install pyyaml`.", file=sys.stderr)
|
|
78
|
+
sys.exit(2)
|
|
79
|
+
return yaml.safe_load(match.group(1)) or {}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _body_after_frontmatter(text: str) -> str:
|
|
83
|
+
match = FRONTMATTER_PATTERN.match(text)
|
|
84
|
+
return text[match.end():] if match else text
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _check_frontmatter(fm: dict, findings: List[Finding]):
|
|
88
|
+
missing = REQUIRED_FRONTMATTER - set(fm.keys())
|
|
89
|
+
for key in sorted(missing):
|
|
90
|
+
findings.append(Finding("error", "frontmatter", f"missing: {key}"))
|
|
91
|
+
if fm.get("type") and fm["type"] not in VALID_TYPES:
|
|
92
|
+
findings.append(Finding("error", "frontmatter",
|
|
93
|
+
f"invalid type '{fm['type']}'"))
|
|
94
|
+
if fm.get("scope") and fm["scope"] not in VALID_SCOPES:
|
|
95
|
+
findings.append(Finding("error", "frontmatter",
|
|
96
|
+
f"invalid scope '{fm['scope']}'"))
|
|
97
|
+
if fm.get("stage") and fm["stage"] not in VALID_STAGES:
|
|
98
|
+
findings.append(Finding("error", "frontmatter",
|
|
99
|
+
f"invalid stage '{fm['stage']}'"))
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _check_sections(body: str, findings: List[Finding]):
|
|
103
|
+
for pattern, name in REQUIRED_SECTIONS:
|
|
104
|
+
if not re.search(pattern, body, flags=re.MULTILINE):
|
|
105
|
+
findings.append(Finding("error", "sections", f"missing section: {name}"))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _extract_evidence_refs(body: str) -> List[str]:
|
|
109
|
+
refs: List[str] = []
|
|
110
|
+
ev_match = re.search(r"^##\s+3\.\s+Evidence\b(.+?)(?=^##\s)", body,
|
|
111
|
+
flags=re.DOTALL | re.MULTILINE)
|
|
112
|
+
if not ev_match:
|
|
113
|
+
return refs
|
|
114
|
+
for line in ev_match.group(1).splitlines():
|
|
115
|
+
m = re.match(r"\s*-?\s*ref:\s*(\S+)", line)
|
|
116
|
+
if m:
|
|
117
|
+
refs.append(m.group(1).strip())
|
|
118
|
+
return refs
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _check_evidence(body: str, findings: List[Finding]):
|
|
122
|
+
refs = _extract_evidence_refs(body)
|
|
123
|
+
if len(refs) < 2:
|
|
124
|
+
findings.append(Finding("error", "evidence",
|
|
125
|
+
f"need ≥2 evidence refs, found {len(refs)}"))
|
|
126
|
+
return
|
|
127
|
+
# Independence — two distinct hosts OR two distinct paths.
|
|
128
|
+
hosts = {urlparse(r).netloc or r for r in refs}
|
|
129
|
+
paths = {urlparse(r).path.rsplit("/", 2)[-2:] and urlparse(r).path for r in refs}
|
|
130
|
+
if len(hosts) < 2 and len({tuple(urlparse(r).path.strip("/").split("/")[:2]) for r in refs}) < 2:
|
|
131
|
+
findings.append(Finding("warning", "evidence",
|
|
132
|
+
"evidence refs look similar — verify independence"))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _strip_html_comments(text: str) -> str:
|
|
136
|
+
return re.sub(r"<!--.*?-->", "", text, flags=re.DOTALL)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _check_markers(body: str, findings: List[Finding]):
|
|
140
|
+
stripped = _strip_html_comments(body)
|
|
141
|
+
for line_no, line in enumerate(stripped.splitlines(), 1):
|
|
142
|
+
if line.lstrip().startswith("//"):
|
|
143
|
+
continue
|
|
144
|
+
if BAD_MARKERS.search(line):
|
|
145
|
+
findings.append(Finding("error", "markers",
|
|
146
|
+
f"draft placeholder on line {line_no}: {line.strip()[:60]}"))
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _check_success_signal(body: str, findings: List[Finding]):
|
|
150
|
+
m = re.search(r"^##\s+7\.\s+Success signal\b(.+?)(?=^##\s)", body,
|
|
151
|
+
flags=re.DOTALL | re.MULTILINE)
|
|
152
|
+
if not m:
|
|
153
|
+
return
|
|
154
|
+
sect = m.group(1)
|
|
155
|
+
for label in ("Metric:", "Baseline:", "Target:", "Evaluation date:"):
|
|
156
|
+
if label not in sect:
|
|
157
|
+
findings.append(Finding("error", "success-signal",
|
|
158
|
+
f"missing '{label}' entry"))
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _check_originating_project(body: str, fm: dict,
|
|
162
|
+
findings: List[Finding]):
|
|
163
|
+
"""Section 10 must name the originating project once stage=upstream.
|
|
164
|
+
|
|
165
|
+
`originating_project` is metadata only — the linter does NOT check
|
|
166
|
+
for specific identifiers. It only ensures the slot is filled so the
|
|
167
|
+
Q2 outcome measurement can group merged proposals by consumer repo.
|
|
168
|
+
"""
|
|
169
|
+
if fm.get("stage") != "upstream":
|
|
170
|
+
return
|
|
171
|
+
m = re.search(r"^##\s+10\.\s+Upstream PR\b(.+?)(?:^##\s|\Z)", body,
|
|
172
|
+
flags=re.DOTALL | re.MULTILINE)
|
|
173
|
+
sect = m.group(1) if m else ""
|
|
174
|
+
if "Originating project:" not in sect:
|
|
175
|
+
findings.append(Finding("error", "originating-project",
|
|
176
|
+
"Section 10 must include 'Originating "
|
|
177
|
+
"project: <slug>' when stage=upstream"))
|
|
178
|
+
return
|
|
179
|
+
line = re.search(r"Originating project:\s*(.*)", sect)
|
|
180
|
+
value = (line.group(1).strip() if line else "")
|
|
181
|
+
if not value or value.startswith("<") or value in {"-", "…", "TBD"}:
|
|
182
|
+
findings.append(Finding("error", "originating-project",
|
|
183
|
+
"Originating project slot is empty or "
|
|
184
|
+
"left as template placeholder"))
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _proposal_rate_warning(path: Path, findings: List[Finding],
|
|
188
|
+
limit: int = 6, window_days: int = 90) -> None:
|
|
189
|
+
"""Soft cap: warn if the proposals/ directory already holds `limit`
|
|
190
|
+
proposals authored within the last `window_days`.
|
|
191
|
+
|
|
192
|
+
Never a hard block — the Stage-4 gate does not adjudicate volume.
|
|
193
|
+
The goal is to surface a consumer that is over-fitting the package.
|
|
194
|
+
"""
|
|
195
|
+
import datetime as dt
|
|
196
|
+
parent = path.parent
|
|
197
|
+
if parent.name != "proposals":
|
|
198
|
+
return
|
|
199
|
+
cutoff = dt.date.today() - dt.timedelta(days=window_days)
|
|
200
|
+
recent = 0
|
|
201
|
+
for md in parent.glob("*.md"):
|
|
202
|
+
if md.resolve() == path.resolve():
|
|
203
|
+
continue
|
|
204
|
+
try:
|
|
205
|
+
text = md.read_text(encoding="utf-8", errors="replace")
|
|
206
|
+
except OSError:
|
|
207
|
+
continue
|
|
208
|
+
fm_m = FRONTMATTER_PATTERN.match(text)
|
|
209
|
+
if not fm_m:
|
|
210
|
+
continue
|
|
211
|
+
created_m = re.search(r"^created:\s*(\S+)", fm_m.group(1),
|
|
212
|
+
flags=re.MULTILINE)
|
|
213
|
+
if not created_m:
|
|
214
|
+
continue
|
|
215
|
+
try:
|
|
216
|
+
created = dt.date.fromisoformat(created_m.group(1).strip())
|
|
217
|
+
except ValueError:
|
|
218
|
+
continue
|
|
219
|
+
if created >= cutoff:
|
|
220
|
+
recent += 1
|
|
221
|
+
if recent >= limit:
|
|
222
|
+
findings.append(Finding(
|
|
223
|
+
"warning", "rate-limit",
|
|
224
|
+
f"{recent} proposals in the last {window_days}d — consider "
|
|
225
|
+
"bundling or pruning; the package is a public good, not a "
|
|
226
|
+
"per-project scratchpad",
|
|
227
|
+
))
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _run_checks(text: str, path: Path | None = None) -> List[Finding]:
|
|
231
|
+
findings: List[Finding] = []
|
|
232
|
+
fm = _load_frontmatter(text)
|
|
233
|
+
_check_frontmatter(fm, findings)
|
|
234
|
+
body = _body_after_frontmatter(text)
|
|
235
|
+
_check_sections(body, findings)
|
|
236
|
+
_check_evidence(body, findings)
|
|
237
|
+
_check_markers(body, findings)
|
|
238
|
+
_check_success_signal(body, findings)
|
|
239
|
+
_check_originating_project(body, fm, findings)
|
|
240
|
+
if path is not None:
|
|
241
|
+
_proposal_rate_warning(path, findings)
|
|
242
|
+
return findings
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def main() -> int:
|
|
246
|
+
ap = argparse.ArgumentParser(description=__doc__)
|
|
247
|
+
ap.add_argument("path", help="Path to the proposal .md file")
|
|
248
|
+
ap.add_argument("--format", choices=["text", "json"], default="text")
|
|
249
|
+
args = ap.parse_args()
|
|
250
|
+
path = Path(args.path)
|
|
251
|
+
if not path.exists():
|
|
252
|
+
print(f"error: {path} not found", file=sys.stderr)
|
|
253
|
+
return 3
|
|
254
|
+
findings = _run_checks(path.read_text(encoding="utf-8"), path=path)
|
|
255
|
+
errors = [f for f in findings if f.severity == "error"]
|
|
256
|
+
if args.format == "json":
|
|
257
|
+
print(json.dumps({"findings": [asdict(f) for f in findings]}, indent=2))
|
|
258
|
+
else:
|
|
259
|
+
for f in findings:
|
|
260
|
+
icon = "❌" if f.severity == "error" else "⚠️"
|
|
261
|
+
print(f" {icon} [{f.section}] {f.message}")
|
|
262
|
+
print(f"\nSummary: {len(errors)} error(s), "
|
|
263
|
+
f"{sum(1 for f in findings if f.severity == 'warning')} warning(s)")
|
|
264
|
+
print(f"Verdict: {'BLOCK' if errors else 'PASS'}")
|
|
265
|
+
return 1 if errors else 0
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
if __name__ == "__main__":
|
|
269
|
+
sys.exit(main())
|