/** * Minimal-by-default mutate envelope projection (T9931 / Saga T9855 / E9.4). * * For state-modifying ops (`tasks.add`, `tasks.add-batch`, `tasks.update`, * `tasks.complete`, `tasks.delete`) the dispatcher used to return the full * post-mutation task record — title, description, acceptance, verification, * createdAt, updatedAt, labels, the entire row. Agents almost never need any * of that to keep working; they only need enough information to confirm the * mutation landed and to feed the next operation. This module strips the * payload down to `{count, created[], updated[], deleted[]}` (and, for * single-task ops, a few extra routing keys like `status`, `completedAt`, or * `changes`). A deprecated `ids[]` alias remains for existing field pointers. * * This is the mutate-side analogue to {@link applyProjectionPlan} for read * ops in `./mvi-projection.ts`. The two modules use the same opt-out signal * (`--full` / `--verbose` / `--human`) so a single CLI flag restores verbose * behaviour everywhere. * * @packageDocumentation * @module @cleocode/core/dispatch/mutate-projection * * @epic T9855 (Saga) * @task T9931 (E9.4) */ import type { ProjectionMode } from './mvi-projection.js'; /** * Minimal envelope shape returned for batch-style mutate ops. * * Always includes a count and operation-specific affected task IDs. For * single-task ops (`add`, `update`, `complete`, `delete`) `count` is `1` and * exactly one of `created`, `updated`, or `deleted` contains the affected ID. * For `add-batch`, `created` reflects the entire transaction. */ export interface MinimalMutateEnvelope { /** Number of records the mutation affected. */ count: number; /** Task IDs created by the mutation, in operation order. */ created: string[]; /** Task IDs updated by the mutation, in operation order. */ updated: string[]; /** Task IDs deleted by the mutation, in operation order. */ deleted: string[]; /** * Deprecated legacy alias for the non-empty created/updated/deleted set. * Kept so `/data/ids/0` remains script-compatible while callers migrate. */ ids: string[]; /** Machine-readable hints for deprecated field paths. */ fieldPathHints: Record; /** * Per-op routing extras kept for single-task ops: * - `status` — post-mutation task status (add, update, complete) * - `completedAt` — ISO timestamp (complete only) * - `changes` — list of fields that changed (update only) * - `dryRun` — true when no DB write occurred (add, add-batch) * * Index signature is intentionally open so future ops can attach their * own minimal extras without expanding the type registry. */ [key: string]: unknown; } /** * Plan describing how to derive a {@link MinimalMutateEnvelope} from a raw * mutate op data payload. * * `extract` runs against `response.data` (NOT the full response) and must * return a fresh object — callers treat the result as immutable. */ export interface MutateProjectionPlan { /** Canonical `.` key this plan applies to. */ operation: string; /** * Extractor that turns the raw mutate result into the minimal envelope. * * Implementations MUST be defensive: the raw shape may be missing fields * when the underlying core op returned partial data (e.g. a dry-run path * that returned synthetic IDs). When the extractor cannot determine an * ID it returns `count: 0, ids: []` rather than throwing — the original * envelope is then returned unchanged by {@link applyMutateProjection}. */ extract: (data: Record) => MinimalMutateEnvelope; } /** * SSoT mapping of mutate operation → projection plan. * * The keys MUST match the canonical `.` identifier used * by the dispatcher. Ops absent from this table opt OUT of minimal projection * (the original payload flows through untouched). */ export declare const MUTATE_PROJECTION_PLANS: Readonly>; /** * Apply the {@link MUTATE_PROJECTION_PLANS} entry for an operation, returning * the minimal envelope when a plan exists and `mode` is `'mvi'`. * * Behaviour table: * * | mode | plan present? | extractor returned count? | output | * |---------|---------------|---------------------------|-----------------------| * | `full` | any | any | original `data` | * | `mvi` | no | n/a | original `data` | * | `mvi` | yes | `count > 0` | minimal envelope | * | `mvi` | yes | `count === 0` | original `data` | * * The last row guards against silent data loss: if the extractor could not * find any ID in the raw payload (e.g. an unexpected shape from a future * core op revision) the caller still sees the full payload rather than an * empty `{count:0, ids:[]}` envelope. * * @param data - The dispatch response `data` payload. * @param operation - The canonical `.` identifier. * @param mode - `'mvi'` applies the plan; `'full'` is a no-op. * @returns Either the minimal envelope or the original `data` reference. */ export declare function applyMutateProjection(data: unknown, operation: string, mode: ProjectionMode): unknown; //# sourceMappingURL=mutate-projection.d.ts.map