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.
- package/LICENSE +21 -0
- package/README.md +90 -14
- package/agents/fos-executor.md +105 -39
- package/agents/fos-plan-checker.md +62 -25
- package/agents/fos-planner.md +80 -72
- package/agents/fos-researcher.md +26 -15
- package/agents/fos-verifier.md +96 -27
- package/bin/fos-tools.cjs +146 -42
- package/bin/install.js +8 -5
- package/commands/fos/add-feature.md +1 -2
- package/commands/fos/discuss.md +0 -1
- package/commands/fos/new-app.md +2 -4
- package/commands/fos/new-milestone.md +1 -1
- package/commands/fos/plan.md +0 -2
- package/package.json +7 -1
- package/references/app-patterns.md +128 -21
- package/references/deployment.md +40 -124
- package/references/module-index.md +32 -0
- package/references/sdk/chain.md +92 -0
- package/references/sdk/communities.md +159 -0
- package/references/sdk/events.md +212 -0
- package/references/sdk/init.md +126 -0
- package/references/sdk/navigation.md +49 -0
- package/references/sdk/offices.md +76 -0
- package/references/sdk/partnerships.md +111 -0
- package/references/sdk/storage.md +44 -0
- package/references/sdk/thirdparty.md +240 -0
- package/references/sdk/token-amount.md +99 -0
- package/references/sdk/types.md +27 -0
- package/references/sdk/ui-utils.md +39 -0
- package/references/sdk/user.md +208 -0
- package/references/sdk/wallet.md +334 -0
- package/references/verification-rules.md +111 -50
- package/templates/app/frontier-services.tsx +871 -0
- package/templates/app/layout-standalone.tsx +8 -0
- package/templates/app/layout.tsx +19 -9
- package/templates/app/package-standalone.json +35 -0
- package/templates/app/package.json +2 -1
- package/templates/app/public/favicon.svg +3 -0
- package/templates/app/sdk-context.tsx +7 -9
- package/templates/app/sdk-services.tsx +98 -0
- package/templates/app/vercel-standalone.json +5 -0
- package/templates/app/vercel.json +8 -95
- package/templates/state/plan.md +32 -14
- package/templates/state/requirements.md +1 -1
- package/templates/state/roadmap.md +57 -24
- package/templates/state/summary.md +27 -30
- package/workflows/add-feature.md +6 -1
- package/workflows/discuss.md +126 -11
- package/workflows/execute-plan.md +21 -14
- package/workflows/execute.md +204 -24
- package/workflows/new-app.md +64 -23
- package/workflows/new-milestone.md +10 -3
- package/workflows/plan.md +16 -5
- package/workflows/ship.md +91 -34
- package/workflows/status.md +1 -2
- package/references/module-inference.md +0 -349
- package/references/sdk-surface.md +0 -1622
- package/templates/app/main-simple.tsx +0 -19
- 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.
|
|
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', '
|
|
274
|
-
permissions: ['wallet:getBalance', 'wallet:
|
|
275
|
-
'wallet:transferFrontierDollar', 'wallet:
|
|
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
|
-
|
|
419
|
-
|
|
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
|
-
//
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
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
|
-
//
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|
-
|
|
466
|
-
|
|
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
|
-
//
|
|
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
|
|
511
|
-
if (
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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-
|
|
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>
|
package/commands/fos/discuss.md
CHANGED
|
@@ -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>
|
package/commands/fos/new-app.md
CHANGED
|
@@ -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"
|
|
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/
|
|
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-
|
|
19
|
+
@$HOME/.claude/frontier-os-app-builder/references/module-index.md
|
|
20
20
|
</execution_context>
|
|
21
21
|
|
|
22
22
|
<context>
|
package/commands/fos/plan.md
CHANGED
|
@@ -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.
|
|
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",
|