@event4u/agent-config 10.1.0 → 10.3.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 (158) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +110 -167
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/analyze/reference-repo.md +62 -0
  5. package/dist/agent-src/commands/roadmap/create.md +4 -1
  6. package/dist/agent-src/commands/roadmap/next.md +38 -0
  7. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +22 -1
  8. package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -1
  9. package/dist/agent-src/personas/advisors/first-principles.md +6 -0
  10. package/dist/agent-src/rules/active-remediation.md +53 -2
  11. package/dist/agent-src/rules/code-provenance.md +66 -4
  12. package/dist/agent-src/rules/content-quoting-floor.md +6 -0
  13. package/dist/agent-src/rules/context-hygiene.md +39 -0
  14. package/dist/agent-src/rules/design-fidelity.md +49 -3
  15. package/dist/agent-src/rules/token-budget-discipline.md +3 -2
  16. package/dist/agent-src/rules/token-efficiency.md +22 -0
  17. package/dist/agent-src/skills/ai-council/SKILL.md +28 -6
  18. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  19. package/dist/agent-src/skills/design-review/references/verification-automation.md +23 -1
  20. package/dist/agent-src/skills/fe-design/SKILL.md +27 -3
  21. package/dist/agent-src/skills/judge-synthesis/SKILL.md +30 -0
  22. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +11 -0
  23. package/dist/agent-src/skills/roadmap-writing/SKILL.md +9 -9
  24. package/dist/agent-src/skills/skill-writing/SKILL.md +4 -0
  25. package/dist/agent-src/skills/token-optimizer/SKILL.md +5 -1
  26. package/dist/agent-src/templates/agent-settings.md +12 -28
  27. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +2 -2
  28. package/dist/agent-src/templates/persona.md +26 -0
  29. package/dist/agent-src/templates/roadmaps.md +27 -7
  30. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -1
  31. package/dist/agent-src/templates/skill.md +35 -1
  32. package/dist/cli/commands/commands.candidates.test.js +257 -0
  33. package/dist/cli/commands/commands.candidates.test.js.map +1 -0
  34. package/dist/cli/commands/commands.js +199 -0
  35. package/dist/cli/commands/commands.js.map +1 -1
  36. package/dist/cli/main.js +1 -0
  37. package/dist/cli/main.js.map +1 -1
  38. package/dist/cli/registry.js +2 -2
  39. package/dist/cli/registry.js.map +1 -1
  40. package/dist/cli-delegate/{chunk-3JUTT26I.js → chunk-6ENSXSBW.js} +1 -1
  41. package/dist/cli-delegate/{chunk-TVGXH7VA.js → chunk-6LOPHJLD.js} +1 -1
  42. package/dist/cli-delegate/{chunk-XT2YTJCZ.js → chunk-AYKQGIBG.js} +4 -0
  43. package/dist/cli-delegate/{chunk-HJSKTMIF.js → chunk-BV3WR67D.js} +3 -19
  44. package/dist/cli-delegate/{chunk-HTIU3W56.js → chunk-BWMXLD4B.js} +6 -2
  45. package/dist/cli-delegate/{chunk-2H5SE7DU.js → chunk-FV34EGEX.js} +166 -39
  46. package/dist/cli-delegate/{chunk-XTC5ARB6.js → chunk-IR3IVRVC.js} +7 -2
  47. package/dist/cli-delegate/{chunk-LRXJK6GN.js → chunk-JMQZ7MM5.js} +1 -1
  48. package/dist/cli-delegate/{chunk-NX5AXSLD.js → chunk-X3VOARZD.js} +3 -3
  49. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  50. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  51. package/dist/cli-delegate/cmd_conformance.js +881 -204
  52. package/dist/cli-delegate/cmd_doctor.js +3 -3
  53. package/dist/cli-delegate/cmd_explain.js +2 -2
  54. package/dist/cli-delegate/cmd_export.js +4 -4
  55. package/dist/cli-delegate/cmd_handoff.js +6 -5
  56. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  57. package/dist/cli-delegate/cmd_migrate.js +2 -2
  58. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  59. package/dist/cli-delegate/cmd_prune.js +4 -4
  60. package/dist/cli-delegate/cmd_route_audit.js +2 -2
  61. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  62. package/dist/cli-delegate/cmd_session_recycle.js +44 -9
  63. package/dist/cli-delegate/cmd_settings_get.js +2 -2
  64. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  65. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  66. package/dist/cli-delegate/cmd_sync.js +4 -4
  67. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  68. package/dist/cli-delegate/cmd_update.js +1 -1
  69. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  70. package/dist/cli-delegate/cmd_validate.js +4 -4
  71. package/dist/cli-delegate/cmd_versions.js +1 -1
  72. package/dist/discovery/deprecation-report.md +1 -1
  73. package/dist/discovery/discovery-manifest.json +21 -21
  74. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  75. package/dist/discovery/discovery-manifest.summary.md +1 -1
  76. package/dist/discovery/dormancy-report.md +1 -1
  77. package/dist/discovery/orphan-report.md +1 -1
  78. package/dist/discovery/packs.json +2 -2
  79. package/dist/discovery/trust-report.md +1 -1
  80. package/dist/discovery/workspaces.json +2 -2
  81. package/dist/hooks/dispatch.js +204 -44
  82. package/dist/install/install.mjs +9 -21
  83. package/dist/mcp/registry-manifest.json +2 -2
  84. package/dist/mcp/server.json +2 -2
  85. package/dist/mcp/server.mjs +1337 -490
  86. package/dist/router.json +1 -1
  87. package/dist/scripts/_lib/agent_settings.js +25 -2
  88. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  89. package/dist/scripts/_lib/compile_time_toggles.js +4 -3
  90. package/dist/scripts/_lib/compile_time_toggles.js.map +1 -1
  91. package/dist/server/io/yamlIO.js +0 -2
  92. package/dist/server/io/yamlIO.js.map +1 -1
  93. package/dist/server/schemas/settings.js +3 -9
  94. package/dist/server/schemas/settings.js.map +1 -1
  95. package/dist/shared/settingsClasses.js +64 -2
  96. package/dist/shared/settingsClasses.js.map +1 -1
  97. package/dist/ui/assets/{index-B5qGYOJo.js → index-5fXOHoVh.js} +2 -2
  98. package/dist/ui/assets/index-5fXOHoVh.js.map +1 -0
  99. package/dist/ui/index.html +1 -1
  100. package/docs/contracts/settings-classes.md +307 -145
  101. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +54 -0
  102. package/docs/guidelines/agent-infra/layered-settings.md +1 -2
  103. package/docs/guidelines/agent-infra/symptom-driven-harvest-loop.md +104 -0
  104. package/docs/guidelines/design-antipatterns.md +79 -10
  105. package/docs/guidelines/design-fidelity-mechanics.md +120 -2
  106. package/package.json +1 -1
  107. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -1
  108. package/src/config/agent-settings.template.yml +12 -30
  109. package/src/config/gate-coverage.yml +42 -8
  110. package/src/config/gate-violation-baselines.json +15 -3
  111. package/src/config/profiles/balanced.ini +0 -2
  112. package/src/config/profiles/full.ini +1 -3
  113. package/src/config/profiles/minimal.ini +0 -2
  114. package/src/config/review-prompt-binding-baseline.json +19 -0
  115. package/src/config/rule-enforcement-baseline.json +0 -1
  116. package/src/scripts/_cli/cmd_session_recycle.ts +66 -9
  117. package/src/scripts/_cli/handoff_sessions.ts +3 -2
  118. package/src/scripts/_dispatch.bash +1 -0
  119. package/src/scripts/_lib/agent_settings.ts +25 -2
  120. package/src/scripts/_lib/bench_telegraph.ts +1 -1
  121. package/src/scripts/_lib/cc_transcript.ts +25 -0
  122. package/src/scripts/_lib/compile_time_toggles.ts +4 -3
  123. package/src/scripts/ai_council/clients.ts +243 -34
  124. package/src/scripts/cache_realization_report.ts +3 -2
  125. package/src/scripts/check_ci_local_parity.ts +60 -6
  126. package/src/scripts/check_review_prompt_binding.ts +553 -0
  127. package/src/scripts/check_rule_projection_integrity.ts +3 -1
  128. package/src/scripts/check_suppression_hygiene.ts +19 -3
  129. package/src/scripts/conformance_scan.ts +282 -9
  130. package/src/scripts/cost/track.mjs +10 -4
  131. package/src/scripts/council_cli.ts +33 -3
  132. package/src/scripts/design_slop_rules.test.ts +37 -6
  133. package/src/scripts/design_slop_rules.ts +150 -22
  134. package/src/scripts/dispatch_r2_reviewer.ts +15 -1
  135. package/src/scripts/external_sources_denylist.json +3 -1
  136. package/src/scripts/hook_manifest.yaml +17 -6
  137. package/src/scripts/hooks/block_unauthorized_git.ts +54 -8
  138. package/src/scripts/hooks/delegation_nudge_hook.ts +33 -8
  139. package/src/scripts/hooks/evidence_independence.ts +61 -9
  140. package/src/scripts/hooks/session_eol_hook.ts +123 -3
  141. package/src/scripts/hooks/turn_end_gate_hook.ts +31 -0
  142. package/src/scripts/hooks/ui_route_nudge_hook.ts +55 -2
  143. package/src/scripts/lint_design_antipattern_parity.ts +201 -0
  144. package/src/scripts/lint_harvest_provenance.ts +483 -0
  145. package/src/scripts/lint_settings_classes.ts +273 -11
  146. package/src/scripts/lint_skill_router_head.ts +254 -0
  147. package/src/scripts/lint_symptom_intake.ts +241 -0
  148. package/src/scripts/report_consultation_rate.ts +128 -2
  149. package/src/scripts/report_skill_activation.ts +6 -4
  150. package/src/scripts/report_skill_obligation_violations.ts +2 -1
  151. package/src/scripts/run_skill_evals.ts +10 -5
  152. package/src/scripts/schemas/persona.schema.json +8 -0
  153. package/src/scripts/schemas/provenance-harvest.schema.json +39 -0
  154. package/src/scripts/sweep_dead_scan_roots.ts +51 -0
  155. package/src/server/io/yamlIO.ts +0 -2
  156. package/src/server/schemas/settings.ts +3 -19
  157. package/src/shared/settingsClasses.ts +93 -2
  158. package/dist/ui/assets/index-B5qGYOJo.js.map +0 -1
@@ -27,7 +27,7 @@
27
27
  document.documentElement.setAttribute('data-theme', theme);
28
28
  })();
29
29
  </script>
30
- <script type="module" crossorigin src="/assets/index-B5qGYOJo.js"></script>
30
+ <script type="module" crossorigin src="/assets/index-5fXOHoVh.js"></script>
31
31
  <link rel="stylesheet" crossorigin href="/assets/index-jSfMW8_t.css">
32
32
  </head>
33
33
  <body>
@@ -187,10 +187,14 @@ dispatch runs, not WHETHER the layer exists, so they keep their own C rows.
187
187
 
188
188
  | Class | Keys |
189
189
  |---|---|
190
- | A — preference | 27 |
190
+ | A — preference | 26 |
191
191
  | B — consent | 3 |
192
- | C — guarded | 110 |
193
- | **Total** | **140** |
192
+ | C — guarded | 106 |
193
+ | **Total** | **135** |
194
+
195
+ The total was 140 until 2026-08-12, when five of the six keys no code path read were
196
+ deleted, minus the one held open (§ The six unread keys, below): one A
197
+ (`telegraph.speak_scope`) and four C.
194
198
 
195
199
  The total is every leaf in the template, where *leaf* means anything that is not
196
200
  a **non-empty** map. An empty map (like the former `subagents.host_capabilities: {}`) is a real
@@ -202,152 +206,274 @@ class is exactly what this contract exists to prevent.
202
206
  no row. It is a credential; were it ever uncommented it is C, and the lint would
203
207
  demand a row before the build went green.
204
208
 
209
+ ## The disposition axis — should the key exist at all?
210
+
211
+ A/B/C answers **who may write a key**. It does not answer **whether the key
212
+ should exist**, so a second, orthogonal axis carries that question. Every leaf
213
+ lands in exactly one disposition; a key with no disposition is the finding,
214
+ because it means nobody has said.
215
+
216
+ | Disposition | Meaning | Action |
217
+ |---|---|---|
218
+ | `derivable` | the mechanism itself can decide, from the situation, better than a flag can | delete; move the decision into the mechanism |
219
+ | `un-inferrable` | a fact about the human that nothing in the environment carries (name, language, IDE binary) | keep — this is the floor |
220
+ | `consent` | a standing authorisation for something the package would otherwise do to the user | keep, but re-examine whether the ACTION needs authorising at all |
221
+ | `policy` | a project-level fact the tree could carry instead (audience, jurisdiction) | move into the project surface, then delete the key |
222
+
223
+ **A `derivable` row must name its replacement**, written after an em dash:
224
+ `derivable — <what decides instead>`. That clause is the falsifier. Without it
225
+ the label degrades into a synonym for "inconvenient to keep", and the direction
226
+ of this axis pushes every borderline row toward exactly that. A row that cannot
227
+ name a concrete mechanism is reclassified, not deleted —
228
+ `lint_settings_classes` rejects the bare label.
229
+
230
+ **Spend and irreversible outward actions are never `derivable`.** A flag whose
231
+ stated purpose is to delay a mechanism usually prevents the evidence that would
232
+ justify the mechanism, which makes "should this run?" keys the strongest
233
+ deletion candidates — but a key that bounds cost or authorises something the
234
+ user cannot un-see is `consent` however inferable it looks. The direction is
235
+ toward fewer keys, not toward fewer confirmations.
236
+
237
+ The axis lives in the same table and the same gate as the class, deliberately.
238
+ A separate classification artefact would be a second thing to keep in sync with
239
+ the template, which is the drift this contract exists to prevent.
240
+
241
+ ## Dispositions
242
+
243
+ | Disposition | Keys |
244
+ |---|---|
245
+ | derivable | 83 |
246
+ | un-inferrable | 9 |
247
+ | consent | 38 |
248
+ | policy | 5 |
249
+ | **Total** | **135** |
250
+
251
+ First measured 2026-08-12 at 140 leaves (derivable 88 · consent 38 ·
252
+ un-inferrable 9 · policy 5), from the table below rather than predicted — the
253
+ numbers were deliberately not guessed in advance, because a target set before the
254
+ classification is a target the classification then argues toward. The six unread
255
+ keys were deleted the same day, which is where the −5 `derivable` comes from;
256
+ `consent` is unchanged because the one consent-classified key among them was
257
+ held open rather than deleted.
258
+
259
+ `derivable` is the **deletion queue, not a deletion**: a row stays until the
260
+ mechanism it names actually exists, so 83 measures work outstanding, not keys
261
+ about to disappear. The count is expected to fall while `un-inferrable` does not
262
+ — those 9 plus whatever survives re-examination in `consent` are the floor this
263
+ surface has, and stating it is the point. `policy` is the smallest class and the
264
+ only one whose action is a *move* rather than a keep or a delete: five keys carry
265
+ a project fact the tree could hold instead.
266
+
267
+ <<<<<<< HEAD
268
+ ## The floor — the nine keys no mechanism can derive
269
+
270
+ This is the residual set: not "what is left over today", but what stays after the
271
+ `derivable` queue drains to zero. A floor asserted without reasons is where the
272
+ next round quietly re-grows, so each key carries the argument for why the
273
+ situation cannot answer it. The test each one passes is **not** "hard to detect" —
274
+ it is that a probe could at best enumerate candidates while the *choice among them*
275
+ belongs to the human, and choosing wrong has a cost the agent cannot take back.
276
+
277
+ `consent` (38) and `policy` (5) are deliberately **not** part of this floor:
278
+ consent rows survive only what re-examination leaves of them, and every policy row
279
+ is scheduled to move into the project surface and then disappear. The floor is the
280
+ nine below.
281
+
282
+ | Key | Why nothing can derive it |
283
+ |---|---|
284
+ | `profile.id` | Selects which product surface is projected at all. The same repository is worked by a developer, a founder, and an ops engineer on different days — the axis is a fact about the person in the chair, and the tree carries no trace of it. |
285
+ | `personal.ide` | Names a binary the agent will execute. A probe can enumerate installed editors; it cannot know which one the human wants opened, and having several installed is the normal case rather than the ambiguous one. Guessing here does not misconfigure a preference, it runs the wrong program. |
286
+ | `personal.canary_name` | How the user wants to be addressed. `git config user.name` is a commit identity, not a form of address, and the two differ for most people who use a nickname at all — deriving one from the other is how the canary ends up greeting a stranger. |
287
+ | `subagents.model_map.lite` | Names an external model endpoint for the cheapest tier. Which endpoints an account can actually reach is not in the tree, and the only probe that would establish it is a paid call. |
288
+ | `subagents.model_map.medium` | Same, for the middle tier — and the tier boundaries are a spend judgement, not a capability fact, so even a complete endpoint list would not choose. |
289
+ | `subagents.model_map.high` | Same, for the top tier, where a wrong guess is the most expensive one available. |
290
+ | `subagents.implementer_model` | Names the endpoint that does the bulk of the work, so it is where a wrong default costs the most per run. Empty means "same tier as the session model", which is a deferral to a human choice already made, not a derivation. |
291
+ | `subagents.judge_model` | Names the endpoint that reviews the implementer. Its default is stated relative to the implementer rather than derived from the environment, and pinning it to a specific model is the reason someone sets it at all. |
292
+ | `ai_team.model` | Names the external model a teammate session runs. Availability is an account and auth fact that lives outside this repository entirely. |
293
+
294
+ Five of the nine are model endpoints, and they share one argument: an endpoint list
295
+ is account state, and the only mechanism that could observe it spends money to do
296
+ so. That is the shape of an `un-inferrable` row — not "we did not bother", but "the
297
+ observation is itself the thing the user is deciding whether to pay for".
298
+
299
+ ## The six unread keys — five deleted, one held open
300
+
301
+ **Six keys had no reader at all** — found while classifying, not sought:
302
+ `telegraph.speak_scope`, `chat_history.max_size_kb`, `chat_history.on_overflow`,
303
+ `quality.wait_for_remote_ci`, `screenshots.data_bearing_gate`, and
304
+ `legal_review_prep.consented_at`. Each was in the template, in the schema, on the
305
+ reference page, and in several cases in the setup wizard; none was consulted by
306
+ any code path. They were configured, documented, surfaced and inert. That is a
307
+ sharper finding than the 83, because a key nothing reads cannot be defended on
308
+ the grounds that someone depends on it.
309
+
310
+ **Five of the six are gone (2026-08-12, `road-to-zero-settings` Phase 2.1).**
311
+ They are the one batch whose removal is provably free: a key nothing reads
312
+ cannot change a default by leaving, so no replacement mechanism had to ship
313
+ first. Each carries its own reason string in `REMOVED_KEYS`, so an older install
314
+ that still sets one warns once and boots unchanged.
315
+
316
+ The sixth, `screenshots.data_bearing_gate`, **stays** — and the reason it stays
317
+ is the finding, not an exception. It is `consent`, and its missing reader means
318
+ the authorisation it appears to carry is not enforced anywhere. Deleting it
319
+ would remove the appearance of a gate and leave the unguarded action; the
320
+ repair is to build the reader, which is Phase 3 work with a real behaviour
321
+ change behind it. `legal_review_prep.consented_at` looked like the same case and
322
+ is not: it is the *timestamp* of a consent whose actual gate is
323
+ `legal_review_prep.acknowledged`, which is read and stays.
324
+
325
+ **The counter-argument is recorded rather than settled**, because it was raised
326
+ against this decision in parallel and is not obviously wrong: a data-bearing
327
+ screenshot embed is a *published egress*, so its confirmation routes into
328
+ `non-destructive-by-default`, which refuses a settings override by construction.
329
+ On that reading an `off` could never have been honoured at all, the reference
330
+ page advertises an opt-out that cannot exist, and the key is `derivable` with the
331
+ unconditional gate in `doc-screenshot-hygiene` as its replacement. Which reading
332
+ wins decides whether Phase 3 builds a reader or deletes a false promise, so it is
333
+ a product call and it is left to the maintainer. Kept as-is meanwhile: the
334
+ conservative side of that disagreement is the one that changes nothing.
335
+
205
336
  ## The table
206
337
 
207
338
  Rows follow template order, so a diff against the template reads straight down.
208
339
 
209
- | Key | Class | Default | Why |
210
- |---|---|---|---|
211
- | `agent_config_version` | C | `""` | installer-owned pin selecting which package code executes |
212
- | `profile.id` | C | `developer` | master axis selecting the projected skill and command surface |
213
- | `projection.mode` | C | `scoped` | governs which artefacts reach the host trees at all |
214
- | `projection.rule_workspaces` | C | 9 workspaces | allowlist deciding which rules reach the agent |
215
- | `projection.rule_packs` | C | `[]` | second allowlist axis on rule projection |
216
- | `discipline_profile` | C | `__DISCIPLINE_PROFILE__` | master switch for the discipline rule tier |
217
- | `rule_loading_tier` | C | `__RULE_LOADING_TIER__` | legacy master switch for rule loading |
218
- | `lean_projection.mode` | C | `eager-all` | `thin` removes rule bodies from the agent's context |
219
- | `telegraph.speak` | C | `false` | ships a rule body; a token-cost lever in both directions |
220
- | `telegraph.speak_scope` | A | `"off"` | output register once that rule ships |
221
- | `tokens.rich_skills` | C | `"on"` | token-spend lever |
222
- | `cost.budgets.daily` | C | `0` | rolling spend ceiling |
223
- | `cost.budgets.weekly` | C | `0` | rolling spend ceiling |
224
- | `cost.budgets.monthly` | C | `0` | rolling spend ceiling |
225
- | `cost.budgets.per_tier.cheap` | C | `null` | per-tier spend ceiling |
226
- | `cost.budgets.per_tier.medium` | C | `null` | per-tier spend ceiling |
227
- | `cost.budgets.per_tier.strong` | C | `null` | per-tier spend ceiling |
228
- | `cost.enforcement` | C | `advisory` | decides whether a breach blocks or is merely logged |
229
- | `model.auto_switch` | C | `suggest` | authorises native model overrides, which is spend |
230
- | `personal.ide` | C | `""` | names a binary the agent would execute |
231
- | `personal.open_edited_files` | B | `false` | starts invoking that binary on every edit |
232
- | `personal.rtk_installed` | A | `false` | auto-detected machine fact |
233
- | `personal.minimal_output` | A | `true` | reply-shape preference |
234
- | `personal.play_by_play` | A | `false` | narration preference |
235
- | `personal.canary_name` | B | `""` | arms the session-degradation canary |
236
- | `personal.pr_comment_bot_icon` | A | `false` | comment cosmetics |
237
- | `personal.pr_progress_comments` | C | `false` | authorises unsolicited outbound comments on a PR |
238
- | `personal.autonomy` | C | `auto` | suppresses confirmation questions |
239
- | `personal.user_type` | C | `"__USER_TYPE__"` | master axis filtering the projected surface |
240
- | `verbosity.intent_announcements` | A | `false` | narration preference |
241
- | `verbosity.preview_artifacts` | C | `false` | removes pre-action review of commits, PRs, and branches |
242
- | `verbosity.routine_confirmations` | C | `false` | removes confirmation prompts |
243
- | `verbosity.offer_council_in_delivery` | A | `false` | offers a paid step; never takes it |
244
- | `verbosity.post_action_reports` | A | `minimal` | size of a status block |
245
- | `project.pr_template` | C | `.github/pull_request_template.md` | filesystem path whose contents reach an outbound PR |
246
- | `project.upstream_repo` | C | `""` | destination of outbound improvement PRs |
247
- | `project.improvement_pr_branch_prefix` | A | `improve/agent-` | branch-name cosmetics |
248
- | `project.audience` | C | `public` | C-test 4 — it governs the agent's own reasoning discipline: `self` makes the § 8-pre demand gate inert. Who a project is built for is a fact only its maintainer knows, so the agent never infers it and never asks; hand-edit or the GUI write route. The default is today's behaviour, so an install that never sets it is unchanged |
249
- | `github.pr_reply_method` | A | `create_review_comment` | picks between two endpoints of one operation |
250
- | `augment.rules_use_symlinks` | A | `false` | reversible install mechanics |
251
- | `eloquent.access_style` | A | `getters_setters` | code convention |
252
- | `chat_history.enabled` | C | `true` | kill-switch over a path that writes conversation content to disk |
253
- | `chat_history.frequency` | C | `__CHAT_HISTORY_FREQUENCY__` | capture granularity — a value that reduces what is captured erases the trail |
254
- | `chat_history.max_size_kb` | C | `__CHAT_HISTORY_MAX_SIZE_KB__` | cap on how much conversation lands on disk |
255
- | `chat_history.on_overflow` | C | `__CHAT_HISTORY_ON_OVERFLOW__` | decides what survives when the log fills; an audit-integrity choice, not a preference |
256
- | `chat_history.text_limits.user` | C | `0` | cap on how much user text is written to disk |
257
- | `chat_history.text_limits.agent` | C | `5000` | cap on how much agent text is written to disk |
258
- | `chat_history.text_limits.tool` | C | `200` | cap on how much tool payload is written to disk |
259
- | `chat_history.text_limits.phase` | C | `200` | cap on how much phase text is written to disk |
260
- | `pipelines.skill_improvement` | A | `true` | proposes a capture; the user still decides |
261
- | `reasoning.enabled` | C | `true` | master switch for the agent's own reasoning discipline |
262
- | `reasoning.auto_gate` | C | `true` | decides when that discipline engages |
263
- | `reasoning.components.orchestrator` | C | `true` | a component of the agent's own discipline |
264
- | `reasoning.components.notes_first` | C | `true` | a component of the agent's own discipline |
265
- | `reasoning.components.grounding` | C | `true` | a component of the agent's own discipline |
266
- | `reasoning.components.intent` | C | `true` | a component of the agent's own discipline |
267
- | `reasoning.components.complexity_first` | C | `true` | a component of the agent's own discipline |
268
- | `reasoning.components.verifier_default` | C | `true` | disabling it removes a verification step |
269
- | `reasoning.components.prediction_tracking` | C | `true` | a component of the agent's own discipline |
270
- | `reasoning.components.decision_ledger` | C | `true` | a component of the agent's own discipline |
271
- | `reasoning.components.uncertainty_budget` | C | `true` | a component of the agent's own discipline |
272
- | `roadmap.skip_pre_run_gate` | C | `true` | disables a pre-run confirmation gate |
273
- | `roadmap.quality_cadence` | C | `end_of_roadmap` | governs when verification runs |
274
- | `roadmap.dashboard_regen_cadence` | A | `every_5_steps` | beat of a derived view |
275
- | `roadmap.horizon_weeks` | C | `0` | a non-zero value relaxes a lint's plate-token ban |
276
- | `planning.challenge_on_create` | C | `true` | disables the plan-confidence gate |
277
- | `planning.risk_review` | C | `true` | disables the risk-register validator |
278
- | `planning.completion_review` | C | `true` | disables the completion-review validator |
279
- | `quality.local_auto_run` | C | `false` | governs whether local verification runs at all |
280
- | `quality.wait_for_remote_ci` | C | `false` | governs whether the authoritative gate is waited on |
281
- | `design.fidelity_mode` | C | `strict` | strict-mode selector, one of whose values is a Hard Floor |
282
- | `consistency.cross_source` | C | `"on"` | disables the cross-source discrepancy gate |
283
- | `screenshots.identity_allowlist` | C | `[]` | allowlist of identities that ship unredacted |
284
- | `screenshots.forbid_terminal_capture` | C | `true` | kill-switch over the highest-leak capture path |
285
- | `screenshots.data_bearing_gate` | C | `"on"` | the human-confirmation gate over a published egress |
286
- | `code_style.docblocks` | A | `minimal` | code convention |
287
- | `subagents.downshift` | C | `true` | routes to another model tier, which is spend and quality |
288
- | `subagents.quota_arbitrage` | C | `true` | spends from a separate quota pool |
289
- | `subagents.model_map.lite` | C | `""` | names an external model endpoint |
290
- | `subagents.model_map.medium` | C | `""` | names an external model endpoint |
291
- | `subagents.model_map.high` | C | `""` | names an external model endpoint |
292
- | `subagents.implementer_model` | C | `""` | names an external model endpoint |
293
- | `subagents.judge_model` | C | `""` | names an external model endpoint |
294
- | `subagents.model_ceiling` | C | `""` | session-wide subagent model cap (exported as `CLAUDE_CODE_SUBAGENT_MODEL` by suite-owned CLI spawn wrappers), which is spend and quality |
295
- | `subagents.max_parallel` | C | `3` | parallelism cap, and therefore a spend rate |
296
- | `subagents.adversarial_council` | C | `"off"` | governs a paid verification step |
297
- | `worktrees.mode` | C | `ask` | standing permission for autonomous worktree creation |
298
- | `ai_team.model` | C | `auto` | names an external model |
299
- | `ai_team.allow_delegate` | C | `false` | grants an external tool write access to the repository |
300
- | `ai_team.max_calls_per_day` | C | `50` | quota cap on a shared budget |
301
- | `ai_team.suppress_setup_hint` | A | `false` | hint cosmetics |
302
- | `ai_team.review_gate.managed` | C | `false` | governs an upstream review gate |
303
- | `ai_team.review_gate.max_consecutive_blocks` | C | `3` | circuit-breaker threshold |
304
- | `emergency.orchestration_halt` | C | `false` | the one audited incident switch over the always-on orchestration stack — see § The one exception above |
305
- | `emergency.orchestration_halt_justification` | C | `""` | required non-empty before the halt may be lifted; an audit-trail field |
306
- | `onboarding.onboarded` | C | `false` | flipping it bypasses the onboarding gate |
307
- | `commands.auto_detect` | C | `enabled` | kill-switch for orchestrator auto-detection |
308
- | `commands.suggestion.enabled` | A | `true` | a convenience layer; governs no gate and no spend |
309
- | `commands.suggestion.confidence_floor` | A | `0.6` | tuning of that convenience layer |
310
- | `commands.suggestion.cooldown_seconds` | A | `600` | tuning of that convenience layer |
311
- | `commands.suggestion.max_options` | A | `4` | tuning of that convenience layer |
312
- | `commands.suggestion.blocklist` | C | `[]` | a deny-list |
313
- | `commands.create_pr.preview_description` | C | `false` | removes pre-publish review of an outbound artefact |
314
- | `commands.create_pr.detail_level` | A | `min` | verbosity of a generated body |
315
- | `commands.create_pr.api_examples` | A | `true` | verbosity of a generated body |
316
- | `commands.create_pr.screenshots` | C | `false` | puts captured screenshots into a published PR body |
317
- | `commands.create_pr.ui_paths` | C | `[]` | glob allowlist |
318
- | `commands.create_pr.api_paths` | C | `[]` | glob allowlist |
319
- | `memory.cadence` | C | `always` | suppressing the visibility line hides what the agent learned from the user |
320
- | `memory.review_threshold` | A | `10` | when a review preview surfaces; governs no gate |
321
- | `memory.redact_patterns` | C | `[]` | deny-list of secret and PII regexes |
322
- | `memory.session_index` | A | `"off"` | injects a compact index at session start |
323
- | `memory.learn_on_session_end` | B | `false` | turns on automatic memory writes at session end |
324
- | `knowledge.global_sharing.enabled` | C | `true` | kill-switch over cross-project egress |
325
- | `knowledge.global_sharing.allowed_tiers` | C | `[public]` | allowlist for that egress |
326
- | `knowledge.global_sharing.redaction.enabled` | C | `true` | disabling it removes the redaction floor |
327
- | `knowledge.global_sharing.redaction.halt_on_trigger` | C | `true` | disabling it removes halt-and-prompt |
328
- | `knowledge.global_sharing.auto_promote_threshold` | C | `2` | threshold governing that egress |
329
- | `knowledge.global_sharing.freshness.hypothesis_after_days` | A | `90` | freshness heuristic on a card already shared |
330
- | `knowledge.global_sharing.freshness.stale_after_days` | A | `180` | freshness heuristic on a card already shared |
331
- | `hooks.concern_budget.max_per_event` | C | `8` | budget cap on hook concerns |
332
- | `hooks.concern_budget.tier1_concerns` | C | `[]` | allowlist of concerns permitted to fail closed |
333
- | `hooks.concern_budget.hard_fail` | C | `false` | weakens the budget gate to warn-only |
334
- | `hooks.injection_scan.enabled` | C | `false` | the prompt-injection scanner |
335
- | `hooks.rtk_wrap.enabled` | C | `false` | configures code that runs on every tool call |
336
- | `hooks.design_slop.enabled` | C | `false` | configures code that runs on every tool call |
337
- | `hooks.ui_route_nudge.enabled` | C | `false` | configures code that runs on every tool call |
338
- | `hooks.code_graph.enabled` | C | `false` | configures code that runs on every tool call |
339
- | `decision_engine.surface_traces` | C | `false` | the decision engine’s own black box; the agent must not be able to close it |
340
- | `decision_engine.min_confidence` | C | `"off"` | the confidence gate |
341
- | `decision_engine.block_on_risk` | C | `"off"` | the risk-class gate |
342
- | `decision_engine.require_memory_hits` | C | `false` | a phase gate |
343
- | `decision_engine.on_block` | C | `stop` | `warn` advances past a gate that fired |
344
- | `decision_engine.ask_timeout_seconds` | C | `30` | how long a fired gate waits before falling back |
345
- | `decision_engine.on_block_fallback` | C | `stop` | fail-safe versus fail-open after that timeout |
346
- | `update_check.enabled` | C | `true` | a background safety check; disabling it pins the user to known-vulnerable code |
347
- | `explain.enable_last` | A | `true` | a read-only diagnostics surface |
348
- | `legal_review_prep.acknowledged` | C | `false` | the consent gate; the safety floor requires the wizard checkbox |
349
- | `legal_review_prep.consented_at` | C | `""` | the record of that consent |
350
- | `legal_review_prep.require_council` | C | `true` | a fail-closed defence-in-depth gate |
340
+ | Key | Class | Default | Why | Disposition |
341
+ |---|---|---|---|---|
342
+ | `agent_config_version` | C | `""` | installer-owned pin selecting which package code executes | derivable — the installed package's own `package.json` version; `check_template_pin_drift` already enforces pin == package.json |
343
+ | `profile.id` | C | `developer` | master axis selecting the projected skill and command surface | un-inferrable |
344
+ | `projection.mode` | C | `scoped` | governs which artefacts reach the host trees at all | derivable — the resolved active-profile + `runtime.active_packs` set `_resolve_scoped_projection` already computes |
345
+ | `projection.rule_workspaces` | C | 9 workspaces | allowlist deciding which rules reach the agent | derivable — the rule's own `workspaces:` frontmatter intersected with the active profile/pack set, as `rule_scope.ts` already performs for `rule_packs: auto` |
346
+ | `projection.rule_packs` | C | `[]` | second allowlist axis on rule projection | derivable — the `auto` derivation already implemented in `src/install/rule_scope.ts` |
347
+ | `discipline_profile` | C | `__DISCIPLINE_PROFILE__` | master switch for the discipline rule tier | derivable — its own `auto` resolution against `src/config/host-capabilities.yml` |
348
+ | `rule_loading_tier` | C | `__RULE_LOADING_TIER__` | legacy master switch for rule loading | derivable — `discipline_profile` supersedes it with a documented mapping (minimal→off, balanced→essential, full→full) |
349
+ | `lean_projection.mode` | C | `eager-all` | `thin` removes rule bodies from the agent's context | derivable — `probe_host_compliance.ts` already computes the per-host thin/eager recommendation |
350
+ | `telegraph.speak` | C | `false` | ships a rule body; a token-cost lever in both directions | derivable — the telegraph kill-criterion bench verdict is a package-level decision, not a per-install one |
351
+ | `tokens.rich_skills` | C | `"on"` | token-spend lever | derivable — the skill's own `token_budget_class: rich` declaration plus the CI ceiling in `lint_token_budget_discipline.ts` |
352
+ | `cost.budgets.daily` | C | `0` | rolling spend ceiling | consent |
353
+ | `cost.budgets.weekly` | C | `0` | rolling spend ceiling | consent |
354
+ | `cost.budgets.monthly` | C | `0` | rolling spend ceiling | consent |
355
+ | `cost.budgets.per_tier.cheap` | C | `null` | per-tier spend ceiling | consent |
356
+ | `cost.budgets.per_tier.medium` | C | `null` | per-tier spend ceiling | consent |
357
+ | `cost.budgets.per_tier.strong` | C | `null` | per-tier spend ceiling | consent |
358
+ | `cost.enforcement` | C | `advisory` | decides whether a breach blocks or is merely logged | consent |
359
+ | `model.auto_switch` | C | `suggest` | authorises native model overrides, which is spend | consent |
360
+ | `personal.ide` | C | `""` | names a binary the agent would execute | un-inferrable |
361
+ | `personal.open_edited_files` | B | `false` | starts invoking that binary on every edit | consent |
362
+ | `personal.rtk_installed` | A | `false` | auto-detected machine fact | derivable — the wizard's own two-stage PATH probe (`which rtk` plus an identity check), which already overwrites the key |
363
+ | `personal.minimal_output` | A | `true` | reply-shape preference | derivable — `direct-answers` Iron Law 3 already fixes reply length per reply |
364
+ | `personal.play_by_play` | A | `false` | narration preference | derivable — `direct-answers`' narration ban is the standing default; an in-turn request is the only thing that lifts it |
365
+ | `personal.canary_name` | B | `""` | arms the session-degradation canary | un-inferrable |
366
+ | `personal.pr_comment_bot_icon` | A | `false` | comment cosmetics | derivable — `no-decorative-emojis-in-git-surfaces` already forbids the icon in PR comments |
367
+ | `personal.pr_progress_comments` | C | `false` | authorises unsolicited outbound comments on a PR | consent |
368
+ | `personal.autonomy` | C | `auto` | suppresses confirmation questions | derivable — `no-cheap-questions`' mode-independent Pre-Send Self-Check decides per question |
369
+ | `personal.user_type` | C | `"__USER_TYPE__"` | master axis filtering the projected surface | derivable — `profile.id` already carries the persona axis over a near-identical value set |
370
+ | `verbosity.intent_announcements` | A | `false` | narration preference | derivable — `personal.play_by_play` already gates the narration carve-out this key sits under |
371
+ | `verbosity.preview_artifacts` | C | `false` | removes pre-action review of commits, PRs, and branches | derivable — the Iron-Law gates already decide which artefacts need a pre-action look |
372
+ | `verbosity.routine_confirmations` | C | `false` | removes confirmation prompts | derivable — `no-cheap-questions`' Pre-Send Self-Check already decides whether a confirmation carries a real trade-off |
373
+ | `verbosity.offer_council_in_delivery` | A | `false` | offers a paid step; never takes it | derivable — `agent-config council:status`, which answers whether there is anything to offer |
374
+ | `verbosity.post_action_reports` | A | `minimal` | size of a status block | derivable — `direct-answers` Iron Law 3 and the reply-close contract already fix the status block to ONE end-summary |
375
+ | `project.pr_template` | C | `.github/pull_request_template.md` | filesystem path whose contents reach an outbound PR | derivable — GitHub's own PR-template resolution order; the key only caches a filesystem lookup |
376
+ | `project.upstream_repo` | C | `""` | destination of outbound improvement PRs | derivable — the installed package's own `package.json` repository field |
377
+ | `project.improvement_pr_branch_prefix` | A | `improve/agent-` | branch-name cosmetics | derivable — the repo's own branch-naming convention, observable from `git branch -r` |
378
+ | `project.audience` | C | `public` | C-test 4 — it governs the agent's own reasoning discipline: `self` makes the § 8-pre demand gate inert. Who a project is built for is a fact only its maintainer knows, so the agent never infers it and never asks; hand-edit or the GUI write route. The default is today's behaviour, so an install that never sets it is unchanged | policy |
379
+ | `github.pr_reply_method` | A | `create_review_comment` | picks between two endpoints of one operation | derivable — the `auto` value already in the enum: the routing detects the working endpoint on first use and writes it back |
380
+ | `augment.rules_use_symlinks` | A | `false` | reversible install mechanics | derivable — dev-mode detection at install time plus a symlink-capability probe on the target filesystem |
381
+ | `eloquent.access_style` | A | `getters_setters` | code convention | derivable — the convention the project's existing models already use; `standards-from-config` reads it off the tree |
382
+ | `chat_history.enabled` | C | `true` | kill-switch over a path that writes conversation content to disk | consent |
383
+ | `chat_history.frequency` | C | `__CHAT_HISTORY_FREQUENCY__` | capture granularity — a value that reduces what is captured erases the trail | consent |
384
+ | `chat_history.text_limits.user` | C | `0` | cap on how much user text is written to disk | consent |
385
+ | `chat_history.text_limits.agent` | C | `5000` | cap on how much agent text is written to disk | consent |
386
+ | `chat_history.text_limits.tool` | C | `200` | cap on how much tool payload is written to disk | consent |
387
+ | `chat_history.text_limits.phase` | C | `200` | cap on how much phase text is written to disk | consent |
388
+ | `pipelines.skill_improvement` | A | `true` | proposes a capture; the user still decides | derivable — the pipeline's own trigger condition; the capture is already a user-confirmed proposal |
389
+ | `reasoning.enabled` | C | `true` | master switch for the agent's own reasoning discipline | derivable — the RDP gate's own task-triviality and host self-assessment signals already decide per turn |
390
+ | `reasoning.auto_gate` | C | `true` | decides when that discipline engages | derivable — it only removes the RDP gate's host self-assessment signal, its cheapest and most situational input |
391
+ | `reasoning.components.orchestrator` | C | `true` | a component of the agent's own discipline | derivable — the RDP gate's task signal (complex / multi-component vs trivial) |
392
+ | `reasoning.components.notes_first` | C | `true` | a component of the agent's own discipline | derivable — the RDP gate's task signal; the notes file only exists once the gate engaged |
393
+ | `reasoning.components.grounding` | C | `true` | a component of the agent's own discipline | derivable — `think-before-action`'s own info-gap condition, which `source-discovery-gate` already tests |
394
+ | `reasoning.components.intent` | C | `true` | a component of the agent's own discipline | derivable — the RDP gate's host self-assessment signal |
395
+ | `reasoning.components.complexity_first` | C | `true` | a component of the agent's own discipline | derivable — the RDP gate's task signal (a load-bearing unknown exists or it does not) |
396
+ | `reasoning.components.verifier_default` | C | `true` | disabling it removes a verification step | derivable — the verifier's own structural-complexity gate |
397
+ | `reasoning.components.prediction_tracking` | C | `true` | a component of the agent's own discipline | derivable — the RDP gate's task signal; a turn with no prediction to log produces no entry |
398
+ | `reasoning.components.decision_ledger` | C | `true` | a component of the agent's own discipline | derivable — the escalation litmus in `notes-first-reasoning` (tactical to notes, durable to ADR) |
399
+ | `reasoning.components.uncertainty_budget` | C | `true` | a component of the agent's own discipline | derivable — the RDP gate's task signal; the score feeds adaptive effort only where the gate already engaged |
400
+ | `roadmap.skip_pre_run_gate` | C | `true` | disables a pre-run confirmation gate | derivable — the pre-run gate's own ambiguity condition; a genuine ambiguity prompts regardless |
401
+ | `roadmap.quality_cadence` | C | `end_of_roadmap` | governs when verification runs | derivable — `quality.local_auto_run` decides whether local verification runs, and the `verify-before-complete` evidence gate decides the moment |
402
+ | `roadmap.dashboard_regen_cadence` | A | `every_5_steps` | beat of a derived view | derivable — the dashboard is derived: `roadmap:progress` regenerates deterministically from the roadmap files |
403
+ | `roadmap.horizon_weeks` | C | `0` | a non-zero value relaxes a lint's plate-token ban | policy |
404
+ | `planning.challenge_on_create` | C | `true` | disables the plan-confidence gate | derivable — the gate's own confidence conditions; a confident plan passes straight through |
405
+ | `planning.risk_review` | C | `true` | disables the risk-register validator | derivable — `lint_plan_risk_register`'s own scope predicate (ready, non-draft plans only) |
406
+ | `planning.completion_review` | C | `true` | disables the completion-review validator | derivable — `check_completion_review`'s own scope predicate, bound to the current diff hash |
407
+ | `quality.local_auto_run` | C | `false` | governs whether local verification runs at all | consent |
408
+ | `design.fidelity_mode` | C | `strict` | strict-mode selector, one of whose values is a Hard Floor | policy |
409
+ | `consistency.cross_source` | C | `"on"` | disables the cross-source discrepancy gate | derivable — the rule's own trigger condition; a discrepancy exists only when two present sources contradict |
410
+ | `screenshots.identity_allowlist` | C | `[]` | allowlist of identities that ship unredacted | consent |
411
+ | `screenshots.forbid_terminal_capture` | C | `true` | kill-switch over the highest-leak capture path | consent |
412
+ | `screenshots.data_bearing_gate` | C | `"on"` | the human-confirmation gate over a published egress | consent |
413
+ | `code_style.docblocks` | A | `minimal` | code convention | derivable — the project's own linter/style config and the docblock density of the touched file, which `standards-from-config` reads off the tree |
414
+ | `subagents.downshift` | C | `true` | routes to another model tier, which is spend and quality | derivable — the per-slice tier assignment in `auto-dispatch-classification`, which the orchestrator already computes per dispatch |
415
+ | `subagents.quota_arbitrage` | C | `true` | spends from a separate quota pool | consent |
416
+ | `subagents.model_map.lite` | C | `""` | names an external model endpoint | un-inferrable |
417
+ | `subagents.model_map.medium` | C | `""` | names an external model endpoint | un-inferrable |
418
+ | `subagents.model_map.high` | C | `""` | names an external model endpoint | un-inferrable |
419
+ | `subagents.implementer_model` | C | `""` | names an external model endpoint | un-inferrable |
420
+ | `subagents.judge_model` | C | `""` | names an external model endpoint | un-inferrable |
421
+ | `subagents.model_ceiling` | C | `""` | session-wide subagent model cap (exported as `CLAUDE_CODE_SUBAGENT_MODEL` by suite-owned CLI spawn wrappers), which is spend and quality | consent |
422
+ | `subagents.max_parallel` | C | `3` | parallelism cap, and therefore a spend rate | consent |
423
+ | `subagents.adversarial_council` | C | `"off"` | governs a paid verification step | consent |
424
+ | `worktrees.mode` | C | `ask` | standing permission for autonomous worktree creation | consent |
425
+ | `ai_team.model` | C | `auto` | names an external model | un-inferrable |
426
+ | `ai_team.allow_delegate` | C | `false` | grants an external tool write access to the repository | consent |
427
+ | `ai_team.max_calls_per_day` | C | `50` | quota cap on a shared budget | consent |
428
+ | `ai_team.suppress_setup_hint` | A | `false` | hint cosmetics | derivable — the hint's own precondition; `agent-config doctor --check team` already knows whether team mode is configured |
429
+ | `ai_team.review_gate.managed` | C | `false` | governs an upstream review gate | consent |
430
+ | `ai_team.review_gate.max_consecutive_blocks` | C | `3` | circuit-breaker threshold | derivable — the existing N=3 validation-loop budget in `autonomous-execution`, which already bounds consecutive failed attempts on one target |
431
+ | `emergency.orchestration_halt` | C | `false` | the one audited incident switch over the always-on orchestration stack — see § The one exception above | consent |
432
+ | `emergency.orchestration_halt_justification` | C | `""` | required non-empty before the halt may be lifted; an audit-trail field | consent |
433
+ | `onboarding.onboarded` | C | `false` | flipping it bypasses the onboarding gate | derivable — the wizard's own completion artefacts; the onboarding hook can read whether setup actually ran instead of trusting a self-reported flag |
434
+ | `commands.auto_detect` | C | `enabled` | kill-switch for orchestrator auto-detection | derivable — the orchestrator's own confidence-tiered detection table plus the non-interactive TTY/CI probe |
435
+ | `commands.suggestion.enabled` | A | `true` | a convenience layer; governs no gate and no spend | derivable — the suggester's own match-score threshold and cooldown; a prompt that matches nothing already produces silence |
436
+ | `commands.suggestion.confidence_floor` | A | `0.6` | tuning of that convenience layer | derivable — the suggester's calibrated constant, with the existing per-command frontmatter override where one command needs a different bar |
437
+ | `commands.suggestion.cooldown_seconds` | A | `600` | tuning of that convenience layer | derivable — the per-command cooldown tracker, which already reads session behaviour |
438
+ | `commands.suggestion.max_options` | A | `4` | tuning of that convenience layer | derivable — the number of matches that clear the confidence floor, bounded by the numbered-options shape `user-interaction` fixes |
439
+ | `commands.suggestion.blocklist` | C | `[]` | a deny-list | derivable — the same cooldown tracker that reads whether the user picks a suggestion; repeated non-selection is the signal a hand-maintained deny-list stands in for |
440
+ | `commands.create_pr.preview_description` | C | `false` | removes pre-publish review of an outbound artefact | consent |
441
+ | `commands.create_pr.detail_level` | A | `min` | verbosity of a generated body | derivable — the diff the command already reads (changed-file count and risk surface) |
442
+ | `commands.create_pr.api_examples` | A | `true` | verbosity of a generated body | derivable — the command's own API-surface detection plus its grounded-source requirement |
443
+ | `commands.create_pr.screenshots` | C | `false` | puts captured screenshots into a published PR body | consent |
444
+ | `commands.create_pr.ui_paths` | C | `[]` | glob allowlist | derivable — the frontend-surface heuristic the PR-description flow already applies when the glob list is empty |
445
+ | `commands.create_pr.api_paths` | C | `[]` | glob allowlist | derivable — the API-endpoint heuristic the same flow already applies as its documented empty-list fallback |
446
+ | `memory.cadence` | C | `always` | suppressing the visibility line hides what the agent learned from the user | derivable — the hits/asks count the memory-visibility summary already computes; the line only exists when memory was consulted |
447
+ | `memory.review_threshold` | A | `10` | when a review preview surfaces; governs no gate | derivable — the unreviewed-intake count `/memory load` already computes before rendering its preview |
448
+ | `memory.redact_patterns` | C | `[]` | deny-list of secret and PII regexes | policy |
449
+ | `memory.session_index` | A | `"off"` | injects a compact index at session start | derivable — the row cap and index cost the mechanism already computes; the flag only holds an unproven ship-criterion open |
450
+ | `memory.learn_on_session_end` | B | `false` | turns on automatic memory writes at session end | consent |
451
+ | `knowledge.global_sharing.enabled` | C | `true` | kill-switch over cross-project egress | consent |
452
+ | `knowledge.global_sharing.allowed_tiers` | C | `[public]` | allowlist for that egress | consent |
453
+ | `knowledge.global_sharing.redaction.enabled` | C | `true` | disabling it removes the redaction floor | derivable — the redaction scan's own match result; no violation means no-op, so the flag can only remove a floor on an already-authorised path |
454
+ | `knowledge.global_sharing.redaction.halt_on_trigger` | C | `true` | disabling it removes halt-and-prompt | derivable — the violations list the redaction scan already returns; a non-empty list IS the halt condition |
455
+ | `knowledge.global_sharing.auto_promote_threshold` | C | `2` | threshold governing that egress | derivable — the distinct-repo count the promotion candidates already compute; promotion stays suggest-only and human-confirmed |
456
+ | `knowledge.global_sharing.freshness.hypothesis_after_days` | A | `90` | freshness heuristic on a card already shared | derivable — the age computation over the card's own `last_verified` provenance footer |
457
+ | `knowledge.global_sharing.freshness.stale_after_days` | A | `180` | freshness heuristic on a card already shared | derivable — the same age computation; the cut-point is advisory because the card is a cache, never a source of truth |
458
+ | `hooks.concern_budget.max_per_event` | C | `8` | budget cap on hook concerns | derivable — the gate's own constant over `hook_manifest.yaml`, with no consumer-situational input to read |
459
+ | `hooks.concern_budget.tier1_concerns` | C | `[]` | allowlist of concerns permitted to fail closed | policy |
460
+ | `hooks.concern_budget.hard_fail` | C | `false` | weakens the budget gate to warn-only | derivable — the gate's own `--strict` argv, which CI already passes to sibling gates |
461
+ | `hooks.injection_scan.enabled` | C | `false` | the prompt-injection scanner | derivable — the scanner's own signature match on the tool envelope; warn-only and silent on no hit |
462
+ | `hooks.rtk_wrap.enabled` | C | `false` | configures code that runs on every tool call | derivable — the live PATH and identity probe the hook already runs; silent when rtk is absent |
463
+ | `hooks.design_slop.enabled` | C | `false` | configures code that runs on every tool call | derivable — the rule-registry match plus the hook's own per-signature silence cap |
464
+ | `hooks.ui_route_nudge.enabled` | C | `false` | configures code that runs on every tool call | derivable — the UI-surface predicate plus the hook's own two-nudges-per-session cap |
465
+ | `hooks.code_graph.enabled` | C | `false` | configures code that runs on every tool call | derivable — the index-detection probe the nudge already runs; no index means silence |
466
+ | `decision_engine.surface_traces` | C | `false` | the decision engine’s own black box; the agent must not be able to close it | derivable — the engine's own active-gate state; there is nothing to surface when no gate fired |
467
+ | `decision_engine.min_confidence` | C | `"off"` | the confidence gate | derivable — the confidence band the scoring engine already computes at the plan phase |
468
+ | `decision_engine.block_on_risk` | C | `"off"` | the risk-class gate | derivable — the risk class the engine already computes at the implement phase; the Hard Floor covers the irreversible end unconditionally |
469
+ | `decision_engine.require_memory_hits` | C | `false` | a phase gate | derivable — the memory-hit count at the refine phase; its own template comment says the flag delays that soak |
470
+ | `decision_engine.on_block` | C | `stop` | `warn` advances past a gate that fired | derivable — the non-interactive probe decides ask-versus-stop, and the fired gate's own action decides the rest |
471
+ | `decision_engine.ask_timeout_seconds` | C | `30` | how long a fired gate waits before falling back | derivable — the same non-interactive probe: where nobody can answer there is nothing to wait for |
472
+ | `decision_engine.on_block_fallback` | C | `stop` | fail-safe versus fail-open after that timeout | derivable — the same non-interactive detection; a gate that fires with no one to answer resolves fail-safe by construction |
473
+ | `update_check.enabled` | C | `true` | a background safety check; disabling it pins the user to known-vulnerable code | consent |
474
+ | `explain.enable_last` | A | `true` | a read-only diagnostics surface | derivable — the presence of a work-state trace to render; with no trace the command is already a no-op |
475
+ | `legal_review_prep.acknowledged` | C | `false` | the consent gate; the safety floor requires the wizard checkbox | consent |
476
+ | `legal_review_prep.require_council` | C | `true` | a fail-closed defence-in-depth gate | consent |
351
477
 
352
478
  ## The council review of the C list (2026-08-05)
353
479
 
@@ -365,6 +491,10 @@ worst placed to certify about their own list.
365
491
  | `update_check.enabled` | a background safety check; switching it off pins the user to known-vulnerable code |
366
492
  | `chat_history.frequency` | reduces what is captured, so the trail thins |
367
493
  | `chat_history.on_overflow` | decides what survives when the log fills |
494
+ <!-- Historical record: `chat_history.on_overflow` was deleted 2026-08-12 as one
495
+ of the six unread keys. The A → C move above still stands as what the
496
+ council decided about it while it existed. -->
497
+
368
498
  | `memory.cadence` | suppresses the line that tells the user what the agent learned |
369
499
  | `decision_engine.surface_traces` | the decision engine's own black box |
370
500
 
@@ -396,6 +526,38 @@ that says "include examples" is bounded by the C-classed allow-list that decides
396
526
  approval ever stops being a separate mechanical step and becomes an in-turn
397
527
  "ok", it moves to C.
398
528
 
529
+ ## The floor — the residual `un-inferrable` set, with the reason each survives
530
+
531
+ These nine are the answer to *"how few keys can this surface have?"*, and the
532
+ answer is published rather than asserted: each row states what a mechanism would
533
+ have to observe to derive the value, and why nothing in the environment carries
534
+ that. A row here is falsifiable — name the probe and it stops being
535
+ un-inferrable.
536
+
537
+ The direction this contract encodes is fewer keys. This section is where that
538
+ direction stops, and stating the stopping point is what keeps "we are down to N"
539
+ from being a slogan. `un-inferrable` is the only disposition expected NOT to
540
+ shrink; `derivable` is a queue, `consent` is under re-examination, and `policy`
541
+ moves into the project surface.
542
+
543
+ | Key | Why no mechanism can derive it |
544
+ |---|---|
545
+ | `profile.id` | Which of the six audience identities the human *is*. The tree carries what the project contains, never who is sitting in front of it — a repo full of TypeScript is equally a developer's, an agency's, and a founder's. |
546
+ | `personal.ide` | Names a binary to execute. A probe can list what is installed; it cannot know which one the human wants opened, and guessing wrong executes the wrong program. |
547
+ | `personal.canary_name` | What the human wants to be called. `git config user.name` supplies a *prefill*, never the answer — the two differ for most people, and a wrong name is worse than none, because the canary then signals on a token the user never watches for. |
548
+ | `subagents.model_map.lite` | Names an external model endpoint. Which endpoints an account may call is a billing fact behind a vendor, not a property of the machine or the repo. |
549
+ | `subagents.model_map.medium` | Same — the endpoint this account may call at this tier. |
550
+ | `subagents.model_map.high` | Same — the endpoint this account may call at this tier. |
551
+ | `subagents.implementer_model` | Same, for the implementer role: which endpoint is permitted and paid for is outside anything the package can observe. |
552
+ | `subagents.judge_model` | Same, for the judge role — and here a wrong default is worse than an empty one, because it would silently judge with the model under test. |
553
+ | `ai_team.model` | Same, for the team surface. `auto` is a resolution *strategy*, not a derivation: it still needs the endpoint list this key supplies. |
554
+
555
+ The `consent` class (38) is deliberately NOT part of this floor. Those keys are
556
+ kept for now but sit under the Phase-3 re-examination that asks whether the
557
+ ACTION needs authorising at all — a consent gate on something the package should
558
+ not be doing is two problems wearing one flag, and the repair may remove the
559
+ action rather than the key.
560
+
399
561
  ## Adding a key
400
562
 
401
563
  1. Add it to `src/config/agent-settings.template.yml` and to