@design-ai/cli 4.55.0 → 4.56.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.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +39 -0
- package/README.ko.md +7 -7
- package/README.md +9 -9
- package/cli/lib/mcp-server.mjs +208 -10
- package/cli/lib/site-analysis.mjs +297 -0
- package/cli/lib/site-args.mjs +433 -0
- package/cli/lib/site-bundle-build.mjs +127 -0
- package/cli/lib/site-bundle-check.mjs +454 -0
- package/cli/lib/site-bundle-commands.mjs +95 -0
- package/cli/lib/site-bundle-compare.mjs +157 -0
- package/cli/lib/site-bundle-contract.mjs +79 -0
- package/cli/lib/site-bundle-files.mjs +87 -0
- package/cli/lib/site-bundle-handoff-runbook-actions.mjs +113 -0
- package/cli/lib/site-bundle-handoff-runbook-evidence-fields.mjs +164 -0
- package/cli/lib/site-bundle-handoff-runbook-evidence.mjs +334 -0
- package/cli/lib/site-bundle-handoff-runbook-format.mjs +31 -0
- package/cli/lib/site-bundle-handoff-runbook-stage-metadata.mjs +84 -0
- package/cli/lib/site-bundle-handoff-runbook.mjs +1331 -0
- package/cli/lib/site-bundle-handoff-summary.mjs +183 -0
- package/cli/lib/site-bundle-handoff.mjs +271 -0
- package/cli/lib/site-bundle-readme.mjs +98 -0
- package/cli/lib/site-bundle-repair-report.mjs +143 -0
- package/cli/lib/site-bundle-repair.mjs +68 -0
- package/cli/lib/site-content.mjs +399 -0
- package/cli/lib/site-evidence.mjs +35 -0
- package/cli/lib/site-mcp-commands.mjs +28 -0
- package/cli/lib/site-mcp-probes.mjs +159 -0
- package/cli/lib/site-mcp-readiness.mjs +157 -0
- package/cli/lib/site-mcp-report.mjs +324 -0
- package/cli/lib/site-next-actions.mjs +333 -0
- package/cli/lib/site-options.mjs +104 -0
- package/cli/lib/site-prompts.mjs +332 -0
- package/cli/lib/site-starter.mjs +153 -0
- package/cli/lib/site-strings.mjs +23 -0
- package/cli/lib/site-tasks.mjs +93 -0
- package/cli/lib/site-workflow-graph.mjs +309 -0
- package/cli/lib/site-workspace.mjs +492 -0
- package/cli/lib/site.mjs +108 -6617
- package/docs/DISTRIBUTION.ko.md +35 -6
- package/docs/DISTRIBUTION.md +35 -8
- package/docs/RELEASE-CHECKLIST.md +20 -3
- package/docs/ROADMAP.md +2179 -0
- package/docs/external-status.md +22 -7
- package/docs/integrations/design-ai-mcp-server.md +32 -0
- package/docs/integrations/vscode-walkthrough.ko.md +3 -3
- package/docs/integrations/vscode-walkthrough.md +3 -3
- package/docs/site-overrides/main.html +1 -1
- package/package.json +1 -1
- package/tools/audit/package-smoke.py +106 -0
- package/tools/audit/registry-smoke.py +378 -10
- package/tools/audit/smoke_assertions.py +83 -22
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
// Next-action reports for Website Improvement workspaces.
|
|
2
|
+
|
|
3
|
+
import { buildSiteMcpProbeReport } from "./site-mcp-probes.mjs";
|
|
4
|
+
import { buildSiteMcpCheckReport, combineStatuses } from "./site-mcp-report.mjs";
|
|
5
|
+
import { buildSiteNextActionCommandSet, siteMcpCommandTarget } from "./site-mcp-commands.mjs";
|
|
6
|
+
import { PRIORITY_OPTIONS } from "./site-options.mjs";
|
|
7
|
+
import { countImplementationEvidence } from "./site-evidence.mjs";
|
|
8
|
+
|
|
9
|
+
function nextActionEntry({ severity, title, reason, command = "", references = [] }) {
|
|
10
|
+
return {
|
|
11
|
+
severity,
|
|
12
|
+
title,
|
|
13
|
+
reason,
|
|
14
|
+
command,
|
|
15
|
+
references,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function quoteCliValue(value) {
|
|
20
|
+
const text = String(value || "");
|
|
21
|
+
if (/^[A-Za-z0-9_./:@+-]+$/.test(text)) {
|
|
22
|
+
return text;
|
|
23
|
+
}
|
|
24
|
+
return `'${text.replaceAll("'", "'\"'\"'")}'`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function buildSiteInitCommand(profile, outPath = "website-workspace.json") {
|
|
28
|
+
const args = [
|
|
29
|
+
"design-ai site --init",
|
|
30
|
+
"--name",
|
|
31
|
+
quoteCliValue(profile.name),
|
|
32
|
+
"--live-url",
|
|
33
|
+
quoteCliValue(profile.liveUrl),
|
|
34
|
+
];
|
|
35
|
+
if (profile.repoUrl) args.push("--repo-url", quoteCliValue(profile.repoUrl));
|
|
36
|
+
if (profile.localPath) args.push("--local-path", quoteCliValue(profile.localPath));
|
|
37
|
+
if (profile.figmaUrl) args.push("--figma-url", quoteCliValue(profile.figmaUrl));
|
|
38
|
+
if (profile.brandNotes) args.push("--brand-notes", quoteCliValue(profile.brandNotes));
|
|
39
|
+
if (profile.deployProvider && profile.deployProvider !== "none") args.push("--deploy", quoteCliValue(profile.deployProvider));
|
|
40
|
+
if (profile.sentryProject) args.push("--sentry", quoteCliValue(profile.sentryProject));
|
|
41
|
+
if (profile.cms && profile.cms !== "none") args.push("--cms", quoteCliValue(profile.cms));
|
|
42
|
+
if (profile.database && profile.database !== "none") args.push("--database", quoteCliValue(profile.database));
|
|
43
|
+
for (const page of profile.pages) args.push("--page", quoteCliValue(page));
|
|
44
|
+
for (const flow of profile.userFlows) args.push("--flow", quoteCliValue(flow));
|
|
45
|
+
for (const viewport of profile.viewports) args.push("--viewport", quoteCliValue(viewport));
|
|
46
|
+
args.push("--out", quoteCliValue(outPath));
|
|
47
|
+
return args.join(" ");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function buildSiteNextActionsReport(workspace, summary = {}) {
|
|
51
|
+
const filePath = summary.filePath || "workspace.json";
|
|
52
|
+
const commandTarget = siteMcpCommandTarget(filePath);
|
|
53
|
+
const commands = buildSiteNextActionCommandSet(commandTarget);
|
|
54
|
+
const mcpReport = buildSiteMcpCheckReport(workspace, summary);
|
|
55
|
+
const mcpProbeReport = buildSiteMcpProbeReport(workspace);
|
|
56
|
+
const topTasks = workspace.refactorTasks
|
|
57
|
+
.slice()
|
|
58
|
+
.sort((a, b) => PRIORITY_OPTIONS.indexOf(a.priority) - PRIORITY_OPTIONS.indexOf(b.priority))
|
|
59
|
+
.slice(0, 3);
|
|
60
|
+
const actions = [];
|
|
61
|
+
|
|
62
|
+
for (const issue of (summary.issues || []).filter((item) => item.level !== "pass")) {
|
|
63
|
+
actions.push(nextActionEntry({
|
|
64
|
+
severity: issue.level === "fail" ? "blocking" : "warning",
|
|
65
|
+
title: `Fix workspace validation: ${issue.id}`,
|
|
66
|
+
reason: issue.message,
|
|
67
|
+
command: commands.summary,
|
|
68
|
+
references: [issue.id],
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
for (const item of mcpReport.items.filter((mcp) => mcp.requestedStatus === "required" && mcp.level !== "pass")) {
|
|
73
|
+
actions.push(nextActionEntry({
|
|
74
|
+
severity: "blocking",
|
|
75
|
+
title: `Add required MCP readiness: ${item.label}`,
|
|
76
|
+
reason: item.actions.join(" ") || "Required MCP readiness is missing.",
|
|
77
|
+
command: commands.mcpCheck,
|
|
78
|
+
references: [item.key],
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for (const item of mcpReport.items.filter((mcp) => mcp.requestedStatus === "optional" && mcp.level !== "pass")) {
|
|
83
|
+
actions.push(nextActionEntry({
|
|
84
|
+
severity: "warning",
|
|
85
|
+
title: `Clarify optional MCP readiness: ${item.label}`,
|
|
86
|
+
reason: item.actions.join(" ") || "Optional MCP readiness is missing; add evidence or mark it unused.",
|
|
87
|
+
command: commands.mcpPlan,
|
|
88
|
+
references: [item.key],
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const gap of mcpReport.taskGaps) {
|
|
93
|
+
actions.push(nextActionEntry({
|
|
94
|
+
severity: "warning",
|
|
95
|
+
title: `Align MCP status for ${gap.taskId}`,
|
|
96
|
+
reason: gap.message,
|
|
97
|
+
command: commands.mcpPlan,
|
|
98
|
+
references: [gap.taskId, gap.mcp],
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
for (const item of mcpProbeReport.items.filter((probe) => probe.level !== "pass")) {
|
|
103
|
+
actions.push(nextActionEntry({
|
|
104
|
+
severity: item.level === "fail" ? "blocking" : "warning",
|
|
105
|
+
title: `Resolve MCP probe readiness: ${item.label}`,
|
|
106
|
+
reason: item.actions.join(" ") || item.message,
|
|
107
|
+
command: item.level === "fail" ? commands.mcpCheckProbes : commands.mcpPlanProbes,
|
|
108
|
+
references: [item.id, item.key],
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (workspace.refactorTasks.length === 0) {
|
|
113
|
+
actions.push(nextActionEntry({
|
|
114
|
+
severity: "setup",
|
|
115
|
+
title: "Generate starter refactor tasks",
|
|
116
|
+
reason: "No refactor tasks exist yet; generate task scaffolding from audit findings before implementation handoff.",
|
|
117
|
+
command: commands.tasks,
|
|
118
|
+
references: ["refactorTasks"],
|
|
119
|
+
}));
|
|
120
|
+
} else {
|
|
121
|
+
const selected = topTasks[0];
|
|
122
|
+
actions.push(nextActionEntry({
|
|
123
|
+
severity: "implementation",
|
|
124
|
+
title: `Prepare Codex implementation prompt for ${selected.id}`,
|
|
125
|
+
reason: `${selected.title} is the highest-priority available refactor task.`,
|
|
126
|
+
command: commands.implementationPrompt,
|
|
127
|
+
references: [selected.id],
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const evidenceCounts = countImplementationEvidence(summary.counts || workspace.implementationEvidence);
|
|
132
|
+
if (evidenceCounts.executedWork === 0 || evidenceCounts.verificationResults === 0) {
|
|
133
|
+
actions.push(nextActionEntry({
|
|
134
|
+
severity: "handoff",
|
|
135
|
+
title: "Create implementation evidence trail",
|
|
136
|
+
reason: "Executed work or verification results are still empty, so the handoff report should capture what remains unverified.",
|
|
137
|
+
command: commands.handoffReport,
|
|
138
|
+
references: ["implementationEvidence"],
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
actions.push(nextActionEntry({
|
|
143
|
+
severity: "handoff",
|
|
144
|
+
title: "Export portable handoff bundle",
|
|
145
|
+
reason: "A bundle keeps summary, tasks, MCP evidence, prompts, and handoff report together for the target website repo workflow.",
|
|
146
|
+
command: commands.handoffBundle,
|
|
147
|
+
references: ["bundle"],
|
|
148
|
+
}));
|
|
149
|
+
|
|
150
|
+
const severityOrder = {
|
|
151
|
+
blocking: 0,
|
|
152
|
+
warning: 1,
|
|
153
|
+
setup: 2,
|
|
154
|
+
implementation: 3,
|
|
155
|
+
handoff: 4,
|
|
156
|
+
};
|
|
157
|
+
const rankedActions = actions
|
|
158
|
+
.map((action, index) => ({ action, index }))
|
|
159
|
+
.sort((a, b) => {
|
|
160
|
+
const severityDiff = (severityOrder[a.action.severity] ?? 99) - (severityOrder[b.action.severity] ?? 99);
|
|
161
|
+
return severityDiff || a.index - b.index;
|
|
162
|
+
})
|
|
163
|
+
.map(({ action }, index) => ({
|
|
164
|
+
rank: index + 1,
|
|
165
|
+
...action,
|
|
166
|
+
}));
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
kind: "website-improvement-next-actions",
|
|
170
|
+
version: 1,
|
|
171
|
+
filePath,
|
|
172
|
+
status: combineStatuses(summary.status || "pass", mcpReport.status, mcpProbeReport.status),
|
|
173
|
+
workspaceStatus: summary.status || "unknown",
|
|
174
|
+
mcpStatus: mcpReport.status,
|
|
175
|
+
mcpProbeStatus: mcpProbeReport.status,
|
|
176
|
+
mcpProbeCounts: {
|
|
177
|
+
count: mcpProbeReport.count,
|
|
178
|
+
pass: mcpProbeReport.pass,
|
|
179
|
+
warn: mcpProbeReport.warn,
|
|
180
|
+
fail: mcpProbeReport.fail,
|
|
181
|
+
},
|
|
182
|
+
site: {
|
|
183
|
+
name: workspace.siteProfile.name,
|
|
184
|
+
liveUrl: workspace.siteProfile.liveUrl,
|
|
185
|
+
repoUrl: workspace.siteProfile.repoUrl,
|
|
186
|
+
localPath: workspace.siteProfile.localPath,
|
|
187
|
+
},
|
|
188
|
+
counts: {
|
|
189
|
+
actions: rankedActions.length,
|
|
190
|
+
blocking: rankedActions.filter((action) => action.severity === "blocking").length,
|
|
191
|
+
warnings: rankedActions.filter((action) => action.severity === "warning").length,
|
|
192
|
+
tasks: workspace.refactorTasks.length,
|
|
193
|
+
requiredMcpMissing: mcpReport.items.filter((item) => item.requestedStatus === "required" && item.level !== "pass").length,
|
|
194
|
+
taskGaps: mcpReport.taskGaps.length,
|
|
195
|
+
probeGaps: mcpProbeReport.items.filter((item) => item.level !== "pass").length,
|
|
196
|
+
},
|
|
197
|
+
topTasks: topTasks.map((task) => ({
|
|
198
|
+
id: task.id,
|
|
199
|
+
title: task.title,
|
|
200
|
+
priority: task.priority,
|
|
201
|
+
category: task.category,
|
|
202
|
+
impact: task.impact,
|
|
203
|
+
effort: task.effort,
|
|
204
|
+
})),
|
|
205
|
+
actions: rankedActions,
|
|
206
|
+
commands,
|
|
207
|
+
boundaries: [
|
|
208
|
+
"This next-action report is deterministic and local.",
|
|
209
|
+
"It does not call external MCPs, mutate the target website repo, run Lighthouse/axe, capture screenshots, or write deployment/CMS/Sentry data.",
|
|
210
|
+
"MCP probes are read-only local URL/path/reference checks and do not connect to external MCP servers.",
|
|
211
|
+
"Run implementation commands in the target website workflow after readiness blockers are cleared.",
|
|
212
|
+
],
|
|
213
|
+
externalCalls: false,
|
|
214
|
+
targetRepoMutation: false,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function buildSiteInitNextActionsReport(workspace, summary = {}) {
|
|
219
|
+
const filePath = summary.filePath || "website-workspace.json";
|
|
220
|
+
const report = buildSiteNextActionsReport(workspace, {
|
|
221
|
+
...summary,
|
|
222
|
+
filePath,
|
|
223
|
+
});
|
|
224
|
+
const createWorkspaceCommand = buildSiteInitCommand(workspace.siteProfile, filePath);
|
|
225
|
+
const createWorkspaceAction = {
|
|
226
|
+
rank: 1,
|
|
227
|
+
...nextActionEntry({
|
|
228
|
+
severity: "setup",
|
|
229
|
+
title: "Save the generated Website Improvement workspace",
|
|
230
|
+
reason: "The company dogfood flow needs a durable workspace JSON before MCP checks, task generation, handoff reports, or target-repo prompts can reference it.",
|
|
231
|
+
command: createWorkspaceCommand,
|
|
232
|
+
references: ["siteProfile", "workspace"],
|
|
233
|
+
}),
|
|
234
|
+
};
|
|
235
|
+
const actions = [createWorkspaceAction, ...report.actions.map((action) => ({
|
|
236
|
+
...action,
|
|
237
|
+
rank: action.rank + 1,
|
|
238
|
+
}))];
|
|
239
|
+
return {
|
|
240
|
+
...report,
|
|
241
|
+
mode: "init-next-actions",
|
|
242
|
+
counts: {
|
|
243
|
+
...report.counts,
|
|
244
|
+
actions: actions.length,
|
|
245
|
+
blocking: actions.filter((action) => action.severity === "blocking").length,
|
|
246
|
+
warnings: actions.filter((action) => action.severity === "warning").length,
|
|
247
|
+
},
|
|
248
|
+
actions,
|
|
249
|
+
commands: {
|
|
250
|
+
createWorkspace: createWorkspaceCommand,
|
|
251
|
+
...report.commands,
|
|
252
|
+
},
|
|
253
|
+
boundaries: [
|
|
254
|
+
"This init next-action report is deterministic and local.",
|
|
255
|
+
"Save the workspace JSON first when you plan to continue in the Website Console or target website repo.",
|
|
256
|
+
...report.boundaries,
|
|
257
|
+
],
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function buildSiteIntakeNextActionsReport(workspace, summary = {}, options = {}) {
|
|
262
|
+
const intakePath = options.intakePath || "company-website-intake.md";
|
|
263
|
+
const workspacePath = options.workspacePath || "website-workspace.json";
|
|
264
|
+
const report = buildSiteNextActionsReport(workspace, {
|
|
265
|
+
...summary,
|
|
266
|
+
filePath: workspacePath,
|
|
267
|
+
});
|
|
268
|
+
const createWorkspaceCommand = options.stdin
|
|
269
|
+
? `cat company-website-intake.md | design-ai site --from-intake --stdin --out ${quoteCliValue(workspacePath)} --force`
|
|
270
|
+
: `design-ai site --from-intake ${quoteCliValue(intakePath)} --out ${quoteCliValue(workspacePath)} --force`;
|
|
271
|
+
const createWorkspaceAction = {
|
|
272
|
+
rank: 1,
|
|
273
|
+
...nextActionEntry({
|
|
274
|
+
severity: "setup",
|
|
275
|
+
title: "Save the parsed Website Improvement workspace",
|
|
276
|
+
reason: "The filled intake Markdown should be converted into durable workspace JSON before MCP checks, task generation, handoff reports, or target-repo prompts reference it.",
|
|
277
|
+
command: createWorkspaceCommand,
|
|
278
|
+
references: ["intake", "workspace"],
|
|
279
|
+
}),
|
|
280
|
+
};
|
|
281
|
+
const actions = [createWorkspaceAction, ...report.actions.map((action) => ({
|
|
282
|
+
...action,
|
|
283
|
+
rank: action.rank + 1,
|
|
284
|
+
}))];
|
|
285
|
+
return {
|
|
286
|
+
...report,
|
|
287
|
+
mode: "from-intake-next-actions",
|
|
288
|
+
intakePath,
|
|
289
|
+
counts: {
|
|
290
|
+
...report.counts,
|
|
291
|
+
actions: actions.length,
|
|
292
|
+
blocking: actions.filter((action) => action.severity === "blocking").length,
|
|
293
|
+
warnings: actions.filter((action) => action.severity === "warning").length,
|
|
294
|
+
},
|
|
295
|
+
actions,
|
|
296
|
+
commands: {
|
|
297
|
+
createWorkspace: createWorkspaceCommand,
|
|
298
|
+
...report.commands,
|
|
299
|
+
},
|
|
300
|
+
boundaries: [
|
|
301
|
+
"This intake next-action report is deterministic and local.",
|
|
302
|
+
"Save the parsed workspace JSON first when you plan to continue in the Website Console or target website repo.",
|
|
303
|
+
...report.boundaries,
|
|
304
|
+
],
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function formatSiteNextActionsJson(report) {
|
|
309
|
+
return JSON.stringify(report, null, 2);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export function formatSiteNextActionsHuman(report) {
|
|
313
|
+
return [
|
|
314
|
+
`Website Improvement next actions: ${report.site.name}`,
|
|
315
|
+
"",
|
|
316
|
+
`Status: ${report.status}`,
|
|
317
|
+
`Workspace status: ${report.workspaceStatus}`,
|
|
318
|
+
`MCP status: ${report.mcpStatus}`,
|
|
319
|
+
`MCP probe status: ${report.mcpProbeStatus}`,
|
|
320
|
+
`MCP probes: ${report.mcpProbeCounts.pass}/${report.mcpProbeCounts.count} passing, ${report.mcpProbeCounts.warn} warning, ${report.mcpProbeCounts.fail} failing`,
|
|
321
|
+
`Actions: ${report.counts.actions} (${report.counts.blocking} blocking, ${report.counts.warnings} warning)`,
|
|
322
|
+
"",
|
|
323
|
+
"Prioritized actions:",
|
|
324
|
+
...report.actions.map((action) => {
|
|
325
|
+
const command = action.command ? `\n Command: \`${action.command}\`` : "";
|
|
326
|
+
const refs = action.references.length ? `\n References: ${action.references.join(", ")}` : "";
|
|
327
|
+
return `${action.rank}. [${action.severity}] ${action.title}\n Why: ${action.reason}${command}${refs}`;
|
|
328
|
+
}),
|
|
329
|
+
"",
|
|
330
|
+
"Boundaries:",
|
|
331
|
+
...report.boundaries.map((boundary) => `- ${boundary}`),
|
|
332
|
+
].join("\n");
|
|
333
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Shared option catalogs for Website Improvement workspace helpers.
|
|
2
|
+
|
|
3
|
+
export const AUDIT_CATEGORIES = [
|
|
4
|
+
{
|
|
5
|
+
id: "visual-design",
|
|
6
|
+
label: "Visual Design",
|
|
7
|
+
defaultVerification: [
|
|
8
|
+
"Compare spacing rhythm across target pages",
|
|
9
|
+
"Check contrast ratios for key text pairs",
|
|
10
|
+
],
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
id: "ux-flow",
|
|
14
|
+
label: "UX Flow",
|
|
15
|
+
defaultVerification: [
|
|
16
|
+
"Complete the primary user flow on desktop and mobile",
|
|
17
|
+
"Confirm one dominant CTA per decision point",
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "responsive",
|
|
22
|
+
label: "Responsive QA",
|
|
23
|
+
defaultVerification: [
|
|
24
|
+
"Verify desktop, tablet, and mobile viewports",
|
|
25
|
+
"Check text wrapping and touch targets",
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "accessibility",
|
|
30
|
+
label: "Accessibility",
|
|
31
|
+
defaultVerification: [
|
|
32
|
+
"Tab through all interactive controls",
|
|
33
|
+
"Confirm visible focus and accessible names",
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "performance",
|
|
38
|
+
label: "Performance",
|
|
39
|
+
defaultVerification: [
|
|
40
|
+
"Run Lighthouse or deployment analytics when available",
|
|
41
|
+
"Confirm image dimensions and lazy-loading",
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "seo",
|
|
46
|
+
label: "SEO",
|
|
47
|
+
defaultVerification: [
|
|
48
|
+
"Inspect metadata for each priority page",
|
|
49
|
+
"Validate heading order and canonical links",
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: "technical-quality",
|
|
54
|
+
label: "Technical Quality",
|
|
55
|
+
defaultVerification: [
|
|
56
|
+
"Inspect component ownership before editing",
|
|
57
|
+
"Run target repo lint/typecheck/build",
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: "runtime-issues",
|
|
62
|
+
label: "Runtime Issues",
|
|
63
|
+
defaultVerification: [
|
|
64
|
+
"Open the site in Browser or Chrome DevTools",
|
|
65
|
+
"Confirm console and network panels are clean",
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "content-quality",
|
|
70
|
+
label: "Content Quality",
|
|
71
|
+
defaultVerification: [
|
|
72
|
+
"Read the page as a first-time visitor",
|
|
73
|
+
"Check whether claims have concrete proof",
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
export const MCP_ITEMS = [
|
|
79
|
+
["github", "GitHub"],
|
|
80
|
+
["figma", "Figma"],
|
|
81
|
+
["browser", "Browser/Playwright"],
|
|
82
|
+
["chromeDevtools", "Chrome DevTools"],
|
|
83
|
+
["deploy", "Deploy"],
|
|
84
|
+
["sentry", "Sentry"],
|
|
85
|
+
["database", "Database"],
|
|
86
|
+
["cms", "CMS"],
|
|
87
|
+
["collaboration", "Collaboration"],
|
|
88
|
+
["research", "Research"],
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
export const PRIORITY_OPTIONS = ["p0", "p1", "p2", "p3"];
|
|
92
|
+
export const DEPLOY_OPTIONS = ["vercel", "netlify", "cloudflare", "other", "none"];
|
|
93
|
+
export const CMS_OPTIONS = ["sanity", "contentful", "wordpress", "shopify", "none", "other"];
|
|
94
|
+
export const DATABASE_OPTIONS = ["supabase", "neon", "postgres", "none", "other"];
|
|
95
|
+
export const VIEWPORT_OPTIONS = ["desktop", "tablet", "mobile"];
|
|
96
|
+
export const SITE_INTAKE_TEMPLATE_LANGUAGE_OPTIONS = ["en", "ko"];
|
|
97
|
+
export const CHECKLIST_STATUS_OPTIONS = ["todo", "in-progress", "done", "blocked"];
|
|
98
|
+
export const MCP_STATUS_OPTIONS = ["required", "optional", "unused", "unavailable"];
|
|
99
|
+
export const IMPACT_OPTIONS = ["high", "medium", "low"];
|
|
100
|
+
export const EFFORT_OPTIONS = ["high", "medium", "low"];
|
|
101
|
+
|
|
102
|
+
export function categoryById(id) {
|
|
103
|
+
return AUDIT_CATEGORIES.find((category) => category.id === id) || AUDIT_CATEGORIES[0];
|
|
104
|
+
}
|