m0saic 0.2.1 → 0.3.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.
Files changed (292) hide show
  1. package/LICENSE +22 -7
  2. package/README.md +23 -5
  3. package/dist/browseE2e.js +1 -1
  4. package/dist/connectionsFromEnv.js +1 -1
  5. package/dist/e2eTemplateVariants.js +1 -1
  6. package/dist/frontDoor.js +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/inlineDsl.js +1 -1
  9. package/dist/mcp/bridgeClient.js +1 -0
  10. package/dist/mcp/server.js +1 -0
  11. package/dist/mcp/tools.js +1 -0
  12. package/dist/mosaicxRunner.js +1 -1
  13. package/dist/outputPattern.js +1 -1
  14. package/dist/showcaseFeed.js +1 -1
  15. package/dist/templateDoctor.js +1 -1
  16. package/dist/utils/checkFeasibility.js +1 -1
  17. package/dist/utils/collectRenderErrors.js +1 -1
  18. package/dist/utils/enrichImageAlphaFromDoc.js +1 -1
  19. package/dist/utils/ensureFfmpeg.js +1 -1
  20. package/dist/utils/extractLayoutMeta.js +1 -1
  21. package/dist/utils/failureHints.js +1 -1
  22. package/dist/utils/ffmpegProbe.js +1 -1
  23. package/dist/utils/formatM0saicForCli.js +1 -1
  24. package/dist/utils/hashFile.js +1 -1
  25. package/dist/utils/helpGroups.js +1 -1
  26. package/dist/utils/installContext.js +1 -0
  27. package/dist/utils/invocation.js +1 -1
  28. package/dist/utils/licenseActivation.js +1 -0
  29. package/dist/utils/licenseActivationWorker.js +1 -0
  30. package/dist/utils/mosaicSpinner.js +1 -1
  31. package/dist/utils/parseDimensions.js +1 -1
  32. package/dist/utils/pathInfo.js +1 -1
  33. package/dist/utils/readJsonArg.js +1 -1
  34. package/dist/utils/renderOutcome.js +1 -1
  35. package/dist/utils/renderReport.js +1 -1
  36. package/dist/utils/renderSignals.js +1 -1
  37. package/dist/utils/renderWorkspace.js +1 -1
  38. package/dist/utils/reportOutputFormat.js +1 -0
  39. package/dist/utils/setupFfmpeg.js +1 -1
  40. package/dist/utils/telemetry.js +1 -1
  41. package/dist/utils/telemetryFlushWorker.js +1 -1
  42. package/dist/utils/telemetryUpstream.js +1 -1
  43. package/dist/utils/telemetryUsage.js +1 -1
  44. package/dist/utils/toolchainConfig.js +1 -1
  45. package/dist/utils/tutorialDuration.js +1 -1
  46. package/dist/utils/updateCheck.js +1 -1
  47. package/dist/utils/updateCheckWorker.js +1 -1
  48. package/dist/utils/validateSourceCounts.js +1 -1
  49. package/dist/utils/versions.js +1 -1
  50. package/dist/webCustomizeLink.js +1 -1
  51. package/node_modules/@m0saic/community-m/NOTICE +9 -0
  52. package/node_modules/@m0saic/community-m/release.json +2 -2
  53. package/node_modules/@m0saic/core/dist/core/buildChildMosaicSource.js +1 -1
  54. package/node_modules/@m0saic/core/dist/core/buildChunkCommands.js +1 -1
  55. package/node_modules/@m0saic/core/dist/core/buildEncodeCommands.js +1 -1
  56. package/node_modules/@m0saic/core/dist/core/buildLavfiSource.js +1 -1
  57. package/node_modules/@m0saic/core/dist/core/buildMediaSource.js +1 -1
  58. package/node_modules/@m0saic/core/dist/core/buildMosaicNode.js +1 -1
  59. package/node_modules/@m0saic/core/dist/core/buildMosaicPlanFromFile.js +1 -1
  60. package/node_modules/@m0saic/core/dist/core/buildSvgTextSource.js +1 -1
  61. package/node_modules/@m0saic/core/dist/core/buildTextRenderCommand.js +1 -1
  62. package/node_modules/@m0saic/core/dist/core/collectRefTargets.js +1 -1
  63. package/node_modules/@m0saic/core/dist/core/index.js +1 -1
  64. package/node_modules/@m0saic/core/dist/core/maskCacheDir.js +1 -1
  65. package/node_modules/@m0saic/core/dist/core/maskWorkerBridge.js +1 -1
  66. package/node_modules/@m0saic/core/dist/core/playbackPlaySpeed.js +1 -1
  67. package/node_modules/@m0saic/core/dist/core/prepareProps.js +1 -1
  68. package/node_modules/@m0saic/core/dist/core/primaryOutput.js +1 -1
  69. package/node_modules/@m0saic/core/dist/core/rasterizeMaskPng.js +1 -1
  70. package/node_modules/@m0saic/core/dist/core/rasterizeSvgMediaPng.js +1 -1
  71. package/node_modules/@m0saic/core/dist/core/refTargetTap.js +1 -1
  72. package/node_modules/@m0saic/core/dist/core/resolveMasks.js +1 -1
  73. package/node_modules/@m0saic/core/dist/core/resolveMasksSync.js +1 -1
  74. package/node_modules/@m0saic/core/dist/core/resolveStrokeRingsSync.js +1 -1
  75. package/node_modules/@m0saic/core/dist/core/roundedRectMask.js +1 -1
  76. package/node_modules/@m0saic/core/dist/core/strokeRing.js +1 -1
  77. package/node_modules/@m0saic/core/dist/core/svgRaster.js +1 -1
  78. package/node_modules/@m0saic/core/dist/defaults.js +1 -1
  79. package/node_modules/@m0saic/core/dist/ffmpeg/backgroundImageInput.js +1 -1
  80. package/node_modules/@m0saic/core/dist/ffmpeg/bufferGuard.js +1 -1
  81. package/node_modules/@m0saic/core/dist/ffmpeg/ffmpegCommands.js +1 -1
  82. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyBackdropBlur.js +1 -1
  83. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyBlur.js +1 -1
  84. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyBorderRadius.js +1 -1
  85. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyCamera.js +1 -1
  86. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyChromaKey.js +1 -1
  87. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyFade.js +1 -1
  88. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyGrade.js +1 -1
  89. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyMask.js +1 -1
  90. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyNoise.js +1 -1
  91. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyPixelize.js +1 -1
  92. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyRotate.js +1 -1
  93. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyStroke.js +1 -1
  94. package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyTileEffects.js +1 -1
  95. package/node_modules/@m0saic/core/dist/ffmpeg/filters/coverCrop.js +1 -1
  96. package/node_modules/@m0saic/core/dist/ffmpeg/filters/index.js +1 -1
  97. package/node_modules/@m0saic/core/dist/ffmpeg/filters/sourceRectCrop.js +1 -1
  98. package/node_modules/@m0saic/core/dist/ffmpeg/gridLowering.js +1 -1
  99. package/node_modules/@m0saic/core/dist/ffmpeg/index.js +1 -1
  100. package/node_modules/@m0saic/core/dist/ffmpeg/splitAvMux.js +1 -1
  101. package/node_modules/@m0saic/core/dist/ffmpeg/threadGuard.js +1 -1
  102. package/node_modules/@m0saic/core/dist/flatten/index.js +1 -1
  103. package/node_modules/@m0saic/core/dist/fs/index.js +1 -1
  104. package/node_modules/@m0saic/core/dist/fs/tempWorkspace.js +1 -1
  105. package/node_modules/@m0saic/core/dist/index.js +1 -1
  106. package/node_modules/@m0saic/core/dist/media/buildAssetManifestFromInputs.js +1 -1
  107. package/node_modules/@m0saic/core/dist/media/buildMediaRegistryFromInput.js +1 -1
  108. package/node_modules/@m0saic/core/dist/media/collectMediaInputsFromInvocationProps.js +1 -1
  109. package/node_modules/@m0saic/core/dist/media/collectMediaInputsFromMosaicRenderableFile.js +1 -1
  110. package/node_modules/@m0saic/core/dist/media/collectMediaInputsFromProps.js +1 -1
  111. package/node_modules/@m0saic/core/dist/media/index.js +1 -1
  112. package/node_modules/@m0saic/core/dist/media/internalMintAsset.js +1 -1
  113. package/node_modules/@m0saic/core/dist/media/remoteUrl.js +1 -1
  114. package/node_modules/@m0saic/core/dist/media/stageUnsafeFilenames.js +1 -1
  115. package/node_modules/@m0saic/core/dist/media/types.js +1 -1
  116. package/node_modules/@m0saic/core/dist/output/index.js +1 -1
  117. package/node_modules/@m0saic/core/dist/output/resolveOutputFormat.js +1 -1
  118. package/node_modules/@m0saic/core/dist/output/types.js +1 -1
  119. package/node_modules/@m0saic/core/dist/probe/cellLuminanceProbe.js +1 -1
  120. package/node_modules/@m0saic/core/dist/probe/extractSubtitleCues.js +1 -1
  121. package/node_modules/@m0saic/core/dist/probe/helpers.js +1 -1
  122. package/node_modules/@m0saic/core/dist/probe/index.js +1 -1
  123. package/node_modules/@m0saic/core/dist/probe/luminanceProbe.js +1 -1
  124. package/node_modules/@m0saic/core/dist/probe/probeMedia.js +1 -1
  125. package/node_modules/@m0saic/core/dist/probe/runFFprobe.js +1 -1
  126. package/node_modules/@m0saic/core/dist/probe/types.js +1 -1
  127. package/node_modules/@m0saic/core/dist/runtime/engineRedaction.js +1 -1
  128. package/node_modules/@m0saic/core/dist/runtime/ffmpegFailure.js +1 -1
  129. package/node_modules/@m0saic/core/dist/runtime/filterPreflight.js +1 -1
  130. package/node_modules/@m0saic/core/dist/runtime/hashFile.js +1 -1
  131. package/node_modules/@m0saic/core/dist/runtime/index.js +1 -1
  132. package/node_modules/@m0saic/core/dist/runtime/pathInfo.js +1 -1
  133. package/node_modules/@m0saic/core/dist/runtime/perfHeatmap.js +1 -1
  134. package/node_modules/@m0saic/core/dist/runtime/perfReport.js +1 -1
  135. package/node_modules/@m0saic/core/dist/runtime/pipelineM0p.js +1 -1
  136. package/node_modules/@m0saic/core/dist/runtime/renderCostModel.constants.js +1 -1
  137. package/node_modules/@m0saic/core/dist/runtime/renderCostModel.js +1 -1
  138. package/node_modules/@m0saic/core/dist/runtime/renderReport.js +1 -1
  139. package/node_modules/@m0saic/core/dist/runtime/renderSidecars.js +1 -1
  140. package/node_modules/@m0saic/core/dist/runtime/resolveMosaicx.js +1 -1
  141. package/node_modules/@m0saic/core/dist/runtime/runPlan.js +1 -1
  142. package/node_modules/@m0saic/core/dist/runtime/types.js +1 -1
  143. package/node_modules/@m0saic/core/dist/runtime/upstream.js +1 -1
  144. package/node_modules/@m0saic/core/dist/runtime/writeSidecars.js +1 -1
  145. package/node_modules/@m0saic/core/dist/types/chunk.js +1 -1
  146. package/node_modules/@m0saic/core/dist/types/index.js +1 -1
  147. package/node_modules/@m0saic/core/dist/types/mosaic-plan.js +1 -1
  148. package/node_modules/@m0saic/core/dist/utils/assertTiming.js +1 -1
  149. package/node_modules/@m0saic/core/dist/utils/command.js +1 -1
  150. package/node_modules/@m0saic/core/dist/utils/createEngineContext.js +1 -1
  151. package/node_modules/@m0saic/core/dist/utils/createTemplateRenderCache.js +1 -1
  152. package/node_modules/@m0saic/core/dist/utils/ffmpegColor.js +1 -1
  153. package/node_modules/@m0saic/core/dist/utils/formatDuration.js +1 -1
  154. package/node_modules/@m0saic/core/dist/utils/fsSafeId.js +1 -1
  155. package/node_modules/@m0saic/core/dist/utils/index.js +1 -1
  156. package/node_modules/@m0saic/core/dist/utils/lowerRenderableToMosaicDocument.js +1 -1
  157. package/node_modules/@m0saic/core/dist/utils/movSafeCodec.js +1 -1
  158. package/node_modules/@m0saic/core/dist/utils/resolveBoxFrac.js +1 -1
  159. package/node_modules/@m0saic/core/dist/validate/index.js +1 -1
  160. package/node_modules/@m0saic/core/scripts/mask-rasterize-core.js +1 -1
  161. package/node_modules/@m0saic/core/scripts/mask-rasterize-worker.js +1 -1
  162. package/node_modules/@m0saic/core/scripts/mask-worker-thread.js +1 -1
  163. package/node_modules/@m0saic/dictionary/NOTICE +9 -0
  164. package/node_modules/@m0saic/dictionary/README.md +315 -0
  165. package/node_modules/@m0saic/dictionary/package.json +1 -1
  166. package/node_modules/@m0saic/dsl/package.json +1 -1
  167. package/node_modules/@m0saic/dsl-file-formats/dist/cjs/agent.js +6 -0
  168. package/node_modules/@m0saic/dsl-file-formats/dist/cjs/m0/parseM0File.js +1 -1
  169. package/node_modules/@m0saic/dsl-file-formats/dist/cjs/m0/serializeM0File.js +2 -2
  170. package/node_modules/@m0saic/dsl-file-formats/dist/cjs/m0c/m0cFile.js +3 -3
  171. package/node_modules/@m0saic/dsl-file-formats/dist/cjs/types.js +1 -1
  172. package/node_modules/@m0saic/dsl-file-formats/package.json +1 -1
  173. package/node_modules/@m0saic/dsl-stdlib/dist/cjs/builders/bakeM0cInsets.js +1 -0
  174. package/node_modules/@m0saic/dsl-stdlib/dist/cjs/builders/index.js +1 -1
  175. package/node_modules/@m0saic/dsl-stdlib/package.json +1 -1
  176. package/node_modules/@m0saic/knowledge/LICENSE +21 -0
  177. package/node_modules/@m0saic/knowledge/README.md +71 -0
  178. package/node_modules/@m0saic/knowledge/dist/index.js +1 -0
  179. package/node_modules/@m0saic/knowledge/docs/README.md +60 -0
  180. package/node_modules/@m0saic/knowledge/docs/file-formats/m0-iteration-protocol.md +120 -0
  181. package/node_modules/@m0saic/knowledge/docs/file-formats/m0p-and-custom-field.md +195 -0
  182. package/node_modules/@m0saic/knowledge/docs/handbook/README.md +27 -0
  183. package/node_modules/@m0saic/knowledge/docs/handbook/composition-arithmetic.md +278 -0
  184. package/node_modules/@m0saic/knowledge/docs/handbook/dsl-complexity.md +75 -0
  185. package/node_modules/@m0saic/knowledge/docs/handbook/dsl-rules.md +367 -0
  186. package/node_modules/@m0saic/knowledge/docs/handbook/feasibility-precision-quantization.md +591 -0
  187. package/node_modules/@m0saic/knowledge/docs/handbook/m0-construction-methods.md +201 -0
  188. package/node_modules/@m0saic/knowledge/docs/handbook/precision-tiers.md +84 -0
  189. package/node_modules/@m0saic/knowledge/docs/m0saic-thesis.md +95 -0
  190. package/node_modules/@m0saic/knowledge/docs/runtime/README.md +17 -0
  191. package/node_modules/@m0saic/knowledge/docs/runtime/cli-usage.md +447 -0
  192. package/node_modules/@m0saic/knowledge/docs/runtime/ffmpeg-expression-limits.md +117 -0
  193. package/node_modules/@m0saic/knowledge/docs/runtime/reduce-to-one.md +96 -0
  194. package/node_modules/@m0saic/knowledge/docs/skills/README.md +40 -0
  195. package/node_modules/@m0saic/knowledge/docs/skills/axis-and-geometry.md +103 -0
  196. package/node_modules/@m0saic/knowledge/docs/skills/dsl-stdlib-method-catalog.md +7 -0
  197. package/node_modules/@m0saic/knowledge/docs/skills/identity.md +123 -0
  198. package/node_modules/@m0saic/knowledge/docs/skills/labels-and-masks.md +170 -0
  199. package/node_modules/@m0saic/knowledge/docs/skills/m0saic-string-generation.md +251 -0
  200. package/node_modules/@m0saic/knowledge/docs/skills/more-atoms-not-bigger-atoms.md +77 -0
  201. package/node_modules/@m0saic/knowledge/docs/skills/overlay-semantics.md +194 -0
  202. package/node_modules/@m0saic/knowledge/docs/skills/parse-apis.md +79 -0
  203. package/node_modules/@m0saic/knowledge/docs/skills/passthrough-semantics.md +136 -0
  204. package/node_modules/@m0saic/knowledge/docs/skills/structural-construction.md +86 -0
  205. package/node_modules/@m0saic/knowledge/docs/skills/text-in-templates.md +126 -0
  206. package/node_modules/@m0saic/knowledge/docs/skills/zero-overlay-analysis.md +87 -0
  207. package/node_modules/@m0saic/knowledge/docs/templates/README.md +65 -0
  208. package/node_modules/@m0saic/knowledge/docs/templates/capability-templates.md +72 -0
  209. package/node_modules/@m0saic/knowledge/docs/templates/construction-strategy.md +329 -0
  210. package/node_modules/@m0saic/knowledge/docs/templates/data-pipeline.md +324 -0
  211. package/node_modules/@m0saic/knowledge/docs/templates/emission-patterns.md +130 -0
  212. package/node_modules/@m0saic/knowledge/docs/templates/geometry-recipes.md +248 -0
  213. package/node_modules/@m0saic/knowledge/docs/templates/layout-contract.md +168 -0
  214. package/node_modules/@m0saic/knowledge/docs/templates/output-resolution-tree.md +202 -0
  215. package/node_modules/@m0saic/knowledge/docs/templates/patterns/case-study-lessons.md +69 -0
  216. package/node_modules/@m0saic/knowledge/docs/templates/patterns/perf-authoring-rules.md +100 -0
  217. package/node_modules/@m0saic/knowledge/docs/templates/patterns/primitive-extraction-pattern.md +103 -0
  218. package/node_modules/@m0saic/knowledge/docs/templates/philosophy-and-contract.md +310 -0
  219. package/node_modules/@m0saic/knowledge/docs/templates/recursion-nested-rendering.md +154 -0
  220. package/node_modules/@m0saic/knowledge/docs/templates/reference/grid.md +104 -0
  221. package/node_modules/@m0saic/knowledge/docs/templates/reference/json-prop-type.md +169 -0
  222. package/node_modules/@m0saic/knowledge/docs/templates/reference/mosaic-color.md +81 -0
  223. package/node_modules/@m0saic/knowledge/docs/templates/reference/mosaic-placement-props.md +103 -0
  224. package/node_modules/@m0saic/knowledge/docs/templates/reference/prop-bindings.md +324 -0
  225. package/node_modules/@m0saic/knowledge/docs/templates/reference/template-flags.md +224 -0
  226. package/node_modules/@m0saic/knowledge/docs/templates/render-lifecycle.md +117 -0
  227. package/node_modules/@m0saic/knowledge/docs/templates/rendering-model-contract.md +392 -0
  228. package/node_modules/@m0saic/knowledge/docs/templates/standalone-pack-authoring.md +299 -0
  229. package/node_modules/@m0saic/knowledge/docs/templates/theming.md +81 -0
  230. package/node_modules/@m0saic/knowledge/docs/templates/ui-controls.md +150 -0
  231. package/node_modules/@m0saic/knowledge/package.json +6 -0
  232. package/node_modules/@m0saic/momo-types/README.md +109 -0
  233. package/node_modules/@m0saic/momo-types/dist/agent.js +1 -6
  234. package/node_modules/@m0saic/momo-types/dist/context.js +1 -1
  235. package/node_modules/@m0saic/momo-types/package.json +1 -1
  236. package/node_modules/@m0saic/platform/README.md +3 -0
  237. package/node_modules/@m0saic/platform/dist/cjs/index.js +1 -1
  238. package/node_modules/@m0saic/platform/dist/cjs/mosaic/outputKind/outputKind.js +1 -1
  239. package/node_modules/@m0saic/platform/dist/cjs/mosaic/propBindings/index.js +1 -1
  240. package/node_modules/@m0saic/platform/dist/cjs/mosaic/propBindings/propBindings.js +1 -1
  241. package/node_modules/@m0saic/platform/dist/cjs/mosaic/validate/validateSources.js +1 -1
  242. package/node_modules/@m0saic/platform/dist/cjs/packages/mosaicPackages.js +1 -0
  243. package/node_modules/@m0saic/platform/dist/cjs/paths/m0saicRoot.js +1 -1
  244. package/node_modules/@m0saic/platform/dist/cjs/telemetry/lifecycle.js +1 -1
  245. package/node_modules/@m0saic/platform/dist/cjs/telemetry/preview.js +1 -1
  246. package/node_modules/@m0saic/platform/dist/cjs/telemetry/sender.js +1 -1
  247. package/node_modules/@m0saic/platform/dist/cjs/telemetry/usageRecorder.js +1 -1
  248. package/node_modules/@m0saic/platform/dist/cjs/telemetry/usageStore.js +3 -3
  249. package/node_modules/@m0saic/platform/dist/cjs/toolchain/ffmpeg/baseline.json +25 -97
  250. package/node_modules/@m0saic/platform/dist/cjs/toolchain/ffmpeg/index.js +1 -1
  251. package/node_modules/@m0saic/platform/dist/cjs/toolchain/ffmpeg/install.js +2 -2
  252. package/node_modules/@m0saic/platform/dist/cjs/toolchain/goldenFfmpeg.js +6 -6
  253. package/node_modules/@m0saic/platform/package.json +1 -1
  254. package/node_modules/@m0saic/product/dist/communityRelease.js +1 -1
  255. package/node_modules/@m0saic/product/dist/freeTierLicense.js +1 -1
  256. package/node_modules/@m0saic/product/dist/index.js +1 -1
  257. package/node_modules/@m0saic/product/dist/licenseActivationNotice.js +1 -0
  258. package/node_modules/@m0saic/product/dist/licenseFile.js +1 -0
  259. package/node_modules/@m0saic/product/dist/licenseToken.js +1 -1
  260. package/node_modules/@m0saic/product/dist/makeScratchPath.js +1 -0
  261. package/node_modules/@m0saic/product/dist/postRenderWrapper.js +1 -1
  262. package/node_modules/@m0saic/product/dist/publicKeys.js +1 -1
  263. package/node_modules/@m0saic/product/dist/revokedKeys.js +1 -1
  264. package/node_modules/@m0saic/product/dist/upstreamDefaults.js +1 -1
  265. package/node_modules/@m0saic/product/dist/workspaceScaffold.js +1 -0
  266. package/node_modules/@m0saic/template-utils/dist/brand/hello-world/helloWorld.js +1 -1
  267. package/node_modules/@m0saic/template-utils/dist/geometry-contract/index.js +1 -1
  268. package/node_modules/@m0saic/template-utils/dist/geometry-contract/layoutConstraint.js +2 -2
  269. package/node_modules/@m0saic/template-utils/dist/m0saic/loadSession.js +1 -1
  270. package/node_modules/@m0saic/template-utils/dist/render/createDesignContext.js +1 -1
  271. package/node_modules/@m0saic/template-utils/dist/sources/makeErrorMosaic.js +2 -2
  272. package/node_modules/@m0saic/template-utils/dist/sources/svgTextSource.js +1 -1
  273. package/node_modules/@m0saic/template-utils/dist/template/auditRenderedTemplate.js +5 -5
  274. package/node_modules/@m0saic/template-utils/dist/template/templateConventions.js +3 -3
  275. package/node_modules/@m0saic/template-utils/dist/template/validateTemplateProps.js +1 -1
  276. package/node_modules/@m0saic/template-utils/dist/text/fitText.js +6 -6
  277. package/node_modules/@m0saic/template-utils/package.json +1 -1
  278. package/node_modules/@m0saic/templates/NOTICE +9 -0
  279. package/node_modules/@m0saic/templates/dist/m0saic/media/blur-regions/v1/tutorial.js +1 -1
  280. package/node_modules/@m0saic/templates/package.json +1 -1
  281. package/node_modules/@m0saic/templates-advanced/NOTICE +9 -0
  282. package/node_modules/@m0saic/text/package.json +1 -1
  283. package/node_modules/@m0saic/types/dist/analytics/consent.js +1 -1
  284. package/node_modules/@m0saic/types/dist/analytics/event.js +1 -1
  285. package/node_modules/@m0saic/types/dist/analytics/usageMetrics.js +1 -1
  286. package/node_modules/@m0saic/types/dist/identifiers/identifiers.js +1 -1
  287. package/node_modules/@m0saic/types/dist/telemetry/ffmpegFailure.js +1 -1
  288. package/node_modules/@m0saic/types/package.json +1 -1
  289. package/node_modules/@m0saic/types-internal/dist/analytics/featureKeys.js +1 -1
  290. package/package.json +13 -11
  291. package/resources/starter-base/starter-base.json +10 -0
  292. package/resources/starter-base/starter-base.tgz +0 -0
@@ -0,0 +1,96 @@
1
+ # "Push complexity down" — reduce to 1, then bake the constant
2
+
3
+ Two moves, applied in order. Move 1 is structural (isolate complexity); move 2
4
+ is temporal (stop recomputing a constant). They compose: nest, prove the knobs,
5
+ then bake. The user's vocabulary for this is literally **"reduce to 1"**, **"push
6
+ complexity down"**, and **"bake that result to a flat video file."**
7
+
8
+ ## Move 1 — Reduce to 1 (nested source)
9
+
10
+ When a subtree is too complex or too precise, render it as its own **nested
11
+ source** (child mosaic document). In the parent it collapses to a single `F` —
12
+ one cell, one source ref. High-level layout stays simple; the complexity is
13
+ isolated one level down. It still renders every frame; you've only separated
14
+ concerns by precision tier (e.g. a px-baked, quantization-sensitive scatter vs.
15
+ resolution-independent chrome).
16
+
17
+ Mechanism: wrap the subtree as a child doc (`children[...]` + a
18
+ `{type:"mosaic", ref}` source) so the engine renders it into its own
19
+ framebuffer and the parent sees one `F`. Same primitive as nested-mosaic
20
+ clipping.
21
+
22
+ ## Move 2 — Bake the constant (flat asset)
23
+
24
+ When a subtree is **identical on every render** — a fixed background, a
25
+ decorative field, a logo sting with no data dependency — don't render it at
26
+ runtime at all. Pre-render it **once** and reference the result as a flat asset.
27
+
28
+ How:
29
+ 1. Author a one-off **`internal: true`** bake template whose only job is to
30
+ render that subtree full-canvas, opaque, at each target aspect (e.g.
31
+ `hero/ffmpeg-pulse/scatter-bake/v1`).
32
+ 2. `m0saic make` it once per aspect → small `.mp4` / `.png` into the pack's
33
+ `_shared/assets/` (mirror to `dist` via `build:templates`).
34
+ 3. In the real template, replace the nested subtree with one
35
+ `{type:"media", mediaType:"video"|"image", assetId, placement:{fit:"cover"}}`
36
+ source, picking the asset by aspect (`scatter-${variantKey}.mp4`).
37
+ 4. Update the unit test: assert the `assets.<name>` ref + the `mediaType`, and
38
+ DROP the now-stale "child carries N tiles / animates" assertions.
39
+
40
+ Determinism still holds: a baked asset is a committed fixture, byte-identical
41
+ every run. Animation is fine to bake — the reveal/motion lives in the video.
42
+
43
+ ## When to bake (the trigger)
44
+
45
+ > "When you notice DSL count is high **and** render is long, and the result is
46
+ > intended to be the same every time — bake it to a flat file."
47
+
48
+ All three must hold:
49
+ - **High DSL / long render** — the subtree dominates `dsl-complexity.md` metrics
50
+ or wall-clock.
51
+ - **Constant across renders** — no prop/data dependency; same pixels every time.
52
+ (If it varies with data, you cannot bake it — keep it live or reduce to 1.)
53
+ - **Knobs are locked** — bake LAST, after the look is signed off. Baking freezes
54
+ the subtree; re-tuning means re-baking.
55
+
56
+ ## When NOT to bake
57
+
58
+ - The subtree depends on props/data (varies per render) → it's not constant.
59
+ - The look isn't locked yet → premature; you'll re-bake every iteration.
60
+ - The subtree is cheap → baking adds an asset + a build step for no win.
61
+
62
+ ## Measured payoff (FFmpeg-pulse title beat, 2026-06-23)
63
+
64
+ The title beat's signature background is a ~225-rect scatter with an L→R reveal —
65
+ the same on every render. Baking it to a flat per-aspect `.mp4`:
66
+
67
+ | Metric | Live scatter (inlined) | Baked scatter (1 video src) | Change |
68
+ |---|---|---|---|
69
+ | Wall-clock render (1920×1080, 9 s) | ~5 min | 66 s | ~4.5× faster, ~78% less |
70
+ | Flattened `.mosaic` size | ~163 K chars | 3,838 chars | ~98% smaller |
71
+ | Flattened source count | 238 | 14 | ~94% fewer |
72
+ | Baked asset size | — | ~98–155 KB / aspect | one-time, reused |
73
+
74
+ One-time bake cost ~3 m 21 s/aspect, amortized over every future render (it pays
75
+ for itself after ~1 render). The residual 66 s is the **chrome-overlay floor** —
76
+ the variable, prop-driven work that legitimately stays live. The bake removed the
77
+ *constant* cost and left only the *variable* cost; that's the whole point.
78
+
79
+ ## Trade-offs
80
+
81
+ - **Inline:** one flat doc, simplest pipeline; fat parent m0, mixed precision
82
+ tiers, depth accrues toward the ~25-layer overlay mask ceiling (see
83
+ `feasibility-precision-quantization.md` and the overlay-depth limit), full cost
84
+ every render.
85
+ - **Reduced to 1 (nested):** clean parent, isolated complexity, dodges the mask
86
+ ceiling; still full render cost (the subtree still renders).
87
+ - **Baked (flat asset):** near-zero per-render cost for that subtree, tiny
88
+ parent; but adds a committed asset + a one-off bake template + a build step, and
89
+ the subtree is frozen (re-tune ⇒ re-bake).
90
+
91
+ ## Adjacent
92
+
93
+ `dsl-complexity.md` (metrics → *when*), `feasibility-precision-quantization.md`
94
+ (precision tiers + the mask ceiling), nested-mosaic clipping (the move-1
95
+ mechanism). The shipped reference for a constant-subtree bake is
96
+ https://github.com/m0saic-project/m0saic-packages/blob/main/packages/templates/src/m0saic/hero/ffmpeg-pulse/scatter-bake/v1.
@@ -0,0 +1,40 @@
1
+ # skills/ — DSL & engine mental models
2
+
3
+ Operational skills layered on the handbook. **The handbook is canonical** — a doc
4
+ here that restates grammar is a checklist form of the same rules, and on any
5
+ conflict [`../handbook/`](../handbook/README.md) wins.
6
+
7
+ ## Grammar & construction (emitting valid m0)
8
+
9
+ - [`structural-construction.md`](structural-construction.md) — the build-time
10
+ rule checklist (count-exactness, overlay discipline, trailing-passthrough).
11
+ - [`m0saic-string-generation.md`](m0saic-string-generation.md) — programmatic
12
+ generation: builders first, unified transforms, validate, repair loop.
13
+ - [`dsl-stdlib-method-catalog.md`](dsl-stdlib-method-catalog.md) — pointer to
14
+ the full stdlib catalog (colocated with the package).
15
+
16
+ ## Geometry & semantics (what the parser does)
17
+
18
+ - [`axis-and-geometry.md`](axis-and-geometry.md) — split axes, `splitEven`
19
+ remainders, rect propagation.
20
+ - [`passthrough-semantics.md`](passthrough-semantics.md) — `0` donation runs,
21
+ claimants, carry scoping.
22
+ - [`overlay-semantics.md`](overlay-semantics.md) — **the overlay anchor**:
23
+ attachment, bodies, deferred paint order.
24
+ - [`zero-overlay-analysis.md`](zero-overlay-analysis.md) — the `0{}` phantom
25
+ operator (rarely needed; read overlay-semantics first).
26
+
27
+ ## Identity & parsing
28
+
29
+ - [`identity.md`](identity.md) — StableKey, the five axes, selection policies.
30
+ - [`parse-apis.md`](parse-apis.md) — which parse API to use + the
31
+ frames→sources bridge.
32
+
33
+ ## Authoring surfaces
34
+
35
+ - [`labels-and-masks.md`](labels-and-masks.md) — labels/masks across
36
+ dictionary → generator → editor → disk.
37
+ - [`text-in-templates.md`](text-in-templates.md) — text sources, rasterizer
38
+ choice, sizing traps.
39
+ - [`more-atoms-not-bigger-atoms.md`](more-atoms-not-bigger-atoms.md) — the
40
+ ffmpeg scaling contract (capacity grows with atom COUNT).
@@ -0,0 +1,103 @@
1
+ ## Axis & Geometry (Splits, Pixels, Remainders)
2
+
3
+ The math layer of the walk: exact rectangle geometry from `()` and `[]`,
4
+ deterministic pixel-remainder distribution (`splitEven`), and how `0`-runs and `-`
5
+ holes shape final rects.
6
+
7
+ > **Source of truth:** `splitEven` in [https://github.com/m0saic-dsl/m0/blob/main/packages/dsl/src/parse/m0StringParser.ts](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl/src/parse/m0StringParser.ts)
8
+ > (line 478 as of 2026-07-27). Locked behavior: outside-in remainder distribution.
9
+ > Test fixtures in [https://github.com/m0saic-dsl/m0/blob/main/packages/dsl/src/parse/outside-in-remainder.test.ts](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl/src/parse/outside-in-remainder.test.ts).
10
+
11
+ ## Axis semantics
12
+
13
+ - Column split `N( ... )` — splits **width** into N segments; height stays the
14
+ container's height.
15
+ - Row split `N[ ... ]` — splits **height** into N segments; width stays the
16
+ container's width.
17
+
18
+ Children are laid out in order:
19
+
20
+ - Columns advance **x** (left → right)
21
+ - Rows advance **y** (top → bottom)
22
+
23
+ ## splitEven pixel distribution (deterministic)
24
+
25
+ When splitting an integer pixel length (`total`) into `parts`:
26
+
27
+ - `base = floor(total / parts)`
28
+ - `remainder = total - base * parts`
29
+ - The `remainder` extra pixels are distributed **outside-in**: indices
30
+ 0, P-1, 1, P-2, 2, P-3, ...
31
+ - The remaining segments get `base`
32
+
33
+ Example:
34
+
35
+ - `total = 1080`, `parts = 7`
36
+ - `base = 154`, `remainder = 2`
37
+ - Outside-in order: index 0 gets +1, then index 6 gets +1
38
+ - Sizes: `[155, 154, 154, 154, 154, 154, 155]`
39
+
40
+ Key consequence: remainders distribute symmetrically from the edges inward, keeping
41
+ layouts visually balanced.
42
+
43
+ ## Coordinate propagation (rects)
44
+
45
+ Every node owns a rectangle `(x, y, width, height)`. Splits carve that rect into
46
+ child rects:
47
+
48
+ - Column split: child width from `splitEven(width, N)`; child x = cumulative sum of
49
+ prior child widths; y/height unchanged.
50
+ - Row split: child height from `splitEven(height, N)`; child y = cumulative sum of
51
+ prior child heights; x/width unchanged.
52
+
53
+ Overlays always reuse the **owner rect** (same x/y/width/height) and never escape it.
54
+
55
+ ## How `0` and `-` affect geometry
56
+
57
+ ### `0` (passthrough)
58
+
59
+ - Consumes a split slot; adds its slot size into "carry"
60
+ - The claimant absorbs carry + its own slot, and snaps back to the run start position
61
+
62
+ Geometry impact: `0` changes the eventual claimant rect size and origin. `0` itself
63
+ creates no visible rect (but may create overlay rects via `0{...}`).
64
+
65
+ ### `-` (null)
66
+
67
+ - Consumes a split slot; does NOT donate forward
68
+ - Creates a hole / gutter region; can still host overlays (`-{...}`)
69
+
70
+ Geometry impact: a stable region that does not affect siblings beyond consuming its
71
+ share of split space. Useful for isolating sub-layouts and masks.
72
+
73
+ ## Why resolution matters (integer pixels)
74
+
75
+ All geometry is integer-pixel based. Two implications:
76
+
77
+ 1. A layout can look "perfect" at one size and slightly biased at another, because
78
+ remainder pixels distribute outside-in (edges first).
79
+ 2. Bitmap-like layouts (e.g. 64×64 encodings) require compatible output sizes,
80
+ otherwise meaning drifts due to integer rounding distribution.
81
+
82
+ Guidance: if a layout encodes literal grid art, render at sizes aligned to that grid
83
+ (multiples of the grid resolution). For feasibility guards, quantization strategy,
84
+ and quantization-free construction, see
85
+ [`../handbook/feasibility-precision-quantization.md`](../handbook/feasibility-precision-quantization.md).
86
+
87
+ ## Minimal examples
88
+
89
+ Even-ish columns — `3(1,1,1)` at width=10:
90
+
91
+ - sizes = `[4,3,3]` (1 remainder pixel goes to the first edge)
92
+
93
+ Rows — `2[1,1]` at height=5:
94
+
95
+ - sizes = `[3,2]`
96
+
97
+ Donation changes claimant geometry — `3(0,1,1)`:
98
+
99
+ - first tile claims 2 slots (`0` + its own)
100
+
101
+ Hole creates gutter — `3(1,-,1)`:
102
+
103
+ - middle region is an explicit empty gutter
@@ -0,0 +1,7 @@
1
+ # dsl-stdlib method catalog → see the package
2
+
3
+ The full `@m0saic/dsl-stdlib` method catalog (builders, transforms, queries, masks, SVG import, specialized generators) is **colocated with the package** so it can't drift from the code:
4
+
5
+ ➡️ [https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-stdlib/.ai/method-catalog.md](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-stdlib/.ai/method-catalog.md)
6
+
7
+ That doc is regenerated/reviewed in the same change that alters the API. This file is only a pointer — don't duplicate the catalog here.
@@ -0,0 +1,123 @@
1
+ # Identity — StableKey, depth axes, and selection
2
+
3
+ Merged 2026-07-27 from four overlapping docs (stablekey-and-overlay-identity,
4
+ identity-model, structural-vs-overlay-depth, structural-identity_visual-identity —
5
+ deleted; git history has the long forms). One doc, one owner: everything about
6
+ *referring to the same node* across parses, edits, and renders.
7
+
8
+ > **Source of truth:** `StableKey` + `M0NodeIdentity` in
9
+ > [https://github.com/m0saic-dsl/m0/blob/main/packages/dsl/src/types.ts](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl/src/types.ts); identity
10
+ > construction in [`parse/m0StringParser.ts`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl/src/parse/m0StringParser.ts)
11
+ > (search `buildIdentity`, `makeStableKeySegment`).
12
+
13
+ ## 1. The identity contract
14
+
15
+ Every parsed node receives a deterministic `stableKey` — the address of the parser's
16
+ walk through **structure**. Segments encode node kind + split axis + childIndex among
17
+ structural siblings. Segment grammar (verified at runtime): `r` (root) ·
18
+ `g{row|col}c{n}` (group) · `fc{n}` (frame) · `pc{n}` (passthrough) · `nc{n}` (null) ·
19
+ `/ov{d}c{k}` (overlay namespace).
20
+
21
+ Same canonical string → same StableKeys, same structuralDepth, same overlay
22
+ namespace. If the string changes, the tree changes and some keys change — that is
23
+ correct, not a bug.
24
+
25
+ **StableKey is NOT:** `paintOrder` / `stackOrder` (paint depends on overlay-deferral
26
+ rules), display/label numbering, or geometry. Geometry is *derived* —
27
+ `rect = f(m0, width, height)` — and shifts with resolution and `splitEven`
28
+ remainders while keys stay put. The DSL guarantees **structural** identity, never
29
+ **visual** identity.
30
+
31
+ ## 2. The five axes — keep them separate
32
+
33
+ | Axis | Increments when | Use it for |
34
+ |---|---|---|
35
+ | `structuralDepth` (`meta.structuralDepth`) | entering `N(...)` / `N[...]` | tree indentation, containment reasoning |
36
+ | `overlayDepth` | entering `{...}` | layer filtering |
37
+ | `paintOrder` / `stackOrder` | derived from traversal + overlay deferral | paint simulation ONLY |
38
+ | `logicalIndex` | per rendered leaf, logical order | source assignment (`sources[i]`) |
39
+ | `stableKey` | — (structural address) | persistent identity across edits |
40
+
41
+ Worked example — `2(2(1,1),1)` (verified at runtime): the outermost split **IS the
42
+ root** (`stableKey: r`, structuralDepth 0); the inner group is depth **1**
43
+ (`r/gcolc0`); its tiles are depth **2** (`r/gcolc0/fc0`, `fc1`); the outer `1` is
44
+ depth **1** (`r/fc1`). There is no extra root node above the outermost split.
45
+
46
+ `1{1{1}}` has structuralDepth 0 on all three nodes and overlayDepth 0/1/2 — the two
47
+ depth systems are orthogonal: deep structure with zero overlays, flat structure with
48
+ 100 overlays, or both.
49
+
50
+ Never assume `deeper == painted later` — overlay deferral (and area-descending
51
+ zero-overlay stacking) controls paint timing, not depth. See
52
+ [`overlay-semantics.md`](overlay-semantics.md).
53
+
54
+ > ⚠️ overlayDepth is structurally free but NOT render-free: each level is a
55
+ > sequential blend pass, and inline-masks silently drop past ~25 nested layers
56
+ > (engine wall W3 — internal: `.ai/moat/runtime/ffmpeg-limitations.md`).
57
+
58
+ ## 3. The overlay invariant
59
+
60
+ Overlay subtrees do NOT affect structural childIndex assignment:
61
+
62
+ - Adding/removing overlays never renumbers the base tree.
63
+ - Overlay frames live in a separate namespace — `<ownerStableKey>/ov<depth>c<k>`
64
+ (`r/fc0` → `r/fc0/ov1c0` → `r/fc0/ov1c0/ov2c0`) — so overlay keys cannot collide
65
+ with or shift structural keys.
66
+
67
+ This is why overlays can be used freely (debug layers, labels, reveals) without
68
+ destabilizing the base layout or any tool keyed on it.
69
+
70
+ ## 4. logicalIndex vs paintOrder
71
+
72
+ RenderFrames carry both `paintOrder` (stacking order) and `logicalIndex` (logical
73
+ tile index — same as `LogicalFrame.logicalIndex`; there is **no `sourceIndex`
74
+ field** in https://github.com/m0saic-dsl/m0/blob/main/packages/dsl). Build sources in logical order, paint in stack order —
75
+ the split keeps the source array clean of paint semantics. See
76
+ [`parse-apis.md`](parse-apis.md) for which parse API returns which.
77
+
78
+ ## 5. Stability limits — what edits do to keys
79
+
80
+ Keys **WILL change** when you: change split counts, insert/remove siblings in the
81
+ base tree, change axis/group nesting. Keys will **NOT change** when you: add/remove
82
+ overlays, deepen overlay nesting, reorder overlay-only layers.
83
+
84
+ Overlay data attaches to `ownerStableKey`, so across edits: split *inside* the owner
85
+ → owner survives → overlay stays valid; edit a sibling → unaffected; delete/replace
86
+ the owner → the overlay has no owner and cannot reattach. That last case is correct
87
+ behavior, not data loss to be papered over.
88
+
89
+ **Never reattach by geometry.** Preserving overlays via nearest-rect / similar-size /
90
+ pixel-overlap heuristics introduces non-determinism and unfixable edge cases. If the
91
+ owner is gone, the overlay is gone. Determinism > convenience.
92
+
93
+ ## 6. Selection policies (agent workflows)
94
+
95
+ When you need to "pick a tile" — recursive growth, demos, batch transforms — pick by
96
+ StableKey, not geometry or paint order. Deterministic policies:
97
+
98
+ - **Smallest StableKey lexicographically** — stable across edits, cheap.
99
+ - **Earliest leaf in StableKey-sorted order** — a "top-left-most" that survives
100
+ structural change.
101
+ - **`(seed + step) mod leafCount`** over a StableKey-sorted leaf list — round-robin
102
+ demos where each step targets a different tile.
103
+
104
+ Anti-patterns: selecting by pixel position (resolution change → different
105
+ selection), by paint order (adding overlays shifts it), or by unsorted traversal
106
+ order.
107
+
108
+ ## 7. Labeling
109
+
110
+ Label tiles by StableKey (`.m0c` labels are StableKey-keyed); use the label `text`
111
+ as the human-meaningful join key (`.m0p` regions reference labels by text). If a
112
+ label's key no longer exists in the current parse, `validateLabels`
113
+ (`@m0saic/dsl-file-formats`) flags it — see
114
+ [`../file-formats/m0p-and-custom-field.md`](../file-formats/m0p-and-custom-field.md) §5.
115
+
116
+ ## 8. Common mistakes
117
+
118
+ - Treating overlay tiles as structural leaves — scope "leaves" iterations to the
119
+ base namespace; overlays live under `/ov…`.
120
+ - Confusing overlayDepth for structuralDepth (UI tree depth ≠ "inside another split").
121
+ - Hardcoding StableKey strings — they're stable across *layout* edits but computed
122
+ from structure; always derive them from a parse, never string-match literals.
123
+ - Assuming paintOrder reflects structure — it's derived, overlay rules own it.
@@ -0,0 +1,170 @@
1
+ # Labels and Masks
2
+
3
+ How per-leaf **labels** and **masks** travel from a dictionary entry, through a
4
+ generator, into the editor, and back to disk. The surface spans four packages; this is
5
+ the single map.
6
+
7
+ ---
8
+
9
+ ## 1. What lives where
10
+
11
+ | Layer | Shape | Home |
12
+ |---|---|---|
13
+ | **On disk** | `M0cFile` — `m0` + `labels` (`Record<StableKey, M0Label>`) + `masks` (`Record<StableKey, M0cMaskEntry \| null>`) + `fill` + `size` | https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/types.ts |
14
+ | **Dictionary entry** | `MosaicDictionaryEntry.labels` / `.masks` — same maps at runtime | https://github.com/m0saic-project/m0saic-packages/blob/main/packages/types/src/dictionary/dictionary.ts |
15
+ | **Editor (live)** | `m0cExtrasRef` — `{ labels, masks, derive, custom }` for the open canvas | the Mosaic Desktop / Web app source (not published) |
16
+ | **Generator output** | `GeneratorResult.m0c?: string` — optional serialized blob | https://github.com/m0saic-project/m0saic-packages/blob/main/packages/dictionary/src/generators |
17
+
18
+ > **`labels[k].color` ≠ the rect fill.** `labels[k].color` tints the *badge*; `fill[k]`
19
+ > paints the *rect*. The inspector once conflated them — don't re-conflate.
20
+
21
+ ---
22
+
23
+ ## 2. Dictionary entry convention
24
+
25
+ - An entry MAY ship **`m0saic.m0c`** instead of `m0saic.m0`. The `.m0c` is
26
+ authoritative; `loadEntryM0()` auto-detects by filename and **throws if both exist**.
27
+ - **`m0saic_src.m0`** is a read-only sibling auto-regenerated by `validate.js`, carrying
28
+ a `# note:` header. It exists for grep-by-DSL and human inspection. **No runtime reads
29
+ it** — never edit it, never treat it as a source.
30
+ - **`entry.masks`** (StableKey-keyed) is the canonical mask path. `entry.maskSets` /
31
+ `getMaskSet()` is reserved for future *named alternate* sets — no current entry uses
32
+ it. Don't reach for it.
33
+ - Positional lookup goes through `getSourceOrderStableKeys(entry)`
34
+ (https://github.com/m0saic-project/m0saic-packages/blob/main/packages/dictionary/src/sourceOrder.ts#L50, memoized per `(entry.id, m0.length)`).
35
+ See logo v2/v3 and qr-animate.
36
+ ⚠️ **It throws when `entry.m0` isn't inlined.** Heavy entries carry a lazy
37
+ `entry.m0File` instead. For those, call `resolveM0saic(entry)` first and pass the
38
+ resolved string to the companion **`getSourceOrderStableKeysForM0(id, m0, w, h)`**.
39
+ The error message says this, but only after you've already hit it.
40
+ - One-shot migrations live in **https://github.com/m0saic-project/m0saic-packages/blob/main/packages/dictionary/tools** (not repo-root `tools/`):
41
+ `migrate-masks-to-m0c.mjs` converts legacy `masks.json` + `.m0` → `.m0c`;
42
+ `normalize-mask-paths.mjs` runs the drop-rect-shaped + snap-to-bounds cleanup. Both
43
+ route through `parseM0StringComplete` to turn positional masks into per-StableKey
44
+ entries.
45
+
46
+ ---
47
+
48
+ ## 3. Generator label tiers
49
+
50
+ Every label-emitting generator exposes `labels: LabelTier`
51
+ (`"silent" | "signposts" | "atlas"`) built via `labelTierParam({ defaultTier })`
52
+ (https://github.com/m0saic-project/m0saic-packages/blob/main/packages/dictionary/src/generators/labelTier.ts).
53
+
54
+ | Tier | Emits |
55
+ |---|---|
56
+ | `silent` | plain m0, no labels |
57
+ | `signposts` | named structural regions only ("hero", "feature") |
58
+ | `atlas` | signposts + per-cell / per-level enumeration |
59
+
60
+ `off` is accepted as a spelling alias for `silent`; **`silent` is the canonical wire
61
+ value**. Resolve untrusted input with `resolveLabelTier(raw, fallback)`.
62
+
63
+ ### Per-generator defaults and emission path
64
+
65
+ Two emission paths, and which one a generator uses is not arbitrary:
66
+
67
+ - **`emitLabeledM0c({ m0, size, app, tier, labelsBySourceIndex, keyedLabels })`** —
68
+ use when labels map **positionally** to logical source order. Handles
69
+ source-index → stableKey translation, including a feasibility-fallback probe
70
+ scale-up for high-precision layouts.
71
+ - **Direct `serializeM0cFile`** — use when the generator must **classify nulls by
72
+ position** or carries masks. Parse the m0, compute the placed-content bbox, classify
73
+ each `kind: "null"` editorFrame by centroid offset into `padding-top` /
74
+ `padding-right` / `padding-bottom` / `padding-left`. The same algorithm appears in
75
+ every padding-classifying generator — copy it, don't re-derive it.
76
+
77
+ | Generator | Default tier | Path |
78
+ |---|---|---|
79
+ | `qrCodeGenerator` | **`signposts`** | direct |
80
+ | `barcodeGenerator` | **`signposts`** | direct |
81
+ | `aspectFit` | `silent` | direct (padding classification) |
82
+ | `placeRect` | `silent` | direct (padding classification) |
83
+ | `snapGrid` | `silent` | direct (padding classification) |
84
+ | `aspectSafeGrid` | `silent` | direct (padding classification) |
85
+ | `grid` | `silent` | `emitLabeledM0c` |
86
+ | `spotlightGenerator` | `silent` | `emitLabeledM0c` |
87
+ | `magazineGenerator` | `silent` | `emitLabeledM0c` |
88
+ | `comparisonGenerator` | `silent` | `emitLabeledM0c` |
89
+ | `rankedListGenerator` | `silent` | `emitLabeledM0c` |
90
+ | `goldenLayout` | `silent` | `emitLabeledM0c` |
91
+ | `goldenSpiralGenerator` | `silent` | `emitLabeledM0c` |
92
+ | `safeCanvas` | `silent` | `emitLabeledM0c` |
93
+
94
+ **`silent` is the default everywhere except the two code generators** (QR, barcode),
95
+ which default to `signposts` to preserve their always-on label channel.
96
+
97
+ *Keep this table in sync when adding a generator — verify with
98
+ `grep -A3 "labelTierParam(" https://github.com/m0saic-project/m0saic-packages/blob/main/packages/dictionary/src/generators/*.ts.*
99
+
100
+ ---
101
+
102
+ ## 4. Editor rendering and drop rules
103
+
104
+ **Chip render gate** — `Frame.tsx`: `canShowLabel = hasLabel && minPx >= 70`. There is
105
+ **no kind filter here**: frames, plain nulls, and passthroughs all wear chips once
106
+ mounted. Visibility moved upstream to the `showNullFrames` toggle, which controls
107
+ whether nulls reach `displayFrames` at all.
108
+
109
+ **Drop-label remap** — `ViewFrame.tsx` `buildDropZone`:
110
+
111
+ ```ts
112
+ const isLabelable = (f) => f.kind === "frame" || f.kind === "null";
113
+ ```
114
+
115
+ ⚠️ **The root node is deliberately excluded.** Including it shifts every
116
+ position-slice mapping by one — the off-by-one that mislabeled aspectFit's `content`.
117
+ Bare-`F` drops (canvas was `"r"`) take a separate path: the new canvas *is* the dropped
118
+ m0, so labels apply with their original keys.
119
+
120
+ > **Name collision — two different `isLabelable`.** `ViewFrame`'s is **node-kind**
121
+ > based (above). `App.tsx`'s is **format** based
122
+ > (`loadedFormat === "m0c" || loadedFormat === "m0p"` — can this file carry labels at
123
+ > all). Same identifier, unrelated meanings, different files. Check which one you're
124
+ > reading.
125
+
126
+ **Why no `isLogicalOwner` requirement.** aspectFit-style generators label plain `-`
127
+ nulls (border padding). Requiring `-{...}` overlay anchors would force every
128
+ padding-labeling generator to wrap each null in an overlay purely to make it visible.
129
+ The relaxed rule lets any structural node carry a label, matching the `.m0c` format's
130
+ own permissiveness.
131
+
132
+ ---
133
+
134
+ ## 5. Undo participation
135
+
136
+ `useUndoRedoText(initial, { onCommit, onUndo, onRedo })` exposes side-channel
137
+ callbacks. `App.tsx` snapshots `{ labels, masks }` from `m0cExtrasRef` into a parallel
138
+ stack on every text commit, and restores on undo/redo.
139
+
140
+ - Manual `setFrameLabel` edits **between** commits don't push their own entry — they're
141
+ absorbed into the *next* commit's snapshot. So manual label → text edit → Ctrl-Z
142
+ restores the manual label too.
143
+ - Drop-derived labels vanish cleanly on Ctrl-Z because the snapshot at the drop's commit
144
+ is taken **before** the handler merges drop labels (`setProfileText` calls `onCommit`
145
+ synchronously, ahead of the `m0cExtrasRef` mutation). This ordering is load-bearing.
146
+
147
+ ---
148
+
149
+ ## 6. UI affordances
150
+
151
+ - **The dictionary panel's drag chip is the sole apply path.** Click-drag splices into a
152
+ frame; double-click replaces the canvas (confirm modal when the canvas has structure;
153
+ bare-`F` skips the prompt). The standalone "Use Layout" button was **removed** — it
154
+ duplicated the pipeline and kept drifting.
155
+ - **Save-As gates `.m0`** whenever labels or masks exist (`m0SaveBlocked` in `App.tsx`).
156
+ Both the Cmd/Ctrl+S guard and the format chooser respect it — a `.m0` save would
157
+ silently drop the sidecar maps.
158
+
159
+ ---
160
+
161
+ ## 7. Settled items (don't re-debate)
162
+
163
+ - `aspectSafeGrid` carries m0c only on the **landscape primary** variant; portrait
164
+ alternates don't support m0c yet. Noted in its labels-param description.
165
+ - `LabelTier` naming is **settled**. Renaming touches ~14 generators plus the panel UI.
166
+ - Outer-gutter nulls in `safeCanvas` are **not** labeled — canvas margin, not
167
+ addressable cells.
168
+
169
+ **Related:** `file-formats/m0p-and-custom-field.md` covers `.m0c`'s sibling format but
170
+ predates this convention — read this doc for the entry convention and tier param.