Address the two final whole-PR findings from the consolidated movie repair
brief. A fresh openai-chat response must provide a speech-bearing string
transcript even when local ASR is off; null must not reuse the no-transcript
sentinel belonging to deterministic engines or cached accepted audio.
Preserve the bounded candidate loop and rejected-byte evidence.
Report failed Windows tree termination as OSError so the recorder owner's
existing per-child handler continues all cleanup and retains failure metadata.
Card rendering checks its acquired browser handle before acting on the PID,
propagates wait failure, and reports locked-profile removal instead of
allowing a pending successful return to hide incomplete cleanup.
Add fake HTTP/process/filesystem boundary regressions for both findings,
including real adapter invocation, accepted chat cache reuse, ASR modes,
normal completed cards, and serve cleanup after a failed leader later exits.
Correct the rejected-chat fixture to use the chat engine. No media or native
browser execution was performed; Drew retains personal video acceptance.
Validation: expected RED failures retained; 40 focused tests and the single
75-test contracts entrypoint pass. Full evidence and self-review are in
.superpowers/sdd/2026-09-11-movie-committee-repairs/final-fix-report.md.
Repair the shipped Unix, logging, subtitle, cursor, narration, and recorder guidance against the literal fake-boundary failures recorded for Task 4. The primary pipeline and subtitle recipe now fail fast, measured offsets reach subtitle generation, producer logging preserves the real status under the pipefail owner, and cursor mouseup restores the released state.
Document the accepted narration/cache contract, cooperative recorder cleanup limits, and the safe contracts-suite entrypoint without changing Windows recipes or the existing evidence and human-viewing gates. Include the controller-owned plan bookkeeping and record the executable RED/GREEN results while leaving independent fresh-reader trials pending.
Prompt: implement Task 4 focused executable movie-guide corrections after Tasks 1-3, using writing-skills and only fake producers, text fixtures, and fake DOM execution.
Verification: python3 .superpowers/review/pr2214/committee/recipe-probes.py; uv run --script tests/proving-it-works-with-a-movie/run-tests.py --suite contracts; git diff --check.
Address both independent Task 3 review findings at 42486dbb. When an owned leader exits before tree cleanup, the existing parentage helper cannot confirm orphan descendant cleanup. Treat that state as incomplete, preserve PID metadata, return failure, and never invoke the helper on the exited leader's numeric PID. Continue releasing the other owned resources without adding descendant tracking.
Keep a recording capture failure truthful while preserving available completed command evidence: outcome remains failed, exit status remains 1, and the capture error is retained alongside ok, native exit_code, and cwd. A completed successful command does not make a failed recording successful, and no successful take manifest is published.
TDD regressions reproduced an exited leader incorrectly returning 0 and capture failures dropping completed native status for exits 0 and 7. All 14 covering lifecycle and observation tests pass using fake process handles, fake clocks, mocked capture/log boundaries, and intercepted media writes; git diff --check passes. No real media generation or inspection, process/browser launches, SessionTests, FilmGridTests, or full media suites were executed. Detailed RED/GREEN evidence is appended to .superpowers/sdd/2026-09-11-movie-committee-repairs/task-3-report.md.
Implement Task 3 of the consolidated PR 2214 movie repairs. Startup failures could leak an already launched ttyd or browser because acquisitions preceded the cleanup block; close killed historical numeric PIDs and reported success without confirmed cleanup. Register each acquired resource inside serve's try/finally, invalidate readiness on shutdown, retain logs, and atomically retire PID metadata only after confirmed owned-process and profile cleanup. Close now requests stop and waits under one overall 30-second deadline without killing PIDs.
Poll CDP and owner readiness while observing commands without recording, preserving a completed native exit status across simultaneous disconnects and reserving exit 2 for live unfinished commands. Fill only bounded 5 fps slots when a final capture crosses the hard or hold endpoint, correctly strip ST-terminated OSC titles, and emit ASCII-escaped stdout JSON while preserving UTF-8 session files. A serve-only CDP call-boundary check prevents a stop from waiting through multiple consecutive calls.
Add 21 contract tests using fake processes, fake websocket responses, fake clocks, byte-token capture callbacks, and intercepted frame writes. Register real-session test cleanup immediately after Popen and retain live PID snapshots, but do not execute that fixture. RED evidence and implementation report are in .superpowers/sdd/2026-09-11-movie-committee-repairs/task-3-report.md. Validation: 26/26 authorized prompt, serve-argument, and recorder contract tests pass; git diff --check passes. No media generation, inspection, browser/ttyd launch, real session or frame-grid suite was performed. Native movie acceptance remains Drew's review; an abruptly hard-killed owner with a live browser and stale readiness remains the agreed limitation.
Address Task 2 review round 1: initial character budgets count spaces that disappear between chunks, so proportional timing can exceed --max-secs even when a further word-boundary split is feasible. Reallocate after splitting an over-target multiword cue, checking actual integer millisecond intervals each time.
Coalescing runs once before refinement, and refinement stops at the available millisecond count or unsplittable words. This keeps tiny impossible readability targets bounded while preserving every word and the full measured scene interval.
Added a failing six-second unequal-chunk regression and a tiny-target termination/positive-interval guard. The RED emitted 3273 ms for a cue with a 3000 ms target. GREEN: 43 safe contract tests and six covering existing offset/BOM tests pass. All verification remained text/data or mocked media boundaries.
Implement Task 2 of the movie committee repairs. Allocate proportional cue boundaries across each complete rounded scene interval, reserve positive millisecond spans, and coalesce chunks when the available interval cannot represent them separately. Readability limits guide word splitting without dropping text or clipping narration tails; invalid intervals fail before subtitle output is written.
Explicitly select the supplied soft subtitle track with optional source audio, including the hard-burn fallback. Parse only numbered SRT cue timing lines so arrow-bearing captions cannot crash the checker or inflate coverage. Preserve the existing maximum cue end policy, assembly-offset intersection, and partial manual retiming.
Add 17 safe subtitle contracts and register the contracts runner suite. Real-file mocked narrate/assemble/subtitle reruns retain removed narration WAV evidence while omitting stale assembly audio and offsets. Verification: 41 contract tests and 18 authorized existing regressions pass; only text and mocked media boundaries were exercised. Native Windows and human video acceptance remain outside this verification.
Close Task 1 review round 2 without production changes. Feed actual unsupported ASR text through auto and strict verification while proving off does not call ASR. Run the second rejected narration invocation without --force, then assert it synthesizes new takes and retains distinct rejected bytes instead of reusing cache evidence.
Address Task 1 review round 1. Treat successful empty ASR output as speech failure rather than an unavailable verifier, reject empty chat claims within the existing bounded retry loop, and extend unsupported segmentation detection to supplementary CJK ideographs.
Withdraw cached acceptance before every revalidation so strict failures and interrupts cannot leave stale publication. Preserve nested manifest WAV paths on cache reacceptance, and measure a unique candidate before promotion so duration failures retain their evidence across reruns. Add structured movie geometry coverage plus both silent and source-audio mapping tests. All tests use uv --no-project with mocked synthesis, ASR, probes, and encoding; no media operation was run.
Repair Task 1 from the 2026-09-11 movie committee plan. Narration now atomically withdraws acceptance before it mutates accepted bytes, stages failed takes as retained evidence, and publishes a manifest entry only after transcript gates and duration measurement. It preflights ffprobe, preserves bounded retries and cache identity, and distinguishes unsupported token comparison from cache identity.
Assembly now validates accepted manifest narration before it starts encoding, ignores generated narration for movie scenes, selects manifest WAV paths, maps source or synthetic movie audio explicitly, fits wide movies within the requested inner rectangle, and escapes only literal directory percent signs in sequence paths. The focused regression suite mocks every media boundary; real-media fixture declarations are updated but not executed. Prompt constraints prohibit real media generation, probing, inspection, synthesis, ASR, browser, checker, or full media suites.
Address the final three review findings on PR #2214, as approved by Drew. Count both sides of every non-equal transcript span so a short insertion or expanded replacement cannot evade the drift gate on a longer script. Preserve the existing length and run thresholds.
Honor --no-expect-audio for encoded silent tracks. Base subtitle requirements on detected audible speech so opting out of expected audio does not suppress captions for speech that is present.
Extract the first embedded subtitle stream as SRT when no sidecar is present and apply the same cue-end check to either source. Empty cues fail even for short narration, and extraction or malformed timing errors are reported as failures. Preserve the silent end-card allowance.
Validation: the new tests first reproduced ten failing cases across narration insertion, silent-track opt-out, and embedded subtitle handling. All 35 focused narration, checker-policy, and subtitle-text tests now pass. External media commands, audio and picture sampling, contact-sheet creation, synthesis, and ASR were mocked; no actual media inspection or live ASR was performed. Drew retains final video acceptance.
Address the fresh review on PR #2214 after the #2275 integration. Drew approved fixing the two reproduced bugs and keeping the specified auto/on/off verification semantics.
Cache accepted narration by normalized text plus effective engine, voice, and synthesis model. Resolve voice defaults before rendering, invalidate entries without settings, and retain requested ASR checks on cache hits. Exclude rejected clips as before.
Treat manual subtitle offsets as start-time overrides. Only assembly offsets JSON selects scenes in the cut, including when manual timing overrides are also supplied. Empty narrated cuts write an empty SRT without crashing.
Make the gated Unix example pass --verify on and document the actual local ASR modes. Auto remains permissive if ASR is unavailable; on remains strict.
Validation: observed the new cache and subtitle regressions fail before the fixes; all 23 focused narration and subtitle-text tests now pass. Synthesis, duration probing, and ASR are mocked. No media inspection or live ASR was performed; Drew retains final video acceptance.
Prevent failed narration scenes from entering the cache manifest, while leaving their generated WAV files available as failure evidence. Add filesystem-backed regressions covering repeated rejected chat synthesis, accepted-scene reuse, and strict ASR rejection of cached audio.
Refuse nonempty recording directories both before CLI session side effects and at the direct film boundary. The regression preserves existing numbered frames and a sentinel byte-for-byte across run, key, watch, and direct film refusal.
Make subtitle capability tests independent of the host FFmpeg installation, skip the real pixel test before probing unavailable tools, retain strict skipped-capability rejection, and remove only the unused websockets runner dependency.
Align scrubber and independent audit prompts around one shared redaction policy while preserving safe command, result, source, session-line, quotation, and linkage structure. Add finished-handoff evidence and reconciliation instructions, provenance labels across case/report/bundle/issue templates, and the structural existence check for the shared reference.\n\nThis patch responds to the retained negative post-report handoff baseline: cited result bodies were removed wholesale, source findings and the positive related-session match were not verifiable, provenance and export statements were stale, and scrub counts disagreed. The behavioral handoff validation remains pending for the follow-up task; this commit records only the focused product guidance and structural RED/GREEN evidence.
At Drew's request, apply the evaluated shared-discovery variant to Jesse's
existing PR #2236. Resolve native session sources and record semantics from
available tools, documentation and bounded inspection. Record verified absolute
paths, linkage, extraction queries, human-message distinctions, usage-counter
semantics and uncertainty once in the case for all analysts to consume.
Replace the three per-harness references and update structural checks.
This is exactly the evaluated source tree at
3f0a63e860, applied as one commit on
801badbf71. Fourteen files change;
126 lines added, 285 removed. No private eval fixtures or transcripts ship.
Validation:
- Structural test: 45 passed, 0 failed before and after application.
- Staged tree exactly matches the evaluated candidate; diff check passes.
- Independent read-only review: no actionable blockers.
- Retained before/after full doctor runs: one pair each on native Claude,
Codex and Pi. All six delivered reports and completed seven dimensions.
Shared discovered all three native session families without the removed
references. Both versions had report-quality defects; shared Codex deleted
its cited case through a fixture symlink. Preserve this negative result.
- Eight fresh Codex follow-ups: original/shared x symlink/ordinary-home x
two repeats, one retained historical session family. All eight retained
cases and supported the four core findings. Seven native final deliveries;
one shared run stopped on provider capacity after writing its report.
No deletion recurred. One original reused three analysts for seven tasks.
Recorded follow-up cost $34.8617883, all eight attempts accounted for.
These observations support this scoped simplification, not general equivalence
or a causal claim that reference removal caused or could not cause a failure.
Child assignment/model choices were native behavior; the complete variants
also differ in analyst prompts. Common provenance, citation-verification and
measurement problems remain separate follow-ups. No new paid runs were made
for this publication; evidence and independent audits are retained privately
by Drew. Behavioral evaluation provenance: campaigns
358c7333-c5f0-48bd-a733-61196da992ed and
102d630d-30ef-49a0-97e1-8dd410ed0548.
Prepared with GPT-6 using Codex through Paseo; local codex-cli 0.153.4.
Skills used: superpowers writing-skills, using-git-worktrees,
requesting-code-review, verification-before-completion; primeradiant-ops
linear-ticket-lifecycle. Drew approved publishing this evaluated variant.
Enabled plugins in the publishing checkout's Codex configuration:
- github@openai-curated
- documents@openai-primary-runtime
- spreadsheets@openai-primary-runtime
- presentations@openai-primary-runtime
- primeradiant-ops@primeradiant
- slack@openai-curated
- linear@openai-curated
- codex-security@openai-curated
- pdf@openai-primary-runtime
- template-creator@openai-primary-runtime
- sites@openai-bundled
- visualize@openai-bundled
- computer-use@openai-bundled
- cloud-build@superpowers-cloud-build
- browser@openai-bundled
- superpowers@superpowers-dev
- stream-deck-agents-codex@drew-local
- computer-history@openai-bundled
- codex-app-tools@openai-bundled
- unified-computer-use@openai-bundled
- chrome@openai-bundled
- bits-and-bolts@mcp-extensions-early-access
- visual-probe@visual-probe-local
Tracking: PRI-3127
Move GitHub search and prefilled-link mechanics to references/github-issues.md.
State the redaction levels neutrally instead of nudging toward more data.
Say that all seven analysts always run and what the quick-reference table
is for. Add a title slot and a bundle slot to the issue template. Drop the
duplicated human-prompts rule from request-conflicts. Prose fixes: active
voice, dangling modifier, vague referents, two lists turned into tables.
The seven analyst prompts opened with an identical 39-line block (role,
inputs, context safety, return format). It now lives once in
prompts/analyst-common.md and each dimension prompt points at it. The
wc -lc / long-line / never-cat rule was restated in nine places; it now
lives in references/context-safety.md and everything else points there.
Addresses arittr's review on #2236.
Never build or push a bundle unprompted. When intake names a bug report as
the goal, say once that a bundle is available on request, then wait. On
handover, state what the bundle contains, point at the scrub log, and say
scrubbing can miss things so every file needs review before sharing.
Raise the SKILL.md word budget to 1000 to fit the added rule.
Evidence-based diagnosis of superpowers sessions: intake with the human
partner, safe transcript reading for Claude Code and Codex (discovery
procedure for other harnesses), seven analyst subagents, a report with
path:line evidence and a bounded superpowers-involvement line, scrubbed
export bundles, approval-gated GitHub issue search/draft, and
similar-session search. Includes spec, plan, structure test, and README
and docs index lines.
Developed RED-GREEN-REFACTOR per writing-skills: 46 scored scenario runs
across five SKILL.md versions, all twelve scenarios clean against the
final version, micro-tests control 5/5 to skill 0/5 on both
baseline-failing prohibitions, and one end-to-end run. Eval records are
kept by the maintainer outside the repo.
Claude-Session: https://claude.ai/code/session_01DyaGKhTXvHNs2JgPhDktz7
Windows has no tmux, so the recorder had grown into a 738-line daemon with a
file-based request protocol, request IDs, wait-only result retrieval, and a
Win32 Job Object module. Replace it with the Unix route's shape: serve keeps
ttyd and a headless browser alive and logs the terminal's output; run, key,
watch, and close are one-shot CDP calls against that browser. The installed
prompt reports each command's status through the window title, so run can
print it without any visible marker.
Process cleanup uses taskkill /T (a pgrep walk on Unix) instead of Job
Objects, which also simplifies the card renderer. The session tests run on
macOS too, since nothing in the script is Windows-specific.
Verified: 9 session tests per shell on Windows 11 for PowerShell 5.1,
PowerShell 7, and Git Bash; the browser suite with Chrome and Edge; 44
portable tests on macOS against a real ttyd session.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The in-process narration and subtitle tests let the tools' stdout and
stderr through to the runner. Capture both and assert the expected
diagnostics.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The Python suite ported the three shell tests' assertions so they run on
Windows; both copies were kept and the README mapped one to the other. Keep
the portable suite. Drop the one-shot Windows acceptance driver and its
browser fixture, which produced evidence rather than regressions, and the
never-implemented reserved suite names.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The first, broader OS-compatibility rollout was stopped and replaced by the
narrower Windows completion. Its feasibility probe, probe cleanup test,
design, review, 12-task plan, results report, and the completion plan and
review record were internal execution artifacts with machine-specific paths.
The one probe-derived test list is inlined into the terminal suite.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Brings the proving-it-works-with-a-movie skill (demo/screencast/proof-video
recording, plus the check-movie timeline gate that catches frozen pictures,
narration drift, and dropped words) into superpowers core, along with its
supporting docs, scripts, and shell regression tests.
Source: prime-radiant-inc/proving-it-works (MIT, same copyright holder),
skills/proving-it-works-with-a-movie/ at time of import. The five scripts
(narrate, make-subtitles, assemble, burn-subtitles, check-movie) are
self-contained uv --script files with inline PEP 723 dependency
declarations, so they port with no new project-level dependency wiring.
Test paths were adjusted one directory level to match superpowers'
tests/<skill-name>/ layout (the standalone repo kept tests/ as a
top-level sibling of skills/).
Adds a Verification entry to README's Skills Library list.
Goal: fold this into 6.4 and retire the standalone repo.
When an SDD implementer commits to the wrong branch (#2050), the
BASE..HEAD range handed to review-package is either empty or not rooted
at BASE. Both cases previously produced a review package silently —
an empty one lets the reviewer approve "clean" work that isn't there.
Add two mechanical guards after BASE/HEAD validation, exiting 3 (vs 2
for usage errors) so callers can distinguish range problems:
- git merge-base --is-ancestor BASE HEAD, else "HEAD is not a
descendant of BASE"
- git rev-list --count BASE..HEAD > 0, else "empty commit range"
Guard shape credits the analysis in closed PR #2082 by @stantheman0128.
Fixes#2050
Codex marketplace users hit 'Permission denied' running SDD helpers:
some extractors (Python zipfile) discard Unix mode attributes when
unpacking the package, so task-brief's and review-package's direct exec
of their sibling sdd-workspace fails. Our packaging preserves 0755
(git archive | tar -xpf, asserted by the existing packaging test) — the
bits are lost on the consumer side, which no packaging change can reach.
Invoking the sibling via "${BASH:-bash}" makes the exec bit irrelevant.
TDD: new regression case copies the helpers, chmod -x, runs task-brief
via bash — RED with the reported rc=126 Permission denied, GREEN after.
Reported in #2040 (michaelholcomb-creator). Fixes#2040.
Re-ran the clean-session acceptance test with the mapping file and the
SKILL.md Platform Adaptation pointer removed: using-superpowers and
brainstorming still auto-trigger first, and the full workflow chain
(writing-plans, executing-plans, TDD, verification) resolves every action
to Devin's native tools. Devin CLI's own system prompt already documents
its tools (skill invocation, subagent profiles, todo tracking, question
prompts), so the mapping was redundant. Test now validates the manifest only.
Devin CLI's `devin plugins install obra/superpowers` fails today because the
repo has no `.devin-plugin/plugin.json` manifest. Add the manifest (skills are
auto-discovered from the co-located skills/ directory), a Devin tool mapping
linked from using-superpowers' Platform Adaptation section, a README install
section, version tracking in .version-bump.json, a Codex-sync exclude for the
new dotdir, and a CI-safe test mirroring the kimi/antigravity test style.
Bootstrap rides Devin's native skill surfacing: every installed skill's
name + description is injected into the system prompt at session start with a
standing instruction to invoke matching skills via the native skill tool.
Acceptance test ("Let's make a react todo list") passes in a clean session:
using-superpowers and brainstorming auto-trigger before any code is written.
Register the Hermes YAML manifest alongside the existing JSON manifests. Route manifest reads and writes by extension through jq or Mike Farah yq v4, with field names and values passed as data.
Preflight every present manifest before the mutating bump loop so a deterministic YAML read failure cannot leave earlier JSON manifests partially updated. Cover check, audit, bump, registry wiring, and byte-for-byte no-partial-write behavior with one focused fixture test.
The 20-test suite still exercised the dead on_session_start/inject_message
mechanism (17 failures against the rewritten plugin). Rewritten for the
real contract: pre_llm_call registration + first-turn-only context return,
register_skill receiving pathlib.Path (the conftest mock now raises on str,
mirroring hermes' AttributeError that silently disables a plugin), both
install layouts resolving skills, loud failure when skills are missing,
tool mapping sourced verbatim from hermes-tools.md, and a bootstrap-size
guard against hermes' 10k-char context spill threshold. 19 tests, passing.
Install docs collapse into the README section per maintainer direction:
docs/README.hermes.md and .hermes-plugin/INSTALL.md are gone; the README
carries the two-line install plus the compaction caveat. plugin.yaml
version aligned to 6.1.1.
Rebase of PR #1922 onto current dev: the ~14 files of v6.1.0-era
codex/release drift are dropped, the porting-guide edits (stale against
the post-prune rewrite, no Hermes content) are dropped, and the Hermes
surface is kept intact: .hermes-plugin/ (on_session_start bootstrap
injection), tests/hermes/ (20 tests, passing), docs/README.hermes.md,
references/hermes-tools.md, the Platform Adaptation row, README section,
and Python ignores.
Known open items from review, unchanged by this rebase: the injection
mechanism uses ctx.inject_message from on_session_start, which the
official plugin guide does not document (pre_llm_call returning
{"context": ...} is the sanctioned path), skills are not registered via
ctx.register_skill, and the acceptance transcript predates the fix.
Co-authored-by: kumarabd <kumarabd@users.noreply.github.com>
Follow-up to #2011 (which fixed the ./-prefix mismatch for the documented
pattern form): strip a leading ./ from the caller's pattern instead of
double-prefixing it into a never-matching ././ form, and also match the
pattern with '**/' collapsed, since find -path cannot match '**/' against
zero directory levels and silently skipped files directly under the base
directory (src/top.test.ts vs src/**/*.test.ts).
Adds a deterministic test suite for the script with a stubbed npm.
tests/claude-code/test-subagent-driven-development.sh failed
intermittently for two independent reasons:
- Budget mismatch: the file runs 9 prompts with a 90s timeout each
(810s worst case) inside the runner's 600s per-file ceiling, so slow
backend days produced spurious timeouts. Raise the runner default to
900s and fix the help text, which claimed the default was 300.
- Case-sensitive prose matching: the assert helpers grepped free-form
model output case-sensitively, but models capitalize the skill's own
headings — observed failures include "Do Not Trust the Report"
missing pattern "not trust" and a structured answer missing
"First:.*spec.*compliance". Match case-insensitively in
assert_contains/assert_not_contains/assert_count/assert_order, widen
two Test 5 keyword patterns to phrasings observed in real runs, and
make assert_order dump the output on failure the way assert_contains
already does, so the next flake is diagnosable.
Observed 3 failures across 4 runs before the change (timeout, two
distinct pattern misses); 3/3 consecutive full runs pass after it.
The packaging pipeline only worked on a Mac with default umask, for
three stacked reasons:
- The deterministic-metadata tar flags (--uid/--gid/--uname/--gname)
are bsdtar spellings; GNU tar rejects them, so the tar.gz archive
step died on Linux. Detect the tar flavor and use --owner=:0
--group=:0 --numeric-owner on GNU tar, which writes byte-identical
ustar headers (uid/gid 0, empty uname/gname).
- Staged file modes depended on two umasks canceling out: git archive
masks entry modes with tar.umask (git default 0002 -> 775), and the
unflagged tar extraction re-masked with the process umask (022 on
macOS -> 755, but 002 elsewhere -> 775). Pin tar.umask=0022 on the
archive call and extract with -p so staged modes are canonical
755/644 on every machine.
- The test's timestamp assertion parsed bsdtar's -tv column layout and
expected epoch 0 rendered in a US timezone ("Dec 31 1969"); GNU tar
uses different columns and UTC hosts render "1970-01-01". Assert
mtime == 0 via python3 tarfile instead, matching how the test
already checks zip timestamps.
tests/codex/test-package-codex-plugin.sh now passes on Linux/GNU tar;
the bsdtar branch preserves the exact flags that passed on macOS.
The SessionStart command string starts with a quoted path, which breaks
both Windows shells Claude Code may hand it to: PowerShell parses the
leading quoted string as an expression and dies on the next bareword
('Unexpected token session-start', #1751), and cmd.exe's /c quote rule
drops the outer quotes when the path contains a metacharacter, so a
profile dir like C:\Users\Name(External) truncates the command at the
'(' (#1918). Either way the bootstrap silently never loads.
Declare shell: "bash" on the hook. Claude Code >= 2.1.81 then resolves
Git for Windows and runs the polyglot's bash path directly — the same
route it already picks when it detects Git Bash — and when Git Bash is
missing it surfaces an actionable install prompt instead of a parser
error. Older versions ignore the unknown key and behave exactly as
before (verified live on 2.0.77 and 2.1.80).
Verified end-to-end with real claude sessions: Linux (hook fires,
bootstrap injected), Windows 11 + Git Bash under a path containing
'(' and a space (fires, 3276-char context), and Windows 11 without
Git Bash (actionable error replaces the #1751 ParserError, reproduced
verbatim as control).
Fixes#1751Fixes#1918
sdd-workspace now requires the plan file and resolves
.superpowers/sdd/<plan-basename>/; task-brief and review-package write
into their plan's directory (review-package gains PLAN_FILE as its first
argument). Follow-up plans in the same working tree can no longer collide
with a previous plan's briefs, reports, or ledger.
The pi tokens (subagent, pi-subagents, Task, TODO.md) also appear in the
surrounding prose, so matching the whole file passed even with the mapping
table deleted — the exact regression this test exists to catch. Filter to
table rows (lines starting with '|') so the assertion fails when the table
is gone and passes on dev.
Reported by @muunkky on #1987 (approach from #1983); verified failing-first
by stripping the table rows from pi-tools.md.