@theproductguy/create-mission-control 1.0.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 (195) hide show
  1. package/README.md +37 -0
  2. package/bin/cli.js +170 -0
  3. package/package.json +44 -0
  4. package/src/template/App.tsx +28 -0
  5. package/src/template/agent-os/commands/create-tasks/1-get-spec-requirements.md +19 -0
  6. package/src/template/agent-os/commands/create-tasks/2-create-tasks-list.md +234 -0
  7. package/src/template/agent-os/commands/create-tasks/create-tasks.md +254 -0
  8. package/src/template/agent-os/commands/design-screen/design-screen.md +32 -0
  9. package/src/template/agent-os/commands/design-shell/design-shell.md +34 -0
  10. package/src/template/agent-os/commands/design-tokens/design-tokens.md +36 -0
  11. package/src/template/agent-os/commands/export-product/export-product.md +181 -0
  12. package/src/template/agent-os/commands/implement-tasks/1-determine-tasks.md +13 -0
  13. package/src/template/agent-os/commands/implement-tasks/2-implement-tasks.md +63 -0
  14. package/src/template/agent-os/commands/implement-tasks/3-verify-implementation.md +113 -0
  15. package/src/template/agent-os/commands/implement-tasks/implement-tasks.md +207 -0
  16. package/src/template/agent-os/commands/initialize-design/initialize-design.md +67 -0
  17. package/src/template/agent-os/commands/orchestrate-tasks/orchestrate-tasks.md +180 -0
  18. package/src/template/agent-os/commands/plan-product/1-product-concept.md +53 -0
  19. package/src/template/agent-os/commands/plan-product/2-create-mission.md +78 -0
  20. package/src/template/agent-os/commands/plan-product/3-create-roadmap.md +73 -0
  21. package/src/template/agent-os/commands/plan-product/4-create-tech-stack.md +46 -0
  22. package/src/template/agent-os/commands/plan-product/plan-product.md +241 -0
  23. package/src/template/agent-os/commands/sample-data/sample-data.md +51 -0
  24. package/src/template/agent-os/commands/scaffold-implementation/scaffold-implementation.md +35 -0
  25. package/src/template/agent-os/commands/screenshot-design/screenshot-design.md +21 -0
  26. package/src/template/agent-os/commands/shape-spec/1-initialize-spec.md +95 -0
  27. package/src/template/agent-os/commands/shape-spec/2-shape-spec.md +300 -0
  28. package/src/template/agent-os/commands/shape-spec/shape-spec.md +40 -0
  29. package/src/template/agent-os/commands/write-spec/write-spec.md +134 -0
  30. package/src/template/agent-os/config.yml +13 -0
  31. package/src/template/agent-os/product/mission.md +29 -0
  32. package/src/template/agent-os/product/roadmap.md +9 -0
  33. package/src/template/agent-os/product/tech-stack.md +14 -0
  34. package/src/template/agent-os/scripts/generate_docs.sh +150 -0
  35. package/src/template/agent-os/specs/README.md +1 -0
  36. package/src/template/agent-os/standards/backend/api.md +10 -0
  37. package/src/template/agent-os/standards/backend/migrations.md +9 -0
  38. package/src/template/agent-os/standards/backend/models.md +10 -0
  39. package/src/template/agent-os/standards/backend/queries.md +9 -0
  40. package/src/template/agent-os/standards/frontend/accessibility.md +10 -0
  41. package/src/template/agent-os/standards/frontend/components.md +11 -0
  42. package/src/template/agent-os/standards/frontend/css.md +7 -0
  43. package/src/template/agent-os/standards/frontend/responsive.md +11 -0
  44. package/src/template/agent-os/standards/global/coding-style.md +10 -0
  45. package/src/template/agent-os/standards/global/commenting.md +5 -0
  46. package/src/template/agent-os/standards/global/conventions.md +11 -0
  47. package/src/template/agent-os/standards/global/error-handling.md +9 -0
  48. package/src/template/agent-os/standards/global/tech-stack.md +31 -0
  49. package/src/template/agent-os/standards/global/validation.md +11 -0
  50. package/src/template/agent-os/standards/testing/test-writing.md +9 -0
  51. package/src/template/agent-os-ui/README.md +73 -0
  52. package/src/template/agent-os-ui/package.json +54 -0
  53. package/src/template/agent-os-ui/src/components/AgentShell.tsx +31 -0
  54. package/src/template/agent-os-ui/src/components/AgentSidebar.tsx +65 -0
  55. package/src/template/agent-os-ui/src/components/GuidanceCard.tsx +75 -0
  56. package/src/template/agent-os-ui/src/components/MarkdownViewer.tsx +25 -0
  57. package/src/template/agent-os-ui/src/components/PromptButton.tsx +28 -0
  58. package/src/template/agent-os-ui/src/components/StatusItem.tsx +45 -0
  59. package/src/template/agent-os-ui/src/components/ThemeToggle.tsx +72 -0
  60. package/src/template/agent-os-ui/src/index.ts +11 -0
  61. package/src/template/agent-os-ui/src/style.css +3 -0
  62. package/src/template/agent-os-ui/tsconfig.json +33 -0
  63. package/src/template/agent-os-ui/vite.config.ts +32 -0
  64. package/src/template/control-center/backend/index.js +253 -0
  65. package/src/template/control-center/backend/package.json +19 -0
  66. package/src/template/control-center/frontend/README.md +73 -0
  67. package/src/template/control-center/frontend/eslint.config.js +23 -0
  68. package/src/template/control-center/frontend/index.html +21 -0
  69. package/src/template/control-center/frontend/package.json +43 -0
  70. package/src/template/control-center/frontend/postcss.config.js +6 -0
  71. package/src/template/control-center/frontend/public/favicon.svg +4 -0
  72. package/src/template/control-center/frontend/public/runtime-config.json +11 -0
  73. package/src/template/control-center/frontend/public/vite.svg +1 -0
  74. package/src/template/control-center/frontend/src/App.css +42 -0
  75. package/src/template/control-center/frontend/src/App.tsx +835 -0
  76. package/src/template/control-center/frontend/src/assets/react.svg +1 -0
  77. package/src/template/control-center/frontend/src/components/ThemeToggle.tsx +64 -0
  78. package/src/template/control-center/frontend/src/components/ui/ToastContext.tsx +81 -0
  79. package/src/template/control-center/frontend/src/index.css +149 -0
  80. package/src/template/control-center/frontend/src/main.tsx +14 -0
  81. package/src/template/control-center/frontend/src/vite-env.d.ts +1 -0
  82. package/src/template/control-center/frontend/tailwind.config.js +81 -0
  83. package/src/template/control-center/frontend/tsconfig.app.json +28 -0
  84. package/src/template/control-center/frontend/tsconfig.json +7 -0
  85. package/src/template/control-center/frontend/tsconfig.node.json +26 -0
  86. package/src/template/control-center/frontend/vite.config.ts +21 -0
  87. package/src/template/design/.claude/commands/design-os/data-model.md +122 -0
  88. package/src/template/design/.claude/commands/design-os/design-screen.md +309 -0
  89. package/src/template/design/.claude/commands/design-os/design-shell.md +238 -0
  90. package/src/template/design/.claude/commands/design-os/design-tokens.md +166 -0
  91. package/src/template/design/.claude/commands/design-os/export-product.md +1105 -0
  92. package/src/template/design/.claude/commands/design-os/product-roadmap.md +121 -0
  93. package/src/template/design/.claude/commands/design-os/product-vision.md +99 -0
  94. package/src/template/design/.claude/commands/design-os/sample-data.md +263 -0
  95. package/src/template/design/.claude/commands/design-os/screenshot-design.md +112 -0
  96. package/src/template/design/.claude/commands/design-os/shape-section.md +138 -0
  97. package/src/template/design/.claude/skills/frontend-design/SKILL.md +42 -0
  98. package/src/template/design/.github/CODE_OF_CONDUCT.md +5 -0
  99. package/src/template/design/.github/CONTRIBUTING.md +51 -0
  100. package/src/template/design/.github/ISSUE_TEMPLATE/config.yml +22 -0
  101. package/src/template/design/.github/PULL_REQUEST_TEMPLATE.md +20 -0
  102. package/src/template/design/.github/SECURITY.yml +5 -0
  103. package/src/template/design/.github/SUPPORT.md +19 -0
  104. package/src/template/design/.github/workflows/pr-decline.yml +135 -0
  105. package/src/template/design/.github/workflows/stale.yml +25 -0
  106. package/src/template/design/CHANGELOG.md +13 -0
  107. package/src/template/design/LICENSE +21 -0
  108. package/src/template/design/README.md +54 -0
  109. package/src/template/design/agents.md +218 -0
  110. package/src/template/design/claude.md +1 -0
  111. package/src/template/design/components.json +22 -0
  112. package/src/template/design/docs/codebase-implementation.md +153 -0
  113. package/src/template/design/docs/design-section.md +135 -0
  114. package/src/template/design/docs/export.md +149 -0
  115. package/src/template/design/docs/getting-started.md +59 -0
  116. package/src/template/design/docs/index.md +56 -0
  117. package/src/template/design/docs/product-planning.md +113 -0
  118. package/src/template/design/docs/requirements.md +22 -0
  119. package/src/template/design/docs/usage.md +62 -0
  120. package/src/template/design/eslint.config.js +23 -0
  121. package/src/template/design/index.html +21 -0
  122. package/src/template/design/package.json +46 -0
  123. package/src/template/design/postcss.config.js +6 -0
  124. package/src/template/design/public/favicon.svg +4 -0
  125. package/src/template/design/public/vite.svg +1 -0
  126. package/src/template/design/src/assets/react.svg +1 -0
  127. package/src/template/design/src/components/AppLayout.tsx +95 -0
  128. package/src/template/design/src/components/DataCard.tsx +139 -0
  129. package/src/template/design/src/components/DataModelPage.tsx +120 -0
  130. package/src/template/design/src/components/DesignPage.tsx +284 -0
  131. package/src/template/design/src/components/EmptyState.tsx +158 -0
  132. package/src/template/design/src/components/ExportPage.tsx +354 -0
  133. package/src/template/design/src/components/NextPhaseButton.tsx +33 -0
  134. package/src/template/design/src/components/PhaseNav.tsx +152 -0
  135. package/src/template/design/src/components/PhaseWarningBanner.tsx +81 -0
  136. package/src/template/design/src/components/ProductOverviewCard.tsx +102 -0
  137. package/src/template/design/src/components/ProductPage.tsx +97 -0
  138. package/src/template/design/src/components/ScreenDesignPage.tsx +370 -0
  139. package/src/template/design/src/components/ScreenDesignsCard.tsx +49 -0
  140. package/src/template/design/src/components/SectionPage.tsx +256 -0
  141. package/src/template/design/src/components/SectionsCard.tsx +47 -0
  142. package/src/template/design/src/components/SectionsPage.tsx +181 -0
  143. package/src/template/design/src/components/ShellCard.tsx +85 -0
  144. package/src/template/design/src/components/ShellDesignPage.tsx +242 -0
  145. package/src/template/design/src/components/SpecCard.tsx +121 -0
  146. package/src/template/design/src/components/StepIndicator.tsx +75 -0
  147. package/src/template/design/src/components/ThemeToggle.tsx +86 -0
  148. package/src/template/design/src/components/ui/ToastContext.tsx +81 -0
  149. package/src/template/design/src/components/ui/avatar.tsx +53 -0
  150. package/src/template/design/src/components/ui/badge.tsx +46 -0
  151. package/src/template/design/src/components/ui/button.tsx +60 -0
  152. package/src/template/design/src/components/ui/card.tsx +92 -0
  153. package/src/template/design/src/components/ui/collapsible.tsx +48 -0
  154. package/src/template/design/src/components/ui/dialog.tsx +143 -0
  155. package/src/template/design/src/components/ui/dropdown-menu.tsx +255 -0
  156. package/src/template/design/src/components/ui/input.tsx +21 -0
  157. package/src/template/design/src/components/ui/label.tsx +22 -0
  158. package/src/template/design/src/components/ui/progress.tsx +24 -0
  159. package/src/template/design/src/components/ui/scroll-area.tsx +18 -0
  160. package/src/template/design/src/components/ui/select.tsx +67 -0
  161. package/src/template/design/src/components/ui/separator.tsx +28 -0
  162. package/src/template/design/src/components/ui/sheet.tsx +137 -0
  163. package/src/template/design/src/components/ui/skeleton.tsx +13 -0
  164. package/src/template/design/src/components/ui/switch.tsx +46 -0
  165. package/src/template/design/src/components/ui/table.tsx +116 -0
  166. package/src/template/design/src/components/ui/tabs.tsx +64 -0
  167. package/src/template/design/src/index.css +239 -0
  168. package/src/template/design/src/lib/data-model-loader.ts +91 -0
  169. package/src/template/design/src/lib/design-system-loader.ts +101 -0
  170. package/src/template/design/src/lib/product-loader.ts +221 -0
  171. package/src/template/design/src/lib/router.tsx +61 -0
  172. package/src/template/design/src/lib/section-loader.ts +272 -0
  173. package/src/template/design/src/lib/shell-loader.ts +175 -0
  174. package/src/template/design/src/lib/utils.ts +6 -0
  175. package/src/template/design/src/main.tsx +15 -0
  176. package/src/template/design/src/sections/.gitkeep +0 -0
  177. package/src/template/design/src/sections/ai-orchestration-engine-oai/OrchestrationEngine.tsx +348 -0
  178. package/src/template/design/src/sections/core-platform-shell/AppShell.tsx +403 -0
  179. package/src/template/design/src/sections/gemini-live-integration/GeminiIntegration.tsx +332 -0
  180. package/src/template/design/src/sections/interactive-2d-canvas/WhiteboardCanvas.tsx +334 -0
  181. package/src/template/design/src/sections/participation-equity-tracker/EquityTracker.tsx +383 -0
  182. package/src/template/design/src/sections/persistent-memory-system/PersistentMemory.tsx +308 -0
  183. package/src/template/design/src/sections/real-time-communication-layer/VideoSession.tsx +342 -0
  184. package/src/template/design/src/sections/visual-intelligence-agents/VisualAgents.tsx +311 -0
  185. package/src/template/design/src/types/product.ts +97 -0
  186. package/src/template/design/src/types/section.ts +33 -0
  187. package/src/template/design/tailwind.config.js +77 -0
  188. package/src/template/design/tsconfig.app.json +34 -0
  189. package/src/template/design/tsconfig.json +13 -0
  190. package/src/template/design/tsconfig.node.json +26 -0
  191. package/src/template/design/vite.config.ts +17 -0
  192. package/src/template/index.css +102 -0
  193. package/src/template/package.json +27 -0
  194. package/src/template/tailwind.config.js +80 -0
  195. package/src/template/vite.config.ts +9 -0
@@ -0,0 +1,72 @@
1
+ import { useState, useEffect } from 'react'
2
+ import { Moon, Sun } from 'lucide-react'
3
+
4
+ export type Theme = 'light' | 'dark' | 'system'
5
+
6
+ interface ThemeToggleProps {
7
+ onThemeChange?: (theme: Theme) => void
8
+ className?: string
9
+ }
10
+
11
+ export function ThemeToggle({ onThemeChange, className }: ThemeToggleProps) {
12
+ const [theme, setTheme] = useState<Theme>(() => {
13
+ if (typeof window !== 'undefined') {
14
+ return (localStorage.getItem('theme') as Theme) || 'system'
15
+ }
16
+ return 'system'
17
+ })
18
+
19
+ useEffect(() => {
20
+ const root = document.documentElement
21
+
22
+ const applyTheme = (targetTheme: Theme) => {
23
+ if (targetTheme === 'system') {
24
+ const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches
25
+ root.classList.toggle('dark', systemDark)
26
+ } else {
27
+ root.classList.toggle('dark', targetTheme === 'dark')
28
+ }
29
+ }
30
+
31
+ applyTheme(theme)
32
+ localStorage.setItem('theme', theme)
33
+
34
+ // Notify parent
35
+ onThemeChange?.(theme)
36
+
37
+ // Listen for system theme changes when in system mode
38
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
39
+ const handleChange = () => {
40
+ if (theme === 'system') {
41
+ applyTheme('system')
42
+ }
43
+ }
44
+ mediaQuery.addEventListener('change', handleChange)
45
+
46
+ return () => mediaQuery.removeEventListener('change', handleChange)
47
+ }, [theme, onThemeChange])
48
+
49
+ const toggleTheme = () => {
50
+ setTheme((prev) => {
51
+ if (prev === 'light') return 'dark'
52
+ if (prev === 'dark') return 'system'
53
+ return 'light'
54
+ })
55
+ }
56
+
57
+ const isDark = theme === 'dark' || (theme === 'system' && typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches)
58
+
59
+ return (
60
+ <button
61
+ onClick={toggleTheme}
62
+ className={`w-9 h-9 flex items-center justify-center rounded-md text-stone-500 hover:text-stone-900 dark:text-stone-400 dark:hover:text-stone-100 hover:bg-stone-100 dark:hover:bg-stone-800 transition-colors ${className || ''}`}
63
+ title={`Theme: ${theme}`}
64
+ >
65
+ {isDark ? (
66
+ <Moon className="w-5 h-5" strokeWidth={1.5} />
67
+ ) : (
68
+ <Sun className="w-5 h-5" strokeWidth={1.5} />
69
+ )}
70
+ </button>
71
+ )
72
+ }
@@ -0,0 +1,11 @@
1
+ import './style.css'
2
+
3
+ export { AgentShell } from './components/AgentShell'
4
+ export { AgentSidebar } from './components/AgentSidebar'
5
+ export { GuidanceCard } from './components/GuidanceCard'
6
+ export { ThemeToggle } from './components/ThemeToggle'
7
+ export { PromptButton } from './components/PromptButton'
8
+ export { StatusItem } from './components/StatusItem'
9
+ export { MarkdownViewer } from './components/MarkdownViewer'
10
+ // Export types if needed
11
+ export type { Theme } from './components/ThemeToggle'
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
@@ -0,0 +1,33 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": [
6
+ "ES2020",
7
+ "DOM",
8
+ "DOM.Iterable"
9
+ ],
10
+ "module": "ESNext",
11
+ "skipLibCheck": true,
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": true,
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+ "declaration": true,
23
+ "baseUrl": ".",
24
+ "paths": {
25
+ "@/*": [
26
+ "./src/*"
27
+ ]
28
+ }
29
+ },
30
+ "include": [
31
+ "src"
32
+ ]
33
+ }
@@ -0,0 +1,32 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+ import dts from 'vite-plugin-dts';
4
+ import { resolve } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = resolve(__filename, '..');
9
+
10
+ export default defineConfig({
11
+ plugins: [
12
+ react(),
13
+ dts({ include: ['src'] })
14
+ ],
15
+ build: {
16
+ lib: {
17
+ entry: resolve(__dirname, 'src/index.ts'),
18
+ name: 'AgentOSUI',
19
+ fileName: 'agent-os-ui',
20
+ },
21
+ rollupOptions: {
22
+ external: ['react', 'react-dom', 'react/jsx-runtime'],
23
+ output: {
24
+ globals: {
25
+ react: 'React',
26
+ 'react-dom': 'ReactDOM',
27
+ 'react/jsx-runtime': 'jsxRuntime',
28
+ },
29
+ },
30
+ },
31
+ },
32
+ });
@@ -0,0 +1,253 @@
1
+ const express = require('express');
2
+ const cors = require('cors');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { glob } = require('glob');
6
+
7
+ const app = express();
8
+ const PORT = process.env.PORT || 5403;
9
+ const DESIGN_PORT = process.env.DESIGN_PORT || 5400;
10
+ const APP_PORT = process.env.APP_PORT || 5402;
11
+
12
+ // Configuration
13
+ const PROJECT_ROOT = path.resolve(__dirname, '../..'); // learning-agent-os root
14
+ const APP_DIR = path.join(PROJECT_ROOT, 'app');
15
+ const AGENT_OS_DIR = path.join(PROJECT_ROOT, 'agent-os');
16
+
17
+ app.use(cors());
18
+ app.use(express.json());
19
+
20
+ // Helper to check file existence
21
+ const checkFile = (filePath) => {
22
+ return fs.existsSync(path.join(AGENT_OS_DIR, filePath));
23
+ };
24
+
25
+ // Helper to parse markdown checkboxes
26
+ const parseStatus = (relativePath) => {
27
+ const fullPath = path.join(AGENT_OS_DIR, relativePath);
28
+ console.log(`Reading path: ${fullPath}`);
29
+ if (!fs.existsSync(fullPath)) {
30
+ console.log(`File not found: ${fullPath}`);
31
+ return { exists: false, completed: 0, total: 0, nextItem: null, items: [] };
32
+ }
33
+ const content = fs.readFileSync(fullPath, 'utf-8');
34
+ const total = (content.match(/- \[ \]/g) || []).length + (content.match(/- \[x\]/g) || []).length;
35
+ const completed = (content.match(/- \[x\]/g) || []).length;
36
+
37
+ // Find next incomplete item and all items
38
+ let nextItem = null;
39
+ const items = [];
40
+ const lines = content.split('\n');
41
+
42
+ for (const line of lines) {
43
+ const match = line.match(/^\s*-\s*\[([ x])\]\s*(.+)$/);
44
+ if (match) {
45
+ const isCompleted = match[1] === 'x';
46
+ const text = match[2].trim();
47
+ // Clean up text (remove bolding, etc)
48
+ const cleanText = text.replace(/\*\*/g, '').replace(/^\d+\.\s*/, '');
49
+
50
+ items.push({ name: cleanText, completed: isCompleted });
51
+
52
+ if (!nextItem && !isCompleted) {
53
+ nextItem = cleanText;
54
+ }
55
+ }
56
+ }
57
+
58
+ // Check for boilerplate indicators
59
+ const boilerplateMarkers = [
60
+ '[Your Product Name]',
61
+ '[Database choice]',
62
+ '[Role]',
63
+ '[Feature 1]',
64
+ '[Target Audience]',
65
+ '[Unique Value Proposition',
66
+ 'MVP Launch',
67
+ 'First User',
68
+ 'Feature A'
69
+ ];
70
+ const isBoilerplate = boilerplateMarkers.some(marker => content.includes(marker));
71
+
72
+ return { exists: true, isBoilerplate, completed, total, nextItem, items };
73
+ };
74
+
75
+ // Helper to check service health
76
+ const checkService = (port) => {
77
+ return new Promise((resolve) => {
78
+ const http = require('http');
79
+ const req = http.get(`http://localhost:${port}/`, { timeout: 2000 }, (res) => {
80
+ // If we get any response, the port is active and serving HTTP
81
+ resolve(true);
82
+ // conn.destroy(); // Not needed if we just consume/ignore.
83
+ // Actually, we should consume resume to avoid hanging?
84
+ // Or just destroy.
85
+ res.resume();
86
+ });
87
+
88
+ req.on('error', (e) => {
89
+ resolve(false);
90
+ });
91
+
92
+ req.on('timeout', () => {
93
+ req.destroy();
94
+ resolve(false);
95
+ });
96
+ });
97
+ };
98
+
99
+ // API: Get Project Status
100
+ app.get('/api/status', async (req, res) => {
101
+ try {
102
+ const productFiles = {
103
+ mission: parseStatus('product/mission.md').exists ? parseStatus('product/mission.md') : parseStatus('product/product-overview.md'),
104
+ roadmap: parseStatus('product/roadmap.md').exists ? parseStatus('product/roadmap.md') : parseStatus('product/product-roadmap.md'),
105
+ techStack: parseStatus('product/tech-stack.md'),
106
+ };
107
+
108
+ // Get Specs
109
+ const specDirs = glob.sync('specs/*/', { cwd: AGENT_OS_DIR });
110
+ const specs = specDirs.map(dir => {
111
+ const name = path.basename(dir);
112
+ return {
113
+ name,
114
+ spec: parseStatus(`specs/${name}/spec.md`),
115
+ tasks: parseStatus(`specs/${name}/tasks.md`),
116
+ };
117
+ });
118
+
119
+ // Check Services
120
+ const services = {
121
+ api: true, // We are responding, so we are alive
122
+ design: await checkService(DESIGN_PORT),
123
+ app: await checkService(APP_PORT)
124
+ };
125
+
126
+ // Check for Design OS export and steps
127
+ const designDir = path.join(PROJECT_ROOT, 'design-system');
128
+ // Note: In dev, these files are in design/public/product. In prod, injected elsewhere.
129
+ // But for this local dev setup, we check where the initialize-design command puts them?
130
+ // Actually, initialize-design puts them in `design/public/product`.
131
+
132
+ const hasDesignExport = fs.existsSync(path.join(PROJECT_ROOT, 'product-plan'));
133
+ const hasDesignInit = fs.existsSync(path.join(designDir, 'product/product-overview.md'));
134
+ const hasTokens = fs.existsSync(path.join(designDir, 'product/design-system/colors.json'));
135
+ const hasShell = fs.existsSync(path.join(designDir, 'product/shell/spec.md'));
136
+
137
+ res.json({
138
+ product: productFiles,
139
+ services,
140
+ design: {
141
+ exists: hasTokens,
142
+ initialized: hasDesignInit || fs.existsSync(path.join(designDir, 'product/mission.md')) || fs.existsSync(path.join(designDir, 'product/product-overview.md')),
143
+ tokens: hasTokens,
144
+ shell: hasShell,
145
+ exported: hasDesignExport,
146
+ exportPrompts: {
147
+ oneShot: fs.existsSync(path.join(PROJECT_ROOT, 'product-plan/prompts/one-shot-prompt.md')),
148
+ section: fs.existsSync(path.join(PROJECT_ROOT, 'product-plan/prompts/section-prompt.md'))
149
+ }
150
+ },
151
+ implementation: {
152
+ scaffolded: fs.existsSync(path.join(APP_DIR, 'src/lib/utils.ts'))
153
+ },
154
+ specs,
155
+ projectRoot: PROJECT_ROOT
156
+ });
157
+ } catch (error) {
158
+ console.error(error);
159
+ res.status(500).json({ error: error.message });
160
+ }
161
+ });
162
+
163
+ // API: Scaffold New Spec
164
+ app.post('/api/scaffold/spec', (req, res) => {
165
+ const { name } = req.body;
166
+ if (!name) return res.status(400).json({ error: 'Spec name required' });
167
+
168
+ const specDir = path.join(AGENT_OS_DIR, 'specs', name);
169
+ if (fs.existsSync(specDir)) return res.status(400).json({ error: 'Spec already exists' });
170
+
171
+ fs.mkdirSync(specDir, { recursive: true });
172
+ // Create empty placeholders
173
+ fs.writeFileSync(path.join(specDir, 'spec.md'), '# Spec: ' + name);
174
+ fs.writeFileSync(path.join(specDir, 'tasks.md'), '# Tasks\n\n- [ ] Initial task');
175
+
176
+ res.json({ success: true, path: specDir });
177
+ });
178
+
179
+ // API: Delete Spec
180
+ app.delete('/api/scaffold/spec/:name', (req, res) => {
181
+ const { name } = req.params;
182
+ if (!name) return res.status(400).json({ error: 'Spec name required' });
183
+
184
+ // Validate name to prevent directory traversal or deleting non-spec files
185
+ // Allow alphanumeric, hyphens, underscores
186
+ if (!/^[a-zA-Z0-9-_]+$/.test(name)) {
187
+ return res.status(400).json({ error: 'Invalid spec name' });
188
+ }
189
+
190
+ const specDir = path.join(AGENT_OS_DIR, 'specs', name);
191
+ if (!fs.existsSync(specDir)) {
192
+ return res.status(404).json({ error: 'Spec not found' });
193
+ }
194
+
195
+ try {
196
+ fs.rmSync(specDir, { recursive: true, force: true });
197
+ res.json({ success: true });
198
+ } catch (error) {
199
+ console.error('Delete error:', error);
200
+ res.status(500).json({ error: 'Failed to delete spec' });
201
+ }
202
+ });
203
+
204
+ // API: Get File Content
205
+ app.get('/api/files', (req, res) => {
206
+ const { path: filePath } = req.query;
207
+ if (!filePath) return res.status(400).json({ error: 'File path required' });
208
+
209
+ // Prevent directory traversal
210
+ const safePath = path.normalize(filePath).replace(/^(\.\.(\/|\\|$))+/, '');
211
+ const absolutePath = path.join(AGENT_OS_DIR, safePath);
212
+
213
+ if (!absolutePath.startsWith(AGENT_OS_DIR)) {
214
+ return res.status(403).json({ error: 'Access denied' });
215
+ }
216
+
217
+ if (!fs.existsSync(absolutePath)) {
218
+ return res.status(404).json({ error: 'File not found' });
219
+ }
220
+
221
+ try {
222
+ const content = fs.readFileSync(absolutePath, 'utf-8');
223
+ res.json({ content });
224
+ } catch (error) {
225
+ res.status(500).json({ error: error.message });
226
+ }
227
+ });
228
+
229
+ // API: Save File Content
230
+ app.post('/api/files', (req, res) => {
231
+ const { path: filePath, content } = req.body;
232
+ if (!filePath || content === undefined) return res.status(400).json({ error: 'File path and content required' });
233
+
234
+ // Prevent directory traversal
235
+ const safePath = path.normalize(filePath).replace(/^(\.\.(\/|\\|$))+/, '');
236
+ const absolutePath = path.join(AGENT_OS_DIR, safePath);
237
+
238
+ if (!absolutePath.startsWith(AGENT_OS_DIR)) {
239
+ return res.status(403).json({ error: 'Access denied' });
240
+ }
241
+
242
+ try {
243
+ fs.writeFileSync(absolutePath, content, 'utf-8');
244
+ res.json({ success: true });
245
+ } catch (error) {
246
+ res.status(500).json({ error: error.message });
247
+ }
248
+ });
249
+
250
+ app.listen(PORT, () => {
251
+ console.log(`Control Center Backend running on http://localhost:${PORT}`);
252
+ console.log(`Monitoring Agent OS at: ${AGENT_OS_DIR}`);
253
+ });
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "backend",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "start": "node index.js",
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [],
11
+ "author": "",
12
+ "license": "ISC",
13
+ "dependencies": {
14
+ "cors": "^2.8.5",
15
+ "dotenv": "^17.2.3",
16
+ "express": "^5.2.1",
17
+ "glob": "^10.3.10"
18
+ }
19
+ }
@@ -0,0 +1,73 @@
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9
+
10
+ ## React Compiler
11
+
12
+ The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13
+
14
+ ## Expanding the ESLint configuration
15
+
16
+ If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
17
+
18
+ ```js
19
+ export default defineConfig([
20
+ globalIgnores(['dist']),
21
+ {
22
+ files: ['**/*.{ts,tsx}'],
23
+ extends: [
24
+ // Other configs...
25
+
26
+ // Remove tseslint.configs.recommended and replace with this
27
+ tseslint.configs.recommendedTypeChecked,
28
+ // Alternatively, use this for stricter rules
29
+ tseslint.configs.strictTypeChecked,
30
+ // Optionally, add this for stylistic rules
31
+ tseslint.configs.stylisticTypeChecked,
32
+
33
+ // Other configs...
34
+ ],
35
+ languageOptions: {
36
+ parserOptions: {
37
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
38
+ tsconfigRootDir: import.meta.dirname,
39
+ },
40
+ // other options...
41
+ },
42
+ },
43
+ ])
44
+ ```
45
+
46
+ You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
47
+
48
+ ```js
49
+ // eslint.config.js
50
+ import reactX from 'eslint-plugin-react-x'
51
+ import reactDom from 'eslint-plugin-react-dom'
52
+
53
+ export default defineConfig([
54
+ globalIgnores(['dist']),
55
+ {
56
+ files: ['**/*.{ts,tsx}'],
57
+ extends: [
58
+ // Other configs...
59
+ // Enable lint rules for React
60
+ reactX.configs['recommended-typescript'],
61
+ // Enable lint rules for React DOM
62
+ reactDom.configs.recommended,
63
+ ],
64
+ languageOptions: {
65
+ parserOptions: {
66
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
67
+ tsconfigRootDir: import.meta.dirname,
68
+ },
69
+ // other options...
70
+ },
71
+ },
72
+ ])
73
+ ```
@@ -0,0 +1,23 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import tseslint from 'typescript-eslint'
6
+ import { defineConfig, globalIgnores } from 'eslint/config'
7
+
8
+ export default defineConfig([
9
+ globalIgnores(['dist']),
10
+ {
11
+ files: ['**/*.{ts,tsx}'],
12
+ extends: [
13
+ js.configs.recommended,
14
+ tseslint.configs.recommended,
15
+ reactHooks.configs.flat.recommended,
16
+ reactRefresh.configs.vite,
17
+ ],
18
+ languageOptions: {
19
+ ecmaVersion: 2020,
20
+ globals: globals.browser,
21
+ },
22
+ },
23
+ ])
@@ -0,0 +1,21 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link
10
+ href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=IBM+Plex+Mono:wght@400;500&display=swap"
11
+ rel="stylesheet">
12
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
13
+ <title>Control Center</title>
14
+ </head>
15
+
16
+ <body>
17
+ <div id="root"></div>
18
+ <script type="module" src="/src/main.tsx"></script>
19
+ </body>
20
+
21
+ </html>
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "frontend",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc -b && vite build",
9
+ "lint": "eslint .",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "@builderos/agent-os-ui": "*",
14
+ "@tailwindcss/typography": "^0.5.19",
15
+ "axios": "^1.13.2",
16
+ "clsx": "^2.1.1",
17
+ "framer-motion": "^12.23.26",
18
+ "lucide-react": "^0.562.0",
19
+ "react": "^18.3.1",
20
+ "react-dom": "^18.3.1",
21
+ "react-markdown": "^9.0.1",
22
+ "remark-breaks": "^4.0.0",
23
+ "remark-gfm": "^4.0.1",
24
+ "tailwind-merge": "^3.4.0"
25
+ },
26
+ "devDependencies": {
27
+ "@eslint/js": "^9.39.1",
28
+ "@types/node": "^24.10.1",
29
+ "@types/react": "^18.3.12",
30
+ "@types/react-dom": "^18.3.1",
31
+ "@vitejs/plugin-react": "^5.1.1",
32
+ "autoprefixer": "^10.4.23",
33
+ "eslint": "^9.39.1",
34
+ "eslint-plugin-react-hooks": "^7.0.1",
35
+ "eslint-plugin-react-refresh": "^0.4.24",
36
+ "globals": "^16.5.0",
37
+ "postcss": "^8.5.6",
38
+ "tailwindcss": "^3.4.17",
39
+ "typescript": "~5.9.3",
40
+ "typescript-eslint": "^8.46.4",
41
+ "vite": "^7.2.4"
42
+ }
43
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
+ <rect width="100" height="100" rx="20" fill="#1c1917"/>
3
+ <path d="M50 20 L75 80 L50 65 L25 80 Z" fill="white" stroke="none"/>
4
+ </svg>
@@ -0,0 +1,11 @@
1
+ {
2
+ "api": "",
3
+ "app": "http://localhost:3002",
4
+ "design": "http://localhost:3000",
5
+ "ports": {
6
+ "design": 3000,
7
+ "api": 3003,
8
+ "app": 3002,
9
+ "ui": 5173
10
+ }
11
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -0,0 +1,42 @@
1
+ #root {
2
+ max-width: 1280px;
3
+ margin: 0 auto;
4
+ padding: 2rem;
5
+ text-align: center;
6
+ }
7
+
8
+ .logo {
9
+ height: 6em;
10
+ padding: 1.5em;
11
+ will-change: filter;
12
+ transition: filter 300ms;
13
+ }
14
+ .logo:hover {
15
+ filter: drop-shadow(0 0 2em #646cffaa);
16
+ }
17
+ .logo.react:hover {
18
+ filter: drop-shadow(0 0 2em #61dafbaa);
19
+ }
20
+
21
+ @keyframes logo-spin {
22
+ from {
23
+ transform: rotate(0deg);
24
+ }
25
+ to {
26
+ transform: rotate(360deg);
27
+ }
28
+ }
29
+
30
+ @media (prefers-reduced-motion: no-preference) {
31
+ a:nth-of-type(2) .logo {
32
+ animation: logo-spin infinite 20s linear;
33
+ }
34
+ }
35
+
36
+ .card {
37
+ padding: 2em;
38
+ }
39
+
40
+ .read-the-docs {
41
+ color: #888;
42
+ }