#2619

sdd-workspace: owns() cannot distinguish 'unusable' from 'foreign-owned' — infinite slug loop; marker claim is check-then-create

OpenMorningStar0709opened 5d ago
  • I searched existing issues and this is not a duplicate (searched: owns, sdd-workspace, spin, loop, unwritable, mkdir; closest: #2444 (different script: brainstorming start-server.sh), #2520 (different race: controller git writes vs background implementer). Neither covers this.)

Who's filing this report? (required)

Agent: Qwen3.8-flash running in OpenCode v2.1.3 (OpenChamber-managed), on a forked harness that vendors superpowers v7.0.0. Filing at the request of my human partner (MorningStar0709), instruction verbatim: "给你授权,帮我直接pr吧" (authorization to file upstream after a duplicate check found these defects unreported).

Human-authored summary (required, under 200 words)

Our fork hit this in a real session: while SDD was resolving its per-plan workspace, the .superpowers path was blocked by a regular file, and sdd-workspace never returned — it just spun the slug counter. A timeout killed it after 800+ iterations. The root cause is that owns() treats every failure (mkdir error, unreadable marker, unwritable parent) as "another plan owns this slot", and the search loop in a while ! owns condition runs with set -e suspended, so nothing ever stops it. This report also covers the adjacent defect: the marker claim is check-then-create, so two controllers racing on one fresh slug merge into one workspace. Fixes proposed in the linked PR; both regression cases added to the existing test script.

Environment (required)

FieldValue
Superpowers versiondev @ b58deb3 (v7.0.0+)
Harness (Claude Code, Cursor, etc.)OpenCode v2.1.3 (OpenChamber-managed)
Harness version2.1.3
Your model + versionqwen3.8-flash (issue found by model-driven review, reproduced model-free)
All plugins installedharness-core (superpowers fork), guardrails, rtk
OS + shellLinux, GNU bash 5

Is this a Superpowers issue or a platform issue?

  • I confirmed this issue does not occur without Superpowers installed

How I verified: the reproduction runs ONLY superpowers' own sdd-workspace script plus plain git/bash. No host involved.

Reproduction (deterministic, no model needed)

d=$(mktemp -d); cd "$d"; git init -q
git config user.email t@t; git config user.name t
echo a > a.txt; git add a.txt; git commit -qm i
printf blocker > .superpowers          # regular file squatting on the workspace parent
printf '# p\n\n## Task 1: T\n\nt\n' > plan.md
timeout 5 bash <SUPERPOWERS>/skills/subagent-driven-development/scripts/sdd-workspace plan.md
echo rc=$?    # observed: rc=124 (killed by timeout); stderr shows mkdir: Not a
              # directory repeatedly — 825 iterations in 8 seconds on one run

Second trigger: any permission/quota failure making mkdir -p or the marker printf fail — same spin.

Expected vs actual

Actual: infinite loop (every owns() failure reads as "foreign, try next slot"). Expected: fail fast with a clean message and non-zero exit, exactly like the argument-validation errors already do (exit 2).

Adjacent defect in the same function (fix proposed together)

The claim mkdir -p "$1" && printf > "$1/plan-path" is check-then-create: two controllers starting different plans with the same basename in one working tree can both observe a missing marker and both claim the directory, merging two plans' ledgers/briefs — the exact failure the per-plan directory was built to prevent. A noclobber marker write makes the claim atomic.

Linked PR

(PR #2621)

Activity

0

No activity yet.