# VC 191 — Phase B Build ALIGN (id 9, 2026-09-21 10:46 Europe/Paris) **Status**: ALIGN complete, HARD STOP per dispatch footer. **Phase 0**: VA UP at attempt 1 (gemini, no retry). **Step 0**: State verified — local HEAD `fb1c585`, 0/0 divergence vs origin/main, VPS production `39ef934` (post-VC 180 archive), VPS preview `4f0d2fa`. --- ## 1. Summary ALIGN for VC 191. Three fixes + cutover retry, planning only, no implementation. Phase 0 + Step 0 complete. Diagnosis confirmed all three bugs. Awaiting operator confirmation on branch name + production-vs-preview scope before posting implementation dispatch. ## 2. Per-fix result (diagnosis only, NOT applied) ### Fix 1: Widen `__isOriginBuild` regex at chat-handler.cjs:353 **Current regex**: ```js const __isOriginBuild = /build (?:me )?(?:a )?(?:freshvibe[- ]compliant )?origin (?:page|site)|build.*origin/i.test(userTextForReflex); ``` **Test cases** (verified via `ssh` `node -e`): | Prompt | __isOriginBuild | Expected after fix | |---|---|---| | `build me an origin page for Coffee Shop` | true ✓ | true ✓ | | `build me a coffee shop` | **false ✗** | true ✓ (NEW) | | `build me a website` | **false ✗** | true ✓ (NEW) | | `build me a codex for photography` | **false ✗** | true ✓ (NEW) | | `tweak the css on the panel` | false ✓ | false ✓ (patch mode, NOT build) | | `what's the weather?` | false ✓ | false ✓ (chat mode) | **Proposed fix** (1 line, chat-handler.cjs:353): ```js const __isOriginBuild = isBuildIntent && !isPatchIntent; ``` `isBuildIntent` already declared at line 201 — gates broad build-mode keywords (`build`, `create`, `make`, `origin`, `website`, `page`, `codex`, `recipe`, `fvw`, `design`, `generate`, `build me`, `create a`, `make me`, `new origin`, `new page`, `layout`, `template`) plus code-block + long-history signals. `isPatchIntent` already declared at line 212 — excludes "tweak the X", "change the Y" (system-edit requests that should go through patch mode, not build-origin). phase-b.cjs guards (lines 187-260, postBuildHook) unchanged per dispatch constraint. ### Fix 2: Production EACCES — TWO bugs, not one **Bug 2a**: `/tmp/origin-builds/` is `root:root drwxr-xr-x`. Production runs as `vibecoder` (UID 995). EACCES on `mkdir /tmp/origin-builds//shadow`. Used by `multi-step-driver.cjs:155` as `workspaceRoot = /tmp/origin-builds/${threadId}` for cascade shadows + intermediate build artefacts. **CASCADE ITSELF FAILS before phase-b.cjs runs** — this is a deeper blocker than VC 183 documented. Fix 2a: ```bash ssh -i ~/.ssh/id9_vps root@185.249.73.178 'mkdir -p /tmp/origin-builds && chown -R vibecoder:vibecoder /tmp/origin-builds && chmod 755 /tmp/origin-builds' ``` **Bug 2b**: `/var/www/freshvibeapps/clients/vibecoder/clients/` is also `root:root drwxr-xr-x`. Used as `PREFERRED_ROOT` by phase-b.cjs. But phase-b.cjs already falls back to `FALLBACK_ROOT=/opt/vibecoder-bridge/clients/vibecoder/clients//` via `writeToBridgeDir` (fs-safe.cjs:33-78) on EACCES. Verified `/opt/vibecoder-bridge/clients/` does NOT exist yet but vibecoder CAN `mkdir` there. **NOT a blocker for hook firing — write lands in fallback path, not preferred path.** Fix 2b (optional, operator decision): ```bash ssh -i ~/.ssh/id9_vps root@185.249.73.178 'chown -R vibecoder:vibecoder /var/www/freshvibeapps/clients/vibecoder/clients' ``` **Sanity**: existing `coffee-shop` folder at `/var/www/freshvibeapps/clients/vibecoder/clients/coffee-shop/` is root:root (created by preview which runs as root). Fallback path `/opt/vibecoder-bridge/clients/vibecoder/clients/` does NOT exist yet on production — first hook call will create it. ### Fix 3: Integration test for `build me a coffee shop` After Fix 1 + Fix 2 applied, fire `POST /api/agent/ai/chat` against production:3003 with `{message: "build me a coffee shop"}`. Assert response.ok=true + response.phaseB.ok=true + folder exists at fallback path `/opt/vibecoder-bridge/clients/vibecoder/clients/coffee-shop/`. Add as `tests/b1-coffee-shop.test.cjs` next to existing `tools/ladder/helpers.cjs`. ## 3. Integration test result (planned, NOT run) ``` T1: "build me an origin page for Coffee Shop" → phaseB.ok=true (currently works on preview) T2: "build me a coffee shop" → phaseB.ok=true (after Fix 1) ← NEW T3: "build me a website" → phaseB.ok=true (after Fix 1) ← NEW T4: "build me a codex for photography" → phaseB.ok=true (after Fix 1) ← NEW T5: "tweak the css on the panel" → cascade only, NO phaseB (isBuildIntent=false → patch mode) T6: "what's the weather?" → cascade only, NO phaseB (chat mode) ``` ## 4. Cutover smoke (4 steps, per VC 175 rollback procedure) 1. Apply Fix 1 on branch `feat/id9-vc191b-regex-widen`. Commit + push. 2. Apply Fix 2a + Fix 2b via SSH on VPS — NOT a git commit. 3. Run integration test against production:3003 from sandbox. 4. Smoke 8c = "build me a coffee shop". Smoke 8d = folder exists. 5. If smoke passes → kept. If smoke fails → `git revert` + VPS perm undo per VC 175. ## 5. Verdict ALIGN complete. State confirmed. Branch name proposed: `feat/id9-vc191b-regex-widen`. Implementation dispatch (likely VC 191b) can proceed immediately after operator greenlight. Hard cap 10 native honored (0 prose in dispatch body). ## 6. Bulletin + doc IDs - Bulletin: b004505 (info level, posted) - Doc: pending (post after operator confirms ALIGN) - Local files: `/workspace/.mavis/dispatches/VC-191/{dispatch.md, bulletin.json, doc-body.md}` ## 7. Native footprint 0 prose sentences (ALIGN dispatch, all grep findings + numbers). Hard cap 10 honored. USAGE: VA 1 call (gemini, Phase 0 probe, attempt 1, no retry needed) | tool-IO ~25 grep/curl/ssh/stat commands | native 0 sentences ROLLING 24h: VC 183 run 3 (b004501, duplicate-detection warn, no work) → VC 191 (this dispatch) NATIVE FOOTPRINT: 0 prose sentences --- PROMPT #VC 191 | id 9