Conversation
|
👋 Thanks for opening your first PR to Vexa, @jfw-ppi! Highly recommended (not required): hop into our Discord Your PR is judged on its evidence — the observation bundle + the diff — not on whether you |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c18d14099
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
2c18d14 to
5fd6ab7
Compare
🃏 Merge card — #1385
Not mergeable yet — every row above must be accepted before merge (choke point 1). Fill in what's ❌ above, then this clears automatically. How a PR reaches merge: the merge bar. |
bf7c092 to
c947d5d
Compare
…position root The sensor's default is 400ms - sized to span a packet gap, not a speech pause. Measured entry-timestamp staleness during real pauses is p50 550ms, so the MEDIAN natural pause trips a synthesized deactivation and one speech phase fragments. Against the current channelizer (5 x 30 min seeded tapes): 400ms gives 1.67 lane activations per real turn, 800ms gives 1.13 - the knee - for 1.8pp more contamination; 1600ms starts merging turns. The value ships as a PARAMETER at the composition root: the sensor owns the `inactiveMs` seam and its packet-gap default, nothing more. Overridable via VEXA_CSRC_INACTIVE_MS - forwarded to spawned bots by the runtime kernel's tuning allowlist (profiles.py), inherited from the host env on the lite/process backend. An override that was SET but is unusable (empty, NaN, below one 100ms poll, above 10s) warns and falls back to the measured default: a NaN window makes both of the sensor's comparisons false and re-deactivates every source on every poll - the exact fragmentation this value exists to end, worse and silent. Scope: fragmentation only - no value of inactiveMs/lookbackMs/ flickerHoldMs brings lane contamination into a usable range (see TEAMS_CSRC_CONTESTED_TRANSCRIPTS.md). Measured in a downstream deployment against real Teams sessions and ported here against the same seams. Closes Vexa-ai#1383 Signed-off-by: Jacob Weinhold <29459386+jfw-ppi@users.noreply.github.com>
c947d5d to
b61e54e
Compare
…an unusable window The composed 800 ms window shipped, but the override could not reach a bot on compose or helm: both render only the six BOT_* tuning keys onto the runtime, so the kernel's allowlist never saw it. Now compose, helm (runtime.csrcInactiveMs) and lite render it, the runtime's config.v1 declaration carries it (gate:config-contract), and the configuration reference documents it. Blank is unset. The deploy templates render an unset knob as an empty string and every other bot tuning knob reads that as "no override"; the resolver now does the same, so a default deployment boots without a false warning. A non-blank unusable value still warns and falls back. The sensor is the point of introduction of the NaN failure mode (both liveness comparisons false, every source flipped on every poll), so it now refuses a non-finite or sub-poll window from any caller, falls back to its default and says so through its log. Pinned for NaN, a sub-poll value and Infinity. The two mixed-pipeline comments that stated the sensor's 400 ms as a fact now state the composed window. The capture-bridge rationale names the measurement as downstream and the pipeline it was replayed through; the changelog fragment claims the mechanism proved and labels the activations-per-turn reduction as a downstream measurement. Refs Vexa-ai#1383 Signed-off-by: Jacob Weinhold <29459386+jfw-ppi@users.noreply.github.com>
Signed-off-by: Jacob Weinhold <29459386+jfw-ppi@users.noreply.github.com>
Delivers issue: #1383 — mechanism delivered; the issue's live leg (row A3) is now witnessed upstream by the author on a real Teams meeting (C0); the non-author sign-off is still open.
Contribution rights
under Apache-2.0, and it is not owned or controlled by an employer, client, or other entity.
may control this contribution. I am requesting Vexa's private corporate-authorization process.
Every commit carries my DCO
Signed-off-by.What & why
The transport sensor's
CSRC_INACTIVE_MS = 400spans a packet gap; in real Teams meetings it also does speech-pause duty, where it is too short: entry-timestamp staleness during natural pauses is p50 ≈ 550 ms, so the median pause trips a synthesized deactivation and one speech phase fragments. Replayed through the Teams CSRC channelizer, 400 ms gives 1.67 lane activations per real turn; 800 ms gives 1.13 (the knee) for ~1.8 pp more contamination; 1600 ms starts merging turns. Those numbers are a downstream measurement (#1383); this PR ports the mechanism.capture-bridge.ts) passes 800 ms through the sensor's existinginactiveMsparameter. The sensor keeps its packet-gap default and now refuses a non-finite or sub-poll window from any caller — it is the point of introduction of the NaN failure mode (both liveness comparisons false, every source flipped on every poll).VEXA_CSRC_INACTIVE_MSoverrides it per deployment: rendered onto the runtime by compose, helm (runtime.csrcInactiveMs) and lite, declared in the runtime's config.v1, forwarded to spawned bots by the kernel's tuning allowlist, documented in the configuration reference. Unset or blank ⇒ the default, silently — the templates render an unset knob as an empty string, and every other bot tuning knob reads it that way; a non-blank unusable value (NaN, below one 100 ms poll, above 10 s) warns and falls back.mixed-pipelinecomments that stated the sensor's 400 ms as a fact now state the composed window.Scope: fragmentation only. Lane contamination is out of scope (
TEAMS_CSRC_CONTESTED_TRANSCRIPTS.mdcovers the adjacent contested-words problem).Observation bundle
C0 — the author's live witness (upstream, this head, real Teams) · a compose stack built from this tree (
vexa-v012, PR bot image5d493bfa972f, PR runtime image built from the same tree and pinned by its own tag; local CPU Whispersmallviadeploy/transcription; nothing external) in a real Teams meeting, one witness bot spawned throughPOST /bots, admitted by hand. Three rounds, each read off the witness's own<session>.csrc.jsonlsidecar and its[Csrc] csrc poll started (100ms, inactive after N ms)log line, withVEXA_CSRC_INACTIVE_MSset on the compose.env→ runtime container → spawned bot env (verified bydocker inspectat each hop):Synthetic speech, two speaker bots (Piper TTS), same ten-turn exchange at both windows: 1.00 activation per utterance at 800 ms and at 400 ms, one attributed transcript segment per utterance both times — no regression at 800 ms; synthetic speech never pauses long enough to discriminate the windows.
One human reading ten scripted sentences with natural pauses, once per window: 400 ms → 13 activations, 7 re-activations within 0.6 s of the previous deactivation, 8 transcript segments with two garbled; 800 ms → 5 activations, 9 attributable segments. The reading cadence differed between the two readings, so this row shows the direction only.
The same two recordings (the witness's own recordings of round 2, 74 s and 72 s), replayed through a speaker bot into both windows — cadence held constant:
· concluded: on identical human audio the 800 ms window halves the transport activations for the same ten sentences and removes most sub-window re-activations, on both recordings; the composed window and the override reach the real bot on compose. Absolute counts are below the live reading because the replay re-encodes through a bot's virtual microphone; the ratio holds. Not claimed: the downstream per-turn numbers (C5), which need many speakers and hours; this is one voice, ten sentences, two recordings. Full timelines and tapes kept by the author; the recordings are the author's own voice and can be shared with a validator.
C1 — sensor ·
pnpm --filter @vexa/mixed-capture-core test· green: 500 ms of silence held open inside a caller's 800 ms window, deactivation synthesized past it;inactiveMsofNaN,50andInfinityeach fall back to 400 ms with one activation and no flip-flop, said throughlog.C2 — composition root ·
npx tsx src/csrc-wiring.test.tson the built bundle, plain and withVEXA_CSRC_INACTIVE_MS=abcambient · green both times: the real bridge hands the real sensor factoryinactiveMs=800; garbage/zero/negative/sub-poll/over-ceiling fall back with one warning each; unset, blank and a good override are silent. Negative control: deleting the oneinactiveMs: csrcInactiveMs,line from the page-side call turns 2 checks red — the two named RED-at-base.C3 — kernel + deploy surfaces ·
test_profiles.py+test_config_contract.py(22 passed);deploy/helm/tests/test_template.sh(gate:helm PASS);helm template --set runtime.csrcInactiveMs=1200anddocker compose configwith the env set · the runtime carriesVEXA_CSRC_INACTIVE_MS: "1200"on both.C4 — workspace · full
@vexa/botsuite exit 0; gate:node (18 packages build + test) green;node scripts/gates.mjs allgreen exceptconfig-contract, which named the missing declaration — declared, that gate re-run green; the full sweep was not re-run after that one-line fix.C5 — measurements · downstream, prior to this port: staleness percentiles and the 400/800/1600 ms sweep over 5 × 30 min tapes. Not reproducible here — the tapes carry meeting audio, and the percentiles need raw poll samples a
csrc.jsonltape (post-window transitions) does not record.Acceptance floor (the issue's numbering)
csrc-poll.test.ts); composition passes 800 (capture-bridge.tsCSRC_DEFAULT_INACTIVE_MS, asserted on the object that crosses to the sensor); override and unusable-window refusal pinned incsrc-poll.test.tsresolveCsrcInactiveMs+ warning pinned incsrc-wiring.test.ts(floor/ceiling boundary-exact; blank silent); reachability pinned bytest_profiles.py(kernel) and the helm/compose renders (C3)Docs diff (D6c)
docs/changelog.d/1385-csrc-inactive-window.md(the mechanism proved; the reduction labelled a downstream measurement), theVEXA_CSRC_INACTIVE_MSrow indocs/docs/configuration.mdx,runtime.csrcInactiveMsinvalues.yaml.Security checks
No new dependencies, no lockfile change. The templates pass one env string through, the kernel copies it verbatim, the bot
JSON.stringifys it in its one warning and hands the page a number. Nothing touches auth, secrets or the network.Validation request
A non-author with Teams capture: reproduce C0 round 3 in about ten minutes — a stack from this head, one witness bot, and either read ten sentences with natural pauses yourself or replay any recording of natural speech through a second participant, once with
VEXA_CSRC_INACTIVE_MS=400on the runtime and once unset. Compare the activation count in the witness'scsrc.jsonl(or thecsrc-crossedcounter in its log) for the same audio; the author's two recordings are available on request. Deployments validated in this PR: compose, live (C0); helm and lite: template render only (C3), no live run — honestly unclaimed.Era
Based on and verified against
main@3f5c3c03(the v0.12.26 train).Authorship
Sole author: the human submitting this. No agent co-author trailers (D13). Tooling disclosure: port and verification assisted by Claude Code; the measurements are from live captures in a downstream deployment.