frontier-os-app-builder 1.0.0 → 1.1.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.
package/README.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Frontier OS App Builder
2
2
 
3
- A meta-prompting framework for building Frontier OS apps with Claude Code. Provides a guided workflow from idea to deployed app, with built-in knowledge of the Frontier SDK, app patterns, and deployment requirements.
3
+ [![npm version](https://img.shields.io/npm/v/frontier-os-app-builder.svg)](https://www.npmjs.com/package/frontier-os-app-builder)
4
+
5
+ A meta-prompting framework for building [Frontier OS](https://os.frontiertower.io) apps with [Claude Code](https://claude.ai/code). Provides a guided workflow from idea to deployed app, with built-in knowledge of the Frontier SDK, app patterns, and deployment requirements.
6
+
7
+ ## Prerequisites
8
+
9
+ - [Claude Code](https://claude.ai/code) installed
10
+ - Node.js 18+
4
11
 
5
12
  ## Install
6
13
 
@@ -16,15 +23,17 @@ To uninstall:
16
23
  npx frontier-os-app-builder --uninstall
17
24
  ```
18
25
 
19
- ## Usage
26
+ ## Quick Start
20
27
 
21
- Create a new directory for your app, then run:
28
+ 1. Create a directory for your new app
29
+ 2. Open Claude Code in that directory
30
+ 3. Run:
22
31
 
23
32
  ```
24
- /fos:new-app "a room booking app for Frontier members"
33
+ /fos:new-app "A tip jar app where members can tip baristas and staff with FND"
25
34
  ```
26
35
 
27
- The framework guides you through each step, telling you when to `/clear` and what command to run next:
36
+ 4. Follow the guided workflow the framework tells you what to do next after each step:
28
37
 
29
38
  ```
30
39
  /fos:new-app "description" → gather requirements, infer SDK modules, create roadmap
@@ -39,6 +48,16 @@ The framework guides you through each step, telling you when to `/clear` and wha
39
48
  /fos:ship → deploy to Vercel + register in app store
40
49
  ```
41
50
 
51
+ 5. Keep building — add features or start a new version:
52
+
53
+ ```
54
+ /fos:add-feature "leaderboard" → adds a new phase to the current milestone
55
+ /clear
56
+ /fos:discuss N → /fos:plan N → /fos:execute N → same loop
57
+
58
+ /fos:new-milestone "v2 features" → archives v1, creates new phases for v2
59
+ ```
60
+
42
61
  ## Commands
43
62
 
44
63
  | Command | Purpose |
@@ -63,20 +82,36 @@ The framework is a multi-layered meta-prompting system:
63
82
  - **References** — built-in Frontier SDK and app pattern knowledge
64
83
  - **Templates** — production-tested boilerplate from existing Frontier OS apps
65
84
 
66
- Each command reads state from `.frontier-app/` on disk, does its work, writes updated state, and tells you what to do next. The `/clear` between steps keeps your context window fresh.
85
+ Each command reads state from `.frontier-app/` on disk, does its work, writes updated state, and tells you what to do next. Running `/clear` between steps keeps your context window fresh — the file-based state bridges the gap.
67
86
 
68
87
  ## Key features
69
88
 
70
- - Infers SDK modules from your app description ("room booking" → Events + Wallet)
71
- - Asks smart domain questions, not generic ones
72
- - Researches patterns from production Frontier OS apps
73
- - Uses proven templates instead of generating code from scratch
74
- - Verifies against Frontier-specific rules (CORS, iframe detection, permissions)
75
- - Milestone system for iterative development (v1 → v2 → v3)
89
+ - **Module inference** describe your app in plain English and the framework maps it to the right SDK modules ("room booking" → Events + Wallet + User)
90
+ - **Smart questions** — asks domain questions ("Should bookings require FND payment?"), not technical ones ("Which SDK modules?")
91
+ - **Production templates** — boilerplate extracted from real Frontier OS apps, not generated from scratch
92
+ - **Frontier-specific verification** checks CORS origins, iframe detection, standalone fallback, SDK permissions, dark theme
93
+ - **Milestones** iterative development with `/fos:new-milestone` for v2, v3, and beyond
76
94
 
77
- ## State
95
+ ## SDK Coverage
78
96
 
79
- All project state lives in `.frontier-app/` as human-readable Markdown and JSON:
97
+ The framework has built-in knowledge of all 10 Frontier SDK modules:
98
+
99
+ | Module | What it does |
100
+ |---|---|
101
+ | Wallet | Balances, FND transfers, token swaps, fiat on/off-ramp |
102
+ | User | Profiles, referrals, KYC, access controls |
103
+ | Events | Event management, room listings, bookings |
104
+ | Communities | Community management, internship passes |
105
+ | Partnerships | Sponsor passes |
106
+ | Offices | Building access passes |
107
+ | Storage | Persistent key-value storage |
108
+ | Chain | Network config, contract addresses |
109
+ | ThirdParty | App registration, webhooks, developer accounts |
110
+ | Navigation | App-to-app deep linking |
111
+
112
+ ## Project State
113
+
114
+ All state lives in `.frontier-app/` as human-readable Markdown and JSON — no database, no server:
80
115
 
81
116
  ```
82
117
  .frontier-app/
@@ -90,3 +125,19 @@ All project state lives in `.frontier-app/` as human-readable Markdown and JSON:
90
125
  ├── 02-feature/
91
126
  └── ...
92
127
  ```
128
+
129
+ ## Example Apps
130
+
131
+ Ideas to get started:
132
+
133
+ | App | Description | SDK Modules |
134
+ |---|---|---|
135
+ | Tip Jar | Members tip baristas with FND | Wallet, User |
136
+ | Visitor Check-in | Kiosk for building access passes | Offices, User |
137
+ | Room Booking | Book coworking rooms with payment | Events, Wallet, User |
138
+ | Event Organizer | Create and manage community events | Events, Communities, User |
139
+ | Sponsor Dashboard | Manage partnership passes | Partnerships, User |
140
+
141
+ ## License
142
+
143
+ MIT
@@ -27,7 +27,26 @@ Before executing, discover project context:
27
27
 
28
28
  <execution_flow>
29
29
 
30
- <step name="load_project_state" priority="first">
30
+ <step name="verify_cwd" priority="first">
31
+ **CRITICAL — Verify working directory before anything else.**
32
+
33
+ When spawned in a worktree, your CWD may be the worktree root, not the app directory. Check:
34
+
35
+ ```bash
36
+ ls .frontier-app/manifest.json 2>/dev/null && echo "CWD OK" || echo "CWD WRONG"
37
+ ```
38
+
39
+ If `CWD WRONG`: look for the app directory inside the current directory. The worktree contains a copy of the repo — `cd` into it:
40
+ ```bash
41
+ # Find the app directory (has .frontier-app/)
42
+ APP_DIR=$(find . -maxdepth 2 -name "manifest.json" -path "*/.frontier-app/*" -exec dirname {} \; | head -1 | sed 's|/.frontier-app||')
43
+ cd "$APP_DIR"
44
+ ```
45
+
46
+ **All subsequent commands and file paths must be relative to the app root (where `.frontier-app/` exists).** Never use absolute worktree paths in git add commands — use paths relative to the repo root (e.g., `git add .frontier-app/phases/01-scaffold/01-01-SUMMARY.md`, NOT `git add frontier-os-app-name/.frontier-app/...`).
47
+ </step>
48
+
49
+ <step name="load_project_state">
31
50
  Load execution context:
32
51
 
33
52
  1. Read `.frontier-app/PROJECT.md` — app name, description, SDK modules
@@ -102,27 +121,42 @@ node $HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs scaffold <template>
102
121
  | Template | Destination |
103
122
  |----------|-------------|
104
123
  | `index.html` | `./index.html` |
105
- | `package.json` | `./package.json` |
124
+ | `package-standalone.json` | `./package.json` |
106
125
  | `postcss.config.js` | `./postcss.config.js` |
107
126
  | `tsconfig.json` | `./tsconfig.json` |
108
- | `vercel.json` | `./vercel.json` |
127
+ | `vercel-standalone.json` | `./vercel.json` |
109
128
  | `vite.config.ts` | `./vite.config.ts` |
110
- | `sdk-context.tsx` | `./src/lib/sdk-context.tsx` |
111
- | `layout.tsx` | `./src/views/Layout.tsx` |
112
- | `main-router.tsx` or `main-simple.tsx` | `./src/main.tsx` |
129
+ | `frontier-services.tsx` | `./src/lib/frontier-services.tsx` |
130
+ | `layout-standalone.tsx` | `./src/views/Layout.tsx` |
131
+ | `main-router.tsx` or `main-simple-standalone.tsx` | `./src/main.tsx` |
113
132
  | `router.tsx` | `./src/router.tsx` |
114
133
  | `index.css` | `./src/styles/index.css` |
115
134
  | `test-setup.ts` | `./src/test/setup.ts` |
116
135
  | `gitignore` | `./.gitignore` |
117
136
 
118
137
  **Critical scaffold requirements:**
119
- - `src/lib/sdk-context.tsx` — NEVER modify after scaffold. Identical across all apps.
120
- - `src/views/Layout.tsx` — Must include `isInFrontierApp()` detection, `createStandaloneHTML()` fallback, `SdkProvider` wrapping children
138
+ - `src/lib/frontier-services.tsx` — Exports `useServices()` with mock backend. Modified only during SDK Integration phase.
139
+ - `src/views/Layout.tsx` — Dark-themed shell wrapping Outlet with FrontierServicesProvider. SdkProvider added during SDK Integration phase.
121
140
  - `src/styles/index.css` — Must include `@import "tailwindcss"`, complete `@theme` block with ALL CSS variables, `@layer base` with body styles
122
141
  - `index.html` — Must have `<body class="dark">`, Plus Jakarta Sans font links
123
- - `vercel.json` — Must have all 5 CORS origin blocks + SPA rewrite
142
+ - `vercel.json` — SPA rewrite only at scaffold time. CORS origins added during SDK Integration phase.
124
143
  - `package.json` — Must have correct scripts (dev, build, preview, lint, test) and all required dependencies
125
144
 
145
+ **Phase 1 scaffold BLOCKLIST — If any of these exist after scaffold, you have a bug. Fix it before committing:**
146
+ - ❌ `src/lib/sdk-context.tsx` — DELETE if created. This file belongs to SDK Integration phase only.
147
+ - ❌ `@frontiertower/frontier-sdk` in package.json — REMOVE from dependencies. SDK is added in SDK Integration phase.
148
+ - ❌ `isInFrontierApp` or `createStandaloneHTML` in Layout.tsx — REWRITE Layout to use simple FrontierServicesProvider + Outlet pattern.
149
+ - ❌ `SdkProvider` anywhere — REPLACE with FrontierServicesProvider.
150
+ - ❌ `useSdk` anywhere — REPLACE with useServices.
151
+ - ❌ Any import from `@frontiertower/frontier-sdk` — REMOVE. The SDK package does not exist in Phase 1.
152
+ - ❌ CORS headers in vercel.json — REMOVE. Use SPA rewrite only.
153
+
154
+ **Self-check after scaffold (run before committing):**
155
+ ```bash
156
+ # All of these must return NO matches. If any match, fix before committing.
157
+ grep -r "sdk-context\|useSdk\|SdkProvider\|@frontiertower/frontier-sdk\|isInFrontierApp\|createStandaloneHTML" src/ package.json vercel.json --include="*.tsx" --include="*.ts" --include="*.json" 2>/dev/null | grep -v node_modules || echo "CLEAN: No SDK artifacts in Phase 1"
158
+ ```
159
+
126
160
  </scaffold_execution>
127
161
 
128
162
  <feature_execution>
@@ -131,29 +165,29 @@ node $HOME/.claude/frontier-os-app-builder/bin/fos-tools.cjs scaffold <template>
131
165
 
132
166
  For feature tasks (Phase 2+), write actual TypeScript/React code.
133
167
 
134
- ### SDK Code Patterns
168
+ ### Services Code Patterns
135
169
 
136
170
  **Always use these exact patterns:**
137
171
 
138
- **Import SDK:**
172
+ **Import services:**
139
173
  ```typescript
140
- import { useSdk } from '../lib/sdk-context';
174
+ import { useServices } from '../lib/frontier-services';
141
175
  ```
142
176
 
143
177
  **Access module:**
144
178
  ```typescript
145
- const sdk = useSdk();
146
- const wallet = sdk.getWallet();
179
+ const services = useServices();
180
+ const wallet = services.wallet;
147
181
  ```
148
182
 
149
183
  **Create hooks with loading/error states:**
150
184
  ```typescript
151
185
  import { useState, useEffect } from 'react';
152
- import { useSdk } from '../lib/sdk-context';
186
+ import { useServices } from '../lib/frontier-services';
153
187
  import type { ReturnType } from '@frontiertower/frontier-sdk';
154
188
 
155
189
  export function useFeature() {
156
- const sdk = useSdk();
190
+ const services = useServices();
157
191
  const [data, setData] = useState<ReturnType | null>(null);
158
192
  const [loading, setLoading] = useState(true);
159
193
  const [error, setError] = useState<string | null>(null);
@@ -161,7 +195,7 @@ export function useFeature() {
161
195
  useEffect(() => {
162
196
  const fetchData = async () => {
163
197
  try {
164
- const result = await sdk.getModule().method();
198
+ const result = await services.module.method();
165
199
  setData(result);
166
200
  } catch (err) {
167
201
  setError(err instanceof Error ? err.message : 'Failed to load data');
@@ -170,7 +204,7 @@ export function useFeature() {
170
204
  }
171
205
  };
172
206
  fetchData();
173
- }, [sdk]);
207
+ }, [services]);
174
208
 
175
209
  return { data, loading, error };
176
210
  }
@@ -224,8 +258,83 @@ Always use these semantic classes (defined in index.css @theme block):
224
258
  - If a type is not exported by the SDK, define a local interface that matches the SDK's return shape
225
259
  - Always use `strict: true` TypeScript
226
260
 
261
+ ### Module Access Reference
262
+
263
+ When accessing modules via `useServices()`, use these property names:
264
+
265
+ | Service Property | Description |
266
+ |-----------------|-------------|
267
+ | `services.wallet` | Wallet operations (balance, transactions, send) |
268
+ | `services.storage` | Storage operations (get, set, delete) |
269
+ | `services.chain` | Chain/blockchain operations |
270
+ | `services.user` | User profile and authentication |
271
+ | `services.partnerships` | Partnerships module |
272
+ | `services.thirdParty` | Third-party integrations |
273
+ | `services.communities` | Communities module |
274
+ | `services.events` | Events module |
275
+ | `services.offices` | Offices module |
276
+ | `services.navigation` | Navigation module |
277
+
227
278
  </feature_execution>
228
279
 
280
+ <frontier_os_rules>
281
+ **CRITICAL — These rules apply to ALL code written for Frontier OS apps.**
282
+
283
+ **Read the current phase and sdkPhase from manifest.json to determine which tier applies.**
284
+
285
+ **TIER 1 — ALL PHASES:**
286
+ 1. **Dark theme:** Tailwind dark theme. Backgrounds: `bg-background`, `bg-card`, `bg-muted-background`. Text: `text-foreground`, `text-card-foreground`, `text-muted-foreground`. No hardcoded colors (no bg-white, text-black, bg-gray-900).
287
+ 2. **Error handling:** All service calls wrapped in try/catch. Loading states for async operations. Error states with user-friendly messages.
288
+ 3. **TypeScript strict:** All code in TypeScript strict mode. No `any` types unless explicitly justified.
289
+ 4. **Testing:** Vitest for unit tests. Test files in `src/test/`.
290
+ 5. **Service access:** Feature phases use `useServices()` from `src/lib/frontier-services.tsx`. Never import SDK directly in feature hooks or views.
291
+ 6. **Mock layer:** Mock services return realistic data matching SDK return types. Hooks must work identically whether backed by mocks or real SDK.
292
+
293
+ **TIER 2 — SDK INTEGRATION PHASE ONLY:**
294
+ 7. **SDK access:** `useSdk()` hook from `src/lib/sdk-context.tsx`, used only inside `sdk-services.tsx` and `Layout.tsx`.
295
+ 8. **Iframe detection:** `isInFrontierApp()` check in Layout.tsx. Standalone mode shows fallback banner.
296
+ 9. **SdkProvider wrapping:** App wrapped in SdkProvider when inside iframe. SDK initialized once via useRef, destroyed on unmount.
297
+ 10. **Permissions:** Every SDK method used must have permission declared in manifest.json.
298
+ 11. **CORS:** vercel.json must include all 3 Frontier OS origins (os.frontiertower.io, sandbox.os.frontiertower.io, localhost:5173).
299
+ 12. **SDK imports:** Use `@frontiertower/frontier-sdk` for SDK classes. Exact import paths, not barrel imports.
300
+ </frontier_os_rules>
301
+
302
+ <sdk_integration_execution>
303
+
304
+ ### SDK Integration Phase Execution
305
+
306
+ For the SDK Integration phase (always the final phase), perform these mechanical operations:
307
+
308
+ **Step 1: Add SDK dependency**
309
+ ```bash
310
+ npm install @frontiertower/frontier-sdk
311
+ ```
312
+
313
+ **Step 2: Create sdk-context.tsx**
314
+ Render from `templates/app/sdk-context.tsx` to `src/lib/sdk-context.tsx`.
315
+ This file is IDENTICAL across all apps — never customize it.
316
+
317
+ **Step 3: Create sdk-services.tsx**
318
+ Render from `templates/app/sdk-services.tsx` to `src/lib/sdk-services.tsx`.
319
+ This adapter maps each `FrontierServices` method to the corresponding `sdk.getModule().method()` call.
320
+
321
+ **Step 4: Upgrade frontier-services.tsx**
322
+ Modify `src/lib/frontier-services.tsx` to add environment detection:
323
+ - Import `isInFrontierApp` from `@frontiertower/frontier-sdk/ui-utils`
324
+ - If in iframe: import and use `createSdkServices` from `./sdk-services`
325
+ - If standalone: use existing `createMockServices()` (no change to mock code)
326
+
327
+ **Step 5: Upgrade Layout.tsx**
328
+ Follow standard Layout pattern from `templates/app/layout.tsx`:
329
+ - Add `isInFrontierApp()` detection
330
+ - Add `createStandaloneHTML()` fallback for standalone mode
331
+ - Wrap children in `SdkProvider` when in iframe
332
+
333
+ **Step 6: Add CORS origins to vercel.json**
334
+ Replace vercel.json with full version from `templates/app/vercel.json` (has all 3 CORS origin blocks plus SPA rewrite).
335
+
336
+ </sdk_integration_execution>
337
+
229
338
  <deviation_rules>
230
339
  **While executing, you WILL discover work not in the plan.** Apply these rules automatically. Track all deviations for Summary.
231
340
 
@@ -239,7 +348,7 @@ No user permission needed for Rules 1-3.
239
348
 
240
349
  **Trigger:** Code doesn't work as intended (broken behavior, errors, incorrect output)
241
350
 
242
- **Examples:** Wrong SDK method call, type errors, null pointer exceptions, broken imports, incorrect hook dependencies, missing await on SDK promises
351
+ **Examples:** Wrong service method call, type errors, null pointer exceptions, broken imports, incorrect hook dependencies, missing await on service promises
243
352
 
244
353
  ---
245
354
 
@@ -247,7 +356,7 @@ No user permission needed for Rules 1-3.
247
356
 
248
357
  **Trigger:** Code missing essential features for correctness, security, or basic operation
249
358
 
250
- **Examples:** Missing error handling on SDK calls, no loading states, missing null checks on SDK responses, no standalone fallback in Layout, missing CORS headers in vercel.json, no dark theme on new components
359
+ **Examples:** Missing error handling on service calls, no loading states, missing null checks on service responses, no dark theme on new components
251
360
 
252
361
  ---
253
362
 
@@ -255,7 +364,7 @@ No user permission needed for Rules 1-3.
255
364
 
256
365
  **Trigger:** Something prevents completing current task
257
366
 
258
- **Examples:** Missing dependency, wrong import path, build error, TypeScript error, missing SDK type export, Vite config issue
367
+ **Examples:** Missing dependency, wrong import path, build error, TypeScript error, missing type export, Vite config issue
259
368
 
260
369
  ---
261
370
 
@@ -263,7 +372,7 @@ No user permission needed for Rules 1-3.
263
372
 
264
373
  **Trigger:** Fix requires significant structural modification
265
374
 
266
- **Examples:** Changing SDK module approach, switching from single view to router, changing state management strategy, adding a new SDK module not in manifest
375
+ **Examples:** Changing service module approach, switching from single view to router, changing state management strategy, adding a new service module not in manifest
267
376
 
268
377
  **Action:** STOP --> return checkpoint with: what found, proposed change, why needed, impact, alternatives. **User decision required.**
269
378
 
@@ -400,11 +509,11 @@ tasks_completed: N/N
400
509
 
401
510
  - [Decision and rationale]
402
511
 
403
- ## SDK Methods Used
512
+ ## Service Methods Used
404
513
 
405
514
  | Method | Module | Permission | Files |
406
515
  |--------|--------|------------|-------|
407
- | getBalanceFormatted() | Wallet | wallet:getBalanceFormatted | src/hooks/useBalance.ts |
516
+ | wallet.getBalanceFormatted() | Wallet | wallet:getBalanceFormatted | src/hooks/useBalance.ts |
408
517
 
409
518
  ## Deviations from Plan
410
519
 
@@ -74,6 +74,8 @@ Then verify each level against the actual plan files.
74
74
  3. Check method signatures match (parameter types, return types)
75
75
  4. Verify the correct module accessor is used (e.g., `getWallet()` not `wallet()`)
76
76
 
77
+ Feature phases access methods via `services.module.method()` (not `sdk.getModule().method()`). The method NAMES are the same — validate against sdk-surface.md for correctness. The import path should be `../lib/frontier-services`, not `../lib/sdk-context`.
78
+
77
79
  **Validation rules:**
78
80
  - Method must exist in @frontier-os-app-builder/references/sdk-surface.md
79
81
  - Module accessor must use the correct getter: `sdk.getWallet()`, `sdk.getStorage()`, etc.
@@ -101,6 +103,8 @@ issue:
101
103
 
102
104
  **Question:** Do SDK methods used in plans have corresponding permissions in manifest.json?
103
105
 
106
+ For feature phases: permission mismatches are severity **warning** (permissions are enforced at SDK Integration). For SDK Integration phase: permission mismatches are severity **blocker** (permissions must match real SDK calls).
107
+
104
108
  **Process:**
105
109
  1. Extract all SDK method calls from plan tasks
106
110
  2. Map each to its required permission using the pattern: `sdk.getModule().method()` --> `module:method`
@@ -147,13 +151,14 @@ issue:
147
151
  - Files outside `src/` that should be inside
148
152
  - Wrong casing (lowercase views, PascalCase hooks)
149
153
  - Tests not in `src/test/`
150
- - SDK-context.tsx modification (it must be identical across apps)
154
+ - Feature phase tasks importing from `sdk-context` instead of `frontier-services`
151
155
 
152
156
  **Red flags:**
153
157
  - `src/components/layout.tsx` (wrong case — should be `Layout.tsx`)
154
158
  - `src/useBalance.ts` (wrong location — should be `src/hooks/useBalance.ts`)
155
159
  - `tests/` at root (wrong — should be `src/test/`)
156
- - Any task modifying `src/lib/sdk-context.tsx`
160
+ - Feature phase task importing from `src/lib/sdk-context` (should be `src/lib/frontier-services`)
161
+ - Any task modifying `src/lib/sdk-context.tsx` (only created during SDK Integration phase)
157
162
 
158
163
  **Example issue:**
159
164
  ```yaml
@@ -176,30 +181,42 @@ issue:
176
181
  - `package.json` (correct scripts, dependencies)
177
182
  - `postcss.config.js` (imports @tailwindcss/postcss)
178
183
  - `tsconfig.json` (strict mode, correct types)
179
- - `vercel.json` (all 5 CORS origins)
184
+ - `vercel.json`
180
185
  - `vite.config.ts`
181
186
  - `src/main.tsx`
182
- - `src/lib/sdk-context.tsx`
183
- - `src/views/Layout.tsx` (with isInFrontierApp, createStandaloneHTML, SdkProvider)
187
+ - `src/lib/frontier-services.tsx` (with `useServices()` export and `createMockServices()` export)
188
+ - `src/views/Layout.tsx` (with `FrontierServicesProvider`)
184
189
  - `src/styles/index.css` (Tailwind import, @theme block with all CSS variables, @layer base)
185
190
  - `.gitignore`
186
191
  2. Check that task actions mention key requirements:
187
- - iframe detection via `isInFrontierApp()`
188
- - Standalone fallback via `createStandaloneHTML()`
189
- - SdkProvider wrapping children
192
+ - `useServices()` export in frontier-services.tsx
193
+ - `createMockServices()` export in frontier-services.tsx
194
+ - `FrontierServicesProvider` wrapping children in Layout
190
195
  - Dark theme CSS variables (all variables from T-01)
191
196
  - Plus Jakarta Sans font loading (T-03)
192
- - 5 CORS origins in vercel.json (C-01)
193
197
  - Correct package.json scripts: dev, build, preview, lint, test (C-04)
194
198
 
199
+ 3. **BLOCKLIST CHECK** — Scan the plan for any of these. If found, it is a **blocker**:
200
+ - ❌ `sdk-context.tsx` referenced as a file to create — belongs to SDK Integration phase only
201
+ - ❌ `@frontiertower/frontier-sdk` in dependencies — SDK not installed until SDK Integration
202
+ - ❌ `isInFrontierApp` or `createStandaloneHTML` in any task action — SDK Integration concerns
203
+ - ❌ `SdkProvider` in any task action — use `FrontierServicesProvider` instead
204
+ - ❌ `useSdk` in any task action — use `useServices` instead
205
+ - ❌ `layout.tsx` template (without `-standalone`) — use `layout-standalone.tsx`
206
+ - ❌ `package.json` template (without `-standalone`) — use `package-standalone.json`
207
+ - ❌ `vercel.json` template (without `-standalone`) — use `vercel-standalone.json`
208
+ - ❌ `main-simple.tsx` template (without `-standalone`) — use `main-simple-standalone.tsx`
209
+
210
+ If the researcher recommended SDK patterns from production apps, the planner should NOT have included them in Phase 1. Flag as blocker with fix hint: "Phase 1 is standalone-first. Remove SDK artifacts and use standalone templates."
211
+
195
212
  **Example issue:**
196
213
  ```yaml
197
214
  issue:
198
215
  dimension: scaffold_completeness
199
216
  severity: blocker
200
- description: "Scaffold plan missing vercel.json creation required for CORS and SPA routing"
217
+ description: "Phase 1 plan creates sdk-context.tsxthis belongs to SDK Integration phase, not scaffold"
201
218
  plan: "01-01"
202
- fix_hint: "Add task or expand existing task to create vercel.json with all 5 CORS origin blocks and SPA rewrite"
219
+ fix_hint: "Remove sdk-context.tsx from plan. Phase 1 uses frontier-services.tsx for the services layer."
203
220
  ```
204
221
 
205
222
  ## Dimension 5: Task Completeness
@@ -227,7 +244,7 @@ issue:
227
244
  issue:
228
245
  dimension: task_completeness
229
246
  severity: blocker
230
- description: "Task 2 action says 'create payment handler' without specifying which SDK method (payWithFrontierDollar? transferOverallFrontierDollar?)"
247
+ description: "Task 2 action says 'create payment handler' without specifying which SDK method (transferFrontierDollar? transferOverallFrontierDollar?)"
231
248
  plan: "02-01"
232
249
  task: 2
233
250
  fix_hint: "Specify exact SDK method, parameters, return type, and error handling in action"
@@ -244,13 +261,14 @@ issue:
244
261
 
245
262
  **Frontier OS specific wiring patterns:**
246
263
  ```
247
- Hook --> Component: Does a view import and call the hook?
248
- Component --> SdkProvider: Is the view rendered inside SdkProvider?
249
- SDK call --> Error handling: Does the action mention try/catch?
250
- Router --> View: Does the router import the view component?
251
- Layout --> SdkProvider: Does Layout wrap children with SdkProvider?
264
+ Hook --> Component: Does view import and call hook?
265
+ Hook --> Services: Does hook import useServices() from frontier-services?
266
+ Service call --> Error handling: Does action mention try/catch?
267
+ Router --> View: Does router import view component?
252
268
  ```
253
269
 
270
+ Note: SdkProvider wiring is checked only for SDK Integration phase plans.
271
+
254
272
  **Red flags:**
255
273
  - Hook created but no view imports it
256
274
  - View created but not added to router
@@ -329,6 +347,23 @@ issue:
329
347
  - Test files in wrong location
330
348
  - Test task with vague action ("write tests") instead of specific test cases
331
349
 
350
+ ## Dimension 10: SDK Integration Phase Completeness
351
+
352
+ **Applies to:** SDK Integration phase plans only. Skip for feature phase plans.
353
+
354
+ **Question:** Does the plan cover all mechanical steps for SDK Integration?
355
+
356
+ **Checklist:**
357
+ 1. Plan includes task to add `@frontiertower/frontier-sdk` dependency (`npm install`)
358
+ 2. Plan includes task to create `src/lib/sdk-context.tsx` from template
359
+ 3. Plan includes task to create `src/lib/sdk-services.tsx` adapter
360
+ 4. Plan includes task to upgrade `src/lib/frontier-services.tsx` with environment detection
361
+ 5. Plan includes task to upgrade `src/views/Layout.tsx` with iframe detection + SdkProvider
362
+ 6. Plan includes task to add CORS origins to `vercel.json`
363
+ 7. Plan includes verification task (build, typecheck, full validation)
364
+
365
+ **Severity:** blocker for any missing step — SDK Integration is standardized and every step is required.
366
+
332
367
  </verification_dimensions>
333
368
 
334
369
  <output_format>
@@ -357,6 +392,7 @@ Return structured PASS/FAIL with issues list:
357
392
  | 7 | Context Compliance | PASS/FAIL/N/A | [count] |
358
393
  | 8 | Scope Sanity | PASS/FAIL | [count] |
359
394
  | 9 | Test Coverage | PASS/FAIL | [count] |
395
+ | 10 | SDK Integration Completeness | PASS/FAIL/N/A | [count] |
360
396
 
361
397
  ### Issues
362
398