Skip to content

deploy: the WSL2 backend_ai_stack_host override skips the locality check its sibling task already applies #17244

Description

@mrveiss

roles/backend/tasks/main.yml:51 rewrites backend_ai_stack_host on WSL2 machines without
checking 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-58 sets backend_ai_stack_host to the Windows-host address
seen from WSL2 (explained in the comment at roles/backend/tasks/main.yml:78), guarded by:

  • WSL2 detected from /proc/version (roles/backend/tasks/main.yml:43)
  • the value still equals the shipped default — so an operator who set their own host is not
    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_fact
with no reachability check behind it.

The fix already exists twelve lines below

roles/backend/tasks/main.yml:60-66 sets backend_chromadb_host and does ask the locality
question:

backend_chromadb_host: "{{ '<wsl-host-addr>' if (role_ai_stack_active | default(false) | bool)
                           else backend_ai_stack_host }}"

It uses the WSL2 address only when role_ai_stack_active says the stack is on this node, and
otherwise follows backend_ai_stack_host. That is the pattern :51 should follow. No new
mechanism is needed — role_ai_stack_active is already resolved and already used in this file.

Acceptance criteria

  • roles/backend/tasks/main.yml:51 gains the same locality condition
    roles/backend/tasks/main.yml:60 already applies, so the WSL2 gateway address is used
    only 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 }}" at roles/backend/tasks/main.yml:76. Ticking the original
    text literally would have required reversing a working fix.)
  • When the override is applied, the play output states the value and the reason, so a wrong
    address is visible at deploy time rather than at first connection failure.
  • Covered by a multi-host WSL2 case — a single-node run cannot exercise the branch that
    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:60 was listed as a defect. It is the opposite — it is the
    topology-aware precedent, and the issue now cites it as the fix.
  • roles/backend/tasks/main.yml:76 was listed as a defect. It sets backend_host to the
    all-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 was
overstated and is corrected with it.

Related

Activity

  1. added this to the v0.9.0 milestone on Sep 22, 2026
  2. 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
  3. mrveiss commented on Sep 23, 2026

    @mrveiss
    OwnerAuthor

    AC verification against merged main — 1 of 3 met, issue stays OPEN

    Verified from origin/main at 31310392df; fix merged as b77f0d618a. No branch carries this
    work.

    • The locality condition is applied. roles/backend/tasks/main.yml — task Backend | 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_host task 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 bare set_fact with no debug/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/tests on origin/main returns nothing, and no WSL2-named guard exists
      under repo_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.

  4. mrveiss commented on Sep 28, 2026

    @mrveiss
    OwnerAuthor

    Classification (for work assignment — not a fix proposal)


    Generated by Claude Code

  5. mrveiss commented on Sep 28, 2026

    @mrveiss
    OwnerAuthor

    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> at 7adaca8c29.

    AC1 — the locality condition — MET, against an amended criterion. roles/backend/tasks/main.yml:51-65 now 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. 17244 appears twice in that file, both at the set_fact (:51, :53). There is no debug/announce task, so a wrong address is still first visible at connection failure rather than at deploy time. No file under repo_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.

  6. mrveiss commented on Sep 28, 2026

    @mrveiss
    OwnerAuthor

    Chunk triage — v0.9.2 node plane and deploy. Read-only at origin/main 7adaca8c29; nothing labelled or moved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions