@event4u/agent-config 14.6.0 → 14.7.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.
Files changed (188) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +260 -7
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/analyze/inbox.md +264 -10
  5. package/dist/agent-src/commands/analyze.md +1 -1
  6. package/dist/agent-src/commands/roadmap/process-full.md +116 -30
  7. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +31 -0
  8. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +135 -104
  9. package/dist/agent-src/rules/context-hygiene.md +2 -0
  10. package/dist/agent-src/rules/decision-revisit-gate.md +3 -0
  11. package/dist/agent-src/rules/fix-what-you-see.md +108 -0
  12. package/dist/agent-src/rules/no-roadmap-references.md +0 -5
  13. package/dist/agent-src/rules/recurring-criticism.md +110 -0
  14. package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
  15. package/dist/agent-src/rules/rule-type-governance.md +0 -2
  16. package/dist/agent-src/rules/self-repair-loop.md +17 -0
  17. package/dist/agent-src/rules/skill-quality.md +0 -2
  18. package/dist/agent-src/rules/source-confidentiality.md +37 -7
  19. package/dist/agent-src/scripts/archival_sweep.ts +117 -0
  20. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
  21. package/dist/agent-src/scripts/gate_budget.ts +282 -0
  22. package/dist/agent-src/scripts/gate_execute.ts +72 -31
  23. package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
  24. package/dist/agent-src/scripts/update_roadmap_progress.ts +251 -7
  25. package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
  26. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
  27. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
  28. package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
  29. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
  30. package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
  31. package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
  32. package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
  33. package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
  34. package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
  35. package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
  36. package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
  37. package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
  38. package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
  39. package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
  40. package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
  41. package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
  42. package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
  43. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  44. package/dist/agent-src/templates/roadmaps.md +45 -2
  45. package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
  46. package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
  47. package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
  48. package/dist/cli/registry.js +1 -1
  49. package/dist/cli/registry.js.map +1 -1
  50. package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
  51. package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-4VR4ORQ6.js} +10 -7
  52. package/dist/cli-delegate/chunk-6EOCNQAM.js +402 -0
  53. package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-74E3TKWV.js} +381 -280
  54. package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-7F3VYSM2.js} +4 -4
  55. package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
  56. package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
  57. package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-GJ5BVHXM.js} +72 -165
  58. package/dist/cli-delegate/{chunk-P6LQDIWK.js → chunk-JZ4NR2TW.js} +338 -0
  59. package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
  60. package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
  61. package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
  62. package/dist/cli-delegate/cmd_conformance.js +459 -709
  63. package/dist/cli-delegate/cmd_doctor.js +6 -6
  64. package/dist/cli-delegate/cmd_explain.js +1 -1
  65. package/dist/cli-delegate/cmd_export.js +7 -6
  66. package/dist/cli-delegate/cmd_handoff.js +6 -6
  67. package/dist/cli-delegate/cmd_packs_active.js +1 -1
  68. package/dist/cli-delegate/cmd_preflight.js +2 -2
  69. package/dist/cli-delegate/cmd_prune.js +7 -6
  70. package/dist/cli-delegate/cmd_session_recycle.js +840 -30
  71. package/dist/cli-delegate/cmd_settings_migrate.js +7 -6
  72. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  73. package/dist/cli-delegate/cmd_sync.js +7 -6
  74. package/dist/cli-delegate/cmd_uninstall.js +9 -7
  75. package/dist/cli-delegate/cmd_update.js +1 -1
  76. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  77. package/dist/cli-delegate/cmd_validate.js +7 -6
  78. package/dist/discovery/deprecation-report.md +1 -1
  79. package/dist/discovery/discovery-manifest.json +68 -25
  80. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  81. package/dist/discovery/discovery-manifest.summary.md +4 -4
  82. package/dist/discovery/dormancy-report.md +1 -1
  83. package/dist/discovery/orphan-report.md +1 -1
  84. package/dist/discovery/packs.json +10 -8
  85. package/dist/discovery/trust-report.md +3 -3
  86. package/dist/discovery/workspaces.json +8 -6
  87. package/dist/hooks/dispatch.js +2901 -2053
  88. package/dist/install/claudePathsPlan.js +187 -0
  89. package/dist/install/claudePathsPlan.js.map +1 -0
  90. package/dist/install/hostLayerFingerprint.js +136 -0
  91. package/dist/install/hostLayerFingerprint.js.map +1 -0
  92. package/dist/install/install.mjs +553 -425
  93. package/dist/install/partitionEligibility.js +276 -0
  94. package/dist/install/partitionEligibility.js.map +1 -0
  95. package/dist/mcp/registry-manifest.json +3 -3
  96. package/dist/mcp/server.json +2 -2
  97. package/dist/mcp/server.mjs +1744 -1191
  98. package/dist/router.json +1 -1
  99. package/dist/scripts/_lib/agent_src.js +41 -0
  100. package/dist/scripts/_lib/agent_src.js.map +1 -1
  101. package/dist/scripts/_lib/install_layout.js +83 -0
  102. package/dist/scripts/_lib/install_layout.js.map +1 -0
  103. package/dist/scripts/_lib/installed_lock.js +444 -0
  104. package/dist/scripts/_lib/installed_lock.js.map +1 -0
  105. package/dist/scripts/condense.js +13 -164
  106. package/dist/scripts/condense.js.map +1 -1
  107. package/dist/server/schemas/settings.js +4 -0
  108. package/dist/server/schemas/settings.js.map +1 -1
  109. package/docs/contracts/settings-classes.md +12 -6
  110. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
  111. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
  112. package/docs/guidelines/agent-infra/memory-access.md +17 -0
  113. package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
  114. package/package.json +1 -1
  115. package/src/agent-src/scripts/archival_sweep.ts +117 -0
  116. package/src/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
  117. package/src/agent-src/scripts/gate_budget.ts +282 -0
  118. package/src/agent-src/scripts/gate_execute.ts +72 -31
  119. package/src/agent-src/scripts/roadmap_gates.ts +74 -3
  120. package/src/agent-src/scripts/update_roadmap_progress.ts +251 -7
  121. package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
  122. package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
  123. package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
  124. package/src/config/agent-settings.template.yml +27 -2
  125. package/src/config/ci-local-parity.yml +18 -0
  126. package/src/config/estate-count-budget.json +339 -3
  127. package/src/config/gate-violation-baselines.json +41 -41
  128. package/src/config/rule-activation-census.json +14 -6
  129. package/src/config/rule-stub-ceilings.json +19 -6
  130. package/src/install/claudePathsPlan.ts +196 -0
  131. package/src/install/hostLayerFingerprint.ts +145 -0
  132. package/src/install/partitionEligibility.ts +325 -0
  133. package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
  134. package/src/scripts/_dispatch.bash +6 -1
  135. package/src/scripts/_lib/ac_heading.ts +30 -0
  136. package/src/scripts/_lib/agent_src.ts +42 -0
  137. package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
  138. package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
  139. package/src/scripts/_lib/envelope_grounding.ts +38 -8
  140. package/src/scripts/_lib/installed_lock.ts +50 -5
  141. package/src/scripts/_lib/md_section.ts +129 -0
  142. package/src/scripts/_lib/scope_guard.sh +26 -3
  143. package/src/scripts/_lib/self_repair.ts +19 -0
  144. package/src/scripts/_lib/self_repair_class_b.ts +171 -0
  145. package/src/scripts/ai_council/cli_help.ts +55 -0
  146. package/src/scripts/before_complete_hook.ts +153 -28
  147. package/src/scripts/bench_ab_v2_complexity.ts +27 -7
  148. package/src/scripts/check_references.ts +60 -0
  149. package/src/scripts/check_release_published.ts +32 -11
  150. package/src/scripts/check_single_delivery.ts +59 -15
  151. package/src/scripts/ci_settle.ts +170 -0
  152. package/src/scripts/condense.ts +20 -170
  153. package/src/scripts/council_cli.ts +3 -3
  154. package/src/scripts/dispatch_r2_reviewer.ts +6 -14
  155. package/src/scripts/hook_manifest.json +1 -1
  156. package/src/scripts/hook_manifest.yaml +77 -14
  157. package/src/scripts/hooks/block_no_verify.ts +61 -10
  158. package/src/scripts/hooks/block_unauthorized_git.ts +1 -1
  159. package/src/scripts/hooks/concern_registry.ts +4 -0
  160. package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
  161. package/src/scripts/hooks/run_continuation_hook.ts +8 -5
  162. package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
  163. package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
  164. package/src/scripts/hooks/state_io.ts +782 -20
  165. package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
  166. package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
  167. package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
  168. package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
  169. package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
  170. package/src/scripts/install.ts +16 -11
  171. package/src/scripts/language_mirror_hook.ts +561 -25
  172. package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
  173. package/src/scripts/lint_plan_risk_register.ts +4 -3
  174. package/src/scripts/lint_skill_router_head.ts +4 -4
  175. package/src/scripts/mcp_server/tools.ts +2 -2
  176. package/src/scripts/new_roadmap.ts +136 -0
  177. package/src/scripts/pack_mcp_content.ts +20 -5
  178. package/src/scripts/release.ts +37 -38
  179. package/src/scripts/report_layer_overlap.ts +6 -0
  180. package/src/scripts/self_repair_hook.ts +37 -5
  181. package/src/scripts/session_register_hook.ts +11 -0
  182. package/src/scripts/skill_usage_collect.ts +11 -1
  183. package/src/scripts/skill_usage_report.ts +278 -8
  184. package/src/scripts/sync_pr_branch.ts +7 -0
  185. package/src/server/schemas/settings.ts +8 -0
  186. package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
  187. package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
  188. /package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
@@ -0,0 +1,320 @@
1
+ # ai-council — advanced modes
2
+
3
+ > Mode body of the [`ai-council`](../SKILL.md) skill (router-head retrofit,
4
+ > 2026-08-20). Content moved VERBATIM from SKILL.md — load this file when the
5
+ > mode table in SKILL.md routes here.
6
+
7
+ ## Multi-round debate (`rounds:N`)
8
+
9
+ `consult(..., rounds=N)` enables 2-3 round critique loops. Round 1
10
+ runs the standard single-round flow. Round 2+ rebuilds the user
11
+ prompt as `<original artefact> + <prior round, anonymised>` so each
12
+ member can refine, agree, or push back on the previous critique
13
+ without seeing which provider produced which point.
14
+
15
+ The default round count comes from `defaults.min_rounds` in
16
+ `~/.event4u/agent-config/settings/.ai-council.yml` (default `2` so members critique each other
17
+ at least once before convergence). The host agent does **not** ask
18
+ "how many rounds?" when the requested count is `<= min_rounds` —
19
+ the settings owner already made that decision. Ask only when a
20
+ genuinely complex artefact justifies more depth than the default.
21
+
22
+ ### Deep-reasoning tier (`council_depth: deep`)
23
+
24
+ Architecture review, refactoring proposals, and bug-diagnosis runs
25
+ benefit from an extra critique round. The deep tier is opt-in per
26
+ artefact:
27
+
28
+ 1. The consuming **rule, skill, or command** declares
29
+ `council_depth: deep` in its frontmatter. The schema accepts
30
+ **only `deep`** — `standard` is the implicit default and is
31
+ rejected by the linter (every frontmatter byte costs context
32
+ window; see `scripts/schemas/{rule,skill,command}.schema.json`).
33
+ To return an artefact to default depth, **delete the key**.
34
+ 2. The **host agent** reads that frontmatter when it dispatches the
35
+ council and passes `--depth deep` to `council_cli`. If multiple
36
+ active artefacts disagree, **deep wins** (max policy).
37
+ 3. The **CLI** floors the round count at
38
+ `max(ai_council.deep_min_rounds, ai_council.min_rounds)` —
39
+ defaults to `3` and `2` respectively. Lowering `deep_min_rounds`
40
+ below `min_rounds` has no effect (defensive max).
41
+
42
+ The CLI itself has no knowledge of frontmatter; the contract is the
43
+ flag. Resolution chain (highest priority first):
44
+
45
+ ```
46
+ --rounds N → explicit, any value (user override)
47
+ --depth deep → max(deep_min_rounds, min_rounds)
48
+ (no flag) → min_rounds (default 2)
49
+ ```
50
+
51
+ | Property | Behaviour |
52
+ |---|---|
53
+ | Default count | `ai_council.min_rounds` (default `2`). Override per-invocation with `rounds:N` (or `--rounds N` to the CLI). |
54
+ | Deep floor | `ai_council.deep_min_rounds` (default `3`). Activated by `council_depth: deep` in artefact frontmatter (host translates to `--depth deep`) or explicit `--depth deep` on the CLI. Floored at `min_rounds`. |
55
+ | Anonymisation | Provider/model identity is stripped. Reviewers are labelled `Reviewer A / B / C…` in input order. |
56
+ | Errored prior responses | Skipped — they reveal nothing useful and can leak provider error formats. |
57
+ | Cost budget | Accumulates across rounds. A round-2 call that breaches the cap fires `on_overrun` exactly like a round-1 breach. |
58
+ | Daily limit | Same — every billable round-2 call records spend in the rolling 24h ledger. |
59
+ | Return value | Final round only. Use `on_round_complete(round_idx, responses)` to capture intermediate rounds for rendering. |
60
+
61
+ > Iron Law: anonymisation is non-negotiable. If you ever need to
62
+ > surface "which model said what" between rounds, that is a different
63
+ > feature — debug-only, off by default, never enabled in user-facing
64
+ > output. The neutrality contract dies the moment a member learns it
65
+ > is talking to Claude vs GPT in round 2.
66
+
67
+ Pre-call estimate must surface the round count: total = `N × single-round cost`. Render inline:
68
+
69
+ ```
70
+ External council call — billable · 2 rounds
71
+ Round 1: artefact only
72
+ Round 2: artefact + anonymised round 1 critiques
73
+
74
+ | member | per-round | × 2 |
75
+ |--------------------|----------:|--------:|
76
+ | anthropic/sonnet | $0.0176 | $0.0352 |
77
+ | openai/gpt-4o | $0.0121 | $0.0242 |
78
+ | **total** | | $0.0594 |
79
+ ```
80
+
81
+ ### Manual-mode parity
82
+
83
+ The orchestrator drives rounds the same way for `api` and `manual`
84
+ transports. One round = one full pass over every enabled member,
85
+ top-to-bottom, then `_augment_for_next_round()` folds the
86
+ anonymised critiques into the round-N+1 user prompt. For manual
87
+ mode this means: emit the round-1 block for member A → user
88
+ pastes A's reply → next member B → user pastes B's reply → host
89
+ agent consolidates round 1 → emit the round-2 block (now carrying
90
+ the anonymised round-1 critiques) for member A → … and so on
91
+ until the configured round count is reached. ManualClient's
92
+ internal "more feedback" follow-up loop (1 / 2 / 3 menu) is
93
+ **inside** a single member's chat thread and is orthogonal to the
94
+ orchestrator-level rounds.
95
+
96
+ ### `/council debate` sub-command (progressive disclosure)
97
+
98
+ `/council debate <artefact> [--rounds N] [--continue-as-debate <session>]`
99
+ runs an **interactive** multi-round critique with a confirmation gate
100
+ between every round so the user can stop the spend at any point.
101
+
102
+ | Property | Behaviour |
103
+ |---|---|
104
+ | Round flow | Same orchestrator as `rounds:N` (`run_debate()`), but each round prints its responses then pauses on a y/n prompt before launching the next round. |
105
+ | Cost gate | After every round the CLI prints `Spent so far: $X · Next round: ~$Y · Cap: $Z`. `n` exits cleanly with partial results; `y` continues. |
106
+ | Hard cap | If the projected next-round cost would breach `max_total_usd`, `run_debate()` raises `DebateCapExceeded` and the CLI exits with the partial transcript. No silent overrun. |
107
+ | `--continue-as-debate` | Seeds round 1 from an existing `/council default` (or analysis lens) session. No round-1 API calls are billed; round 2+ run normally. Member list must match. |
108
+ | Session files | One file per round under `agents/runtime/council/sessions/<slug>/debate-round-NN.md`. |
109
+ | Anonymisation | Identical to `rounds:N`. The continue-as-debate path also anonymises the seeded round-1 responses when building the round-2 prompt. |
110
+
111
+ Use this when the artefact is genuinely contentious and the user
112
+ wants to control depth interactively. For a fire-and-forget
113
+ multi-round run, prefer `consult(..., rounds=N)` or `--rounds N` on
114
+ `/council default`.
115
+
116
+
117
+ ## Karpathy peer-review (opt-in)
118
+
119
+ After the final deliberation round, an optional **anonymous peer-review
120
+ pass** lets each member critique the *other* members' responses for
121
+ blind spots before synthesis. Inspired by Andrej Karpathy's "ask the
122
+ strongest models to review each other anonymously" pattern; see his
123
+ [talks / threads on inter-model critique](https://karpathy.ai/) and the
124
+ internal verdict in
125
+ `agents/runtime/council/sessions/2026-05-14-ai-council-redesign/round-2.md`
126
+ (R2 split: one approve-as-flag, one reject-as-default → opt-in only).
127
+
128
+ Pipeline order when every feature is active:
129
+
130
+ ```
131
+ deliberation rounds → peer-review → consensus-scoring → synthesis
132
+ ```
133
+
134
+ Activation — two equivalent paths:
135
+
136
+ * CLI: `--peer-review` on `council:estimate` or `council:run`.
137
+ * Config: `ai_council.peer_review.enabled: true` in
138
+ `~/.event4u/agent-config/settings/.ai-council.yml`. Default is `false`.
139
+
140
+ Mechanics:
141
+
142
+ 1. The final deliberation round's outputs are anonymised into
143
+ `Response-A`, `Response-B`, … in stable input order. Provider /
144
+ model identity is stripped (Iron-Law neutrality holds); empty or
145
+ errored deliberation responses are skipped.
146
+ 2. Each member receives an N−1 view (its own response filtered out)
147
+ plus the Karpathy prompt: *strongest response*, *weakest blind
148
+ spot*, *what did everyone miss*, *refinement*.
149
+ 3. The N critiques flow back into synthesis through a
150
+ "Peer-Review-Surfaced Blind Spots" addendum on the lens template.
151
+ 4. **Advisor preserve-persona (R4 Q3, hard-coded):** when the
152
+ deliberation was an advisor-mode run (Phase 6), anonymisation
153
+ strips provider identity but **preserves the advisor persona
154
+ label**. Peer-review renders as `Response A (Contrarian)`, never
155
+ `Response A (Anthropic Opus)`. Plain-member runs strip identity
156
+ entirely.
157
+
158
+ Cost — adds exactly N billable calls (one per member) at the same
159
+ per-call cost as a deliberation call. The `council:estimate` table
160
+ surfaces the delta as a `+peer-review: +N calls (~+$X)` row.
161
+
162
+ Needs ≥ 2 distinct deliberation outputs; below that the round is a
163
+ no-op and nothing extra is billed. Self-review is structurally
164
+ impossible — a member never sees its own response.
165
+
166
+ ## Thinking-style advisors (replace-mode)
167
+
168
+ Phase 6 introduces five **advisor personas** that the council can adopt
169
+ in *replace-mode*: an enabled advisor substitutes its bound member's
170
+ plain call with the same provider running the advisor's persona prompt.
171
+ Total call count stays the same as a plain run — only the system prompt
172
+ swaps. Five advisors mirror an external advisor set, each a substantial
173
+ persona file (not a tagline):
174
+
175
+ | Advisor | Default bound member | Focus |
176
+ |---|---|---|
177
+ | **Contrarian** | `anthropic` | strongest counterargument, hidden assumptions |
178
+ | **First-Principles** | `anthropic` | strip metaphor, derive from physics / math / cost |
179
+ | **Expansionist** | `openai` | adjacent opportunities, second-order effects |
180
+ | **Outsider** | `openai` | naive-but-sharp questions, beginner's-mind probes |
181
+ | **Executor** | `anthropic` | what ships this quarter, what blocks delivery |
182
+
183
+ Activation — edit `~/.event4u/agent-config/settings/.ai-council.yml` and flip the advisor's
184
+ `enabled: true`. Optional `model: <name>` overrides the bound member's
185
+ default model. Validation rule: an advisor referencing a disabled
186
+ member fails closed at config load — never silently skipped.
187
+
188
+ ```yaml
189
+ advisors:
190
+ contrarian:
191
+ enabled: true # ← swap anthropic's plain call for contrarian
192
+ member: anthropic
193
+ # model: claude-opus-4 # optional pin
194
+ ```
195
+
196
+ `council:estimate` surfaces every active swap on a dedicated line above
197
+ the cost table:
198
+
199
+ ```
200
+ council:estimate · mode=prompt · members=2 (billable=2)
201
+ advisor: Contrarian on anthropic via claude-sonnet-4-5
202
+ anthropic/claude-sonnet-4-5: ~991 in + 256 out = $0.0068
203
+ openai/gpt-4o: ~208 in + 256 out = $0.0031
204
+ ```
205
+
206
+ Cost-bounded guarantee — replace-mode never adds calls. The advisor
207
+ persona prompt is larger than a plain prompt (~1k extra input tokens
208
+ per swap), so the per-call estimate widens slightly. Output tokens and
209
+ call count are unaffected.
210
+
211
+ Peer-review interaction — when peer-review fires on an advisor-mode
212
+ run, anonymisation **preserves the advisor persona label** while
213
+ stripping provider identity: `Response A (Contrarian)` instead of bare
214
+ `Response A`. See §Karpathy peer-review point 4 for the contract.
215
+
216
+ One-per-provider invariant — two enabled advisors targeting the same
217
+ member is a config error (replace-mode runs exactly one advisor per
218
+ provider; the call plan never doubles up by accident).
219
+
220
+ ## Decision-replay artefact (Phase 9, audit trail)
221
+
222
+ Every session that runs consensus scoring drops a
223
+ `decision-replay.md` next to the saved `responses.json`. Pure
224
+ projection of the consensus block plus the final-round per-member
225
+ texts — **no extra model calls, no extra spend**. Surfaces, per top
226
+ finding: verdict band (Strong/Moderate/Weak), evidence-quality bucket
227
+ (H/M/L), agree/dissent split, and one key argument per member.
228
+
229
+ Two render modes:
230
+
231
+ * **Full** (default) — per-member arguments attributed to
232
+ `provider:model`. Reasoning is traceable, vendor identity is
233
+ visible.
234
+ * **Redacted** — verdict + evidence-quality + counts only. Use for
235
+ surfaces where attributing reasoning to a specific model would leak
236
+ vendor-preference signal.
237
+
238
+ Toggles (config, see `ai-council-config § Decision-replay artefact`):
239
+
240
+ * `ai_council.decision_replay.enabled` — master switch (default
241
+ `true`).
242
+ * `ai_council.decision_replay.include_member_arguments` — flip to
243
+ `false` for redacted-by-default.
244
+ * `ai_council.lenses.<lens>.decision_replay.*` — per-lens override
245
+ beats the global block.
246
+
247
+ CLI:
248
+
249
+ * Written automatically by `council run` whenever the lens triggers
250
+ consensus scoring.
251
+ * `council replay <responses.json>` re-renders from a saved session;
252
+ `--redact-member-arguments` / `--include-member-arguments` flip the
253
+ view independent of config. Useful for sharing a redacted variant
254
+ of an already-paid run.
255
+
256
+ ## Lightweight-QA fast-path (Phase 11)
257
+
258
+ Low-impact questions classified by Phase 10's impact router can route
259
+ to a restricted fast-path instead of the full debate loop. The
260
+ trade-off is explicit: **1 round · ≤2 members · $0.05/answer · 2500
261
+ tokens**. No advisors, no peer-review, no consensus scoring — the goal
262
+ is a quick answer with a transparency marker, not a deliberation.
263
+
264
+ ### Iron Law
265
+
266
+ `high_impact` and `user_required` **never** route to the fast-path,
267
+ regardless of config. Schema validation rejects the override. The
268
+ fast-path only activates when:
269
+
270
+ 1. `ai_council.enabled: true` AND
271
+ 2. `decision_resolution.low_impact.mode: council` AND
272
+ 3. At least one member has `participate_low_impact: true` (default
273
+ `false` — explicit opt-in per member).
274
+
275
+ Default route for `low_impact` is **`agent`** — nothing reaches the
276
+ council without an explicit two-knob opt-in (flip the class to
277
+ `council` *and* mark at least one member `participate_low_impact: true`).
278
+ See [`ai-council-config § Low-impact council opt-in`](../../../../../docs/contracts/ai-council-config.md#low-impact-council-opt-in)
279
+ for the worked YAML example, validation behaviour, and unavailable-marker
280
+ contract.
281
+
282
+ ### Output marker (always surfaced)
283
+
284
+ * **Resolved** — `> Resolved via low-impact council (anthropic): <one-line answer>`
285
+ * **Split** — `> Low-impact council split — escalating to user (anthropic: X / openai: Y):`
286
+ * **Aborted** — `> Low-impact council aborted (token cap) — escalating to user:`
287
+
288
+ The marker is mandatory: the agent never silently substitutes a
289
+ fast-path verdict for its own answer.
290
+
291
+ ### Session artefact
292
+
293
+ Every fast-path attempt appends one line to
294
+ `agents/runtime/council/sessions/<date>-<slug>/low-impact-resolutions.md`:
295
+
296
+ ```
297
+ 2025-05-14T10:00:00Z | resolved | members=2/2 | members(anthropic, openai) cost=$0.0034 | Q=Service vs Repository for this read path?
298
+ ```
299
+
300
+ Append-only, one line per resolution. The parser tolerates free-form
301
+ section headers around the canonical lines, so the artefact may grow
302
+ human notes without breaking aggregation.
303
+
304
+ ### `council replay --low-impact-stats`
305
+
306
+ Re-projection of the session log into a summary block:
307
+
308
+ ```
309
+ $ council replay agents/runtime/council/sessions/2025-05-14-foo/responses.json --low-impact-stats
310
+ # Low-impact fast-path · session summary
311
+
312
+ - attempts: 4
313
+ - status: aborted=1 · resolved=2 · split=1
314
+ - members: anthropic=4 · openai=3
315
+ - total cost: $0.0096
316
+ ```
317
+
318
+ No model calls — pure parse of the markdown log. Returns 0 when the
319
+ session had no fast-path entries (a clean session is not an error).
320
+
@@ -0,0 +1,99 @@
1
+ # ai-council — cost awareness and redaction
2
+
3
+ > Mode body of the [`ai-council`](../SKILL.md) skill (router-head retrofit,
4
+ > 2026-08-20). Content moved VERBATIM from SKILL.md — load this file when the
5
+ > mode table in SKILL.md routes here.
6
+
7
+ ## Redaction expectations
8
+
9
+ The bundler's redaction pass strips:
10
+
11
+ - Paths matching `~/.event4u/agent-config/*.key` and the legacy
12
+ `~/.config/agent-config/*.key`.
13
+ - Lines starting with `Authorization:`.
14
+ - `key = …`, `secret = …`, `token = …`, `password = …` assignments.
15
+ - `sk-ant-…` and `sk-…` token-like strings.
16
+
17
+ If your artefact contains other sensitive data (customer names,
18
+ internal hostnames, contractual prose) you are responsible for
19
+ scrubbing it before bundling. The redaction pass is a **floor**, not
20
+ a ceiling.
21
+
22
+ ## Cost awareness
23
+
24
+ Every consultation hits a paid API. The orchestrator enforces
25
+ per-invocation caps from `ai_council.cost_budget`:
26
+
27
+ - `max_input_tokens` / `max_output_tokens` — token caps across all members.
28
+ - `max_total_usd` — per-invocation USD ceiling. `0` disables the USD ceiling (token caps still apply).
29
+ - `max_calls` — maximum number of council members per invocation.
30
+ - `daily_limit_usd` — rolling 24h spend cap across all `/council`
31
+ invocations. `0` disables. Persists in
32
+ `~/.event4u/agent-config/council-spend.jsonl` (mode 0600; legacy
33
+ `~/.config/agent-config/council-spend.jsonl` read as fallback). Breach
34
+ fires `on_overrun(event)` with `event.breach_kind == "daily"` and,
35
+ if the callback returns False or is absent, tags the member
36
+ `daily_budget_exceeded` instead of `cost_budget_exceeded`.
37
+
38
+ Prices come from `agents/runtime/.agent-prices.md` (gitignored, refreshed weekly).
39
+ The pricing module bootstraps it from `_default_prices.ts` on first
40
+ use and flags it stale when older than the most recent Monday 00:00
41
+ UTC.
42
+
43
+ ### Pre-call estimate format
44
+
45
+ Before the cost gate, compute `orchestrator.estimate(question, members,
46
+ table)` and render a per-member table. Heuristic: `len(text) / 4` for
47
+ input, member's `max_tokens` ceiling for output (actual spend is
48
+ usually lower).
49
+
50
+ > External council call — billable
51
+ >
52
+ > Mode: roadmap · Target: `agents/roadmaps/<name>.md` (~3 KB after redaction)
53
+ >
54
+ > | member | est. in / out tokens | est. USD |
55
+ > |---------------------------------|---------------------:|---------:|
56
+ > | anthropic / claude-sonnet-4-5 | ~750 / 1024 | $0.0176 |
57
+ > | openai / gpt-4o | ~750 / 1024 | $0.0121 |
58
+ > | **total** | | **$0.0297** |
59
+ >
60
+ > Budget: 50k in / 20k out tokens · USD ceiling: $0.50
61
+ >
62
+ > 1. Run the consultation
63
+ > 2. Cancel
64
+
65
+ ### Stale price-table gate
66
+
67
+ If `pricing.is_stale(table)` returns true, ask before proceeding:
68
+
69
+ > Price table is stale (last_updated: YYYY-MM-DD)
70
+ > 1. Refresh now (`./scripts-run src/scripts/update_prices`)
71
+ > 2. Continue with the stale table
72
+ > 3. Cancel
73
+
74
+ Do not silently auto-refresh — the user keeps control.
75
+
76
+ ### Mid-flow overrun callback (`on_overrun`)
77
+
78
+ The orchestrator runs members **sequentially**. Before each member
79
+ whose projected spend would breach a cap, it invokes the
80
+ `on_overrun(event)` callback. The callback returns `True` to proceed
81
+ with that member (raises the effective ceiling for THIS call only)
82
+ or `False` to skip and record `cost_budget_exceeded`. The callback
83
+ fires again for every subsequent breaching member — the user keeps
84
+ control on each step.
85
+
86
+ > Cost budget overrun — pausing before next member
87
+ >
88
+ > Member: openai / gpt-4o (member 2 of 2)
89
+ > Already spent: ~620 in / ~480 out tokens · $0.0094
90
+ > Next call estimate: ~750 in / 1024 out tokens · $0.0121
91
+ > **Projected total after this call: $0.0215** (ceiling: $0.0150)
92
+ >
93
+ > 1. Continue with this member
94
+ > 2. Skip this member (records `cost_budget_exceeded`, continues with the rest)
95
+
96
+ Without `on_overrun`, breaching short-circuits all remaining members
97
+ (v1 fallback). Do not retry silently. Surface the partial result and
98
+ ask the user.
99
+
@@ -0,0 +1,162 @@
1
+ # ai-council — execution and degradation modes
2
+
3
+ > Mode body of the [`ai-council`](../SKILL.md) skill (router-head retrofit,
4
+ > 2026-08-20). Content moved VERBATIM from SKILL.md — load this file when the
5
+ > mode table in SKILL.md routes here.
6
+
7
+ ## Execution modes
8
+
9
+ A council member can run in one of three transports. The neutrality
10
+ preamble is identical across all of them — only the path the bytes
11
+ travel changes.
12
+
13
+ | Mode | Client | Billable | Transport | Status |
14
+ |---|---|---|---|---|
15
+ | `api` | `AnthropicClient` / `OpenAIClient` / `GeminiClient` / `XAIClient` / `PerplexityClient` | yes | provider SDK + key from `~/.event4u/agent-config/<provider>.key` (legacy `~/.config/agent-config/<provider>.key` read as fallback) | shipped |
16
+ | `manual` | `ManualClient` | no | `stdout` (prompt block) + `stdin` (user pastes the web-UI reply, terminated by a line containing only `END`) | shipped (Phase 2b) |
17
+ | `cli` | `AnthropicCliClient` / `OpenAICliClient` / `GeminiCliClient` | no (subscription-authed) | local subprocess against the vendor CLI (`claude`, `codex`, `gemini`); auth delegated to the CLI's own session, no API key flows through this process | shipped (anthropic/openai/gemini · Phase 3) |
18
+
19
+ Resolution lives in `scripts/ai_council/modes.ts`:
20
+ `resolve_mode(name, invocation_mode, member_settings, global_mode)`
21
+ with precedence **invocation flag > per-member setting > global
22
+ setting > default (`manual`)**. Whitespace-and-case insensitive; empty
23
+ strings fall through; unknown values raise `InvalidModeError` with
24
+ the offending settings path (`ai_council.mode`,
25
+ `ai_council.members.<name>.mode`, or `/council mode=`).
26
+
27
+ ### Manual-mode UX
28
+
29
+ `ManualClient` is the user-as-transport variant: the agent prints
30
+ one Markdown block per member (system prompt + handoff preamble +
31
+ artefact between two `═` rules), the user pastes it into a web
32
+ chat (Claude.ai, ChatGPT, Gemini), then pastes the reply back
33
+ ending with a line containing only `END`. After each reply, a 1/2/3
34
+ menu surfaces:
35
+
36
+ 1. More feedback for this member (continue this thread)
37
+ 2. Done with this member, move to the next
38
+ 3. Abort the council run
39
+
40
+ `1` re-emits a follow-up block addressed to the **same chat
41
+ thread** (no system prompt repetition). `2` records the round and
42
+ moves to the next member. `3` returns `error="manual_aborted"` for
43
+ that member and the orchestrator stops the fan-out.
44
+
45
+ ### CLI-mode UX
46
+
47
+ `mode: cli` runs the council through the vendor's local CLI
48
+ instead of the API. Authentication is delegated — the user logs
49
+ into each CLI once (`claude login`, `codex login`, `gemini`), and
50
+ the orchestrator inherits the subscription. No API key flows
51
+ through this process. `billable=False`, so the cost gate is
52
+ bypassed; the local `cli_call_budget.max_calls_per_day.<provider>`
53
+ quota (state at `~/.event4u/agent-config/cli-calls.json`, daily
54
+ UTC reset) is the only per-day brake.
55
+
56
+ Three vendor CLIs are wired:
57
+
58
+ - **Anthropic / Claude** — invokes `claude --print --output-format json`
59
+ and parses the standard envelope (`result` + `usage` + `session_id`
60
+ + `total_cost_usd`). Token counts and reported cost survive to
61
+ `metadata` for audit.
62
+
63
+ ```yaml
64
+ members:
65
+ anthropic:
66
+ enabled: true
67
+ mode: cli
68
+ model: claude-sonnet-4-5
69
+ ```
70
+
71
+ - **OpenAI / Codex** — invokes `codex exec --json -` with the prompt piped on
72
+ stdin, and walks the newline-delimited JSON event stream, pulling text from
73
+ `item.completed` and tokens from `turn.completed`. Session id is preserved.
74
+ Unlike the Anthropic client, there is **no separate system-prompt channel**:
75
+ `codex exec` has no `--system` flag, so a system prompt is prepended to the
76
+ user prompt in the same payload.
77
+
78
+ ```yaml
79
+ members:
80
+ openai:
81
+ enabled: true
82
+ mode: cli
83
+ model: gpt-5
84
+ ```
85
+
86
+ - **Google / Gemini** — invokes `gemini --output-format json` with
87
+ the prompt piped on stdin, parses the `response` + `stats.models.<m>.tokens`
88
+ envelope. OAuth consent must be granted once interactively before
89
+ the CLI is usable from a non-interactive shell. Like Codex and unlike Claude,
90
+ it has **no system-prompt flag** — `--system` is rejected outright with
91
+ `Unknown argument: system` — so the system prompt is prepended to the piped
92
+ payload.
93
+
94
+ Two caveats before enabling it, both measured 2026-08-12 and neither resolved.
95
+ The CLI's own `--help` says `-p/--prompt` is what selects non-interactive
96
+ mode, and this invocation passes neither `-p` nor the `query` positional;
97
+ whether piped stdin alone keeps it headless is **unestablished**. And the
98
+ free tier now refuses this client outright with `IneligibleTierError`, so a
99
+ round-trip could not be completed here at all. Enable it only if you can
100
+ confirm both on your own account.
101
+
102
+ ```yaml
103
+ members:
104
+ gemini:
105
+ enabled: false # see the two caveats above before flipping this
106
+ mode: cli
107
+ model: gemini-2.5-pro
108
+ ```
109
+
110
+ Auth-failure stderr from any vendor CLI surfaces as
111
+ `error="auth_expired"` with the original stderr tail in
112
+ `metadata.stderr_tail` so the user knows to re-login. A missing
113
+ binary at construction time fails fast with `CouncilDisabledError`
114
+ naming the binary and the YAML override path — never silently
115
+ substitutes.
116
+
117
+ `xai` + `perplexity` accept `mode: cli` from Phase 4 onward, but
118
+ their community CLIs DO consume the API key and DO NOT bypass
119
+ per-token billing — the contract doc warns explicitly.
120
+
121
+ Both take a single `-p <prompt>` and have no second channel, so the system
122
+ prompt is folded into that same value. Until 2026-08-12 it was **discarded**,
123
+ and these two members answered every question with no role, no neutrality
124
+ framing and no output contract while the run counted the reply as a peer
125
+ verdict. Two consequences worth knowing: their whole prompt travels on argv, so
126
+ a very large one can fail with `os_error: E2BIG` (the response carries a `hint`
127
+ saying so), and because their CLIs report no usage block, the input side of
128
+ their cost is an estimate rather than a provider figure.
129
+
130
+ ### Cost-gate bypass for non-billable members
131
+
132
+ `ExternalAIClient.billable` is the contract. Clients with
133
+ `billable=False` (`ManualClient`, `AnthropicCliClient`,
134
+ `OpenAICliClient`, `GeminiCliClient`) bypass the cost gate entirely —
135
+ the orchestrator skips the
136
+ projection check, the `on_overrun` callback, and the USD-budget
137
+ short-circuit for that member, but still records the response's
138
+ token counts (from the manual-paste length heuristic or the
139
+ provider's reply, when available) for observability. Mixed runs
140
+ (one cli + one api) gate only the api members.
141
+
142
+ ## Degradation modes
143
+
144
+ How the council behaves when fewer than two billable members are
145
+ reachable. The orchestrator never silently substitutes — degradation
146
+ is visible to the user.
147
+
148
+ | Reachable | Behaviour | Independence |
149
+ |---|---|---|
150
+ | **2+** | Full fan-out, multi-round debate. Default. | High — cross-provider diversity. |
151
+ | **1** | Single-voice critique with a degraded-run warning. Multi-round mode lets the model see its own anonymised reply, but convergence ≠ correctness. | Low — shared blind spots. |
152
+ | **0** | Council skipped. Surface the failure, proceed without external review. **Never** substitute the host or an unrequested manual pass. | None. |
153
+
154
+ Rejected anti-patterns (council convergence, 2026-05-06): persona
155
+ prompts (same model, same blind spots, more cost), temperature
156
+ spread (noise, not signal), host-as-fallback (Iron Law breach).
157
+ Supported single-provider strategy is **sibling models on the same
158
+ provider** (e.g. Sonnet ↔ Opus, gpt-4o ↔ o1) — different training
159
+ cutoffs / reasoning architectures within one provider family. Cost
160
+ is real (siblings price-tier higher); explicit opt-in per invocation,
161
+ not a default.
162
+