fix(core): SIGPIPE-immune account resolution under pipefail#60
Merged
Conversation
…low-up) `subctl teams openai-codex -a openai-jason --dry-run` failed with 'unknown account: openai-jason' on pristine main (5/5). bin/subctl sets `set -uo pipefail`; subctl_resolve_alias piped the slow subctl_list_accounts producer (5 _subctl_trim command substitutions per row) into an early-exit awk. awk's exit closed the pipe mid-write, the producer took SIGPIPE, pipefail turned the pipeline status into 141, and `resolved=$(subctl_resolve_alias …) || subctl_die` fired even though the alias had already been printed and captured. Position-dependent: early/mid-file aliases always lost the race; last-row aliases always won. Fix: buffer the roster once per call (local all=$(subctl_list_accounts)) and feed every early-exit awk via herestring — no pipe, no SIGPIPE, no 141. Applied to both exposed helpers (subctl_resolve_alias, all three passes, and subctl_account_field); the remaining list_accounts consumers in core.sh (accounts_by_provider, count_by_provider) have no early exit and are unaffected. v3.3.13 three-pass semantics unchanged — the five pre-existing core.test.ts contract tests stay green untouched. Regression tests mirror bin/subctl's exact environment: `set -uo pipefail`, a 50-row roster with the target on row 1 (deterministic race), 5 repeats per lookup, plus the exact caller shape that died (capture || die). Proven to catch the bug: 3/3 new lookup tests fail on pristine core.sh, 0 fail on the fix; manual repro went 5/5 → 0/5. Gate: bun test lib providers dashboard/__tests__ — failure set byte-identical to pristine origin/main baseline (22 fail / 3 errors, known environmental + cli.test.ts set); +4 new tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Latent since v3.3.13 interacted with bin/subctl's pre-existing
set -uo pipefail: the resolver's early-exit awk SIGPIPEssubctl_list_accountsmid-write, so the pipeline exits 141 even though the alias was printed and captured —|| subctl_die "unknown account"fires on a successful lookup. Position-dependent race (last-row aliases always safe, mid-file aliases reliably fail), which is why every same-day proof passed. Surfaced by W6.5's codex dry-run proofs (openai-jason, row 4/7: 5/5 fail on pristine main).Fix: buffer-once + herestring in
subctl_resolve_alias(all three passes) andsubctl_account_field; early-exit semantics and the v3.3.13 three-pass contract unchanged. Other list_accounts consumers audited — no early-exit awk, untouched.Orchestrator-verified: 9/9 core.test.ts (4 new tests mirror bin/subctl's pipefail env on a 50-row early-target roster; worker red-proofed them against pristine core.sh — 3 fail there); live 5/5 repro → 5/5 clean on the original failing command; suite failure set byte-identical to baseline.
🤖 Generated with Claude Code