@event4u/agent-config 9.9.0 → 9.10.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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +153 -194
- package/README.md +1 -1
- package/dist/agent-src/commands/agent-status.md +12 -11
- package/dist/agent-src/commands/agents/user/accept.md +115 -30
- package/dist/agent-src/commands/agents/user/delete.md +147 -0
- package/dist/agent-src/commands/agents/user/review.md +65 -28
- package/dist/agent-src/commands/agents/user/show.md +82 -29
- package/dist/agent-src/commands/agents/user/update.md +2 -2
- package/dist/agent-src/commands/agents/user.md +16 -3
- package/dist/agent-src/commands/check-current-md.md +0 -10
- package/dist/agent-src/commands/condense.md +28 -97
- package/dist/agent-src/commands/cost/report.md +7 -0
- package/dist/agent-src/commands/fix/portability.md +0 -8
- package/dist/agent-src/commands/fix/refs.md +0 -8
- package/dist/agent-src/commands/humanize.md +2 -2
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- package/dist/agent-src/commands/memory/load.md +11 -0
- package/dist/agent-src/commands/optimize/skills.md +1 -1
- package/dist/agent-src/commands/pr/create.md +4 -4
- package/dist/agent-src/commands/profile/show.md +3 -3
- package/dist/agent-src/commands/rule-compliance-audit.md +5 -4
- package/dist/agent-src/commands/security-audit-config.md +1 -1
- package/dist/agent-src/commands/sync/gitignore/fix.md +1 -1
- package/dist/agent-src/commands/tdd.md +21 -0
- package/dist/agent-src/commands/team/delegate.md +2 -2
- package/dist/agent-src/commands/team-knowledge/bootstrap.md +9 -8
- package/dist/agent-src/commands/team-knowledge/consolidate.md +8 -7
- package/dist/agent-src/commands/team.md +4 -1
- package/dist/agent-src/commands/upstream-contribute.md +0 -1
- package/dist/agent-src/contexts/authority/commit-mechanics.md +7 -0
- package/dist/agent-src/contexts/authority/destructive-mechanics.md +16 -0
- package/dist/agent-src/contexts/authority/scope-mechanics.md +61 -0
- package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +20 -18
- package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/source-of-truth-mechanics.md +9 -10
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +11 -0
- package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +26 -15
- package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +3 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +67 -37
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
- package/dist/agent-src/contexts/execution/autonomy-examples.md +1 -1
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +7 -6
- package/dist/agent-src/contexts/execution/evidence-discipline.md +92 -77
- package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +22 -21
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +24 -0
- package/dist/agent-src/contexts/execution/project-intelligence.md +122 -103
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +23 -21
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +5 -5
- package/dist/agent-src/contexts/execution/subagent-routing.md +11 -0
- package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +13 -13
- package/dist/agent-src/contexts/execution/subagent-steering.md +36 -34
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +1 -1
- package/dist/agent-src/contexts/execution/user-memory-channels.md +189 -0
- package/dist/agent-src/contexts/execution/verification-mechanics.md +9 -0
- package/dist/agent-src/contexts/model-recommendations.md +3 -2
- package/dist/agent-src/contexts/subagent-configuration.md +3 -3
- package/dist/agent-src/ghostwriter/README.md +2 -2
- package/dist/agent-src/packs/README.md +1 -1
- package/dist/agent-src/personas/README.md +5 -5
- package/dist/agent-src/personas/_template-specialist/persona.md +3 -3
- package/dist/agent-src/personas/backend-architect.md +24 -23
- package/dist/agent-src/personas/eloquent-tamer.md +30 -30
- package/dist/agent-src/personas/frontend-engineer.md +30 -30
- package/dist/agent-src/personas/product-owner.md +41 -38
- package/dist/agent-src/personas/qa.md +13 -13
- package/dist/agent-src/personas/security-engineer.md +22 -22
- package/dist/agent-src/presets/README.md +3 -3
- package/dist/agent-src/profiles/README.md +3 -3
- package/dist/agent-src/rules/active-remediation.md +2 -2
- package/dist/agent-src/rules/artifact-engagement-recording.md +4 -4
- package/dist/agent-src/rules/ask-when-uncertain.md +0 -4
- package/dist/agent-src/rules/augment-edit-discipline.md +1 -1
- package/dist/agent-src/rules/broken-access-control.md +4 -4
- package/dist/agent-src/rules/code-comment-discipline.md +1 -1
- package/dist/agent-src/rules/code-provenance.md +2 -2
- package/dist/agent-src/rules/commit-policy.md +4 -9
- package/dist/agent-src/rules/communication-through-line.md +5 -5
- package/dist/agent-src/rules/decision-revisit-gate.md +1 -1
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -1
- package/dist/agent-src/rules/domain-adoption-policy.md +1 -1
- package/dist/agent-src/rules/domain-safety-pii.md +1 -1
- package/dist/agent-src/rules/external-code-graph-interop.md +1 -1
- package/dist/agent-src/rules/fast-path-marker-visibility.md +43 -7
- package/dist/agent-src/rules/finance-safety-floor.md +1 -1
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +3 -3
- package/dist/agent-src/rules/history-discipline.md +1 -1
- package/dist/agent-src/rules/legal-safety-floor.md +1 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +5 -5
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +10 -8
- package/dist/agent-src/rules/media-governance-routing.md +13 -13
- package/dist/agent-src/rules/media-sync-ground-truth.md +29 -11
- package/dist/agent-src/rules/no-cheap-questions.md +7 -7
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +29 -18
- package/dist/agent-src/rules/non-destructive-by-default.md +5 -23
- package/dist/agent-src/rules/onboarding-gate.md +14 -4
- package/dist/agent-src/rules/persona-governance.md +2 -2
- package/dist/agent-src/rules/prefer-enums-over-literals.md +9 -9
- package/dist/agent-src/rules/preservation-guard.md +10 -2
- package/dist/agent-src/rules/question-not-instruction.md +1 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +6 -6
- package/dist/agent-src/rules/rule-type-governance.md +1 -1
- package/dist/agent-src/rules/scale-discipline.md +1 -1
- package/dist/agent-src/rules/scope-control.md +1 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +1 -1
- package/dist/agent-src/rules/security-sensitive-stop.md +17 -11
- package/dist/agent-src/rules/senior-engineering-discipline.md +17 -17
- package/dist/agent-src/rules/session-canary.md +1 -1
- package/dist/agent-src/rules/skill-quality.md +1 -1
- package/dist/agent-src/rules/source-confidentiality.md +21 -19
- package/dist/agent-src/rules/source-of-truth.md +6 -5
- package/dist/agent-src/rules/spreadsheet-source-quality.md +2 -2
- package/dist/agent-src/rules/strategy-safety-floor.md +1 -1
- package/dist/agent-src/rules/think-before-action.md +5 -5
- package/dist/agent-src/rules/token-budget-discipline.md +5 -3
- package/dist/agent-src/rules/token-efficiency.md +2 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +4 -4
- package/dist/agent-src/rules/user-interaction.md +12 -0
- package/dist/agent-src/rules/verify-before-complete.md +4 -24
- package/dist/agent-src/skills/adversarial-review/SKILL.md +2 -2
- package/dist/agent-src/skills/agent-security-review/SKILL.md +52 -45
- package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +2 -2
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +20 -20
- package/dist/agent-src/skills/ai-council/SKILL.md +185 -128
- package/dist/agent-src/skills/analysis-skill-router/SKILL.md +3 -3
- package/dist/agent-src/skills/api-endpoint/SKILL.md +2 -2
- package/dist/agent-src/skills/artisan-commands/SKILL.md +2 -2
- package/dist/agent-src/skills/async-python-patterns/SKILL.md +8 -7
- package/dist/agent-src/skills/authz-review/SKILL.md +16 -15
- package/dist/agent-src/skills/aws-infrastructure/SKILL.md +5 -5
- package/dist/agent-src/skills/blade-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +30 -12
- package/dist/agent-src/skills/code-intelligence/SKILL.md +0 -1
- package/dist/agent-src/skills/code-intelligence/evals/triggers.json +52 -0
- package/dist/agent-src/skills/code-review/SKILL.md +6 -6
- package/dist/agent-src/skills/command-routing/SKILL.md +5 -4
- package/dist/agent-src/skills/composer-packages/SKILL.md +2 -2
- package/dist/agent-src/skills/condense-memory/SKILL.md +43 -41
- package/dist/agent-src/skills/context-document/SKILL.md +23 -21
- package/dist/agent-src/skills/copilot-config/SKILL.md +6 -1
- package/dist/agent-src/skills/decision-record/SKILL.md +20 -18
- package/dist/agent-src/skills/design-intelligence/SKILL.md +4 -4
- package/dist/agent-src/skills/design-review/SKILL.md +15 -14
- package/dist/agent-src/skills/design-system-capture/reference/design-system-json.md +28 -25
- package/dist/agent-src/skills/devcontainer/SKILL.md +2 -2
- package/dist/agent-src/skills/docker/SKILL.md +1 -1
- package/dist/agent-src/skills/docx-authoring/evals/triggers.json +52 -0
- package/dist/agent-src/skills/emit-tickets/SKILL.md +2 -2
- package/dist/agent-src/skills/error-handling-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +2 -2
- package/dist/agent-src/skills/evaluate-llm-feature/SKILL.md +0 -1
- package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +52 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +6 -5
- package/dist/agent-src/skills/feature-planning/SKILL.md +2 -2
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +3 -3
- package/dist/agent-src/skills/flux/SKILL.md +1 -1
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +13 -13
- package/dist/agent-src/skills/git-workflow/SKILL.md +33 -33
- package/dist/agent-src/skills/grafana/SKILL.md +5 -0
- package/dist/agent-src/skills/humanizer/SKILL.md +83 -66
- package/dist/agent-src/skills/humanizer/data/patterns.md +14 -14
- package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +4 -4
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +82 -37
- package/dist/agent-src/skills/judge-bug-hunter/SKILL.md +17 -5
- package/dist/agent-src/skills/judge-injection-defense/SKILL.md +63 -25
- package/dist/agent-src/skills/judge-security-auditor/SKILL.md +2 -0
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +72 -28
- package/dist/agent-src/skills/laravel-horizon/SKILL.md +5 -0
- package/dist/agent-src/skills/laravel-mail/SKILL.md +5 -4
- package/dist/agent-src/skills/laravel-middleware/SKILL.md +5 -4
- package/dist/agent-src/skills/laravel-notifications/SKILL.md +10 -9
- package/dist/agent-src/skills/laravel-pennant/SKILL.md +1 -1
- package/dist/agent-src/skills/laravel-pulse/SKILL.md +9 -8
- package/dist/agent-src/skills/laravel-reverb/SKILL.md +6 -5
- package/dist/agent-src/skills/laravel-scheduling/SKILL.md +6 -1
- package/dist/agent-src/skills/laravel-validation/SKILL.md +12 -0
- package/dist/agent-src/skills/launch-readiness/SKILL.md +1 -1
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +7 -7
- package/dist/agent-src/skills/learning-tutor/SKILL.md +44 -43
- package/dist/agent-src/skills/learning-tutor/evals/triggers.json +52 -0
- package/dist/agent-src/skills/license-compliance-audit/SKILL.md +7 -7
- package/dist/agent-src/skills/license-compliance-borrow-check/SKILL.md +3 -3
- package/dist/agent-src/skills/license-compliance-credits/SKILL.md +4 -4
- package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +0 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +69 -64
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +6 -6
- package/dist/agent-src/skills/pdf-tools/evals/triggers.json +52 -0
- package/dist/agent-src/skills/performance-analysis/SKILL.md +7 -3
- package/dist/agent-src/skills/persona-improvement/SKILL.md +0 -2
- package/dist/agent-src/skills/persona-improvement/evals/triggers.json +52 -0
- package/dist/agent-src/skills/php-coder/SKILL.md +10 -0
- package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +129 -120
- package/dist/agent-src/skills/prediction-pool-optimizer/reference/ev-fixtures.md +36 -35
- package/dist/agent-src/skills/prediction-pool-optimizer/reference/odds-and-bonus.md +45 -41
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +4 -4
- package/dist/agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +3 -3
- package/dist/agent-src/skills/project-analysis-react/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analysis-symfony/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analysis-zend-laminas/SKILL.md +2 -2
- package/dist/agent-src/skills/prompt-engineering-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/prompt-validator/SKILL.md +39 -39
- package/dist/agent-src/skills/quality-tools/SKILL.md +15 -15
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +55 -19
- package/dist/agent-src/skills/react-shadcn-ui/reference/registry.md +29 -27
- package/dist/agent-src/skills/readme-writing-package/SKILL.md +2 -2
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +25 -25
- package/dist/agent-src/skills/recursive-verification/SKILL.md +6 -5
- package/dist/agent-src/skills/refine-prompt/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +20 -2
- package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
- package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
- package/dist/agent-src/skills/roadmap-management/SKILL.md +80 -66
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +84 -77
- package/dist/agent-src/skills/rule-refactor/SKILL.md +1 -1
- package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +52 -0
- package/dist/agent-src/skills/security-audit/SKILL.md +26 -9
- package/dist/agent-src/skills/security-maturity-assessment/SKILL.md +38 -16
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +14 -11
- package/dist/agent-src/skills/skill-writing/SKILL.md +9 -8
- package/dist/agent-src/skills/song-to-script/SKILL.md +93 -85
- package/dist/agent-src/skills/sql-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/stakeholder-tradeoff/SKILL.md +4 -3
- package/dist/agent-src/skills/standards-from-config/SKILL.md +61 -43
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +22 -8
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +28 -2
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +13 -13
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +22 -21
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/technical-specification/SKILL.md +5 -0
- package/dist/agent-src/skills/terraform/SKILL.md +2 -2
- package/dist/agent-src/skills/terragrunt/SKILL.md +8 -8
- package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +1 -1
- package/dist/agent-src/skills/threat-modeling/SKILL.md +19 -13
- package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +0 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +9 -9
- package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -1
- package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +4 -6
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +67 -61
- package/dist/agent-src/skills/video-director/SKILL.md +7 -7
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +3 -3
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/contexts/knowledge-pages.md +47 -45
- package/dist/agent-src/templates/contexts/lesson-card.md +2 -2
- package/dist/agent-src/templates/contexts/tenant-boundaries.md +2 -2
- package/dist/agent-src/templates/contexts.md +1 -1
- package/dist/agent-src/templates/features.md +1 -1
- package/dist/agent-src/templates/roadmaps.md +125 -116
- package/dist/agent-src/templates/rule.md +2 -1
- package/dist/agent-src/templates/scripts/pr_risk_review.ts +0 -0
- package/dist/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
- package/dist/agent-src/templates/scripts/tier_usage_report.ts +2 -2
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -2
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +1 -1
- package/dist/agent-src/user-types/README.md +8 -8
- package/dist/agent-src/user-types/galabau-field-crew.md +34 -33
- package/dist/agent-src/user-types/metalworking-shop.md +35 -34
- package/dist/agent-src/user-types/truck-driver.md +22 -20
- package/dist/cli/python/workspace_roles.js +2 -2
- package/dist/cli/python/workspace_roles.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +88 -62
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +186 -12
- package/dist/install/install.mjs +8 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1199 -857
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/compile_time_toggles.js +48 -0
- package/dist/scripts/_lib/compile_time_toggles.js.map +1 -0
- package/dist/scripts/condense.js +234 -217
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +4 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/shared/userMd/utils.js +30 -0
- package/dist/shared/userMd/utils.js.map +1 -1
- package/dist/ui/assets/index-BpSQt5vm.js.map +1 -1
- package/docs/guidelines/agent-infra/api-cost-levers.md +56 -5
- package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +93 -33
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/pr_risk_review.ts +0 -0
- package/src/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
- package/src/agent-src/templates/scripts/tier_usage_report.ts +2 -2
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -2
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +1 -1
- package/src/config/agent-settings.template.yml +32 -2
- package/src/config/ci-local-parity.yml +142 -0
- package/src/config/gate-coverage.yml +127 -0
- package/src/config/preamble-payload-budget.json +44 -0
- package/src/scripts/_cli/cmd_doctor.ts +78 -2
- package/src/scripts/_lib/agent_user_profile.ts +381 -0
- package/src/scripts/_lib/agents_overlay.ts +9 -0
- package/src/scripts/_lib/anchor_eval.ts +311 -0
- package/src/scripts/_lib/cc_transcript.ts +316 -0
- package/src/scripts/_lib/compile_time_toggles.ts +79 -0
- package/src/scripts/_lib/confusables.ts +101 -0
- package/src/scripts/_lib/duplicate_scope_census.ts +77 -0
- package/src/scripts/_lib/managed_agents_folder.ts +181 -0
- package/src/scripts/_lib/payload_hash_drift.ts +126 -0
- package/src/scripts/_lib/preservation_migration.ts +291 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +166 -2
- package/src/scripts/_lib/scan_scope.ts +115 -0
- package/src/scripts/_lib/user_global_memory_audit.ts +187 -0
- package/src/scripts/_lib/user_global_observations.ts +830 -0
- package/src/scripts/_lib/user_global_revocations.ts +110 -0
- package/src/scripts/_lib/user_memory_gate_counters.ts +291 -0
- package/src/scripts/ai_council/blind_review.ts +0 -0
- package/src/scripts/ai_council/budget_guard.ts +90 -11
- package/src/scripts/ai_council/bundler.ts +2 -2
- package/src/scripts/ai_council/clients.ts +59 -3
- package/src/scripts/ai_council/config.ts +38 -0
- package/src/scripts/ai_council/orchestrator.ts +54 -9
- package/src/scripts/ai_team/team_dispatch.ts +17 -6
- package/src/scripts/anchor_eval_falsify.ts +198 -0
- package/src/scripts/anchor_scoring_run.ts +239 -0
- package/src/scripts/annotate_discovery.ts +1 -65
- package/src/scripts/bench_quality_run.ts +168 -4
- package/src/scripts/cache_realization_report.ts +782 -0
- package/src/scripts/check_artefact_count_messaging.ts +5 -1
- package/src/scripts/check_augment_description_cap.ts +15 -4
- package/src/scripts/check_ci_local_parity.ts +317 -0
- package/src/scripts/check_condensation.ts +96 -191
- package/src/scripts/check_context_paths.ts +38 -9
- package/src/scripts/check_gate_coverage.ts +299 -0
- package/src/scripts/check_iron_law_prominence.ts +22 -1
- package/src/scripts/check_kernel_prefix_stability.ts +0 -0
- package/src/scripts/check_no_new_legacy_path.ts +16 -6
- package/src/scripts/check_no_roadmap_refs.ts +22 -9
- package/src/scripts/check_originality_freshness.ts +167 -0
- package/src/scripts/check_preamble_payload_budget.ts +130 -0
- package/src/scripts/check_proposal.ts +0 -0
- package/src/scripts/check_references.ts +0 -1
- package/src/scripts/check_safety_floor_untouched.ts +171 -24
- package/src/scripts/check_site_links.ts +62 -3
- package/src/scripts/ci_status.ts +0 -0
- package/src/scripts/cluster_near_miss_patterns.ts +0 -0
- package/src/scripts/code_graph/build.ts +0 -0
- package/src/scripts/command_suggester/types.ts +0 -0
- package/src/scripts/compile_router.ts +10 -14
- package/src/scripts/condense.sh +3 -4
- package/src/scripts/condense.ts +247 -228
- package/src/scripts/cost/track.mjs +168 -33
- package/src/scripts/cost_summary.ts +33 -1
- package/src/scripts/council_cli.ts +45 -3
- package/src/scripts/discovery_graph.ts +0 -0
- package/src/scripts/encoding_corpus.ts +500 -0
- package/src/scripts/encoding_corpus_report.ts +216 -0
- package/src/scripts/generate_index.ts +19 -2
- package/src/scripts/install-hooks.sh +2 -2
- package/src/scripts/learning_sidecar.ts +0 -0
- package/src/scripts/lint_confusables.ts +10 -72
- package/src/scripts/lint_featured_skills.ts +0 -0
- package/src/scripts/lint_hidden_unicode.ts +208 -0
- package/src/scripts/lint_load_context.ts +17 -5
- package/src/scripts/lint_new_skill_gate.ts +9 -3
- package/src/scripts/lint_no_python_twin_rationale.ts +17 -2
- package/src/scripts/lint_originality.ts +1 -1
- package/src/scripts/lint_skill_originality.ts +1 -1
- package/src/scripts/lint_ticket_buildable.ts +1 -1
- package/src/scripts/mcp_server/tools.ts +4 -4
- package/src/scripts/measure_scope_dedup.ts +224 -0
- package/src/scripts/memory_lookup.ts +0 -0
- package/src/scripts/mine_session.ts +98 -0
- package/src/scripts/orchestration_payload_hash_drift.ts +145 -0
- package/src/scripts/preamble_byte_census.ts +574 -0
- package/src/scripts/probe_skill_registration.ts +2 -2
- package/src/scripts/redact_hook_capture.ts +13 -0
- package/src/scripts/release.ts +65 -10
- package/src/scripts/router_telemetry.ts +1 -1
- package/src/scripts/second_brain_retrieval.ts +14 -4
- package/src/scripts/skill_linter.ts +5 -0
- package/src/scripts/surface-tiers.yml +2 -0
- package/src/scripts/validate_pack_yaml.ts +0 -0
- package/src/server/schemas/settings.ts +8 -0
- package/src/shared/userMd/utils.ts +31 -0
- package/dist/agent-src/rules/telegraph-speak.md +0 -87
|
@@ -58,7 +58,11 @@ export const SURFACES: readonly string[] = [
|
|
|
58
58
|
// watched this file. Added 2026-07-25 so a hand-typed count here fails CI.
|
|
59
59
|
'docs/distribution/registries.md',
|
|
60
60
|
'site/src/content/docs/index.mdx',
|
|
61
|
-
|
|
61
|
+
// NOT site/src/content/docs/claims.md — it is gitignored generated output
|
|
62
|
+
// (site/sync-docs.mjs copies docs/CLAIMS.md into it), and docs/CLAIMS.md is
|
|
63
|
+
// already checked above. Watching the copy added no coverage and turned a
|
|
64
|
+
// stale LOCAL artefact into a red gate, while CI passed because the file is
|
|
65
|
+
// absent there. A gate must judge repo content, not untracked local state.
|
|
62
66
|
];
|
|
63
67
|
|
|
64
68
|
/** kind → canonical-count resolver. "governed rules" is the canonical total
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* Ported from the retired Python `src/scripts/check_augment_description_cap.py` (ADR-200,
|
|
7
7
|
* Phase 4 / Wave 4c). The CLI contract is pinned — no flags, exit
|
|
8
8
|
* codes (0 pass, 1 over-cap), stdout/stderr split, byte-identical finding
|
|
9
|
-
* messages, same scan scope (
|
|
9
|
+
* messages, same scan scope (`src/rules/*.md`) and file
|
|
10
10
|
* ordering. Historical quirks are preserved deliberately — tests and downstream consumers pin the exact behaviour.
|
|
11
11
|
*
|
|
12
|
-
* For every `type: auto` rule under
|
|
12
|
+
* For every `type: auto` rule under `src/rules/`,
|
|
13
13
|
* fail CI when the frontmatter `description:` exceeds DESC_CAP chars.
|
|
14
14
|
*
|
|
15
15
|
* Why: Augment injects each auto-rule's description into the
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* analysis showed this channel consuming 25 % of the workspace-guidelines
|
|
18
18
|
* ceiling. Capping descriptions guards future drift.
|
|
19
19
|
*
|
|
20
|
-
* Source of truth:
|
|
20
|
+
* Source of truth: `src/rules/`. The condensed
|
|
21
21
|
* projection is regenerated; the source dictates what ships.
|
|
22
22
|
*
|
|
23
23
|
* Exit codes: 0 = pass, 1 = at least one rule over cap.
|
|
@@ -31,7 +31,12 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
31
31
|
// Mirrors the Python `Path(__file__).resolve().parent.parent.parent`.
|
|
32
32
|
const _HERE = fileURLToPath(import.meta.url);
|
|
33
33
|
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
34
|
-
|
|
34
|
+
// Retargeted 2026-07-29: pointed at the tree emptied by the ADR-051 flat-`src/`
|
|
35
|
+
// migration, so this gate printed "All 0 auto-rule descriptions ≤ 150 chars." and
|
|
36
|
+
// exited 0 while wired into CI — the count sat in its own output the whole time.
|
|
37
|
+
// Retargeting surfaced 16 real cap violations (98 auto-rules, max 189); all 16
|
|
38
|
+
// were shortened under an explicit operator review that kept every matching term.
|
|
39
|
+
const RULES_DIR = path.join(REPO_ROOT, 'src', 'rules');
|
|
35
40
|
const DESC_CAP = 150;
|
|
36
41
|
|
|
37
42
|
const _FM_LINE_RE = /^([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/;
|
|
@@ -103,6 +108,12 @@ export function main(): number {
|
|
|
103
108
|
}
|
|
104
109
|
}
|
|
105
110
|
|
|
111
|
+
// Gate-coverage contract (src/config/gate-coverage.yml): emitted BEFORE the
|
|
112
|
+
// pass/fail branch. Coverage and verdict are different questions — a gate that
|
|
113
|
+
// found real violations still scanned its corpus, and reporting the count only
|
|
114
|
+
// on the success path would make it look 'silent' to check_gate_coverage.
|
|
115
|
+
process.stdout.write(`scanned: ${String(checked)}\n`);
|
|
116
|
+
|
|
106
117
|
if (failures.length) {
|
|
107
118
|
process.stderr.write(
|
|
108
119
|
`❌ ${failures.length} auto-rule description(s) exceed ${DESC_CAP} chars:\n\n`,
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* CI ↔ local parity checker.
|
|
4
|
+
*
|
|
5
|
+
* A gate that exists on one side only drifts silently on the other, and both
|
|
6
|
+
* directions cost real defects (see `src/config/ci-local-parity.yml` for the
|
|
7
|
+
* measured cases). This checker DERIVES both sides rather than trusting a list:
|
|
8
|
+
*
|
|
9
|
+
* CI side every gate invocation in `.github/workflows/*.yml`
|
|
10
|
+
* local side the transitive closure of `task ci` / `task consistency` plus the
|
|
11
|
+
* pre-push hook, resolved through `Taskfile.yml` + `taskfiles/*.yml`
|
|
12
|
+
*
|
|
13
|
+
* Anything on one side and not the other must be declared in the manifest with a
|
|
14
|
+
* reason, or this fails. Drift stays allowed — but only on the record.
|
|
15
|
+
*
|
|
16
|
+
* Deriving beats listing because a hand-maintained list is exactly what goes stale:
|
|
17
|
+
* the first version of this analysis was done with a one-level grep and reported 71
|
|
18
|
+
* CI-only gates when the real number was 12. The closure is the whole point.
|
|
19
|
+
*
|
|
20
|
+
* Exit codes: 0 parity declared · 1 undeclared drift · 2 manifest/IO error.
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* ./scripts-run src/scripts/check_ci_local_parity
|
|
24
|
+
* ./scripts-run src/scripts/check_ci_local_parity --format json
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import * as fs from 'node:fs';
|
|
28
|
+
import * as path from 'node:path';
|
|
29
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
30
|
+
|
|
31
|
+
import { parse as parseYaml } from 'yaml';
|
|
32
|
+
|
|
33
|
+
const _FILE = fileURLToPath(import.meta.url);
|
|
34
|
+
export const REPO = path.resolve(path.dirname(_FILE), '..', '..');
|
|
35
|
+
const MANIFEST = path.join(REPO, 'src', 'config', 'ci-local-parity.yml');
|
|
36
|
+
const HOOK = path.join(REPO, 'src', 'scripts', 'install-hooks.sh');
|
|
37
|
+
|
|
38
|
+
/** Roots of the local closure. `ci` is the local mirror; the hook is what a push runs. */
|
|
39
|
+
const LOCAL_ROOTS = ['ci', 'consistency'] as const;
|
|
40
|
+
|
|
41
|
+
export interface Declared {
|
|
42
|
+
id: string;
|
|
43
|
+
class: string;
|
|
44
|
+
reason: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface Manifest {
|
|
48
|
+
pre_push_budget_seconds: number;
|
|
49
|
+
ci_only: Declared[];
|
|
50
|
+
local_only: Declared[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function load_manifest(file = MANIFEST): Manifest {
|
|
54
|
+
if (!fs.existsSync(file)) {
|
|
55
|
+
throw new Error(`manifest not found: ${path.relative(REPO, file)}`);
|
|
56
|
+
}
|
|
57
|
+
const doc = parseYaml(fs.readFileSync(file, 'utf-8')) as Record<string, unknown>;
|
|
58
|
+
const read = (key: string): Declared[] => {
|
|
59
|
+
const raw = doc[key];
|
|
60
|
+
if (raw === null || raw === undefined) return [];
|
|
61
|
+
if (!Array.isArray(raw)) throw new Error(`${key} must be a list`);
|
|
62
|
+
return raw.map((e, i) => {
|
|
63
|
+
const o = e as Record<string, unknown>;
|
|
64
|
+
const id = String(o['id'] ?? '');
|
|
65
|
+
if (id === '') throw new Error(`${key}[${String(i)}]: missing id`);
|
|
66
|
+
const reason = String(o['reason'] ?? '');
|
|
67
|
+
if (reason.trim() === '') {
|
|
68
|
+
// A declaration without a reason is the escape hatch that eats the
|
|
69
|
+
// gate: it looks reviewed and says nothing.
|
|
70
|
+
throw new Error(`${key} (${id}): reason must be non-empty`);
|
|
71
|
+
}
|
|
72
|
+
return { id, class: String(o['class'] ?? 'unclassified'), reason };
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
const budget = Number(doc['pre_push_budget_seconds']);
|
|
76
|
+
if (!Number.isFinite(budget) || budget <= 0) {
|
|
77
|
+
throw new Error('pre_push_budget_seconds must be a positive number');
|
|
78
|
+
}
|
|
79
|
+
return { pre_push_budget_seconds: budget, ci_only: read('ci_only'), local_only: read('local_only') };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Gate ids invoked anywhere in a blob of shell/YAML text. */
|
|
83
|
+
export function extract_gates(text: string): Set<string> {
|
|
84
|
+
const out = new Set<string>();
|
|
85
|
+
// ./scripts-run src/scripts/<name> | npx tsx src/scripts/<name>.ts | .sh
|
|
86
|
+
//
|
|
87
|
+
// The negative lookahead rejects a DIRECTORY segment: `src/scripts/_lib/x.ts`
|
|
88
|
+
// must not register `_lib` as a gate. Without it the first run reported 23
|
|
89
|
+
// CI-only gates, 10 of which were directory names (_cli, _lib, mcp_server, …) —
|
|
90
|
+
// a checker whose own extraction invents gates is worse than none, because every
|
|
91
|
+
// real finding then sits in a pile of noise. The backslash in the class is not
|
|
92
|
+
// decoration: the pre-push hook greps an escaped path (`pack_dependency_allowlist\.json`),
|
|
93
|
+
// and without it that JSON file registered as a local-only gate.
|
|
94
|
+
for (const m of text.matchAll(/src\/scripts\/([a-z0-9_]+)(?:\.(?:ts|sh))?(?![\w/.\\-])/g)) {
|
|
95
|
+
out.add(m[1] as string);
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** `task <name>` references in a blob of shell/YAML text. */
|
|
101
|
+
export function extract_tasks(text: string): Set<string> {
|
|
102
|
+
const out = new Set<string>();
|
|
103
|
+
for (const m of text.matchAll(/\btask\s+([a-z][a-z0-9:_-]*)/g)) {
|
|
104
|
+
out.add(m[1] as string);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface TaskDef {
|
|
110
|
+
cmds: string[];
|
|
111
|
+
deps: string[];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Every task in Taskfile.yml + taskfiles/*.yml, flattened by name. */
|
|
115
|
+
export function load_tasks(repo = REPO): Map<string, TaskDef> {
|
|
116
|
+
const files = [path.join(repo, 'Taskfile.yml')];
|
|
117
|
+
const dir = path.join(repo, 'taskfiles');
|
|
118
|
+
if (fs.existsSync(dir)) {
|
|
119
|
+
for (const f of fs.readdirSync(dir).sort()) {
|
|
120
|
+
if (f.endsWith('.yml') || f.endsWith('.yaml')) files.push(path.join(dir, f));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const tasks = new Map<string, TaskDef>();
|
|
124
|
+
for (const file of files) {
|
|
125
|
+
if (!fs.existsSync(file)) continue;
|
|
126
|
+
let doc: Record<string, unknown>;
|
|
127
|
+
try {
|
|
128
|
+
doc = parseYaml(fs.readFileSync(file, 'utf-8')) as Record<string, unknown>;
|
|
129
|
+
} catch {
|
|
130
|
+
continue; // a malformed taskfile is another gate's verdict, not ours
|
|
131
|
+
}
|
|
132
|
+
const raw = doc['tasks'];
|
|
133
|
+
if (typeof raw !== 'object' || raw === null) continue;
|
|
134
|
+
for (const [name, body] of Object.entries(raw as Record<string, unknown>)) {
|
|
135
|
+
const def: TaskDef = { cmds: [], deps: [] };
|
|
136
|
+
const b = (typeof body === 'object' && body !== null ? body : {}) as Record<string, unknown>;
|
|
137
|
+
for (const key of ['cmd', 'cmds', 'deps']) {
|
|
138
|
+
const v = b[key];
|
|
139
|
+
if (typeof v === 'string') def.cmds.push(v);
|
|
140
|
+
else if (Array.isArray(v)) {
|
|
141
|
+
for (const item of v) {
|
|
142
|
+
if (typeof item === 'string') {
|
|
143
|
+
if (key === 'deps') def.deps.push(item);
|
|
144
|
+
else def.cmds.push(item);
|
|
145
|
+
} else if (typeof item === 'object' && item !== null) {
|
|
146
|
+
const o = item as Record<string, unknown>;
|
|
147
|
+
if (typeof o['task'] === 'string') def.deps.push(o['task']);
|
|
148
|
+
if (typeof o['cmd'] === 'string') def.cmds.push(o['cmd']);
|
|
149
|
+
if (typeof o['defer'] === 'object' && o['defer'] !== null) {
|
|
150
|
+
const d = o['defer'] as Record<string, unknown>;
|
|
151
|
+
if (typeof d['task'] === 'string') def.deps.push(d['task']);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Later files win only if the name is new — mirrors `flatten: true`.
|
|
158
|
+
if (!tasks.has(name)) tasks.set(name, def);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return tasks;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Transitive closure of gate ids reachable from a set of task roots. */
|
|
165
|
+
export function local_closure(roots: readonly string[], tasks: Map<string, TaskDef>): Set<string> {
|
|
166
|
+
const gates = new Set<string>();
|
|
167
|
+
const seen = new Set<string>();
|
|
168
|
+
const queue = [...roots];
|
|
169
|
+
while (queue.length > 0) {
|
|
170
|
+
const name = queue.shift() as string;
|
|
171
|
+
if (seen.has(name)) continue;
|
|
172
|
+
seen.add(name);
|
|
173
|
+
const def = tasks.get(name);
|
|
174
|
+
if (def === undefined) continue;
|
|
175
|
+
for (const blob of [...def.cmds]) {
|
|
176
|
+
for (const g of extract_gates(blob)) gates.add(g);
|
|
177
|
+
for (const t of extract_tasks(blob)) queue.push(t);
|
|
178
|
+
}
|
|
179
|
+
for (const d of def.deps) queue.push(d);
|
|
180
|
+
}
|
|
181
|
+
return gates;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function _read_all(dir: string): string {
|
|
185
|
+
if (!fs.existsSync(dir)) return '';
|
|
186
|
+
return fs
|
|
187
|
+
.readdirSync(dir)
|
|
188
|
+
.filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))
|
|
189
|
+
.sort()
|
|
190
|
+
.map((f) => fs.readFileSync(path.join(dir, f), 'utf-8'))
|
|
191
|
+
.join('\n');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface ParityReport {
|
|
195
|
+
ci_gates: string[];
|
|
196
|
+
local_gates: string[];
|
|
197
|
+
undeclared_ci_only: string[];
|
|
198
|
+
undeclared_local_only: string[];
|
|
199
|
+
stale_declarations: string[];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function analyse(repo = REPO, manifest?: Manifest): ParityReport {
|
|
203
|
+
const mf = manifest ?? load_manifest();
|
|
204
|
+
const tasks = load_tasks(repo);
|
|
205
|
+
|
|
206
|
+
const ciText = _read_all(path.join(repo, '.github', 'workflows'));
|
|
207
|
+
const ciGates = new Set(extract_gates(ciText));
|
|
208
|
+
// A workflow may reach a gate through a task, so expand those too.
|
|
209
|
+
for (const t of extract_tasks(ciText)) {
|
|
210
|
+
for (const g of local_closure([t], tasks)) ciGates.add(g);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const localGates = local_closure(LOCAL_ROOTS, tasks);
|
|
214
|
+
if (fs.existsSync(HOOK)) {
|
|
215
|
+
const hook = fs.readFileSync(HOOK, 'utf-8');
|
|
216
|
+
for (const g of extract_gates(hook)) localGates.add(g);
|
|
217
|
+
for (const t of extract_tasks(hook)) {
|
|
218
|
+
for (const g of local_closure([t], tasks)) localGates.add(g);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const declaredCi = new Set(mf.ci_only.map((d) => d.id));
|
|
223
|
+
const declaredLocal = new Set(mf.local_only.map((d) => d.id));
|
|
224
|
+
|
|
225
|
+
const undeclared_ci_only = [...ciGates].filter((g) => !localGates.has(g) && !declaredCi.has(g)).sort();
|
|
226
|
+
const undeclared_local_only = [...localGates].filter((g) => !ciGates.has(g) && !declaredLocal.has(g)).sort();
|
|
227
|
+
// A declaration for a gate that is now on both sides is stale — it grants an
|
|
228
|
+
// exemption nothing needs, and the next reader trusts it.
|
|
229
|
+
const stale_declarations = [
|
|
230
|
+
...[...declaredCi].filter((g) => localGates.has(g) && ciGates.has(g)),
|
|
231
|
+
...[...declaredLocal].filter((g) => localGates.has(g) && ciGates.has(g)),
|
|
232
|
+
].sort();
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
ci_gates: [...ciGates].sort(),
|
|
236
|
+
local_gates: [...localGates].sort(),
|
|
237
|
+
undeclared_ci_only,
|
|
238
|
+
undeclared_local_only,
|
|
239
|
+
stale_declarations,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
244
|
+
const wantJson = argv.includes('--format') && argv[argv.indexOf('--format') + 1] === 'json';
|
|
245
|
+
let mf: Manifest;
|
|
246
|
+
try {
|
|
247
|
+
mf = load_manifest();
|
|
248
|
+
} catch (e) {
|
|
249
|
+
process.stderr.write(`❌ ci-local-parity manifest: ${(e as Error).message}\n`);
|
|
250
|
+
return 2;
|
|
251
|
+
}
|
|
252
|
+
const r = analyse(REPO, mf);
|
|
253
|
+
|
|
254
|
+
if (wantJson) {
|
|
255
|
+
process.stdout.write(`${JSON.stringify({ generated_by: 'check_ci_local_parity', ...r }, null, 2)}\n`);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Emitted on every path, including failure — a gate with findings must still
|
|
259
|
+
// report what it inspected.
|
|
260
|
+
process.stderr.write(`scanned: ${String(r.ci_gates.length + r.local_gates.length)}\n`);
|
|
261
|
+
|
|
262
|
+
let failed = false;
|
|
263
|
+
if (r.undeclared_ci_only.length > 0) {
|
|
264
|
+
failed = true;
|
|
265
|
+
process.stdout.write(
|
|
266
|
+
`❌ ${String(r.undeclared_ci_only.length)} gate(s) run in CI but are unreachable locally:\n`,
|
|
267
|
+
);
|
|
268
|
+
for (const g of r.undeclared_ci_only) process.stdout.write(` - ${g}\n`);
|
|
269
|
+
process.stdout.write(
|
|
270
|
+
"\n Either wire it into the `task ci` chain, or declare it under `ci_only:` in\n" +
|
|
271
|
+
' src/config/ci-local-parity.yml with the reason it cannot run locally.\n' +
|
|
272
|
+
' Undeclared, it means a contributor discovers this failure only after pushing.\n',
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
if (r.undeclared_local_only.length > 0) {
|
|
276
|
+
failed = true;
|
|
277
|
+
process.stdout.write(
|
|
278
|
+
`❌ ${String(r.undeclared_local_only.length)} gate(s) run locally but in no workflow:\n`,
|
|
279
|
+
);
|
|
280
|
+
for (const g of r.undeclared_local_only) process.stdout.write(` - ${g}\n`);
|
|
281
|
+
process.stdout.write(
|
|
282
|
+
'\n Prefer adding it to a workflow — this is the direction that let real defects\n' +
|
|
283
|
+
' merge (16 stale index rows reached main behind a local-only check-index).\n' +
|
|
284
|
+
' If remote enforcement is genuinely not wanted, declare it under `local_only:`.\n',
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
if (r.stale_declarations.length > 0) {
|
|
288
|
+
failed = true;
|
|
289
|
+
process.stdout.write(
|
|
290
|
+
`❌ ${String(r.stale_declarations.length)} stale declaration(s) — now on BOTH sides, so the exemption is dead:\n`,
|
|
291
|
+
);
|
|
292
|
+
for (const g of r.stale_declarations) process.stdout.write(` - ${g}\n`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (!failed) {
|
|
296
|
+
process.stdout.write(
|
|
297
|
+
`✅ CI ↔ local parity: ${String(r.ci_gates.length)} CI gate(s), ${String(r.local_gates.length)} local, ` +
|
|
298
|
+
`${String(mf.ci_only.length)} declared CI-only, ${String(mf.local_only.length)} declared local-only.\n`,
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
return failed ? 1 : 0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function _isCliEntry(): boolean {
|
|
305
|
+
if (process.argv[1] === undefined) return false;
|
|
306
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
307
|
+
if (import.meta.url === argvUrl) return true;
|
|
308
|
+
try {
|
|
309
|
+
return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(path.resolve(process.argv[1]));
|
|
310
|
+
} catch {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (_isCliEntry()) {
|
|
316
|
+
process.exit(main());
|
|
317
|
+
}
|