feat(FN-4367): finalize structured workflow verdict contract

Fusion-Task-Id: FN-4367
Fusion-Task-Lineage: adbfac60-5cfe-4ae9-9706-1094dfe7d676
This commit is contained in:
Fusion
2026-05-14 11:08:10 -07:00
committed by gsxdsm
parent db78679758
commit 09ad2b4edf
12 changed files with 206 additions and 347 deletions

View File

@@ -1,110 +1,56 @@
#!/usr/bin/env node
/**
* Replace the WS-006 (Frontend UX Design) workflow step prompt in the database
* with the updated version that uses structured JSON verdict output.
*
* Usage:
* node scripts/replace-ws006-prompt.mjs [--db=.fusion/fusion.db] [--dry-run]
*
* Flags:
* --db=<path> Path to the SQLite database (default: .fusion/fusion.db)
* --dry-run Print the new prompt without writing to the database
*
* Idempotent: re-running replaces the prompt again with the same content.
* WS-006 rollback prompt (captured from DB before replacement):
* (not captured in this worktree; run `sqlite3 .fusion/fusion.db "SELECT prompt FROM workflow_steps WHERE id='WS-006';"` before applying in production)
*/
import Database from "better-sqlite3";
import { resolve } from "node:path";
const args = process.argv.slice(2);
const dbArg = args.find((a) => a.startsWith("--db="));
const dryRun = args.includes("--dry-run");
const dbPath = dbArg ? dbArg.slice(5) : ".fusion/fusion.db";
const NEW_PROMPT = `You are the Frontend UX Design workflow reviewer.
const NEW_PROMPT = `You are a UX design reviewer. Verify frontend changes maintain visual polish and consistency with existing UI patterns and design tokens.
Step 1 (mandatory, first): inspect the already-provided "Diff Scope" block in system context.
If no frontend/UI files are in scope, immediately output exactly:
{"verdict":"APPROVE","notes":"out of scope: no UI files changed"}
and STOP.
## Step 1: Scope Check (MANDATORY FIRST)
If frontend/UI files exist in scope, review only those scoped files for:
- visual hierarchy
- spacing/typography consistency
- token-based color/style usage
- component reuse and design-system consistency
- responsive behavior
The task harness provides a "Diff Scope" listing files this task actually changed.
If changes are acceptable: use APPROVE or APPROVE_WITH_NOTES.
If changes are required: use REVISE with concrete actionable notes.
If the Diff Scope contains ZERO frontend/UI files (no .tsx/.jsx/.ts/.js component files, no .css/.scss/.sass/.styl, no .html/.vue/.svelte/.astro, no design-token/theme files), output ONLY:
Final output rule: output exactly one trailing JSON object and STOP (no prose, no markdown fences):
{"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}`;
\`\`\`json-workflow-verdict
{"verdict":"PASS","notes":"No UI changes in scope — approved."}
\`\`\`
Then STOP. Do not browse the worktree. Do not read any files.
If there ARE frontend/UI files in scope, proceed to Step 2.
## Step 2: Design Review
Restrict your review to ONLY the UI files in the diff scope.
Check:
1. **Visual Hierarchy** — heading levels, content flow, information architecture
2. **Spacing and Typography** — consistent margins, padding, gaps, type scale
3. **Color and Token Consistency** — CSS custom properties and design tokens used; no hardcoded colors
4. **Component Reuse** — existing components reused; no one-off styling or duplication
5. **Responsive Behavior** — layouts adapt across viewports
6. **Fit with Design Language** — border radius, shadows, transitions, icon style match patterns
## Output Format
End your response with a JSON verdict block:
For clean reviews:
\`\`\`json-workflow-verdict
{"verdict":"PASS","notes":"<1-2 sentence summary>"}
\`\`\`
For issues requiring code changes:
\`\`\`json-workflow-verdict
{"verdict":"FAIL","notes":"<specific files and what needs to change>"}
\`\`\`
Prioritize: layout breaks > visual inconsistency > style preferences.
Do NOT spend time on nits when no real issues exist.`;
const STEP_ID = "frontend-ux-design";
async function main() {
if (dryRun) {
console.log("=== DRY RUN: New WS-006 prompt ===\n");
console.log(NEW_PROMPT);
console.log("\n=== End of prompt ===");
return;
}
const resolvedPath = resolve(dbPath);
console.log(`Opening database: ${resolvedPath}`);
const db = new Database(resolvedPath);
// Check if the workflow step exists
const row = db.prepare("SELECT id, name, prompt FROM workflow_steps WHERE id = ?").get(STEP_ID);
if (!row) {
console.error(`Workflow step '${STEP_ID}' not found in database. No action taken.`);
db.close();
process.exit(0);
}
console.log(`Found workflow step: ${row.name} (${row.id})`);
console.log(`Old prompt length: ${row.prompt?.length ?? 0} chars`);
console.log(`New prompt length: ${NEW_PROMPT.length} chars`);
const result = db.prepare("UPDATE workflow_steps SET prompt = ?, updatedAt = ? WHERE id = ?").run(
NEW_PROMPT,
new Date().toISOString(),
STEP_ID,
);
console.log(`Updated ${result.changes} row(s).`);
db.close();
const dbPath = (process.argv.find((arg) => arg.startsWith("--db=")) || "--db=.fusion/fusion.db").slice(5);
const checkOnly = process.argv.includes("--check");
const db = new Database(resolve(dbPath));
const row = db.prepare("SELECT id, name, prompt FROM workflow_steps WHERE id = 'WS-006'").get();
if (!row) {
console.error("WS-006 not found");
process.exit(1);
}
main().catch((err) => {
console.error("Error:", err.message);
process.exit(1);
});
const current = row.prompt ?? "";
if (checkOnly) {
console.log(current === NEW_PROMPT ? "WS-006 prompt matches target" : "WS-006 prompt differs from target");
process.exit(0);
}
if (current === NEW_PROMPT) {
console.log("No-op: WS-006 prompt already matches target.");
process.exit(0);
}
const beforeLen = current.length;
const afterLen = NEW_PROMPT.length;
console.error(`Updating ${row.id} (${row.name}) length ${beforeLen} -> ${afterLen}`);
for (const line of ["--- old", "+++ new", `- first line: ${current.split("\n")[0] || ""}`, `+ first line: ${NEW_PROMPT.split("\n")[0] || ""}`]) {
console.error(line);
}
db.prepare("UPDATE workflow_steps SET prompt = ?, updatedAt = ? WHERE id = 'WS-006'").run(NEW_PROMPT, new Date().toISOString());
console.log(`Updated ${row.id} (${row.name})`);