Skip to content

Commit 7746688

Browse files
authored
refactor platform control boundaries (#150)
1 parent 61a9026 commit 7746688

27 files changed

Lines changed: 696 additions & 200 deletions

AGENTS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ This file provides guidance to Codex (Codex.ai/code) when working with code in t
4444
- Use TypeScript strict mode
4545
- Always follow best practices
4646
- Write self-documenting code: for complex functions, describe purpose, expected inputs, and expected outputs above the function
47+
- In `lib/platform/`, prefer one primary action per file. Use noun directories and verb file names, and add a short boundary comment above the main exported function covering purpose, expected inputs/preconditions, expected outputs/guarantees, and what is out of scope.
4748
- Use functional components with hooks
4849

4950
### Naming Conventions
@@ -52,6 +53,7 @@ This file provides guidance to Codex (Codex.ai/code) when working with code in t
5253
- Database tables: PascalCase (Prisma models)
5354
- API routes: kebab-case
5455
- Files: kebab-case
56+
- In `lib/platform/`, file names should usually be action-oriented verbs such as `create-project-with-sandbox`, `find-installation-repository`, or `get-user-default-namespace`, rather than vague names like `shared` or `helpers`.
5557

5658
### Component Organization
5759
- **Route-specific components**: Place in `_components/` directory under the route folder

docs/architecture-evolution.md

Lines changed: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -129,30 +129,32 @@ This layer should be the only place that knows provider-specific protocol detail
129129

130130
## Ideal Repository Shape
131131

132-
The repository should gradually move toward something like this:
132+
The repository should gradually move toward a platform-shaped layout, with
133+
`lib/platform/` acting as the main container for control-plane code:
133134

134135
```text
135136
app/
136137
Framework entrypoints only
137138
138139
lib/
139140
domain/
140-
control/
141-
commands/
142-
queries/
143-
persistence/
144-
orchestrators/
145-
resources/
146-
tasks/
147-
executors/
148-
k8s/
149-
sandbox/
150-
deploy/
151-
integrations/
152-
github/
153-
ttyd/
154-
k8s/
155-
aiproxy/
141+
platform/
142+
control/
143+
commands/
144+
queries/
145+
persistence/
146+
orchestrators/
147+
resources/
148+
tasks/
149+
executors/
150+
k8s/
151+
sandbox/
152+
deploy/
153+
integrations/
154+
github/
155+
ttyd/
156+
k8s/
157+
aiproxy/
156158
policies/
157159
shared/
158160
```
@@ -206,7 +208,7 @@ Typical examples:
206208

207209
This is the layer that turns interaction into durable state changes.
208210

209-
### `lib/persistence/`
211+
### `lib/platform/persistence/`
210212

211213
Should contain:
212214

@@ -215,9 +217,11 @@ Should contain:
215217
- lock management
216218
- state transition persistence
217219

218-
This corresponds closely to what `lib/repo/` does today, but with a name that better reflects its role in a control-plane system.
220+
This corresponds closely to what `lib/repo/` does today, but relocated under
221+
`platform/` so the control plane and its persistence boundaries live in one
222+
coherent top-level area.
219223

220-
### `lib/orchestrators/`
224+
### `lib/platform/orchestrators/`
221225

222226
Should contain:
223227

@@ -230,7 +234,7 @@ This layer is currently spread across `jobs/` and `events/`.
230234

231235
Long term, the code should make it easy to inspect one workflow in one place, instead of hopping across multiple implementation-mechanism directories.
232236

233-
### `lib/executors/`
237+
### `lib/platform/executors/`
234238

235239
Should contain:
236240

@@ -247,7 +251,7 @@ The key separation is:
247251
- orchestrators decide whether to run
248252
- executors perform the work
249253

250-
### `lib/integrations/`
254+
### `lib/platform/integrations/`
251255

252256
Should contain:
253257

@@ -307,6 +311,46 @@ It is to make the codebase reflect the platform's actual conceptual boundaries:
307311
- execution
308312
- external integration
309313

314+
### Rule 6: Prefer one primary platform action per file
315+
316+
Within `lib/platform/`, prefer files that exist to express one primary platform action.
317+
318+
Examples:
319+
320+
- `create-project-from-github.ts`
321+
- `create-clone-repository-task.ts`
322+
- `find-installation-repository.ts`
323+
- `get-user-default-namespace.ts`
324+
325+
This improves scanability. A reader should be able to infer the main responsibility
326+
of a file from its name before opening it.
327+
328+
### Rule 7: Use noun directories and verb file names
329+
330+
Within `lib/platform/`:
331+
332+
- directories should describe the boundary or subsystem
333+
- files should describe the primary action they perform
334+
335+
Examples:
336+
337+
- good directory names: `control`, `persistence`, `integrations`, `project-task`
338+
- good file names: `create-project-with-sandbox`, `create-clone-repository-task`, `find-github-installation-by-id`
339+
- weaker file names: `shared`, `github`, `repository-access`, `user-namespace`
340+
341+
### Rule 8: Primary platform functions must carry boundary comments
342+
343+
If a file in `lib/platform/` exists to perform one primary action, its main exported
344+
function should have a short comment that explains:
345+
346+
- purpose
347+
- expected inputs or preconditions
348+
- expected outputs or guarantees
349+
- what is explicitly out of scope
350+
351+
The goal is not comment volume. The goal is to make the file's architectural role
352+
obvious without reading the full implementation.
353+
310354
## Suggested Migration Strategy
311355

312356
The next phase should be gradual.

docs/prds/README.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# PRDs
2+
3+
This directory stores implementation-facing product requirement documents for the
4+
current Fulling codebase.
5+
6+
## What belongs here
7+
8+
Put documents here when they define product behavior that directly affects:
9+
10+
- control-plane state
11+
- UI-visible status semantics
12+
- retry behavior
13+
- persistence requirements
14+
- API or workflow expectations for a concrete feature
15+
16+
Examples:
17+
18+
- import project control flow
19+
- deploy project workflow
20+
- install skill behavior
21+
- database creation UX and state semantics
22+
23+
## What does not belong here
24+
25+
Do not put high-level strategy, roadmap thinking, or long-range architecture vision here.
26+
Those should stay in the handbook project space.
27+
28+
Recommended split:
29+
30+
- `handbook/projects/fulling/`
31+
- vision
32+
- roadmap
33+
- version plans
34+
- postmortems
35+
- architecture direction
36+
- `docs/prds/`
37+
- implementation-facing feature requirements for the repository
38+
39+
## Naming
40+
41+
- One PRD per feature or workflow
42+
- Use stable kebab-case file names
43+
- Prefer names like `import-project-control-flow.md`
44+
45+
## Suggested PRD structure
46+
47+
Each PRD should usually include:
48+
49+
1. Goal
50+
2. Scope
51+
3. Success semantics
52+
4. Failure semantics
53+
5. State requirements
54+
6. UI requirements
55+
7. Retry behavior
56+
8. Persistence requirements
57+
9. Non-goals
58+
59+
## Current PRDs
60+
61+
- [Import Project Control Flow](./import-project-control-flow.md)
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Import Project Control Flow
2+
3+
Status: Draft
4+
5+
## Goal
6+
7+
Define the product behavior and control-plane semantics for importing a GitHub
8+
repository as a Fulling project.
9+
10+
This PRD exists to clarify what "success" means for:
11+
12+
- project creation
13+
- sandbox creation
14+
- repository cloning
15+
- import failure handling
16+
17+
## Scope
18+
19+
This document covers the current import flow for:
20+
21+
- creating a project from a GitHub repository
22+
- creating the initial sandbox for that project
23+
- cloning the selected repository into the sandbox
24+
- representing clone failure without rolling back the project
25+
26+
This document does not define future repository analysis, skill installation, or
27+
deploy automation after import.
28+
29+
## User Intent
30+
31+
When a user imports a project from GitHub, the system receives two requested outcomes:
32+
33+
1. Create and start a sandbox for the project
34+
2. Clone the selected GitHub repository into that sandbox
35+
36+
These two outcomes are related, but they are not treated as a single all-or-nothing
37+
product success condition.
38+
39+
## Success Semantics
40+
41+
### Project creation success
42+
43+
A project is considered successfully created when its sandbox is successfully created
44+
and reaches a runnable state.
45+
46+
This means:
47+
48+
- if sandbox creation succeeds, project creation succeeds
49+
- project success is not blocked by repository clone failure
50+
51+
### Import transaction success
52+
53+
The import transaction is considered successful only when the repository is cloned
54+
successfully into the sandbox.
55+
56+
## Failure Semantics
57+
58+
### Sandbox creation failure
59+
60+
If the sandbox fails to reach a runnable state, project creation is considered failed.
61+
62+
### Repository clone failure
63+
64+
If the sandbox succeeds but repository cloning fails, the system must:
65+
66+
- keep the project
67+
- keep the sandbox
68+
- mark the import transaction as failed
69+
- preserve the GitHub association metadata on the project
70+
71+
Clone failure does not roll back the project.
72+
73+
Examples of clone failure include:
74+
75+
- repository does not exist
76+
- repository access is denied
77+
- clone operation times out
78+
- GitHub access token or upstream operation fails
79+
80+
## Current UX Requirements
81+
82+
For the current stage of the product:
83+
84+
- the user should still land in a usable project with an empty sandbox
85+
- no dedicated import-failure modal is required yet
86+
- the system should preserve existing code paths as much as possible
87+
88+
## Status Requirements
89+
90+
The system should represent two layers of status:
91+
92+
1. Project resource status
93+
2. Import transaction status
94+
95+
For the current product behavior:
96+
97+
- project status may become `RUNNING`
98+
- import may independently become `IMPORT_FAILED`
99+
100+
The intended current UI meaning is:
101+
102+
- `RUNNING + IMPORT FAILED`
103+
104+
This combination means:
105+
106+
- the sandbox is available
107+
- the project exists and is usable
108+
- the requested repository import did not complete successfully
109+
110+
## Retry Behavior
111+
112+
Repository clone should automatically retry up to 3 times, matching the current system behavior.
113+
114+
Requirements:
115+
116+
- retries are automatic
117+
- no manual retry UX is required in this phase
118+
- exhausting retries should leave the project intact and mark import as failed
119+
120+
## Persistence Requirements
121+
122+
The system must persist enough state to represent:
123+
124+
- that the project exists
125+
- that the sandbox exists
126+
- that the project was created from GitHub
127+
- that the clone task was attempted
128+
- whether the clone task eventually succeeded or failed
129+
130+
If clone fails, the database must still clearly reflect:
131+
132+
- project creation succeeded
133+
- import did not succeed
134+
135+
## GitHub Metadata Requirements
136+
137+
If the repository later becomes unavailable or permissions change, the project should
138+
continue to retain its GitHub association metadata.
139+
140+
This means clone failure or later repository access loss should not automatically clear:
141+
142+
- GitHub installation reference
143+
- GitHub repository ID
144+
- GitHub repository full name
145+
- default branch metadata
146+
147+
## Non-Goals
148+
149+
This PRD does not define:
150+
151+
- a new import intent model
152+
- a dedicated import failure modal
153+
- post-import repository analysis
154+
- skill installation after import
155+
- deployment after import
156+
- new manual retry workflows
157+
158+
## Implementation Notes
159+
160+
Current implementation should preserve this product contract:
161+
162+
- project creation success is anchored to sandbox success
163+
- clone failure is visible as an import failure, not as project creation failure
164+
- import logic may fail independently after the project already exists

0 commit comments

Comments
 (0)