Repository navigation
feat: import a folder as a project - #210
Conversation
Move the rules for which of a workspace's files are the app's, and how they pack as an app document, from the hub's app snapshot into packages/schemas as app-files.ts, free of Node's Buffer, so a browser can pack a person's own code the way the hub packs a coder's workspace. The hub re-exports them; its walk of a workspace stays where it was.
readRepository turns a directory's files, usually a git repository, into the project file the import takes, as if Builder had made the project: the code becomes the app document, honouring the directory's .gitignore files and the app rules, and the planning documents and the design are taken from the places a Builder export, a seed fixture or a coder workspace keeps them. The report names each document Builder expects that the directory lacks, and suggests files to leave out: those whose names say they hold a secret, and lockfiles the sandbox does not use.
…acks When an import files the app's code without some of its documents, as a person's own repository does, the opening message names them and asks the coordinator to learn the app from its code, ask the person what the code cannot tell it, write the brief itself and have the writers produce the rest in Builder's order, each for the person's approval. The coordinator's prompt says the same for an imported project.
Add Import a folder beside Import project on the new-project page. The folder is read in the browser: Chromium's folder picker is walked without entering dependencies or .git, and other browsers list the folder's files through a folder input. A card shows the title, the code's size, the documents found and the ones Builder will write with the person, and the files suggested for leaving out, ticked from the start, which they can keep. Importing files the project and opens it. The user manual describes it.
bun run import:repo <directory> writes the directory as the project file Import project reads, listing its files with git when it is a repository, and reports which of Builder's documents it lacks so an agent can draft them, have the person approve them and run again with --drafts. The operate-corbits-builder skill gains an Import a directory procedure built on it; README and DEV.md name the script.
There was a problem hiding this comment.
Triage requests changes:
- Conventions: added code matches a code pattern
apps/web/src/pages/projects.tsx:297 promise-chain: Promise chain; use async/await with try/catch.packages/schemas/src/app-files.ts:86 nested-ternary: Nested ternary; use if statements or a lookup.packages/schemas/src/repository-import.ts:489 empty-list-fallback: Invented fallback `?? []`; handle the missing value instead.packages/schemas/src/repository-import.ts:498 empty-list-fallback: Invented fallback `?? []`; handle the missing value instead.packages/schemas/src/repository-import.ts:191-195 nested-ternary: Nested ternary; use if statements or a lookup.packages/schemas/src/repository-import.ts:216-223 promise-chain: Promise chain; use async/await with try/catch.scripts/import-repo.ts:26 zero-fallback: Invented fallback `?? 0`; handle the missing value instead.scripts/import-repo.ts:106 empty-list-fallback: Invented fallback `?? []`; handle the missing value instead.
- Invented fallbacks: added code matches a code pattern
packages/schemas/src/app-files.ts:75 empty-fallback: Invented fallback (an empty string, list, object or zero); handle the missing value instead.packages/schemas/src/repository-import.ts:381 empty-fallback: Invented fallback (an empty string, list, object or zero); handle the missing value instead.packages/schemas/src/repository-import.ts:389 empty-fallback: Invented fallback (an empty string, list, object or zero); handle the missing value instead.packages/schemas/src/repository-import.ts:474 empty-fallback: Invented fallback (an empty string, list, object or zero); handle the missing value instead.packages/schemas/src/repository-import.ts:478 empty-fallback: Invented fallback (an empty string, list, object or zero); handle the missing value instead.
…s from the folder import The repository reader handles a missing option instead of reading it as empty, decides a file's suggested reason with if statements and decodes a file's text through an awaited helper; the app file rules compare keys with if statements and add binaries in a loop; the page awaits the folder picker; the script reads a listed file's size from its stat.
|
Triage: Pass No changes needed from you. A maintainer will review this pull request. Stacked on #209: only this pull request's own changes were checked. Notes:
|
Nothing triage asked to change still fails, so this request no longer stands.
| return IMPORTED_PROJECT_LEAD + filed + (withApp ? IMPORT_APP_MESSAGE : ""); | ||
| const unwritten = | ||
| withApp && missing.length | ||
| ? ` The code came from my own repository, so these documents were never written: ${missing.join(", ")}. Read the code with read_artifact, its package.json and README first, and write the brief yourself from what it shows, asking me only what the code cannot tell you; then have the writers produce the rest in order, each instruction carrying what you learned from the code, and have me approve each one before the next.` |
There was a problem hiding this comment.
P2 · Opening message always tells the coordinator to write the brief, even when the brief was imported
The message lists only the missing kinds, but its instruction still says to write the brief and then have the writers produce the rest. If the import already includes problem_brief and lacks only later documents such as design or build_plan, the coordinator is told to write a brief anyway. That can replace or duplicate the person's imported brief and send them through approvals they don't need.
Import a folder whose files include the app and a problem_brief but no design or build_plan.
Resolve this comment. Triage will not finish while it is open.
| if (folderInput.current) folderInput.current.value = ""; | ||
| } | ||
| }; | ||
| const pickFolder = async () => chooseFolder(await pickDirectory()); |
There was a problem hiding this comment.
P2 · Folder picker errors are not caught and the walk runs without a busy state
pickDirectory() is awaited before chooseFolder and outside its try/catch. It walks every file in the folder and rethrows anything that is not an AbortError. When the button calls void pickFolder(), such an error becomes an unhandled promise rejection and no toast appears. Also, busy is not set during the walk, which can be slow on a large folder, so the buttons stay enabled and a second import can start.
In Chromium, pick a folder where getFile() fails (permission denied, or a file that cannot be read), or pick a large tree and click again while it is still being walked.
Resolve this comment. Triage will not finish while it is open.
| if (!under(directory, path) || excludedPath(within(directory, path))) | ||
| continue; |
There was a problem hiding this comment.
P2 · A malformed approaches.json aborts the whole import
Every other bad input here is skipped: bad JSON makes parseJson return undefined, and a bad project.json or design is ignored. But JSON that parses and does not fit the schema makes ApproachesMeta.assert throw, so readRepository rejects and nothing is imported.
A repository whose docs/approaches.json is valid JSON but not in Builder's ApproachesMeta shape, e.g. {} or a file from some other tool.
Resolve this comment. Triage will not finish while it is open.
| title: options.title, | ||
| approve: options.approve, | ||
| exclude, | ||
| gitignore: !git, |
There was a problem hiding this comment.
P2 · Drafts directory is filtered through git's ignore rules, so drafted documents can silently vanish
Drafts are listed with the same code as the app (listDirectory). That code uses git ls-files --exclude-standard whenever the drafts folder sits inside any git work tree. If that repository's .gitignore matches the drafts, git leaves them out and nothing reports it. The documents then show as missing and the import exits 2, even though the person approved drafts for them.
--drafts points at a gitignored folder inside a git work tree, e.g. repo/tmp/drafts with tmp/ in .gitignore.
Resolve this comment. Triage will not finish while it is open.
The base branch was changed.
What
Imports a folder, usually a git repository, as a Builder project: from the new-project page, from the command line, and through the operate skill.
Why
Import only took a project file Builder itself had exported, so code that already existed could not become a project. A folder should import as if Builder had made it: the code as the app, any planning documents or design the folder keeps filed with it, and the coordinator writing the rest with the person, for their approval, before anything is built.
Changes
packages/schemas/src/app-files.ts: Builder's rules for which files are the app's and how they pack, moved out of the hub and freed ofBuffer, so a browser packs code the way the hub packs a coder's workspace. The hub re-exports them.packages/schemas/src/repository-import.ts:readRepositoryturns a directory's files into the project file the import takes, honouring.gitignorefiles, finding documents where an export, a seed fixture or a coder workspace keeps them, reporting what is missing, and suggesting files to leave out: names that say secret, and lockfiles the sandbox does not use.ignorebecomes a schemas dependency.apps/hub/src/config/import.ts,apps/hub/src/projects/routes.ts,workflows/coordinator/src/prompt.ts: the opening message of an import that filed code without its documents names them, and the coordinator learns the app from its code, asks the person what the code cannot tell it, writes the brief and has the writers produce the rest in order, each for approval.apps/web/src/api/repository.tsandapps/web/src/pages/projects.tsx: Import a folder beside Import project. Chromium's folder picker is walked without entering dependencies or.git; other browsers use a folder input. A card shows the title, the code's size, the documents found and the ones Builder will write, and the suggested exclusions, ticked from the start and keepable.scripts/import-repo.ts(bun run import:repo): the same reading from the command line, listing files with git when the directory is a repository, with--drafts,--approve,--excludeand--allow-missingfor an agent that drafts the missing documents first.skills/operate-corbits-builder/SKILL.md: an "Import a directory" procedure that drafts each missing document the way Builder's writers do and gets the person's approval of each before importing.docs/USER_MANUAL.mdsection 8,docs/DEV.mdandREADME.mddescribe the folder import and the script.packages/schemas/src/repository-import.test.ts,apps/web/src/api/repository.test.ts,test/integration/import-repo.test.ts.