pgw#995: env carries values, never a branch selection — wave 2, the BEHAVIOUR axis, and a rig that can see hub env delivery - #521
Merged
Conversation
PaulFidika
force-pushed
the
995-env-logic-sweep
branch
from
August 7, 2026 06:16
f9a7f4e to
bb52303
Compare
…the BEHAVIOUR axis, plus a rig that can see hub env delivery
pgw#990 deleted GEN_WORKER_PREFER_AOT, the flag that gated both the mint recipe
and cell discovery, silently disarmed on a release rebuild, and cost three pod
attempts. This is the class rather than the instance.
WHY THE EXISTING CENSUS COULD NOT HAVE CAUGHT IT. pgw#929/931 is a real census —
79 classified (file, variable) pairs — but all six of its classifications answer
WHERE a read happens relative to the config pipeline, never WHETHER it selects
behaviour. Those are orthogonal, and the postmortem lives entirely on the second
axis. The proof it was missing rather than implicit is in the allowlist itself:
GEN_WORKER_AOT_EXPORT_PARALLEL and _REUSE were filed as LIBRARY (torch has never
heard of either name — they are first-party feature gates), and BG_YIELD /
EAGER_FIRST_BOOT / MINT_IN_PROCESS as STANDALONE, "a CLI that loads no app
config", while all three were read from executor.py on the serving hot path of
every production pod.
DELETED — three switches, each default-ON with zero fleet declarations, so
deleting the env makes the shape every pod already ran unconditional and NO
pod's behaviour changes:
GEN_WORKER_BG_YIELD + the legacy idle-gate tree it selected
GEN_WORKER_EAGER_FIRST_BOOT + REFUSAL_EAGER_FIRST_DISABLED, which can no
longer be returned (a refusal reason
nobody can reach is a cause a reader hunts
for and never finds)
GEN_WORKER_AOT_WRAPPER_SPLIT_OFF
KEPT — and "delete every kill switch" is wrong in two separate directions:
AOT_RUN_IMPL_SPLIT_OFF LIVE. 5 SDXL releases declare it, 1 endpoint carries a
non-deleted entry. It sits in the same file as its
deleted sibling and looks identical — zero
declarations is a fact you MEASURE.
AOT_EXPORT_PARALLEL default-OFF and dark by their own docstrings. Deleting
AOT_EXPORT_REUSE those gates makes an unproven path unconditional,
which is a LAUNCH, not a deletion.
HOST_MOVE_GUARD, PROBE ruled exceptions with named threats.
TESTS STOP USING ENV AS A RED-VERIFICATION SEAM. BG_YIELD=0 and
EAGER_FIRST_BOOT=0 drove RED arms in four files. An env kept alive to be a test
seam is still an env a release rebuild can flip. Those arms are replaced by
absolute-bound assertions plus source-level guards proving the deleted arm is
UNREACHABLE, not merely unused — deleting a switch and deleting its tests looks
identical to deleting a switch and leaving a second reader behind, which is
exactly how PREFER_AOT kept a live gate after one was believed removed.
THE GUARD. lint_config_reads.py gains an AST pass that flags any env read
feeding a conditional and fails the build unless the (file, variable) pair is in
BEHAVIOUR_GATES *with the threat it defends against* — "it is useful" and "it is
off by default" are rejected, and stale exemptions fail too. Same structural bar
as the mint_recipe guard shipped in 0.93.2. RED-verified: adding a plausible new
switch to executor.py fails with a message naming the postmortem.
NOT DELETED, and it is the one remaining defect: GEN_WORKER_MINT_IN_PROCESS.
Default-ON, zero declarations, and enable_compiled(delegate=False) is a strictly
better parameter seam that already exists — blocked only on ten test sites
across seven files that force the shape via the env and drive the executor.
Recorded as a burn-down, not an exception.
DELIVERABLE 2 — the rig blind spot. micro_mint_rig.py runs the whole mint
machinery locally, which is why a change can be proven before PyPI, but it
CONSTRUCTS ITS OWN ENVIRONMENT (mint_process.child_env for the mint child,
dict(os.environ) for the adopting process) — shapes no production pod ever has.
So the chain that actually delivers env to a pod (function declares ->
release_env_declarations -> endpoint_env_entries -> Resolve -> pod env ->
Settings) was invisible to every test in this repo, and the regression class
that took PREFER_AOT dark had exactly one detector: a pod.
tests/harness/hub_env.py models the hub's rule (an entry reaches the pod only if
the release DECLARES its name, plus the reserved-namespace defence) and reports
withholdings in th#1650's typed vocabulary. `--hub-env` boots the mint child
through it and STRIPS ambient values, so a developer's shell cannot stand in for
a hub-delivered one — that substitution is what the blind spot was made of, and
a mode that allowed it would be decoration.
tests/test_hub_env_delivery_pgw995.py drives the real config.load_settings()
over hub-resolved environments and reproduces the postmortem in milliseconds:
release N declares the name and the value reaches Settings; release N+1 is
rebuilt without the declaration, nobody touches the entry, and the value is
withheld AND says so.
Full HelloAck-shaped boot (Vault, applies_to version/tag matching, mTLS resolve)
is filed on pgw#995 with an owner. Hub half: th#1650.
Gates: lint_config_reads OK (77 pairs), lint_http_timeouts OK,
lint_unreached_surface OK, ruff clean on src/gen_worker and every changed file.
CI caught what the local run had not reached: test_aot_wrapper_split_pgw793 referenced ws.DISABLE_ENV, the GEN_WORKER_AOT_WRAPPER_SPLIT_OFF constant deleted with the switch. The test asserted install() could be killed by the env; it now asserts the opposite — that the retired name is inert and the constant is gone. Which is the point rather than a formality: a test that merely stopped mentioning the switch would pass identically whether the deletion took or left a live reader behind somewhere else, and that ambiguity is exactly how GEN_WORKER_PREFER_AOT kept a live gate after one was believed removed.
PaulFidika
force-pushed
the
995-env-logic-sweep
branch
from
August 7, 2026 06:34
bb52303 to
e6804ae
Compare
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.
pgw#990 deleted
GEN_WORKER_PREFER_AOT— the flag that gated both the mint recipe and cell discovery, silently disarmed on a release rebuild, and cost three pod attempts before anyone noticed the whole AOT path was dark. This PR is the class, not the instance.Why the existing census could not have caught it
pgw#929/931's
config_reads_allowlist.txtis a real census — 79 classified (file, variable) pairs. But all six of its classifications (VIOLATION / BOOTSTRAP / IPC / LIBRARY / STANDALONE / TRIPWIRE) answer WHERE a read happens relative to the config pipeline. None answers WHETHER it selects behaviour. Those are orthogonal axes, and the postmortem lives entirely on the second one.The evidence the axis was missing rather than implicit is in the allowlist itself:
GEN_WORKER_AOT_EXPORT_PARALLELand_REUSEwere classified LIBRARY. Torch has never heard of either name — they are first-party feature gates that happened to be filed next toTORCHINDUCTOR_CACHE_DIR.GEN_WORKER_BG_YIELD,_EAGER_FIRST_BOOT,_MINT_IN_PROCESSwere classified STANDALONE — "a CLI/convert path that loads no app config" — while all three are read fromexecutor.pyon the serving hot path of every production pod.A classification scheme that lets three serving-path behaviour switches be labelled "standalone CLI" isn't wrong at any single line; it's measuring the wrong quantity.
The census, on the behaviour axis
GEN_WORKER_BG_YIELDGEN_WORKER_EAGER_FIRST_BOOTGEN_WORKER_AOT_WRAPPER_SPLIT_OFFGEN_WORKER_MINT_IN_PROCESSGEN_WORKER_AOT_RUN_IMPL_SPLIT_OFFGEN_WORKER_AOT_EXPORT_PARALLELGEN_WORKER_AOT_EXPORT_REUSEGEN_WORKER_HOST_MOVE_GUARDGEN_WORKER_PROBE/_PUBLISH_ARMEDPODGUARD_STATEThe three deletions share one property, and it is the test rather than a hope: their default is ON, so deleting the env makes the CURRENT PRODUCTION BEHAVIOUR unconditional. No pod's behaviour changes.
"Delete every kill switch" is wrong in two separate directions, and saying so is part of the finding:
AOT_RUN_IMPL_SPLIT_OFFsits in the same file as its deleted sibling and looks identical — and it is LIVE: 5 SDXL releases declare it, 1 endpoint carries a non-deleted entry. Zero declarations is a fact you measure, not one you infer from the code.AOT_EXPORT_PARALLEL/_REUSEare default-OFF and dark by their own docstrings. Deleting those gates makes an unproven path unconditional — a launch, not a deletion.Tests stop using env as a red-verification seam
BG_YIELD=0andEAGER_FIRST_BOOT=0drove RED arms in four files. An env kept alive to be a test seam is still an env a release rebuild can flip — the mechanism doesn't care about the intent.Those arms are replaced by absolute-bound assertions plus source-level guards proving the deleted arm is unreachable, not merely unused. That distinction is load-bearing: deleting a switch and deleting its tests looks identical to deleting a switch and leaving a second reader behind — which is exactly how PREFER_AOT kept a live gate after one was believed removed.
The guard (the bar this PR was held to)
scripts/lint_config_reads.pygains an AST pass that flags any env read feeding a conditional and fails the build unless the (file, variable) pair is inBEHAVIOUR_GATESwith the threat it defends against. "It is useful" and "it is off by default" are rejected. Stale exemptions fail too — an exemption for a read that no longer exists is the second carrier this gate exists to prevent.RED-verified — adding a plausible new switch to
executor.py:The guard also caught my own over-seeding of
BEHAVIOUR_GATES— seven entries I added for reads its conservative detector correctly does not flag. Those were removed rather than the check loosened.The one remaining defect
GEN_WORKER_MINT_IN_PROCESSis not deleted. Default-ON, zero declarations, andenable_compiled(delegate=False)→caller_forced_in_processis a strictly better parameter seam that already exists, making the env redundant with it. What blocks the deletion is ten test sites across seven files that force the shape via the env and then drive the executor, which reaches the policy withdelegate=None. Threading the parameter through those call sites is a real refactor of a 4k-line test file and does not belong in a sweep. Recorded inBEHAVIOUR_GATESas a burn-down, not an exception.Deliverable 2 — the rig could not see hub env delivery
micro_mint_rig.py(pgw#978) runs the whole mint machinery locally and is why this repo can prove a change before PyPI. But it constructs its own environment —mint_process.child_envfor the mint child,dict(os.environ)for the adopting process. Neither is a shape a production pod ever has, so this chain was invisible to every test in the repo:That chain is what took PREFER_AOT dark. The regression class had exactly one detector: a pod.
tests/harness/hub_env.pymodels the hub's rule (an entry reaches the pod only if the release declares its name, plus the reserved-namespace defence) and reports withholdings in th#1650's typed vocabulary. Deliberately small — a big fake hub drifts from the real one and starts certifying its own behaviour, which a test asserts against.micro_mint_rig.py --hub-envboots the mint child through it, and strips ambient values so a developer's own shell cannot stand in for a hub-delivered one. That substitution is what the blind spot was made of; a mode that allowed it would be decoration.tests/test_hub_env_delivery_pgw995.pydrives the realconfig.load_settings()over hub-resolved environments and reproduces the postmortem in milliseconds: release N declares the name and the value reachesSettings; release N+1 is rebuilt without the declaration, nobody touches the entry, and the value is withheld and says so.Full HelloAck-shaped boot (Vault,
applies_toversion/tag matching, the mTLS resolve path) is filed on pgw#995 with an owner.Verification
lint_config_reads.pyOK — 77 pairs, all classified; behaviour axis green and RED-verifiedlint_http_timeouts.py,lint_unreached_surface.pyOKruff check src/gen_workerclean; every changed file cleantest_mint_gate_pgw677,test_mint_reopen_pgw677,test_mint_vram_budget_pgw737,test_eager_first_boot_pgw671,test_aot_mint_unblock_pgw813_pgw815,test_hub_env_delivery_pgw995(8 new)Hub half: th#1650 (tensorhub #882) — the silent
continueinEndpointEnvService.Resolvethat did the disarming.