@theproductguy/create-mission-control 1.0.3 → 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 +63 -7
- package/package.json +2 -2
- package/src/template/.env.example +28 -0
- package/src/template/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- package/src/template/.github/ISSUE_TEMPLATE/feature_request.md +30 -0
- package/src/template/.github/PULL_REQUEST_TEMPLATE.md +33 -0
- package/src/template/.github/workflows/ci.yml +83 -0
- package/src/template/.husky/commit-msg +1 -0
- package/src/template/.husky/pre-commit +1 -0
- package/src/template/.prettierrc +11 -0
- package/src/template/README.md +78 -0
- package/src/template/agent-os/commands/create-constitution/create-constitution.md +89 -0
- package/src/template/agent-os/commands/export-product/export-product.md +24 -0
- package/src/template/agent-os/commands/initialize-design/initialize-design.md +10 -1
- package/src/template/agent-os/commands/research-tech/research-tech.md +93 -0
- package/src/template/agent-os/commands/shape-spec/shape-spec.md +2 -1
- package/src/template/agent-os/docs/context7.md +20 -0
- package/src/template/commitlint.config.js +25 -0
- package/src/template/control-center/backend/index.js +67 -4
- package/src/template/control-center/frontend/src/App.tsx +193 -64
- package/src/template/design-system/{.claude → .gemini}/commands/design-os/design-shell.md +95 -69
- package/src/template/design-system/.gemini/commands/design-os/design-tokens.md +211 -0
- package/src/template/design-system/.gemini/commands/impeccable/WORKFLOW.md +163 -0
- package/src/template/design-system/.gemini/commands/impeccable/adapt.md +189 -0
- package/src/template/design-system/.gemini/commands/impeccable/animate.md +184 -0
- package/src/template/design-system/.gemini/commands/impeccable/audit.md +123 -0
- package/src/template/design-system/.gemini/commands/impeccable/bolder.md +126 -0
- package/src/template/design-system/.gemini/commands/impeccable/clarify.md +173 -0
- package/src/template/design-system/.gemini/commands/impeccable/colorize.md +152 -0
- package/src/template/design-system/.gemini/commands/impeccable/critique.md +112 -0
- package/src/template/design-system/.gemini/commands/impeccable/delight.md +311 -0
- package/src/template/design-system/.gemini/commands/impeccable/extract.md +88 -0
- package/src/template/design-system/.gemini/commands/impeccable/harden.md +351 -0
- package/src/template/design-system/.gemini/commands/impeccable/normalize.md +61 -0
- package/src/template/design-system/.gemini/commands/impeccable/onboard.md +236 -0
- package/src/template/design-system/.gemini/commands/impeccable/optimize.md +262 -0
- package/src/template/design-system/.gemini/commands/impeccable/polish.md +196 -0
- package/src/template/design-system/.gemini/commands/impeccable/quieter.md +112 -0
- package/src/template/design-system/.gemini/commands/impeccable/simplify.md +131 -0
- package/src/template/design-system/.gemini/commands/impeccable/teach-impeccable.md +67 -0
- package/src/template/design-system/.gemini/hooks/ai-slop-guard.md +80 -0
- package/src/template/design-system/.gemini/hooks/on-design-complete.md +63 -0
- package/src/template/design-system/.gemini/skills/frontend-design/SKILL.md +126 -0
- package/src/template/design-system/.gemini/skills/frontend-design/reference/color-and-contrast.md +132 -0
- package/src/template/design-system/.gemini/skills/frontend-design/reference/interaction-design.md +123 -0
- package/src/template/design-system/.gemini/skills/frontend-design/reference/motion-design.md +99 -0
- package/src/template/design-system/.gemini/skills/frontend-design/reference/responsive-design.md +114 -0
- package/src/template/design-system/.gemini/skills/frontend-design/reference/spatial-design.md +100 -0
- package/src/template/design-system/.gemini/skills/frontend-design/reference/typography.md +131 -0
- package/src/template/design-system/.gemini/skills/frontend-design/reference/ux-writing.md +107 -0
- package/src/template/design-system/src/components/DesignPage.tsx +104 -0
- package/src/template/eslint.config.js +37 -0
- package/src/template/lint-staged.config.js +6 -0
- package/src/template/package-lock.json +10308 -0
- package/src/template/package.json +25 -2
- package/src/template/src/__tests__/example.test.ts +17 -0
- package/src/template/src/__tests__/setup.ts +14 -0
- package/src/template/vitest.config.ts +25 -0
- package/src/template/design-system/.claude/commands/design-os/design-tokens.md +0 -166
- package/src/template/design-system/.claude/skills/frontend-design/SKILL.md +0 -42
- /package/src/template/design-system/{.claude → .gemini}/commands/design-os/data-model.md +0 -0
- /package/src/template/design-system/{.claude → .gemini}/commands/design-os/design-screen.md +0 -0
- /package/src/template/design-system/{.claude → .gemini}/commands/design-os/export-product.md +0 -0
- /package/src/template/design-system/{.claude → .gemini}/commands/design-os/product-roadmap.md +0 -0
- /package/src/template/design-system/{.claude → .gemini}/commands/design-os/product-vision.md +0 -0
- /package/src/template/design-system/{.claude → .gemini}/commands/design-os/sample-data.md +0 -0
- /package/src/template/design-system/{.claude → .gemini}/commands/design-os/screenshot-design.md +0 -0
- /package/src/template/design-system/{.claude → .gemini}/commands/design-os/shape-section.md +0 -0
- /package/src/template/design-system/{claude.md → gemini.md} +0 -0
|
@@ -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
|
+
}
|
|
@@ -125,15 +125,64 @@ app.get('/api/status', async (req, res) => {
|
|
|
125
125
|
|
|
126
126
|
// Check for Design OS export and steps
|
|
127
127
|
const designDir = path.join(PROJECT_ROOT, 'design-system');
|
|
128
|
-
|
|
129
|
-
//
|
|
130
|
-
|
|
128
|
+
|
|
129
|
+
// QA Check
|
|
130
|
+
const qaDir = path.join(designDir, 'QA');
|
|
131
|
+
const auditReport = path.join(qaDir, 'audit-report.md');
|
|
132
|
+
const polishReport = path.join(qaDir, 'polish-report.md');
|
|
131
133
|
|
|
132
134
|
const hasDesignExport = fs.existsSync(path.join(PROJECT_ROOT, 'product-plan'));
|
|
133
135
|
const hasDesignInit = fs.existsSync(path.join(designDir, 'product/product-overview.md'));
|
|
134
136
|
const hasTokens = fs.existsSync(path.join(designDir, 'product/design-system/colors.json'));
|
|
135
137
|
const hasShell = fs.existsSync(path.join(designDir, 'product/shell/spec.md'));
|
|
136
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
|
+
|
|
137
186
|
res.json({
|
|
138
187
|
product: productFiles,
|
|
139
188
|
services,
|
|
@@ -146,10 +195,24 @@ app.get('/api/status', async (req, res) => {
|
|
|
146
195
|
exportPrompts: {
|
|
147
196
|
oneShot: fs.existsSync(path.join(PROJECT_ROOT, 'product-plan/prompts/one-shot-prompt.md')),
|
|
148
197
|
section: fs.existsSync(path.join(PROJECT_ROOT, 'product-plan/prompts/section-prompt.md'))
|
|
198
|
+
},
|
|
199
|
+
qa: {
|
|
200
|
+
audit: fs.existsSync(auditReport),
|
|
201
|
+
polish: fs.existsSync(polishReport)
|
|
149
202
|
}
|
|
150
203
|
},
|
|
151
204
|
implementation: {
|
|
152
|
-
scaffolded:
|
|
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
|
|
153
216
|
},
|
|
154
217
|
specs,
|
|
155
218
|
projectRoot: PROJECT_ROOT
|
|
@@ -39,9 +39,28 @@ interface ProjectState {
|
|
|
39
39
|
oneShot: boolean;
|
|
40
40
|
section: boolean;
|
|
41
41
|
};
|
|
42
|
+
qa?: {
|
|
43
|
+
audit: boolean;
|
|
44
|
+
polish: boolean;
|
|
45
|
+
};
|
|
42
46
|
};
|
|
43
47
|
implementation: {
|
|
44
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
|
+
};
|
|
45
64
|
};
|
|
46
65
|
specs: Spec[];
|
|
47
66
|
services?: {
|
|
@@ -646,6 +665,17 @@ function App() {
|
|
|
646
665
|
</div>
|
|
647
666
|
</div>
|
|
648
667
|
|
|
668
|
+
<div className="grid grid-cols-2 gap-2">
|
|
669
|
+
<div className={`p-2 rounded-lg border text-center ${state?.design?.qa?.audit ? 'bg-emerald-50/50 border-emerald-200 text-emerald-700 dark:bg-emerald-900/20 dark:border-emerald-800 dark:text-emerald-300' : 'bg-secondary/20 border-border/50 text-muted-foreground'}`}>
|
|
670
|
+
<span className="text-xs font-medium block mb-1">Audit</span>
|
|
671
|
+
{state?.design?.qa?.audit ? <CheckSquare size={14} className="mx-auto" /> : <span className="block w-2 h-2 rounded-full bg-stone-300 mx-auto mt-1" />}
|
|
672
|
+
</div>
|
|
673
|
+
<div className={`p-2 rounded-lg border text-center ${state?.design?.qa?.polish ? 'bg-emerald-50/50 border-emerald-200 text-emerald-700 dark:bg-emerald-900/20 dark:border-emerald-800 dark:text-emerald-300' : 'bg-secondary/20 border-border/50 text-muted-foreground'}`}>
|
|
674
|
+
<span className="text-xs font-medium block mb-1">Polish</span>
|
|
675
|
+
{state?.design?.qa?.polish ? <CheckSquare size={14} className="mx-auto" /> : <span className="block w-2 h-2 rounded-full bg-stone-300 mx-auto mt-1" />}
|
|
676
|
+
</div>
|
|
677
|
+
</div>
|
|
678
|
+
|
|
649
679
|
<div className="flex items-center justify-between p-3 bg-secondary/30 rounded-lg border border-border/50">
|
|
650
680
|
<span className="text-foreground font-medium text-sm flex items-center gap-2"><ArrowRight size={16} className="text-muted-foreground" /> Export</span>
|
|
651
681
|
{state?.design?.exported ? (
|
|
@@ -658,7 +688,7 @@ function App() {
|
|
|
658
688
|
</div>
|
|
659
689
|
</div>
|
|
660
690
|
|
|
661
|
-
<div className="mt-6 flex gap-2">
|
|
691
|
+
<div className="mt-6 flex flex-col gap-2">
|
|
662
692
|
{!state?.design?.initialized && (
|
|
663
693
|
<PromptButton
|
|
664
694
|
label="Sync Data"
|
|
@@ -667,80 +697,33 @@ function App() {
|
|
|
667
697
|
primary
|
|
668
698
|
/>
|
|
669
699
|
)}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
<span className="text-foreground font-medium text-sm flex items-center gap-2"><Layout size={16} className="text-muted-foreground" /> Scaffold</span>
|
|
685
|
-
{state?.implementation?.scaffolded ? (
|
|
686
|
-
<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>
|
|
687
|
-
) : (
|
|
688
|
-
<span className="text-muted-foreground bg-secondary px-2 py-0.5 rounded text-xs font-medium border border-border">Pending</span>
|
|
689
|
-
)}
|
|
690
|
-
</div>
|
|
691
|
-
</div>
|
|
692
|
-
|
|
693
|
-
<div className="mt-6">
|
|
694
|
-
{!state?.implementation?.scaffolded ? (
|
|
695
|
-
<PromptButton
|
|
696
|
-
label="Scaffold App"
|
|
697
|
-
prompt="Antigravity, scaffold the implementation. Read 'agent-os/commands/scaffold-implementation/scaffold-implementation.md'."
|
|
698
|
-
onClick={copyToClipboard}
|
|
699
|
-
/>
|
|
700
|
-
) : (
|
|
701
|
-
<div className="p-3 bg-secondary/30 rounded-lg border border-border/50 text-sm text-muted-foreground text-center italic mb-4">
|
|
702
|
-
App scaffolded. Ready for implementation.
|
|
703
|
-
</div>
|
|
704
|
-
)}
|
|
705
|
-
|
|
706
|
-
{state?.implementation?.scaffolded && state?.design?.exportPrompts?.oneShot && (
|
|
707
|
-
<div className="pt-3 border-t border-border/50">
|
|
708
|
-
<p className="text-xs text-muted-foreground mb-2 font-medium">Implementation Options:</p>
|
|
709
|
-
<div className="space-y-2">
|
|
710
|
-
<PromptButton
|
|
711
|
-
label="Option A: One-Shot (All)"
|
|
712
|
-
prompt={`Antigravity, implement the app. Read 'product-plan/prompts/one-shot-prompt.md'.`}
|
|
713
|
-
onClick={copyToClipboard}
|
|
714
|
-
small
|
|
715
|
-
primary
|
|
716
|
-
/>
|
|
717
|
-
{state?.design?.exportPrompts?.section && (
|
|
718
|
-
<div className="relative">
|
|
719
|
-
<PromptButton
|
|
720
|
-
label="Option B: Incremental (Section)"
|
|
721
|
-
prompt={`Antigravity, implement a section. Read 'product-plan/prompts/section-prompt.md'.`}
|
|
722
|
-
onClick={copyToClipboard}
|
|
723
|
-
small
|
|
724
|
-
/>
|
|
725
|
-
<p className="text-[10px] text-muted-foreground mt-1.5 text-center leading-tight">
|
|
726
|
-
Build feature-by-feature using the <strong>Feature Specs</strong> list →
|
|
727
|
-
</p>
|
|
728
|
-
</div>
|
|
729
|
-
)}
|
|
730
|
-
</div>
|
|
700
|
+
{state?.design?.initialized && !state?.design?.exported && (
|
|
701
|
+
<div className="flex gap-2">
|
|
702
|
+
<PromptButton
|
|
703
|
+
label="Run Audit"
|
|
704
|
+
prompt="Antigravity, run an audit on the design system. Read 'design-system/.gemini/commands/impeccable/audit.md'."
|
|
705
|
+
onClick={copyToClipboard}
|
|
706
|
+
small
|
|
707
|
+
/>
|
|
708
|
+
<PromptButton
|
|
709
|
+
label="Run Polish"
|
|
710
|
+
prompt="Antigravity, run a polish pass. Read 'design-system/.gemini/commands/impeccable/polish.md'."
|
|
711
|
+
onClick={copyToClipboard}
|
|
712
|
+
small
|
|
713
|
+
/>
|
|
731
714
|
</div>
|
|
732
715
|
)}
|
|
733
716
|
</div>
|
|
734
717
|
</section>
|
|
735
718
|
|
|
736
|
-
{/* Phase
|
|
719
|
+
{/* Phase 3: Feature Specs */}
|
|
737
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">
|
|
738
721
|
<div className="flex items-center justify-between mb-5 pb-4 border-b border-border/50">
|
|
739
722
|
<div className="flex items-center gap-3">
|
|
740
723
|
<div className="p-2 bg-sidebar-primary/10 text-sidebar-primary rounded-lg">
|
|
741
724
|
<Code size={20} />
|
|
742
725
|
</div>
|
|
743
|
-
<h2 className="text-lg font-semibold">
|
|
726
|
+
<h2 className="text-lg font-semibold">3. Feature Specs</h2>
|
|
744
727
|
</div>
|
|
745
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"
|
|
746
729
|
onClick={() => setCreatingSpec(true)}>
|
|
@@ -749,6 +732,24 @@ function App() {
|
|
|
749
732
|
</div>
|
|
750
733
|
|
|
751
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
|
+
)}
|
|
752
753
|
{state?.specs?.map(spec => (
|
|
753
754
|
<div key={spec.name} className="bg-secondary/20 p-4 rounded-lg border border-border/50 hover:border-border transition-colors group relative">
|
|
754
755
|
<button
|
|
@@ -835,6 +836,134 @@ function App() {
|
|
|
835
836
|
|
|
836
837
|
</div>
|
|
837
838
|
</section>
|
|
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> ←
|
|
958
|
+
</p>
|
|
959
|
+
</div>
|
|
960
|
+
)}
|
|
961
|
+
</div>
|
|
962
|
+
</div>
|
|
963
|
+
)}
|
|
964
|
+
</div>
|
|
965
|
+
</section>
|
|
966
|
+
|
|
838
967
|
</main>
|
|
839
968
|
</div>
|
|
840
969
|
</div>
|