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
@@ -4,6 +4,19 @@ Defines what the fos-verifier agent must check after generating or modifying a F
4
4
 
5
5
  ---
6
6
 
7
+ ## Verification Tiers
8
+
9
+ Rules are split into two tiers based on when they apply:
10
+
11
+ | Tier | Rules | When to Run |
12
+ |------|-------|-------------|
13
+ | **Tier 1 (Design)** | S-01–S-03, T-01–T-05, B-01–B-03, C-02–C-04, M-01–M-03 | After every phase |
14
+ | **Tier 2 (SDK)** | I-01–I-04, C-01, C-05, P-01–P-03 | After SDK Integration phase only |
15
+
16
+ To determine the current tier: read `sdkPhase` from `.frontier-app/manifest.json`. If the current phase matches `sdkPhase`, run both Tier 1 and Tier 2. Otherwise, run Tier 1 only. If `sdkPhase` is absent from the manifest, run all checks (backward compatibility).
17
+
18
+ ---
19
+
7
20
  ## Structure Checks
8
21
 
9
22
  These verify the generated file tree matches the standard Frontier OS app layout.
@@ -20,7 +33,7 @@ tsconfig.json
20
33
  vercel.json
21
34
  vite.config.ts
22
35
  src/main.tsx
23
- src/lib/sdk-context.tsx
36
+ src/lib/frontier-services.tsx
24
37
  src/views/Layout.tsx
25
38
  src/styles/index.css
26
39
  ```
@@ -35,7 +48,7 @@ The `src/` directory must contain at minimum:
35
48
  src/
36
49
  main.tsx
37
50
  lib/
38
- sdk-context.tsx
51
+ frontier-services.tsx
39
52
  views/
40
53
  Layout.tsx
41
54
  styles/
@@ -57,6 +70,8 @@ src/
57
70
  components/
58
71
  ```
59
72
 
73
+ > **Note:** `src/lib/sdk-context.tsx` and `src/lib/sdk-services.tsx` exist only **after** the SDK Integration phase (Tier 2). They are not present during pre-integration phases, so S-02 (a Tier-1 check that runs after every phase) must not require them.
74
+
60
75
  **Pass condition:** All required paths exist. Optional paths should be present when the corresponding feature is used (e.g., `router.tsx` when `react-router-dom` is a dependency).
61
76
 
62
77
  ### S-03: No extraneous top-level files
@@ -82,6 +97,8 @@ README.md
82
97
 
83
98
  ## SDK Integration Checks
84
99
 
100
+ > **Tier 2 — SDK Integration phase only.** Skip these checks for all other phases.
101
+
85
102
  These verify the app correctly integrates with the Frontier SDK.
86
103
 
87
104
  ### I-01: isInFrontierApp() call in Layout.tsx
@@ -115,24 +132,26 @@ if (standaloneHtml) {
115
132
  }
116
133
  ```
117
134
 
118
- ### I-03: SdkProvider wrapping children in Layout.tsx
135
+ ### I-03: SdkProvider + FrontierServicesProvider wrapping children in Layout.tsx
119
136
 
120
- When inside the Frontier app, the Layout must wrap its children (either `<Outlet />` or a single component) with `<SdkProvider>`.
137
+ When inside the Frontier app, the Layout must wrap its children with `<SdkProvider>` AND bridge the SDK into `<FrontierServicesProvider>`. Feature code consumes `useServices()`, so without `FrontierServicesProvider` the app **crashes at runtime** ("useServices must be used within FrontierServicesProvider").
121
138
 
122
- **Pass condition:** The return statement for the "in Frontier" case contains:
139
+ **Pass condition:** Layout's "in Frontier" return path contains both providers:
123
140
  ```tsx
124
141
  <SdkProvider>
125
- <Outlet /> {/* or a single component */}
142
+ <SdkServicesBridge> {/* useSdk() createSdkServices(sdk) FrontierServicesProvider */}
143
+ <Outlet />
144
+ </SdkServicesBridge>
126
145
  </SdkProvider>
127
146
  ```
128
147
 
129
148
  ### I-04: useSdk() hook available and used
130
149
 
131
- `src/lib/sdk-context.tsx` must export `useSdk` and `SdkProvider`. Any view component that accesses the SDK must call `useSdk()`.
150
+ `src/lib/sdk-context.tsx` must export `useSdk` and `SdkProvider`. Only `sdk-services.tsx` and `src/views/Layout.tsx` may consume them; feature code under `src/hooks/`, `src/views/`, and `src/components/` accesses the SDK indirectly through `useServices()` (see M-03), never `useSdk()` directly.
132
151
 
133
152
  **Pass condition:**
134
153
  - `sdk-context.tsx` exports `useSdk` and `SdkProvider`.
135
- - Every file that accesses SDK methods imports `useSdk` from `../lib/sdk-context` (or appropriate relative path) and calls it within the component body.
154
+ - `useSdk()` / `SdkProvider` are consumed only by `sdk-services.tsx` and `Layout.tsx`; feature code uses `useServices()` from `../lib/frontier-services` (see M-03), not `useSdk`.
136
155
  - No direct `new FrontierSDK()` calls outside of `sdk-context.tsx`.
137
156
 
138
157
  ---
@@ -141,27 +160,23 @@ When inside the Frontier app, the Layout must wrap its children (either `<Outlet
141
160
 
142
161
  These verify configuration files have the correct content.
143
162
 
144
- ### C-01: vercel.json has all 5 CORS origin blocks
163
+ ### C-01: vercel.json has CORS + CSP frame-ancestors for the 3 origins
145
164
 
146
- The `vercel.json` file must contain exactly 5 header blocks, one for each allowed origin:
165
+ > **Tier 2 SDK Integration phase only.**
147
166
 
148
- 1. `https://os.frontiertower.io`
149
- 2. `https://alpha.os.frontiertower.io`
150
- 3. `https://beta.os.frontiertower.io`
151
- 4. `https://sandbox.os.frontiertower.io`
152
- 5. `http://localhost:5173`
153
-
154
- Each block must include:
155
- - `Access-Control-Allow-Origin` matching the origin
167
+ The `vercel.json` file uses a single unconditional header block containing:
168
+ - `Access-Control-Allow-Origin: https://os.frontiertower.io` (the production origin)
156
169
  - `Access-Control-Allow-Methods: GET, OPTIONS`
157
170
  - `Access-Control-Allow-Headers: Content-Type`
171
+ - `Content-Security-Policy` with `frame-ancestors` listing all 3 live origins (`https://os.frontiertower.io`, `https://sandbox.os.frontiertower.io`, `http://localhost:5173`) — this governs iframe embedding
172
+ - security headers: `X-Content-Type-Options`, `Referrer-Policy`, `Permissions-Policy`
158
173
 
159
174
  It must also include the SPA rewrite:
160
175
  ```json
161
176
  { "source": "/(.*)", "destination": "/index.html" }
162
177
  ```
163
178
 
164
- **Pass condition:** All 5 origin blocks are present with correct headers. The rewrite rule exists.
179
+ **Pass condition:** All 3 origins appear in the `frame-ancestors` directive, the CORS and security headers are present, and the rewrite rule exists.
165
180
 
166
181
  ### C-02: tsconfig.json has strict mode and vitest types
167
182
 
@@ -203,12 +218,12 @@ The `test` script may be omitted if the app has no tests and vitest is not in de
203
218
 
204
219
  **Pass condition:** All listed scripts are present with exact command values. If vitest is in devDependencies, the `test` script must be present.
205
220
 
206
- ### C-05: package.json has required dependencies
221
+ ### C-05a: package.json has required dependencies (Tier 1)
207
222
 
208
223
  The following must be in `dependencies`:
209
- - `@frontiertower/frontier-sdk`
210
224
  - `react`
211
225
  - `react-dom`
226
+ - `react-router-dom` (when the app uses routing)
212
227
 
213
228
  The following must be in `devDependencies`:
214
229
  - `@tailwindcss/postcss`
@@ -219,23 +234,32 @@ The following must be in `devDependencies`:
219
234
  - `tailwindcss`
220
235
  - `typescript`
221
236
  - `vite`
237
+ - `vitest`
222
238
 
223
- When the app uses routing, `react-router-dom` must be in `dependencies`.
224
-
225
- When the app has tests, the following must be in `devDependencies`:
239
+ When the app has tests, the following must also be in `devDependencies`:
226
240
  - `@testing-library/jest-dom`
227
241
  - `@testing-library/react`
228
242
  - `@testing-library/user-event`
229
243
  - `@vitest/coverage-v8`
230
244
  - `jsdom`
231
- - `vitest`
232
245
 
233
246
  **Pass condition:** All listed packages are present in the correct section.
234
247
 
248
+ ### C-05b: package.json has SDK dependency (Tier 2)
249
+
250
+ > **Tier 2 — SDK Integration phase only.**
251
+
252
+ The following must be in `dependencies`:
253
+ - `@frontiertower/frontier-sdk`
254
+
255
+ **Pass condition:** `@frontiertower/frontier-sdk` is present in `dependencies`.
256
+
235
257
  ---
236
258
 
237
259
  ## Permission Checks
238
260
 
261
+ > **Tier 2 — SDK Integration phase only.** Permission checks only apply after the SDK is wired in.
262
+
239
263
  These verify that declared permissions match actual SDK usage.
240
264
 
241
265
  ### P-01: Manifest permissions match SDK method calls
@@ -263,6 +287,7 @@ Method-to-permission mapping follows the pattern:
263
287
  - `sdk.getOffices().<method>()` --> `offices:<method>`
264
288
  - `sdk.getThirdParty().<method>()` --> `thirdParty:<method>`
265
289
  - `sdk.getChain().<method>()` --> `chain:<method>`
290
+ - `sdk.getNavigation().<method>()` --> `navigation:<method>`
266
291
 
267
292
  **Pass condition:** No SDK method is called without the corresponding permission being declared.
268
293
 
@@ -375,30 +400,66 @@ The `@layer base` block must include:
375
400
 
376
401
  ---
377
402
 
403
+ ## Mock Layer Checks
404
+
405
+ > **Tier 1 — Run after every phase** (except Phase 1 scaffold-only verification).
406
+
407
+ ### M-01: frontier-services.tsx exports useServices
408
+
409
+ `src/lib/frontier-services.tsx` must exist and export a `useServices` function.
410
+
411
+ **Pass condition:** `grep -q "export.*useServices" src/lib/frontier-services.tsx`
412
+
413
+ **Severity:** Error
414
+
415
+ ### M-02: createMockServices exported
416
+
417
+ `src/lib/frontier-services.tsx` must export `createMockServices`.
418
+
419
+ **Pass condition:** `grep -q "export.*createMockServices" src/lib/frontier-services.tsx`
420
+
421
+ **Severity:** Error
422
+
423
+ ### M-03: No direct SDK imports in feature code
424
+
425
+ Source files under `src/hooks/`, `src/views/`, and `src/components/` must NOT import from `@frontiertower/frontier-sdk` or `../lib/sdk-context`. Feature code should use `useServices()` from `../lib/frontier-services`.
426
+
427
+ **Pass condition:** No matches for `from.*@frontiertower/frontier-sdk` or `from.*sdk-context` in `src/hooks/`, `src/views/`, `src/components/` (excluding `src/lib/`).
428
+
429
+ **Severity:** Error — indicates feature code bypassing the services abstraction
430
+
431
+ **Note:** This check does NOT apply during the SDK Integration phase, where `sdk-context.tsx` and `sdk-services.tsx` legitimately import from the SDK.
432
+
433
+ ---
434
+
378
435
  ## Summary Checklist
379
436
 
380
- | ID | Category | Rule | Severity |
381
- | ---- | ------------- | --------------------------------------------------- | -------- |
382
- | S-01 | Structure | Required files exist | Error |
383
- | S-02 | Structure | Directory structure matches pattern | Error |
384
- | S-03 | Structure | No extraneous top-level files | Warning |
385
- | I-01 | SDK | isInFrontierApp() call in Layout.tsx | Error |
386
- | I-02 | SDK | createStandaloneHTML() fallback in Layout.tsx | Error |
387
- | I-03 | SDK | SdkProvider wrapping children in Layout.tsx | Error |
388
- | I-04 | SDK | useSdk() hook available and used | Error |
389
- | C-01 | Configuration | vercel.json has all 5 CORS origin blocks | Error |
390
- | C-02 | Configuration | tsconfig.json has strict mode and vitest types | Error |
391
- | C-03 | Configuration | postcss.config.js imports @tailwindcss/postcss | Error |
392
- | C-04 | Configuration | package.json has correct scripts | Error |
393
- | C-05 | Configuration | package.json has required dependencies | Error |
394
- | P-01 | Permissions | Manifest permissions match SDK method calls | Error |
395
- | P-02 | Permissions | No SDK methods called without permission | Error |
396
- | P-03 | Permissions | No unnecessary permissions declared | Warning |
397
- | B-01 | Build | tsc --noEmit passes | Error |
398
- | B-02 | Build | vite build succeeds | Error |
399
- | B-03 | Build | vitest run passes (if tests exist) | Error |
400
- | T-01 | Theme | Dark theme CSS variables defined in index.css | Error |
401
- | T-02 | Theme | body class="dark" in index.html | Error |
402
- | T-03 | Theme | Plus Jakarta Sans font loaded | Error |
403
- | T-04 | Theme | @import "tailwindcss" in index.css | Error |
404
- | T-05 | Theme | Base layer styles present | Error |
437
+ | ID | Category | Rule | Tier | Severity |
438
+ | ----- | ------------- | --------------------------------------------------- | ------ | -------- |
439
+ | S-01 | Structure | Required files exist | Tier 1 | Error |
440
+ | S-02 | Structure | Directory structure matches pattern | Tier 1 | Error |
441
+ | S-03 | Structure | No extraneous top-level files | Tier 1 | Warning |
442
+ | I-01 | SDK | isInFrontierApp() call in Layout.tsx | Tier 2 | Error |
443
+ | I-02 | SDK | createStandaloneHTML() fallback in Layout.tsx | Tier 2 | Error |
444
+ | I-03 | SDK | SdkProvider wrapping children in Layout.tsx | Tier 2 | Error |
445
+ | I-04 | SDK | useSdk() hook available and used | Tier 2 | Error |
446
+ | C-01 | Configuration | vercel.json: CORS + CSP frame-ancestors (3 origins) | Tier 2 | Error |
447
+ | C-02 | Configuration | tsconfig.json has strict mode and vitest types | Tier 1 | Error |
448
+ | C-03 | Configuration | postcss.config.js imports @tailwindcss/postcss | Tier 1 | Error |
449
+ | C-04 | Configuration | package.json has correct scripts | Tier 1 | Error |
450
+ | C-05a | Configuration | package.json has required dependencies | Tier 1 | Error |
451
+ | C-05b | Configuration | package.json has SDK dependency | Tier 2 | Error |
452
+ | M-01 | Mock Layer | frontier-services.tsx exports useServices | Tier 1 | Error |
453
+ | M-02 | Mock Layer | createMockServices exported | Tier 1 | Error |
454
+ | M-03 | Mock Layer | No direct SDK imports in feature code | Tier 1 | Error |
455
+ | P-01 | Permissions | Manifest permissions match SDK method calls | Tier 2 | Error |
456
+ | P-02 | Permissions | No SDK methods called without permission | Tier 2 | Error |
457
+ | P-03 | Permissions | No unnecessary permissions declared | Tier 2 | Warning |
458
+ | B-01 | Build | tsc --noEmit passes | Tier 1 | Error |
459
+ | B-02 | Build | vite build succeeds | Tier 1 | Error |
460
+ | B-03 | Build | vitest run passes (if tests exist) | Tier 1 | Error |
461
+ | T-01 | Theme | Dark theme CSS variables defined in index.css | Tier 1 | Error |
462
+ | T-02 | Theme | body class="dark" in index.html | Tier 1 | Error |
463
+ | T-03 | Theme | Plus Jakarta Sans font loaded | Tier 1 | Error |
464
+ | T-04 | Theme | @import "tailwindcss" in index.css | Tier 1 | Error |
465
+ | T-05 | Theme | Base layer styles present | Tier 1 | Error |