Skip to content

fix(codex): preserve SDD helper executable modes in packaging - #2069

Open
arimu1 wants to merge 1 commit into
obra:devfrom
arimu1:fix/2040-sdd-helper-executable-bits
Open

fix(codex): preserve SDD helper executable modes in packaging#2069
arimu1 wants to merge 1 commit into
obra:devfrom
arimu1:fix/2040-sdd-helper-executable-bits

Conversation

@arimu1

@arimu1 arimu1 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

This PR MUST target the dev branch, not main. main is the
released branch; active work lands on dev first. PRs opened against
main will be asked to retarget dev before review.

Who is submitting this PR? (required)

Field Value
Your model + version Grok 4.5
Harness + version Grok Build (xAI)
All plugins installed none (no Cursor plugins; implementator run under Grok Build only)
Human partner who reviewed this diff arimu1

What problem are you trying to solve?

Real report in #2040 from @michaelholcomb-creator: Superpowers 6.2.0 installed via the Codex marketplace cache arrived with these SDD helpers at mode 0644 (non-executable):

  • skills/subagent-driven-development/scripts/sdd-workspace
  • skills/subagent-driven-development/scripts/task-brief
  • skills/subagent-driven-development/scripts/review-package

Direct invocation fails with Permission denied. Running only task-brief / review-package through Bash does not fully recover the default-output path, because both scripts previously directly executed their sibling sdd-workspace (which still needs +x).

Upstream git already records all three as 100755. The portal packager (scripts/package-codex-plugin.sh) already aims to preserve modes, but:

  1. Packaging tests only checked one helper after Info-ZIP extract, and did not assert the zip external attributes that installers read.
  2. Zip extractors that ignore Unix external attributes (e.g. Python zipfile.extractall) leave helpers at 0644 even when the archive stores 0755 — verified locally: same archive → CLI unzip = 755, Python extract = 644.

What does this PR change?

  1. Packaging: After git archive | tar -xpf, re-apply chmod a+x for every staged path that is 100755 in the packaged ref, and fail closed if any remains non-executable. Accept linked worktrees (.git file) as valid checkouts.
  2. SDD helpers: task-brief and review-package invoke sdd-workspace via "${BASH:-bash}" so default OUTFILE resolution works when helpers are mode-stripped but invoked with Bash.
  3. Tests: Assert zip extract +x and stored zip external attrs 0o755 for all three SDD helpers; assert tar.gz modes for all three; add mode-stripped install-path coverage in test-sdd-workspace.sh.

Is this change appropriate for the core library?

Yes. This is core Codex packaging infrastructure plus the shared SDD helper scripts every harness uses. It does not add third-party dependencies, domain skills, or project-specific config.

What alternatives did you consider?

  1. Docs-only / “run via bash” in SKILL.md only — does not fix packaging modes, and without the sibling-bash change, bash task-brief still fails when it directly execs non-executable sdd-workspace.
  2. Change default package format to tar.gz — marketplace/portal consumers expect zip; would not help installers that strip modes on extract.
  3. Post-install chmod hook — we do not control the Codex marketplace install path; not available in-repo.
  4. Only strengthen packaging / only sibling bash — either alone is incomplete (archive correctness vs install resilience). Combined approach covers both layers we control.

Does this PR contain multiple unrelated changes?

No. All changes are for #2040: preserve/assert SDD helper execute bits in Codex packaging, and make sibling helper invocation work when installers drop +x.

Existing PRs

Environment tested

Harness (e.g. Claude Code, Cursor) Harness version Model Model version/ID
Grok Build (local shell + git packaging) current session Grok 4.5 Grok 4.5
macOS zsh + bash + Info-ZIP + Python 3.14 zipfile

New harness support (required if this PR adds a new harness)

N/A — does not add a new harness.

Clean-session transcript for "Let's make a react todo list"
N/A — not a new harness integration.

Evaluation

  • What was the initial prompt you (or your human partner) used to start the session that led to this change?
  • How many eval sessions did you run AFTER making the change?
    • Focused deterministic suites (not multi-session skill evals): tests/claude-code/test-sdd-workspace.sh (16/16 PASS including new mode-stripped cases); tests/codex/test-package-codex-plugin.sh (all new/mode assertions PASS; one pre-existing zip timestamp timezone assertion still fails on this host — same class as open fix(codex): make package timestamps timezone-independent #2007, not introduced by this change).
  • How did outcomes change compared to before the change?
    • Before: package tests only checked one helper after unzip; no zip external-attr assertion for the three SDD scripts; bash task-brief with all three at 0644 failed when resolving default OUTFILE because it directly executed sdd-workspace.
    • After: packaging re-chmods staged 100755 paths and fails closed; tests assert 0o755 in the zip for all three helpers + extract +x + tar modes; with helpers at 0644, bash task-brief / bash review-package still write under .superpowers/sdd/<plan>/.

Rigor

  • If this is a skills change: I used superpowers:writing-skills and completed adversarial pressure testing (paste results below)
  • This change was tested adversarially, not just on the happy path
  • I did not modify carefully-tuned content (Red Flags table, rationalizations, "human partner" language) without extensive evals showing the change is an improvement

Not a behavior-shaping skill prose change: only helper scripts (sibling invocation), packaging script, and tests. Adversarial cases: mode-stripped copies (chmod a-x), direct exec of stripped sdd-workspace (still fails as expected), Python zip extract vs CLI unzip on the produced archive.

Human review

  • A human has reviewed the COMPLETE proposed diff before submission

Fixes #2040

Codex marketplace installs of 6.2.0 left sdd-workspace, task-brief, and
review-package non-executable (0644). Keep git 100755 modes in the portal
zip/tar stage, assert them in packaging tests, and invoke sdd-workspace via
bash from siblings so default OUTFILE still works when extractors drop +x.

Fixes obra#2040
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