Skip to content

Design review: start threads without a project (upstream #13612) #963

Description

@rynfar

Maintainer asked (2026-10-01) to consider this as Pylon product work with its own design review, not a straight port.

Upstream: 6b286ae8a2 (pingdotgg/t3code#13612, 23 files, +1081/-100) lets a user start a chat with no project/folder attached. It arrived after the frozen cycle #961 bound and belongs to the next upstream cycle, where this issue owns its disposition.

Questions for the design: what workspace/cwd a projectless thread runs in for each provider (Claude, Codex, Prime, ACP), how checkpoints/diffs/terminal behave, sidebar grouping on web/desktop/mobile, remote/tunnel environments, and migration/projection impact (Pylon renumbered migrations; never reuse upstream numbering).

Exit: a recorded decision (adopt with adaptations / design differently / decline) linked from the upstream review index.

Activity

  1. rynfar commented on Oct 2, 2026

    @rynfar
    CollaboratorAuthor

    Design review

    Design review: start threads without a project

    Reviewed against Pylon 00884406f7d8c59c3ee98a617ba8a1eb64661a04, upstream 6b286ae8a20ef2e18fa70b09e92f66edd859128b (#13612), and 39405f1992 (#14532).

    Upstream behavior

    “No project” is a UI abstraction over an ordinary persisted project. apps/server/src/ws.ts adds projects.ensureScratch, which creates or reuses one project at <server baseDir>/scratch. It dispatches existing project.create and project.meta.update commands. Concurrent creation resolves through the existing unique active workspace-root invariant.

    Each new Scratch thread receives a plain subdirectory named from the date, prompt words, and thread ID. Its path occupies the existing worktreePath field, so providers, terminals, and file browsing use that directory. It is not a Git worktree.

    Contract additions are ProjectEnsureScratchResult, an authenticated operate-scope RPC, optional ServerConfig.scratchWorkspaceRoot, and chat.newWithoutProject. Project IDs remain required; no persistence migration or new event type is introduced. Scratch is unavailable when the server data directory lies inside a Git checkout or repository detection fails.

    Web/desktop entry points include NoProjectsHero.tsx, CommandPalette.tsx, DraftHeroHeadline.tsx, and mod+alt+n. Draft project changes preserve the composer. useThreadActions.ts excludes Scratch folders from Git worktree deletion; deleting a thread retains its files.

    The mobile follow-up is material: NewTaskRouteScreen.tsx removes Scratch-only scopes from ordinary project rows and renders one “No project” row above the list. When there are no ordinary projects, it offers the empty-state action instead. NewTaskDraftScreen.tsx uses a neutral heading; NewTaskContextPickerScreens.tsx ensures the destination machine’s Scratch project before retargeting a draft. Workspace selection is suppressed through new-task-flow-provider.tsx.

    Current Pylon behavior

    Pylon’s contracts require project IDs, and its new-task picker requires a project. There is no Scratch RPC or advertised Scratch root. Existing non-Git projects and worktreePath routing provide much of the execution plumbing.

    apps/server/src/orchestration/decider.ts already enforces project workspace uniqueness. However, Pylon has richer rollback, workspace ownership, cleanup, and Prime recovery behavior. A non-null worktreePath cannot become sufficient evidence of Git isolation.

    There is also an environment-selection discrepancy to resolve: upstream web’s actual useScratchProject.ts preserves the current machine and only chooses an unambiguous sole offering machine when none is current; mobile falls back to the first eligible machine.

    Options

    • Don’t adopt. Retain project-first web, desktop, and mobile flows. No contracts, migrations, decider/projection, remote/tunnel, or provider changes. Low risk and negligible implementation size; users must add a folder before starting.
    • Adapt Scratch projects. Adopt both commits’ final UX and additive contracts, preserving existing events/projections and required project IDs. Put allocation and recovery behind a server-owned service with explicit ownership and retry handling. All three clients participate; folders and credentials remain on the selected environment for local, remote, and tunnel access. Prime and other adapters receive an ordinary cwd through existing admission paths. Medium risk; roughly 1–2 engineering weeks including lifecycle coverage.
    • Make projects genuinely optional. Add nullable project identity and explicit workspace identity across commands, events, projections, clients, and provider consumers. This requires historical replay compatibility and Pylon-numbered migrations; the current manifest ends at 67. Remote routing still requires an environment. High risk and several weeks; unnecessary for the requested UX.

    Recommendation

    Adapt Scratch projects, subject to maintainer decisions on machine selection and file retention. Include #14532 immediately.

    Before adoption, address directory allocation occurring before command acceptance: replaying a request can allocate another directory even when dispatch ultimately returns an existing command receipt. Define how retained folders are discoverable and how Scratch behaves after configuration changes, project deletion, or server downgrade.

    Phase implementation as server allocation/recovery and contracts, then shared client targeting, then web/desktop/mobile entry points. Keep multi-model Git fan-out from #964 unavailable for Scratch. Name-only project creation is a separate alternative, not an automatic conversion of Scratch files.

    Verification plan

    Cover concurrent ensure calls, deleted-folder restoration, allocation collisions, traversal-like IDs, interrupted/repeated bootstrap, and data directories inside Git. Verify both project↔Scratch draft transitions, machine switching, attachments, terminal/file cwd, deletion retention, reconnect, and mixed-version environments. Exercise Prime native/ACP and other supported providers; reject unsupported Git/rollback operations explicitly. Wait on worker drains and receipts.

    Actual verification

    Ran git show for both commits, rg searches, git rev-parse HEAD, and git status --short; HEAD matched the assigned base and status was clean. gh issue view 963 --repo pylon-code/pylon failed because GitHub was unreachable. No tests, builds, browser sessions, or edits were performed.

    Read-only design review (Codex via relay, coordinated by Claude Opus 5.5) against Pylon 00884406f7. Decisions stay with the maintainer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions