frontier-os-app-builder 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -14
  3. package/agents/fos-executor.md +105 -39
  4. package/agents/fos-plan-checker.md +62 -25
  5. package/agents/fos-planner.md +80 -72
  6. package/agents/fos-researcher.md +26 -15
  7. package/agents/fos-verifier.md +96 -27
  8. package/bin/fos-tools.cjs +146 -42
  9. package/bin/install.js +8 -5
  10. package/commands/fos/add-feature.md +1 -2
  11. package/commands/fos/discuss.md +0 -1
  12. package/commands/fos/new-app.md +2 -4
  13. package/commands/fos/new-milestone.md +1 -1
  14. package/commands/fos/plan.md +0 -2
  15. package/package.json +7 -1
  16. package/references/app-patterns.md +128 -21
  17. package/references/deployment.md +40 -124
  18. package/references/module-index.md +32 -0
  19. package/references/sdk/chain.md +92 -0
  20. package/references/sdk/communities.md +159 -0
  21. package/references/sdk/events.md +212 -0
  22. package/references/sdk/init.md +126 -0
  23. package/references/sdk/navigation.md +49 -0
  24. package/references/sdk/offices.md +76 -0
  25. package/references/sdk/partnerships.md +111 -0
  26. package/references/sdk/storage.md +44 -0
  27. package/references/sdk/thirdparty.md +240 -0
  28. package/references/sdk/token-amount.md +99 -0
  29. package/references/sdk/types.md +27 -0
  30. package/references/sdk/ui-utils.md +39 -0
  31. package/references/sdk/user.md +208 -0
  32. package/references/sdk/wallet.md +334 -0
  33. package/references/verification-rules.md +111 -50
  34. package/templates/app/frontier-services.tsx +871 -0
  35. package/templates/app/layout-standalone.tsx +8 -0
  36. package/templates/app/layout.tsx +19 -9
  37. package/templates/app/package-standalone.json +35 -0
  38. package/templates/app/package.json +2 -1
  39. package/templates/app/public/favicon.svg +3 -0
  40. package/templates/app/sdk-context.tsx +7 -9
  41. package/templates/app/sdk-services.tsx +98 -0
  42. package/templates/app/vercel-standalone.json +5 -0
  43. package/templates/app/vercel.json +8 -95
  44. package/templates/state/plan.md +32 -14
  45. package/templates/state/requirements.md +1 -1
  46. package/templates/state/roadmap.md +57 -24
  47. package/templates/state/summary.md +27 -30
  48. package/workflows/add-feature.md +6 -1
  49. package/workflows/discuss.md +126 -11
  50. package/workflows/execute-plan.md +21 -14
  51. package/workflows/execute.md +204 -24
  52. package/workflows/new-app.md +64 -23
  53. package/workflows/new-milestone.md +10 -3
  54. package/workflows/plan.md +16 -5
  55. package/workflows/ship.md +91 -34
  56. package/workflows/status.md +1 -2
  57. package/references/module-inference.md +0 -349
  58. package/references/sdk-surface.md +0 -1622
  59. package/templates/app/main-simple.tsx +0 -19
  60. package/templates/state/manifest.json +0 -11
@@ -31,6 +31,13 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
31
31
 
32
32
  Parse JSON for: `phase`, `phase_dir`, `plans`, `summaries`, `incomplete_plans`, `all_complete`, `manifest`, `state`, `project_path`, `roadmap_path`, `template_home`, `version`.
33
33
 
34
+ **Generate focused SDK reference for this app's modules:**
35
+ ```bash
36
+ MODULES=$(node -e "const m=JSON.parse(require('fs').readFileSync('.frontier-app/manifest.json','utf8')); console.log(m.modules.join(','))")
37
+ SDK_REF=$(node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" sdk-ref --modules "$MODULES")
38
+ SDK_REF_PATH="${SDK_REF#@file:}"
39
+ ```
40
+
34
41
  **If .frontier-app/ not found:**
35
42
  ```
36
43
  Error: No .frontier-app/ directory found.
@@ -123,22 +130,29 @@ For each plan file in `incomplete_plans`:
123
130
  ```
124
131
  Task(
125
132
  subagent_type="fos-executor",
133
+ isolation="worktree",
126
134
  prompt="
127
135
  <objective>
128
136
  Execute plan [plan_number] of Phase [phase_number]-[phase_name].
129
137
  Commit each task atomically. Create SUMMARY.md when done. Update STATE.md.
130
138
  </objective>
131
139
 
140
+ <parallel_execution>
141
+ You are running as a PARALLEL executor agent. Use --no-verify on all git
142
+ commits to avoid pre-commit hook contention with other agents. The
143
+ orchestrator validates hooks once after all agents complete.
144
+ </parallel_execution>
145
+
132
146
  <execution_context>
133
147
  @$HOME/.claude/frontier-os-app-builder/workflows/execute-plan.md
134
148
  @$HOME/.claude/frontier-os-app-builder/templates/state/summary.md
135
- @$HOME/.claude/frontier-os-app-builder/references/sdk-surface.md
136
149
  @$HOME/.claude/frontier-os-app-builder/references/app-patterns.md
137
150
  @$HOME/.claude/frontier-os-app-builder/references/verification-rules.md
138
151
  </execution_context>
139
152
 
140
153
  <files_to_read>
141
154
  Read these files at execution start using the Read tool:
155
+ - $SDK_REF_PATH (focused SDK reference for this app's modules)
142
156
  - $PHASE_DIR/[plan_file] (The plan to execute)
143
157
  - .frontier-app/PROJECT.md (App vision, SDK modules)
144
158
  - .frontier-app/manifest.json (Permissions)
@@ -164,13 +178,33 @@ For each plan file in `incomplete_plans`:
164
178
  **Completion verification (per plan):**
165
179
  ```bash
166
180
  SUMMARY_FILE="$PHASE_DIR/[plan_prefix]-SUMMARY.md"
167
- test -f "$SUMMARY_FILE" && echo "complete" || echo "incomplete"
181
+ if [ ! -f "$SUMMARY_FILE" ]; then
182
+ echo "incomplete"
183
+ elif grep -q "Self-Check: FAILED" "$SUMMARY_FILE"; then
184
+ echo "self-check-failed"
185
+ else
186
+ echo "complete"
187
+ fi
168
188
  ```
169
189
 
170
- If SUMMARY.md exists and git log shows recent commits for this plan: treat as complete.
171
- If SUMMARY.md missing after agent returns: report as failed.
190
+ - **complete:** SUMMARY.md exists, self-check passed, git log shows recent commits. Treat as successful.
191
+ - **self-check-failed:** SUMMARY.md exists but executor detected issues. Read the SUMMARY.md to extract what failed, then ask:
192
+ - "Retry this plan?" — re-spawn the executor
193
+ - "Fix manually?" — exit with pointer to SUMMARY.md
194
+ - "Continue anyway?" — note the gap for the verifier
195
+ - **incomplete:** SUMMARY.md missing after agent returns. Either the agent crashed or hit a checkpoint (see handle_checkpoints step). Report as failed.
196
+
197
+ 4. **Post-wave hook validation (parallel mode):**
172
198
 
173
- 4. **Report wave completion:**
199
+ When agents committed with `--no-verify`, run pre-commit hooks once after the wave:
200
+ ```bash
201
+ git stash --quiet 2>/dev/null || true
202
+ git hook run pre-commit 2>&1 || echo "Warning: Pre-commit hooks failed — review before continuing"
203
+ git stash pop --quiet 2>/dev/null || true
204
+ ```
205
+ If hooks fail: report the failure and ask "Fix hook issues now?" or "Continue to next wave?"
206
+
207
+ 5. **Report wave completion:**
174
208
 
175
209
  For each completed plan, read its SUMMARY.md and extract:
176
210
  - One-liner description
@@ -189,7 +223,7 @@ For each plan file in `incomplete_plans`:
189
223
  ---
190
224
  ```
191
225
 
192
- 5. **Handle failures:**
226
+ 6. **Handle failures:**
193
227
 
194
228
  If a plan fails:
195
229
  - Report which plan failed and why (from agent output or error)
@@ -199,6 +233,95 @@ For each plan file in `incomplete_plans`:
199
233
  - If stop: save state and exit
200
234
  </step>
201
235
 
236
+ <step name="handle_checkpoints">
237
+ **Handle executor agents that returned checkpoint state instead of completion.**
238
+
239
+ When an executor agent returns a structured checkpoint (output contains `## CHECKPOINT REACHED` and no SUMMARY.md was created), it means a `checkpoint:human-verify` or `checkpoint:decision` task was encountered.
240
+
241
+ **Detection:** After each executor returns in a wave, check:
242
+ - If SUMMARY.md exists for that plan: agent completed normally. Skip this step.
243
+ - If SUMMARY.md does NOT exist AND agent output contains `## CHECKPOINT REACHED`: checkpoint hit.
244
+
245
+ **For each checkpoint:**
246
+
247
+ 1. **Parse the checkpoint return:**
248
+ - Type: `human-verify` or `decision`
249
+ - Plan ID and progress (completed/total tasks)
250
+ - Completed tasks table (with commit hashes)
251
+ - Checkpoint details (what to verify or decide)
252
+ - Awaiting section (what user needs to provide)
253
+
254
+ 2. **Present to user:**
255
+ ```
256
+ ## Checkpoint: [Type]
257
+
258
+ **Plan:** [plan ID] — [plan name]
259
+ **Progress:** [completed]/[total] tasks complete
260
+
261
+ [Checkpoint details from agent return]
262
+
263
+ [Awaiting section from agent return]
264
+ ```
265
+
266
+ Use AskUserQuestion (if available):
267
+ - header: "Checkpoint: [Type]"
268
+ - question: "[Awaiting section content]"
269
+ - If human-verify: options: ["Approved", "Issues found — describe below"]
270
+ - If decision: options from checkpoint details
271
+
272
+ If AskUserQuestion denied: default to "Approved" for human-verify, or the first/recommended option for decisions.
273
+
274
+ 3. **Spawn a FRESH continuation executor:**
275
+
276
+ ```
277
+ Task(
278
+ subagent_type="fos-executor",
279
+ isolation="worktree",
280
+ prompt="
281
+ <objective>
282
+ Continue execution of plan [plan_number], Phase [phase_number]-[phase_name].
283
+ Previous agent completed [N] tasks before hitting a checkpoint.
284
+ Resume from Task [resume_task_number]: [resume_task_name].
285
+ </objective>
286
+
287
+ <completed_tasks>
288
+ [Completed tasks table from checkpoint return — task names + commit hashes]
289
+ </completed_tasks>
290
+
291
+ <user_response>
292
+ [User's response to checkpoint]
293
+ </user_response>
294
+
295
+ <resume_instructions>
296
+ Start from Task [resume_task_number]: [resume_task_name].
297
+ Verify previous commits exist before continuing.
298
+ Do NOT redo completed tasks.
299
+ </resume_instructions>
300
+
301
+ <execution_context>
302
+ @$HOME/.claude/frontier-os-app-builder/workflows/execute-plan.md
303
+ @$HOME/.claude/frontier-os-app-builder/templates/state/summary.md
304
+ @$HOME/.claude/frontier-os-app-builder/references/app-patterns.md
305
+ @$HOME/.claude/frontier-os-app-builder/references/verification-rules.md
306
+ </execution_context>
307
+
308
+ <files_to_read>
309
+ Read these files at execution start using the Read tool:
310
+ - $SDK_REF_PATH (focused SDK reference for this app's modules)
311
+ - $PHASE_DIR/[plan_file] (The plan to execute)
312
+ - .frontier-app/PROJECT.md (App vision, SDK modules)
313
+ - .frontier-app/manifest.json (Permissions)
314
+ - .frontier-app/STATE.md (Current state)
315
+ </files_to_read>
316
+ "
317
+ )
318
+ ```
319
+
320
+ 4. **Wait for continuation agent.** If it hits another checkpoint, repeat from step 1. If it completes (SUMMARY.md created), treat as normal completion.
321
+
322
+ **Why fresh agent, not resume:** Fresh agents with explicit completed-task state are more reliable than attempting to resume a paused agent context.
323
+ </step>
324
+
202
325
  <step name="spawn_verifier">
203
326
  **After all waves complete: verify the phase.**
204
327
 
@@ -211,6 +334,10 @@ Task(
211
334
  Check all success criteria from ROADMAP.md are met.
212
335
  Check all SUMMARY.md files for issues.
213
336
  Run structural and permission validation.
337
+
338
+ Read sdkPhase from manifest.json. If current phase matches sdkPhase, run BOTH
339
+ Tier 1 (standalone app quality) and Tier 2 (SDK integration correctness) checks.
340
+ Otherwise, run Tier 1 checks only.
214
341
  </objective>
215
342
 
216
343
  <files_to_read>
@@ -223,15 +350,19 @@ Task(
223
350
 
224
351
  <verification_commands>
225
352
  Run these checks:
226
- - node '$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs' validate structure
227
- - node '$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs' validate permissions
353
+ - node '$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs' validate structure --phase "$PHASE"
354
+ - node '$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs' validate permissions --phase "$PHASE"
228
355
  - npx tsc --noEmit (if app source exists)
229
356
  - npm run build (if package.json exists)
230
357
  </verification_commands>
231
358
 
232
359
  <output>
233
- Return structured result:
234
- - verdict: PASS or FAIL
360
+ Write VERIFICATION.md to $PHASE_DIR/{phase_num}-VERIFICATION.md using the Write tool,
361
+ following the output_format structure in your agent definition (frontmatter with status,
362
+ verified_date, checks_passed, gaps fields, then full check results by category).
363
+
364
+ Then return structured result to the orchestrator:
365
+ - verdict: PASSED or GAPS_FOUND
235
366
  - criteria_results: each success criterion with pass/fail
236
367
  - gaps: list of gaps found (if any)
237
368
  - suggestions: optional improvements
@@ -240,24 +371,48 @@ Task(
240
371
  )
241
372
  ```
242
373
 
243
- **If verifier returns FAIL:**
374
+ **Parse verifier verdict from VERIFICATION.md:**
375
+ ```bash
376
+ VERIFICATION_FILE="$PHASE_DIR/${PADDED}-VERIFICATION.md"
377
+ VERDICT=$(grep -m1 "^status:" "$VERIFICATION_FILE" | awk '{print $2}')
244
378
  ```
245
- ## Verification Issues
246
379
 
247
- The verifier found [count] issue(s):
380
+ **If verdict is `passed`:**
381
+ Verifier confirmed phase delivers on its promises. Continue to update_state_and_roadmap.
382
+
383
+ **If verdict is `gaps_found`:**
384
+ ```
385
+ ## Verification: Gaps Found
248
386
 
249
- 1. [Issue description]
250
- 2. [Issue description]
387
+ Phase [N]: [Name] — [checks_passed] checks passed, gaps remain.
251
388
 
252
- Options:
253
- - Generate fix plans for these gaps
254
- - Address manually and re-verify
255
- - Accept and move on (gaps noted)
389
+ | # | Check | Issue | Severity |
390
+ |---|-------|-------|----------|
391
+ | 1 | [Check ID] | [What failed] | Blocker/Warning |
392
+ | 2 | [Check ID] | [What failed] | Blocker/Warning |
393
+
394
+ [Gap details from VERIFICATION.md Gaps section]
256
395
  ```
257
396
 
258
- Use AskUserQuestion to let user decide.
397
+ Use AskUserQuestion (if available):
398
+ - header: "Verification Gaps"
399
+ - question: "How do you want to handle these gaps?"
400
+ - options:
401
+ - "Generate gap-closure plans and re-execute" — Creates fix plans, executes them, then re-verifies
402
+ - "Fix manually and re-verify" — You address the issues, then run `/fos:execute [N]` again
403
+ - "Accept with gaps noted" — Mark phase as partial, gaps documented in VERIFICATION.md
404
+
405
+ **If "Generate gap-closure plans":**
406
+ 1. Read the Gaps section from VERIFICATION.md
407
+ 2. Spawn fos-planner with the gap list as context to create targeted fix plans
408
+ 3. Execute the new plans (re-enter execute_waves for the gap-closure plans only)
409
+ 4. Re-run verifier after gap-closure plans complete
259
410
 
260
- **If "Generate fix plans":** Create gap-closure plans in the phase directory and re-execute.
411
+ **If "Fix manually":** Exit with message: "Fix the gaps listed in `$VERIFICATION_FILE`, then run `/fos:execute [N]` to re-verify."
412
+
413
+ **If "Accept with gaps":** Continue to update_state_and_roadmap. Update phase status to "partial" instead of "complete" in STATE.md. Gaps remain documented in VERIFICATION.md.
414
+
415
+ **If AskUserQuestion denied:** Default to "Generate gap-closure plans and re-execute".
261
416
  </step>
262
417
 
263
418
  <step name="update_state_and_roadmap">
@@ -273,11 +428,20 @@ Use AskUserQuestion to let user decide.
273
428
  node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update status "phase-complete"
274
429
  node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update phase "$PHASE"
275
430
 
431
+ # Read sdkPhase from manifest
432
+ SDK_PHASE=$(node -e "const m=JSON.parse(require('fs').readFileSync('.frontier-app/manifest.json','utf8')); console.log(m.sdkPhase || -1)")
433
+
276
434
  # Set next action based on whether more phases remain
277
435
  if [ "$PHASE" -lt "$TOTAL_PHASES" ]; then
278
436
  NEXT_PHASE=$((PHASE + 1))
279
- node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update next_action "/fos:discuss $NEXT_PHASE"
280
- node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update status "ready-to-discuss"
437
+ if [ "$NEXT_PHASE" -eq "$SDK_PHASE" ]; then
438
+ # SDK Integration phase is mechanical — skip discuss, go straight to plan
439
+ node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update next_action "/fos:plan $NEXT_PHASE"
440
+ node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update status "ready-to-plan"
441
+ else
442
+ node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update next_action "/fos:discuss $NEXT_PHASE"
443
+ node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update status "ready-to-discuss"
444
+ fi
281
445
  else
282
446
  node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update next_action "/fos:ship"
283
447
  node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" state update status "milestone-complete"
@@ -317,7 +481,23 @@ Plans completed:
317
481
  - [Plan 01]: [one-liner from SUMMARY.md]
318
482
  - [Plan 02]: [one-liner from SUMMARY.md]
319
483
 
320
- [If more phases remain:]
484
+ [If completed phase was the SDK Integration phase (sdkPhase from manifest.json):]
485
+ ────────────────────────────────────────
486
+ SDK Integration complete. App is now Frontier OS-ready.
487
+ Next up: `/fos:ship` — Deploy to Vercel and register in the Frontier app store.
488
+
489
+ Run `/clear` first to free your context window.
490
+ ────────────────────────────────────────
491
+
492
+ [If more phases remain AND next phase is sdkPhase:]
493
+ ────────────────────────────────────────
494
+ Next up: `/fos:plan [N+1]`
495
+ Plan Phase [N+1]: [Name] — SDK Integration is mechanical, skipping discuss.
496
+
497
+ Run `/clear` first to free your context window.
498
+ ────────────────────────────────────────
499
+
500
+ [If more phases remain (default):]
321
501
  ────────────────────────────────────────
322
502
  Next up: `/fos:discuss [N+1]`
323
503
  Discuss Phase [N+1]: [Name] — capture implementation decisions before planning.
@@ -38,6 +38,14 @@ If you want to start fresh: delete .frontier-app/ and run /fos:new-app again
38
38
  Exit workflow.
39
39
 
40
40
  **If `has_git` is false:** Will initialize git after scaffolding (step 9).
41
+
42
+ **Check for Studio context file:**
43
+ Read `.frontier-studio-context.md` if it exists in the current directory or `../.frontier-studio-context.md` in the parent. This file contains Frontier Tower domain knowledge (floors, membership, events, governance, existing apps) selected by the developer in Frontier Studio. It complements the SDK technical references you already have — use it to inform module inference, domain questions, and requirements throughout the workflow. Skip if the file doesn't exist.
44
+
45
+ **After reading (if it existed):** Delete the file to prevent stale context from leaking into future app creations:
46
+ ```bash
47
+ rm -f .frontier-studio-context.md ../.frontier-studio-context.md
48
+ ```
41
49
  </step>
42
50
 
43
51
  <step name="gather_description">
@@ -50,10 +58,15 @@ Check if `$ARGUMENTS` contains a description (any text that isn't just flags).
50
58
  Building: "[description from arguments]"
51
59
  ```
52
60
 
53
- **If no description:** Use AskUserQuestion:
61
+ **If no description:** Use AskUserQuestion (if available):
54
62
  - header: "App Idea"
55
63
  - question: "What Frontier OS app do you want to build? Describe it in plain language — what it does, who uses it, and what Frontier features it needs."
56
64
 
65
+ If AskUserQuestion is denied (autonomous/don't-ask mode), output an error and exit — a description is required:
66
+ ```
67
+ Error: No app description provided. Usage: /fos:new-app "describe your app"
68
+ ```
69
+
57
70
  **Store the description** for use in subsequent steps.
58
71
  </step>
59
72
 
@@ -125,6 +138,8 @@ Generate 2-5 questions based on WHICH modules were inferred. These are DOMAIN qu
125
138
 
126
139
  **Ask questions one batch at a time** using AskUserQuestion with appropriate options for each. Keep it to ONE round of questions — do not over-interrogate.
127
140
 
141
+ **If AskUserQuestion is denied (autonomous/don't-ask mode):** Skip this step entirely. Use reasonable defaults based on the description and any Studio context file. Briefly state the defaults you're choosing and why, then proceed to confirmation.
142
+
128
143
  **For modules with no specific questions** (Storage, Chain): skip — these are utility modules with standard patterns.
129
144
  </step>
130
145
 
@@ -148,14 +163,15 @@ Incorporate answers from smart questions to refine the module list. If the user'
148
163
 
149
164
  ### Phases Preview
150
165
 
151
- 1. **Phase 1: Scaffold + SDK Core** — Project setup, SdkProvider, iframe detection, dark theme
166
+ 1. **Phase 1: Scaffold + Standalone Shell** — Project setup, services layer, mock data, dark theme
152
167
  2. **Phase 2: [Feature]** — [From description + smart question answers]
153
- 3. **Phase N: [Feature]** — [From description + smart question answers]
168
+ ...
169
+ N. **Phase N: SDK Integration** — Wire SDK, create adapter, upgrade Layout for iframe
154
170
 
155
171
  Total permissions: [N]
156
172
  ```
157
173
 
158
- Use AskUserQuestion:
174
+ Use AskUserQuestion (if available):
159
175
  - header: "Confirm"
160
176
  - question: "Does this look right?"
161
177
  - options:
@@ -165,31 +181,62 @@ Use AskUserQuestion:
165
181
 
166
182
  **If "Change something":** Ask what to change, adjust, and re-confirm.
167
183
  **If "Start over":** Return to step 2.
184
+
185
+ **If AskUserQuestion is denied (autonomous/don't-ask mode):** Display the summary and proceed directly to scaffolding. The user can adjust later via `/fos:add-feature` or by editing manifest.json.
168
186
  </step>
169
187
 
170
188
  <step name="create_app_directory">
171
- **Create the app directory structure.**
189
+ **Create the app directory and project state structure.**
190
+
191
+ Generate the app directory name from the confirmed app name:
192
+ - Kebab-case the name: "Tip Jar" → "tip-jar"
193
+ - Prefix with `frontier-os-app-`: "tip-jar" → "frontier-os-app-tip-jar"
194
+
195
+ If the current directory already IS the app directory (user pre-created it and cd'd in), skip directory creation — just create `.frontier-app/` in place.
196
+
197
+ Otherwise, create the directory and **change into it immediately**:
172
198
 
173
199
  ```bash
174
- APP_DIR=$(pwd)
175
- mkdir -p .frontier-app/phases/01-scaffold
200
+ APP_SLUG="frontier-os-app-[kebab-name]"
201
+ mkdir -p "$APP_SLUG" && cd "$APP_SLUG"
202
+ ```
203
+
204
+ **CRITICAL:** After creating the directory, ALL subsequent commands (file writes, git, scaffold, etc.) MUST use the new app directory as the working directory. Use absolute paths or `cd` into the directory in every Bash call. The `cd` in a single Bash call does NOT persist to subsequent Bash calls — so either:
205
+ - Prefix every Bash command with `cd "$APP_DIR" &&`, or
206
+ - Use absolute paths (`$APP_DIR/.frontier-app/...`) for all file operations
207
+
208
+ Set `APP_DIR` to the absolute path of the new app directory:
209
+ ```bash
210
+ APP_DIR="$(pwd)/$APP_SLUG"
211
+ ```
212
+
213
+ Then create the project state directory:
214
+
215
+ ```bash
216
+ mkdir -p "$APP_DIR/.frontier-app/phases/01-scaffold"
176
217
  ```
177
218
 
178
219
  This creates:
220
+ - `frontier-os-app-[name]/` — The app project directory (auto-created)
179
221
  - `.frontier-app/` — Project state directory
180
222
  - `.frontier-app/phases/01-scaffold/` — Phase 1 directory (always created)
223
+
224
+ **How to detect if already in an app directory:**
225
+ If the user already created and cd'd into a directory named `frontier-os-app-*` that is empty (no files except maybe `.git`), treat it as the app directory and skip creation. Otherwise, create the subdirectory.
181
226
  </step>
182
227
 
183
228
  <step name="create_roadmap">
184
229
  **Build the phased roadmap.**
185
230
 
186
- Phase 1 is ALWAYS "Scaffold + SDK Core" — this is non-negotiable for every Frontier OS app.
231
+ Phase 1 is ALWAYS "Scaffold + Standalone Shell" — this is non-negotiable for every Frontier OS app.
232
+ The LAST phase is ALWAYS "SDK Integration" — a mechanical phase that wires the real Frontier SDK. This phase is auto-added and has fixed success criteria (no user decisions needed). It is non-negotiable.
187
233
 
188
234
  Additional phases come from the features identified in steps 3-5:
189
235
  - Group related features into coherent phases
190
236
  - Each phase should deliver something testable
191
237
  - Keep to 3-6 total phases for v1 — ship fast
192
238
  - Order phases by dependency (features that build on each other)
239
+ - The final phase is always "SDK Integration" — auto-added after all feature phases
193
240
 
194
241
  **Phase sizing heuristics:**
195
242
  - Simple feature (one SDK module, one view): 1 phase, 1-2 plans
@@ -260,10 +307,12 @@ Construct the manifest object:
260
307
  "permissions": ["storage:get", "storage:set", ...all permissions...],
261
308
  "milestone": "v1",
262
309
  "phases": [
263
- {"number": 1, "name": "Scaffold + SDK Core", "status": "not-started"},
310
+ {"number": 1, "name": "Scaffold + Standalone Shell", "status": "not-started"},
264
311
  {"number": 2, "name": "[Feature]", "status": "not-started"},
265
312
  ...
266
- ]
313
+ {"number": N, "name": "SDK Integration", "status": "not-started"}
314
+ ],
315
+ "sdkPhase": N
267
316
  }
268
317
  ```
269
318
 
@@ -273,27 +322,19 @@ Write to `.frontier-app/manifest.json`.
273
322
  <step name="git_init_and_commit">
274
323
  **Initialize git and create initial commit.**
275
324
 
325
+ All commands in this step MUST run inside `$APP_DIR`:
326
+
276
327
  **If `has_git` is false:**
277
328
  ```bash
278
- git init
329
+ cd "$APP_DIR" && git init
279
330
  ```
280
331
 
281
332
  **Create .gitignore if it doesn't exist:**
282
- ```bash
283
- cat > .gitignore << 'GITIGNORE'
284
- node_modules/
285
- dist/
286
- .env
287
- .env.local
288
- *.log
289
- .DS_Store
290
- GITIGNORE
291
- ```
333
+ Write `.gitignore` to `$APP_DIR/.gitignore`.
292
334
 
293
335
  **Commit all state files:**
294
336
  ```bash
295
- git add .frontier-app/ .gitignore
296
- git commit -m "feat: initialize [App Name] — Frontier OS app
337
+ cd "$APP_DIR" && git add .frontier-app/ .gitignore && git commit -m "feat: initialize [App Name] — Frontier OS app
297
338
 
298
339
  SDK Modules: [comma-separated modules]
299
340
  Phases: [count] phases planned for v1
@@ -65,7 +65,7 @@ Create or append to `.frontier-app/MILESTONES.md`:
65
65
 
66
66
  | Phase | Name | Plans | Status |
67
67
  |-------|------|-------|--------|
68
- | 1 | Scaffold + SDK Core | 1/1 | Complete |
68
+ | 1 | Scaffold + Standalone Shell | 1/1 | Complete |
69
69
  | 2 | [Name] | N/N | Complete |
70
70
  | ... | ... | ... | ... |
71
71
 
@@ -91,10 +91,15 @@ Check if `$ARGUMENTS` contains feature descriptions.
91
91
 
92
92
  **If description provided in $ARGUMENTS:** Use it directly.
93
93
 
94
- **If no description:** Use AskUserQuestion:
94
+ **If no description:** Use AskUserQuestion (if available):
95
95
  - header: "New Milestone"
96
96
  - question: "What features should [App Name] [next version] include? Describe the new capabilities you want to add."
97
97
 
98
+ If AskUserQuestion denied: error and exit — a description is required:
99
+ ```
100
+ Error: No feature descriptions provided. Usage: /fos:new-milestone "describe new features"
101
+ ```
102
+
98
103
  Parse the response into individual features. Each feature becomes a candidate for a phase.
99
104
  </step>
100
105
 
@@ -154,13 +159,15 @@ Starting from Phase [N]:
154
159
  - [ ] **Phase [N+2]: [Feature Name]** — [Description]
155
160
  ```
156
161
 
157
- Use AskUserQuestion:
162
+ Use AskUserQuestion (if available):
158
163
  - header: "Confirm"
159
164
  - question: "Does this milestone plan look right?"
160
165
  - options:
161
166
  - "Looks good" — Create the phases
162
167
  - "Change something" — Adjust phases
163
168
  - "Cancel" — Don't start new milestone yet
169
+
170
+ If AskUserQuestion denied: display the plan and proceed with "Looks good".
164
171
  </step>
165
172
 
166
173
  <step name="update_all_state_files">
package/workflows/plan.md CHANGED
@@ -27,6 +27,13 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
27
27
 
28
28
  Parse JSON for: `phase`, `phase_dir`, `has_context`, `has_research`, `existing_plans`, `manifest`, `state`, `project_path`, `roadmap_path`, `template_home`, `version`.
29
29
 
30
+ **Generate focused SDK reference for this app's modules:**
31
+ ```bash
32
+ MODULES=$(node -e "const m=JSON.parse(require('fs').readFileSync('.frontier-app/manifest.json','utf8')); console.log(m.modules.join(','))")
33
+ SDK_REF=$(node "$HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs" sdk-ref --modules "$MODULES")
34
+ SDK_REF_PATH="${SDK_REF#@file:}"
35
+ ```
36
+
30
37
  **If .frontier-app/ not found:**
31
38
  ```
32
39
  Error: No .frontier-app/ directory found.
@@ -52,7 +59,7 @@ Continue anyway? (y/n)
52
59
  ```
53
60
 
54
61
  **If `existing_plans` is not empty:**
55
- Use AskUserQuestion:
62
+ Use AskUserQuestion (if available):
56
63
  - header: "Existing Plans"
57
64
  - question: "Phase [N] already has [count] plan(s). What do you want to do?"
58
65
  - options:
@@ -60,6 +67,8 @@ Use AskUserQuestion:
60
67
  - "View plans" — Show existing plans before deciding
61
68
  - "Keep them" — Skip planning, proceed to execution
62
69
 
70
+ If AskUserQuestion denied: default to "Replan" — delete existing plans and create new ones.
71
+
63
72
  **If "Keep them":** Exit with next-up `/fos:execute N`.
64
73
  **If "Replan":** Continue (plans will be overwritten).
65
74
  </step>
@@ -80,12 +89,12 @@ Task(
80
89
 
81
90
  <execution_context>
82
91
  @$HOME/.claude/frontier-os-app-builder/agents/fos-researcher.md
83
- @$HOME/.claude/frontier-os-app-builder/references/sdk-surface.md
84
92
  @$HOME/.claude/frontier-os-app-builder/references/app-patterns.md
85
93
  </execution_context>
86
94
 
87
95
  <files_to_read>
88
96
  Read these files at execution start using the Read tool:
97
+ - $SDK_REF_PATH (focused SDK reference for this app's modules)
89
98
  - .frontier-app/PROJECT.md (App vision, SDK modules, constraints)
90
99
  - .frontier-app/manifest.json (Declared permissions and metadata)
91
100
  - .frontier-app/ROADMAP.md (Phase goal and requirements)
@@ -124,13 +133,13 @@ Task(
124
133
 
125
134
  <execution_context>
126
135
  @$HOME/.claude/frontier-os-app-builder/templates/state/plan.md
127
- @$HOME/.claude/frontier-os-app-builder/references/sdk-surface.md
128
136
  @$HOME/.claude/frontier-os-app-builder/references/app-patterns.md
129
137
  @$HOME/.claude/frontier-os-app-builder/references/verification-rules.md
130
138
  </execution_context>
131
139
 
132
140
  <files_to_read>
133
141
  Read these files at execution start using the Read tool:
142
+ - $SDK_REF_PATH (focused SDK reference for this app's modules)
134
143
  - .frontier-app/PROJECT.md (App vision, SDK modules, constraints)
135
144
  - .frontier-app/manifest.json (Declared permissions and metadata)
136
145
  - .frontier-app/ROADMAP.md (Phase goal, success criteria, requirements)
@@ -139,8 +148,10 @@ Task(
139
148
  </files_to_read>
140
149
 
141
150
  <planning_rules>
142
- - Phase 1 (Scaffold): ALWAYS exactly 1 plan. Uses templates from templates/app/.
151
+ - Phase 1 (Scaffold + Standalone Shell): ALWAYS exactly 1 plan. Uses standalone templates: `frontier-services.tsx`, `layout-standalone.tsx`, `package-standalone.json`, `main-router.tsx`, `vercel-standalone.json`.
152
+ - SDK Integration phase: ALWAYS exactly 1 plan. Mechanical — adds SDK dependency, creates adapter, upgrades Layout. Minimal research needed.
143
153
  - Feature phases: 1-3 plans. Prefer fewer, larger plans over many small ones.
154
+ - Feature phase tasks reference `useServices()` from `../lib/frontier-services` for all service access. Method names are validated against the focused SDK reference for correctness.
144
155
  - Each plan gets 2-3 tasks. Tasks are atomic — one clear action each.
145
156
  - Wave 1 = no dependencies. Wave 2 = depends on Wave 1. Usually 1 wave is enough.
146
157
  - Vertical slices: Plan 01 = Event listing (hook + component + route), NOT Plan 01 = All hooks.
@@ -192,7 +203,7 @@ Task(
192
203
  5. **Verification:** Does every plan include build + typecheck verification?
193
204
  6. **Dependencies:** Are wave assignments correct? No circular deps?
194
205
  7. **File conflicts:** Do any plans modify the same files in the same wave?
195
- 8. **Frontier compliance:** Dark theme, iframe detection, SdkProvider wrapping — all covered?
206
+ 8. **Tier compliance:** Dark theme, services layer, mock data — all covered? (Tier 1 for feature phases; full SDK check for SDK Integration phase only)
196
207
  </check_criteria>
197
208
 
198
209
  <output>