m0saic 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -7
- package/README.md +23 -5
- package/dist/browseE2e.js +1 -1
- package/dist/connectionsFromEnv.js +1 -1
- package/dist/e2eTemplateVariants.js +1 -1
- package/dist/frontDoor.js +1 -1
- package/dist/index.js +1 -1
- package/dist/inlineDsl.js +1 -1
- package/dist/mcp/bridgeClient.js +1 -0
- package/dist/mcp/server.js +1 -0
- package/dist/mcp/tools.js +1 -0
- package/dist/mosaicxRunner.js +1 -1
- package/dist/outputPattern.js +1 -1
- package/dist/showcaseFeed.js +1 -1
- package/dist/templateDoctor.js +1 -1
- package/dist/utils/checkFeasibility.js +1 -1
- package/dist/utils/collectRenderErrors.js +1 -1
- package/dist/utils/enrichImageAlphaFromDoc.js +1 -1
- package/dist/utils/ensureFfmpeg.js +1 -1
- package/dist/utils/extractLayoutMeta.js +1 -1
- package/dist/utils/failureHints.js +1 -1
- package/dist/utils/ffmpegProbe.js +1 -1
- package/dist/utils/formatM0saicForCli.js +1 -1
- package/dist/utils/hashFile.js +1 -1
- package/dist/utils/helpGroups.js +1 -1
- package/dist/utils/installContext.js +1 -0
- package/dist/utils/invocation.js +1 -1
- package/dist/utils/licenseActivation.js +1 -0
- package/dist/utils/licenseActivationWorker.js +1 -0
- package/dist/utils/mosaicSpinner.js +1 -1
- package/dist/utils/parseDimensions.js +1 -1
- package/dist/utils/pathInfo.js +1 -1
- package/dist/utils/readJsonArg.js +1 -1
- package/dist/utils/renderOutcome.js +1 -1
- package/dist/utils/renderReport.js +1 -1
- package/dist/utils/renderSignals.js +1 -1
- package/dist/utils/renderWorkspace.js +1 -1
- package/dist/utils/reportOutputFormat.js +1 -0
- package/dist/utils/setupFfmpeg.js +1 -1
- package/dist/utils/telemetry.js +1 -1
- package/dist/utils/telemetryFlushWorker.js +1 -1
- package/dist/utils/telemetryUpstream.js +1 -1
- package/dist/utils/telemetryUsage.js +1 -1
- package/dist/utils/toolchainConfig.js +1 -1
- package/dist/utils/tutorialDuration.js +1 -1
- package/dist/utils/updateCheck.js +1 -1
- package/dist/utils/updateCheckWorker.js +1 -1
- package/dist/utils/validateSourceCounts.js +1 -1
- package/dist/utils/versions.js +1 -1
- package/dist/webCustomizeLink.js +1 -1
- package/node_modules/@m0saic/community-m/NOTICE +9 -0
- package/node_modules/@m0saic/community-m/release.json +2 -2
- package/node_modules/@m0saic/core/dist/core/buildChildMosaicSource.js +1 -1
- package/node_modules/@m0saic/core/dist/core/buildChunkCommands.js +1 -1
- package/node_modules/@m0saic/core/dist/core/buildEncodeCommands.js +1 -1
- package/node_modules/@m0saic/core/dist/core/buildLavfiSource.js +1 -1
- package/node_modules/@m0saic/core/dist/core/buildMediaSource.js +1 -1
- package/node_modules/@m0saic/core/dist/core/buildMosaicNode.js +1 -1
- package/node_modules/@m0saic/core/dist/core/buildMosaicPlanFromFile.js +1 -1
- package/node_modules/@m0saic/core/dist/core/buildSvgTextSource.js +1 -1
- package/node_modules/@m0saic/core/dist/core/buildTextRenderCommand.js +1 -1
- package/node_modules/@m0saic/core/dist/core/collectRefTargets.js +1 -1
- package/node_modules/@m0saic/core/dist/core/index.js +1 -1
- package/node_modules/@m0saic/core/dist/core/maskCacheDir.js +1 -1
- package/node_modules/@m0saic/core/dist/core/maskWorkerBridge.js +1 -1
- package/node_modules/@m0saic/core/dist/core/playbackPlaySpeed.js +1 -1
- package/node_modules/@m0saic/core/dist/core/prepareProps.js +1 -1
- package/node_modules/@m0saic/core/dist/core/primaryOutput.js +1 -1
- package/node_modules/@m0saic/core/dist/core/rasterizeMaskPng.js +1 -1
- package/node_modules/@m0saic/core/dist/core/rasterizeSvgMediaPng.js +1 -1
- package/node_modules/@m0saic/core/dist/core/refTargetTap.js +1 -1
- package/node_modules/@m0saic/core/dist/core/resolveMasks.js +1 -1
- package/node_modules/@m0saic/core/dist/core/resolveMasksSync.js +1 -1
- package/node_modules/@m0saic/core/dist/core/resolveStrokeRingsSync.js +1 -1
- package/node_modules/@m0saic/core/dist/core/roundedRectMask.js +1 -1
- package/node_modules/@m0saic/core/dist/core/strokeRing.js +1 -1
- package/node_modules/@m0saic/core/dist/core/svgRaster.js +1 -1
- package/node_modules/@m0saic/core/dist/defaults.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/backgroundImageInput.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/bufferGuard.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/ffmpegCommands.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyBackdropBlur.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyBlur.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyBorderRadius.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyCamera.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyChromaKey.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyFade.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyGrade.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyMask.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyNoise.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyPixelize.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyRotate.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyStroke.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/applyTileEffects.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/coverCrop.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/index.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/filters/sourceRectCrop.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/gridLowering.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/index.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/splitAvMux.js +1 -1
- package/node_modules/@m0saic/core/dist/ffmpeg/threadGuard.js +1 -1
- package/node_modules/@m0saic/core/dist/flatten/index.js +1 -1
- package/node_modules/@m0saic/core/dist/fs/index.js +1 -1
- package/node_modules/@m0saic/core/dist/fs/tempWorkspace.js +1 -1
- package/node_modules/@m0saic/core/dist/index.js +1 -1
- package/node_modules/@m0saic/core/dist/media/buildAssetManifestFromInputs.js +1 -1
- package/node_modules/@m0saic/core/dist/media/buildMediaRegistryFromInput.js +1 -1
- package/node_modules/@m0saic/core/dist/media/collectMediaInputsFromInvocationProps.js +1 -1
- package/node_modules/@m0saic/core/dist/media/collectMediaInputsFromMosaicRenderableFile.js +1 -1
- package/node_modules/@m0saic/core/dist/media/collectMediaInputsFromProps.js +1 -1
- package/node_modules/@m0saic/core/dist/media/index.js +1 -1
- package/node_modules/@m0saic/core/dist/media/internalMintAsset.js +1 -1
- package/node_modules/@m0saic/core/dist/media/remoteUrl.js +1 -1
- package/node_modules/@m0saic/core/dist/media/stageUnsafeFilenames.js +1 -1
- package/node_modules/@m0saic/core/dist/media/types.js +1 -1
- package/node_modules/@m0saic/core/dist/output/index.js +1 -1
- package/node_modules/@m0saic/core/dist/output/resolveOutputFormat.js +1 -1
- package/node_modules/@m0saic/core/dist/output/types.js +1 -1
- package/node_modules/@m0saic/core/dist/probe/cellLuminanceProbe.js +1 -1
- package/node_modules/@m0saic/core/dist/probe/extractSubtitleCues.js +1 -1
- package/node_modules/@m0saic/core/dist/probe/helpers.js +1 -1
- package/node_modules/@m0saic/core/dist/probe/index.js +1 -1
- package/node_modules/@m0saic/core/dist/probe/luminanceProbe.js +1 -1
- package/node_modules/@m0saic/core/dist/probe/probeMedia.js +1 -1
- package/node_modules/@m0saic/core/dist/probe/runFFprobe.js +1 -1
- package/node_modules/@m0saic/core/dist/probe/types.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/engineRedaction.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/ffmpegFailure.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/filterPreflight.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/hashFile.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/index.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/pathInfo.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/perfHeatmap.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/perfReport.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/pipelineM0p.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/renderCostModel.constants.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/renderCostModel.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/renderReport.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/renderSidecars.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/resolveMosaicx.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/runPlan.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/types.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/upstream.js +1 -1
- package/node_modules/@m0saic/core/dist/runtime/writeSidecars.js +1 -1
- package/node_modules/@m0saic/core/dist/types/chunk.js +1 -1
- package/node_modules/@m0saic/core/dist/types/index.js +1 -1
- package/node_modules/@m0saic/core/dist/types/mosaic-plan.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/assertTiming.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/command.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/createEngineContext.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/createTemplateRenderCache.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/ffmpegColor.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/formatDuration.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/fsSafeId.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/index.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/lowerRenderableToMosaicDocument.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/movSafeCodec.js +1 -1
- package/node_modules/@m0saic/core/dist/utils/resolveBoxFrac.js +1 -1
- package/node_modules/@m0saic/core/dist/validate/index.js +1 -1
- package/node_modules/@m0saic/core/scripts/mask-rasterize-core.js +1 -1
- package/node_modules/@m0saic/core/scripts/mask-rasterize-worker.js +1 -1
- package/node_modules/@m0saic/core/scripts/mask-worker-thread.js +1 -1
- package/node_modules/@m0saic/dictionary/NOTICE +9 -0
- package/node_modules/@m0saic/dictionary/README.md +315 -0
- package/node_modules/@m0saic/dictionary/package.json +1 -1
- package/node_modules/@m0saic/dsl/package.json +1 -1
- package/node_modules/@m0saic/dsl-file-formats/dist/cjs/agent.js +6 -0
- package/node_modules/@m0saic/dsl-file-formats/dist/cjs/m0/parseM0File.js +1 -1
- package/node_modules/@m0saic/dsl-file-formats/dist/cjs/m0/serializeM0File.js +2 -2
- package/node_modules/@m0saic/dsl-file-formats/dist/cjs/m0c/m0cFile.js +3 -3
- package/node_modules/@m0saic/dsl-file-formats/dist/cjs/types.js +1 -1
- package/node_modules/@m0saic/dsl-file-formats/package.json +1 -1
- package/node_modules/@m0saic/dsl-stdlib/dist/cjs/builders/bakeM0cInsets.js +1 -0
- package/node_modules/@m0saic/dsl-stdlib/dist/cjs/builders/index.js +1 -1
- package/node_modules/@m0saic/dsl-stdlib/package.json +1 -1
- package/node_modules/@m0saic/knowledge/LICENSE +21 -0
- package/node_modules/@m0saic/knowledge/README.md +71 -0
- package/node_modules/@m0saic/knowledge/dist/index.js +1 -0
- package/node_modules/@m0saic/knowledge/docs/README.md +60 -0
- package/node_modules/@m0saic/knowledge/docs/file-formats/m0-iteration-protocol.md +120 -0
- package/node_modules/@m0saic/knowledge/docs/file-formats/m0p-and-custom-field.md +195 -0
- package/node_modules/@m0saic/knowledge/docs/handbook/README.md +27 -0
- package/node_modules/@m0saic/knowledge/docs/handbook/composition-arithmetic.md +278 -0
- package/node_modules/@m0saic/knowledge/docs/handbook/dsl-complexity.md +75 -0
- package/node_modules/@m0saic/knowledge/docs/handbook/dsl-rules.md +367 -0
- package/node_modules/@m0saic/knowledge/docs/handbook/feasibility-precision-quantization.md +591 -0
- package/node_modules/@m0saic/knowledge/docs/handbook/m0-construction-methods.md +201 -0
- package/node_modules/@m0saic/knowledge/docs/handbook/precision-tiers.md +84 -0
- package/node_modules/@m0saic/knowledge/docs/m0saic-thesis.md +95 -0
- package/node_modules/@m0saic/knowledge/docs/runtime/README.md +24 -0
- package/node_modules/@m0saic/knowledge/docs/runtime/agent-at-the-canvas.md +108 -0
- package/node_modules/@m0saic/knowledge/docs/runtime/cli-usage.md +475 -0
- package/node_modules/@m0saic/knowledge/docs/runtime/ffmpeg-expression-limits.md +117 -0
- package/node_modules/@m0saic/knowledge/docs/runtime/reduce-to-one.md +96 -0
- package/node_modules/@m0saic/knowledge/docs/skills/README.md +40 -0
- package/node_modules/@m0saic/knowledge/docs/skills/axis-and-geometry.md +103 -0
- package/node_modules/@m0saic/knowledge/docs/skills/dsl-stdlib-method-catalog.md +7 -0
- package/node_modules/@m0saic/knowledge/docs/skills/identity.md +123 -0
- package/node_modules/@m0saic/knowledge/docs/skills/labels-and-masks.md +170 -0
- package/node_modules/@m0saic/knowledge/docs/skills/m0saic-string-generation.md +251 -0
- package/node_modules/@m0saic/knowledge/docs/skills/more-atoms-not-bigger-atoms.md +77 -0
- package/node_modules/@m0saic/knowledge/docs/skills/overlay-semantics.md +194 -0
- package/node_modules/@m0saic/knowledge/docs/skills/parse-apis.md +79 -0
- package/node_modules/@m0saic/knowledge/docs/skills/passthrough-semantics.md +136 -0
- package/node_modules/@m0saic/knowledge/docs/skills/structural-construction.md +86 -0
- package/node_modules/@m0saic/knowledge/docs/skills/text-in-templates.md +126 -0
- package/node_modules/@m0saic/knowledge/docs/skills/zero-overlay-analysis.md +87 -0
- package/node_modules/@m0saic/knowledge/docs/templates/README.md +65 -0
- package/node_modules/@m0saic/knowledge/docs/templates/capability-templates.md +72 -0
- package/node_modules/@m0saic/knowledge/docs/templates/construction-strategy.md +329 -0
- package/node_modules/@m0saic/knowledge/docs/templates/data-pipeline.md +324 -0
- package/node_modules/@m0saic/knowledge/docs/templates/emission-patterns.md +130 -0
- package/node_modules/@m0saic/knowledge/docs/templates/geometry-recipes.md +248 -0
- package/node_modules/@m0saic/knowledge/docs/templates/layout-contract.md +168 -0
- package/node_modules/@m0saic/knowledge/docs/templates/output-resolution-tree.md +210 -0
- package/node_modules/@m0saic/knowledge/docs/templates/patterns/case-study-lessons.md +69 -0
- package/node_modules/@m0saic/knowledge/docs/templates/patterns/perf-authoring-rules.md +100 -0
- package/node_modules/@m0saic/knowledge/docs/templates/patterns/primitive-extraction-pattern.md +103 -0
- package/node_modules/@m0saic/knowledge/docs/templates/philosophy-and-contract.md +310 -0
- package/node_modules/@m0saic/knowledge/docs/templates/recursion-nested-rendering.md +154 -0
- package/node_modules/@m0saic/knowledge/docs/templates/reference/grid.md +104 -0
- package/node_modules/@m0saic/knowledge/docs/templates/reference/json-prop-type.md +169 -0
- package/node_modules/@m0saic/knowledge/docs/templates/reference/mosaic-color.md +81 -0
- package/node_modules/@m0saic/knowledge/docs/templates/reference/mosaic-placement-props.md +103 -0
- package/node_modules/@m0saic/knowledge/docs/templates/reference/prop-bindings.md +338 -0
- package/node_modules/@m0saic/knowledge/docs/templates/reference/template-flags.md +236 -0
- package/node_modules/@m0saic/knowledge/docs/templates/render-lifecycle.md +117 -0
- package/node_modules/@m0saic/knowledge/docs/templates/rendering-model-contract.md +392 -0
- package/node_modules/@m0saic/knowledge/docs/templates/standalone-pack-authoring.md +309 -0
- package/node_modules/@m0saic/knowledge/docs/templates/theming.md +81 -0
- package/node_modules/@m0saic/knowledge/docs/templates/ui-controls.md +150 -0
- package/node_modules/@m0saic/knowledge/package.json +6 -0
- package/node_modules/@m0saic/momo-types/README.md +109 -0
- package/node_modules/@m0saic/momo-types/dist/agent.js +1 -6
- package/node_modules/@m0saic/momo-types/dist/context.js +1 -1
- package/node_modules/@m0saic/momo-types/package.json +1 -1
- package/node_modules/@m0saic/platform/README.md +3 -0
- package/node_modules/@m0saic/platform/dist/cjs/index.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/mosaic/outputKind/outputKind.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/mosaic/propBindings/index.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/mosaic/propBindings/propBindings.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/mosaic/validate/validateSources.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/packages/mosaicPackages.js +1 -0
- package/node_modules/@m0saic/platform/dist/cjs/paths/m0saicRoot.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/telemetry/lifecycle.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/telemetry/preview.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/telemetry/sender.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/telemetry/usageRecorder.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/telemetry/usageStore.js +3 -3
- package/node_modules/@m0saic/platform/dist/cjs/template-repos/index.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/template-repos/loadTemplateRepoFromPath.js +4 -4
- package/node_modules/@m0saic/platform/dist/cjs/template-repos/templateCatalogSidecars.js +2 -0
- package/node_modules/@m0saic/platform/dist/cjs/templateCatalog/index.js +1 -0
- package/node_modules/@m0saic/platform/dist/cjs/templateCatalog/templateCatalog.js +1 -0
- package/node_modules/@m0saic/platform/dist/cjs/toolchain/ffmpeg/baseline.json +25 -97
- package/node_modules/@m0saic/platform/dist/cjs/toolchain/ffmpeg/index.js +1 -1
- package/node_modules/@m0saic/platform/dist/cjs/toolchain/ffmpeg/install.js +2 -2
- package/node_modules/@m0saic/platform/dist/cjs/toolchain/goldenFfmpeg.js +6 -6
- package/node_modules/@m0saic/platform/package.json +1 -1
- package/node_modules/@m0saic/product/dist/communityRelease.js +1 -1
- package/node_modules/@m0saic/product/dist/freeTierLicense.js +1 -1
- package/node_modules/@m0saic/product/dist/index.js +1 -1
- package/node_modules/@m0saic/product/dist/licenseActivationNotice.js +1 -0
- package/node_modules/@m0saic/product/dist/licenseFile.js +1 -0
- package/node_modules/@m0saic/product/dist/licenseToken.js +1 -1
- package/node_modules/@m0saic/product/dist/makeScratchPath.js +1 -0
- package/node_modules/@m0saic/product/dist/postRenderWrapper.js +1 -1
- package/node_modules/@m0saic/product/dist/publicKeys.js +1 -1
- package/node_modules/@m0saic/product/dist/revokedKeys.js +1 -1
- package/node_modules/@m0saic/product/dist/upstreamDefaults.js +1 -1
- package/node_modules/@m0saic/product/dist/workspaceScaffold.js +1 -0
- package/node_modules/@m0saic/template-utils/dist/brand/hello-world/helloWorld.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/geometry-contract/frameResolution.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/geometry-contract/index.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/geometry-contract/layoutConstraint.js +2 -2
- package/node_modules/@m0saic/template-utils/dist/m0saic/loadSession.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/render/createDesignContext.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/sources/makeErrorMosaic.js +2 -2
- package/node_modules/@m0saic/template-utils/dist/sources/svgTextSource.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/template/auditRenderedTemplate.js +5 -5
- package/node_modules/@m0saic/template-utils/dist/template/auditSchemaConventions.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/template/defineMosaicTemplate.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/template/resolveTemplateOutputHints.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/template/templateCatalogStore.js +1 -0
- package/node_modules/@m0saic/template-utils/dist/template/templateConventions.js +4 -4
- package/node_modules/@m0saic/template-utils/dist/template/templateRegistry.js +3 -3
- package/node_modules/@m0saic/template-utils/dist/template/validateTemplateProps.js +1 -1
- package/node_modules/@m0saic/template-utils/dist/text/fitText.js +6 -6
- package/node_modules/@m0saic/template-utils/package.json +1 -1
- package/node_modules/@m0saic/templates/NOTICE +9 -0
- package/node_modules/@m0saic/templates/dist/catalog.js +1 -0
- package/node_modules/@m0saic/templates/dist/freeze.js +8 -8
- package/node_modules/@m0saic/templates/dist/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/_shared/canvas-handles.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/_shared/stand-in.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/agents/commit-feed/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/agents/commit-feed/v2/commit-feed.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/agents/commit-feed/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/agents/trace-timeline/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/agents/trace-timeline/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/agents/trace-timeline/v2/trace-timeline.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/_shared/alpine-conventions.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/bar-graph/v2/bar-graph.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/bar-graph/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/commit-feed/v3/commit-feed.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/commit-feed/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/contributor-table/v2/contributor-table.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/contributor-table/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/donut/v4/donut.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/donut/v4/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/heatmap/v3/heatmap.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/heatmap/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/kpi-card/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/kpi-card/v3/kpi-card.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/leaderboard/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/leaderboard/v2/leaderboard.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/line-chart/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/line-chart/v3/line-chart.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/progress-card/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/progress-card/v2/progress-card.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/stat-card/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/stat-card/v2/stat-card.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/timeline/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/timeline/v3/timeline.js +4 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/treemap/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/alpine/treemap/v3/treemap.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/benchmark/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/benchmark/report/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/benchmark/report/v2/report.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/brand/business-card/v2/business-card.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/brand/business-card/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/brand/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/brand/logo/v4/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/brand/logo/v4/logo_runner.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/charts/bar-graph/v3/bar-graph.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/charts/bar-graph/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/charts/donut/v5/donut.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/charts/donut/v5/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/charts/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/charts/line-chart/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/charts/line-chart/v2/line-chart.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/charts/stat-card/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/charts/stat-card/v2/stat-card.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/code/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/code/snippet-morph/v2/snippet-morph.js +3 -0
- package/node_modules/@m0saic/templates/dist/m0saic/collage/image-collage/v2/image-collage.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/collage/image-collage/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/collage/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/dsl-tutorial/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/dsl-tutorial/v2/dsl-tutorial.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/dsl-tutorial/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/github/year-card/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/github/year-card/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/github/year-card/v2/year-card.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/hero/ffmpeg-pulse/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/hero/ffmpeg-pulse/runner/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/hero/ffmpeg-pulse/runner/v2/runner.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/barcode/v2/barcode.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/barcode/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/blur-regions/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/blur-regions/v1/tutorial.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/blur-regions/v2/blur-regions.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/blur-regions/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/highlights/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/highlights/v2/highlights.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/highlights/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/logo-animate/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/logo-animate/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/logo-animate/v2/logo-animate.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/metadata-stamp/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/metadata-stamp/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/metadata-stamp/v2/metadata-stamp.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/qr/code/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/qr/code/v2/qr-code.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/qr/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/qr/stamp/v2/qr-stamp-custom.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/screencap_grid/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/screencap_grid/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/screencap_grid/v3/screencap-grid.js +4 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/screencap_grid_aspect_safe/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/screencap_grid_aspect_safe/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/screencap_grid_aspect_safe/v2/screencap-grid-aspect-safe.js +3 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/scroll_wall/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/scroll_wall/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/scroll_wall/v2/scroll-wall.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/subtitle-burn/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/subtitle-burn/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/subtitle-burn/v2/subtitle-burn.js +4 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/trickplay/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/trickplay/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/trickplay/v2/trickplay.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/video_to_png_sequence/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/video_to_png_sequence/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/video_to_png_sequence/v2/video-to-png-sequence.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/watermark/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/media/watermark/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/media/watermark/v2/watermark.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/primitives/grid/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/primitives/grid/v3/grid.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/social/quote-card/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/social/quote-card/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/social/quote-card/v2/quote-card.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/story/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/story/narrated-chapters/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/story/narrated-chapters/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/story/narrated-chapters/v2/narrated-chapters.js +4 -0
- package/node_modules/@m0saic/templates/dist/m0saic/story/scrapbook/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/story/scrapbook/v2/props.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/story/scrapbook/v2/scrapbook.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/theming/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/theming/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/theming/v2/theming.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/web/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/m0saic/web/page-skeleton/v2/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/web/page-skeleton/v2/page-skeleton.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/wireframe/base/v3/index.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/wireframe/base/v3/wireframe.js +1 -0
- package/node_modules/@m0saic/templates/dist/m0saic/wireframe/index.js +1 -1
- package/node_modules/@m0saic/templates/dist/repo.js +1 -1
- package/node_modules/@m0saic/templates/dist/template-catalog.json +5429 -0
- package/node_modules/@m0saic/templates/dist/template-registry.js +1 -1
- package/node_modules/@m0saic/templates/dist/web.js +1 -1
- package/node_modules/@m0saic/templates/package.json +1 -1
- package/node_modules/@m0saic/templates/template-catalog.json +5429 -0
- package/node_modules/@m0saic/templates/template-manifest.json +1030 -286
- package/node_modules/@m0saic/templates/web-template-ids.json +38 -0
- package/node_modules/@m0saic/templates-advanced/NOTICE +9 -0
- package/node_modules/@m0saic/text/package.json +1 -1
- package/node_modules/@m0saic/types/dist/analytics/consent.js +1 -1
- package/node_modules/@m0saic/types/dist/analytics/event.js +1 -1
- package/node_modules/@m0saic/types/dist/analytics/usageMetrics.js +1 -1
- package/node_modules/@m0saic/types/dist/identifiers/identifiers.js +1 -1
- package/node_modules/@m0saic/types/dist/telemetry/ffmpegFailure.js +1 -1
- package/node_modules/@m0saic/types/dist/template/template.js +1 -1
- package/node_modules/@m0saic/types/package.json +1 -1
- package/node_modules/@m0saic/types-internal/dist/analytics/featureKeys.js +1 -1
- package/package.json +13 -11
- package/resources/starter-base/starter-base.json +10 -0
- package/resources/starter-base/starter-base.tgz +0 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
# m0saic CLI usage
|
|
2
|
+
|
|
3
|
+
> Regenerated 2026-07-29 from the CLI source (not published) — re-verify with
|
|
4
|
+
> `m0saic --help` / `grep -c '.command(' the CLI source (not published) (14 as of
|
|
5
|
+
> 2026-07-29, **2 of them dev-gated** — `browse-templates` and `momo`; a 15th
|
|
6
|
+
> command, `telemetry`, registers via a helper — see below). So: 12 public
|
|
7
|
+
> commands + 2 dev-gated + `telemetry`.
|
|
8
|
+
>
|
|
9
|
+
> **2026-09-16:** `doctor` (added after this snapshot, dev-gated at 0.1.0) is now
|
|
10
|
+
> **public** — see its row; `browse-templates` and `momo` remain the only two
|
|
11
|
+
> `if (DEV_MODE)` commands. Public set is locked by `PUBLIC_COMMANDS` in
|
|
12
|
+
> the CLI source (not published) (15 incl. `doctor`, `hello-world`).
|
|
13
|
+
|
|
14
|
+
Source of truth: [the CLI source (not published)](the CLI source (not published))
|
|
15
|
+
(~5,866 lines). Inline-DSL arg parsing: [the CLI source (not published)](the CLI source (not published)).
|
|
16
|
+
Root `COMMANDS.md` (monorepo document, not published) documents the inline-DSL shorthand + test tiers.
|
|
17
|
+
|
|
18
|
+
## Entry routing — inline-DSL mode is first-class
|
|
19
|
+
|
|
20
|
+
Before commander ever runs, `index.ts:~7279-7285` inspects `process.argv[2]`:
|
|
21
|
+
`isInlineM0()` (`inlineDsl.ts:36-41`) treats ANY first arg that is not a flag and
|
|
22
|
+
not in `KNOWN_SUBCOMMANDS` as an inline m0 string and dispatches to
|
|
23
|
+
`handleInlineDsl` instead of `program.parseAsync`.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
m0saic "2(1,1)" # static wireframe → output.png (default mode "wire")
|
|
27
|
+
m0saic "2(1,1)" --anim # animated wireframe → output.mp4
|
|
28
|
+
m0saic "2(1,1)" --wire # explicit static (same as default)
|
|
29
|
+
m0saic layout.m0 # .m0 / .m0c paths also accepted (index.ts:~7184-7270)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- Args after the string parse via `parseInlineArgs` (`inlineDsl.ts:123`): `-w/-h`
|
|
33
|
+
(default 1920×1080), `-o`, `--fps`, `--durationMs`, `--props`, `--save-mosaic`,
|
|
34
|
+
`--save-m0`, `--prefer-pretty-m0`/`--prefer-canonical-m0`, `--disable-ui`,
|
|
35
|
+
`--format`, `--alpha`, `--validate-only`, `--report`, `--toolchain`, plus the
|
|
36
|
+
dev-gated dump flags (below).
|
|
37
|
+
- The string is validated with `validateM0String` before render (index.ts:~7222);
|
|
38
|
+
whitespace is stripped. Always shell-quote the DSL (parens/brackets).
|
|
39
|
+
- Output extension is coerced to match mode (`resolveInlineOutput`,
|
|
40
|
+
`inlineDsl.ts:86` — `--anim -o out.png` → `out.mp4`).
|
|
41
|
+
- Mode maps onto the wireframe handlers: `wire` → `handleWireframe`, `anim` →
|
|
42
|
+
`handleAnimatedWireframe` (index.ts:~7264-7266).
|
|
43
|
+
|
|
44
|
+
## Command table
|
|
45
|
+
|
|
46
|
+
18 `.command(` registrations in `index.ts` + `telemetry` registered by
|
|
47
|
+
`registerTelemetryCommand(program)` (index.ts:~7138 → `utils/telemetry.ts:~372`).
|
|
48
|
+
Two of the 18 sit inside `if (DEV_MODE) { … }` and are absent from the public
|
|
49
|
+
help — see the DEV-GATED rows below.
|
|
50
|
+
|
|
51
|
+
> **Line numbers are loose signposts, written `~NNNN`** (founder ruling
|
|
52
|
+
> 2026-09-25). `index.ts` is ~7,200 lines and every number in this doc had drifted
|
|
53
|
+
> within weeks. **The greppable symbol is the anchor; the number only says
|
|
54
|
+
> roughly where to look.** A number that has moved is not a defect and does not
|
|
55
|
+
> earn a fix pass — correct one when you are editing that row anyway, and
|
|
56
|
+
> otherwise leave it.
|
|
57
|
+
|
|
58
|
+
| Command (index.ts line) | What it does |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `make <input>` (~5095) | Primary render: template id / `.mosaic` / `.mosaicx` → video or image. Full flag surface below. |
|
|
61
|
+
| `hello-world` | The first render — a thin alias for `make @m0saic/hello-world/v1` (the brand card; output defaults to `hello-world.mp4`). With `--template-repo <path...>` / `--community-repo <path>` it renders the loaded repo's **front door** instead: the first repo (load order) whose `repo.helloWorld` names a template that registered, announced as `Front door: <id> — <repo>'s hello-world`; no repos, or none that name one → the core card with a one-line why. Takes `-o -w -h --fps --durationMs --props --quiet --verbose` (no engine surface). Picker: the CLI source (not published). |
|
|
62
|
+
| `make-wireframe` (~5462) | Static wireframe PNG from `--m0 <string>` or `--mfile <path>`. |
|
|
63
|
+
| `make-wireframe-animated` (~5568) | Animated wireframe MP4 from `--m0`/`--mfile`; extra `--disable-ui`. |
|
|
64
|
+
| `flatten <input>` (~5680) | Inline all `type:mosaic` children of a `.mosaic`/template into one flat JSON doc — no render. |
|
|
65
|
+
| `resolve <input>` (~5800) | `.mosaicx` recipe → resolved `.mosaic` provenance doc, no ffmpeg; `--flatten` also inlines children. |
|
|
66
|
+
| `list-templates` (~5946) | Print registered template ids (`--json`); annotates primitive/internal/deprecated. |
|
|
67
|
+
| `doctor <repoDir>` | **Public since 0.2.0** (dev-gated at 0.1.0; founder ruling 2026-09-16, BURN-DOWN D5 → publish). Run the template conventions over a template repo folder — the same checks its build gate (`tools/check-registry.mjs`) runs, from outside (agents, reviewers, forks, CI on a fork): definition-time + render-time conventions (the 13 throw-posture ones incl. `latticeSmooth`) and, when the repo commits `layout-fingerprints/` or `.layout.m0` sidecars, the fingerprint diff. `--json` (one object: `ok, repo, mode, loadDiagnostics, rendered, skipped, errors, warnings, notes, fingerprints, conventions`), `--sweep` (also render on the standard 1080p canvases → `canvasEnvelope`), `--entry <path>`, `--src <dir>`. Loads through `loadTemplateRepoFromPath` under the external origin scope, so conventions RECORD rather than throw and one bad template never hides the rest. **Runs the repo's template module bodies in-process** — prints a trust warning to stderr (not under `--json`). Exit 1 on any error-severity finding or a fatal load diagnostic. It is the pack-publishing contract for community/starter authors ("the publish requirement for packs"). Impl: the CLI source (not published); locked public by `__tests__/cli.surface.test.js`. |
|
|
68
|
+
| `browse-templates` (~6033) | **DEV-GATED** (whole command inside `if (DEV_MODE)`, 4792): interactive TTY picker (template → variant → confirm → delegates to `make`). It drives the E2E variant matrix and writes to `test-output/` — a development harness, not a user surface. |
|
|
69
|
+
| `momo <message…>` (~6282) | **DEV-GATED** (whole command inside `if (DEV_MODE)`, 5040): relay English geometry instruction to Momo in a running Mosaic Desktop over the loopback bridge; exit 0 applied / 2 not-applied / 1 couldn't-run. |
|
|
70
|
+
| `init <name>` (~6464) | Scaffold a template workspace — the compact starter twin, renamed to the user's handle. `--dir`, `--handle`, `--display-name`. Shares ONE scaffold with Desktop's Start pane (`scaffoldTemplateWorkspace` in `@m0saic/product`), so the two cannot drift. Deliberately does NOT write the trust store: loading an external repo is the user's consent, recorded by the app in `~/m0saic/template-trust.json`. Prints the install / build / fingerprint line and the Add-source hint. |
|
|
71
|
+
| `mcp` (~6538) | Run the CLI as an **MCP server** over stdio — the agent-facing surface. See below. |
|
|
72
|
+
| `open [file]` (~6608) | Open a file in Mosaic Desktop, or `--template` / `--make` to open the Make page via the bridge. See below. |
|
|
73
|
+
| `setup` (~6830) | Download + install the pinned ffmpeg toolchain (`--gpl` default / `--lgpl` / `--yes` / `--platform-key`). Idempotent: detects installed golden slot or a PATH ffmpeg with libx264. **The only path that downloads** — renders never do. TTY asks `Download the pinned GPL ffmpeg build now?`; non-TTY / `CI` need explicit approval — `--yes` (or the `--gpl` / `--lgpl` repair flags), otherwise `No terminal to ask for approval on.` + exit 1, nothing downloaded. Ends `✓ ffmpeg is ready. Now run your m0saic command again.` |
|
|
74
|
+
| `activate <key>` (~7000) | Validate + store a license key at `~/m0saic/license.json` (`M0SAIC_PRODUCT_KEY` env wins over the file). **A VERIFIED key — valid, in grace, expired or revoked — also sends ONE notice to m0saic.io from a detached worker (`utils/licenseActivation.ts` → `licenseActivationWorker.js`): the key's `keyId`, the outcome, `surface: "cli"`, the CLI's major.minor. Never the token, the email or the install id. Sent in EVERY telemetry mode — the one signal outside them (founder ruling 2026-09-26); honours `M0SAIC_TELEMETRY_ENDPOINT=off`, `CI` (unless the endpoint came from env) and dormancy (a dev checkout never sends); ignores the mode and `DO_NOT_TRACK`. The command prints "Told m0saic.io this key was used …" after the verdict, and `--help` says so. An unverified key sends nothing.** `TELEMETRY.md` §1.16. |
|
|
75
|
+
| `license` (~6991) | Show tier/holder/expiry; `--remove` returns to free tier. |
|
|
76
|
+
| `update` (~7050) | Check npm for a newer release; offers `npm i -g m0saic@latest`. |
|
|
77
|
+
| `versions` (~7116) | Print **every bundled `@m0saic/*` package**, grouped by tier (language / substrate / product — the CLI bundles no community package) + ffmpeg baseline/runtime + resolved toolchain. `--json`: `packages` holds ALL bundled packages (a superset of the old `templates`/`types` pair, so scripts keep working). Classification comes from `@m0saic/platform` `describeMosaicPackage`, shared with Desktop's Tools → About this build (2026-09-26). |
|
|
78
|
+
| `telemetry` (via helper) | Subcommands `status` (default) · `set-mode <standard\|local-only\|ghost>` · `list` · `preview` · `flush` · `clear`. Since 0.2.0 PUBLISHED builds transmit (Standard mode): day summary + today-so-far rollups after renders via a detached worker, to `https://m0saic.io/api/telemetry`. Workspace builds are dormant. Gates for harnesses: `M0SAIC_TELEMETRY=ghost` (nothing recorded), `M0SAIC_TELEMETRY_ENDPOINT=off` (nothing sent), `CI` (no send unless the endpoint is set by env). **Modes govern usage telemetry only: `activate` is in `CLI_USAGE_SKIPPED_COMMANDS`** — its notice is identity-less, and the rollup deliberately carries no `cli.command.activate` counter beside it (the pairing would link an install id to a key id). `status` / `preview` cannot list the notice: it is never queued. Full reference: `TELEMETRY.md` at the repo root (§1.16 for the notice). |
|
|
79
|
+
|
|
80
|
+
> **`decode-watermark` is GONE** (removed 2026-07-28). Recovering a forensic
|
|
81
|
+
> watermark is now an ordinary template — `@m0saic/forensic/watermark/verify/v1`,
|
|
82
|
+
> run through `make` — because a CLI can't grow a bespoke command per template
|
|
83
|
+
> family. The old `--ffmpeg <path>` override it carried is now the template's
|
|
84
|
+
> `ffmpegPath` prop.
|
|
85
|
+
|
|
86
|
+
## `make` input routing (index.ts:~5340-5372)
|
|
87
|
+
|
|
88
|
+
1. Extension `.mosaic` → `handleMosaicFile` — parse JSON renderable, resolve
|
|
89
|
+
relative media against the file's dir, plan + render.
|
|
90
|
+
2. Extension `.mosaicx` → `handleMosaicxFile` (~4214) — the **resolve-then-render
|
|
91
|
+
branch**: absolutize asset paths → apply the doc's `runner` block as option
|
|
92
|
+
defaults (explicit flags win) → sibling `.m0v` auto-discovery → route
|
|
93
|
+
`--inputs`/`--input-dir` into the single `template_invocation`'s
|
|
94
|
+
`props.sourceIds` (ambiguous multi-invocation → error; zero inputs on an
|
|
95
|
+
input-requiring template → renders a usage-card and exits non-zero) →
|
|
96
|
+
`resolveMosaicx` → write resolved doc to a tmp `.mosaic` → delegate to
|
|
97
|
+
`handleMosaicFile` (~4460, defined ~4475) so the post-resolve render path is shared.
|
|
98
|
+
**Two roots accepted** (2026-08-14): `mosaicx_document` and
|
|
99
|
+
`mosaicx_pipeline` (a root-level template chain — see
|
|
100
|
+
`templates/data-pipeline.md`). The header echoes which one it read
|
|
101
|
+
(`kind: mosaicx_pipeline`). A chain root has no top-level `sources`, so the
|
|
102
|
+
`--inputs` routing and the usage-card gap detection above are inert for it;
|
|
103
|
+
`runner` applies to both. Same for `resolve <input>`.
|
|
104
|
+
**Duration is an ASK on this path** (2026-09-05): `--durationMs ??
|
|
105
|
+
wrapper.durationMs` reaches the template as `userIntent.durationMs` via
|
|
106
|
+
`mosaicxUserIntent` (`mosaicxRunner.ts:405`) on both `make` and `resolve`, so a
|
|
107
|
+
self-timing template FITS its walk to the length (as Make does) instead of
|
|
108
|
+
being trimmed to it. Mint ledger wrappers mirroring the template's natural
|
|
109
|
+
length unless the variant is deliberately pinned.
|
|
110
|
+
3. No extension + starts with `@` → `handleTemplateMake` — template id, merge
|
|
111
|
+
`--props` over `defaultProps`, render.
|
|
112
|
+
4. Anything else → error, exit 1.
|
|
113
|
+
|
|
114
|
+
## Exit codes (2026-09-15)
|
|
115
|
+
|
|
116
|
+
| Code | Meaning | File at `-o`? |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| `0` | Success — the output is the render asked for. | Yes |
|
|
119
|
+
| `1` | Failure — plan build threw, ffmpeg exited non-zero, validation failed, zero commands. | No / unusable |
|
|
120
|
+
| `2` | `momo` ran but did not apply a change. | n/a |
|
|
121
|
+
| `3` | **RENDER DEGRADED** — the renderable carried `engine.renderStatus: "error"`, so the output is an **error mosaic**. | **Yes**, valid media |
|
|
122
|
+
|
|
123
|
+
**Why 3 exists.** A template that hits bad input does not crash: it returns
|
|
124
|
+
`makeErrorMosaic(...)`, a readable card stamped `engine.renderStatus: "error"`.
|
|
125
|
+
That card renders, so the CLI used to write it and exit 0 — a caller whose only
|
|
126
|
+
success test was "did a file appear at the expected path?" reported success on a
|
|
127
|
+
picture of an error. 3 is deliberately not 1: exit 1 means "there is no output,
|
|
128
|
+
retry or clean up", which is false here. The engine still never aborts on the
|
|
129
|
+
marker — it renders, writes the file, and *then* the CLI reports.
|
|
130
|
+
|
|
131
|
+
**Detection** (`src/utils/collectRenderErrors.ts`) walks the WHOLE renderable
|
|
132
|
+
tree for the marker: document level, source level, nested `children`
|
|
133
|
+
(recursively), and pipeline `steps` (dispatching per step, so a nested pipeline
|
|
134
|
+
is walked too). **One error mosaic anywhere in the tree degrades the whole run** —
|
|
135
|
+
a batch where 4 of 5 steps are fine still exits 3, because one deliverable is an
|
|
136
|
+
error card. `errors[].path` in the sidecar (`children.hero.sources[0]`,
|
|
137
|
+
`steps[1].sources[0]`) says which.
|
|
138
|
+
|
|
139
|
+
> ⚠️ Historical: the walker read `doc.config?.sources`, but
|
|
140
|
+
> `MosaicDocument.sources` was hoisted out of `config` long ago — so every
|
|
141
|
+
> source-level marker (exactly where `makeErrorMosaic` puts it) was invisible and
|
|
142
|
+
> every error-mosaic render exited 0. `mosaicxRunner` hand-promoted its error to
|
|
143
|
+
> doc level to work around it; both the bug and the workaround are gone.
|
|
144
|
+
|
|
145
|
+
**Classification** (`src/utils/renderOutcome.ts` — the single decision point; all
|
|
146
|
+
12 report call sites in `index.ts` route through it):
|
|
147
|
+
|
|
148
|
+
- **Hard errors beat engine errors.** A run with both is 1, not 3.
|
|
149
|
+
- A **zero-command plan** counts its engine errors as hard — there is no output
|
|
150
|
+
to call degraded — so that path stays 1.
|
|
151
|
+
- Free vs paid tier is **orthogonal**. The marker is read off the document, not
|
|
152
|
+
the file; the free-tier QR wrap runs before classification, so on free tier the
|
|
153
|
+
error card ships stamped and still exits 3. A stamp failure is swallowed as a
|
|
154
|
+
warning and never changes the exit code.
|
|
155
|
+
|
|
156
|
+
With `--report` the same verdict is machine-readable, so a caller that parses the
|
|
157
|
+
sidecar never needs the exit code and a caller that reads exit codes never needs
|
|
158
|
+
the JSON:
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{ "ok": false, "exitCode": 3, "renderStatus": "degraded",
|
|
162
|
+
"renderErrorCodes": ["ENGINE_ERROR"],
|
|
163
|
+
"errors": [{ "code": "ENGINE_ERROR", "message": "Quote Card: quote must not be empty", "path": "sources[0]" }] }
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## `make` flags
|
|
167
|
+
|
|
168
|
+
**Core** — `-w/--width` and `-h/--height` are `requiredOption`s. Then:
|
|
169
|
+
`-o/--output` (defaults `out.mp4` / `out.png`, index.ts:~172-173), `--fps` (1–120),
|
|
170
|
+
`--durationMs` (>0), `--format`/`--output-kind` (`video|image`),
|
|
171
|
+
`--alpha`/`--no-alpha`, `--props <jsonOrPath>` (inline JSON **or** `@path/to/json`
|
|
172
|
+
— `utils/readJsonArg.ts:18` strips the `@` and reads the file),
|
|
173
|
+
`--validate-only` (exit 0/1/3, no render — 3 = the renderable IS an error
|
|
174
|
+
mosaic; prints `Validation DEGRADED`), `--report` (`.output.json` /
|
|
175
|
+
`.validate.json` sidecars, both carrying `renderStatus` + `renderErrorCodes`),
|
|
176
|
+
`--save-mosaic [path]`, `--save-m0 [path]`,
|
|
177
|
+
`--keep-temp`, `--quiet`, `--verbose`, `--prefer-pretty-m0` /
|
|
178
|
+
`--prefer-canonical-m0` (printed-m0 form only; note: NOT `--prefer-*-m0saic`),
|
|
179
|
+
`--background-color <color>`, `--template-repo <path...>` +
|
|
180
|
+
`--template-repo-entry <file>` (external template repos), `--community-repo <path>`
|
|
181
|
+
(ONE checkout of the official community repo — see the community gate below).
|
|
182
|
+
|
|
183
|
+
**Encode surface** (index.ts:~4231-4338, mirrors the Make page's Advanced panel;
|
|
184
|
+
precedence: flags > `.m0v` preset > doc-on-disk > engine default):
|
|
185
|
+
`--target <preset>` (`web-mp4|web-webm|alpha-mov|image-png|image-jpeg|animated-gif|audio-mp3|audio-wav`),
|
|
186
|
+
`--container`, `--video-codec`, `--audio-codec`, `--pixel-format`, `--bitrate`
|
|
187
|
+
(CRF wins on conflict), `--crf`, `--encoder-preset`, `--encoder-profile`,
|
|
188
|
+
`--encoder-level`, `--encoder-options <k=v,…>`, `--gop-size`, `--audio-bitrate`,
|
|
189
|
+
`--audio-sample-rate`, `--audio-channel-layout`, `--no-audio` (`-an`),
|
|
190
|
+
`--color-space`/`--color-range`/`--color-primaries`/`--color-transfer`
|
|
191
|
+
(metadata-only), `--metadata-title`/`-description`/`-author`/`-copyright`/`-comment`.
|
|
192
|
+
|
|
193
|
+
**Batching / multi-output**: `--inputs <files...>` (populates `sourceIds`; wins
|
|
194
|
+
over `--input-dir`), `--input-dir <path>` (+ `--recursive` for depth-first walk),
|
|
195
|
+
`--output-pattern <pattern>` (tokens `{{base}} {{ext}} {{stepName}} {{index}}
|
|
196
|
+
{{i}} {{date}} {{batch}} {{label}}`; collisions get `-1,-2,…`), `--batch <name>`.
|
|
197
|
+
|
|
198
|
+
**`.m0v`**: `--m0v <path>` loads a Mosaic Vocabulary file two ways — named
|
|
199
|
+
outputs onto `ctx.userIntent.outputs` (template-consultative) AND a post-render
|
|
200
|
+
merge onto the renderable **by index** when entry counts match
|
|
201
|
+
(index.ts:~4218-4221; `BaseRenderOptions` docstring ~541-557).
|
|
202
|
+
|
|
203
|
+
**Toolchain**: `--toolchain <name>` is a **global program option**
|
|
204
|
+
(index.ts:~526), not make-specific — a named entry from `m0saic.local.json`, with
|
|
205
|
+
implicit `gpl`/`lgpl` golden slots merged in. Resolution precedence: `--toolchain`
|
|
206
|
+
flag > `M0SAIC_TOOLCHAIN` env > config `defaultToolchain` > PATH/golden fallback
|
|
207
|
+
(`utils/toolchainConfig.ts:129`). There is **no** `--ffmpeg` anywhere on the CLI
|
|
208
|
+
any more (it left with `decode-watermark`) — the equivalent is the verify
|
|
209
|
+
template's `ffmpegPath` prop; `--platform-key` only on `setup`.
|
|
210
|
+
|
|
211
|
+
**No-ffmpeg gate** (`utils/ensureFfmpeg.ts` via `ensureRenderToolchain()`, index.ts
|
|
212
|
+
~404, first thing in every render handler): resolved ffmpeg fails to probe → the
|
|
213
|
+
4-line `ffmpeg isn't detected.` message (points at `setup`) and **exit 1** — TTY,
|
|
214
|
+
piped and CI alike; no prompt, no inline download, no auto-install (founder
|
|
215
|
+
ruling 2026-09-16; supersedes cli-v1-publish.md Phase 2). `setup` is the only
|
|
216
|
+
downloader, and it too never fetches without approval (TTY prompt, or `--yes`).
|
|
217
|
+
Spell every `setup` hint with `cliSetupCommand()` (`utils/invocation.ts`):
|
|
218
|
+
`npx m0saic setup` under npx, `m0saic setup` installed.
|
|
219
|
+
|
|
220
|
+
**Perf**: `--perf [path]` writes a `.perf.json` sidecar — per-ffmpeg-command
|
|
221
|
+
timing rolled up by mosaic node (names the bottleneck panel/template).
|
|
222
|
+
|
|
223
|
+
**DEV-GATED** (each wrapped in `.hideHelp(!DEV_MODE)`; `DEV_MODE =
|
|
224
|
+
process.env.M0SAIC_DEV === "1"` at index.ts:~71, compile-stripped to `false` in
|
|
225
|
+
the published artifact): `--dev` (commands + timings), `--print-commands`,
|
|
226
|
+
`--save-plan [path]`, `--save-commands [path]`. Same gating inside inline-DSL
|
|
227
|
+
mode (`inlineDsl.ts:148-154`). Also dev-gated: the whole `momo` command, the
|
|
228
|
+
whole `browse-templates` command, and `open`'s
|
|
229
|
+
`--agent-note`/`--agent-question`. `--save-mosaic` and `--save-m0` are NOT gated,
|
|
230
|
+
and neither is `doctor` (public since 0.2.0).
|
|
231
|
+
|
|
232
|
+
> Note: a dev-gated command's NAME still appears in `KNOWN_SUBCOMMANDS`
|
|
233
|
+
> (`inlineDsl.ts:11-29`), outside the gate — the inline-DSL router has to know
|
|
234
|
+
> `momo` is a subcommand and not an m0 string. So grepping a shipped tarball for
|
|
235
|
+
> `momo` / `browse-templates` finds hits; that is the router table, not the
|
|
236
|
+
> gated implementation.
|
|
237
|
+
|
|
238
|
+
## External template repos and the community gate (2026-09-16)
|
|
239
|
+
|
|
240
|
+
**Three reserved identities, exact-match, nothing else is checked:** template
|
|
241
|
+
namespaces `@m0saic/` and `@m0saic-dev/`, repo id `@m0saic-community`
|
|
242
|
+
(`index.ts:~907-909`; registry compare is case-insensitive, `templateRegistry.ts:~112`).
|
|
243
|
+
Every other namespace / repo id is open. `--template-repo` never grants anything.
|
|
244
|
+
|
|
245
|
+
**The grant.** `--community-repo <path>` says "this IS the official repo"; the
|
|
246
|
+
`@m0saic-dev/` grant comes only from `verifyCommunityRelease()` (`@m0saic/product`
|
|
247
|
+
`communityRelease.ts`) passing on the checkout's `release.json` against
|
|
248
|
+
`LICENSE_PUBLIC_KEYS` (`publicKeys.ts` — the licence k1 family; rotation = append
|
|
249
|
+
`k2`, ship, sign with `M0SAIC_SIGNING_KID=k2`; older CLIs report `unknown-kid`).
|
|
250
|
+
The gate runs BEFORE the entry module is imported. All gate/notice lines go to
|
|
251
|
+
stderr (survive `--quiet`, keep `--json` stdout clean):
|
|
252
|
+
|
|
253
|
+
- ok → `✓ community repo verified: <tag> (signed, <kid>)`
|
|
254
|
+
- else → `⚠ <path> is not a verified release of the official community repo
|
|
255
|
+
(<reason>). Loaded as an ordinary template repo — its @m0saic-dev/ ids are
|
|
256
|
+
refused. Get the official checkout: the link on m0saic.io/community` → the
|
|
257
|
+
reserved ids are refused in ONE collapsed line, `⚠ [template-repo]
|
|
258
|
+
TEMPLATE_ID_RESERVED_NAMESPACE: refused <N> ids in reserved namespace
|
|
259
|
+
(@m0saic-dev/…): <id1>, <id2>, <id3>, …` (other rejection codes stay one line
|
|
260
|
+
each) → the existing `❌ Refusing to use template repo` block → **exit 1**.
|
|
261
|
+
|
|
262
|
+
**`release.json` v1:** `{ schemaVersion: 1, tag, publishedAt, treeSha256,
|
|
263
|
+
signature: { kid, alg: "ed25519", sig: <base64url> } }` (`--unsigned` omits
|
|
264
|
+
`signature`; the legacy `{ tag, publishedAt }` reads as `missing-signature`).
|
|
265
|
+
Tree = every file under `dist/**` + `template-manifest.json` + `package.json`,
|
|
266
|
+
sorted POSIX paths, one `"<path>\0<sha256>\n"` line each; `*.json` hashed on
|
|
267
|
+
`JSON.stringify(JSON.parse(text))` (BOM stripped; CRLF / re-indent survive, a
|
|
268
|
+
key reorder does not), other files raw bytes; no symlink is ever followed.
|
|
269
|
+
Payload `"m0saic-community-release/v1\n<tag>\n<publishedAt>\n<treeSha256>\n"`
|
|
270
|
+
(`publishedAt` must be ISO 8601, else `malformed`). Ladder:
|
|
271
|
+
`missing-release → malformed → missing-signature → unknown-kid → bad-signature
|
|
272
|
+
→ symlink-in-tree / foreign-modules → tree-mismatch → ok` — signature before
|
|
273
|
+
tree, so `tree-mismatch` = authentic release with edited dist/manifests,
|
|
274
|
+
`bad-signature` = forged `release.json`; the two structural refusals
|
|
275
|
+
(`symlink-in-tree`: ANY symlink under `dist/**`, `dist` itself or a signed
|
|
276
|
+
root file; `foreign-modules`: a `node_modules` dir at the root or under
|
|
277
|
+
`dist/`) sit between them and carry the offending path in the notice —
|
|
278
|
+
`(symlink-in-tree: dist/node_modules)`, `(foreign-modules: node_modules)`.
|
|
279
|
+
`publishedAt` is signed but there is still no anti-rollback (an older
|
|
280
|
+
authentic release verifies).
|
|
281
|
+
|
|
282
|
+
**A checkout never supplies `@m0saic/*` to itself.** The loader
|
|
283
|
+
(`@m0saic/platform` `template-repos/hostFirstResolution.ts`, installed by
|
|
284
|
+
`loadTemplateRepoFromPath` before the entry import) resolves every
|
|
285
|
+
`@m0saic/<pkg>[/<subpath>]` require whose parent file lies under a loaded
|
|
286
|
+
repo root from the HOST's own `node_modules` walk — the CLI's vendored copies,
|
|
287
|
+
the desktop's bundle, the workspace under dev — never from the checkout. So a
|
|
288
|
+
clone with nothing installed loads anywhere (0.2.0 is the first CLI that
|
|
289
|
+
can), and a `node_modules/@m0saic/template-utils` planted beside a tree is
|
|
290
|
+
never evaluated, via `--community-repo` or `--template-repo` alike. Every
|
|
291
|
+
other specifier (`sharp`, `@twemoji/svg`, relative paths) resolves as before,
|
|
292
|
+
from the checkout. CommonJS only — an `.mjs` entry's static `import`s use the
|
|
293
|
+
ESM resolver, which has no hook.
|
|
294
|
+
|
|
295
|
+
**Minting:** `scripts/sync-community-templates.mjs --tag <tag> --out <dir>` signs
|
|
296
|
+
with `M0SAIC_SIGNING_KEY_FILE` (REQUIRED — no default path; production laptop
|
|
297
|
+
only) under `M0SAIC_SIGNING_KID` (default `k1`), self-verifies against the
|
|
298
|
+
embedded keys, writes `.gitattributes` (`* -text`). Unset or missing key =
|
|
299
|
+
refused, never a silent unsigned release; `--unsigned` = loud banner, a snapshot
|
|
300
|
+
no shipped CLI trusts.
|
|
301
|
+
|
|
302
|
+
**DEV seam (workspace builds only, inside `if (DEV_MODE)`):** reasons
|
|
303
|
+
`missing-release` / `missing-signature` are still granted — `✓ community repo:
|
|
304
|
+
<path> (dev build: unsigned community checkout trusted)` (the in-repo
|
|
305
|
+
https://github.com/m0saic-project/m0saic-community-templates/blob/main has no `release.json`) — and
|
|
306
|
+
`M0SAIC_COMMUNITY_TRUST_KEY_PEM` (+ `M0SAIC_COMMUNITY_TRUST_KEY_KID`, default `k1`)
|
|
307
|
+
adds a public key for tests. Tampered tree, forged release or unknown kid are
|
|
308
|
+
refused even in dev. The tarball folds `process.env.M0SAIC_DEV` to `"0"` and the
|
|
309
|
+
audit bans the token, so none of this ships.
|
|
310
|
+
|
|
311
|
+
**Lookalikes are a display concern** — one stderr line for UNSIGNED repos, never a
|
|
312
|
+
refusal: `⚠ [template-repo] <subject> is not an official m0saic namespace — only
|
|
313
|
+
@m0saic/ and @m0saic-dev/ are, and they are signed.` Subject: loaded publisher
|
|
314
|
+
namespaces starting with `@m0saic` that are not exactly the two reserved ones →
|
|
315
|
+
else a repoId matching `/m0saic|mosaic/i` → else `"<displayName>" (<repoId>)`.
|
|
316
|
+
Never for repoId exactly `@m0saic-community`: via `--template-repo` that gets
|
|
317
|
+
`⚠ [template-repo] repo id "@m0saic-community" is reserved for the official
|
|
318
|
+
community repo and this checkout is unverified — loading it under ordinary
|
|
319
|
+
rules.` A `--community-repo` checkout that fails the gate gets ONLY the
|
|
320
|
+
not-verified notice.
|
|
321
|
+
|
|
322
|
+
**Desktop:** `installVersion()` runs `validateCommunityTree` → `verifyCommunityTree`
|
|
323
|
+
(inline-requires `@m0saic/product`) → refuses `tag-mismatch`; failure =
|
|
324
|
+
`{ ok:false, error: "downloaded tree rejected: release signature not verified
|
|
325
|
+
(<reason>): <detail>", reason }` on the existing IPC path; `installed.json` gains
|
|
326
|
+
`signedBy` + `treeSha256`; seam `installVersion({ releasePublicKeys })`. The
|
|
327
|
+
seed/installed load path (`loadCommunityRepo`) does not re-verify; consent gate
|
|
328
|
+
unchanged.
|
|
329
|
+
|
|
330
|
+
Help wording for `make` / `hello-world` / `list-templates` is ONE string,
|
|
331
|
+
test-locked (`__tests__/cli.flags.test.js`): "…Grants the @m0saic-dev/ namespace
|
|
332
|
+
when its release signature verifies (unsigned or modified checkouts load as
|
|
333
|
+
ordinary repos); the community checkout loads only this way".
|
|
334
|
+
|
|
335
|
+
### Hardening (rounds 2 + 3, 2026-09-16)
|
|
336
|
+
|
|
337
|
+
**Host-first `@m0saic/*` resolution.** https://github.com/m0saic-project/m0saic-packages/blob/main/packages/platform/src/template-repos/hostFirstResolution.ts (wired in `loadTemplateRepoFromPath.ts` via `registerHostFirstRepoRoot(repoRoot)` before the native `import(file://…)` of the entry): ONE wrapper around Node's real `Module._resolveFilename` (found by walking the prototype chain — under Jest `node:module` exports a subclass copy), installed once per process, persistent so render-time lazy requires are covered. A request matching `/^@m0saic\/[^/\\]+(?:\/.*)?$/` whose requesting module lies under a registered root (realpath'd) is resolved from the HOST's own `node_modules` walk — never the checkout's. Everything else (relative paths, non-`@m0saic` deps, host code) is untouched. CJS only. Consequences: a community clone loads from ANY directory with no `node_modules` (before this, `--community-repo` only worked inside the monorepo); a planted `node_modules/@m0saic/*` beside a verified tree is never evaluated, via either flag; a starter's `file:` link to `@m0saic/template-utils` resolves to the same physical package — no drift.
|
|
338
|
+
|
|
339
|
+
**Fail-closed tree verification** (`inspectReleaseTree` in `communityRelease.ts`; desktop mirror `inspectCommunityTree` in the Mosaic Desktop / Web app source (not published), run by `installVersion`). A release tree is plain files and directories, nothing else. Refused, in this order after the signature check and before the hash compare: `symlink-in-tree` (ANY symlink — file or dir — under `dist/**`, `dist` itself, a signed root file, or ANY entry at the checkout root); `special-file-in-tree` (FIFO / socket / device anywhere in the same places — a FIFO named `dist/publishers.js` shadows the signed `dist/publishers/` dir and blocks or executes whoever opens it); `foreign-modules` (a `node_modules` dir at the root or under `dist/`, matched case-insensitively). `verifyCommunityRelease` lstats `release.json` before opening it (a FIFO planted there used to hang the verifier). The hasher THROWS `ReleaseTreeError` on a special entry rather than skipping it; `signCommunityRelease` refuses to sign such a tree. The signed payload is `"m0saic-community-release/v1\n<tag>\n<publishedAt>\n<treeSha256>\n"`. The CLI notice carries the detail for these reasons — `(foreign-modules: node_modules)`; for `special-file-in-tree` the CLI does NOT load the folder at all (an ordinary load provably hangs): notice + `❌ Refusing to use template repo` + exit 1.
|
|
340
|
+
|
|
341
|
+
**Community deps.** The `@m0saic-dev/community-m` pack (the only `sharp` / `@twemoji/svg` user) was deleted as defunct on 2026-09-16; both left the community `package.json` and BOTH allowlists (`dep-allowlist.json` ↔ `TEMPLATE_REPO_DEP_ALLOWLIST`, lockstep-tested). Community templates may import only what the hosts ship: `@m0saic/{types,template-utils,dsl-stdlib,platform,dsl}` + `node:path`. A native or third-party runtime dep is a founder decision. `sharp` survives only as a root devDependency for core/templates tests.
|
|
342
|
+
|
|
343
|
+
**Accepted residual.** A third-party `--template-repo` checkout with its own `node_modules` runs its own copies of non-`@m0saic` deps — third-party code, with the notice printed; it cannot obtain a reserved identity that way (adversary-verified). DEV builds (`M0SAIC_DEV=1`, compile-stripped from the tarball) still trust an unsigned checkout for `missing-release` / `missing-signature` only; a tampered or forged tree is refused even in dev.
|
|
344
|
+
|
|
345
|
+
## Wireframe commands
|
|
346
|
+
|
|
347
|
+
`make-wireframe` / `make-wireframe-animated` take the layout as `--m0 <string>`
|
|
348
|
+
(inline DSL — the flag is `--m0`, not `--m0saic`) or `--mfile <path>`, plus the
|
|
349
|
+
same core/save/report/`--m0v`/`--output-pattern` surface as `make` (no encode
|
|
350
|
+
surface, no `--inputs`). Animated adds `--disable-ui` (index.ts:~4504).
|
|
351
|
+
|
|
352
|
+
## `m0saic open` — pointer only
|
|
353
|
+
|
|
354
|
+
The canonical protocol (candidate file naming, agent block, iteration ritual,
|
|
355
|
+
`--template` hot-reload loop) lives in
|
|
356
|
+
[https://github.com/m0saic-project/m0saic-sandbox/blob/main/packages/sandbox/agent.md](https://github.com/m0saic-project/m0saic-sandbox/blob/main/packages/sandbox/agent.md) — read that,
|
|
357
|
+
not this. Shape only: `open <file>` accepts `.m0 .m0c .m0p .m0v .mosaic
|
|
358
|
+
.mosaicx` and routes to Mosaic Desktop (auto-detects a running dev electron on
|
|
359
|
+
macOS; `--app <path>` override); `open --template <id> [--props/--props-file]`
|
|
360
|
+
opens the Make page via the loopback bridge, hot-reloading fresh
|
|
361
|
+
https://github.com/m0saic-project/m0saic-packages/blob/main/packages/templates/dist first (`--no-reload` to skip); `open --make
|
|
362
|
+
<file.mosaicx>` opens an authored `.mosaicx` in Make and adopts it for the
|
|
363
|
+
agent loop.
|
|
364
|
+
|
|
365
|
+
## `m0saic mcp` — the agent surface (2026-09-25)
|
|
366
|
+
|
|
367
|
+
MCP has three primitives; this server implements **tools** only (model-invoked).
|
|
368
|
+
Transport is newline-delimited JSON-RPC 2.0 over stdio, hand-rolled in
|
|
369
|
+
`src/mcp/server.ts` (~230 lines, **zero runtime deps**: the official SDK carries
|
|
370
|
+
17, including express, hono, cors, jose and ajv, and the CLI vendors its whole
|
|
371
|
+
closure into the published tarball). `initialize` echoes the client's
|
|
372
|
+
`protocolVersion`; a tool that throws returns `isError: true` rather than a
|
|
373
|
+
JSON-RPC error, so the model sees the failure instead of the transport eating it.
|
|
374
|
+
|
|
375
|
+
The 21 tools (`src/mcp/tools.ts`; the list is locked in `tools.test.ts`), in four groups:
|
|
376
|
+
|
|
377
|
+
- **Knowledge** — `knowledge_list`, `knowledge_read`, `knowledge_search`. The
|
|
378
|
+
`@m0saic/knowledge` docs, so an agent reads the handbook instead of guessing.
|
|
379
|
+
- **Local, no app needed** — `list_templates`, `template_props`, `validate_m0`,
|
|
380
|
+
`workspace_scaffold`, `render_still`, `doctor`.
|
|
381
|
+
- **Through the loopback bridge into a running Desktop — the authoring loop** —
|
|
382
|
+
`desktop_status` (also says which flow you are in: `in-the-room`, a shell
|
|
383
|
+
Desktop's Agent panel opened, or `ecosystem`), `desktop_open_in_make` (open a
|
|
384
|
+
template for review — this resets the person's session on it),
|
|
385
|
+
`desktop_reload_sources`, `desktop_read_verdict` (takes a template id, or the
|
|
386
|
+
path of a forked `.mosaic`; surfaces `srcMosaic` + `geometryEdits`).
|
|
387
|
+
- **The live canvas (0.3.1)** — see it: `desktop_layout` (the template, every
|
|
388
|
+
tile's bound prop and shown value, the current bag with `changedKeys`, the
|
|
389
|
+
modes; `detail`, `tileId`, `prop`), `desktop_snapshot` (a PNG on disk); act
|
|
390
|
+
through Make's own handlers: `desktop_set_props` (THE way to change a prop —
|
|
391
|
+
one undoable write, "Agent changed …"), `desktop_select_tile`,
|
|
392
|
+
`desktop_make_control` (reveal, camera, undo/redo, view, preview mode, canvas,
|
|
393
|
+
tile card, studio, cover, hover, tile override); branch when the template has
|
|
394
|
+
no knob: `desktop_fork_to_document` (a plain `.mosaic` + its m0),
|
|
395
|
+
`desktop_open_file`, `desktop_edit_geometry` (a pending ghost the person
|
|
396
|
+
applies). Behaviour and etiquette: [`agent-at-the-canvas.md`](agent-at-the-canvas.md);
|
|
397
|
+
the wire: `docs/compat-bridges.md` (0.3.1 routes).
|
|
398
|
+
|
|
399
|
+
Three rules the implementation enforces:
|
|
400
|
+
|
|
401
|
+
- **`render_still` pins `M0SAIC_CLI=/usr/bin/false`.** `@m0saic/benchmark/run/v1`
|
|
402
|
+
re-invokes `argv[1]`; without the pin a render from inside the CLI fork-bombs.
|
|
403
|
+
- **Failures return a HINT, never raw stderr** (`findFailureHint`). Engine text is
|
|
404
|
+
moat: the argv and the filtergraph never cross to a model.
|
|
405
|
+
- **The act routes never focus or restore the window**, and every live-canvas verb
|
|
406
|
+
runs the handler a click would — Desktop's main process sanitises the verb and
|
|
407
|
+
its args inbound and rebuilds every result from an allow-list outbound
|
|
408
|
+
(`electron/makeAgent.js`), so nothing an agent polls can carry a plan, an argv
|
|
409
|
+
or a filtergraph.
|
|
410
|
+
|
|
411
|
+
`src/mcp/bridgeClient.ts` is the transport for the desktop tools. A 404 means
|
|
412
|
+
`route-missing` — "this Desktop is too old for that route" — not "the app is
|
|
413
|
+
down"; the compat warning prints once per process. The full route table is
|
|
414
|
+
`docs/compat-bridges.md`.
|
|
415
|
+
|
|
416
|
+
**`--agent-note` / `--agent-question` are PUBLIC** as of this line (the DEV_MODE
|
|
417
|
+
strip is gone and `__tests__/cli.surface.test.js` asserts they appear in the
|
|
418
|
+
published help — the lock was inverted, not removed). With `--template` they seed
|
|
419
|
+
a note / question into Make's File tab for the reviewer to answer.
|
|
420
|
+
|
|
421
|
+
## `m0saic doctor` answers a VERSIONED question (2026-09-25)
|
|
422
|
+
|
|
423
|
+
Conventions change, so "does this repo pass?" is the wrong question — the right one is **which line
|
|
424
|
+
does it pass at.** `report.conventions` carries it:
|
|
425
|
+
|
|
426
|
+
```
|
|
427
|
+
conventions: meets 0.2.0 (shipped at 0.2.0).
|
|
428
|
+
behind 0.3.0: bindingsDeclared, canvasFill
|
|
429
|
+
9 of 96 template(s) behind — a vN+1 on each clears it.
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
- **`meets`** — the newest m0saic line every template in the repo satisfies (error severity only; a
|
|
433
|
+
`record` warning is advice, not a failure to meet a line).
|
|
434
|
+
- **`behind`** — the lines it does not meet, with the rules that fail, oldest first.
|
|
435
|
+
- **`shippedAt`** — the repo's own `frozen.manifest.json` `release`.
|
|
436
|
+
- **`target`** — the repo's `repo.conventions` (e.g. `"0.3.1"`, 0.3.1): the line whose rules it has
|
|
437
|
+
adopted. Each template is held to the LOWER of its shipped line and the target; rules introduced after
|
|
438
|
+
that are lag ("behind"), never errors. A repo moves its target when its templates have adopted the
|
|
439
|
+
newer rules — like a crate's edition. Absent: held to every rule this CLI knows. A malformed target is
|
|
440
|
+
a load warning (`CONVENTIONS_TARGET`); one newer than the CLI knows is a note. The summary line reads
|
|
441
|
+
`conventions: meets 0.3.0 (targets 0.3.0).` and a lagging template says *"the repo targets 0.3.0:
|
|
442
|
+
behind on catalogSidecar — not a defect, adopt them, then move repo.conventions."*
|
|
443
|
+
- **`lagOnly`** — true when EVERY failure comes from a line newer than `shippedAt`. The footer then
|
|
444
|
+
says so explicitly: *"Not a defect: these templates met the conventions of their day. Fix at the
|
|
445
|
+
next vN."*
|
|
446
|
+
|
|
447
|
+
**A template is allowed to lag.** It met the conventions of its day; the rules moved; the fix is its
|
|
448
|
+
next `vN`. **A repo is allowed to target an older line too** (`repo.conventions`): a new m0saic release
|
|
449
|
+
never turns its build red — the freeze protects what shipped, the target protects a repo with no freeze
|
|
450
|
+
(every third-party repo). What the rules guarantee is that **NEW** templates meet the CURRENT line — which is why the
|
|
451
|
+
postures throw (founder: "we need to be greedy about adding conventions because agents, especially
|
|
452
|
+
non-frontier ones, won't"). The exit code is still 1 on any error, because the status is informational
|
|
453
|
+
and the message carries the meaning.
|
|
454
|
+
|
|
455
|
+
`TEMPLATE_CONVENTION_SINCE` in `@m0saic/template-utils` is the map of rule → line. Everything
|
|
456
|
+
pre-0.3.0 reads `0.2.0`: at that freeze the whole shipped fleet passed every rule then in force, so it
|
|
457
|
+
is a true lower bound rather than a guessed date.
|
|
458
|
+
|
|
459
|
+
## Failure modes
|
|
460
|
+
|
|
461
|
+
- `spawnSync m0saic EACCES` — the CLI isn't built/linked on this machine:
|
|
462
|
+
`cd the CLI source (not published) && npm run build && npm link`.
|
|
463
|
+
- No ffmpeg at all → `ffmpeg isn't detected.` (4 lines), exit 1, nothing
|
|
464
|
+
downloaded (`ensureRenderToolchain()`, index.ts ~404); run `m0saic setup`
|
|
465
|
+
(`npx m0saic setup` under npx), then re-run. A broken golden slot prints
|
|
466
|
+
`❌ Toolchain "gpl" (golden) is broken … Re-install it: m0saic setup --gpl`.
|
|
467
|
+
- Free tier re-encodes every deliverable (QR stamp wrap) — codecs/durations
|
|
468
|
+
change, breaking probe-based assertions. Check `npm run tier:status` first;
|
|
469
|
+
full rule in the maintainers' agent contract §7.7 (not published).
|
|
470
|
+
- Non-zero ffmpeg exits print a core-computed failure classification after the
|
|
471
|
+
exit-code line (`printFfmpegFailure`, index.ts:~113) — read it before rerunning
|
|
472
|
+
with `--verbose`.
|
|
473
|
+
- Invalid m0 strings fail fast at validation (`validateM0String`), not inside
|
|
474
|
+
ffmpeg; `SPLIT_EXCEEDS_AXIS` means the split count exceeds the pixel axis —
|
|
475
|
+
see `docs/handbook/feasibility-precision-quantization.md`.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# FFmpeg Expression Limits — the parse-depth cliff (a phantom "OOM")
|
|
2
|
+
|
|
3
|
+
**Source of truth:** `rebalanceAdditiveChains` in
|
|
4
|
+
[https://github.com/m0saic-project/m0saic-packages/blob/main/packages/platform/src/ffexpr/balance.ts](https://github.com/m0saic-project/m0saic-packages/blob/main/packages/platform/src/ffexpr/balance.ts)
|
|
5
|
+
(`DEFAULT_MAX_FLAT_ADDITIVE_TERMS = 32`); the funnels that apply it —
|
|
6
|
+
`quoteEnableArg` in [https://github.com/m0saic-project/m0saic-packages/blob/main/packages/platform/src/ffexpr/ffmpeg.ts](https://github.com/m0saic-project/m0saic-packages/blob/main/packages/platform/src/ffexpr/ffmpeg.ts),
|
|
7
|
+
`buildOverlayAlphaFilter` + `buildCameraFilters` in `@m0saic/core`.
|
|
8
|
+
Verified against BtbN ffmpeg `N-124278-gcc3ca17127-20260430` (the pinned GPL build).
|
|
9
|
+
|
|
10
|
+
> Companion mental model: [`../skills/more-atoms-not-bigger-atoms.md`](../skills/more-atoms-not-bigger-atoms.md).
|
|
11
|
+
> This doc is the measured case study; that one is the general principle.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## The symptom (and why it lies)
|
|
16
|
+
|
|
17
|
+
FFmpeg's expression parser (`av_expr_parse`, `libavutil/eval.c`) has a **fixed
|
|
18
|
+
recursion budget (~100)**. When an emitted expression exceeds it, filtergraph
|
|
19
|
+
init fails with:
|
|
20
|
+
|
|
21
|
+
- **`Error initializing filters / Error : Cannot allocate memory` (−12)** — a
|
|
22
|
+
**phantom OOM**: deterministic, ~60 ms, completely independent of free RAM.
|
|
23
|
+
This is the additive-chain shape.
|
|
24
|
+
- or **`Missing ')' or too many args` → `Invalid argument` (−22) /
|
|
25
|
+
`Error reinitializing filters`** — the deeply-nested shape (e.g. a `crop`
|
|
26
|
+
focus expr).
|
|
27
|
+
|
|
28
|
+
The word "memory" is a lie. It is NOT commit pressure, graph size, filter
|
|
29
|
+
count, or a platform difference — all of which this failure repeatedly (and
|
|
30
|
+
expensively) misled debugging toward. It is one expression too deep.
|
|
31
|
+
|
|
32
|
+
## The cliff (measured, term-count-driven — NOT chars)
|
|
33
|
+
|
|
34
|
+
- A **flat `a+b+c+…` chain fails at exactly 99 terms** (98 parses, 99 fails).
|
|
35
|
+
Character length is irrelevant: a 3.8 K-char / 98-term expr parses; a
|
|
36
|
+
2.3 K-char / 99-term expr fails.
|
|
37
|
+
- **Genuine nesting** (nested `if(cond,…,else)` chains) fails at ~100 levels.
|
|
38
|
+
- Because ffmpeg spends one recursion level **per additive term at the same
|
|
39
|
+
nesting level**, both shapes share the same ~100 budget.
|
|
40
|
+
|
|
41
|
+
## The two shapes → the two fixes
|
|
42
|
+
|
|
43
|
+
1. **Flat additive chains** (`enable` window sums, the `overlay.enable`→`geq`
|
|
44
|
+
alpha fold, camera zoom/focus). Fixable by REGROUPING the same terms into a
|
|
45
|
+
**balanced binary tree** — `((a+b)+(c+d))…` — which keeps parse depth
|
|
46
|
+
O(log N) and is safe past 1024 terms. This is `rebalanceAdditiveChains`.
|
|
47
|
+
2. **Deep nesting** (one nested `if()` level per keyframe). Rebalancing CANNOT
|
|
48
|
+
help — the builder must **emit a flat shape instead**. dsl-tutorial's camera
|
|
49
|
+
`focusExpr` was rewritten from nested `if(lt(t,…),…, else)` (depth 109 at
|
|
50
|
+
10×10) to a **flat sum of disjoint window-gated smoothstep segments**
|
|
51
|
+
(`lt` head + `gte·lt` segments + `gte` tail).
|
|
52
|
+
|
|
53
|
+
## Authoring rule
|
|
54
|
+
|
|
55
|
+
**No flat additive chain longer than ~32 terms, and no piecewise-over-time
|
|
56
|
+
expression built as a nested if-else chain, should ever reach a filtergraph.**
|
|
57
|
+
Build piecewise-in-time values as **flat gated sums**; long chains are
|
|
58
|
+
auto-rebalanced at the engine funnels below.
|
|
59
|
+
|
|
60
|
+
## Engine enforcement (shipped 2026-07-02 — route new work through these)
|
|
61
|
+
|
|
62
|
+
`rebalanceAdditiveChains` (`@m0saic/platform` `ffexpr/balance.ts`, threshold
|
|
63
|
+
`DEFAULT_MAX_FLAT_ADDITIVE_TERMS = 32`) is applied automatically at every
|
|
64
|
+
expression funnel:
|
|
65
|
+
|
|
66
|
+
- `quoteEnableArg` — ALL `:enable='…'` sites (overlay, drawtext,
|
|
67
|
+
`compileEnableArg`).
|
|
68
|
+
- `buildOverlayAlphaFilter` — the `overlay.enable` → `geq` alpha fold.
|
|
69
|
+
- `buildCameraFilters` — zoom/focus chains.
|
|
70
|
+
|
|
71
|
+
Chains **≤ 32 terms pass through byte-identical** (goldens unaffected); only
|
|
72
|
+
longer chains are regrouped. Rebalancing fixes PARSE; it does not change eval
|
|
73
|
+
cost (see below).
|
|
74
|
+
|
|
75
|
+
**Known bypasses to watch:** hand-rolled lavfi strings that build `enable=`
|
|
76
|
+
outside the funnels — dsl-string caret-track `drawbox`, dsl-canvas `drawbox`
|
|
77
|
+
(both currently ≤3-term chains, safe) — and any template that still builds a
|
|
78
|
+
nested-`if` expression (e.g. a line-chart animation) which will hit the cliff
|
|
79
|
+
if its dataset grows. Keep per-filter chains small, or call
|
|
80
|
+
`rebalanceAdditiveChains` before joining.
|
|
81
|
+
|
|
82
|
+
## The "graph-SIZE OOM" was this cliff wearing a trench coat (debunked)
|
|
83
|
+
|
|
84
|
+
A separate ≈130 K-chars / 9 000-filters "graph-size OOM" mode was once believed
|
|
85
|
+
to exist, and a `splitByGraphBudget` chunker was calibrated against it. **It does
|
|
86
|
+
not reproduce.** Direct verification:
|
|
87
|
+
|
|
88
|
+
- The exact 142 K canvas part it was calibrated on renders standalone at full
|
|
89
|
+
duration; so do a **12 000-chained-drawbox / 1.19 MB single graph** and a
|
|
90
|
+
9 000-filter graph.
|
|
91
|
+
- Every recorded failure sidecar in `smokebatch/` (smoke9–29) is a command
|
|
92
|
+
whose EXPRESSIONS cross the parse cliff (flat ≥99 or nesting ≥109), failing in
|
|
93
|
+
<80 ms with −12/−22. **No sidecar ever names a size-heavy command.**
|
|
94
|
+
|
|
95
|
+
Graph chars merely *correlated* with expression bulk in that era's graphs. The
|
|
96
|
+
graph-size chunker was reverted. **Do not re-add a filtergraph-size split
|
|
97
|
+
chasing a "size OOM" — it is the parse cliff.** (The input-count split,
|
|
98
|
+
`maxInputsPerCommand`, is a separate and real argv/process-arg constraint and
|
|
99
|
+
stays.)
|
|
100
|
+
|
|
101
|
+
## Note: the macOS "grind" is a different wall
|
|
102
|
+
|
|
103
|
+
The same dense graphs that fail fast on Windows (parse cliff) instead ran for
|
|
104
|
+
20+ min on macOS. That was NOT the parse cliff (Mac's ffmpeg parses flat chains
|
|
105
|
+
fine) — it was **per-pixel `geq` eval cost** (O(terms) per pixel per plane per
|
|
106
|
+
frame). Rebalancing does not reduce it; density caps like `PULSE_TERM_CAP` and
|
|
107
|
+
representational fixes (SVG masks, pre-rendered intermediates) do. That's a
|
|
108
|
+
perf ceiling, not a crash — see the "more atoms" skill, atom 2.
|
|
109
|
+
|
|
110
|
+
There is also a *third*, mechanically distinct macOS wall on
|
|
111
|
+
conversion-/input-dense graphs (many `scale`/`format` nodes + many still
|
|
112
|
+
inputs, e.g. dsl-tutorial grids): **swscale thread-cap exhaustion**, where
|
|
113
|
+
per-conversion thread pools blow past `kern.num_taskthreads` and frames freeze
|
|
114
|
+
at t=0 or grind at ~1 fps. That one is neither parse depth nor `geq` eval cost —
|
|
115
|
+
that wall is engine-internal: `.ai/moat/runtime/macos-swscale-thread-cap.md`
|
|
116
|
+
(absent in the shipped copy; symptom summary: dense still-image canvases freeze
|
|
117
|
+
at t=0 / grind ~1 fps on macOS — the engine's threadGuard mitigates it).
|