/**
 * Cancel propagation (events doc v0.1.2 §2.5, Step 9 of 10).
 *
 * Cancel is a TERMINAL REASON, not an error — Run/Node/Activity each
 * have an independent `cancelled` terminal state.  The chain (§2.5):
 *
 *   cancelRequested(target)
 *     → scheduler broadcasts to non-terminal nodes
 *     → for each running activity: send cancel signal
 *     → cancelDelivered (worker acknowledges)
 *     → worker cleans up
 *     → activityCanceled (Activity terminal)
 *     → nodeCanceled    (Node terminal, only after ALL its activities
 *                        reach a terminal state; spec §2.5 "partial
 *                        cancel": cancelRequested(activityId) does NOT
 *                        auto-cancel parent node)
 *     → runCanceled     (Run terminal, only when all nodes terminal;
 *                        spec §2.5: cancelRequested(nodeId) does NOT
 *                        auto-cancel parent run)
 *
 * Step 9 deliverables:
 *   - `requestCancel`, `deliverCancel`, `completeActivityCancel` —
 *     host functions that write the corresponding events.
 *   - replay projection of in-flight cancel state so resume can
 *     detect dangling cancels (cancelRequested written, terminal
 *     missing) and complete them.
 *   - resume integration: a third recovery branch alongside
 *     reconcile + wait recovery.
 *
 * Step 9 does NOT:
 *   - implement the scheduler broadcast (run/node → activity fan-out
 *     is Step 10+ scheduler concern; this layer assumes the caller
 *     supplies activity-level cancels);
 *   - decide retry policy (cancel preempts retry — once canceled,
 *     terminal stays canceled, not failed/retryable).
 */
// ─── Host API ─────────────────────────────────────────────────────────────
/**
 * Originating cancel event.  Records the intent without changing any
 * entity state — the actual transitions happen via cancelDelivered →
 * activityCanceled.
 */
export async function requestCancel(log, input, actor = 'human') {
    return (await log.append({
        runId: log.runId,
        type: 'cancelRequested',
        actor,
        payload: {
            target: input.target,
            reason: input.reason,
            by: input.by,
        },
    }));
}
/**
 * Worker acknowledges the cancel signal for a specific activity.
 * Multiple cancelDelivered events may fan out from a single
 * cancelRequested(run|node).
 */
export async function deliverCancel(log, input, actor = 'worker') {
    return (await log.append({
        runId: log.runId,
        type: 'cancelDelivered',
        actor,
        payload: {
            target: input.target,
            activityId: input.activityId,
        },
    }));
}
/**
 * Activity terminal in the cancel branch.  Spec §2.5: cancel produces
 * a distinct terminal state (not activityFailed/canceled error code).
 */
export async function completeActivityCancel(log, input, actor = 'scheduler') {
    return (await log.append({
        runId: log.runId,
        type: 'activityCanceled',
        actor,
        payload: {
            activityId: input.activityId,
            attemptId: input.attemptId,
            cancelOriginEventId: input.cancelOriginEventId,
        },
    }));
}
/**
 * Node terminal in the cancel branch.  Spec §2.5: nodeCanceled fires
 * only after ALL of the node's activities have reached terminal — the
 * caller (scheduler / supervisor) is responsible for verifying that
 * precondition before invoking.  This helper merely writes the event.
 */
export async function completeNodeCancel(log, input, actor = 'scheduler') {
    return (await log.append({
        runId: log.runId,
        type: 'nodeCanceled',
        actor,
        payload: {
            nodeId: input.nodeId,
            cancelOriginEventId: input.cancelOriginEventId,
        },
    }));
}
/**
 * Run terminal in the cancel branch.  Spec §2.5: runCanceled fires
 * only after ALL of the run's nodes have reached terminal.  Same
 * precondition responsibility as `completeNodeCancel` — this helper
 * writes the event but doesn't enforce dependencies.
 */
export async function completeRunCancel(log, input, actor = 'scheduler') {
    return (await log.append({
        runId: log.runId,
        type: 'runCanceled',
        actor,
        payload: {
            cancelOriginEventId: input.cancelOriginEventId,
        },
    }));
}
//# sourceMappingURL=cancel.js.map