@m0saic/knowledge 0.2.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 (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dist/index.d.ts +8 -0
  4. package/dist/index.js +7 -0
  5. package/docs/README.md +60 -0
  6. package/docs/file-formats/m0-iteration-protocol.md +120 -0
  7. package/docs/file-formats/m0p-and-custom-field.md +195 -0
  8. package/docs/handbook/README.md +27 -0
  9. package/docs/handbook/composition-arithmetic.md +278 -0
  10. package/docs/handbook/dsl-complexity.md +75 -0
  11. package/docs/handbook/dsl-rules.md +367 -0
  12. package/docs/handbook/feasibility-precision-quantization.md +591 -0
  13. package/docs/handbook/m0-construction-methods.md +201 -0
  14. package/docs/handbook/precision-tiers.md +84 -0
  15. package/docs/m0saic-thesis.md +95 -0
  16. package/docs/runtime/README.md +17 -0
  17. package/docs/runtime/cli-usage.md +372 -0
  18. package/docs/runtime/ffmpeg-expression-limits.md +117 -0
  19. package/docs/runtime/reduce-to-one.md +96 -0
  20. package/docs/skills/README.md +40 -0
  21. package/docs/skills/axis-and-geometry.md +103 -0
  22. package/docs/skills/dsl-stdlib-method-catalog.md +7 -0
  23. package/docs/skills/identity.md +123 -0
  24. package/docs/skills/labels-and-masks.md +170 -0
  25. package/docs/skills/m0saic-string-generation.md +251 -0
  26. package/docs/skills/more-atoms-not-bigger-atoms.md +77 -0
  27. package/docs/skills/overlay-semantics.md +194 -0
  28. package/docs/skills/parse-apis.md +79 -0
  29. package/docs/skills/passthrough-semantics.md +136 -0
  30. package/docs/skills/structural-construction.md +86 -0
  31. package/docs/skills/text-in-templates.md +126 -0
  32. package/docs/skills/zero-overlay-analysis.md +87 -0
  33. package/docs/templates/README.md +65 -0
  34. package/docs/templates/capability-templates.md +72 -0
  35. package/docs/templates/construction-strategy.md +329 -0
  36. package/docs/templates/data-pipeline.md +324 -0
  37. package/docs/templates/emission-patterns.md +130 -0
  38. package/docs/templates/geometry-recipes.md +248 -0
  39. package/docs/templates/layout-contract.md +168 -0
  40. package/docs/templates/output-resolution-tree.md +202 -0
  41. package/docs/templates/patterns/case-study-lessons.md +69 -0
  42. package/docs/templates/patterns/perf-authoring-rules.md +100 -0
  43. package/docs/templates/patterns/primitive-extraction-pattern.md +103 -0
  44. package/docs/templates/philosophy-and-contract.md +310 -0
  45. package/docs/templates/recursion-nested-rendering.md +138 -0
  46. package/docs/templates/reference/grid.md +104 -0
  47. package/docs/templates/reference/json-prop-type.md +169 -0
  48. package/docs/templates/reference/mosaic-color.md +81 -0
  49. package/docs/templates/reference/mosaic-placement-props.md +103 -0
  50. package/docs/templates/reference/prop-bindings.md +203 -0
  51. package/docs/templates/reference/template-flags.md +205 -0
  52. package/docs/templates/render-lifecycle.md +117 -0
  53. package/docs/templates/rendering-model-contract.md +392 -0
  54. package/docs/templates/standalone-pack-authoring.md +233 -0
  55. package/docs/templates/theming.md +81 -0
  56. package/docs/templates/ui-controls.md +150 -0
  57. package/package.json +37 -0
@@ -0,0 +1,81 @@
1
+ # Theming — design tokens over the upstream channel
2
+
3
+ > Templates layer. How a template consumes (or produces) shared design tokens.
4
+ > Landed in F4 (`charts/stat-card/v1` is the first consumer). The token
5
+ > plumbing lives in `@m0saic/template-utils` (`src/theming/`); the contract in
6
+ > `@m0saic/types`; the reference producer at `@m0saic/theming/v1`.
7
+
8
+ Theming lets a **producer** template publish design tokens that any **consumer**
9
+ template overlays onto its own constants. Producer and consumer agree ONLY on a
10
+ token SHAPE + an alias — never on a specific producer — so any conforming
11
+ producer is swappable under any consumer.
12
+
13
+ ## The three homes
14
+
15
+ - **Contract** — `@m0saic/types`: `MosaicThemeTokens` (21 role-based keys:
16
+ `surface*` / `text*` / `accent*` / `positive` / `negative` / `grid*` /
17
+ `axis*` / `radius` / `dataPalette`), `MosaicThemeMode`
18
+ (`dark` | `light` | `high-contrast`), `MOSAIC_THEME_ALIAS` (`"theme"`),
19
+ `MOSAIC_THEME_TOKEN_KEYS`. Keys are ADDITIVE-ONLY (renames force a
20
+ re-checkpoint).
21
+ - **Plumbing** — `@m0saic/template-utils` (`src/theming/`): `publishTheme`,
22
+ `readTheme`, `applyTheme` (sync — ctx-read + per-key overlay), and
23
+ `resolveThemeTokens` (async — find-or-seed) + `ThemeSourceConfig`.
24
+ - **Reference producer** — `@m0saic/theming/v1`: a layered system —
25
+ `M0SAIC_BRAND` (reference: navy + orange) → semantic `ThemeTokens` →
26
+ `THEME_PRESETS` / `resolveTheme(mode)`. Publishes via `publishTheme`;
27
+ `preview:false` emits a data-only doc valid only as an `intermediate`
28
+ pipeline step.
29
+
30
+ ## Consumer authoring pattern (the copyable recipe)
31
+
32
+ 1. Declare your current constants as a full `MosaicThemeTokens` `LOCAL_THEME`
33
+ (used keys carry the current hexes VERBATIM → byte-identity; unused keys are
34
+ defensible locals, never read). Do NOT import the producer's `resolveTheme`
35
+ into the fallback — coupling the fallback to a producer preset risks a drift
36
+ that breaks byte-identity.
37
+ 2. Add an opt-in `theme?: ThemeSourceConfig` prop
38
+ (`{ slug?, namespace?, props?, forceFetch? }`).
39
+ 3. In `render`: `const theme = await resolveThemeTokens(LOCAL_THEME, ctx,
40
+ props.theme);` then read `theme.<key>` everywhere a constant was read.
41
+
42
+ ## The resolution model — `theme = ctx[namespace] ?? seed(slug) ?? fallback`
43
+
44
+ The same one call serves both roles a template can play:
45
+
46
+ - **Vanilla** (no config, or a config without a `slug`): reads the default
47
+ `"theme"` namespace off ctx, else `LOCAL_THEME`. Un-themed → byte-identical.
48
+ - **Child** (nested under a producer/pipeline that published tokens): finds them
49
+ on `ctx.upstreamData[namespace]` → uses them. No `slug` needed.
50
+ - **Head** (top-level, nothing upstream, `slug` configured): INVOKES the producer
51
+ (`renderNestedTemplate` — a BUILD-TIME doc build, NOT ffmpeg) to seed the
52
+ tokens, then reads them.
53
+ - **`forceFetch`**: re-seed via `slug` even when the namespace is populated
54
+ (escape hatch for a namespace collision; the real fix is usually higher in the
55
+ chain).
56
+
57
+ **Swap the theme = swap `props.theme.slug` (or its `props`)** — a data change,
58
+ never consumer code. `applyTheme` is the sync subset (ctx-read + overlay, no
59
+ seeding) for consumers that never self-seed.
60
+
61
+ ## Two hard rules
62
+
63
+ - Read via `applyTheme` / `resolveThemeTokens` (which read
64
+ `ctx.upstreamData[alias]` through `getUpstreamBlock`). NEVER hand-read
65
+ `ctx.upstreamVariables` for theme.
66
+ - `LOCAL_THEME`'s used keys = the template's current hexes, so an un-themed,
67
+ un-configured render is byte-identical to pre-theming. Verify with a doc
68
+ snapshot deep-equal.
69
+
70
+ ## Pipeline alternative (production path for a chain)
71
+
72
+ To re-skin a whole chain, put the producer as an `intermediate: true` step ahead
73
+ of the consumers:
74
+ `[ @m0saic/theming/v1 preset:dark preview:false → …consumers ]`. The producer
75
+ threads tokens downstream at zero render cost; swapping the step's `preset`
76
+ re-skins everything. Consumers need no `slug` in this mode — they find the tokens
77
+ on ctx as children.
78
+
79
+ Reference consumer: `charts/stat-card/v1` (first `resolveThemeTokens` consumer,
80
+ F4). See also `data-pipeline.md`
81
+ §"Publish channels × read views" for the underlying upstream channel.
@@ -0,0 +1,150 @@
1
+ # Template UI controls
2
+
3
+ Templates declare per-prop editor controls via `meta.control` on each
4
+ `MosaicTemplatePropDefinition`. The desktop app's prop-dispatch surfaces read those
5
+ declarations and render the matching widget.
6
+
7
+ ⚠️ **If you are adding a new control kind: the dispatch is duplicated across TWO
8
+ surfaces, and a one-surface change silently no-ops on the other.** Update both.
9
+ (There is no `props-control-dispatch.md` yet — the writeup is still an unmerged
10
+ candidate at (internal design history); read
11
+ that for the two surface locations.)
12
+
13
+ ---
14
+
15
+ ## The `picker` taxonomy
16
+
17
+ `MosaicPropControl.picker` is a closed union
18
+ (https://github.com/m0saic-project/m0saic-packages/blob/main/packages/types/src/template/template.ts#L186):
19
+
20
+ | Value | Renders | Prop shape |
21
+ |---|---|---|
22
+ | `"file"` | OS file picker | one `type: "media"` prop |
23
+ | `"folder"` | OS folder picker | one `type: "media"` prop |
24
+ | `"time-range"` | Single-range clip modal | **paired** `*StartMs` / `*EndMs` numbers |
25
+ | `"time-ranges"` | Multi-range Clip-Range Studio | **one** `type: "json"` prop |
26
+ | `"cards"` | Image-card option grid | any prop with `control.options` |
27
+
28
+ `"time-range"` and `"time-ranges"` are **both current and both in use** — the plural did
29
+ not supersede the singular. Pick by cardinality:
30
+
31
+ - **One window** out of a source (trim, clip, preview segment) → `"time-range"`.
32
+ Adopters: `media/subtitle-burn/v1`, `language/dual-sub/v1`,
33
+ `media/video_to_png_sequence/v1`.
34
+ - **N windows** (highlight reels, multi-cut) → `"time-ranges"`.
35
+ Adopter: `media/highlights/v1`.
36
+
37
+ ---
38
+
39
+ ## `"time-range"` — the paired-prop picker
40
+
41
+ Declared on **both** halves of a `<base>StartMs` / `<base>EndMs` numeric pair, with the
42
+ same control block on each:
43
+
44
+ ```ts
45
+ clipStartMs: {
46
+ type: "number",
47
+ required: false,
48
+ meta: {
49
+ control: {
50
+ picker: "time-range",
51
+ videoFromProp: "sourceId", // sibling prop holding the video path
52
+ targetDurationMsFromProp: "duration", // optional — draws a "target band"
53
+ markersProvider: { // optional — semantic timeline ticks
54
+ kind: "subtitles",
55
+ videoFromProp: "sourceId",
56
+ languageFromProp: "languageCode",
57
+ trackIndexFromProp: "trackIndex",
58
+ },
59
+ },
60
+ ui: { label: "Clip start (ms)" },
61
+ },
62
+ },
63
+ clipEndMs: { /* mirrors clipStartMs, label "Clip end (ms)" */ },
64
+ ```
65
+
66
+ **Pairing rule.** The dispatch matches the two halves by name suffix
67
+ (`*StartMs` ↔ `*EndMs`) via `planTimeRangeEntries`
68
+ (the Mosaic Desktop / Web app source (not published)). Both dispatch surfaces
69
+ call that same planner, so pair-detection cannot drift between them.
70
+
71
+ **`{ 0, 0 }` means "full source"** — it is the documented cleared sentinel, not a
72
+ zero-length range. Don't treat it as an empty selection.
73
+
74
+ ---
75
+
76
+ ## `"time-ranges"` — the multi-range studio
77
+
78
+ **One** `type: "json"` prop whose value is `Array<MosaicTimeRangeMs>`
79
+ (`{ startMs, endMs, label? }`; integer ms, source-relative, sorted ascending; overlaps
80
+ allowed; `[]` = no selection). No prop pairing — the editor reads and writes the whole
81
+ array in a single `onChange`.
82
+
83
+ ```ts
84
+ clipRanges: {
85
+ type: "json",
86
+ required: false,
87
+ meta: { control: { picker: "time-ranges", videoFromProp: "sourceId" } },
88
+ },
89
+ ```
90
+
91
+ **Read the value with `parseTimeRangesValue`**
92
+ (https://github.com/m0saic-project/m0saic-packages/blob/main/packages/template-utils/src/media/timeRanges.ts) — never hand-parse. The boundary is
93
+ deliberately permissive (see `reference/json-prop-type.md`), so the value may arrive as a
94
+ parsed array *or* a JSON string.
95
+
96
+ ---
97
+
98
+ ## Both pickers are one component underneath
99
+
100
+ The Clip-Range Studio is the single implementation; the singular picker is an adapter
101
+ over it.
102
+
103
+ | Component | Role |
104
+ |---|---|
105
+ | `rangestudio/ClipRangeStudio.tsx` + `ClipRangeStudioModal.tsx` | the studio |
106
+ | `rangestudio/SingleRangeModal.tsx` | single-range adapter — the studio at `maxRanges: 1`, legacy `{startMs, endMs}` in/out |
107
+ | `rangestudio/TimeRangesField.tsx` | the `"time-ranges"` form field, rendered by **both** dispatch chains |
108
+
109
+ > **Historical note:** `TimeRangePickerField.tsx` / `TimeRangePickerModal.tsx` were
110
+ > **deleted** in the Clip-Range Studio rebuild. `SingleRangeModal` is their drop-in
111
+ > replacement with the same public API. Older docs, plans, and candidates that cite
112
+ > those two filenames are stale — the *pattern* they describe survived, the files did
113
+ > not.
114
+
115
+ Consumers of `SingleRangeModal` today: `PropsSchemaForm`, `MakePage`, and
116
+ `compose/sources/MediaSourceEditor`.
117
+
118
+ ---
119
+
120
+ ## Marker providers (declarative)
121
+
122
+ `markersProvider` asks the editor to overlay semantic landmarks on the timeline. The
123
+ union currently has **exactly one kind**:
124
+
125
+ - **`kind: "subtitles"`** — extracts cues for the resolved language/track and draws them
126
+ as ticks with inline labels. Chain: `subtitles:extract` IPC
127
+ (the Mosaic Desktop / Web app source (not published)) → cue hook → `markers` on the studio. The cues are
128
+ also painted as a live caption overlay on the preview `<video>`, because HTML5 video
129
+ cannot surface embedded MKV subtitle tracks.
130
+
131
+ **There is no fallback path.** A `kind` the dispatch doesn't recognize is *silently
132
+ ignored* — no warning, no error, the markers just never appear. Adding a kind
133
+ (`scene-cuts`, `audio-peaks`, `chapters`) means expanding the union **and** adding the
134
+ IPC **and** the hook **and** the dispatch wiring, in lockstep.
135
+
136
+ ---
137
+
138
+ ## Companion props and gotchas
139
+
140
+ **Loop mode.** A time-range pairs naturally with a loop-mode enum when the selected
141
+ segment can be shorter or longer than the render duration. Subtitle-burn's
142
+ `clipLoopMode: "cut" | "loop" | "freeze"` is the reference — a plain enum via
143
+ `meta.control.options`, threaded into `MosaicPlaybackProps.loopMode` at render time.
144
+
145
+ **Cue-offset trap on clipped templates.** When a template offsets cues to output-time
146
+ (subtitle-burn's `offsetCuesToOutput(rawCues, clipStartMs, clipEndMs, durationMs)`), the
147
+ picked range must actually overlap where cues exist — otherwise the render is silently
148
+ subtitle-free. The marker overlay is the editor-side mitigation: users see where cues
149
+ live and aim accordingly. Surface this on any cue-bearing template rather than burying
150
+ it.
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@m0saic/knowledge",
3
+ "version": "0.2.0",
4
+ "private": false,
5
+ "license": "MIT",
6
+ "description": "The m0saic knowledge base for agents and authors: the m0 handbook, the engine mental models, and the template-authoring contract, as plain Markdown. Point your coding agent at README.md before it writes a template.",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "scripts": {
10
+ "build": "node test/docs.test.mjs --build",
11
+ "test": "node --test test/docs.test.mjs"
12
+ },
13
+ "keywords": [
14
+ "m0saic",
15
+ "m0",
16
+ "templates",
17
+ "knowledge-base",
18
+ "agents",
19
+ "AGENTS.md"
20
+ ],
21
+ "author": "m0saic LLC",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/m0saic-project/m0saic-packages.git",
25
+ "directory": "packages/knowledge"
26
+ },
27
+ "homepage": "https://github.com/m0saic-project/m0saic-packages/tree/main/packages/knowledge#readme",
28
+ "bugs": {
29
+ "url": "https://github.com/m0saic-project/m0saic-packages/issues"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "docs",
34
+ "LICENSE",
35
+ "README.md"
36
+ ]
37
+ }