Skip to content

fix: two silent-failure defects in the Plane sync path - #371

Closed
DrumRobot wants to merge 2 commits into
next-fixfrom
fix/plane-sync-es6kr-identifier
Closed

fix: two silent-failure defects in the Plane sync path#371
DrumRobot wants to merge 2 commits into
next-fixfrom
fix/plane-sync-es6kr-identifier

Conversation

@DrumRobot

Copy link
Copy Markdown
Member

Two independent silent-failure defects surfaced while running a Plane intake flow end to end. Both are fix type, so this is a patch bundle targeting next-fix.

1. INDEX_LINE_RE never matched digit-bearing project identifiers

plane_sync.py matched the Plane identifier prefix with [A-Z]+. Any workspace whose project identifier contains a digit — ES6KR-117 — therefore matched no index line at all.

The failure mode is what made this expensive: plane_sync reported No changes (0 index lines moved to completed/cancelled) and exited 0. There was no error to notice, so an entire workspace's Plane sync was inert while looking healthy. INFRA-12 matched fine, which is why the gap survived.

Widened to [A-Z][A-Z0-9]*. Still letter-initial, so [123-4] is not absorbed as an identifier. Covered in both directions by a new regression test.

2. The k3s-fallback escaping test depended on ambient kubectl

create_via_k3s_fallback() returns early when shutil.which("kubectl") is None, before it ever reaches subprocess.run. test_k3s_fallback_script_survives_quote_in_workspace_slug never stubbed that lookup, so on a host without kubectl the function short-circuits and the test fails on assert captured_cmd — asserting on ambient tooling rather than on the escaping behaviour it is named for.

This is not hypothetical: it failed a real pre-push run whose hook environment did not carry /usr/local/bin, blocking a push of main + next-fix. It would fail the same way on any CI host without kubectl installed.

Stubbed shutil.which the way the sibling test test_k3s_fallback_skips_gracefully_without_kubectl already does, so the escaping path runs unconditionally.

Test plan

  • uvx --from pytest pytest tests in the worktree → 95 passed, 4 skipped (94 before; +1 new regression test)
  • Defect 1 reproduced before the fix: INDEX_LINE_RE.match() returned None for a real ES6KR-117 index line, and plane_sync --dry-run reported 0 index lines against a tracker that contained one
  • Defect 2 reproduced before the fix: with PATH stripped of kubectl, create_via_k3s_fallback returned kubectl not available on PATH and subprocess.run was never called — exactly the observed assertion failure
  • Defect 2 verified after the fix under the same condition: env PATH=/opt/homebrew/bin:/usr/bin:/bin uvx --from pytest pytest tests/test_plane_profile.py6 passed (no kubectl on that PATH)
  • Pre-push CI parity (lint-frontmatter + bats + pytest) passed on push

INDEX_LINE_RE matched the identifier prefix with [A-Z]+, so an index line
from a workspace whose project identifier contains a digit (ES6KR-117) never
matched. plane_sync then reported "0 index lines" and left every marker
unsynced — a silent no-op rather than a loud failure, which is why the gap
went unnoticed.

Widen the prefix to [A-Z][A-Z0-9]* (still letter-initial, so a purely numeric
[123-4] is not absorbed) and cover both directions with a regression test.
create_via_k3s_fallback() returns before subprocess.run() when kubectl is
absent from PATH, so the escaping test asserted on ambient tooling rather
than on the behaviour it names. It failed in a pre-push run whose hook
environment had no /usr/local/bin, and would fail on any CI host without
kubectl installed.

Stub shutil.which the same way test_k3s_fallback_skips_gracefully_without_kubectl
already does, so the test exercises the escaping path unconditionally.
@DrumRobot
DrumRobot marked this pull request as ready for review August 22, 2026 16:18
@DrumRobot DrumRobot closed this Aug 26, 2026
@DrumRobot
DrumRobot deleted the fix/plane-sync-es6kr-identifier branch August 26, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant