@rubytech/create-maxy-code 0.1.108 → 0.1.109

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -1
  3. package/payload/platform/plugins/cloudflare/scripts/list-cf-domains.sh +12 -12
  4. package/payload/platform/plugins/cloudflare/scripts/list-cf-domains.ts +9 -43
  5. package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +27 -29
  6. package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +14 -9
  7. package/payload/platform/plugins/docs/references/platform.md +4 -22
  8. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  9. package/payload/platform/plugins/docs/references/troubleshooting.md +4 -316
  10. package/payload/platform/plugins/venture-studio/PLUGIN.md +35 -4
  11. package/payload/platform/plugins/venture-studio/bin/scaffold.sh +104 -0
  12. package/payload/platform/plugins/venture-studio/skills/investor-data-room/SKILL.md +3 -1
  13. package/payload/platform/plugins/work/mcp/dist/cli/project-create-cli.d.ts +2 -0
  14. package/payload/platform/plugins/work/mcp/dist/cli/project-create-cli.d.ts.map +1 -0
  15. package/payload/platform/plugins/work/mcp/dist/cli/project-create-cli.js +78 -0
  16. package/payload/platform/plugins/work/mcp/dist/cli/project-create-cli.js.map +1 -0
  17. package/payload/platform/scripts/vnc.sh +4 -3
  18. package/payload/premium-plugins/venture-studio/PLUGIN.md +35 -4
  19. package/payload/premium-plugins/venture-studio/bin/scaffold.sh +104 -0
  20. package/payload/premium-plugins/venture-studio/skills/investor-data-room/SKILL.md +3 -1
  21. package/payload/server/{chunk-AGFS3TVN.js → chunk-FSPPVVWM.js} +1303 -496
  22. package/payload/server/maxy-edge.js +21 -259
  23. package/payload/server/public/assets/{ChatInput-DJsqm_Gf.js → ChatInput-CsnIedhS.js} +1 -5
  24. package/payload/server/public/assets/{Checkbox-DGZG9BKc.js → Checkbox-CWugFyFT.js} +1 -1
  25. package/payload/server/public/assets/admin-D3gZuyUn.js +217 -0
  26. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Dw16BhiX.js → architectureDiagram-Q4EWVU46-CeTRKWDb.js} +1 -1
  27. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DIOpmf5Y.js → blockDiagram-DXYQGD6D-DeeIX5U3.js} +1 -1
  28. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-Tdb_HZeX.js → c4Diagram-AHTNJAMY-CFsqZuil.js} +1 -1
  29. package/payload/server/public/assets/channel-CrSx5mnG.js +1 -0
  30. package/payload/server/public/assets/{chunk-336JU56O-CebpwDDe.js → chunk-336JU56O-DpIXuFM0.js} +2 -2
  31. package/payload/server/public/assets/{chunk-426QAEUC-BtRCmfDU.js → chunk-426QAEUC-Qk8qqrvA.js} +1 -1
  32. package/payload/server/public/assets/{chunk-4TB4RGXK-BZ3GEWs3.js → chunk-4TB4RGXK-DtM8-CUn.js} +1 -1
  33. package/payload/server/public/assets/{chunk-5FUZZQ4R-iDI6Xu0U.js → chunk-5FUZZQ4R-CrSQ4ySU.js} +1 -1
  34. package/payload/server/public/assets/{chunk-5PVQY5BW-SQD_EpYa.js → chunk-5PVQY5BW-Bn2nQwdj.js} +1 -1
  35. package/payload/server/public/assets/{chunk-EDXVE4YY-CtCcA7_e.js → chunk-EDXVE4YY-CzCPnR0P.js} +1 -1
  36. package/payload/server/public/assets/{chunk-ENJZ2VHE-pXVGVCbb.js → chunk-ENJZ2VHE-CgZj9RoG.js} +1 -1
  37. package/payload/server/public/assets/{chunk-ICPOFSXX-Dkzg9o2N.js → chunk-ICPOFSXX-wy-eNjwW.js} +1 -1
  38. package/payload/server/public/assets/{chunk-OYMX7WX6-1ZZWzf9F.js → chunk-OYMX7WX6-CMmJtL8S.js} +1 -1
  39. package/payload/server/public/assets/{chunk-U2HBQHQK-CpQ3kzO0.js → chunk-U2HBQHQK-CFCW7OaT.js} +1 -1
  40. package/payload/server/public/assets/{chunk-X2U36JSP-C2LkxroC.js → chunk-X2U36JSP-Bgh-CJSN.js} +1 -1
  41. package/payload/server/public/assets/{chunk-YZCP3GAM-Bl5jBOt5.js → chunk-YZCP3GAM-BXKwZ4vN.js} +1 -1
  42. package/payload/server/public/assets/{chunk-ZZ45TVLE-CHtnptPS.js → chunk-ZZ45TVLE-BiOuK5NP.js} +1 -1
  43. package/payload/server/public/assets/classDiagram-6PBFFD2Q-C3IDJsqN.js +1 -0
  44. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BOIrJ5Zb.js +1 -0
  45. package/payload/server/public/assets/clone-P8Fkz7JD.js +1 -0
  46. package/payload/server/public/assets/{dagre-BziN0Nkh.js → dagre-DyCxa9Q2.js} +1 -1
  47. package/payload/server/public/assets/{dagre-KV5264BT-B7OG1g1Y.js → dagre-KV5264BT-Cffo_hmf.js} +1 -1
  48. package/payload/server/public/assets/data-DRfwJPja.js +1 -0
  49. package/payload/server/public/assets/{diagram-5BDNPKRD-Bf31nIDs.js → diagram-5BDNPKRD-Bt93Du3V.js} +1 -1
  50. package/payload/server/public/assets/{diagram-G4DWMVQ6-DQu85hhH.js → diagram-G4DWMVQ6-v4r-tBsC.js} +1 -1
  51. package/payload/server/public/assets/{diagram-MMDJMWI5-5tstbs4y.js → diagram-MMDJMWI5-DKrVPOP-.js} +1 -1
  52. package/payload/server/public/assets/{diagram-TYMM5635--MOV1U4o.js → diagram-TYMM5635-B1PzWQb9.js} +1 -1
  53. package/payload/server/public/assets/{erDiagram-SMLLAGMA-BtAnOJmd.js → erDiagram-SMLLAGMA-ClQzsQAs.js} +1 -1
  54. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CybiCIih.js → flowDiagram-DWJPFMVM-h3IbpN_7.js} +1 -1
  55. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-B44jN7Cy.js → ganttDiagram-T4ZO3ILL-ClaxOJi8.js} +1 -1
  56. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-CT7iYcwg.js → gitGraphDiagram-UUTBAWPF-pM-U4ClD.js} +1 -1
  57. package/payload/server/public/assets/graph-B4FFYwus.js +1 -0
  58. package/payload/server/public/assets/graph-labels-Cpk9Ktt0.js +1 -0
  59. package/payload/server/public/assets/{graphlib-DP4o0pYL.js → graphlib-CwimOv_M.js} +1 -1
  60. package/payload/server/public/assets/{infoDiagram-42DDH7IO-CvxFpFHN.js → infoDiagram-42DDH7IO-DcO3Giwe.js} +1 -1
  61. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-CUwWLPeR.js → ishikawaDiagram-UXIWVN3A-BcdSL5VS.js} +1 -1
  62. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-y-OnGgLi.js → journeyDiagram-VCZTEJTY-CYahHYzf.js} +1 -1
  63. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-BhrSe8R4.js → kanban-definition-6JOO6SKY-Cl5KhoS4.js} +1 -1
  64. package/payload/server/public/assets/lib--yuBd0Xi.js +33 -0
  65. package/payload/server/public/assets/{line-C9uS7z4J.js → line-d_2oTxLp.js} +1 -1
  66. package/payload/server/public/assets/{mermaid-parser.core-Cg4ZdKp-.js → mermaid-parser.core-CMMDGv3x.js} +1 -1
  67. package/payload/server/public/assets/{mermaid.core-BHdKOsex.js → mermaid.core-DK9ENGbr.js} +3 -3
  68. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-NBYiXHo7.js → mindmap-definition-QFDTVHPH-mA3x3MFG.js} +1 -1
  69. package/payload/server/public/assets/page-CgDmg_fX.js +1 -0
  70. package/payload/server/public/assets/{page-D9YpwhIu.js → page-D9lluVl7.js} +2 -2
  71. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CbojC64C.js → pieDiagram-DEJITSTG-CW1nGFlY.js} +1 -1
  72. package/payload/server/public/assets/public-DdLMkNdS.js +7 -0
  73. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CnnoZXcL.js → quadrantDiagram-34T5L4WZ-DI5igJhR.js} +1 -1
  74. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DFRFRtyJ.js → requirementDiagram-MS252O5E-DyVeI4e_.js} +1 -1
  75. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DU5gcpzO.js → sankeyDiagram-XADWPNL6-CCTTBYKY.js} +1 -1
  76. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BN7HZ6Hq.js → sequenceDiagram-FGHM5R23-hVVf35ly.js} +1 -1
  77. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DG6cCjvg.js → stateDiagram-FHFEXIEX-CSLuQDUX.js} +1 -1
  78. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-C5JejhQU.js +1 -0
  79. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-qmV-8SEV.js → timeline-definition-GMOUNBTQ-sxC3W8Q4.js} +1 -1
  80. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BMXQ1s3n.js → vennDiagram-DHZGUBPP-Ro-ton6Z.js} +1 -1
  81. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-CoAdP1Gw.js → wardleyDiagram-NUSXRM2D-T-dKD0Zx.js} +1 -1
  82. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CZlfGTEn.js → xychartDiagram-5P7HB3ND-CfProPts.js} +1 -1
  83. package/payload/server/public/data.html +4 -4
  84. package/payload/server/public/graph.html +5 -5
  85. package/payload/server/public/index.html +7 -7
  86. package/payload/server/public/public.html +4 -4
  87. package/payload/server/server.js +299 -1392
  88. package/payload/platform/plugins/cloudflare/scripts/_stream-log.sh +0 -154
  89. package/payload/server/chunk-BDFOTLPW.js +0 -759
  90. package/payload/server/chunk-JRBCOVA4.js +0 -1305
  91. package/payload/server/cloudflare-task-tracker-M5ONAGUT.js +0 -22
  92. package/payload/server/public/assets/admin-BvzMvMGo.js +0 -217
  93. package/payload/server/public/assets/channel-DThrH4QF.js +0 -1
  94. package/payload/server/public/assets/classDiagram-6PBFFD2Q-BC6oGTNX.js +0 -1
  95. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-COwC5Umh.js +0 -1
  96. package/payload/server/public/assets/clone-Chp7hvnA.js +0 -1
  97. package/payload/server/public/assets/data-BAgaPs4j.js +0 -1
  98. package/payload/server/public/assets/graph-Cma7EArf.js +0 -1
  99. package/payload/server/public/assets/graph-labels-DyKk6Sxf.js +0 -1
  100. package/payload/server/public/assets/lib-CpkYtEDz.js +0 -29
  101. package/payload/server/public/assets/page-B4IWl3aZ.js +0 -1
  102. package/payload/server/public/assets/public-BtOXjy3A.js +0 -8
  103. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CvVd1Q_q.js +0 -1
@@ -184,325 +184,13 @@ If the initial Cloudflare login fails during setup, {{productName}} will fall ba
184
184
 
185
185
  ---
186
186
 
187
- ## Action runner — upgrade or Cloudflare setup appears stuck
188
187
 
189
- replaced the ttyd/xterm admin terminal with a detached action runner. Upgrades and Cloudflare setup now run under transient `systemd-run --user` units whose stdout+stderr land in a persisted per-action log, streamed to the browser via SSE. An earlier fix moved the four routes that serve the modal (`/api/admin/actions/*`, `/api/admin/version`) onto `maxy-edge.service`, so the log panel's stream survives a mid-run restart of `maxy.service` without reconnecting.
188
+ ## Software update and Cloudflare setup
190
189
 
191
- **"Connection lost reconnecting…" banner appears during an upgrade.** On post-Task-666 bundles this should never appear while the upgrade is in flight the routes live on the always-on edge. If you see the banner during steps 8→11 of an upgrade on a current bundle, it is a **regression**, not expected behaviour: the routes have drifted back onto `maxy.service` or the edge's Hono dispatcher is not intercepting them. Check `~/.maxy/logs/edge.log` for `[edge-admin]` entries during the window; absence means the edge never received the request. The prebuild gate `platform/ui/scripts/check-edge-admin-routes.mjs` exists specifically to catch this drift before it ships.
190
+ Both flows run on the native Claude Code PTY surface in admin chat (Task 287). The retired action-runner / terminal-modal troubleshooting sections that lived here have been removed because those surfaces no longer exist; failures now manifest as plain stderr from the agent-invoked Bash command, visible in chat.
192
191
 
193
- **Agent does not respond to any message after a fresh install or restart.** The chat ingress quartet surfaces where the request silently stopped. From admin chat, ask the agent to read the chat-ingress timeline for the last 5 minutes — internally it runs `logs-read.sh --tail chat-attempts 5`, which cross-greps `edge.log` and `server.log` for the four checkpoints (edge inbound, admin-auth verdict, handler entry, edge outcome). Any missing row localises the failure: no edge inbound = request never reached the device (network, DNS, or cloudflare tunnel); inbound present + no auth verdict = handler unreachable (Hono routing regression); auth verdict = reject + a `code=` value the client banner matches; auth = accept + no handler entry = post-auth routing regression; all three rows present + no edge outcome = upstream crash or socket abort. See the developer doc `.docs/web-chat.md#chat-ingress-quartet` for the full state-machine and the prefix taxonomy.
194
-
195
- **Heartbeat stalled** (log panel header shows rising `silent Ns` amber badge).
196
-
197
- - Open the log panel header: `state: <systemd_state>` tells you the unit's current state.
198
- - `systemd_state: active` + silent >30s → the child is running but emitting nothing. Expected for `npx` while it downloads the tarball, or `cloudflared tunnel login` waiting for an operator click.
199
- - `systemd_state: inactive` + no `exit` event → the exit event was missed; the server-side heartbeat timer will emit it on the next 5 s tick.
200
- - `systemd_state: failed` → see the next symptom.
201
-
202
- **`ActiveState=failed`** (log panel's exit banner shows a non-zero code).
203
-
204
- - Read the persisted log directly: `~/.maxy/logs/actions/<actionId>.log` (or `.realagent/...`) has every stdout+stderr line the unit emitted.
205
- - `journalctl --user --identifier=maxy-action-<actionId>` shows systemd's own record including ExecStartPre/ExecStopPost if any.
206
- - Common cases:
207
- - Wrong sudo password → `sudo: 1 incorrect password attempt` near the top of the log; re-open the upgrade modal, enter the correct password.
208
- - Network failure during `npx` → `npm ERR! network` lines; re-open the modal and retry when network is restored.
209
- - `cloudflared tunnel login` timed out waiting for OAuth → action exits non-zero with `Timed out after Ns waiting for cert.pem`; re-trigger from the Cloudflare setup form.
210
-
211
- **"Authorise in Cloudflare" button never appears** (cloudflare-setup action).
212
-
213
- The setup script emits either the raw `https://dash.cloudflare.com/argotunnel?...` URL in cloudflared's own stderr OR an explicit `OAUTH_URL: <url>` stdout line once URL extraction succeeds. The log panel's regex matches either. If neither appears within ~15 s of launch:
214
-
215
- - The action log file (`~/.maxy/logs/actions/<actionId>.log`) should show `[script:setup-tunnel:cloudflared]` lines. No such lines → cloudflared isn't spawning (check whether the binary is on PATH in the transient unit; `systemctl --user show maxy-action-<actionId>` reveals the environment).
216
- - Lines present but no URL → cloudflared output-format drift; file a task with the last 20 lines of the action log.
217
-
218
- **Log file missing (action stream returns 404).**
219
-
220
- The transient unit was auto-collected by systemd before the client subscribed. Race condition: action finished in <1 s. The per-action log file is retained for 7 days; look for it by name under `~/.maxy/logs/actions/`. If it isn't there, the unit failed before any output (check `journalctl --user -u maxy-action-<id>`).
221
-
222
- **Cloudflare-setup action card shows "Failed (exit null)" after the tunnel works.**
223
-
224
- > **Pre-Task-860 misdiagnosis.** Devices on platform versions misrender a successful `cloudflare-setup` run as red `Failed (exit null) · ~20s` because the script-armed brand-service restart kills the SSE generator before it can read the action's exit code. The Cloudflare side is fine in this case — the tunnel is created, DNS is routed, the brand service comes back up.
225
- >
226
- > **First-line check:** open the persisted action log directly. Two markers prove success:
227
- >
228
- > ```bash
229
- > grep -E 'step=service-restart-armed exit=0|step=done' \
230
- > ~/.{configDir}/logs/actions/cloudflare-setup-*.log | tail -2
231
- > ```
232
- >
233
- > Both lines present in the log ⇒ the script succeeded; the UI banner is the bug, not the run. On post-Task-860 platforms the action card renders `Completed · Ns` on the same log shape; the card now distinguishes four states:
234
- >
235
- > - `Completed` (green) — `code === 0` (whether reported by systemd or recovered from the log).
236
- > - `Failed (exit N)` (red) — non-zero exit reported by systemd. Real failure, follow the existing remediation paths.
237
- > - `Restart in progress` (neutral sage) — arming line present in log but the post-arm `step=done` was not written before the unit was GC'd. Resolves automatically once `/api/admin/version` responds; if it stays >90 s, falls through to amber.
238
- > - `Failed (exit unobserved)` (amber) — neither systemd nor the log can confirm a terminal state. Check `journalctl --user -u maxy-action-<id>`; the unit failed early or the log was truncated.
239
- >
240
- > The server emits `[action-runner] reconcile actionId=<id> result=<succeeded|failed|restart-in-progress|unresolved> source=<systemd|persisted-log> ms=<n>` once per terminal-state resolution. Missing reconcile line on a finished run = stale platform; upgrade.
241
-
242
- **Cloudflare-setup auto-relays "completed" but the next chat turn 502s.**
243
-
244
- The current contract is a single client-driven resume: when the setup script exits cleanly, the form fires a resume event, the chat hook waits for `/api/health` to fail then succeed (the brand-service down-then-up cycle), re-binds the conversation to the new server process, and sends the "completed" marker as a normal hidden chat POST that re-invokes the agent in the operator's real session. No relay queue, no boot-drain, no banner.
245
-
246
- Diagnostic recipe:
247
-
248
- ```
249
- grep '\[admin-resume\] reason=post-restart' ~/.maxy/logs/server.log | tail # /resume server-side
250
- grep '\[session\] cookie-bridge accountId=' ~/.maxy/logs/server.log | tail # session re-hydrated
251
- grep '\[persist\] .* role=user .* Cloudflare setup completed' ~/.maxy/logs/server.log | tail
252
- grep '\[client-event\] kind=post-restart-resume' ~/.maxy/logs/server.log | tail
253
- ```
254
-
255
- Failure modes:
256
- - `[client-event] kind=post-restart-resume phase=start` absent: form's CustomEvent never reached the chat hook (regression in form `onExit` or chat-listener mount).
257
- - `[client-event] phase=start` present, `[admin-resume] reason=post-restart` absent: `waitForRestartCycle` exhausted its bound (brand never restarted) or `/resume` rejected — check `phase=health-timeout` / `phase=resume-rejected`.
258
- - All four present except `[persist] role=user … Cloudflare setup completed`: marker chat POST failed — check the chat surface for an inline error or a `phase=resume-error` line.
259
- - Refresh after a successful Cloudflare setup shows a visible `Cloudflare setup completed (actionId: …)` user bubble: the resume mappers' synthetic-marker suppression broke or the marker shape drifted. Server-side `[admin-resume] syntheticHidden=<n>` field on the same line counts user rows the client should hide (`_componentDone` envelopes, `_lifecycle` envelopes, and the `Cloudflare setup completed (actionId: …)` literal) — a count of 0 against a refresh that should have hidden one means the helper at `platform/ui/app/lib/synthetic-marker.ts` no longer recognises the producing literal (check `CloudflareSetupForm.tsx` and `useAdminChat.ts` for shape drift).
260
-
261
- ---
262
-
263
- ## Software Update click shows an error instead of opening the terminal
264
-
265
- > **First-line diagnostic for the byte-stream xterm.js terminal surface:** `sudo systemctl --user status maxy-ttyd` plus `sudo grep 'ttyd-proxy' ~/.maxy/logs/edge-boot.log | tail -20`. Failure mode signals: `ttyd-ws-upgrade accepted` with no `ttyd-proxy-open` → `maxy-ttyd.service` is down; `ttyd-proxy-open` with no `ttyd-proxy-chunk dir=upstream→client` → ttyd/tmux is not attaching a PTY.
266
-
267
- **Symptom:** You clicked **Upgrade** in the Software Update modal, but instead of the VNC terminal overlay appearing, the modal shows a red error row like:
268
-
269
- ```
270
- [terminal-launch] failed err="window absent from target display after spawn" pid=1234 display=:99 observed_windows=0 transport=vnc reason=upgrade
271
- ```
272
-
273
- …and the Upgrade button re-labels to "Try again".
274
-
275
- **What it means:** `POST /api/admin/terminal/launch-upgrade` returned a 502 — the admin server tried to spawn a real terminal on the VNC display `:99` with `npx -y @rubytech/create-maxy@latest` pre-loaded, but the spawn failed or the window never appeared on the target display. The modal's upgrade path uses the same pipeline as the header-menu Terminal; if the operator Terminal button works, the VNC stack itself is healthy and the fault is usually a missing dep or a stale binary. If the operator Terminal also fails, start with the "Header Terminal click shows an error alert" section below.
276
-
277
- Step-by-step diagnosis — the error string in the modal is identical to the entry in `~/.maxy/logs/vnc-boot.log`, so you can grep it directly:
278
-
279
- ```bash
280
- # 1. Find the latest upgrade launch attempt
281
- sudo grep 'action=launch-upgrade' ~/.maxy/logs/vnc-boot.log | tail -10
282
-
283
- # 2. See the script-level failure line (same string the modal shows)
284
- sudo tail -n 30 ~/.maxy/logs/terminal-launch.log
285
-
286
- # 3. Verify binaries are present
287
- which xterm xdotool
288
-
289
- # 4. Confirm the VNC display itself is up
290
- DISPLAY=:99 xdpyinfo >/dev/null 2>&1 && echo "display:99 ok" || echo "display dead"
291
- ```
292
-
293
- **Common upgrade-specific failures:**
294
-
295
- - `err="no terminal emulator installed"` → run `sudo apt-get install -y xterm xdotool` or re-run `npx -y @rubytech/create-maxy@latest` — the installer provisions both as hard deps.
296
- - `err="spawn detached but no terminal PID visible within 1s"... reason=upgrade` → X server on `:99` is wedged. the VNC stack is owned by `maxy-edge`, so the recovery is `sudo systemctl --user restart maxy-edge` (cycles `vnc.sh start` via that unit's ExecStartPre). Then click **Try again** in the modal.
297
- - `err="window absent from target display after spawn"... reason=upgrade` → the spawn succeeded but landed on the wrong display (earlier platform fixes class). Re-run the installer to refresh the `resolve_terminal_bin` logic. If a stale `gnome-terminal` is hitting `:99` via D-Bus delegation, the installer's `xterm` fallback is the fix.
298
- - `err="xdotool not installed — re-run installer to repair"` → earlier platform fixes preflight. `sudo apt-get install -y xdotool` or re-run the installer.
299
- - `err="VNC failed to start after recovery attempt"` → `Xtigervnc` itself is not coming up. Inspect `~/.maxy/logs/vnc-boot.log` for tigervnc startup lines; `ss -ltn '(sport = 6080 or sport = 5900)'` should show both ports listening.
300
-
301
- **Click Try again** after applying any fix — the modal re-POSTs the launch-upgrade request.
302
-
303
- ---
304
-
305
- ## Upgrade terminal stays black after clicking Upgrade (VNC WebSocket rejected)
306
-
307
- **Symptom:** The launch-upgrade POST returns 200 (the server-side spawn succeeded), but the browser's VNC iframe shows a black rectangle and the DevTools console spins on `WebSocket connection to '/websockify' failed` / `Connection closed (code: 1006)` every few seconds.
308
-
309
- **What it means:** The browser has a session cookie the `/websockify` auth gate refuses to accept., every rejection logs three fields that identify the failing layer:
310
-
311
- ```bash
312
- sudo tail -200 ~/.maxy/logs/vnc-boot.log | grep 'decision="rejected"'
313
- ```
314
-
315
- - `cookieHeaderPresent=false` → the browser never sent a cookie. Check the iframe context / SameSite policy / cookie domain. Most commonly: the user opened admin over HTTP instead of HTTPS, or the cookie is scoped to a different subdomain.
316
- - `cookieHeaderPresent=true tokenPresent=false` → the cookie is present but the server rejects its signature. This is either tampering or a corrupted/missing shared secret. Check that `~/.maxy/credentials/remote-session-secret` exists on disk (mode `0600`, 64 hex chars) and has not been recently overwritten.
317
- - `tokenExpired=true` → the 24h session TTL elapsed. Log in again.
318
-
319
- If the secret file is missing entirely, re-run `npx -y @rubytech/create-maxy@latest` — the installer provisions it idempotently, preserving an existing file on upgrade and creating a fresh one on first install.
320
-
321
- ---
322
-
323
- ## Upgrade terminal opens but npx never runs
324
-
325
- **Symptom:** You clicked **Upgrade**, the VNC overlay opened with a visible shell prompt, but `npx -y @rubytech/create-maxy@latest` does not execute and the shell is idle.
326
-
327
- **What it means:** The VNC spawn succeeded but the binary-specific command dispatcher (xterm `-e` or gnome-terminal `--`) did not forward the command. Given the installer ships `xterm` on `:99` by default (with D-Bus-safe dispatching), the likely causes are:
328
-
329
- - A stale binary override has re-pointed `resolve_terminal_bin` to `gnome-terminal` on `:99` despite the fix.
330
- - A shell the operator manually spawned (via the header Terminal) wasn't killed before the upgrade click, and `ensureTerminalUpgrade`'s pre-kill step silently failed.
331
-
332
- **Check:**
333
-
334
- ```bash
335
- # The spawned binary must appear in this log with the bash-c wrapper
336
- sudo grep 'started.*reason=upgrade' ~/.maxy/logs/terminal-launch.log | tail -3
337
- # Expected shape: started pid=<N> display=:99 cmd="/usr/bin/xterm... -e bash -c 'npx -y @rubytech/create-maxy@latest; exec bash'" transport=vnc windowPresent=true reason=upgrade
338
- ```
339
-
340
- If the `cmd=` field does not contain `-e bash -c`, re-run the installer — the vnc.sh on the device is stale. If the command IS logged correctly but nothing is running, open the VNC overlay and type `history | tail` inside the shell — if the npx line is there, it ran and exited (check `~/.maxy/logs/install-*.log` for the exit status).
341
-
342
- ---
343
-
344
- ## Header Terminal click shows an error alert
345
-
346
- **Symptom:** You opened the burger menu and clicked **Terminal**, but instead of the overlay appearing you got an inline error like "Terminal failed to start" or "VNC failed to start".
347
-
348
- **What it means:** `POST /api/admin/terminal/launch` returned a 502 — either the VNC stack on port 5900 is down or the terminal emulator could not be spawned on display `:99`. This is a VNC-stack or display-spawn failure.
349
-
350
- Step-by-step diagnosis:
351
-
352
- ```bash
353
- # 1. Check the terminal-launch log for the specific failure reason
354
- sudo tail -n 50 ~/.maxy/logs/terminal-launch.log
355
-
356
- # 2. Check the node-side state machine (ensure-terminal entries)
357
- sudo grep ensure-terminal ~/.maxy/logs/vnc-boot.log | tail -20
358
-
359
- # 3. Verify the VNC display itself is healthy
360
- sudo ~/maxy/platform/scripts/vnc.sh status # should print "running"
361
- DISPLAY=:99 xdpyinfo >/dev/null 2>&1 && echo "display ok" || echo "display dead"
362
-
363
- # 4. Confirm a terminal binary is installed (xterm is the always-available fallback)
364
- which gnome-terminal; which xterm
365
- ```
366
-
367
- Most common failures and fixes:
368
-
369
- - `[terminal-launch] failed err="no terminal emulator installed"` → run `sudo apt-get install -y xterm xdotool` (or re-run the installer, which installs both as dependencies).
370
- - `[terminal-launch] failed err="spawn detached but no terminal PID visible within 1s"` → X server on `:99` is wedged. `sudo systemctl --user restart maxy-ui` cycles the VNC stack via `vnc.sh start`.
371
- - `[terminal-launch] failed err="window absent from target display after spawn" pid=<N> display=:99 observed_windows=0` → the spawned emulator's window landed on the wrong display (earlier platform fixes — almost always a stale gnome-terminal binary on an upgraded install; the fix ships `xterm` as the `:99` default but a stale `resolve_terminal_bin` on an old bundle can still trigger it). Check `which gnome-terminal xterm xdotool` — all three should exist; if not, re-run the installer. Also check `DISPLAY=:99 xdotool search --onlyvisible --class '.'` manually: empty output confirms no window on `:99`; a non-empty result after a fresh click means the window IS there and the check itself is wrong (file an issue).
372
- - `ensure-terminal action="escalate-vnc-restart"` followed by `degraded` → `Xtigervnc` itself is not coming up. Check `~/.maxy/logs/vnc-boot.log` for the tigervnc startup lines.
373
-
374
- ## Terminal fails after upgrade — `Invalid response` or `window absent from target display`
375
-
376
- **Symptom:** You upgraded a {{productName}} device and the header-menu **Terminal** click now fails — overlay shows `Invalid response`, or `terminal-launch.log` shows `[terminal-launch] failed err="window absent from target display after spawn" pid=<N> display=:99 observed_windows=0 transport=vnc cmd="/usr/bin/xterm "`. The terminal worked on the previous version and the upgrade reported success.
377
-
378
- **What it means:** The installer declared a new apt dep between versions (e.g. `xdotool` in 1.0.667), but on your device the installer's apt step was silently skipped because `sudo` requires a password and the installer could not escalate non-interactively. The declared dep was never installed, and `vnc.sh check_window_on_display` then either failed to find the binary (exit 127 now surfaces this as a distinct `failed err="xdotool not installed — re-run installer to repair"` line) or reached the `window absent` path because its preflight tool was missing. See `.docs/deployment.md` ("sudo interactivity contract") for the full mechanism.
379
-
380
- **Check:**
381
-
382
- ```bash
383
- dpkg -s xdotool 2>&1 | head -2 # should report "Status: install ok installed"
384
- which xdotool # should return /usr/bin/xdotool
385
- ```
386
-
387
- **Fix — two options:**
388
-
389
- 1. **Re-run the installer from an interactive shell** (preferred on upgrade — picks up any future missing deps too):
390
-
391
- ```bash
392
- npx -y @rubytech/create-maxy@latest
393
- ```
394
-
395
- The installer now probes `dpkg -s` for every declared apt dep and either prompts you for your sudo password to install missing ones, or loud-fails non-interactively with the exact `sudo apt-get install -y <list>` command to repair. It will no longer print `Skipping apt-get (deps assumed present from prior install)` and continue as if green.
396
-
397
- 2. **Repair manually** (faster if you only want the one binary):
398
-
399
- ```bash
400
- sudo apt-get install -y xdotool
401
- ```
402
-
403
- Then click **Terminal** again — it should spawn within a second and the overlay should render the xterm.
404
-
405
- **Regression boundary:** if you see `[terminal-launch] failed err="xdotool not installed — re-run installer to repair"` in `~/.maxy/logs/terminal-launch.log`, the vnc.sh preflight is telling you the binary is missing before spawn — same class as above, distinct from the earlier platform fixes `window absent from target display after spawn` string. The two strings never appear for the same click.
406
-
407
- ---
408
-
409
- ## Installer aborts on Ubuntu 24.04 with `dpkg -s: chromium`
410
-
411
- **Symptom:** On a fresh (or re-run) `npx -y @rubytech/create-maxy@latest` on an Ubuntu 24.04 Noble laptop/desktop, step 1/12 aborts:
412
-
413
- ```
414
- [1/12] System dependencies and network...
415
- Missing apt deps (1): chromium
416
- apt install (VNC stack): tigervnc-standalone-server python3-websockify novnc xdg-utils chromium xterm xdotool
417
- > sudo apt-get install -y... chromium...
418
- OK in 0.3s
419
- [ERROR] Setup failed: apt-get install (VNC stack) returned 0 but packages are still not installed per dpkg -s: chromium
420
- ```
421
-
422
- Directly probing the device shows `dpkg -s chromium` non-zero, `apt-cache policy chromium` reports `Candidate: (none)`, but `/usr/bin/chromium` exists and works, and `snap list chromium` shows the snap is installed.
423
-
424
- **What it means:** You are on a **pre-637 installer**. On Noble, `chromium` is a virtual package aliasing to `chromium-browser` — `apt-get install chromium` succeeds silently but nothing named `chromium` ever lands in dpkg's state DB. the post-install probe (correctly) notices the discrepancy and aborts. An earlier fix added alias resolution (`chromium` → `chromium-browser`) so the probe matches the dpkg-recorded name and passes.
425
-
426
- **Fix:** Upgrade to a post-637 version of `@rubytech/create-maxy`:
427
-
428
- ```bash
429
- npx -y @rubytech/create-maxy@latest
430
- ```
431
-
432
- **Manual bypass** (if you must install before 637 publishes, or if you're on a restricted shell): pre-install the real.deb name and re-run the installer.
433
-
434
- ```bash
435
- sudo apt-get install -y chromium-browser
436
- npx -y @rubytech/create-maxy@latest
437
- ```
438
-
439
- The installer's resolver will then see `dpkg -s chromium-browser` exit 0 for the alias target, filter `chromium` out of the missing set, and skip the apt-install branch entirely. Raspberry Pi OS (Debian 12 Bookworm) is unaffected — `chromium` IS a concrete.deb on Bookworm.
440
-
441
- **Deeper diagnostic**: post-637 installer logs carry the full classification in the error message itself — `(resolved-name=<name>, apt-cache-policy=<summary>, command-v=<path>, snap-status=<summary>)`. If you see that longer form and still fail, the apt state itself is inconsistent (snap removed, `chromium-browser` uninstalled after previous install) — repair with `sudo apt-get install --reinstall -y chromium-browser`.
442
-
443
- ---
444
-
445
- ## VNC browser will not start on Linux laptop — `Permission denied (13)` on SingletonLock
446
-
447
- **Symptom:** Boot log `~/.{brand}/logs/vnc-boot.log` shows:
448
-
449
- ```
450
- Starting Chromium on :<vncDisplay> (vnc) profile=/home/<user>/.{brand}/chromium-profile CDP=:<cdpPort>
451
- ERROR:chrome/browser/process_singleton_posix.cc:345] Failed to create
452
- /home/<user>/.{brand}/chromium-profile/SingletonLock: Permission denied (13)
453
- ERROR: Chromium failed to start on :<vncDisplay> (vnc) — CDP port <cdpPort> not listening (browser-specialist degraded)
454
- ```
455
-
456
- `dmesg` (or `journalctl -k`) shows AppArmor `DENIED` lines naming `profile="snap.chromium.chromium"` and the `~/.{brand}/chromium-profile/` path. The brand admin chat reports the public-agent VNC browser as unavailable.
457
-
458
- **What it means:** Your `/usr/bin/chromium` is a snap symlink. Snap's AppArmor profile excludes hidden top-level paths under `$HOME` from its `home` interface, so writes to per-brand Chromium profile dirs at `~/.maxy/chromium-profile/` and `~/.realagent/chromium-profile/` are denied — Chromium cannot create its `SingletonLock` and never starts the CDP listener. This is exclusively a Linux-laptop problem (Ubuntu Noble); Raspberry Pi OS Bookworm ships `chromium` as a real `.deb` and is unaffected.
459
-
460
- **Fix:** Re-run the installer at version 1.0.849 or later. The installer detects the snap-confined chromium during system-dependency setup and replaces it with Google Chrome stable from Google's signed apt repo:
461
-
462
- ```bash
463
- npx -y @rubytech/create-maxy@latest
464
- ```
465
-
466
- The resolved non-snap binary path is recorded at `<INSTALL_DIR>/platform/config/chromium-binary.path` (single line) and read by every Chromium call site (VNC service, in-page wrapper, Playwright server). After re-running, verify with the bundled acceptance script:
467
-
468
- ```bash
469
- MAXY_PLATFORM_ROOT=$HOME/<install-dir>/platform $HOME/<install-dir>/platform/scripts/test-laptop-vnc-boot.sh
470
- ```
471
-
472
- The script exits 0 only when (1) the configured Chromium realpath is non-snap, (2) the path is absolute and executable, (3) the per-brand CDP port returns Chromium version JSON, and (4) `vnc-boot.log` since the last `[vnc.sh] start` ends with `VNC + browser stack running` and contains no `Chromium failed to start` line.
473
-
474
- **Deeper diagnostic:** `vnc.sh` and the in-page wrapper now refuse to start (and exit with a snap-Chromium reference in the boot log) when `chromium-binary.path` is absent or its realpath lands under `/snap/`. If you see those messages, the install completed before the fix shipped — re-run `npx -y @rubytech/create-maxy@latest`. Manual workaround for an emergency (not a fix): `sudo apt-get install -y google-chrome-stable` and confirm `which google-chrome-stable` is non-snap, then re-run the installer to write `chromium-binary.path`.
475
-
476
- ---
477
-
478
- ## Terminal iframe renders black and cursor vanishes over the canvas
479
-
480
- **Symptom:** Header-menu Terminal click appears to succeed — no error toast, overlay opens — but the iframe renders uniformly black, keystrokes do not reach any shell, and the mouse cursor disappears the moment it enters the iframe (visible elsewhere in the page).
481
-
482
- **What it means:** This is the exact symptom class that earlier platform fixes closed. Before 632, `/usr/bin/gnome-terminal` would receive `DISPLAY=:99` but D-Bus-delegate the window-create request to the session's `gnome-terminal-server`, which opens the window on `:0` (the operator's physical screen) instead. The iframe, rendering `:99`, has no window to show — hence the black canvas, dead keystrokes, and null-cursor (noVNC's Cursor pseudo-encoding renders `cursor: none` when the server sends no cursor). If you are seeing this *after* earlier platform fixes shipped, the installer did not run on this device or a stale bundle is in place.
483
-
484
- Step-by-step diagnosis:
485
-
486
- ```bash
487
- # 1. Check terminal-launch.log for the window-absent failure
488
- sudo grep 'window absent from target display' ~/.maxy/logs/terminal-launch.log | tail -5
489
-
490
- # 2. Verify the expected binaries are installed
491
- which xterm xdotool # both must exist — installer adds them
492
-
493
- # 3. Confirm the VNC display is serving the iframe
494
- DISPLAY=:99 xdpyinfo >/dev/null 2>&1 && echo "display:99 ok"
495
- DISPLAY=:99 xdotool search --onlyvisible --class '.' # non-empty means windows ARE on:99
496
-
497
- # 4. Check which binary resolve_terminal_bin chose
498
- grep 'cmd=' ~/.maxy/logs/terminal-launch.log | tail -3
499
- # Expected for remote-origin clicks: cmd="/usr/bin/xterm"
500
- # If you see: cmd="/usr/bin/gnome-terminal --wait" on:99 → stale bundle, re-run installer
501
- ```
502
-
503
- If the failure log shows `window absent from target display`, the fix already ran but spawn still went to the wrong display — re-run the installer (`npx -y @rubytech/create-maxy@latest`) from a shell to pick up the latest `xterm` + `xdotool` preflight. If the failure log shows no recent entries and the iframe is still black, check `ss -ltn '(sport = 6080 or sport = 5900)'` and `pgrep -af Xtigervnc|websockify` — the symptom might be a VNC-stack regression rather than a terminal-binary mismatch.
504
-
505
- Both the header Terminal and the Software Update modal's Upgrade button now share the same VNC spawn pipeline, so a failure in one usually reproduces in the other — if the header Terminal opens a blank shell cleanly but the Upgrade modal errors, the problem is upgrade-specific (see "Software Update click shows an error" above).
192
+ - **Software update.** Re-run `npx -y @rubytech/create-<brand>@latest` from a shell; if the installer fails, its stdout is the diagnostic record. HeaderMenu turns sage when `installed === latest`.
193
+ - **Cloudflare setup.** The agent invokes `~/setup-tunnel.sh` via Bash. Failures surface as the script's own `[setup-tunnel] step=… result=error reason=…` lines in chat plus a non-zero exit. Recovery paths live in the cloudflare plugin's `references/reset-guide.md` and `references/manual-setup.md`.
506
194
 
507
195
  ## Orphan Account Directory Archived to `.trash/`
508
196
 
@@ -23,13 +23,44 @@ Outcome (binding):
23
23
 
24
24
  Constraint (binding): **No downstream venture-studio skill (`brand-pack`, `zero-to-prototype`, `investor-data-room` Stages 3+, etc.) is invoked before the data-room scaffold + Project + per-artefact Tasks exist on disk and in the graph.** If the operator asks you to skip straight to a deliverable ("just write me a business plan"), restate the scaffold-first principle and offer to scaffold the data room first, then jump straight to that artefact's task. The principle is the outcome contract; the scaffold proves it.
25
25
 
26
+ ### Deterministic pre-flight gate
27
+
28
+ Before invoking any downstream skill, both checks below must pass. Both are deterministic — exit-code on `ls`, structured output on `project-list`. Neither check depends on LLM judgement.
29
+
30
+ 1. **Directory check:** `[ -d "${PROJECT_ROOT}/.docs/data-room/01-narrative" ]` returns exit 0.
31
+ 2. **Graph check:** the `project-list` tool returns a Project whose `name` matches the business's working name.
32
+
33
+ If either check fails, run the scaffolding script (see below) before the skill fires. If the script fails, surface the literal stderr error to the operator — do not narrate around it (memory: [[feedback_no_stdout_parsing_for_control_flow]]).
34
+
35
+ ### Scaffolding script
36
+
37
+ `bin/scaffold.sh` is the deterministic enforcement layer. It creates the Project + eight artefact Tasks (via the work plugin's `project-create-cli` bridge) and materialises the ten-section directory tree. Graph write first, directories second; idempotent re-run if any partial state lands.
38
+
39
+ ```bash
40
+ ACCOUNT_ID="${ACCOUNT_ID}" \
41
+ premium-plugins/venture-studio/bin/scaffold.sh \
42
+ "${PROJECT_ROOT}" \
43
+ "${BUSINESS_NAME}"
44
+ ```
45
+
46
+ The script is the binding check, not the prose principle above. The prose explains why; the script is what makes it true.
47
+
26
48
  ## First-conversation routing
27
49
 
28
- When the operator first invokes this agent, confirm the intent ("Are we founding a new business, or working on an existing one?") and run the scaffolding sequence:
50
+ When the operator first invokes this agent, confirm the intent ("Are we founding a new business, or working on an existing one?") and run the scaffolding script — it does steps 1–3 below in a single atomic invocation:
51
+
52
+ ```bash
53
+ ACCOUNT_ID="${ACCOUNT_ID}" \
54
+ premium-plugins/venture-studio/bin/scaffold.sh \
55
+ "${PROJECT_ROOT}" \
56
+ "${BUSINESS_NAME}"
57
+ ```
58
+
59
+ The script's three effects:
29
60
 
30
- 1. **Scaffold the data room.** Invoke the `investor-data-room` skill Stage 2 — it creates the ten-section graph under the operator's project root (`<project-site>/.docs/data-room/`). The tree is named upfront so every artefact has a slot to land in.
31
- 2. **Create the `Project` node.** Use the `projects` plugin's `project-create` tool with tier `full` (data-room work is multi-phase). Project name is the business's working name; description references the data-room root path. The `project-create` call accepts a work-items list — pre-seed it with the artefact tasks below in one transaction.
32
- 3. **Enumerate Tasks per artefact**, one per data-room section / output document, in section order. Suggested task list (the `project-create` tool accepts these as `workItems`):
61
+ 1. **Scaffolds the data room.** Materialises the ten-section directory tree under `<project-root>/.docs/data-room/`. Every artefact has a slot to land in before any artefact is produced.
62
+ 2. **Creates the `Project` node.** Tier `full` (data-room work is multi-phase). Project name is the business's working name; description references the data-room root path.
63
+ 3. **Enumerates the eight artefact Tasks** in section order one transaction, atomic with the Project. The work-item list the script pre-seeds:
33
64
  - **Stage 1 — Office-hours design doc** → produces `01-narrative/office-hours-design.md` (skill: `office-hours`)
34
65
  - **Brand pack** → produces brand identity files into `06-product-ip/brand/` (skill: `brand-pack`)
35
66
  - **Stage 2 — Wedge validation + landing page + PRD** → produces `01-narrative/{PMF, LANDING, PRD}.md` (skill: `zero-to-prototype`)
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env bash
2
+ # Venture-studio data-room scaffold — deterministic enforcement of the
3
+ # scaffold-first principle (Task 286 + feedback_doctrine_paragraph_is_not_a_gate).
4
+ #
5
+ # Creates exactly one Project (with eight pre-seeded artefact Tasks) in
6
+ # the graph, then materialises the ten-section data-room directory tree
7
+ # on disk. The venture-studio agent's downstream skills are gated on
8
+ # both signals existing — see venture-studio/PLUGIN.md.
9
+ #
10
+ # Order of operations: graph write first, directories second. The CLI's
11
+ # duplicate-name guard makes the script safely re-runnable after any
12
+ # partial failure: a second run finds the existing Project, returns its
13
+ # id, and retries the mkdir step.
14
+ #
15
+ # Usage:
16
+ # ACCOUNT_ID=<uuid> scaffold.sh <project-root> <business-name>
17
+ #
18
+ # Exit codes:
19
+ # 0 scaffold complete (or already existed)
20
+ # 2 bad arguments / missing ACCOUNT_ID
21
+ # 1 graph write failed, directory mkdir failed, or CLI binary missing
22
+
23
+ set -euo pipefail
24
+
25
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
26
+ # Deployed layout per packages/create-maxy-code/scripts/bundle.js:
27
+ # <install>/premium-plugins/venture-studio/bin/scaffold.sh
28
+ # <install>/platform/plugins/work/mcp/dist/cli/project-create-cli.js
29
+ CLI_BIN="${SCRIPT_DIR}/../../../platform/plugins/work/mcp/dist/cli/project-create-cli.js"
30
+
31
+ if [[ $# -ne 2 ]]; then
32
+ echo "scaffold.sh: usage: ACCOUNT_ID=<uuid> $0 <project-root> <business-name>" >&2
33
+ exit 2
34
+ fi
35
+
36
+ PROJECT_ROOT="$1"
37
+ BUSINESS_NAME="$2"
38
+
39
+ if [[ -z "${ACCOUNT_ID:-}" ]]; then
40
+ echo "scaffold.sh: ACCOUNT_ID env var required" >&2
41
+ exit 2
42
+ fi
43
+
44
+ if [[ ! -d "$PROJECT_ROOT" ]]; then
45
+ echo "scaffold.sh: project root does not exist: $PROJECT_ROOT" >&2
46
+ exit 2
47
+ fi
48
+
49
+ if [[ ! -f "$CLI_BIN" ]]; then
50
+ echo "scaffold.sh: project-create CLI not built or missing at: $CLI_BIN" >&2
51
+ exit 1
52
+ fi
53
+
54
+ DATA_ROOM="${PROJECT_ROOT}/.docs/data-room"
55
+
56
+ # Eight pre-seeded artefact tasks — order and names match
57
+ # premium-plugins/venture-studio/PLUGIN.md § First-conversation routing.
58
+ # Section order is preserved so the agent can walk them sequentially.
59
+ PAYLOAD=$(cat <<JSON
60
+ {
61
+ "accountId": "${ACCOUNT_ID}",
62
+ "name": "${BUSINESS_NAME}",
63
+ "description": "Venture-studio data room for ${BUSINESS_NAME}. Root: ${DATA_ROOM}",
64
+ "tier": "full",
65
+ "workItems": [
66
+ {"name": "Stage 1 — Office-hours design doc", "description": "Produces 01-narrative/office-hours-design.md via the office-hours skill."},
67
+ {"name": "Brand pack", "description": "Produces brand identity (palette, typography, logo) into 06-product-ip/brand/ via the brand-pack skill."},
68
+ {"name": "Stage 2 — Wedge validation + landing page + PRD", "description": "Produces 01-narrative/{PMF,LANDING,PRD}.md via the zero-to-prototype skill."},
69
+ {"name": "Stage 3 — Business plan", "description": "Produces 01-narrative/business-plan.md via investor-data-room Stage 3."},
70
+ {"name": "Stage 3b — Term sheet", "description": "Produces html/prospectus/term_sheet.html via investor-data-room Stage 3b."},
71
+ {"name": "Stage 4 — Deck blueprint", "description": "Produces 01-narrative/deck-blueprint.md via investor-data-room Stage 4."},
72
+ {"name": "Stage 4b — Prospectus", "description": "Produces html/prospectus/index.html via investor-data-room Stage 4b."},
73
+ {"name": "Stage 5 — Rendered PDFs", "description": "Produces html/{business-plan,prospectus,deck}/*.pdf via investor-data-room Stage 5."}
74
+ ]
75
+ }
76
+ JSON
77
+ )
78
+
79
+ # Graph write first. CLI returns {projectId, existing:bool} on stdout;
80
+ # on any failure it exits non-zero with a literal stderr message that
81
+ # propagates here verbatim — no prose-parsing for control flow
82
+ # (memory: feedback_no_stdout_parsing_for_control_flow).
83
+ RESULT=$(node "$CLI_BIN" "$PAYLOAD")
84
+ echo "scaffold.sh: project-create CLI returned: $RESULT"
85
+
86
+ # Directories second. The agent's pre-flight gate keys on the existence
87
+ # of 01-narrative/ (it AND-checks with project-list); creating it last
88
+ # means partial state (graph-only) is naturally invisible to the gate
89
+ # until mkdir succeeds.
90
+ for section in \
91
+ 01-narrative \
92
+ 02-corporate-legal \
93
+ 03-cap-table \
94
+ 04-financials \
95
+ 05-team \
96
+ 06-product-ip \
97
+ 07-customers \
98
+ 08-market \
99
+ 09-traction-metrics \
100
+ 10-supporting; do
101
+ mkdir -p "${DATA_ROOM}/${section}"
102
+ done
103
+
104
+ echo "scaffold.sh: data-room scaffolded at ${DATA_ROOM}"
@@ -96,7 +96,9 @@ This file is the working substrate. It stays internal-only. Every later artefact
96
96
 
97
97
  ## Stage 2 — Data room scaffold
98
98
 
99
- Build the directory tree above. Each section gets a `README.md` that doubles as a content checklist (purpose, expected contents, current state, gaps). The graph structure is fixed: ten numbered sections (`01-narrative` through `10-supporting`) plus a top-level README and an `html/` subdirectory for rendered deliverables.
99
+ When invoked under the venture-studio agent, scaffolding is done by the deterministic script at `premium-plugins/venture-studio/bin/scaffold.sh` it creates the Project + eight artefact Tasks and the ten-section directory tree in one atomic invocation. The script is idempotent; re-runs against an existing data room are a no-op. See `venture-studio/PLUGIN.md` § "Scaffolding script".
100
+
101
+ When invoked outside the venture-studio agent (standalone usage of this skill), build the directory tree manually. Each section gets a `README.md` that doubles as a content checklist (purpose, expected contents, current state, gaps). The graph structure is fixed: ten numbered sections (`01-narrative` through `10-supporting`) plus a top-level README and an `html/` subdirectory for rendered deliverables.
100
102
 
101
103
  **File-naming conventions:**
102
104
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=project-create-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-create-cli.d.ts","sourceRoot":"","sources":["../../src/cli/project-create-cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,78 @@
1
+ // CLI bridge for shell scripts that need to scaffold a Project + Tasks
2
+ // atomically (e.g. premium-plugins/venture-studio/bin/scaffold.sh). The
3
+ // scaffold script is the deterministic enforcement layer for the
4
+ // venture-studio scaffold-first principle (see Task 286 +
5
+ // feedback_doctrine_paragraph_is_not_a_gate); to remain deterministic it
6
+ // must invoke a single binary, not narrate intent for the LLM. This CLI
7
+ // is that binary.
8
+ //
9
+ // Contract:
10
+ // node project-create-cli.js '<json-payload>'
11
+ // payload: { accountId, name, description, tier, workItems[], createdBy }
12
+ // exit 0 + stdout JSON { projectId, existing: boolean } on success
13
+ // exit non-zero + literal stderr message on any failure
14
+ //
15
+ // Idempotency guard lives here, NOT in projectCreate(). projectCreate()
16
+ // always mints a fresh UUID — modifying it to MERGE on (accountId, name)
17
+ // would change semantics for every existing caller. The CLI runs a
18
+ // pre-check MATCH on (accountId, name); if a Project exists, it returns
19
+ // the existing projectId with existing=true and skips the write. This
20
+ // makes the scaffold script safely re-runnable after a partial failure
21
+ // (e.g. graph write succeeds but mkdir fails — second run finds the
22
+ // Project and only retries mkdir).
23
+ import { projectCreate } from "../tools/project-create.js";
24
+ import { getDriver } from "../lib/neo4j.js";
25
+ async function findExistingProject(accountId, name) {
26
+ const driver = getDriver();
27
+ const session = driver.session();
28
+ try {
29
+ const result = await session.run(`MATCH (p:Project {accountId: $accountId, name: $name})
30
+ RETURN p.taskId AS projectId LIMIT 1`, { accountId, name });
31
+ if (result.records.length === 0)
32
+ return null;
33
+ return result.records[0].get("projectId");
34
+ }
35
+ finally {
36
+ await session.close();
37
+ }
38
+ }
39
+ async function main() {
40
+ const raw = process.argv[2];
41
+ if (!raw) {
42
+ process.stderr.write("project-create-cli: missing JSON payload argument\n");
43
+ process.exit(2);
44
+ }
45
+ let payload;
46
+ try {
47
+ payload = JSON.parse(raw);
48
+ }
49
+ catch (err) {
50
+ process.stderr.write(`project-create-cli: malformed JSON payload: ${err.message}\n`);
51
+ process.exit(2);
52
+ }
53
+ if (!payload.accountId || !payload.name) {
54
+ process.stderr.write("project-create-cli: payload missing required field (accountId, name)\n");
55
+ process.exit(2);
56
+ }
57
+ const createdBy = payload.createdBy ?? {
58
+ tool: "project-create-cli",
59
+ source: "scaffold-script",
60
+ };
61
+ const existing = await findExistingProject(payload.accountId, payload.name);
62
+ if (existing) {
63
+ process.stdout.write(JSON.stringify({ projectId: existing, existing: true }) + "\n");
64
+ return;
65
+ }
66
+ const result = await projectCreate({
67
+ ...payload,
68
+ createdBy,
69
+ });
70
+ process.stdout.write(JSON.stringify({ projectId: result.projectId, existing: false, childTaskIds: result.childTaskIds }) + "\n");
71
+ }
72
+ main()
73
+ .then(() => process.exit(0))
74
+ .catch((err) => {
75
+ process.stderr.write(`project-create-cli: ${err.message}\n`);
76
+ process.exit(1);
77
+ });
78
+ //# sourceMappingURL=project-create-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-create-cli.js","sourceRoot":"","sources":["../../src/cli/project-create-cli.ts"],"names":[],"mappings":"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"}
@@ -323,9 +323,10 @@ start_chrome() {
323
323
  }
324
324
 
325
325
  # ---------------------------------------------------------------------------
326
- # retired the admin-UI terminal surface entirely: the header
327
- # TerminalOverlay + UpdateModal embedded terminal stack is gone. Only
328
- # the Chromium surface remains for BrowserOverlay.
326
+ # Retired in Task 287: the admin-UI terminal and browser-overlay surfaces
327
+ # are gone. This script still launches Chromium for legacy installs where
328
+ # the brand VNC is used for ad-hoc operator browsing; on maxy-code the
329
+ # admin chat PTY is the only interactive surface.
329
330
  # ---------------------------------------------------------------------------
330
331
 
331
332
  start_chrome_native() {