@event4u/agent-config 9.36.0 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +57 -0
- package/agents/templates/.ai-council.yml.example +31 -51
- package/dist/agent-src/commands/analyze/conformance.md +15 -4
- package/dist/agent-src/rules/session-canary.md +28 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/{chunk-SFGARMAB.js → chunk-2H5SE7DU.js} +24 -4
- package/dist/cli-delegate/{chunk-U7CMAIOC.js → chunk-3JUTT26I.js} +1 -1
- package/dist/cli-delegate/{chunk-JP53LNVT.js → chunk-HJSKTMIF.js} +6 -14
- package/dist/cli-delegate/{chunk-QEEB4LHO.js → chunk-LRXJK6GN.js} +1 -1
- package/dist/cli-delegate/{chunk-NR7HSN3P.js → chunk-NX5AXSLD.js} +3 -3
- package/dist/cli-delegate/{chunk-AG47LAGQ.js → chunk-TVGXH7VA.js} +1 -1
- package/dist/cli-delegate/{chunk-55RI5UXK.js → chunk-XT2YTJCZ.js} +22 -18
- package/dist/cli-delegate/{chunk-JEJABGKB.js → chunk-XTC5ARB6.js} +16 -12
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +1037 -196
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_explain.js +2 -2
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +3 -3
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_route_audit.js +2 -2
- package/dist/cli-delegate/cmd_route_explain.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +1 -1
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +4 -4
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +125 -89
- package/dist/install/install.mjs +22 -26
- package/dist/mcp/registry-manifest.json +1 -1
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1556 -613
- package/dist/scripts/_lib/agent_settings.js +39 -25
- package/dist/scripts/_lib/agent_settings.js.map +1 -1
- package/dist/scripts/condense.js +15 -2
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/routes/wizard.js +23 -3
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/server/schemas/settings.js +6 -6
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/contracts/settings-classes.md +14 -9
- package/package.json +1 -1
- package/src/config/agent-settings.template.yml +6 -36
- package/src/config/ci-local-parity.yml +44 -0
- package/src/scripts/_lib/agent_settings.ts +39 -25
- package/src/scripts/_lib/environment_detector.ts +52 -1
- package/src/scripts/ai_council/config.ts +62 -24
- package/src/scripts/before_complete_hook.ts +39 -0
- package/src/scripts/check_bridge_derivation.ts +89 -3
- package/src/scripts/check_ci_local_parity.ts +74 -0
- package/src/scripts/check_references.ts +15 -1
- package/src/scripts/condense.ts +16 -2
- package/src/scripts/conformance_scan.ts +200 -9
- package/src/scripts/council_cli.ts +95 -3
- package/src/scripts/hook_manifest.yaml +12 -6
- package/src/scripts/hooks/block_no_verify.ts +82 -9
- package/src/scripts/hooks/turn_end_gate_hook.ts +138 -105
- package/src/scripts/probe_promissory_closing.ts +180 -0
- package/src/scripts/probe_session_canary.ts +180 -0
- 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
|
+
"version": "10.0.0",
|
|
10
10
|
"keywords": [
|
|
11
11
|
"agent-config",
|
|
12
12
|
"skills",
|
package/CHANGELOG.md
CHANGED
|
@@ -339,6 +339,63 @@ 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
|
+
## [10.0.0](https://github.com/event4u-app/agent-config/compare/9.36.0...10.0.0) (2026-08-12)
|
|
343
|
+
|
|
344
|
+
### Release highlights
|
|
345
|
+
|
|
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 030ca0d, c1bc2aa, 4eda4ff.
|
|
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 7c6b404.
|
|
351
|
+
- **Known limitations:** _none_
|
|
352
|
+
|
|
353
|
+
### BREAKING CHANGES
|
|
354
|
+
|
|
355
|
+
* **council:** transport is resolved per machine, not configured ([4eda4ff](https://github.com/event4u-app/agent-config/commit/4eda4ff0f518cb30778dc139852576efd35bd57a))
|
|
356
|
+
|
|
357
|
+
### Features
|
|
358
|
+
|
|
359
|
+
* **ci:** the parity gate learns about preflight, which it never inspected ([44151b0](https://github.com/event4u-app/agent-config/commit/44151b02cd765aff16d7e95459752ec553c1d57b))
|
|
360
|
+
* **conformance:** a fifth check, an era guard, and the denominator the rate was missing ([f7edbdc](https://github.com/event4u-app/agent-config/commit/f7edbdc99533d433ff2b1857bac5bc7fb2929fe8))
|
|
361
|
+
* **hooks:** refuse a completion claim while the last CI read is unsettled ([1ea7536](https://github.com/event4u-app/agent-config/commit/1ea753629ce6a468e061af1ee2f7ac3f38f6bebd))
|
|
362
|
+
* **turn-end-gate:** arm it unconditionally, with no settings surface ([42cd613](https://github.com/event4u-app/agent-config/commit/42cd6131761a5b6681583abd8b7100f4415d84bf))
|
|
363
|
+
|
|
364
|
+
### Bug Fixes
|
|
365
|
+
|
|
366
|
+
* **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))
|
|
367
|
+
* **council:** validate the output path before spending, and count attendance from answers ([a23d6c8](https://github.com/event4u-app/agent-config/commit/a23d6c84d4963f17ca94838bdbc9f7067b72e77a))
|
|
368
|
+
* **hooks:** block-no-verify stops failing closed on heredoc prose ([7ac5cd2](https://github.com/event4u-app/agent-config/commit/7ac5cd227d34dbc92f9f0438746ff5cd1317e5d2))
|
|
369
|
+
* **taskfile:** block-scalar the bridge-derivation desc so the taskfile parses ([9b0f7b9](https://github.com/event4u-app/agent-config/commit/9b0f7b90ba9bac04c7b0e80dbeaeb99a3aab4cc3))
|
|
370
|
+
* **council:** use a Json-typed sentinel for the ignored-key presence check ([29b9f42](https://github.com/event4u-app/agent-config/commit/29b9f42e505c187f2b35abcb81cc6e7055d5507f))
|
|
371
|
+
* **detection:** find the Claude subscription in the macOS Keychain ([72de870](https://github.com/event4u-app/agent-config/commit/72de8706812ea2cf30940697887964ae1406a3e4))
|
|
372
|
+
* **gates:** scope bridge-derivation to the roots this checkout writes ([ea1b1d4](https://github.com/event4u-app/agent-config/commit/ea1b1d4e230375db0ae1c8e01226d8527a08a1e7))
|
|
373
|
+
|
|
374
|
+
### Documentation
|
|
375
|
+
|
|
376
|
+
* **review:** re-bind the R2 artefact to the fixed scope ([304b898](https://github.com/event4u-app/agent-config/commit/304b89866880c23f68106c096df20ce18ed207b7))
|
|
377
|
+
* **review:** record the R2 findings before fixing any of them ([bdf45c2](https://github.com/event4u-app/agent-config/commit/bdf45c2e86b2839f3c64d432d50285f043f08d3d))
|
|
378
|
+
* **roadmaps:** the fifth check makes two Context claims stale, in both directions ([6915456](https://github.com/event4u-app/agent-config/commit/6915456005fd164bc525103c6f0b59f05dbc8169))
|
|
379
|
+
* **analyze:** the conformance command documented four checks, there are five ([d05f97e](https://github.com/event4u-app/agent-config/commit/d05f97e13b03cc04036d83aba4df6635e0323932))
|
|
380
|
+
* **conformance:** round 7 — the honest downgrades and the archived roadmap ([c1bc2aa](https://github.com/event4u-app/agent-config/commit/c1bc2aaef41b04aa76024f9949c9e10eacd9886c))
|
|
381
|
+
* **council:** the template and contract stop documenting a setting that is gone ([49d58fa](https://github.com/event4u-app/agent-config/commit/49d58fa28778359416459465cf066b7d8fccb363))
|
|
382
|
+
* **roadmap:** close the stop-refusal blocker, open the two follow-up tracks ([7c6b404](https://github.com/event4u-app/agent-config/commit/7c6b4045c2cadf023d1f434ff851cec86372613a))
|
|
383
|
+
|
|
384
|
+
### Refactoring
|
|
385
|
+
|
|
386
|
+
* **condense:** expose the active-tool set root-parameterised ([d795d6a](https://github.com/event4u-app/agent-config/commit/d795d6a666f57be451d0dd5462b8725b56e44e75))
|
|
387
|
+
* **settings:** delete hooks.turn_end_gate.* and give REMOVED_KEYS per-key reasons ([f5b316b](https://github.com/event4u-app/agent-config/commit/f5b316b4bc531e2cf7ce0d65556c4a2737cbe0dc))
|
|
388
|
+
|
|
389
|
+
### Tests
|
|
390
|
+
|
|
391
|
+
* **hooks:** prove the completion detector is wired, not just correct ([4d284ef](https://github.com/event4u-app/agent-config/commit/4d284efa10ba939066edfc42c4a735d94e794def))
|
|
392
|
+
|
|
393
|
+
### Chores
|
|
394
|
+
|
|
395
|
+
* **condense:** re-project session-canary after the reproduction-command fix ([2d344c4](https://github.com/event4u-app/agent-config/commit/2d344c4d2183a608986f9dce485f1e5006e48863))
|
|
396
|
+
|
|
397
|
+
Tests: 13384 (+51 since 9.36.0)
|
|
398
|
+
|
|
342
399
|
## [9.36.0](https://github.com/event4u-app/agent-config/compare/9.35.0...9.36.0) (2026-08-12)
|
|
343
400
|
|
|
344
401
|
### Release highlights
|
|
@@ -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:
|
|
29
|
-
#
|
|
30
|
-
#
|
|
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.
|
|
51
|
+
# Per-invocation defaults.
|
|
48
52
|
defaults:
|
|
49
|
-
#
|
|
50
|
-
# below, and per-invocation via `/council mode:<x>`).
|
|
53
|
+
# There is NO transport-mode setting, deliberately.
|
|
51
54
|
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
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
|
-
#
|
|
78
|
-
#
|
|
79
|
-
# the
|
|
80
|
-
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
|
|
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.
|
|
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
|
|
76
|
-
language pin, git authorization, vacuous evidence, evidence steering
|
|
77
|
-
|
|
78
|
-
|
|
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 —
|
|
@@ -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: "
|
|
42
|
+
agent_config_version: "10.0.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-
|
|
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-
|
|
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-
|
|
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(
|
|
@@ -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-
|
|
5
|
+
} from "./chunk-HJSKTMIF.js";
|
|
6
6
|
import {
|
|
7
7
|
main
|
|
8
|
-
} from "./chunk-
|
|
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-
|
|
51
|
+
} from "./chunk-XTC5ARB6.js";
|
|
52
52
|
import {
|
|
53
53
|
event4u_root,
|
|
54
54
|
legacy_xdg_root,
|
|
@@ -40,7 +40,6 @@ var _VALID_PROVIDERS = /* @__PURE__ */ new Set([
|
|
|
40
40
|
"xai",
|
|
41
41
|
"perplexity"
|
|
42
42
|
]);
|
|
43
|
-
var _VALID_MODES = /* @__PURE__ */ new Set(["api", "manual", "cli", "auto"]);
|
|
44
43
|
var _RAW_KEY_PREFIXES = [
|
|
45
44
|
"sk-",
|
|
46
45
|
"sk-ant-",
|
|
@@ -303,7 +302,11 @@ function _build_config(raw, source_path) {
|
|
|
303
302
|
if (!_isBool(enabled)) {
|
|
304
303
|
throw new CouncilConfigError("`enabled` must be a bool.");
|
|
305
304
|
}
|
|
306
|
-
const
|
|
305
|
+
const ignored_transport_keys = [];
|
|
306
|
+
const defaults = _build_defaults(
|
|
307
|
+
_asDict(_getOr(raw, "defaults", {})),
|
|
308
|
+
ignored_transport_keys
|
|
309
|
+
);
|
|
307
310
|
const cost_budget = _build_cost_budget(
|
|
308
311
|
_asDict(_getOr(raw, "cost_budget", {}))
|
|
309
312
|
);
|
|
@@ -315,7 +318,12 @@ function _build_config(raw, source_path) {
|
|
|
315
318
|
for (const [name, cfg] of Object.entries(members_raw)) {
|
|
316
319
|
members.set(
|
|
317
320
|
name,
|
|
318
|
-
_build_member(
|
|
321
|
+
_build_member(
|
|
322
|
+
name,
|
|
323
|
+
_asDict(_orEmpty(cfg)),
|
|
324
|
+
defaults.mode,
|
|
325
|
+
ignored_transport_keys
|
|
326
|
+
)
|
|
319
327
|
);
|
|
320
328
|
}
|
|
321
329
|
const advisors_raw = _getOr(raw, "advisors", {});
|
|
@@ -414,7 +422,8 @@ function _build_config(raw, source_path) {
|
|
|
414
422
|
routing,
|
|
415
423
|
low_impact,
|
|
416
424
|
lens_overrides,
|
|
417
|
-
source_path
|
|
425
|
+
source_path,
|
|
426
|
+
ignored_transport_keys
|
|
418
427
|
};
|
|
419
428
|
}
|
|
420
429
|
function _orEmpty(value) {
|
|
@@ -892,16 +901,14 @@ function _build_consensus_scoring(d) {
|
|
|
892
901
|
};
|
|
893
902
|
}
|
|
894
903
|
var _VALID_MEMBER_MODES = /* @__PURE__ */ new Set(["cli", "api"]);
|
|
895
|
-
function _build_defaults(d) {
|
|
904
|
+
function _build_defaults(d, ignored = []) {
|
|
896
905
|
if (!_isDict(d)) {
|
|
897
906
|
throw new CouncilConfigError("`defaults` must be a mapping.");
|
|
898
907
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
throw new CouncilConfigError(
|
|
902
|
-
`defaults.mode=${_pyRepr(mode)} not in ${_sortedListRepr(_VALID_MODES)}.`
|
|
903
|
-
);
|
|
908
|
+
if (_get(d, "mode", null) !== null) {
|
|
909
|
+
ignored.push("defaults.mode");
|
|
904
910
|
}
|
|
911
|
+
const mode = "auto";
|
|
905
912
|
const member_mode = _get(d, "member_mode", "cli");
|
|
906
913
|
if (!(_isStr(member_mode) && _VALID_MEMBER_MODES.has(member_mode))) {
|
|
907
914
|
throw new CouncilConfigError(
|
|
@@ -1058,7 +1065,7 @@ function _build_cost_budget(d) {
|
|
|
1058
1065
|
}
|
|
1059
1066
|
return cb;
|
|
1060
1067
|
}
|
|
1061
|
-
function _build_member(name, cfg, default_mode = "auto") {
|
|
1068
|
+
function _build_member(name, cfg, default_mode = "auto", ignored = []) {
|
|
1062
1069
|
if (!_VALID_PROVIDERS.has(name)) {
|
|
1063
1070
|
throw new CouncilConfigError(
|
|
1064
1071
|
`members.${name}: unknown provider; valid: ${_sortedListRepr(_VALID_PROVIDERS)}.`
|
|
@@ -1069,14 +1076,11 @@ function _build_member(name, cfg, default_mode = "auto") {
|
|
|
1069
1076
|
const model = _pyTruthy(modelVal) ? modelVal : "";
|
|
1070
1077
|
const api_key_ref_raw = _get(cfg, "api_key_ref", null);
|
|
1071
1078
|
const api_key_ref = api_key_ref_raw === void 0 ? null : api_key_ref_raw;
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
if (member_mode !== null && !(_isStr(member_mode) && _VALID_MODES.has(member_mode))) {
|
|
1075
|
-
throw new CouncilConfigError(
|
|
1076
|
-
`members.${name}.mode=${_pyRepr(member_mode)} not in ${_sortedListRepr(_VALID_MODES)}.`
|
|
1077
|
-
);
|
|
1079
|
+
if (_get(cfg, "mode", null) !== null) {
|
|
1080
|
+
ignored.push(`members.${name}.mode`);
|
|
1078
1081
|
}
|
|
1079
|
-
const
|
|
1082
|
+
const member_mode = null;
|
|
1083
|
+
const effective_mode = default_mode;
|
|
1080
1084
|
const binary_raw = _get(cfg, "binary", null);
|
|
1081
1085
|
const binary = binary_raw === void 0 ? null : binary_raw;
|
|
1082
1086
|
if (binary !== null) {
|
|
@@ -504,14 +504,18 @@ function load_agent_settings(options = {}) {
|
|
|
504
504
|
_warn_removed_always_on_keys(merged);
|
|
505
505
|
return merged;
|
|
506
506
|
}
|
|
507
|
-
var
|
|
508
|
-
"subagents.enabled",
|
|
509
|
-
"subagents.auto",
|
|
510
|
-
"subagents.host_capabilities",
|
|
511
|
-
"subagents.budget_routing",
|
|
512
|
-
"ai_team.enabled"
|
|
513
|
-
]
|
|
514
|
-
|
|
507
|
+
var REMOVED_KEYS = /* @__PURE__ */ new Map([
|
|
508
|
+
["subagents.enabled", "always-on orchestration"],
|
|
509
|
+
["subagents.auto", "always-on orchestration"],
|
|
510
|
+
["subagents.host_capabilities", "always-on orchestration"],
|
|
511
|
+
["subagents.budget_routing", "always-on orchestration"],
|
|
512
|
+
["ai_team.enabled", "always-on orchestration"],
|
|
513
|
+
["hooks.turn_end_gate.enabled", "the turn-end gate is always armed"],
|
|
514
|
+
["hooks.turn_end_gate.promissory", "the turn-end gate is always armed"],
|
|
515
|
+
["hooks.turn_end_gate.language", "the turn-end gate is always armed"],
|
|
516
|
+
["hooks.turn_end_gate.verification", "the turn-end gate is always armed"]
|
|
517
|
+
]);
|
|
518
|
+
var _warnedRemovedKeys = /* @__PURE__ */ new Set();
|
|
515
519
|
function _readDottedSettingsPath(root, dotted) {
|
|
516
520
|
let node = root;
|
|
517
521
|
for (const part of dotted.split(".")) {
|
|
@@ -523,15 +527,15 @@ function _readDottedSettingsPath(root, dotted) {
|
|
|
523
527
|
return node;
|
|
524
528
|
}
|
|
525
529
|
function _warn_removed_always_on_keys(merged) {
|
|
526
|
-
for (const key of
|
|
527
|
-
if (
|
|
530
|
+
for (const [key, reason] of REMOVED_KEYS) {
|
|
531
|
+
if (_warnedRemovedKeys.has(key)) {
|
|
528
532
|
continue;
|
|
529
533
|
}
|
|
530
534
|
if (_readDottedSettingsPath(merged, key) === void 0) {
|
|
531
535
|
continue;
|
|
532
536
|
}
|
|
533
|
-
|
|
534
|
-
process.stderr.write(`${key} was removed (
|
|
537
|
+
_warnedRemovedKeys.add(key);
|
|
538
|
+
process.stderr.write(`${key} was removed (${reason}); ignored.
|
|
535
539
|
`);
|
|
536
540
|
}
|
|
537
541
|
}
|
|
@@ -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-
|
|
4
|
+
} from "./chunk-XTC5ARB6.js";
|
|
5
5
|
import "./chunk-NDJLNC6Q.js";
|
|
6
6
|
import "./chunk-J55WI3RR.js";
|
|
7
7
|
|