@event4u/agent-config 16.3.0 → 16.5.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 +178 -78
- 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/design.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/design-antipatterns.md +1 -1
- 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 +14 -48
- 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/accessibility-auditor/data/aria-patterns.csv +2 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- 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/canvas-design/SKILL.md +4 -2
- 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-intelligence/references/integration-mapping.md +13 -10
- 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/fe-design/references/design-patterns.md +49 -2
- package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
- 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/iconography/SKILL.md +4 -2
- package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
- package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
- package/dist/agent-src/skills/logo-generation/SKILL.md +12 -8
- 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/svg-authoring/SKILL.md +318 -0
- 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/skills/wireframe/SKILL.md +5 -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/commands/uiRender.js +201 -4
- package/dist/cli/commands/uiRenderAsset.js +1308 -0
- package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
- package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
- package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
- package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
- package/dist/cli/commands/uiRenderAssetTypes.js +145 -0
- package/dist/cli/main.js +47 -1
- package/dist/cli/registry.js +2 -1
- package/dist/cli-delegate/check_update_banner.js +195 -119
- package/dist/cli-delegate/{chunk-S4UMZNES.js → chunk-4DBG5K7M.js} +5 -5
- 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-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-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-NQ7WT43P.js → chunk-TMWYUOK4.js} +75 -12
- 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 +489 -238
- 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 +171 -107
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +7 -7
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +41 -22
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +16 -11
- package/dist/hooks/dispatch.js +2520 -1924
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/hooks/svg_rules.chunk.cjs +1626 -0
- package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
- 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 +3063 -2160
- 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/scan_scope.js +105 -0
- package/dist/scripts/_lib/settings_removed_keys.js +168 -0
- package/dist/scripts/_lib/svg_dom.js +284 -0
- package/dist/scripts/_lib/svg_geometry.js +477 -0
- package/dist/scripts/_lib/svg_motion.js +179 -0
- package/dist/scripts/_lib/svg_rules.js +1337 -0
- package/dist/scripts/_lib/svg_urls.js +67 -0
- package/dist/scripts/_lib/thin_rules.js +80 -3
- package/dist/scripts/lint_svg_asset.js +324 -0
- 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/design-antipatterns.md +1 -1
- package/docs/guidelines/php/git.md +15 -2
- package/package.json +4 -3
- 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 +56 -16
- 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 +55 -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/svg_dom.ts +318 -0
- package/src/scripts/_lib/svg_geometry.ts +480 -0
- package/src/scripts/_lib/svg_motion.ts +208 -0
- package/src/scripts/_lib/svg_rules.ts +1453 -0
- package/src/scripts/_lib/svg_urls.ts +72 -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/verification_command.ts +59 -0
- package/src/scripts/_lib/verify_clause.ts +27 -17
- 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/block_speaking_inbox_dir.ts +16 -1
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
- package/src/scripts/hooks/design_pass_hook.ts +157 -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/svg_obligation.ts +497 -0
- package/src/scripts/hooks/svg_rules_loader.ts +133 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +7 -46
- package/src/scripts/hooks/turn_end_gate_hook.ts +6 -3
- 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_consolidation_lineage.ts +6 -3
- package/src/scripts/lint_design_quality.ts +60 -12
- package/src/scripts/lint_evidence_artifacts.ts +9 -0
- package/src/scripts/lint_hook_concern_budget.ts +10 -21
- package/src/scripts/lint_motion_authority_drift.ts +27 -0
- 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_svg_asset.ts +365 -0
- 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
|
@@ -57,13 +57,14 @@ import * as os from 'node:os';
|
|
|
57
57
|
import {
|
|
58
58
|
buildHostLimitRows,
|
|
59
59
|
loadHostInstructionLimits,
|
|
60
|
+
ownershipLine,
|
|
60
61
|
readLayer,
|
|
61
62
|
renderHostLimitRows,
|
|
63
|
+
resolveLayerOwnership,
|
|
62
64
|
type LayerReading,
|
|
63
65
|
} from '../scripts/_lib/installed_layer.js';
|
|
64
66
|
import { GLOBAL_RULE_DIRS, globalRuleLayerPath } from './globalRuleLayers.js';
|
|
65
67
|
import { manifest_path } from '../scripts/_lib/installed_tools.js';
|
|
66
|
-
import { NO_RECORDED_HASHES, readRecordedHashes } from './recordedOwnership.js';
|
|
67
68
|
import {
|
|
68
69
|
absoluteBodyLinkPrefix,
|
|
69
70
|
build_thin,
|
|
@@ -271,6 +272,38 @@ export function describeThinInstalledLayer(res: ThinInstalledLayerResult): strin
|
|
|
271
272
|
return out;
|
|
272
273
|
}
|
|
273
274
|
|
|
275
|
+
/**
|
|
276
|
+
* What {@link installReceiptBudgetLines} may be told about ownership evidence.
|
|
277
|
+
*
|
|
278
|
+
* Declared ABOVE that function's own doc block on purpose. It first sat between
|
|
279
|
+
* the doc block and the function, which silently re-attached the function's
|
|
280
|
+
* contract — "step 1.4's at install", "global layers only, deliberately",
|
|
281
|
+
* "never throws" — to this interface, and interfaces erase on emit, so the
|
|
282
|
+
* contract disappeared from the shipped JS and from IDE hover on the function.
|
|
283
|
+
*/
|
|
284
|
+
export interface InstallReceiptOwnershipOptions {
|
|
285
|
+
/**
|
|
286
|
+
* The installed-tools manifest. `undefined` uses `manifest_path(packageRoot)`;
|
|
287
|
+
* `null` reads none.
|
|
288
|
+
*
|
|
289
|
+
* Overridable so a test can be hermetic. That lock file is gitignored, so
|
|
290
|
+
* it is absent in CI and present on any checkout where a project-scoped
|
|
291
|
+
* install has run — a case reading it implicitly turns green-in-CI,
|
|
292
|
+
* red-on-a-maintainer's-machine, for a reason unrelated to what it tests.
|
|
293
|
+
*/
|
|
294
|
+
readonly manifestPath?: string | null | undefined;
|
|
295
|
+
/** `deployed-files.json`. `undefined` reads the user-global default; `null` reads none. */
|
|
296
|
+
readonly inventoryPath?: string | null | undefined;
|
|
297
|
+
/**
|
|
298
|
+
* Anchor → anchor-relative paths this run just wrote.
|
|
299
|
+
*
|
|
300
|
+
* The installer holds exactly this set at the moment it prints the receipt,
|
|
301
|
+
* and `record_deploy` has not run yet, so on a FIRST install it is the only
|
|
302
|
+
* evidence the files are ours.
|
|
303
|
+
*/
|
|
304
|
+
readonly thisDeploy?: ReadonlyMap<string, Iterable<string>> | null | undefined;
|
|
305
|
+
}
|
|
306
|
+
|
|
274
307
|
/**
|
|
275
308
|
* The install receipt's instruction-budget block — step 1.4's "at install".
|
|
276
309
|
*
|
|
@@ -289,15 +322,47 @@ export function describeThinInstalledLayer(res: ThinInstalledLayerResult): strin
|
|
|
289
322
|
* Never throws. A receipt that cannot be measured is silent rather than fatal —
|
|
290
323
|
* the deploy it describes has already happened correctly.
|
|
291
324
|
*/
|
|
292
|
-
export function installReceiptBudgetLines(
|
|
325
|
+
export function installReceiptBudgetLines(
|
|
326
|
+
packageRoot: string,
|
|
327
|
+
home: string = os.homedir(),
|
|
328
|
+
opts: InstallReceiptOwnershipOptions = {},
|
|
329
|
+
): string[] {
|
|
293
330
|
try {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
331
|
+
// ONE RESOLVER, SHARED WITH THE REPORT — step 1.2. This used to read
|
|
332
|
+
// `manifest_path(packageRoot)`, the PACKAGE root's lock, which on a
|
|
333
|
+
// global-only install names a file no global install ever writes; the
|
|
334
|
+
// receipt then printed `0 package-owned` for a layer it had itself just
|
|
335
|
+
// deployed. `resolveLayerOwnership` falls through to the inventory, and
|
|
336
|
+
// `thisDeploy` covers the first install, where the receipt prints
|
|
337
|
+
// before `record_deploy` has written anything.
|
|
338
|
+
const { recorded, sources } = resolveLayerOwnership({
|
|
339
|
+
manifestPath: opts.manifestPath === undefined ? manifest_path(packageRoot) : opts.manifestPath,
|
|
340
|
+
projectRoot: packageRoot,
|
|
341
|
+
// The same home the layers below are read from — the inventory's
|
|
342
|
+
// anchor is tilde-relative, so the two must agree or the receipt
|
|
343
|
+
// measures one install and claims ownership of another.
|
|
344
|
+
home,
|
|
345
|
+
// THE RECEIPT IS THE "ASKING PROCESS" CASE, so it names no home
|
|
346
|
+
// here. It runs inside the install that WROTE the inventory, and
|
|
347
|
+
// that writer resolves the path through `inventory_path()` —
|
|
348
|
+
// honouring `AGENT_CONFIG_DEPLOY_INVENTORY`, which names a FILE
|
|
349
|
+
// rather than a home, and `EVENT4U_CONFIG_HOME`. Passing `home`
|
|
350
|
+
// would take `defaultInventoryPath`'s stated-home branch and read
|
|
351
|
+
// `<home>/.event4u/...`, a file nothing wrote under either
|
|
352
|
+
// override, and the inventory evidence would be silently lost.
|
|
353
|
+
// UNDEFINED IS LEFT UNDEFINED so `resolveLayerOwnership` applies
|
|
354
|
+
// `defaultInventoryPath(home)` — the SAME resolution the report
|
|
355
|
+
// uses. Hardcoding `inventory_path()` here made the two readers
|
|
356
|
+
// step 1.2 exists to reconcile disagree for any home that is not
|
|
357
|
+
// the asking process's: the receipt read one install's inventory
|
|
358
|
+
// and then expanded its tilde-relative anchors against the OTHER
|
|
359
|
+
// home, which is the cross-home misattribution two docstrings in
|
|
360
|
+
// the resolver forbid. `defaultInventoryPath` already returns
|
|
361
|
+
// `inventory_path()` when the stated home IS this process's, which
|
|
362
|
+
// is the case that motivated the hardcode.
|
|
363
|
+
inventoryPath: opts.inventoryPath,
|
|
364
|
+
thisDeploy: opts.thisDeploy,
|
|
365
|
+
});
|
|
301
366
|
const layers: LayerReading[] = [];
|
|
302
367
|
for (const host of Object.keys(GLOBAL_RULE_DIRS).sort()) {
|
|
303
368
|
const dir = globalRuleLayerPath(host, home);
|
|
@@ -305,7 +370,8 @@ export function installReceiptBudgetLines(packageRoot: string, home: string = os
|
|
|
305
370
|
layers.push(readLayer(host, 'global', dir, recorded));
|
|
306
371
|
}
|
|
307
372
|
const rows = buildHostLimitRows(layers, loadHostInstructionLimits());
|
|
308
|
-
|
|
373
|
+
if (rows.length === 0) return [];
|
|
374
|
+
return [` ${ownershipLine(sources)}`, ...renderHostLimitRows(rows).map((l) => ` ${l}`)];
|
|
309
375
|
} catch {
|
|
310
376
|
return [];
|
|
311
377
|
}
|
|
@@ -152,32 +152,90 @@ const EMPTY_COUNTS = (): Record<LinkVerdict, number> => ({
|
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
*
|
|
155
|
+
* Every `.md` file under `dir`, as POSIX paths relative to it, sorted.
|
|
156
156
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* from what is shipped.
|
|
157
|
+
* Recursive because skills (`<name>/SKILL.md`), commands (`<cluster>/x.md`) and
|
|
158
|
+
* contexts nest.
|
|
160
159
|
*/
|
|
161
|
-
|
|
160
|
+
function markdownFilesUnder(dir: string): string[] {
|
|
161
|
+
const out: string[] = [];
|
|
162
|
+
const walk = (rel: string): void => {
|
|
163
|
+
for (const e of fs.readdirSync(path.join(dir, rel), { withFileTypes: true })) {
|
|
164
|
+
const child = rel === '' ? e.name : `${rel}/${e.name}`;
|
|
165
|
+
if (e.isDirectory()) walk(child);
|
|
166
|
+
else if (e.name.endsWith('.md')) out.push(child);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
walk('');
|
|
170
|
+
return out.sort();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Does this link point into a tree no install ever carries — `docs/`, which
|
|
175
|
+
* holds the ADRs?
|
|
176
|
+
*
|
|
177
|
+
* Decided from where the file sits in the PACKAGE (`dist/agent-src/<kind>/…`),
|
|
178
|
+
* not from where the install puts it: an author linking `docs/` meant the
|
|
179
|
+
* repository, whatever the host does. Two shapes count — a target landing under
|
|
180
|
+
* the top-level `docs/`, and a target naming a `docs/` segment or an ADR file
|
|
181
|
+
* that resolves to nothing in the package (an author writing `../docs/x` from
|
|
182
|
+
* a rule meant the repository's `docs/`, not a sibling that does not exist).
|
|
183
|
+
* `guidelines/docs/` is a real projected directory, which is why existence
|
|
184
|
+
* decides the second shape rather than the word alone.
|
|
185
|
+
*/
|
|
186
|
+
export function isNonProjectedTarget(packageRoot: string, packageFromDir: string, target: string): boolean {
|
|
187
|
+
const bare = withoutAnchor(target);
|
|
188
|
+
const resolved = path.posix.normalize(path.posix.join(packageFromDir, bare));
|
|
189
|
+
if (resolved === 'docs' || resolved.startsWith('docs/')) return true;
|
|
190
|
+
if (!/(^|\/)(docs\/|ADR-\d)/.test(bare)) return false;
|
|
191
|
+
return resolved.startsWith('..') || !fs.existsSync(path.join(packageRoot, resolved));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** A per-kind audit: the deployable reading, and the non-projected row apart. */
|
|
195
|
+
export type KindLinkReport = LinkAuditReport & { non_projected: LinkAudit[] };
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Audit every link in every file of ONE installed kind.
|
|
199
|
+
*
|
|
200
|
+
* `kindSource` is the package directory the plan copies (`dist/agent-src/skills`).
|
|
201
|
+
* A file nested at `<rel>/x.md` is installed at `<dest>/<rel>/x.md`, so its links
|
|
202
|
+
* resolve from that directory — through the same {@link auditLink} the rule
|
|
203
|
+
* audit uses, because a second resolver would be the drift this count exists to
|
|
204
|
+
* catch.
|
|
205
|
+
*
|
|
206
|
+
* Returns null when the plan does not install the kind at all: "not installed"
|
|
207
|
+
* is a different answer from "installed with zero links".
|
|
208
|
+
*/
|
|
209
|
+
export function auditInstalledKindLinks(
|
|
210
|
+
plan: DeployPlan,
|
|
211
|
+
packageRoot: string,
|
|
212
|
+
kindSource: string,
|
|
213
|
+
): KindLinkReport | null {
|
|
214
|
+
let dest: string | undefined;
|
|
215
|
+
for (const [d, source] of plan) if (source === kindSource) dest = d;
|
|
216
|
+
if (dest === undefined) return null;
|
|
217
|
+
|
|
162
218
|
const audits: LinkAudit[] = [];
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
.
|
|
169
|
-
|
|
170
|
-
.
|
|
171
|
-
.sort();
|
|
172
|
-
for (const file of files) {
|
|
173
|
-
const rule = file.replace(/\.md$/, '');
|
|
219
|
+
const nonProjected: LinkAudit[] = [];
|
|
220
|
+
const dir = path.join(packageRoot, kindSource);
|
|
221
|
+
if (fs.existsSync(dir)) {
|
|
222
|
+
for (const file of markdownFilesUnder(dir)) {
|
|
223
|
+
const relDir = path.posix.dirname(file);
|
|
224
|
+
const installedDir = relDir === '.' ? dest : dest === '' ? relDir : `${dest}/${relDir}`;
|
|
225
|
+
const packageDir = relDir === '.' ? kindSource : `${kindSource}/${relDir}`;
|
|
226
|
+
const id = file.replace(/\.md$/, '');
|
|
174
227
|
const body = fs.readFileSync(path.join(dir, file), 'utf8');
|
|
175
228
|
for (const target of relativeLinkTargets(body)) {
|
|
176
|
-
|
|
229
|
+
const audit = auditLink(id, target, installedDir, plan, packageRoot);
|
|
230
|
+
if (isNonProjectedTarget(packageRoot, packageDir, target)) nonProjected.push(audit);
|
|
231
|
+
else audits.push(audit);
|
|
177
232
|
}
|
|
178
233
|
}
|
|
179
234
|
}
|
|
235
|
+
return { ...summarise(audits), non_projected: nonProjected };
|
|
236
|
+
}
|
|
180
237
|
|
|
238
|
+
function summarise(audits: LinkAudit[]): LinkAuditReport {
|
|
181
239
|
const counts = EMPTY_COUNTS();
|
|
182
240
|
for (const a of audits) counts[a.verdict] += 1;
|
|
183
241
|
|
|
@@ -196,6 +254,36 @@ export function auditInstalledRuleLinks(plan: DeployPlan, packageRoot: string):
|
|
|
196
254
|
return { audits, counts, by_directory };
|
|
197
255
|
}
|
|
198
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Audit every link in every rule the plan installs.
|
|
259
|
+
*
|
|
260
|
+
* `packageRoot` is the package checkout the installer copies FROM; the rule
|
|
261
|
+
* bodies are read from the plan's own rules source, so the audit cannot drift
|
|
262
|
+
* from what is shipped. Non-projected targets stay IN this reading: its
|
|
263
|
+
* recorded figures predate the per-kind split.
|
|
264
|
+
*/
|
|
265
|
+
export function auditInstalledRuleLinks(plan: DeployPlan, packageRoot: string): LinkAuditReport {
|
|
266
|
+
const audits: LinkAudit[] = [];
|
|
267
|
+
for (const [dest, source] of plan) {
|
|
268
|
+
if (!source.endsWith('/rules')) continue;
|
|
269
|
+
const dir = path.join(packageRoot, source);
|
|
270
|
+
if (!fs.existsSync(dir)) continue;
|
|
271
|
+
const files = fs
|
|
272
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
273
|
+
.filter((e) => !e.isDirectory() && e.name.endsWith('.md'))
|
|
274
|
+
.map((e) => e.name)
|
|
275
|
+
.sort();
|
|
276
|
+
for (const file of files) {
|
|
277
|
+
const rule = file.replace(/\.md$/, '');
|
|
278
|
+
const body = fs.readFileSync(path.join(dir, file), 'utf8');
|
|
279
|
+
for (const target of relativeLinkTargets(body)) {
|
|
280
|
+
audits.push(auditLink(rule, target, dest, plan, packageRoot));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return summarise(audits);
|
|
285
|
+
}
|
|
286
|
+
|
|
199
287
|
/**
|
|
200
288
|
* Standing-text cost of the rewrite option, in characters.
|
|
201
289
|
*
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
* - `changes` — files touched (array of {kind, stack, file, summary}).
|
|
13
13
|
* - `outcomes` — directive → "success" / "blocked" / … .
|
|
14
14
|
* - `halts` — array of recorded halts.
|
|
15
|
-
* 2.
|
|
15
|
+
* 2. the context-hygiene hook's state file (`STATE_FILE`, imported from
|
|
16
|
+
* `context_hygiene_hook.ts` rather than spelled here — two independent
|
|
17
|
+
* spellings of this path drifted apart before). Fields read:
|
|
16
18
|
* - `tool_calls` (int)
|
|
17
|
-
* - `consecutive_same_tool`(int)
|
|
18
|
-
* - `loop_detected` (bool)
|
|
19
19
|
*
|
|
20
20
|
* There is NO general token/cost data source in this package (only
|
|
21
21
|
* video-specific telemetry), so the report deliberately does NOT report
|
|
@@ -33,18 +33,16 @@ import process from 'node:process';
|
|
|
33
33
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
34
34
|
|
|
35
35
|
import { ProjectRootError, resolve_project_root } from '../_lib/agent_settings.js';
|
|
36
|
+
import { STATE_FILE as HYGIENE_STATE_FILE } from '../context_hygiene_hook.js';
|
|
36
37
|
import { StateLoadError, load_state } from './explain_last/state_loader.js';
|
|
37
38
|
|
|
38
39
|
type Dict = Record<string, unknown>;
|
|
39
40
|
|
|
40
41
|
const _HERE = fileURLToPath(import.meta.url);
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
'state',
|
|
46
|
-
'context-hygiene.json',
|
|
47
|
-
);
|
|
43
|
+
// Imported from the hook rather than spelled here — the hook is the writer,
|
|
44
|
+
// so it is the single source of truth for the path it writes to.
|
|
45
|
+
const CONTEXT_HYGIENE_RELATIVE = HYGIENE_STATE_FILE;
|
|
48
46
|
|
|
49
47
|
/** Python `raise SystemExit(code)` analogue — propagates an explicit code. */
|
|
50
48
|
class SystemExitError extends Error {
|
|
@@ -196,11 +194,7 @@ export function render_report(state: Dict, hygiene: Dict | null): string {
|
|
|
196
194
|
lines.push('_Context-hygiene snapshot not available._');
|
|
197
195
|
} else {
|
|
198
196
|
const toolCalls = intOrUnknown(hygiene['tool_calls']);
|
|
199
|
-
const consecutive = intOrUnknown(hygiene['consecutive_same_tool']);
|
|
200
|
-
const loop = hygiene['loop_detected'] === true;
|
|
201
197
|
lines.push(`- Tool calls: ${toolCalls}`);
|
|
202
|
-
lines.push(`- Consecutive same-tool calls: ${consecutive}`);
|
|
203
|
-
lines.push(`- Loop detected: ${loop ? 'yes' : 'no'}`);
|
|
204
198
|
}
|
|
205
199
|
lines.push('');
|
|
206
200
|
|
|
@@ -253,8 +247,8 @@ Sources read:
|
|
|
253
247
|
· changes — files touched
|
|
254
248
|
· outcomes — per-directive success / blocked
|
|
255
249
|
· halts — recorded halts
|
|
256
|
-
agents/
|
|
257
|
-
· tool_calls
|
|
250
|
+
agents/state/context-hygiene.json
|
|
251
|
+
· tool_calls
|
|
258
252
|
|
|
259
253
|
Token/cost is NOT reported — this package has no per-session token
|
|
260
254
|
source (only video-specific telemetry).
|
|
@@ -42,6 +42,7 @@ import { atomicAppendLine } from '../../install/atomic.js';
|
|
|
42
42
|
import { readRecentEntries } from '../../install/txlog.js';
|
|
43
43
|
import { detectToolPresence } from '../../install/detect.js';
|
|
44
44
|
import { resolvePackageRoot } from '../_lib/package_root.js';
|
|
45
|
+
import { THIN_ENTRY_MARKER } from '../_lib/thin_rules.js';
|
|
45
46
|
import { routeTargetPathsPosix } from '../router_target_paths.mjs';
|
|
46
47
|
import { buildFunnel, render as renderFunnel } from '../report_conformance_funnel.js';
|
|
47
48
|
import {
|
|
@@ -74,8 +75,18 @@ export const CONFORMANCE_CHECK_IDS = [
|
|
|
74
75
|
'host-manifest',
|
|
75
76
|
] as const;
|
|
76
77
|
|
|
77
|
-
/**
|
|
78
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Marker emitted by `project_thin_rules.thin_entry()` — the thin-stub signature.
|
|
80
|
+
*
|
|
81
|
+
* RE-EXPORTED, NEVER RE-SPELLED — step 2.1 of
|
|
82
|
+
* `road-to-a-thinned-layer-measured-in-one-unit`. This was its own literal, a
|
|
83
|
+
* substring of the writer's constant without the blockquote prefix and the full
|
|
84
|
+
* stop, which is exactly the drift `THIN_ENTRY_MARKER`'s own docstring warns
|
|
85
|
+
* about: shorten the writer and this detector keeps matching the old sentence,
|
|
86
|
+
* silently, in the direction where a stub it fails to recognise reads as a
|
|
87
|
+
* complete rule body. The name stays so existing callers are unchanged.
|
|
88
|
+
*/
|
|
89
|
+
export const THIN_STUB_MARKER = THIN_ENTRY_MARKER;
|
|
79
90
|
|
|
80
91
|
/**
|
|
81
92
|
* Rendering symbols for this verb's rows — doctor's table plus `unknown`.
|
|
@@ -114,7 +114,7 @@ import {
|
|
|
114
114
|
resolve_project_root,
|
|
115
115
|
type TraceRecord,
|
|
116
116
|
} from '../_lib/agent_settings.js';
|
|
117
|
-
import { executionJson, forgeProtectionJsonFor } from './doctor_execution.js';
|
|
117
|
+
import { executionJson, forgeDepsFor, forgeProtectionJsonFor, type ForgeDeps } from './doctor_execution.js';
|
|
118
118
|
import { checkOfflineReadiness, trafficEnvironmentJson } from './doctor_network_posture.js';
|
|
119
119
|
import * as ai_council_clients from '../ai_council/clients.js';
|
|
120
120
|
import * as ai_council_config from '../ai_council/config.js';
|
|
@@ -2945,7 +2945,7 @@ function _run_no_manifest(
|
|
|
2945
2945
|
checks.some((c) => c['id'] === opts.check && c['status'] === 'skipped');
|
|
2946
2946
|
|
|
2947
2947
|
if (opts.json) {
|
|
2948
|
-
_emit_json(project_root, [], [], [], [], checks, origin);
|
|
2948
|
+
_emit_json(project_root, [], [], [], [], checks, origin, forgeDepsFor(opts));
|
|
2949
2949
|
} else if (opts.check === null) {
|
|
2950
2950
|
print(` 📍 project_root: ${project_root} (origin: ${origin})`);
|
|
2951
2951
|
if (bridge_present) {
|
|
@@ -2998,7 +2998,7 @@ function _emit_json(
|
|
|
2998
2998
|
foreign: Dict[],
|
|
2999
2999
|
tag_drift: Dict[],
|
|
3000
3000
|
checks: Dict[] | null = null,
|
|
3001
|
-
origin: string | null = null,
|
|
3001
|
+
origin: string | null = null, forge: ForgeDeps = {},
|
|
3002
3002
|
): void {
|
|
3003
3003
|
const payload: Dict = {
|
|
3004
3004
|
project_root: String(project_root),
|
|
@@ -3009,7 +3009,7 @@ function _emit_json(
|
|
|
3009
3009
|
};
|
|
3010
3010
|
if (origin !== null) payload['project_root_origin'] = origin;
|
|
3011
3011
|
payload['execution'] = executionJson(() => iter_setting_overrides({ cwd: project_root }));
|
|
3012
|
-
payload['forge_protection'] = forgeProtectionJsonFor(String(project_root)); // 3.2 · AC-5
|
|
3012
|
+
payload['forge_protection'] = forgeProtectionJsonFor(String(project_root), forge); // 3.2 · AC-5
|
|
3013
3013
|
payload['traffic_environment'] = trafficEnvironmentJson(process.env);
|
|
3014
3014
|
if (checks !== null) {
|
|
3015
3015
|
payload['checks'] = checks;
|
|
@@ -3066,7 +3066,7 @@ interface Options {
|
|
|
3066
3066
|
ci: boolean;
|
|
3067
3067
|
strict: boolean; strict_level: string; // see `_doctor_strict.ts`
|
|
3068
3068
|
check: string | null;
|
|
3069
|
-
trace_root: boolean;
|
|
3069
|
+
trace_root: boolean; no_forge: boolean; online: boolean; // opt-out / opt-in; `forgeDepsFor`
|
|
3070
3070
|
context: boolean;
|
|
3071
3071
|
anatomy: boolean;
|
|
3072
3072
|
repair: string | null;
|
|
@@ -3080,14 +3080,14 @@ const PROG = 'agent-config doctor';
|
|
|
3080
3080
|
const USAGE =
|
|
3081
3081
|
`usage: ${PROG} [-h] [--project PROJECT] [--json] [--ci] [--check ID]\n` +
|
|
3082
3082
|
STRICT_USAGE +
|
|
3083
|
-
' [--trace-root] [--context] [--anatomy]\n' +
|
|
3084
|
-
' [--repair ID]\n';
|
|
3083
|
+
' [--trace-root] [--context] [--anatomy] [--no-forge]\n' +
|
|
3084
|
+
' [--online] [--repair ID]\n';
|
|
3085
3085
|
|
|
3086
3086
|
const _STORE_TRUE_FLAGS: Record<string, keyof Options> = {
|
|
3087
3087
|
'--json': 'json',
|
|
3088
3088
|
'--ci': 'ci',
|
|
3089
3089
|
...STRICT_STORE_TRUE,
|
|
3090
|
-
'--trace-root': 'trace_root',
|
|
3090
|
+
'--trace-root': 'trace_root', '--no-forge': 'no_forge', '--offline': 'no_forge', '--online': 'online',
|
|
3091
3091
|
'--context': 'context',
|
|
3092
3092
|
'--anatomy': 'anatomy',
|
|
3093
3093
|
};
|
|
@@ -3112,7 +3112,7 @@ function _parse(argv: string[]): Options {
|
|
|
3112
3112
|
ci: false,
|
|
3113
3113
|
...STRICT_DEFAULTS,
|
|
3114
3114
|
check: null,
|
|
3115
|
-
trace_root: false,
|
|
3115
|
+
trace_root: false, no_forge: false, online: false,
|
|
3116
3116
|
context: false,
|
|
3117
3117
|
anatomy: false,
|
|
3118
3118
|
repair: null,
|
|
@@ -3390,7 +3390,7 @@ function main(argv: string[] | null = null): number {
|
|
|
3390
3390
|
const fail_check = checks.some((c) => c['status'] === 'fail');
|
|
3391
3391
|
|
|
3392
3392
|
if (opts.json) {
|
|
3393
|
-
_emit_json(project_root, missing, modified, foreign, tag_drift, checks, origin);
|
|
3393
|
+
_emit_json(project_root, missing, modified, foreign, tag_drift, checks, origin, forgeDepsFor(opts));
|
|
3394
3394
|
} else {
|
|
3395
3395
|
if (opts.check === null) {
|
|
3396
3396
|
print(` 📍 project_root: ${project_root} (origin: ${origin})`);
|
|
@@ -16,8 +16,14 @@
|
|
|
16
16
|
* the hook path, and `neighbour-overlap.json`, the cross-root pairs keyed by the
|
|
17
17
|
* census digest. Nothing outside that directory is touched, and a failed write
|
|
18
18
|
* is not a failed census.
|
|
19
|
+
*
|
|
20
|
+
* `--contradictions` (step 2.2) writes neither cache. It forms candidate pairs
|
|
21
|
+
* and hands them to ONE council seat, whose question and transcript land under
|
|
22
|
+
* gitignored `agents/runtime/council/`; with no council configured it prints
|
|
23
|
+
* `n/a` and asks nobody.
|
|
19
24
|
*/
|
|
20
25
|
|
|
26
|
+
import { spawnSync } from 'node:child_process';
|
|
21
27
|
import * as fs from 'node:fs';
|
|
22
28
|
import * as path from 'node:path';
|
|
23
29
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
@@ -32,6 +38,22 @@ import {
|
|
|
32
38
|
type NeighbourCensus,
|
|
33
39
|
} from '../_lib/neighbour_census.js';
|
|
34
40
|
import { scanNeighbourBody, writeScanCache } from '../_lib/neighbour_scan.js';
|
|
41
|
+
import {
|
|
42
|
+
RANK_NEIGHBOUR_ALWAYS_ON,
|
|
43
|
+
RANK_NEIGHBOUR_SKILL,
|
|
44
|
+
RANK_PROJECT,
|
|
45
|
+
collisionPair,
|
|
46
|
+
extractInstructions,
|
|
47
|
+
modalityPairs,
|
|
48
|
+
parseVerdicts,
|
|
49
|
+
renderReview,
|
|
50
|
+
reviewRows,
|
|
51
|
+
seatPrompt,
|
|
52
|
+
type CandidatePair,
|
|
53
|
+
type InstructionSource,
|
|
54
|
+
type ReviewRow,
|
|
55
|
+
} from '../_lib/neighbour_contradictions.js';
|
|
56
|
+
import { resolveAvailability } from '../council_availability_hook.js';
|
|
35
57
|
import { resolvePackageRoot } from '../_lib/package_root.js';
|
|
36
58
|
import {
|
|
37
59
|
OVERLAP_THRESHOLD,
|
|
@@ -144,6 +166,109 @@ export function runCensus(
|
|
|
144
166
|
return full;
|
|
145
167
|
}
|
|
146
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Candidate pairs for `--contradictions` (step 2.2), READ-ONLY.
|
|
171
|
+
*
|
|
172
|
+
* Calls `census()` directly rather than `runCensus()`, because the latter
|
|
173
|
+
* writes the scan and overlap caches and this mode promises to change no file.
|
|
174
|
+
* The shape scan still runs, and a refused neighbour body contributes no line.
|
|
175
|
+
*/
|
|
176
|
+
export function contradictionCandidates(
|
|
177
|
+
projectRoot: string,
|
|
178
|
+
packageRoot: string,
|
|
179
|
+
homeRoot?: string,
|
|
180
|
+
): CandidatePair[] {
|
|
181
|
+
const ours = ourSkillNames(packageRoot);
|
|
182
|
+
const c = census(projectRoot, {
|
|
183
|
+
gatedEvents: gatedEvents(packageRoot),
|
|
184
|
+
templatesRoot: path.join(packageRoot, 'src', 'agent-src', 'templates'),
|
|
185
|
+
ourSkillNames: ours,
|
|
186
|
+
packageRoot,
|
|
187
|
+
scan: (p) => scanNeighbourBody(p).kind,
|
|
188
|
+
...(homeRoot === undefined ? {} : { homeRoot }),
|
|
189
|
+
});
|
|
190
|
+
const sources: InstructionSource[] = [];
|
|
191
|
+
for (const name of ['CLAUDE.md', 'AGENTS.md']) {
|
|
192
|
+
const file = path.join(projectRoot, name);
|
|
193
|
+
if (fs.existsSync(file)) sources.push({ label: name, file, rank: RANK_PROJECT });
|
|
194
|
+
}
|
|
195
|
+
for (const r of c.rule_files) {
|
|
196
|
+
if (scanNeighbourBody(r.source).kind === null) {
|
|
197
|
+
sources.push({ label: r.id, file: r.source, rank: RANK_NEIGHBOUR_ALWAYS_ON });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (const s of c.skills) {
|
|
201
|
+
if (s.unscanned === null) sources.push({ label: s.qualified, file: s.source, rank: RANK_NEIGHBOUR_SKILL });
|
|
202
|
+
}
|
|
203
|
+
const pairs = modalityPairs(sources.flatMap((src) => extractInstructions(src)));
|
|
204
|
+
for (const s of c.skills) {
|
|
205
|
+
const name = s.qualified.split(':').slice(1).join(':') || s.qualified;
|
|
206
|
+
if (ours.has(name)) pairs.push(collisionPair(s.qualified, name));
|
|
207
|
+
}
|
|
208
|
+
return pairs;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** One council seat, run through the council CLI; `null` when it cannot answer. */
|
|
212
|
+
export type Seat = (prompt: string) => string | null;
|
|
213
|
+
|
|
214
|
+
function councilSeat(projectRoot: string): Seat {
|
|
215
|
+
return (prompt) => {
|
|
216
|
+
const stamp = new Date().toISOString().replace(/[:.]/gu, '-');
|
|
217
|
+
const q = path.join(projectRoot, 'agents', 'runtime', 'council', 'questions', `neighbour-contradictions-${stamp}.md`);
|
|
218
|
+
const out = path.join(projectRoot, 'agents', 'runtime', 'council', 'responses', `neighbour-contradictions-${stamp}.md`);
|
|
219
|
+
try {
|
|
220
|
+
fs.mkdirSync(path.dirname(q), { recursive: true });
|
|
221
|
+
fs.writeFileSync(q, prompt, 'utf-8');
|
|
222
|
+
const args = ['council', 'run', q, '--single', '--prompt-mode', 'analysis', '--output', out, '--confirm', '--invocation', 'user_explicit'];
|
|
223
|
+
const res = spawnSync('agent-config', args, { cwd: projectRoot, encoding: 'utf-8' });
|
|
224
|
+
if (res.status !== 0) return null;
|
|
225
|
+
const doc = JSON.parse(fs.readFileSync(out, 'utf-8')) as { responses?: { text?: string }[] };
|
|
226
|
+
return doc.responses?.map((r) => r.text ?? '').join('\n') ?? null;
|
|
227
|
+
} catch {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* `--contradictions`: a verdict table, or `n/a` when no council is configured.
|
|
235
|
+
*
|
|
236
|
+
* Report-only — it edits nothing and gates nothing. The council transcript the
|
|
237
|
+
* seat writes lands under gitignored `agents/runtime/council/`; no tracked file
|
|
238
|
+
* changes.
|
|
239
|
+
*/
|
|
240
|
+
export function runContradictions(
|
|
241
|
+
projectRoot: string,
|
|
242
|
+
packageRoot: string,
|
|
243
|
+
opts: { homeRoot?: string; seat?: Seat; configured?: boolean } = {},
|
|
244
|
+
): { lines: string[]; rows: ReviewRow[] | null } {
|
|
245
|
+
const configured =
|
|
246
|
+
opts.configured ?? resolveAvailability(projectRoot, process.env)?.configured ?? false;
|
|
247
|
+
const pairs = contradictionCandidates(projectRoot, packageRoot, opts.homeRoot);
|
|
248
|
+
if (!configured) {
|
|
249
|
+
return {
|
|
250
|
+
lines: [` contradictions: n/a — no council configured (${pairs.length} candidate pair(s) formed, none reviewed)`],
|
|
251
|
+
rows: null,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
if (pairs.length === 0) return { lines: renderReview([]), rows: [] };
|
|
255
|
+
let rubric = '';
|
|
256
|
+
for (const rel of [['dist', 'agent-src', 'rules'], ['src', 'rules']]) {
|
|
257
|
+
try {
|
|
258
|
+
rubric = fs.readFileSync(path.join(packageRoot, ...rel, 'neighbour-precedence.md'), 'utf-8');
|
|
259
|
+
break;
|
|
260
|
+
} catch {
|
|
261
|
+
// Try the next layout.
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const answer = (opts.seat ?? councilSeat(projectRoot))(seatPrompt(pairs, rubric));
|
|
265
|
+
if (answer === null) {
|
|
266
|
+
return { lines: [` contradictions: n/a — the council seat did not answer (${pairs.length} candidate pair(s) formed)`], rows: null };
|
|
267
|
+
}
|
|
268
|
+
const rows = reviewRows(pairs, parseVerdicts(answer, pairs.length));
|
|
269
|
+
return { lines: renderReview(rows), rows };
|
|
270
|
+
}
|
|
271
|
+
|
|
147
272
|
/** The one line the full `doctor` run prints, linking to this verb. */
|
|
148
273
|
export function summaryLine(c: NeighbourCensus): string {
|
|
149
274
|
const counts = [
|
|
@@ -218,10 +343,12 @@ export function renderText(c: NeighbourCensus): string[] {
|
|
|
218
343
|
|
|
219
344
|
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
220
345
|
let json = false;
|
|
346
|
+
let contradictions = false;
|
|
221
347
|
let root = process.cwd();
|
|
222
348
|
let home: string | undefined;
|
|
223
349
|
for (let i = 0; i < argv.length; i += 1) {
|
|
224
350
|
if (argv[i] === '--json') json = true;
|
|
351
|
+
else if (argv[i] === '--contradictions') contradictions = true;
|
|
225
352
|
else if (argv[i] === '--project') {
|
|
226
353
|
root = argv[i + 1] ?? root;
|
|
227
354
|
i += 1;
|
|
@@ -237,6 +364,12 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
|
237
364
|
return 2;
|
|
238
365
|
}
|
|
239
366
|
}
|
|
367
|
+
if (contradictions) {
|
|
368
|
+
const r = runContradictions(path.resolve(root), resolvePackageRoot(import.meta.url), home === undefined ? {} : { homeRoot: home });
|
|
369
|
+
if (json) process.stdout.write(`${JSON.stringify({ contradictions: r.rows })}\n`);
|
|
370
|
+
else for (const line of r.lines) process.stdout.write(`${line}\n`);
|
|
371
|
+
return 0;
|
|
372
|
+
}
|
|
240
373
|
const c = runCensus(path.resolve(root), resolvePackageRoot(import.meta.url), home);
|
|
241
374
|
if (json) {
|
|
242
375
|
// Compact, not pretty-printed: this is the machine contract, and the
|