Conversation
Implements all 3 phases of the plan at docs/plans/2026-04-25-001-feat-new-product-creation-flow-plan.md: Phase 1 — Foundations - ScratchpadService with on-disk layout at <userData>/scratchpads/<taskId>/ <sanitized-name>/, atomic .posthog.json manifest, full DI/tRPC wiring - PostHog API: createProject / updateProject / deleteProject + hooks Phase 2 — Creation flow + agent capabilities - "New product" entry points: button under PromptInput + command palette - ProductCreationDialog with project picker, rounds selector (3..5), and ScratchpadCreationSaga with rollbacks (project / task / dir / workspace / agent session) - posthog_code__askClarification MCP tool + ClarificationBlock UI; in-process Streamable-HTTP MCP server registered alongside existing servers - posthog_code__registerPreview MCP tool + PreviewService (node-pty, port denylist, cwd traversal guard, manifest persistence, auto-resume on app relaunch) + Electron <webview> preview tab Phase 3 — Lifecycle - Sidebar: NotePencil draft icon, Trash button, group icon swap, multi-step useDeleteScratchpad (preview kill, dir delete, conditional project delete, task delete) - Publish flow: secret-leakage guard, git init + commit + GitHub POST /user/repos + push, manifest patch, project rename via renderer hook, PublishDialog wired into TaskDetail header for drafts only Workspace gets an orthogonal `scratchpad: boolean` axis (does NOT extend WorkspaceMode); migrated via 0006_scratchpad_workspaces.sql. 1033/1033 tests passing; 82 new tests across the new units. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Reads as "We'll ask up to [3|4|5] rounds of clarifying questions..." instead of separating the prose from the picker. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Prompt To Fix All With AIThis is a comment left during a code review.
Path: apps/code/src/renderer/features/scratchpads/hooks/useDeleteScratchpad.ts
Line: 42-53
Comment:
**Active agent session not disconnected before task deletion**
`deleteScratchpadImperative` kills previews and deletes the scratchpad directory and PostHog task, but never calls `disconnectFromTask`. If an agent is actively running when the user clicks "Trash", it continues executing inside the now-deleted directory and will make calls against a task that no longer exists — producing confusing error toasts and potentially leaving orphaned processes.
The saga rollback explicitly uses `getSessionService().disconnectFromTask(taskId)` for this very reason (see `scratchpad-creation.ts` step `agent_session` rollback). The same call should be inserted here, ideally before step 3 (scratchpad directory deletion).
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: apps/code/src/main/services/preview/service.ts
Line: 389-397
Comment:
**`fetch` inside `waitForHealth` has no per-request timeout**
Each `fetch(opts.url)` call has no `AbortSignal` or timeout option. If the spawned server accepts the TCP connection but stalls before sending headers (e.g. slow startup, misconfigured framework), a single `fetch` can block for Node's default socket timeout (minutes), making the loop run far past the intended `HEALTH_TIMEOUT_MS = 60 s` deadline.
A short `AbortSignal.timeout(opts.intervalMs)` wrapped in a `try/catch` (since abort throws) is the minimal fix and keeps the poll rate honest.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: apps/code/src/main/services/scratchpad/service.ts
Line: 356-358
Comment:
**`git commit` will fail when no global git identity is configured**
The commit step runs without `-c user.email=...` / `-c user.name=...`:
```
await this.runGit(scratchpadPath, ["commit", "-m", "Initial commit"]);
```
If the user has never run `git config --global user.email`, git emits "Author identity unknown … Please tell me who you are." — returned as a `git_error` with a message that makes it look like a bug rather than a missing config. Adding inline `-c` flags (e.g. `user.email=noreply@posthog.com`, `user.name=PostHog Code`) makes the initial commit unconditionally succeed without touching the user's global config.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(code): inline rounds selector into t..." | Re-trigger Greptile |
| // 2. Kill all running previews for this task. Best-effort. | ||
| await trpcClient.preview.unregister.mutate({ taskId }).catch((err) => { | ||
| log.warn("Failed to unregister previews", { taskId, err }); | ||
| }); | ||
|
|
||
| // 3. Delete the scratchpad directory + manifest. | ||
| try { | ||
| await trpcClient.scratchpad.delete.mutate({ taskId }); | ||
| } catch (err) { | ||
| log.error("Failed to delete scratchpad directory", { taskId, err }); | ||
| toast.error("Failed to delete draft files"); | ||
| } |
There was a problem hiding this comment.
Active agent session not disconnected before task deletion
deleteScratchpadImperative kills previews and deletes the scratchpad directory and PostHog task, but never calls disconnectFromTask. If an agent is actively running when the user clicks "Trash", it continues executing inside the now-deleted directory and will make calls against a task that no longer exists — producing confusing error toasts and potentially leaving orphaned processes.
The saga rollback explicitly uses getSessionService().disconnectFromTask(taskId) for this very reason (see scratchpad-creation.ts step agent_session rollback). The same call should be inserted here, ideally before step 3 (scratchpad directory deletion).
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/scratchpads/hooks/useDeleteScratchpad.ts
Line: 42-53
Comment:
**Active agent session not disconnected before task deletion**
`deleteScratchpadImperative` kills previews and deletes the scratchpad directory and PostHog task, but never calls `disconnectFromTask`. If an agent is actively running when the user clicks "Trash", it continues executing inside the now-deleted directory and will make calls against a task that no longer exists — producing confusing error toasts and potentially leaving orphaned processes.
The saga rollback explicitly uses `getSessionService().disconnectFromTask(taskId)` for this very reason (see `scratchpad-creation.ts` step `agent_session` rollback). The same call should be inserted here, ideally before step 3 (scratchpad directory deletion).
How can I resolve this? If you propose a fix, please make it concise.| try { | ||
| const res = await fetch(opts.url, { method: "GET" }); | ||
| const code = res.status; | ||
| if ((code >= 200 && code < 400) || code === 404) { | ||
| return true; | ||
| } | ||
| } catch { | ||
| // Server isn't up yet — keep waiting. | ||
| } |
There was a problem hiding this comment.
fetch inside waitForHealth has no per-request timeout
Each fetch(opts.url) call has no AbortSignal or timeout option. If the spawned server accepts the TCP connection but stalls before sending headers (e.g. slow startup, misconfigured framework), a single fetch can block for Node's default socket timeout (minutes), making the loop run far past the intended HEALTH_TIMEOUT_MS = 60 s deadline.
A short AbortSignal.timeout(opts.intervalMs) wrapped in a try/catch (since abort throws) is the minimal fix and keeps the poll rate honest.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/main/services/preview/service.ts
Line: 389-397
Comment:
**`fetch` inside `waitForHealth` has no per-request timeout**
Each `fetch(opts.url)` call has no `AbortSignal` or timeout option. If the spawned server accepts the TCP connection but stalls before sending headers (e.g. slow startup, misconfigured framework), a single `fetch` can block for Node's default socket timeout (minutes), making the loop run far past the intended `HEALTH_TIMEOUT_MS = 60 s` deadline.
A short `AbortSignal.timeout(opts.intervalMs)` wrapped in a `try/catch` (since abort throws) is the minimal fix and keeps the poll rate honest.
How can I resolve this? If you propose a fix, please make it concise.| ]).catch(() => undefined); | ||
| await this.runGit(scratchpadPath, ["add", "."]); | ||
| await this.runGit(scratchpadPath, ["commit", "-m", "Initial commit"]); |
There was a problem hiding this comment.
git commit will fail when no global git identity is configured
The commit step runs without -c user.email=... / -c user.name=...:
await this.runGit(scratchpadPath, ["commit", "-m", "Initial commit"]);
If the user has never run git config --global user.email, git emits "Author identity unknown … Please tell me who you are." — returned as a git_error with a message that makes it look like a bug rather than a missing config. Adding inline -c flags (e.g. user.email=noreply@posthog.com, user.name=PostHog Code) makes the initial commit unconditionally succeed without touching the user's global config.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/main/services/scratchpad/service.ts
Line: 356-358
Comment:
**`git commit` will fail when no global git identity is configured**
The commit step runs without `-c user.email=...` / `-c user.name=...`:
```
await this.runGit(scratchpadPath, ["commit", "-m", "Initial commit"]);
```
If the user has never run `git config --global user.email`, git emits "Author identity unknown … Please tell me who you are." — returned as a `git_error` with a message that makes it look like a bug rather than a missing config. Adding inline `-c` flags (e.g. `user.email=noreply@posthog.com`, `user.name=PostHog Code`) makes the initial commit unconditionally succeed without touching the user's global config.
How can I resolve this? If you propose a fix, please make it concise.Replaces the SegmentedControl with a small inline number input bounded to [1..5]. Reads naturally as part of the sentence and supports the full range without needing 5 separate buttons. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Inline-aligned with the surrounding sentence, exposes the full 1..5 range (default 3, capped at 5). Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Lets users scaffold a scratchpad without linking a PostHog project. Manifest projectId becomes nullable; saga gains a third mutually-exclusive mode (skipProject). When set: - No project is created or linked. - Scaffolding prompt skips the instrumentation step entirely. - Publish refuses to run with a clear "link a project before publishing" message instead of attempting GitHub work it can't complete. useDeleteScratchpad already tolerated a missing projectId; updated the null check to be explicit. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
The Product Creation Dialog's project picker now reads from @features/projects/hooks/useProjects — the same hook the sidebar's "Change project" dialog uses — instead of a separate posthog-projects hook that fetched the same data through a different endpoint. Drops the now-unused listProjects client method and the posthog-projects useProjects hook. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
The classic. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Scratchpads are mostly throwaway, so creating a real PostHog project at scaffold time produces clutter. New flow: Creation dialog (Product Creation): - Two options: "Let's do this later" (default) and "Use existing project". - "Auto-create new project" removed entirely. Scaffolding: - PostHog instrumentation skills always run, regardless of project link state. The agent reads API key + host from env vars (POSTHOG_API_KEY, POSTHOG_HOST) and writes a .env.example. No hardcoded keys/IDs. Publish: - If the manifest has no projectId, the Publish dialog shows a project link step: create new project (with editable name) or pick existing. The chosen projectId is patched into the manifest before the publish flow runs. Existing manifests with projectId already set behave the same as before. Saga: - Drops autoCreateProject input + the posthog_project step entirely. - Output drops autoCreatedProject; projectId stays nullable. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Auto-create at scaffold time was the only thing that produced the prefix; now that's gone. Cleaning up the dead code: - usePublishScratchpad: drops the rename step (no prefix to strip) and the productName input. Hook just publishes. - useDeleteScratchpad: drops the project deletion path entirely. Drafts only ever reference user-picked projects, which we never delete. - posthogClient.deleteProject + useDeleteProject hook: deleted; no consumers remain. - DraftTaskHeaderActions: takes taskTitle directly instead of fetching the linked project to derive a name. - PublishDialog: stops threading productName through to the publish hook; only uses it as a pre-fill for the create-new-project name. Tests trimmed accordingly. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Bug fix: the rounds banner was nested inside the PostHog project section, visually attaching it to the project picker. Now it lives at the top as the framing copy. Polish: - Title size 4 + small rocket icon — this is a beginning, not a row in a settings list - Banner moved directly below the title and tinted with accent colors so it reads as a system-level promise rather than body chrome - Trim banner copy: "rounds of clarifying questions to shape your product." → "rounds of questions before scaffolding." - Indent the project picker / helper text under their respective radios so the relationship is unambiguous - Trim the "later" helper to one line - Submit button: "Create product" → "Start building" with a rocket icon - Voice fix: "What's the name of your new thing?" → "What are we calling it?" (was the only label that didn't use first-person agent voice) Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
The IPC layer can drop null property values, so the server saw undefined and rejected with "expected: number" — even though the schema was nullable. Switch to nullish() and normalize to null in the service so the manifest always stores null when no project is linked. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Two bugs after clicking Start building: 1. The user landed on a blank "Select repository folder" view instead of the new task. The saga passed a synthetic `folderId` (the scratchpad path) without registering the scratchpad in the folders DB, so navigateToTask's folder lookup failed and fell into an auto-recreate branch that fought with the workspace we just created. Fix: register the scratchpad as a real folder before workspace creation and pass the folder's UUID through. 2. Reopening the dialog showed it stuck "loading" with no progress. `agent_session` was a saga step, so the dialog's submitting state stayed on for the entire (slow) connectToTask call. If that step failed it would also roll back the workspace + scratchpad + task, leaving the user staring at a now-deleted task. Fix: pull agent_session out of the saga. The saga ends after workspace creation, returns the prepared initialPrompt, and the dialog kicks off connectToTask in the background with toast-on-failure. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
The folder-aware UI (file watchers, status bar, "Changes" panel) all assume a git directory and surface "This folder is not a git repository" the moment a fresh scratchpad opens. Holding off git init until publish time was too clever — just init it as part of scaffolding. ScratchpadService.scaffoldEmpty now runs `git init -b main` immediately after creating the directory. Scaffolding prompt no longer forbids git; it tells the agent the dir is already a fresh repo on main with no commits, so it can use git normally (with the obvious "don't push" / "don't init in subdirs" guardrails). Publish-time `git init` is now a no-op for already-initialized repos. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
The saga was creating the PostHog task but never invalidating the tasks-list TanStack Query cache. Side effects: - New task didn't appear in the sidebar until the 30s poll (so the user couldn't navigate back to it after leaving). - task-detail couldn't resolve the just-created task in the cache, so it fell back to "Select a repository folder" until the poll fired. After saga success, call useCreateTask().invalidateTasks(task) — same helper the regular task-creation flow uses — to optimistically prime the cache and trigger a refetch. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Product name lives in the scratchpad directory name and the agent's first message — no need to repeat it in the task title. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
The hook no longer deletes any PostHog project (project linking happens at publish time via explicit user action; we never delete user-picked projects). Update the confirm message to match. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
- Title is now `Building ${productName}` so each scratchpad gets a
distinct sidebar entry while still keeping the product name out of
the verbose phrase.
- Embeds the same `PromptInput` component the New task input uses, so
the dialog inherits: execution mode (incl. bypass permissions),
model + adapter, reasoning level, file attachments, command palette
(`@` mentions, `/` skills).
- Saga gains an optional `filePaths` input that is woven into the
agent's first turn via `buildPromptBlocks`, so attached files become
resource_link blocks the agent can read while clarifying.
- Adapter, executionMode, model, reasoningLevel are forwarded to both
the saga and the subsequent `connectToTask` call.
Generated-By: PostHog Code
Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
- Drop PromptInput in favour of a plain TextArea — the dialog doesn't need a "Send" button, just the text. - Reuse the same ModeSelector / UnifiedModelSelector / ReasoningLevelSelector the New task input uses, but rendered as a standalone toolbar above the action row instead of being baked into the editor. - Toolbar and action row are both right-aligned. - Default mode is now "auto" for both adapters (was "plan" for Claude). - Submitting state takes over the dialog as a loading curtain with a rotating set of unhinged messages, and we navigate first / close last so the empty TaskInput never bleeds through during the transition. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
The scaffolding flow has the agent open a preview via the posthog_code__registerPreview tool once the dev server is up — but this happens silently. Add a one-liner to the prompt instructing the agent to send a short hello at the start that explains what's about to happen, including that a preview tab will open by itself. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
MCP server (the headline fix):
- The stateless StreamableHTTP pattern requires a fresh McpServer +
transport per HTTP request. The previous code shared one transport
across requests, which worked for the first connection but broke
tools/list on agent reconnect after an app restart — agents would
report the registerPreview/askClarification tools as "not in this
session's tool list". Now we build the server inside the request
handler and tear it down on response close.
Dialog defaults:
- New product dialog always defaults the mode to "auto" regardless of
the user's New-task mode preference; settings-based fallback dropped.
Repo helpers:
- REPO_NAME_RE + sanitizeRepoName moved to @shared/utils/repo so the
PublishDialog and the main-process publisher validate identically.
- PublishDialog now uses useCreateProject() instead of poking
posthogClient.createProject directly — picks up cache invalidation.
Secret-leakage check:
- Replaced the hand-rolled gitignore matcher (~70 lines) with
`git ls-files --others --cached --exclude-standard -z`. Correct
semantics for negation, nested gitignores, etc., for free.
Saga utilities:
- createSagaLogger(scope) extracted; both task and scratchpad sagas
use it.
- taskCreationStepConfig() helper — the create-then-rollback pattern
for the shared task_creation step now lives in one place.
Performance:
- ScratchpadService.list() walks taskDirs concurrently and uses
withFileTypes:true to drop the per-entry stat round-trip.
- getScratchpadPath same treatment.
- findOffendingFiles parallelizes sibling walks.
- ensureGitignore uses writeFile {flag:"wx"} instead of access+write.
- PreviewService.resumeFromManifest spawns previews concurrently.
- PreviewService health probe takes an AbortController and aborts on
killProcess/shutdown so dead probes don't run to completion.
- useDraftTaskIds debounces (150 ms) the cache invalidation triggered
by scratchpad lifecycle events; bursty publish-time manifest
patches no longer thrash the sidebar.
Code quality:
- PublishDialog body extracted into a child component keyed by useId
+ conditional mount, so each open gets fresh form state with no
reset effect.
- A handful of redundant casts dropped from preview/service and the
product dialog.
Generated-By: PostHog Code
Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
addPreviewTab now puts the preview alongside the chat instead of in the main tab list: 1. If a preview tab with the same name already exists, update its URL and activate (re-registration may have changed the port). 2. Else, if there's already a non-main leaf panel (the user has a split open), drop the preview in there as a new tab. 3. Otherwise, split the main panel 50/50 horizontally and put the preview in the new right pane so the chat stays visible. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
PostHog Code doesn't preinstall Anthropic's frontend-design skill (the bundled posthog plugin only carries instrument-* skills), but it MAY be available in the session via Claude Code's plugin marketplace. Tell the agent to invoke /frontend-design if present; otherwise apply the same principles inline so we don't end up with cookie-cutter purple-on-white AI defaults. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Loading a Claude Code skill at runtime is, in practice, the same as WebFetching its SKILL.md and following the contents. Drop the conditional /frontend-design dance and just point the agent at raw.githubusercontent.com — works regardless of whether the user has the plugin installed locally. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Per user feedback, "product" sounds too serious — "app" keeps the door
open for hackathons and weekend projects. Updated:
- Sidebar entry button under PromptInput
- Command palette entry ("New app" / "Create new app")
- Dialog title + loading curtain ("Create a new app", "Preparing your app")
- Inline error copy ("Failed to create app")
- Analytics action enum value (new-product → new-app)
- Scaffolding prompt phrasing the agent reads
Internal identifiers (file/component/store/feature names) keep the
existing "product" naming since they're not user-visible — renaming
them is churn for no UX gain.
Generated-By: PostHog Code
Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Lift the framing banner from "I'll ask up to N rounds" into a small hero block with a punchy lead, a Sparkle icon, and a one-paragraph explanation that articulates why this isn't just a fancy New Task: clarification first, agent picks the stack, PostHog wired from commit 1, live preview opens automatically. Subtle accent gradient ties the block to the rocket-icon title. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Reordered the agent's workflow so a live preview comes up as fast as possible: 1. Clarify 2. Scaffold the bare minimum that runs (no features yet) 3. Start the dev server + register the preview NOW 4. Build it out (with the user watching) 5. Wire up PostHog instrumentation The whole thing is one big template-string now instead of an array of joined fragments — easier to read and easier to edit. The intro message also tells the user to expect a preview "as fast as possible", and the build-out step calls out that HMR / re-registration is fine so the agent isn't shy about restarting. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
…n AskUserQuestion Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
ModeSelector, UnifiedModelSelector, and ReasoningLevelSelector now accept
a portalContainer ref. When set, the menu content is portaled into that
container instead of <body>, keeping it inside the dialog's FocusScope
so focus and pointer events behave normally. ProductCreationDialog
threads the ref through. modal={false} stops Base UI from rendering its
own backdrop on top of the dialog content.
Generated-By: PostHog Code
Task-Id: 91418382-614e-4310-b210-6dc2d047ea27
The agent now uses Claude's built-in AskUserQuestion to ask up to N clarifying rounds before scaffolding. Round count is selected inline in the dialog banner via SegmentedControl and threaded through the saga + scaffolding prompt as a budget hint — no host-side enforcement. Generated-By: PostHog Code Task-Id: 142b4c29-fa5f-4e02-9bc9-de8b22313475
Summary
A "New app" creation flow for PostHog Code: end-to-end from "I have an idea" to "I'm watching it run" with PostHog instrumentation already set up. Like a local Lovable.
The user clicks "Scaffold a brand-new app" under the prompt input (or runs New app from the command palette), describes the idea, optionally picks an existing PostHog project, and hits Start building. The agent is launched into a fresh
git-initialized scratchpad with a prompt that runs a few rounds of clarification, Socrates-style (picking the stack, making product decisions), builds the project, instruments PostHog, and registers a preview tab. The user can then take it from there and iterate.When the dev server is up, the preview opens automatically in a 50/50 split next to the chat. When ready, Publish turns the scratchpad into a real GitHub repo and links/creates the PostHog project.
What's in the box
(As summarized by Claude - pretty damn long)
ScratchpadService— atomic.posthog.jsonmanifest I/O at<userData>/scratchpads/<taskId>/<sanitized-name>/. Manifest is the authoritative source ofpublished/draft state.git init -b mainruns at scaffold time so folder-aware UI (file watchers, status bar, Changes panel) doesn't break with "This folder is not a git repository".createProject/updateProjectclient methods +useCreateProject/useUpdateProjectTanStack hooks.Creation flow
PromptInputand command palette item.ModeSelector/UnifiedModelSelector/ReasoningLevelSelectorfrom the New-task input as a standalone right-aligned toolbar, plus the same submit hotkeys. Defaults the execution mode toautoregardless of the user's New-task preference. Submit shows a loading curtain with rotating cheeky messages ("Convincing the silicon to think…", "Bribing the file system…") while the saga runs.ScratchpadCreationSagaorchestrates:task_creation→scratchpad_dir(withgit init) →folder_registration→workspace_creation. Each step has a tested rollback. Agent connection runs after the saga (not as a saga step) so a slow/failing connect can't undo the workspace after the user navigated to it.posthog_code__askClarificationMCP tool + customClarificationBlockUI. New in-process Streamable-HTTP MCP server (PosthogCodeMcpService) registered alongside the existing PostHog MCP viaauth-adapter.ts::buildMcpServers. Per-request server + transport pattern, so tool discovery survives agent reconnects after app restart. Round cap is a soft UX guard — agent recovers via its own loop.posthog_code__registerPreviewMCP tool +PreviewService(node-pty, port denylist[22, 25, 80, 443, 5432, 6379, 8123, 9000], cwd traversal guard, manifest persistence, auto-resume on app relaunch, AbortController-cancellable health probe). New panel tab type renders the dev server in an Electron<webview>with sharedpartition: \"preview\". Preview opens in a 50/50 horizontal split next to the chat (multiple previews stack as tabs in the right pane).frontend-designskill (https://raw.githubusercontent.com/anthropics/claude-code/main/plugins/frontend-design/skills/frontend-design/SKILL.md) and follow it for any UI work, run the PostHog instrumentation slash-skills, and callregisterPreviewonce the dev server is up. Hard guardrails: never write.posthog.jsondirectly, no remote add/push, mainstream stacks only.Lifecycle
NotePencildraft icon for unpublished scratchpads, group-section icon swap when every task in the group is a draft, hover Trash button.useDeleteScratchpadruns preview unregister → dir delete → task delete → cache invalidate. Linked PostHog projects are never auto-deleted (drafts only ever reference user-picked or publish-time-created projects).PublishDialogdoes project link (create-new with editable name or pick existing) when the manifest has noprojectId, repo name + visibility (private default), gh-token gating, repo conflict (422) inline retry, secret-leakage guard. Service-sidepublishrunsgit init -b main(no-op if already initialized) +git add . && git commit -m \"Initial commit\"+POST /user/repos+git push -u origin main+ manifest patch. Renderer hook then optionally renames the linked PostHog project. The secret-leakage walk usesgit ls-files --others --cached --exclude-standard -zso gitignore semantics (negation, nested gitignores, global gitignore) are handled correctly without a bespoke matcher.Architectural notes
scratchpad: booleanaxis —WorkspaceModeis not extended (per the plan's Key Technical Decisions). Migrated via0006_scratchpad_workspaces.sql.Building \${productName}so the sidebar can distinguish multiple drafts at a glance. Product name still drives the directory name.autoexecution mode is the dialog default — scaffolding-from-scratch needs to run scaffolders, install deps, and start servers without per-step approval.git push..gitignoreships withnode_modules/,.env*,dist/,build/,.DS_Store,*.pem,*.key,.next/,.vite/,.posthog.json{,.tmp}.Testing
pnpm --filter code typecheck— cleanpnpm --filter code test— passes; the only failures in the full suite are pre-existing flakyarchive/service.integration.test.tsworktree tests (unrelated to this work)pnpm lint— clean (the one Biome warning surfaced is inpackages/agent/src/handoff-checkpoint.tsand pre-existing onmain)Post-Deploy Monitoring & Validation
scratchpad-service,scratchpad-creation-saga,task-creation-saga,preview-service,posthog-code-mcp,delete-scratchpad,scratchpad-publish,product-creation-dialog,useDraftTaskIdsNotePencilicon next to drafts; Publish button appears in the task header for drafts only; preview opens in a right pane on dev-server readyls -la \"\$HOME/Library/Application Support/@posthog/posthog-code/scratchpads/\"after creating an app → directory +<sanitized-name>/.posthog.jsonand.git/presentcat \"\$HOME/.../scratchpads/<taskId>/<name>/.posthog.json\"→{ projectId: number | null, published: false, ... }posthog_code__registerPreviewandposthog_code__askClarificationin its tool list (verified by per-request MCP server fix; previously broke on app restart)posthog_code__registerPreviewresolving (60s health-probe ceiling, abortable on shutdown).scratchpad-creation-sagaerror logs.preview-servicelogs.POST /user/repossucceeds (e.g. push failure) leave the remote intact and require manualgit pushfrom the user. Documented in the dialog UX.Plan reference
Created with PostHog Code