Skip to content

A checklist computed at runtime

The escalation boundaryDashboardSDKconditionalx-lt-widgetx-lt-source

The workflow decides which steps a person must confirm. The form renders them from the row, so one schema serves every variation.

The situation

A release check depends on the order: a fragile item adds a packing step, an export order adds a customs step. The list changes per run, and maintaining a form per combination is not an option.

The recipe

workflows/release-check.ts
import { Durable } from '@hotmeshio/hotmesh';
import { conditional, type LTEnvelope } from '@hotmeshio/long-tail';
export async function releaseCheck(envelope: LTEnvelope) {
const { orderId, fragile, international } = envelope.data;
const { workflowId } = Durable.workflow.workflowInfo();
const steps = [
{ id: 'count', label: 'Item count matches the order' },
...(fragile ? [{ id: 'wrap', label: 'Fragile items are wrapped' }] : []),
...(international ? [{ id: 'customs', label: 'Customs form is attached' }] : []),
];
const result = await conditional<{ checks: Record<string, boolean> }>(`release-check-${workflowId}`, {
role: 'packing',
description: `Release checks for ${orderId}`,
envelope: { checklist_items: steps },
metadata: {
orderId,
form_schema: {
title: 'Release check',
required: ['checks'],
properties: {
checks: { type: 'object', 'x-lt-widget': 'checklist', 'x-lt-source': 'envelope.checklist_items' },
},
},
},
});
if (!result) return { data: { orderId, released: false } };
const missed = steps.filter((s) => !result.checks[s.id]).map((s) => s.label);
return { data: { orderId, released: missed.length === 0, missed } };
}

x-lt-source points the checklist widget at the items the workflow wrote onto the row’s envelope. The count and wording vary per escalation; the schema stays the same.

The guarantee

The person sees exactly the steps this run computed, and the answer comes back keyed by the step ids the workflow chose. See Forms.