Problem
Generated apps are currently created below apps/<slug>, while the Studio root declares:
"workspaces": [
".",
"apps/*"
]
The Dashboard also runs bun install from the Studio repository root. As a result, every generated app becomes part of the Studio workspace installation and mutates the repository-level bun.lock.
This causes two architectural and workflow problems:
- Generated apps are not validated as truly standalone consumers. Their dependency graph may be satisfied through the Studio workspace installation and root-level package resolution.
- Local project creation or dependency updates dirty the Studio repository's committed
bun.lock, mixing intentional Studio dependency updates with generated-user-project state that must not be committed.
The existing test named keeps generated apps outside Studio workspace installs currently expects ['.', 'apps/*'], which actually includes every generated app and therefore validates the opposite behavior.
Required solution
1. Restrict the Studio workspace to repository-owned packages
Change the root workspace declaration to an explicit allowlist:
"workspaces": [
".",
"apps/studio"
]
Do not use apps/* and do not maintain dynamic exclusion entries for generated projects.
2. Install every generated app from its own project root
All install/update operations initiated by the Dashboard or host must execute with the generated project directory as cwd:
await runCommand({
command: 'bun',
args: ['install'],
cwd: projectPath,
});
Equivalent CLI behavior:
bun install --cwd <projectPath>
Do not use a root install or workspace --filter, because both retain the shared Studio lockfile boundary.
3. Give each generated app its own installation state
Expected generated project layout:
<projectPath>/
├── package.json
├── bun.lock
├── node_modules/
├── app/
└── infra/
The Studio repository retains only its own bun.lock and node_modules.
4. Run project commands from the same project root
Expo start, dependency updates, type checks, and other app-owned commands must use cwd: projectPath. The Dashboard must never rely on root hoisting for generated apps.
5. Correct and strengthen tests
Update the current workspace test to require:
expect(packageJson.workspaces).toEqual(['.', 'apps/studio']);
expect(packageJson.workspaces).not.toContain('apps/*');
Add host/orchestrator tests asserting that generated app installation:
expect(spawnOptions.cwd).toBe(projectPath);
expect(spawnOptions.cwd).not.toBe(studioRoot);
Also verify that installing or updating a generated app does not modify the Studio root bun.lock, and that the generated app receives its own bun.lock.
6. Keep Studio Knip scoped to repository-owned workspaces
The current Studio Knip config already explicitly declares . and apps/studio; retain that scope. Generated apps should be linted/checked through app-owned commands, not included in Studio repository Knip discovery.
Acceptance criteria
- Root
workspaces contains only . and apps/studio.
- Creating/installing/updating a generated app does not change the Studio root
bun.lock.
- Every generated app has its own
bun.lock and dependency installation.
- Generated app commands execute with
cwd === projectPath.
- Studio CI and Knip do not scan arbitrary generated apps.
- A generated app can be copied outside the Studio checkout, installed, and launched without relying on Studio root
node_modules.
Problem
Generated apps are currently created below
apps/<slug>, while the Studio root declares:The Dashboard also runs
bun installfrom the Studio repository root. As a result, every generated app becomes part of the Studio workspace installation and mutates the repository-levelbun.lock.This causes two architectural and workflow problems:
bun.lock, mixing intentional Studio dependency updates with generated-user-project state that must not be committed.The existing test named
keeps generated apps outside Studio workspace installscurrently expects['.', 'apps/*'], which actually includes every generated app and therefore validates the opposite behavior.Required solution
1. Restrict the Studio workspace to repository-owned packages
Change the root workspace declaration to an explicit allowlist:
Do not use
apps/*and do not maintain dynamic exclusion entries for generated projects.2. Install every generated app from its own project root
All install/update operations initiated by the Dashboard or host must execute with the generated project directory as
cwd:Equivalent CLI behavior:
Do not use a root install or workspace
--filter, because both retain the shared Studio lockfile boundary.3. Give each generated app its own installation state
Expected generated project layout:
The Studio repository retains only its own
bun.lockandnode_modules.4. Run project commands from the same project root
Expo start, dependency updates, type checks, and other app-owned commands must use
cwd: projectPath. The Dashboard must never rely on root hoisting for generated apps.5. Correct and strengthen tests
Update the current workspace test to require:
Add host/orchestrator tests asserting that generated app installation:
Also verify that installing or updating a generated app does not modify the Studio root
bun.lock, and that the generated app receives its ownbun.lock.6. Keep Studio Knip scoped to repository-owned workspaces
The current Studio Knip config already explicitly declares
.andapps/studio; retain that scope. Generated apps should be linted/checked through app-owned commands, not included in Studio repository Knip discovery.Acceptance criteria
workspacescontains only.andapps/studio.bun.lock.bun.lockand dependency installation.cwd === projectPath.node_modules.