@event4u/agent-config 14.8.0 → 14.9.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 +165 -237
- package/README.md +1 -1
- package/agents/templates/.ai-council.yml.example +34 -4
- package/dist/agent-src/commands/pr/merge.md +9 -5
- package/dist/agent-src/commands/review/changes.md +95 -14
- package/dist/agent-src/commands/roadmap/process-full.md +2 -2
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +77 -0
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +36 -0
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +80 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +9 -3
- package/dist/agent-src/skills/code-review/evals/evals.json +87 -46
- package/dist/agent-src/skills/humanizer/SKILL.md +39 -0
- package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +57 -0
- package/dist/agent-src/skills/humanizer/references/fixtures.md +54 -0
- package/dist/agent-src/skills/judge-spec-compliance/SKILL.md +154 -0
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +45 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +18 -18
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +8 -0
- package/dist/cli/registry.js +2 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-MMSGVZKV.js → chunk-77GR3VD4.js} +65 -40
- package/dist/cli-delegate/{chunk-Q26HT4QT.js → chunk-E46KPN6K.js} +251 -150
- package/dist/cli-delegate/{chunk-EEJUMCDZ.js → chunk-PLSG6UL5.js} +1 -1
- package/dist/cli-delegate/cmd_conformance.js +89 -13
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +2 -2
- package/dist/cli-delegate/cmd_memory_get.js +1 -1
- package/dist/cli-delegate/cmd_route_audit.js +1 -1
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +37 -15
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +5 -4
- package/dist/hooks/dispatch.js +562 -204
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +808 -331
- package/dist/scripts/_lib/claude_plugin.js +162 -0
- package/dist/scripts/_lib/claude_plugin.js.map +1 -0
- package/dist/scripts/_lib/environment_detector.js +397 -0
- package/dist/scripts/_lib/environment_detector.js.map +1 -0
- package/dist/scripts/_lib/spawn_env.js +129 -0
- package/dist/scripts/_lib/spawn_env.js.map +1 -0
- package/dist/scripts/ai_council/modes.js +199 -0
- package/dist/scripts/ai_council/modes.js.map +1 -0
- package/dist/scripts/ai_council/transport_resolver.js +418 -0
- package/dist/scripts/ai_council/transport_resolver.js.map +1 -0
- package/dist/server/routes/wizard.js +3 -2
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/ui/assets/index-Cxgy63kz.js +26 -0
- package/dist/ui/assets/index-Cxgy63kz.js.map +1 -0
- package/dist/ui/index.html +1 -1
- package/docs/guidelines/agent-infra/traceability-field-mechanics.md +50 -0
- package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +17 -0
- package/package.json +7 -3
- package/src/config/estate-count-budget.json +13 -744
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +247 -9
- package/src/config/gate-violation-baselines.json +72 -72
- package/src/config/publish-surface.json +60 -0
- package/src/config/requirements-trace-budget.json +32 -0
- package/src/config/rule-stub-ceilings.json +8 -1
- package/src/scripts/_dispatch.bash +7 -0
- package/src/scripts/_lib/base_tree.ts +175 -0
- package/src/scripts/_lib/billing_grant.ts +165 -0
- package/src/scripts/_lib/billing_grant_cli.ts +123 -0
- package/src/scripts/_lib/council_fallback_posture.ts +53 -6
- package/src/scripts/_lib/council_fallback_wiring.ts +61 -1
- package/src/scripts/_lib/host_capability.ts +59 -5
- package/src/scripts/_lib/quota_parked.ts +133 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +62 -0
- package/src/scripts/_lib/review_telemetry.ts +196 -0
- package/src/scripts/_lib/subagent_response.ts +92 -0
- package/src/scripts/adr/regenerate_index.ts +14 -7
- package/src/scripts/ai_council/clients.ts +12 -1
- package/src/scripts/ai_council/config.ts +72 -115
- package/src/scripts/ai_council/fallback_config.ts +19 -7
- package/src/scripts/ai_council/mid_flight_fallback.ts +88 -7
- package/src/scripts/ai_council/orchestrator.ts +2 -2
- package/src/scripts/ai_council/py_format.ts +124 -0
- package/src/scripts/ai_council/transport_resolver.ts +65 -2
- package/src/scripts/audit_adr_coverage.ts +33 -6
- package/src/scripts/check_council_pin_staleness.ts +300 -0
- package/src/scripts/check_estate_count.ts +420 -293
- package/src/scripts/check_gate_coverage.ts +91 -0
- package/src/scripts/check_no_stub_inventory_table.ts +292 -0
- package/src/scripts/check_pack_size.ts +234 -1
- package/src/scripts/check_publish_surface.ts +297 -0
- package/src/scripts/check_requirements_trace.ts +378 -0
- package/src/scripts/check_secret_leak.ts +166 -12
- package/src/scripts/code_graph/cli.ts +44 -5
- package/src/scripts/code_graph/extract.ts +87 -0
- package/src/scripts/council_cli.ts +12 -16
- package/src/scripts/detect_ai_tells.ts +87 -0
- package/src/scripts/dispatch_r2_reviewer.ts +42 -0
- package/src/scripts/generate_capabilities_index.ts +41 -0
- package/src/scripts/git_authorization_hook.ts +54 -4
- package/src/scripts/hooks/block_unauthorized_git.ts +19 -1
- package/src/scripts/hooks/run_continuation_hook.ts +3 -1
- package/src/scripts/hooks/subagent_ledger_hook.ts +76 -11
- package/src/scripts/injection_scan_hook.ts +120 -10
- package/src/scripts/lint_adr_sweep_routing.ts +365 -0
- package/src/scripts/lint_workflow_security.ts +53 -10
- package/src/scripts/lint_workflow_security_allowlist.json +2 -18
- package/src/scripts/report_envelope_rate.ts +166 -0
- package/src/scripts/review_axis_report.ts +218 -0
- package/src/scripts/run_supervise.ts +46 -1
- package/src/scripts/schemas/evals.schema.json +5 -0
- package/src/scripts/sync_pr_branch.ts +14 -7
- package/dist/cli/commands/commands.candidates.test.js +0 -257
- package/dist/cli/commands/commands.candidates.test.js.map +0 -1
- package/dist/cli/commands/profiles.test.js +0 -88
- package/dist/cli/commands/profiles.test.js.map +0 -1
- package/dist/cli/commands/recordTriggerEval.test.js +0 -113
- package/dist/cli/commands/recordTriggerEval.test.js.map +0 -1
- package/dist/cli/configRoot.test.js +0 -97
- package/dist/cli/configRoot.test.js.map +0 -1
- package/dist/cli/mcp/content.test.js +0 -54
- package/dist/cli/mcp/content.test.js.map +0 -1
- package/dist/cli/mcp/dispatch.test.js +0 -108
- package/dist/cli/mcp/dispatch.test.js.map +0 -1
- package/dist/server/writeRoot.test.js +0 -91
- package/dist/server/writeRoot.test.js.map +0 -1
- package/dist/shared/capabilities.test.js +0 -39
- package/dist/shared/capabilities.test.js.map +0 -1
- package/dist/ui/assets/index-C1pBRm1f.js +0 -26
- package/dist/ui/assets/index-C1pBRm1f.js.map +0 -1
- /package/dist/cli-delegate/{chunk-N7CDDGI3.js → chunk-CYH5SP6M.js} +0 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://github.com/event4u-app/agent-config/actions/workflows/smoke.yml) [](https://github.com/event4u-app/agent-config/actions/workflows/smoke-public-install.yml) [](https://www.npmjs.com/package/@event4u/agent-config) [](https://glama.ai/mcp/servers/event4u-app/agent-config) [](https://mcptoplist.com/server/glama%2Fevent4u-app%2Fagent-config)
|
|
6
6
|
|
|
7
|
-
[](dist/agent-src/skills/) [](dist/agent-src/rules/) [](dist/agent-src/commands/) [](docs/guidelines/) [](dist/agent-src/personas/) [](dist/agent-src/personas/advisors/)
|
|
8
8
|
|
|
9
9
|
**Try it in 30 seconds** — drop one read-only subagent into any repo and watch it gate "done": `@production-validator check this branch is actually done`. No wizard, no lock-in, nothing else installed — the [30-second wedge ↓](#quickstart) is the whole first step. Start at the proof, not the catalog: **[event4u-app.github.io/agent-config/proof/](https://event4u-app.github.io/agent-config/proof/)**.
|
|
10
10
|
|
|
@@ -289,8 +289,20 @@ quorum: majority
|
|
|
289
289
|
# markers.
|
|
290
290
|
members:
|
|
291
291
|
anthropic:
|
|
292
|
+
# `sonnet` is a vendor ALIAS, not a version. `claude --help` documents
|
|
293
|
+
# 'fable', 'opus' and 'sonnet' as "an alias for the latest model" in their
|
|
294
|
+
# band, so this line cannot go stale the way a dated id can — the same
|
|
295
|
+
# property `codex-default` gives the openai member below.
|
|
296
|
+
#
|
|
297
|
+
# Until 2026-08-22 this read a dated, several-generation-old id: an enabled
|
|
298
|
+
# member of a quality council pinned in a template nobody re-reads, with
|
|
299
|
+
# nothing in the file able to notice. Read from the provider's own CLI
|
|
300
|
+
# surface, never from recall.
|
|
301
|
+
#
|
|
302
|
+
# A member on an alias or a sentinel needs no `verified_at:` — see the
|
|
303
|
+
# disabled members below for the stamped form.
|
|
292
304
|
enabled: true
|
|
293
|
-
model:
|
|
305
|
+
model: sonnet
|
|
294
306
|
api_key_ref: file:anthropic.key
|
|
295
307
|
# binary: /usr/local/bin/claude # only valid when mode == cli
|
|
296
308
|
# Phase 7 — size-fit downgrade ladder (smallest → largest). The
|
|
@@ -298,9 +310,9 @@ members:
|
|
|
298
310
|
# classifier flags a request as oversized, it suggests the next
|
|
299
311
|
# rung *down*; the top rung is the default for complex prompts.
|
|
300
312
|
model_ladder:
|
|
301
|
-
-
|
|
302
|
-
-
|
|
303
|
-
-
|
|
313
|
+
- haiku
|
|
314
|
+
- sonnet
|
|
315
|
+
- opus
|
|
304
316
|
# Prompt caching (GA — no beta header) is ON by default: the stable
|
|
305
317
|
# system + artefact prefix is sent as a cache-controlled block, so
|
|
306
318
|
# members 2..N in a round (and round-2+ within the 5-min TTL) read
|
|
@@ -381,20 +393,38 @@ members:
|
|
|
381
393
|
|
|
382
394
|
gemini:
|
|
383
395
|
enabled: false
|
|
396
|
+
# not-listed: gemini — the `gemini` CLI is installed here and its `--help` exposes only `-m, --model <string>` — no listing subcommand and no documented "latest" alias, so no sentinel could be substituted. An honest null for this provider, not a guess.
|
|
397
|
+
# The pin is therefore stamped as-of the drain date with NO refresh claimed;
|
|
398
|
+
# `verified_at` records when a human last looked, which is the only thing it
|
|
399
|
+
# has ever meant. This member ships disabled, so the pin costs nothing today
|
|
400
|
+
# and `check_council_pin_staleness` will say so when the stamp ages out.
|
|
384
401
|
model: gemini-2.5-pro
|
|
402
|
+
verified_at: "2026-08-22"
|
|
385
403
|
api_key_ref: env:GEMINI_API_KEY
|
|
386
404
|
# binary: /usr/local/bin/gemini # only valid when mode == cli
|
|
387
405
|
|
|
388
406
|
xai:
|
|
389
407
|
enabled: false
|
|
408
|
+
# not-listed: grok — no `grok` binary on this machine, so the provider's own surface was unreachable.
|
|
409
|
+
# The pin is therefore stamped as-of the drain date with NO refresh claimed;
|
|
410
|
+
# `verified_at` records when a human last looked, which is the only thing it
|
|
411
|
+
# has ever meant. This member ships disabled, so the pin costs nothing today
|
|
412
|
+
# and `check_council_pin_staleness` will say so when the stamp ages out.
|
|
390
413
|
model: grok-4
|
|
414
|
+
verified_at: "2026-08-22"
|
|
391
415
|
api_key_ref: env:XAI_API_KEY
|
|
392
416
|
# binary: /usr/local/bin/grok # The CLI consumes XAI_API_KEY and remains billable=True;
|
|
393
417
|
# # cost_budget.max_total_usd STILL applies. Opt-in only.
|
|
394
418
|
|
|
395
419
|
perplexity:
|
|
396
420
|
enabled: false
|
|
421
|
+
# not-listed: sonar — no `sonar` binary on this machine, so the provider's own surface was unreachable.
|
|
422
|
+
# The pin is therefore stamped as-of the drain date with NO refresh claimed;
|
|
423
|
+
# `verified_at` records when a human last looked, which is the only thing it
|
|
424
|
+
# has ever meant. This member ships disabled, so the pin costs nothing today
|
|
425
|
+
# and `check_council_pin_staleness` will say so when the stamp ages out.
|
|
397
426
|
model: sonar-pro
|
|
427
|
+
verified_at: "2026-08-22"
|
|
398
428
|
api_key_ref: env:PERPLEXITY_API_KEY
|
|
399
429
|
# binary: /usr/local/bin/perplexity # The CLI consumes PERPLEXITY_API_KEY and remains billable=True;
|
|
400
430
|
# # cost_budget.max_total_usd STILL applies. Opt-in only.
|
|
@@ -134,14 +134,19 @@ pushed ([`git-history-discipline`](../../../../rules/git-history-discipline.md))
|
|
|
134
134
|
## 3. Resolve conflicts by class, never by taste
|
|
135
135
|
|
|
136
136
|
Conflicts between queued PRs are expected, not exceptional: in this repository
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
roadmap PRs touch the same handful of shared paths, so each merge can
|
|
138
|
+
re-conflict every remaining PR. Resolve semantically, by these enumerated
|
|
139
|
+
classes.
|
|
140
|
+
|
|
141
|
+
`src/config/estate-count-budget.json` used to be the second-worst offender here
|
|
142
|
+
and no longer belongs in any class below: ADR-243 removed its stored baseline, so
|
|
143
|
+
it changes on a policy decision rather than once per roadmap touch. A conflict in
|
|
144
|
+
it now means two humans edited the same policy sentence — read both sides.
|
|
140
145
|
|
|
141
146
|
| Class | Files | Resolution |
|
|
142
147
|
|---|---|---|
|
|
143
148
|
| Roadmap files | `agents/roadmaps/**` | Union of completions. Never un-check a box either side checked; never resurrect a roadmap either side archived or parked. |
|
|
144
|
-
| Generated artefacts | `agents/roadmaps-progress.md` · `
|
|
149
|
+
| Generated artefacts | `agents/roadmaps-progress.md` · `docs/catalog.md` · `docs/command-flows.md` · `agents/index.md` · any file whose first three lines say generated / do-not-edit | Never hand-merge. Take either side, then **regenerate** with the repo's own task and commit the regenerated output. |
|
|
145
150
|
| Archive move vs. edit | `agents/roadmaps/{archive,later,skipped}/**` — one side renamed or deleted, the other edited | The archived end-state wins. Re-apply the edit at the new path if it still matters; otherwise drop it and record the drop in the summary. |
|
|
146
151
|
| Evidence files | `agents/evidence/**` | Append-only. Keep both sides. |
|
|
147
152
|
|
|
@@ -169,7 +174,6 @@ regenerate. Exclude those paths before deciding:
|
|
|
169
174
|
```bash
|
|
170
175
|
git diff origin/<base>...HEAD --stat -- . \
|
|
171
176
|
':(exclude)agents/roadmaps-progress.md' \
|
|
172
|
-
':(exclude)src/config/estate-count-budget.json' \
|
|
173
177
|
':(exclude)docs/catalog.md' ':(exclude)agents/index.md'
|
|
174
178
|
```
|
|
175
179
|
|
|
@@ -9,7 +9,7 @@ visibility: internal
|
|
|
9
9
|
sub: changes
|
|
10
10
|
cluster: review
|
|
11
11
|
skills: [code-review, subagent-orchestration, judge-bug-hunter, judge-security-auditor, judge-test-coverage, judge-code-quality, architecture-review-lens, judge-synthesis, git-workflow]
|
|
12
|
-
description: Self-review local changes before creating a PR — dispatches to
|
|
12
|
+
description: Self-review local changes before creating a PR — dispatches to six specialized judges (bug, security, tests, quality, architecture, spec) and consolidates verdicts
|
|
13
13
|
suggestion:
|
|
14
14
|
eligible: false
|
|
15
15
|
rationale: "Cluster sub-command — reached via its cluster head's routing or its explicit /cluster:sub name; not independently suggested (surface-consolidation)."
|
|
@@ -24,7 +24,7 @@ packs:
|
|
|
24
24
|
## Instructions
|
|
25
25
|
|
|
26
26
|
Review all uncommitted and committed-but-not-pushed changes against
|
|
27
|
-
the default branch (`main`) by dispatching to
|
|
27
|
+
the default branch (`main`) by dispatching to six specialized judge
|
|
28
28
|
sub-skills and consolidating their verdicts.
|
|
29
29
|
|
|
30
30
|
### 1. Update the current branch
|
|
@@ -51,6 +51,18 @@ to make sure the current branch is up to date with its base chain:
|
|
|
51
51
|
|
|
52
52
|
### 2. Gather the diff
|
|
53
53
|
|
|
54
|
+
**Verify the base ref before diffing against it.** The commands below assume
|
|
55
|
+
`origin/main` exists and is the right base, and nothing checked. This step
|
|
56
|
+
already knows how to ask git a question — `git rev-parse --abbrev-ref HEAD`
|
|
57
|
+
above — so the shape was present and simply not applied to the base:
|
|
58
|
+
|
|
59
|
+
- `git rev-parse --verify origin/main` — the base ref resolves.
|
|
60
|
+
- **Does not resolve → stop here and say so.** Do not fall back to a
|
|
61
|
+
different base, and do not diff against `HEAD` alone. A review whose scope
|
|
62
|
+
silently became "the whole branch" or "the last commit" reports findings
|
|
63
|
+
against a diff nobody asked about, and the reader has no way to see that the
|
|
64
|
+
scope moved. Name the ref that failed.
|
|
65
|
+
|
|
54
66
|
- `git diff origin/main..HEAD --stat` — overview of changed files
|
|
55
67
|
- `git diff origin/main..HEAD` — full committed-but-not-pushed diff
|
|
56
68
|
- `git diff --stat` + `git diff` — unstaged changes on top
|
|
@@ -65,7 +77,39 @@ Read `.agent-settings.yml`:
|
|
|
65
77
|
|
|
66
78
|
Unknown alias → stop. Never silently fall back.
|
|
67
79
|
|
|
68
|
-
###
|
|
80
|
+
### 3b. Bind the criteria source before dispatching
|
|
81
|
+
|
|
82
|
+
The spec judge below is only as good as the criteria it reads, so where they
|
|
83
|
+
came from is recorded **before** the dispatch, not reconstructed after it.
|
|
84
|
+
Exactly one of three states, and the state is written into the review report:
|
|
85
|
+
|
|
86
|
+
| `criteria_source` | When | What the report says |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| `supplied` | a roadmap, ticket, issue or AC block was explicitly handed in — name it by path or id | the criteria, verbatim, and where they came from |
|
|
89
|
+
| `not_provided` | an ad-hoc branch review with no criteria anywhere | "no acceptance criteria supplied — requirement compliance NOT verified" |
|
|
90
|
+
| `supplied_unparseable` | criteria were handed over and could not be read in a recognised shape | an **error**: the review skipped a dimension it was asked to check |
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
CRITERIA ARE READ ONLY WHEN SUPPLIED. NEVER DERIVED FROM THE BRANCH,
|
|
94
|
+
THE COMMIT MESSAGES, OR THE PR BODY — AND NEVER FROM THE DIFF.
|
|
95
|
+
A JUDGE THAT INFERS THE REQUIREMENT FROM THE CHANGE IT IS JUDGING
|
|
96
|
+
ALWAYS FINDS THE CHANGE COMPLIANT. SILENCE IS `not_provided`, NEVER A PASS.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
There is deliberately **no `derived` state**. Deriving criteria from the branch
|
|
100
|
+
was the alternative considered and rejected: the `derived` label would have to
|
|
101
|
+
be honoured by every consumer of the report to be worth anything, and a label
|
|
102
|
+
that is requested rather than enforced degrades to silence exactly when it
|
|
103
|
+
matters. Decided by AI council on 2026-08-22 (degraded, 1 of 2 seats — the
|
|
104
|
+
second returned an empty response), and the alternative is recorded here rather
|
|
105
|
+
than only in the decision so a later reader can see it was weighed.
|
|
106
|
+
|
|
107
|
+
`supplied_unparseable` is separated from `not_provided` for the same reason:
|
|
108
|
+
folded together, a handover the reviewer could not parse would report as "there
|
|
109
|
+
was nothing to check", which is the one outcome that hides a real failure
|
|
110
|
+
behind a benign one.
|
|
111
|
+
|
|
112
|
+
### 4. Dispatch to the six judges
|
|
69
113
|
|
|
70
114
|
Each judge receives **the same diff plus the task context** (ticket,
|
|
71
115
|
PR body, commit messages) and runs independently. The judges are:
|
|
@@ -77,20 +121,37 @@ PR body, commit messages) and runs independently. The judges are:
|
|
|
77
121
|
| [`judge-test-coverage`](../../skills/judge-test-coverage/SKILL.md) | Missing assertions, uncovered branches, over-mocking, regression-test gaps |
|
|
78
122
|
| [`judge-code-quality`](../../skills/judge-code-quality/SKILL.md) | Naming, SRP, DRY, dead code, consistency with codebase conventions |
|
|
79
123
|
| [`architecture-review-lens`](../../skills/architecture-review-lens/SKILL.md) | Layer violations, dependency direction, leaky abstractions, cross-service contract drift |
|
|
124
|
+
| [`judge-spec-compliance`](../../skills/judge-spec-compliance/SKILL.md) | Does the diff satisfy every acceptance criterion **as stated**? Reads the criteria before the diff, and never infers them from it |
|
|
80
125
|
|
|
81
|
-
The
|
|
126
|
+
The six judges weight equally in the consolidated verdict — none
|
|
82
127
|
overrides another.
|
|
83
128
|
|
|
129
|
+
**Why the sixth exists, and why it is not a severity.** The other five all ask a
|
|
130
|
+
craft-or-correctness question, so a change that is correct, clean, well-tested
|
|
131
|
+
and architecturally sound — and **does not do what was asked** — used to pass
|
|
132
|
+
this path with five green verdicts. Its finding does **not** enter the shared
|
|
133
|
+
severity axis: `judge-synthesis` carries it on its own dimension, because "this
|
|
134
|
+
does not do what was asked" is not comparable to "this variable is badly named",
|
|
135
|
+
and on one scale the second can outrank the first whenever three judges raise
|
|
136
|
+
nits and one raises the spec gap.
|
|
137
|
+
|
|
138
|
+
**When no criteria were supplied** — an ad-hoc branch review — this judge
|
|
139
|
+
returns a no-criteria verdict, never `SATISFIED`. That is not an abstention the
|
|
140
|
+
consolidated verdict may drop: it changes what "done" is allowed to claim to
|
|
141
|
+
*"craft quality verified; requirement compliance NOT verified"*. If that reads as
|
|
142
|
+
most reviews, the honest reading is that most reviews were previously reporting a
|
|
143
|
+
confidence they had not earned.
|
|
144
|
+
|
|
84
145
|
Pick dispatch mode based on diff size and environment:
|
|
85
146
|
|
|
86
147
|
- **Sequential** (default, simplest) — run bug-hunter → security-auditor
|
|
87
|
-
→ test-coverage → code-quality → architecture-review-lens
|
|
88
|
-
each verdict
|
|
148
|
+
→ test-coverage → code-quality → architecture-review-lens →
|
|
149
|
+
spec-compliance, collect each verdict
|
|
89
150
|
- **Parallel** — if `subagents.max_parallel` in `.agent-settings.yml` is
|
|
90
|
-
≥ 5 and subagent dispatch is available, run all
|
|
151
|
+
≥ 5 and subagent dispatch is available, run all six concurrently
|
|
91
152
|
following the `do-in-parallel` pattern in
|
|
92
153
|
[`subagent-orchestration`](../../skills/subagent-orchestration/SKILL.md);
|
|
93
|
-
the
|
|
154
|
+
the six judges operate on the same diff but produce independent
|
|
94
155
|
reports, so no shared-state risk
|
|
95
156
|
|
|
96
157
|
Each judge returns its own `Judge / Model / Target / Verdict /
|
|
@@ -108,14 +169,14 @@ Read `verbosity.offer_council_in_delivery` from `.agent-settings.yml`
|
|
|
108
169
|
- `true`: when `ai_council.enabled: true` **and** at least one member
|
|
109
170
|
enabled, ask (in the user's language):
|
|
110
171
|
|
|
111
|
-
> 1. Add an external council review alongside the
|
|
172
|
+
> 1. Add an external council review alongside the six internal judges? (billable)
|
|
112
173
|
> 2. Skip — internal judges only
|
|
113
174
|
|
|
114
175
|
Also suppress when `personal.autonomy: on` (council is billable).
|
|
115
176
|
|
|
116
177
|
If picked **1**:
|
|
117
178
|
|
|
118
|
-
- Run `/council diff:<base>..<head>` in parallel with the
|
|
179
|
+
- Run `/council diff:<base>..<head>` in parallel with the six
|
|
119
180
|
internal judges (or sequentially after them — whichever the
|
|
120
181
|
dispatch mode picked in step 4 supports).
|
|
121
182
|
- Treat each council member as one extra "judge" in the consolidated
|
|
@@ -140,7 +201,7 @@ Read `subagents.adversarial_council` from `.agent-settings.yml` (default
|
|
|
140
201
|
which supplies the four slots, the one-question budget, and the storage line
|
|
141
202
|
(not persisted: `subagents.adversarial_council` is class C). What only this
|
|
142
203
|
command knows is *why now*: the diff is high-risk, and the offer is a paid
|
|
143
|
-
distinct-model red-team for finding coverage against the
|
|
204
|
+
distinct-model red-team for finding coverage against the six internal judges.
|
|
144
205
|
- `on`: run it automatically on a high-risk diff.
|
|
145
206
|
|
|
146
207
|
When run, dispatch the
|
|
@@ -164,16 +225,36 @@ step 4 (plus any external council blocks from 4b) and produces one report:
|
|
|
164
225
|
- A **must-fix / should-fix / advisory** split, each entry tagged with the
|
|
165
226
|
judge(s) that raised it
|
|
166
227
|
|
|
228
|
+
- A **spec-compliance block**, kept apart from that split — the
|
|
229
|
+
`criteria_source` state from step 3b, the per-criterion verdicts, and the
|
|
230
|
+
count of `MISSING` plus `PARTIAL`. See
|
|
231
|
+
[`judge-synthesis` § 4c](../../skills/judge-synthesis/SKILL.md); a spec
|
|
232
|
+
finding never becomes a craft finding.
|
|
233
|
+
|
|
167
234
|
`judge-synthesis` emits no single quality score and never auto-gates — it
|
|
168
235
|
structures the verdicts so the next step's decision is informed.
|
|
169
236
|
|
|
237
|
+
**The report names its criteria source, always.** A reader six months later
|
|
238
|
+
cannot otherwise tell "we checked the requirements and they were met" from
|
|
239
|
+
"nobody checked" — and those are the two readings a bare `proceed` collapses.
|
|
240
|
+
Where the state is `not_provided`, the overall sentence says *craft quality
|
|
241
|
+
verified; requirement compliance NOT verified*, never a plain pass.
|
|
242
|
+
|
|
243
|
+
**One telemetry line per review** records the structural outcome: which judges
|
|
244
|
+
ran, whether the spec axis was reachable, and whether it changed the
|
|
245
|
+
recommendation. Built and validated by
|
|
246
|
+
`src/scripts/_lib/review_telemetry.ts::buildReviewLine`, which carries no field
|
|
247
|
+
able to hold free-form content and **rejects** an input that adds one. Read the
|
|
248
|
+
window back with `./scripts-run src/scripts/review_axis_report`; it reports
|
|
249
|
+
"nothing observed" and "the axis changed nothing" as two different answers.
|
|
250
|
+
|
|
170
251
|
### 6. Decide next steps
|
|
171
252
|
|
|
172
253
|
- If **any** judge returned `reject` → stop; the approach must change
|
|
173
254
|
before proceeding
|
|
174
255
|
- If **any** judge returned `revise` → fix 🔴 findings automatically,
|
|
175
256
|
ask before fixing 🟡 findings, report 🟢 as suggestions
|
|
176
|
-
- If all
|
|
257
|
+
- If all six returned `apply` → the diff is ready; report and stop
|
|
177
258
|
|
|
178
259
|
**Opt-in (never auto-on):** when the `revise` findings are *test-driven*
|
|
179
260
|
(failing checks, not subjective craft) and you want bounded auto-repair
|
|
@@ -218,7 +299,7 @@ Per `verbosity.routine_confirmations` (default `false`):
|
|
|
218
299
|
## Use this command when
|
|
219
300
|
|
|
220
301
|
- Preparing a self-review before opening a PR
|
|
221
|
-
- Stress-testing a local branch with the same
|
|
302
|
+
- Stress-testing a local branch with the same six lenses a reviewer
|
|
222
303
|
would apply
|
|
223
304
|
- Sanity-checking a diff before handing it to `/create-pr`
|
|
224
305
|
|
|
@@ -247,6 +328,6 @@ Per `verbosity.routine_confirmations` (default `false`):
|
|
|
247
328
|
|
|
248
329
|
- **LLM-as-a-Judge** — [arxiv.org/abs/2306.05685](https://arxiv.org/abs/2306.05685)
|
|
249
330
|
MT-Bench and Chatbot Arena — judging LLM outputs with LLM judges.
|
|
250
|
-
This command adapts the pattern by dispatching to
|
|
331
|
+
This command adapts the pattern by dispatching to six specialized
|
|
251
332
|
judges (bug, security, tests, quality) instead of a single generic
|
|
252
333
|
judge, and consolidating their verdicts.
|
|
@@ -175,8 +175,8 @@ contract.
|
|
|
175
175
|
|
|
176
176
|
**Mergeability is per-PR against a recorded base, never a queue property.**
|
|
177
177
|
When every PR in the estate touches the same generated files — in this
|
|
178
|
-
repository `agents/roadmaps-progress.md` and
|
|
179
|
-
|
|
178
|
+
repository `agents/roadmaps-progress.md` and the archive index — making PR *n*
|
|
179
|
+
mergeable against base
|
|
180
180
|
SHA `M` says nothing about its state once PR *n−1* advances the base to `M1`.
|
|
181
181
|
Report "mergeable against base `<SHA>`", never "the queue is mergeable".
|
|
182
182
|
|
|
@@ -100,6 +100,83 @@ provenance before treating a `false` as a host limitation: on an unrecognized
|
|
|
100
100
|
host every field is `default`, which is an absence of knowledge and not a
|
|
101
101
|
measurement.
|
|
102
102
|
|
|
103
|
+
## Observation protocol — what may be written into a registry row
|
|
104
|
+
|
|
105
|
+
**Added 2026-08-22** (`road-to-host-capability-observations` Phase 1). The
|
|
106
|
+
registry held **one** row while **eight** platform keys were declared, so on
|
|
107
|
+
seven hosts every field was the safe default — and `false` carried two meanings
|
|
108
|
+
at once. This protocol is what makes them distinguishable.
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
A ROW IS WRITTEN FROM AN OBSERVATION IN A REAL SESSION, NEVER FROM THE HOST'S
|
|
112
|
+
DOCUMENTATION. A CAPABILITY THAT EXISTS ON PAPER AND NOT IN THE SESSION PRODUCES
|
|
113
|
+
A ROUTING DECISION THAT FAILS SILENTLY.
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**This is a written criterion a human applies, and deliberately not a script.**
|
|
117
|
+
A prober that decides for itself what counts as evidence is the inference
|
|
118
|
+
`host_capability.ts` already forbids, wearing an executable's authority.
|
|
119
|
+
|
|
120
|
+
### Per-field criterion — each one transcript-observable
|
|
121
|
+
|
|
122
|
+
| Field | What counts as an observation |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `subagent_spawn` | a dispatch record showing a **child leg with its own turn** — a start and a stop that pair, so the child's duration is measurable rather than inferred |
|
|
125
|
+
| `parallel_spawn` | **two child legs whose intervals overlap** — concurrently open children at one instant, not two children in sequence |
|
|
126
|
+
| `status_polling` | a **completed poll returning a state the parent did not already hold**. A poll that returns what the parent knew is not an observation of polling |
|
|
127
|
+
| `separate_quota_pool` | a **child leg continuing across a parent quota condition** — the parent constrained, the child proceeding |
|
|
128
|
+
| `worker_respawn` | **one task continuing across a killed and re-spawned worker, same task id.** Never inferred from the fact that spawning and killing both exist separately |
|
|
129
|
+
|
|
130
|
+
### `agent_teams` is out of scope for a row, by construction
|
|
131
|
+
|
|
132
|
+
It is resolved **only** by the live environment probe and is never inferred from
|
|
133
|
+
a host id — `host_capability.ts` states that in the field's own doc comment, and
|
|
134
|
+
records that this repository has observed the flag's documented existence and
|
|
135
|
+
never its shape on any host. So: do not add it to a registry row. Observe it, if
|
|
136
|
+
at all, through the live probe.
|
|
137
|
+
|
|
138
|
+
### Observed-absent is not the same row as never-looked
|
|
139
|
+
|
|
140
|
+
Both render as `false`, and collapsing them is the defect this protocol opens
|
|
141
|
+
against — a reader then cannot tell whether a capability was tested.
|
|
142
|
+
|
|
143
|
+
- **Never looked** — the field is **absent from the row**. It resolves to the
|
|
144
|
+
safe default, and `describeHostCapabilities` reports its source as `default`.
|
|
145
|
+
This is the state that needs no marker, because the absence *is* the record.
|
|
146
|
+
- **Observed absent** — the field is present and `false`, and carries a
|
|
147
|
+
`<field>_absent` citation in the same doc comment. Present-and-`false` is the
|
|
148
|
+
marker: it is only reachable by someone who wrote it deliberately, and the
|
|
149
|
+
provenance surface then reports `registry` rather than `default` — which is
|
|
150
|
+
exactly the distinction, readable from `routing:doctor` without opening the
|
|
151
|
+
file.
|
|
152
|
+
|
|
153
|
+
### The four-part citation — a row without all four is not admissible
|
|
154
|
+
|
|
155
|
+
1. **the host** — the platform key from `hook_manifest.yaml`;
|
|
156
|
+
2. **the host version** at the time of observation;
|
|
157
|
+
3. **the transcript or artefact reference** the observation is read from;
|
|
158
|
+
4. **the date**.
|
|
159
|
+
|
|
160
|
+
Worked example, which a later row can be pattern-matched against:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
// subagent_spawn: OBSERVED — claude (Claude Code, Opus 5 1M session, 2026-08-22)
|
|
164
|
+
// agents/runtime/state/subagent-ledger/2026-08.jsonl: 445 `subagent_start`
|
|
165
|
+
// records and 420 stops carrying a measured `duration_ms`, i.e. 420 child legs
|
|
166
|
+
// whose start and stop pair. A measurable child duration is the criterion.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Pre-state, pinned so the Phase 2 diff reads as an addition
|
|
170
|
+
|
|
171
|
+
At the commit this protocol landed on, the registry was exactly:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
const HOST_CAPABILITY_REGISTRY = { claude: { subagent_spawn: true, parallel_spawn: true } };
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
One host, two fields. Six fields across seven other hosts resolved to the
|
|
178
|
+
all-`false` safe default.
|
|
179
|
+
|
|
103
180
|
## Related
|
|
104
181
|
|
|
105
182
|
- [`subagent-configuration`](../subagent-configuration.md) — the `subagents.*`
|
|
@@ -159,6 +159,42 @@ preservation test in that rule already splits them the same way:
|
|
|
159
159
|
use; the default stays `wait` either way. -->
|
|
160
160
|
|
|
161
161
|
|
|
162
|
+
### 2c. `traceability` — requirement to acceptance to evidence, OPTIONAL
|
|
163
|
+
|
|
164
|
+
**Optional for every complexity, including `structural`.** Absent means *not
|
|
165
|
+
declared*, which is a different claim from "there is no requirement". Nothing
|
|
166
|
+
fails for omitting it, and no gate enforces it — the only consumer is a listing
|
|
167
|
+
inventory (`check_requirements_trace`) that exits 0 always. Requiredness is
|
|
168
|
+
deliberately **not** decided here (AI council 2/2, 2026-08-22): deciding it
|
|
169
|
+
before the listing phase has produced a count is deciding it on intuition.
|
|
170
|
+
|
|
171
|
+
A repeated **row**, not three flat fields:
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
traceability:
|
|
175
|
+
- requirement_id: pointer-reaches-the-worker
|
|
176
|
+
acceptance_id: pointer-under-line-cap
|
|
177
|
+
evidence_refs:
|
|
178
|
+
- src/scripts/dispatch_r2_reviewer.ts
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Three flat top-level fields would be **countable but not traceable**: with more
|
|
182
|
+
than one requirement and a shared pool of refs the relation is an ambiguous
|
|
183
|
+
many-to-many, so a gate could report a populated count while providing no
|
|
184
|
+
dependable trace. The row carries the relation.
|
|
185
|
+
|
|
186
|
+
Both grammars are reused, never invented — the claim-ledger kebab slug
|
|
187
|
+
(`docs/CLAIMS.md` § Entry schema) for the two ids, and the envelope ref-token
|
|
188
|
+
rule (`_lib/subagent_response.ts`) for `evidence_refs`: ref tokens, never
|
|
189
|
+
bodies.
|
|
190
|
+
|
|
191
|
+
Identity semantics, revision semantics, the three senses of "gate" and the
|
|
192
|
+
`[AC:<id>]` convention — including the verified fact that nothing parses
|
|
193
|
+
`verify:` lines structurally today — are in
|
|
194
|
+
[`guideline:agent-infra/traceability-field-mechanics`](../../../../docs/guidelines/agent-infra/traceability-field-mechanics.md).
|
|
195
|
+
They are not optional reading: a slug grammar does not imply a namespace, and
|
|
196
|
+
`evidence_refs` are syntactically safe tokens rather than verified evidence.
|
|
197
|
+
|
|
162
198
|
## 3. Grants activated by acceptance
|
|
163
199
|
|
|
164
200
|
| Grant | Boundary |
|
|
@@ -31,6 +31,86 @@ orchestrator synthesises and re-verifies.
|
|
|
31
31
|
chars (~3k tokens against a measured ~251k spawn floor). Constants + checks:
|
|
32
32
|
`src/scripts/_lib/subagent_response.ts`.
|
|
33
33
|
|
|
34
|
+
## The canonical shape, and the three-way divergence it resolves
|
|
35
|
+
|
|
36
|
+
**Reconciled 2026-08-22** (`road-to-subagent-envelope-adoption` Phase 0, AI
|
|
37
|
+
council 2/2 convergent). One contract existed in three mutually inconsistent
|
|
38
|
+
states, and the ledger's `0 valid envelopes of 1,845 stops` could not be cited
|
|
39
|
+
as evidence about any one of them, because a reader had to assume which.
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
THE BODY SCHEMA IS `validateResponse`'S FIVE REQUIRED FIELDS. PRODUCERS CONVERGE
|
|
43
|
+
ON IT; THE VALIDATOR IS NOT WIDENED TO THE UNION OF WHAT PRODUCERS HAPPEN TO SEND.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Direction chosen: **narrow the contract to what the validator already accepts**,
|
|
47
|
+
not widen the validator. Widening makes every future divergence legal by
|
|
48
|
+
construction, which is how one contract came to have three states.
|
|
49
|
+
|
|
50
|
+
### Per-field divergence, one row per field
|
|
51
|
+
|
|
52
|
+
| Field | spawn-contract (f) | `team_dispatch` model JSON (`:297`) | `subagent_response.ts` validator | `dispatch_r2_reviewer` |
|
|
53
|
+
|---|---|---|---|---|
|
|
54
|
+
| `summary` | — (not a field clause) | present | **required** | silent |
|
|
55
|
+
| `handoff` | — | **absent** | **required** | silent |
|
|
56
|
+
| `confidence` | — | **absent** | **required** (`low\|medium\|high`) | silent |
|
|
57
|
+
| `findings` | — | present, `{severity, evidence, suggested_fix, location}` | **required**, `{title, evidence_refs?, mutating?}` | silent |
|
|
58
|
+
| `risks` | — | **absent** | **required** | silent |
|
|
59
|
+
| `artifact_paths` | — | absent | optional | silent |
|
|
60
|
+
| `assumptions` | — | absent | optional | silent |
|
|
61
|
+
| `status` | — | present, 3 model values | **not a body field** | silent |
|
|
62
|
+
|
|
63
|
+
An empty cell is a finding, not a pass. `dispatch_r2_reviewer` is silent on
|
|
64
|
+
every row — 1,292 lines with **0** hits for `envelope`, `DONE_WITH_CONCERNS`,
|
|
65
|
+
`response.contract` or `response_contract`.
|
|
66
|
+
|
|
67
|
+
### Four boundaries, because "the contract" was conflating them
|
|
68
|
+
|
|
69
|
+
The council's sharpest correction: schema, lifecycle state, delivery and
|
|
70
|
+
classification were being treated as one thing.
|
|
71
|
+
|
|
72
|
+
1. **Body schema** — the five required fields above, plus the two optional ones.
|
|
73
|
+
2. **Lifecycle frame** — `DONE` / `DONE_WITH_CONCERNS` / `NEEDS_CONTEXT` from a
|
|
74
|
+
model, plus `BLOCKED` orchestrator-side only (`team_dispatch.ts:391`'s
|
|
75
|
+
`_MODEL_STATUSES` is the three-value set a model may send). **Not a body
|
|
76
|
+
field**, which is why narrowing the body does not delete it.
|
|
77
|
+
3. **Delivery protocol** — serialize once, persist that exact serialization,
|
|
78
|
+
then emit the identical value as the final text-only message. This is
|
|
79
|
+
spawn-contract rule (f), and it **survives the narrowing**: its two clauses
|
|
80
|
+
are delivery invariants, not fields, so they were never candidates for the
|
|
81
|
+
validator's five.
|
|
82
|
+
4. **Classification** — validate and record against an explicit contract and
|
|
83
|
+
classifier version.
|
|
84
|
+
|
|
85
|
+
### Who owns the delivery protocol — and it is not the model
|
|
86
|
+
|
|
87
|
+
`team_dispatch.ts:280` asks a **read-only** model with no command or filesystem
|
|
88
|
+
access to return its review JSON. That model **cannot** satisfy "disk copy
|
|
89
|
+
written first", so rule (f) is an impossible prompt obligation for this
|
|
90
|
+
producer. The trusted dispatcher owns it: parse the producer's response, project
|
|
91
|
+
it into the canonical body, add the lifecycle frame, write the durable copy,
|
|
92
|
+
then emit the identical serialized value.
|
|
93
|
+
|
|
94
|
+
Recorded rather than implemented here — the projection adapter is a mechanism
|
|
95
|
+
this roadmap's Phase 1 does not ship, and saying so is cheaper than a contract
|
|
96
|
+
clause nobody can satisfy.
|
|
97
|
+
|
|
98
|
+
### The validator is not the reason the rate is zero
|
|
99
|
+
|
|
100
|
+
Checked directly on 2026-08-22, because "zero valid envelopes over 1,845 stops"
|
|
101
|
+
has three possible causes and they need separating: a validator that rejects
|
|
102
|
+
valid input, producers that do not emit the fields, or a shape nobody can
|
|
103
|
+
produce.
|
|
104
|
+
|
|
105
|
+
`validateResponse` was run by hand against a minimal envelope
|
|
106
|
+
(`{summary, handoff, confidence, findings: [], risks: []}`) and a rich one
|
|
107
|
+
(with `findings[{title, evidence_refs, mutating}]` and `artifact_paths`).
|
|
108
|
+
**Both validate.** The `team_dispatch` model shape fails on four of five.
|
|
109
|
+
|
|
110
|
+
So the contract is implementable and the validator is correct; the rate is zero
|
|
111
|
+
because producers do not emit the shape. That removes the precondition one
|
|
112
|
+
council seat set before any narrowing.
|
|
113
|
+
|
|
34
114
|
## Durable copy — the envelope on disk before the message
|
|
35
115
|
|
|
36
116
|
```
|
|
@@ -69,9 +69,15 @@ delegating unbounded execution of everything the task's data happens to say.
|
|
|
69
69
|
|
|
70
70
|
No deterministic gate inspects fetched/tool/RAG content for injected
|
|
71
71
|
instructions — the quarantine is carried by the model (ADR-135 lists it in the
|
|
72
|
-
CRITICAL policy class
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
CRITICAL policy class). Counting an adjacent lint here would be coverage
|
|
73
|
+
inflation, so none is counted.
|
|
74
|
+
|
|
75
|
+
**A content-scanning hook now exists and this field is unchanged.**
|
|
76
|
+
`injection_scan_hook.ts` is warn-only and default-OFF: it cannot refuse, and a
|
|
77
|
+
hook that cannot refuse does not enforce. This section used to say no such
|
|
78
|
+
backstop existed and that a future one would change the field — the first half
|
|
79
|
+
is now false, the second always was. Detail:
|
|
80
|
+
[`untrusted-input-spotlighting § The content-scanning hook`](../docs/guidelines/agent-infra/untrusted-input-spotlighting.md).
|
|
75
81
|
|
|
76
82
|
Body migrated to [`guideline:agent-infra/untrusted-input-spotlighting`](../docs/guidelines/agent-infra/untrusted-input-spotlighting.md) (per P4 of `road-to-kernel-and-router.md`) — runtime defense protocol (separate / spotlight / refuse role-takeover / no silent egress / untrusted agent-instruction files), hidden-instruction awareness (invisible Unicode + confusables), injection-signal taxonomy, least-agency → existing-gate OWASP mapping.
|
|
77
83
|
Trigger-set above activates this routing on demand, independent of the discipline profile (ADR-110).
|