Repository navigation
Description
Problem
bin/agy-proxy.mjs parses all four of its numeric environment knobs with a bare Number(...) and no validation (main bd880194, file sha256 7de2c21d…):
bin/agy-proxy.mjs:168—MODELS_TTL_MS = Number(process.env.AGY_PROXY_MODELS_TTL_MS || 300000)bin/agy-proxy.mjs:453—TURN_TIMEOUT_MS = Number(process.env.AGY_PROXY_TURN_TIMEOUT_MS || 300000)bin/agy-proxy.mjs:456—MAX_LIVE_WORKERS = Number(process.env.AGY_PROXY_MAX_LIVE_WORKERS || 32)bin/agy-proxy.mjs:457—SESSION_IDLE_TTL_MS = Number(process.env.AGY_PROXY_SESSION_TTL_MS || 30 * 60 * 1000)
The proxy starts healthy with any of these typo'd, and each bad value silently breaks a different safety/behaviour knob instead of failing at startup.
Verified behaviour (laptop probe, verbatim parsing + consumer expressions)
Probe: ~/git/fleet/probe-2026-10-28-laneA-agyenv/probe.mjs on the laptop, against the shipped parsing shape and the exact consumer comparisons. Control (unset / 300) behaves correctly in every case.
AGY_PROXY_*='abc'→NaNeverywhere:- Model catalog never refreshes:
:290Date.now() - modelsFetchedAt > MODELS_TTL_MSis3600000 > NaN= false even an hour later — the proxy serves the stale/fallback catalog forever. - Idle sessions never evict:
:695now - w.lastUsedAt > SESSION_IDLE_TTL_MSis false at any age. - The live-worker cap never fires:
:701live.length >= MAX_LIVE_WORKERSis100 >= NaN= false — warmagyworkers accumulate unbounded. - Every turn "times out" immediately:
:641setTimeout(..., TURN_TIMEOUT_MS)withNaNis clamped to 1 ms (NodeTimeoutNaNWarning), so each turn is killed and reported asagy turn timed out after NaNms.
- Model catalog never refreshes:
AGY_PROXY_TURN_TIMEOUT_MS='-5'or'9999999999999'(>2³¹): Node clamps both to 1 ms (TimeoutNegativeWarning/TimeoutOverflowWarning) — measured firing at ~3–7 ms vs the 300 ms control firing at 301 ms. Same total breakage as the typo case, with a plausible-looking value in the unit file.AGY_PROXY_MAX_LIVE_WORKERS='0': the eviction loop at:701runswhile (live.length >= 0), which is true even for an empty list;live.shift()yieldsundefinedand destructuring it throwsTypeError: undefined is not iterableinsideevictLiveWorkersIfNeeded(called from the 60 s interval at:708and fromacquireWorker). Reproduced verbatim in the probe.- Negative TTLs invert the gates the other way:
MODELS_TTL_MS=-5re-pulls the catalog on every check,SESSION_IDLE_TTL_MS=-5evicts every live worker on every sweep.
Why it matters
These are operator knobs in systemd unit environment lines — exactly the place a typo lands. Today a typo does not fail the unit; it disables the resource caps that keep resident warm workers bounded, freezes the model catalog, or makes every request fail as a "timeout" whose message (after NaNms) points at the upstream, not the config. The sibling case in commandcode-proxy is tracked as #1809; this is the same class in a different proxy with four knobs and three distinct failure shapes (never / always / crash), so it needs its own pin — including whether MAX_LIVE_WORKERS=0 is a legitimate "no live workers" setting or an invalid value.
Dedup
Searched open + closed issues for agy-proxy, AGY_PROXY_, and bare Number: #1809 covers only COMMANDCODE_PROXY_TIMEOUT_MS in bin/commandcode-proxy.mjs; #483/#661 covered proxy ports via the strict parseProxyPort helper in bin/proxy-port.mjs. No issue covers agy-proxy's duration/count env vars.
Acceptance criteria
- All four
AGY_PROXY_*numeric env vars are validated at startup through one strict parser (positive finite integer in a stated range; durations also within the 2³¹−1setTimeoutbound): an invalid value fails startup loudly, naming the variable and the offending value — no silentNaN/negative/overflow behaviour. - The pinned contract for
AGY_PROXY_MAX_LIVE_WORKERS=0is implemented and tested (either refused as invalid, or honoured without the eviction loop throwing on an empty worker list). - Tests in
bin/agy-proxy.test.mjs(or a shared helper's tests) cover each var with: unset (default), a valid value,'abc', a negative,0where it matters, and a >2³¹ duration. - Valid configurations are unchanged: defaults 300000 / 300000 / 32 / 1800000 and the model-refresh, turn-timeout, idle-eviction, and cap behaviours they drive.
Activity
developing-today commentedon Oct 29, 2026
CODE-1007
dezren39 commentedon Oct 29, 2026
🤖 Agent note · filed
dezren39 commentedon Oct 30, 2026
agent-note:v1 — design-architect pass 22 (2026-10-30): ADOPTED as Phase 1 of design #2835 (bin/ proxies, with #2823/#2786/#1809): this issue's four knobs parse through the NEW shared helpers Phase 1 adds to bin/proxy-port.mjs — TTLs and turn timeout as millis (digits-only, 1-2^31-1), MAX_LIVE_WORKERS as count (>=1; 0 is a bug spelling, not a setting) — not private guards. Linked as a sub-issue of #2835 (verified in its sub_issues list). Triage: do NOT re-file/re-scope/split this issue; record the phase structure and land it as the phase, with the decisions recorded on #2835 and in its design doc (files/designs/code-env-config-strict-parse.md). This issue keeps its own queued triage packet.
68 remaining items
dezren39 commentedon Nov 4, 2026
🤖 Agent note · picked up
repo-worker-code), lane8ac61616-3815-4e7b-b33d-840a3829154a(OpenChamber scheduled lane)dezren39 commentedon Nov 4, 2026
🤖 Agent note · parked
repo-worker-code), lane8ac61616-3815-4e7b-b33d-840a3829154a(OpenChamber scheduled lane)8bb1e43, but matching PR fix(agy-proxy): strictly parse numeric env settings (#2096) #4079 is OPEN/non-draft and authored by Drewry Pope (dezren39). Main still uses bareNumber()for all four settings. I did not touch the Drew-owned PR or create competing work.queue/parkedandstatus/parkedset;work/assignedretained.dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 5, 2026
🤖 Agent note · handed off