@event4u/agent-config 1.15.0 → 1.17.0
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/commands/{agents-audit.md → agents/audit.md} +4 -3
- package/.agent-src/commands/{agents-cleanup.md → agents/cleanup.md} +12 -6
- package/.agent-src/commands/{agents-prepare.md → agents/prepare.md} +4 -3
- package/.agent-src/commands/agents.md +46 -0
- package/.agent-src/commands/bug-fix.md +1 -1
- package/.agent-src/commands/bug-investigate.md +2 -2
- package/.agent-src/commands/{chat-history-checkpoint.md → chat-history/checkpoint.md} +5 -5
- package/.agent-src/commands/{chat-history-clear.md → chat-history/clear.md} +5 -5
- package/.agent-src/commands/{chat-history-resume.md → chat-history/resume.md} +4 -4
- package/.agent-src/commands/chat-history/show.md +107 -0
- package/.agent-src/commands/chat-history.md +33 -89
- package/.agent-src/commands/check-current-md.md +1 -1
- package/.agent-src/commands/{commit-in-chunks.md → commit/in-chunks.md} +15 -13
- package/.agent-src/commands/commit.md +22 -2
- package/.agent-src/commands/{context-create.md → context/create.md} +4 -3
- package/.agent-src/commands/{context-refactor.md → context/refactor.md} +4 -3
- package/.agent-src/commands/context.md +44 -0
- package/.agent-src/commands/{copilot-agents-init.md → copilot-agents/init.md} +4 -3
- package/.agent-src/commands/{copilot-agents-optimize.md → copilot-agents/optimize.md} +4 -3
- package/.agent-src/commands/copilot-agents.md +44 -0
- package/.agent-src/commands/council/default.md +221 -0
- package/.agent-src/commands/council/design.md +97 -0
- package/.agent-src/commands/council/optimize.md +116 -0
- package/.agent-src/commands/council/pr.md +124 -0
- package/.agent-src/commands/council.md +54 -0
- package/.agent-src/commands/{create-pr-description.md → create-pr/description-only.md} +4 -2
- package/.agent-src/commands/create-pr.md +49 -5
- package/.agent-src/commands/e2e-heal.md +1 -1
- package/.agent-src/commands/e2e-plan.md +1 -1
- package/.agent-src/commands/{feature-dev.md → feature/dev.md} +6 -3
- package/.agent-src/commands/{feature-explore.md → feature/explore.md} +5 -4
- package/.agent-src/commands/{feature-plan.md → feature/plan.md} +32 -5
- package/.agent-src/commands/{feature-refactor.md → feature/refactor.md} +4 -3
- package/.agent-src/commands/{feature-roadmap.md → feature/roadmap.md} +7 -6
- package/.agent-src/commands/feature.md +52 -0
- package/.agent-src/commands/{fix-ci.md → fix/ci.md} +4 -3
- package/.agent-src/commands/{fix-portability.md → fix/portability.md} +4 -3
- package/.agent-src/commands/{fix-pr-bot-comments.md → fix/pr-bots.md} +4 -3
- package/.agent-src/commands/{fix-pr-developer-comments.md → fix/pr-developers.md} +4 -3
- package/.agent-src/commands/{fix-pr-comments.md → fix/pr.md} +7 -6
- package/.agent-src/commands/{fix-references.md → fix/refs.md} +4 -3
- package/.agent-src/commands/{fix-seeder.md → fix/seeder.md} +4 -3
- package/.agent-src/commands/fix.md +54 -0
- package/.agent-src/commands/jira-ticket.md +1 -1
- package/.agent-src/commands/{do-and-judge.md → judge/on-diff.md} +7 -6
- package/.agent-src/commands/judge/solo.md +90 -0
- package/.agent-src/commands/{do-in-steps.md → judge/steps.md} +8 -7
- package/.agent-src/commands/judge.md +35 -70
- package/.agent-src/commands/{memory-add.md → memory/add.md} +7 -6
- package/.agent-src/commands/{memory-full.md → memory/load.md} +6 -5
- package/.agent-src/commands/{memory-promote.md → memory/promote.md} +6 -5
- package/.agent-src/commands/{propose-memory.md → memory/propose.md} +6 -5
- package/.agent-src/commands/memory.md +48 -0
- package/.agent-src/commands/mode.md +5 -5
- package/.agent-src/commands/{module-create.md → module/create.md} +4 -3
- package/.agent-src/commands/{module-explore.md → module/explore.md} +4 -3
- package/.agent-src/commands/module.md +44 -0
- package/.agent-src/commands/onboard.md +3 -3
- package/.agent-src/commands/{optimize-agents.md → optimize/agents.md} +5 -4
- package/.agent-src/commands/{optimize-augmentignore.md → optimize/augmentignore.md} +4 -4
- package/.agent-src/commands/{optimize-rtk-filters.md → optimize/rtk.md} +4 -3
- package/.agent-src/commands/{optimize-skills.md → optimize/skills.md} +5 -4
- package/.agent-src/commands/optimize.md +48 -0
- package/.agent-src/commands/{override-create.md → override/create.md} +4 -3
- package/.agent-src/commands/{override-manage.md → override/manage.md} +4 -3
- package/.agent-src/commands/override.md +44 -0
- package/.agent-src/commands/review-changes.md +26 -1
- package/.agent-src/commands/review-routing.md +1 -1
- package/.agent-src/commands/{roadmap-create.md → roadmap/create.md} +33 -5
- package/.agent-src/commands/{roadmap-execute.md → roadmap/execute.md} +4 -3
- package/.agent-src/commands/roadmap.md +44 -0
- package/.agent-src/commands/set-cost-profile.md +3 -3
- package/.agent-src/commands/sync-agent-settings.md +2 -2
- package/.agent-src/commands/{tests-create.md → tests/create.md} +5 -4
- package/.agent-src/commands/{tests-execute.md → tests/execute.md} +4 -3
- package/.agent-src/commands/tests.md +44 -0
- package/.agent-src/commands/upstream-contribute.md +1 -1
- package/.agent-src/contexts/authority/commit-mechanics.md +57 -0
- package/.agent-src/contexts/authority/destructive-mechanics.md +66 -0
- package/.agent-src/contexts/authority/scope-mechanics.md +87 -0
- package/.agent-src/contexts/communication/rules-auto/artifact-engagement-recording-mechanics.md +72 -0
- package/.agent-src/contexts/communication/rules-auto/augment-portability-mechanics.md +79 -0
- package/.agent-src/contexts/communication/rules-auto/augment-source-of-truth-mechanics.md +98 -0
- package/.agent-src/contexts/communication/rules-auto/cli-output-handling-mechanics.md +87 -0
- package/.agent-src/contexts/communication/rules-auto/command-suggestion-policy-mechanics.md +62 -0
- package/.agent-src/contexts/communication/rules-auto/docs-sync-mechanics.md +78 -0
- package/.agent-src/contexts/communication/rules-auto/package-ci-checks-mechanics.md +85 -0
- package/.agent-src/contexts/communication/rules-auto/review-routing-awareness-mechanics.md +65 -0
- package/.agent-src/contexts/communication/rules-auto/roadmap-progress-sync-mechanics.md +78 -0
- package/.agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +62 -0
- package/.agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +55 -0
- package/.agent-src/contexts/communication/rules-auto/ui-audit-gate-mechanics.md +53 -0
- package/.agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +77 -0
- package/.agent-src/contexts/execution/autonomy-detection.md +54 -0
- package/.agent-src/contexts/execution/autonomy-examples.md +90 -0
- package/.agent-src/contexts/execution/autonomy-mechanics.md +29 -0
- package/.agent-src/contexts/execution/verification-mechanics.md +80 -0
- package/.agent-src/contexts/judges/no-consolidate-rationale.md +102 -0
- package/.agent-src/contexts/judges/persona-voice-rubric.md +140 -0
- package/.agent-src/personas/README.md +1 -1
- package/.agent-src/rules/agent-authority.md +24 -0
- package/.agent-src/rules/architecture.md +1 -1
- package/.agent-src/rules/artifact-drafting-protocol.md +1 -1
- package/.agent-src/rules/artifact-engagement-recording.md +14 -70
- package/.agent-src/rules/ask-when-uncertain.md +28 -43
- package/.agent-src/rules/augment-portability.md +15 -61
- package/.agent-src/rules/augment-source-of-truth.md +27 -93
- package/.agent-src/rules/autonomous-execution.md +78 -114
- package/.agent-src/rules/capture-learnings.md +1 -1
- package/.agent-src/rules/chat-history-cadence.md +3 -3
- package/.agent-src/rules/chat-history-ownership.md +3 -3
- package/.agent-src/rules/chat-history-visibility.md +3 -3
- package/.agent-src/rules/cli-output-handling.md +10 -76
- package/.agent-src/rules/command-suggestion-policy.md +93 -0
- package/.agent-src/rules/commit-conventions.md +17 -14
- package/.agent-src/rules/commit-policy.md +14 -42
- package/.agent-src/rules/context-hygiene.md +3 -3
- package/.agent-src/rules/direct-answers.md +34 -49
- package/.agent-src/rules/docker-commands.md +5 -5
- package/.agent-src/rules/docs-sync.md +16 -70
- package/.agent-src/rules/e2e-testing.md +1 -1
- package/.agent-src/rules/guidelines.md +4 -4
- package/.agent-src/rules/improve-before-implement.md +2 -2
- package/.agent-src/rules/language-and-tone.md +50 -133
- package/.agent-src/rules/minimal-safe-diff.md +3 -3
- package/.agent-src/rules/missing-tool-handling.md +28 -22
- package/.agent-src/rules/model-recommendation.md +4 -4
- package/.agent-src/rules/no-cheap-questions.md +82 -0
- package/.agent-src/rules/no-roadmap-references.md +73 -0
- package/.agent-src/rules/non-destructive-by-default.md +15 -49
- package/.agent-src/rules/onboarding-gate.md +5 -5
- package/.agent-src/rules/package-ci-checks.md +21 -61
- package/.agent-src/rules/preservation-guard.md +64 -29
- package/.agent-src/rules/review-routing-awareness.md +26 -45
- package/.agent-src/rules/roadmap-progress-sync.md +28 -96
- package/.agent-src/rules/role-mode-adherence.md +2 -2
- package/.agent-src/rules/scope-control.md +65 -46
- package/.agent-src/rules/security-sensitive-stop.md +9 -9
- package/.agent-src/rules/size-enforcement.md +1 -1
- package/.agent-src/rules/skill-quality.md +16 -48
- package/.agent-src/rules/{slash-commands.md → slash-command-routing-policy.md} +7 -4
- package/.agent-src/rules/think-before-action.md +55 -45
- package/.agent-src/rules/token-efficiency.md +4 -4
- package/.agent-src/rules/tool-safety.md +19 -16
- package/.agent-src/rules/{ui-audit-before-build.md → ui-audit-gate.md} +27 -41
- package/.agent-src/rules/user-interaction.md +16 -71
- package/.agent-src/rules/verify-before-complete.md +12 -67
- package/.agent-src/scripts/update_roadmap_progress.py +9 -4
- package/.agent-src/skills/ai-council/SKILL.md +335 -0
- package/.agent-src/skills/api-endpoint/SKILL.md +2 -2
- package/.agent-src/skills/api-testing/SKILL.md +1 -1
- package/.agent-src/skills/blade-ui/SKILL.md +1 -1
- package/.agent-src/skills/blast-radius-analyzer/SKILL.md +1 -1
- package/.agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/.agent-src/skills/check-refs/SKILL.md +59 -40
- package/.agent-src/skills/command-routing/SKILL.md +1 -1
- package/.agent-src/skills/command-writing/SKILL.md +1 -1
- package/.agent-src/skills/conventional-commits-writing/SKILL.md +86 -28
- package/.agent-src/skills/copilot-agents-optimization/SKILL.md +7 -7
- package/.agent-src/skills/developer-like-execution/SKILL.md +6 -6
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +101 -65
- package/.agent-src/skills/flux/SKILL.md +31 -11
- package/.agent-src/skills/git-workflow/SKILL.md +1 -1
- package/.agent-src/skills/github-ci/SKILL.md +2 -2
- package/.agent-src/skills/guideline-writing/SKILL.md +11 -11
- package/.agent-src/skills/judge-code-quality/SKILL.md +7 -8
- package/.agent-src/skills/judge-security-auditor/SKILL.md +4 -5
- package/.agent-src/skills/judge-test-coverage/SKILL.md +3 -4
- package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +4 -4
- package/.agent-src/skills/lint-skills/SKILL.md +57 -39
- package/.agent-src/skills/livewire/SKILL.md +1 -1
- package/.agent-src/skills/md-language-check/SKILL.md +61 -39
- package/.agent-src/skills/override-management/SKILL.md +7 -7
- package/.agent-src/skills/php-coder/SKILL.md +1 -1
- package/.agent-src/skills/playwright-testing/SKILL.md +2 -2
- package/.agent-src/skills/quality-tools/SKILL.md +2 -2
- package/.agent-src/skills/react-shadcn-ui/SKILL.md +116 -43
- package/.agent-src/skills/readme-reviewer/SKILL.md +31 -30
- package/.agent-src/skills/readme-writing/SKILL.md +79 -54
- package/.agent-src/skills/readme-writing-package/SKILL.md +51 -48
- package/.agent-src/skills/receiving-code-review/SKILL.md +53 -48
- package/.agent-src/skills/refine-prompt/SKILL.md +0 -1
- package/.agent-src/skills/requesting-code-review/SKILL.md +35 -30
- package/.agent-src/skills/review-routing/SKILL.md +2 -2
- package/.agent-src/skills/rule-writing/SKILL.md +1 -1
- package/.agent-src/skills/security/SKILL.md +7 -2
- package/.agent-src/skills/security-audit/SKILL.md +7 -3
- package/.agent-src/skills/skill-reviewer/SKILL.md +1 -1
- package/.agent-src/skills/skill-writing/SKILL.md +3 -3
- package/.agent-src/skills/subagent-orchestration/SKILL.md +1 -0
- package/.agent-src/skills/systematic-debugging/SKILL.md +69 -61
- package/.agent-src/skills/test-driven-development/SKILL.md +59 -57
- package/.agent-src/skills/test-performance/SKILL.md +0 -1
- package/.agent-src/skills/traefik/SKILL.md +4 -4
- package/.agent-src/skills/upstream-contribute/SKILL.md +1 -1
- package/.agent-src/skills/validate-feature-fit/SKILL.md +2 -2
- package/.agent-src/skills/{verify-before-complete → verify-completion-evidence}/SKILL.md +30 -28
- package/.agent-src/templates/agent-settings.md +8 -8
- package/.agent-src/templates/contexts/auth-model.md +1 -1
- package/.agent-src/templates/scripts/README.md +2 -2
- package/.agent-src/templates/scripts/telemetry/aggregator.py +16 -1
- package/.agent-src/templates/scripts/telemetry/engagement.py +59 -0
- package/.agent-src/templates/scripts/telemetry/report_renderer.py +28 -1
- package/.agent-src/templates/scripts/telemetry_record.py +14 -1
- package/.claude-plugin/marketplace.json +31 -12
- package/AGENTS.md +11 -9
- package/CHANGELOG.md +213 -2
- package/README.md +43 -44
- package/config/agent-settings.template.yml +58 -1
- package/config/gitignore-block.txt +3 -0
- package/docs/architecture.md +5 -7
- package/docs/catalog.md +359 -0
- package/docs/contracts/STABILITY.md +46 -1
- package/docs/contracts/adr-chat-history-split.md +1 -3
- package/docs/contracts/adr-command-suggestion.md +3 -5
- package/docs/contracts/adr-implement-ticket-runtime.md +1 -2
- package/docs/contracts/adr-product-ui-track.md +5 -8
- package/docs/contracts/adr-prompt-driven-execution.md +3 -4
- package/docs/contracts/agent-memory-contract.md +8 -13
- package/docs/contracts/artifact-engagement-flow.md +7 -10
- package/docs/contracts/command-clusters.md +56 -46
- package/docs/contracts/command-suggestion-flow.md +4 -6
- package/docs/contracts/context-paths.md +99 -0
- package/docs/contracts/file-ownership-matrix.json +6722 -0
- package/docs/contracts/file-ownership-matrix.md +134 -0
- package/docs/contracts/implement-ticket-flow.md +8 -11
- package/docs/contracts/linear-ai-rules-inclusion.md +1 -2
- package/docs/contracts/linear-ai-three-layers.md +0 -2
- package/docs/contracts/load-context-budget-model.md +178 -0
- package/docs/contracts/load-context-schema.md +184 -0
- package/docs/contracts/rule-interactions.md +0 -1
- package/docs/contracts/rule-interactions.yml +96 -0
- package/docs/contracts/rule-priority-hierarchy.md +87 -0
- package/docs/contracts/ui-track-flow.md +8 -18
- package/docs/customization.md +16 -0
- package/docs/end-to-end-walkthroughs.md +165 -0
- package/docs/getting-started.md +29 -10
- package/docs/github-topics.md +12 -3
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +100 -0
- package/docs/guidelines/agent-infra/language-and-tone-examples.md +79 -0
- package/{.agent-src → docs}/guidelines/docs/readme-size-and-splitting.md +26 -25
- package/docs/guidelines/php/git.md +164 -0
- package/docs/migrations/commands-1.15.0.md +1 -1
- package/docs/showcase.md +9 -4
- package/docs/skills-catalog.md +14 -8
- package/docs/ui-track-mental-model.md +2 -2
- package/llms.txt +13 -7
- package/package.json +1 -1
- package/scripts/_one_off_phase4_dispatch_latency.py +108 -0
- package/scripts/_one_off_phase6_trigger_jaccard.py +92 -0
- package/scripts/_phase2_shim_helper.py +109 -0
- package/scripts/agent-config +33 -0
- package/scripts/ai_council/__init__.py +39 -0
- package/scripts/ai_council/_default_prices.py +41 -0
- package/scripts/ai_council/_one_off_2a4_acceptance.py +208 -0
- package/scripts/ai_council/_one_off_context_layer_v1_estimate.py +67 -0
- package/scripts/ai_council/_one_off_context_layer_v1_review.py +292 -0
- package/scripts/ai_council/_one_off_followups_review.py +259 -0
- package/scripts/ai_council/_one_off_nondestructive_inline_audit.py +209 -0
- package/scripts/ai_council/_one_off_phase_2a_budget_rebalance.py +257 -0
- package/scripts/ai_council/_one_off_phase_2a_post_revert.py +197 -0
- package/scripts/ai_council/_one_off_rebalancing_audit.py +149 -0
- package/scripts/ai_council/_one_off_roundtrip.py +106 -0
- package/scripts/ai_council/_one_off_rule_hardening_v1.py +251 -0
- package/scripts/ai_council/_one_off_structural_open_questions.py +232 -0
- package/scripts/ai_council/_one_off_structural_optimization.py +144 -0
- package/scripts/ai_council/_one_off_structural_v3_gaps.py +252 -0
- package/scripts/ai_council/_one_off_structural_v3_review.py +240 -0
- package/scripts/ai_council/budget_guard.py +172 -0
- package/scripts/ai_council/bundler.py +261 -0
- package/scripts/ai_council/clients.py +381 -0
- package/scripts/ai_council/modes.py +127 -0
- package/scripts/ai_council/orchestrator.py +350 -0
- package/scripts/ai_council/pricing.py +213 -0
- package/scripts/ai_council/project_context.py +159 -0
- package/scripts/ai_council/prompts.py +232 -0
- package/scripts/ai_council/session.py +144 -0
- package/scripts/check_always_budget.py +444 -0
- package/scripts/check_augmentignore.py +69 -0
- package/scripts/check_cluster_patterns.py +159 -0
- package/scripts/check_command_count_messaging.py +127 -0
- package/scripts/check_context_paths.py +201 -0
- package/scripts/check_no_roadmap_refs.py +155 -0
- package/scripts/check_phase_coupling.py +148 -0
- package/scripts/check_portability.py +57 -0
- package/scripts/check_public_catalog_links.py +122 -0
- package/scripts/check_references.py +33 -3
- package/scripts/check_roadmap_trackable.py +111 -0
- package/scripts/check_safety_floor_untouched.py +125 -0
- package/scripts/command_suggester/cooldown.py +1 -1
- package/scripts/command_suggester/loader.py +4 -1
- package/scripts/compress.py +59 -13
- package/scripts/generate_index.py +270 -0
- package/scripts/generate_ownership_matrix.py +323 -0
- package/scripts/hooks/augment-roadmap-progress.sh +57 -0
- package/scripts/install.py +49 -28
- package/scripts/install_anthropic_key.sh +5 -0
- package/scripts/install_openai_key.sh +106 -0
- package/scripts/lint_load_context.py +163 -0
- package/scripts/lint_no_new_atomic_commands.py +12 -11
- package/scripts/requirements-evals.txt +1 -0
- package/scripts/roadmap_progress_hook.py +159 -0
- package/scripts/schemas/command.schema.json +22 -1
- package/scripts/schemas/rule.schema.json +10 -0
- package/scripts/skill_linter.py +13 -4
- package/scripts/sync_agent_settings.py +26 -3
- package/scripts/update_counts.py +16 -4
- package/scripts/update_prices.py +124 -0
- package/.agent-src/guidelines/php/git.md +0 -96
- package/.agent-src/rules/command-suggestion.md +0 -134
- /package/{.agent-src → docs}/guidelines/agent-infra/agent-interaction-and-decision-quality.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/break-glass-usage.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/developer-judgment.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/engineering-memory-data-format.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/layered-settings.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/memory-access.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/naming.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/output-patterns.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/review-routing-data-format.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/role-contracts.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/role-mode-router.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/runtime-layer.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/self-improvement-pipeline.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/size-and-scope.md +0 -0
- /package/{.agent-src → docs}/guidelines/agent-infra/tool-integration.md +0 -0
- /package/{.agent-src → docs}/guidelines/e2e/playwright.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/api-design.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/artisan-commands.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/blade-ui.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/controllers.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/database.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/eloquent.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/flux.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/general.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/jobs.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/livewire.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/logging.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/naming.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/dependency-injection.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/dtos.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/events.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/factory.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/pipelines.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/policies.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/repositories.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/service-layer.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns/strategy.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/patterns.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/performance.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/resources.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/security.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/sql.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/validations.md +0 -0
- /package/{.agent-src → docs}/guidelines/php/websocket.md +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Command-count messaging gate (regression guard for road-to-pr-34-followups 1.2).
|
|
4
|
+
|
|
5
|
+
Public surfaces (README.md, AGENTS.md, docs/getting-started.md) advertise
|
|
6
|
+
the size of the command catalog. PR #34 collapses atomic commands into
|
|
7
|
+
clusters via deprecation shims — the externally meaningful number is the
|
|
8
|
+
**active** command count (non-shim files), not the raw file count. This
|
|
9
|
+
gate sources canonical counts from `.agent-src.uncompressed/commands/`
|
|
10
|
+
frontmatter and fails when any documented number drifts from those.
|
|
11
|
+
|
|
12
|
+
Canonical counts:
|
|
13
|
+
total = number of *.md files under .agent-src.uncompressed/commands/
|
|
14
|
+
shims = files whose frontmatter declares `superseded_by:`
|
|
15
|
+
active = total - shims
|
|
16
|
+
|
|
17
|
+
Patterns checked (per file):
|
|
18
|
+
|
|
19
|
+
README.md
|
|
20
|
+
hero row "<strong>{N} Commands</strong>" → active
|
|
21
|
+
browse line "Browse all {N} active commands" → active
|
|
22
|
+
browse meta "{N} files total" → total
|
|
23
|
+
browse meta "{N} are deprecation shims" → shims
|
|
24
|
+
tools blurb "{N} native commands" → active
|
|
25
|
+
|
|
26
|
+
AGENTS.md
|
|
27
|
+
tree "commands/ ({N} files — {A} active + {S} deprecation shims)"
|
|
28
|
+
|
|
29
|
+
docs/getting-started.md
|
|
30
|
+
browse line "Browse all {N} active commands" → active
|
|
31
|
+
|
|
32
|
+
Exit codes: 0 = clean, 1 = drift detected.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
from __future__ import annotations
|
|
36
|
+
|
|
37
|
+
import re
|
|
38
|
+
import sys
|
|
39
|
+
from pathlib import Path
|
|
40
|
+
|
|
41
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
42
|
+
COMMANDS_DIR = ROOT / ".agent-src.uncompressed" / "commands"
|
|
43
|
+
README = ROOT / "README.md"
|
|
44
|
+
AGENTS = ROOT / "AGENTS.md"
|
|
45
|
+
GETTING_STARTED = ROOT / "docs" / "getting-started.md"
|
|
46
|
+
|
|
47
|
+
FM_RE = re.compile(r"^---\s*\n(.*?)\n---", re.DOTALL)
|
|
48
|
+
SUPERSEDED_RE = re.compile(r"^superseded_by:\s*\S", re.MULTILINE)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def canonical_counts() -> tuple[int, int, int]:
|
|
52
|
+
if not COMMANDS_DIR.is_dir():
|
|
53
|
+
print(f"❌ {COMMANDS_DIR.relative_to(ROOT)} not found", file=sys.stderr)
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
total = shims = 0
|
|
56
|
+
for f in COMMANDS_DIR.rglob("*.md"):
|
|
57
|
+
if f.name == "AGENTS.md":
|
|
58
|
+
continue
|
|
59
|
+
total += 1
|
|
60
|
+
m = FM_RE.match(f.read_text(encoding="utf-8"))
|
|
61
|
+
fm = m.group(1) if m else ""
|
|
62
|
+
if SUPERSEDED_RE.search(fm):
|
|
63
|
+
shims += 1
|
|
64
|
+
return total, shims, total - shims
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _check(path: Path, pattern: str, expected: int, label: str) -> str | None:
|
|
68
|
+
if not path.exists():
|
|
69
|
+
return f"missing file: {path.relative_to(ROOT)}"
|
|
70
|
+
m = re.search(pattern, path.read_text(encoding="utf-8"))
|
|
71
|
+
if not m:
|
|
72
|
+
return f"{path.relative_to(ROOT)}: pattern not found for `{label}` — /{pattern}/"
|
|
73
|
+
found = int(m.group(1))
|
|
74
|
+
if found != expected:
|
|
75
|
+
return f"{path.relative_to(ROOT)}: `{label}` says {found}, expected {expected}"
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def main() -> int:
|
|
80
|
+
total, shims, active = canonical_counts()
|
|
81
|
+
print(f"Canonical counts: {total} files · {shims} shims · {active} active")
|
|
82
|
+
|
|
83
|
+
checks = [
|
|
84
|
+
# README.md
|
|
85
|
+
(README, r"<strong>(\d+) Commands</strong>", active, "hero row"),
|
|
86
|
+
(README, r"Browse all (\d+) active commands", active, "browse line"),
|
|
87
|
+
(README, r"\+ (\d+) native commands\)", active, "tools blurb"),
|
|
88
|
+
# docs/getting-started.md
|
|
89
|
+
(GETTING_STARTED, r"Browse all (\d+) active commands", active, "browse line"),
|
|
90
|
+
]
|
|
91
|
+
# Shim-specific messaging only applies during a deprecation window.
|
|
92
|
+
# When shims == 0 the clauses are dropped from public docs entirely;
|
|
93
|
+
# re-add these patterns when a new deprecation cycle starts.
|
|
94
|
+
if shims > 0:
|
|
95
|
+
checks.extend([
|
|
96
|
+
(README, r"\((\d+) files total ", total, "browse meta · total files"),
|
|
97
|
+
(README, r"— (\d+) are deprecation shims", shims, "browse meta · shims"),
|
|
98
|
+
(AGENTS, r"commands/\s+\((\d+) files —", total, "tree · total files"),
|
|
99
|
+
(AGENTS, r"files — (\d+) active", active, "tree · active"),
|
|
100
|
+
(AGENTS, r"active \+ (\d+) deprecation shims", shims, "tree · shims"),
|
|
101
|
+
])
|
|
102
|
+
|
|
103
|
+
errors: list[str] = []
|
|
104
|
+
for path, pattern, expected, label in checks:
|
|
105
|
+
err = _check(path, pattern, expected, label)
|
|
106
|
+
if err:
|
|
107
|
+
errors.append(err)
|
|
108
|
+
|
|
109
|
+
if not errors:
|
|
110
|
+
print("✅ All command-count messaging in sync with registry.")
|
|
111
|
+
return 0
|
|
112
|
+
|
|
113
|
+
print(f"❌ Command-count messaging drift — {len(errors)} mismatch(es):")
|
|
114
|
+
for e in errors:
|
|
115
|
+
print(f" {e}")
|
|
116
|
+
print(
|
|
117
|
+
"\nFix: update the documented numbers above, or run "
|
|
118
|
+
"`task check-command-count` after editing."
|
|
119
|
+
)
|
|
120
|
+
print(
|
|
121
|
+
"Why this gate exists: see `agents/roadmaps/road-to-pr-34-followups.md` § 1.2."
|
|
122
|
+
)
|
|
123
|
+
return 1
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
if __name__ == "__main__":
|
|
127
|
+
sys.exit(main())
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Context-file path & orphan checker.
|
|
3
|
+
|
|
4
|
+
Validates that every `*.md` under `.agent-src.uncompressed/contexts/`:
|
|
5
|
+
|
|
6
|
+
1. Lives in a locked sub-tree (or is one of six grandfathered root files).
|
|
7
|
+
2. Does not collide on basename with another context file in another sub-tree.
|
|
8
|
+
3. Is referenced by at least one rule, skill, command, or other context
|
|
9
|
+
(via `load_context:` frontmatter or a markdown body path mention).
|
|
10
|
+
|
|
11
|
+
Contract: docs/contracts/context-paths.md
|
|
12
|
+
Roadmap: road-to-structural-optimization.md § 0.6
|
|
13
|
+
|
|
14
|
+
Exit codes: 0 = clean, 1 = violations, 3 = internal error.
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import json
|
|
20
|
+
import sys
|
|
21
|
+
from dataclasses import asdict, dataclass
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
25
|
+
CONTEXTS_ROOT = ROOT / ".agent-src.uncompressed" / "contexts"
|
|
26
|
+
|
|
27
|
+
# Sub-trees that may contain context files. Update in lock-step with
|
|
28
|
+
# docs/contracts/context-paths.md whenever a roadmap revision adds one.
|
|
29
|
+
LOCKED_SUBTREES = (
|
|
30
|
+
"communication/rules-always",
|
|
31
|
+
"communication/rules-auto",
|
|
32
|
+
"judges",
|
|
33
|
+
"analysis",
|
|
34
|
+
"skills",
|
|
35
|
+
"chat-history",
|
|
36
|
+
"execution",
|
|
37
|
+
"authority",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Files allowed to remain at the contexts root. Anything else at the root
|
|
41
|
+
# fails the path check. New context files MUST live in a sub-tree.
|
|
42
|
+
GRANDFATHERED_ROOT_FILES = frozenset({
|
|
43
|
+
"augment-infrastructure.md",
|
|
44
|
+
"documentation-hierarchy.md",
|
|
45
|
+
"model-recommendations.md",
|
|
46
|
+
"override-system.md",
|
|
47
|
+
"skills-and-commands.md",
|
|
48
|
+
"subagent-configuration.md",
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
# Directories whose content we scan for references to a context file.
|
|
52
|
+
# `agents/roadmaps` is included because in-flight roadmap docs are
|
|
53
|
+
# legitimate referrers during multi-phase rollouts — a context can land
|
|
54
|
+
# in phase N while its first rule/skill referrer lands in phase N+k.
|
|
55
|
+
# Without this scan dir, every newly-introduced context would orphan
|
|
56
|
+
# until the consuming artefact lands, blocking phase-by-phase commits.
|
|
57
|
+
REFERENCE_SCAN_DIRS = (
|
|
58
|
+
".agent-src.uncompressed/rules",
|
|
59
|
+
".agent-src.uncompressed/skills",
|
|
60
|
+
".agent-src.uncompressed/commands",
|
|
61
|
+
".agent-src.uncompressed/contexts",
|
|
62
|
+
"agents/roadmaps",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass
|
|
67
|
+
class Violation:
|
|
68
|
+
file: str
|
|
69
|
+
kind: str # "out-of-tree" | "root-not-grandfathered" | "collision" | "orphan"
|
|
70
|
+
detail: str
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _collect_contexts(root: Path) -> list[Path]:
|
|
74
|
+
if not (root / CONTEXTS_ROOT.relative_to(ROOT)).exists():
|
|
75
|
+
return []
|
|
76
|
+
return sorted((root / CONTEXTS_ROOT.relative_to(ROOT)).rglob("*.md"))
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _check_path(ctx: Path, contexts_root: Path) -> Violation | None:
|
|
80
|
+
rel = ctx.relative_to(contexts_root)
|
|
81
|
+
parts = rel.parts
|
|
82
|
+
if len(parts) == 1:
|
|
83
|
+
if parts[0] not in GRANDFATHERED_ROOT_FILES:
|
|
84
|
+
return Violation(
|
|
85
|
+
file=str(ctx),
|
|
86
|
+
kind="root-not-grandfathered",
|
|
87
|
+
detail=(f"new file at contexts/ root — must live in one of "
|
|
88
|
+
f"{sorted(LOCKED_SUBTREES)} or be added to "
|
|
89
|
+
"GRANDFATHERED_ROOT_FILES via a roadmap revision"),
|
|
90
|
+
)
|
|
91
|
+
return None
|
|
92
|
+
subtree = "/".join(parts[:-1])
|
|
93
|
+
# Allow nested matches: e.g. communication/rules-always/foo/bar.md still
|
|
94
|
+
# lives under "communication/rules-always". Direct prefix match suffices.
|
|
95
|
+
for allowed in LOCKED_SUBTREES:
|
|
96
|
+
if subtree == allowed or subtree.startswith(allowed + "/"):
|
|
97
|
+
return None
|
|
98
|
+
return Violation(
|
|
99
|
+
file=str(ctx),
|
|
100
|
+
kind="out-of-tree",
|
|
101
|
+
detail=(f"sub-tree '{subtree}' is not in LOCKED_SUBTREES — see "
|
|
102
|
+
"docs/contracts/context-paths.md to add a new sub-tree"),
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _check_collisions(contexts: list[Path], contexts_root: Path) -> list[Violation]:
|
|
107
|
+
by_name: dict[str, list[Path]] = {}
|
|
108
|
+
for ctx in contexts:
|
|
109
|
+
by_name.setdefault(ctx.name, []).append(ctx)
|
|
110
|
+
out: list[Violation] = []
|
|
111
|
+
for name, paths in by_name.items():
|
|
112
|
+
if len(paths) <= 1:
|
|
113
|
+
continue
|
|
114
|
+
rels = sorted(str(p.relative_to(contexts_root)) for p in paths)
|
|
115
|
+
for p in paths:
|
|
116
|
+
out.append(Violation(
|
|
117
|
+
file=str(p),
|
|
118
|
+
kind="collision",
|
|
119
|
+
detail=f"basename '{name}' shared with: {', '.join(r for r in rels if r != str(p.relative_to(contexts_root)))}",
|
|
120
|
+
))
|
|
121
|
+
return out
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _build_reference_corpus(root: Path) -> str:
|
|
125
|
+
chunks: list[str] = []
|
|
126
|
+
for d in REFERENCE_SCAN_DIRS:
|
|
127
|
+
base = root / d
|
|
128
|
+
if not base.exists():
|
|
129
|
+
continue
|
|
130
|
+
for f in base.rglob("*.md"):
|
|
131
|
+
try:
|
|
132
|
+
chunks.append(f.read_text(encoding="utf-8"))
|
|
133
|
+
except OSError:
|
|
134
|
+
continue
|
|
135
|
+
return "\n".join(chunks)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _check_orphans(contexts: list[Path], corpus: str, root: Path) -> list[Violation]:
|
|
139
|
+
out: list[Violation] = []
|
|
140
|
+
for ctx in contexts:
|
|
141
|
+
rel_src = str(ctx.relative_to(root)) # .agent-src.uncompressed/contexts/...
|
|
142
|
+
rel_short = rel_src.split("contexts/", 1)[-1] # judges/persona-voice-rubric.md
|
|
143
|
+
candidates = (rel_src, f"contexts/{rel_short}", rel_short)
|
|
144
|
+
# Exclude self-references: drop this file's own content from the
|
|
145
|
+
# corpus check by reading the file and subtracting its substring.
|
|
146
|
+
try:
|
|
147
|
+
own_text = ctx.read_text(encoding="utf-8")
|
|
148
|
+
except OSError:
|
|
149
|
+
own_text = ""
|
|
150
|
+
external_corpus = corpus.replace(own_text, "") if own_text else corpus
|
|
151
|
+
if not any(c in external_corpus for c in candidates):
|
|
152
|
+
out.append(Violation(
|
|
153
|
+
file=str(ctx),
|
|
154
|
+
kind="orphan",
|
|
155
|
+
detail="not referenced by any rule, skill, command, or other context",
|
|
156
|
+
))
|
|
157
|
+
return out
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def scan(root: Path) -> list[Violation]:
|
|
161
|
+
contexts_root = root / CONTEXTS_ROOT.relative_to(ROOT)
|
|
162
|
+
contexts = _collect_contexts(root)
|
|
163
|
+
violations: list[Violation] = []
|
|
164
|
+
for ctx in contexts:
|
|
165
|
+
v = _check_path(ctx, contexts_root)
|
|
166
|
+
if v:
|
|
167
|
+
violations.append(v)
|
|
168
|
+
violations.extend(_check_collisions(contexts, contexts_root))
|
|
169
|
+
corpus = _build_reference_corpus(root)
|
|
170
|
+
violations.extend(_check_orphans(contexts, corpus, root))
|
|
171
|
+
return violations
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def format_text(violations: list[Violation]) -> str:
|
|
175
|
+
if not violations:
|
|
176
|
+
return "✅ No context-path violations."
|
|
177
|
+
lines = [f"❌ Found {len(violations)} context-path violation(s):\n"]
|
|
178
|
+
for v in violations:
|
|
179
|
+
lines.append(f" 🔴 [{v.kind}] {v.file}\n {v.detail}")
|
|
180
|
+
return "\n".join(lines)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def main() -> int:
|
|
184
|
+
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
185
|
+
parser.add_argument("--format", choices=["text", "json"], default="text")
|
|
186
|
+
parser.add_argument("--root", type=Path, default=ROOT)
|
|
187
|
+
args = parser.parse_args()
|
|
188
|
+
try:
|
|
189
|
+
violations = scan(args.root)
|
|
190
|
+
except Exception as e: # pragma: no cover
|
|
191
|
+
print(f"Internal error: {e}", file=sys.stderr)
|
|
192
|
+
return 3
|
|
193
|
+
if args.format == "json":
|
|
194
|
+
print(json.dumps([asdict(v) for v in violations], indent=2))
|
|
195
|
+
else:
|
|
196
|
+
print(format_text(violations))
|
|
197
|
+
return 1 if violations else 0
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
if __name__ == "__main__":
|
|
201
|
+
sys.exit(main())
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""No-roadmap-references checker.
|
|
3
|
+
|
|
4
|
+
Stable artifacts (rules, skills, commands, contexts, guidelines, AGENTS.md,
|
|
5
|
+
README, copilot-instructions) must NOT cite a specific roadmap file in
|
|
6
|
+
`agents/roadmaps/`. Roadmap files are transient — archived, skipped, or
|
|
7
|
+
deleted as work completes — and stable artifacts citing them rot.
|
|
8
|
+
|
|
9
|
+
Allowed: directory mentions (`agents/roadmaps/`, `agents/roadmaps/archive/`,
|
|
10
|
+
`agents/roadmaps/skipped/`). Forbidden: specific `*.md` files inside those
|
|
11
|
+
directories.
|
|
12
|
+
|
|
13
|
+
Contract: .agent-src.uncompressed/rules/no-roadmap-references.md
|
|
14
|
+
|
|
15
|
+
Exit codes: 0 = clean, 1 = violations, 3 = internal error.
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import json
|
|
21
|
+
import re
|
|
22
|
+
import sys
|
|
23
|
+
from dataclasses import asdict, dataclass
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
|
|
26
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
27
|
+
|
|
28
|
+
# Stable artefact trees — every `*.md` below MUST be free of roadmap-file
|
|
29
|
+
# citations. Directory mentions stay allowed (the regex below excludes them).
|
|
30
|
+
STABLE_TREES = (
|
|
31
|
+
".agent-src.uncompressed/rules",
|
|
32
|
+
".agent-src.uncompressed/skills",
|
|
33
|
+
".agent-src.uncompressed/commands",
|
|
34
|
+
".agent-src.uncompressed/contexts",
|
|
35
|
+
".agent-src.uncompressed/templates",
|
|
36
|
+
".agent-src.uncompressed/personas",
|
|
37
|
+
"agents/contexts",
|
|
38
|
+
"docs/guidelines",
|
|
39
|
+
"docs/contracts",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Stable single-file artefacts at well-known paths.
|
|
43
|
+
STABLE_FILES = (
|
|
44
|
+
"AGENTS.md",
|
|
45
|
+
"README.md",
|
|
46
|
+
"copilot-instructions.md",
|
|
47
|
+
"docs/architecture.md",
|
|
48
|
+
"docs/customization.md",
|
|
49
|
+
"docs/getting-started.md",
|
|
50
|
+
"docs/catalog.md",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Roadmap-file pattern: any `*.md` file under `agents/roadmaps/` at any
|
|
54
|
+
# depth (including `archive/`, `skipped/`, and nested topical subfolders
|
|
55
|
+
# like `agent-memory/`). Directory-only mentions (`agents/roadmaps/`
|
|
56
|
+
# with trailing slash, no filename) and placeholder mentions like
|
|
57
|
+
# `agents/roadmaps/<file>.md` (angle-bracket placeholder) do NOT match.
|
|
58
|
+
ROADMAP_FILE_RE = re.compile(
|
|
59
|
+
r"agents/roadmaps/(?:[a-z0-9][a-z0-9_-]*/)*[a-z0-9][a-z0-9_-]*\.md",
|
|
60
|
+
re.IGNORECASE,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
# Files that may legitimately quote forbidden patterns inside backticks for
|
|
64
|
+
# documentation purposes — the rule itself, the companion CI script docs,
|
|
65
|
+
# and the contract doc that names the rule.
|
|
66
|
+
SELF_DOCUMENTING_ALLOWLIST = frozenset({
|
|
67
|
+
".agent-src.uncompressed/rules/no-roadmap-references.md",
|
|
68
|
+
"docs/guidelines/agent-infra/no-roadmap-references.md",
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class Violation:
|
|
74
|
+
file: str
|
|
75
|
+
line: int
|
|
76
|
+
match: str
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _scan_file(path: Path, root: Path) -> list[Violation]:
|
|
80
|
+
rel = str(path.relative_to(root))
|
|
81
|
+
if rel in SELF_DOCUMENTING_ALLOWLIST:
|
|
82
|
+
return []
|
|
83
|
+
try:
|
|
84
|
+
text = path.read_text(encoding="utf-8")
|
|
85
|
+
except OSError:
|
|
86
|
+
return []
|
|
87
|
+
out: list[Violation] = []
|
|
88
|
+
in_fence = False
|
|
89
|
+
for n, line in enumerate(text.splitlines(), start=1):
|
|
90
|
+
# Skip fenced code blocks — path listings inside ``` are functional
|
|
91
|
+
# constants (command contracts, runtime checks), not link rot.
|
|
92
|
+
stripped = line.lstrip()
|
|
93
|
+
if stripped.startswith("```"):
|
|
94
|
+
in_fence = not in_fence
|
|
95
|
+
continue
|
|
96
|
+
if in_fence:
|
|
97
|
+
continue
|
|
98
|
+
for m in ROADMAP_FILE_RE.finditer(line):
|
|
99
|
+
out.append(Violation(file=rel, line=n, match=m.group(0)))
|
|
100
|
+
return out
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _collect_targets(root: Path) -> list[Path]:
|
|
104
|
+
targets: list[Path] = []
|
|
105
|
+
for d in STABLE_TREES:
|
|
106
|
+
base = root / d
|
|
107
|
+
if not base.exists():
|
|
108
|
+
continue
|
|
109
|
+
targets.extend(sorted(base.rglob("*.md")))
|
|
110
|
+
for f in STABLE_FILES:
|
|
111
|
+
p = root / f
|
|
112
|
+
if p.exists():
|
|
113
|
+
targets.append(p)
|
|
114
|
+
return targets
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def scan(root: Path) -> list[Violation]:
|
|
118
|
+
out: list[Violation] = []
|
|
119
|
+
for path in _collect_targets(root):
|
|
120
|
+
out.extend(_scan_file(path, root))
|
|
121
|
+
return out
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def format_text(violations: list[Violation]) -> str:
|
|
125
|
+
if not violations:
|
|
126
|
+
return "✅ No roadmap-file references in stable artifacts."
|
|
127
|
+
lines = [f"❌ Found {len(violations)} roadmap reference(s) in stable artifacts:\n"]
|
|
128
|
+
for v in violations:
|
|
129
|
+
lines.append(f" 🔴 {v.file}:{v.line} → {v.match}")
|
|
130
|
+
lines.append(
|
|
131
|
+
"\nPromote the durable conclusion to agents/contexts/ and cite that "
|
|
132
|
+
"instead. See .agent-src.uncompressed/rules/no-roadmap-references.md."
|
|
133
|
+
)
|
|
134
|
+
return "\n".join(lines)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def main() -> int:
|
|
138
|
+
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
139
|
+
parser.add_argument("--format", choices=["text", "json"], default="text")
|
|
140
|
+
parser.add_argument("--root", type=Path, default=ROOT)
|
|
141
|
+
args = parser.parse_args()
|
|
142
|
+
try:
|
|
143
|
+
violations = scan(args.root)
|
|
144
|
+
except Exception as e: # pragma: no cover
|
|
145
|
+
print(f"Internal error: {e}", file=sys.stderr)
|
|
146
|
+
return 3
|
|
147
|
+
if args.format == "json":
|
|
148
|
+
print(json.dumps([asdict(v) for v in violations], indent=2))
|
|
149
|
+
else:
|
|
150
|
+
print(format_text(violations))
|
|
151
|
+
return 1 if violations else 0
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
sys.exit(main())
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Phase 6 → Phase 2B coupling guard (Phase 0.3.3).
|
|
3
|
+
|
|
4
|
+
Re-runs the audit recorded in `agents/roadmaps/phase6-2b-coupling.md`
|
|
5
|
+
on every CI run. Fails the build if any of the 13 Phase-2B target
|
|
6
|
+
rules introduces a reference to one of the three Phase-6-owned rules
|
|
7
|
+
(`chat-history-cadence`, `chat-history-ownership`,
|
|
8
|
+
`chat-history-visibility`) — by rule name, `load_context:` entry, or
|
|
9
|
+
body link / cite.
|
|
10
|
+
|
|
11
|
+
Excluded from the coupling probe (separate infrastructure, not
|
|
12
|
+
reshaped by Phase 6):
|
|
13
|
+
|
|
14
|
+
- The CLI dispatcher subcommand `./agent-config chat-history:hook`
|
|
15
|
+
and any other `chat-history:*` colon-suffix command surface.
|
|
16
|
+
|
|
17
|
+
Exit codes: 0 = decoupling intact, 1 = coupling detected,
|
|
18
|
+
3 = internal error (target rule missing, unreadable file).
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import argparse
|
|
24
|
+
import re
|
|
25
|
+
import sys
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
29
|
+
SRC_RULES = REPO_ROOT / ".agent-src.uncompressed" / "rules"
|
|
30
|
+
COMP_RULES = REPO_ROOT / ".agent-src" / "rules"
|
|
31
|
+
|
|
32
|
+
# Phase 2B priority list — see road-to-structural-optimization.md § Phase 2 → 2B.
|
|
33
|
+
TARGET_RULES: tuple[str, ...] = (
|
|
34
|
+
"roadmap-progress-sync",
|
|
35
|
+
"user-interaction",
|
|
36
|
+
"augment-source-of-truth",
|
|
37
|
+
"command-suggestion-policy",
|
|
38
|
+
"artifact-engagement-recording",
|
|
39
|
+
"review-routing-awareness",
|
|
40
|
+
"autonomous-execution",
|
|
41
|
+
"docs-sync",
|
|
42
|
+
"cli-output-handling",
|
|
43
|
+
"augment-portability",
|
|
44
|
+
"ui-audit-gate",
|
|
45
|
+
"skill-quality",
|
|
46
|
+
"package-ci-checks",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Phase 6 owns these three rule names. Match must be a *rule reference*,
|
|
50
|
+
# not a *dispatcher reference* (chat-history:hook etc).
|
|
51
|
+
PHASE6_RULES: tuple[str, ...] = (
|
|
52
|
+
"chat-history-cadence",
|
|
53
|
+
"chat-history-ownership",
|
|
54
|
+
"chat-history-visibility",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Rule-reference pattern: rule name not immediately followed by `:` (which
|
|
58
|
+
# would mark it as a CLI subcommand like `chat-history:hook`). Allows
|
|
59
|
+
# trailing word-boundary characters typical of Markdown / YAML contexts.
|
|
60
|
+
_RULE_REF_RE = re.compile(
|
|
61
|
+
r"\bchat-history-(?:cadence|ownership|visibility)\b(?!:)"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _scan(file: Path) -> list[tuple[int, str]]:
|
|
66
|
+
"""Return [(line_no, line)] of rule-reference matches in `file`."""
|
|
67
|
+
if not file.is_file():
|
|
68
|
+
return []
|
|
69
|
+
hits: list[tuple[int, str]] = []
|
|
70
|
+
for i, line in enumerate(file.read_text(encoding="utf-8").splitlines(), 1):
|
|
71
|
+
if _RULE_REF_RE.search(line):
|
|
72
|
+
hits.append((i, line.strip()))
|
|
73
|
+
return hits
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _check_surface(label: str, base: Path) -> tuple[int, list[str]]:
|
|
77
|
+
"""Scan `base` for all 13 Phase-2B targets; return (#hits, formatted lines)."""
|
|
78
|
+
if not base.is_dir():
|
|
79
|
+
return 0, [f"❌ {label} dir missing: {base}"]
|
|
80
|
+
out: list[str] = []
|
|
81
|
+
total = 0
|
|
82
|
+
for rule in TARGET_RULES:
|
|
83
|
+
path = base / f"{rule}.md"
|
|
84
|
+
if not path.is_file():
|
|
85
|
+
return 0, [f"❌ target rule missing: {path}"]
|
|
86
|
+
hits = _scan(path)
|
|
87
|
+
if not hits:
|
|
88
|
+
continue
|
|
89
|
+
total += len(hits)
|
|
90
|
+
for line_no, line in hits:
|
|
91
|
+
out.append(f" {label}/{rule}.md:{line_no} {line}")
|
|
92
|
+
return total, out
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def main() -> int:
|
|
96
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
97
|
+
parser.add_argument(
|
|
98
|
+
"--quiet",
|
|
99
|
+
action="store_true",
|
|
100
|
+
help="suppress the per-rule breakdown when no coupling found",
|
|
101
|
+
)
|
|
102
|
+
args = parser.parse_args()
|
|
103
|
+
|
|
104
|
+
hits_src, lines_src = _check_surface("uncompressed", SRC_RULES)
|
|
105
|
+
if any(line.startswith("❌") for line in lines_src):
|
|
106
|
+
for line in lines_src:
|
|
107
|
+
print(line, file=sys.stderr)
|
|
108
|
+
return 3
|
|
109
|
+
hits_comp, lines_comp = _check_surface("compressed", COMP_RULES)
|
|
110
|
+
if any(line.startswith("❌") for line in lines_comp):
|
|
111
|
+
for line in lines_comp:
|
|
112
|
+
print(line, file=sys.stderr)
|
|
113
|
+
return 3
|
|
114
|
+
|
|
115
|
+
total = hits_src + hits_comp
|
|
116
|
+
|
|
117
|
+
if total == 0:
|
|
118
|
+
if not args.quiet:
|
|
119
|
+
print(
|
|
120
|
+
f"✅ Phase 6 → 2B decoupling intact: 0 rule-references "
|
|
121
|
+
f"across {len(TARGET_RULES)} Phase-2B targets "
|
|
122
|
+
f"(uncompressed + compressed surfaces)."
|
|
123
|
+
)
|
|
124
|
+
print(
|
|
125
|
+
" probe: rule names, load_context: entries, body "
|
|
126
|
+
"link/cite — dispatcher subcommand chat-history:hook "
|
|
127
|
+
"excluded by design."
|
|
128
|
+
)
|
|
129
|
+
return 0
|
|
130
|
+
|
|
131
|
+
print(
|
|
132
|
+
f"❌ Phase 6 → 2B coupling detected: {total} rule-reference(s) "
|
|
133
|
+
f"across Phase-2B targets:"
|
|
134
|
+
)
|
|
135
|
+
for line in lines_src + lines_comp:
|
|
136
|
+
print(line)
|
|
137
|
+
print(
|
|
138
|
+
"\n Action: see agents/roadmaps/phase6-2b-coupling.md. "
|
|
139
|
+
"Either drop the new reference, migrate it to the dispatcher "
|
|
140
|
+
"(chat-history:hook), or trigger the >0-hits branch in 0.3.2 "
|
|
141
|
+
"(Phase 6 ships call-signature contract before Phase 2B "
|
|
142
|
+
"touches the coupled rule)."
|
|
143
|
+
)
|
|
144
|
+
return 1
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
sys.exit(main())
|