Summary
gt_wasteland_done / cloud wl.done can report success and publish an in-review wanted item branch without creating the required completions row. Admin accept/merge then fails because the submitter branch does not contain a completion, even though the wanted row shows status='in_review' and has evidence_url.
Observed case:
- Mayor called
gt_wasteland_done with item_id=w-eb7abcda4064 and evidence https://github.com/Kilo-Org/cloud/pull/3349.
- The wanted row was updated/visible as
in_review with evidence.
- No row existed in
completions on the submitter branch.
- Admin accept failed with the branch not containing a completion.
Likely Root Cause
packages/wl-sdk/src/ops/mutate.ts has status-only idempotency:
applyMutation reads the wanted status on wl/<rig>/<wantedId>.
- If
branchStatus === targetStatus, it returns success immediately.
- For
done, targetStatus is in_review.
That means a branch already at wanted.status='in_review' skips all done DML, including the second statement from submitCompletionDML that inserts into completions.
Relevant code paths:
services/gastown/container/plugin/mayor-tools.ts exposes gt_wasteland_done.
services/gastown/src/handlers/wasteland-tools.handler.ts calls WASTELAND_SERVICE.markWantedItemDone.
services/wasteland/src/wanted-board/wanted-board-ops-sdk-inner.ts calls wl.done(itemId, { evidence }).
packages/wl-sdk/src/ops/done.ts builds submitCompletionDML(...).
packages/wl-sdk/src/commons/dml.generated.ts returns UPDATE wanted ... plus INSERT IGNORE INTO completions ....
packages/wl-sdk/src/ops/mutate.ts can skip those statements when the branch status is already in_review.
The review inbox can still look valid because it displays evidence from wanted.evidence_url before falling back to completions.evidence, while admin accept requires a real completions row.
Canonical Wasteland Comparison
Canonical wasteland (/Users/john/projects/professional/kilo/wasteland) normally creates a completion for wl done:
internal/sdk/mutations.go:57 implements Client.Done.
internal/commons/commons.go:364 builds SubmitCompletionDML with both UPDATE wanted and INSERT IGNORE INTO completions.
internal/sdk/mutate.go:61 applies those statements to the PR branch.
Canonical also has a status-based prIdempotent shortcut for already-in_review branches, so an already-in-review branch missing a completion would likely not be repaired there either. However, cloud's applyMutation is broader than canonical because it short-circuits purely on branch status; canonical falls through when branch status equals main status.
Proposed Fix
Make done idempotency validate the completion invariant, not only wanted status.
Minimal targeted approach:
- Keep generic
applyMutation behavior for other operations.
- For
done, when the branch is already in_review, read completions for wanted_id on wl/<rig>/<wantedId>.
- If a completion exists, return idempotent success.
- If no completion exists, run a repair path that inserts the missing completion, or proceed with mutation logic in a way that executes the
INSERT IGNORE INTO completions statement.
- Add a regression test where the branch wanted row is
in_review but no completion exists; wl.done should issue a write that creates the completion.
Potential files:
packages/wl-sdk/src/ops/done.ts
packages/wl-sdk/src/ops/mutate.ts if a reusable/custom idempotency hook is needed
packages/wl-sdk/src/ops/done.test.ts
- Possibly
services/wasteland/src/wanted-board/wanted-board-ops-sdk.test.ts for the adapter-level behavior
Acceptance Criteria
- Re-running
gt_wasteland_done on an in_review branch without a completion creates or repairs the completion row.
- Re-running
gt_wasteland_done on an in_review branch with a completion remains idempotent and does not create duplicate completion rows.
- Admin accept receives or can resolve
completion_id and no longer fails for a branch that has valid evidence.
Summary
gt_wasteland_done/ cloudwl.donecan report success and publish an in-review wanted item branch without creating the requiredcompletionsrow. Admin accept/merge then fails because the submitter branch does not contain a completion, even though the wanted row showsstatus='in_review'and hasevidence_url.Observed case:
gt_wasteland_donewithitem_id=w-eb7abcda4064and evidencehttps://github.com/Kilo-Org/cloud/pull/3349.in_reviewwith evidence.completionson the submitter branch.Likely Root Cause
packages/wl-sdk/src/ops/mutate.tshas status-only idempotency:applyMutationreads the wanted status onwl/<rig>/<wantedId>.branchStatus === targetStatus, it returns success immediately.done,targetStatusisin_review.That means a branch already at
wanted.status='in_review'skips alldoneDML, including the second statement fromsubmitCompletionDMLthat inserts intocompletions.Relevant code paths:
services/gastown/container/plugin/mayor-tools.tsexposesgt_wasteland_done.services/gastown/src/handlers/wasteland-tools.handler.tscallsWASTELAND_SERVICE.markWantedItemDone.services/wasteland/src/wanted-board/wanted-board-ops-sdk-inner.tscallswl.done(itemId, { evidence }).packages/wl-sdk/src/ops/done.tsbuildssubmitCompletionDML(...).packages/wl-sdk/src/commons/dml.generated.tsreturnsUPDATE wanted ...plusINSERT IGNORE INTO completions ....packages/wl-sdk/src/ops/mutate.tscan skip those statements when the branch status is alreadyin_review.The review inbox can still look valid because it displays evidence from
wanted.evidence_urlbefore falling back tocompletions.evidence, while admin accept requires a realcompletionsrow.Canonical Wasteland Comparison
Canonical wasteland (
/Users/john/projects/professional/kilo/wasteland) normally creates a completion forwl done:internal/sdk/mutations.go:57implementsClient.Done.internal/commons/commons.go:364buildsSubmitCompletionDMLwith bothUPDATE wantedandINSERT IGNORE INTO completions.internal/sdk/mutate.go:61applies those statements to the PR branch.Canonical also has a status-based
prIdempotentshortcut for already-in_reviewbranches, so an already-in-review branch missing a completion would likely not be repaired there either. However, cloud'sapplyMutationis broader than canonical because it short-circuits purely on branch status; canonical falls through when branch status equals main status.Proposed Fix
Make
doneidempotency validate the completion invariant, not only wanted status.Minimal targeted approach:
applyMutationbehavior for other operations.done, when the branch is alreadyin_review, readcompletionsforwanted_idonwl/<rig>/<wantedId>.INSERT IGNORE INTO completionsstatement.in_reviewbut no completion exists;wl.doneshould issue a write that creates the completion.Potential files:
packages/wl-sdk/src/ops/done.tspackages/wl-sdk/src/ops/mutate.tsif a reusable/custom idempotency hook is neededpackages/wl-sdk/src/ops/done.test.tsservices/wasteland/src/wanted-board/wanted-board-ops-sdk.test.tsfor the adapter-level behaviorAcceptance Criteria
gt_wasteland_doneon anin_reviewbranch without a completion creates or repairs the completion row.gt_wasteland_doneon anin_reviewbranch with a completion remains idempotent and does not create duplicate completion rows.completion_idand no longer fails for a branch that has valid evidence.