Swarm 0.10.0: out-of-band transport, telemetry, model discovery, one config parser - #54
Open
gering wants to merge 10 commits into
Open
Swarm 0.10.0: out-of-band transport, telemetry, model discovery, one config parser#54gering wants to merge 10 commits into
gering wants to merge 10 commits into
Conversation
The prompt travelled as one argv word, so exec's MAX_ARG_STRLEN (128 KiB on Linux) was the binding limit and forced a 120 KiB cap. Above it the skill set EXTERNALS_OVERSIZE and dropped EVERY external voice — the same damage as a backend timeout, from a limit that was never inherent to the CLIs. Neither CLI needs the prompt on argv: codex reads it from stdin (`-- -`), grok takes `--prompt-file`. The adapter now normalizes every input form to one file and hands over the PATH, so the diff never enters a shell variable either. - Cap now bounds model context, not exec: SWARM_MAX_PROMPT_BYTES (default 512 KiB). Adapter and the skill's oversize guard read the same env knob with the same default, so an override reaches the externals instead of being short-circuited by a skip that never heard about it. - Temp prompts are chmod 600 before content lands and removed by the EXIT trap on every path; a caller-owned --prompt-file is never mutated, so concurrent per-cluster voices sharing one prompt file cannot corrupt each other. - grok's --prompt-file is preflighted (stubbable, so the argv tests stay hermetic) with an upgrade error — never a silent fallback to --single, which would reinstate the wall as a mystery failure on big diffs. - test_sandbox_deny.py pins the transport itself (regressions are silent: only large diffs would start failing); test_lens_sync.py pins the two cap defaults together and keeps the 4 KiB --lens-instr headroom covered. Verified end-to-end at 164 KiB through both backends. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
The timeouts were long attributed to prompt size. Measured on one 42 KB diff, one variable at a time, that is wrong: grok high breakage 374s 4 findings grok low breakage 161s 4 findings grok high consistency 28s 6 findings codex high breakage 104s 2 findings A 164 KiB control prompt returned in 20s (grok) / 8.6s (codex). The lens CLUSTER dominates (13x), effort is secondary (2.3x, and bought zero extra findings here), and backends differ 3.6x — grok is simply the slow voice on the cluster whose briefs demand exploration (cross-file-trace reads neighboring files). Size is ruled out. Chunking the diff would therefore target the one variable measurement excludes; splitting by LENS targets the one that dominates. Recorded in the knowledge entry so the next round starts from data instead of the old assumption. - agents.sh: `run --telemetry <file> --unit <name>` appends one JSON line per call (duration, effective effort/model, prompt bytes, backend rc, timed_out, and the wall the call actually ran under). Written from the EXIT trap, so a timeout is recorded too; the backend's own rc is captured before it is translated into the adapter exit code, or 124 and 1 would be indistinguishable. - telemetry-report.py renders it under the balance block and flags any SURVIVING call at >=60% of its wall — the case backendErrors structurally cannot show, since a voice finishing at 550s and one at 20s are both "ok". - Opt-in end to end: no --telemetry means the previous behaviour, byte for byte. Diagnostics never fail a review — a missing, truncated or malformed file degrades to less output, never a non-zero exit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
Proposed as a speed fix; the measurement corrected that, and the correction is recorded rather than quietly dropped: old: one 3-lens breakage call 374s -> 4 findings, THREE of them cross-file-trace new: breakage (2 lenses) 313s -> 4 findings the combined call missed entirely new: reach (cross-file-trace) 126s -> 4 findings, ~the combined call's set The real defect was LENS CROWD-OUT: one lens consumed the call while correctness/removed-behavior barely reported. Split, the diff-local lenses found four issues the combined call never surfaced. It is NOT a throughput win — the longest call drops only 374->313s and total work rises to 439s, so no single lens split clears the 600s wall. Effort remains the largest untried runtime lever (374->161s for identical findings). Two further effects, neither reachable by lowering effort: a timeout now costs one lens instead of three (the family-critical case — grok is the only third-family voice), and `reach` holds no MANDATORY lens, so the gate may prune the whole call on a diff with no cross-file surface. Fixes found by the new breakage voice reviewing this very branch: - The skill's EXTERNALS_OVERSIZE guard read SWARM_MAX_PROMPT_BYTES without the adapter's validation. A malformed value expands to 0, the threshold goes negative, and EVERY external voice is dropped SILENTLY — while the adapter refuses the same value loudly. Now rejected symmetrically (SWARM_CFG_ERR), pinned by test_lens_sync.py in both directions. - The grok --prompt-file capability probe ran `grok --help` unbounded, outside with_timeout: a wedged CLI would hang the review before any review work. Now capped by SWARM_PROBE_TIMEOUT with -k, degrading to "assume supported" where no timeout binary exists rather than hanging or refusing. - A header comment still promised a --single fallback the preflight replaced with a hard error. Also measured and REJECTED: `grok --max-turns` (10 -> 10s but ZERO findings; 20 -> 279s, 4). The truncated run exits rc=0 with empty findings, so the pipeline reads a silenced voice as "reviewed cleanly, found nothing" — worse than a timeout, which at least reaches backendErrors. Documented in the knowledge entry so it is not retried blind. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
Two leftovers from the timeout task, both about making an unavoidable failure legible rather than preventing it. Timeout passthrough. The adapter's cap and the Bash window the transport agent runs under both defaulted to 600s, so which fired first was undefined — and when the outer one won, the run lost rc=124, the "timed out after Ns" message and the telemetry timeout flag, leaving a bare killed command. That lost diagnosis is why raising SWARM_TIMEOUT looked counterproductive. It now travels skill → workflow, which pins the adapter cap a margin below the Bash window so it always wins the race, and says so when a requested value exceeds what one Bash call can hold. SWARM_TIMEOUT=0 is passed through, with a log line that the outer window still kills at 600s and will report generically. This does NOT raise the ceiling — only async transport can (tasks/async-poll-external-voices.md). Family coverage. Consensus is defined as ">=2 agreeing families", so losing one silently changes what every CONSENSUS and every solo MEANS: a finding that would have been corroborated is routed through the adversarial verifier instead. The counts look identical to a healthy run — that silent degradation is the reason this task existed. balance now carries familiesExpected/Present/Lost and consensusReachable, and the report prints a warning directly under Bilanz:, including the case where fewer than two families survived and NO finding can reach consensus. Presence is per family, not per call: one dead cluster beside a live one is not a lost family (that stays a backendErrors entry). Both pinned by test_lens_sync.py, including that the Bash window is derived rather than a second hard-coded literal — the tie is the bug. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
grok had been absent from EVERY review since CLI 1.0.3 — silently. That release
changed the `grok models` bullet marker so only the DEFAULT keeps `*`:
* grok-4.6 (default)
- grok-4.5 <- the pinned model, invisible to a `*`-only matcher
So readiness reported "this CLI does not offer grok-4.5" for a CLI that offers
it, and the sole third model family dropped out of the ensemble. No timeout, no
error — just two families where the report claimed three. Same damage as the
600s wall this branch is about, reached by a different route.
Rather than re-pin to 4.6 and wait for the next break, the model is now
DISCOVERED. Ported from ~/dotfiles' cc-harness-agents (same provider), with one
gate substituted: that helper withholds an upgrade until a model's context
window is known; the adapter withholds it until --json-schema ENFORCEMENT is
known, because a model that merely accepts the flag returns
structuredOutput:null and fails after a full review is paid for.
- GROK_CANONICAL_RE accepts only bare version ids, major >= 4 — rejecting dated
snapshots, reasoning/non-reasoning splits, multi-agent, build, composer and
image/video variants. Major >= 4 keeps a catalog regressing to grok-3* from
pulling the ensemble backwards.
- Ordering is component-wise: grok-4.20 beats grok-4.6. As a decimal fraction it
would lose, but the provider means the 20th minor release and already ships
4.20-derived ids.
- GROK_SCHEMA_VERIFIED is the hard gate AND the upgrade ritual: a newer
canonical model is named on stderr, never selected. Verified on CLI 1.0.3 that
grok-4.5 and grok-4.6 both return an envelope whose .structuredOutput carries
the schema's findings; reviews now run on grok-4.6.
- Readiness and the run_grok preflight moved from "is THIS id listed/requested"
to "is a schema-verified model on offer/requested" — the exact-id form is what
let the marker change drop the backend. An explicit --model still bypasses
discovery, never the schema gate.
test_grok_models.py pins both listing formats against the SHIPPED awk program
(extracted, never re-typed) plus the ordering, the filter against the live
14-id catalog, the verified gate, and that the fallback pin is itself verified.
Two self-inflicted test bugs found and fixed while writing it: an extraction
regex that silently matched nothing (every assertion then passing over empty
output), and a verdict block left mid-file so the discovery half's failures
were recorded but never read.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
A full /swarm:review of this branch: 23 findings across 3 model families and 11 lenses, 17 agreed, 5 partial, 1 declined. The two critical ones were introduced by the preceding commits in this very PR. Degraded-discovery fallback pointed at the NEWEST verified model. That value is reached ONLY when the model list could not be read — precisely when least is known about the host — so a CLI too old to offer grok-4.6 got an unknown model id, rejected every call, and lost the whole grok family for the run. The exact silent-family-loss this branch exists to prevent, reintroduced by its own model bump. It is now the OLDEST verified id; discovery still selects grok-4.6 whenever the list is readable, and the test pins the invariant (oldest verified) rather than the literal value. --unit / --telemetry were interpolated into the transport command unquoted while the neighbouring --lens-instr was shell-quoted. Both go through shQuote now. Also fixed: - The `grok --help` probe read a timed-out probe (rc 124/137, empty stdout) as "flag absent", telling users to upgrade an already-current CLI while the voice died. It degrades like the sibling model probe now. ready_hint blamed the CLI for what is often a missing GROK_SCHEMA_VERIFIED entry; it names the right remedy per case. - Timeout margin 30s -> 60s: it did not cover the adapter's own bounded probes, so the outer Bash window could still win the race. The default no longer requests a value it will always cap, so the "exceeds what one Bash call can hold" warning stops firing on every default run. - Telemetry string fields are JSON-escaped (a malformed record is silently SKIPPED by the reader — it reads as "that voice never ran"), and the report marks calls that died in the adapter before the backend ran, previously indistinguishable from a fast success. - The consensus-unreachable warning no longer hides inside the families-lost branch: a run that only ever had one family loses nothing yet still cannot form consensus, and printed nothing at all. - SWARM_MAX_PROMPT_BYTES normalized with 10# (leading zero was read as octal); the stdin path bounds what it writes to disk instead of measuring after; the report labels grok by family, not by an id it cannot keep current. - Docs swept for discovery + the 5-cluster split. Activation surfaces (plugin.json, marketplace.json, CLAUDE.md) are model-name-free — they load in every session and a version there goes stale by itself. - Test hygiene the review caught in the tests I added last round: a shadowed name, mid-file imports, an unreachable check(), and fixtures that never got cleaned up. Declined: replacing the hand-rolled version ordering with `sort -V`. It works on this host, but the ordering deliberately mirrors the cc-harness-agents implementation that ranks the same ids; two implementations free to diverge cost more than the 40 lines saved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
17 findings, 3 model families, no backend errors. Both criticals were HALF-DONE
fixes from 0.9.3 — the same mistake twice, each time in one half of a pair:
SWARM_MAX_PROMPT_BYTES was decimal-forced in the skill but not in the adapter.
The two sides of one shared gate then read the same value differently: 0100000
is 100000 in the skill (lets every voice through) and octal 32768 in the adapter
(rejects each one), converting the single deterministic skip into exactly the
per-call error storm that guard exists to prevent. 080000 additionally died in
arithmetic under set -e instead of erroring cleanly. Both sides normalize now,
and the test requires it of BOTH rather than of one.
The transport command quoted only the arguments 0.9.3 added. ADAPTER and
EXTERNAL_PROMPT sat in plain double quotes on the same line — which do not stop
$(...), backticks or ${...} from expanding in the shell that runs the string —
immediately under the comment explaining why TMPDIR-derived paths must be
quoted. Every interpolated path goes through shQuote now.
Also:
- The empty-prompt guard had weakened from "no visible content" to "zero bytes"
when 0.8.0 moved the prompt out of a shell variable, so a whitespace-only
prompt would spend a full backend call. Checks for non-whitespace again.
- SWARM_TIMEOUT reaches the workflow only when the user actually set it —
hardcoding 600 meant the derived default was never used and the "exceeds what
one Bash call can hold" warning still fired on every stock run, which 0.9.3
claimed to have stopped. It is decimal-forced too: the value lands in a bare
JS numeric literal where 0600 is legacy octal 384.
- Telemetry: _json_escape now covers every control character (JSON forbids all
of them unescaped, and the reader DROPS a malformed record — which reads as
"that voice never ran"); timeout_seconds:0 means cap-disabled, not
field-missing, so an uncapped call stops being scored against a wall that
never applied; a non-numeric field can no longer crash a report whose whole
contract is to never fail a review.
- One _bounded_probe primitive replaces a timeout prelude that existed three
times and had already drifted: one copy checked rc before trusting output,
another swallowed it and read empty output as a definite "flag absent".
- Smaller: no empty "(ausgefallen: )" in the case that warning was written for;
_grok_version_newer refuses leading-zero components instead of aborting;
ready_hint forks once; the prep block reads the prompt size once; the agents
skill and pipeline-blueprint caught up with discovery and the 5-cluster split.
Declined: folding GROK_CANONICAL_RE into the verified table (the filter must
also see UNVERIFIED newer models — that is the entire upgrade signal), and
caching grok probes across adapter processes (staleness in a path whose probes
are already bounded).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
Third review round found its criticals in the previous round's fixes again — same shape each time: a value two places must agree on, fixed in one of them. Answer the class, not the instance. - Add `agents.sh config`: the resolved, validated numeric configuration as key=value lines. The skill reads it instead of re-parsing SWARM_*. - Add `_resolve_int` as the one parser (digits-only, 10# decimal, range check after conversion, wrap guard, explicit upper bound). - Enforce the timeout with `-k`: SIGTERM alone let a backend outlive the cap, so the outer window killed the adapter and no telemetry survived. - Cap SWARM_PROBE_TIMEOUT at 20s and document the coupling to the workflow's TIMEOUT_MARGIN_S. - Move grok's --prompt-file probe into readiness; validate a --model override against the offered list. - Use 126, not 127, as _bounded_probe's "cannot bound" sentinel. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
gering
force-pushed
the
task/fix-swarm-timeout-ceiling
branch
from
August 22, 2026 17:54
77ad813 to
1bbd385
Compare
`cat <<HDR` must stay unquoted so $NONCE and $CAP_RULES expand, but that also evaluates backticks in the body. The rule naming the allowed finding prefixes carried markdown backticks around `[lens]`, so bash ran it: every review since 0.7.0 printed "[lens]: command not found" and shipped a prompt whose rule had lost the tag it was describing. Found by running the prep block end-to-end rather than reading it. test_lens_sync.py now rejects any backtick or $( inside an unquoted heredoc there, and was verified to fail on the reintroduced bug. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
First review run on 0.10.x, all three families live, 190 KiB prompt. 13 agreed findings applied. - agents.sh config reports probe_budget_seconds; the skill passes it and the workflow builds TIMEOUT_MARGIN_S from it. The old literal restated the adapter's constants in a comment, and 0.10.0's third bounded probe pushed the worst case to 69s against a 60s margin — the outer window would win the race and destroy the rc=124 + telemetry evidence. - Memoize the --help capability probe (at most two probes per run). - Treat rc 137 as a timeout everywhere via _is_timeout_rc: -k SIGKILLs a SIGTERM-ignoring backend, and every consumer keyed on 124 alone. - Resolve SWARM_TIMEOUT/SWARM_PROBE_TIMEOUT lazily so --help/jail/list survive a malformed knob; run resolves in the main shell so the wall reaches both the message and the telemetry record. - Quote the cap that actually fired, not a hard-coded 512 KiB. - Drop the empty require_valid_timeout stub; fix stale 126/127 comments, the third grok remedy, the degrade warning, a duplicated test, the telemetry-report mode bit, and a wrong claim in the 0.9.4 entry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Swarm reviews reproducibly lost an entire model family — three runs in a row, always
grok × breakageat exactly 600 s. This PR removes the adjacent failure mode, measures away several wrong theories, and makes the remaining one legible. It does not raise the 600 s ceiling; that needs an async transport and is split out intotasks/async-poll-external-voices.md.exec'sMAX_ARG_STRLENis no longer the binding limit. Above the old cap the skill dropped every external voice — the same damage as a timeout, from a limit that was never inherent to the CLIs.rc=124survives; per-call telemetry exposes voices approaching the wall before they cross it; a lost model family is called out where it changes meaning — in the consensus line.Measurements (these drove the decisions)
Same 42 KB diff, one variable at a time:
Control: a 164 KiB prompt returned in 20 s (grok) / 8.6 s (codex) — 4× the bytes, 1/20th the time.
grok --max-turns: rejected. N=10 → 10 s but zero findings; N=20 → 279 s. The truncated run exitsrc=0with empty findings, so the pipeline reads a silenced voice as "reviewed cleanly, found nothing" — worse than a timeout, which at least reachesbackendErrors.add-swarm-review-profiles.Changes
Transport (0.8.0) — codex reads the prompt from stdin (
-- -), grok via--prompt-file; the adapter passes the file path through instead of reading it into a shell variable. Cap is now model context (SWARM_MAX_PROMPT_BYTES, 512 KiB), read by adapter and skill from the same knob so an override reaches both. Verified end-to-end at 164 KiB on both backends.Telemetry (0.8.1) —
agents.sh run --telemetry <file> --unit <name>records duration, effective effort/model, prompt bytes, backend rc,timed_outand the wall the call ran under, written from the EXIT trap so timeouts are captured.telemetry-report.pyflags any surviving call at ≥60 % of its wall — the casebackendErrorsstructurally cannot show.Lens split (0.9.0) —
cross-file-tracemoves into its ownreachcluster. The measured reason is lens crowd-out: the combined 3-lens call returned 3 of 4 findings from one lens; split, the other two found 4 issues it had missed entirely. Not a speed fix — the longest call drops only 374 → 313 s.Diagnosis (0.9.1) — both timeouts derive from one value, with the adapter cap pinned below the Bash window so it wins the race and
rc=124survives (the old 600/600 tie is why raisingSWARM_TIMEOUTlooked counterproductive). The balance block now names a lost model family and states that consensus weakened — or became unreachable.Model discovery (0.9.2) — the grok model is discovered from
grok modelsinstead of pinned: a canonical-id filter, component-wise version ordering (sogrok-4.20sorts abovegrok-4.6, which string comparison gets backwards), and a hard verification gate — a model must be schema-verified before the adapter will run it, because a CLI that merely accepts--json-schemaand returnsstructuredOutput: nullfails only after burning a full review. The remaining pin is a floor, deliberately the oldest verified id. This section exists because grok CLI 1.0.3 changed its listing format to mark only the default with*, and the old*-only matcher concluded the pinned model was not offered — dropping grok from every review, silently.test_grok_models.pynow parses the shippedawkprogram out ofagents.sh(never a retyped copy) and pins both listing formats against it.One parser for the numeric knobs (0.10.0) — new verb
agents.sh configprints the resolved, validated configuration (max_prompt_bytes,cap_headroom,oversize_threshold,timeout_seconds,probe_timeout_seconds); the skill's prep block reads those lines instead of re-deriving them. One_resolve_intenforces digits-only,10#decimal forcing, a range check after conversion, a length guard against 64-bit wrap, and an explicit upper bound. Also:with_timeoutescalates to SIGKILL (-k 3) — plain SIGTERM let a backend outlive the cap, so the outer Bash window killed the adapter instead and no telemetry survived;SWARM_PROBE_TIMEOUTis capped at 20 s and the coupling to the workflow'sTIMEOUT_MARGIN_Sis documented on both sides; grok's--prompt-fileprobe moved into readiness (a CLI without it now reports not-ready once, instead of every cluster failing identically); a--modeloverride is validated against the offered list;_bounded_probeuses 126, not 127, as its "cannot bound this call" sentinel, sincetimeoutitself exits 127 for a missing command.Prompt heredoc (0.10.1) —
cat <<HDRis unquoted on purpose ($NONCE/$CAP_RULESmust expand), which also evaluates backticks in the body. The rule listing the allowed finding prefixes was written with markdown backticks around`[lens]`, so bash ran it as a command: every review since 0.7.0 printed[lens]: command not foundand shipped a prompt whose rule had lost the very tag it describes. Found by executing the prep block rather than reading it — the three self-reviews below could not see it for exactly that reason.test_lens_sync.pynow rejects any backtick or$(inside an unquoted heredoc there.Review of 0.10.x (0.10.2) — the first run on this branch's own adapter, all three families live, 190 KiB prompt (the size that would have dropped every external voice before 0.8.0). 21 findings, 13 applied. The critical one closed the loop on 0.10.0:
TIMEOUT_MARGIN_Swas a hand-derived literal restating the adapter's probe constants in a comment, and 0.10.0's third bounded probe pushed the worst case to 3 × 23 = 69 s against a 60 s margin — the outer window would win the race again and destroy therc=124+ telemetry evidence.agents.sh configreportsprobe_budget_secondsnow, the skill passes it, the workflow derives its margin from it, and the--helpprobe is memoized. Also:rc=137counts as a timeout everywhere (-kSIGKILLs a SIGTERM-ignoring backend — which grok is documented as being — and every consumer keyed on 124 alone); a malformedSWARM_TIMEOUTno longer exits 2 from--help/jail/list; the oversize message quotes the cap that actually fired instead of a hard-coded 512 KiB.What three self-reviews found
The branch reviewed itself three times (
/swarm:review --fix). Round 1 found real defects in the feature code — the skill's oversize guard readSWARM_MAX_PROMPT_BYTESwithout the adapter's validation, so a malformed value made the threshold negative and dropped every external voice silently; the grok capability probe rangrok --helpunbounded outsidewith_timeout.Rounds 2 and 3 then found only defects introduced by the previous round's fixes, and always in the same shape: a value two places must agree on, corrected in one of them.
Patching the reported instance never ended the class, so 0.10.0 removes the second parser rather than fixing it a fourth time.
test_lens_sync.pyguards the design directly — it requires the single parser and theconfigdispatch, and negatively asserts that no second parse reappears in the skill.Readiness
test_telemetry_report.py,test_grok_models.py, plus transport + coupling guards in the existing suites);check-structure.pycleanswarm-backend-adapter.md+swarm-review-pipeline.mdcarry the measurement matrix, the rejected alternatives, the discovery design and the one-parser rationalemainTest plan
/swarm:reviewon a normal diff — three full rounds run on this branch; externals participate,Voices:timing section appears under the balance blockEXTERNALS_OVERSIZE=0at 190 KiB against the adapter-reported threshold (the old 118 784-byte constant would have skipped every external voice)SWARM_MAX_PROMPT_BYTES=abc→agents.sh configexits 2 with one message, so the skill stops instead of silently reducing the ensemble to Claude-only. Also verified:0100000resolves to 100000 (not octal 32768), a cap at/below the 4096-byte headroom is refused, andSWARM_PROBE_TIMEOUT=300is refused against the 20 s ceilingSWARM_TIMEOUT=5against grok returnedgrok timed out after 5sin 6.7 s wall (cap + probe overhead),adapter_rc=1, and the telemetry record{"backend_rc":124,"timed_out":true,"timeout_seconds":5,"model":"grok-4.6"}— i.e. the inner cap wins the race, the EXIT trap still fires, and discovery picked the newest verified model. The consensus-line wording downstream of this is workflow-side and unchanged by this branch🤖 Generated with Claude Code
https://claude.ai/code/session_01JHKreruna9RfZHcEq6YPub