Repository navigation
deploy: the WSL2 backend_ai_stack_host override skips the locality check its sibling task already applies #17244
Description
Activity
- addedbugSomething isn't workingSomething isn't working
on Sep 22, 2026 - changed the title
[-]deploy: three WSL2 host overrides pin a service address from a machine property, not from where the service runs[/-][+]deploy: the WSL2 backend_ai_stack_host override skips the locality check its sibling task already applies[/+]on Sep 22, 2026 AC verification against merged
main— 1 of 3 met, issue stays OPENVerified from
origin/mainat31310392df; fix merged asb77f0d618a. No branch carries this
work.- The locality condition is applied.
roles/backend/tasks/main.yml— taskBackend | Set backend_ai_stack_host on WSL2 hosts (#3503, #17244)now resolves
backend_wsl2_loopback_host if (role_ai_stack_active | default(false) | bool) else backend_wsl2_gateway_host, which is the same question its sibling
backend_chromadb_hosttask has always asked. The two WSL2 guards and the
shipped-default guard are unchanged. - The play output states the value and the reason when the override is applied. NOT MET.
The task is a bareset_factwith nodebug/announce step; the reasoning is in a YAML
comment, which never reaches play output. A wrong address is still invisible until the
first connection failure — the exact outcome this criterion existed to prevent. - Covered by a multi-host WSL2 case. NOT MET.
git grep -l '17244' -- repo_tests autobot-slm-backend/testsonorigin/mainreturns nothing, and no WSL2-named guard exists
underrepo_tests/. The branch that matters — WSL2 host where the AI stack is elsewhere —
is untested, so this is a reasoned change with no regression cover.
Verdict: the one-line behaviour fix is correct and verified in merged code. The two criteria
that make it observable and kept are not delivered, so the issue stays open on those.- The locality condition is applied.
Classification (for work assignment — not a fix proposal)
- Scope:
deploy(secondaryansible) - Primary files/dirs:
autobot-slm-backend/ansible/roles/backend/tasks/main.yml, taskBackend | Set backend_ai_stack_host on WSL2 hosts (#3503, #17244)near:51(verified on main). A test would go underrepo_tests/(none exists; see below). - Class: not the
code_sourceclass of CRITICAL(deploy): backend provisioning aborts on every non-manager host — a task executes a script out of code_source, which exists only on the controller (rc=127) #17242/deploy: five more tasks read code_source on hosts that do not have it — three are in the builtin updater (#17242 class) #17243/deploy: seven pip tasks install from code_source on fleet nodes — the class is 16 sites, not 6 #17246. This is a WSL2 host-address locality defect from the same sweep. Same-file collision: it editsroles/backend/tasks/main.yml, as CRITICAL(deploy): backend provisioning aborts on every non-manager host — a task executes a script out of code_source, which exists only on the controller (rc=127) #17242 and deploy: five more tasks read code_source on hosts that do not have it — three are in the builtin updater (#17242 class) #17243 do, so under the same-file rule it goes with whichever session holds that file. - Umbrella: no.
- Blocked by: nothing visible in the issue.
- AC1 (the locality condition) is merged (
b77f0d618). The task now resolvesbackend_wsl2_loopback_host if role_ai_stack_active else backend_wsl2_gateway_host, verified on main at 7adaca8. - AC2 (announce the value and reason in the play output) is still open: no
debug/announce step was found in:45-80on main. - AC3 (a multi-host WSL2 case) is still open.
- AC1 (the locality condition) is merged (
- Read vs inferred: Read the issue body, its 1 comment (the AC verification of 2026-09-23), and on main
roles/backend/tasks/main.yml:45-80. Whether AC3 means a repository test or a live multi-host run is my reading, not stated in the issue. - Undetermined: whether AC3 can be met by a repository test or needs host evidence. The wording ("covered by a multi-host WSL2 case") supports either reading.
Generated by Claude Code
- Scope:
Closure pass — the fix is merged, one criterion was inverted and has been amended, and two remain. Not closed.
Evidence via
git show origin/main:<path>at7adaca8c29.AC1 — the locality condition — MET, against an amended criterion.
roles/backend/tasks/main.yml:51-65now asks the locality question:- name: "Backend | Set backend_ai_stack_host on WSL2 hosts (#3503, #17244)" ansible.builtin.set_fact: backend_ai_stack_host: "{{ backend_wsl2_loopback_host if (role_ai_stack_active | default(false) | bool) else backend_wsl2_gateway_host }}"
with the reasoning at
:53-59, including that the two tasks "sat twelve lines apart and disagreed".I amended the criterion text rather than reinterpreting it, and it is worth being explicit about why. As filed, AC1 required that "the WSL2 address is used only when the AI stack is on this node". The merged logic is the opposite: loopback when the stack is co-located, the WSL2 gateway when it is elsewhere. The merged logic is the correct one — the gateway address reaches the Windows side, which is only useful when the stack is not on this node — and it matches the sibling this criterion was explicitly modelled on,
roles/backend/tasks/main.yml:76:backend_chromadb_host: "{{ '127.0.0.1' if (role_ai_stack_active | default(false) | bool) else backend_ai_stack_host }}"
Ticking the original wording literally would have required reversing a working fix. The criterion, not the code, was wrong; the amendment is recorded in the body with the date and this reason.
AC2 — the override announces its value and reason at deploy time — NOT MET.
17244appears twice in that file, both at theset_fact(:51,:53). There is nodebug/announce task, so a wrong address is still first visible at connection failure rather than at deploy time. No file underrepo_tests/references this issue, while #17242, #17243 and #17331 each have a guard — so this fix is also the only one of the four with no regression cover.AC3 — multi-host WSL2 coverage — NOT MEASURABLE NOW. Host mid-update; and by the issue's own note the branch that matters cannot be exercised on a single node. Unticked deliberately.
Held open by AC2 and AC3. AC2 is one task in one file and should ride the next PR that touches this role rather than opening its own.
Chunk triage —
v0.9.2 node plane and deploy. Read-only atorigin/main7adaca8c29; nothing labelled or moved.- Already closure-passed today. The code fix is merged; AC1 was inverted as filed and I amended the criterion text (the WSL2 gateway address is right only when the stack is not local — matching the
backend_chromadb_hostsibling at:76). Ticking the original wording would have required reversing a working fix. - Held open by two:
- AC2 — the override announces its value and reason at deploy time — CODE, and small.
17244appears twice in the file, both at theset_fact; there is no debug/announce task, so a wrong address still surfaces at first connection failure. - AC3 — multi-host WSL2 coverage — HOST. Mark as such.
- AC2 — the override announces its value and reason at deploy time — CODE, and small.
- Mixed; stays in the chunk. The code remainder is one task in one file.
- Same-file note:
roles/backend/tasks/main.ymlis shared with CRITICAL(deploy): backend provisioning aborts on every non-manager host — a task executes a script out of code_source, which exists only on the controller (rc=127) #17242. These two are the cheapest pairing in the chunk — one agent, one PR, two small edits ~930 lines apart. - Also true and worth carrying: this is the only one of the deploy five with no regression cover — nothing under
repo_tests/references it, while CRITICAL(deploy): backend provisioning aborts on every non-manager host — a task executes a script out of code_source, which exists only on the controller (rc=127) #17242, deploy: five more tasks read code_source on hosts that do not have it — three are in the builtin updater (#17242 class) #17243 and CRITICAL(deploy): the filtered backend manifest bakes a controller-only constraint path, so provisioning still aborts on every non-manager node #17331 each have a guard.
- Already closure-passed today. The code fix is merged; AC1 was inverted as filed and I amended the criterion text (the WSL2 gateway address is right only when the stack is not local — matching the
roles/backend/tasks/main.yml:51rewritesbackend_ai_stack_hoston WSL2 machines withoutchecking whether the AI stack is actually on that machine. Its sibling task twelve lines
below does check, which is what makes this an inconsistency rather than a design choice.
The one site
roles/backend/tasks/main.yml:51-58setsbackend_ai_stack_hostto the Windows-host addressseen from WSL2 (explained in the comment at
roles/backend/tasks/main.yml:78), guarded by:/proc/version(roles/backend/tasks/main.yml:43)overridden
Both guards are correct and limit the blast radius. What is missing is the third question:
is the AI stack on this machine at all? "This machine is WSL2" is a property of the machine.
Where the AI stack runs is a property of the topology. Only the second one justifies pointing
the backend at the local Windows host.
On a single-node WSL2 install the two coincide, which is why #3503 was right at the time. On a
multi-host install where the AI stack lives elsewhere and the operator left the default in
place, the backend is pointed at its own Windows host, silently — the override is a
set_factwith no reachability check behind it.
The fix already exists twelve lines below
roles/backend/tasks/main.yml:60-66setsbackend_chromadb_hostand does ask the localityquestion:
It uses the WSL2 address only when
role_ai_stack_activesays the stack is on this node, andotherwise follows
backend_ai_stack_host. That is the pattern:51should follow. No newmechanism is needed —
role_ai_stack_activeis already resolved and already used in this file.Acceptance criteria
roles/backend/tasks/main.yml:51gains the same locality conditionroles/backend/tasks/main.yml:60already applies, so the WSL2 gateway address is usedonly when the AI stack is not on this node, and loopback when it is.
(Criterion amended 2026-09-28 — not reinterpreted. As filed it said "the WSL2 address is
used only when the AI stack is on this node", which inverts the mapping: the gateway address
reaches the Windows side and is right only when the stack is elsewhere. The sibling this
criterion was modelled on states the correct direction —
backend_chromadb_host: "{{ '127.0.0.1' if (role_ai_stack_active | default(false) | bool) else backend_ai_stack_host }}"atroles/backend/tasks/main.yml:76. Ticking the originaltext literally would have required reversing a working fix.)
address is visible at deploy time rather than at first connection failure.
matters, because there the two conditions coincide.
Not claimed
Not confirmed to be misrouting any live deployment; that depends on where the AI stack actually
runs, which is a deployment fact rather than a repository one. This is a latent condition.
Correction (2026-09-22, shortly after filing). The original text claimed three sites
pinned a service host. Re-checked each against the file; two of the three were wrong and are
withdrawn:
roles/backend/tasks/main.yml:60was listed as a defect. It is the opposite — it is thetopology-aware precedent, and the issue now cites it as the fix.
roles/backend/tasks/main.yml:76was listed as a defect. It setsbackend_hostto theall-interfaces bind address, which is a listen setting, not a remote target, and carries
no misrouting risk.
The remaining site is
:51. The issue has been rewritten to that scope; the title wasoverstated and is corrected with it.
Related
:51for the single-node case, correctly for that case:60, the locality-aware sibling