@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +260 -7
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/inbox.md +264 -10
- package/dist/agent-src/commands/analyze.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +116 -30
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +31 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +135 -104
- package/dist/agent-src/rules/context-hygiene.md +2 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +3 -0
- package/dist/agent-src/rules/fix-what-you-see.md +108 -0
- package/dist/agent-src/rules/no-roadmap-references.md +0 -5
- package/dist/agent-src/rules/recurring-criticism.md +110 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -2
- package/dist/agent-src/rules/self-repair-loop.md +17 -0
- package/dist/agent-src/rules/skill-quality.md +0 -2
- package/dist/agent-src/rules/source-confidentiality.md +37 -7
- package/dist/agent-src/scripts/archival_sweep.ts +117 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/dist/agent-src/scripts/gate_budget.ts +282 -0
- package/dist/agent-src/scripts/gate_execute.ts +72 -31
- package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
- package/dist/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
- package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
- package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
- package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
- package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
- package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
- package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
- package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
- package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
- package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
- package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
- package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +45 -2
- package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/dist/cli/registry.js +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
- package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-4VR4ORQ6.js} +10 -7
- package/dist/cli-delegate/chunk-6EOCNQAM.js +402 -0
- package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-74E3TKWV.js} +381 -280
- package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-7F3VYSM2.js} +4 -4
- package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
- package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
- package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-GJ5BVHXM.js} +72 -165
- package/dist/cli-delegate/{chunk-P6LQDIWK.js → chunk-JZ4NR2TW.js} +338 -0
- package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
- package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
- package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
- package/dist/cli-delegate/cmd_conformance.js +459 -709
- package/dist/cli-delegate/cmd_doctor.js +6 -6
- package/dist/cli-delegate/cmd_explain.js +1 -1
- package/dist/cli-delegate/cmd_export.js +7 -6
- package/dist/cli-delegate/cmd_handoff.js +6 -6
- package/dist/cli-delegate/cmd_packs_active.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +7 -6
- package/dist/cli-delegate/cmd_session_recycle.js +840 -30
- package/dist/cli-delegate/cmd_settings_migrate.js +7 -6
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +7 -6
- package/dist/cli-delegate/cmd_uninstall.js +9 -7
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +7 -6
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +68 -25
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +10 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +8 -6
- package/dist/hooks/dispatch.js +2901 -2053
- package/dist/install/claudePathsPlan.js +187 -0
- package/dist/install/claudePathsPlan.js.map +1 -0
- package/dist/install/hostLayerFingerprint.js +136 -0
- package/dist/install/hostLayerFingerprint.js.map +1 -0
- package/dist/install/install.mjs +553 -425
- package/dist/install/partitionEligibility.js +276 -0
- package/dist/install/partitionEligibility.js.map +1 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1744 -1191
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_src.js +41 -0
- package/dist/scripts/_lib/agent_src.js.map +1 -1
- package/dist/scripts/_lib/install_layout.js +83 -0
- package/dist/scripts/_lib/install_layout.js.map +1 -0
- package/dist/scripts/_lib/installed_lock.js +444 -0
- package/dist/scripts/_lib/installed_lock.js.map +1 -0
- package/dist/scripts/condense.js +13 -164
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +4 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +12 -6
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
- package/docs/guidelines/agent-infra/memory-access.md +17 -0
- package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
- package/package.json +1 -1
- package/src/agent-src/scripts/archival_sweep.ts +117 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
- package/src/agent-src/scripts/gate_budget.ts +282 -0
- package/src/agent-src/scripts/gate_execute.ts +72 -31
- package/src/agent-src/scripts/roadmap_gates.ts +74 -3
- package/src/agent-src/scripts/update_roadmap_progress.ts +251 -7
- package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
- package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
- package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
- package/src/config/agent-settings.template.yml +27 -2
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/estate-count-budget.json +339 -3
- package/src/config/gate-violation-baselines.json +41 -41
- package/src/config/rule-activation-census.json +14 -6
- package/src/config/rule-stub-ceilings.json +19 -6
- package/src/install/claudePathsPlan.ts +196 -0
- package/src/install/hostLayerFingerprint.ts +145 -0
- package/src/install/partitionEligibility.ts +325 -0
- package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
- package/src/scripts/_dispatch.bash +6 -1
- package/src/scripts/_lib/ac_heading.ts +30 -0
- package/src/scripts/_lib/agent_src.ts +42 -0
- package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
- package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
- package/src/scripts/_lib/envelope_grounding.ts +38 -8
- package/src/scripts/_lib/installed_lock.ts +50 -5
- package/src/scripts/_lib/md_section.ts +129 -0
- package/src/scripts/_lib/scope_guard.sh +26 -3
- package/src/scripts/_lib/self_repair.ts +19 -0
- package/src/scripts/_lib/self_repair_class_b.ts +171 -0
- package/src/scripts/ai_council/cli_help.ts +55 -0
- package/src/scripts/before_complete_hook.ts +153 -28
- package/src/scripts/bench_ab_v2_complexity.ts +27 -7
- package/src/scripts/check_references.ts +60 -0
- package/src/scripts/check_release_published.ts +32 -11
- package/src/scripts/check_single_delivery.ts +59 -15
- package/src/scripts/ci_settle.ts +170 -0
- package/src/scripts/condense.ts +20 -170
- package/src/scripts/council_cli.ts +3 -3
- package/src/scripts/dispatch_r2_reviewer.ts +6 -14
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +77 -14
- package/src/scripts/hooks/block_no_verify.ts +61 -10
- package/src/scripts/hooks/block_unauthorized_git.ts +1 -1
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
- package/src/scripts/hooks/run_continuation_hook.ts +8 -5
- package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
- package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
- package/src/scripts/hooks/state_io.ts +782 -20
- package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
- package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
- package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
- package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
- package/src/scripts/install.ts +16 -11
- package/src/scripts/language_mirror_hook.ts +561 -25
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_plan_risk_register.ts +4 -3
- package/src/scripts/lint_skill_router_head.ts +4 -4
- package/src/scripts/mcp_server/tools.ts +2 -2
- package/src/scripts/new_roadmap.ts +136 -0
- package/src/scripts/pack_mcp_content.ts +20 -5
- package/src/scripts/release.ts +37 -38
- package/src/scripts/report_layer_overlap.ts +6 -0
- package/src/scripts/self_repair_hook.ts +37 -5
- package/src/scripts/session_register_hook.ts +11 -0
- package/src/scripts/skill_usage_collect.ts +11 -1
- package/src/scripts/skill_usage_report.ts +278 -8
- package/src/scripts/sync_pr_branch.ts +7 -0
- package/src/server/schemas/settings.ts +8 -0
- package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
- package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
- /package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
|
@@ -203,353 +203,48 @@ Anonymising the host as "Reviewer C" is worse than excluding it — the
|
|
|
203
203
|
user is told they got an outside vote when they did not. Externals
|
|
204
204
|
down → surface and skip; never substitute the host as a reviewer.
|
|
205
205
|
|
|
206
|
-
|
|
206
|
+
## Modes
|
|
207
207
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
208
|
+
This skill is a router head. Everything above is true in every mode and stays
|
|
209
|
+
here: which decision classes reach the council at all, what to do when it cannot
|
|
210
|
+
answer, the user-global configuration fact, the necessity self-check, and the
|
|
211
|
+
neutrality Iron Law. So does the output format below — it is an ordered MUST that
|
|
212
|
+
a pointer cannot carry. The operational manuals live in `references/`; load the
|
|
213
|
+
one the task calls for, not the set.
|
|
213
214
|
|
|
214
|
-
|
|
|
215
|
-
|---|---|
|
|
216
|
-
| Project name (from `composer.json` / `package.json` / repo dir) | Host-agent identity (Augment, Claude Code, Cursor, Cline, Windsurf, Copilot agent) — stripped line-by-line before send |
|
|
217
|
-
| Stack one-liner inferred from manifest files | Host-agent reasoning, prior turns, internal analysis |
|
|
218
|
-
| One paragraph of repo purpose from `README.md` (max 400 chars) | Host-agent framing language ("I think this looks weak", "the user probably wants…") |
|
|
219
|
-
| The user's **original ask** verbatim (the free-form sentence that triggered `/council`) | Anything the host agent generated about the artefact |
|
|
220
|
-
|
|
221
|
-
`detect_project_context()` in `scripts/ai_council/project_context.ts`
|
|
222
|
-
reads only the manifest files + root README; missing fields collapse
|
|
223
|
-
to `None` and the preamble silently omits the line. With both
|
|
224
|
-
`project=None` and `original_ask=""`, the preamble degrades to the
|
|
225
|
-
bare `NEUTRALITY_PREAMBLE` (v1 shape — back-compat for callers that
|
|
226
|
-
have not migrated yet).
|
|
227
|
-
|
|
228
|
-
## Execution modes
|
|
229
|
-
|
|
230
|
-
A council member can run in one of three transports. The neutrality
|
|
231
|
-
preamble is identical across all of them — only the path the bytes
|
|
232
|
-
travel changes.
|
|
233
|
-
|
|
234
|
-
| Mode | Client | Billable | Transport | Status |
|
|
235
|
-
|---|---|---|---|---|
|
|
236
|
-
| `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 |
|
|
237
|
-
| `manual` | `ManualClient` | no | `stdout` (prompt block) + `stdin` (user pastes the web-UI reply, terminated by a line containing only `END`) | shipped (Phase 2b) |
|
|
238
|
-
| `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) |
|
|
239
|
-
|
|
240
|
-
Resolution lives in `scripts/ai_council/modes.ts`:
|
|
241
|
-
`resolve_mode(name, invocation_mode, member_settings, global_mode)`
|
|
242
|
-
with precedence **invocation flag > per-member setting > global
|
|
243
|
-
setting > default (`manual`)**. Whitespace-and-case insensitive; empty
|
|
244
|
-
strings fall through; unknown values raise `InvalidModeError` with
|
|
245
|
-
the offending settings path (`ai_council.mode`,
|
|
246
|
-
`ai_council.members.<name>.mode`, or `/council mode=`).
|
|
247
|
-
|
|
248
|
-
### Manual-mode UX
|
|
249
|
-
|
|
250
|
-
`ManualClient` is the user-as-transport variant: the agent prints
|
|
251
|
-
one Markdown block per member (system prompt + handoff preamble +
|
|
252
|
-
artefact between two `═` rules), the user pastes it into a web
|
|
253
|
-
chat (Claude.ai, ChatGPT, Gemini), then pastes the reply back
|
|
254
|
-
ending with a line containing only `END`. After each reply, a 1/2/3
|
|
255
|
-
menu surfaces:
|
|
256
|
-
|
|
257
|
-
1. More feedback for this member (continue this thread)
|
|
258
|
-
2. Done with this member, move to the next
|
|
259
|
-
3. Abort the council run
|
|
260
|
-
|
|
261
|
-
`1` re-emits a follow-up block addressed to the **same chat
|
|
262
|
-
thread** (no system prompt repetition). `2` records the round and
|
|
263
|
-
moves to the next member. `3` returns `error="manual_aborted"` for
|
|
264
|
-
that member and the orchestrator stops the fan-out.
|
|
265
|
-
|
|
266
|
-
### CLI-mode UX
|
|
267
|
-
|
|
268
|
-
`mode: cli` runs the council through the vendor's local CLI
|
|
269
|
-
instead of the API. Authentication is delegated — the user logs
|
|
270
|
-
into each CLI once (`claude login`, `codex login`, `gemini`), and
|
|
271
|
-
the orchestrator inherits the subscription. No API key flows
|
|
272
|
-
through this process. `billable=False`, so the cost gate is
|
|
273
|
-
bypassed; the local `cli_call_budget.max_calls_per_day.<provider>`
|
|
274
|
-
quota (state at `~/.event4u/agent-config/cli-calls.json`, daily
|
|
275
|
-
UTC reset) is the only per-day brake.
|
|
276
|
-
|
|
277
|
-
Three vendor CLIs are wired:
|
|
278
|
-
|
|
279
|
-
- **Anthropic / Claude** — invokes `claude --print --output-format json`
|
|
280
|
-
and parses the standard envelope (`result` + `usage` + `session_id`
|
|
281
|
-
+ `total_cost_usd`). Token counts and reported cost survive to
|
|
282
|
-
`metadata` for audit.
|
|
283
|
-
|
|
284
|
-
```yaml
|
|
285
|
-
members:
|
|
286
|
-
anthropic:
|
|
287
|
-
enabled: true
|
|
288
|
-
mode: cli
|
|
289
|
-
model: claude-sonnet-4-5
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
- **OpenAI / Codex** — invokes `codex exec --json -` with the prompt piped on
|
|
293
|
-
stdin, and walks the newline-delimited JSON event stream, pulling text from
|
|
294
|
-
`item.completed` and tokens from `turn.completed`. Session id is preserved.
|
|
295
|
-
Unlike the Anthropic client, there is **no separate system-prompt channel**:
|
|
296
|
-
`codex exec` has no `--system` flag, so a system prompt is prepended to the
|
|
297
|
-
user prompt in the same payload.
|
|
298
|
-
|
|
299
|
-
```yaml
|
|
300
|
-
members:
|
|
301
|
-
openai:
|
|
302
|
-
enabled: true
|
|
303
|
-
mode: cli
|
|
304
|
-
model: gpt-5
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
- **Google / Gemini** — invokes `gemini --output-format json` with
|
|
308
|
-
the prompt piped on stdin, parses the `response` + `stats.models.<m>.tokens`
|
|
309
|
-
envelope. OAuth consent must be granted once interactively before
|
|
310
|
-
the CLI is usable from a non-interactive shell. Like Codex and unlike Claude,
|
|
311
|
-
it has **no system-prompt flag** — `--system` is rejected outright with
|
|
312
|
-
`Unknown argument: system` — so the system prompt is prepended to the piped
|
|
313
|
-
payload.
|
|
314
|
-
|
|
315
|
-
Two caveats before enabling it, both measured 2026-08-12 and neither resolved.
|
|
316
|
-
The CLI's own `--help` says `-p/--prompt` is what selects non-interactive
|
|
317
|
-
mode, and this invocation passes neither `-p` nor the `query` positional;
|
|
318
|
-
whether piped stdin alone keeps it headless is **unestablished**. And the
|
|
319
|
-
free tier now refuses this client outright with `IneligibleTierError`, so a
|
|
320
|
-
round-trip could not be completed here at all. Enable it only if you can
|
|
321
|
-
confirm both on your own account.
|
|
322
|
-
|
|
323
|
-
```yaml
|
|
324
|
-
members:
|
|
325
|
-
gemini:
|
|
326
|
-
enabled: false # see the two caveats above before flipping this
|
|
327
|
-
mode: cli
|
|
328
|
-
model: gemini-2.5-pro
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
Auth-failure stderr from any vendor CLI surfaces as
|
|
332
|
-
`error="auth_expired"` with the original stderr tail in
|
|
333
|
-
`metadata.stderr_tail` so the user knows to re-login. A missing
|
|
334
|
-
binary at construction time fails fast with `CouncilDisabledError`
|
|
335
|
-
naming the binary and the YAML override path — never silently
|
|
336
|
-
substitutes.
|
|
337
|
-
|
|
338
|
-
`xai` + `perplexity` accept `mode: cli` from Phase 4 onward, but
|
|
339
|
-
their community CLIs DO consume the API key and DO NOT bypass
|
|
340
|
-
per-token billing — the contract doc warns explicitly.
|
|
341
|
-
|
|
342
|
-
Both take a single `-p <prompt>` and have no second channel, so the system
|
|
343
|
-
prompt is folded into that same value. Until 2026-08-12 it was **discarded**,
|
|
344
|
-
and these two members answered every question with no role, no neutrality
|
|
345
|
-
framing and no output contract while the run counted the reply as a peer
|
|
346
|
-
verdict. Two consequences worth knowing: their whole prompt travels on argv, so
|
|
347
|
-
a very large one can fail with `os_error: E2BIG` (the response carries a `hint`
|
|
348
|
-
saying so), and because their CLIs report no usage block, the input side of
|
|
349
|
-
their cost is an estimate rather than a provider figure.
|
|
350
|
-
|
|
351
|
-
### Cost-gate bypass for non-billable members
|
|
352
|
-
|
|
353
|
-
`ExternalAIClient.billable` is the contract. Clients with
|
|
354
|
-
`billable=False` (`ManualClient`, `AnthropicCliClient`,
|
|
355
|
-
`OpenAICliClient`, `GeminiCliClient`) bypass the cost gate entirely —
|
|
356
|
-
the orchestrator skips the
|
|
357
|
-
projection check, the `on_overrun` callback, and the USD-budget
|
|
358
|
-
short-circuit for that member, but still records the response's
|
|
359
|
-
token counts (from the manual-paste length heuristic or the
|
|
360
|
-
provider's reply, when available) for observability. Mixed runs
|
|
361
|
-
(one cli + one api) gate only the api members.
|
|
362
|
-
|
|
363
|
-
## Degradation modes
|
|
364
|
-
|
|
365
|
-
How the council behaves when fewer than two billable members are
|
|
366
|
-
reachable. The orchestrator never silently substitutes — degradation
|
|
367
|
-
is visible to the user.
|
|
368
|
-
|
|
369
|
-
| Reachable | Behaviour | Independence |
|
|
215
|
+
| Task | Mode body | Covers |
|
|
370
216
|
|---|---|---|
|
|
371
|
-
|
|
|
372
|
-
|
|
|
373
|
-
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
not a default.
|
|
217
|
+
| Pick an execution mode, or handle a degraded one | [`references/execution-modes.md`](references/execution-modes.md) | Manual-mode and CLI-mode UX, the cost-gate bypass for non-billable members, degradation modes |
|
|
218
|
+
| Run a session end to end | [`references/procedure.md`](references/procedure.md) | The neutrality context-handoff, the numbered procedure, the convener-skeptic stance, why a mechanism claim needs a probe rather than a second opinion, what this is NOT |
|
|
219
|
+
| Place the artefact, or render the synthesis | [`references/output-and-synthesis.md`](references/output-and-synthesis.md) | Output path convention with its forbidden and exempt sets, lens-aware synthesis templates, the `--prose-synthesis` escape hatch, renderer lens resolution |
|
|
220
|
+
| Estimate or gate the spend, or check what is redacted | [`references/cost-and-redaction.md`](references/cost-and-redaction.md) | Redaction expectations, cost awareness, the pre-call estimate format, the stale price-table gate, the mid-flow overrun callback |
|
|
221
|
+
| Multi-round debate, deep tier, advisors, replay, low-impact fast-path | [`references/advanced-modes.md`](references/advanced-modes.md) | `rounds:N` debate, the deep-reasoning tier and its manual-mode parity, `/council debate`, Karpathy peer-review, thinking-style advisors, the decision-replay artefact, the Lightweight-QA fast-path with its own Iron Law and output markers |
|
|
222
|
+
|
|
223
|
+
Two of those bodies carry obligations a pointer cannot summarise: the
|
|
224
|
+
output-path convention is enforced by CI, and the Lightweight-QA fast-path
|
|
225
|
+
markers are required verbatim by
|
|
226
|
+
[`fast-path-marker-visibility`](../../rules/fast-path-marker-visibility.md).
|
|
227
|
+
Load the body before acting in either mode rather than working from memory of it.
|
|
383
228
|
|
|
384
229
|
## Procedure
|
|
385
230
|
|
|
386
|
-
1. **
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
2. **
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
- **Billable members with no ceiling at all** (`max_total_usd: 0` AND
|
|
404
|
-
`daily_limit_usd: 0`) → unbounded paid spend, so surface the estimate
|
|
405
|
-
and require an explicit `1`. Nothing bounds the call, so the user must.
|
|
406
|
-
|
|
407
|
-
Autonomy settings do not *create* a bound and do not lift the last case.
|
|
408
|
-
Consumers who want the old per-run gate back set a small
|
|
409
|
-
`cost_budget.max_total_usd`: every call then breaches and `on_overrun`
|
|
410
|
-
asks, per member.
|
|
411
|
-
4. **Fan out.** Dispatch the bundle to each enabled council member via
|
|
412
|
-
`scripts/ai_council/orchestrator.ts`. Each member receives the
|
|
413
|
-
neutrality preamble from `prompts.ts` plus the artefact — nothing
|
|
414
|
-
from the host agent's prior reasoning.
|
|
415
|
-
5. **Render results.** Stack each member's response under its own
|
|
416
|
-
provider-attributed heading. Never merge or paraphrase responses
|
|
417
|
-
into the host agent's voice.
|
|
418
|
-
6. **Summarise.** Write a `Convergence / Divergence` block listing
|
|
419
|
-
agreements, disagreements, and unique insights — provider-attributed.
|
|
420
|
-
7. **Critically evaluate** every finding before it leaves the host
|
|
421
|
-
(see *Critical evaluation* below). The host is the convener **and**
|
|
422
|
-
the skeptic — never a reviewer of the artefact itself, but always a
|
|
423
|
-
reviewer of the **council's output**.
|
|
424
|
-
8. **Translate validated findings to options.** Convert each finding
|
|
425
|
-
the host accepts (or accepts with modification) into a concrete
|
|
426
|
-
numbered option for the user. Tag every option with the host's
|
|
427
|
-
verdict so the user sees the agent's reasoned position, not the
|
|
428
|
-
council's raw output. The user decides; the council advises; the
|
|
429
|
-
host filters.
|
|
430
|
-
|
|
431
|
-
## Critical evaluation — convener-skeptic stance
|
|
432
|
-
|
|
433
|
-
```
|
|
434
|
-
COUNCIL CONVERGENCE IS NOT CORRECTNESS.
|
|
435
|
-
DO NOT BLINDLY ACCEPT FINDINGS. DO NOT BLINDLY REJECT THEM.
|
|
436
|
-
EVERY FINDING GETS A REASONED VERDICT BEFORE IT REACHES THE USER.
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
### Mechanism claims need a probe, not a second opinion
|
|
440
|
-
|
|
441
|
-
```
|
|
442
|
-
A MECHANISM CLAIM IN A COUNCIL ARTEFACT IS MARKED `unverified:` UNTIL A PROBE COVERS IT.
|
|
443
|
-
A VERDICT RESTING ON AN UNVERIFIED MECHANISM CLAIM DOES NOT BIND.
|
|
444
|
-
SEVERAL MODELS AGREEING MULTIPLIES PLAUSIBILITY. IT DOES NOT PRODUCE EVIDENCE.
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
A **mechanism claim** asserts how the machine behaves: "this toggle removes the
|
|
448
|
-
cost", "that gate scans X", "the host reads the router". The council deliberates
|
|
449
|
-
over **arguments**, never against the running system — it cannot execute a command,
|
|
450
|
-
so it has no way to falsify one. Marking such a claim `unverified:` in the artefact
|
|
451
|
-
keeps the reader from mistaking a well-argued mechanism for a measured one, and the
|
|
452
|
-
non-binding clause means the fix for a wrong claim is a probe, not a re-vote.
|
|
453
|
-
|
|
454
|
-
**Case zero (2026-07-29).** An accepted ADR claimed a compile-time toggle gave
|
|
455
|
-
"zero-cost dormancy" because the rule was dropped from `dist/router.json`. Two
|
|
456
|
-
council members praised the reasoning; neither could check it. A one-line `grep`
|
|
457
|
-
later showed the toggle was read by the router compiler and by **nothing in the
|
|
458
|
-
projector**, so the rule's body kept shipping as a file — and the host reads the
|
|
459
|
-
file. The claim was half wrong, the verdict that rested on it was void, and what
|
|
460
|
-
caught it was a probe, not a third opinion.
|
|
461
|
-
|
|
462
|
-
The council is **uninformed about the codebase, ADRs, locked
|
|
463
|
-
contracts, prior decisions, and project history** — it sees only the
|
|
464
|
-
artefact + neutrality preamble. That is the source of its diversity
|
|
465
|
-
**and** its blind spots. Convergence between members can mean shared
|
|
466
|
-
generic best-practice priors, not project-specific correctness.
|
|
467
|
-
|
|
468
|
-
The host applies a critical lens to **every finding** (convergence
|
|
469
|
-
**and** divergence) before surfacing it as a numbered option:
|
|
470
|
-
|
|
471
|
-
| Check | Question | Tool |
|
|
472
|
-
|---|---|---|
|
|
473
|
-
| **Codebase fit** | Does the finding match the actual code, files, signatures, conventions? | `view` / `codebase-retrieval` / `grep` |
|
|
474
|
-
| **Locked-decision conflict** | Does it contradict an ADR, kernel rule, contract under `docs/contracts/`, or `docs/decisions/`? | `view` |
|
|
475
|
-
| **Already addressed** | Is it a generic best-practice already covered by an existing rule, skill, or test? | `view` / `grep` |
|
|
476
|
-
| **Cost / benefit** | Is the change worth the diff size, churn, and review cost vs. the marginal benefit? | reasoning |
|
|
477
|
-
| **Hallucination** | Does the finding cite a file, function, or behavior that does not exist? | `view` |
|
|
478
|
-
|
|
479
|
-
Each finding receives one of three verdicts:
|
|
480
|
-
|
|
481
|
-
- **`accept`** — codebase fits, no locked-decision conflict, benefit clears cost. Surface as a normal numbered option.
|
|
482
|
-
- **`accept-with-modification`** — core insight valid, but the proposed shape needs adjusting (wrong file, contradicts ADR detail, scope creep). Surface with the **modified** patch and a one-line note.
|
|
483
|
-
- **`reject`** — finding is wrong (hallucinated reference, contradicts a locked decision, already addressed, generic noise). Surface as a **Rejected by host** entry with a one-line reason. Still visible — the user can override.
|
|
484
|
-
|
|
485
|
-
The verdict is the host's **own** reasoning, not the council's.
|
|
486
|
-
Pretending convergence equals correctness, or paraphrasing council
|
|
487
|
-
output as host analysis, both breach the [`direct-answers`](../../rules/direct-answers.md)
|
|
488
|
-
no-invented-facts rule. When the host cannot reach a confident
|
|
489
|
-
verdict on a finding (mixed evidence, ambiguous scope), it surfaces
|
|
490
|
-
the finding as `needs-input` with the open question — the user
|
|
491
|
-
decides, the host does not guess.
|
|
492
|
-
|
|
493
|
-
### What this is NOT
|
|
494
|
-
|
|
495
|
-
- **Not a re-review by the host.** The host did not write the artefact independently and cannot critique it independently — that boundary still holds.
|
|
496
|
-
- **Not a vote against the council.** Rejecting a finding requires evidence (file, line, contract reference), not preference.
|
|
497
|
-
- **Not silent filtering.** Every finding reaches the user with its verdict and reason. The user can pick a `reject` option and override the host.
|
|
498
|
-
|
|
499
|
-
## Output path convention
|
|
500
|
-
|
|
501
|
-
Council artefacts (questions, responses, sessions) are **dev-time
|
|
502
|
-
scratch** — gitignored in both the package repo and consumer repos
|
|
503
|
-
and auto-pruned after `ai_council.session_retention_days` (default
|
|
504
|
-
7). They inform a decision; they are not the durable contract. The
|
|
505
|
-
durable contract lives in the roadmap / ADR / skill body that cites
|
|
506
|
-
the council's convergence inline.
|
|
507
|
-
|
|
508
|
-
**Linking to a specific council file is forbidden by
|
|
509
|
-
[`no-roadmap-references`](../../rules/no-roadmap-references.md)
|
|
510
|
-
(council clause)** — gitignored, not in the cloned repo, gone after
|
|
511
|
-
the retention window. Inline the convergence with date + members
|
|
512
|
-
instead.
|
|
513
|
-
|
|
514
|
-
Three directories, three modes:
|
|
515
|
-
|
|
516
|
-
| Mode | Path | Format |
|
|
517
|
-
|---|---|---|
|
|
518
|
-
| **Topic-anchored question** (paired with a roadmap or ADR) | `agents/runtime/council/questions/<topic-slug>.md` | Markdown |
|
|
519
|
-
| **Topic-anchored response** (paired with the question above) | `agents/runtime/council/responses/<topic-slug>.json` | JSON from `council:run --output` |
|
|
520
|
-
| **Ad-hoc session** (no durable artefact yet) | `agents/runtime/council/sessions/<UTC-timestamp>.json` | JSON from `council:run --output` |
|
|
521
|
-
|
|
522
|
-
`<topic-slug>` is kebab-case and **must match** the corresponding
|
|
523
|
-
roadmap / ADR slug if one exists (e.g. `path-fixes` mirrors the
|
|
524
|
-
matching `road-to-<topic-slug>` roadmap under `agents/roadmaps/`).
|
|
525
|
-
|
|
526
|
-
### Forbidden
|
|
527
|
-
|
|
528
|
-
- Files at `agents/` root (e.g. `agents/runtime/council/question-foo.md`).
|
|
529
|
-
- Dot-prefix scratch (e.g. `agents/.council-question-foo.md`).
|
|
530
|
-
- Any other directory below `agents/` (e.g. `agents/scratch/`,
|
|
531
|
-
`agents/evidence/notes/`). Operator scratch belongs under
|
|
532
|
-
`agents/runtime/tmp/` (gitignored).
|
|
533
|
-
- Cross-references from any artefact to specific council files —
|
|
534
|
-
see [`no-roadmap-references`](../../rules/no-roadmap-references.md)
|
|
535
|
-
(council clause). Inline the convergence summary instead, with
|
|
536
|
-
date and member list for traceability (`Council (claude-sonnet-4-5
|
|
537
|
-
+ gpt-4o, YYYY-MM-DD) reviewed N candidate strategies; converged
|
|
538
|
-
on …`).
|
|
539
|
-
|
|
540
|
-
### Exempt
|
|
541
|
-
|
|
542
|
-
- `agents/evidence/audits/` — historical audit bundles. The canonical
|
|
543
|
-
council dirs are gitignored; audit bundles are tracked,
|
|
544
|
-
cohesive narratives that may include council artefacts as
|
|
545
|
-
part of their evidence trail (e.g. `audits/2026-05-14-north-star/`
|
|
546
|
-
bundling its triggering question, raw responses, and synthesis
|
|
547
|
-
alongside the audit's findings). The layout linter
|
|
548
|
-
(`scripts/check_council_layout.ts`) skips this directory.
|
|
549
|
-
|
|
550
|
-
`scripts/check_council_layout.ts` is the mechanical check for the
|
|
551
|
-
output path convention — wire it into the package's CI pipeline so
|
|
552
|
-
violations break the build.
|
|
231
|
+
1. **Inspect first.** Run the necessity self-check above and read the artefact
|
|
232
|
+
you are about to hand over. It is cheaper to not convene than to convene and
|
|
233
|
+
discard.
|
|
234
|
+
2. **Confirm availability** — `agent-config council:status`, never an inference
|
|
235
|
+
from the project tree (see § Configuration is ALWAYS user-global).
|
|
236
|
+
3. **Pick the execution mode** from
|
|
237
|
+
[`references/execution-modes.md`](references/execution-modes.md).
|
|
238
|
+
4. **Run the session** per the numbered procedure in
|
|
239
|
+
[`references/procedure.md`](references/procedure.md), under the neutrality
|
|
240
|
+
Iron Law above — the preamble is not optional and the question is never
|
|
241
|
+
authored toward a conclusion.
|
|
242
|
+
5. **Estimate the spend before the call** per
|
|
243
|
+
[`references/cost-and-redaction.md`](references/cost-and-redaction.md).
|
|
244
|
+
6. **Write the artefact** in the output format below, at the path
|
|
245
|
+
[`references/output-and-synthesis.md`](references/output-and-synthesis.md)
|
|
246
|
+
fixes, then apply the convener-skeptic verdict yourself — convergence is not
|
|
247
|
+
correctness.
|
|
553
248
|
|
|
554
249
|
## Output format
|
|
555
250
|
|
|
@@ -596,69 +291,6 @@ attributed to the host.
|
|
|
596
291
|
> counting council votes. Mirrored in `code-review` so the boundary is
|
|
597
292
|
> grep-checkable from both sides.
|
|
598
293
|
|
|
599
|
-
## Synthesis templates (lens-aware)
|
|
600
|
-
|
|
601
|
-
The **Convergence / Divergence** slot in `council:render` output is
|
|
602
|
-
populated with a lens-specific synthesis prompt. The host agent reads
|
|
603
|
-
this prompt and writes the summary in the shape it dictates. The five
|
|
604
|
-
templates live in `scripts/ai_council/prompts.ts::_SYNTHESIS_TABLE`
|
|
605
|
-
and are exposed via `synthesis_template(mode)`.
|
|
606
|
-
|
|
607
|
-
**R4 Q4 split** — decision lenses get a structured Karpathy-style
|
|
608
|
-
template; creative lenses keep an open-ended prose body. **Every lens
|
|
609
|
-
now closes with two required verdict-discipline sections** — **Kill
|
|
610
|
-
criteria** (observable falsifiers with a threshold or event, checkable
|
|
611
|
-
without re-convening the council) and **Concrete next step** (exactly
|
|
612
|
-
one artefact-producing action) — added so no synthesis ships an
|
|
613
|
-
unfalsifiable verdict (road-to-opt-council-deliberation Phase 0):
|
|
614
|
-
|
|
615
|
-
| Lens | Class | Synthesis sections |
|
|
616
|
-
|---|---|---|
|
|
617
|
-
| `default` | decision | Agreement · Clashes · Blind spots · Recommendation · **Kill criteria · Concrete next step** |
|
|
618
|
-
| `pr` | decision | Consensus · Conflicts · Must-fix before merge · Recommendation · **Kill criteria · Concrete next step** |
|
|
619
|
-
| `analysis` | decision | Top-10 by consensus · Supporting · Outliers · **Kill criteria · Concrete next step** |
|
|
620
|
-
| `design` | creative | open prose body + **Kill criteria · Concrete next step** |
|
|
621
|
-
| `optimize` | creative | open prose body + **Kill criteria · Concrete next step** |
|
|
622
|
-
|
|
623
|
-
Input modes (`prompt` / `roadmap` / `diff` / `files`) inherit the
|
|
624
|
-
`default` decision template — they are bundling shapes, not lenses.
|
|
625
|
-
|
|
626
|
-
**Source citations:**
|
|
627
|
-
* Template shape — Round 2 council verdict
|
|
628
|
-
(`agents/runtime/council/sessions/2026-05-14-ai-council-redesign/round-1.md`,
|
|
629
|
-
Opus's lens-adaptive synthesis proposal).
|
|
630
|
-
* Decision/creative split — Round 4 Q4 verdict
|
|
631
|
-
(`agents/runtime/council/sessions/2026-05-14-ai-council-redesign/round-3-responses.json`).
|
|
632
|
-
R4 reframed `optimize` as creative because perf trade-offs resist
|
|
633
|
-
pre-templated shape — Performance-wins / Trade-offs /
|
|
634
|
-
Implementation-order is too rigid for the variety of optimize-lens
|
|
635
|
-
artefacts. R4 reframed `design` for the same reason — design
|
|
636
|
-
critiques are inherently narrative.
|
|
637
|
-
|
|
638
|
-
### `--prose-synthesis` escape hatch (R4 Q4)
|
|
639
|
-
|
|
640
|
-
Both `council:run` and `council:render` accept symmetric escape-hatch
|
|
641
|
-
flags on top of the lens table:
|
|
642
|
-
|
|
643
|
-
* `--prose-synthesis` — force creative-lens passthrough (bare slot)
|
|
644
|
-
regardless of lens. Use when the user on `default`/`pr`/`analysis`
|
|
645
|
-
prefers a narrative recommendation over the structured template.
|
|
646
|
-
* `--no-prose-synthesis` — force the `default` structured template
|
|
647
|
-
even on a creative lens. Use when a `design` or `optimize` artefact
|
|
648
|
-
has a one-shot need for Karpathy-style structure.
|
|
649
|
-
|
|
650
|
-
The flag is mutually exclusive — picking one disables the other on
|
|
651
|
-
the same invocation. When `council:run` records either flag in the
|
|
652
|
-
output JSON, `council:render` honours it unless the renderer is
|
|
653
|
-
called with an explicit flag of its own.
|
|
654
|
-
|
|
655
|
-
### Renderer lens resolution
|
|
656
|
-
|
|
657
|
-
`council:render <responses.json>` resolves the active lens in this
|
|
658
|
-
order: explicit `--prompt-mode` flag > `prompt_mode` field in the
|
|
659
|
-
payload > `mode` field in the payload > `None` (default decision
|
|
660
|
-
template). The `--prose-synthesis` / `--no-prose-synthesis` flag
|
|
661
|
-
overrides the table regardless of how the lens resolved.
|
|
662
294
|
|
|
663
295
|
## Do NOT
|
|
664
296
|
|
|
@@ -704,412 +336,21 @@ Real failure modes seen in the wild:
|
|
|
704
336
|
| Reject a finding on preference, not evidence. | "I don't like this" is not a verdict. | Cite the file, line, ADR, or contract that justifies the rejection — or surface as `needs-input`. |
|
|
705
337
|
| Paraphrase council output into the host's own analysis to defend a verdict. | Strips attribution, breaches `direct-answers` no-invented-facts. | Verdict cites host evidence (file:line); council output stays attributed in the per-member sections. |
|
|
706
338
|
|
|
707
|
-
## Redaction
|
|
708
|
-
|
|
709
|
-
The bundler's redaction pass strips:
|
|
710
|
-
|
|
711
|
-
- Paths matching `~/.event4u/agent-config/*.key` and the legacy
|
|
712
|
-
`~/.config/agent-config/*.key`.
|
|
713
|
-
- Lines starting with `Authorization:`.
|
|
714
|
-
- `key = …`, `secret = …`, `token = …`, `password = …` assignments.
|
|
715
|
-
- `sk-ant-…` and `sk-…` token-like strings.
|
|
716
|
-
|
|
717
|
-
If your artefact contains other sensitive data (customer names,
|
|
718
|
-
internal hostnames, contractual prose) you are responsible for
|
|
719
|
-
scrubbing it before bundling. The redaction pass is a **floor**, not
|
|
720
|
-
a ceiling.
|
|
721
|
-
|
|
722
|
-
## Cost awareness
|
|
723
|
-
|
|
724
|
-
Every consultation hits a paid API. The orchestrator enforces
|
|
725
|
-
per-invocation caps from `ai_council.cost_budget`:
|
|
726
|
-
|
|
727
|
-
- `max_input_tokens` / `max_output_tokens` — token caps across all members.
|
|
728
|
-
- `max_total_usd` — per-invocation USD ceiling. `0` disables the USD ceiling (token caps still apply).
|
|
729
|
-
- `max_calls` — maximum number of council members per invocation.
|
|
730
|
-
- `daily_limit_usd` — rolling 24h spend cap across all `/council`
|
|
731
|
-
invocations. `0` disables. Persists in
|
|
732
|
-
`~/.event4u/agent-config/council-spend.jsonl` (mode 0600; legacy
|
|
733
|
-
`~/.config/agent-config/council-spend.jsonl` read as fallback). Breach
|
|
734
|
-
fires `on_overrun(event)` with `event.breach_kind == "daily"` and,
|
|
735
|
-
if the callback returns False or is absent, tags the member
|
|
736
|
-
`daily_budget_exceeded` instead of `cost_budget_exceeded`.
|
|
737
|
-
|
|
738
|
-
Prices come from `agents/runtime/.agent-prices.md` (gitignored, refreshed weekly).
|
|
739
|
-
The pricing module bootstraps it from `_default_prices.ts` on first
|
|
740
|
-
use and flags it stale when older than the most recent Monday 00:00
|
|
741
|
-
UTC.
|
|
742
|
-
|
|
743
|
-
### Pre-call estimate format
|
|
744
|
-
|
|
745
|
-
Before the cost gate, compute `orchestrator.estimate(question, members,
|
|
746
|
-
table)` and render a per-member table. Heuristic: `len(text) / 4` for
|
|
747
|
-
input, member's `max_tokens` ceiling for output (actual spend is
|
|
748
|
-
usually lower).
|
|
749
|
-
|
|
750
|
-
> External council call — billable
|
|
751
|
-
>
|
|
752
|
-
> Mode: roadmap · Target: `agents/roadmaps/<name>.md` (~3 KB after redaction)
|
|
753
|
-
>
|
|
754
|
-
> | member | est. in / out tokens | est. USD |
|
|
755
|
-
> |---------------------------------|---------------------:|---------:|
|
|
756
|
-
> | anthropic / claude-sonnet-4-5 | ~750 / 1024 | $0.0176 |
|
|
757
|
-
> | openai / gpt-4o | ~750 / 1024 | $0.0121 |
|
|
758
|
-
> | **total** | | **$0.0297** |
|
|
759
|
-
>
|
|
760
|
-
> Budget: 50k in / 20k out tokens · USD ceiling: $0.50
|
|
761
|
-
>
|
|
762
|
-
> 1. Run the consultation
|
|
763
|
-
> 2. Cancel
|
|
764
|
-
|
|
765
|
-
### Stale price-table gate
|
|
766
|
-
|
|
767
|
-
If `pricing.is_stale(table)` returns true, ask before proceeding:
|
|
339
|
+
## Redaction and cost
|
|
768
340
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
341
|
+
Both moved verbatim to
|
|
342
|
+
[`references/cost-and-redaction.md`](references/cost-and-redaction.md): what the
|
|
343
|
+
bundler's redaction pass strips, the cost-awareness rules, the pre-call estimate
|
|
344
|
+
format, the stale price-table gate, and the mid-flow overrun callback. A breach
|
|
345
|
+
without `on_overrun` short-circuits the remaining members — surface the partial
|
|
346
|
+
result and ask, never retry silently.
|
|
773
347
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
### Mid-flow overrun callback (`on_overrun`)
|
|
777
|
-
|
|
778
|
-
The orchestrator runs members **sequentially**. Before each member
|
|
779
|
-
whose projected spend would breach a cap, it invokes the
|
|
780
|
-
`on_overrun(event)` callback. The callback returns `True` to proceed
|
|
781
|
-
with that member (raises the effective ceiling for THIS call only)
|
|
782
|
-
or `False` to skip and record `cost_budget_exceeded`. The callback
|
|
783
|
-
fires again for every subsequent breaching member — the user keeps
|
|
784
|
-
control on each step.
|
|
785
|
-
|
|
786
|
-
> Cost budget overrun — pausing before next member
|
|
787
|
-
>
|
|
788
|
-
> Member: openai / gpt-4o (member 2 of 2)
|
|
789
|
-
> Already spent: ~620 in / ~480 out tokens · $0.0094
|
|
790
|
-
> Next call estimate: ~750 in / 1024 out tokens · $0.0121
|
|
791
|
-
> **Projected total after this call: $0.0215** (ceiling: $0.0150)
|
|
792
|
-
>
|
|
793
|
-
> 1. Continue with this member
|
|
794
|
-
> 2. Skip this member (records `cost_budget_exceeded`, continues with the rest)
|
|
795
|
-
|
|
796
|
-
Without `on_overrun`, breaching short-circuits all remaining members
|
|
797
|
-
(v1 fallback). Do not retry silently. Surface the partial result and
|
|
798
|
-
ask the user.
|
|
799
|
-
|
|
800
|
-
## Multi-round debate (`rounds:N`)
|
|
801
|
-
|
|
802
|
-
`consult(..., rounds=N)` enables 2-3 round critique loops. Round 1
|
|
803
|
-
runs the standard single-round flow. Round 2+ rebuilds the user
|
|
804
|
-
prompt as `<original artefact> + <prior round, anonymised>` so each
|
|
805
|
-
member can refine, agree, or push back on the previous critique
|
|
806
|
-
without seeing which provider produced which point.
|
|
807
|
-
|
|
808
|
-
The default round count comes from `defaults.min_rounds` in
|
|
809
|
-
`~/.event4u/agent-config/settings/.ai-council.yml` (default `2` so members critique each other
|
|
810
|
-
at least once before convergence). The host agent does **not** ask
|
|
811
|
-
"how many rounds?" when the requested count is `<= min_rounds` —
|
|
812
|
-
the settings owner already made that decision. Ask only when a
|
|
813
|
-
genuinely complex artefact justifies more depth than the default.
|
|
814
|
-
|
|
815
|
-
### Deep-reasoning tier (`council_depth: deep`)
|
|
816
|
-
|
|
817
|
-
Architecture review, refactoring proposals, and bug-diagnosis runs
|
|
818
|
-
benefit from an extra critique round. The deep tier is opt-in per
|
|
819
|
-
artefact:
|
|
820
|
-
|
|
821
|
-
1. The consuming **rule, skill, or command** declares
|
|
822
|
-
`council_depth: deep` in its frontmatter. The schema accepts
|
|
823
|
-
**only `deep`** — `standard` is the implicit default and is
|
|
824
|
-
rejected by the linter (every frontmatter byte costs context
|
|
825
|
-
window; see `scripts/schemas/{rule,skill,command}.schema.json`).
|
|
826
|
-
To return an artefact to default depth, **delete the key**.
|
|
827
|
-
2. The **host agent** reads that frontmatter when it dispatches the
|
|
828
|
-
council and passes `--depth deep` to `council_cli`. If multiple
|
|
829
|
-
active artefacts disagree, **deep wins** (max policy).
|
|
830
|
-
3. The **CLI** floors the round count at
|
|
831
|
-
`max(ai_council.deep_min_rounds, ai_council.min_rounds)` —
|
|
832
|
-
defaults to `3` and `2` respectively. Lowering `deep_min_rounds`
|
|
833
|
-
below `min_rounds` has no effect (defensive max).
|
|
834
|
-
|
|
835
|
-
The CLI itself has no knowledge of frontmatter; the contract is the
|
|
836
|
-
flag. Resolution chain (highest priority first):
|
|
837
|
-
|
|
838
|
-
```
|
|
839
|
-
--rounds N → explicit, any value (user override)
|
|
840
|
-
--depth deep → max(deep_min_rounds, min_rounds)
|
|
841
|
-
(no flag) → min_rounds (default 2)
|
|
842
|
-
```
|
|
843
|
-
|
|
844
|
-
| Property | Behaviour |
|
|
845
|
-
|---|---|
|
|
846
|
-
| Default count | `ai_council.min_rounds` (default `2`). Override per-invocation with `rounds:N` (or `--rounds N` to the CLI). |
|
|
847
|
-
| 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`. |
|
|
848
|
-
| Anonymisation | Provider/model identity is stripped. Reviewers are labelled `Reviewer A / B / C…` in input order. |
|
|
849
|
-
| Errored prior responses | Skipped — they reveal nothing useful and can leak provider error formats. |
|
|
850
|
-
| Cost budget | Accumulates across rounds. A round-2 call that breaches the cap fires `on_overrun` exactly like a round-1 breach. |
|
|
851
|
-
| Daily limit | Same — every billable round-2 call records spend in the rolling 24h ledger. |
|
|
852
|
-
| Return value | Final round only. Use `on_round_complete(round_idx, responses)` to capture intermediate rounds for rendering. |
|
|
853
|
-
|
|
854
|
-
> Iron Law: anonymisation is non-negotiable. If you ever need to
|
|
855
|
-
> surface "which model said what" between rounds, that is a different
|
|
856
|
-
> feature — debug-only, off by default, never enabled in user-facing
|
|
857
|
-
> output. The neutrality contract dies the moment a member learns it
|
|
858
|
-
> is talking to Claude vs GPT in round 2.
|
|
859
|
-
|
|
860
|
-
Pre-call estimate must surface the round count: total = `N × single-round cost`. Render inline:
|
|
861
|
-
|
|
862
|
-
```
|
|
863
|
-
External council call — billable · 2 rounds
|
|
864
|
-
Round 1: artefact only
|
|
865
|
-
Round 2: artefact + anonymised round 1 critiques
|
|
866
|
-
|
|
867
|
-
| member | per-round | × 2 |
|
|
868
|
-
|--------------------|----------:|--------:|
|
|
869
|
-
| anthropic/sonnet | $0.0176 | $0.0352 |
|
|
870
|
-
| openai/gpt-4o | $0.0121 | $0.0242 |
|
|
871
|
-
| **total** | | $0.0594 |
|
|
872
|
-
```
|
|
873
|
-
|
|
874
|
-
### Manual-mode parity
|
|
875
|
-
|
|
876
|
-
The orchestrator drives rounds the same way for `api` and `manual`
|
|
877
|
-
transports. One round = one full pass over every enabled member,
|
|
878
|
-
top-to-bottom, then `_augment_for_next_round()` folds the
|
|
879
|
-
anonymised critiques into the round-N+1 user prompt. For manual
|
|
880
|
-
mode this means: emit the round-1 block for member A → user
|
|
881
|
-
pastes A's reply → next member B → user pastes B's reply → host
|
|
882
|
-
agent consolidates round 1 → emit the round-2 block (now carrying
|
|
883
|
-
the anonymised round-1 critiques) for member A → … and so on
|
|
884
|
-
until the configured round count is reached. ManualClient's
|
|
885
|
-
internal "more feedback" follow-up loop (1 / 2 / 3 menu) is
|
|
886
|
-
**inside** a single member's chat thread and is orthogonal to the
|
|
887
|
-
orchestrator-level rounds.
|
|
888
|
-
|
|
889
|
-
### `/council debate` sub-command (progressive disclosure)
|
|
890
|
-
|
|
891
|
-
`/council debate <artefact> [--rounds N] [--continue-as-debate <session>]`
|
|
892
|
-
runs an **interactive** multi-round critique with a confirmation gate
|
|
893
|
-
between every round so the user can stop the spend at any point.
|
|
894
|
-
|
|
895
|
-
| Property | Behaviour |
|
|
896
|
-
|---|---|
|
|
897
|
-
| 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. |
|
|
898
|
-
| 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. |
|
|
899
|
-
| 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. |
|
|
900
|
-
| `--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. |
|
|
901
|
-
| Session files | One file per round under `agents/runtime/council/sessions/<slug>/debate-round-NN.md`. |
|
|
902
|
-
| Anonymisation | Identical to `rounds:N`. The continue-as-debate path also anonymises the seeded round-1 responses when building the round-2 prompt. |
|
|
903
|
-
|
|
904
|
-
Use this when the artefact is genuinely contentious and the user
|
|
905
|
-
wants to control depth interactively. For a fire-and-forget
|
|
906
|
-
multi-round run, prefer `consult(..., rounds=N)` or `--rounds N` on
|
|
907
|
-
`/council default`.
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
## Karpathy peer-review (opt-in)
|
|
911
|
-
|
|
912
|
-
After the final deliberation round, an optional **anonymous peer-review
|
|
913
|
-
pass** lets each member critique the *other* members' responses for
|
|
914
|
-
blind spots before synthesis. Inspired by Andrej Karpathy's "ask the
|
|
915
|
-
strongest models to review each other anonymously" pattern; see his
|
|
916
|
-
[talks / threads on inter-model critique](https://karpathy.ai/) and the
|
|
917
|
-
internal verdict in
|
|
918
|
-
`agents/runtime/council/sessions/2026-05-14-ai-council-redesign/round-2.md`
|
|
919
|
-
(R2 split: one approve-as-flag, one reject-as-default → opt-in only).
|
|
920
|
-
|
|
921
|
-
Pipeline order when every feature is active:
|
|
922
|
-
|
|
923
|
-
```
|
|
924
|
-
deliberation rounds → peer-review → consensus-scoring → synthesis
|
|
925
|
-
```
|
|
926
|
-
|
|
927
|
-
Activation — two equivalent paths:
|
|
928
|
-
|
|
929
|
-
* CLI: `--peer-review` on `council:estimate` or `council:run`.
|
|
930
|
-
* Config: `ai_council.peer_review.enabled: true` in
|
|
931
|
-
`~/.event4u/agent-config/settings/.ai-council.yml`. Default is `false`.
|
|
932
|
-
|
|
933
|
-
Mechanics:
|
|
934
|
-
|
|
935
|
-
1. The final deliberation round's outputs are anonymised into
|
|
936
|
-
`Response-A`, `Response-B`, … in stable input order. Provider /
|
|
937
|
-
model identity is stripped (Iron-Law neutrality holds); empty or
|
|
938
|
-
errored deliberation responses are skipped.
|
|
939
|
-
2. Each member receives an N−1 view (its own response filtered out)
|
|
940
|
-
plus the Karpathy prompt: *strongest response*, *weakest blind
|
|
941
|
-
spot*, *what did everyone miss*, *refinement*.
|
|
942
|
-
3. The N critiques flow back into synthesis through a
|
|
943
|
-
"Peer-Review-Surfaced Blind Spots" addendum on the lens template.
|
|
944
|
-
4. **Advisor preserve-persona (R4 Q3, hard-coded):** when the
|
|
945
|
-
deliberation was an advisor-mode run (Phase 6), anonymisation
|
|
946
|
-
strips provider identity but **preserves the advisor persona
|
|
947
|
-
label**. Peer-review renders as `Response A (Contrarian)`, never
|
|
948
|
-
`Response A (Anthropic Opus)`. Plain-member runs strip identity
|
|
949
|
-
entirely.
|
|
950
|
-
|
|
951
|
-
Cost — adds exactly N billable calls (one per member) at the same
|
|
952
|
-
per-call cost as a deliberation call. The `council:estimate` table
|
|
953
|
-
surfaces the delta as a `+peer-review: +N calls (~+$X)` row.
|
|
954
|
-
|
|
955
|
-
Needs ≥ 2 distinct deliberation outputs; below that the round is a
|
|
956
|
-
no-op and nothing extra is billed. Self-review is structurally
|
|
957
|
-
impossible — a member never sees its own response.
|
|
958
|
-
|
|
959
|
-
## Thinking-style advisors (replace-mode)
|
|
960
|
-
|
|
961
|
-
Phase 6 introduces five **advisor personas** that the council can adopt
|
|
962
|
-
in *replace-mode*: an enabled advisor substitutes its bound member's
|
|
963
|
-
plain call with the same provider running the advisor's persona prompt.
|
|
964
|
-
Total call count stays the same as a plain run — only the system prompt
|
|
965
|
-
swaps. Five advisors mirror an external advisor set, each a substantial
|
|
966
|
-
persona file (not a tagline):
|
|
967
|
-
|
|
968
|
-
| Advisor | Default bound member | Focus |
|
|
969
|
-
|---|---|---|
|
|
970
|
-
| **Contrarian** | `anthropic` | strongest counterargument, hidden assumptions |
|
|
971
|
-
| **First-Principles** | `anthropic` | strip metaphor, derive from physics / math / cost |
|
|
972
|
-
| **Expansionist** | `openai` | adjacent opportunities, second-order effects |
|
|
973
|
-
| **Outsider** | `openai` | naive-but-sharp questions, beginner's-mind probes |
|
|
974
|
-
| **Executor** | `anthropic` | what ships this quarter, what blocks delivery |
|
|
975
|
-
|
|
976
|
-
Activation — edit `~/.event4u/agent-config/settings/.ai-council.yml` and flip the advisor's
|
|
977
|
-
`enabled: true`. Optional `model: <name>` overrides the bound member's
|
|
978
|
-
default model. Validation rule: an advisor referencing a disabled
|
|
979
|
-
member fails closed at config load — never silently skipped.
|
|
980
|
-
|
|
981
|
-
```yaml
|
|
982
|
-
advisors:
|
|
983
|
-
contrarian:
|
|
984
|
-
enabled: true # ← swap anthropic's plain call for contrarian
|
|
985
|
-
member: anthropic
|
|
986
|
-
# model: claude-opus-4 # optional pin
|
|
987
|
-
```
|
|
988
|
-
|
|
989
|
-
`council:estimate` surfaces every active swap on a dedicated line above
|
|
990
|
-
the cost table:
|
|
991
|
-
|
|
992
|
-
```
|
|
993
|
-
council:estimate · mode=prompt · members=2 (billable=2)
|
|
994
|
-
advisor: Contrarian on anthropic via claude-sonnet-4-5
|
|
995
|
-
anthropic/claude-sonnet-4-5: ~991 in + 256 out = $0.0068
|
|
996
|
-
openai/gpt-4o: ~208 in + 256 out = $0.0031
|
|
997
|
-
```
|
|
998
|
-
|
|
999
|
-
Cost-bounded guarantee — replace-mode never adds calls. The advisor
|
|
1000
|
-
persona prompt is larger than a plain prompt (~1k extra input tokens
|
|
1001
|
-
per swap), so the per-call estimate widens slightly. Output tokens and
|
|
1002
|
-
call count are unaffected.
|
|
1003
|
-
|
|
1004
|
-
Peer-review interaction — when peer-review fires on an advisor-mode
|
|
1005
|
-
run, anonymisation **preserves the advisor persona label** while
|
|
1006
|
-
stripping provider identity: `Response A (Contrarian)` instead of bare
|
|
1007
|
-
`Response A`. See §Karpathy peer-review point 4 for the contract.
|
|
1008
|
-
|
|
1009
|
-
One-per-provider invariant — two enabled advisors targeting the same
|
|
1010
|
-
member is a config error (replace-mode runs exactly one advisor per
|
|
1011
|
-
provider; the call plan never doubles up by accident).
|
|
1012
|
-
|
|
1013
|
-
## Decision-replay artefact (Phase 9, audit trail)
|
|
1014
|
-
|
|
1015
|
-
Every session that runs consensus scoring drops a
|
|
1016
|
-
`decision-replay.md` next to the saved `responses.json`. Pure
|
|
1017
|
-
projection of the consensus block plus the final-round per-member
|
|
1018
|
-
texts — **no extra model calls, no extra spend**. Surfaces, per top
|
|
1019
|
-
finding: verdict band (Strong/Moderate/Weak), evidence-quality bucket
|
|
1020
|
-
(H/M/L), agree/dissent split, and one key argument per member.
|
|
1021
|
-
|
|
1022
|
-
Two render modes:
|
|
1023
|
-
|
|
1024
|
-
* **Full** (default) — per-member arguments attributed to
|
|
1025
|
-
`provider:model`. Reasoning is traceable, vendor identity is
|
|
1026
|
-
visible.
|
|
1027
|
-
* **Redacted** — verdict + evidence-quality + counts only. Use for
|
|
1028
|
-
surfaces where attributing reasoning to a specific model would leak
|
|
1029
|
-
vendor-preference signal.
|
|
1030
|
-
|
|
1031
|
-
Toggles (config, see `ai-council-config § Decision-replay artefact`):
|
|
1032
|
-
|
|
1033
|
-
* `ai_council.decision_replay.enabled` — master switch (default
|
|
1034
|
-
`true`).
|
|
1035
|
-
* `ai_council.decision_replay.include_member_arguments` — flip to
|
|
1036
|
-
`false` for redacted-by-default.
|
|
1037
|
-
* `ai_council.lenses.<lens>.decision_replay.*` — per-lens override
|
|
1038
|
-
beats the global block.
|
|
1039
|
-
|
|
1040
|
-
CLI:
|
|
1041
|
-
|
|
1042
|
-
* Written automatically by `council run` whenever the lens triggers
|
|
1043
|
-
consensus scoring.
|
|
1044
|
-
* `council replay <responses.json>` re-renders from a saved session;
|
|
1045
|
-
`--redact-member-arguments` / `--include-member-arguments` flip the
|
|
1046
|
-
view independent of config. Useful for sharing a redacted variant
|
|
1047
|
-
of an already-paid run.
|
|
1048
|
-
|
|
1049
|
-
## Lightweight-QA fast-path (Phase 11)
|
|
1050
|
-
|
|
1051
|
-
Low-impact questions classified by Phase 10's impact router can route
|
|
1052
|
-
to a restricted fast-path instead of the full debate loop. The
|
|
1053
|
-
trade-off is explicit: **1 round · ≤2 members · $0.05/answer · 2500
|
|
1054
|
-
tokens**. No advisors, no peer-review, no consensus scoring — the goal
|
|
1055
|
-
is a quick answer with a transparency marker, not a deliberation.
|
|
1056
|
-
|
|
1057
|
-
### Iron Law
|
|
1058
|
-
|
|
1059
|
-
`high_impact` and `user_required` **never** route to the fast-path,
|
|
1060
|
-
regardless of config. Schema validation rejects the override. The
|
|
1061
|
-
fast-path only activates when:
|
|
1062
|
-
|
|
1063
|
-
1. `ai_council.enabled: true` AND
|
|
1064
|
-
2. `decision_resolution.low_impact.mode: council` AND
|
|
1065
|
-
3. At least one member has `participate_low_impact: true` (default
|
|
1066
|
-
`false` — explicit opt-in per member).
|
|
1067
|
-
|
|
1068
|
-
Default route for `low_impact` is **`agent`** — nothing reaches the
|
|
1069
|
-
council without an explicit two-knob opt-in (flip the class to
|
|
1070
|
-
`council` *and* mark at least one member `participate_low_impact: true`).
|
|
1071
|
-
See [`ai-council-config § Low-impact council opt-in`](../../../docs/contracts/ai-council-config.md#low-impact-council-opt-in)
|
|
1072
|
-
for the worked YAML example, validation behaviour, and unavailable-marker
|
|
1073
|
-
contract.
|
|
1074
|
-
|
|
1075
|
-
### Output marker (always surfaced)
|
|
1076
|
-
|
|
1077
|
-
* **Resolved** — `> Resolved via low-impact council (anthropic): <one-line answer>`
|
|
1078
|
-
* **Split** — `> Low-impact council split — escalating to user (anthropic: X / openai: Y):`
|
|
1079
|
-
* **Aborted** — `> Low-impact council aborted (token cap) — escalating to user:`
|
|
1080
|
-
|
|
1081
|
-
The marker is mandatory: the agent never silently substitutes a
|
|
1082
|
-
fast-path verdict for its own answer.
|
|
1083
|
-
|
|
1084
|
-
### Session artefact
|
|
1085
|
-
|
|
1086
|
-
Every fast-path attempt appends one line to
|
|
1087
|
-
`agents/runtime/council/sessions/<date>-<slug>/low-impact-resolutions.md`:
|
|
1088
|
-
|
|
1089
|
-
```
|
|
1090
|
-
2025-05-14T10:00:00Z | resolved | members=2/2 | members(anthropic, openai) cost=$0.0034 | Q=Service vs Repository for this read path?
|
|
1091
|
-
```
|
|
1092
|
-
|
|
1093
|
-
Append-only, one line per resolution. The parser tolerates free-form
|
|
1094
|
-
section headers around the canonical lines, so the artefact may grow
|
|
1095
|
-
human notes without breaking aggregation.
|
|
1096
|
-
|
|
1097
|
-
### `council replay --low-impact-stats`
|
|
1098
|
-
|
|
1099
|
-
Re-projection of the session log into a summary block:
|
|
1100
|
-
|
|
1101
|
-
```
|
|
1102
|
-
$ council replay agents/runtime/council/sessions/2025-05-14-foo/responses.json --low-impact-stats
|
|
1103
|
-
# Low-impact fast-path · session summary
|
|
1104
|
-
|
|
1105
|
-
- attempts: 4
|
|
1106
|
-
- status: aborted=1 · resolved=2 · split=1
|
|
1107
|
-
- members: anthropic=4 · openai=3
|
|
1108
|
-
- total cost: $0.0096
|
|
1109
|
-
```
|
|
348
|
+
## Advanced modes
|
|
1110
349
|
|
|
1111
|
-
|
|
1112
|
-
|
|
350
|
+
Multi-round debate, the deep-reasoning tier, Karpathy peer-review, thinking-style
|
|
351
|
+
advisors, the decision-replay artefact and the Lightweight-QA fast-path moved
|
|
352
|
+
verbatim to [`references/advanced-modes.md`](references/advanced-modes.md). Each
|
|
353
|
+
is opt-in and each prices higher than a single round; none is a default.
|
|
1113
354
|
|
|
1114
355
|
## See also
|
|
1115
356
|
|