@archie/devtools 0.0.26 → 0.0.27

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.
@@ -0,0 +1,577 @@
1
+ // node_modules/tsup/assets/esm_shims.js
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+ var getFilename = () => fileURLToPath(import.meta.url);
5
+ var getDirname = () => path.dirname(getFilename());
6
+ var __dirname = /* @__PURE__ */ getDirname();
7
+
8
+ // src/babel-plugin-editor-meta.ts
9
+ import * as nodePath from "path";
10
+ function meaningfulChildren(t, children) {
11
+ return children.filter((child) => {
12
+ if (t.isJSXText(child)) return child.value.trim() !== "";
13
+ if (t.isJSXExpressionContainer(child)) return !t.isJSXEmptyExpression(child.expression);
14
+ return true;
15
+ });
16
+ }
17
+ var KIT_SLOT_ATTR = "data-kit-slot";
18
+ var MAX_SLOT_SEGMENTS = 4;
19
+ var NON_BINDING_ATTRS = /* @__PURE__ */ new Set(["__editorMeta", "key", "ref", KIT_SLOT_ATTR]);
20
+ var STRUCTURAL_ATTRS = /* @__PURE__ */ new Set([
21
+ "id",
22
+ "htmlFor",
23
+ "slot",
24
+ "name",
25
+ "type",
26
+ "role",
27
+ // The camelCase carrier of the SAME durable key as `data-agent-id`: kit
28
+ // components take `agentId` and render it as the data attribute. Found on the
29
+ // real corpus (×4) — blocking only the dashed form would have left the prop
30
+ // form routable, and a durable key with a string-literal usage value sails
31
+ // straight through the usage-value law.
32
+ "agentId"
33
+ ]);
34
+ function isNonContentAttribute(name) {
35
+ if (/^on[A-Z]/.test(name)) return true;
36
+ if (name.startsWith("data-")) return true;
37
+ return STRUCTURAL_ATTRS.has(name);
38
+ }
39
+ function normalizeSlot(raw) {
40
+ const value = raw.trim();
41
+ if (!value) return null;
42
+ const segments = value.split("/");
43
+ if (segments.length > MAX_SLOT_SEGMENTS) return null;
44
+ if (segments.some((segment) => segment.trim() === "")) return null;
45
+ return value;
46
+ }
47
+ function isPackageImport(src) {
48
+ if (src.startsWith(".") || src.startsWith("/")) return false;
49
+ if (src.startsWith("@")) {
50
+ const slashIdx = src.indexOf("/");
51
+ if (slashIdx === 1) return false;
52
+ if (slashIdx > 1) return true;
53
+ return true;
54
+ }
55
+ if (src.startsWith("~/") || src.startsWith("#/")) return false;
56
+ return true;
57
+ }
58
+ function babelPluginEditorMeta({ types: t }, opts = {}) {
59
+ const {
60
+ fileExclude = /node_modules/,
61
+ instrumentImported = true,
62
+ includeHostSourceRef = false,
63
+ origin = "screen"
64
+ } = opts;
65
+ function getJSXTagName(el) {
66
+ const { name } = el;
67
+ if (t.isJSXIdentifier(name)) return name.name;
68
+ if (t.isJSXMemberExpression(name)) {
69
+ const parts = [];
70
+ let current = name;
71
+ while (t.isJSXMemberExpression(current)) {
72
+ parts.unshift(current.property.name);
73
+ current = current.object;
74
+ }
75
+ if (t.isJSXIdentifier(current)) parts.unshift(current.name);
76
+ return parts.join(".");
77
+ }
78
+ return "";
79
+ }
80
+ function isHostLikeMemberExpressionName(name) {
81
+ if (!t.isJSXMemberExpression(name)) return false;
82
+ const propertyName = name.property.name;
83
+ return propertyName[0] === propertyName[0].toLowerCase();
84
+ }
85
+ function computeNodeId(file, line, col, componentName) {
86
+ return `${file}:${line}:${col}:${componentName}`;
87
+ }
88
+ function isMovable(path2) {
89
+ const elPath = path2.parentPath;
90
+ if (!elPath) return false;
91
+ const parentEl = elPath.parentPath;
92
+ if (!parentEl || !parentEl.isJSXElement()) return false;
93
+ const siblings = parentEl.node.children.filter(
94
+ (c) => t.isJSXElement(c)
95
+ );
96
+ return siblings.length >= 2;
97
+ }
98
+ function getParentNodeId(path2, file) {
99
+ const elPath = path2.parentPath;
100
+ if (!elPath) return null;
101
+ let ancestor = elPath.parentPath;
102
+ while (ancestor) {
103
+ if (ancestor.isJSXElement()) {
104
+ const opening = ancestor.node.openingElement;
105
+ const loc = opening.loc?.start;
106
+ if (loc) {
107
+ const tag = getJSXTagName(opening);
108
+ return computeNodeId(file, loc.line, loc.column + 1, tag);
109
+ }
110
+ return null;
111
+ }
112
+ ancestor = ancestor.parentPath;
113
+ }
114
+ return null;
115
+ }
116
+ function extractStaticProps(attrs) {
117
+ const props = [];
118
+ let hasAny = false;
119
+ for (const attr of attrs) {
120
+ if (t.isJSXSpreadAttribute(attr)) continue;
121
+ if (!t.isJSXAttribute(attr)) continue;
122
+ const keyName = t.isJSXIdentifier(attr.name) ? attr.name.name : attr.name.name.name;
123
+ if (keyName === "__editorMeta") continue;
124
+ let value;
125
+ if (attr.value === null || attr.value === void 0) {
126
+ value = t.booleanLiteral(true);
127
+ } else if (t.isStringLiteral(attr.value)) {
128
+ value = attr.value;
129
+ } else if (t.isJSXExpressionContainer(attr.value)) {
130
+ const expr = attr.value.expression;
131
+ if (t.isNumericLiteral(expr)) {
132
+ value = expr;
133
+ } else if (t.isBooleanLiteral(expr)) {
134
+ value = expr;
135
+ } else if (t.isNullLiteral(expr)) {
136
+ value = expr;
137
+ } else if (t.isStringLiteral(expr)) {
138
+ value = expr;
139
+ } else {
140
+ value = t.stringLiteral("__dynamic__");
141
+ }
142
+ } else {
143
+ continue;
144
+ }
145
+ props.push(t.objectProperty(t.stringLiteral(keyName), value));
146
+ hasAny = true;
147
+ }
148
+ return hasAny ? t.objectExpression(props) : null;
149
+ }
150
+ function isMetaStripSpreadExpression(arg) {
151
+ if (!t.isCallExpression(arg)) return false;
152
+ if (!t.isArrowFunctionExpression(arg.callee)) return false;
153
+ const [firstParam] = arg.callee.params;
154
+ if (!firstParam || !t.isObjectPattern(firstParam)) return false;
155
+ return firstParam.properties.some((prop) => {
156
+ if (!t.isObjectProperty(prop)) return false;
157
+ if (!t.isIdentifier(prop.key)) return false;
158
+ return prop.key.name === "__editorMeta";
159
+ });
160
+ }
161
+ function hasTruthyAsChildProp(attrs) {
162
+ for (const attr of attrs) {
163
+ if (!t.isJSXAttribute(attr) || !t.isJSXIdentifier(attr.name, { name: "asChild" })) {
164
+ continue;
165
+ }
166
+ if (attr.value == null) return true;
167
+ if (t.isJSXExpressionContainer(attr.value)) {
168
+ const expr = attr.value.expression;
169
+ if (t.isBooleanLiteral(expr)) return expr.value;
170
+ }
171
+ if (t.isStringLiteral(attr.value)) return attr.value.value !== "false";
172
+ return true;
173
+ }
174
+ return false;
175
+ }
176
+ function buildPayloadFilter(payload) {
177
+ return t.callExpression(
178
+ t.arrowFunctionExpression(
179
+ [
180
+ t.objectPattern([
181
+ t.objectProperty(
182
+ t.identifier("__editorMeta"),
183
+ t.identifier("_$em"),
184
+ false,
185
+ false
186
+ ),
187
+ t.objectProperty(
188
+ t.stringLiteral(KIT_SLOT_ATTR),
189
+ t.identifier("_$ks"),
190
+ false,
191
+ false
192
+ ),
193
+ t.restElement(t.identifier("_$r"))
194
+ ])
195
+ ],
196
+ t.identifier("_$r")
197
+ ),
198
+ [t.objectExpression([t.spreadElement(payload)])]
199
+ );
200
+ }
201
+ function sanitizeSpreadAttributes(attrs) {
202
+ for (const attr of attrs) {
203
+ if (!t.isJSXSpreadAttribute(attr)) continue;
204
+ if (isMetaStripSpreadExpression(attr.argument)) continue;
205
+ attr.argument = buildPayloadFilter(attr.argument);
206
+ }
207
+ }
208
+ function consumeKitSlot(attrs) {
209
+ let slot = null;
210
+ let found = false;
211
+ for (const attr of attrs) {
212
+ if (!t.isJSXAttribute(attr)) continue;
213
+ if (!t.isJSXIdentifier(attr.name, { name: KIT_SLOT_ATTR })) continue;
214
+ found = true;
215
+ if (slot !== null) continue;
216
+ const { value } = attr;
217
+ if (t.isStringLiteral(value)) {
218
+ slot = normalizeSlot(value.value);
219
+ } else if (t.isJSXExpressionContainer(value) && t.isStringLiteral(value.expression)) {
220
+ slot = normalizeSlot(value.expression.value);
221
+ }
222
+ }
223
+ if (!found) return { slot: null, found: false, attrs };
224
+ return {
225
+ slot,
226
+ found: true,
227
+ attrs: attrs.filter(
228
+ (attr) => !(t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name, { name: KIT_SLOT_ATTR }))
229
+ )
230
+ };
231
+ }
232
+ function getFunctionName(fn) {
233
+ const node = fn.node;
234
+ if (t.isFunctionDeclaration(node) && node.id) return node.id.name;
235
+ if (t.isFunctionExpression(node) && node.id) return node.id.name;
236
+ const parent = fn.parentPath;
237
+ if (parent?.isVariableDeclarator() && t.isIdentifier(parent.node.id)) {
238
+ return parent.node.id.name;
239
+ }
240
+ return null;
241
+ }
242
+ function buildPropMap(pattern) {
243
+ const map = /* @__PURE__ */ new Map();
244
+ for (const prop of pattern.properties) {
245
+ if (!t.isObjectProperty(prop) || prop.computed) continue;
246
+ const key = t.isIdentifier(prop.key) ? prop.key.name : t.isStringLiteral(prop.key) ? prop.key.value : null;
247
+ if (!key) continue;
248
+ const value = prop.value;
249
+ if (t.isIdentifier(value)) {
250
+ map.set(value.name, key);
251
+ } else if (t.isAssignmentPattern(value) && t.isIdentifier(value.left)) {
252
+ map.set(value.left.name, key);
253
+ }
254
+ }
255
+ return map;
256
+ }
257
+ function resolvePropContext(path2) {
258
+ let fn = path2.getFunctionParent();
259
+ while (fn) {
260
+ const [first] = fn.node.params;
261
+ if (first && t.isObjectPattern(first) && fn.scope.parent === fn.scope.getProgramParent()) {
262
+ return {
263
+ componentScope: fn.scope,
264
+ propMap: buildPropMap(first),
265
+ componentName: getFunctionName(fn)
266
+ };
267
+ }
268
+ fn = fn.getFunctionParent();
269
+ }
270
+ return null;
271
+ }
272
+ function resolveProp(name, scope, ctx) {
273
+ const prop = ctx.propMap.get(name);
274
+ if (!prop) return null;
275
+ const binding = scope.getBinding(name);
276
+ if (!binding) return null;
277
+ if (binding.scope !== ctx.componentScope) return null;
278
+ if (!binding.constant) return null;
279
+ return prop;
280
+ }
281
+ function isScopeWithinComponent(scope, ctx) {
282
+ let current = scope;
283
+ while (current) {
284
+ if (current === ctx.componentScope) return true;
285
+ current = current.parent;
286
+ }
287
+ return false;
288
+ }
289
+ function resolveLocalConstInit(name, scope, ctx) {
290
+ const binding = scope.getBinding(name);
291
+ if (!binding) return null;
292
+ if (!binding.constant) return null;
293
+ const declarator = binding.path;
294
+ if (!declarator.isVariableDeclarator()) return null;
295
+ if (!isScopeWithinComponent(binding.scope, ctx)) return null;
296
+ const init = declarator.node.init;
297
+ if (!init || !t.isExpression(init)) return null;
298
+ return { init, scope: declarator.scope };
299
+ }
300
+ function isStaticStringLiteral(node) {
301
+ if (t.isStringLiteral(node)) return true;
302
+ return t.isTemplateLiteral(node) && node.expressions.length === 0;
303
+ }
304
+ function collectPropIdentifiers(node, scope, ctx, out = []) {
305
+ if (!node) return out;
306
+ const visit = (child) => collectPropIdentifiers(child, scope, ctx, out);
307
+ if (t.isIdentifier(node)) {
308
+ const prop = resolveProp(node.name, scope, ctx);
309
+ if (prop && !out.includes(prop)) out.push(prop);
310
+ return out;
311
+ }
312
+ if (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) {
313
+ visit(node.object);
314
+ if (node.computed) visit(node.property);
315
+ return out;
316
+ }
317
+ if (t.isCallExpression(node) || t.isOptionalCallExpression(node)) {
318
+ visit(node.callee);
319
+ node.arguments.forEach((arg) => visit(arg));
320
+ return out;
321
+ }
322
+ if (t.isTemplateLiteral(node)) {
323
+ node.expressions.forEach((expr) => visit(expr));
324
+ return out;
325
+ }
326
+ if (t.isConditionalExpression(node)) {
327
+ visit(node.test);
328
+ visit(node.consequent);
329
+ visit(node.alternate);
330
+ return out;
331
+ }
332
+ if (t.isLogicalExpression(node) || t.isBinaryExpression(node)) {
333
+ visit(node.left);
334
+ visit(node.right);
335
+ return out;
336
+ }
337
+ if (t.isUnaryExpression(node) || t.isAwaitExpression(node)) {
338
+ visit(node.argument);
339
+ return out;
340
+ }
341
+ if (t.isArrayExpression(node)) {
342
+ node.elements.forEach((el) => visit(el));
343
+ return out;
344
+ }
345
+ if (t.isObjectExpression(node)) {
346
+ for (const prop of node.properties) {
347
+ if (t.isObjectProperty(prop)) {
348
+ if (prop.computed) visit(prop.key);
349
+ visit(prop.value);
350
+ } else if (t.isSpreadElement(prop)) {
351
+ visit(prop.argument);
352
+ }
353
+ }
354
+ return out;
355
+ }
356
+ if (t.isSpreadElement(node)) {
357
+ visit(node.argument);
358
+ return out;
359
+ }
360
+ if (t.isTSAsExpression(node) || t.isTSNonNullExpression(node) || t.isTypeCastExpression(node)) {
361
+ visit(node.expression);
362
+ return out;
363
+ }
364
+ return out;
365
+ }
366
+ function classifyExpression(expr, scope, ctx, hop) {
367
+ if (t.isIdentifier(expr)) {
368
+ const prop = resolveProp(expr.name, scope, ctx);
369
+ if (prop) return { kind: "direct", prop };
370
+ if (hop > 0) return null;
371
+ const local = resolveLocalConstInit(expr.name, scope, ctx);
372
+ if (!local) return null;
373
+ const inner = classifyExpression(local.init, local.scope, ctx, hop + 1);
374
+ if (!inner) return null;
375
+ return { kind: inner.kind === "formatted" ? "formatted" : "derived", prop: inner.prop };
376
+ }
377
+ if (t.isLogicalExpression(expr) && (expr.operator === "||" || expr.operator === "??") && isStaticStringLiteral(expr.right)) {
378
+ const left = classifyExpression(expr.left, scope, ctx, hop);
379
+ if (!left) return null;
380
+ return { kind: left.kind === "formatted" ? "formatted" : "derived", prop: left.prop };
381
+ }
382
+ const props = collectPropIdentifiers(expr, scope, ctx);
383
+ return props.length > 0 ? { kind: "formatted", prop: props[0] } : null;
384
+ }
385
+ function collectPropBindings(path2, attrs) {
386
+ const ctx = resolvePropContext(path2);
387
+ if (!ctx || ctx.propMap.size === 0) return { bindings: [], owner: null };
388
+ if (ctx.componentName === null) return { bindings: [], owner: null };
389
+ const scope = path2.scope;
390
+ const bindings = [];
391
+ const elementPath = path2.parentPath;
392
+ if (elementPath && elementPath.isJSXElement()) {
393
+ const children = meaningfulChildren(t, elementPath.node.children);
394
+ const isSoleChild = children.length === 1;
395
+ for (const child of children) {
396
+ if (!t.isJSXExpressionContainer(child)) continue;
397
+ const expression = child.expression;
398
+ if (t.isJSXEmptyExpression(expression)) continue;
399
+ const verdict = classifyExpression(expression, scope, ctx, 0);
400
+ if (!verdict) continue;
401
+ bindings.push({
402
+ target: "children",
403
+ prop: verdict.prop,
404
+ kind: isSoleChild ? verdict.kind : "formatted"
405
+ });
406
+ }
407
+ }
408
+ for (const attr of attrs) {
409
+ if (!t.isJSXAttribute(attr)) continue;
410
+ const name = t.isJSXIdentifier(attr.name) ? attr.name.name : `${attr.name.namespace.name}:${attr.name.name.name}`;
411
+ if (NON_BINDING_ATTRS.has(name)) continue;
412
+ const value = attr.value;
413
+ if (!t.isJSXExpressionContainer(value)) continue;
414
+ const expression = value.expression;
415
+ if (t.isJSXEmptyExpression(expression)) continue;
416
+ const verdict = classifyExpression(expression, scope, ctx, 0);
417
+ if (!verdict) continue;
418
+ bindings.push({
419
+ target: `attr:${name}`,
420
+ prop: verdict.prop,
421
+ // M2b: machine-contract attributes are reported, never offered.
422
+ kind: isNonContentAttribute(name) ? "formatted" : verdict.kind
423
+ });
424
+ }
425
+ return { bindings, owner: bindings.length > 0 ? ctx.componentName : null };
426
+ }
427
+ function propBindingsToAst(bindings) {
428
+ return t.arrayExpression(
429
+ bindings.map(
430
+ (binding) => t.objectExpression([
431
+ t.objectProperty(t.identifier("target"), t.stringLiteral(binding.target)),
432
+ t.objectProperty(t.identifier("prop"), t.stringLiteral(binding.prop)),
433
+ t.objectProperty(t.identifier("kind"), t.stringLiteral(binding.kind))
434
+ ])
435
+ )
436
+ );
437
+ }
438
+ return {
439
+ name: "babel-plugin-editor-meta",
440
+ visitor: {
441
+ CallExpression(path2, state) {
442
+ const filename = state.filename ?? "";
443
+ if (fileExclude.test(filename)) return;
444
+ const callee = path2.node.callee;
445
+ let isCreateElement = false;
446
+ let isCloneElement = false;
447
+ if (t.isIdentifier(callee, { name: "createElement" })) {
448
+ isCreateElement = true;
449
+ } else if (t.isMemberExpression(callee) && t.isIdentifier(callee.property, { name: "createElement" })) {
450
+ isCreateElement = true;
451
+ } else if (t.isIdentifier(callee, { name: "cloneElement" })) {
452
+ isCloneElement = true;
453
+ } else if (t.isMemberExpression(callee) && t.isIdentifier(callee.property, { name: "cloneElement" })) {
454
+ isCloneElement = true;
455
+ }
456
+ if (!isCreateElement && !isCloneElement) return;
457
+ const args = path2.node.arguments;
458
+ if (args.length < 2) return;
459
+ if (isCreateElement && !t.isStringLiteral(args[0])) return;
460
+ const propsArg = args[1];
461
+ if (!propsArg || t.isNullLiteral(propsArg)) return;
462
+ if (!t.isExpression(propsArg)) return;
463
+ if (isMetaStripSpreadExpression(propsArg)) return;
464
+ args[1] = buildPayloadFilter(propsArg);
465
+ },
466
+ JSXOpeningElement(path2, state) {
467
+ const consumed = consumeKitSlot(path2.node.attributes);
468
+ path2.node.attributes = consumed.attrs;
469
+ const slot = consumed.slot;
470
+ const hasSlotAttr = consumed.found;
471
+ const filename = state.filename ?? "";
472
+ if (fileExclude.test(filename)) return;
473
+ const existing = path2.node.attributes.find(
474
+ (a) => t.isJSXAttribute(a) && t.isJSXIdentifier(a.name, { name: "__editorMeta" })
475
+ );
476
+ if (existing) return;
477
+ const loc = path2.node.loc?.start;
478
+ if (!loc) return;
479
+ const root = state.file.opts.root ?? "";
480
+ const file = root ? nodePath.relative(root, filename) : filename;
481
+ const line = loc.line;
482
+ const col = loc.column + 1;
483
+ const componentName = getJSXTagName(path2.node);
484
+ if (!componentName) return;
485
+ const isHostLikeMemberExpression = isHostLikeMemberExpressionName(path2.node.name);
486
+ const isHostElement = componentName[0] === componentName[0].toLowerCase();
487
+ sanitizeSpreadAttributes(path2.node.attributes);
488
+ if (hasTruthyAsChildProp(path2.node.attributes)) {
489
+ return;
490
+ }
491
+ let rootName = null;
492
+ if (t.isJSXIdentifier(path2.node.name)) {
493
+ rootName = path2.node.name.name;
494
+ } else if (t.isJSXMemberExpression(path2.node.name)) {
495
+ let cur = path2.node.name;
496
+ while (t.isJSXMemberExpression(cur)) cur = cur.object;
497
+ if (t.isJSXIdentifier(cur)) rootName = cur.name;
498
+ }
499
+ if (rootName) {
500
+ const binding = path2.scope.getBinding(rootName);
501
+ if (binding) {
502
+ const bp = binding.path;
503
+ if (bp.isImportSpecifier() || bp.isImportDefaultSpecifier() || bp.isImportNamespaceSpecifier()) {
504
+ if (!instrumentImported) return;
505
+ const decl = bp.parentPath;
506
+ if (decl?.isImportDeclaration()) {
507
+ const src = decl.node.source.value;
508
+ if (isPackageImport(src) && !isHostLikeMemberExpression) return;
509
+ }
510
+ }
511
+ const programScope = path2.scope.getProgramParent();
512
+ if (binding.scope !== programScope) return;
513
+ }
514
+ }
515
+ const nodeId = computeNodeId(file, line, col, componentName);
516
+ const isKitOrigin = origin === "kit" || hasSlotAttr;
517
+ const movable = isKitOrigin ? false : isMovable(path2);
518
+ const parentNodeId = getParentNodeId(path2, file);
519
+ const staticPropsObj = extractStaticProps(path2.node.attributes);
520
+ const { bindings, owner } = collectPropBindings(path2, path2.node.attributes);
521
+ const metaObj = t.objectExpression([
522
+ t.objectProperty(t.identifier("nodeId"), t.stringLiteral(nodeId)),
523
+ t.objectProperty(t.identifier("file"), t.stringLiteral(file)),
524
+ t.objectProperty(t.identifier("line"), t.numericLiteral(line)),
525
+ t.objectProperty(t.identifier("col"), t.numericLiteral(col)),
526
+ t.objectProperty(t.identifier("componentName"), t.stringLiteral(componentName)),
527
+ t.objectProperty(
528
+ t.identifier("staticProps"),
529
+ staticPropsObj ?? t.nullLiteral()
530
+ ),
531
+ t.objectProperty(t.identifier("movable"), t.booleanLiteral(movable)),
532
+ t.objectProperty(
533
+ t.identifier("parentNodeId"),
534
+ parentNodeId ? t.stringLiteral(parentNodeId) : t.nullLiteral()
535
+ )
536
+ ]);
537
+ if (slot !== null) {
538
+ metaObj.properties.push(
539
+ t.objectProperty(t.identifier("slot"), t.stringLiteral(slot))
540
+ );
541
+ }
542
+ if (bindings.length > 0) {
543
+ metaObj.properties.push(
544
+ t.objectProperty(t.identifier("propBindings"), propBindingsToAst(bindings))
545
+ );
546
+ metaObj.properties.push(
547
+ t.objectProperty(
548
+ t.identifier("propOwner"),
549
+ owner ? t.stringLiteral(owner) : t.nullLiteral()
550
+ )
551
+ );
552
+ }
553
+ if (isHostElement && includeHostSourceRef) {
554
+ path2.node.attributes.push(
555
+ t.jsxAttribute(
556
+ t.jsxIdentifier("data-archie-source-ref"),
557
+ t.stringLiteral(`${file}::${line}::${col}`)
558
+ )
559
+ );
560
+ }
561
+ const metaThunk = t.arrowFunctionExpression([], metaObj);
562
+ path2.node.attributes.push(
563
+ t.jsxAttribute(
564
+ t.jsxIdentifier("__editorMeta"),
565
+ t.jsxExpressionContainer(metaThunk)
566
+ )
567
+ );
568
+ }
569
+ }
570
+ };
571
+ }
572
+
573
+ export {
574
+ __dirname,
575
+ meaningfulChildren,
576
+ babelPluginEditorMeta
577
+ };
@@ -4098,6 +4098,19 @@ function dispatchRuntimeEvent(detail) {
4098
4098
  if (typeof window === "undefined") return;
4099
4099
  window.dispatchEvent(new CustomEvent(DND_RUNTIME_EVENT, { detail }));
4100
4100
  }
4101
+ function resolveRowBinding(el) {
4102
+ let node = el;
4103
+ for (let depth = 0; node && depth < MAX_ROW_BINDING_ANCESTOR_DEPTH; depth += 1) {
4104
+ const rowId = node.getAttribute("data-agent-row");
4105
+ if (rowId !== null && rowId !== "") {
4106
+ const entity = node.getAttribute("data-agent-entity");
4107
+ return entity ? { entity, rowId } : null;
4108
+ }
4109
+ node = node.parentElement;
4110
+ }
4111
+ return null;
4112
+ }
4113
+ var MAX_ROW_BINDING_ANCESTOR_DEPTH = 12;
4101
4114
  function mergeInspectorTheme(theme) {
4102
4115
  return {
4103
4116
  ...DEFAULT_INSPECTOR_THEME,
@@ -4484,16 +4497,6 @@ function createCommitLaneIdentitySnapshot(params) {
4484
4497
  committable: true
4485
4498
  };
4486
4499
  }
4487
- function hasSafeOccurrenceIdentities(lane, duplicateNodeKey) {
4488
- const effectiveNodeIds = lane.commitNodeIds.filter(
4489
- (commitNodeId) => lane.nodeKeysByCommitNodeId.get(commitNodeId) === duplicateNodeKey
4490
- ).map(
4491
- (commitNodeId) => lane.effectiveNodeIdsByCommitNodeId.get(commitNodeId) ?? null
4492
- );
4493
- return effectiveNodeIds.length > 1 && effectiveNodeIds.every(
4494
- (effectiveNodeId) => typeof effectiveNodeId === "string" && effectiveNodeId.length > 0
4495
- ) && new Set(effectiveNodeIds).size === effectiveNodeIds.length;
4496
- }
4497
4500
  function buildLanePersistenceDiagnostics(params) {
4498
4501
  const duplicateNodeKeys = detectDuplicateSourceBackedNodeKeys(
4499
4502
  buildNodeKeysFromCommitIds(
@@ -4504,24 +4507,10 @@ function buildLanePersistenceDiagnostics(params) {
4504
4507
  if (duplicateNodeKeys.length === 0) {
4505
4508
  return null;
4506
4509
  }
4507
- const safeDuplicateNodeKeys = duplicateNodeKeys.filter(
4508
- (nodeKey) => hasSafeOccurrenceIdentities(params.lane, nodeKey)
4509
- );
4510
- if (safeDuplicateNodeKeys.length === duplicateNodeKeys.length) {
4511
- return {
4512
- notes: safeDuplicateNodeKeys.map(
4513
- (nodeKey) => `Arrange lane ${params.lane.laneContainerId} repeats source-backed nodeKey ${nodeKey}, but runtime assigned explicit occurrence identities for each commit root.`
4514
- )
4515
- };
4516
- }
4517
4510
  return {
4518
- structurallyUnsafe: true,
4519
- blockedReasons: duplicateNodeKeys.map(
4520
- (nodeKey) => `Arrange lane ${params.lane.laneContainerId} contains multiple commit roots with the same source-backed nodeKey (${nodeKey}), so local save is unsafe.`
4521
- ),
4522
- notes: [
4523
- `Lane ${params.lane.laneContainerId} duplicates source-backed nodeKeys: ${duplicateNodeKeys.join(", ")}`
4524
- ]
4511
+ notes: duplicateNodeKeys.map(
4512
+ (nodeKey) => `Arrange lane ${params.lane.laneContainerId} repeats source-backed nodeKey ${nodeKey}, but runtime assigned explicit occurrence identities for each commit root.`
4513
+ )
4525
4514
  };
4526
4515
  }
4527
4516
  function removeCommitNodeId(commitNodeIds, commitNodeId) {
@@ -4736,6 +4725,7 @@ var useDesignModeStore = create((set, get) => ({
4736
4725
  beforeSibling,
4737
4726
  afterSibling,
4738
4727
  diagnostics,
4728
+ binding,
4739
4729
  componentName,
4740
4730
  before,
4741
4731
  after
@@ -4762,6 +4752,7 @@ var useDesignModeStore = create((set, get) => ({
4762
4752
  beforeSibling: beforeSibling ?? null,
4763
4753
  afterSibling: afterSibling ?? null,
4764
4754
  diagnostics: diagnostics ?? null,
4755
+ binding: binding ?? null,
4765
4756
  payload: { before, after },
4766
4757
  at: now
4767
4758
  };
@@ -6451,6 +6442,8 @@ function serializeArrangeChange(event, index) {
6451
6442
  sourceBeforeSibling: event.kind === "move" ? event.sourceBeforeSibling : void 0,
6452
6443
  sourceAfterSibling: event.kind === "move" ? event.sourceAfterSibling : void 0,
6453
6444
  diagnostics: event.kind === "move" ? event.diagnostics : void 0,
6445
+ // ARCH-1065 D17 — which slice row this move addresses.
6446
+ binding: event.kind === "move" ? event.binding : void 0,
6454
6447
  // Insert-specific fields
6455
6448
  displayName: event.kind === "insert" ? event.displayName : void 0,
6456
6449
  html: event.kind === "insert" ? event.html : void 0,
@@ -7981,6 +7974,7 @@ function recordCommittedMove(args) {
7981
7974
  });
7982
7975
  const componentName = getEditorMeta(anchorEl)?.componentName;
7983
7976
  const operationId = `${command.at}:${anchorNodeId}`;
7977
+ const binding = resolveRowBinding(selectedEl);
7984
7978
  const beforePayload = buildMovePayloadWithEffectiveIdentities({
7985
7979
  placement: command.from,
7986
7980
  containerIdentity: sourceContainerIdentity,
@@ -8010,6 +8004,7 @@ function recordCommittedMove(args) {
8010
8004
  sourceBeforeSibling: sourceBeforeSiblingIdentity,
8011
8005
  sourceAfterSibling: sourceAfterSiblingIdentity,
8012
8006
  diagnostics,
8007
+ binding,
8013
8008
  container: containerIdentity,
8014
8009
  beforeSibling: beforeSiblingIdentity,
8015
8010
  afterSibling: afterSiblingIdentity,