@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
|
@@ -250,6 +250,55 @@ def check_file(filepath: Path, patterns: list, allowlist: list) -> List[Violatio
|
|
|
250
250
|
return violations
|
|
251
251
|
|
|
252
252
|
|
|
253
|
+
# ── Identity-framing detector ───────────────────────────────────────────
|
|
254
|
+
# The package's public identity surface (README, AGENTS, copilot-instructions)
|
|
255
|
+
# must read stack-neutral. Laravel is the deepest reference stack today, never
|
|
256
|
+
# the headline. This detector flags banned phrases that elevate any single
|
|
257
|
+
# stack to identity status. Source-of-truth list lives in the
|
|
258
|
+
# road-to-1-15-followups.md roadmap (P0 #1, F1.5).
|
|
259
|
+
_IDENTITY_FRAMING_PATTERNS: list[tuple[re.Pattern, str]] = [
|
|
260
|
+
(re.compile(r"\bLaravel-first\b", re.IGNORECASE), "identity-laravel-first"),
|
|
261
|
+
(re.compile(r"\bfor\s+PHP\s*/\s*Laravel\s+teams?\b", re.IGNORECASE), "identity-for-php-laravel-teams"),
|
|
262
|
+
(re.compile(r"\bfor\s+Laravel\s+teams?\b", re.IGNORECASE), "identity-for-laravel-teams"),
|
|
263
|
+
(re.compile(r"\bprimary\s+audience\s*[:=]\s*Laravel\b", re.IGNORECASE), "identity-primary-audience-laravel"),
|
|
264
|
+
(re.compile(r"\bbuilt\s+for\s+Laravel\b", re.IGNORECASE), "identity-built-for-laravel"),
|
|
265
|
+
(re.compile(r"\bLaravel\s*=\s*primary\b", re.IGNORECASE), "identity-laravel-equals-primary"),
|
|
266
|
+
(re.compile(r"\*\*Reference\s+implementation:\s*Laravel\.?\*\*", re.IGNORECASE), "identity-reference-implementation-laravel"),
|
|
267
|
+
]
|
|
268
|
+
|
|
269
|
+
# Files whose identity framing must stay stack-neutral. Relative to repo root.
|
|
270
|
+
IDENTITY_SCAN_FILES = [
|
|
271
|
+
"README.md",
|
|
272
|
+
"AGENTS.md",
|
|
273
|
+
".github/copilot-instructions.md",
|
|
274
|
+
]
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def check_identity_framing(filepath: Path) -> List[Violation]:
|
|
278
|
+
"""Flag banned identity-framing phrases in README / AGENTS / copilot-instructions.
|
|
279
|
+
|
|
280
|
+
The package presents itself as a universal governance system; any phrase
|
|
281
|
+
that pins identity to a single stack (Laravel-first, built for Laravel,
|
|
282
|
+
Reference implementation: Laravel as a bolded headline) is a regression.
|
|
283
|
+
"""
|
|
284
|
+
violations: List[Violation] = []
|
|
285
|
+
try:
|
|
286
|
+
lines = filepath.read_text(encoding="utf-8").splitlines()
|
|
287
|
+
except Exception:
|
|
288
|
+
return violations
|
|
289
|
+
|
|
290
|
+
for i, line in enumerate(lines, 1):
|
|
291
|
+
for pattern, name in _IDENTITY_FRAMING_PATTERNS:
|
|
292
|
+
m = pattern.search(line)
|
|
293
|
+
if m:
|
|
294
|
+
violations.append(Violation(
|
|
295
|
+
file=str(filepath), line=i, match=m.group(0),
|
|
296
|
+
pattern_name=name, severity="error",
|
|
297
|
+
context=line.strip(),
|
|
298
|
+
))
|
|
299
|
+
return violations
|
|
300
|
+
|
|
301
|
+
|
|
253
302
|
# ── Task-command detector ───────────────────────────────────────────────
|
|
254
303
|
# Artefact files shipped in the package must not reference `task <name>`
|
|
255
304
|
# invocations (per augment-portability rule). Consumer projects may not
|
|
@@ -266,6 +315,7 @@ _TASK_FENCE_RE = re.compile(r"^\s*task\s+([a-z][a-z0-9:_-]*)\b")
|
|
|
266
315
|
# by the task-invocation detector (but still scanned for layer 1 + 2).
|
|
267
316
|
_TASK_DETECTOR_SKIP = (
|
|
268
317
|
"rules/augment-portability.md",
|
|
318
|
+
"contexts/communication/rules-auto/augment-portability-mechanics.md",
|
|
269
319
|
)
|
|
270
320
|
|
|
271
321
|
|
|
@@ -373,6 +423,7 @@ _CLI_INVOCATION_MAP: list[tuple[re.Pattern, str]] = [
|
|
|
373
423
|
# own help, the portability rule that defines the mapping).
|
|
374
424
|
_CLI_DETECTOR_SKIP = (
|
|
375
425
|
"rules/augment-portability.md",
|
|
426
|
+
"contexts/communication/rules-auto/augment-portability-mechanics.md",
|
|
376
427
|
)
|
|
377
428
|
|
|
378
429
|
|
|
@@ -467,6 +518,12 @@ def scan_all(root: Path) -> tuple[List[Violation], list[str]]:
|
|
|
467
518
|
if not any(path_str.endswith(skip) for skip in _CLI_DETECTOR_SKIP):
|
|
468
519
|
violations.extend(check_cli_invocations(f))
|
|
469
520
|
|
|
521
|
+
# Layer 5: identity-framing scan on the public identity surface
|
|
522
|
+
for rel in IDENTITY_SCAN_FILES:
|
|
523
|
+
f = root / rel
|
|
524
|
+
if f.is_file():
|
|
525
|
+
violations.extend(check_identity_framing(f))
|
|
526
|
+
|
|
470
527
|
return violations, detected
|
|
471
528
|
|
|
472
529
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Public-catalog link checker (regression guard for road-to-pr-34-followups 1.1).
|
|
4
|
+
|
|
5
|
+
`docs/catalog.md` is the consumer-facing catalog rendered by
|
|
6
|
+
`scripts/generate_index.py`. Consumers receive the package via npm /
|
|
7
|
+
Composer / archive surfaces — `.agent-src.uncompressed/` is **not**
|
|
8
|
+
shipped (see `package.json#files`). Every link in the public catalog
|
|
9
|
+
must therefore resolve to a shipped surface.
|
|
10
|
+
|
|
11
|
+
Checks:
|
|
12
|
+
1. No link href contains `.agent-src.uncompressed/`.
|
|
13
|
+
2. Every link href resolves on disk.
|
|
14
|
+
3. Every link href starts with a path declared in `package.json#files`
|
|
15
|
+
(or one of the always-shipped root files).
|
|
16
|
+
|
|
17
|
+
Exit codes: 0 = clean, 1 = violations found.
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
python3 scripts/check_public_catalog_links.py
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import json
|
|
26
|
+
import re
|
|
27
|
+
import sys
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
31
|
+
CATALOG = ROOT / "docs" / "catalog.md"
|
|
32
|
+
PACKAGE_JSON = ROOT / "package.json"
|
|
33
|
+
|
|
34
|
+
LINK_RE = re.compile(r"\]\((?P<href>[^)\s]+)(?:\s+\"[^\"]*\")?\)")
|
|
35
|
+
FORBIDDEN_PREFIX = ".agent-src.uncompressed/"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _shipped_roots() -> tuple[set[str], set[str]]:
|
|
39
|
+
"""Return (shipped_dirs, shipped_files) from package.json#files."""
|
|
40
|
+
data = json.loads(PACKAGE_JSON.read_text(encoding="utf-8"))
|
|
41
|
+
dirs: set[str] = set()
|
|
42
|
+
files: set[str] = set()
|
|
43
|
+
for entry in data.get("files", []):
|
|
44
|
+
if entry.endswith("/"):
|
|
45
|
+
dirs.add(entry.rstrip("/"))
|
|
46
|
+
else:
|
|
47
|
+
files.add(entry)
|
|
48
|
+
return dirs, files
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _resolve(href: str) -> Path | None:
|
|
52
|
+
href = href.split("#", 1)[0]
|
|
53
|
+
if not href or href.startswith(("http://", "https://", "mailto:", "tel:")):
|
|
54
|
+
return None
|
|
55
|
+
target = (CATALOG.parent / href).resolve()
|
|
56
|
+
try:
|
|
57
|
+
return target.relative_to(ROOT.resolve())
|
|
58
|
+
except ValueError:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _under_shipped_surface(rel: Path, dirs: set[str], files: set[str]) -> bool:
|
|
63
|
+
s = str(rel)
|
|
64
|
+
if s in files:
|
|
65
|
+
return True
|
|
66
|
+
return any(s == d or s.startswith(d + "/") for d in dirs)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def main() -> int:
|
|
70
|
+
if not CATALOG.exists():
|
|
71
|
+
print(f"❌ {CATALOG.relative_to(ROOT)} not found")
|
|
72
|
+
return 1
|
|
73
|
+
|
|
74
|
+
dirs, files = _shipped_roots()
|
|
75
|
+
text = CATALOG.read_text(encoding="utf-8")
|
|
76
|
+
|
|
77
|
+
forbidden: list[tuple[int, str]] = []
|
|
78
|
+
missing: list[tuple[int, str]] = []
|
|
79
|
+
unshipped: list[tuple[int, str]] = []
|
|
80
|
+
|
|
81
|
+
for lineno, line in enumerate(text.splitlines(), 1):
|
|
82
|
+
for m in LINK_RE.finditer(line):
|
|
83
|
+
href = m.group("href")
|
|
84
|
+
if FORBIDDEN_PREFIX in href:
|
|
85
|
+
forbidden.append((lineno, href))
|
|
86
|
+
continue
|
|
87
|
+
rel = _resolve(href)
|
|
88
|
+
if rel is None:
|
|
89
|
+
continue # external / non-resolvable
|
|
90
|
+
if not (ROOT / rel).exists():
|
|
91
|
+
missing.append((lineno, href))
|
|
92
|
+
continue
|
|
93
|
+
if not _under_shipped_surface(rel, dirs, files):
|
|
94
|
+
unshipped.append((lineno, href))
|
|
95
|
+
|
|
96
|
+
total_violations = len(forbidden) + len(missing) + len(unshipped)
|
|
97
|
+
if not total_violations:
|
|
98
|
+
print(f"✅ docs/catalog.md — all links resolve to shipped surfaces.")
|
|
99
|
+
return 0
|
|
100
|
+
|
|
101
|
+
print(f"❌ docs/catalog.md — {total_violations} violation(s):")
|
|
102
|
+
if forbidden:
|
|
103
|
+
print(f"\n {len(forbidden)} link(s) point at unshipped `.agent-src.uncompressed/`:")
|
|
104
|
+
for ln, href in forbidden[:10]:
|
|
105
|
+
print(f" line {ln}: {href}")
|
|
106
|
+
if len(forbidden) > 10:
|
|
107
|
+
print(f" … and {len(forbidden) - 10} more")
|
|
108
|
+
if missing:
|
|
109
|
+
print(f"\n {len(missing)} link(s) do not resolve on disk:")
|
|
110
|
+
for ln, href in missing[:10]:
|
|
111
|
+
print(f" line {ln}: {href}")
|
|
112
|
+
if unshipped:
|
|
113
|
+
print(f"\n {len(unshipped)} link(s) point outside `package.json#files`:")
|
|
114
|
+
for ln, href in unshipped[:10]:
|
|
115
|
+
print(f" line {ln}: {href}")
|
|
116
|
+
print("\nFix: update `scripts/generate_index.py` _to_shipped_path() / catalog renderer,")
|
|
117
|
+
print("then re-run `python3 scripts/generate_index.py`.")
|
|
118
|
+
return 1
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if __name__ == "__main__":
|
|
122
|
+
sys.exit(main())
|
|
@@ -32,7 +32,10 @@ class BrokenRef:
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
SCAN_DIRS = [".agent-src", "agents"]
|
|
35
|
-
SKIP_DIRS = [
|
|
35
|
+
SKIP_DIRS = [
|
|
36
|
+
"agents/roadmaps/archive", # archived roadmaps have historical refs
|
|
37
|
+
"agents/council-sessions", # per-user audit trail (gitignored), captured provider output
|
|
38
|
+
]
|
|
36
39
|
ROOT = Path(".")
|
|
37
40
|
|
|
38
41
|
# YAML memory files (engineering-memory layer) live under `agents/memory/`.
|
|
@@ -98,6 +101,14 @@ EXAMPLE_PATH_PATTERNS = [
|
|
|
98
101
|
re.compile(r"skills/[\w-]+/SKILL\.md"), # example skill paths in commands
|
|
99
102
|
re.compile(r"\{"), # template placeholders like {module}
|
|
100
103
|
re.compile(r"\.compression-hashes\.json"), # JSON file, not .md
|
|
104
|
+
# Forward references inside in-flight planning docs (road-to-
|
|
105
|
+
# structural-optimization.md and its companion spike protocols).
|
|
106
|
+
# Each pattern below is removed once the matching phase lands.
|
|
107
|
+
re.compile(r"structural-optimization-3a-spike\.md"), # 3a.0.2
|
|
108
|
+
re.compile(r"contexts/judges/no-consolidate-rationale"), # 3a.0.2 abort
|
|
109
|
+
re.compile(r"contexts/judges/judge-shared-procedure"), # 3a.1
|
|
110
|
+
re.compile(r"contexts/analysis/project-analysis-core-procedure"), # 3b.1
|
|
111
|
+
re.compile(r"agents/roadmaps/phase6-non-overlap-evidence"), # 6.1 conditional
|
|
101
112
|
]
|
|
102
113
|
|
|
103
114
|
|
|
@@ -115,8 +126,20 @@ def collect_artifacts(root: Path) -> dict[str, set[str]]:
|
|
|
115
126
|
arts["skills"].add(d.name)
|
|
116
127
|
for f in (augment / "rules").glob("*.md") if (augment / "rules").exists() else []:
|
|
117
128
|
arts["rules"].add(f.stem)
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
cmd_dir = augment / "commands"
|
|
130
|
+
if cmd_dir.exists():
|
|
131
|
+
for f in cmd_dir.rglob("*.md"):
|
|
132
|
+
if f.name == "AGENTS.md":
|
|
133
|
+
continue
|
|
134
|
+
# Top-level: bare stem ("commit"). Nested: cluster-sub ("council-default")
|
|
135
|
+
# AND the cluster:sub form, since references may use either.
|
|
136
|
+
rel = f.relative_to(cmd_dir).with_suffix("")
|
|
137
|
+
parts = rel.parts
|
|
138
|
+
if len(parts) == 1:
|
|
139
|
+
arts["commands"].add(parts[0])
|
|
140
|
+
else:
|
|
141
|
+
arts["commands"].add("-".join(parts))
|
|
142
|
+
arts["commands"].add(":".join(parts))
|
|
120
143
|
gdir = augment / "guidelines"
|
|
121
144
|
if gdir.exists():
|
|
122
145
|
for f in gdir.rglob("*.md"):
|
|
@@ -222,6 +245,13 @@ def check_file(filepath: Path, artifacts: dict[str, set[str]], root: Path) -> Li
|
|
|
222
245
|
if any(p.search(raw_ref) for p in EXAMPLE_PATH_PATTERNS):
|
|
223
246
|
continue
|
|
224
247
|
|
|
248
|
+
# Skip references into directories already excluded from scanning
|
|
249
|
+
# (gitignored audit trails, archived roadmaps). Files there are
|
|
250
|
+
# not committed, so existence checks would always fail in CI.
|
|
251
|
+
if any(raw_ref.startswith(skip + "/") or raw_ref == skip
|
|
252
|
+
for skip in SKIP_DIRS):
|
|
253
|
+
continue
|
|
254
|
+
|
|
225
255
|
resolved = False
|
|
226
256
|
# Try raw ref as-is from root (covers .agent-src/..., agents/..., etc.)
|
|
227
257
|
if (root / raw_ref).exists():
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""CI guard for the `roadmap-progress-sync` rule's trackability Iron Law.
|
|
3
|
+
|
|
4
|
+
Every non-draft file under `agents/roadmaps/` (excluding `archive/`,
|
|
5
|
+
`skipped/`, template/README/open-questions) MUST:
|
|
6
|
+
|
|
7
|
+
1. Be parseable by the dashboard's `PHASE_RE` — i.e. contain at least
|
|
8
|
+
one `## Phase <id>` or `### Phase <id>` heading.
|
|
9
|
+
2. Have at least one trackable checkbox (`- [ ]`, `[x]`, `[~]`, `[-]`)
|
|
10
|
+
under every parsed phase.
|
|
11
|
+
|
|
12
|
+
A roadmap that fails (1) is invisible to `agents/roadmaps-progress.md`
|
|
13
|
+
and silently lies to the next reader. A phase that fails (2) shows as
|
|
14
|
+
`⬜ empty` and contributes nothing to progress percentages.
|
|
15
|
+
|
|
16
|
+
Both failure modes are rule violations per
|
|
17
|
+
`.augment/rules/roadmap-progress-sync.md` § "Iron Law — every active
|
|
18
|
+
roadmap is trackable". This script is the CI backstop so the rule
|
|
19
|
+
cannot be quietly broken again.
|
|
20
|
+
|
|
21
|
+
Exit codes:
|
|
22
|
+
0 — every active roadmap has parseable phases with at least one
|
|
23
|
+
checkbox per phase.
|
|
24
|
+
1 — at least one violation found; details printed to stdout.
|
|
25
|
+
|
|
26
|
+
Invocation (from project root):
|
|
27
|
+
python3 scripts/check_roadmap_trackable.py
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import sys
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
|
|
35
|
+
# Reuse the dashboard's regexes and helpers — single source of truth so
|
|
36
|
+
# the linter cannot drift from what the dashboard actually parses.
|
|
37
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / ".augment" / "scripts"))
|
|
38
|
+
from update_roadmap_progress import ( # noqa: E402
|
|
39
|
+
CHECKBOX_RE,
|
|
40
|
+
PHASE_RE,
|
|
41
|
+
is_draft,
|
|
42
|
+
is_roadmap_candidate,
|
|
43
|
+
parse_frontmatter,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
ROADMAP_ROOT = Path("agents/roadmaps")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def find_active_roadmaps(root: Path) -> list[Path]:
|
|
50
|
+
"""Return every non-draft roadmap candidate under root."""
|
|
51
|
+
out: list[Path] = []
|
|
52
|
+
for path in sorted(root.rglob("*.md")):
|
|
53
|
+
if not path.is_file() or not is_roadmap_candidate(path):
|
|
54
|
+
continue
|
|
55
|
+
text = path.read_text(encoding="utf-8")
|
|
56
|
+
if is_draft(parse_frontmatter(text)):
|
|
57
|
+
continue
|
|
58
|
+
out.append(path)
|
|
59
|
+
return out
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def violations_for(path: Path) -> list[str]:
|
|
63
|
+
"""Return human-readable violation strings for a single roadmap."""
|
|
64
|
+
text = path.read_text(encoding="utf-8")
|
|
65
|
+
matches = list(PHASE_RE.finditer(text))
|
|
66
|
+
if not matches:
|
|
67
|
+
return [
|
|
68
|
+
f"{path}: no `## Phase <id>` or `### Phase <id>` heading "
|
|
69
|
+
"matched the dashboard's PHASE_RE — roadmap is invisible "
|
|
70
|
+
"to agents/roadmaps-progress.md. Either rename headings to "
|
|
71
|
+
"the canonical `Phase <id>` form or add `status: draft` to "
|
|
72
|
+
"the frontmatter."
|
|
73
|
+
]
|
|
74
|
+
out: list[str] = []
|
|
75
|
+
for i, pm in enumerate(matches):
|
|
76
|
+
start = pm.end()
|
|
77
|
+
end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
|
|
78
|
+
if not CHECKBOX_RE.search(text[start:end]):
|
|
79
|
+
phase_id = pm.group(2)
|
|
80
|
+
name = (pm.group(3) or "").strip() or f"Phase {phase_id}"
|
|
81
|
+
out.append(
|
|
82
|
+
f"{path}: Phase {phase_id} ({name[:60]}) has zero "
|
|
83
|
+
"trackable checkboxes — add at least one `- [ ]` (or "
|
|
84
|
+
"`[x]`/`[~]`/`[-]`) item or remove the phase."
|
|
85
|
+
)
|
|
86
|
+
return out
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def main() -> int:
|
|
90
|
+
if not ROADMAP_ROOT.is_dir():
|
|
91
|
+
print(f"❌ {ROADMAP_ROOT} not found — run from project root.", file=sys.stderr)
|
|
92
|
+
return 1
|
|
93
|
+
findings: list[str] = []
|
|
94
|
+
for path in find_active_roadmaps(ROADMAP_ROOT):
|
|
95
|
+
findings.extend(violations_for(path))
|
|
96
|
+
if findings:
|
|
97
|
+
print("❌ Trackable-roadmap rule violations:\n")
|
|
98
|
+
for f in findings:
|
|
99
|
+
print(f" - {f}")
|
|
100
|
+
print(
|
|
101
|
+
"\nRule: .augment/rules/roadmap-progress-sync.md "
|
|
102
|
+
'§ "Iron Law — every active roadmap is trackable"'
|
|
103
|
+
)
|
|
104
|
+
return 1
|
|
105
|
+
count = len(find_active_roadmaps(ROADMAP_ROOT))
|
|
106
|
+
print(f"✅ {count} active roadmap(s) — all parseable, all phases have checkboxes.")
|
|
107
|
+
return 0
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
if __name__ == "__main__":
|
|
111
|
+
sys.exit(main())
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Safety-floor exclusion linter (Phase 2A.0 of road-to-structural-optimization).
|
|
3
|
+
|
|
4
|
+
Per Q3=A locked decision (council Round 3, 2026-05-03), the four
|
|
5
|
+
safety-floor always-rules are out of scope for Phase 2A slimming:
|
|
6
|
+
|
|
7
|
+
- non-destructive-by-default
|
|
8
|
+
- commit-policy
|
|
9
|
+
- scope-control
|
|
10
|
+
- verify-before-complete
|
|
11
|
+
|
|
12
|
+
This linter compares HEAD against a baseline ref (default: ``main``)
|
|
13
|
+
and fails CI if any of those four rule files were modified by the
|
|
14
|
+
working branch.
|
|
15
|
+
|
|
16
|
+
Lift via the two-gate rollback documented in
|
|
17
|
+
``agents/roadmaps/road-to-structural-optimization.md`` § Phase 2A
|
|
18
|
+
Abort/rollback.
|
|
19
|
+
|
|
20
|
+
Exit codes: 0 = clean (or skipped — see ``--skip-if-no-baseline``),
|
|
21
|
+
1 = safety-floor file modified, 3 = internal error.
|
|
22
|
+
"""
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import argparse
|
|
26
|
+
import subprocess
|
|
27
|
+
import sys
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
31
|
+
RULES_DIR_REL = ".agent-src.uncompressed/rules"
|
|
32
|
+
SAFETY_FLOOR = (
|
|
33
|
+
"non-destructive-by-default.md",
|
|
34
|
+
"commit-policy.md",
|
|
35
|
+
"scope-control.md",
|
|
36
|
+
"verify-before-complete.md",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _run_git(args: list[str]) -> tuple[int, str]:
|
|
41
|
+
proc = subprocess.run(
|
|
42
|
+
["git", *args],
|
|
43
|
+
cwd=REPO_ROOT,
|
|
44
|
+
capture_output=True,
|
|
45
|
+
text=True,
|
|
46
|
+
check=False,
|
|
47
|
+
)
|
|
48
|
+
return proc.returncode, (proc.stdout or "") + (proc.stderr or "")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _baseline_exists(ref: str) -> bool:
|
|
52
|
+
code, _ = _run_git(["rev-parse", "--verify", "--quiet", ref])
|
|
53
|
+
return code == 0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _changed_files(baseline: str) -> list[str]:
|
|
57
|
+
code, output = _run_git(["diff", "--name-only", f"{baseline}...HEAD"])
|
|
58
|
+
if code != 0:
|
|
59
|
+
raise RuntimeError(f"git diff failed: {output}")
|
|
60
|
+
return [line.strip() for line in output.splitlines() if line.strip()]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def main() -> int:
|
|
64
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
"--baseline",
|
|
67
|
+
default="origin/main",
|
|
68
|
+
help="Baseline ref (default: origin/main)",
|
|
69
|
+
)
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"--skip-if-no-baseline",
|
|
72
|
+
action="store_true",
|
|
73
|
+
help="Exit 0 silently if baseline ref does not exist (local dev)",
|
|
74
|
+
)
|
|
75
|
+
args = parser.parse_args()
|
|
76
|
+
|
|
77
|
+
if not _baseline_exists(args.baseline):
|
|
78
|
+
if args.skip_if_no_baseline:
|
|
79
|
+
print(f"ℹ️ baseline {args.baseline} not found — skipped")
|
|
80
|
+
return 0
|
|
81
|
+
# Fallback: try plain `main`
|
|
82
|
+
if _baseline_exists("main"):
|
|
83
|
+
args.baseline = "main"
|
|
84
|
+
else:
|
|
85
|
+
print(
|
|
86
|
+
f"❌ baseline {args.baseline} (and `main`) not found. "
|
|
87
|
+
"Pass --skip-if-no-baseline to silence in local dev.",
|
|
88
|
+
file=sys.stderr,
|
|
89
|
+
)
|
|
90
|
+
return 3
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
changed = _changed_files(args.baseline)
|
|
94
|
+
except RuntimeError as exc:
|
|
95
|
+
print(f"❌ {exc}", file=sys.stderr)
|
|
96
|
+
return 3
|
|
97
|
+
|
|
98
|
+
floor_paths = {f"{RULES_DIR_REL}/{name}" for name in SAFETY_FLOOR}
|
|
99
|
+
breaches = sorted(p for p in changed if p in floor_paths)
|
|
100
|
+
|
|
101
|
+
if breaches:
|
|
102
|
+
print(
|
|
103
|
+
"❌ Safety-floor rule(s) modified — Phase 2A is not allowed to "
|
|
104
|
+
"touch these (Q3=A locked decision):",
|
|
105
|
+
file=sys.stderr,
|
|
106
|
+
)
|
|
107
|
+
for path in breaches:
|
|
108
|
+
print(f" {path}", file=sys.stderr)
|
|
109
|
+
print(
|
|
110
|
+
"\n Lift via the two-gate rollback documented in "
|
|
111
|
+
"agents/roadmaps/road-to-structural-optimization.md "
|
|
112
|
+
"§ Phase 2A Abort/rollback.",
|
|
113
|
+
file=sys.stderr,
|
|
114
|
+
)
|
|
115
|
+
return 1
|
|
116
|
+
|
|
117
|
+
print(
|
|
118
|
+
f"✅ Safety-floor untouched ({len(SAFETY_FLOOR)} rules guarded "
|
|
119
|
+
f"vs. {args.baseline})."
|
|
120
|
+
)
|
|
121
|
+
return 0
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
if __name__ == "__main__":
|
|
125
|
+
sys.exit(main())
|
|
@@ -31,7 +31,7 @@ def is_explicit_slash_invocation(message: str) -> bool:
|
|
|
31
31
|
|
|
32
32
|
Per the `command-suggestion` rule, explicit slash invocations
|
|
33
33
|
bypass the suggestion layer entirely \u2014 they're handled by
|
|
34
|
-
`slash-
|
|
34
|
+
`slash-command-routing-policy` directly. The engine should not score in that
|
|
35
35
|
case. Helper exposed for the runtime caller and the GT-CS4
|
|
36
36
|
golden.
|
|
37
37
|
"""
|
|
@@ -26,7 +26,10 @@ def load_commands(commands_dir: Path) -> list[CommandSpec]:
|
|
|
26
26
|
this loader.
|
|
27
27
|
"""
|
|
28
28
|
specs: list[CommandSpec] = []
|
|
29
|
-
for path in sorted(commands_dir.
|
|
29
|
+
for path in sorted(commands_dir.rglob("*.md")):
|
|
30
|
+
# Skip cluster authoring docs — not commands.
|
|
31
|
+
if path.name == "AGENTS.md":
|
|
32
|
+
continue
|
|
30
33
|
text = path.read_text(encoding="utf-8")
|
|
31
34
|
data, _offset = parse_frontmatter(text)
|
|
32
35
|
if data is None:
|
package/scripts/compress.py
CHANGED
|
@@ -312,6 +312,29 @@ def generate_gemini_md() -> None:
|
|
|
312
312
|
print(" ✅ Created GEMINI.md → AGENTS.md symlink")
|
|
313
313
|
|
|
314
314
|
|
|
315
|
+
def _command_slug(source_file: Path) -> str:
|
|
316
|
+
"""Return the flat .claude/skills/ slug for a command source file.
|
|
317
|
+
|
|
318
|
+
Top-level commands keep their stem (`commit.md` → `commit`). Nested
|
|
319
|
+
commands flatten the relative path with `-` (`council/default.md` →
|
|
320
|
+
`council-default`). Keeps slug collisions out of `.claude/skills/`
|
|
321
|
+
while preserving native nested invocation in `.agent-src/commands/`.
|
|
322
|
+
"""
|
|
323
|
+
rel = source_file.relative_to(COMMANDS_SOURCE)
|
|
324
|
+
return "-".join(rel.with_suffix("").parts)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def _iter_commands():
|
|
328
|
+
"""Yield (source_file, slug) for every command .md file (recursive)."""
|
|
329
|
+
if not COMMANDS_SOURCE.exists():
|
|
330
|
+
return
|
|
331
|
+
for source_file in sorted(COMMANDS_SOURCE.rglob("*.md")):
|
|
332
|
+
# Skip the cluster AGENTS.md authoring doc (not a command).
|
|
333
|
+
if source_file.name == "AGENTS.md":
|
|
334
|
+
continue
|
|
335
|
+
yield source_file, _command_slug(source_file)
|
|
336
|
+
|
|
337
|
+
|
|
315
338
|
def generate_claude_skills() -> None:
|
|
316
339
|
"""Create .claude/skills/ symlinks for ALL skills in .agent-src/skills/.
|
|
317
340
|
"""
|
|
@@ -321,16 +344,14 @@ def generate_claude_skills() -> None:
|
|
|
321
344
|
|
|
322
345
|
# All skill directories in .agent-src/skills/
|
|
323
346
|
skills = sorted([d.name for d in SKILLS_SOURCE.iterdir() if d.is_dir()])
|
|
324
|
-
# All command
|
|
325
|
-
|
|
326
|
-
if COMMANDS_SOURCE.exists():
|
|
327
|
-
command_names = {f.stem for f in COMMANDS_SOURCE.glob("*.md")}
|
|
347
|
+
# All command slugs (to protect from stale cleanup)
|
|
348
|
+
command_slugs = {slug for _, slug in _iter_commands()}
|
|
328
349
|
|
|
329
350
|
CLAUDE_SKILLS_DIR.mkdir(parents=True, exist_ok=True)
|
|
330
351
|
|
|
331
352
|
# Clean stale symlinks (but not converted commands or README)
|
|
332
353
|
for item in CLAUDE_SKILLS_DIR.iterdir():
|
|
333
|
-
if item.is_symlink() and item.name not in skills and item.name not in
|
|
354
|
+
if item.is_symlink() and item.name not in skills and item.name not in command_slugs and item.name != "README.md":
|
|
334
355
|
item.unlink()
|
|
335
356
|
|
|
336
357
|
count = 0
|
|
@@ -357,11 +378,15 @@ def extract_description_from_md(content: str) -> str:
|
|
|
357
378
|
|
|
358
379
|
|
|
359
380
|
def generate_claude_commands() -> None:
|
|
360
|
-
"""Create .claude/skills/{
|
|
381
|
+
"""Create .claude/skills/{slug}/SKILL.md symlinks for ALL Augment commands.
|
|
361
382
|
|
|
362
383
|
Commands in .agent-src/commands/ are the single source of truth.
|
|
363
384
|
They must include name: and disable-model-invocation: true in frontmatter
|
|
364
385
|
(added once, then maintained as part of the command file).
|
|
386
|
+
|
|
387
|
+
Top-level commands use their filename stem as the slug. Nested
|
|
388
|
+
cluster commands (e.g. `commands/council/default.md`) are flattened
|
|
389
|
+
to `council-default` so directories never collide in `.claude/skills/`.
|
|
365
390
|
"""
|
|
366
391
|
if not COMMANDS_SOURCE.exists():
|
|
367
392
|
print(" ⚠️ .agent-src/commands/ not found — skipping commands")
|
|
@@ -374,32 +399,53 @@ def generate_claude_commands() -> None:
|
|
|
374
399
|
if SKILLS_SOURCE.exists():
|
|
375
400
|
skill_names = {d.name for d in SKILLS_SOURCE.iterdir() if d.is_dir()}
|
|
376
401
|
|
|
402
|
+
# Track current command slugs for stale-directory cleanup
|
|
403
|
+
current_slugs: set[str] = set()
|
|
377
404
|
count = 0
|
|
378
405
|
skipped = 0
|
|
379
|
-
for source_file in
|
|
380
|
-
name = source_file.stem
|
|
381
|
-
|
|
406
|
+
for source_file, slug in _iter_commands():
|
|
382
407
|
# Skip if a real skill with the same name exists — skill takes priority
|
|
383
|
-
if
|
|
408
|
+
if slug in skill_names:
|
|
384
409
|
skipped += 1
|
|
385
410
|
continue
|
|
386
411
|
|
|
412
|
+
current_slugs.add(slug)
|
|
413
|
+
|
|
387
414
|
# Create skill directory (real dir, symlinked SKILL.md inside)
|
|
388
|
-
skill_dir = CLAUDE_SKILLS_DIR /
|
|
415
|
+
skill_dir = CLAUDE_SKILLS_DIR / slug
|
|
389
416
|
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
390
417
|
|
|
391
418
|
skill_file = skill_dir / "SKILL.md"
|
|
392
419
|
if skill_file.exists() or skill_file.is_symlink():
|
|
393
420
|
skill_file.unlink()
|
|
394
421
|
|
|
395
|
-
# Symlink: .claude/skills/{
|
|
396
|
-
|
|
422
|
+
# Symlink: .claude/skills/{slug}/SKILL.md → ../../../.agent-src/commands/<rel-path>
|
|
423
|
+
rel_path = source_file.relative_to(COMMANDS_SOURCE)
|
|
424
|
+
rel_target = Path("../../../.agent-src/commands") / rel_path
|
|
397
425
|
skill_file.symlink_to(rel_target)
|
|
398
426
|
count += 1
|
|
399
427
|
|
|
428
|
+
# Clean stale command skill directories — real dirs from removed commands.
|
|
429
|
+
# Only delete if the directory contains exactly the SKILL.md symlink we created.
|
|
430
|
+
removed_dirs = 0
|
|
431
|
+
for item in CLAUDE_SKILLS_DIR.iterdir():
|
|
432
|
+
if not item.is_dir() or item.is_symlink():
|
|
433
|
+
continue
|
|
434
|
+
if item.name in skill_names or item.name in current_slugs:
|
|
435
|
+
continue
|
|
436
|
+
skill_md = item / "SKILL.md"
|
|
437
|
+
if skill_md.is_symlink():
|
|
438
|
+
entries = list(item.iterdir())
|
|
439
|
+
if len(entries) == 1 and entries[0].name == "SKILL.md":
|
|
440
|
+
skill_md.unlink()
|
|
441
|
+
item.rmdir()
|
|
442
|
+
removed_dirs += 1
|
|
443
|
+
|
|
400
444
|
msg = f" ✅ Created {count} command symlinks in .claude/skills/"
|
|
401
445
|
if skipped:
|
|
402
446
|
msg += f" ({skipped} skipped — same-name skill exists)"
|
|
447
|
+
if removed_dirs:
|
|
448
|
+
msg += f" ({removed_dirs} stale dirs removed)"
|
|
403
449
|
print(msg)
|
|
404
450
|
|
|
405
451
|
|