@fuaran-ui/ops 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Result, NodeId, NodeKind, JsonValue, Binding, SemanticStyle, StateBehaviour, Node, Cell, ColExpr, DataSource, Transform, EvalError, Table, TextSource, CellFormat, ColumnWidth, Orientation, ToneVariant, StyleWeight, Emphasis, HeadingVariant, BadgeVariant, IconSource } from '@fuaran-ui/schema';
1
+ import { Result, NodeId, NodeKind, JsonValue, Binding, SemanticStyle, StateBehaviour, Node, Cell, ColExpr, DataSource, Transform, EvalError, Table, TextSource, CellFormat, ColumnWidth, Orientation, ToneVariant, StyleWeight, Emphasis, HeadingVariant, BadgeVariant, IconSource, IconSize } from '@fuaran-ui/schema';
2
2
 
3
3
  /** Local JSON AST. Shape-for-shape port of the F# decoder's private `Json` DU. */
4
4
  type JsonAst = {
@@ -142,6 +142,22 @@ interface DecodeError {
142
142
  readonly expectedShape?: string;
143
143
  }
144
144
  type R<T> = Result<T, DecodeError>;
145
+ /**
146
+ * Phase 818 — materialise a LIVE Transform source's resolved store value as the
147
+ * evaluation input table: row-major rows transpose through the same 815
148
+ * normalisation the decode-time snapshot used, then decode through the
149
+ * columnar codec (schema inference included). `ok: false` for any value that
150
+ * cannot be read as data — callers surface that loudly, never silently
151
+ * (the Phase-427 mismatch posture). Exported for the renderers' shared
152
+ * `evalTransformFrame` live leg.
153
+ */
154
+ declare const liveValueToTable: (v: unknown) => {
155
+ readonly ok: true;
156
+ readonly value: Table;
157
+ } | {
158
+ readonly ok: false;
159
+ readonly error: string;
160
+ };
145
161
  /** Typed-value coercers for `TreeOp.UpdateProp` (used by the apply engine). */
146
162
  declare const coerce: {
147
163
  int: (v: JsonValue) => Result<number, string>;
@@ -168,6 +184,10 @@ declare const coerce: {
168
184
  headingVariant: (v: JsonValue) => Result<HeadingVariant, string>;
169
185
  badgeVariant: (v: JsonValue) => Result<BadgeVariant, string>;
170
186
  iconSource: (v: JsonValue) => Result<IconSource, string>;
187
+ /** `Icon.Size : IconSize` (Phase 821) — the UpdateProp twin of `decodeIconSize`,
188
+ * added with the standalone Icon display kind. */
189
+ iconSize: (v: JsonValue) => Result<IconSize, string>;
190
+ stringOption: (v: JsonValue) => Result<string | undefined, string>;
171
191
  };
172
192
  /** Decode a canonical-JSON `Node` payload into the storage-shape `Node<unknown>`. */
173
193
  declare const decodeNode: (json: string) => R<Node<unknown>>;
@@ -197,6 +217,168 @@ type ApplyResult<TMsg> = Result<{
197
217
  */
198
218
  declare const apply: <TMsg>(tree: Node<TMsg>, op: TreeOp<TMsg>) => ApplyResult<TMsg>;
199
219
 
220
+ /**
221
+ * Where a node should sit among its destination siblings, stated the only way
222
+ * the op vocabulary allows: by naming an existing sibling, or an end.
223
+ */
224
+ type Placement =
225
+ /** Append — what `InsertChild` / `MoveNode` do on their own. */
226
+ {
227
+ readonly kind: 'Last';
228
+ }
229
+ /** Prepend — before every current sibling. */
230
+ | {
231
+ readonly kind: 'First';
232
+ }
233
+ /** Immediately before the named sibling. */
234
+ | {
235
+ readonly kind: 'Before';
236
+ readonly anchor: NodeId;
237
+ }
238
+ /** Immediately after the named sibling. */
239
+ | {
240
+ readonly kind: 'After';
241
+ readonly anchor: NodeId;
242
+ };
243
+ /** A structural destination: which parent, and where among its children. */
244
+ interface PlaceTarget {
245
+ readonly parentId: NodeId;
246
+ readonly placement: Placement;
247
+ }
248
+ /**
249
+ * Why a placement could not become an op. Each case is a pre-statement of the
250
+ * apply-time refusal the emitted op would have met, so a helper rejection and
251
+ * an apply rejection agree — no false permit, no false refuse.
252
+ */
253
+ type PlaceError =
254
+ /** The destination parent is not in the tree (apply: `ParentNotFound`). */
255
+ {
256
+ readonly kind: 'ParentNotFound';
257
+ readonly parentId: NodeId;
258
+ }
259
+ /** The destination parent's kind has no children field (apply: `ChildlessKind`). */
260
+ | {
261
+ readonly kind: 'ChildlessKind';
262
+ readonly parentId: NodeId;
263
+ }
264
+ /**
265
+ * The node to move / nudge / duplicate is not structurally addressable
266
+ * (absent, or held in a non-structural position the structural ops cannot
267
+ * reach) — apply: `NodeNotFound`.
268
+ */
269
+ | {
270
+ readonly kind: 'NodeNotFound';
271
+ readonly nodeId: NodeId;
272
+ }
273
+ /**
274
+ * The placement anchor is not among the destination's post-op children. The
275
+ * only op that could honour it — a `ReorderChildren` naming it — is refused
276
+ * by the apply engine as `OrderingMismatch`.
277
+ */
278
+ | {
279
+ readonly kind: 'UnknownAnchor';
280
+ readonly anchor: NodeId;
281
+ }
282
+ /**
283
+ * The subtree being inserted carries an id already present in the tree
284
+ * (apply: `DuplicateNodeId`).
285
+ */
286
+ | {
287
+ readonly kind: 'DuplicateId';
288
+ readonly nodeId: NodeId;
289
+ }
290
+ /** The node would become its own parent (apply: `KindMismatch`). */
291
+ | {
292
+ readonly kind: 'MoveIntoSelf';
293
+ readonly nodeId: NodeId;
294
+ }
295
+ /**
296
+ * The destination sits inside the node's own subtree — a cycle (apply:
297
+ * `KindMismatch`).
298
+ */
299
+ | {
300
+ readonly kind: 'MoveIntoDescendant';
301
+ readonly nodeId: NodeId;
302
+ readonly parentId: NodeId;
303
+ }
304
+ /** The root has no siblings to nudge among. */
305
+ | {
306
+ readonly kind: 'CannotNudgeRoot';
307
+ readonly nodeId: NodeId;
308
+ }
309
+ /** The nudge would leave the sibling range (already first / already last). */
310
+ | {
311
+ readonly kind: 'NudgeOutOfRange';
312
+ readonly nodeId: NodeId;
313
+ readonly delta: number;
314
+ };
315
+ /**
316
+ * How the clone verbs mint replacement ids: given the id being replaced and a
317
+ * predicate over every id already claimed (the whole target tree, the whole
318
+ * incoming subtree, and ids minted earlier in the same remap), return an id
319
+ * the predicate refuses. Injectable so a host with its own id discipline can
320
+ * supply it; `derivedFreshIds` is the default.
321
+ */
322
+ type FreshIds = (oldId: string, taken: (candidate: string) => boolean) => string;
323
+ /**
324
+ * The default strategy: `<oldId>-copy`, then `<oldId>-copy-2`, `-copy-3`, … —
325
+ * the first candidate not already taken. Deterministic (derived from the id it
326
+ * replaces, no ambient state) and collision-free by probing.
327
+ */
328
+ declare const derivedFreshIds: FreshIds;
329
+ /**
330
+ * Sequential ids under a fixed prefix (`<prefix>-1`, `-2`, …) — the
331
+ * deterministic-replay option: the minted sequence depends only on the prefix
332
+ * and the order of requests, never on the ids being replaced. Each call to
333
+ * `sequentialFreshIds` starts its own counter.
334
+ */
335
+ declare const sequentialFreshIds: (prefix: string) => FreshIds;
336
+ /**
337
+ * Whether `moved` may legally take up residence at `target` — the pre-check an
338
+ * editor uses to grey out an illegal drop without a dry-run apply. Mirrors the
339
+ * apply engine's rejections: absent node, move into itself, move into its own
340
+ * descendant (a cycle), absent or childless destination, unknown anchor.
341
+ */
342
+ declare const canPlace: <TMsg>(root: Node<TMsg>, moved: NodeId, target: PlaceTarget) => Result<void, PlaceError>;
343
+ /**
344
+ * The op an insertion becomes. `InsertChild` appends, so the wanted order is
345
+ * computed over the post-insert membership and stated by `ReorderChildren`
346
+ * naming every sibling id; the reorder leg is dropped when appending already
347
+ * produces that order.
348
+ */
349
+ declare const placeOp: <TMsg>(root: Node<TMsg>, child: Node<TMsg>, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
350
+ /**
351
+ * The op a move becomes. `MoveNode` appends under the new parent, and the node
352
+ * may already be one of that parent's children (a re-placement within one
353
+ * parent), so the post-move membership is the siblings WITHOUT it plus it.
354
+ */
355
+ declare const moveOp: <TMsg>(root: Node<TMsg>, moved: NodeId, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
356
+ /**
357
+ * The op a keyboard move-up (`-1`) / move-down (`+1`) becomes: the node
358
+ * swapped with the sibling `delta` positions away, stated as the FULL sibling
359
+ * id order (which is what `ReorderChildren` requires — a partial list is
360
+ * refused by the apply engine, and rightly, since a partial order is not one).
361
+ */
362
+ declare const nudgeOp: <TMsg>(root: Node<TMsg>, nodeId: NodeId, delta: number) => Result<TreeOp<TMsg>, PlaceError>;
363
+ /**
364
+ * Duplicate the subtree rooted at `source` and place the clone at `target`,
365
+ * minting replacement ids with `freshIds`. The emitted op is an ordinary
366
+ * placed insert — the clone is a fresh subtree, so the standard apply gate
367
+ * (including the tree-wide duplicate-id check) accepts it unchanged.
368
+ */
369
+ declare const duplicateOpWith: <TMsg>(freshIds: FreshIds, root: Node<TMsg>, source: NodeId, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
370
+ /** `duplicateOpWith` under the default derived-suffix id strategy. */
371
+ declare const duplicateOp: <TMsg>(root: Node<TMsg>, source: NodeId, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
372
+ /**
373
+ * Place a subtree lifted from a DIFFERENT tree into `targetRoot`, remapping
374
+ * any id that collides with one already present (ids with no collision are
375
+ * preserved). The incoming subtree's ids must be unique within itself — a
376
+ * subtree extracted from any well-formed tree is.
377
+ */
378
+ declare const pasteOpWith: <TMsg>(freshIds: FreshIds, targetRoot: Node<TMsg>, incoming: Node<TMsg>, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
379
+ /** `pasteOpWith` under the default derived-suffix id strategy. */
380
+ declare const pasteOp: <TMsg>(targetRoot: Node<TMsg>, incoming: Node<TMsg>, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
381
+
200
382
  /** The result envelope captured on a DAG record (closed shape). */
201
383
  type DagResultEnvelope = {
202
384
  readonly $type: 'Success';
@@ -547,4 +729,4 @@ declare const decodeElicitationOutcome: (json: string) => Result<ElicitationOutc
547
729
  */
548
730
  declare const validateAnswerDocument: (json: string) => Result<undefined, ElicitationError>;
549
731
 
550
- export { type Answer, type AnswerContract, type AnswerField, type AnswerSpace, type AnswerValue, type ApplyError, type ApplyErrorCode, type ApplyResult, type Compatibility, type DagOpRecord, type DagResultEnvelope, type DecodeError, type DecodeErrorCode, type Decoded, ELICITATION_KEY, ELICITATION_VERSION, type ElicitationEnvelope, type ElicitationError, type ElicitationErrorCode, type ElicitationOutcome, type ElicitationOutcomeEnvelope, type Envelope, type EnvelopeError, type EnvelopeErrorCode, type EvalEnv, type JsonAst, type MergeConflict, type MergeResult, type OpApplyTelemetryRecord, PAYLOAD_KEY, PROFILE_KEY, type ParseError, type Profile, REQUIRED_PROFILE_KEY, type SourceResolver, type TreeOp, type UnknownKind, apply, cellString, coerce, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, merge3Way, negotiate, negotiateEnvelope, noResolve, parse, pipelineParams, reencodeNode, renderAstCanonical, renderProfile, stepParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument };
732
+ export { type Answer, type AnswerContract, type AnswerField, type AnswerSpace, type AnswerValue, type ApplyError, type ApplyErrorCode, type ApplyResult, type Compatibility, type DagOpRecord, type DagResultEnvelope, type DecodeError, type DecodeErrorCode, type Decoded, ELICITATION_KEY, ELICITATION_VERSION, type ElicitationEnvelope, type ElicitationError, type ElicitationErrorCode, type ElicitationOutcome, type ElicitationOutcomeEnvelope, type Envelope, type EnvelopeError, type EnvelopeErrorCode, type EvalEnv, type FreshIds, type JsonAst, type MergeConflict, type MergeResult, type OpApplyTelemetryRecord, PAYLOAD_KEY, PROFILE_KEY, type ParseError, type PlaceError, type PlaceTarget, type Placement, type Profile, REQUIRED_PROFILE_KEY, type SourceResolver, type TreeOp, type UnknownKind, apply, canPlace, cellString, coerce, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, derivedFreshIds, duplicateOp, duplicateOpWith, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, liveValueToTable, merge3Way, moveOp, negotiate, negotiateEnvelope, noResolve, nudgeOp, parse, pasteOp, pasteOpWith, pipelineParams, placeOp, reencodeNode, renderAstCanonical, renderProfile, sequentialFreshIds, stepParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Result, NodeId, NodeKind, JsonValue, Binding, SemanticStyle, StateBehaviour, Node, Cell, ColExpr, DataSource, Transform, EvalError, Table, TextSource, CellFormat, ColumnWidth, Orientation, ToneVariant, StyleWeight, Emphasis, HeadingVariant, BadgeVariant, IconSource } from '@fuaran-ui/schema';
1
+ import { Result, NodeId, NodeKind, JsonValue, Binding, SemanticStyle, StateBehaviour, Node, Cell, ColExpr, DataSource, Transform, EvalError, Table, TextSource, CellFormat, ColumnWidth, Orientation, ToneVariant, StyleWeight, Emphasis, HeadingVariant, BadgeVariant, IconSource, IconSize } from '@fuaran-ui/schema';
2
2
 
3
3
  /** Local JSON AST. Shape-for-shape port of the F# decoder's private `Json` DU. */
4
4
  type JsonAst = {
@@ -142,6 +142,22 @@ interface DecodeError {
142
142
  readonly expectedShape?: string;
143
143
  }
144
144
  type R<T> = Result<T, DecodeError>;
145
+ /**
146
+ * Phase 818 — materialise a LIVE Transform source's resolved store value as the
147
+ * evaluation input table: row-major rows transpose through the same 815
148
+ * normalisation the decode-time snapshot used, then decode through the
149
+ * columnar codec (schema inference included). `ok: false` for any value that
150
+ * cannot be read as data — callers surface that loudly, never silently
151
+ * (the Phase-427 mismatch posture). Exported for the renderers' shared
152
+ * `evalTransformFrame` live leg.
153
+ */
154
+ declare const liveValueToTable: (v: unknown) => {
155
+ readonly ok: true;
156
+ readonly value: Table;
157
+ } | {
158
+ readonly ok: false;
159
+ readonly error: string;
160
+ };
145
161
  /** Typed-value coercers for `TreeOp.UpdateProp` (used by the apply engine). */
146
162
  declare const coerce: {
147
163
  int: (v: JsonValue) => Result<number, string>;
@@ -168,6 +184,10 @@ declare const coerce: {
168
184
  headingVariant: (v: JsonValue) => Result<HeadingVariant, string>;
169
185
  badgeVariant: (v: JsonValue) => Result<BadgeVariant, string>;
170
186
  iconSource: (v: JsonValue) => Result<IconSource, string>;
187
+ /** `Icon.Size : IconSize` (Phase 821) — the UpdateProp twin of `decodeIconSize`,
188
+ * added with the standalone Icon display kind. */
189
+ iconSize: (v: JsonValue) => Result<IconSize, string>;
190
+ stringOption: (v: JsonValue) => Result<string | undefined, string>;
171
191
  };
172
192
  /** Decode a canonical-JSON `Node` payload into the storage-shape `Node<unknown>`. */
173
193
  declare const decodeNode: (json: string) => R<Node<unknown>>;
@@ -197,6 +217,168 @@ type ApplyResult<TMsg> = Result<{
197
217
  */
198
218
  declare const apply: <TMsg>(tree: Node<TMsg>, op: TreeOp<TMsg>) => ApplyResult<TMsg>;
199
219
 
220
+ /**
221
+ * Where a node should sit among its destination siblings, stated the only way
222
+ * the op vocabulary allows: by naming an existing sibling, or an end.
223
+ */
224
+ type Placement =
225
+ /** Append — what `InsertChild` / `MoveNode` do on their own. */
226
+ {
227
+ readonly kind: 'Last';
228
+ }
229
+ /** Prepend — before every current sibling. */
230
+ | {
231
+ readonly kind: 'First';
232
+ }
233
+ /** Immediately before the named sibling. */
234
+ | {
235
+ readonly kind: 'Before';
236
+ readonly anchor: NodeId;
237
+ }
238
+ /** Immediately after the named sibling. */
239
+ | {
240
+ readonly kind: 'After';
241
+ readonly anchor: NodeId;
242
+ };
243
+ /** A structural destination: which parent, and where among its children. */
244
+ interface PlaceTarget {
245
+ readonly parentId: NodeId;
246
+ readonly placement: Placement;
247
+ }
248
+ /**
249
+ * Why a placement could not become an op. Each case is a pre-statement of the
250
+ * apply-time refusal the emitted op would have met, so a helper rejection and
251
+ * an apply rejection agree — no false permit, no false refuse.
252
+ */
253
+ type PlaceError =
254
+ /** The destination parent is not in the tree (apply: `ParentNotFound`). */
255
+ {
256
+ readonly kind: 'ParentNotFound';
257
+ readonly parentId: NodeId;
258
+ }
259
+ /** The destination parent's kind has no children field (apply: `ChildlessKind`). */
260
+ | {
261
+ readonly kind: 'ChildlessKind';
262
+ readonly parentId: NodeId;
263
+ }
264
+ /**
265
+ * The node to move / nudge / duplicate is not structurally addressable
266
+ * (absent, or held in a non-structural position the structural ops cannot
267
+ * reach) — apply: `NodeNotFound`.
268
+ */
269
+ | {
270
+ readonly kind: 'NodeNotFound';
271
+ readonly nodeId: NodeId;
272
+ }
273
+ /**
274
+ * The placement anchor is not among the destination's post-op children. The
275
+ * only op that could honour it — a `ReorderChildren` naming it — is refused
276
+ * by the apply engine as `OrderingMismatch`.
277
+ */
278
+ | {
279
+ readonly kind: 'UnknownAnchor';
280
+ readonly anchor: NodeId;
281
+ }
282
+ /**
283
+ * The subtree being inserted carries an id already present in the tree
284
+ * (apply: `DuplicateNodeId`).
285
+ */
286
+ | {
287
+ readonly kind: 'DuplicateId';
288
+ readonly nodeId: NodeId;
289
+ }
290
+ /** The node would become its own parent (apply: `KindMismatch`). */
291
+ | {
292
+ readonly kind: 'MoveIntoSelf';
293
+ readonly nodeId: NodeId;
294
+ }
295
+ /**
296
+ * The destination sits inside the node's own subtree — a cycle (apply:
297
+ * `KindMismatch`).
298
+ */
299
+ | {
300
+ readonly kind: 'MoveIntoDescendant';
301
+ readonly nodeId: NodeId;
302
+ readonly parentId: NodeId;
303
+ }
304
+ /** The root has no siblings to nudge among. */
305
+ | {
306
+ readonly kind: 'CannotNudgeRoot';
307
+ readonly nodeId: NodeId;
308
+ }
309
+ /** The nudge would leave the sibling range (already first / already last). */
310
+ | {
311
+ readonly kind: 'NudgeOutOfRange';
312
+ readonly nodeId: NodeId;
313
+ readonly delta: number;
314
+ };
315
+ /**
316
+ * How the clone verbs mint replacement ids: given the id being replaced and a
317
+ * predicate over every id already claimed (the whole target tree, the whole
318
+ * incoming subtree, and ids minted earlier in the same remap), return an id
319
+ * the predicate refuses. Injectable so a host with its own id discipline can
320
+ * supply it; `derivedFreshIds` is the default.
321
+ */
322
+ type FreshIds = (oldId: string, taken: (candidate: string) => boolean) => string;
323
+ /**
324
+ * The default strategy: `<oldId>-copy`, then `<oldId>-copy-2`, `-copy-3`, … —
325
+ * the first candidate not already taken. Deterministic (derived from the id it
326
+ * replaces, no ambient state) and collision-free by probing.
327
+ */
328
+ declare const derivedFreshIds: FreshIds;
329
+ /**
330
+ * Sequential ids under a fixed prefix (`<prefix>-1`, `-2`, …) — the
331
+ * deterministic-replay option: the minted sequence depends only on the prefix
332
+ * and the order of requests, never on the ids being replaced. Each call to
333
+ * `sequentialFreshIds` starts its own counter.
334
+ */
335
+ declare const sequentialFreshIds: (prefix: string) => FreshIds;
336
+ /**
337
+ * Whether `moved` may legally take up residence at `target` — the pre-check an
338
+ * editor uses to grey out an illegal drop without a dry-run apply. Mirrors the
339
+ * apply engine's rejections: absent node, move into itself, move into its own
340
+ * descendant (a cycle), absent or childless destination, unknown anchor.
341
+ */
342
+ declare const canPlace: <TMsg>(root: Node<TMsg>, moved: NodeId, target: PlaceTarget) => Result<void, PlaceError>;
343
+ /**
344
+ * The op an insertion becomes. `InsertChild` appends, so the wanted order is
345
+ * computed over the post-insert membership and stated by `ReorderChildren`
346
+ * naming every sibling id; the reorder leg is dropped when appending already
347
+ * produces that order.
348
+ */
349
+ declare const placeOp: <TMsg>(root: Node<TMsg>, child: Node<TMsg>, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
350
+ /**
351
+ * The op a move becomes. `MoveNode` appends under the new parent, and the node
352
+ * may already be one of that parent's children (a re-placement within one
353
+ * parent), so the post-move membership is the siblings WITHOUT it plus it.
354
+ */
355
+ declare const moveOp: <TMsg>(root: Node<TMsg>, moved: NodeId, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
356
+ /**
357
+ * The op a keyboard move-up (`-1`) / move-down (`+1`) becomes: the node
358
+ * swapped with the sibling `delta` positions away, stated as the FULL sibling
359
+ * id order (which is what `ReorderChildren` requires — a partial list is
360
+ * refused by the apply engine, and rightly, since a partial order is not one).
361
+ */
362
+ declare const nudgeOp: <TMsg>(root: Node<TMsg>, nodeId: NodeId, delta: number) => Result<TreeOp<TMsg>, PlaceError>;
363
+ /**
364
+ * Duplicate the subtree rooted at `source` and place the clone at `target`,
365
+ * minting replacement ids with `freshIds`. The emitted op is an ordinary
366
+ * placed insert — the clone is a fresh subtree, so the standard apply gate
367
+ * (including the tree-wide duplicate-id check) accepts it unchanged.
368
+ */
369
+ declare const duplicateOpWith: <TMsg>(freshIds: FreshIds, root: Node<TMsg>, source: NodeId, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
370
+ /** `duplicateOpWith` under the default derived-suffix id strategy. */
371
+ declare const duplicateOp: <TMsg>(root: Node<TMsg>, source: NodeId, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
372
+ /**
373
+ * Place a subtree lifted from a DIFFERENT tree into `targetRoot`, remapping
374
+ * any id that collides with one already present (ids with no collision are
375
+ * preserved). The incoming subtree's ids must be unique within itself — a
376
+ * subtree extracted from any well-formed tree is.
377
+ */
378
+ declare const pasteOpWith: <TMsg>(freshIds: FreshIds, targetRoot: Node<TMsg>, incoming: Node<TMsg>, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
379
+ /** `pasteOpWith` under the default derived-suffix id strategy. */
380
+ declare const pasteOp: <TMsg>(targetRoot: Node<TMsg>, incoming: Node<TMsg>, target: PlaceTarget) => Result<TreeOp<TMsg>, PlaceError>;
381
+
200
382
  /** The result envelope captured on a DAG record (closed shape). */
201
383
  type DagResultEnvelope = {
202
384
  readonly $type: 'Success';
@@ -547,4 +729,4 @@ declare const decodeElicitationOutcome: (json: string) => Result<ElicitationOutc
547
729
  */
548
730
  declare const validateAnswerDocument: (json: string) => Result<undefined, ElicitationError>;
549
731
 
550
- export { type Answer, type AnswerContract, type AnswerField, type AnswerSpace, type AnswerValue, type ApplyError, type ApplyErrorCode, type ApplyResult, type Compatibility, type DagOpRecord, type DagResultEnvelope, type DecodeError, type DecodeErrorCode, type Decoded, ELICITATION_KEY, ELICITATION_VERSION, type ElicitationEnvelope, type ElicitationError, type ElicitationErrorCode, type ElicitationOutcome, type ElicitationOutcomeEnvelope, type Envelope, type EnvelopeError, type EnvelopeErrorCode, type EvalEnv, type JsonAst, type MergeConflict, type MergeResult, type OpApplyTelemetryRecord, PAYLOAD_KEY, PROFILE_KEY, type ParseError, type Profile, REQUIRED_PROFILE_KEY, type SourceResolver, type TreeOp, type UnknownKind, apply, cellString, coerce, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, merge3Way, negotiate, negotiateEnvelope, noResolve, parse, pipelineParams, reencodeNode, renderAstCanonical, renderProfile, stepParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument };
732
+ export { type Answer, type AnswerContract, type AnswerField, type AnswerSpace, type AnswerValue, type ApplyError, type ApplyErrorCode, type ApplyResult, type Compatibility, type DagOpRecord, type DagResultEnvelope, type DecodeError, type DecodeErrorCode, type Decoded, ELICITATION_KEY, ELICITATION_VERSION, type ElicitationEnvelope, type ElicitationError, type ElicitationErrorCode, type ElicitationOutcome, type ElicitationOutcomeEnvelope, type Envelope, type EnvelopeError, type EnvelopeErrorCode, type EvalEnv, type FreshIds, type JsonAst, type MergeConflict, type MergeResult, type OpApplyTelemetryRecord, PAYLOAD_KEY, PROFILE_KEY, type ParseError, type PlaceError, type PlaceTarget, type Placement, type Profile, REQUIRED_PROFILE_KEY, type SourceResolver, type TreeOp, type UnknownKind, apply, canPlace, cellString, coerce, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, derivedFreshIds, duplicateOp, duplicateOpWith, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, liveValueToTable, merge3Way, moveOp, negotiate, negotiateEnvelope, noResolve, nudgeOp, parse, pasteOp, pasteOpWith, pipelineParams, placeOp, reencodeNode, renderAstCanonical, renderProfile, sequentialFreshIds, stepParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument };