From ff4c572157a41c6b8603d57af5f9a806b246000a Mon Sep 17 00:00:00 2001 From: Matthias Meister Date: Sat, 13 Jun 2026 21:09:49 +0200 Subject: [PATCH] Refactor pipeline task handling and UI flows --- ...udits-with-Convex-Workflow-and-Workpool.md | 53 +++ components/audits/audits-board.tsx | 62 +++- convex/_generated/api.d.ts | 4 + convex/auditGeneration.ts | 24 +- convex/auditGenerationAction.ts | 337 ++++++++++++------ convex/auditWorkflow.ts | 238 +++++++++++++ convex/audits.ts | 113 +++++- convex/convex.config.ts | 4 + convex/pageSpeed.ts | 16 +- convex/pageSpeedAction.ts | 199 ++++++----- convex/runs.ts | 108 +++++- convex/schema.ts | 8 + lib/ai/schemas.ts | 13 + lib/audits/progress.ts | 75 ++++ package.json | 2 + pnpm-lock.yaml | 36 ++ tests/ai-schemas.test.ts | 52 +++ tests/audit-generation-action-source.test.ts | 63 ++-- tests/audit-progress.test.ts | 41 +++ tests/audit-workflow-source.test.ts | 92 +++++ tests/audits-board-layout.test.ts | 7 +- tests/audits-dashboard-query-source.test.ts | 21 ++ tests/pagespeed-action-source.test.ts | 8 +- tests/pagespeed-persistence-source.test.ts | 6 +- 24 files changed, 1346 insertions(+), 236 deletions(-) create mode 100644 backlog/tasks/task-54 - Orchestrate-audits-with-Convex-Workflow-and-Workpool.md create mode 100644 convex/auditWorkflow.ts create mode 100644 lib/audits/progress.ts create mode 100644 tests/audit-progress.test.ts create mode 100644 tests/audit-workflow-source.test.ts diff --git a/backlog/tasks/task-54 - Orchestrate-audits-with-Convex-Workflow-and-Workpool.md b/backlog/tasks/task-54 - Orchestrate-audits-with-Convex-Workflow-and-Workpool.md new file mode 100644 index 0000000..877c38d --- /dev/null +++ b/backlog/tasks/task-54 - Orchestrate-audits-with-Convex-Workflow-and-Workpool.md @@ -0,0 +1,53 @@ +--- +id: TASK-54 +title: Orchestrate audits with Convex Workflow and Workpool +status: In Progress +assignee: [] +created_date: '2026-06-12 19:45' +updated_date: '2026-06-13 05:56' +labels: [] +dependencies: [] +priority: high +ordinal: 56000 +--- + +## Description + + +Replace the fragile audit scheduler chain with Convex Workflow/Workpool orchestration while keeping agentRuns as the visible product state for progress, retries, dashboard cards, and manual retry. + + +## Acceptance Criteria + +- [x] #1 Audit starts create a visible agentRuns-backed card immediately in the audit dashboard +- [x] #2 Convex Workflow and Workpool dependencies and components are registered +- [x] #3 Audit progress exposes step, total, label, and percent in dashboard rows +- [x] #4 Retry behavior is tracked on agentRuns and user-facing errors are hidden until final failure +- [x] #5 Audit dashboard supports a manual retry action for final failed runs +- [x] #6 Existing audit and outreach persistence remains compatible + + +## Implementation Plan + + +1. Add failing source/UI tests for workflow registration, immediate audit dashboard rows, progress mapping, retry controls, and retry orchestration. +2. Add Convex Workflow/Workpool dependencies and register components. +3. Add agentRun orchestration/progress fields and helper mappings. +4. Start audits through Workflow while preserving existing agentRuns as product state. +5. Surface active audit runs, progress, retry state, and manual retry in the audit dashboard. +6. Adjust quality-review behavior and run verification. + + +## Implementation Notes + + +Implemented Workflow/Workpool orchestration for root audit runs, progress mapping, dashboard retry UI, parallel PageSpeed strategies, and parallel German copy calls. Ran npx convex codegen and pnpm test successfully (416/416). Task remains In Progress pending user confirmation. + +Added workflow-specific wrapper actions so Workpool retries throw on failed PageSpeed/audit-generation steps, while legacy actions remain compatible. Re-ran pnpm test successfully (416/416) after codegen. + +User reported runtime regression: root audit workflow fails during 2/6 PageSpeed and jumps to 6/6 with PageSpeed-Analyse konnte nicht abgeschlossen werden. Investigating with systematic debugging before patching. + +Fixed runtime regression reported after Workflow migration: the workflow marked root audit runs as running before PageSpeed, while startPageSpeedAuditRun rejected running runs and returned null before any PageSpeed work began. startPageSpeedAuditRun now accepts running root audit runs. The final workflow failure path now preserves the current failing progress step instead of forcing qualityReview/6 of 6. Added regression coverage in tests/audit-workflow-source.test.ts. Verified with pnpm test (418/418), git diff --check, and npx convex dev --once against the dev deployment. + +Implemented LLM copy review replacement for the hard German-Copy-Guard gate. qualityReview now supports severity, rewriteRequired, revisedCopy, one automatic rewrite attempt, deterministic guard telemetry, and warning-only copy feedback. Audit/outreach persistence proceeds after copy review warnings; only technical/schema/provider/persistence failures remain fatal. Also deduped audit dashboard rows so child audit_generation runs are hidden behind visible root audit runs for the same lead. Verified with focused tests, pnpm test (420/420), git diff --check, and npx convex dev --once against the dev deployment. + diff --git a/components/audits/audits-board.tsx b/components/audits/audits-board.tsx index be4abee..00a8b92 100644 --- a/components/audits/audits-board.tsx +++ b/components/audits/audits-board.tsx @@ -2,12 +2,13 @@ import { useMemo, useState } from "react"; -import { useQuery } from "convex/react"; +import { useMutation, useQuery } from "convex/react"; import { FunctionReturnType } from "convex/server"; -import { Activity, Files, FileSearch, SquarePen } from "lucide-react"; +import { Activity, Files, FileSearch, RotateCcw, SquarePen } from "lucide-react"; import Link from "next/link"; import { api } from "@/convex/_generated/api"; +import type { Id } from "@/convex/_generated/dataModel"; import { Skeleton } from "@/components/ui/skeleton"; import { Badge } from "@/components/ui/badge"; import { @@ -96,7 +97,9 @@ function AuditsBoardLoading() { export function AuditsBoard() { const dashboardRows = useQuery(api.audits.listDashboardRows, { limit: 100 }); + const retryAuditRun = useMutation(api.audits.retryAuditRun); const [activeFilter, setActiveFilter] = useState("all"); + const [retryingRunId, setRetryingRunId] = useState(null); const rows = useMemo(() => { if (!dashboardRows) { return []; @@ -141,6 +144,14 @@ export function AuditsBoard() { { label: "Pipeline", value: "generation", count: statusCounts.generation }, { label: "Fehlgeschlagen", value: "failed", count: statusCounts.failed }, ]; + const handleRetryAudit = async (runId: Id<"agentRuns">) => { + setRetryingRunId(runId); + try { + await retryAuditRun({ runId }); + } finally { + setRetryingRunId(null); + } + }; if (dashboardRows === undefined) { return ; @@ -260,6 +271,41 @@ export function AuditsBoard() { {row.errorSummary}

) : null} + {row.kind === "generation" ? ( +
+
+ + {row.progress.step}/{row.progress.total} · {row.progress.label} + + + {row.progress.percent}% + +
+
+
+
+ {row.retry.isRetrying ? ( +

+ Versuch {row.retry.attempt}/{row.retry.maxAttempts} läuft +

+ ) : null} + {row.retry.isRetrying && row.retry.lastRetryReason ? ( +

+ {row.retry.lastRetryReason} +

+ ) : null} +
+ ) : null}
@@ -271,6 +317,18 @@ export function AuditsBoard() {