@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,159 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
MCP config renderer — one ``mcp.json`` → per-tool output files.
|
|
4
|
+
|
|
5
|
+
Reads ``mcp.json`` at repo root (``{ "servers": { <name>: { command, args,
|
|
6
|
+
env, cwd } } }``), substitutes ``${env:VAR}`` placeholders from the
|
|
7
|
+
environment, and writes each target tool's concrete config format.
|
|
8
|
+
|
|
9
|
+
Targets:
|
|
10
|
+
.cursor/mcp.json (in-project)
|
|
11
|
+
.windsurf/mcp.json (in-project)
|
|
12
|
+
~/.config/claude-desktop/claude_desktop_config.json (user, opt-in)
|
|
13
|
+
|
|
14
|
+
All targets use the same ``mcpServers`` top-level key. The source file
|
|
15
|
+
uses ``servers`` to keep our internal schema stable if a downstream
|
|
16
|
+
format ever diverges.
|
|
17
|
+
|
|
18
|
+
Failure mode: unresolved ``${env:VAR}`` placeholders are collected first,
|
|
19
|
+
then reported together and a non-zero exit is raised. No target file is
|
|
20
|
+
written when any placeholder is missing.
|
|
21
|
+
|
|
22
|
+
See docs/mcp.md for schema, usage, and worked examples.
|
|
23
|
+
"""
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import argparse
|
|
27
|
+
import json
|
|
28
|
+
import os
|
|
29
|
+
import re
|
|
30
|
+
import sys
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
from typing import Any
|
|
33
|
+
|
|
34
|
+
PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
|
35
|
+
SOURCE_FILE = PROJECT_ROOT / "mcp.json"
|
|
36
|
+
|
|
37
|
+
ENV_PLACEHOLDER = re.compile(r"\$\{env:([^}]+)\}")
|
|
38
|
+
|
|
39
|
+
# In-project targets. Claude Desktop is user-scope, opt-in via --claude-desktop.
|
|
40
|
+
IN_PROJECT_TARGETS: dict[str, Path] = {
|
|
41
|
+
"cursor": PROJECT_ROOT / ".cursor" / "mcp.json",
|
|
42
|
+
"windsurf": PROJECT_ROOT / ".windsurf" / "mcp.json",
|
|
43
|
+
}
|
|
44
|
+
CLAUDE_DESKTOP_TARGET = Path.home() / ".config" / "claude-desktop" / "claude_desktop_config.json"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def substitute(value: Any, path: str, missing: list[tuple[str, str]]) -> Any:
|
|
48
|
+
"""Recursively substitute ${env:VAR} in strings.
|
|
49
|
+
|
|
50
|
+
Missing variables are appended to ``missing`` as ``(var_name, json_path)``
|
|
51
|
+
instead of raising, so a single run surfaces *all* gaps at once.
|
|
52
|
+
"""
|
|
53
|
+
if isinstance(value, str):
|
|
54
|
+
def repl(match: re.Match[str]) -> str:
|
|
55
|
+
name = match.group(1)
|
|
56
|
+
env_value = os.environ.get(name)
|
|
57
|
+
if env_value is None:
|
|
58
|
+
missing.append((name, path))
|
|
59
|
+
return match.group(0)
|
|
60
|
+
return env_value
|
|
61
|
+
return ENV_PLACEHOLDER.sub(repl, value)
|
|
62
|
+
if isinstance(value, dict):
|
|
63
|
+
return {k: substitute(v, f"{path}.{k}", missing) for k, v in value.items()}
|
|
64
|
+
if isinstance(value, list):
|
|
65
|
+
return [substitute(v, f"{path}[{i}]", missing) for i, v in enumerate(value)]
|
|
66
|
+
return value
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def load_source(source: Path) -> dict[str, Any]:
|
|
70
|
+
if not source.exists():
|
|
71
|
+
raise SystemExit(f"❌ Source file not found: {source}")
|
|
72
|
+
try:
|
|
73
|
+
data = json.loads(source.read_text(encoding="utf-8"))
|
|
74
|
+
except json.JSONDecodeError as exc:
|
|
75
|
+
raise SystemExit(f"❌ Invalid JSON in {source}: {exc}") from exc
|
|
76
|
+
if not isinstance(data, dict) or "servers" not in data or not isinstance(data["servers"], dict):
|
|
77
|
+
raise SystemExit(f"❌ {source} must contain a top-level 'servers' object.")
|
|
78
|
+
return data
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def render(data: dict[str, Any]) -> tuple[dict[str, Any], list[tuple[str, str]]]:
|
|
82
|
+
"""Return (rendered, missing). Caller decides what to do on missing."""
|
|
83
|
+
missing: list[tuple[str, str]] = []
|
|
84
|
+
resolved_servers = substitute(data["servers"], "servers", missing)
|
|
85
|
+
return {"mcpServers": resolved_servers}, missing
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def format_missing_report(missing: list[tuple[str, str]]) -> str:
|
|
89
|
+
grouped: dict[str, list[str]] = {}
|
|
90
|
+
for name, path in missing:
|
|
91
|
+
grouped.setdefault(name, []).append(path)
|
|
92
|
+
lines = [f"❌ Unresolved ${{env:VAR}} placeholders ({len(grouped)} variable(s)):"]
|
|
93
|
+
for name in sorted(grouped):
|
|
94
|
+
lines.append(f" - {name} used at:")
|
|
95
|
+
for path in grouped[name]:
|
|
96
|
+
lines.append(f" {path}")
|
|
97
|
+
lines.append("\nSet the variable(s) in your environment and re-run.")
|
|
98
|
+
return "\n".join(lines)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def write_target(path: Path, content: dict[str, Any]) -> None:
|
|
102
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
103
|
+
serialized = json.dumps(content, indent=2, sort_keys=True) + "\n"
|
|
104
|
+
path.write_text(serialized, encoding="utf-8")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def collect_targets(include_claude_desktop: bool) -> dict[str, Path]:
|
|
108
|
+
targets = dict(IN_PROJECT_TARGETS)
|
|
109
|
+
if include_claude_desktop:
|
|
110
|
+
targets["claude-desktop"] = CLAUDE_DESKTOP_TARGET
|
|
111
|
+
return targets
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def cmd_render(args: argparse.Namespace) -> int:
|
|
115
|
+
data = load_source(Path(args.source))
|
|
116
|
+
rendered, missing = render(data)
|
|
117
|
+
if missing:
|
|
118
|
+
print(format_missing_report(missing), file=sys.stderr)
|
|
119
|
+
return 1
|
|
120
|
+
targets = collect_targets(args.claude_desktop)
|
|
121
|
+
for name, path in targets.items():
|
|
122
|
+
write_target(path, rendered)
|
|
123
|
+
print(f"✅ {name:16} → {path}")
|
|
124
|
+
return 0
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def cmd_check(args: argparse.Namespace) -> int:
|
|
128
|
+
data = load_source(Path(args.source))
|
|
129
|
+
rendered, missing = render(data)
|
|
130
|
+
if missing:
|
|
131
|
+
print(format_missing_report(missing), file=sys.stderr)
|
|
132
|
+
return 1
|
|
133
|
+
serialized = json.dumps(rendered, indent=2, sort_keys=True) + "\n"
|
|
134
|
+
targets = collect_targets(args.claude_desktop)
|
|
135
|
+
diffs = []
|
|
136
|
+
for name, path in targets.items():
|
|
137
|
+
actual = path.read_text(encoding="utf-8") if path.exists() else ""
|
|
138
|
+
if actual != serialized:
|
|
139
|
+
diffs.append((name, path))
|
|
140
|
+
if diffs:
|
|
141
|
+
print("❌ Targets out of date (run `task mcp:render`):", file=sys.stderr)
|
|
142
|
+
for name, path in diffs:
|
|
143
|
+
print(f" - {name}: {path}", file=sys.stderr)
|
|
144
|
+
return 1
|
|
145
|
+
print("✅ All MCP targets match source.")
|
|
146
|
+
return 0
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def main(argv: list[str] | None = None) -> int:
|
|
150
|
+
parser = argparse.ArgumentParser(description="Render mcp.json → per-tool config files.")
|
|
151
|
+
parser.add_argument("--source", default=str(SOURCE_FILE), help="Source mcp.json (default: repo root)")
|
|
152
|
+
parser.add_argument("--claude-desktop", action="store_true", help="Also write Claude Desktop user-scope config")
|
|
153
|
+
parser.add_argument("--check", action="store_true", help="Dry-run; exit non-zero if targets are stale")
|
|
154
|
+
args = parser.parse_args(argv)
|
|
155
|
+
return cmd_check(args) if args.check else cmd_render(args)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
if __name__ == "__main__":
|
|
159
|
+
sys.exit(main())
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Measure presence of the eight Phase-3.1 judge patterns across all skills.
|
|
4
|
+
|
|
5
|
+
Produces the before/after baseline for
|
|
6
|
+
`agents/roadmaps/road-to-stronger-skills.md`. Zero side-effects: this is a
|
|
7
|
+
read-only reporter. No skill file is ever mutated.
|
|
8
|
+
|
|
9
|
+
Patterns (see road-to-stronger-skills.md for definitions):
|
|
10
|
+
1. System-prompt opening (blockquote role frame under the top heading)
|
|
11
|
+
2. Scope routing (`route to [sibling]` inside "Do NOT use when")
|
|
12
|
+
3. Validation gate (`## Validation` appears before `## Output format`)
|
|
13
|
+
4. Ordered output fields (numbered required-fields list)
|
|
14
|
+
5. Severity legend (🔴/🟡/🟢 with concrete definitions)
|
|
15
|
+
6. References section with at least one URL
|
|
16
|
+
7. Runtime boundary disclaimer
|
|
17
|
+
8. Anti-sycophancy rules in "Do NOT"
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
python3 scripts/measure_patterns.py # human table, grouped by tier
|
|
21
|
+
python3 scripts/measure_patterns.py --json # machine-readable summary
|
|
22
|
+
python3 scripts/measure_patterns.py --tier 1 # only Tier-1 skills
|
|
23
|
+
python3 scripts/measure_patterns.py --diff-baseline <file.json>
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import argparse
|
|
28
|
+
import json
|
|
29
|
+
import re
|
|
30
|
+
import sys
|
|
31
|
+
from dataclasses import dataclass, asdict, field
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
from typing import Iterable
|
|
34
|
+
|
|
35
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
36
|
+
SKILLS_DIR = ROOT / ".agent-src.uncompressed" / "skills"
|
|
37
|
+
|
|
38
|
+
# Tier assignments mirror agents/roadmaps/road-to-stronger-skills.md.
|
|
39
|
+
# "compliant" = already meets the target patterns (the four Phase-3.1 judges).
|
|
40
|
+
TIERS: dict[str, int | str] = {
|
|
41
|
+
# Tier 1 — Verdict / Review / Gate (patterns 1-8)
|
|
42
|
+
"adversarial-review": 1, "authz-review": 1, "code-review": 1,
|
|
43
|
+
"design-review": 1, "performance-analysis": 1, "project-analyzer": 1,
|
|
44
|
+
"readme-reviewer": 1, "receiving-code-review": 1,
|
|
45
|
+
"requesting-code-review": 1, "security-audit": 1, "skill-reviewer": 1,
|
|
46
|
+
"threat-modeling": 1, "validate-feature-fit": 1,
|
|
47
|
+
"verify-before-complete": 1,
|
|
48
|
+
# Tier 2 — Analysis / Investigation / Orchestration (patterns 1-4, +6)
|
|
49
|
+
"agent-docs-writing": 2, "analysis-autonomous-mode": 2,
|
|
50
|
+
"analysis-skill-router": 2, "blast-radius-analyzer": 2,
|
|
51
|
+
"bug-analyzer": 2, "code-refactoring": 2, "data-flow-mapper": 2,
|
|
52
|
+
"command-routing": 2, "copilot-agents-optimization": 2,
|
|
53
|
+
"description-assist": 2, "developer-like-execution": 2,
|
|
54
|
+
"feature-planning": 2, "learning-to-rule-or-skill": 2,
|
|
55
|
+
"project-analysis-core": 2, "project-analysis-hypothesis-driven": 2,
|
|
56
|
+
"project-analysis-laravel": 2, "project-analysis-nextjs": 2,
|
|
57
|
+
"project-analysis-node-express": 2, "project-analysis-react": 2,
|
|
58
|
+
"project-analysis-symfony": 2, "project-analysis-zend-laminas": 2,
|
|
59
|
+
"sequential-thinking": 2, "skill-improvement-pipeline": 2,
|
|
60
|
+
"subagent-orchestration": 2, "systematic-debugging": 2,
|
|
61
|
+
"universal-project-analysis": 2,
|
|
62
|
+
# Tier 3 — Coding / Authoring / Doing (patterns 1+2)
|
|
63
|
+
"api-design": 3, "api-endpoint": 3, "api-testing": 3,
|
|
64
|
+
"artisan-commands": 3, "blade-ui": 3, "command-writing": 3,
|
|
65
|
+
"composer-packages": 3, "context-document": 3,
|
|
66
|
+
"conventional-commits-writing": 3, "dashboard-design": 3,
|
|
67
|
+
"dependency-upgrade": 3, "dto-creator": 3, "eloquent": 3,
|
|
68
|
+
"fe-design": 3, "finishing-a-development-branch": 3, "flux": 3,
|
|
69
|
+
"git-workflow": 3, "guideline-writing": 3, "jobs-events": 3,
|
|
70
|
+
"laravel": 3, "laravel-horizon": 3, "laravel-mail": 3,
|
|
71
|
+
"laravel-middleware": 3, "laravel-notifications": 3,
|
|
72
|
+
"laravel-pennant": 3, "laravel-pulse": 3, "laravel-reverb": 3,
|
|
73
|
+
"laravel-scheduling": 3, "laravel-validation": 3, "livewire": 3,
|
|
74
|
+
"logging-monitoring": 3, "merge-conflicts": 3, "migration-creator": 3,
|
|
75
|
+
"module-management": 3, "openapi": 3, "override-management": 3,
|
|
76
|
+
"pest-testing": 3, "php-coder": 3, "php-debugging": 3,
|
|
77
|
+
"php-service": 3, "playwright-testing": 3, "readme-writing": 3,
|
|
78
|
+
"readme-writing-package": 3, "roadmap-management": 3, "rule-writing": 3,
|
|
79
|
+
"skill-management": 3, "skill-writing": 3, "sql-writing": 3,
|
|
80
|
+
"technical-specification": 3, "test-driven-development": 3,
|
|
81
|
+
"test-performance": 3, "upstream-contribute": 3,
|
|
82
|
+
"using-git-worktrees": 3,
|
|
83
|
+
# Tier 4 — Reference / Tooling / Integration (pattern 2 where siblings)
|
|
84
|
+
"aws-infrastructure": 4, "check-refs": 4, "copilot-config": 4,
|
|
85
|
+
"database": 4, "devcontainer": 4, "docker": 4, "file-editor": 4,
|
|
86
|
+
"github-ci": 4, "grafana": 4, "jira-integration": 4, "lint-skills": 4,
|
|
87
|
+
"mcp": 4, "multi-tenancy": 4, "performance": 4, "project-docs": 4,
|
|
88
|
+
"quality-tools": 4, "rtk-output-filtering": 4, "security": 4,
|
|
89
|
+
"sentry-integration": 4, "terraform": 4, "terragrunt": 4,
|
|
90
|
+
"traefik": 4, "websocket": 4,
|
|
91
|
+
# Already compliant (the four Phase-3.1 judges)
|
|
92
|
+
"judge-bug-hunter": "compliant", "judge-code-quality": "compliant",
|
|
93
|
+
"judge-security-auditor": "compliant",
|
|
94
|
+
"judge-test-coverage": "compliant",
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Which patterns count as "required" per tier. Skipped patterns are still
|
|
98
|
+
# reported (so we can see the footprint) but do not affect compliance score.
|
|
99
|
+
TIER_TARGETS: dict[int | str, set[int]] = {
|
|
100
|
+
1: {1, 2, 3, 4, 5, 6, 7, 8},
|
|
101
|
+
2: {1, 2, 3, 4}, # pattern 6 optional, measured separately
|
|
102
|
+
3: {1, 2},
|
|
103
|
+
4: {2},
|
|
104
|
+
"compliant": set(), # reference baseline — already green
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass
|
|
109
|
+
class Detection:
|
|
110
|
+
skill: str
|
|
111
|
+
tier: int | str
|
|
112
|
+
patterns: dict[int, bool] = field(default_factory=dict)
|
|
113
|
+
score: float = 0.0
|
|
114
|
+
required: int = 0
|
|
115
|
+
present: int = 0
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _section_indices(text: str) -> dict[str, tuple[int, int]]:
|
|
119
|
+
"""Return {section_title: (start_char, end_char)} for each ## heading."""
|
|
120
|
+
headings = [(m.start(), m.group(1).strip())
|
|
121
|
+
for m in re.finditer(r"^##\s+(.+?)\s*$", text, re.MULTILINE)]
|
|
122
|
+
sections: dict[str, tuple[int, int]] = {}
|
|
123
|
+
for i, (start, title) in enumerate(headings):
|
|
124
|
+
end = headings[i + 1][0] if i + 1 < len(headings) else len(text)
|
|
125
|
+
sections[title] = (start, end)
|
|
126
|
+
return sections
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _body_after_top_heading(text: str) -> str:
|
|
131
|
+
"""Return the slice between the first `# ` heading and the first `## `."""
|
|
132
|
+
m = re.search(r"^#\s+.+$", text, re.MULTILINE)
|
|
133
|
+
if not m:
|
|
134
|
+
return ""
|
|
135
|
+
after = text[m.end():]
|
|
136
|
+
m2 = re.search(r"^##\s+", after, re.MULTILINE)
|
|
137
|
+
return after[:m2.start()] if m2 else after
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def detect_pattern_1(text: str) -> bool:
|
|
141
|
+
"""System-prompt opening: blockquote role frame under the top heading."""
|
|
142
|
+
body = _body_after_top_heading(text)
|
|
143
|
+
for line in body.splitlines():
|
|
144
|
+
s = line.strip()
|
|
145
|
+
if not s:
|
|
146
|
+
continue
|
|
147
|
+
if s.startswith(">"):
|
|
148
|
+
quote = s.lstrip("> ").strip()
|
|
149
|
+
return bool(re.match(r"You are (a|an|the)\s", quote))
|
|
150
|
+
return False
|
|
151
|
+
return False
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def detect_pattern_2(text: str, sections: dict[str, tuple[int, int]]) -> bool:
|
|
155
|
+
"""Scope routing with an explicit sibling link in the When/Do-NOT area."""
|
|
156
|
+
candidates = [t for t in sections
|
|
157
|
+
if re.match(r"(when to use|do\s*not\s*use\s*when)", t, re.I)]
|
|
158
|
+
chunk = text if not candidates else \
|
|
159
|
+
text[sections[candidates[0]][0]:sections[candidates[0]][1]]
|
|
160
|
+
return bool(re.search(
|
|
161
|
+
r"route to\s*\[`?[a-z0-9-]+`?\]\([^)]*SKILL\.md\)", chunk, re.I))
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def detect_pattern_3(text: str, sections: dict[str, tuple[int, int]]) -> bool:
|
|
165
|
+
"""Validation gate appears as its own section before Output format."""
|
|
166
|
+
val_start = next((s for t, (s, _) in sections.items()
|
|
167
|
+
if t.lower().startswith("validation")), None)
|
|
168
|
+
out_start = next((s for t, (s, _) in sections.items()
|
|
169
|
+
if t.lower().startswith("output")), None)
|
|
170
|
+
if val_start is None or out_start is None or val_start >= out_start:
|
|
171
|
+
return False
|
|
172
|
+
for title, (start, end) in sections.items():
|
|
173
|
+
if title.lower().startswith("validation"):
|
|
174
|
+
body = text[start:end]
|
|
175
|
+
if re.search(r"before finalizing", body, re.I):
|
|
176
|
+
return True
|
|
177
|
+
if len(re.findall(r"^\s*\d+\.\s+", body, re.MULTILINE)) >= 3:
|
|
178
|
+
return True
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def detect_pattern_4(text: str, sections: dict[str, tuple[int, int]]) -> bool:
|
|
183
|
+
"""Ordered output fields — explicit required-fields list."""
|
|
184
|
+
for title, (start, end) in sections.items():
|
|
185
|
+
if title.lower().startswith("output"):
|
|
186
|
+
if re.search(r"required fields\s*\(ordered\)", text[start:end], re.I):
|
|
187
|
+
return True
|
|
188
|
+
return False
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def detect_pattern_5(text: str) -> bool:
|
|
192
|
+
"""Severity legend: all three of 🔴 🟡 🟢 with concrete definitions."""
|
|
193
|
+
return bool(re.search(
|
|
194
|
+
r"🔴[^🔴🟡🟢]{3,}🟡[^🔴🟡🟢]{3,}🟢[^🔴🟡🟢]{3,}", text))
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def detect_pattern_6(text: str, sections: dict[str, tuple[int, int]]) -> bool:
|
|
198
|
+
"""References section present and contains at least one URL."""
|
|
199
|
+
for title, (start, end) in sections.items():
|
|
200
|
+
if title.lower() == "references":
|
|
201
|
+
return bool(re.search(r"https?://", text[start:end]))
|
|
202
|
+
return False
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def detect_pattern_7(text: str) -> bool:
|
|
206
|
+
"""Runtime boundary disclaimer — names what the skill does NOT execute."""
|
|
207
|
+
patterns = [
|
|
208
|
+
r"runtime confirmation.*(follow[- ]up|implementer)",
|
|
209
|
+
r"(the judge|this skill) does not execute",
|
|
210
|
+
r"(leaves|defers) runtime.*(to|for) the implementer",
|
|
211
|
+
r"is a follow[- ]up for the implementer",
|
|
212
|
+
]
|
|
213
|
+
return any(re.search(p, text, re.I) for p in patterns)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def detect_pattern_8(text: str, sections: dict[str, tuple[int, int]]) -> bool:
|
|
217
|
+
"""Anti-sycophancy rules in Do NOT section."""
|
|
218
|
+
body = "".join(text[s:e] + "\n" for t, (s, e) in sections.items()
|
|
219
|
+
if t.lower().startswith("do not"))
|
|
220
|
+
if not body:
|
|
221
|
+
return False
|
|
222
|
+
patterns = [
|
|
223
|
+
r"NEVER\s+return\s+`?\w+`?\s+out of politeness",
|
|
224
|
+
r"NEVER\s+silently\s+fall\s+back",
|
|
225
|
+
r"NEVER\s+rubber[- ]stamp",
|
|
226
|
+
r"NEVER\s+accept.*as (a )?substitute",
|
|
227
|
+
]
|
|
228
|
+
return any(re.search(p, body, re.I) for p in patterns)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
DETECTORS = {
|
|
232
|
+
1: detect_pattern_1, 2: detect_pattern_2, 3: detect_pattern_3,
|
|
233
|
+
4: detect_pattern_4, 5: detect_pattern_5, 6: detect_pattern_6,
|
|
234
|
+
7: detect_pattern_7, 8: detect_pattern_8,
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def scan_skill(path: Path) -> Detection:
|
|
240
|
+
name = path.parent.name
|
|
241
|
+
tier = TIERS.get(name, "unclassified")
|
|
242
|
+
text = path.read_text(encoding="utf-8")
|
|
243
|
+
sections = _section_indices(text)
|
|
244
|
+
results: dict[int, bool] = {}
|
|
245
|
+
for n, fn in DETECTORS.items():
|
|
246
|
+
try:
|
|
247
|
+
results[n] = (fn(text, sections)
|
|
248
|
+
if fn.__code__.co_argcount == 2 else fn(text))
|
|
249
|
+
except Exception:
|
|
250
|
+
results[n] = False
|
|
251
|
+
required = TIER_TARGETS.get(tier, set())
|
|
252
|
+
present = sum(1 for p in required if results.get(p))
|
|
253
|
+
score = (present / len(required)) if required else 1.0
|
|
254
|
+
return Detection(
|
|
255
|
+
skill=name, tier=tier, patterns=results,
|
|
256
|
+
score=round(score, 3), required=len(required), present=present,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def collect(root: Path) -> list[Detection]:
|
|
261
|
+
results: list[Detection] = []
|
|
262
|
+
for skill_md in sorted(root.glob("*/SKILL.md")):
|
|
263
|
+
results.append(scan_skill(skill_md))
|
|
264
|
+
return results
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _render_table(rows: Iterable[Detection], tier_filter: int | None) -> str:
|
|
268
|
+
lines = []
|
|
269
|
+
tiers_order: list[int | str] = [1, 2, 3, 4, "compliant", "unclassified"]
|
|
270
|
+
by_tier: dict[int | str, list[Detection]] = {t: [] for t in tiers_order}
|
|
271
|
+
for r in rows:
|
|
272
|
+
by_tier.setdefault(r.tier, []).append(r)
|
|
273
|
+
for tier in tiers_order:
|
|
274
|
+
group = by_tier.get(tier, [])
|
|
275
|
+
if not group:
|
|
276
|
+
continue
|
|
277
|
+
if tier_filter is not None and tier != tier_filter:
|
|
278
|
+
continue
|
|
279
|
+
label = f"Tier {tier}" if isinstance(tier, int) else f"{tier}"
|
|
280
|
+
required = TIER_TARGETS.get(tier, set())
|
|
281
|
+
lines.append(f"\n## {label} ({len(group)} skills, "
|
|
282
|
+
f"required patterns: {sorted(required) or '—'})")
|
|
283
|
+
lines.append("| Skill | Score | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |")
|
|
284
|
+
lines.append("|---|---:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|")
|
|
285
|
+
for r in sorted(group, key=lambda d: (-d.score, d.skill)):
|
|
286
|
+
cells = []
|
|
287
|
+
for p in range(1, 9):
|
|
288
|
+
has = r.patterns.get(p, False)
|
|
289
|
+
is_req = p in required
|
|
290
|
+
cells.append(
|
|
291
|
+
"✅" if has and is_req else
|
|
292
|
+
"☑️" if has else
|
|
293
|
+
"·" if not is_req else "❌"
|
|
294
|
+
)
|
|
295
|
+
pct = f"{int(r.score * 100)}%" if required else "—"
|
|
296
|
+
lines.append(f"| `{r.skill}` | {pct} | " + " | ".join(cells) + " |")
|
|
297
|
+
lines.append("\nLegend: ✅ required + present · ❌ required + missing · "
|
|
298
|
+
"☑️ present but optional · · not required")
|
|
299
|
+
return "\n".join(lines)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def _summary(rows: list[Detection]) -> dict:
|
|
303
|
+
agg: dict = {"total_skills": len(rows), "by_tier": {}}
|
|
304
|
+
for tier in [1, 2, 3, 4]:
|
|
305
|
+
group = [r for r in rows if r.tier == tier]
|
|
306
|
+
if not group:
|
|
307
|
+
continue
|
|
308
|
+
fully = sum(1 for r in group if r.score >= 1.0)
|
|
309
|
+
avg = round(sum(r.score for r in group) / len(group), 3)
|
|
310
|
+
agg["by_tier"][str(tier)] = {
|
|
311
|
+
"count": len(group),
|
|
312
|
+
"fully_compliant": fully,
|
|
313
|
+
"avg_score": avg,
|
|
314
|
+
"required_patterns": sorted(TIER_TARGETS[tier]),
|
|
315
|
+
}
|
|
316
|
+
return agg
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def main(argv: list[str] | None = None) -> int:
|
|
320
|
+
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
321
|
+
ap.add_argument("--json", action="store_true",
|
|
322
|
+
help="emit machine-readable JSON")
|
|
323
|
+
ap.add_argument("--tier", type=int, choices=[1, 2, 3, 4],
|
|
324
|
+
help="only report one tier")
|
|
325
|
+
ap.add_argument("--diff-baseline", type=Path,
|
|
326
|
+
help="JSON file from an earlier run to diff against")
|
|
327
|
+
args = ap.parse_args(argv)
|
|
328
|
+
|
|
329
|
+
if not SKILLS_DIR.is_dir():
|
|
330
|
+
print(f"ERROR: {SKILLS_DIR} not found", file=sys.stderr)
|
|
331
|
+
return 3
|
|
332
|
+
|
|
333
|
+
rows = collect(SKILLS_DIR)
|
|
334
|
+
|
|
335
|
+
if args.json:
|
|
336
|
+
payload = {
|
|
337
|
+
"summary": _summary(rows),
|
|
338
|
+
"skills": [asdict(r) for r in rows],
|
|
339
|
+
}
|
|
340
|
+
print(json.dumps(payload, indent=2, sort_keys=True))
|
|
341
|
+
return 0
|
|
342
|
+
|
|
343
|
+
summary = _summary(rows)
|
|
344
|
+
print(f"# Pattern Presence — {summary['total_skills']} skills scanned\n")
|
|
345
|
+
print("## Per-tier summary\n")
|
|
346
|
+
print("| Tier | Skills | Fully compliant | Avg score | Required |")
|
|
347
|
+
print("|---|---:|---:|---:|---|")
|
|
348
|
+
for t in [1, 2, 3, 4]:
|
|
349
|
+
info = summary["by_tier"].get(str(t))
|
|
350
|
+
if not info:
|
|
351
|
+
continue
|
|
352
|
+
print(f"| {t} | {info['count']} | {info['fully_compliant']} | "
|
|
353
|
+
f"{int(info['avg_score'] * 100)}% | "
|
|
354
|
+
f"{info['required_patterns']} |")
|
|
355
|
+
|
|
356
|
+
print(_render_table(rows, args.tier))
|
|
357
|
+
|
|
358
|
+
if args.diff_baseline and args.diff_baseline.is_file():
|
|
359
|
+
prev = json.loads(args.diff_baseline.read_text())
|
|
360
|
+
prev_by = {s["skill"]: s for s in prev.get("skills", [])}
|
|
361
|
+
moves = []
|
|
362
|
+
for r in rows:
|
|
363
|
+
p = prev_by.get(r.skill)
|
|
364
|
+
if p and p["score"] != r.score:
|
|
365
|
+
moves.append((r.skill, p["score"], r.score))
|
|
366
|
+
if moves:
|
|
367
|
+
print("\n## Changes since baseline\n")
|
|
368
|
+
for skill, old, new in sorted(moves, key=lambda m: m[2] - m[1]):
|
|
369
|
+
arrow = "⬆️" if new > old else "⬇️"
|
|
370
|
+
print(f"- {arrow} `{skill}`: "
|
|
371
|
+
f"{int(old * 100)}% → {int(new * 100)}%")
|
|
372
|
+
return 0
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
if __name__ == "__main__":
|
|
376
|
+
sys.exit(main())
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Content-addressed hash for a curated memory entry.
|
|
3
|
+
|
|
4
|
+
The hash is SHA-256 over the canonical-JSON-serialized entry, truncated
|
|
5
|
+
to the first 12 hex chars. Canonical JSON sorts object keys, uses no
|
|
6
|
+
extra whitespace, and normalises types so two equivalent entries hash
|
|
7
|
+
identically regardless of YAML formatting.
|
|
8
|
+
|
|
9
|
+
Used by `/memory-promote` to pick the filename
|
|
10
|
+
`agents/memory/<type>/<hash>.yml` so the same entry promoted on two
|
|
11
|
+
branches converges to a single file after `git merge`.
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
python3 scripts/memory_hash.py --yaml path/to/entry.yml
|
|
15
|
+
echo '{"id":"x"}' | python3 scripts/memory_hash.py --json-stdin
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import argparse
|
|
21
|
+
import hashlib
|
|
22
|
+
import json
|
|
23
|
+
import sys
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from typing import Any
|
|
26
|
+
|
|
27
|
+
HASH_LEN = 12
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def canonical_json(obj: Any) -> bytes:
|
|
31
|
+
return json.dumps(
|
|
32
|
+
obj,
|
|
33
|
+
sort_keys=True,
|
|
34
|
+
separators=(",", ":"),
|
|
35
|
+
ensure_ascii=False,
|
|
36
|
+
default=str,
|
|
37
|
+
).encode("utf-8")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def hash_entry(obj: Any) -> str:
|
|
41
|
+
return hashlib.sha256(canonical_json(obj)).hexdigest()[:HASH_LEN]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _load_yaml(path: Path) -> Any:
|
|
45
|
+
try:
|
|
46
|
+
import yaml
|
|
47
|
+
except ImportError:
|
|
48
|
+
print("error: PyYAML not installed. `pip install pyyaml`.",
|
|
49
|
+
file=sys.stderr)
|
|
50
|
+
sys.exit(2)
|
|
51
|
+
with path.open(encoding="utf-8") as fh:
|
|
52
|
+
return yaml.safe_load(fh)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def main() -> int:
|
|
56
|
+
ap = argparse.ArgumentParser(description=__doc__)
|
|
57
|
+
grp = ap.add_mutually_exclusive_group(required=True)
|
|
58
|
+
grp.add_argument("--yaml", help="YAML file containing one entry")
|
|
59
|
+
grp.add_argument("--json-stdin", action="store_true",
|
|
60
|
+
help="Read JSON object from stdin")
|
|
61
|
+
args = ap.parse_args()
|
|
62
|
+
if args.yaml:
|
|
63
|
+
entry = _load_yaml(Path(args.yaml))
|
|
64
|
+
else:
|
|
65
|
+
entry = json.load(sys.stdin)
|
|
66
|
+
if not isinstance(entry, (dict, list)):
|
|
67
|
+
print(f"error: expected object/array, got {type(entry).__name__}",
|
|
68
|
+
file=sys.stderr)
|
|
69
|
+
return 1
|
|
70
|
+
print(hash_entry(entry))
|
|
71
|
+
return 0
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if __name__ == "__main__":
|
|
75
|
+
sys.exit(main())
|