@event4u/agent-config 9.26.0 → 9.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/AGENTS.md +12 -11
- package/CHANGELOG.md +134 -207
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/conformance.md +43 -0
- package/dist/agent-src/commands/roadmap/next.md +65 -3
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +10 -3
- package/dist/agent-src/rules/active-remediation.md +2 -0
- package/dist/agent-src/rules/analysis-skill-routing.md +2 -0
- package/dist/agent-src/rules/architecture.md +2 -0
- package/dist/agent-src/rules/artifact-drafting-protocol.md +2 -0
- package/dist/agent-src/rules/artifact-engagement-recording.md +6 -1
- package/dist/agent-src/rules/augment-edit-discipline.md +2 -0
- package/dist/agent-src/rules/autonomous-execution.md +3 -1
- package/dist/agent-src/rules/brand-consistency.md +2 -0
- package/dist/agent-src/rules/brand-source-of-truth.md +35 -6
- package/dist/agent-src/rules/broken-access-control.md +2 -0
- package/dist/agent-src/rules/cli-output-handling.md +2 -0
- package/dist/agent-src/rules/code-comment-discipline.md +2 -0
- package/dist/agent-src/rules/code-provenance.md +2 -0
- package/dist/agent-src/rules/command-suggestion-policy.md +2 -0
- package/dist/agent-src/rules/commit-conventions.md +2 -0
- package/dist/agent-src/rules/communication-through-line.md +2 -0
- package/dist/agent-src/rules/content-quoting-floor.md +2 -0
- package/dist/agent-src/rules/context-hygiene.md +13 -1
- package/dist/agent-src/rules/copilot-routing.md +2 -0
- package/dist/agent-src/rules/council-availability.md +93 -0
- package/dist/agent-src/rules/cross-source-consistency.md +5 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +2 -0
- package/dist/agent-src/rules/delegation-policy.md +31 -5
- package/dist/agent-src/rules/design-fidelity.md +5 -0
- package/dist/agent-src/rules/design-review-after-ui-write.md +4 -0
- package/dist/agent-src/rules/devcontainer-routing.md +2 -0
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +2 -0
- package/dist/agent-src/rules/docker-commands.md +2 -0
- package/dist/agent-src/rules/domain-adoption-policy.md +2 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +2 -0
- package/dist/agent-src/rules/domain-safety-pii.md +2 -0
- package/dist/agent-src/rules/domain-safety-retention.md +2 -0
- package/dist/agent-src/rules/downstream-changes.md +2 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
- package/dist/agent-src/rules/evaluator-independence.md +14 -3
- package/dist/agent-src/rules/external-code-graph-interop.md +4 -1
- package/dist/agent-src/rules/external-reference-deep-dive.md +2 -0
- package/dist/agent-src/rules/fast-path-marker-visibility.md +2 -0
- package/dist/agent-src/rules/finance-safety-floor.md +3 -1
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +2 -0
- package/dist/agent-src/rules/git-history-discipline.md +3 -1
- package/dist/agent-src/rules/guidelines.md +2 -0
- package/dist/agent-src/rules/history-discipline.md +5 -1
- package/dist/agent-src/rules/icon-consistency.md +2 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +2 -0
- package/dist/agent-src/rules/improve-before-implement.md +2 -0
- package/dist/agent-src/rules/invite-challenge.md +2 -0
- package/dist/agent-src/rules/laravel-routing.md +2 -0
- package/dist/agent-src/rules/laravel-translations.md +2 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +2 -0
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +2 -0
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +2 -0
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +2 -0
- package/dist/agent-src/rules/media-governance-routing.md +2 -0
- package/dist/agent-src/rules/media-sync-ground-truth.md +2 -0
- package/dist/agent-src/rules/minimal-safe-diff.md +2 -0
- package/dist/agent-src/rules/missing-tool-handling.md +2 -0
- package/dist/agent-src/rules/model-recommendation.md +2 -0
- package/dist/agent-src/rules/no-attribution-footers.md +2 -0
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +2 -0
- package/dist/agent-src/rules/no-pr-progress-comments.md +5 -1
- package/dist/agent-src/rules/no-roadmap-references.md +2 -0
- package/dist/agent-src/rules/notes-first-reasoning.md +2 -0
- package/dist/agent-src/rules/onboarding-gate.md +5 -1
- package/dist/agent-src/rules/output-discipline.md +2 -0
- package/dist/agent-src/rules/package-ci-checks.md +2 -0
- package/dist/agent-src/rules/persona-governance.md +2 -0
- package/dist/agent-src/rules/php-coding.md +2 -0
- package/dist/agent-src/rules/prefer-enums-over-literals.md +2 -0
- package/dist/agent-src/rules/preservation-guard.md +2 -0
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -0
- package/dist/agent-src/rules/question-not-instruction.md +2 -0
- package/dist/agent-src/rules/reviewer-awareness.md +2 -0
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +6 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +2 -0
- package/dist/agent-src/rules/role-mode-adherence.md +3 -1
- package/dist/agent-src/rules/rule-type-governance.md +2 -0
- package/dist/agent-src/rules/runtime-safety.md +2 -0
- package/dist/agent-src/rules/scale-discipline.md +5 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
- package/dist/agent-src/rules/self-repair-loop.md +103 -0
- package/dist/agent-src/rules/senior-engineering-discipline.md +2 -0
- package/dist/agent-src/rules/session-canary.md +62 -19
- package/dist/agent-src/rules/settings-ask-protocol.md +4 -0
- package/dist/agent-src/rules/size-enforcement.md +2 -0
- package/dist/agent-src/rules/skill-improvement-trigger.md +2 -0
- package/dist/agent-src/rules/skill-quality.md +2 -0
- package/dist/agent-src/rules/slash-command-routing-policy.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +2 -0
- package/dist/agent-src/rules/source-discovery-gate.md +2 -0
- package/dist/agent-src/rules/source-of-truth.md +2 -0
- package/dist/agent-src/rules/spreadsheet-source-quality.md +2 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +3 -1
- package/dist/agent-src/rules/symfony-routing.md +2 -0
- package/dist/agent-src/rules/think-before-action.md +2 -0
- package/dist/agent-src/rules/token-budget-discipline.md +5 -1
- package/dist/agent-src/rules/token-efficiency.md +2 -0
- package/dist/agent-src/rules/token-optimizer-maintenance.md +2 -0
- package/dist/agent-src/rules/tool-safety.md +7 -1
- package/dist/agent-src/rules/ui-audit-gate.md +4 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +2 -0
- package/dist/agent-src/rules/upstream-proposal.md +2 -0
- package/dist/agent-src/rules/user-interaction.md +2 -0
- package/dist/agent-src/rules/user-interrupt-priority.md +2 -0
- package/dist/agent-src/skills/adversarial-review/SKILL.md +1 -1
- package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
- package/dist/agent-src/skills/performance-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-improvement/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/security-audit/SKILL.md +1 -1
- package/dist/agent-src/skills/sequential-thinking/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
- package/dist/agent-src/templates/AGENTS.md +6 -10
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli/registry.js +9 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-22GCIJ2O.js +270 -0
- package/dist/cli-delegate/{chunk-BSLUHV2F.js → chunk-2BE5I2MN.js} +156 -141
- package/dist/cli-delegate/{chunk-AIIUU73N.js → chunk-7OMQCH4V.js} +1 -1
- package/dist/cli-delegate/{chunk-HJ6DAJHR.js → chunk-GB2FSUEE.js} +57 -7
- package/dist/cli-delegate/{chunk-WR6GTRHJ.js → chunk-JXARCGVN.js} +3 -3
- package/dist/cli-delegate/{chunk-SJQMJI7M.js → chunk-PQSAQKHW.js} +467 -305
- package/dist/cli-delegate/chunk-REKCMYOU.js +2991 -0
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +134 -0
- package/dist/cli-delegate/cmd_conformance.js +7 -7
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +4 -4
- package/dist/cli-delegate/cmd_explain.js +80 -330
- package/dist/cli-delegate/cmd_export.js +5 -5
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +2 -2
- package/dist/cli-delegate/cmd_mcp_available.js +433 -0
- package/dist/cli-delegate/cmd_migrate.js +3 -3
- package/dist/cli-delegate/cmd_packs_active.js +153 -0
- package/dist/cli-delegate/cmd_preflight.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +5 -5
- package/dist/cli-delegate/cmd_route_audit.js +8 -8
- package/dist/cli-delegate/cmd_route_explain.js +4 -4
- package/dist/cli-delegate/cmd_settings_get.js +272 -0
- package/dist/cli-delegate/cmd_settings_migrate.js +5 -5
- package/dist/cli-delegate/cmd_settings_set.js +7 -2967
- package/dist/cli-delegate/cmd_sync.js +5 -5
- package/dist/cli-delegate/cmd_uninstall.js +5 -5
- package/dist/cli-delegate/cmd_update.js +4 -4
- package/dist/cli-delegate/cmd_upgrade.js +4 -4
- package/dist/cli-delegate/cmd_validate.js +5 -5
- package/dist/cli-delegate/cmd_versions.js +4 -4
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +184 -124
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +7 -5
- package/dist/discovery/trust-report.md +11 -11
- package/dist/discovery/workspaces.json +6 -4
- package/dist/hooks/dispatch.js +9080 -5701
- package/dist/install/install.mjs +698 -508
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +698 -437
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +80 -15
- package/dist/scripts/_lib/agent_settings.js.map +1 -1
- package/dist/scripts/condense.js +33 -2
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/io/yamlIO.js +85 -0
- package/dist/server/io/yamlIO.js.map +1 -1
- package/dist/server/routes/settings.js +1 -12
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/routes/wizard.js +52 -2
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/shared/settingsCarveOut.js +118 -0
- package/dist/shared/settingsCarveOut.js.map +1 -0
- package/dist/shared/settingsSurface.js +7 -1
- package/dist/shared/settingsSurface.js.map +1 -1
- package/dist/ui/assets/index-DmR0mbk4.js.map +1 -1
- package/docs/contracts/settings-classes.md +29 -8
- package/docs/guidelines/agent-infra/memory-access.md +14 -3
- package/package.json +1 -1
- package/src/agent-src/templates/AGENTS.md +6 -10
- package/src/config/budgets.yml +29 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +26 -0
- package/src/scripts/_cli/cmd_brand_status.ts +174 -0
- package/src/scripts/_cli/cmd_doctor.ts +6 -21
- package/src/scripts/_cli/cmd_mcp_available.ts +266 -0
- package/src/scripts/_cli/cmd_packs_active.ts +225 -0
- package/src/scripts/_cli/cmd_settings_get.ts +324 -0
- package/src/scripts/_dispatch.bash +75 -0
- package/src/scripts/_lib/agent_settings.ts +82 -16
- package/src/scripts/_lib/carrier_divergence.ts +135 -0
- package/src/scripts/_lib/git_common_dir.ts +128 -0
- package/src/scripts/_lib/host_capability.ts +84 -1
- package/src/scripts/_lib/obligation_frequency.ts +391 -0
- package/src/scripts/_lib/prompt_shape.ts +88 -0
- package/src/scripts/_lib/review_skipped_record.ts +102 -0
- package/src/scripts/_lib/rule_layer_overlap.ts +254 -0
- package/src/scripts/_lib/self_repair.ts +342 -0
- package/src/scripts/_lib/self_repair_store.ts +100 -0
- package/src/scripts/_lib/session_register.ts +361 -0
- package/src/scripts/_lib/transcript_entry.ts +80 -0
- package/src/scripts/check_branch_freshness.ts +255 -0
- package/src/scripts/check_council_config_location.ts +125 -1
- package/src/scripts/check_enforcement_coverage.ts +192 -7
- package/src/scripts/check_rule_projection_integrity.ts +364 -0
- package/src/scripts/check_standing_rule_delivery.ts +314 -0
- package/src/scripts/condense.ts +36 -2
- package/src/scripts/config/profiles.ts +13 -3
- package/src/scripts/conformance_scan.ts +307 -24
- package/src/scripts/council_availability_hook.ts +188 -0
- package/src/scripts/council_cli.ts +126 -7
- package/src/scripts/generate_settings_reference.ts +232 -0
- package/src/scripts/hook_manifest.yaml +155 -33
- package/src/scripts/hooks/block_no_verify.ts +95 -3
- package/src/scripts/hooks/block_unauthorized_git.ts +217 -2
- package/src/scripts/hooks/concern_registry.ts +12 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +450 -0
- package/src/scripts/hooks/end_review_nudge_hook.ts +726 -0
- package/src/scripts/hooks/orchestration_record_hook.ts +342 -0
- package/src/scripts/install.ts +151 -0
- package/src/scripts/language_mirror_hook.ts +49 -6
- package/src/scripts/measure_scope_dedup.ts +19 -13
- package/src/scripts/onboarding_gate_hook.ts +40 -1
- package/src/scripts/orchestration_backfill.ts +354 -0
- package/src/scripts/orchestration_record.ts +4 -1
- package/src/scripts/preamble_byte_census.ts +9 -20
- package/src/scripts/release.ts +142 -36
- package/src/scripts/report_carrier_divergence.ts +364 -0
- package/src/scripts/report_skill_activation.ts +257 -0
- package/src/scripts/report_skill_obligation_violations.ts +579 -0
- package/src/scripts/routing_doctor.ts +77 -6
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/self_repair_cli.ts +240 -0
- package/src/scripts/self_repair_hook.ts +241 -0
- package/src/scripts/session_canary_hook.ts +35 -3
- package/src/scripts/session_register_hook.ts +288 -0
- package/src/scripts/sessions_cli.ts +140 -0
- package/src/scripts/validate_frontmatter.ts +68 -0
- package/src/server/io/yamlIO.ts +87 -0
- package/src/shared/settingsCarveOut.ts +143 -0
- package/src/shared/settingsSurface.ts +7 -1
|
@@ -63,6 +63,8 @@ import { format_install_hints } from './ai_council/cli_hints.js';
|
|
|
63
63
|
import {
|
|
64
64
|
type AdvisorConfig,
|
|
65
65
|
type CouncilConfig,
|
|
66
|
+
COUNCIL_CONFIG_ENV,
|
|
67
|
+
COUNCIL_CONFIG_USER_GLOBAL_REL,
|
|
66
68
|
CouncilConfigError,
|
|
67
69
|
load_council_config,
|
|
68
70
|
resolve_api_key,
|
|
@@ -558,9 +560,22 @@ function build_members(settings: Dict, opts: BuildMembersOptions = {}): External
|
|
|
558
560
|
|
|
559
561
|
const ai = _isDict(settings) ? ((settings['ai_council'] as Dict) || {}) : {};
|
|
560
562
|
if (!_pyBool(ai['enabled'])) {
|
|
563
|
+
// The file this message names is load-bearing, and it named the wrong one
|
|
564
|
+
// for months. Measured across 10 sessions in one consumer project: the
|
|
565
|
+
// agent reasoned from `.agent-settings.yml` six times, concluded no
|
|
566
|
+
// council existed, and substituted a weaker path — and one session
|
|
567
|
+
// "fixed" it by COPYING the user-global config into the project tree,
|
|
568
|
+
// because this message told it that was where the switch lived. An error
|
|
569
|
+
// from the authoritative tool is the strongest signal in the room; when
|
|
570
|
+
// it points at the wrong file it does not merely fail to help, it
|
|
571
|
+
// manufactures the wrong belief. Name the real path (ADR-104: always
|
|
572
|
+
// user-global, never project-local) and name the verb that reports it.
|
|
561
573
|
throw new CouncilDisabledError(
|
|
562
|
-
|
|
563
|
-
'flip it on before invoking
|
|
574
|
+
`enabled is false in the council config (${COUNCIL_CONFIG_USER_GLOBAL_REL} ` +
|
|
575
|
+
'under the user-global agent-config root) — flip it on before invoking ' +
|
|
576
|
+
'council:* commands. This config is NEVER project-local (ADR-104), so do ' +
|
|
577
|
+
'not look for it, or create it, in the project tree. ' +
|
|
578
|
+
'`agent-config council:status` prints the resolved path.',
|
|
564
579
|
);
|
|
565
580
|
}
|
|
566
581
|
const members_cfg = (ai['members'] as Dict) || {};
|
|
@@ -608,7 +623,8 @@ function build_members(settings: Dict, opts: BuildMembersOptions = {}): External
|
|
|
608
623
|
if (name in siblings) {
|
|
609
624
|
throw new CouncilDisabledError(
|
|
610
625
|
`--siblings targets member ${_pyReprStr(name)} but it is not ` +
|
|
611
|
-
`enabled in
|
|
626
|
+
`enabled in the council config (members.${name}.enabled in ` +
|
|
627
|
+
`${COUNCIL_CONFIG_USER_GLOBAL_REL} under the user-global root).`,
|
|
612
628
|
);
|
|
613
629
|
}
|
|
614
630
|
continue;
|
|
@@ -714,8 +730,10 @@ function build_members(settings: Dict, opts: BuildMembersOptions = {}): External
|
|
|
714
730
|
);
|
|
715
731
|
}
|
|
716
732
|
throw new CouncilDisabledError(
|
|
717
|
-
'no council member has `enabled: true` — enable at least one
|
|
718
|
-
|
|
733
|
+
'no council member has `enabled: true` — enable at least one under ' +
|
|
734
|
+
`members.* in ${COUNCIL_CONFIG_USER_GLOBAL_REL} (user-global root; ` +
|
|
735
|
+
'never the project tree, ADR-104). `agent-config council:status` ' +
|
|
736
|
+
'prints the resolved path.',
|
|
719
737
|
);
|
|
720
738
|
}
|
|
721
739
|
return members;
|
|
@@ -1855,6 +1873,95 @@ function _emit_shadow_slo_banner(): void {
|
|
|
1855
1873
|
}
|
|
1856
1874
|
}
|
|
1857
1875
|
|
|
1876
|
+
/**
|
|
1877
|
+
* `council:status` — answer "is a council configured, and from where" without
|
|
1878
|
+
* spending anything, so no caller has to infer it from a filename.
|
|
1879
|
+
*
|
|
1880
|
+
* WHY THIS EXISTS. Measured 2026-08-08: an agent working in a consumer project
|
|
1881
|
+
* announced "Kein Council konfiguriert (keine `.agent-settings.yml`)" and
|
|
1882
|
+
* substituted a weaker subagent fan-out. The council was configured the whole
|
|
1883
|
+
* time, user-globally. The inference was wrong twice over — the council config
|
|
1884
|
+
* has not lived in `.agent-settings.yml` since the Phase-0 migration, and per
|
|
1885
|
+
* ADR-104 the project tree is **never** searched, so the presence or absence of
|
|
1886
|
+
* any project file says nothing at all about council availability.
|
|
1887
|
+
*
|
|
1888
|
+
* The guidance was not missing: `/council default` states this emphatically in
|
|
1889
|
+
* four places. But a command file only loads when the command is invoked, and
|
|
1890
|
+
* the agent was deciding *whether a capability existed* — a question it reached
|
|
1891
|
+
* before invoking anything. The always-loaded layer says "when the council is
|
|
1892
|
+
* enabled" and never says how to find out.
|
|
1893
|
+
*
|
|
1894
|
+
* So the fix is not more prose. It is a check that costs nothing to run and
|
|
1895
|
+
* leaves nothing to infer. Exit is always 0 — this reports a state, it does not
|
|
1896
|
+
* gate — and the verdict line is machine-greppable in both directions.
|
|
1897
|
+
*/
|
|
1898
|
+
export function cmd_status(args: Args, opts: { env?: Record<string, string | undefined> } = {}): number {
|
|
1899
|
+
const env = opts.env ?? process.env;
|
|
1900
|
+
const override = env[COUNCIL_CONFIG_ENV];
|
|
1901
|
+
const path_ = resolve_config_path(REPO_ROOT, { env: env as never });
|
|
1902
|
+
const exists = fs.existsSync(String(path_));
|
|
1903
|
+
const provenance = override ? `${COUNCIL_CONFIG_ENV} override` : 'user-global';
|
|
1904
|
+
|
|
1905
|
+
let cfg: CouncilConfig | null = null;
|
|
1906
|
+
let parse_error: string | null = null;
|
|
1907
|
+
if (exists) {
|
|
1908
|
+
try {
|
|
1909
|
+
cfg = load_council_config(path_);
|
|
1910
|
+
} catch (exc) {
|
|
1911
|
+
parse_error = exc instanceof Error ? exc.message : String(exc);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
const enabledMembers = cfg === null ? [] : [...cfg.members.entries()].filter(([, m]) => m.enabled);
|
|
1916
|
+
// "Configured" deliberately means: a readable file whose `enabled` is true and
|
|
1917
|
+
// which has at least one enabled member. A file that parses but enables
|
|
1918
|
+
// nothing is the case a caller most needs told apart from a missing file,
|
|
1919
|
+
// because only one of the two is fixed by writing a config.
|
|
1920
|
+
const configured = cfg !== null && cfg.enabled && enabledMembers.length > 0;
|
|
1921
|
+
|
|
1922
|
+
if (_getattr(args, 'json', false)) {
|
|
1923
|
+
_stdout(
|
|
1924
|
+
`${JSON.stringify({
|
|
1925
|
+
configured,
|
|
1926
|
+
path: String(path_),
|
|
1927
|
+
exists,
|
|
1928
|
+
provenance,
|
|
1929
|
+
enabled: cfg?.enabled ?? null,
|
|
1930
|
+
members_total: cfg === null ? null : cfg.members.size,
|
|
1931
|
+
members_enabled: cfg === null ? null : enabledMembers.length,
|
|
1932
|
+
member_names: enabledMembers.map(([n]) => n),
|
|
1933
|
+
parse_error,
|
|
1934
|
+
project_tree_consulted: false,
|
|
1935
|
+
})}\n`,
|
|
1936
|
+
);
|
|
1937
|
+
return 0;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
_stdout(`council:status · ${configured ? 'CONFIGURED' : 'NOT CONFIGURED'}\n`);
|
|
1941
|
+
_stdout(` config path ${String(path_)}\n`);
|
|
1942
|
+
_stdout(` resolved by ${provenance}\n`);
|
|
1943
|
+
_stdout(` file exists ${exists ? 'yes' : 'no'}\n`);
|
|
1944
|
+
if (parse_error !== null) {
|
|
1945
|
+
_stdout(` parse error ${parse_error}\n`);
|
|
1946
|
+
}
|
|
1947
|
+
if (cfg !== null) {
|
|
1948
|
+
_stdout(` enabled ${cfg.enabled ? 'yes' : 'no'}\n`);
|
|
1949
|
+
_stdout(` members ${enabledMembers.length} enabled of ${cfg.members.size}\n`);
|
|
1950
|
+
if (enabledMembers.length > 0) {
|
|
1951
|
+
_stdout(` ${enabledMembers.map(([n]) => n).join(', ')}\n`);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
_stdout('\n');
|
|
1955
|
+
_stdout(' The project tree is NEVER consulted (ADR-104). No project file —\n');
|
|
1956
|
+
_stdout(' `.agent-settings.yml` included — indicates council availability in\n');
|
|
1957
|
+
_stdout(' either direction. Do not infer it from one; run this instead.\n');
|
|
1958
|
+
if (!configured) {
|
|
1959
|
+
_stdout(`\n To configure: write ${COUNCIL_CONFIG_USER_GLOBAL_REL} under the user-global\n`);
|
|
1960
|
+
_stdout(' agent-config root, with `enabled: true` and at least one enabled member.\n');
|
|
1961
|
+
}
|
|
1962
|
+
return 0;
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1858
1965
|
function _apply_solo_dispatch(members: ExternalAIClient[]): [ExternalAIClient[], string | null] {
|
|
1859
1966
|
let cfg: CouncilConfig;
|
|
1860
1967
|
try {
|
|
@@ -2826,13 +2933,15 @@ interface Args {
|
|
|
2826
2933
|
// shadow-report
|
|
2827
2934
|
log: string | null;
|
|
2828
2935
|
window_days: number;
|
|
2936
|
+
// status
|
|
2937
|
+
json: boolean;
|
|
2829
2938
|
}
|
|
2830
2939
|
|
|
2831
|
-
const _SUBCOMMANDS = ['estimate', 'run', 'debate', 'render', 'replay', 'quota', 'shadow-report'];
|
|
2940
|
+
const _SUBCOMMANDS = ['estimate', 'run', 'debate', 'render', 'replay', 'quota', 'shadow-report', 'status'];
|
|
2832
2941
|
|
|
2833
2942
|
const _TOP_USAGE =
|
|
2834
2943
|
`usage: ${_PROG} [-h]\n` +
|
|
2835
|
-
` {estimate,run,debate,render,replay,quota,shadow-report}\n` +
|
|
2944
|
+
` {estimate,run,debate,render,replay,quota,shadow-report,status}\n` +
|
|
2836
2945
|
` ...\n`;
|
|
2837
2946
|
|
|
2838
2947
|
function _topError(message: string): never {
|
|
@@ -2886,6 +2995,7 @@ function _defaultArgs(): Args {
|
|
|
2886
2995
|
reset: null,
|
|
2887
2996
|
log: null,
|
|
2888
2997
|
window_days: 7,
|
|
2998
|
+
json: false,
|
|
2889
2999
|
};
|
|
2890
3000
|
}
|
|
2891
3001
|
|
|
@@ -3009,6 +3119,12 @@ function _specsFor(cmd: string): { positionals: string[]; opts: OptSpec[]; requi
|
|
|
3009
3119
|
],
|
|
3010
3120
|
requiredOpts: [],
|
|
3011
3121
|
};
|
|
3122
|
+
case 'status':
|
|
3123
|
+
return {
|
|
3124
|
+
positionals: [],
|
|
3125
|
+
opts: [{ flag: '--json', takesValue: false, apply: (o) => (o.json = true) }],
|
|
3126
|
+
requiredOpts: [],
|
|
3127
|
+
};
|
|
3012
3128
|
default:
|
|
3013
3129
|
return { positionals: [], opts: [], requiredOpts: [] };
|
|
3014
3130
|
}
|
|
@@ -3213,6 +3329,9 @@ function main(argv: string[] | null = null): number {
|
|
|
3213
3329
|
if (args.cmd === 'shadow-report') {
|
|
3214
3330
|
return cmd_shadow_report(args);
|
|
3215
3331
|
}
|
|
3332
|
+
if (args.cmd === 'status') {
|
|
3333
|
+
return cmd_status(args);
|
|
3334
|
+
}
|
|
3216
3335
|
} catch (exc) {
|
|
3217
3336
|
if (exc instanceof CouncilDisabledError) {
|
|
3218
3337
|
_stderr(`❌ council:${args.cmd}: ${exc.message}\n`);
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Generate the human-readable settings reference page.
|
|
4
|
+
*
|
|
5
|
+
* `road-to-zero-ceremony-settings` Phase 3 step 3. The user's global settings
|
|
6
|
+
* file is becoming sparse, so the long-form explanation that used to ride along
|
|
7
|
+
* as template comments has to survive somewhere the user can still read it.
|
|
8
|
+
*
|
|
9
|
+
* The page is derived from TWO sources that already exist, and from nothing
|
|
10
|
+
* else — the point is that there is no third surface to keep in sync:
|
|
11
|
+
*
|
|
12
|
+
* 1. the zod settings schema (`src/server/schemas/settings.ts`), flattened
|
|
13
|
+
* through the same `flattenSurface` the installer uses for its upgrade
|
|
14
|
+
* delta, so type / default / enum / description come from one place;
|
|
15
|
+
* 2. the A/B/C class table (`docs/contracts/settings-classes.md`), parsed by
|
|
16
|
+
* the same `parseSettingsClassRows` the lint and the writer use, so the
|
|
17
|
+
* page cannot claim a class the fence does not enforce.
|
|
18
|
+
*
|
|
19
|
+
* The package VERSION is deliberately absent from the output. Rendering it
|
|
20
|
+
* would make this page drift on every release bump and red `--check` for a
|
|
21
|
+
* change nobody made — the page describes the schema's shape, not the release
|
|
22
|
+
* that shipped it.
|
|
23
|
+
*
|
|
24
|
+
* Produces: docs/settings-reference.md
|
|
25
|
+
*
|
|
26
|
+
* Modes:
|
|
27
|
+
* --check Regenerate to memory and diff against the committed page.
|
|
28
|
+
* (default) Regenerate in place; exit 0 on success.
|
|
29
|
+
*
|
|
30
|
+
* Exit codes: 0 = ok, 1 = drift (--check), 2 = bad usage, 3 = internal.
|
|
31
|
+
*/
|
|
32
|
+
import * as fs from 'node:fs';
|
|
33
|
+
import * as path from 'node:path';
|
|
34
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
35
|
+
|
|
36
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
37
|
+
|
|
38
|
+
import { settingsSchema } from '../server/schemas/settings.js';
|
|
39
|
+
import {
|
|
40
|
+
buildSettingsClassIndex,
|
|
41
|
+
parseSettingsClassRows,
|
|
42
|
+
type SettingsClass,
|
|
43
|
+
} from '../shared/settingsClasses.js';
|
|
44
|
+
import { flattenSurface, type SurfaceEntry } from '../shared/settingsSurface.js';
|
|
45
|
+
|
|
46
|
+
const _HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
47
|
+
export const ROOT = path.resolve(_HERE, '..', '..');
|
|
48
|
+
|
|
49
|
+
export const CONTRACT_REL = path.join('docs', 'contracts', 'settings-classes.md');
|
|
50
|
+
export const OUTPUT_REL = path.join('docs', 'settings-reference.md');
|
|
51
|
+
|
|
52
|
+
/** What each class means for the reader. Mirrors the contract's own table. */
|
|
53
|
+
const CLASS_BLURB: Record<SettingsClass, string> = {
|
|
54
|
+
A: 'preference — the agent may set it; you are never asked',
|
|
55
|
+
B: 'consent — the agent asks once, then persists your answer',
|
|
56
|
+
C: 'guarded — only you (GUI or hand-edit) may change it',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** A key with no row in the contract. The lint fails on these separately. */
|
|
60
|
+
const UNCLASSIFIED = '—';
|
|
61
|
+
|
|
62
|
+
export interface ReferenceRow {
|
|
63
|
+
key: string;
|
|
64
|
+
cls: SettingsClass | null;
|
|
65
|
+
entry: SurfaceEntry;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Group by top-level segment so the page reads like the template did.
|
|
70
|
+
* Leaves with no dot (e.g. `discipline_profile`) group under `(root)`.
|
|
71
|
+
*/
|
|
72
|
+
export function groupRows(rows: readonly ReferenceRow[]): Map<string, ReferenceRow[]> {
|
|
73
|
+
const groups = new Map<string, ReferenceRow[]>();
|
|
74
|
+
for (const row of rows) {
|
|
75
|
+
const dot = row.key.indexOf('.');
|
|
76
|
+
const section = dot === -1 ? '(root)' : row.key.slice(0, dot);
|
|
77
|
+
const bucket = groups.get(section);
|
|
78
|
+
if (bucket === undefined) groups.set(section, [row]);
|
|
79
|
+
else bucket.push(row);
|
|
80
|
+
}
|
|
81
|
+
return groups;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Render a value for a markdown table cell — never let it break the row. */
|
|
85
|
+
export function renderCell(value: unknown): string {
|
|
86
|
+
if (value === undefined) return '';
|
|
87
|
+
const json = JSON.stringify(value);
|
|
88
|
+
if (json === undefined) return '';
|
|
89
|
+
return `\`${json.replace(/\|/g, '\\|')}\``;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Descriptions are free prose; pipes and newlines would break the table. */
|
|
93
|
+
export function renderProse(value: string | undefined): string {
|
|
94
|
+
if (value === undefined || value === '') return '';
|
|
95
|
+
return value.replace(/\s+/g, ' ').replace(/\|/g, '\\|').trim();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function buildRows(contractMarkdown: string): ReferenceRow[] {
|
|
99
|
+
const jsonSchema = zodToJsonSchema(settingsSchema, {
|
|
100
|
+
name: 'AgentSettings',
|
|
101
|
+
$refStrategy: 'none',
|
|
102
|
+
target: 'jsonSchema7',
|
|
103
|
+
}) as Parameters<typeof flattenSurface>[0];
|
|
104
|
+
// The version is a required parameter of the shared flattener and is
|
|
105
|
+
// discarded here on purpose — see the module header.
|
|
106
|
+
const surface = flattenSurface(jsonSchema, 'unversioned');
|
|
107
|
+
const classIndex = buildSettingsClassIndex(parseSettingsClassRows(contractMarkdown));
|
|
108
|
+
|
|
109
|
+
return Object.keys(surface.entries)
|
|
110
|
+
.sort()
|
|
111
|
+
.map((key) => ({
|
|
112
|
+
key,
|
|
113
|
+
cls: classIndex.get(key) ?? null,
|
|
114
|
+
entry: surface.entries[key] as SurfaceEntry,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function renderPage(rows: readonly ReferenceRow[]): string {
|
|
119
|
+
const out: string[] = [];
|
|
120
|
+
out.push('# Settings reference — every key, its class, and its default');
|
|
121
|
+
out.push('');
|
|
122
|
+
out.push('> **Generated** by `src/scripts/generate_settings_reference.ts` — do NOT');
|
|
123
|
+
out.push('> hand-edit. Derived from the zod settings schema plus the A/B/C class');
|
|
124
|
+
out.push('> table in [`settings-classes`](contracts/settings-classes.md).');
|
|
125
|
+
out.push('> Drift-checked in CI (`--check`).');
|
|
126
|
+
out.push('');
|
|
127
|
+
out.push('Your global settings file is **sparse**: it records the decisions you');
|
|
128
|
+
out.push('actually made, not every key that exists. A key absent from the file');
|
|
129
|
+
out.push('resolves to the default listed here. This page is where the long-form');
|
|
130
|
+
out.push('explanation lives now that the file no longer carries it as comments.');
|
|
131
|
+
out.push('');
|
|
132
|
+
out.push('**Class** answers one question — *who may write this key.*');
|
|
133
|
+
out.push('');
|
|
134
|
+
for (const cls of ['A', 'B', 'C'] as const) {
|
|
135
|
+
out.push(`- **${cls}** — ${CLASS_BLURB[cls]}`);
|
|
136
|
+
}
|
|
137
|
+
out.push('');
|
|
138
|
+
|
|
139
|
+
const groups = groupRows(rows);
|
|
140
|
+
for (const section of [...groups.keys()].sort()) {
|
|
141
|
+
const bucket = groups.get(section) as ReferenceRow[];
|
|
142
|
+
out.push(`## ${section}`);
|
|
143
|
+
out.push('');
|
|
144
|
+
out.push('| Key | Class | Type | Default | Allowed values | What it does |');
|
|
145
|
+
out.push('|---|---|---|---|---|---|');
|
|
146
|
+
for (const row of bucket) {
|
|
147
|
+
const allowed = row.entry.enum === undefined
|
|
148
|
+
? ''
|
|
149
|
+
: row.entry.enum.map((v) => `\`${String(v)}\``).join(' · ');
|
|
150
|
+
out.push(
|
|
151
|
+
`| \`${row.key}\` | ${row.cls ?? UNCLASSIFIED} | ${row.entry.type} | `
|
|
152
|
+
+ `${renderCell(row.entry.default)} | ${allowed} | ${renderProse(row.entry.description)} |`,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
out.push('');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
out.push('## See also');
|
|
159
|
+
out.push('');
|
|
160
|
+
out.push('- [`settings-classes`](contracts/settings-classes.md) — the class contract this page reads.');
|
|
161
|
+
out.push('- [`settings-api`](contracts/settings-api.md) — the read/write surface.');
|
|
162
|
+
out.push('');
|
|
163
|
+
return out.join('\n');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function generate(root: string): string {
|
|
167
|
+
const contract = fs.readFileSync(path.join(root, CONTRACT_REL), 'utf-8');
|
|
168
|
+
return renderPage(buildRows(contract));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
interface Args {
|
|
172
|
+
check: boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function parse_args(argv: readonly string[]): Args {
|
|
176
|
+
const args: Args = { check: false };
|
|
177
|
+
for (const a of argv) {
|
|
178
|
+
if (a === '--check') {
|
|
179
|
+
args.check = true;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
process.stderr.write(`generate_settings_reference: unknown argument: ${a}\n`);
|
|
183
|
+
process.exit(2);
|
|
184
|
+
}
|
|
185
|
+
return args;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function main(argv?: readonly string[]): number {
|
|
189
|
+
const args = parse_args(argv ?? process.argv.slice(2));
|
|
190
|
+
const out_path = path.join(ROOT, OUTPUT_REL);
|
|
191
|
+
|
|
192
|
+
let rendered: string;
|
|
193
|
+
try {
|
|
194
|
+
rendered = generate(ROOT);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
process.stderr.write(`generate_settings_reference: ${String(err)}\n`);
|
|
197
|
+
return 3;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (args.check) {
|
|
201
|
+
let committed: string | null = null;
|
|
202
|
+
try {
|
|
203
|
+
committed = fs.readFileSync(out_path, 'utf-8');
|
|
204
|
+
} catch {
|
|
205
|
+
committed = null;
|
|
206
|
+
}
|
|
207
|
+
if (committed !== rendered) {
|
|
208
|
+
process.stderr.write(
|
|
209
|
+
`❌ ${OUTPUT_REL} is out of date.\n`
|
|
210
|
+
+ ' Regenerate: ./scripts-run src/scripts/generate_settings_reference\n',
|
|
211
|
+
);
|
|
212
|
+
return 1;
|
|
213
|
+
}
|
|
214
|
+
process.stdout.write(`✅ ${OUTPUT_REL} is up to date.\n`);
|
|
215
|
+
return 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
fs.mkdirSync(path.dirname(out_path), { recursive: true });
|
|
219
|
+
fs.writeFileSync(out_path, rendered, 'utf-8');
|
|
220
|
+
process.stdout.write(`✅ wrote ${OUTPUT_REL}\n`);
|
|
221
|
+
return 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function _invoked_directly(): boolean {
|
|
225
|
+
if (process.argv[1] === undefined) return false;
|
|
226
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
227
|
+
return import.meta.url === argvUrl;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (_invoked_directly()) {
|
|
231
|
+
process.exitCode = main();
|
|
232
|
+
}
|