← ACE Carousel CreatorCONTENT HISTORY

Update to ACE Carousel Creator

Snapshot Nov 6, 2026 · 00:15 UTC · version 0.2.0

WHAT CHANGED

Package or technical metadata updated

Package or technical metadata updated

Observed in package metadata. These changes alone do not establish a new customer-facing feature.

Save ACE Carousel Creator and check future changes in Following.

Up to 3 plugins free · no card required.

All fields and original values.

These are saved file metadata. Open a changed file to read its text edits.

Package file

Before

Oct 24, 2026 · 13:48 UTC

Not present

After

Nov 6, 2026 · 00:15 UTC

{"sha256":"5f2025d9087cd8dc93ebe395791fda81379d9a438862e6e87a69b5faf4cc2b77","size":47}

Package file

Before

Oct 24, 2026 · 13:48 UTC

Not present

After

Nov 6, 2026 · 00:15 UTC

{"sha256":"fd48d4fdbb81718d2dfbffa6314dee7c56d042aa5dd96d34d45ee3b38ba91e49","size":315}

Package file

Before

Oct 24, 2026 · 13:48 UTC

Not present

After

Nov 6, 2026 · 00:15 UTC

{"sha256":"29942ea87db4340c9a272091ada1b037d8b8b02a2e76dce75509cb8a1e418059","size":2313}

Package file

Before

Oct 24, 2026 · 13:48 UTC

Not present

After

Nov 6, 2026 · 00:15 UTC

{"sha256":"2014b20842e56188734f68b1490b3cbb5a8dd5365993de5a9935fdc353ff30fc","size":1112}

Compare saved observations

Download comparison JSON

src/diagnostics.mjs

− removed · + added

--- before
+++ after
@@ -0,0 +1,98 @@
+import { resourceMaps } from './catalog.mjs';
+import { ratioAspects } from './recipes.mjs';
+
+const EPS = 1e-6;
+const near = (a, b, tolerance = 0.002) => Math.abs(a - b) <= tolerance;
+const intersects = (a, b) => a && b && Math.min(a.right, b.right) - Math.max(a.left, b.left) > EPS && Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top) > EPS;
+
+/** Conservative world-space bounds in slide-width units, including rotation. Text needs real font metrics. */
+export function layerBounds(kind, layer, ratio) {
+  const aspect = ratioAspects[ratio];
+  let w, h;
+  if (kind === 'text') return null;
+  if (kind === 'frame') {
+    const entry = resourceMaps.frames.get(layer.preset);
+    if (!entry) return null;
+    w = layer.width; h = w * entry.pixels[1] / entry.pixels[0];
+  } else if (layer.size) { w = layer.size[0]; h = layer.size[1] / aspect; }
+  else return null;
+  const angle = (layer.rotate ?? 0) * Math.PI / 180;
+  const bw = Math.abs(w * Math.cos(angle)) + Math.abs(h * Math.sin(angle));
+  const bh = Math.abs(w * Math.sin(angle)) + Math.abs(h * Math.cos(angle));
+  const extra = kind === 'shape' ? layer.stroke?.width ?? 0 : 0;
+  const x = layer.slide - 1 + layer.at[0], y = layer.at[1] / aspect;
+  return { left: x - bw / 2 - extra, right: x + bw / 2 + extra, top: y - bh / 2 - extra, bottom: y + bh / 2 + extra };
+}
+
+export function diagnoseDocument(document) {
+  const warnings = [], usage = {}, maxWarnings = 100;
+  let omitted = 0;
+  const add = (code, path, slide, message, suggestion) => {
+    if (warnings.length === maxWarnings) { omitted++; return; }
+    warnings.push({ code, severity: 'warning', path, slide, message, suggestion });
+  };
+  const rows = document.layers.map((wrapper, index) => {
+    const [kind, layer] = Object.entries(wrapper)[0];
+    usage[kind] = (usage[kind] ?? 0) + 1;
+    return { kind, layer, index, bounds: layerBounds(kind, layer, document.ratio) };
+  });
+  const aspect = ratioAspects[document.ratio];
+  const imageGroups = new Map();
+  for (const row of rows) {
+    const { kind, layer: p, index, bounds } = row, path = `layers.${index}.${kind}`;
+    if (kind === 'image') {
+      if (p.border && !['FFFFFF', '1F1F1F'].includes(p.border.color.toUpperCase())) add('IMAGE_BORDER_COLOR_LOSS', path + '.border.color', p.slide, 'ACE saves only a white or dark image border; this color will change.', 'Use FFFFFF/1F1F1F, a suitable grid mat, or keep an intentional colored shape backing.');
+      const back = rows[index - 1];
+      if (back?.kind === 'shape') {
+        const s = back.layer;
+        const dx = (s.size[0] - p.size[0]) / 2, dy = (s.size[1] - p.size[1]) / (2 * aspect);
+        if (s.kind === 'rectangle' && ['FFFFFF', '1F1F1F'].includes(s.fill?.toUpperCase()) && !s.shadow && !s.gradient && !s.stroke && !s.blendMode && (s.opacity ?? 1) === 1 && s.slide === p.slide && s.at.every((v, i) => near(v, p.at[i])) && near(s.rotate ?? 0, p.rotate ?? 0) && dx > EPS && dx < 0.06 && near(dx, dy) && !p.border && !p.corner) {
+          add('POSSIBLE_NATIVE_IMAGE_BORDER', path, p.slide, 'A uniform white/dark rectangle directly behind this photo resembles a photo border.', 'Consider image.border if it preserves the intended geometry; retain the backing when independently editable decoration is intended.');
+        }
+      }
+      if (!(p.rotate ?? 0) && !(p.opacity !== undefined && p.opacity !== 1) && !p.blend && !p.blendMode && !p.border && !p.corner) {
+        const group = imageGroups.get(p.slide) ?? [];
+        group.push(row); imageGroups.set(p.slide, group);
+      }
+    }
+    if (kind === 'grid') {
+      for (let i = 0; i < p.cells.length; i++) for (let j = i + 1; j < p.cells.length; j++) {
+        const rect = cell => { const [x,y,w,h] = cell.rect; return { left:x, right:x+w, top:y, bottom:y+h }; };
+        if (intersects(rect(p.cells[i]), rect(p.cells[j]))) { add('OVERLAPPING_GRID_CELLS', path + '.cells', p.slide, `Cells ${i} and ${j} overlap before gutters.`, 'Check the recipe coordinates; keep intentional overlap if it is part of the composition.'); i = p.cells.length; break; }
+      }
+    }
+    if (kind === 'mask' || kind === 'blender') {
+      // Operators apply to groups on a continuous strip. Different home slides can still overlap.
+      const lower = rows.slice(0, index).filter(r => !['mask','blender'].includes(r.kind));
+      const upper = rows.slice(index + 1).filter(r => !['mask','blender'].includes(r.kind));
+      const canReach = group => group.some(r => r.kind === 'text' || intersects(bounds, r.bounds));
+      if (!canReach(lower) || !canReach(upper)) add('EFFECT_OPERANDS_OUTSIDE_REGION', path, p.slide, 'At least one side of this operator has no content bounds intersecting its region.', 'Inspect the operator region and layer order in ACE. Text bounds and actual mask pixels need native rendering.');
+    }
+    if (bounds && !intersects(bounds, {left:0,right:document.slides,top:0,bottom:1/aspect})) add('OUTSIDE_CAROUSEL', path, p.slide, 'This layer bounds is outside the whole carousel strip.', 'Check global geometry; preserve an intentional off-canvas layer.');
+    if (kind === 'shape' && p.kind === 'rectangle' && p.fill?.toUpperCase() === document.background.toUpperCase() && !p.gradient && !p.stroke && !p.shadow) {
+      const back = rows[index - 1];
+      if (back?.kind === 'shape') {
+        const s = back.layer;
+        if (s.kind === 'rectangle' && s.fill && !s.gradient && !s.stroke && !s.shadow && s.slide === p.slide && near(s.rotate ?? 0, p.rotate ?? 0) && s.at.every((v,i) => near(v,p.at[i])) && s.size.every((v,i) => v > p.size[i] && v < p.size[i] * 1.25)) add('POSSIBLE_SHAPE_OUTLINE', path, p.slide, 'Two filled rectangles may be simulating an outline by covering the center.', 'Consider one shape with fill:null and stroke; do not replace if the inner fill intentionally hides other content.');
+      }
+    }
+  }
+  // Detect complete regular galleries only; unrelated photos and free collages remain valid.
+  for (const [slide, photos] of imageGroups) {
+    if (photos.length < 3 || photos.length > 16) continue;
+    const [first] = photos;
+    if (!photos.every(r => r.layer.size.every((v,i) => near(v, first.layer.size[i])))) continue;
+    const unique = values => values.toSorted((a,b) => a-b).filter((v,i,all) => i === 0 || !near(v,all[i-1]));
+    const xs = unique(photos.map(r => r.layer.at[0])), ys = unique(photos.map(r => r.layer.at[1]));
+    const evenlySpaced = values => values.length < 3 || values.slice(2).every((v,i) => near(v-values[i+1],values[1]-values[0]));
+    if (xs.length * ys.length !== photos.length || !evenlySpaced(xs) || !evenlySpaced(ys)) continue;
+    const occupied = new Set(photos.map(r => xs.findIndex(x=>near(x,r.layer.at[0])) + ':' + ys.findIndex(y=>near(y,r.layer.at[1]))));
+    if (occupied.size !== photos.length || photos.some((a,i) => photos.slice(i+1).some(b => intersects(a.bounds,b.bounds)))) continue;
+    add('POSSIBLE_NATIVE_GRID', `layers.${first.index}.image`, slide, `${photos.length} equal-size aligned photos form a regular gallery.`, 'Consider a native grid for shared spacing and photo replacement. Check gutter units and preserve independent photo treatment when intended.');
+  }
+  for (let slide = 1; slide <= document.slides; slide++) {
+    const region = { left:slide-1, right:slide, top:0, bottom:1/aspect };
+    if (!rows.some(r => r.kind === 'text' ? r.layer.slide === slide : intersects(r.bounds,region))) add('NO_PLACED_CONTENT', 'layers', slide, 'No sized layer intersects this slide and no text is anchored here.', 'Check whether the blank slide is intentional. Cross-slide text needs actual font measurement.');
+  }
+  return { warnings, omitted_warnings: omitted, layer_usage: usage, checks: { structure: 'passed', semantics: 'heuristic', text_measurement: 'not performed', visual_check: 'not performed' } };
+}
Full technical diff · 55 changed fields

added /files/.dockerignore

BEFORE
Field was absent
AFTER
{
  "sha256": "5f2025d9087cd8dc93ebe395791fda81379d9a438862e6e87a69b5faf4cc2b77",
  "size": 47
}

added /files/Dockerfile

BEFORE
Field was absent
AFTER
{
  "sha256": "fd48d4fdbb81718d2dfbffa6314dee7c56d042aa5dd96d34d45ee3b38ba91e49",
  "size": 315
}

added /files/LICENSE

BEFORE
Field was absent
AFTER
{
  "sha256": "29942ea87db4340c9a272091ada1b037d8b8b02a2e76dce75509cb8a1e418059",
  "size": 2313
}

added /files/README.md

BEFORE
Field was absent
AFTER
{
  "sha256": "2014b20842e56188734f68b1490b3cbb5a8dd5365993de5a9935fdc353ff30fc",
  "size": 1112
}

added /files/data~1catalog.json

BEFORE
Field was absent
AFTER
{
  "sha256": "93dcbf982d26c83ffef1134e7dd95115ce7337cd741ff963f27310becb4fff88",
  "size": 425901
}

added /files/data~1examples.json

BEFORE
Field was absent
AFTER
{
  "sha256": "9300369fb5b6ed73beb1db3352df1c6fb08e7c891589f6cb4e834beac9ecf124",
  "size": 3675
}

added /files/examples~1contact-gallery.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "31383e1bfa7f27aaf6b8d5fd6c450ec039e4be05390398b27341c2d82670733f",
  "size": 1626
}

added /files/examples~1effects-study.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "709a9449fa409ef272e58f07764eb2661961888a41329284a9b9aaf4fec1796c",
  "size": 1210
}

added /files/examples~1free-collage.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "82e9ea3801309187184a41c6a0490d4af1fa792abca303f462ae9d1a0a9b48a0",
  "size": 1139
}

added /files/examples~1photo-story.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "10b1f45fe3eab32b55740bfb3526831a23374ae41120ff05fead7a8761fd9d47",
  "size": 1060
}

added /files/examples~1smart-stamp.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "b039ec2ed3e17f9c1757f4380f7abe5ce366bb71d06153e087053cf0f21ae019",
  "size": 914
}

added /files/examples~1type-led.yaml

BEFORE
Field was absent
AFTER
{
  "sha256": "4220649308cf1b1b3418409b1d880b516df55e3e81dd87a9a44b3226b63d55da",
  "size": 1200
}

added /files/native~1RendererApp.swift

BEFORE
Field was absent
AFTER
{
  "sha256": "90f7699ffa9b44cb1263dbfebab1f0c1062ebf934cb97a4e718cc577fc66539c",
  "size": 4434
}

changed /files/package-lock.json/sha256

BEFORE
"ad8658df058ed6e12856e442e18591e49ee0dae7af722e8482940b43fa6d0432"
AFTER
"1ff211f79a56954cb9b076c2eeedd85b56a361584f8205f11b84764f4f4fdf75"

changed /files/package.json/sha256

BEFORE
"2d43a17f4b9852e8cea13f32c903536b8fc8132607045a72d1f3c710c8de3efc"
AFTER
"ea3ade412901851f814ecda42c8a32e00e72052bba153bc76f5ff515a30be224"

changed /files/package.json/size

BEFORE
503
AFTER
908

changed /files/plugin.json/sha256

BEFORE
"9171fcb956c5e86ca839303912e290b0db31660efcd7017698fb540d21bd9ba5"
AFTER
"8cdbe9970f20ed8120bd20a37b5e1c0604b48aa49e099bd00920e372734e2566"

changed /files/plugin.json/size

BEFORE
11337
AFTER
10022

changed /files/scripts~1build-carousel.mjs/sha256

BEFORE
"0ec532932ce99c8e02f0f2b57730efd590f17b5c822c18ccb35aaaf43f0dab3f"
AFTER
"8496a1368be3dbf2ef9245f449ac7a5158dec37184fa30c638ed127e663e65b2"

changed /files/scripts~1build-carousel.mjs/size

BEFORE
1161
AFTER
1184

added /files/scripts~1check-server.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "42674a0f1e3797f36247f0093dae0cba1d4b8c407690bd929902d881605767ff",
  "size": 4394
}

added /files/scripts~1get-spec.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "771b4044e7bb24fa563b169e8c1880b41709c76c35c5778279004b47f85861d9",
  "size": 311
}

changed /files/scripts~1package-plugin.mjs/sha256

BEFORE
"698df0d5de5c1a076b100f47f0e00705467a85b77d31b9fae15e5bc36ebb7fa8"
AFTER
"7df454a476fa80d28753c85541082b193a6b0aa1156bbadc3b80e7a3783ce7a3"

changed /files/scripts~1package-plugin.mjs/size

BEFORE
5594
AFTER
6810

added /files/scripts~1render-carousel.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "ae7b739231767f5e17dd7957c179bbdc617fe9d4718437967733df67ad031537",
  "size": 1450
}

added /files/scripts~1setup-native-renderer.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "f18984ec4a2fa0587d737db082e4cfa33ea09adda828b4cce915bc61b812d8a6",
  "size": 4180
}

added /files/scripts~1sync-catalog.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "315dccd2343306cef52dedbd87798d495f5b0c5ad9e66bdeb9e56bc4e692fae8",
  "size": 626
}

changed /files/skills~1create-carousel~1SKILL.md/sha256

BEFORE
"9151fb427fee5e69f407c0f1e2ee2f33d77d2b0cc99f4f6409730ad62cd6de25"
AFTER
"0d4c5ec38abdeeae533cdd8985685be4c0f532a0637f95767d2b999e605fa9e7"

changed /files/skills~1create-carousel~1SKILL.md/size

BEFORE
3939
AFTER
10609

added /files/skills~1create-carousel~1references~1DESIGN_GUIDE.md

BEFORE
Field was absent
AFTER
{
  "sha256": "2ffd410e74f7028499999a3373315b076c5b1cea0930664fe14726810fc1b618",
  "size": 4266
}

changed /files/skills~1create-carousel~1references~1DSL_LAYOUT_SPEC.md/sha256

BEFORE
"1278b5f6f81afe42e29433479c5c102e3f75ae16eb93e23dd0eb2a70a15125d1"
AFTER
"3394ff0ae25f338c282c55fe53dc580ae2c596b62f09da77f24452a5724e6cb0"

changed /files/skills~1create-carousel~1references~1DSL_LAYOUT_SPEC.md/size

BEFORE
212874
AFTER
218069

added /files/skills~1create-carousel~1references~1WRITING_GUIDE.md

BEFORE
Field was absent
AFTER
{
  "sha256": "fcf68ef35f4e3a858d3d6236e4f3dd182fd52b018c24cd663d257ed1b4a2f477",
  "size": 5902
}

changed /files/src~1archive.mjs/sha256

BEFORE
"a7c8b4ed23371010e755a3898f926f6bed4d2dd5d257d4a7c98a3041a048b46d"
AFTER
"f082bea90b8ff5e2655cccd7044bff2248d551e8989c734ee24ce4a8b14b64e9"

changed /files/src~1archive.mjs/size

BEFORE
2908
AFTER
3498

added /files/src~1catalog.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "41e0108752aff449b825d15a46808ccdbc43649ba4998143118dca4b3e6ca962",
  "size": 6068
}

added /files/src~1diagnostics.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "a620e5631de644ab4a5586127c4612a94695152202b26145336f1d8cf70cacd5",
  "size": 7803
}

changed /files/src~1document.mjs/sha256

BEFORE
"a38e271507e7b55fb606ad619d907a6836ecdce8dafd502b8f042d155d3a6f7c"
AFTER
"97a4868aafefe954717d9058d5d910639076613b8e157f80f2f47c42db8c46ec"

changed /files/src~1document.mjs/size

BEFORE
13586
AFTER
12413

added /files/src~1errors.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "d1f236c2bff72432b73e3aa27ad675ee1038c80ccf8b457fbb4f717898061660",
  "size": 44
}

added /files/src~1recipes.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "660b575c97fc2ee70c0668c482d8f949185cf748acc7caee62b739fc44bbdcd1",
  "size": 4103
}

added /files/src~1renderer.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "44b8f9cad2feabe0b99cce1e8a6a6e830b8788ad8112b58c0444eedf720720da",
  "size": 7706
}

changed /files/src~1server.mjs/sha256

BEFORE
"711db8dfd4f596dcf673d6edd728f96ebc6177fb05284310b40748ffb3777679"
AFTER
"67a96be7fcf04f603c900ce5151b73943c671f7cdbe65e82ef1be6d494008ca4"

changed /files/src~1server.mjs/size

BEFORE
10916
AFTER
23198

added /files/src~1spec.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "2564a2e59d6abbc363d6622741e0c47e0958013bde2472295b8b4586d2858fcf",
  "size": 4491
}

changed /files/tests~1carousel.test.mjs/sha256

BEFORE
"d006e3346166652fa2104ebe75ec621f545255cd58924f86f4f922065dcac398"
AFTER
"3d2bef07c979ebb12149442ecc81704d5ead4822ec58bea2d43a64c8b15db026"

changed /files/tests~1carousel.test.mjs/size

BEFORE
8150
AFTER
8364

added /files/tests~1diagnostics.test.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "b3baa3352b4a57b38e13e674ec4a96f6a7d8547b251f2a1f6474327773a46cd8",
  "size": 5280
}

added /files/tests~1discovery.test.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "d6b7f4e6447e9d398b1b88feead7644d6f29be721a9175d8a29fcdb40e9cec75",
  "size": 8147
}

changed /files/tests~1http.integration.mjs/sha256

BEFORE
"f77721afd3db1659dda0874702326c703b627185729fb2f462c1ec3dd94aa166"
AFTER
"d2f14621194cf28139f2e04dd77df988d7423f6c0b2b070e9e231796c383d7ae"

changed /files/tests~1http.integration.mjs/size

BEFORE
2053
AFTER
2995

added /files/tests~1native.integration.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "37bc67dd03fa1931a1a52c9ee0860a3b9e056619d0f8a735ee029ac3ae33412d",
  "size": 7909
}

added /files/tests~1package.test.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "c7d100facf765bd64763a2825e65a2a2f662f94fc5ded114f524aabf039b11c9",
  "size": 2933
}

added /files/tests~1preview.test.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "a3b1c7317dc71d4d065156a89014b131b997e7c0c06203b8b4deac0d24fe9c89",
  "size": 5386
}

added /files/tests~1uploads.test.mjs

BEFORE
Field was absent
AFTER
{
  "sha256": "3e7dc647b2c2268e0c4cd71e119af9531079aced921011a081d1d5a7448d323b",
  "size": 6352
}
Full snapshot data
{
  "files": {
    ".app.json": {
      "sha256": "5e21add253e73f295f8dd9638efdad6133db89cea1afc6eb8bef86fcd9dc9d29",
      "size": 108
    },
    ".dockerignore": {
      "sha256": "5f2025d9087cd8dc93ebe395791fda81379d9a438862e6e87a69b5faf4cc2b77",
      "size": 47
    },
    "Dockerfile": {
      "sha256": "fd48d4fdbb81718d2dfbffa6314dee7c56d042aa5dd96d34d45ee3b38ba91e49",
      "size": 315
    },
    "LICENSE": {
      "sha256": "29942ea87db4340c9a272091ada1b037d8b8b02a2e76dce75509cb8a1e418059",
      "size": 2313
    },
    "README.md": {
      "sha256": "2014b20842e56188734f68b1490b3cbb5a8dd5365993de5a9935fdc353ff30fc",
      "size": 1112
    },
    "assets/icon.png": {
      "sha256": "6dfad6349d9c99ac11613f4abbe19fe6e608f89357e0c2ff87abf7079072cb83",
      "size": 31011
    },
    "data/catalog.json": {
      "sha256": "93dcbf982d26c83ffef1134e7dd95115ce7337cd741ff963f27310becb4fff88",
      "size": 425901
    },
    "data/examples.json": {
      "sha256": "9300369fb5b6ed73beb1db3352df1c6fb08e7c891589f6cb4e834beac9ecf124",
      "size": 3675
    },
    "examples/contact-gallery.yaml": {
      "sha256": "31383e1bfa7f27aaf6b8d5fd6c450ec039e4be05390398b27341c2d82670733f",
      "size": 1626
    },
    "examples/creator-demo-preview.png": {
      "sha256": "72f9bdd64e2f4bbbeee007d645a75ea38e90713f99079c5fbafe74f8c3ea306c",
      "size": 69512
    },
    "examples/creator-demo.carousel": {
      "sha256": "4a16b05ee1c671d4e57d58136058838c15b542456f55d0e25df92941f9a64465",
      "size": 5679
    },
    "examples/creator-demo.yaml": {
      "sha256": "ac375143bd9958012deed3c38cb84c212a585c40a96c051f5503df17b74f642a",
      "size": 3908
    },
    "examples/effects-study.yaml": {
      "sha256": "709a9449fa409ef272e58f07764eb2661961888a41329284a9b9aaf4fec1796c",
      "size": 1210
    },
    "examples/free-collage.yaml": {
      "sha256": "82e9ea3801309187184a41c6a0490d4af1fa792abca303f462ae9d1a0a9b48a0",
      "size": 1139
    },
    "examples/photo-story.yaml": {
      "sha256": "10b1f45fe3eab32b55740bfb3526831a23374ae41120ff05fead7a8761fd9d47",
      "size": 1060
    },
    "examples/smart-stamp.yaml": {
      "sha256": "b039ec2ed3e17f9c1757f4380f7abe5ce366bb71d06153e087053cf0f21ae019",
      "size": 914
    },
    "examples/type-led.yaml": {
      "sha256": "4220649308cf1b1b3418409b1d880b516df55e3e81dd87a9a44b3226b63d55da",
      "size": 1200
    },
    "mcp.json": {
      "sha256": "828f2d5c8663ded2b9b701aa0fd0f0848bd1fbd865c1e8a170bb1b13148e7ccb",
      "size": 210
    },
    "native/RendererApp.swift": {
      "sha256": "90f7699ffa9b44cb1263dbfebab1f0c1062ebf934cb97a4e718cc577fc66539c",
      "size": 4434
    },
    "package-lock.json": {
      "sha256": "1ff211f79a56954cb9b076c2eeedd85b56a361584f8205f11b84764f4f4fdf75",
      "size": 61504
    },
    "package.json": {
      "sha256": "ea3ade412901851f814ecda42c8a32e00e72052bba153bc76f5ff515a30be224",
      "size": 908
    },
    "plugin.json": {
      "sha256": "8cdbe9970f20ed8120bd20a37b5e1c0604b48aa49e099bd00920e372734e2566",
      "size": 10022
    },
    "scripts/build-carousel.mjs": {
      "sha256": "8496a1368be3dbf2ef9245f449ac7a5158dec37184fa30c638ed127e663e65b2",
      "size": 1184
    },
    "scripts/check-server.mjs": {
      "sha256": "42674a0f1e3797f36247f0093dae0cba1d4b8c407690bd929902d881605767ff",
      "size": 4394
    },
    "scripts/get-spec.mjs": {
      "sha256": "771b4044e7bb24fa563b169e8c1880b41709c76c35c5778279004b47f85861d9",
      "size": 311
    },
    "scripts/package-plugin.mjs": {
      "sha256": "7df454a476fa80d28753c85541082b193a6b0aa1156bbadc3b80e7a3783ce7a3",
      "size": 6810
    },
    "scripts/render-carousel.mjs": {
      "sha256": "ae7b739231767f5e17dd7957c179bbdc617fe9d4718437967733df67ad031537",
      "size": 1450
    },
    "scripts/setup-native-renderer.mjs": {
      "sha256": "f18984ec4a2fa0587d737db082e4cfa33ea09adda828b4cce915bc61b812d8a6",
      "size": 4180
    },
    "scripts/sync-catalog.mjs": {
      "sha256": "315dccd2343306cef52dedbd87798d495f5b0c5ad9e66bdeb9e56bc4e692fae8",
      "size": 626
    },
    "skills/create-carousel/SKILL.md": {
      "sha256": "0d4c5ec38abdeeae533cdd8985685be4c0f532a0637f95767d2b999e605fa9e7",
      "size": 10609
    },
    "skills/create-carousel/references/DESIGN_GUIDE.md": {
      "sha256": "2ffd410e74f7028499999a3373315b076c5b1cea0930664fe14726810fc1b618",
      "size": 4266
    },
    "skills/create-carousel/references/DSL_LAYOUT_SPEC.md": {
      "sha256": "3394ff0ae25f338c282c55fe53dc580ae2c596b62f09da77f24452a5724e6cb0",
      "size": 218069
    },
    "skills/create-carousel/references/WRITING_GUIDE.md": {
      "sha256": "fcf68ef35f4e3a858d3d6236e4f3dd182fd52b018c24cd663d257ed1b4a2f477",
      "size": 5902
    },
    "src/archive.mjs": {
      "sha256": "f082bea90b8ff5e2655cccd7044bff2248d551e8989c734ee24ce4a8b14b64e9",
      "size": 3498
    },
    "src/catalog.mjs": {
      "sha256": "41e0108752aff449b825d15a46808ccdbc43649ba4998143118dca4b3e6ca962",
      "size": 6068
    },
    "src/diagnostics.mjs": {
      "sha256": "a620e5631de644ab4a5586127c4612a94695152202b26145336f1d8cf70cacd5",
      "size": 7803
    },
    "src/document.mjs": {
      "sha256": "97a4868aafefe954717d9058d5d910639076613b8e157f80f2f47c42db8c46ec",
      "size": 12413
    },
    "src/errors.mjs": {
      "sha256": "d1f236c2bff72432b73e3aa27ad675ee1038c80ccf8b457fbb4f717898061660",
      "size": 44
    },
    "src/recipes.mjs": {
      "sha256": "660b575c97fc2ee70c0668c482d8f949185cf748acc7caee62b739fc44bbdcd1",
      "size": 4103
    },
    "src/renderer.mjs": {
      "sha256": "44b8f9cad2feabe0b99cce1e8a6a6e830b8788ad8112b58c0444eedf720720da",
      "size": 7706
    },
    "src/server.mjs": {
      "sha256": "67a96be7fcf04f603c900ce5151b73943c671f7cdbe65e82ef1be6d494008ca4",
      "size": 23198
    },
    "src/spec.mjs": {
      "sha256": "2564a2e59d6abbc363d6622741e0c47e0958013bde2472295b8b4586d2858fcf",
      "size": 4491
    },
    "tests/carousel.test.mjs": {
      "sha256": "3d2bef07c979ebb12149442ecc81704d5ead4822ec58bea2d43a64c8b15db026",
      "size": 8364
    },
    "tests/diagnostics.test.mjs": {
      "sha256": "b3baa3352b4a57b38e13e674ec4a96f6a7d8547b251f2a1f6474327773a46cd8",
      "size": 5280
    },
    "tests/discovery.test.mjs": {
      "sha256": "d6b7f4e6447e9d398b1b88feead7644d6f29be721a9175d8a29fcdb40e9cec75",
      "size": 8147
    },
    "tests/http.integration.mjs": {
      "sha256": "d2f14621194cf28139f2e04dd77df988d7423f6c0b2b070e9e231796c383d7ae",
      "size": 2995
    },
    "tests/native.integration.mjs": {
      "sha256": "37bc67dd03fa1931a1a52c9ee0860a3b9e056619d0f8a735ee029ac3ae33412d",
      "size": 7909
    },
    "tests/package.test.mjs": {
      "sha256": "c7d100facf765bd64763a2825e65a2a2f662f94fc5ded114f524aabf039b11c9",
      "size": 2933
    },
    "tests/preview.test.mjs": {
      "sha256": "a3b1c7317dc71d4d065156a89014b131b997e7c0c06203b8b4deac0d24fe9c89",
      "size": 5386
    },
    "tests/uploads.test.mjs": {
      "sha256": "3e7dc647b2c2268e0c4cd71e119af9531079aced921011a081d1d5a7448d323b",
      "size": 6352
    }
  }
}

SHA-256 of public snapshot: 64959cf6937ca474b78ee128969c5afdcb3064e41f5dc2d8e4ef072e2c240fab