@event4u/agent-config 16.3.0 → 16.4.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +251 -0
- package/README.md +2 -2
- package/agents/templates/.ai-council.yml.example +26 -8
- package/dist/agent-src/commands/analyze/inbox.md +10 -7
- package/dist/agent-src/commands/bug/investigate.md +1 -1
- package/dist/agent-src/commands/commit/in-chunks.md +40 -31
- package/dist/agent-src/commands/commit.md +72 -33
- package/dist/agent-src/commands/condense.md +2 -8
- package/dist/agent-src/commands/council/debate.md +11 -7
- package/dist/agent-src/commands/council/default.md +10 -9
- package/dist/agent-src/commands/council.md +1 -1
- package/dist/agent-src/commands/estimate-ticket.md +1 -1
- package/dist/agent-src/commands/feature/explore.md +3 -3
- package/dist/agent-src/commands/feature/plan.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +17 -3
- package/dist/agent-src/commands/fix/commit-messages.md +48 -23
- package/dist/agent-src/commands/fix/pr-comments.md +3 -6
- package/dist/agent-src/commands/implement-ticket.md +3 -3
- package/dist/agent-src/commands/memory/add.md +4 -16
- package/dist/agent-src/commands/memory/load.md +5 -6
- package/dist/agent-src/commands/memory/promote.md +3 -16
- package/dist/agent-src/commands/mission/upgrade.md +3 -2
- package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
- package/dist/agent-src/commands/optimize/deep.md +4 -2
- package/dist/agent-src/commands/optimize/rtk.md +4 -26
- package/dist/agent-src/commands/pr/create/description-only.md +18 -15
- package/dist/agent-src/commands/pr/create.md +42 -34
- package/dist/agent-src/commands/pr/merge.md +136 -9
- package/dist/agent-src/commands/prepare-for-review.md +13 -11
- package/dist/agent-src/commands/project/analyze.md +7 -35
- package/dist/agent-src/commands/refine-ticket.md +1 -1
- package/dist/agent-src/commands/review/changes.md +14 -19
- package/dist/agent-src/commands/roadmap/next.md +10 -1
- package/dist/agent-src/commands/roadmap/process-full.md +52 -38
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +64 -14
- package/dist/agent-src/commands/worktree/create.md +7 -3
- package/dist/agent-src/commands/worktree/verify.md +2 -1
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
- package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
- package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
- package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
- package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
- package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +67 -52
- package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
- package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
- package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +4 -10
- package/dist/agent-src/contexts/subagent-configuration.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
- package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
- package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
- package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
- package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
- package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
- package/dist/agent-src/guidelines/php/git.md +15 -2
- package/dist/agent-src/rules/active-remediation.md +0 -1
- package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
- package/dist/agent-src/rules/architecture.md +0 -1
- package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
- package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
- package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
- package/dist/agent-src/rules/autonomous-execution.md +0 -1
- package/dist/agent-src/rules/brand-consistency.md +0 -1
- package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
- package/dist/agent-src/rules/broken-access-control.md +0 -1
- package/dist/agent-src/rules/cli-output-handling.md +0 -1
- package/dist/agent-src/rules/code-comment-discipline.md +0 -1
- package/dist/agent-src/rules/code-provenance.md +0 -1
- package/dist/agent-src/rules/command-suggestion-policy.md +0 -1
- package/dist/agent-src/rules/commit-conventions.md +1 -2
- package/dist/agent-src/rules/communication-through-line.md +1 -2
- package/dist/agent-src/rules/content-quoting-floor.md +1 -2
- package/dist/agent-src/rules/context-hygiene.md +5 -5
- package/dist/agent-src/rules/copilot-routing.md +1 -2
- package/dist/agent-src/rules/council-availability.md +4 -4
- package/dist/agent-src/rules/cross-source-consistency.md +4 -6
- package/dist/agent-src/rules/decision-revisit-gate.md +2 -3
- package/dist/agent-src/rules/delegation-policy.md +2 -3
- package/dist/agent-src/rules/design-fidelity.md +0 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
- package/dist/agent-src/rules/devcontainer-routing.md +1 -2
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +0 -1
- package/dist/agent-src/rules/docker-commands.md +0 -1
- package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
- package/dist/agent-src/rules/domain-safety-disclaimer.md +0 -1
- package/dist/agent-src/rules/domain-safety-pii.md +0 -1
- package/dist/agent-src/rules/domain-safety-retention.md +0 -1
- package/dist/agent-src/rules/downstream-changes.md +0 -1
- package/dist/agent-src/rules/engineering-safety-floor.md +0 -1
- package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
- package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -2
- package/dist/agent-src/rules/finance-safety-floor.md +0 -1
- package/dist/agent-src/rules/fix-what-you-see.md +6 -32
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
- package/dist/agent-src/rules/git-history-discipline.md +1 -2
- package/dist/agent-src/rules/guidelines.md +0 -1
- package/dist/agent-src/rules/history-discipline.md +0 -1
- package/dist/agent-src/rules/icon-consistency.md +0 -1
- package/dist/agent-src/rules/image-likeness-and-rights.md +0 -1
- package/dist/agent-src/rules/improve-before-implement.md +0 -1
- package/dist/agent-src/rules/invite-challenge.md +0 -1
- package/dist/agent-src/rules/laravel-routing.md +1 -2
- package/dist/agent-src/rules/laravel-translations.md +0 -1
- package/dist/agent-src/rules/legal-safety-floor.md +0 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +0 -1
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +0 -1
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
- package/dist/agent-src/rules/media-governance-routing.md +1 -2
- package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
- package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
- package/dist/agent-src/rules/missing-tool-handling.md +0 -1
- package/dist/agent-src/rules/model-recommendation.md +0 -1
- package/dist/agent-src/rules/neighbour-precedence.md +64 -0
- package/dist/agent-src/rules/no-attribution-footers.md +0 -1
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
- package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
- package/dist/agent-src/rules/no-roadmap-references.md +0 -1
- package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
- package/dist/agent-src/rules/onboarding-gate.md +0 -1
- package/dist/agent-src/rules/output-discipline.md +0 -1
- package/dist/agent-src/rules/package-ci-checks.md +0 -1
- package/dist/agent-src/rules/persona-governance.md +2 -3
- package/dist/agent-src/rules/php-coding.md +0 -1
- package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
- package/dist/agent-src/rules/preservation-guard.md +0 -1
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -3
- package/dist/agent-src/rules/question-not-instruction.md +0 -1
- package/dist/agent-src/rules/reviewer-awareness.md +0 -1
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +3 -6
- package/dist/agent-src/rules/role-mode-adherence.md +0 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -1
- package/dist/agent-src/rules/runtime-safety.md +0 -1
- package/dist/agent-src/rules/scale-discipline.md +0 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +0 -1
- package/dist/agent-src/rules/security-sensitive-stop.md +0 -1
- package/dist/agent-src/rules/self-repair-loop.md +0 -1
- package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
- package/dist/agent-src/rules/session-canary.md +0 -1
- package/dist/agent-src/rules/settings-ask-protocol.md +5 -6
- package/dist/agent-src/rules/size-enforcement.md +0 -1
- package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
- package/dist/agent-src/rules/skill-quality.md +0 -1
- package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
- package/dist/agent-src/rules/source-confidentiality.md +0 -1
- package/dist/agent-src/rules/source-discovery-gate.md +0 -1
- package/dist/agent-src/rules/source-of-truth.md +0 -1
- package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
- package/dist/agent-src/rules/strategy-safety-floor.md +0 -1
- package/dist/agent-src/rules/symfony-routing.md +1 -2
- package/dist/agent-src/rules/think-before-action.md +0 -1
- package/dist/agent-src/rules/token-budget-discipline.md +12 -46
- package/dist/agent-src/rules/token-efficiency.md +0 -1
- package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
- package/dist/agent-src/rules/tool-safety.md +0 -1
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +0 -1
- package/dist/agent-src/rules/upstream-proposal.md +0 -1
- package/dist/agent-src/rules/user-interaction.md +0 -1
- package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
- package/dist/agent-src/scripts/gate_budget.ts +47 -23
- package/dist/agent-src/scripts/gate_execute.ts +12 -4
- package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
- package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
- package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
- package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
- package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
- package/dist/agent-src/skills/database/data/manifest.json +2 -2
- package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
- package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
- package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
- package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
- package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
- package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
- package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
- package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -2
- package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agent-settings.md +46 -129
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
- package/dist/agent-src/templates/command.md +2 -2
- package/dist/agent-src/templates/roadmaps.md +6 -1
- package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
- package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
- package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
- package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli-delegate/check_update_banner.js +195 -119
- package/dist/cli-delegate/{chunk-TRI6DQZ6.js → chunk-5GPULQBE.js} +60 -42
- package/dist/cli-delegate/{chunk-JQVYKIZA.js → chunk-6SRJTYJS.js} +33 -177
- package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
- package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
- package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
- package/dist/cli-delegate/{chunk-NQ7WT43P.js → chunk-AED2VQGM.js} +65 -11
- package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
- package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
- package/dist/cli-delegate/{chunk-NXEILF2K.js → chunk-F3QDG2GT.js} +481 -72
- package/dist/cli-delegate/{chunk-CQWX336L.js → chunk-G5VVIZRC.js} +3 -3
- package/dist/cli-delegate/{chunk-JY2I2DXV.js → chunk-H76PHZBI.js} +137 -60
- package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
- package/dist/cli-delegate/{chunk-LIYTLH6O.js → chunk-KXXWJTDO.js} +5 -10
- package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
- package/dist/cli-delegate/{chunk-S4YWNRKO.js → chunk-MDPPKQCQ.js} +34 -1
- package/dist/cli-delegate/{chunk-S4UMZNES.js → chunk-MSUL5NYP.js} +5 -5
- package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
- package/dist/cli-delegate/{chunk-GKE7ZVFA.js → chunk-PWX7CKMD.js} +1 -1
- package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
- package/dist/cli-delegate/{chunk-RQNNW7IF.js → chunk-T7XSJSUQ.js} +433 -632
- package/dist/cli-delegate/{chunk-EEHDXSYD.js → chunk-WQWXGIWB.js} +12 -273
- package/dist/cli-delegate/{chunk-QLDHIPWR.js → chunk-XQTPXKFA.js} +1 -1
- package/dist/cli-delegate/cmd_analyze_session.js +223 -43
- package/dist/cli-delegate/cmd_brand_status.js +3 -2
- package/dist/cli-delegate/cmd_conformance.js +105 -35
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +15 -12
- package/dist/cli-delegate/cmd_doctor_neighbours.js +11 -4
- package/dist/cli-delegate/cmd_explain.js +43 -19
- package/dist/cli-delegate/cmd_export.js +10 -10
- package/dist/cli-delegate/cmd_git_convention.js +1851 -0
- package/dist/cli-delegate/cmd_handoff.js +40 -21
- package/dist/cli-delegate/cmd_mcp_available.js +3 -2
- package/dist/cli-delegate/cmd_migrate.js +3 -3
- package/dist/cli-delegate/cmd_packs_active.js +4 -3
- package/dist/cli-delegate/cmd_prune.js +10 -10
- package/dist/cli-delegate/cmd_route_audit.js +7 -7
- package/dist/cli-delegate/cmd_route_explain.js +5 -5
- package/dist/cli-delegate/cmd_session_recycle.js +9 -7
- package/dist/cli-delegate/cmd_settings_check.js +54 -7
- package/dist/cli-delegate/cmd_settings_get.js +18 -8
- package/dist/cli-delegate/cmd_settings_migrate.js +10 -10
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +10 -10
- package/dist/cli-delegate/cmd_uninstall.js +10 -10
- package/dist/cli-delegate/cmd_update.js +7 -7
- package/dist/cli-delegate/cmd_upgrade.js +7 -7
- package/dist/cli-delegate/cmd_validate.js +10 -10
- package/dist/cli-delegate/cmd_versions.js +5 -5
- package/dist/cli-delegate/gate_budget.js +1 -1
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +129 -90
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +24 -9
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +2151 -1820
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/install/install.mjs +462 -431
- package/dist/install/installThinLayer.js +40 -12
- package/dist/install/installedRuleLinks.js +105 -19
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
- package/dist/mcp/registry-manifest.json +5 -5
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +2702 -1995
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +15 -120
- package/dist/scripts/_lib/compile_time_toggles.js +12 -21
- package/dist/scripts/_lib/git_convention.js +232 -0
- package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
- package/dist/scripts/_lib/installed_layer.js +344 -18
- package/dist/scripts/_lib/package_root.js +68 -0
- package/dist/scripts/_lib/rule_law_section.js +1 -1
- package/dist/scripts/_lib/settings_removed_keys.js +168 -0
- package/dist/scripts/_lib/thin_rules.js +80 -3
- package/dist/server/app.js +2 -1
- package/dist/server/gitKeysGate.js +105 -0
- package/dist/server/routes/settings.js +67 -8
- package/dist/server/routes/wizard.js +4 -0
- package/dist/server/schemas/settings.js +23 -81
- package/dist/shared/skillRanking.js +30 -4
- package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +72 -1
- package/docs/contracts/settings-classes.md +35 -65
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
- package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
- package/docs/guidelines/agent-infra/layered-settings.md +13 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
- package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
- package/docs/guidelines/php/git.md +15 -2
- package/package.json +1 -1
- package/src/agent-src/scripts/gate_budget.ts +47 -23
- package/src/agent-src/scripts/gate_execute.ts +12 -4
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
- package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
- package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
- package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
- package/src/config/agent-settings.template.yml +79 -312
- package/src/config/agents-paths.yml +16 -0
- package/src/config/assurance-capability-registry.json +7 -3
- package/src/config/ci-local-parity.yml +3 -0
- package/src/config/continuity-surface.json +3 -3
- package/src/config/discovery/packs.yml +17 -1
- package/src/config/evaluator-budgets.json +19 -6
- package/src/config/gate-coverage.yml +65 -23
- package/src/config/gate-violation-baselines.json +53 -13
- package/src/config/gitignore-block.txt +19 -0
- package/src/config/hook-bundle-budget.json +1 -1
- package/src/config/release-gate-locality.yml +2 -1
- package/src/config/routing-coverage-seed.json +48 -6
- package/src/config/rule-law-ceilings.json +12 -6
- package/src/config/rule-obligations.json +833 -0
- package/src/install/installThinLayer.ts +76 -10
- package/src/install/installedRuleLinks.ts +105 -17
- package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
- package/src/scripts/_cli/cmd_conformance.ts +13 -2
- package/src/scripts/_cli/cmd_doctor.ts +10 -10
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +133 -0
- package/src/scripts/_cli/cmd_explain.ts +72 -14
- package/src/scripts/_cli/cmd_git_convention.ts +637 -0
- package/src/scripts/_cli/cmd_settings_check.ts +66 -8
- package/src/scripts/_cli/cmd_settings_get.ts +18 -3
- package/src/scripts/_cli/doctor_execution.ts +72 -1
- package/src/scripts/_dispatch.bash +37 -2
- package/src/scripts/_lib/agent_settings.ts +15 -124
- package/src/scripts/_lib/blocked_by_marker.ts +1 -1
- package/src/scripts/_lib/compile_time_toggles.ts +12 -21
- package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
- package/src/scripts/_lib/git_base_ref.ts +92 -0
- package/src/scripts/_lib/git_convention.ts +291 -0
- package/src/scripts/_lib/git_convention_carrier.ts +389 -0
- package/src/scripts/_lib/git_convention_grammar.ts +246 -0
- package/src/scripts/_lib/git_convention_measure.ts +344 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +74 -0
- package/src/scripts/_lib/graph_feeder_record.ts +236 -13
- package/src/scripts/_lib/installed_layer.ts +448 -23
- package/src/scripts/_lib/knowledge_global.ts +14 -1
- package/src/scripts/_lib/module_reach.ts +456 -0
- package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +8 -10
- package/src/scripts/_lib/ratification_artifact.ts +220 -1
- package/src/scripts/_lib/ratification_subject.ts +92 -0
- package/src/scripts/_lib/release_findings_ingest.ts +15 -7
- package/src/scripts/_lib/release_highlights.ts +5 -0
- package/src/scripts/_lib/rule_law_section.ts +1 -1
- package/src/scripts/_lib/rule_obligations.ts +205 -0
- package/src/scripts/_lib/self_repair.ts +1 -1
- package/src/scripts/_lib/settings_removed_keys.ts +173 -0
- package/src/scripts/_lib/test_red_state.ts +5 -0
- package/src/scripts/_lib/thin_rules.ts +83 -3
- package/src/scripts/_lib/touched_file_quality.ts +142 -6
- package/src/scripts/_lib/worker_budget.ts +1 -1
- package/src/scripts/adr/regenerate_index.ts +16 -1
- package/src/scripts/ai_council/config.ts +7 -7
- package/src/scripts/ai_council/modification_review.ts +100 -0
- package/src/scripts/ai_council/modification_review_questions.ts +90 -0
- package/src/scripts/ai_council/orchestrator.ts +5 -5
- package/src/scripts/ai_council/spend_gate.ts +18 -7
- package/src/scripts/ai_team/config.ts +11 -16
- package/src/scripts/audit_user_type_axis.ts +20 -8
- package/src/scripts/bench_ab_clone.ts +1 -2
- package/src/scripts/bench_concern_spawn_path.ts +129 -0
- package/src/scripts/bench_graph_feeder_latency.ts +584 -0
- package/src/scripts/check_agent_artifact_location.ts +36 -0
- package/src/scripts/check_branch_freshness.ts +147 -24
- package/src/scripts/check_enforcement_coverage.ts +130 -0
- package/src/scripts/check_evaluator_budgets.ts +4 -0
- package/src/scripts/check_finding_dispositions.ts +88 -25
- package/src/scripts/check_gate_coverage.ts +4 -3
- package/src/scripts/check_gate_reachability.ts +48 -1
- package/src/scripts/check_generator_sync.ts +48 -0
- package/src/scripts/check_hook_bundle_composition.ts +107 -0
- package/src/scripts/check_kernel_edit_ratified.ts +86 -6
- package/src/scripts/check_pack_size.ts +1 -1
- package/src/scripts/check_release_manifest_content.ts +189 -0
- package/src/scripts/check_standing_rule_delivery.ts +96 -0
- package/src/scripts/check_suppression_hygiene.ts +2 -5
- package/src/scripts/ci_settle.ts +42 -5
- package/src/scripts/classify_merge_risk.ts +320 -0
- package/src/scripts/closure_scan.ts +91 -1
- package/src/scripts/command_suggester/settings.ts +8 -108
- package/src/scripts/command_suggester/types.ts +4 -5
- package/src/scripts/consumer_matrix.ts +102 -0
- package/src/scripts/context_hygiene_hook.ts +13 -23
- package/src/scripts/cost/preflight.mjs +12 -1
- package/src/scripts/council_cli.ts +7 -7
- package/src/scripts/dispatch_r2_reviewer.ts +24 -11
- package/src/scripts/explain_run.ts +8 -13
- package/src/scripts/generate_git_convention_grammar.ts +127 -0
- package/src/scripts/generate_host_cost_table.ts +20 -3
- package/src/scripts/handoff_context_hook.ts +86 -37
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +25 -6
- package/src/scripts/hooks/block_config_weakening.ts +48 -5
- package/src/scripts/hooks/block_plumbing_writes.ts +8 -4
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
- package/src/scripts/hooks/evidence_independence.ts +12 -4
- package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
- package/src/scripts/hooks/push_settle_hook.ts +4 -3
- package/src/scripts/hooks/rule_inject_hook.ts +44 -3
- package/src/scripts/hooks/state_io.ts +8 -4
- package/src/scripts/hooks/telemetry_usage_hook.ts +7 -46
- package/src/scripts/hooks/turn_end_gate_hook.ts +1 -0
- package/src/scripts/install-hooks.sh +42 -14
- package/src/scripts/install.ts +7 -31
- package/src/scripts/lint_blocker_citations.ts +198 -0
- package/src/scripts/lint_evidence_artifacts.ts +9 -0
- package/src/scripts/lint_hook_concern_budget.ts +10 -21
- package/src/scripts/lint_pack_boundaries.ts +406 -28
- package/src/scripts/lint_roadmap_blockers.ts +282 -29
- package/src/scripts/lint_roadmap_complexity.ts +4 -2
- package/src/scripts/lint_rule_law_section.ts +151 -21
- package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
- package/src/scripts/lint_settings_classes.ts +1 -1
- package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
- package/src/scripts/lint_workflow_security.ts +12 -1
- package/src/scripts/measure_skill_ranker_baseline.ts +5 -0
- package/src/scripts/model_rule_injection.ts +3 -3
- package/src/scripts/onboarding_gate_hook.ts +7 -6
- package/src/scripts/print_required_checks.ts +15 -3
- package/src/scripts/probe_host_compliance.ts +33 -5
- package/src/scripts/probe_turnaround.ts +183 -3
- package/src/scripts/ratification_header.ts +77 -0
- package/src/scripts/refusal_envelope.ts +138 -0
- package/src/scripts/release_publication.ts +29 -3
- package/src/scripts/report_dispatch_import_closure.ts +76 -0
- package/src/scripts/report_installed_rule_links.ts +118 -1
- package/src/scripts/report_module_reach.ts +212 -0
- package/src/scripts/report_obligation_mechanism.ts +16 -18
- package/src/scripts/report_parked_blockers.ts +222 -0
- package/src/scripts/report_required_checks_drift.ts +196 -0
- package/src/scripts/report_skill_ranker_confusion.ts +103 -2
- package/src/scripts/report_standing_payload_by_host.ts +1 -1
- package/src/scripts/routing_doctor.ts +2 -2
- package/src/scripts/schemas/agent-settings.schema.json +17 -31
- package/src/scripts/schemas/command.schema.json +1 -1
- package/src/scripts/schemas/skill.schema.json +1 -1
- package/src/scripts/self_review_gate.ts +39 -2
- package/src/scripts/skill_tools/score_skill_relevance.ts +28 -19
- package/src/scripts/sync_pr_branch.ts +403 -132
- package/src/scripts/trigger_eval_grandfather.json +0 -16
- package/src/server/schemas/settings.ts +33 -177
- package/src/shared/skillRanking.ts +53 -4
- package/dist/cli-delegate/chunk-NYX3L2PZ.js +0 -99
- package/src/scripts/_lib/config_chain.ts +0 -477
- package/src/scripts/_lib/conformance_report.ts +0 -403
- package/src/scripts/_lib/eval_discrimination.ts +0 -95
- package/src/scripts/_lib/evaluator_promotion.ts +0 -225
- package/src/scripts/_lib/file_slicer.ts +0 -117
- package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
- package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
- package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
- package/src/scripts/_lib/role_split.ts +0 -338
|
@@ -29,10 +29,12 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
29
29
|
|
|
30
30
|
import {
|
|
31
31
|
type LinkAuditReport,
|
|
32
|
+
auditInstalledKindLinks,
|
|
32
33
|
auditInstalledRuleLinks,
|
|
33
34
|
deployPlanFrom,
|
|
34
35
|
rewriteOptionCost,
|
|
35
36
|
} from '../install/installedRuleLinks.js';
|
|
37
|
+
import { loadBaselines } from './_lib/gate_baseline.js';
|
|
36
38
|
import { GLOBAL_DEPLOY_SOURCES } from './install.js';
|
|
37
39
|
|
|
38
40
|
// ledger-exempt: a REPORTER, not a gate. It has no verdict for a per-target
|
|
@@ -73,6 +75,89 @@ export function readings(packageRoot: string, prefixChars: number): HostLinkRead
|
|
|
73
75
|
return out;
|
|
74
76
|
}
|
|
75
77
|
|
|
78
|
+
/** Installed artefact kinds `--kinds` can select, in print order. */
|
|
79
|
+
export const LINK_KINDS = ['rules', 'skills', 'commands', 'contexts', 'guidelines'] as const;
|
|
80
|
+
export type LinkKind = (typeof LINK_KINDS)[number];
|
|
81
|
+
|
|
82
|
+
export interface KindLinkReading {
|
|
83
|
+
kind: LinkKind | 'non-projected';
|
|
84
|
+
/** False when the host's plan does not deploy this kind at all. */
|
|
85
|
+
installed: boolean;
|
|
86
|
+
links: number;
|
|
87
|
+
unresolved: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* One reading per selected kind for one host, plus a final `non-projected` row.
|
|
92
|
+
*
|
|
93
|
+
* A link into `docs/` (the ADRs live there) is dead in every install by
|
|
94
|
+
* construction, so it is taken OUT of its kind's deployable count and summed
|
|
95
|
+
* into its own row instead — mixing it in would make a kind's number move for a
|
|
96
|
+
* reason no deploy change can address.
|
|
97
|
+
*/
|
|
98
|
+
export function kindReadings(
|
|
99
|
+
packageRoot: string,
|
|
100
|
+
pairs: ReadonlyArray<readonly [string, string]>,
|
|
101
|
+
kinds: ReadonlyArray<LinkKind>,
|
|
102
|
+
): KindLinkReading[] {
|
|
103
|
+
const plan = deployPlanFrom(pairs);
|
|
104
|
+
const out: KindLinkReading[] = [];
|
|
105
|
+
let npLinks = 0;
|
|
106
|
+
let npUnresolved = 0;
|
|
107
|
+
for (const kind of kinds) {
|
|
108
|
+
const report = auditInstalledKindLinks(plan, packageRoot, `dist/agent-src/${kind}`);
|
|
109
|
+
if (report === null) {
|
|
110
|
+
out.push({ kind, installed: false, links: 0, unresolved: 0 });
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
out.push({
|
|
114
|
+
kind,
|
|
115
|
+
installed: true,
|
|
116
|
+
links: report.audits.length,
|
|
117
|
+
unresolved: report.audits.length - report.counts.resolved,
|
|
118
|
+
});
|
|
119
|
+
npLinks += report.non_projected.length;
|
|
120
|
+
npUnresolved += report.non_projected.filter((a) => a.verdict !== 'resolved').length;
|
|
121
|
+
}
|
|
122
|
+
out.push({ kind: 'non-projected', installed: true, links: npLinks, unresolved: npUnresolved });
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Key of a kind's recorded count in `src/config/gate-violation-baselines.json`. */
|
|
127
|
+
export function kindBaselineKey(host: string, kind: KindLinkReading['kind']): string {
|
|
128
|
+
return `report_installed_rule_links:kinds:${host}:${kind}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The recorded count for each row, or null where none is recorded.
|
|
133
|
+
*
|
|
134
|
+
* Read, never written: the baseline only moves by a reviewed commit, so a new
|
|
135
|
+
* dead link shows as a live count above it rather than as a quietly raised
|
|
136
|
+
* number. Nothing here fails on the comparison (D2 — report, never fail).
|
|
137
|
+
*/
|
|
138
|
+
export function recordedBaselines(packageRoot: string, host: string, rows: KindLinkReading[]): (number | null)[] {
|
|
139
|
+
const { gates } = loadBaselines(packageRoot);
|
|
140
|
+
return rows.map((r) => gates[kindBaselineKey(host, r.kind)]?.count ?? null);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** `kind: <name> unresolved <n> of <m>` — the line form the roadmap fixed. */
|
|
144
|
+
export function formatKindLine(r: KindLinkReading, host: string, baseline: number | null = null): string {
|
|
145
|
+
const name = r.kind === 'non-projected' ? 'non-projected (adr, docs/)' : r.kind;
|
|
146
|
+
const tail = r.installed ? '' : ` (not installed for ${host})`;
|
|
147
|
+
const base =
|
|
148
|
+
baseline === null
|
|
149
|
+
? ''
|
|
150
|
+
: ` [baseline ${String(baseline)}${r.unresolved > baseline ? `, ${String(r.unresolved - baseline)} above it` : ''}]`;
|
|
151
|
+
return `kind: ${name} unresolved ${String(r.unresolved)} of ${String(r.links)}${tail}${base}`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function parseKinds(raw: string): LinkKind[] | null {
|
|
155
|
+
if (raw === 'all') return [...LINK_KINDS];
|
|
156
|
+
const picked = raw.split(',').map((k) => k.trim());
|
|
157
|
+
if (picked.length === 0 || picked.some((k) => !(LINK_KINDS as readonly string[]).includes(k))) return null;
|
|
158
|
+
return LINK_KINDS.filter((k) => picked.includes(k));
|
|
159
|
+
}
|
|
160
|
+
|
|
76
161
|
function flagValue(flag: string): string | null {
|
|
77
162
|
const argv = process.argv.slice(2);
|
|
78
163
|
const i = argv.indexOf(flag);
|
|
@@ -81,9 +166,14 @@ function flagValue(flag: string): string | null {
|
|
|
81
166
|
|
|
82
167
|
const USAGE =
|
|
83
168
|
'usage: report_installed_rule_links [--root DIR] [--prefix-chars N] [--json]\n' +
|
|
169
|
+
' [--kinds all|K[,K...]] [--host HOST]\n' +
|
|
84
170
|
' --root package checkout the installer copies FROM (default: cwd)\n' +
|
|
85
171
|
' --prefix-chars length of the installed package root, for the rewrite price\n' +
|
|
86
172
|
' (default 48, a typical `~/.claude/agent-config` expansion)\n' +
|
|
173
|
+
' --kinds one unresolved count per installed kind instead of the rule\n' +
|
|
174
|
+
` reading: ${LINK_KINDS.join(', ')}, or all; docs/ and ADR\n` +
|
|
175
|
+
' targets are printed as their own row. Reports, never fails.\n' +
|
|
176
|
+
' --host host whose deploy plan --kinds reads (default claude-code)\n' +
|
|
87
177
|
' --json machine-readable readings\n';
|
|
88
178
|
|
|
89
179
|
export function main(): number {
|
|
@@ -93,7 +183,7 @@ export function main(): number {
|
|
|
93
183
|
return 0;
|
|
94
184
|
}
|
|
95
185
|
for (const a of argv) {
|
|
96
|
-
if (a.startsWith('-') && !['--root', '--prefix-chars', '--json'].includes(a)) {
|
|
186
|
+
if (a.startsWith('-') && !['--root', '--prefix-chars', '--json', '--kinds', '--host'].includes(a)) {
|
|
97
187
|
process.stderr.write(`unknown argument: ${a}\n${USAGE}`);
|
|
98
188
|
return 2;
|
|
99
189
|
}
|
|
@@ -111,6 +201,33 @@ export function main(): number {
|
|
|
111
201
|
return 1;
|
|
112
202
|
}
|
|
113
203
|
|
|
204
|
+
const rawKinds = flagValue('--kinds');
|
|
205
|
+
if (rawKinds !== null || argv.includes('--kinds')) {
|
|
206
|
+
const kinds = rawKinds === null ? null : parseKinds(rawKinds);
|
|
207
|
+
if (kinds === null) {
|
|
208
|
+
process.stderr.write(`--kinds takes all or a comma list of: ${LINK_KINDS.join(', ')}\n`);
|
|
209
|
+
return 2;
|
|
210
|
+
}
|
|
211
|
+
const host = flagValue('--host') ?? 'claude-code';
|
|
212
|
+
const pairs = GLOBAL_DEPLOY_SOURCES[host];
|
|
213
|
+
if (pairs === undefined) {
|
|
214
|
+
process.stderr.write(`unknown --host ${host}; known: ${Object.keys(GLOBAL_DEPLOY_SOURCES).join(', ')}\n`);
|
|
215
|
+
return 2;
|
|
216
|
+
}
|
|
217
|
+
const kindRows = kindReadings(root, pairs, kinds);
|
|
218
|
+
const baselines = recordedBaselines(root, host, kindRows);
|
|
219
|
+
if (argv.includes('--json')) {
|
|
220
|
+
const rows = kindRows.map((r, i) => ({ ...r, baseline: baselines[i] }));
|
|
221
|
+
process.stdout.write(`${JSON.stringify({ host, kinds: rows }, null, 2)}\n`);
|
|
222
|
+
return 0;
|
|
223
|
+
}
|
|
224
|
+
process.stdout.write(`installed links per kind, host ${host} (report only; counted since 2026-10-06)\n\n`);
|
|
225
|
+
kindRows.forEach((r, i) => {
|
|
226
|
+
process.stdout.write(` ${formatKindLine(r, host, baselines[i] ?? null)}\n`);
|
|
227
|
+
});
|
|
228
|
+
return 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
114
231
|
const rows = readings(root, prefixChars);
|
|
115
232
|
|
|
116
233
|
if (argv.includes('--json')) {
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Report — which `_lib` modules does nothing in production call?
|
|
4
|
+
*
|
|
5
|
+
* A REPORT, not a gate: it always exits 0. Phase 3 of
|
|
6
|
+
* `road-to-modules-that-something-calls.md` wires its counts into
|
|
7
|
+
* `check_gate_reachability`'s own output, reported and not gated, the way
|
|
8
|
+
* the estate gate already prints its draft-roadmap count.
|
|
9
|
+
*
|
|
10
|
+
* ```bash
|
|
11
|
+
* report_module_reach # human-readable, one line per module
|
|
12
|
+
* report_module_reach --markdown # the four tables, for the evidence page
|
|
13
|
+
* report_module_reach --json
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
18
|
+
import * as fs from 'node:fs';
|
|
19
|
+
|
|
20
|
+
import { analyseModuleReach, groupCounts, type ModuleFact, type ReachGroup } from './_lib/module_reach.js';
|
|
21
|
+
import { assertScanned, reportScanned } from './_lib/scan_scope.js';
|
|
22
|
+
|
|
23
|
+
const _FILE = fileURLToPath(import.meta.url);
|
|
24
|
+
const REPO = path.resolve(path.dirname(_FILE), '..', '..');
|
|
25
|
+
|
|
26
|
+
const GROUP_LABEL: Record<ReachGroup, string> = {
|
|
27
|
+
'contract-test': 'imported by a test under tests/contracts/',
|
|
28
|
+
'open-or-deferred-step': 'named in an open or deferred step',
|
|
29
|
+
'named-outside-open-step': 'named in such a roadmap outside any open step',
|
|
30
|
+
'named-in-none': 'named in no live roadmap',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function humanLine(m: ModuleFact): string {
|
|
34
|
+
const bits = [
|
|
35
|
+
`${m.lines}L`,
|
|
36
|
+
m.namedByProduction ? 'named-by-production' : 'UNREFERENCED',
|
|
37
|
+
m.reachedByImportOrPath ? 'reached' : 'REACHED-BY-NOTHING',
|
|
38
|
+
m.hasOwnEntryPoint ? 'has-entry-point' : null,
|
|
39
|
+
m.registryDeclared.length > 0 ? `registry:[${m.registryDeclared.join(',')}]` : null,
|
|
40
|
+
m.importingTests.length > 0 ? `tests:${String(m.importingTests.length)}` : 'tests:0',
|
|
41
|
+
m.group !== null ? `group:${m.group}` : null,
|
|
42
|
+
].filter((b): b is string => b !== null);
|
|
43
|
+
return ` ${m.relPath} — ${bits.join(' · ')}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function human(modules: readonly ModuleFact[]): string {
|
|
47
|
+
const unreferenced = modules.filter((m) => !m.namedByProduction);
|
|
48
|
+
const unreached = modules.filter((m) => !m.reachedByImportOrPath);
|
|
49
|
+
const counts = groupCounts(unreferenced);
|
|
50
|
+
const lines: string[] = [];
|
|
51
|
+
lines.push(
|
|
52
|
+
`module reach: ${String(modules.length)} module(s) under src/scripts/_lib — ` +
|
|
53
|
+
`${String(unreferenced.length)} unreferenced by name, ${String(unreached.length)} reached by nothing`,
|
|
54
|
+
);
|
|
55
|
+
for (const m of modules) lines.push(humanLine(m));
|
|
56
|
+
lines.push('');
|
|
57
|
+
lines.push('unreferenced-by-name groups:');
|
|
58
|
+
for (const g of Object.keys(GROUP_LABEL) as ReachGroup[]) {
|
|
59
|
+
lines.push(` ${GROUP_LABEL[g]}: ${String(counts[g])}`);
|
|
60
|
+
}
|
|
61
|
+
return lines.join('\n');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function table(modules: readonly ModuleFact[], header: readonly string[], row: (m: ModuleFact) => string[]): string {
|
|
65
|
+
const lines = [`| ${header.join(' | ')} |`, `|${header.map(() => '---').join('|')}|`];
|
|
66
|
+
for (const m of modules) lines.push(`| ${row(m).join(' | ')} |`);
|
|
67
|
+
return lines.join('\n');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function markdown(modules: readonly ModuleFact[], roadmapsAvailable: boolean): string {
|
|
71
|
+
const unreferenced = modules.filter((m) => !m.namedByProduction);
|
|
72
|
+
const unreached = modules.filter((m) => !m.reachedByImportOrPath);
|
|
73
|
+
const byGroup = (g: ReachGroup): ModuleFact[] => unreferenced.filter((m) => m.group === g);
|
|
74
|
+
|
|
75
|
+
const lines: string[] = [];
|
|
76
|
+
lines.push('<!-- evidence-type: analysis -->');
|
|
77
|
+
lines.push('# Module reach — 2026-10');
|
|
78
|
+
lines.push('');
|
|
79
|
+
lines.push(
|
|
80
|
+
`Command: \`npx tsx src/scripts/report_module_reach.ts --markdown\`. ` +
|
|
81
|
+
`${String(modules.length)} module(s) directly under \`src/scripts/_lib/\`, ` +
|
|
82
|
+
`${String(unreferenced.length)} named in no file outside themselves and their own tests, ` +
|
|
83
|
+
`${String(unreached.length)} reached by nothing via import edges or run-by-path.`,
|
|
84
|
+
);
|
|
85
|
+
lines.push('');
|
|
86
|
+
if (!roadmapsAvailable) {
|
|
87
|
+
lines.push('> No `agents/roadmaps/` directory in this checkout — the two roadmap-based groups below are skipped.');
|
|
88
|
+
lines.push('');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
lines.push('## Group 1 — imported by a contract test');
|
|
92
|
+
lines.push('');
|
|
93
|
+
lines.push(table(byGroup('contract-test'), ['module', 'lines', 'evidence'], (m) => [m.relPath, String(m.lines), m.groupEvidence ?? '']));
|
|
94
|
+
lines.push('');
|
|
95
|
+
|
|
96
|
+
lines.push('## Group 2 — named in an open or deferred step');
|
|
97
|
+
lines.push('');
|
|
98
|
+
lines.push(
|
|
99
|
+
table(byGroup('open-or-deferred-step'), ['module', 'lines', 'evidence'], (m) => [
|
|
100
|
+
m.relPath,
|
|
101
|
+
String(m.lines),
|
|
102
|
+
m.groupEvidence ?? '',
|
|
103
|
+
]),
|
|
104
|
+
);
|
|
105
|
+
lines.push('');
|
|
106
|
+
|
|
107
|
+
lines.push('## Group 3 — named in such a roadmap outside any open step');
|
|
108
|
+
lines.push('');
|
|
109
|
+
lines.push(
|
|
110
|
+
table(byGroup('named-outside-open-step'), ['module', 'lines', 'evidence'], (m) => [
|
|
111
|
+
m.relPath,
|
|
112
|
+
String(m.lines),
|
|
113
|
+
m.groupEvidence ?? '',
|
|
114
|
+
]),
|
|
115
|
+
);
|
|
116
|
+
lines.push('');
|
|
117
|
+
|
|
118
|
+
lines.push('## Group 4 — named in no live roadmap');
|
|
119
|
+
lines.push('');
|
|
120
|
+
lines.push(
|
|
121
|
+
table(byGroup('named-in-none'), ['module', 'lines', 'importing tests'], (m) => [
|
|
122
|
+
m.relPath,
|
|
123
|
+
String(m.lines),
|
|
124
|
+
String(m.importingTests.length),
|
|
125
|
+
]),
|
|
126
|
+
);
|
|
127
|
+
lines.push('');
|
|
128
|
+
|
|
129
|
+
lines.push('## Every module under `_lib` — full facts');
|
|
130
|
+
lines.push('');
|
|
131
|
+
lines.push(
|
|
132
|
+
table(
|
|
133
|
+
modules,
|
|
134
|
+
['module', 'lines', 'importing tests', 'named by production', 'has entry point', 'registry', 'reached'],
|
|
135
|
+
(m) => [
|
|
136
|
+
m.relPath,
|
|
137
|
+
String(m.lines),
|
|
138
|
+
String(m.importingTests.length),
|
|
139
|
+
m.namedByProduction ? 'yes' : 'no',
|
|
140
|
+
m.hasOwnEntryPoint ? 'yes' : 'no',
|
|
141
|
+
m.registryDeclared.length > 0 ? m.registryDeclared.join(', ') : '—',
|
|
142
|
+
m.reachedByImportOrPath ? 'yes' : 'no',
|
|
143
|
+
],
|
|
144
|
+
),
|
|
145
|
+
);
|
|
146
|
+
lines.push('');
|
|
147
|
+
|
|
148
|
+
// Phase 2.1: one `reading:` line per fourth-group module — never the
|
|
149
|
+
// whole unreferenced set, which also holds groups 1-3 that Phase 2
|
|
150
|
+
// explicitly leaves untouched. The content here is a placeholder; the
|
|
151
|
+
// real verdict (test-carried / helper-never-connected / only-caller-is-
|
|
152
|
+
// its-own-test) is a judgement call a re-run of this script cannot make,
|
|
153
|
+
// and is filled in by hand after reading each module and its test.
|
|
154
|
+
for (const m of byGroup('named-in-none')) {
|
|
155
|
+
lines.push(`reading: ${m.relPath} — TODO: read the module and its test, then state the verdict`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return lines.join('\n');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function main(argv: readonly string[] = process.argv.slice(2), root = REPO): number {
|
|
162
|
+
const { modules, roadmapsAvailable } = analyseModuleReach(root);
|
|
163
|
+
// One options literal, not three (a second R2 review found it triplicated
|
|
164
|
+
// across the --json, --markdown and default branches).
|
|
165
|
+
const scanOpts = {
|
|
166
|
+
gate: 'report_module_reach',
|
|
167
|
+
scanned: modules.length,
|
|
168
|
+
units: 'module(s) under src/scripts/_lib',
|
|
169
|
+
roots: ['src/scripts/_lib'],
|
|
170
|
+
};
|
|
171
|
+
if (argv.includes('--json')) {
|
|
172
|
+
// No trailing `scanned:` line here — an R2 review found that
|
|
173
|
+
// `reportScanned` (which PRINTS) made this invalid as a single JSON
|
|
174
|
+
// document; `check_gate_reachability.ts`'s own `--json` branch already
|
|
175
|
+
// returns immediately after writing JSON for the same reason. The
|
|
176
|
+
// scope is still ASSERTED (never silently printed clean from an empty
|
|
177
|
+
// corpus).
|
|
178
|
+
assertScanned(scanOpts);
|
|
179
|
+
process.stdout.write(`${JSON.stringify({ modules, roadmapsAvailable }, null, 2)}\n`);
|
|
180
|
+
} else if (argv.includes('--markdown')) {
|
|
181
|
+
// The page is the artifact — no trailing `scanned:` line inside it,
|
|
182
|
+
// but the scope is still asserted (never silently printed clean from
|
|
183
|
+
// an empty corpus). The default human mode below is the only one that
|
|
184
|
+
// still publishes the count per this family's convention.
|
|
185
|
+
assertScanned(scanOpts);
|
|
186
|
+
process.stdout.write(`${markdown(modules, roadmapsAvailable)}\n`);
|
|
187
|
+
} else {
|
|
188
|
+
// Asserted BEFORE writing, matching the other two branches (an R2
|
|
189
|
+
// review found the prior "assert after" order here was the one case
|
|
190
|
+
// that would have printed a human report before a DeadScopeError on
|
|
191
|
+
// an empty corpus, while --json/--markdown print nothing in that
|
|
192
|
+
// case) — then printed, since the default mode is the one that still
|
|
193
|
+
// publishes the count per this family's convention.
|
|
194
|
+
reportScanned(scanOpts);
|
|
195
|
+
process.stdout.write(`${human(modules)}\n`);
|
|
196
|
+
}
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function _isCliEntry(): boolean {
|
|
201
|
+
const a = process.argv[1];
|
|
202
|
+
if (!a) return false;
|
|
203
|
+
if (a === _FILE || pathToFileURL(path.resolve(a)).href === import.meta.url) return true;
|
|
204
|
+
try {
|
|
205
|
+
return fs.realpathSync(a) === fs.realpathSync(_FILE);
|
|
206
|
+
} catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (_isCliEntry()) process.exit(main());
|
|
211
|
+
|
|
212
|
+
export { REPO };
|
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
* declaration resolves TO (a wired validator, a bound hook, nothing).
|
|
12
12
|
* · `report_obligation_carriers` — how many artifacts restate the same
|
|
13
13
|
* obligation, which is a different question from whether one enforces it.
|
|
14
|
-
* ·
|
|
15
|
-
*
|
|
14
|
+
* · `src/config/rule-obligations.json` — the stable obligation ids per rule
|
|
15
|
+
* (road-to-enforcement-per-obligation). It replaced the hand-kept
|
|
16
|
+
* `# obligation: line N` frontmatter marker this report was the only
|
|
17
|
+
* reader of, and whose line numbers had drifted out of the law section on
|
|
18
|
+
* half the rules that carried one.
|
|
16
19
|
*
|
|
17
20
|
* **Two columns, and conflating them would be the error worth avoiding.**
|
|
18
21
|
* `carried` is measured: a gate either refuses or it does not.
|
|
@@ -31,6 +34,8 @@ import * as fs from 'node:fs';
|
|
|
31
34
|
import * as path from 'node:path';
|
|
32
35
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
33
36
|
|
|
37
|
+
import { loadRuleObligations, RULE_OBLIGATIONS_PATH } from './_lib/rule_obligations.js';
|
|
38
|
+
|
|
34
39
|
// ledger-exempt: a REPORTER, not a gate. Its only non-zero exit says an input
|
|
35
40
|
// instrument could not be run, which is a statement about the walk.
|
|
36
41
|
|
|
@@ -53,7 +58,8 @@ const REFUSING: ReadonlySet<string> = new Set(['validator', 'validator-local', '
|
|
|
53
58
|
export interface MechanismRow {
|
|
54
59
|
rule: string;
|
|
55
60
|
tier: string;
|
|
56
|
-
|
|
61
|
+
/** Obligation ids this rule declares, `null` when it declares none (the kernel). */
|
|
62
|
+
obligations: number | null;
|
|
57
63
|
frequency: string;
|
|
58
64
|
declared: number;
|
|
59
65
|
effective: string;
|
|
@@ -65,15 +71,6 @@ export interface MechanismRow {
|
|
|
65
71
|
restatements: number;
|
|
66
72
|
}
|
|
67
73
|
|
|
68
|
-
/** `# obligation: line N` inside the frontmatter block. */
|
|
69
|
-
export function markerLine(content: string): number | null {
|
|
70
|
-
if (!content.startsWith('---')) return null;
|
|
71
|
-
const end = content.indexOf('\n---', 3);
|
|
72
|
-
const block = end === -1 ? content : content.slice(0, end);
|
|
73
|
-
const m = /^#\s*obligation:\s*line\s+(\d+)\s*$/m.exec(block);
|
|
74
|
-
return m ? Number.parseInt(m[1] as string, 10) : null;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
74
|
function run(root: string, script: string, args: readonly string[]): string {
|
|
78
75
|
return execFileSync(path.join(root, 'scripts-run'), [script, ...args], {
|
|
79
76
|
cwd: root,
|
|
@@ -123,10 +120,11 @@ export function rows(root: string): MechanismRow[] {
|
|
|
123
120
|
}
|
|
124
121
|
}
|
|
125
122
|
|
|
123
|
+
const inventory = fs.existsSync(path.join(root, RULE_OBLIGATIONS_PATH))
|
|
124
|
+
? loadRuleObligations(root).rules
|
|
125
|
+
: {};
|
|
126
126
|
const out: MechanismRow[] = [];
|
|
127
127
|
for (const r of coverage.rules) {
|
|
128
|
-
const file = path.join(root, 'src', 'rules', `${r.id}.md`);
|
|
129
|
-
const content = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';
|
|
130
128
|
const declared = r.declared ?? [];
|
|
131
129
|
const effective = r.effective ?? 'none';
|
|
132
130
|
const frequency = r.obligation_frequency ?? '—';
|
|
@@ -140,7 +138,7 @@ export function rows(root: string): MechanismRow[] {
|
|
|
140
138
|
out.push({
|
|
141
139
|
rule: r.id,
|
|
142
140
|
tier: r.tier ?? '—',
|
|
143
|
-
|
|
141
|
+
obligations: inventory[r.id]?.obligations.length ?? null,
|
|
144
142
|
frequency,
|
|
145
143
|
declared: declared.length,
|
|
146
144
|
effective,
|
|
@@ -155,11 +153,11 @@ export function rows(root: string): MechanismRow[] {
|
|
|
155
153
|
|
|
156
154
|
export function renderTable(data: readonly MechanismRow[]): string[] {
|
|
157
155
|
const L: string[] = [];
|
|
158
|
-
L.push('| Rule | Tier |
|
|
156
|
+
L.push('| Rule | Tier | Obligations | Frequency | `enforced_by` | Resolves to | Carried | Slot exists | Restatements |');
|
|
159
157
|
L.push('|---|---|---:|---|---:|---|---|---|---:|');
|
|
160
158
|
for (const r of data) {
|
|
161
159
|
L.push(
|
|
162
|
-
`| \`${r.rule}\` | ${r.tier} | ${r.
|
|
160
|
+
`| \`${r.rule}\` | ${r.tier} | ${r.obligations === null ? '—' : String(r.obligations)} | ` +
|
|
163
161
|
`${r.frequency} | ${String(r.declared)} | \`${r.effective}\` | ${r.carried} | ` +
|
|
164
162
|
`${r.slot_exists ? 'yes' : 'no'} | ${String(r.restatements)} |`,
|
|
165
163
|
);
|
|
@@ -210,7 +208,7 @@ export function main(): number {
|
|
|
210
208
|
` declared gap (the rule says instruction-only / none): ${String(by('declared-gap'))}\n` +
|
|
211
209
|
` no enforcement declaration at all: ${String(by('undeclared'))}\n` +
|
|
212
210
|
` not gated, but a host event fires at the obligation's frequency: ${String(slotNoGate)}\n` +
|
|
213
|
-
`
|
|
211
|
+
` declare no obligation ids: ${String(data.filter((r) => r.obligations === null).length)}\n`,
|
|
214
212
|
);
|
|
215
213
|
return 0;
|
|
216
214
|
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Census of open blockers in parked roadmaps — measures, never gates.
|
|
4
|
+
*
|
|
5
|
+
* `lint_roadmap_blockers` and `/roadmap:resolve-blockers` both exclude
|
|
6
|
+
* the parked directory (`later/`) by a recorded decision ("history rather than
|
|
7
|
+
* debt"). This report reads exactly that directory so the decision can be
|
|
8
|
+
* revisited on a number rather than a guess: every `### blocker:` entry whose
|
|
9
|
+
* `Status:` is not `resolved`, with its file, its raw `Owner:` value and
|
|
10
|
+
* whether that owner is the owner (maintainer / user / owner — the same set
|
|
11
|
+
* `lint_roadmap_blockers` treats as a user decision) or a condition an agent
|
|
12
|
+
* can reach. Separately it lists every blockquote that names an owner
|
|
13
|
+
* question or owner decision, because such a question is invisible to any
|
|
14
|
+
* blocker reader even when its directory is in scope.
|
|
15
|
+
*
|
|
16
|
+
* The raw `Owner:` value is printed beside its classification: the field is
|
|
17
|
+
* free text, and a misread must be visible to whoever reads the report.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ./scripts-run src/scripts/report_parked_blockers
|
|
21
|
+
* ./scripts-run src/scripts/report_parked_blockers --format json
|
|
22
|
+
* ./scripts-run src/scripts/report_parked_blockers --dir <path>
|
|
23
|
+
*
|
|
24
|
+
* Exit codes: 0 report emitted · 2 usage error.
|
|
25
|
+
*/
|
|
26
|
+
import * as fs from 'node:fs';
|
|
27
|
+
import * as path from 'node:path';
|
|
28
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
29
|
+
|
|
30
|
+
import { REPO_ROOT, _stripFencedCode } from './lint_roadmap_blockers.js';
|
|
31
|
+
|
|
32
|
+
type OwnerWait = 'owner' | 'agent';
|
|
33
|
+
|
|
34
|
+
interface ParkedBlocker {
|
|
35
|
+
file: string;
|
|
36
|
+
id: string;
|
|
37
|
+
status: string;
|
|
38
|
+
owner: string;
|
|
39
|
+
wait: OwnerWait;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface OwnerQuestion {
|
|
43
|
+
file: string;
|
|
44
|
+
line: number;
|
|
45
|
+
text: string;
|
|
46
|
+
blocker_entries_in_file: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface Census {
|
|
50
|
+
dir: string;
|
|
51
|
+
files_scanned: number;
|
|
52
|
+
files_with_open_blockers: number;
|
|
53
|
+
blockers: ParkedBlocker[];
|
|
54
|
+
owner_questions: OwnerQuestion[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const BLOCKERS_SECTION_RE = /^##[ \t]+Blockers[ \t]*$/im;
|
|
58
|
+
const NEXT_H2_RE = /^##[ \t]+\S/m;
|
|
59
|
+
const BLOCKER_HEADING_RE = /^###[ \t]+blocker:[ \t]*(.+?)[ \t]*$/gim;
|
|
60
|
+
const STATUS_RE = /^-[ \t]*\*\*Status:\*\*[ \t]*(.*)$/im;
|
|
61
|
+
const OWNER_RE = /^-[ \t]*\*\*Owner:\*\*[ \t]*(.*)$/im;
|
|
62
|
+
const OWNER_WAIT_RE = /^(maintainer|user|owner)\b/i;
|
|
63
|
+
const OWNER_QUESTION_RE = /owner[ \t]+(question|decision)/i;
|
|
64
|
+
|
|
65
|
+
function _classifyOwner(raw: string): OwnerWait {
|
|
66
|
+
return OWNER_WAIT_RE.test(raw.trim()) ? 'owner' : 'agent';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Every blocker entry in one file's `## Blockers` section, open or not. */
|
|
70
|
+
function _blockerEntries(text: string): Array<{ id: string; status: string; owner: string }> {
|
|
71
|
+
const stripped = _stripFencedCode(text);
|
|
72
|
+
const sectionMatch = BLOCKERS_SECTION_RE.exec(stripped);
|
|
73
|
+
if (!sectionMatch) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const start = sectionMatch.index + sectionMatch[0].length;
|
|
77
|
+
const rest = stripped.slice(start);
|
|
78
|
+
const h2 = NEXT_H2_RE.exec(rest);
|
|
79
|
+
const section = h2 ? rest.slice(0, h2.index) : rest;
|
|
80
|
+
|
|
81
|
+
const heads: Array<{ start: number; end: number; id: string }> = [];
|
|
82
|
+
BLOCKER_HEADING_RE.lastIndex = 0;
|
|
83
|
+
let hm: RegExpExecArray | null;
|
|
84
|
+
while ((hm = BLOCKER_HEADING_RE.exec(section)) !== null) {
|
|
85
|
+
heads.push({ start: hm.index, end: hm.index + hm[0].length, id: (hm[1] as string).trim() });
|
|
86
|
+
if (hm.index === BLOCKER_HEADING_RE.lastIndex) {
|
|
87
|
+
BLOCKER_HEADING_RE.lastIndex++;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return heads.map((cur, i) => {
|
|
91
|
+
const next = heads[i + 1];
|
|
92
|
+
const body = section.slice(cur.end, next ? next.start : section.length);
|
|
93
|
+
return {
|
|
94
|
+
id: cur.id,
|
|
95
|
+
status: (STATUS_RE.exec(body)?.[1] ?? '').trim(),
|
|
96
|
+
owner: (OWNER_RE.exec(body)?.[1] ?? '').trim(),
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Blockquote lines that name an owner question or owner decision. */
|
|
102
|
+
function _ownerQuestionLines(text: string): Array<{ line: number; text: string }> {
|
|
103
|
+
const out: Array<{ line: number; text: string }> = [];
|
|
104
|
+
let inFence = false;
|
|
105
|
+
text.split('\n').forEach((raw, i) => {
|
|
106
|
+
if (/^[ \t]*```/.test(raw)) {
|
|
107
|
+
inFence = !inFence;
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (!inFence && /^[ \t]*>/.test(raw) && OWNER_QUESTION_RE.test(raw)) {
|
|
111
|
+
out.push({ line: i + 1, text: raw.trim() });
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function collect(dir: string, root: string = REPO_ROOT): Census {
|
|
118
|
+
const files = fs.existsSync(dir)
|
|
119
|
+
? fs
|
|
120
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
121
|
+
.filter((e) => e.isFile() && e.name.endsWith('.md'))
|
|
122
|
+
.map((e) => path.join(dir, e.name))
|
|
123
|
+
.sort()
|
|
124
|
+
: [];
|
|
125
|
+
const blockers: ParkedBlocker[] = [];
|
|
126
|
+
const ownerQuestions: OwnerQuestion[] = [];
|
|
127
|
+
const filesWithOpen = new Set<string>();
|
|
128
|
+
for (const abs of files) {
|
|
129
|
+
const rel = path.relative(root, abs).split(path.sep).join('/');
|
|
130
|
+
const text = fs.readFileSync(abs, 'utf8');
|
|
131
|
+
const entries = _blockerEntries(text);
|
|
132
|
+
for (const e of entries) {
|
|
133
|
+
if (/^resolved\b/i.test(e.status)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
filesWithOpen.add(rel);
|
|
137
|
+
blockers.push({ file: rel, id: e.id, status: e.status, owner: e.owner, wait: _classifyOwner(e.owner) });
|
|
138
|
+
}
|
|
139
|
+
for (const q of _ownerQuestionLines(text)) {
|
|
140
|
+
ownerQuestions.push({ file: rel, line: q.line, text: q.text, blocker_entries_in_file: entries.length });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
dir: path.relative(root, dir).split(path.sep).join('/'),
|
|
145
|
+
files_scanned: files.length,
|
|
146
|
+
files_with_open_blockers: filesWithOpen.size,
|
|
147
|
+
blockers,
|
|
148
|
+
owner_questions: ownerQuestions,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function format(c: Census): string {
|
|
153
|
+
const owner = c.blockers.filter((b) => b.wait === 'owner');
|
|
154
|
+
const agent = c.blockers.filter((b) => b.wait === 'agent');
|
|
155
|
+
const lines: string[] = [];
|
|
156
|
+
lines.push(`Parked blockers under ${c.dir}/`);
|
|
157
|
+
lines.push(
|
|
158
|
+
`files scanned: ${c.files_scanned} · files with an open blocker: ${c.files_with_open_blockers} · open blockers: ${c.blockers.length} (owner-wait ${owner.length}, agent-wait ${agent.length})`,
|
|
159
|
+
);
|
|
160
|
+
for (const [label, group] of [
|
|
161
|
+
['owner-wait', owner],
|
|
162
|
+
['agent-wait', agent],
|
|
163
|
+
] as const) {
|
|
164
|
+
lines.push('');
|
|
165
|
+
lines.push(`## ${label} (${group.length})`);
|
|
166
|
+
for (const b of group) {
|
|
167
|
+
lines.push(`- ${b.file} · ${b.id} · Owner: ${b.owner || '(none)'} · Status: ${b.status || '(none)'}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
lines.push('');
|
|
171
|
+
lines.push(`## owner questions in blockquotes (${c.owner_questions.length})`);
|
|
172
|
+
for (const q of c.owner_questions) {
|
|
173
|
+
lines.push(`- ${q.file}:${q.line} · blocker entries in file: ${q.blocker_entries_in_file} · ${q.text.slice(0, 120)}`);
|
|
174
|
+
}
|
|
175
|
+
return `${lines.join('\n')}\n`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function fail(message: string): never {
|
|
179
|
+
process.stderr.write(`report_parked_blockers: ${message}\n`);
|
|
180
|
+
process.exit(2);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function main(argv: string[] = process.argv.slice(2)): number {
|
|
184
|
+
let fmt: 'text' | 'json' = 'text';
|
|
185
|
+
let dir = path.join(REPO_ROOT, 'agents', 'roadmaps', 'later');
|
|
186
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
187
|
+
const arg = argv[i];
|
|
188
|
+
if (arg === '--format') {
|
|
189
|
+
const v = argv[i + 1];
|
|
190
|
+
if (v !== 'text' && v !== 'json') fail(`--format must be 'text' or 'json'`);
|
|
191
|
+
fmt = v;
|
|
192
|
+
i += 1;
|
|
193
|
+
} else if (arg === '--dir') {
|
|
194
|
+
const v = argv[i + 1];
|
|
195
|
+
if (v === undefined) fail('--dir requires a value');
|
|
196
|
+
dir = path.resolve(v);
|
|
197
|
+
i += 1;
|
|
198
|
+
} else {
|
|
199
|
+
fail(`unknown argument: ${arg}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const census = collect(dir);
|
|
203
|
+
process.stdout.write(fmt === 'json' ? `${JSON.stringify(census, null, 2)}\n` : format(census));
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (process.argv[1] !== undefined) {
|
|
208
|
+
try {
|
|
209
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
210
|
+
const argv1 = fs.realpathSync(path.resolve(process.argv[1]));
|
|
211
|
+
if (here === argv1) {
|
|
212
|
+
process.exit(main());
|
|
213
|
+
}
|
|
214
|
+
} catch {
|
|
215
|
+
if (import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
|
|
216
|
+
process.exit(main());
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export { _classifyOwner, _blockerEntries, _ownerQuestionLines, collect, format, main };
|
|
222
|
+
export type { Census, ParkedBlocker, OwnerQuestion };
|