Skip to content

fix(sling): refuse cross-store routes that wedge scale_check#13

Open
eric-jones wants to merge 1 commit into
mainfrom
topic/sling-refuse-cross-store
Open

fix(sling): refuse cross-store routes that wedge scale_check#13
eric-jones wants to merge 1 commit into
mainfrom
topic/sling-refuse-cross-store

Conversation

@eric-jones
Copy link
Copy Markdown
Owner

Fork-PR for review. Upstream: gastownhall#2295 WITHDRAWN 2026-05-20 (Q3 refusal-semantic; BLOCKED). Retained on fork.

@eric-jones eric-jones force-pushed the topic/sling-refuse-cross-store branch from b6b01ad to a7d0b7a Compare May 20, 2026 16:07
@eric-jones eric-jones force-pushed the topic/sling-refuse-cross-store branch 3 times, most recently from 5ab338f to ecd201a Compare May 22, 2026 08:18
`gc sling <rig>/<pool> <bead>` silently created an unservable wedge
when the bead's store and the target pool's reachable store
disagreed: `cliBeadRouter.Route` set `gc.routed_to` metadata in
the bead's source store, but the supervisor's default
`EffectiveScaleCheck` runs `bd ready` in the agent's `poolDir` (the
rig directory for a rig-scoped agent) — which only sees the rig
store. A bead routed across stores stayed unassigned forever; the
pool sat at zero with no surfaced error.

Add a guard in `cliBeadRouter.Route`: when the resolved target
agent's reachable workflow store doesn't match `deps.StoreRef`,
refuse the route before `SetMetadata` runs. Error names the source
store, the target's reachable store, and links to tr-6s7yx so
operators can find the design context.

Two small helpers in `assigned_work_scope.go` next to
`assignedWorkStoreRefForAgent`:

  - `agentReachesWorkflowStore` (predicate, used by the guard)
  - `agentReachableStoreLabel` (positive output for error text)

Both are permissive when `cfg` or `agentCfg` is nil — the guard
only refuses on known mismatches so unknown-target routes
(custom sling_query, direct-name targets) fall through unchanged.

Test changes:

  - 5 new tests cover the helpers (7 sub-cases on the predicate,
    label form on the labeler, refuse / allow / hq-allow on the
    router).
  - `TestBuiltInSlingPoolRouteContractUsesMetadataOnly` aligned
    `deps.StoreRef = "rig:saitoc"` (3-line change). The test re-uses
    one physical store as both HQ and saitoc rig; aligning the ref
    matches the rig-side use of that store and preserves the
    original intent (routing uses metadata, not labels +
    scale_check sees demand).
  - Three cross-rig tests renamed and converted from
    "...UsesPrefixStore" to "...RouteRefused" — their original
    assertions documented the silent-wedge behavior this fix
    refuses, so they now assert non-zero exit + refusal message +
    unchanged bead metadata + empty target rig store. The
    refactored `assertHyphenatedRigBeadNotMutatedAndNoOrphan`
    helper mirrors the existing "routed without inline orphan"
    shape for the refusal path.

Related beads:
  - tr-m5fqd — investigation that uncovered the wedge (closed)
  - tr-ht80e — sibling YAML bug from `gc rig add`; separate fix
  - tr-hndhm — sibling caller-side scope bug at the
    config-validation layer; separate fix

Upstream-PR: gastownhall#2295
@eric-jones eric-jones force-pushed the topic/sling-refuse-cross-store branch from ecd201a to f2eb683 Compare May 23, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant