@event4u/agent-config 9.36.0 → 10.1.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 (89) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +117 -2
  3. package/agents/templates/.ai-council.yml.example +31 -51
  4. package/dist/agent-src/commands/analyze/conformance.md +15 -4
  5. package/dist/agent-src/rules/session-canary.md +28 -0
  6. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +17 -0
  7. package/dist/agent-src/skills/adr-create/SKILL.md +5 -0
  8. package/dist/agent-src/skills/check-refs/SKILL.md +5 -0
  9. package/dist/agent-src/skills/lint-skills/SKILL.md +5 -0
  10. package/dist/agent-src/skills/md-language-check/SKILL.md +5 -0
  11. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  12. package/dist/cli-delegate/{chunk-SFGARMAB.js → chunk-2H5SE7DU.js} +24 -4
  13. package/dist/cli-delegate/{chunk-U7CMAIOC.js → chunk-3JUTT26I.js} +1 -1
  14. package/dist/cli-delegate/{chunk-JP53LNVT.js → chunk-HJSKTMIF.js} +6 -14
  15. package/dist/cli-delegate/{chunk-QEEB4LHO.js → chunk-LRXJK6GN.js} +1 -1
  16. package/dist/cli-delegate/{chunk-NR7HSN3P.js → chunk-NX5AXSLD.js} +3 -3
  17. package/dist/cli-delegate/{chunk-AG47LAGQ.js → chunk-TVGXH7VA.js} +1 -1
  18. package/dist/cli-delegate/{chunk-55RI5UXK.js → chunk-XT2YTJCZ.js} +22 -18
  19. package/dist/cli-delegate/{chunk-JEJABGKB.js → chunk-XTC5ARB6.js} +16 -12
  20. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  21. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  22. package/dist/cli-delegate/cmd_conformance.js +1037 -196
  23. package/dist/cli-delegate/cmd_doctor.js +3 -3
  24. package/dist/cli-delegate/cmd_explain.js +2 -2
  25. package/dist/cli-delegate/cmd_export.js +4 -4
  26. package/dist/cli-delegate/cmd_handoff.js +3 -3
  27. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  28. package/dist/cli-delegate/cmd_migrate.js +2 -2
  29. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  30. package/dist/cli-delegate/cmd_prune.js +4 -4
  31. package/dist/cli-delegate/cmd_route_audit.js +2 -2
  32. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  33. package/dist/cli-delegate/cmd_session_recycle.js +1 -1
  34. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  35. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  36. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  37. package/dist/cli-delegate/cmd_sync.js +4 -4
  38. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  39. package/dist/cli-delegate/cmd_update.js +1 -1
  40. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  41. package/dist/cli-delegate/cmd_validate.js +4 -4
  42. package/dist/cli-delegate/cmd_versions.js +1 -1
  43. package/dist/discovery/deprecation-report.md +1 -1
  44. package/dist/discovery/discovery-manifest.json +8 -8
  45. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  46. package/dist/discovery/discovery-manifest.summary.md +1 -1
  47. package/dist/discovery/dormancy-report.md +1 -1
  48. package/dist/discovery/orphan-report.md +1 -1
  49. package/dist/discovery/packs.json +2 -2
  50. package/dist/discovery/trust-report.md +1 -1
  51. package/dist/discovery/workspaces.json +2 -2
  52. package/dist/hooks/dispatch.js +125 -89
  53. package/dist/install/install.mjs +22 -26
  54. package/dist/mcp/registry-manifest.json +1 -1
  55. package/dist/mcp/server.json +2 -2
  56. package/dist/mcp/server.mjs +1579 -616
  57. package/dist/scripts/_lib/agent_settings.js +39 -25
  58. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  59. package/dist/scripts/condense.js +15 -2
  60. package/dist/scripts/condense.js.map +1 -1
  61. package/dist/server/routes/wizard.js +23 -3
  62. package/dist/server/routes/wizard.js.map +1 -1
  63. package/dist/server/schemas/settings.js +6 -6
  64. package/dist/server/schemas/settings.js.map +1 -1
  65. package/docs/contracts/settings-classes.md +14 -9
  66. package/package.json +1 -1
  67. package/src/agent-src/scripts/archive_completed_roadmaps.ts +17 -0
  68. package/src/config/agent-settings.template.yml +6 -36
  69. package/src/config/ci-local-parity.yml +44 -0
  70. package/src/scripts/_lib/agent_settings.ts +39 -25
  71. package/src/scripts/_lib/environment_detector.ts +52 -1
  72. package/src/scripts/_lib/untrusted_content.test.ts +175 -0
  73. package/src/scripts/_lib/untrusted_content.ts +184 -0
  74. package/src/scripts/ai_council/config.ts +62 -24
  75. package/src/scripts/before_complete_hook.ts +39 -0
  76. package/src/scripts/check_bridge_derivation.ts +89 -3
  77. package/src/scripts/check_ci_local_parity.ts +74 -0
  78. package/src/scripts/check_references.ts +15 -1
  79. package/src/scripts/condense.ts +16 -2
  80. package/src/scripts/conformance_scan.ts +200 -9
  81. package/src/scripts/council_cli.ts +95 -3
  82. package/src/scripts/hook_manifest.yaml +12 -6
  83. package/src/scripts/hooks/block_no_verify.ts +82 -9
  84. package/src/scripts/hooks/turn_end_gate_hook.ts +138 -105
  85. package/src/scripts/probe_promissory_closing.ts +180 -0
  86. package/src/scripts/probe_session_canary.ts +180 -0
  87. package/src/scripts/schemas/skill.schema.json +42 -0
  88. package/src/scripts/skill_linter.ts +57 -2
  89. package/src/server/schemas/settings.ts +6 -14
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Bootstrap shim for the event4u agent-config suite. This plugin ships ONLY the dispatcher hooks plus one install-pointer skill — ALL content (skills, rules, commands) is installed via `npx -y @event4u/agent-config init`, which writes the file projection AND registers the same hooks in ~/.claude/settings.json. DEPRECATED as a content channel; kept so the marketplace listing stays discoverable and existing installs keep working hooks.",
9
- "version": "9.36.0",
9
+ "version": "10.1.0",
10
10
  "keywords": [
11
11
  "agent-config",
12
12
  "skills",
package/CHANGELOG.md CHANGED
@@ -339,12 +339,127 @@ Entry-shape contract: [`docs/contracts/CHANGELOG-conventions.md`](docs/contracts
339
339
  > that forces a new era split (`# Era: 9.37.x`, etc.) — see
340
340
  > [`docs/contracts/CHANGELOG-conventions.md § Era splits`](docs/contracts/CHANGELOG-conventions.md).
341
341
 
342
- ## [9.36.0](https://github.com/event4u-app/agent-config/compare/9.35.0...9.36.0) (2026-08-12)
342
+ ## [10.1.0](https://github.com/event4u-app/agent-config/compare/10.0.0...10.1.0) (2026-08-12)
343
343
 
344
344
  ### Release highlights
345
345
 
346
346
  <!-- Curated head: fill before merge, keep it under 10 lines, and leave `_none_` where it is genuinely the answer. The generated log below is unchanged. -->
347
- - **Behaviour changes:** _auto-derived, rewrite before merge:_ rule/schema diffs, breaking commits or removed public surface in 9f69017, 924cad8, 3c20d47, 72bb1bc.
347
+ - **Behaviour changes:** _auto-derived, rewrite before merge:_ rule/schema diffs, breaking commits or removed public surface in 0992c92, 20a8606, 63aeba1.
348
+ - **Default changes + migration:** _none_
349
+ - **Security and correctness:** _none_
350
+ - **Honest nulls:** _auto-derived, rewrite before merge:_ commits carrying an honest-null marker in 0f3ce9b.
351
+ - **Known limitations:** _none_
352
+
353
+ ### Features
354
+
355
+ * **untrusted-content:** tag external content where it enters, with an unforgeable boundary ([7a313ec](https://github.com/event4u-app/agent-config/commit/7a313ecfae4eadd06ff547a4a67d363a6758707b))
356
+ * **skill-schema:** structured runtime requirements, and the rule that gives them teeth ([63aeba1](https://github.com/event4u-app/agent-config/commit/63aeba1070af3d72bcaac0c7f999788d3b833354))
357
+
358
+ ### Bug Fixes
359
+
360
+ * **roadmap,context:** satisfy the two gates this branch newly tripped ([e61d461](https://github.com/event4u-app/agent-config/commit/e61d46142a9dc41841c98360377cc89176ce1057))
361
+ * **roadmap-archival:** an open blocker outlives its steps, and the sweep did not look ([710dc26](https://github.com/event4u-app/agent-config/commit/710dc266a27a82aad9a527c525650e8d43accfdc))
362
+ * **review:** close all eight R2 findings, one of them by admitting a gap instead of papering it ([0992c92](https://github.com/event4u-app/agent-config/commit/0992c92219364bc646e78c29fa3072b5e46361ef))
363
+ * **diff:** drop a regenerated report my git add -A swept in ([3aec031](https://github.com/event4u-app/agent-config/commit/3aec031b160a8bc676053be370b2fddfbeab250c))
364
+ * **skill-schema:** rename requires to runtime_requires — the key was already taken ([20a8606](https://github.com/event4u-app/agent-config/commit/20a86065cc5d9c86e9fdf0710c51ddf850ca7ae4))
365
+ * **roadmap:** anonymize the harvest source per source-confidentiality ([195e444](https://github.com/event4u-app/agent-config/commit/195e444a7b1f9d7d05ac5cb768b0be17a1ac58ea))
366
+
367
+ ### Documentation
368
+
369
+ * **changelog:** curate the 10.0.0 head, which shipped the same placeholder hours later ([0f3ce9b](https://github.com/event4u-app/agent-config/commit/0f3ce9b22c1858e12556a4b0fe95bec1931dde91))
370
+ * **roadmap:** the verified residue of five external release reviews ([a25579f](https://github.com/event4u-app/agent-config/commit/a25579fdf4d13cf6057ccdfeba5dc87990dd11e0))
371
+ * **analysis:** threat-model the confirmation store, and enumerate the buried decisions ([8b18f1c](https://github.com/event4u-app/agent-config/commit/8b18f1c4a850a9b08906aceccbe3562f381de7c3))
372
+ * **records:** three figures five reviews keep re-deriving, corrected at the source ([1612a70](https://github.com/event4u-app/agent-config/commit/1612a70e3e13daa0572fefb4803533708c1273f0))
373
+ * **changelog:** curate the 9.36.0 head that shipped its own placeholder ([83a3922](https://github.com/event4u-app/agent-config/commit/83a3922f63efbe5aca280e775acc85b36573c3f4))
374
+ * **review:** re-bind after the count correction ([9dd75ec](https://github.com/event4u-app/agent-config/commit/9dd75ecf178152641f8744a8f1b81f045befde7b))
375
+ * **roadmap:** correct the test count the review fixes moved ([ec52c42](https://github.com/event4u-app/agent-config/commit/ec52c421ba69dc85ee78095323f8495b93f3dd26))
376
+ * **review:** re-bind the R2 artefact to the fixed scope, dispositions terminal ([e601648](https://github.com/event4u-app/agent-config/commit/e6016487e883f611b2b7b989f23ed682796a6a73))
377
+ * **review:** record the R2 findings before fixing any of them ([1cf8d78](https://github.com/event4u-app/agent-config/commit/1cf8d787c015f51261bdd22b7388e47d127003f6))
378
+ * **roadmap:** add the Acceptance Criteria the completion review needs to bind to ([f35becd](https://github.com/event4u-app/agent-config/commit/f35becd885c09a5ac7f5a678adf29a360e776efa))
379
+ * **roadmap:** follow the schema key rename, and record why the obvious name was unavailable ([5720847](https://github.com/event4u-app/agent-config/commit/572084763fef97eb66fa91fd722d75a9c527440a))
380
+ * **roadmap:** the executable-payload harvest, with four source claims corrected ([2f4d8a8](https://github.com/event4u-app/agent-config/commit/2f4d8a8be5891d6045d4605a4a6d8fe3dc28a65e))
381
+
382
+ ### Tests
383
+
384
+ * **council-cli:** the quota case asserted a property of the developer machine ([35037f9](https://github.com/event4u-app/agent-config/commit/35037f96d3e631d6ee1a235415e716e2a29f8f8c))
385
+
386
+ Tests: 13411 (+27 since 10.0.0)
387
+
388
+ ## [10.0.0](https://github.com/event4u-app/agent-config/compare/9.36.0...10.0.0) (2026-08-12)
389
+
390
+ ### Release highlights
391
+
392
+ - **Behaviour changes:** council transport is **resolved per machine rather than
393
+ configured** — the breaking change this major carries (4eda4ff); every member
394
+ now resolves as `auto`, so a configured CLI call budget applies wherever a
395
+ council config exists. The turn-end gate is armed unconditionally and loses its
396
+ settings surface (42cd613). Conformance round 7 records its downgrades rather
397
+ than restating them (030ca0d, c1bc2aa).
398
+ - **Default changes + migration:** _none_
399
+ - **Security and correctness:** _none_
400
+ - **Honest nulls:** a blocker whose resolution condition no passage of time could
401
+ satisfy — a default-OFF gate cannot soak, so the switch removal discharges it
402
+ and the original wording stays verbatim beside the resolution, because the
403
+ unsatisfiable condition is itself the finding (7c6b404).
404
+ - **Known limitations:** _none_
405
+
406
+ ### BREAKING CHANGES
407
+
408
+ * **council:** transport is resolved per machine, not configured ([4eda4ff](https://github.com/event4u-app/agent-config/commit/4eda4ff0f518cb30778dc139852576efd35bd57a))
409
+
410
+ ### Features
411
+
412
+ * **ci:** the parity gate learns about preflight, which it never inspected ([44151b0](https://github.com/event4u-app/agent-config/commit/44151b02cd765aff16d7e95459752ec553c1d57b))
413
+ * **conformance:** a fifth check, an era guard, and the denominator the rate was missing ([f7edbdc](https://github.com/event4u-app/agent-config/commit/f7edbdc99533d433ff2b1857bac5bc7fb2929fe8))
414
+ * **hooks:** refuse a completion claim while the last CI read is unsettled ([1ea7536](https://github.com/event4u-app/agent-config/commit/1ea753629ce6a468e061af1ee2f7ac3f38f6bebd))
415
+ * **turn-end-gate:** arm it unconditionally, with no settings surface ([42cd613](https://github.com/event4u-app/agent-config/commit/42cd6131761a5b6681583abd8b7100f4415d84bf))
416
+
417
+ ### Bug Fixes
418
+
419
+ * **round7:** close the R2 findings — the two high ones are in my own Phase 1 ([030ca0d](https://github.com/event4u-app/agent-config/commit/030ca0d6e1a6b27ebbebf74a34caa1403cc98dfa))
420
+ * **council:** validate the output path before spending, and count attendance from answers ([a23d6c8](https://github.com/event4u-app/agent-config/commit/a23d6c84d4963f17ca94838bdbc9f7067b72e77a))
421
+ * **hooks:** block-no-verify stops failing closed on heredoc prose ([7ac5cd2](https://github.com/event4u-app/agent-config/commit/7ac5cd227d34dbc92f9f0438746ff5cd1317e5d2))
422
+ * **taskfile:** block-scalar the bridge-derivation desc so the taskfile parses ([9b0f7b9](https://github.com/event4u-app/agent-config/commit/9b0f7b90ba9bac04c7b0e80dbeaeb99a3aab4cc3))
423
+ * **council:** use a Json-typed sentinel for the ignored-key presence check ([29b9f42](https://github.com/event4u-app/agent-config/commit/29b9f42e505c187f2b35abcb81cc6e7055d5507f))
424
+ * **detection:** find the Claude subscription in the macOS Keychain ([72de870](https://github.com/event4u-app/agent-config/commit/72de8706812ea2cf30940697887964ae1406a3e4))
425
+ * **gates:** scope bridge-derivation to the roots this checkout writes ([ea1b1d4](https://github.com/event4u-app/agent-config/commit/ea1b1d4e230375db0ae1c8e01226d8527a08a1e7))
426
+
427
+ ### Documentation
428
+
429
+ * **review:** re-bind the R2 artefact to the fixed scope ([304b898](https://github.com/event4u-app/agent-config/commit/304b89866880c23f68106c096df20ce18ed207b7))
430
+ * **review:** record the R2 findings before fixing any of them ([bdf45c2](https://github.com/event4u-app/agent-config/commit/bdf45c2e86b2839f3c64d432d50285f043f08d3d))
431
+ * **roadmaps:** the fifth check makes two Context claims stale, in both directions ([6915456](https://github.com/event4u-app/agent-config/commit/6915456005fd164bc525103c6f0b59f05dbc8169))
432
+ * **analyze:** the conformance command documented four checks, there are five ([d05f97e](https://github.com/event4u-app/agent-config/commit/d05f97e13b03cc04036d83aba4df6635e0323932))
433
+ * **conformance:** round 7 — the honest downgrades and the archived roadmap ([c1bc2aa](https://github.com/event4u-app/agent-config/commit/c1bc2aaef41b04aa76024f9949c9e10eacd9886c))
434
+ * **council:** the template and contract stop documenting a setting that is gone ([49d58fa](https://github.com/event4u-app/agent-config/commit/49d58fa28778359416459465cf066b7d8fccb363))
435
+ * **roadmap:** close the stop-refusal blocker, open the two follow-up tracks ([7c6b404](https://github.com/event4u-app/agent-config/commit/7c6b4045c2cadf023d1f434ff851cec86372613a))
436
+
437
+ ### Refactoring
438
+
439
+ * **condense:** expose the active-tool set root-parameterised ([d795d6a](https://github.com/event4u-app/agent-config/commit/d795d6a666f57be451d0dd5462b8725b56e44e75))
440
+ * **settings:** delete hooks.turn_end_gate.* and give REMOVED_KEYS per-key reasons ([f5b316b](https://github.com/event4u-app/agent-config/commit/f5b316b4bc531e2cf7ce0d65556c4a2737cbe0dc))
441
+
442
+ ### Tests
443
+
444
+ * **hooks:** prove the completion detector is wired, not just correct ([4d284ef](https://github.com/event4u-app/agent-config/commit/4d284efa10ba939066edfc42c4a735d94e794def))
445
+
446
+ ### Chores
447
+
448
+ * **condense:** re-project session-canary after the reproduction-command fix ([2d344c4](https://github.com/event4u-app/agent-config/commit/2d344c4d2183a608986f9dce485f1e5006e48863))
449
+
450
+ Tests: 13384 (+51 since 9.36.0)
451
+
452
+ ## [9.36.0](https://github.com/event4u-app/agent-config/compare/9.35.0...9.36.0) (2026-08-12)
453
+
454
+ ### Release highlights
455
+
456
+ - **Behaviour changes:** the demand gate reads `project.audience` and is inert at
457
+ `self` — a market-demand ladder no longer fires on a project that intends no
458
+ market (9f69017). The two UI rules stop claiming the `ui-route-nudge` concern
459
+ reads their `keyword:` triggers; it does not, and six surfaces said it did
460
+ (3c20d47). The design skills now reach the consumers they were written for
461
+ (72bb1bc). The CI-side change in 924cad8 is internal to the pipeline and
462
+ changes no consumer-visible behaviour.
348
463
  - **Default changes + migration:** _none_
349
464
  - **Security and correctness:** _none_
350
465
  - **Honest nulls:** _none_
@@ -25,9 +25,13 @@
25
25
  # never at the raw secret. See docs/contracts/ai-council-config.md for
26
26
  # the full schema.
27
27
  #
28
- # Cost note: every consultation makes real, paid API calls. The
29
- # autonomy directive does NOT silently spend tokens — the /council
30
- # command always asks before invoking, even under autonomy: on.
28
+ # Cost note: a consultation is billed only when it resolves to the metered
29
+ # `api` rung. A vendor CLI under your subscription is preferred whenever one
30
+ # resolves, so the common case costs nothing per token — run
31
+ # `agent-config council status` to see the resolved transport and billing class
32
+ # per member before invoking. The autonomy directive does NOT silently spend
33
+ # tokens — the /council command always asks before invoking, even under
34
+ # autonomy: on.
31
35
 
32
36
  # Master switch (true, false). REQUIRED — the loader has no default for it,
33
37
  # so this file's value is the only value.
@@ -44,51 +48,30 @@
44
48
  # "could work" and "may spend" is visible rather than mysterious.
45
49
  enabled: true
46
50
 
47
- # Per-invocation defaults. Each member may override `mode:` below.
51
+ # Per-invocation defaults.
48
52
  defaults:
49
- # Default transport mode for every member (overridable per-member
50
- # below, and per-invocation via `/council mode:<x>`).
53
+ # There is NO transport-mode setting, deliberately.
51
54
  #
52
- # manual = copy & paste — the human transports prompt + reply
53
- # between the agent and an external chat surface. Free,
54
- # no key.
55
- # api = SDK call against a stored key, per-token billing.
56
- # cli = shell out to a locally-installed provider CLI under the
57
- # user's subscription auth (Claude Pro/Max, ChatGPT
58
- # Plus/Pro, Google Gemini, etc.). Spend is covered by the
59
- # flat-rate subscription, not per-token. `cost_budget.
60
- # max_total_usd` does NOT apply; use `cli_call_budget`
61
- # below to guard subscription quotas.
62
- # auto = resolve per provider per invocation: the provider's CLI
63
- # binary resolves AND a credential is present -> cli; else a
64
- # key resolves -> api; else unavailable with a one-line
65
- # reason. `manual` is NEVER part of the auto chain (it would
66
- # always "succeed" and silently turn every call into a
67
- # copy-paste request) — it stays an explicit opt-in.
68
- # THE SHIPPED DEFAULT (road-to-always-on-orchestration
69
- # Phase 3.1 — CLI-first is the owner-set transport doctrine):
70
- # ride the vendor CLI under your subscription first, fall to
71
- # the metered API only where no CLI resolves. Pin `manual` /
72
- # `api` / `cli` here (or per-member below) to override it.
73
- # `cli_call_budget` below ships populated with a generous
74
- # per-provider guard so this default never runs your
75
- # subscription quota uncapped.
55
+ # Transport is resolved per machine per invocation — `cli → api →
56
+ # unavailable`, and an airgapped host forces the `api` rung. A vendor CLI
57
+ # under your subscription is preferred whenever one resolves with a
58
+ # credential, so the free transport wins without anybody configuring it.
76
59
  #
77
- # Precedence: invocation flag > per-member mode > defaults.mode >
78
- # built-in. Two DIFFERENT defaults sit at the bottom, and they are not
79
- # the same thing:
80
- # · omit `defaults.mode` entirely and the loader fills "auto" (was
81
- # "api" before the Phase 3.1 flip) — that is what every real config
82
- # file observes.
83
- # · the resolver's built-in fallback, reached only when no layer at all
84
- # supplies a mode (a settings dict handed straight to the resolver,
85
- # no config file involved), is "manual" — free, no key. A caller who
86
- # named no transport has not asked to spend money. This did NOT flip
87
- # alongside the loader default: `auto` still resolves to a paying
88
- # rung when no CLI is usable, so flipping this too would let a
89
- # caller that bypassed the config file spend money on a preference
90
- # it never stated.
91
- mode: auto
60
+ # It used to be `defaults.mode`, with a per-member override. The default was
61
+ # flipped to CLI-first, but a default only fires on an ABSENT key: every
62
+ # config that had spelled the key out — which this template did, and which
63
+ # the setup wizard wrote — kept its old `api` value and went on paying per
64
+ # token while a paid-for subscription CLI sat unused on the same machine.
65
+ # A knob whose stale value silently costs money is worse than no knob.
66
+ #
67
+ # A file that still carries `mode:` (here or under a member) loads fine; the
68
+ # key is ignored and `agent-config council status` lists it as ignored so you
69
+ # can delete it. To pin one transport for ONE run — including the free,
70
+ # key-free `manual` copy-paste loop — pass `--mode-override` on the
71
+ # invocation. That is a flag, not a setting: it cannot go stale.
72
+ #
73
+ # `agent-config council status` prints the resolved transport and the billing
74
+ # class per member, which is the only honest answer to "will this cost money".
92
75
 
93
76
  # Default number of debate rounds per /council invocation.
94
77
  #
@@ -264,7 +247,9 @@ quorum: majority
264
247
  # under ~/.event4u/agent-config/, legacy
265
248
  # ~/.config/agent-config/ read as a fallback) or an env
266
249
  # var (`env:<VAR>`). Raw keys here are a hard validation
267
- # error. Required for mode: api; optional for cli /
250
+ # error. Optional: it is the credential for the metered `api`
251
+ # fallback rung. Absent, that rung is simply unavailable and
252
+ # the member needs a working CLI. Not needed for cli /
268
253
  # manual / auto (those may authenticate via the CLI).
269
254
  # mode: overrides defaults.mode for this member only.
270
255
  # binary: absolute path to the provider's CLI — only valid when
@@ -290,7 +275,6 @@ members:
290
275
  enabled: true
291
276
  model: claude-sonnet-4-5
292
277
  api_key_ref: file:anthropic.key
293
- # mode: cli # use subscription auth (Claude Pro/Max) — free, see cli_call_budget above
294
278
  # binary: /usr/local/bin/claude # only valid when mode == cli
295
279
  # Phase 7 — size-fit downgrade ladder (smallest → largest). The
296
280
  # active `model:` above must appear on this list. When the size
@@ -325,7 +309,6 @@ members:
325
309
  enabled: true
326
310
  model: gpt-4o
327
311
  api_key_ref: file:openai.key
328
- # mode: cli # use subscription auth (ChatGPT Plus/Pro via Codex CLI) — free
329
312
  # binary: /usr/local/bin/codex # only valid when mode == cli
330
313
  # Phase 7 — size-fit downgrade ladder (smallest → largest). The
331
314
  # active `model:` above must appear on this list.
@@ -340,14 +323,12 @@ members:
340
323
  enabled: false
341
324
  model: gemini-2.5-pro
342
325
  api_key_ref: env:GEMINI_API_KEY
343
- # mode: cli # use Google account (free-tier limits apply) — free
344
326
  # binary: /usr/local/bin/gemini # only valid when mode == cli
345
327
 
346
328
  xai:
347
329
  enabled: false
348
330
  model: grok-4
349
331
  api_key_ref: env:XAI_API_KEY
350
- # mode: cli # community `grok` CLI (Superagent) — ergonomic shortcut, NOT a billing change.
351
332
  # binary: /usr/local/bin/grok # The CLI consumes XAI_API_KEY and remains billable=True;
352
333
  # # cost_budget.max_total_usd STILL applies. Opt-in only.
353
334
 
@@ -355,7 +336,6 @@ members:
355
336
  enabled: false
356
337
  model: sonar-pro
357
338
  api_key_ref: env:PERPLEXITY_API_KEY
358
- # mode: cli # community `perplexity` CLI — ergonomic shortcut, NOT a billing change.
359
339
  # binary: /usr/local/bin/perplexity # The CLI consumes PERPLEXITY_API_KEY and remains billable=True;
360
340
  # # cost_budget.max_total_usd STILL applies. Opt-in only.
361
341
 
@@ -72,10 +72,21 @@ how they make it.
72
72
  agent-config conformance:behavior --limit <N> --output conformance-report.json
73
73
  ```
74
74
 
75
- Replays the local transcript store through the four **mechanised** checks:
76
- language pin, git authorization, vacuous evidence, evidence steering. Every
77
- classifier is imported from the gate it measures, so the scan and the gate
78
- cannot drift apart.
75
+ Replays the local transcript store through the five **mechanised** checks:
76
+ language pin, git authorization, vacuous evidence, evidence steering, and — since
77
+ round 7 — completion claim (a turn claiming the work is done while the last CI
78
+ read in that session was not settled). Every classifier is imported from the gate
79
+ it measures, so the scan and the gate cannot drift apart.
80
+
81
+ Two readings the report now separates, both because round 7's first run got them
82
+ wrong. The **language-pin rate is printed over two denominators** — all assistant
83
+ turns, which is what the band's three reference values used, and turns under a
84
+ German pin, which is the only population the check can fire on; the same corpus
85
+ read 6.5 % on the first and 9.2 % on the second, enough to move the verdict. And
86
+ the **band verdict is withheld over a corpus that spans a carrier landing**
87
+ (`CARRIER_CHANGES`): pooling 23.1 % before a mechanism with 0.0 % after it is a
88
+ weighted average of two systems, and the pooled figure was announced as the
89
+ pre-registered falsifier firing.
79
90
 
80
91
  This is the floor, not the audit. It sees only what already has a gate — which
81
92
  is exactly why it is trustworthy and exactly why it is not sufficient.
@@ -118,6 +118,34 @@ refused turn-end continues in the same turn) that rejects a task-start reply
118
118
  carrying no greeting. Proposed, not shipped; until it is, this obligation is
119
119
  model-carried in practice, whatever the frequency join reports.
120
120
 
121
+ **Round 7 downgrade: that proposed mechanism is UNDECIDABLE as written, and the
122
+ obligation splits into a measured half and an unmeasurable one.** A *task* start
123
+ is recorded nowhere in a transcript — there is no task event on any host, and
124
+ `user-interrupt-priority`'s continuation/clarification/interrupt distinction is a
125
+ judgement, not a field. So a delivery check "that rejects a task-start reply" has
126
+ no way to know a task started. The proposal is not merely unbuilt; as specified it
127
+ cannot be built, and saying "proposed, not shipped" implied otherwise.
128
+
129
+ What IS decidable is the per-**session** instance, and it was measured rather than
130
+ asserted — reproducibly, which took a correction: the probe resolves the name
131
+ through the same settings layers this rule names and REFUSES when no layer carries
132
+ one, so the figure below is reproduced with the name passed explicitly
133
+ (`./scripts-run src/scripts/probe_session_canary --limit 30 --name <your name>`;
134
+ the first version hardcoded a maintainer's nickname as its default, which made the
135
+ number irreproducible for anyone else and silently read 0 %). Over 30 sessions on
136
+ 2026-08-12: the opening greeting is present in **25 of 28** sessions carrying
137
+ assistant prose (89.3 %), and in **24 of 25** post-carrier (96.0 %). Of the three
138
+ misses, two predate the carrier (2026-07-21, 2026-07-29) and one is a session whose
139
+ first thirty turns were tool calls.
140
+
141
+ Both halves of that are load-bearing. The carrier works exactly where it has a
142
+ slot — `session_start` — which is why the session-scope figure is high; and the
143
+ 24-of-29 task-start figure above is not contradicted by it, because the two count
144
+ different events. The honest statement is therefore: **session-scope compliance is
145
+ measured and good; task-scope compliance is unmeasured and unmeasurable with
146
+ today's transcript, and no gate can change that until a task boundary is recorded
147
+ somewhere.** Do not read the 96 % as covering the obligation as a whole.
148
+
121
149
  **The wrong-name half needs nothing, and that is worth stating.** The beat
122
150
  already carries the resolved value — `build_canary_reminder` emits
123
151
  `Canary active for "<name>"`, and the hook no-ops when no layer resolves a name —
@@ -335,6 +335,23 @@ function archive_completed(
335
335
  if (stats.open_ !== 0 || stats.deferred !== 0) {
336
336
  continue; // not complete
337
337
  }
338
+ // An unresolved blocker outlives its steps. Closing every box does not
339
+ // answer a question the roadmap raised for a human, and archiving on
340
+ // step-count alone is how `b-highlights-mechanism` left the active tree
341
+ // unanswered in the 9.29 roadmap — four releases before the failure it
342
+ // predicted shipped in the 9.36.0 changelog head. Same discipline
343
+ // `roadmap-progress-sync` Iron Law 3 applies to `[~]` steps: a roadmap
344
+ // carrying an open decision stays visible until the decision is made.
345
+ const open_blockers = stats.open_blockers;
346
+ if (open_blockers.length > 0) {
347
+ const ids = open_blockers.map((b) => b.id).join(', ');
348
+ process.stderr.write(
349
+ ` ⚠️ ${stats.rel}: all steps closed but ${open_blockers.length} ` +
350
+ `blocker(s) still open (${ids}) — not archived. Resolve them, ` +
351
+ 'or record the decision, then re-run the sweep.\n',
352
+ );
353
+ continue;
354
+ }
338
355
  const old_rel = `agents/roadmaps/${stats.rel}`;
339
356
  if (changed_only && !(touched as Set<string>).has(old_rel)) {
340
357
  continue; // complete, but not this branch's work
@@ -11,6 +11,11 @@ execution:
11
11
  command:
12
12
  - ./scripts-run
13
13
  - src/scripts/adr/regenerate_index
14
+ runtime_requires:
15
+ bins:
16
+ - bash
17
+ - node
18
+ network: []
14
19
  workspaces:
15
20
  - agent-config-maintainer
16
21
  packs:
@@ -11,6 +11,11 @@ execution:
11
11
  command:
12
12
  - ./scripts-run
13
13
  - src/scripts/check_references
14
+ runtime_requires:
15
+ bins:
16
+ - bash
17
+ - node
18
+ network: []
14
19
  workspaces:
15
20
  - agent-config-maintainer
16
21
  packs:
@@ -12,6 +12,11 @@ execution:
12
12
  - ./scripts-run
13
13
  - src/scripts/skill_linter
14
14
  - "--all"
15
+ runtime_requires:
16
+ bins:
17
+ - bash
18
+ - node
19
+ network: []
15
20
  workspaces:
16
21
  - agent-config-maintainer
17
22
  packs:
@@ -11,6 +11,11 @@ execution:
11
11
  command:
12
12
  - ./scripts-run
13
13
  - src/scripts/check_md_language
14
+ runtime_requires:
15
+ bins:
16
+ - bash
17
+ - node
18
+ network: []
14
19
  workspaces:
15
20
  - agent-config-maintainer
16
21
  packs:
@@ -39,7 +39,7 @@ schema_version: 1
39
39
  # CI guard: a release bump of `package.json` must update this value
40
40
  # in lockstep — see scripts/check_template_pin_drift.ts (road-to-
41
41
  # portable-runtime-and-update-check P3.3).
42
- agent_config_version: "9.36.0"
42
+ agent_config_version: "10.1.0"
43
43
 
44
44
  # --- Project identity ---
45
45
  project:
@@ -18,7 +18,7 @@ import {
18
18
  hardenedSpawnEnv,
19
19
  scanTranscripts,
20
20
  weightedInputUnits
21
- } from "./chunk-55RI5UXK.js";
21
+ } from "./chunk-XT2YTJCZ.js";
22
22
  import {
23
23
  git_common_dir
24
24
  } from "./chunk-PZWRPRWP.js";
@@ -52,7 +52,7 @@ import {
52
52
  load_agent_settings,
53
53
  project_settings_path,
54
54
  resolve_project_root
55
- } from "./chunk-JEJABGKB.js";
55
+ } from "./chunk-XTC5ARB6.js";
56
56
  import {
57
57
  event4u_root,
58
58
  resolve_with_fallback,
@@ -3777,6 +3777,22 @@ function homeOf(env) {
3777
3777
  return injected !== "" ? injected : os.homedir();
3778
3778
  }
3779
3779
  var VERSION_PROBE_TIMEOUT_MS = 2e3;
3780
+ var CLAUDE_KEYCHAIN_SERVICE = "Claude Code-credentials";
3781
+ function defaultProbeKeychain(service) {
3782
+ if (process.platform !== "darwin") return false;
3783
+ try {
3784
+ const res = spawnSync2("security", ["find-generic-password", "-s", service], {
3785
+ timeout: VERSION_PROBE_TIMEOUT_MS,
3786
+ encoding: "utf-8",
3787
+ windowsHide: true,
3788
+ env: hardenedSpawnEnv()
3789
+ });
3790
+ if (res.error !== void 0 || res.signal !== null) return false;
3791
+ return res.status === 0;
3792
+ } catch {
3793
+ return false;
3794
+ }
3795
+ }
3780
3796
  function defaultProbeVersion(binary) {
3781
3797
  try {
3782
3798
  const res = spawnSync2(binary, ["--version"], {
@@ -3822,13 +3838,16 @@ function classifyCodexAuth(authPath) {
3822
3838
  if (hasOauth) return "cli-subscription";
3823
3839
  return "cli-api-key";
3824
3840
  }
3825
- function cliSubscriptionEvidence(provider, home, env, claudeConfigDir) {
3841
+ function cliSubscriptionEvidence(provider, home, env, claudeConfigDir, probeKeychain) {
3826
3842
  if (provider === "anthropic") {
3827
3843
  const configDir = claudeConfigDir;
3828
3844
  for (const rel of [".credentials.json", "credentials.json"]) {
3829
3845
  const p = path12.join(configDir, rel);
3830
3846
  if (isFile(p)) return { source: "cli-subscription", evidence: p };
3831
3847
  }
3848
+ if (probeKeychain(CLAUDE_KEYCHAIN_SERVICE)) {
3849
+ return { source: "cli-subscription", evidence: `keychain:${CLAUDE_KEYCHAIN_SERVICE}` };
3850
+ }
3832
3851
  return null;
3833
3852
  }
3834
3853
  if (provider === "openai") {
@@ -3870,10 +3889,11 @@ function detectAuth(opts) {
3870
3889
  const env = opts.env ?? process.env;
3871
3890
  const home = opts.home ?? homeOf(opts.env);
3872
3891
  const claudeConfigDir = opts.home === void 0 && opts.env === void 0 ? claude_config_dir() : (env["CLAUDE_CONFIG_DIR"] ?? "").trim() || path12.join(home, ".claude");
3892
+ const probeKeychain = opts.probeKeychain ?? defaultProbeKeychain;
3873
3893
  const auth = [];
3874
3894
  const keys = [];
3875
3895
  for (const provider of knownProviders()) {
3876
- const cli = cliSubscriptionEvidence(provider, home, env, claudeConfigDir);
3896
+ const cli = cliSubscriptionEvidence(provider, home, env, claudeConfigDir, probeKeychain);
3877
3897
  if (cli !== null) {
3878
3898
  auth.push({ provider, source: cli.source, evidence: cli.evidence });
3879
3899
  }
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __acCreateRequire } from 'node:module'; const require = globalThis.require ?? __acCreateRequire(import.meta.url);
2
2
  import {
3
3
  resolve_project_root
4
- } from "./chunk-JEJABGKB.js";
4
+ } from "./chunk-XTC5ARB6.js";
5
5
  import {
6
6
  resolvePackageRoot
7
7
  } from "./chunk-MCJYCQPF.js";
@@ -4552,21 +4552,13 @@ var settingsSchema = external_exports.object({
4552
4552
  enabled: external_exports.boolean().default(false).describe(
4553
4553
  "PreToolUse code-graph nudge (ADR-124 Phase 4). Default off. When on AND a native code-graph cache or a consumer-shipped graph.json/SCIP index is present, warns once per session (never blocks) as the agent is about to Grep/Glob or Read a source file \u2014 query the graph first for who-calls/where-used/impact questions (or rebuild if stale, build if absent). Source G\u2019s strict block-first-read mode is deliberately un-ported."
4554
4554
  )
4555
- }).default({}),
4556
- turn_end_gate: external_exports.object({
4557
- enabled: external_exports.boolean().default(false).describe(
4558
- "Stop-slot turn-end gate (road-to-conformance-round5 Phase 3). Default off, and it is the only concern that can REFUSE a turn-end rather than a tool call \u2014 so it soaks behind an explicit opt-in before it binds. Round 5 measured the reason: both blocking carriers reached zero violations, neither advisory carrier did, and 19 wrong-language replies survived a pin that had fired 26-35 seconds earlier. A refused turn continues in the SAME turn and is never refused twice."
4559
- ),
4560
- promissory: external_exports.boolean().default(true).describe(
4561
- "Detector A of the turn-end gate: refuse a turn whose closing paragraph promises work not yet performed while asking the user nothing (20 measured occurrences). No fire rate is quoted here on purpose: the measured rate moved twice while the instrument itself was being corrected, so a number in a shipped description would be a moving target. Re-derive it with `measure-turn-end-gate --store <transcript dir>` against your own corpus before arming the gate. Inert while hooks.turn_end_gate.enabled is false."
4562
- ),
4563
- language: external_exports.boolean().default(true).describe(
4564
- "Detector B of the turn-end gate: refuse a turn whose reply is not in the pinned language (19 measured occurrences). Fenced code, inline code, quoted tool output, tables, URLs and paths are stripped first, and the remainder is then scored LEAD-FIRST by the same classifier that sets the pin \u2014 so the verdict usually comes from the reply opening, not from all of it. Sharing that classifier is deliberate: it stops the pin and the detector disagreeing about a turn. Accepted opt-in spellings for the switches below include YAML true/false and yes/no/on/off. Inert while hooks.turn_end_gate.enabled is false."
4565
- ),
4566
- verification: external_exports.boolean().default(true).describe(
4567
- "Detector C of the turn-end gate: refuse a turn that changed a file and then ran nothing that could have checked it \u2014 no test, type-check, lint or build call follows the LAST edit. Ordering is the point: a run before the final edit did not exercise it, which is the freshness clause verify-before-complete states. Read off the turn tool calls, not the prose, because a reply cannot say whether an edit was verified. Deliberately narrow on what counts as verification \u2014 a missed detection costs one unguarded turn, a false refusal teaches you to switch the gate off. No fire rate is quoted: none has been measured yet. Inert while hooks.turn_end_gate.enabled is false."
4568
- )
4569
4555
  }).default({})
4556
+ // `turn_end_gate` is deliberately ABSENT. The stop-slot turn-end gate is
4557
+ // always armed (2026-08-12) and has no settings surface: whether it
4558
+ // fires is decided by each detector's own trigger conditions, not by a
4559
+ // flag. A leftover `hooks.turn_end_gate.*` block from an older install
4560
+ // warns once on stderr and is ignored — see REMOVED_KEYS in
4561
+ // `src/scripts/_lib/agent_settings.ts`.
4570
4562
  }),
4571
4563
  decision_engine: external_exports.object({
4572
4564
  surface_traces: external_exports.boolean().default(false).describe(
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-MMJL4TIX.js";
5
5
  import {
6
6
  load_agent_settings
7
- } from "./chunk-JEJABGKB.js";
7
+ } from "./chunk-XTC5ARB6.js";
8
8
 
9
9
  // src/scripts/chat_history.ts
10
10
  import { createHash } from "node:crypto";
@@ -2,10 +2,10 @@ import { createRequire as __acCreateRequire } from 'node:module'; const require
2
2
  import {
3
3
  ZodFirstPartyTypeKind,
4
4
  settingsSchema
5
- } from "./chunk-JP53LNVT.js";
5
+ } from "./chunk-HJSKTMIF.js";
6
6
  import {
7
7
  main
8
- } from "./chunk-U7CMAIOC.js";
8
+ } from "./chunk-3JUTT26I.js";
9
9
  import {
10
10
  RULE_SOURCE_REL
11
11
  } from "./chunk-BKO2AZ7Z.js";
@@ -48,7 +48,7 @@ import {
48
48
  import {
49
49
  find_project_root_with_anchor,
50
50
  load_agent_settings
51
- } from "./chunk-JEJABGKB.js";
51
+ } from "./chunk-XTC5ARB6.js";
52
52
  import {
53
53
  event4u_root,
54
54
  legacy_xdg_root,
@@ -2,7 +2,7 @@ import { createRequire as __acCreateRequire } from 'node:module'; const require
2
2
  import {
3
3
  DEFAULT_PROJECT_FILE,
4
4
  logger
5
- } from "./chunk-JEJABGKB.js";
5
+ } from "./chunk-XTC5ARB6.js";
6
6
 
7
7
  // src/scripts/config/profiles.ts
8
8
  import * as fs2 from "node:fs";