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
package/bin/fos-tools.cjs CHANGED
@@ -10,7 +10,7 @@ const { execSync } = require('child_process');
10
10
  // Usage: node fos-tools.cjs <command> [args] [--raw] [--pick <field>]
11
11
  // ─────────────────────────────────────────────
12
12
 
13
- const VERSION = '1.0.0';
13
+ const VERSION = '1.2.0';
14
14
 
15
15
  // ── Helpers ──────────────────────────────────
16
16
 
@@ -270,9 +270,9 @@ const MODULE_KEYWORDS = {
270
270
  'withdraw', 'off-ramp', 'bank', 'fiat', 'subscription', 'billing', 'price',
271
271
  'cost', 'fee', 'tip', 'donate', 'donation'],
272
272
  getter: 'sdk.getWallet()',
273
- commonMethods: ['getBalance', 'getBalanceFormatted', 'transferFrontierDollar', 'payWithFrontierDollar'],
274
- permissions: ['wallet:getBalance', 'wallet:getBalanceFormatted', 'wallet:getAddress',
275
- 'wallet:transferFrontierDollar', 'wallet:payWithFrontierDollar']
273
+ commonMethods: ['getBalance', 'transferFrontierDollar', 'transferOverallFrontierDollar'],
274
+ permissions: ['wallet:getBalance', 'wallet:getAddress',
275
+ 'wallet:transferFrontierDollar', 'wallet:transferOverallFrontierDollar']
276
276
  },
277
277
  User: {
278
278
  keywords: ['user', 'profile', 'account', 'member', 'membership', 'auth', 'login',
@@ -287,9 +287,11 @@ const MODULE_KEYWORDS = {
287
287
  'reserve', 'reservation', 'space', 'venue', 'location', 'conference',
288
288
  'meeting', 'coworking'],
289
289
  getter: 'sdk.getEvents()',
290
- commonMethods: ['listEvents', 'createEvent', 'listLocations', 'createRoomBooking'],
290
+ commonMethods: ['listEvents', 'createEvent', 'listLocations', 'createRoomBooking',
291
+ 'getCryptoDepositPreflight', 'placeCryptoDeposit'],
291
292
  permissions: ['events:listEvents', 'events:createEvent', 'events:listLocations',
292
- 'events:listRoomBookings', 'events:createRoomBooking']
293
+ 'events:listRoomBookings', 'events:createRoomBooking',
294
+ 'events:getCryptoDepositPreflight', 'events:placeCryptoDeposit']
293
295
  },
294
296
  Communities: {
295
297
  keywords: ['community', 'group', 'team', 'club', 'internship', 'intern', 'cohort',
@@ -415,8 +417,21 @@ function cmdValidateStructure(cwd, flags) {
415
417
  const issues = [];
416
418
  const checks = [];
417
419
 
418
- const requiredFiles = [
419
- 'src/lib/sdk-context.tsx',
420
+ // Determine verification tier from manifest sdkPhase
421
+ const manifest = loadManifest(cwd);
422
+ const sdkPhase = manifest && manifest.sdkPhase != null ? manifest.sdkPhase : null;
423
+ const currentPhase = flags.phase != null && Number.isInteger(+flags.phase) ? +flags.phase : null;
424
+ // Fallback to STATE.md phase when --phase not passed, so the Tier-2 gate works even if a caller forgets the flag
425
+ const fallbackPhase = flags.phase == null ? (loadState(cwd)?.frontmatter?.phase ?? null) : null;
426
+ const effectivePhase = currentPhase ?? fallbackPhase;
427
+ // Tier 2 only when sdkPhase is set AND current phase matches sdkPhase
428
+ const isTier2 = sdkPhase != null && effectivePhase != null && effectivePhase === sdkPhase;
429
+ // Backward compat: if no sdkPhase in manifest, run all checks (legacy SDK-first apps)
430
+ const isLegacy = sdkPhase == null;
431
+
432
+ // Tier 1 required files (always checked)
433
+ const tier1Files = [
434
+ 'src/lib/frontier-services.tsx',
420
435
  'src/views/Layout.tsx',
421
436
  'src/main.tsx',
422
437
  'src/styles/index.css',
@@ -428,42 +443,74 @@ function cmdValidateStructure(cwd, flags) {
428
443
  'package.json'
429
444
  ];
430
445
 
446
+ // Tier 2 / legacy additional required files
447
+ const tier2Files = [
448
+ 'src/lib/sdk-context.tsx',
449
+ 'src/lib/sdk-services.tsx'
450
+ ];
451
+
452
+ // Legacy apps use sdk-context.tsx instead of frontier-services.tsx
453
+ const requiredFiles = isLegacy
454
+ ? ['src/lib/sdk-context.tsx', 'src/views/Layout.tsx', 'src/main.tsx', 'src/styles/index.css', 'vite.config.ts', 'tsconfig.json', 'postcss.config.js', 'vercel.json', 'index.html', 'package.json']
455
+ : isTier2
456
+ ? [...tier1Files, ...tier2Files]
457
+ : tier1Files;
458
+
431
459
  for (const file of requiredFiles) {
432
460
  const exists = fs.existsSync(path.join(cwd, file));
433
461
  checks.push({ file, exists });
434
462
  if (!exists) issues.push(`Missing required file: ${file}`);
435
463
  }
436
464
 
437
- // Check vercel.json has all 5 CORS origins
438
- const vercelPath = path.join(cwd, 'vercel.json');
439
- if (fs.existsSync(vercelPath)) {
440
- const vercel = readFile(vercelPath);
441
- const origins = [
442
- 'http://localhost:5173',
443
- 'https://sandbox.os.frontiertower.io',
444
- 'https://alpha.os.frontiertower.io',
445
- 'https://beta.os.frontiertower.io',
446
- 'https://os.frontiertower.io'
447
- ];
448
- for (const origin of origins) {
449
- if (!vercel.includes(origin)) {
450
- issues.push(`vercel.json missing CORS origin: ${origin}`);
465
+ // CORS origin checks Tier 2 or legacy only
466
+ if (isLegacy || isTier2) {
467
+ const vercelPath = path.join(cwd, 'vercel.json');
468
+ if (fs.existsSync(vercelPath)) {
469
+ const vercel = readFile(vercelPath);
470
+ const origins = [
471
+ 'http://localhost:5173',
472
+ 'https://sandbox.os.frontiertower.io',
473
+ 'https://os.frontiertower.io'
474
+ ];
475
+ for (const origin of origins) {
476
+ if (!vercel.includes(origin)) {
477
+ issues.push(`vercel.json missing CORS origin: ${origin}`);
478
+ }
451
479
  }
452
480
  }
453
481
  }
454
482
 
455
- // Check Layout.tsx has iframe detection
456
- const layoutPath = path.join(cwd, 'src/views/Layout.tsx');
457
- if (fs.existsSync(layoutPath)) {
458
- const layout = readFile(layoutPath);
459
- if (!layout.includes('isInFrontierApp')) {
460
- issues.push('Layout.tsx missing isInFrontierApp() check');
461
- }
462
- if (!layout.includes('createStandaloneHTML') && !layout.includes('renderStandaloneMessage')) {
463
- issues.push('Layout.tsx missing standalone fallback');
483
+ // Layout SDK checks — Tier 2 or legacy only
484
+ if (isLegacy || isTier2) {
485
+ const layoutPath = path.join(cwd, 'src/views/Layout.tsx');
486
+ if (fs.existsSync(layoutPath)) {
487
+ const layout = readFile(layoutPath);
488
+ if (!layout.includes('isInFrontierApp')) {
489
+ issues.push('Layout.tsx missing isInFrontierApp() check');
490
+ }
491
+ if (!layout.includes('createStandaloneHTML') && !layout.includes('renderStandaloneMessage')) {
492
+ issues.push('Layout.tsx missing standalone fallback');
493
+ }
494
+ if (!layout.includes('SdkProvider')) {
495
+ issues.push('Layout.tsx missing SdkProvider wrapping');
496
+ }
497
+ if (!layout.includes('FrontierServicesProvider')) {
498
+ issues.push('Layout.tsx missing FrontierServicesProvider bridge (useServices() will crash at runtime)');
499
+ }
464
500
  }
465
- if (!layout.includes('SdkProvider')) {
466
- issues.push('Layout.tsx missing SdkProvider wrapping');
501
+ }
502
+
503
+ // Mock layer checks — Tier 1 only (non-legacy apps)
504
+ if (!isLegacy) {
505
+ const servicesPath = path.join(cwd, 'src/lib/frontier-services.tsx');
506
+ if (fs.existsSync(servicesPath)) {
507
+ const services = readFile(servicesPath);
508
+ if (!services.includes('useServices')) {
509
+ issues.push('frontier-services.tsx missing useServices export');
510
+ }
511
+ if (!services.includes('createMockServices')) {
512
+ issues.push('frontier-services.tsx missing createMockServices export');
513
+ }
467
514
  }
468
515
  }
469
516
 
@@ -486,7 +533,8 @@ function cmdValidateStructure(cwd, flags) {
486
533
  pass: issues.length === 0,
487
534
  checks,
488
535
  issues,
489
- checkedFiles: requiredFiles.length
536
+ checkedFiles: requiredFiles.length,
537
+ tier: isLegacy ? 'legacy' : isTier2 ? 2 : 1
490
538
  }, flags);
491
539
  }
492
540
 
@@ -495,9 +543,19 @@ function cmdValidatePermissions(cwd, flags) {
495
543
  if (!manifest) error('.frontier-app/manifest.json not found');
496
544
 
497
545
  const issues = [];
546
+ const warnings = [];
498
547
  const srcDir = path.join(cwd, 'src');
499
548
 
500
- // Find all SDK method calls in source
549
+ // Determine tier
550
+ const sdkPhase = manifest.sdkPhase != null ? manifest.sdkPhase : null;
551
+ const currentPhase = flags.phase != null && Number.isInteger(+flags.phase) ? +flags.phase : null;
552
+ // Fallback to STATE.md phase when --phase not passed, so the Tier-2 gate works even if a caller forgets the flag
553
+ const fallbackPhase = flags.phase == null ? (loadState(cwd)?.frontmatter?.phase ?? null) : null;
554
+ const effectivePhase = currentPhase ?? fallbackPhase;
555
+ const isTier2 = sdkPhase != null && effectivePhase != null && effectivePhase === sdkPhase;
556
+ const isLegacy = sdkPhase == null;
557
+
558
+ // Find all SDK method calls in source (both patterns)
501
559
  const usedMethods = new Set();
502
560
  function scanDir(dir) {
503
561
  if (!fs.existsSync(dir)) return;
@@ -506,9 +564,21 @@ function cmdValidatePermissions(cwd, flags) {
506
564
  scanDir(path.join(dir, entry.name));
507
565
  } else if (entry.isFile() && (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx'))) {
508
566
  const content = readFile(path.join(dir, entry.name));
509
- // Match sdk.getX().methodName() or getX().methodName() patterns
510
- const calls = content.match(/\.(getWallet|getUser|getStorage|getChain|getEvents|getCommunities|getPartnerships|getOffices|getThirdParty)\(\)\.\w+/g);
511
- if (calls) calls.forEach(c => usedMethods.add(c.slice(1)));
567
+ // Match sdk.getX().methodName() or getX().methodName() patterns (legacy/SDK phase)
568
+ const sdkCalls = content.match(/\.(getWallet|getUser|getStorage|getChain|getEvents|getCommunities|getPartnerships|getOffices|getThirdParty|getNavigation)\(\)\.\w+/g);
569
+ if (sdkCalls) sdkCalls.forEach(c => usedMethods.add(c.slice(1)));
570
+ // Match services.module.methodName() patterns (standalone-first)
571
+ const svcCalls = content.match(/services\.(wallet|user|storage|chain|events|communities|partnerships|offices|thirdParty|navigation)\.\w+/g);
572
+ if (svcCalls) {
573
+ svcCalls.forEach(c => {
574
+ // Convert services.wallet.getBalance to getWallet().getBalance
575
+ const parts = c.replace('services.', '').split('.');
576
+ const moduleMap = { wallet: 'getWallet', user: 'getUser', storage: 'getStorage', chain: 'getChain', events: 'getEvents', communities: 'getCommunities', partnerships: 'getPartnerships', offices: 'getOffices', thirdParty: 'getThirdParty', navigation: 'getNavigation' };
577
+ if (moduleMap[parts[0]] && parts[1]) {
578
+ usedMethods.add(`${moduleMap[parts[0]]}().${parts[1]}`);
579
+ }
580
+ });
581
+ }
512
582
  }
513
583
  }
514
584
  }
@@ -529,14 +599,20 @@ function cmdValidatePermissions(cwd, flags) {
529
599
  for (const method of usedMethods) {
530
600
  // Try to find matching permission
531
601
  for (const [pattern, perm] of Object.entries(methodToPermission)) {
532
- if (method.includes(pattern.split('.')[0]) && !declaredPerms.has(perm)) {
602
+ if (method === pattern && !declaredPerms.has(perm)) {
533
603
  missingPerms.push({ method, permission: perm });
534
604
  }
535
605
  }
536
606
  }
537
607
 
538
608
  if (missingPerms.length > 0) {
539
- issues.push(...missingPerms.map(m => `SDK method ${m.method} used but permission ${m.permission} not in manifest`));
609
+ if (isLegacy || isTier2) {
610
+ // Legacy or SDK Integration phase: missing permissions are errors
611
+ issues.push(...missingPerms.map(m => `SDK method ${m.method} used but permission ${m.permission} not in manifest`));
612
+ } else {
613
+ // Feature phases: missing permissions are warnings only
614
+ warnings.push(...missingPerms.map(m => `Service method ${m.method} used — permission ${m.permission} should be in manifest for SDK Integration`));
615
+ }
540
616
  }
541
617
 
542
618
  output({
@@ -544,7 +620,9 @@ function cmdValidatePermissions(cwd, flags) {
544
620
  declaredPermissions: manifest.permissions,
545
621
  usedMethods: Array.from(usedMethods),
546
622
  issues,
547
- missingPermissions: missingPerms
623
+ warnings,
624
+ missingPermissions: missingPerms,
625
+ tier: isLegacy ? 'legacy' : isTier2 ? 2 : 1
548
626
  }, flags);
549
627
  }
550
628
 
@@ -701,13 +779,14 @@ function cmdCommit(message, files, flags) {
701
779
 
702
780
  function main() {
703
781
  const args = process.argv.slice(2);
704
- const flags = { raw: false, pick: null };
782
+ const flags = { raw: false, pick: null, phase: null };
705
783
 
706
784
  // Extract flags
707
785
  const cleanArgs = [];
708
786
  for (let i = 0; i < args.length; i++) {
709
787
  if (args[i] === '--raw') { flags.raw = true; }
710
788
  else if (args[i] === '--pick' && args[i + 1]) { flags.pick = args[++i]; }
789
+ else if (args[i] === '--phase' && args[i + 1]) { flags.phase = args[++i]; }
711
790
  else { cleanArgs.push(args[i]); }
712
791
  }
713
792
 
@@ -786,6 +865,31 @@ Commands:
786
865
  break;
787
866
  }
788
867
 
868
+ case 'sdk-ref': {
869
+ const modulesIdx = rest.indexOf('--modules');
870
+ if (modulesIdx < 0 || !rest[modulesIdx + 1]) {
871
+ error('sdk-ref requires --modules <Module1,Module2,...>');
872
+ }
873
+ const modules = rest[modulesIdx + 1].split(',').map(m => m.trim().toLowerCase());
874
+ const fosHome = process.env.FOS_HOME || path.join(require('os').homedir(), '.claude', 'frontier-os-app-builder');
875
+ const sdkDir = path.join(fosHome, 'references', 'sdk');
876
+ const always = ['init', 'types'];
877
+ const allFiles = [...always, ...modules];
878
+ const parts = [];
879
+ for (const f of allFiles) {
880
+ const fp = path.join(sdkDir, `${f}.md`);
881
+ if (!fs.existsSync(fp)) {
882
+ error(`SDK reference file not found: ${fp}`);
883
+ }
884
+ parts.push(fs.readFileSync(fp, 'utf-8'));
885
+ }
886
+ const content = parts.join('\n\n---\n\n');
887
+ const tmpPath = path.join(require('os').tmpdir(), `fos-sdk-ref-${Date.now()}.md`);
888
+ fs.writeFileSync(tmpPath, content);
889
+ console.log(`@file:${tmpPath}`);
890
+ break;
891
+ }
892
+
789
893
  default:
790
894
  error(`Unknown command: ${command}. Run 'node fos-tools.cjs help' for usage.`);
791
895
  }
package/bin/install.js CHANGED
@@ -10,7 +10,7 @@ const path = require('path');
10
10
  // and templates into ~/.claude/
11
11
  // ─────────────────────────────────────────────
12
12
 
13
- const VERSION = '1.0.0';
13
+ const VERSION = '1.2.0';
14
14
  const PRODUCT = 'frontier-os-app-builder';
15
15
 
16
16
  // Source: this repo
@@ -104,15 +104,16 @@ function install() {
104
104
  log('Installing agents...');
105
105
  const agentSrc = path.join(SRC_ROOT, 'agents');
106
106
  const agentDest = path.join(CLAUDE_HOME, 'agents');
107
+ let agentCount = 0;
107
108
  if (fs.existsSync(agentSrc)) {
108
109
  for (const file of fs.readdirSync(agentSrc)) {
109
110
  if (file.startsWith('fos-') && file.endsWith('.md')) {
110
111
  const dest = copyFile(path.join(agentSrc, file), path.join(agentDest, file));
111
112
  installedFiles.push(dest);
113
+ agentCount++;
112
114
  }
113
115
  }
114
116
  }
115
- const agentCount = installedFiles.filter(f => f.includes('/agents/fos-')).length;
116
117
  success(`${agentCount} agents → ~/.claude/agents/`);
117
118
 
118
119
  // 3. Workflows → ~/.claude/frontier-os-app-builder/workflows/
@@ -149,7 +150,8 @@ function install() {
149
150
  success(`CLI tool → ~/.claude/${PRODUCT}/bin/fos-tools.cjs`);
150
151
  }
151
152
 
152
- // 7. Write manifest
153
+ // 7. Write manifest (record its own path first so uninstall removes it)
154
+ installedFiles.push(MANIFEST_PATH);
153
155
  const manifest = {
154
156
  version: VERSION,
155
157
  installed_at: new Date().toISOString(),
@@ -157,7 +159,6 @@ function install() {
157
159
  };
158
160
  ensureDir(path.dirname(MANIFEST_PATH));
159
161
  fs.writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
160
- installedFiles.push(MANIFEST_PATH);
161
162
 
162
163
  // Summary
163
164
  console.log(`\n\x1b[32m ✓ Installed ${installedFiles.length} files\x1b[0m\n`);
@@ -185,11 +186,13 @@ function uninstall() {
185
186
  }
186
187
  }
187
188
 
188
- // Clean up directories
189
+ // Clean up directories (deepest-first: prune child dirs before their parents)
189
190
  const dirsToClean = [
190
191
  path.join(CLAUDE_HOME, 'commands', 'fos'),
191
192
  path.join(FOS_HOME, 'workflows'),
193
+ path.join(FOS_HOME, 'references', 'sdk'),
192
194
  path.join(FOS_HOME, 'references'),
195
+ path.join(FOS_HOME, 'templates', 'app', 'public'),
193
196
  path.join(FOS_HOME, 'templates', 'app'),
194
197
  path.join(FOS_HOME, 'templates', 'state'),
195
198
  path.join(FOS_HOME, 'templates'),
@@ -16,8 +16,7 @@ Add a new feature to the current milestone. Infers required SDK modules, creates
16
16
 
17
17
  <execution_context>
18
18
  @$HOME/.claude/frontier-os-app-builder/workflows/add-feature.md
19
- @$HOME/.claude/frontier-os-app-builder/references/module-inference.md
20
- @$HOME/.claude/frontier-os-app-builder/references/sdk-surface.md
19
+ @$HOME/.claude/frontier-os-app-builder/references/module-index.md
21
20
  </execution_context>
22
21
 
23
22
  <context>
@@ -19,7 +19,6 @@ Gather implementation decisions for a phase by identifying gray areas and discus
19
19
 
20
20
  <execution_context>
21
21
  @$HOME/.claude/frontier-os-app-builder/workflows/discuss.md
22
- @$HOME/.claude/frontier-os-app-builder/references/sdk-surface.md
23
22
  </execution_context>
24
23
 
25
24
  <context>
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: fos:new-app
3
3
  description: Create a new Frontier OS app from a natural language description
4
- argument-hint: '"app description" [--auto]'
4
+ argument-hint: '"app description"'
5
5
  allowed-tools:
6
6
  - Read
7
7
  - Write
@@ -24,9 +24,7 @@ Initialize a new Frontier OS app through guided flow: gather requirements, infer
24
24
 
25
25
  <execution_context>
26
26
  @$HOME/.claude/frontier-os-app-builder/workflows/new-app.md
27
- @$HOME/.claude/frontier-os-app-builder/references/sdk-surface.md
28
- @$HOME/.claude/frontier-os-app-builder/references/module-inference.md
29
- @$HOME/.claude/frontier-os-app-builder/references/app-patterns.md
27
+ @$HOME/.claude/frontier-os-app-builder/references/module-index.md
30
28
  </execution_context>
31
29
 
32
30
  <context>
@@ -16,7 +16,7 @@ Archive the current milestone and start a new one. Gathers new feature descripti
16
16
 
17
17
  <execution_context>
18
18
  @$HOME/.claude/frontier-os-app-builder/workflows/new-milestone.md
19
- @$HOME/.claude/frontier-os-app-builder/references/module-inference.md
19
+ @$HOME/.claude/frontier-os-app-builder/references/module-index.md
20
20
  </execution_context>
21
21
 
22
22
  <context>
@@ -23,8 +23,6 @@ Create execution plans for a phase by researching existing Frontier OS apps, the
23
23
 
24
24
  <execution_context>
25
25
  @$HOME/.claude/frontier-os-app-builder/workflows/plan.md
26
- @$HOME/.claude/frontier-os-app-builder/references/sdk-surface.md
27
- @$HOME/.claude/frontier-os-app-builder/references/app-patterns.md
28
26
  </execution_context>
29
27
 
30
28
  <context>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontier-os-app-builder",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Meta-prompting framework for building Frontier OS apps with Claude Code",
5
5
  "author": "BerlinhouseLabs",
6
6
  "license": "MIT",
@@ -16,6 +16,12 @@
16
16
  "templates/",
17
17
  "README.md"
18
18
  ],
19
+ "scripts": {
20
+ "prepublishOnly": "node --check bin/install.js && node bin/fos-tools.cjs version"
21
+ },
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
19
25
  "keywords": [
20
26
  "frontier-os",
21
27
  "claude-code",