@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,580 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
README quality linter for agent-config repositories.
|
|
4
|
+
|
|
5
|
+
Detects weak, misleading, or incomplete READMEs by cross-checking
|
|
6
|
+
against actual repository files (Taskfile.yml, package.json, etc.).
|
|
7
|
+
|
|
8
|
+
Checks:
|
|
9
|
+
- Missing title, summary, installation, usage example
|
|
10
|
+
- Weak quickstart (example too far from install)
|
|
11
|
+
- Missing compatibility/requirements for packages
|
|
12
|
+
- Generic boilerplate phrases
|
|
13
|
+
- Command mismatches (documented but not in repo)
|
|
14
|
+
- Bad section order (architecture before install)
|
|
15
|
+
- Overloaded README (too long)
|
|
16
|
+
- Missing dev workflow when tests/CI exist
|
|
17
|
+
|
|
18
|
+
Exit codes:
|
|
19
|
+
0 = pass
|
|
20
|
+
1 = warnings only
|
|
21
|
+
2 = errors
|
|
22
|
+
3 = internal error
|
|
23
|
+
"""
|
|
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 List, Literal, Optional
|
|
34
|
+
|
|
35
|
+
Severity = Literal["error", "warning", "info"]
|
|
36
|
+
RepoType = Literal["package", "app", "cli", "internal", "unknown"]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# --- Patterns ---
|
|
40
|
+
|
|
41
|
+
H1_PATTERN = re.compile(r"^# .+", re.MULTILINE)
|
|
42
|
+
H2_PATTERN = re.compile(r"^## (.+?)\s*$", re.MULTILINE)
|
|
43
|
+
CODE_BLOCK_PATTERN = re.compile(r"```[\s\S]*?```", re.MULTILINE)
|
|
44
|
+
INLINE_COMMAND_PATTERN = re.compile(r"`((?:task|npm run|make)\s+[\w:_-]+(?:\s+[\w:_-]+)?)`")
|
|
45
|
+
|
|
46
|
+
# Built-in commands that are always valid (not custom scripts)
|
|
47
|
+
BUILTIN_COMMANDS = {
|
|
48
|
+
"composer install", "composer update", "composer require", "composer remove",
|
|
49
|
+
"npm install", "npm uninstall", "npm init", "npm test", "npm start",
|
|
50
|
+
"yarn add", "yarn remove", "yarn install",
|
|
51
|
+
"pnpm add", "pnpm remove", "pnpm install",
|
|
52
|
+
"php artisan", "cargo build", "cargo test", "go build", "go test",
|
|
53
|
+
"git clone", "git submodule",
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
INSTALL_HEADINGS = {
|
|
57
|
+
"installation", "install", "setup", "getting started", "quickstart",
|
|
58
|
+
"how to install", "installing",
|
|
59
|
+
}
|
|
60
|
+
USAGE_HEADINGS = {
|
|
61
|
+
"usage", "quickstart", "quick start", "getting started",
|
|
62
|
+
"how to use", "how it works", "basic usage", "examples",
|
|
63
|
+
"minimal example", "minimal usage",
|
|
64
|
+
}
|
|
65
|
+
COMPAT_HEADINGS = {
|
|
66
|
+
"requirements", "compatibility", "prerequisites", "supported versions",
|
|
67
|
+
"system requirements", "dependencies",
|
|
68
|
+
}
|
|
69
|
+
DEV_HEADINGS = {
|
|
70
|
+
"development", "contributing", "testing", "dev", "local development",
|
|
71
|
+
"developer guide", "running tests", "development setup",
|
|
72
|
+
}
|
|
73
|
+
ARCHITECTURE_HEADINGS = {
|
|
74
|
+
"architecture", "internals", "design", "how it works internally",
|
|
75
|
+
"technical details", "implementation",
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
GENERIC_BOILERPLATE = [
|
|
79
|
+
r"(?i)\bmodern and scalable\b",
|
|
80
|
+
r"(?i)\bpowerful and flexible\b",
|
|
81
|
+
r"(?i)\bsimple and intuitive\b",
|
|
82
|
+
r"(?i)\bblazing fast\b",
|
|
83
|
+
r"(?i)\bnext[- ]gen(?:eration)?\b",
|
|
84
|
+
r"(?i)\bworld[- ]class\b",
|
|
85
|
+
r"(?i)\bcutting[- ]edge\b",
|
|
86
|
+
r"(?i)\bseamless(?:ly)? integrat",
|
|
87
|
+
r"(?i)\brobust and reliable\b",
|
|
88
|
+
r"(?i)\blightweight yet powerful\b",
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
OVERLOADED_LINE_THRESHOLD = 500
|
|
92
|
+
WEAK_QUICKSTART_LINE_GAP = 80
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# --- Data classes ---
|
|
96
|
+
|
|
97
|
+
@dataclass
|
|
98
|
+
class Issue:
|
|
99
|
+
severity: Severity
|
|
100
|
+
code: str
|
|
101
|
+
message: str
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass
|
|
105
|
+
class ReadmeLintResult:
|
|
106
|
+
file: str
|
|
107
|
+
repo_type: RepoType
|
|
108
|
+
status: Literal["pass", "pass_with_warnings", "fail"]
|
|
109
|
+
issues: List[Issue]
|
|
110
|
+
line_count: int
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclass
|
|
114
|
+
class RepoContext:
|
|
115
|
+
"""Extracted context about the repository."""
|
|
116
|
+
repo_type: RepoType = "unknown"
|
|
117
|
+
has_composer: bool = False
|
|
118
|
+
has_package_json: bool = False
|
|
119
|
+
has_taskfile: bool = False
|
|
120
|
+
has_makefile: bool = False
|
|
121
|
+
has_dockerfile: bool = False
|
|
122
|
+
has_tests: bool = False
|
|
123
|
+
has_ci: bool = False
|
|
124
|
+
taskfile_tasks: list[str] = field(default_factory=list)
|
|
125
|
+
npm_scripts: list[str] = field(default_factory=list)
|
|
126
|
+
composer_scripts: list[str] = field(default_factory=list)
|
|
127
|
+
make_targets: list[str] = field(default_factory=list)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# --- Repo detection ---
|
|
131
|
+
|
|
132
|
+
def detect_repo_context(root: Path) -> RepoContext:
|
|
133
|
+
ctx = RepoContext()
|
|
134
|
+
ctx.has_composer = (root / "composer.json").exists()
|
|
135
|
+
ctx.has_package_json = (root / "package.json").exists()
|
|
136
|
+
ctx.has_taskfile = (root / "Taskfile.yml").exists() or (root / "Taskfile.yaml").exists()
|
|
137
|
+
ctx.has_makefile = (root / "Makefile").exists()
|
|
138
|
+
ctx.has_dockerfile = (root / "Dockerfile").exists() or (root / "docker-compose.yml").exists()
|
|
139
|
+
ctx.has_tests = (root / "tests").is_dir() or (root / "test").is_dir()
|
|
140
|
+
ctx.has_ci = (root / ".github" / "workflows").is_dir()
|
|
141
|
+
|
|
142
|
+
# Extract available commands
|
|
143
|
+
ctx.taskfile_tasks = _extract_taskfile_tasks(root)
|
|
144
|
+
ctx.npm_scripts = _extract_npm_scripts(root)
|
|
145
|
+
ctx.composer_scripts = _extract_composer_scripts(root)
|
|
146
|
+
ctx.make_targets = _extract_make_targets(root)
|
|
147
|
+
|
|
148
|
+
# Detect repo type
|
|
149
|
+
ctx.repo_type = _detect_repo_type(root, ctx)
|
|
150
|
+
return ctx
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _detect_repo_type(root: Path, ctx: RepoContext) -> RepoType:
|
|
154
|
+
# Package signals
|
|
155
|
+
if ctx.has_composer:
|
|
156
|
+
try:
|
|
157
|
+
data = json.loads((root / "composer.json").read_text())
|
|
158
|
+
pkg_type = data.get("type", "")
|
|
159
|
+
if pkg_type in ("library", "composer-plugin", "symfony-bundle"):
|
|
160
|
+
return "package"
|
|
161
|
+
# No app bootstrap = likely package
|
|
162
|
+
if not (root / "artisan").exists() and not (root / "public" / "index.php").exists():
|
|
163
|
+
return "package"
|
|
164
|
+
except (json.JSONDecodeError, OSError):
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
if ctx.has_package_json:
|
|
168
|
+
try:
|
|
169
|
+
data = json.loads((root / "package.json").read_text())
|
|
170
|
+
if data.get("main") or data.get("exports") or data.get("module"):
|
|
171
|
+
return "package"
|
|
172
|
+
except (json.JSONDecodeError, OSError):
|
|
173
|
+
pass
|
|
174
|
+
|
|
175
|
+
# CLI signals
|
|
176
|
+
bin_dir = root / "bin"
|
|
177
|
+
if bin_dir.is_dir() and any(bin_dir.iterdir()):
|
|
178
|
+
return "cli"
|
|
179
|
+
|
|
180
|
+
# App signals
|
|
181
|
+
if (root / "artisan").exists() or (root / "public" / "index.php").exists():
|
|
182
|
+
return "app"
|
|
183
|
+
if ctx.has_dockerfile and (root / "src").is_dir():
|
|
184
|
+
return "app"
|
|
185
|
+
|
|
186
|
+
# Internal/config signals
|
|
187
|
+
augment_dir = root / ".augment"
|
|
188
|
+
agents_dir = root / "agents"
|
|
189
|
+
if augment_dir.is_dir() or agents_dir.is_dir():
|
|
190
|
+
return "internal"
|
|
191
|
+
|
|
192
|
+
return "unknown"
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _extract_taskfile_tasks(root: Path) -> list[str]:
|
|
196
|
+
for name in ("Taskfile.yml", "Taskfile.yaml"):
|
|
197
|
+
path = root / name
|
|
198
|
+
if path.exists():
|
|
199
|
+
try:
|
|
200
|
+
text = path.read_text()
|
|
201
|
+
return re.findall(r"^\s{2}([\w_-]+):", text, re.MULTILINE)
|
|
202
|
+
except OSError:
|
|
203
|
+
pass
|
|
204
|
+
return []
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _extract_npm_scripts(root: Path) -> list[str]:
|
|
208
|
+
path = root / "package.json"
|
|
209
|
+
if path.exists():
|
|
210
|
+
try:
|
|
211
|
+
data = json.loads(path.read_text())
|
|
212
|
+
return list(data.get("scripts", {}).keys())
|
|
213
|
+
except (json.JSONDecodeError, OSError):
|
|
214
|
+
pass
|
|
215
|
+
return []
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _extract_composer_scripts(root: Path) -> list[str]:
|
|
219
|
+
path = root / "composer.json"
|
|
220
|
+
if path.exists():
|
|
221
|
+
try:
|
|
222
|
+
data = json.loads(path.read_text())
|
|
223
|
+
return list(data.get("scripts", {}).keys())
|
|
224
|
+
except (json.JSONDecodeError, OSError):
|
|
225
|
+
pass
|
|
226
|
+
return []
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _extract_make_targets(root: Path) -> list[str]:
|
|
230
|
+
path = root / "Makefile"
|
|
231
|
+
if path.exists():
|
|
232
|
+
try:
|
|
233
|
+
text = path.read_text()
|
|
234
|
+
return re.findall(r"^([\w_-]+)\s*:", text, re.MULTILINE)
|
|
235
|
+
except OSError:
|
|
236
|
+
pass
|
|
237
|
+
return []
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
# --- Core checks ---
|
|
241
|
+
|
|
242
|
+
def lint_readme(readme_path: Path, repo_root: Path) -> ReadmeLintResult:
|
|
243
|
+
"""Run all checks on a README file."""
|
|
244
|
+
issues: list[Issue] = []
|
|
245
|
+
text = readme_path.read_text(encoding="utf-8")
|
|
246
|
+
lines = text.splitlines()
|
|
247
|
+
line_count = len(lines)
|
|
248
|
+
ctx = detect_repo_context(repo_root)
|
|
249
|
+
|
|
250
|
+
headings = [m.group(1).strip() for m in H2_PATTERN.finditer(text)]
|
|
251
|
+
headings_lower = {h.lower() for h in headings}
|
|
252
|
+
|
|
253
|
+
# 1. Missing title
|
|
254
|
+
if not H1_PATTERN.search(text):
|
|
255
|
+
issues.append(Issue("error", "readme_missing_title", "No H1 heading found"))
|
|
256
|
+
|
|
257
|
+
# 2. Missing summary
|
|
258
|
+
_check_summary(text, issues)
|
|
259
|
+
|
|
260
|
+
# 3. Missing installation
|
|
261
|
+
_check_installation(headings_lower, ctx, issues)
|
|
262
|
+
|
|
263
|
+
# 4. Missing usage example
|
|
264
|
+
_check_usage_example(text, headings_lower, ctx, issues)
|
|
265
|
+
|
|
266
|
+
# 5. Weak quickstart
|
|
267
|
+
_check_quickstart_distance(text, headings, issues)
|
|
268
|
+
|
|
269
|
+
# 6. Missing compatibility (packages)
|
|
270
|
+
_check_compatibility(headings_lower, ctx, issues)
|
|
271
|
+
|
|
272
|
+
# 7. Generic boilerplate
|
|
273
|
+
_check_boilerplate(text, issues)
|
|
274
|
+
|
|
275
|
+
# 8. Missing dev workflow
|
|
276
|
+
_check_dev_workflow(headings_lower, ctx, issues)
|
|
277
|
+
|
|
278
|
+
# 9. Command mismatches
|
|
279
|
+
_check_command_mismatches(text, ctx, issues)
|
|
280
|
+
|
|
281
|
+
# 10. Bad section order
|
|
282
|
+
_check_section_order(headings, issues)
|
|
283
|
+
|
|
284
|
+
# 11. Overloaded README
|
|
285
|
+
_check_overloaded(line_count, issues)
|
|
286
|
+
|
|
287
|
+
# Determine status
|
|
288
|
+
has_errors = any(i.severity == "error" for i in issues)
|
|
289
|
+
has_warnings = any(i.severity == "warning" for i in issues)
|
|
290
|
+
if has_errors:
|
|
291
|
+
status = "fail"
|
|
292
|
+
elif has_warnings:
|
|
293
|
+
status = "pass_with_warnings"
|
|
294
|
+
else:
|
|
295
|
+
status = "pass"
|
|
296
|
+
|
|
297
|
+
return ReadmeLintResult(
|
|
298
|
+
file=str(readme_path),
|
|
299
|
+
repo_type=ctx.repo_type,
|
|
300
|
+
status=status,
|
|
301
|
+
issues=issues,
|
|
302
|
+
line_count=line_count,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
# --- Individual checks ---
|
|
307
|
+
|
|
308
|
+
def _check_summary(text: str, issues: list[Issue]) -> None:
|
|
309
|
+
"""Check if there's a summary paragraph after the title."""
|
|
310
|
+
h1 = H1_PATTERN.search(text)
|
|
311
|
+
if not h1:
|
|
312
|
+
return
|
|
313
|
+
after_title = text[h1.end():h1.end() + 300]
|
|
314
|
+
# Strip leading whitespace and check for text before next heading
|
|
315
|
+
after_stripped = after_title.strip()
|
|
316
|
+
if not after_stripped or after_stripped.startswith("## ") or after_stripped.startswith("```"):
|
|
317
|
+
issues.append(Issue("warning", "readme_missing_summary",
|
|
318
|
+
"No summary paragraph after title"))
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def _check_installation(headings_lower: set[str], ctx: RepoContext, issues: list[Issue]) -> None:
|
|
322
|
+
"""Check for installation/setup section."""
|
|
323
|
+
if ctx.repo_type in ("unknown",):
|
|
324
|
+
return
|
|
325
|
+
if not headings_lower & INSTALL_HEADINGS:
|
|
326
|
+
severity = "error" if ctx.repo_type in ("package", "app", "cli") else "warning"
|
|
327
|
+
issues.append(Issue(severity, "readme_missing_installation",
|
|
328
|
+
f"No installation/setup section found ({ctx.repo_type} repo)"))
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def _check_usage_example(text: str, headings_lower: set[str], ctx: RepoContext,
|
|
332
|
+
issues: list[Issue]) -> None:
|
|
333
|
+
"""Check for usage examples with code blocks."""
|
|
334
|
+
if ctx.repo_type == "unknown":
|
|
335
|
+
return
|
|
336
|
+
has_usage_heading = bool(headings_lower & USAGE_HEADINGS)
|
|
337
|
+
code_blocks = CODE_BLOCK_PATTERN.findall(text)
|
|
338
|
+
if not code_blocks:
|
|
339
|
+
issues.append(Issue("error" if ctx.repo_type == "package" else "warning",
|
|
340
|
+
"readme_missing_usage_example",
|
|
341
|
+
"No code blocks found — likely missing usage examples"))
|
|
342
|
+
elif not has_usage_heading and ctx.repo_type in ("package", "cli"):
|
|
343
|
+
issues.append(Issue("warning", "readme_missing_usage_example",
|
|
344
|
+
"No usage/quickstart section heading found"))
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def _check_quickstart_distance(text: str, headings: list[str], issues: list[Issue]) -> None:
|
|
348
|
+
"""Check if first code block appears too far after install heading."""
|
|
349
|
+
install_line = None
|
|
350
|
+
first_code_line = None
|
|
351
|
+
lines = text.splitlines()
|
|
352
|
+
for i, line in enumerate(lines):
|
|
353
|
+
if install_line is None:
|
|
354
|
+
heading_text = re.match(r"^## (.+)", line)
|
|
355
|
+
if heading_text and heading_text.group(1).strip().lower() in INSTALL_HEADINGS:
|
|
356
|
+
install_line = i
|
|
357
|
+
if first_code_line is None and line.startswith("```"):
|
|
358
|
+
first_code_line = i
|
|
359
|
+
|
|
360
|
+
if install_line is not None and first_code_line is not None:
|
|
361
|
+
gap = first_code_line - install_line
|
|
362
|
+
if gap > WEAK_QUICKSTART_LINE_GAP:
|
|
363
|
+
issues.append(Issue("warning", "readme_weak_quickstart",
|
|
364
|
+
f"First code block is {gap} lines after install heading"))
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def _check_compatibility(headings_lower: set[str], ctx: RepoContext,
|
|
368
|
+
issues: list[Issue]) -> None:
|
|
369
|
+
"""Check for requirements/compatibility section in packages."""
|
|
370
|
+
if ctx.repo_type != "package":
|
|
371
|
+
return
|
|
372
|
+
if not headings_lower & COMPAT_HEADINGS:
|
|
373
|
+
issues.append(Issue("warning", "readme_missing_compatibility",
|
|
374
|
+
"Package repo has no requirements/compatibility section"))
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def _check_boilerplate(text: str, issues: list[Issue]) -> None:
|
|
378
|
+
"""Detect generic marketing boilerplate."""
|
|
379
|
+
matches = []
|
|
380
|
+
for pattern in GENERIC_BOILERPLATE:
|
|
381
|
+
found = re.findall(pattern, text)
|
|
382
|
+
matches.extend(found)
|
|
383
|
+
if matches:
|
|
384
|
+
examples = ", ".join(f'"{m}"' for m in matches[:3])
|
|
385
|
+
issues.append(Issue("warning", "readme_generic_boilerplate",
|
|
386
|
+
f"Generic boilerplate detected: {examples}"))
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def _check_dev_workflow(headings_lower: set[str], ctx: RepoContext,
|
|
390
|
+
issues: list[Issue]) -> None:
|
|
391
|
+
"""Check for dev/testing section when repo has tests or CI."""
|
|
392
|
+
if not (ctx.has_tests or ctx.has_ci):
|
|
393
|
+
return
|
|
394
|
+
if not headings_lower & DEV_HEADINGS:
|
|
395
|
+
issues.append(Issue("warning", "readme_missing_dev_workflow",
|
|
396
|
+
"Repo has tests/CI but README has no development/testing section"))
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def _check_command_mismatches(text: str, ctx: RepoContext, issues: list[Issue]) -> None:
|
|
400
|
+
"""Check if commands in README actually exist in the repo."""
|
|
401
|
+
documented_commands = INLINE_COMMAND_PATTERN.findall(text)
|
|
402
|
+
if not documented_commands:
|
|
403
|
+
return
|
|
404
|
+
|
|
405
|
+
known_commands: set[str] = set()
|
|
406
|
+
for task in ctx.taskfile_tasks:
|
|
407
|
+
known_commands.add(f"task {task}")
|
|
408
|
+
for script in ctx.npm_scripts:
|
|
409
|
+
known_commands.add(f"npm {script}")
|
|
410
|
+
known_commands.add(f"npm run {script}")
|
|
411
|
+
for script in ctx.composer_scripts:
|
|
412
|
+
known_commands.add(f"composer {script}")
|
|
413
|
+
for target in ctx.make_targets:
|
|
414
|
+
known_commands.add(f"make {target}")
|
|
415
|
+
|
|
416
|
+
if not known_commands:
|
|
417
|
+
return # Can't verify without extracted commands
|
|
418
|
+
|
|
419
|
+
mismatches = []
|
|
420
|
+
for cmd in documented_commands:
|
|
421
|
+
cmd_clean = cmd.strip()
|
|
422
|
+
# Check if any known command is a prefix match
|
|
423
|
+
if not any(cmd_clean.startswith(known) or known.startswith(cmd_clean)
|
|
424
|
+
for known in known_commands):
|
|
425
|
+
mismatches.append(cmd_clean)
|
|
426
|
+
|
|
427
|
+
if mismatches:
|
|
428
|
+
examples = ", ".join(f"`{m}`" for m in mismatches[:5])
|
|
429
|
+
issues.append(Issue("warning", "readme_command_mismatch",
|
|
430
|
+
f"Commands in README not found in repo: {examples}"))
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def _check_section_order(headings: list[str], issues: list[Issue]) -> None:
|
|
434
|
+
"""Check if architecture/internals appear before installation/usage."""
|
|
435
|
+
install_idx = None
|
|
436
|
+
arch_idx = None
|
|
437
|
+
for i, h in enumerate(headings):
|
|
438
|
+
h_lower = h.lower()
|
|
439
|
+
if install_idx is None and h_lower in INSTALL_HEADINGS | USAGE_HEADINGS:
|
|
440
|
+
install_idx = i
|
|
441
|
+
if arch_idx is None and h_lower in ARCHITECTURE_HEADINGS:
|
|
442
|
+
arch_idx = i
|
|
443
|
+
|
|
444
|
+
if arch_idx is not None and install_idx is not None and arch_idx < install_idx:
|
|
445
|
+
issues.append(Issue("warning", "readme_bad_section_order",
|
|
446
|
+
"Architecture/internals section appears before installation/usage"))
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def _check_overloaded(line_count: int, issues: list[Issue]) -> None:
|
|
450
|
+
"""Check if README is too long."""
|
|
451
|
+
if line_count > OVERLOADED_LINE_THRESHOLD:
|
|
452
|
+
issues.append(Issue("warning", "readme_overloaded",
|
|
453
|
+
f"README has {line_count} lines (threshold: {OVERLOADED_LINE_THRESHOLD})."
|
|
454
|
+
" Consider moving deep content to /docs"))
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
# --- Output formatting ---
|
|
458
|
+
|
|
459
|
+
def format_text(result: ReadmeLintResult) -> str:
|
|
460
|
+
"""Format result as human-readable text."""
|
|
461
|
+
status_icon = {"pass": "✅", "pass_with_warnings": "⚠️", "fail": "❌"}
|
|
462
|
+
lines = [f"{status_icon.get(result.status, '?')} {result.file} "
|
|
463
|
+
f"(type: {result.repo_type}, {result.line_count} lines)"]
|
|
464
|
+
|
|
465
|
+
if not result.issues:
|
|
466
|
+
lines.append(" No issues found.")
|
|
467
|
+
return "\n".join(lines)
|
|
468
|
+
|
|
469
|
+
severity_icon = {"error": "❌", "warning": "⚠️", "info": "ℹ️"}
|
|
470
|
+
for issue in result.issues:
|
|
471
|
+
icon = severity_icon.get(issue.severity, "?")
|
|
472
|
+
lines.append(f" {icon} [{issue.code}] {issue.message}")
|
|
473
|
+
|
|
474
|
+
return "\n".join(lines)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def format_json(result: ReadmeLintResult) -> str:
|
|
478
|
+
"""Format result as JSON."""
|
|
479
|
+
data = {
|
|
480
|
+
"file": result.file,
|
|
481
|
+
"repo_type": result.repo_type,
|
|
482
|
+
"status": result.status,
|
|
483
|
+
"line_count": result.line_count,
|
|
484
|
+
"issues": [asdict(i) for i in result.issues],
|
|
485
|
+
"summary": {
|
|
486
|
+
"error": sum(1 for i in result.issues if i.severity == "error"),
|
|
487
|
+
"warning": sum(1 for i in result.issues if i.severity == "warning"),
|
|
488
|
+
"info": sum(1 for i in result.issues if i.severity == "info"),
|
|
489
|
+
},
|
|
490
|
+
}
|
|
491
|
+
return json.dumps(data, indent=2)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def format_markdown(result: ReadmeLintResult) -> str:
|
|
495
|
+
"""Format result as markdown for PR comments."""
|
|
496
|
+
lines = [f"## 📝 README Lint: {result.file}", ""]
|
|
497
|
+
lines.append(f"**Repo type:** {result.repo_type} · **Lines:** {result.line_count}")
|
|
498
|
+
lines.append("")
|
|
499
|
+
|
|
500
|
+
if not result.issues:
|
|
501
|
+
lines.append("✅ No issues found.")
|
|
502
|
+
return "\n".join(lines)
|
|
503
|
+
|
|
504
|
+
errors = [i for i in result.issues if i.severity == "error"]
|
|
505
|
+
warnings = [i for i in result.issues if i.severity == "warning"]
|
|
506
|
+
infos = [i for i in result.issues if i.severity == "info"]
|
|
507
|
+
|
|
508
|
+
lines.append(f"| Errors | Warnings | Info |")
|
|
509
|
+
lines.append(f"|---|---|---|")
|
|
510
|
+
lines.append(f"| {len(errors)} | {len(warnings)} | {len(infos)} |")
|
|
511
|
+
lines.append("")
|
|
512
|
+
|
|
513
|
+
if errors:
|
|
514
|
+
lines.append("### ❌ Errors")
|
|
515
|
+
lines.append("")
|
|
516
|
+
for i in errors:
|
|
517
|
+
lines.append(f"- `{i.code}`: {i.message}")
|
|
518
|
+
lines.append("")
|
|
519
|
+
|
|
520
|
+
if warnings:
|
|
521
|
+
lines.append("### ⚠️ Warnings")
|
|
522
|
+
lines.append("")
|
|
523
|
+
for i in warnings:
|
|
524
|
+
lines.append(f"- `{i.code}`: {i.message}")
|
|
525
|
+
lines.append("")
|
|
526
|
+
|
|
527
|
+
if infos:
|
|
528
|
+
lines.append("### ℹ️ Info")
|
|
529
|
+
lines.append("")
|
|
530
|
+
for i in infos:
|
|
531
|
+
lines.append(f"- `{i.code}`: {i.message}")
|
|
532
|
+
|
|
533
|
+
return "\n".join(lines)
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
# --- CLI ---
|
|
537
|
+
|
|
538
|
+
def main() -> int:
|
|
539
|
+
parser = argparse.ArgumentParser(description="README quality linter")
|
|
540
|
+
parser.add_argument("readme", nargs="?", default="README.md",
|
|
541
|
+
help="Path to README file (default: README.md)")
|
|
542
|
+
parser.add_argument("--root", default=".",
|
|
543
|
+
help="Repository root directory (default: cwd)")
|
|
544
|
+
parser.add_argument("--format", choices=["text", "json", "markdown"], default="text",
|
|
545
|
+
help="Output format (default: text)")
|
|
546
|
+
parser.add_argument("--strict", action="store_true",
|
|
547
|
+
help="Treat warnings as errors")
|
|
548
|
+
args = parser.parse_args()
|
|
549
|
+
|
|
550
|
+
readme_path = Path(args.readme)
|
|
551
|
+
repo_root = Path(args.root)
|
|
552
|
+
|
|
553
|
+
if not readme_path.exists():
|
|
554
|
+
print(f"❌ README not found: {readme_path}", file=sys.stderr)
|
|
555
|
+
return 3
|
|
556
|
+
|
|
557
|
+
try:
|
|
558
|
+
result = lint_readme(readme_path, repo_root)
|
|
559
|
+
except Exception as e:
|
|
560
|
+
print(f"❌ Internal error: {e}", file=sys.stderr)
|
|
561
|
+
return 3
|
|
562
|
+
|
|
563
|
+
if args.format == "json":
|
|
564
|
+
print(format_json(result))
|
|
565
|
+
elif args.format == "markdown":
|
|
566
|
+
print(format_markdown(result))
|
|
567
|
+
else:
|
|
568
|
+
print(format_text(result))
|
|
569
|
+
|
|
570
|
+
if result.status == "fail":
|
|
571
|
+
return 2
|
|
572
|
+
if result.status == "pass_with_warnings" and args.strict:
|
|
573
|
+
return 2
|
|
574
|
+
if result.status == "pass_with_warnings":
|
|
575
|
+
return 1
|
|
576
|
+
return 0
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
if __name__ == "__main__":
|
|
580
|
+
sys.exit(main())
|