Loading...
Loading...
Compare original and translation side by side
prd-analyzerprd-analyzerPRD says: "User can export analytics to Tableau"
Backend: ✓ analytics-api.ts exists with Tableau endpoints
Frontend: ✗ No /analytics route
Navigation: ✗ No menu item
Result: Feature "done" in tasks.db, but users can't access itPRD要求:"用户可将分析数据导出至Tableau"
后端: ✓ 存在analytics-api.ts,包含Tableau端点
前端: ✗ 无/analytics路由
导航: ✗ 无菜单项
结果: tasks.db中标记该功能“已完成”,但用户无法访问1. DISCOVER → Find project structure and framework
2. READ → Load PRD features from prd-analyzer output
3. SCAN → Search codebase for implementation evidence
4. AUDIT → Check user-facing accessibility
5. ANALYZE → Compare requirements vs reality
6. REPORT → Generate gap analysis
7. REMEDIATE → Create tasks for missing pieces1. DISCOVER → Find project structure and framework
2. READ → Load PRD features from prd-analyzer output
3. SCAN → Search codebase for implementation evidence
4. AUDIT → Check user-facing accessibility
5. ANALYZE → Compare requirements vs reality
6. REPORT → Generate gap analysis
7. REMEDIATE → Create tasks for missing piecesundefinedundefined
Look for:
- Framework indicators (next.config.js, vite.config.ts, expo.json, etc.)
- Source structure (src/, app/, pages/, etc.)
- Backend location (backend/, server/, api/, etc.)
检查以下内容:
- 框架标识文件(next.config.js、vite.config.ts、expo.json等)
- 源码结构(src/、app/、pages/等)
- 后端位置(backend/、server/、api/等)undefinedundefinedundefinedundefinedaudit-report.mdaudit-results.jsontasks.dbaudit-report.mdaudit-results.jsontasks.db| Level | Name | Meaning |
|---|---|---|
| 0 | Not Started | No implementation evidence |
| 1 | Backend Only | Service/API exists, no frontend |
| 2 | Frontend Exists | UI components exist, not accessible |
| 3 | Routable | Has route/screen, not in navigation |
| 4 | Accessible | In navigation, users can reach it |
| 5 | Complete | Accessible + documented + tested |
| 等级 | 名称 | 含义 |
|---|---|---|
| 0 | 未启动 | 无实现痕迹 |
| 1 | 仅后端实现 | 服务/API已存在,无前端 |
| 2 | 前端已存在 | UI组件已实现,但无法访问 |
| 3 | 可路由 | 有路由/页面,但未加入导航 |
| 4 | 可访问 | 已加入导航,用户可到达 |
| 5 | 完全完成 | 可访问 + 已文档化 + 已测试 |
undefinedundefined
---
---// Detection order
const frameworkIndicators = {
// Web Frameworks
'next.config.js': 'nextjs',
'next.config.mjs': 'nextjs',
'next.config.ts': 'nextjs',
'vite.config.ts': 'vite',
'vite.config.js': 'vite',
'remix.config.js': 'remix',
'astro.config.mjs': 'astro',
// React Router / TanStack
'src/routes.tsx': 'react-router',
'src/router.tsx': 'tanstack-router',
'app/routes/': 'remix',
// Mobile
'app.json': 'expo',
'expo.json': 'expo',
'react-native.config.js': 'react-native',
'ios/': 'react-native',
'android/': 'react-native',
// Backend
'backend/': 'separate-backend',
'server/': 'separate-backend',
'api/': 'api-routes',
};// Detection order
const frameworkIndicators = {
// Web Frameworks
'next.config.js': 'nextjs',
'next.config.mjs': 'nextjs',
'next.config.ts': 'nextjs',
'vite.config.ts': 'vite',
'vite.config.js': 'vite',
'remix.config.js': 'remix',
'astro.config.mjs': 'astro',
// React Router / TanStack
'src/routes.tsx': 'react-router',
'src/router.tsx': 'tanstack-router',
'app/routes/': 'remix',
// Mobile
'app.json': 'expo',
'expo.json': 'expo',
'react-native.config.js': 'react-native',
'ios/': 'react-native',
'android/': 'react-native',
// Backend
'backend/': 'separate-backend',
'server/': 'separate-backend',
'api/': 'api-routes',
};| Framework | Routes Location | Navigation | API Calls |
|---|---|---|---|
| Next.js (pages) | | | |
| Next.js (app) | | | |
| React Router | | | |
| TanStack Router | | | |
| Remix | | | |
| React Native | | | |
| Expo Router | | | |
| 框架 | 路由位置 | 导航 | API调用 |
|---|---|---|---|
| Next.js (pages) | | | |
| Next.js (app) | | | |
| React Router | | | |
| TanStack Router | | | |
| Remix | | | |
| React Native | | | |
| Expo Router | | | |
undefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefined
---
---undefinedundefined| Metric | Count |
|---|---|
| Total Features | 30 |
| Fully Complete (L5) | 12 |
| Accessible (L4) | 5 |
| Routable (L3) | 3 |
| Frontend Exists (L2) | 2 |
| Backend Only (L1) | 8 |
| Not Started (L0) | 0 |
| Metric | Count |
|---|---|
| Total Features | 30 |
| Fully Complete (L5) | 12 |
| Accessible (L4) | 5 |
| Routable (L3) | 3 |
| Frontend Exists (L2) | 2 |
| Backend Only (L1) | 8 |
| Not Started (L0) | 0 |
| Feature | Level | Missing |
|---|---|---|
| F028 Analytics API | L1 | Frontend route, Navigation, UI |
| F029 Tenant Isolation | L1 | Settings UI, BYOK config screen |
| Feature | Level | Missing |
|---|---|---|
| F028 Analytics API | L1 | Frontend route, Navigation, UI |
| F029 Tenant Isolation | L1 | Settings UI, BYOK config screen |
backend/src/services/survey-studio.tsapp/surveys/new/page.tsxbackend/src/services/survey-studio.tsapp/surveys/new/page.tsxbackend/src/services/analytics-api.ts/analyticsapp/analytics/page.tsxundefinedbackend/src/services/analytics-api.ts/analyticsapp/analytics/page.tsxundefined{
"audit_date": "2026-01-12",
"project": "VoiceForm AI",
"framework": {
"frontend": "nextjs-app",
"backend": "separate",
"mobile": null
},
"summary": {
"total_features": 30,
"by_level": {
"L5_complete": 12,
"L4_accessible": 5,
"L3_routable": 3,
"L2_frontend_exists": 2,
"L1_backend_only": 8,
"L0_not_started": 0
}
},
"features": [
{
"id": "F028",
"title": "Analytics API",
"level": 1,
"level_name": "backend_only",
"evidence": {
"backend": {
"found": true,
"files": ["backend/src/services/analytics-api.ts"]
},
"frontend": {
"found": false,
"files": []
},
"route": {
"found": false,
"path": null
},
"navigation": {
"found": false,
"location": null
}
},
"remediation": [
{
"type": "create_route",
"description": "Create analytics page",
"path": "app/analytics/page.tsx"
},
{
"type": "add_navigation",
"description": "Add Analytics to sidebar"
}
]
}
]
}{
"audit_date": "2026-01-12",
"project": "VoiceForm AI",
"framework": {
"frontend": "nextjs-app",
"backend": "separate",
"mobile": null
},
"summary": {
"total_features": 30,
"by_level": {
"L5_complete": 12,
"L4_accessible": 5,
"L3_routable": 3,
"L2_frontend_exists": 2,
"L1_backend_only": 8,
"L0_not_started": 0
}
},
"features": [
{
"id": "F028",
"title": "Analytics API",
"level": 1,
"level_name": "backend_only",
"evidence": {
"backend": {
"found": true,
"files": ["backend/src/services/analytics-api.ts"]
},
"frontend": {
"found": false,
"files": []
},
"route": {
"found": false,
"path": null
},
"navigation": {
"found": false,
"location": null
}
},
"remediation": [
{
"type": "create_route",
"description": "Create analytics page",
"path": "app/analytics/page.tsx"
},
{
"type": "add_navigation",
"description": "Add Analytics to sidebar"
}
]
}
]
}-- New story for missing frontend
INSERT INTO stories (id, epic_id, title, description, status)
VALUES (
'story-028-frontend',
'epic-028',
'Analytics Frontend Implementation',
'Create user-facing analytics dashboard',
'todo'
);
-- Tasks for the story
INSERT INTO tasks (id, story_id, title, task_type, estimate_hours, status)
VALUES
('task-028-f01', 'story-028-frontend', 'Create /analytics route', 'frontend', 4, 'todo'),
('task-028-f02', 'story-028-frontend', 'Build analytics dashboard components', 'frontend', 8, 'todo'),
('task-028-f03', 'story-028-frontend', 'Add Analytics to navigation', 'frontend', 1, 'todo'),
('task-028-f04', 'story-028-frontend', 'Connect to analytics API', 'frontend', 4, 'todo');-- New story for missing frontend
INSERT INTO stories (id, epic_id, title, description, status)
VALUES (
'story-028-frontend',
'epic-028',
'Analytics Frontend Implementation',
'Create user-facing analytics dashboard',
'todo'
);
-- Tasks for the story
INSERT INTO tasks (id, story_id, title, task_type, estimate_hours, status)
VALUES
('task-028-f01', 'story-028-frontend', 'Create /analytics route', 'frontend', 4, 'todo'),
('task-028-f02', 'story-028-frontend', 'Build analytics dashboard components', 'frontend', 8, 'todo'),
('task-028-f03', 'story-028-frontend', 'Add Analytics to navigation', 'frontend', 1, 'todo'),
('task-028-f04', 'story-028-frontend', 'Connect to analytics API', 'frontend', 4, 'todo');| Gap Type | Priority | Rationale |
|---|---|---|
| P0 feature backend-only | P0 | Critical feature unusable |
| P1 feature backend-only | P1 | Important feature unusable |
| Missing navigation | P1 | Feature exists but hidden |
| Missing documentation | P2 | Feature works but undiscoverable |
| Missing error states | P2 | Polish issue |
| 差距类型 | 优先级 | 理由 |
|---|---|---|
| P0功能仅后端实现 | P0 | 关键功能无法使用 |
| P1功能仅后端实现 | P1 | 重要功能无法使用 |
| 缺少导航 | P1 | 功能存在但隐藏 |
| 缺少文档 | P2 | 功能可用但用户无法发现 |
| 缺少错误状态处理 | P2 | 体验优化问题 |
import sqlite3
import json
def load_prd_context(project_path: str):
"""Load features from prd-analyzer output"""
# Load features.json
with open(f"{project_path}/.claude/features.json") as f:
features = json.load(f)
# Load from tasks.db
conn = sqlite3.connect(f"{project_path}/.claude/tasks.db")
conn.row_factory = sqlite3.Row
epics = conn.execute("""
SELECT e.*,
COUNT(s.id) as story_count,
SUM(CASE WHEN s.status = 'done' THEN 1 ELSE 0 END) as done_count
FROM epics e
LEFT JOIN stories s ON s.epic_id = e.id
GROUP BY e.id
""").fetchall()
return {
"features": features,
"epics": [dict(e) for e in epics]
}import sqlite3
import json
def load_prd_context(project_path: str):
"""Load features from prd-analyzer output"""
# Load features.json
with open(f"{project_path}/.claude/features.json") as f:
features = json.load(f)
# Load from tasks.db
conn = sqlite3.connect(f"{project_path}/.claude/tasks.db")
conn.row_factory = sqlite3.Row
epics = conn.execute("""
SELECT e.*,
COUNT(s.id) as story_count,
SUM(CASE WHEN s.status = 'done' THEN 1 ELSE 0 END) as done_count
FROM epics e
LEFT JOIN stories s ON s.epic_id = e.id
GROUP BY e.id
""").fetchall()
return {
"features": features,
"epics": [dict(e) for e in epics]
}-- Mark feature as needing frontend work
UPDATE epics
SET status = 'needs_frontend',
updated_at = datetime('now')
WHERE id = 'epic-028';
-- Add audit metadata
INSERT INTO epic_metadata (epic_id, key, value)
VALUES ('epic-028', 'audit_level', '1'),
('epic-028', 'audit_date', '2026-01-12'),
('epic-028', 'audit_gaps', 'route,navigation,documentation');-- Mark feature as needing frontend work
UPDATE epics
SET status = 'needs_frontend',
updated_at = datetime('now')
WHERE id = 'epic-028';
-- Add audit metadata
INSERT INTO epic_metadata (epic_id, key, value)
VALUES ('epic-028', 'audit_level', '1'),
('epic-028', 'audit_date', '2026-01-12'),
('epic-028', 'audit_gaps', 'route,navigation,documentation');undefinedundefinedundefinedundefinedundefinedundefined
---
---| Anti-Pattern | Problem | Fix |
|---|---|---|
| Trusting tasks.db status | "Done" ≠ user-facing | Always verify in codebase |
| Only checking file existence | File may be empty/stub | Check for real implementation |
| Ignoring navigation | Feature unreachable | Verify menu/nav links |
| Skipping mobile | Desktop-only isn't complete | Check responsive/native |
| No documentation check | Users can't discover | Verify help/docs exist |
| 反模式 | 问题 | 修复方案 |
|---|---|---|
| 信任tasks.db状态 | “已完成” ≠ 面向用户 | 始终在代码库中验证 |
| 仅检查文件存在性 | 文件可能为空/是占位符 | 检查真实实现内容 |
| 忽略导航 | 功能无法被用户找到 | 验证菜单/导航链接 |
| 跳过移动端适配 | 仅桌面端实现不算完整 | 检查响应式/原生实现 |
| 跳过文档检查 | 用户无法发现功能 | 验证帮助文档存在性 |
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Generic tasks | "Add frontend" too vague | Specific: "Create /analytics route" |
| Missing dependencies | Frontend before backend | Check implementation order |
| Overloading | 50 tasks at once | Prioritize by P-level |
| No estimates | Can't plan | Add hour estimates |
| 反模式 | 问题 | 修复方案 |
|---|---|---|
| 通用任务 | “添加前端”过于模糊 | 具体化:“创建/analytics路由” |
| 忽略依赖关系 | 先做前端再做后端 | 检查实现顺序 |
| 任务过载 | 一次性分配50个任务 | 按优先级P等级排序 |
| 无工时估算 | 无法规划 | 添加工时估算 |