Repository navigation
feat: start a new project from just a name (upstream) - #993
Merged
Merged
Conversation
Adapts upstream 148e6deea046658639aae9fef5b349781cec39d1 (#14527) for Pylon. The server operation, RPC and scope already shipped with the orchestrator v2 adoption (ManagedProjectFolders.createNamedProject); this adds the missing contract field, idempotency, interruption handling and the client flows. - contracts: advertise ServerConfig.newProjectsRoot; optional client-chosen projectId on projects.createNew. - server: a retry or concurrent duplicate with the same projectId replays the project the first attempt made (serialized per id, fresh command id per attempt so a retry after a rejection is re-planned); a claimed folder is removed only when the committed state proves no project owns it, including after an interrupt during dispatch. - shared: newProjectFolderName also refuses COM0/LPT0; Unicode and Windows device-name coverage. - client-runtime: path preview, GitHub target/repository helpers, and resolveNewProjectAttempt for idempotent resubmits; createNew command. - web/desktop: New project palette step beside Add existing project, with environment switcher and optional private GitHub publishing. - mobile: add-project/new route and screen. - docs: Pylon-branded user docs in docs/user/source-control.md. (cherry picked from commit 148e6deea046658639aae9fef5b349781cec39d1) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
Review follow-ups for the New project port: - Pending create attempts live in a client-runtime store held at module scope on web and mobile, keyed by environment and normalized name, so closing the palette or leaving the screen no longer mints a new id. - projects.createNew reports a refused id as ProjectCreateNewIdInUseError; clients settle the attempt on it instead of looping on the same id. - Mobile keeps the attempt until the draft opens, so Create after a projection timeout replays the project rather than duplicating it. - A claimed folder is kept only when the project with the requested id is rooted at that folder; an owner elsewhere no longer orphans the scaffold. - Mobile "Add existing project" opens sources for the machine selected on the New project screen. - Document newProjectsRoot as the capability gate for retry replay. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adapts upstream "start a new project from just a name" for Pylon as New project, distinct from Add existing project (add-folder and clone flows are unchanged and reachable from the new step).
Source
148e6deea046658639aae9fef5b349781cec39d1(#14527)Re-grounded against orchestrator v2: the server operation (
ManagedProjectFolders.createNamedProject), theprojects.createNewRPC, its operate-scope authorization, the sharednewProjectFolderNamehelper and the Pylon-branded README already arrived with the v2 adoption. Upstream'sapps/server/src/project/NewProject.ts, itsws.tswiring andserver.test.tscase were therefore not ported; the rest of the commit was cherry-picked (-x) and adapted.Adaptations
ServerConfig.newProjectsRoot(optional) is now part of the schema, so the root the server already returned actually reaches clients;ProjectCreateNewInput.projectId(optional) carries a client-chosen id. Older servers ignore the field (default excess-property handling); older clients omit it and get the previous non-idempotent behavior.projectIdare serialized per id; a retry after a lost response, or a duplicate sent while the first runs, replays the project the first attempt made instead of claiming a-2folder. Only a live project inside the named-projects folder replays; any other owner of the id fails withNamedProjectIdInUseError, sent on the wire as the newProjectCreateNewIdInUseError(only for creates carrying aprojectId, so older clients never see it). Each attempt uses a fresh command id, so a retry after a rejection is planned again rather than resolved to the old rejected receipt. A replay reports a missing first commit from the repository itself.<server baseDir>/projects, i.e. derived from Pylon's runtime home (~/.pylon-code/projectsby default), advertised per environment; no T3 path.assets/icon.svg; first commit oninit.defaultBranch, elsemain. Commit failure keeps the folder and surfaces a warning on every client.sourceControl.publishRepository, using the actual (possibly suffixed) folder from the response. Failure keeps the local project and points at Publish repository. Pylon change: publishing is skipped (with a visible explanation) when the first commit failed, since an unborn repository has nothing to push.newProjectFolderNamealso refusesCOM0/LPT0(superscript forms decompose via NFKD); added Unicode/Windows tests. Non-Latin names fall back toprojectas upstream, keeping folders and GitHub repository names portable; titles keep the name as typed.add-project/newroute ("New Project" title), screen reusing the add-project environment options,waitForProjectbefore opening the draft; Pylon's fixed icon sizes instead of upstream'sPlatformsizing.createNewProjectAttemptStore(client-runtime) keeps unfinished attempts keyed by environment and trimmed/NFC name. Web and mobile hold one at module scope, so closing the palette or leaving the screen keeps the id (until reload). Attempts settle on confirmed success (web) / once the draft opens (mobile), or onProjectCreateNewIdInUseError; other failures keep the id so a retry replays.ServerConfig.newProjectsRootis the gate: the server returned it since the v2 adoption, but the contract never declared it onorigin/pylon(git log -S newProjectsRoot -- packages/contracts/src/server.tsis empty), so earlier servers strip it on encode and their clients never offer New project. Any server that advertises it honorsprojectId. Documented on the schema field.add-projectnow takes an optionalenvironmentId).docs/user/source-control.mddescribes the Pylon behavior, location, retry, commit and publishing failure handling.Kept additive for the parallel Scratch port:
createNewis appended afterwriteFileinprojectCommands.ts;newProjectsRootsits afterrollbackRecoveryOperationIdentityinServerConfig; no Scratch code was touched.Verification
vp run -F t3 typecheck,vp run -F @t3tools/contracts typecheck,vp run -F @t3tools/shared typecheck,vp run -F @t3tools/client-runtime typecheck,vp run -F @t3tools/web typecheck,vp run -F @t3tools/mobile typecheck: each rantsc --noEmit, exit 0.apps/server:vp test run src/project/ManagedProjectFolders.test.ts src/mcp/toolkits/project/handlers.test.ts: 27 passed. New cases: custominit.defaultBranch, commit-signing failure, Unicode/Windows folder names, retry replay, concurrent duplicates joined, replayed missing-commit warning, foreign id refused, rejected-then-retried, interrupted before commit (folder removed), interrupted after commit (kept, retry replays), id taken elsewhere mid-create (scaffold removed). Interrupt tests synchronize onDeferreds, no sleeps.packages/shared:vp test run src/path.test.ts: 9 passed.packages/contracts:vp test run src/project.test.ts: 16 passed (incl. id-in-use error round-trip).packages/client-runtime:vp test run src/operations/projects.test.ts: 23 passed (path preview incl. Windows, suffixed publish target, GitHub readiness, attempt store reuse/normalization/settlement, id-in-use detection).apps/web:vp test run src/components/sidebar/SidebarThreadHeader.test.tsx: 2 passed.apps/mobile:vp test run src/features/projects/AddProjectScreen.logic.test.ts: 6 passed (incl. Add existing project navigation).vp linton changed TS/TSX: no new warnings (CommandPalette keeps its 6 pre-existing warnings).vp fmt --checkon changed files: clean.Unverified
ghaccount.-2); only a durable provisioning intent would close that, which is out of scope.Part of upstream cycle #981.
🤖 Generated with Claude Code