import fs from 'fs'; const p = 'C:/Users/decid/Documents/projects/claude_skill_owl/.planning/phases/19-sendkeys-foundation-capsule-launch/19-03-PLAN.md'; let s = fs.readFileSync(p, 'utf8'); const original = s; // 1. Update must_haves.truths — add CLNCH-09 wiring const truthOld = ' - "capsule.bat template resolves SPT_HOME, self-updates via fc /b against {SPT_HOME}/bin/capsule.bat, calls owl capsule, invokes psmux with -n winname + -f conf + attach"'; const truthNew = ' - "capsule.bat template resolves SPT_HOME, self-updates via fc /b against {SPT_HOME}/bin/capsule.bat, calls owl capsule, captures the `RESOLVED_AGENT_ID: ` line from owl capsule output and uses the resolved id for psmux session/title/has-session (CLNCH-09 / D18 auto-suffix wired end-to-end), invokes psmux with -n winname + -f conf + attach"'; if (!s.includes(truthOld)) throw new Error('truthOld not found'); s = s.replace(truthOld, truthNew); // 2. Replace the capsule.bat template block. Find the existing block between :: D18 comment and :attach // We'll replace the section starting at ":: D18: agent_id argv" through just before ":attach" const oldBat = ` :: D18: agent_id argv or project-folder default set "AGENT_ID=%~1" if "%AGENT_ID%"=="" ( for %%F in ("%CD%") do set "AGENT_ID=%%~nxF" ) if not "%~1"=="" shift :: D17: terminal title (collapse if agent_id == projdir) for %%F in ("%CD%") do set "PROJDIR=%%~nxF" set "TITLE=!AGENT_ID!" if /i not "!AGENT_ID!"=="!PROJDIR!" set "TITLE=!AGENT_ID!:!PROJDIR!" powershell -NoProfile -Command "$host.UI.RawUI.WindowTitle = '!TITLE!'" 2>nul :: Owl binary location set "OWL=%SPT_HOME%\\..\\..\\.claude\\skills\\owl\\owl.exe" if not exist "%OWL%" set "OWL=owl.exe" :: D10: reattach check — if psmux session already exists, skip owl capsule and attach "%PSMUX%" has-session -t "!AGENT_ID!" >nul 2>&1 if not errorlevel 1 ( echo Reactivating spacetime capsule for agent '!AGENT_ID!'... goto :attach ) :: Fresh launch: write skeleton perch + spawn detached capsule-listen "%OWL%" capsule "!AGENT_ID!" --project-dir "!PROJDIR!" if errorlevel 1 ( echo capsule setup failed exit /b 1 ) :: D9: winname = {repo}/{branch} for /f "delims=" %%B in ('git rev-parse --abbrev-ref HEAD 2^>nul') do set "BRANCH=%%B" if "%BRANCH%"=="" set "BRANCH=main" set "WINNAME=!PROJDIR!/!BRANCH!" :: D12: repo-local styling set "CONF=.claude\\psmux.conf" "%PSMUX%" new-session -d -s "!AGENT_ID!" -n "!WINNAME!" -f "!CONF!" "claude --dangerously-skip-permissions"`; const newBat = ` :: D18: agent_id argv or project-folder default (REQUESTED id before CLNCH-09 resolution) set "AGENT_ID=%~1" if "%AGENT_ID%"=="" ( for %%F in ("%CD%") do set "AGENT_ID=%%~nxF" ) if not "%~1"=="" shift :: Project dir (for title + --project-dir arg) for %%F in ("%CD%") do set "PROJDIR=%%~nxF" :: Owl binary location set "OWL=%SPT_HOME%\\..\\..\\.claude\\skills\\owl\\owl.exe" if not exist "%OWL%" set "OWL=owl.exe" :: D10: reattach check — if psmux session already exists for the REQUESTED id, :: skip owl capsule and attach directly. This is the reattach path; suffixing :: (CLNCH-09) only applies to FRESH launches where the requested id collides :: with a live non-psmux-session owlery perch. "%PSMUX%" has-session -t "!AGENT_ID!" >nul 2>&1 if not errorlevel 1 ( echo Reactivating spacetime capsule for agent '!AGENT_ID!'... :: D17: terminal title for reattach path set "TITLE=!AGENT_ID!" if /i not "!AGENT_ID!"=="!PROJDIR!" set "TITLE=!AGENT_ID!:!PROJDIR!" powershell -NoProfile -Command "$host.UI.RawUI.WindowTitle = '!TITLE!'" 2>nul goto :attach ) :: Fresh launch: owl capsule writes skeleton perch + spawns detached capsule-listen. :: CLNCH-09 / D18: owl capsule may auto-suffix the id on owlery-perch collision. :: It prints one line "RESOLVED_AGENT_ID: " that we must capture and use for :: all subsequent psmux commands so the suffixed id is the actual session name. set "RESOLVED_ID=" for /f "tokens=2 delims=: " %%R in ('"%OWL%" capsule "!AGENT_ID!" --project-dir "!PROJDIR!" 2^>^&1 ^| findstr /b "RESOLVED_AGENT_ID:"') do set "RESOLVED_ID=%%R" if "!RESOLVED_ID!"=="" ( :: owl capsule either failed (COLLISION: all 100 suffixes taken, invalid id, :: spawn error) or did not emit the expected line. Either way we cannot proceed. echo capsule setup failed exit /b 1 ) :: From here on, AGENT_ID is the RESOLVED id (may equal the requested id when :: there was no collision, or may be "-N" for 1 <= N <= 99). set "AGENT_ID=!RESOLVED_ID!" :: D17: terminal title (collapse if resolved agent_id == projdir) set "TITLE=!AGENT_ID!" if /i not "!AGENT_ID!"=="!PROJDIR!" set "TITLE=!AGENT_ID!:!PROJDIR!" powershell -NoProfile -Command "$host.UI.RawUI.WindowTitle = '!TITLE!'" 2>nul :: D9: winname = {repo}/{branch} for /f "delims=" %%B in ('git rev-parse --abbrev-ref HEAD 2^>nul') do set "BRANCH=%%B" if "%BRANCH%"=="" set "BRANCH=main" set "WINNAME=!PROJDIR!/!BRANCH!" :: D12: repo-local styling set "CONF=.claude\\psmux.conf" "%PSMUX%" new-session -d -s "!AGENT_ID!" -n "!WINNAME!" -f "!CONF!" "claude --dangerously-skip-permissions"`; if (!s.includes(oldBat)) throw new Error('oldBat not found'); s = s.replace(oldBat, newBat); // 3. Add acceptance criteria: CLNCH-09 wiring const accAnchor = ` - \`grep -q 'has-session' assets/capsule.bat.template\` exits 0 (D10 reattach present)`; const accAdd = ` - \`grep -q 'has-session' assets/capsule.bat.template\` exits 0 (D10 reattach present)\n - \`grep -q 'RESOLVED_AGENT_ID' assets/capsule.bat.template\` exits 0 (CLNCH-09 / D18 resolved-id parse wired)\n - \`grep -q 'set "AGENT_ID=!RESOLVED_ID!"' assets/capsule.bat.template\` exits 0 (resolved id propagated to psmux session name)`; if (!s.includes(accAnchor)) throw new Error('accAnchor not found'); s = s.replace(accAnchor, accAdd); if (s === original) throw new Error('No changes applied'); fs.writeFileSync(p, s); console.log('Plan 03 updated: ' + (s.length - original.length) + ' char delta');