@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
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The registry of DELETED settings keys, and the once-per-run notice a leftover
|
|
3
|
+
* value gets. Extracted from `agent_settings.ts`, which sits at the 1500-line
|
|
4
|
+
* source ceiling — every retirement batch adds entries here, and here they cost
|
|
5
|
+
* no ratchet. `agent_settings.ts` re-exports `REMOVED_KEYS` so existing
|
|
6
|
+
* importers (the loader, `lint_settings_classes`) are unchanged.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Settings keys this package has DELETED. A leftover value from an older
|
|
10
|
+
* install is ignored — never applied by any reader — and surfaced with ONE
|
|
11
|
+
* deprecation line per key per process run (stderr; the exit code never
|
|
12
|
+
* changes).
|
|
13
|
+
*
|
|
14
|
+
* The map carries a per-key REASON rather than one shared sentence, because
|
|
15
|
+
* the list now spans more than one deletion doctrine and a single blanket
|
|
16
|
+
* phrase would mis-attribute every future entry. A reader who hits the line
|
|
17
|
+
* should learn why the key went, not just that it did.
|
|
18
|
+
*
|
|
19
|
+
* `subagents.*` — the always-on-orchestration doctrine
|
|
20
|
+
* (road-to-always-on-orchestration Phase 1): the layer has no per-layer
|
|
21
|
+
* on/off setting any more. `ai_team.enabled` joined in Step 1.3 — the
|
|
22
|
+
* `/team` family's availability is a codex-CLI/auth FACT
|
|
23
|
+
* (`src/scripts/ai_team/availability.ts`), not a flag; the `ai_team` config
|
|
24
|
+
* loader (`src/scripts/ai_team/config.ts`) separately accepts a leftover
|
|
25
|
+
* `enabled` key without failing closed, so this warning is the only surfaced
|
|
26
|
+
* signal of that deletion.
|
|
27
|
+
*
|
|
28
|
+
* `hooks.turn_end_gate.*` — the turn-end gate is always armed (2026-08-12).
|
|
29
|
+
* A default-off safety gate cannot soak, so the switch protecting the soak
|
|
30
|
+
* made the soak impossible; whether the gate fires is now decided by each
|
|
31
|
+
* detector's own trigger conditions. See `turn_end_gate_hook.ts` § "Always
|
|
32
|
+
* armed".
|
|
33
|
+
*
|
|
34
|
+
* The five `derivable` leaves below (2026-08-12, road-to-zero-settings Phase
|
|
35
|
+
* 2.1) are a different case from every entry above them, and the difference is
|
|
36
|
+
* the whole safety argument: no code path ever *consulted* them. Each appeared
|
|
37
|
+
* in the template, the schema and the reference page, and several in the setup
|
|
38
|
+
* wizard, while the decision they looked like they governed was taken
|
|
39
|
+
* elsewhere. A key nothing reads cannot change a default by leaving — so this
|
|
40
|
+
* is the one deletion batch that needs no replacement mechanism, only the
|
|
41
|
+
* per-key statement of what already decides.
|
|
42
|
+
*
|
|
43
|
+
* A sixth unread key, `screenshots.data_bearing_gate`, was found in the same
|
|
44
|
+
* pass and deliberately NOT deleted — it is `consent`, and the open question is
|
|
45
|
+
* whether the repair is to build its missing reader or to delete a promise a
|
|
46
|
+
* Hard Floor can never honour. See `settings-classes.md` § The six unread keys.
|
|
47
|
+
*
|
|
48
|
+
* `worktrees.mode` (2026-08-13, ADR-229) is a third doctrine again: not
|
|
49
|
+
* always-on, not unread. It WAS read, and the reader honoured all three values —
|
|
50
|
+
* the deletion says the decision was never the agent's to make. `ask` bought a
|
|
51
|
+
* round trip per spawn, `on` let the agent start parallel work unprompted, and
|
|
52
|
+
* `off` described the wanted behavior, so `off` became the hardcoded rule and
|
|
53
|
+
* the switch went. What decides instead is the user's own sentence in the chat.
|
|
54
|
+
*
|
|
55
|
+
* The 2026-10-09 batch (road-to-settings-classes-derivable-surface-stagnation
|
|
56
|
+
* Phase 2) is a fourth doctrine: `derivable` keys whose shipped default is the
|
|
57
|
+
* only behavior the package supports. Each WAS read — by code or by rule and
|
|
58
|
+
* command prose — and every reader was rewritten to state the old default as
|
|
59
|
+
* fixed behavior in the same change, so retiring the key changes no effective
|
|
60
|
+
* default; what a consumer who had set a non-default value loses is named by
|
|
61
|
+
* the reason.
|
|
62
|
+
*
|
|
63
|
+
* Every reason string must name what decides INSTEAD, never just "removed".
|
|
64
|
+
* Exported so `lint_settings_classes` can check the deletion side of the
|
|
65
|
+
* surface: a reason that names no replacement, or an entry whose key is live in
|
|
66
|
+
* the template again, is a contradiction the loader itself cannot notice.
|
|
67
|
+
*/
|
|
68
|
+
export const REMOVED_KEYS = new Map([
|
|
69
|
+
['subagents.enabled', 'always-on orchestration'],
|
|
70
|
+
['subagents.auto', 'always-on orchestration'],
|
|
71
|
+
['subagents.host_capabilities', 'always-on orchestration'],
|
|
72
|
+
['subagents.budget_routing', 'always-on orchestration'],
|
|
73
|
+
['ai_team.enabled', 'always-on orchestration'],
|
|
74
|
+
['hooks.turn_end_gate.enabled', 'the turn-end gate is always armed'],
|
|
75
|
+
['hooks.turn_end_gate.promissory', 'the turn-end gate is always armed'],
|
|
76
|
+
['hooks.turn_end_gate.language', 'the turn-end gate is always armed'],
|
|
77
|
+
['hooks.turn_end_gate.verification', 'the turn-end gate is always armed'],
|
|
78
|
+
['telegraph.speak_scope', 'the rule body states its own scope; compile_time_toggles decides whether the rule ships'],
|
|
79
|
+
['chat_history.max_size_kb', 'the rotate command takes --max-kb from argv; session-count pruning bounds the file'],
|
|
80
|
+
['chat_history.on_overflow', 'the overflow mode comes from the rotate command --mode argv'],
|
|
81
|
+
['quality.wait_for_remote_ci', 'whether to poll follows from the push plus a detectable remote pipeline'],
|
|
82
|
+
['legal_review_prep.consented_at', 'the provenance sidecar settings:set writes and consentVerdict reads'],
|
|
83
|
+
['worktrees.mode', 'the user asking for a worktree in the chat; creation is instruction-only and hardcoded'],
|
|
84
|
+
// 2026-10-09 — output and tone
|
|
85
|
+
['personal.minimal_output', 'direct-answers Iron Law 3 mandates terse replies; there is no verbose mode'],
|
|
86
|
+
['personal.play_by_play', 'direct-answers: no narration unless the user asks for it in the turn'],
|
|
87
|
+
['personal.pr_comment_bot_icon', 'no-decorative-emojis-in-git-surfaces forbids the 🤖 prefix'],
|
|
88
|
+
['verbosity.intent_announcements', 'direct-answers: act and emit the result, no "Let me…" openers'],
|
|
89
|
+
['verbosity.preview_artifacts', 'generated content is used directly; preview-on-error and the Iron-Law gates decide when a preview shows'],
|
|
90
|
+
['verbosity.routine_confirmations', 'the no-cheap-questions Pre-Send Self-Check; Iron-Law gates always ask'],
|
|
91
|
+
['verbosity.post_action_reports', 'direct-answers Iron Law 3: a one-line confirmation and one end-summary'],
|
|
92
|
+
['telegraph.speak', 'the telegraph-speak predicate in compile_time_toggles.ts; the bench verdict is package-level (ADR telegraph/0002)'],
|
|
93
|
+
['tokens.rich_skills', "the skill's own token_budget_class: rich plus the lint_token_budget_discipline ceiling"],
|
|
94
|
+
// 2026-10-09 — reasoning protocol switches
|
|
95
|
+
['reasoning.auto_gate', 'the RDP gate task signal plus the host self-assessment in rdp-gate.md'],
|
|
96
|
+
['reasoning.components.orchestrator', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
97
|
+
['reasoning.components.notes_first', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
98
|
+
['reasoning.components.grounding', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
99
|
+
['reasoning.components.intent', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
100
|
+
['reasoning.components.complexity_first', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
101
|
+
['reasoning.components.verifier_default', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
102
|
+
['reasoning.components.prediction_tracking', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
103
|
+
['reasoning.components.decision_ledger', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
104
|
+
['reasoning.components.uncertainty_budget', 'the RDP gate task and host signals decide per component; reasoning.enabled stays the hard off'],
|
|
105
|
+
// 2026-10-09 — roadmap cadence
|
|
106
|
+
['roadmap.skip_pre_run_gate', 'the command name names the scope; only an ambiguous roadmap or an unresolvable conflict shows the gate'],
|
|
107
|
+
['roadmap.dashboard_regen_cadence', 'a fixed cadence: every 5th closed step, every phase boundary, reply end and any file-shape touch'],
|
|
108
|
+
// 2026-10-09 — command suggestion and PR creation
|
|
109
|
+
['commands.auto_detect', "an orchestrator's own auto_detect front-matter and the --no-auto-detect flag"],
|
|
110
|
+
['commands.suggestion.enabled', 'the suggester match-score floor and cooldown; /command-suggestion-off silences one conversation'],
|
|
111
|
+
['commands.suggestion.confidence_floor', "the suggester's fixed 0.6 floor; a command's own suggestion frontmatter can tighten it"],
|
|
112
|
+
['commands.suggestion.cooldown_seconds', "the suggester's fixed 600-second cooldown; a command's own suggestion frontmatter can lengthen it"],
|
|
113
|
+
['commands.suggestion.max_options', 'the fixed cap of 4 suggestions plus the always-present as-is option'],
|
|
114
|
+
['commands.create_pr.api_examples', "/create-pr's grounding rule: an example only from a real source, otherwise a one-line pointer"],
|
|
115
|
+
['commands.create_pr.ui_paths', "/create-pr's light frontend heuristic, which fails open"],
|
|
116
|
+
['commands.create_pr.api_paths', "/create-pr's light API-endpoint heuristic, which fails open"],
|
|
117
|
+
// 2026-10-09 — memory and knowledge sharing
|
|
118
|
+
['memory.cadence', 'a fixed cadence: the memory line renders whenever a memory type was asked; memory.visibility: off still silences it'],
|
|
119
|
+
['memory.review_threshold', "/memory load's fixed preview threshold of 10 unreviewed intake signals"],
|
|
120
|
+
['knowledge.global_sharing.redaction.enabled', 'the write-time redaction scan, which always runs before a card goes global'],
|
|
121
|
+
['knowledge.global_sharing.redaction.halt_on_trigger', 'the redaction gate, which always halts on a confidential-pattern hit'],
|
|
122
|
+
['knowledge.global_sharing.auto_promote_threshold', 'the fixed two-repo sighting count that triggers a promotion suggestion'],
|
|
123
|
+
['knowledge.global_sharing.freshness.hypothesis_after_days', "the card's age over last_verified against the fixed 90-day lead-only window"],
|
|
124
|
+
['knowledge.global_sharing.freshness.stale_after_days', "the card's age over last_verified against the fixed 180-day skip window"],
|
|
125
|
+
// 2026-10-09 — hooks and engine
|
|
126
|
+
['hooks.concern_budget.max_per_event', "the concern-budget gate's own constant of 8 per (platform, event) cell"],
|
|
127
|
+
['hooks.concern_budget.hard_fail', "the concern-budget gate's --strict argv; without it the gate warns"],
|
|
128
|
+
['decision_engine.surface_traces', 'nothing: the per-phase decision trace stays off, the old default'],
|
|
129
|
+
['decision_engine.on_block_fallback', 'the fail-safe: an on_block ask that times out always stops'],
|
|
130
|
+
['explain.enable_last', 'the presence of a work-state trace; explain last always renders it'],
|
|
131
|
+
// 2026-10-09 — remaining
|
|
132
|
+
['project.pr_template', '/create-pr, which reads .github/pull_request_template.md'],
|
|
133
|
+
['pipelines.skill_improvement', 'the skill-improvement-trigger rule; the capture is a proposal the user confirms'],
|
|
134
|
+
['consistency.cross_source', 'the cross-source-consistency rule, always on; batching and the no-cheap-questions floor bound the noise'],
|
|
135
|
+
['subagents.downshift', 'the model_tier each sub-task declares; downshift is always on'],
|
|
136
|
+
['ai_team.suppress_setup_hint', 'nothing: the one-line team-mode setup hint is always shown'],
|
|
137
|
+
]);
|
|
138
|
+
/** Keys already warned about in THIS process — the "once per run" dedupe. */
|
|
139
|
+
const _warnedRemovedKeys = new Set();
|
|
140
|
+
/** Read one dotted path out of a merged settings tree; `undefined` when absent. */
|
|
141
|
+
function _readDotted(root, dotted) {
|
|
142
|
+
let node = root;
|
|
143
|
+
for (const part of dotted.split('.')) {
|
|
144
|
+
if (typeof node !== 'object' || node === null || Array.isArray(node)) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
node = node[part];
|
|
148
|
+
}
|
|
149
|
+
return node;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Warn once per process, on stderr, for every {@link REMOVED_KEYS} entry still
|
|
153
|
+
* present in a resolved settings tree. Never throws, never changes what the
|
|
154
|
+
* caller does with `merged` — a pure notification side effect.
|
|
155
|
+
*/
|
|
156
|
+
export function warnRemovedKeys(merged) {
|
|
157
|
+
for (const [key, reason] of REMOVED_KEYS) {
|
|
158
|
+
if (_warnedRemovedKeys.has(key)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (_readDotted(merged, key) === undefined) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
_warnedRemovedKeys.add(key);
|
|
165
|
+
process.stderr.write(`${key} was removed (${reason}); ignored.\n`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=settings_removed_keys.js.map
|
|
@@ -255,13 +255,90 @@ function _title(s) {
|
|
|
255
255
|
* Exported so the WRITER and every DETECTOR share one definition. A gate that
|
|
256
256
|
* re-spelled this string would drift from the writer silently, and the failure
|
|
257
257
|
* would be invisible in exactly the direction that matters: a stub the gate
|
|
258
|
-
* fails to recognise reads as a complete rule body.
|
|
258
|
+
* fails to recognise reads as a complete rule body. Two gates had done exactly
|
|
259
|
+
* that until step 2.1 of `road-to-a-thinned-layer-measured-in-one-unit`; both
|
|
260
|
+
* import this now.
|
|
261
|
+
*
|
|
262
|
+
* SHORTENED 2026-10-06 from 47 characters to 27 (step 2.2). It is paid once per
|
|
263
|
+
* stub and there were 89 stubs on the measured layer, so the sentence cost
|
|
264
|
+
* 4,183 characters of a 97,496-character standing total; at 27 it costs 2,403,
|
|
265
|
+
* a saving of 1,780 = 20 x 89.
|
|
266
|
+
*
|
|
267
|
+
* WHAT THE SHORTENING WAS NOT ALLOWED TO DO: drop the instruction. This is the
|
|
268
|
+
* only standing text in the whole layer that says what a stub is FOR — "load
|
|
269
|
+
* the body" occurs in no kernel rule and in neither root instruction file — so
|
|
270
|
+
* a bare token like `> thin` would have saved more and left nothing that could
|
|
271
|
+
* be followed. The decision record (D2, K6) rejected that explicitly: nothing
|
|
272
|
+
* in this repository can check whether an instruction nobody states is still
|
|
273
|
+
* obeyed.
|
|
274
|
+
*
|
|
275
|
+
* WHY IT MUST STAY LONG ENOUGH TO BE UNIQUE: {@link is_thin_entry} is a
|
|
276
|
+
* substring test over the whole file, so a marker short or generic enough to
|
|
277
|
+
* occur inside ordinary rule prose would make that rule read as a stub — and
|
|
278
|
+
* nine rule files carry blockquote lines. `thin_marker_unique_in_corpus.test.ts`
|
|
279
|
+
* runs the constant against every rule body in `src/rules/` and against every
|
|
280
|
+
* entry `build_thin` emits, in both directions, which is the check that bounds
|
|
281
|
+
* any further shortening.
|
|
259
282
|
*/
|
|
260
|
-
export const THIN_ENTRY_MARKER = '>
|
|
283
|
+
export const THIN_ENTRY_MARKER = '> Load the body on a match.';
|
|
261
284
|
/** Is this projected entry a pointer stub rather than a rule body? */
|
|
262
285
|
export function is_thin_entry(text) {
|
|
263
286
|
return text.includes(THIN_ENTRY_MARKER);
|
|
264
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* What introduces a stub's body pointer. One writer, one reader.
|
|
290
|
+
*
|
|
291
|
+
* A BARE PATH SINCE 2026-10-06 (step 2.3 of
|
|
292
|
+
* `road-to-a-thinned-layer-measured-in-one-unit`). The pointer used to be a
|
|
293
|
+
* markdown link, ``Body: [`<id>`](<prefix><id>.md)``, whose link TEXT repeated
|
|
294
|
+
* the rule id the target already ends in. That cost `6 + len(id)` per stub over
|
|
295
|
+
* the bare form — 2,359 characters across the 89 stubs of the measured layer,
|
|
296
|
+
* 534 of it pure syntax and the rest the id written a second time.
|
|
297
|
+
*
|
|
298
|
+
* Nothing followed the link as a link. Under `delivery` the hook loads the body
|
|
299
|
+
* and never reads the pointer at all; under `thin` an agent reads the path. A
|
|
300
|
+
* markdown link renders in neither case, so the syntax bought rendering nobody
|
|
301
|
+
* was doing.
|
|
302
|
+
*/
|
|
303
|
+
export const THIN_BODY_POINTER_PREFIX = 'Body: ';
|
|
304
|
+
/**
|
|
305
|
+
* The pointer, as the WRITER emits it — exported so a detector cannot re-spell
|
|
306
|
+
* it, which is the same drift {@link THIN_ENTRY_MARKER} documents one screen up
|
|
307
|
+
* and which two gates had already committed there.
|
|
308
|
+
*
|
|
309
|
+
* WHAT IT CAPTURES is the whole tail of the line from `Body: ` to its end, and
|
|
310
|
+
* that is the intended semantic rather than an accident of greediness: the
|
|
311
|
+
* writer emits the pointer LAST on its line, so the tail IS the path. A review
|
|
312
|
+
* round proposed a lazy `(.+?\.md)` to stop at the first `.md`; measured, it
|
|
313
|
+
* changes nothing, because `\s*$` forces the match to reach end of line either
|
|
314
|
+
* way and a lazy quantifier simply backtracks forward to the same place. The
|
|
315
|
+
* greedy form is kept and the property is pinned by a test, so the next reader
|
|
316
|
+
* meets the measurement instead of repeating the proposal.
|
|
317
|
+
*
|
|
318
|
+
* ANCHORED TO END OF LINE, NOT `\S+`. The pointer is the last thing on its
|
|
319
|
+
* line, and a package root may contain spaces; `\S+` would silently stop at the
|
|
320
|
+
* first one and report a well-formed pointer as missing.
|
|
321
|
+
*
|
|
322
|
+
* COMPOSED FROM {@link THIN_BODY_POINTER_PREFIX} rather than re-spelling it.
|
|
323
|
+
* The constant exists so a reader cannot hold its own copy, and a pattern six
|
|
324
|
+
* lines below it holding a literal `Body: ` would have broken that invariant in
|
|
325
|
+
* the file that states it.
|
|
326
|
+
*/
|
|
327
|
+
export const THIN_BODY_POINTER_RE = (() => {
|
|
328
|
+
const lit = THIN_BODY_POINTER_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
329
|
+
// THE LAST PREFIX ON THE LINE, NOT THE FIRST. `thin_entry` puts the rule's
|
|
330
|
+
// own `description` on the SAME line ahead of the pointer, so a description
|
|
331
|
+
// containing the literal `Body: ` used to start the match inside the
|
|
332
|
+
// description and capture it as part of the path — `has_body_pointer` stayed
|
|
333
|
+
// true while the extraction was wrong, which is a wrong assertion rather
|
|
334
|
+
// than a visible failure. Forbidding a second prefix inside the capture
|
|
335
|
+
// makes the first viable start the last occurrence, which is the pointer.
|
|
336
|
+
return new RegExp(`${lit}((?:(?!${lit}).)+\\.md)\\s*$`, 'm');
|
|
337
|
+
})();
|
|
338
|
+
/** Does this entry carry a body pointer the writer would recognise? */
|
|
339
|
+
export function has_body_pointer(text) {
|
|
340
|
+
return THIN_BODY_POINTER_RE.test(text);
|
|
341
|
+
}
|
|
265
342
|
/**
|
|
266
343
|
* Where a stub tells a reader the body actually is.
|
|
267
344
|
*
|
|
@@ -318,7 +395,7 @@ export function thin_entry(rule_id, text, bodyLinkPrefix = BODY_LINK_PREFIX) {
|
|
|
318
395
|
const fires = hint ? ` Fires on: ${hint}.` : '';
|
|
319
396
|
return (`## ${title}\n` +
|
|
320
397
|
`${THIN_ENTRY_MARKER}${fires} ${desc} ` +
|
|
321
|
-
|
|
398
|
+
`${THIN_BODY_POINTER_PREFIX}${bodyLinkPrefix}${rule_id}.md\n`);
|
|
322
399
|
}
|
|
323
400
|
/**
|
|
324
401
|
* The marker that opens a stub's copied law block, and the one that closes it
|
package/dist/server/app.js
CHANGED
|
@@ -155,7 +155,7 @@ export async function createApp(opts) {
|
|
|
155
155
|
await app.register(pingRoute({ writeRoot, projectScopeRoot, mode, dryRun, projectSurface: opts.projectSurface === true }));
|
|
156
156
|
await app.register(discoveryRoute(opts.discoveryManifestPath ? { manifestPath: opts.discoveryManifestPath } : {}));
|
|
157
157
|
await app.register(schemaRoute());
|
|
158
|
-
await app.register(settingsRoute({ writeRoot, legacyReadRoot, packageRoot, dryRun, userGlobalReadRoot: userGlobalRead }));
|
|
158
|
+
await app.register(settingsRoute({ writeRoot, legacyReadRoot, packageRoot, dryRun, userGlobalReadRoot: userGlobalRead, userGlobalWrite: mode === 'global' }));
|
|
159
159
|
await app.register(settingsChangesRoute({ writeRoot, userGlobalReadRoot: userGlobalRead, dryRun }));
|
|
160
160
|
await app.register(userMdRoute({ writeRoot, legacyReadRoot, dryRun, userGlobalReadRoot: userGlobalRead }));
|
|
161
161
|
await app.register(installRoute(opts.installRouteOptions ?? {}));
|
|
@@ -167,6 +167,7 @@ export async function createApp(opts) {
|
|
|
167
167
|
dryRun,
|
|
168
168
|
userGlobalReadRoot: userGlobalRead,
|
|
169
169
|
extendedSteps: opts.extendedSteps === true,
|
|
170
|
+
userGlobalWrite: mode === 'global',
|
|
170
171
|
...(opts.initialStep !== undefined ? { initialStep: opts.initialStep } : {}),
|
|
171
172
|
...(opts.wizardMode !== undefined ? { wizardMode: opts.wizardMode } : {}),
|
|
172
173
|
}));
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The settings route's handling of the three `git.*` keys.
|
|
3
|
+
*
|
|
4
|
+
* In global mode the route writes the user-global file, and `load_agent_settings`
|
|
5
|
+
* discards `git.*` keys from that file, so a value saved there has no effect in
|
|
6
|
+
* any repository. The form is not offered those keys, and a non-default value is
|
|
7
|
+
* refused with the place a team declares them instead (ADR-283). A template
|
|
8
|
+
* default is accepted: the form round-trips it, and `upgrade` inserts it too.
|
|
9
|
+
*
|
|
10
|
+
* In every mode a value goes through the same check `git:convention show` and
|
|
11
|
+
* `settings:check` run, so a pattern that would reach a shell is refused here as
|
|
12
|
+
* well.
|
|
13
|
+
*/
|
|
14
|
+
import { promises as fs } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { parseYaml } from './io/yamlIO.js';
|
|
17
|
+
import { GIT_CONVENTION_KEYS, invalidReason } from '../scripts/_lib/git_convention.js';
|
|
18
|
+
export const WITHHELD_GIT_KEYS = GIT_CONVENTION_KEYS.map((k) => `git.${k}`);
|
|
19
|
+
export const WITHHELD_REASON = 'This form writes your user-global settings file, which does not carry git.* keys. ' +
|
|
20
|
+
'A team declares them in .git-convention.yml at the repository root; one checkout can set them in its project settings file.';
|
|
21
|
+
function _gitSection(values) {
|
|
22
|
+
const git = values['git'];
|
|
23
|
+
return git !== null && typeof git === 'object' && !Array.isArray(git) ? git : null;
|
|
24
|
+
}
|
|
25
|
+
/** The values and the JSON schema with the `git` section removed. */
|
|
26
|
+
export function withholdGitKeys(values, schema) {
|
|
27
|
+
const { git: _git, ...rest } = values;
|
|
28
|
+
const properties = { ...(schema.properties ?? {}) };
|
|
29
|
+
delete properties['git'];
|
|
30
|
+
const next = { ...schema, properties };
|
|
31
|
+
if (Array.isArray(schema.required))
|
|
32
|
+
next.required = schema.required.filter((k) => k !== 'git');
|
|
33
|
+
return { values: rest, schema: next };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Field issues for the `git.*` values of a write. `defaults` is the template's
|
|
37
|
+
* `git` section; `userGlobal` is true when the write lands in the user-global file.
|
|
38
|
+
*/
|
|
39
|
+
export function gitKeyWriteIssues(values, defaults, userGlobal) {
|
|
40
|
+
const git = _gitSection(values);
|
|
41
|
+
if (git === null)
|
|
42
|
+
return [];
|
|
43
|
+
const fallback = _gitSection(defaults) ?? {};
|
|
44
|
+
const issues = [];
|
|
45
|
+
for (const key of GIT_CONVENTION_KEYS) {
|
|
46
|
+
const value = git[key];
|
|
47
|
+
if (typeof value !== 'string')
|
|
48
|
+
continue;
|
|
49
|
+
const why = invalidReason(key, value);
|
|
50
|
+
if (why !== null) {
|
|
51
|
+
issues.push({ path: `git.${key}`, message: why });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const def = fallback[key];
|
|
55
|
+
if (userGlobal && !(typeof def === 'string' && def === value)) {
|
|
56
|
+
issues.push({ path: `git.${key}`, message: WITHHELD_REASON });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return issues;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The write candidate with the `git` section the file already holds. In global
|
|
63
|
+
* mode the form never showed that section, and the schema's `.default({})`
|
|
64
|
+
* fills template defaults into whatever arrives, so a value the user-global
|
|
65
|
+
* file carries would otherwise read as a change the user made: a guarded-key
|
|
66
|
+
* confirmation for a field they never saw, then a silent reset.
|
|
67
|
+
*
|
|
68
|
+
* `fileValues` is that file alone, never the merged view: the merge carries
|
|
69
|
+
* the template defaults and any project layer, and copying a project value
|
|
70
|
+
* here would write it into the user-global file without passing the gate.
|
|
71
|
+
*/
|
|
72
|
+
export function keepWithheldGit(candidate, fileValues) {
|
|
73
|
+
const { git: _sent, ...rest } = candidate;
|
|
74
|
+
return 'git' in fileValues ? { ...rest, git: fileValues['git'] } : rest;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The before-side of a global-mode diff: the merged view with its `git` section
|
|
78
|
+
* swapped for the file's own, or dropped when the file has none. The candidate
|
|
79
|
+
* from `keepWithheldGit` carries exactly that section, so comparing it against
|
|
80
|
+
* the merged view would report template defaults and project values as edits
|
|
81
|
+
* to a section the form never showed.
|
|
82
|
+
*/
|
|
83
|
+
export function gitDiffBase(merged, fileValues) {
|
|
84
|
+
return keepWithheldGit(merged, fileValues);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The wizard's finish write through the same gate: a 422 is sent and true
|
|
88
|
+
* returned when a `git.*` value is refused. The template's `git` section holds
|
|
89
|
+
* no install placeholder, so it is parsed without substitution.
|
|
90
|
+
*/
|
|
91
|
+
export async function refuseGitKeys(reply, values, packageRoot, userGlobal) {
|
|
92
|
+
let defaults = {};
|
|
93
|
+
try {
|
|
94
|
+
defaults = parseYaml(await fs.readFile(join(packageRoot, 'src', 'config', 'agent-settings.template.yml'), 'utf8'));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
defaults = {};
|
|
98
|
+
}
|
|
99
|
+
const issues = gitKeyWriteIssues(values, defaults, userGlobal);
|
|
100
|
+
if (issues.length === 0)
|
|
101
|
+
return false;
|
|
102
|
+
await reply.code(422).send({ error: { code: 'VALIDATION', message: 'invalid settings', fields: issues } });
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=gitKeysGate.js.map
|
|
@@ -1,12 +1,36 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
3
4
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
4
5
|
import { settingsSchema } from '../schemas/settings.js';
|
|
5
|
-
import { parseYaml, mergeIntoTemplate, diffValues, deepMerge, TEMPLATE_PLACEHOLDER_DEFAULTS } from '../io/yamlIO.js';
|
|
6
|
+
import { parseYaml, mergeIntoTemplate, diffValues, deepMerge, renderSparseSettings, substituteTemplatePlaceholders, TEMPLATE_PLACEHOLDER_DEFAULTS } from '../io/yamlIO.js';
|
|
7
|
+
import { sparseSettingsValues } from './wizard.js';
|
|
6
8
|
import { writeAtomic } from '../io/atomicWrite.js';
|
|
9
|
+
import { WITHHELD_GIT_KEYS, WITHHELD_REASON, gitDiffBase, gitKeyWriteIssues, keepWithheldGit, withholdGitKeys } from '../gitKeysGate.js';
|
|
7
10
|
import { sharedWriteTarget, resolveThroughSymlinks } from '../io/sharedWriteCheck.js';
|
|
8
11
|
import { PACKAGE_ROOT } from '../../cli/paths.js';
|
|
9
12
|
import { buildSettingsClassIndex, guardedChangedKeys, parseSettingsClassRows } from '../../shared/settingsClasses.js';
|
|
13
|
+
/**
|
|
14
|
+
* A fresh user-global file records decisions, not the defaults: the form posts
|
|
15
|
+
* every value, and a copy of the template's would freeze each default at today's
|
|
16
|
+
* value. Only leaves that differ from the template are kept, over the carve-outs.
|
|
17
|
+
*/
|
|
18
|
+
async function freshUserGlobalValues(packageRoot, candidate) {
|
|
19
|
+
const templateBody = await fs.readFile(join(packageRoot, 'src', 'config', 'agent-settings.template.yml'), 'utf8');
|
|
20
|
+
const template = parseYaml(substituteTemplatePlaceholders(templateBody));
|
|
21
|
+
const decided = (value, dflt) => {
|
|
22
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
23
|
+
const base = dflt !== null && typeof dflt === 'object' && !Array.isArray(dflt) ? dflt : {};
|
|
24
|
+
const kept = Object.entries(value)
|
|
25
|
+
.map(([k, v]) => [k, decided(v, base[k])])
|
|
26
|
+
.filter(([, v]) => v !== undefined);
|
|
27
|
+
return kept.length === 0 ? undefined : Object.fromEntries(kept);
|
|
28
|
+
}
|
|
29
|
+
return isDeepStrictEqual(value, dflt) ? undefined : value;
|
|
30
|
+
};
|
|
31
|
+
const own = (decided(candidate, template) ?? {});
|
|
32
|
+
return deepMerge(sparseSettingsValues(templateBody, {}), own);
|
|
33
|
+
}
|
|
10
34
|
/** Sidecar written by `settings:set`, keyed by dotted path. */
|
|
11
35
|
const PROVENANCE_RELATIVE = join('settings', '.agent-settings.provenance.json');
|
|
12
36
|
/**
|
|
@@ -217,6 +241,8 @@ async function readLayeredSettings(packageRoot, writeRoot, legacyReadRoot, userG
|
|
|
217
241
|
])],
|
|
218
242
|
project: projectLayer !== null ? dottedLeafPaths(projectLayer.values) : [],
|
|
219
243
|
},
|
|
244
|
+
writeLayer: globalLayer?.values ?? null,
|
|
245
|
+
writeLayerRaw: globalLayer?.raw ?? null,
|
|
220
246
|
};
|
|
221
247
|
}
|
|
222
248
|
function zodIssuesToFields(issues) {
|
|
@@ -234,6 +260,10 @@ export function settingsRoute(opts) {
|
|
|
234
260
|
app.get('/api/v1/settings', async (_request, reply) => {
|
|
235
261
|
try {
|
|
236
262
|
const state = await readLayeredSettings(packageRoot, opts.writeRoot, opts.legacyReadRoot, opts.userGlobalReadRoot);
|
|
263
|
+
const offered = opts.userGlobalWrite === true
|
|
264
|
+
? withholdGitKeys(state.values, SETTINGS_JSON_SCHEMA)
|
|
265
|
+
: { values: state.values, schema: SETTINGS_JSON_SCHEMA };
|
|
266
|
+
const withheld = opts.userGlobalWrite === true ? { withheld: { keys: WITHHELD_GIT_KEYS, reason: WITHHELD_REASON } } : {};
|
|
237
267
|
if (!state.hasRealFile) {
|
|
238
268
|
// No on-disk file yet — the wizard creates it. Surface the
|
|
239
269
|
// template-defaults values + schema + path in the body so
|
|
@@ -242,19 +272,21 @@ export function settingsRoute(opts) {
|
|
|
242
272
|
// `{}` and the user's first save fails schema validation).
|
|
243
273
|
await reply.code(404).send({
|
|
244
274
|
error: { code: 'NOT_FOUND', message: 'settings file missing' },
|
|
245
|
-
defaults:
|
|
275
|
+
defaults: offered.values,
|
|
246
276
|
lastModified: 0,
|
|
247
277
|
path: SETTINGS_RELATIVE,
|
|
248
|
-
schema:
|
|
278
|
+
schema: offered.schema,
|
|
279
|
+
...withheld,
|
|
249
280
|
});
|
|
250
281
|
return reply;
|
|
251
282
|
}
|
|
252
283
|
const legacyHints = extractLegacyHints(state.values);
|
|
253
284
|
return {
|
|
254
|
-
values:
|
|
285
|
+
values: offered.values,
|
|
255
286
|
lastModified: state.mtimeMs,
|
|
256
287
|
path: SETTINGS_RELATIVE,
|
|
257
|
-
schema:
|
|
288
|
+
schema: offered.schema,
|
|
289
|
+
...withheld,
|
|
258
290
|
legacyHints,
|
|
259
291
|
// Phase 5.4 — per-layer provenance for the settings hub's
|
|
260
292
|
// "set globally / in this project" source badges.
|
|
@@ -293,7 +325,13 @@ export function settingsRoute(opts) {
|
|
|
293
325
|
});
|
|
294
326
|
return reply;
|
|
295
327
|
}
|
|
296
|
-
const
|
|
328
|
+
const candidate = opts.userGlobalWrite === true
|
|
329
|
+
? keepWithheldGit(parsed.data, current.writeLayer ?? {})
|
|
330
|
+
: parsed.data;
|
|
331
|
+
const before = opts.userGlobalWrite === true
|
|
332
|
+
? gitDiffBase(current.values, current.writeLayer ?? {})
|
|
333
|
+
: current.values;
|
|
334
|
+
const changes = diffValues(before, candidate);
|
|
297
335
|
return { changes };
|
|
298
336
|
});
|
|
299
337
|
app.put('/api/v1/settings', async (request, reply) => {
|
|
@@ -310,6 +348,11 @@ export function settingsRoute(opts) {
|
|
|
310
348
|
});
|
|
311
349
|
return reply;
|
|
312
350
|
}
|
|
351
|
+
const gitIssues = gitKeyWriteIssues(parsed.data, await loadDefaultSettings(packageRoot), opts.userGlobalWrite === true);
|
|
352
|
+
if (gitIssues.length > 0) {
|
|
353
|
+
await reply.code(422).send({ error: { code: 'VALIDATION', message: 'invalid settings', fields: gitIssues } });
|
|
354
|
+
return reply;
|
|
355
|
+
}
|
|
313
356
|
const current = await readLayeredSettings(packageRoot, opts.writeRoot, opts.legacyReadRoot, opts.userGlobalReadRoot);
|
|
314
357
|
if (!current.hasRealFile) {
|
|
315
358
|
await reply.code(404).send({ error: { code: 'NOT_FOUND', message: 'settings file missing' } });
|
|
@@ -322,8 +365,22 @@ export function settingsRoute(opts) {
|
|
|
322
365
|
});
|
|
323
366
|
return reply;
|
|
324
367
|
}
|
|
368
|
+
const candidate = opts.userGlobalWrite === true
|
|
369
|
+
? keepWithheldGit(parsed.data, current.writeLayer ?? {})
|
|
370
|
+
: parsed.data;
|
|
325
371
|
try {
|
|
326
|
-
|
|
372
|
+
// In global mode the scaffold may be the project file, whose
|
|
373
|
+
// git section the candidate does not overwrite; the file being
|
|
374
|
+
// written is the base, so a section it lacks stays absent. An
|
|
375
|
+
// absent user-global file is rendered the way the wizard renders
|
|
376
|
+
// a fresh one: merging into an empty body appends flat dotted
|
|
377
|
+
// keys, which no reader resolves.
|
|
378
|
+
const ownRaw = current.writeLayerRaw;
|
|
379
|
+
const merged = opts.userGlobalWrite !== true
|
|
380
|
+
? mergeIntoTemplate(current.raw, candidate)
|
|
381
|
+
: ownRaw !== null
|
|
382
|
+
? mergeIntoTemplate(ownRaw, candidate)
|
|
383
|
+
: renderSparseSettings(await freshUserGlobalValues(packageRoot, candidate));
|
|
327
384
|
if (opts.dryRun === true) {
|
|
328
385
|
// No disk write, no Last-Modified bump — surface the
|
|
329
386
|
// rendered body so the maintainer sees what a real
|
|
@@ -352,7 +409,9 @@ export function settingsRoute(opts) {
|
|
|
352
409
|
// this point and is not gated — it writes nothing.
|
|
353
410
|
if (body.confirmGuarded !== true) {
|
|
354
411
|
const classes = await readClassIndex(packageRoot);
|
|
355
|
-
const guarded = guardedChangedKeys(classes, diffValues(
|
|
412
|
+
const guarded = guardedChangedKeys(classes, diffValues(opts.userGlobalWrite === true
|
|
413
|
+
? gitDiffBase(current.values, current.writeLayer ?? {})
|
|
414
|
+
: current.values, candidate));
|
|
356
415
|
if (guarded.length > 0) {
|
|
357
416
|
await reply.code(409).send({
|
|
358
417
|
error: 'guarded-keys',
|
|
@@ -19,6 +19,7 @@ import { detectAgentSwitch, AGENT_SWITCH_INSTALL_COMMAND, AGENT_SWITCH_REPO } fr
|
|
|
19
19
|
import { readDismissedRecommendations, dismissRecommendation } from '../../install/wizardDismissals.js';
|
|
20
20
|
import { installCompleted, installDoneSummary } from '../../install/preserve.js';
|
|
21
21
|
import { apiOnQuotaView } from '../../scripts/ai_council/transport_resolver.js';
|
|
22
|
+
import { refuseGitKeys } from '../gitKeysGate.js';
|
|
22
23
|
const STATE_REL = join('state', 'wizard-state.json');
|
|
23
24
|
const SETTINGS_REL = join('settings', '.agent-settings.yml');
|
|
24
25
|
const USER_IDENTITY_REL = join('settings', '.agent-user.yml');
|
|
@@ -1198,6 +1199,9 @@ export function wizardRoute(opts) {
|
|
|
1198
1199
|
const effectiveWriteRoot = scope === 'project' && projectScopeRoot !== null
|
|
1199
1200
|
? projectScopeRoot
|
|
1200
1201
|
: opts.writeRoot;
|
|
1202
|
+
const userGlobalTarget = opts.userGlobalWrite === true && effectiveWriteRoot === opts.writeRoot;
|
|
1203
|
+
if (await refuseGitKeys(reply, settingsParsed.data, opts.packageRoot, userGlobalTarget))
|
|
1204
|
+
return reply;
|
|
1201
1205
|
try {
|
|
1202
1206
|
const template = await readTemplate(opts.packageRoot);
|
|
1203
1207
|
const answers = settingsParsed.data;
|