diff --git a/apps/presentation/dashboard/smoke/presentation-surface-schema-smoke.ts b/apps/presentation/dashboard/smoke/presentation-surface-schema-smoke.ts index d1ce201f4..1d15402f2 100644 --- a/apps/presentation/dashboard/smoke/presentation-surface-schema-smoke.ts +++ b/apps/presentation/dashboard/smoke/presentation-surface-schema-smoke.ts @@ -5,6 +5,7 @@ import { parsePresentationSurfaceCollectionResponse, presentationSurfaceCollectionSchema, presentationSurfaceSchema, + todoItemSchema, withGoalActivationState, } from "../src/data/status.js"; import { @@ -23,6 +24,29 @@ function assert(condition: boolean, message: string) { const PAYLOAD_SHA256 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; +const revisedTodo = todoItemSchema.parse({ + index: 0, + text: "Verify the replacement validator", + done: false, + todo_id: "todo_validator_revision", + role: "agent", + completion_validation_required: true, + completion_validation_sha256: PAYLOAD_SHA256, + completion_validation_revision: 1, + completion_validation_revision_history: [{ + revision: 1, + previous_declaration_sha256: "1".repeat(64), + declaration_sha256: PAYLOAD_SHA256, + actor_agent_id: "agent-a", + revised_at: "2026-09-20T00:00:00Z", + }], +}); +assert( + revisedTodo.completion_validation_revision_history.at(-1)?.actor_agent_id === + "agent-a", + "Todo validator revision readback must survive status parsing", +); + function detailRef() { return { extension_id: "test-research-extension", diff --git a/apps/presentation/dashboard/src/data/status.ts b/apps/presentation/dashboard/src/data/status.ts index aa22bec71..613a98ced 100644 --- a/apps/presentation/dashboard/src/data/status.ts +++ b/apps/presentation/dashboard/src/data/status.ts @@ -85,6 +85,16 @@ export const todoItemSchema = z.object({ note: z.string().optional().nullable(), evidence: z.string().optional().nullable(), updated_at: z.string().optional().nullable(), + completion_validation_required: z.boolean().optional().nullable(), + completion_validation_sha256: z.string().optional().nullable(), + completion_validation_revision: z.number().int().nonnegative().optional().nullable(), + completion_validation_revision_history: z.array(z.object({ + revision: z.number().int().positive(), + previous_declaration_sha256: z.string(), + declaration_sha256: z.string(), + actor_agent_id: z.string(), + revised_at: z.string(), + }).passthrough()).optional().default([]), review_materials: z.array(reviewMaterialSchema).optional().default([]), }).passthrough(); diff --git a/apps/presentation/dashboard/src/features/personal-workspace/context-drawer.tsx b/apps/presentation/dashboard/src/features/personal-workspace/context-drawer.tsx index fee7252a6..ad07705f2 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/context-drawer.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/context-drawer.tsx @@ -588,6 +588,11 @@ export function ContextDrawer({ agents, attentionHistory = [], onSelectAttention {selection.item.status === "deferred" || selection.item.resumeWhen ?
{selection.item.validationDigest}