Skip to content

fix(boatstack): stop shipped features re-registering as ambiguous plan candidates - #135

Merged
bigboateng merged 1 commit into
mainfrom
boatstack/fix-shipped-candidate-ambiguity
Jul 23, 2026
Merged

fix(boatstack): stop shipped features re-registering as ambiguous plan candidates#135
bigboateng merged 1 commit into
mainfrom
boatstack/fix-shipped-candidate-ambiguity

Conversation

@bigboateng

Copy link
Copy Markdown
Contributor

Problem

In a repo that has shipped more than one feature and uses worktree delivery mode, next-status from a fresh build worktree returns BLOCKED / AMBIGUOUS "More than one saved feature plan is available", listing every historically shipped feature as a candidate (taxweave: 22 shipped + 1 active = 23). This blocks all forward progress.

Root cause

featurePlanCandidates (next.go) counted a feature dir as an open plan when it had plan.md but no delivery state.json. Delivery state.json is stored per-worktree (deliveryStateDirectory uses git rev-parse --git-dir), and workspace.cleanup_after = merge deletes the feature's worktree on ship — destroying the state.json while the committed plan.md / plan.lock.json / pr.md survive. So every shipped feature matched "planned + no state" and re-registered as an open candidate. ignored_deliveries filters the active-delivery path, not this candidate path.

Fix (Part B only)

The candidate check now skips any feature carrying plan.lock.json (locked/built) or pr.md (shipped) before the state.json test, mirroring orphanedFeatureArtifacts. It relies on the durable committed artifacts, so the loss of an ephemeral state.json on cleanup is harmless. A dir with plan.md only correctly remains the single open candidate.

Part A rejected: relocating delivery state to --git-common-dir would make every active delivery visible in all worktrees, breaking intentional per-worktree isolation (TestManagedDeliveryStateDoesNotBlockUnrelatedWorktrees) and changing cross-worktree push-denial (ActiveManagedDeliveriesClassifyCommand). No delivery-state locality change is made.

Tests

  • TestFeaturePlanCandidatesExcludesLockedAndShippedFeatures — unit.
  • TestResolveNextIgnoresShippedFeatureCandidates — reproduction of the taxweave scenario.
  • TestResolveNextIgnoresShippedFeaturesFromLinkedWorktree — worktree conformance (the exact reported symptom).
  • TestManagedDeliveryStateDoesNotBlockUnrelatedWorktrees — unchanged, still green (isolation not touched).

Verification

From product-engineering-loop: go build ./..., go vet ./..., go test ./... all pass. From labs/12-product-engineering-loop: python3 -m unittest tests.test_product_loop (18 tests) passes.

Rollout (taxweave, after merge)

  1. Bump the helper version.
  2. Revert PR #304 to restore the 22 shipped feature dirs.
  3. Confirm next-status resolves firm-status-finance-aesthetic as the single candidate.

…n candidates

featurePlanCandidates counted a feature dir as an open plan when it had
plan.md but no delivery state.json. Delivery state.json is stored
per-worktree, and workspace.cleanup_after=merge deletes the feature's
worktree on ship, destroying the state.json while the committed
plan.md/plan.lock.json/pr.md survive. From a fresh build worktree every
shipped feature then re-registered as an open candidate, so next-status
returned BLOCKED/AMBIGUOUS.

Skip any feature carrying plan.lock.json (locked/built) or pr.md
(shipped) before the state.json check, mirroring orphanedFeatureArtifacts.
The candidate check now relies on durable committed artifacts, so the loss
of an ephemeral state.json on cleanup is harmless. Delivery-state locality
and cross-worktree push-denial are unchanged (Part A rejected).

Adds unit, ResolveNext reproduction, and linked-worktree conformance tests.
@bigboateng
bigboateng force-pushed the boatstack/fix-shipped-candidate-ambiguity branch from 738bd64 to c288814 Compare July 23, 2026 14:40
@bigboateng
bigboateng merged commit 2203422 into main Jul 23, 2026
5 checks passed
@bigboateng
bigboateng deleted the boatstack/fix-shipped-candidate-ambiguity branch July 23, 2026 15:13
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