smash-os-install 0.3.0 → 0.3.1
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/install.mjs +93 -37
- package/package.json +1 -1
package/install.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* smash-os-install — Install the SmashOS Claude Code harness into any repo.
|
|
4
4
|
*
|
|
@@ -425,47 +425,102 @@ if (isMarketing) {
|
|
|
425
425
|
process.exit(0);
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
428
|
+
const onCancel = () => { console.log(chalk.yellow('\n Cancelled.')); process.exit(0); };
|
|
429
|
+
|
|
430
|
+
// ── Q1: New or existing project? ──────────────────────────────────────────────
|
|
431
|
+
const { projectType } = await prompts({
|
|
432
|
+
type: 'select',
|
|
433
|
+
name: 'projectType',
|
|
434
|
+
message: 'Is this a new project or an existing one?',
|
|
435
|
+
choices: [
|
|
436
|
+
{ title: 'New project — I will describe the tech stack', value: 'new' },
|
|
437
|
+
{ title: 'Existing project — auto-discover tech stack from codebase', value: 'existing' },
|
|
438
|
+
],
|
|
439
|
+
initial: 0,
|
|
440
|
+
}, { onCancel });
|
|
441
|
+
|
|
442
|
+
// ── Auto-discover tech stack for existing projects ────────────────────────────
|
|
443
|
+
function discoverTechStack() {
|
|
444
|
+
const hints = [];
|
|
445
|
+
try {
|
|
446
|
+
const pkg = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf8'));
|
|
447
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
448
|
+
if (deps['next']) hints.push('Next.js');
|
|
449
|
+
else if (deps['react']) hints.push('React');
|
|
450
|
+
if (deps['vue']) hints.push('Vue');
|
|
451
|
+
if (deps['svelte']) hints.push('Svelte');
|
|
452
|
+
if (deps['vite']) hints.push('Vite');
|
|
453
|
+
if (deps['typescript'] || deps['@types/node']) hints.push('TypeScript');
|
|
454
|
+
if (deps['@supabase/supabase-js']) hints.push('Supabase');
|
|
455
|
+
if (deps['prisma']) hints.push('Prisma');
|
|
456
|
+
if (deps['express']) hints.push('Express');
|
|
457
|
+
if (deps['tailwindcss']) hints.push('Tailwind CSS');
|
|
458
|
+
if (deps['react-native'] || deps['expo']) hints.push('React Native / Expo');
|
|
459
|
+
} catch { /* no package.json */ }
|
|
460
|
+
if (existsSync(join(cwd, 'requirements.txt')) || existsSync(join(cwd, 'pyproject.toml'))) hints.push('Python');
|
|
461
|
+
if (existsSync(join(cwd, 'go.mod'))) hints.push('Go');
|
|
462
|
+
if (existsSync(join(cwd, 'Cargo.toml'))) hints.push('Rust');
|
|
463
|
+
if (existsSync(join(cwd, 'pubspec.yaml'))) hints.push('Flutter/Dart');
|
|
464
|
+
return hints.length > 0 ? hints.join(' + ') : 'TypeScript';
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// ── Q2: Project name ──────────────────────────────────────────────────────────
|
|
468
|
+
const { projectName } = await prompts({
|
|
469
|
+
type: 'text',
|
|
470
|
+
name: 'projectName',
|
|
471
|
+
message: 'Project name',
|
|
472
|
+
initial: basename(cwd),
|
|
473
|
+
validate: (v) => (v.trim().length > 0 ? true : 'Required'),
|
|
474
|
+
}, { onCancel });
|
|
475
|
+
|
|
476
|
+
// ── Q3: Tech stack (skip for existing — auto-discovered) ──────────────────────
|
|
477
|
+
let techStack;
|
|
478
|
+
if (projectType === 'existing') {
|
|
479
|
+
techStack = discoverTechStack();
|
|
480
|
+
console.log(' ' + chalk.green('✓') + ' Tech stack detected: ' + chalk.white(techStack));
|
|
481
|
+
} else {
|
|
482
|
+
const r = await prompts({
|
|
437
483
|
type: 'text',
|
|
438
484
|
name: 'techStack',
|
|
439
485
|
message: 'Tech stack (e.g. React + Node.js + Postgres)',
|
|
440
486
|
initial: 'TypeScript',
|
|
441
|
-
},
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
name: 'enhancement',
|
|
445
|
-
message: 'Enhancement mode (superpowers + GSD framework integration)',
|
|
446
|
-
choices: [
|
|
447
|
-
{ title: 'off — roles only, manual framework use', value: 'off' },
|
|
448
|
-
{ title: 'light — roles hint relevant workflows', value: 'light' },
|
|
449
|
-
{ title: 'medium — structured workflows enforced (recommended)', value: 'medium' },
|
|
450
|
-
{ title: 'high — full GSD phase engine + learning extraction', value: 'high' },
|
|
451
|
-
],
|
|
452
|
-
initial: 2,
|
|
453
|
-
},
|
|
454
|
-
{
|
|
455
|
-
type: 'confirm',
|
|
456
|
-
name: 'isFrontend',
|
|
457
|
-
message: 'Is this a frontend project? (React / Next.js / Vue / Svelte — adds UI/UX Designer, Frontend Developer, Frontend QA roles)',
|
|
458
|
-
initial: false,
|
|
459
|
-
},
|
|
460
|
-
{
|
|
461
|
-
type: process.platform === 'win32' ? 'confirm' : null,
|
|
462
|
-
name: 'setupAutomation',
|
|
463
|
-
message: 'Set up Windows Task Scheduler automation? (nightly AI, weekly improvements)',
|
|
464
|
-
initial: true,
|
|
465
|
-
},
|
|
466
|
-
], { onCancel: () => { console.log(chalk.yellow('\n Cancelled.')); process.exit(0); } });
|
|
487
|
+
}, { onCancel });
|
|
488
|
+
techStack = r.techStack;
|
|
489
|
+
}
|
|
467
490
|
|
|
468
|
-
|
|
491
|
+
// ── Q4: Enhancement mode ──────────────────────────────────────────────────────
|
|
492
|
+
const { enhancement } = await prompts({
|
|
493
|
+
type: 'select',
|
|
494
|
+
name: 'enhancement',
|
|
495
|
+
message: 'Enhancement mode (superpowers + GSD framework integration)',
|
|
496
|
+
choices: [
|
|
497
|
+
{ title: 'off — roles only, manual framework use', value: 'off' },
|
|
498
|
+
{ title: 'light — roles hint relevant workflows', value: 'light' },
|
|
499
|
+
{ title: 'medium — structured workflows enforced (recommended)', value: 'medium' },
|
|
500
|
+
{ title: 'high — full GSD phase engine + learning extraction', value: 'high' },
|
|
501
|
+
],
|
|
502
|
+
initial: 2,
|
|
503
|
+
}, { onCancel });
|
|
504
|
+
|
|
505
|
+
// ── Q5: Frontend? ─────────────────────────────────────────────────────────────
|
|
506
|
+
const frontendKeywords = ['react', 'next', 'vue', 'svelte', 'vite', 'tailwind', 'expo'];
|
|
507
|
+
const autoFrontend = frontendKeywords.some(k => techStack.toLowerCase().includes(k));
|
|
508
|
+
const { isFrontend } = await prompts({
|
|
509
|
+
type: 'confirm',
|
|
510
|
+
name: 'isFrontend',
|
|
511
|
+
message: 'Is this a frontend project? (adds UI/UX Designer, Frontend Developer, Frontend QA roles)',
|
|
512
|
+
initial: autoFrontend,
|
|
513
|
+
}, { onCancel });
|
|
514
|
+
|
|
515
|
+
// ── Q6: Windows automation ────────────────────────────────────────────────────
|
|
516
|
+
const { setupAutomation } = process.platform === 'win32'
|
|
517
|
+
? await prompts({
|
|
518
|
+
type: 'confirm',
|
|
519
|
+
name: 'setupAutomation',
|
|
520
|
+
message: 'Set up Windows Task Scheduler automation? (nightly AI, weekly improvements)',
|
|
521
|
+
initial: true,
|
|
522
|
+
}, { onCancel })
|
|
523
|
+
: { setupAutomation: false };
|
|
469
524
|
|
|
470
525
|
// ─── File content ─────────────────────────────────────────────────────────────
|
|
471
526
|
|
|
@@ -696,6 +751,7 @@ const localSkills = {
|
|
|
696
751
|
'smash-os-extract-learnings': `---\nname: smash-os-extract-learnings\ndescription: Extract conventions, decisions, and lessons from the current session and save to ai/memory/. At high enhancement mode this runs automatically after each significant phase. Feeds into skill evolution.\nallowed-tools: Read, Write, Glob\n---\n\n# /smash-os:extract-learnings\n\nExtract and persist learnings from the current session.\n\n## Steps\n\n1. Review recent work in this session — what was built, what decisions were made, what friction was encountered\n2. Identify items in each category:\n - **Conventions discovered**: patterns or standards that emerged or were reinforced\n - **Decisions made**: architectural or product choices with rationale\n - **Lessons learned**: what went wrong or could be improved\n - **Role improvements**: behaviors that should be added/removed from a role definition\n3. Write to \`ai/memory/lessons.md\` (append) — lessons + conventions\n4. Write to \`ai/memory/decisions.md\` (append) — decisions with rationale\n5. If role improvements were identified:\n - Read the relevant \`ai/roles/<role-slug>.md\` file (create it if missing)\n - Propose the improvement inline\n - Ask: "Apply this improvement to the [Role] definition? (y/n)"\n - If yes: write the updated role file\n6. Output a brief summary of what was extracted\n\n## Output Format\n\n\`\`\`\n▸ SMASH OS · learnings extracted\n─────────────────────────────────────\n conventions {N}\n decisions {N}\n lessons {N}\n role updates {N applied | none}\n─────────────────────────────────────\n\`\`\`\n\n## Notes\n- Never overwrite existing entries — always append\n- Role improvements should be additive, not destructive\n- These files are read by skill-evolution — write clearly for future context\n- If nothing significant happened this session: output "No learnings to extract"\n`,
|
|
697
752
|
'smash-os-role-improve': `---\nname: smash-os-role-improve\ndescription: Role improvement pass — reads accumulated learnings from ai/memory/role-learnings/, applies insights back to each role definition. Gains new rules, prunes stale ones, consolidates duplicates, enhances the Enhancement Layer. Run manually or via the RoleImprovement scheduled task.\nallowed-tools: Read, Write, Edit\n---\n\n# /smash-os:role-improve\n\nRead all role learning logs. For each role with new entries, analyse and apply improvements back to the role definition.\n\n## Step 1 — Discover roles with learnings\n\nRead all files in \`ai/memory/role-learnings/\`. Skip any with no entries beyond the header (nothing after the \`---\` separator).\n\n## Step 2 — Analyse each learning log\n\nFor each role that has entries, extract:\n- **Gains** — new constraints or patterns that consistently improved output\n- **Prunes** — Hard Rules flagged as redundant, too slow, or consistently skipped\n- **Consolidations** — duplicate or near-duplicate rules that can be merged\n- **Enhancement Layer improvements** — which skills actually added value at which levels\n\n## Step 3 — Apply improvements to each role file\n\n1. Add new Hard Rules from Gains — each dated \`[YYYY-MM-DD]\`\n2. Remove pruned rules if flagged 3+ times; convert to comment if 1–2 times\n3. Consolidate duplicate rules\n4. Update Enhancement Layer skill mappings\n5. Append to \`## Improvement History\` (create if missing): \`- YYYY-MM-DD: {N gains, M prunes, K consolidations}\`\n\nDo not change Purpose, Responsibilities, Output Format, or Selective Context Load unless a learning entry explicitly proposes it.\n\n## Step 4 — Archive processed learnings\n\nAfter updating a role file, append an archive marker and move processed entries below it. New entries append above the archive.\n\n## Step 5 — Report\n\n\`\`\`\n▸ SMASH OS · role improvement pass\n─────────────────────────────────────\n {date}\n ROLES UPDATED {list with counts}\n ROLES SKIPPED {list — no new learnings}\n─────────────────────────────────────\n\`\`\`\n\n## Rules\n- Never remove a Hard Rule without 3+ learning entries flagging it\n- All new Hard Rules carry a derivation date\n- Idempotent — no new entries = no changes\n`,
|
|
698
753
|
'smash-os-evolve-roles': `---\nname: smash-os-evolve-roles\ndescription: Analyze accumulated learnings from ai/memory/ and propose targeted improvements to SmashOS role files. Bridges extract-learnings to skill evolution. Runs automatically weekly via Task Scheduler.\nallowed-tools: Read, Write, Glob\n---\n\n# /smash-os:evolve-roles\n\nAnalyze learnings accumulated across sessions and evolve role definitions based on real project experience.\n\n## Steps\n\n1. Read \`ai/memory/lessons.md\` — find entries tagged with role improvement suggestions (look for "Role improvements:", "role:", "[role improvement]" markers)\n2. Read \`ai/memory/decisions.md\` — find conventions that should be encoded into specific roles\n3. Skip any learning already marked with \`[applied YYYY-MM-DD]\`\n4. List all files in \`ai/roles/\` — project-specific role overrides\n - If \`ai/roles/\` is empty or missing: offer to scaffold defaults (staff-engineer, senior-developer, security-engineer)\n5. For each pending improvement, identify the target role and present:\n - Current relevant section (or "no file yet")\n - Proposed addition/change (be specific — not "be more careful", but "always check for stale migrations before running tests")\n - Ask: "Apply to [role-name].md? (y/n)"\n6. If approved: write/update \`ai/roles/<role-slug>.md\`, mark the source lesson as \`[applied {date}]\` in lessons.md\n7. After all project-level changes, ask: "Any improvements universal enough for the global skill? (y/n)"\n - If yes: list candidates, confirm each, then append to \`~/.claude/skills/smash-os-role/SKILL.md\` under a "## Project-Learned Behaviors" section\n8. Output summary\n\n## Output Format\n\n\`\`\`\n▸ SMASH OS · role evolution\n─────────────────────────────────────\n learnings reviewed {N}\n improvements found {N}\n applied to roles {N}\n global skill updated {yes | no}\n─────────────────────────────────────\n\`\`\`\n\n## Rules\n- Never remove existing role capabilities — only add or refine\n- Improvements must be specific and actionable, not vague\n- Mark applied learnings so they are not re-proposed on the next run\n- Global skill updates: only universal, project-agnostic behaviors (not "use Postgres migrations" — yes to "always confirm schema changes with Security Engineer before applying")\n- If no pending improvements: output "Roles are up to date — no changes needed"\n`,
|
|
754
|
+
'smash-os-performance': `---\nname: smash-os-performance\ndescription: Full performance audit and fix pipeline for any SmashBurgerBar web app. Scores performance across 6 dimensions, auto-fixes safe issues, generates prioritised action plans.\n---\n\n# /smash-os:performance\n\nRun a full performance audit for the current project. Scores every dimension, auto-fixes safe wins, and generates a prioritised fix plan.\n\n---\n\n## Phase 1 — Detect Project Type\n\nRead \`package.json\` and identify:\n- Framework: React Router v7 / Next.js / plain React\n- Renderer: SSR / CSR / SSG\n- Key deps: \`@tanstack/react-virtual\`, \`@vercel/analytics\`, \`@vercel/speed-insights\`\n- Build tool: Vite / Webpack / Turbopack\n\n---\n\n## Phase 2 — Score Performance Dimensions (0–100 each)\n\n| # | Dimension | Weight | How to measure |\n|---|---|---|---|\n| 1 | **Data Loading Strategy** | 25% | Single Fetch enabled? Loaders return naked objects? \`json()\`/\`defer()\` still used? Streaming used for slow data? |\n| 2 | **Rendering & Hydration** | 20% | Server-first? Unnecessary client components? Hydration mismatches? Third-party SDKs causing flicker? |\n| 3 | **Bundle Size** | 20% | Check \`build/\` output sizes. Large deps in client bundle? Code splitting in place? |\n| 4 | **List & Grid Performance** | 15% | Lists over 100 items without virtualisation? \`@tanstack/react-virtual\` installed? |\n| 5 | **UX Responsiveness** | 10% | \`viewTransition\` on navigation links? \`<Suspense>\` wrapping slow components? \`streamTimeout\` set? |\n| 6 | **Asset & Cache Optimisation** | 10% | Images use \`next/image\` or equivalent? Fonts optimised? \`Cache-Control\` headers set? CDN cache on static assets? |\n\n**Performance Score (PS) = sum of weighted contributions**\n\nGrades: 90–100 A · 75–89 B · 60–74 C · 40–59 D · 0–39 F\n\n---\n\n## Phase 3 — Detect and Fix Common Issues\n\n### Data loading\n- [ ] Replace \`json(return {...})\` with \`return {...}\` (naked object) in all loaders\n- [ ] Replace \`defer()\` with non-awaited promises returned directly from loaders\n- [ ] Add \`shouldRevalidate\` to routes that don't need to re-fetch on every navigation\n- [ ] Identify loaders that await slow external calls — split into critical (awaited) + secondary (streamed)\n\n### Streaming\n- [ ] Check \`entry.server.tsx\` — add \`export const streamTimeout = 5000\` if absent\n- [ ] Wrap components that receive streamed promises in \`<Suspense fallback={...}>\`\n\n### Rendering\n- [ ] Audit \`'use client'\` usage — push boundaries as far down the tree as possible\n- [ ] Check for third-party SDK initialisation in components — move to server loaders\n\n### Lists\n- [ ] Find all \`.map()\` renders of lists > 100 items\n- [ ] Install \`@tanstack/react-virtual\` if not present\n- [ ] Wrap identified lists with \`useVirtualizer\`\n\n### UX transitions\n- [ ] Add \`viewTransition\` to primary navigation \`<Link>\` components\n- [ ] Add \`streamTimeout\` export to \`entry.server.tsx\`\n\n### Assets\n- [ ] Check image tags — ensure \`loading="lazy"\` on below-fold images\n- [ ] Verify \`Cache-Control: public, max-age=31536000, immutable\` on static assets in \`vercel.json\` or equivalent\n\n---\n\n## Phase 4 — Auto-Fix Protocol\n\n| Severity | Action |\n|---|---|\n| Safe mechanical change (remove \`json()\`, add \`streamTimeout\`) | Fix inline, note in report |\n| Requires logic change (split loader, add virtualisation) | Generate \`PERF_PR_N.md\` with exact code change |\n| Requires package install | Print install command, do not run automatically |\n\n---\n\n## Phase 5 — Report Output\n\n\`\`\`\n╔══════════════════════════════════════════════════╗\n║ PERFORMANCE SCORE · [PROJECT NAME] ║\n╠══════════════════════════════════════════════════╣\n║ 1. Data Loading Strategy ██████░░░ 65% ×0.25 ║\n║ 2. Rendering & Hydration ████████░ 80% ×0.20 ║\n║ 3. Bundle Size ███████░░ 70% ×0.20 ║\n║ 4. List Performance ██░░░░░░░ 20% ×0.15 ║\n║ 5. UX Responsiveness █████░░░░ 50% ×0.10 ║\n║ 6. Asset & Cache ████████░ 80% ×0.10 ║\n╠══════════════════════════════════════════════════╣\n║ PERFORMANCE SCORE 63.75 → C ║\n╚══════════════════════════════════════════════════╝\n\nAuto-fixed: N items\nPRs queued: N → PERF_PR_1.md, PERF_PR_2.md\n\nNext actions:\n [HIGH] Virtualise order history list — 3,000 rows rendered on mount\n [HIGH] Split menu loader — Supabase call blocks 1.8s before first byte\n [MED] Add streamTimeout to entry.server.tsx\n [MED] Remove json() from 4 loaders\n [LOW] Add viewTransition to nav links\n\`\`\`\n\nSave report to \`ai/memory/audits/PERF_REPORT_<YYYY-MM-DD>.md\`.\n\n---\n\n## Roles active during this pipeline\n\n| Role | Mode | Responsibility |\n|---|---|---|\n| Staff Engineer | THINKING | Identifies architectural causes of slowness |\n| Senior Developer | EXECUTION | Implements fixes |\n| QA Engineer | VALIDATION | Verifies fixes don't break functionality |\n\n---\n\n## Key research reference\n\n\`docs/research/react-router-v7-performance.md\` — React Router v7 + React 19 performance patterns (Single Fetch, Streaming, View Transitions, Virtualisation).\n\n---\n\n## Rules\n\n- Never virtualise a list without first confirming item count from real data or code\n- Never remove \`await\` from a loader without checking if the data is used in the initial render\n- Always run \`typecheck\` after auto-fixes\n- Store all findings in \`ai/memory/audits/PERF_REPORT_<date>.md\`\n`,
|
|
699
755
|
};
|
|
700
756
|
|
|
701
757
|
// ─── Write files ──────────────────────────────────────────────────────────────
|