@theproductguy/create-mission-control 1.0.4 → 1.0.5

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/bin/cli.js CHANGED
@@ -159,13 +159,62 @@ async function init() {
159
159
 
160
160
  fs.writeFileSync(appPkgPath, JSON.stringify(appPkg, null, 2));
161
161
 
162
+ // 4. Copy root config files
163
+ console.log(cyan('\n4. Setting up quality tooling...'));
164
+
165
+ const rootConfigFiles = [
166
+ '.gitignore',
167
+ '.prettierrc',
168
+ '.env.example',
169
+ 'eslint.config.js',
170
+ 'commitlint.config.js',
171
+ 'lint-staged.config.js',
172
+ 'vitest.config.ts',
173
+ 'README.md'
174
+ ];
175
+
176
+ for (const file of rootConfigFiles) {
177
+ const src = path.join(templateDir, file);
178
+ if (fs.existsSync(src)) {
179
+ fs.copyFileSync(src, path.join(root, file));
180
+ }
181
+ }
182
+
183
+ // Copy directories
184
+ const rootDirs = ['.github', '.husky', '.vscode', 'src/__tests__'];
185
+ for (const dir of rootDirs) {
186
+ const src = path.join(templateDir, dir);
187
+ if (fs.existsSync(src)) {
188
+ fs.cpSync(src, path.join(root, dir), copyOptions);
189
+ }
190
+ }
191
+
192
+ // 5. Initialize git repository
193
+ console.log(cyan('\n5. Initializing git repository...'));
194
+ try {
195
+ const { execSync } = await import('node:child_process');
196
+ execSync('git init', { cwd: root, stdio: 'inherit' });
197
+ execSync('git add .', { cwd: root, stdio: 'ignore' });
198
+ } catch (e) {
199
+ console.log(' (Git initialization skipped - git may not be available)');
200
+ }
162
201
 
163
- console.log(green(`\n\nAgent OS Workspace created successfully! šŸš€\n`));
164
- console.log(`Next steps:\n`);
202
+ console.log(green(`\n\nāœ… Agent OS Workspace created successfully! šŸš€\n`));
203
+ console.log(bold('What\'s included:'));
204
+ console.log(' āœ“ ESLint + Prettier + Husky pre-commit hooks');
205
+ console.log(' āœ“ Vitest for testing');
206
+ console.log(' āœ“ GitHub Actions CI workflow');
207
+ console.log(' āœ“ Impeccable design commands');
208
+ console.log(' āœ“ AI Slop Guard hook');
209
+ console.log(`\n${bold('Next steps:')}\n`);
165
210
  console.log(` cd ${result.projectName}`);
166
211
  console.log(` npm install`);
167
212
  console.log(` npm run dev\n`);
168
- console.log(`This will start the App, Control Center, and Design OS concurrently.`);
213
+ console.log(`${bold('Recommended workflow:')}`);
214
+ console.log(` 1. /plan-product — Define your product`);
215
+ console.log(` 2. /create-constitution — Set project principles`);
216
+ console.log(` 3. /research-tech — Research your stack`);
217
+ console.log(` 4. /design-tokens — Start designing`);
169
218
  });
170
219
  });
171
220
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theproductguy/create-mission-control",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Scaffolding tool for Agent OS applications",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,28 @@
1
+ # ==============================================
2
+ # Environment Variables
3
+ # ==============================================
4
+ # Copy this file to .env.local and fill in your values
5
+ # NEVER commit .env.local to version control
6
+
7
+ # ==============================================
8
+ # Application
9
+ # ==============================================
10
+ # VITE_APP_NAME=My App
11
+ # VITE_APP_URL=http://localhost:5402
12
+
13
+ # ==============================================
14
+ # API Configuration
15
+ # ==============================================
16
+ # VITE_API_URL=http://localhost:5403
17
+
18
+ # ==============================================
19
+ # Feature Flags
20
+ # ==============================================
21
+ # VITE_ENABLE_ANALYTICS=false
22
+ # VITE_ENABLE_DEBUG_MODE=false
23
+
24
+ # ==============================================
25
+ # Third-Party Services (add as needed)
26
+ # ==============================================
27
+ # VITE_SENTRY_DSN=
28
+ # VITE_POSTHOG_KEY=
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a bug to help us improve
4
+ title: '[BUG] '
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Bug Description
10
+
11
+ <!-- A clear and concise description of what the bug is -->
12
+
13
+ ## Steps to Reproduce
14
+
15
+ 1. Go to '...'
16
+ 2. Click on '...'
17
+ 3. Scroll down to '...'
18
+ 4. See error
19
+
20
+ ## Expected Behavior
21
+
22
+ <!-- What you expected to happen -->
23
+
24
+ ## Actual Behavior
25
+
26
+ <!-- What actually happened -->
27
+
28
+ ## Screenshots
29
+
30
+ <!-- If applicable, add screenshots to help explain your problem -->
31
+
32
+ ## Environment
33
+
34
+ - OS: [e.g., macOS 14.0]
35
+ - Browser: [e.g., Chrome 120]
36
+ - Node version: [e.g., 20.10.0]
37
+
38
+ ## Additional Context
39
+
40
+ <!-- Add any other context about the problem here -->
@@ -0,0 +1,30 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest an idea for this project
4
+ title: '[FEATURE] '
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Problem Statement
10
+
11
+ <!-- Describe the problem you're trying to solve -->
12
+
13
+ ## Proposed Solution
14
+
15
+ <!-- Describe the solution you'd like -->
16
+
17
+ ## Alternatives Considered
18
+
19
+ <!-- Describe any alternative solutions or features you've considered -->
20
+
21
+ ## Additional Context
22
+
23
+ <!-- Add any other context, mockups, or screenshots about the feature request here -->
24
+
25
+ ## Acceptance Criteria
26
+
27
+ <!-- Define what "done" looks like for this feature -->
28
+ - [ ] Criterion 1
29
+ - [ ] Criterion 2
30
+ - [ ] Criterion 3
@@ -0,0 +1,33 @@
1
+ ## Description
2
+
3
+ <!-- Describe the changes in this PR -->
4
+
5
+ ## Type of Change
6
+
7
+ - [ ] šŸ› Bug fix (non-breaking change which fixes an issue)
8
+ - [ ] ✨ New feature (non-breaking change which adds functionality)
9
+ - [ ] šŸ’„ Breaking change (fix or feature that would cause existing functionality to not work as expected)
10
+ - [ ] šŸ“ Documentation update
11
+ - [ ] šŸŽØ Style/UI update
12
+ - [ ] ā™»ļø Refactor (no functional changes)
13
+ - [ ] 🧪 Test update
14
+
15
+ ## Related Issues
16
+
17
+ <!-- Link to related issues: Fixes #123 -->
18
+
19
+ ## Checklist
20
+
21
+ - [ ] My code follows the project's style guidelines
22
+ - [ ] I have performed a self-review of my code
23
+ - [ ] I have added tests that prove my fix is effective or that my feature works
24
+ - [ ] New and existing unit tests pass locally with my changes
25
+ - [ ] I have run `/audit` and addressed any issues
26
+
27
+ ## Screenshots (if applicable)
28
+
29
+ <!-- Add screenshots to help explain your changes -->
30
+
31
+ ## Additional Context
32
+
33
+ <!-- Add any other context about the PR here -->
@@ -0,0 +1,83 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main, develop]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Setup Node.js
17
+ uses: actions/setup-node@v4
18
+ with:
19
+ node-version: '20'
20
+ cache: 'npm'
21
+
22
+ - name: Install dependencies
23
+ run: npm ci
24
+
25
+ - name: Run ESLint
26
+ run: npm run lint --if-present
27
+
28
+ - name: Check formatting
29
+ run: npm run format:check --if-present
30
+
31
+ build:
32
+ name: Build
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+
37
+ - name: Setup Node.js
38
+ uses: actions/setup-node@v4
39
+ with:
40
+ node-version: '20'
41
+ cache: 'npm'
42
+
43
+ - name: Install dependencies
44
+ run: npm ci
45
+
46
+ - name: Build
47
+ run: npm run build --if-present
48
+
49
+ test:
50
+ name: Test
51
+ runs-on: ubuntu-latest
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+
55
+ - name: Setup Node.js
56
+ uses: actions/setup-node@v4
57
+ with:
58
+ node-version: '20'
59
+ cache: 'npm'
60
+
61
+ - name: Install dependencies
62
+ run: npm ci
63
+
64
+ - name: Run tests
65
+ run: npm test --if-present
66
+
67
+ typecheck:
68
+ name: Type Check
69
+ runs-on: ubuntu-latest
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+
73
+ - name: Setup Node.js
74
+ uses: actions/setup-node@v4
75
+ with:
76
+ node-version: '20'
77
+ cache: 'npm'
78
+
79
+ - name: Install dependencies
80
+ run: npm ci
81
+
82
+ - name: Type check
83
+ run: npm run typecheck --if-present
@@ -0,0 +1 @@
1
+ npx --no -- commitlint --edit ${1}
@@ -0,0 +1 @@
1
+ npx lint-staged
@@ -0,0 +1,11 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "trailingComma": "es5",
6
+ "printWidth": 100,
7
+ "bracketSpacing": true,
8
+ "arrowParens": "always",
9
+ "endOfLine": "lf",
10
+ "plugins": ["prettier-plugin-tailwindcss"]
11
+ }
@@ -0,0 +1,78 @@
1
+ # {PROJECT_NAME}
2
+
3
+ > Built with [Agent OS](https://github.com/s1dd4rth/mission-control) — Design-driven development
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Install dependencies
9
+ npm install
10
+
11
+ # Start development servers
12
+ npm run dev
13
+ ```
14
+
15
+ This will start:
16
+ - **Design OS:** http://localhost:5400
17
+ - **Mission Control:** http://localhost:5401
18
+ - **Application:** http://localhost:5402
19
+ - **API:** http://localhost:5403
20
+
21
+ ## Project Structure
22
+
23
+ ```
24
+ ā”œā”€ā”€ agent-os/ # Product strategy & commands
25
+ │ ā”œā”€ā”€ product/ # Mission, roadmap, tech stack
26
+ │ ā”œā”€ā”€ commands/ # Agent OS commands
27
+ │ ā”œā”€ā”€ specs/ # Feature specifications
28
+ │ └── constitution.md # Project principles
29
+ │
30
+ ā”œā”€ā”€ design-system/ # Design OS
31
+ │ ā”œā”€ā”€ .gemini/ # Commands, skills, hooks
32
+ │ ā”œā”€ā”€ product/ # Synced from agent-os
33
+ │ └── src/ # Design components
34
+ │
35
+ ā”œā”€ā”€ control-center/ # Mission Control dashboard
36
+ │ ā”œā”€ā”€ frontend/ # React dashboard
37
+ │ └── backend/ # API server
38
+ │
39
+ └── app/ # Your application
40
+ ```
41
+
42
+ ## Available Scripts
43
+
44
+ | Script | Description |
45
+ |--------|-------------|
46
+ | `npm run dev` | Start all development servers |
47
+ | `npm run build` | Build for production |
48
+ | `npm test` | Run tests |
49
+ | `npm run lint` | Run ESLint |
50
+ | `npm run format` | Format with Prettier |
51
+ | `npm run typecheck` | TypeScript type checking |
52
+
53
+ ## Workflow
54
+
55
+ 1. **Plan** — Define mission, roadmap, and tech stack
56
+ 2. **Design** — Create design tokens, shell, and sections
57
+ 3. **Specify** — Shape detailed feature specifications
58
+ 4. **Implement** — Build features with TDD approach
59
+
60
+ ## Quality Commands
61
+
62
+ | Command | Purpose |
63
+ |---------|---------|
64
+ | `/create-constitution` | Establish project principles |
65
+ | `/research-tech` | Research tech stack best practices |
66
+ | `/audit` | Run accessibility & quality audit |
67
+ | `/polish` | Final visual refinements |
68
+
69
+ ## Contributing
70
+
71
+ 1. Create a feature branch from `main`
72
+ 2. Make your changes
73
+ 3. Run `npm run lint && npm test`
74
+ 4. Submit a pull request
75
+
76
+ ## License
77
+
78
+ MIT
@@ -0,0 +1,89 @@
1
+ # COMMAND: Create Constitution
2
+
3
+ ## Goal
4
+ Establish the project's governing principles and development guidelines that will guide all subsequent development phases. This is a one-time setup command inspired by spec-driven development.
5
+
6
+ ## When to Run
7
+ - **Once** at the beginning of a new project
8
+ - After `/plan-product` but before `/design-tokens`
9
+ - When you want to formalize project standards
10
+
11
+ ## Instructions
12
+
13
+ ### Step 1: Gather Context
14
+ Read the following files to understand the project:
15
+ - `agent-os/product/mission.md` — Product vision and goals
16
+ - `agent-os/product/roadmap.md` — Planned features
17
+ - `agent-os/product/tech-stack.md` — Technology choices
18
+
19
+ ### Step 2: Create Constitution Document
20
+ Create `agent-os/constitution.md` with the following sections:
21
+
22
+ ```markdown
23
+ # Project Constitution
24
+
25
+ ## Core Principles
26
+ [3-5 high-level principles that guide all decisions]
27
+
28
+ ## Code Quality Standards
29
+ - [ ] All code must pass ESLint with no errors
30
+ - [ ] All code must be formatted with Prettier
31
+ - [ ] TypeScript strict mode is enforced
32
+ - [ ] No `any` types without explicit justification
33
+ - [ ] All public APIs must have JSDoc comments
34
+
35
+ ## Testing Philosophy
36
+ - [ ] Unit tests for all business logic
37
+ - [ ] Integration tests for critical user flows
38
+ - [ ] Minimum 80% code coverage for new features
39
+ - [ ] TDD approach for complex features
40
+
41
+ ## UX Consistency Rules
42
+ - [ ] Follow the Impeccable design principles
43
+ - [ ] Run `/audit` before any design handoff
44
+ - [ ] No AI Slop patterns (see frontend-design skill)
45
+ - [ ] Mobile-first responsive design
46
+ - [ ] WCAG 2.1 AA accessibility compliance
47
+
48
+ ## Performance Budgets
49
+ - [ ] First Contentful Paint < 1.5s
50
+ - [ ] Largest Contentful Paint < 2.5s
51
+ - [ ] Cumulative Layout Shift < 0.1
52
+ - [ ] Bundle size < 200KB (gzipped)
53
+
54
+ ## Security Requirements
55
+ - [ ] No secrets in code
56
+ - [ ] Input validation on all user inputs
57
+ - [ ] HTTPS only in production
58
+ - [ ] CSP headers configured
59
+
60
+ ## Git Workflow
61
+ - [ ] Conventional commits required
62
+ - [ ] PR reviews required before merge
63
+ - [ ] Feature branches from `main`
64
+ - [ ] Squash merge to maintain clean history
65
+
66
+ ## Definition of Done
67
+ A feature is considered "done" when:
68
+ 1. [ ] Code is written and reviewed
69
+ 2. [ ] Tests are passing (unit + integration)
70
+ 3. [ ] Documentation is updated
71
+ 4. [ ] Accessibility audit passes
72
+ 5. [ ] Performance budget is met
73
+ 6. [ ] `/audit` passes with no critical issues
74
+ ```
75
+
76
+ ### Step 3: Customize for Project
77
+ Based on the product mission and tech stack, customize:
78
+ - Add project-specific principles
79
+ - Adjust performance budgets if needed
80
+ - Add any domain-specific requirements
81
+
82
+ ### Step 4: Verification
83
+ - Confirm `agent-os/constitution.md` exists
84
+ - Output message: "Constitution created! These principles will guide all subsequent development. Run `/research-tech` next to analyze your tech stack."
85
+
86
+ ## Notes
87
+ - The constitution should be a living document
88
+ - Team members should review and commit to these principles
89
+ - Reference this document in code reviews
@@ -0,0 +1,93 @@
1
+ # COMMAND: Research Tech Stack
2
+
3
+ ## Goal
4
+ Research and document best practices, current versions, and known gotchas for the technologies chosen in `tech-stack.md`. This ensures the implementation uses up-to-date patterns and avoids common pitfalls.
5
+
6
+ ## When to Run
7
+ - After `/plan-product` has created `tech-stack.md`
8
+ - Before `/design-tokens` or implementation begins
9
+ - When updating to new versions of key dependencies
10
+
11
+ ## Instructions
12
+
13
+ ### Step 1: Read Tech Stack
14
+ Read `agent-os/product/tech-stack.md` to understand the chosen technologies.
15
+
16
+ ### Step 2: Analyze Technologies
17
+ For each tech choice, answer:
18
+ - **Why this choice?** (Pros/Cons)
19
+ - **Latest Version?** (Use Context7 to check latest docs/features if possible)
20
+ - **Alternatives considered?**
21
+
22
+ > **Tip:** If you have Context7 configured, use it to fetch the latest documentation for accurate analysis.
23
+ > Prompt: "Using Context7, what are the latest best practices for [Technology]?"
24
+
25
+ For each major technology in the stack, research:
26
+
27
+ 1. **Current stable version** — What version should we pin to?
28
+ 2. **Breaking changes** — Any recent breaking changes to be aware of?
29
+ 3. **Best practices** — What are the current recommended patterns?
30
+ 4. **Common pitfalls** — What mistakes do developers commonly make?
31
+ 5. **Performance tips** — Any optimization opportunities?
32
+
33
+ ### Step 3: Create Research Document
34
+ Create `agent-os/research.md` with the following structure:
35
+
36
+ ```markdown
37
+ # Technology Research
38
+
39
+ **Generated:** [Date]
40
+ **Tech Stack:** [List from tech-stack.md]
41
+
42
+ ---
43
+
44
+ ## [Technology Name]
45
+
46
+ ### Version
47
+ - **Recommended:** [version]
48
+ - **Latest Stable:** [version]
49
+ - **Our Choice:** [version + justification]
50
+
51
+ ### Key Features to Use
52
+ - [Feature 1]
53
+ - [Feature 2]
54
+
55
+ ### Patterns to Follow
56
+ - [Pattern 1 with code example]
57
+ - [Pattern 2 with code example]
58
+
59
+ ### Pitfalls to Avoid
60
+ - āš ļø [Pitfall 1 and how to avoid]
61
+ - āš ļø [Pitfall 2 and how to avoid]
62
+
63
+ ### Performance Considerations
64
+ - [Tip 1]
65
+ - [Tip 2]
66
+
67
+ ### Resources
68
+ - [Official docs link]
69
+ - [Helpful article link]
70
+
71
+ ---
72
+
73
+ [Repeat for each technology]
74
+ ```
75
+
76
+ ### Step 4: Identify Integration Concerns
77
+ Document any concerns where technologies interact:
78
+ - State management + React patterns
79
+ - CSS framework + component library conflicts
80
+ - Build tool configuration needs
81
+
82
+ ### Step 5: Create Version Lock File
83
+ Update `package.json` with pinned versions based on research.
84
+
85
+ ### Step 6: Verification
86
+ - Confirm `agent-os/research.md` exists
87
+ - Ensure all major technologies are covered
88
+ - Output message: "Tech research complete! Review the findings in `agent-os/research.md`. Run `/design-tokens` next to begin designing."
89
+
90
+ ## Notes
91
+ - Research should be done even for familiar technologies
92
+ - Check for security advisories on dependencies
93
+ - Consider LTS vs. latest tradeoffs
@@ -11,7 +11,8 @@ Create the technical specification (`spec.md`) for a specific product section.
11
11
 
12
12
  ### Step 1: Analyze Context
13
13
  - Read `design-system/product/product-roadmap.md` to understand where this section fits.
14
- - Read `design-system/product/product-overview.md` to understand the overall product context.
14
+ - Read `design-system/product/product-overview.md` to understand the data model and core flows.
15
+ - Read `design-system/design-tokens.md` and `design-system/app-shell.md` to understand the design language and layout constraints.
15
16
 
16
17
  ### Step 2: Create Spec File
17
18
  Create `design-system/product/sections/[section-id]/spec.md`.
@@ -0,0 +1,20 @@
1
+ # Context7 Integration
2
+
3
+ Context7 (context7.com) provides up-to-date documentation and code examples for your tech stack, ensuring your agent uses the latest APIs and best practices.
4
+
5
+ ## Setup
6
+
7
+ 1. **Get API Key**: Go to [context7.com](https://context7.com) and get your API key.
8
+ 2. **Configure Agent**:
9
+ * **Cursor/Windsurf**: Add Context7 as an MCP server.
10
+ * Server URL: `https://context7.com/api/mcp` (or as per their specific MCP setup instructions)
11
+ * Env: `CONTEXT7_API_KEY=your_key`
12
+ * **Manual**: Just tell the agent "Use Context7 to look up documentation for [library]" if you have the proper system prompt or tool configured.
13
+
14
+ ## Usage
15
+
16
+ When running `/research-tech` or implementation commands, the agent will look for Context7 tools.
17
+
18
+ ### Example Prompts
19
+ - "Using Context7, interpret the latest docs for Next.js App Router."
20
+ - "Check Context7 for `shadcn/ui` installation steps."
@@ -0,0 +1,25 @@
1
+ export default {
2
+ extends: ['@commitlint/config-conventional'],
3
+ rules: {
4
+ 'type-enum': [
5
+ 2,
6
+ 'always',
7
+ [
8
+ 'feat', // New feature
9
+ 'fix', // Bug fix
10
+ 'docs', // Documentation
11
+ 'style', // Formatting, missing semicolons, etc.
12
+ 'refactor', // Code restructuring without changing behavior
13
+ 'perf', // Performance improvements
14
+ 'test', // Adding or updating tests
15
+ 'build', // Build system or dependencies
16
+ 'ci', // CI configuration
17
+ 'chore', // Maintenance tasks
18
+ 'revert', // Reverting changes
19
+ ],
20
+ ],
21
+ 'subject-case': [2, 'always', 'lower-case'],
22
+ 'subject-empty': [2, 'never'],
23
+ 'type-empty': [2, 'never'],
24
+ },
25
+ }
@@ -136,6 +136,53 @@ app.get('/api/status', async (req, res) => {
136
136
  const hasTokens = fs.existsSync(path.join(designDir, 'product/design-system/colors.json'));
137
137
  const hasShell = fs.existsSync(path.join(designDir, 'product/shell/spec.md'));
138
138
 
139
+ // Implementation tracking
140
+ const appDir = path.join(PROJECT_ROOT, 'app');
141
+ const hasScaffold = fs.existsSync(path.join(APP_DIR, 'src/lib/utils.ts'));
142
+
143
+ // Check for test files
144
+ const testFiles = glob.sync('**/*.{test,spec}.{ts,tsx,js,jsx}', { cwd: appDir, ignore: ['node_modules/**'] });
145
+ const hasTests = testFiles.length > 0;
146
+
147
+ // Check for coverage report
148
+ const coverageDir = path.join(PROJECT_ROOT, 'coverage');
149
+ const coverageSummary = path.join(coverageDir, 'coverage-summary.json');
150
+ let coveragePercent = null;
151
+ if (fs.existsSync(coverageSummary)) {
152
+ try {
153
+ const coverage = JSON.parse(fs.readFileSync(coverageSummary, 'utf-8'));
154
+ if (coverage.total && coverage.total.lines) {
155
+ coveragePercent = Math.round(coverage.total.lines.pct);
156
+ }
157
+ } catch (e) {
158
+ // Ignore parsing errors
159
+ }
160
+ }
161
+
162
+ // Check git status
163
+ let gitInfo = { initialized: false, branch: null, uncommitted: 0, lastCommit: null };
164
+ const gitDir = path.join(PROJECT_ROOT, '.git');
165
+ if (fs.existsSync(gitDir)) {
166
+ gitInfo.initialized = true;
167
+ try {
168
+ const { execSync } = require('child_process');
169
+ gitInfo.branch = execSync('git rev-parse --abbrev-ref HEAD', { cwd: PROJECT_ROOT, encoding: 'utf-8' }).trim();
170
+ const status = execSync('git status --porcelain', { cwd: PROJECT_ROOT, encoding: 'utf-8' });
171
+ gitInfo.uncommitted = status.split('\n').filter(l => l.trim()).length;
172
+ try {
173
+ gitInfo.lastCommit = execSync('git log -1 --pretty=format:"%s"', { cwd: PROJECT_ROOT, encoding: 'utf-8' }).trim();
174
+ } catch (e) {
175
+ // No commits yet
176
+ }
177
+ } catch (e) {
178
+ // Git commands failed
179
+ }
180
+ }
181
+
182
+ // Check for linked specs
183
+ const specsWithTasks = specs.filter(s => s.tasks.exists && s.tasks.total > 0);
184
+ const specsCompleted = specs.filter(s => s.tasks.exists && s.tasks.completed === s.tasks.total && s.tasks.total > 0);
185
+
139
186
  res.json({
140
187
  product: productFiles,
141
188
  services,
@@ -155,7 +202,17 @@ app.get('/api/status', async (req, res) => {
155
202
  }
156
203
  },
157
204
  implementation: {
158
- scaffolded: fs.existsSync(path.join(APP_DIR, 'src/lib/utils.ts'))
205
+ scaffolded: hasScaffold,
206
+ tests: {
207
+ count: testFiles.length,
208
+ hasTests
209
+ },
210
+ coverage: coveragePercent,
211
+ specs: {
212
+ total: specsWithTasks.length,
213
+ completed: specsCompleted.length
214
+ },
215
+ git: gitInfo
159
216
  },
160
217
  specs,
161
218
  projectRoot: PROJECT_ROOT
@@ -46,6 +46,21 @@ interface ProjectState {
46
46
  };
47
47
  implementation: {
48
48
  scaffolded: boolean;
49
+ tests?: {
50
+ count: number;
51
+ hasTests: boolean;
52
+ };
53
+ coverage?: number | null;
54
+ specs?: {
55
+ total: number;
56
+ completed: number;
57
+ };
58
+ git?: {
59
+ initialized: boolean;
60
+ branch: string | null;
61
+ uncommitted: number;
62
+ lastCommit: string | null;
63
+ };
49
64
  };
50
65
  specs: Spec[];
51
66
  services?: {
@@ -701,77 +716,14 @@ function App() {
701
716
  </div>
702
717
  </section>
703
718
 
704
- {/* Phase 3: Implementation */}
705
- <section className="bg-card border border-border rounded-xl p-5 shadow-sm h-full flex flex-col transition-all hover:shadow-md hover:border-border/80">
706
- <div className="flex items-center gap-3 mb-5 pb-4 border-b border-border/50">
707
- <div className="p-2 bg-sidebar-primary/10 text-sidebar-primary rounded-lg">
708
- <Package size={20} />
709
- </div>
710
- <h2 className="text-lg font-semibold">3. Implementation</h2>
711
- </div>
712
-
713
- <div className="space-y-4 flex-1">
714
- <div className="flex items-center justify-between p-3 bg-secondary/30 rounded-lg border border-border/50">
715
- <span className="text-foreground font-medium text-sm flex items-center gap-2"><Layout size={16} className="text-muted-foreground" /> Scaffold</span>
716
- {state?.implementation?.scaffolded ? (
717
- <span className="text-emerald-600 bg-emerald-50 dark:bg-emerald-900/20 px-2 py-0.5 rounded text-xs font-medium border border-emerald-200 dark:border-emerald-800">Done</span>
718
- ) : (
719
- <span className="text-muted-foreground bg-secondary px-2 py-0.5 rounded text-xs font-medium border border-border">Pending</span>
720
- )}
721
- </div>
722
- </div>
723
-
724
- <div className="mt-6">
725
- {!state?.implementation?.scaffolded ? (
726
- <PromptButton
727
- label="Scaffold App"
728
- prompt="Antigravity, scaffold the implementation. Read 'agent-os/commands/scaffold-implementation/scaffold-implementation.md'."
729
- onClick={copyToClipboard}
730
- />
731
- ) : (
732
- <div className="p-3 bg-secondary/30 rounded-lg border border-border/50 text-sm text-muted-foreground text-center italic mb-4">
733
- App scaffolded. Ready for implementation.
734
- </div>
735
- )}
736
-
737
- {state?.implementation?.scaffolded && state?.design?.exportPrompts?.oneShot && (
738
- <div className="pt-3 border-t border-border/50">
739
- <p className="text-xs text-muted-foreground mb-2 font-medium">Implementation Options:</p>
740
- <div className="space-y-2">
741
- <PromptButton
742
- label="Option A: One-Shot (All)"
743
- prompt={`Antigravity, implement the app. Read 'product-plan/prompts/one-shot-prompt.md'.`}
744
- onClick={copyToClipboard}
745
- small
746
- primary
747
- />
748
- {state?.design?.exportPrompts?.section && (
749
- <div className="relative">
750
- <PromptButton
751
- label="Option B: Incremental (Section)"
752
- prompt={`Antigravity, implement a section. Read 'product-plan/prompts/section-prompt.md'.`}
753
- onClick={copyToClipboard}
754
- small
755
- />
756
- <p className="text-[10px] text-muted-foreground mt-1.5 text-center leading-tight">
757
- Build feature-by-feature using the <strong>Feature Specs</strong> list &rarr;
758
- </p>
759
- </div>
760
- )}
761
- </div>
762
- </div>
763
- )}
764
- </div>
765
- </section>
766
-
767
- {/* Phase 4: Specs & Implementation */}
719
+ {/* Phase 3: Feature Specs */}
768
720
  <section className="bg-card border border-border rounded-xl p-5 shadow-sm col-span-1 md:col-span-2 lg:col-span-1 h-full flex flex-col transition-all hover:shadow-md hover:border-border/80">
769
721
  <div className="flex items-center justify-between mb-5 pb-4 border-b border-border/50">
770
722
  <div className="flex items-center gap-3">
771
723
  <div className="p-2 bg-sidebar-primary/10 text-sidebar-primary rounded-lg">
772
724
  <Code size={20} />
773
725
  </div>
774
- <h2 className="text-lg font-semibold">4. Feature Specs</h2>
726
+ <h2 className="text-lg font-semibold">3. Feature Specs</h2>
775
727
  </div>
776
728
  <button className="text-xs bg-secondary hover:bg-secondary/80 border border-border px-3 py-2 rounded-md flex items-center gap-1.5 font-medium transition cursor-pointer"
777
729
  onClick={() => setCreatingSpec(true)}>
@@ -780,6 +732,24 @@ function App() {
780
732
  </div>
781
733
 
782
734
  <div className="space-y-3 flex-1 overflow-y-auto max-h-[300px] pr-1">
735
+ {/* Auto-generate from Roadmap after Design Export */}
736
+ {(state?.product?.roadmap?.items?.filter(item =>
737
+ !item.completed &&
738
+ !state?.product?.roadmap?.isBoilerplate
739
+ ) ?? []).length > 0 && !state?.specs?.length && (
740
+ <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 p-4 rounded-lg mb-3">
741
+ <p className="text-sm text-blue-700 dark:text-blue-300 mb-2">
742
+ Ready to generate specs from roadmap items?
743
+ </p>
744
+ <PromptButton
745
+ label="Generate All Specs"
746
+ prompt={`Antigravity, generate feature specs from the roadmap items. For each item in 'agent-os/product/roadmap.md' that is not yet completed, create a spec folder in 'agent-os/specs/[feature-name]/' with spec.md and tasks.md files. Context: 1. Read 'product-plan/product-overview.md' for data model/flows. 2. Read 'design-system/design-tokens.md' and 'design-system/app-shell.md' for UI/UX constraints. 3. Use the shape-spec command: Read 'agent-os/commands/shape-spec/shape-spec.md'.`}
747
+ onClick={copyToClipboard}
748
+ small
749
+ primary
750
+ />
751
+ </div>
752
+ )}
783
753
  {state?.specs?.map(spec => (
784
754
  <div key={spec.name} className="bg-secondary/20 p-4 rounded-lg border border-border/50 hover:border-border transition-colors group relative">
785
755
  <button
@@ -867,6 +837,132 @@ function App() {
867
837
  </div>
868
838
  </section>
869
839
 
840
+ {/* Phase 4: Implementation */}
841
+ <section className="bg-card border border-border rounded-xl p-5 shadow-sm h-full flex flex-col transition-all hover:shadow-md hover:border-border/80">
842
+ <div className="flex items-center gap-3 mb-5 pb-4 border-b border-border/50">
843
+ <div className="p-2 bg-sidebar-primary/10 text-sidebar-primary rounded-lg">
844
+ <Package size={20} />
845
+ </div>
846
+ <h2 className="text-lg font-semibold">4. Implementation</h2>
847
+ </div>
848
+
849
+ <div className="space-y-3 flex-1">
850
+ {/* Scaffold Status */}
851
+ <div className="flex items-center justify-between p-3 bg-secondary/30 rounded-lg border border-border/50">
852
+ <span className="text-foreground font-medium text-sm flex items-center gap-2"><Layout size={16} className="text-muted-foreground" /> Scaffold</span>
853
+ {state?.implementation?.scaffolded ? (
854
+ <span className="text-emerald-600 bg-emerald-50 dark:bg-emerald-900/20 px-2 py-0.5 rounded text-xs font-medium border border-emerald-200 dark:border-emerald-800">Done</span>
855
+ ) : (
856
+ <span className="text-muted-foreground bg-secondary px-2 py-0.5 rounded text-xs font-medium border border-border">Pending</span>
857
+ )}
858
+ </div>
859
+
860
+ {/* Git Status */}
861
+ {state?.implementation?.git?.initialized && (
862
+ <div className="flex items-center justify-between p-3 bg-secondary/30 rounded-lg border border-border/50">
863
+ <span className="text-foreground font-medium text-sm flex items-center gap-2">
864
+ <svg className="w-4 h-4 text-muted-foreground" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /></svg>
865
+ {state.implementation.git.branch || 'main'}
866
+ </span>
867
+ <div className="flex items-center gap-2">
868
+ {state.implementation.git.uncommitted > 0 && (
869
+ <span className="text-amber-600 bg-amber-50 dark:bg-amber-900/20 px-2 py-0.5 rounded text-xs font-medium border border-amber-200 dark:border-amber-800">
870
+ {state.implementation.git.uncommitted} uncommitted
871
+ </span>
872
+ )}
873
+ {state.implementation.git.uncommitted === 0 && (
874
+ <span className="text-emerald-600 bg-emerald-50 dark:bg-emerald-900/20 px-2 py-0.5 rounded text-xs font-medium border border-emerald-200 dark:border-emerald-800">Clean</span>
875
+ )}
876
+ </div>
877
+ </div>
878
+ )}
879
+
880
+ {/* Tests & Coverage */}
881
+ {state?.implementation?.scaffolded && (
882
+ <div className="flex items-center justify-between p-3 bg-secondary/30 rounded-lg border border-border/50">
883
+ <span className="text-foreground font-medium text-sm flex items-center gap-2">
884
+ <CheckSquare size={16} className="text-muted-foreground" /> Tests
885
+ </span>
886
+ <div className="flex items-center gap-2">
887
+ {state?.implementation?.tests?.hasTests ? (
888
+ <span className="text-emerald-600 bg-emerald-50 dark:bg-emerald-900/20 px-2 py-0.5 rounded text-xs font-medium border border-emerald-200 dark:border-emerald-800">
889
+ {state.implementation.tests.count} files
890
+ </span>
891
+ ) : (
892
+ <span className="text-muted-foreground bg-secondary px-2 py-0.5 rounded text-xs font-medium border border-border">No tests</span>
893
+ )}
894
+ {state?.implementation?.coverage !== null && state?.implementation?.coverage !== undefined && (
895
+ <span className={`px-2 py-0.5 rounded text-xs font-medium border ${state.implementation.coverage >= 80
896
+ ? 'text-emerald-600 bg-emerald-50 dark:bg-emerald-900/20 border-emerald-200 dark:border-emerald-800'
897
+ : state.implementation.coverage >= 50
898
+ ? 'text-amber-600 bg-amber-50 dark:bg-amber-900/20 border-amber-200 dark:border-amber-800'
899
+ : 'text-red-600 bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800'
900
+ }`}>
901
+ {state.implementation.coverage}% coverage
902
+ </span>
903
+ )}
904
+ </div>
905
+ </div>
906
+ )}
907
+
908
+ {/* Spec Progress */}
909
+ {state?.implementation?.specs && state.implementation.specs.total > 0 && (
910
+ <div className="flex items-center justify-between p-3 bg-secondary/30 rounded-lg border border-border/50">
911
+ <span className="text-foreground font-medium text-sm flex items-center gap-2">
912
+ <FileText size={16} className="text-muted-foreground" /> Specs
913
+ </span>
914
+ <span className={`px-2 py-0.5 rounded text-xs font-medium border ${state.implementation.specs.completed === state.implementation.specs.total
915
+ ? 'text-emerald-600 bg-emerald-50 dark:bg-emerald-900/20 border-emerald-200 dark:border-emerald-800'
916
+ : 'text-blue-600 bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800'
917
+ }`}>
918
+ {state.implementation.specs.completed}/{state.implementation.specs.total} complete
919
+ </span>
920
+ </div>
921
+ )}
922
+ </div>
923
+
924
+ <div className="mt-6">
925
+ {!state?.implementation?.scaffolded ? (
926
+ <PromptButton
927
+ label="Scaffold App"
928
+ prompt="Antigravity, scaffold the implementation. Read 'agent-os/commands/scaffold-implementation/scaffold-implementation.md'."
929
+ onClick={copyToClipboard}
930
+ />
931
+ ) : (
932
+ <div className="p-3 bg-secondary/30 rounded-lg border border-border/50 text-sm text-muted-foreground text-center italic mb-4">
933
+ App scaffolded. Ready for implementation.
934
+ </div>
935
+ )}
936
+
937
+ {state?.implementation?.scaffolded && state?.design?.exportPrompts?.oneShot && (
938
+ <div className="pt-3 border-t border-border/50">
939
+ <p className="text-xs text-muted-foreground mb-2 font-medium">Implementation Options:</p>
940
+ <div className="space-y-2">
941
+ <PromptButton
942
+ label="Option A: One-Shot (All)"
943
+ prompt={`Antigravity, implement the app. Read 'product-plan/prompts/one-shot-prompt.md'. If Context7 is configured, use it to verify library documentation.`}
944
+ onClick={copyToClipboard}
945
+ small
946
+ primary
947
+ />
948
+ {state?.design?.exportPrompts?.section && (
949
+ <div className="relative">
950
+ <PromptButton
951
+ label="Option B: Incremental (Section)"
952
+ prompt={`Antigravity, implement a section. Read 'product-plan/prompts/section-prompt.md'. Use Context7 for latest docs if available.`}
953
+ onClick={copyToClipboard}
954
+ small
955
+ />
956
+ <p className="text-[10px] text-muted-foreground mt-1.5 text-center leading-tight">
957
+ Build by spec from <strong>Feature Specs</strong> &larr;
958
+ </p>
959
+ </div>
960
+ )}
961
+ </div>
962
+ </div>
963
+ )}
964
+ </div>
965
+ </section>
870
966
 
871
967
  </main>
872
968
  </div>
@@ -0,0 +1,80 @@
1
+ # Hook: AI Slop Guard
2
+
3
+ ## Purpose
4
+ Warn when code or design patterns that indicate generic AI-generated output are detected.
5
+
6
+ ## Trigger
7
+ - PreToolUse: Before writing to CSS/TSX/HTML files
8
+ - PreCommit: Before committing changes
9
+
10
+ ## Patterns to Watch For
11
+
12
+ ### Typography Slop
13
+ - āš ļø `font-family: 'Inter'` — Generic AI default font
14
+ - āš ļø `font-family: 'Roboto'` — Overused AI choice
15
+ - āš ļø `font-family: 'Open Sans'` — Too common
16
+ - āš ļø `font-family: 'Poppins'` — AI favorite
17
+
18
+ ### Color Slop
19
+ - āš ļø `#808080` or `gray` — Dead gray
20
+ - āš ļø `#cccccc`, `#dddddd` — Lifeless neutral
21
+ - āš ļø `#f5f5f5` — The AI background color
22
+ - āš ļø Pure `#000000` or `#ffffff` — No warmth
23
+ - āš ļø `#3b82f6` or `#2563eb` — Everyone's blue
24
+
25
+ ### Layout Slop
26
+ - āš ļø Cards in cards — Nested containers
27
+ - āš ļø Hero with centered h1 + subtitle + CTA — The AI template
28
+ - āš ļø 3-column feature grid — Overused pattern
29
+ - āš ļø Centered everything — Lazy alignment
30
+
31
+ ### Effect Slop
32
+ - āš ļø `backdrop-filter: blur(10px)` — Glassmorphism default
33
+ - āš ļø `border-radius: 12px` — The AI corner radius
34
+ - āš ļø `box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1)` — Tailwind default
35
+
36
+ ### Animation Slop
37
+ - āš ļø `transition: all` — Lazy animation
38
+ - āš ļø `animate-bounce` — Generic micro-interaction
39
+ - āš ļø `animate-pulse` — Loading skeleton overuse
40
+
41
+ ### Copy Slop
42
+ - āš ļø "Streamline your workflow" — Generic SaaS copy
43
+ - āš ļø "Unlock the power of" — AI clichĆ©
44
+ - āš ļø "Seamlessly integrate" — Meaningless buzzword
45
+ - āš ļø "Best-in-class" — Tells nothing
46
+
47
+ ## Response When Detected
48
+
49
+ ```
50
+ āš ļø AI Slop Guard Warning
51
+
52
+ Detected potentially generic AI patterns:
53
+ - [Pattern name]: [File:Line]
54
+
55
+ Consider:
56
+ 1. Running `/audit` to get specific recommendations
57
+ 2. Consulting the frontend-design skill for alternatives
58
+ 3. Using `/bolder` if design is too safe
59
+
60
+ Continue anyway? [y/N]
61
+ ```
62
+
63
+ ## Configuration
64
+ Users can customize in `.gemini/settings.json`:
65
+ ```json
66
+ {
67
+ "hooks": {
68
+ "ai-slop-guard": {
69
+ "enabled": true,
70
+ "strictness": "medium", // low, medium, high
71
+ "ignore": ["Inter"] // Patterns to ignore
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ ## Notes
78
+ - This is a warning, not a blocker
79
+ - Some patterns are acceptable in context
80
+ - The goal is awareness, not restriction
@@ -0,0 +1,63 @@
1
+ # Hook: On Design Complete
2
+
3
+ ## Purpose
4
+ Automatically run quality checks when a design phase is completed.
5
+
6
+ ## Trigger
7
+ After completing:
8
+ - `/design-tokens`
9
+ - `/design-shell`
10
+ - `/design-screen`
11
+
12
+ ## Actions
13
+
14
+ ### 1. Run Auto-Audit
15
+ Execute a mini-audit focusing on the just-completed work:
16
+
17
+ **After `/design-tokens`:**
18
+ - Check for AI slop fonts
19
+ - Verify color hierarchy exists
20
+ - Ensure contrast ratios meet WCAG AA
21
+ - Validate color format consistency
22
+
23
+ **After `/design-shell`:**
24
+ - Check for AI slop layout patterns
25
+ - Verify touch targets (44x44 minimum)
26
+ - Check spacing consistency
27
+ - Validate responsive breakpoints
28
+
29
+ **After `/design-screen`:**
30
+ - Full component audit
31
+ - Accessibility check
32
+ - Performance impact assessment
33
+
34
+ ### 2. Generate Report
35
+ Save audit results to `design-system/QA/[phase]-audit.md`
36
+
37
+ ### 3. Suggest Next Steps
38
+ Based on audit results:
39
+ - If issues found: Suggest specific fix commands
40
+ - If clean: Suggest next phase
41
+
42
+ ## Output Format
43
+
44
+ ```
45
+ āœ… Design phase completed!
46
+
47
+ Auto-audit results:
48
+ ā”œā”€ā”€ Accessibility: āœ“ Pass
49
+ ā”œā”€ā”€ Typography: āš ļø 1 warning (consider font alternatives)
50
+ ā”œā”€ā”€ Colors: āœ“ Pass
51
+ └── Layout: āœ“ Pass
52
+
53
+ Suggestions:
54
+ - Run `/critique` for UX evaluation
55
+ - Continue to `/design-shell` when ready
56
+
57
+ Full report: design-system/QA/tokens-audit.md
58
+ ```
59
+
60
+ ## Notes
61
+ - This hook runs automatically, no user action needed
62
+ - Reports accumulate, so you can see progress over time
63
+ - Hook can be disabled in settings if desired
@@ -0,0 +1,37 @@
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
+
7
+ export default tseslint.config(
8
+ { ignores: ['dist', 'node_modules', 'coverage', '.next', 'build'] },
9
+ {
10
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
11
+ files: ['**/*.{ts,tsx}'],
12
+ languageOptions: {
13
+ ecmaVersion: 2020,
14
+ globals: globals.browser,
15
+ },
16
+ plugins: {
17
+ 'react-hooks': reactHooks,
18
+ 'react-refresh': reactRefresh,
19
+ },
20
+ rules: {
21
+ ...reactHooks.configs.recommended.rules,
22
+ 'react-refresh/only-export-components': [
23
+ 'warn',
24
+ { allowConstantExport: true },
25
+ ],
26
+ // Strict TypeScript rules
27
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
28
+ '@typescript-eslint/no-explicit-any': 'warn',
29
+ '@typescript-eslint/explicit-function-return-type': 'off',
30
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
31
+ // Best practices
32
+ 'no-console': ['warn', { allow: ['warn', 'error'] }],
33
+ 'prefer-const': 'error',
34
+ 'no-var': 'error',
35
+ },
36
+ },
37
+ )
@@ -0,0 +1,6 @@
1
+ export default {
2
+ '*.{ts,tsx}': ['eslint --fix', 'prettier --write'],
3
+ '*.{js,jsx,cjs,mjs}': ['eslint --fix', 'prettier --write'],
4
+ '*.{json,md,yml,yaml}': ['prettier --write'],
5
+ '*.css': ['prettier --write'],
6
+ }
@@ -19,9 +19,32 @@
19
19
  "start:control": "cd control-center/frontend && npm run dev -- --port 5401",
20
20
  "start:app": "cd app && npm run dev -- --port 5402",
21
21
  "build": "npm run build --workspaces",
22
- "test": "npm run test --workspaces"
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "test:coverage": "vitest run --coverage",
25
+ "lint": "eslint . --ext .ts,.tsx,.js,.jsx",
26
+ "lint:fix": "eslint . --ext .ts,.tsx,.js,.jsx --fix",
27
+ "format": "prettier --write .",
28
+ "format:check": "prettier --check .",
29
+ "typecheck": "tsc --noEmit",
30
+ "prepare": "husky"
23
31
  },
24
32
  "devDependencies": {
25
- "concurrently": "^8.2.2"
33
+ "@commitlint/cli": "^19.0.0",
34
+ "@commitlint/config-conventional": "^19.0.0",
35
+ "@eslint/js": "^9.0.0",
36
+ "@types/node": "^20.11.0",
37
+ "@vitest/coverage-v8": "^2.0.0",
38
+ "concurrently": "^8.2.2",
39
+ "eslint": "^9.0.0",
40
+ "eslint-plugin-react-hooks": "^5.0.0",
41
+ "eslint-plugin-react-refresh": "^0.4.0",
42
+ "globals": "^15.0.0",
43
+ "husky": "^9.0.0",
44
+ "lint-staged": "^15.0.0",
45
+ "prettier": "^3.2.0",
46
+ "prettier-plugin-tailwindcss": "^0.6.0",
47
+ "typescript-eslint": "^8.0.0",
48
+ "vitest": "^2.0.0"
26
49
  }
27
50
  }
@@ -0,0 +1,17 @@
1
+ import { describe, it, expect } from 'vitest'
2
+
3
+ describe('Example Test Suite', () => {
4
+ it('should pass a basic test', () => {
5
+ expect(1 + 1).toBe(2)
6
+ })
7
+
8
+ it('should handle strings', () => {
9
+ expect('hello world').toContain('world')
10
+ })
11
+
12
+ it('should handle arrays', () => {
13
+ const items = [1, 2, 3]
14
+ expect(items).toHaveLength(3)
15
+ expect(items).toContain(2)
16
+ })
17
+ })
@@ -0,0 +1,14 @@
1
+ import '@testing-library/jest-dom/vitest'
2
+
3
+ // Global test setup
4
+ beforeAll(() => {
5
+ // Setup code that runs before all tests
6
+ })
7
+
8
+ afterEach(() => {
9
+ // Cleanup after each test
10
+ })
11
+
12
+ afterAll(() => {
13
+ // Cleanup code that runs after all tests
14
+ })
@@ -0,0 +1,25 @@
1
+ import { defineConfig } from 'vitest/config'
2
+ import react from '@vitejs/plugin-react'
3
+ import { resolve } from 'path'
4
+
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ test: {
8
+ globals: true,
9
+ environment: 'jsdom',
10
+ setupFiles: ['./src/__tests__/setup.ts'],
11
+ include: ['**/*.{test,spec}.{ts,tsx}'],
12
+ coverage: {
13
+ reporter: ['text', 'json', 'html'],
14
+ exclude: [
15
+ 'node_modules/',
16
+ 'src/__tests__/setup.ts',
17
+ ],
18
+ },
19
+ },
20
+ resolve: {
21
+ alias: {
22
+ '@': resolve(__dirname, './src'),
23
+ },
24
+ },
25
+ })