@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.
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +7 -0
- package/docs/README.md +60 -0
- package/docs/file-formats/m0-iteration-protocol.md +120 -0
- package/docs/file-formats/m0p-and-custom-field.md +195 -0
- package/docs/handbook/README.md +27 -0
- package/docs/handbook/composition-arithmetic.md +278 -0
- package/docs/handbook/dsl-complexity.md +75 -0
- package/docs/handbook/dsl-rules.md +367 -0
- package/docs/handbook/feasibility-precision-quantization.md +591 -0
- package/docs/handbook/m0-construction-methods.md +201 -0
- package/docs/handbook/precision-tiers.md +84 -0
- package/docs/m0saic-thesis.md +95 -0
- package/docs/runtime/README.md +17 -0
- package/docs/runtime/cli-usage.md +372 -0
- package/docs/runtime/ffmpeg-expression-limits.md +117 -0
- package/docs/runtime/reduce-to-one.md +96 -0
- package/docs/skills/README.md +40 -0
- package/docs/skills/axis-and-geometry.md +103 -0
- package/docs/skills/dsl-stdlib-method-catalog.md +7 -0
- package/docs/skills/identity.md +123 -0
- package/docs/skills/labels-and-masks.md +170 -0
- package/docs/skills/m0saic-string-generation.md +251 -0
- package/docs/skills/more-atoms-not-bigger-atoms.md +77 -0
- package/docs/skills/overlay-semantics.md +194 -0
- package/docs/skills/parse-apis.md +79 -0
- package/docs/skills/passthrough-semantics.md +136 -0
- package/docs/skills/structural-construction.md +86 -0
- package/docs/skills/text-in-templates.md +126 -0
- package/docs/skills/zero-overlay-analysis.md +87 -0
- package/docs/templates/README.md +65 -0
- package/docs/templates/capability-templates.md +72 -0
- package/docs/templates/construction-strategy.md +329 -0
- package/docs/templates/data-pipeline.md +324 -0
- package/docs/templates/emission-patterns.md +130 -0
- package/docs/templates/geometry-recipes.md +248 -0
- package/docs/templates/layout-contract.md +168 -0
- package/docs/templates/output-resolution-tree.md +202 -0
- package/docs/templates/patterns/case-study-lessons.md +69 -0
- package/docs/templates/patterns/perf-authoring-rules.md +100 -0
- package/docs/templates/patterns/primitive-extraction-pattern.md +103 -0
- package/docs/templates/philosophy-and-contract.md +310 -0
- package/docs/templates/recursion-nested-rendering.md +138 -0
- package/docs/templates/reference/grid.md +104 -0
- package/docs/templates/reference/json-prop-type.md +169 -0
- package/docs/templates/reference/mosaic-color.md +81 -0
- package/docs/templates/reference/mosaic-placement-props.md +103 -0
- package/docs/templates/reference/prop-bindings.md +203 -0
- package/docs/templates/reference/template-flags.md +205 -0
- package/docs/templates/render-lifecycle.md +117 -0
- package/docs/templates/rendering-model-contract.md +392 -0
- package/docs/templates/standalone-pack-authoring.md +233 -0
- package/docs/templates/theming.md +81 -0
- package/docs/templates/ui-controls.md +150 -0
- package/package.json +37 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 m0saic LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# @m0saic/knowledge
|
|
2
|
+
|
|
3
|
+
The m0saic knowledge base, as plain Markdown: the **m0 handbook** (grammar,
|
|
4
|
+
semantics, the geometry math), the **skills** (engine mental models and
|
|
5
|
+
invariants), and the **template-authoring contract**. It is the same tree the
|
|
6
|
+
m0saic maintainers' agents work from, generated from the monorepo with every
|
|
7
|
+
internal reference rewritten to a public one.
|
|
8
|
+
|
|
9
|
+
**If you are a coding agent about to write a template: read this file, then
|
|
10
|
+
[`docs/m0saic-thesis.md`](docs/m0saic-thesis.md), then follow the router in
|
|
11
|
+
[`docs/README.md`](docs/README.md).** Nothing here needs a build, a network,
|
|
12
|
+
or a login.
|
|
13
|
+
|
|
14
|
+
## Where it lives on disk
|
|
15
|
+
|
|
16
|
+
- Installed: `node_modules/@m0saic/knowledge/docs/` — the template repo
|
|
17
|
+
starters list this package as a devDependency, so `npm install` puts it
|
|
18
|
+
beside your code.
|
|
19
|
+
- On GitHub: [`m0saic-project/m0saic-packages/packages/knowledge`](https://github.com/m0saic-project/m0saic-packages/tree/main/packages/knowledge).
|
|
20
|
+
|
|
21
|
+
## Authority order
|
|
22
|
+
|
|
23
|
+
1. `docs/handbook/` — canonical truth for the m0 language and its geometry.
|
|
24
|
+
2. `docs/skills/` — mental models and invariants; subordinate to the handbook.
|
|
25
|
+
3. `docs/templates/` — the template contract, construction strategy, recipes,
|
|
26
|
+
perf rules; subordinate to both.
|
|
27
|
+
|
|
28
|
+
Handbook wins over skills, skills over templates, and **code wins over every
|
|
29
|
+
doc**: when a document and the packages disagree, the packages are right. The
|
|
30
|
+
one idea everything rests on: a layout is one string of rectangles
|
|
31
|
+
(`docs/m0saic-thesis.md`).
|
|
32
|
+
|
|
33
|
+
## Read code, not just prose — the three example repos
|
|
34
|
+
|
|
35
|
+
| Repo | What it is | Good for |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| [`m0saic-project/m0saic-template-repo-starter`](https://github.com/m0saic-project/m0saic-template-repo-starter) | ~80 one-concept templates, one lesson each, zero-build | learning the shape of a template; copying a pattern in isolation |
|
|
38
|
+
| [`m0saic-project/m0saic-community-templates`](https://github.com/m0saic-project/m0saic-community-templates) | the public library, one folder per publisher, signed releases | a real submission's layout, tests, registry entry, `deprecated.replacement` |
|
|
39
|
+
| [`m0saic-project/m0saic-packages/packages/templates`](https://github.com/m0saic-project/m0saic-packages/tree/main/packages/templates) | the official library that ships in the product (100+ templates) | the house standard for every kind of template: brand, charts, media, data-driven, pipelines |
|
|
40
|
+
|
|
41
|
+
Start your own from the scaffold:
|
|
42
|
+
[`m0saic-template-repo-starter-base`](https://github.com/m0saic-project/m0saic-template-repo-starter-base)
|
|
43
|
+
(rename its placeholder identity in `src/repo.ts` before you publish).
|
|
44
|
+
|
|
45
|
+
## Verify before you claim it works
|
|
46
|
+
|
|
47
|
+
- `validateM0String(str)` from `@m0saic/dsl` — never ship an m0 string you
|
|
48
|
+
did not validate; `isValidM0String` is the boolean form.
|
|
49
|
+
- `npm run verify` in a starter clone — build, lint, tests, the loader
|
|
50
|
+
contract, the dependency policy.
|
|
51
|
+
- `m0saic doctor <repo>` — the CLI's convention audit over a template repo;
|
|
52
|
+
its `latticeSmooth` finding is blocking.
|
|
53
|
+
- `m0saic make <id> --template-repo <repo> --validate-only` — the plan
|
|
54
|
+
without the render.
|
|
55
|
+
|
|
56
|
+
## What is deliberately not here
|
|
57
|
+
|
|
58
|
+
The engine's internals — filtergraph construction, the cost model, the
|
|
59
|
+
ffmpeg walls and their mitigations, the private app internals. Where a page
|
|
60
|
+
would have cited one it says so in plain text ("absent in the shipped copy")
|
|
61
|
+
and stands on its own. Every author-facing consequence of those internals is
|
|
62
|
+
distilled into [`docs/templates/patterns/perf-authoring-rules.md`](docs/templates/patterns/perf-authoring-rules.md).
|
|
63
|
+
|
|
64
|
+
## Maintenance
|
|
65
|
+
|
|
66
|
+
`docs/` is generated — do not edit it here. The source is the maintainers'
|
|
67
|
+
knowledge tree in the m0saic monorepo; a sync script regenerates this copy
|
|
68
|
+
and fails if any reference to private code survives. Found something wrong?
|
|
69
|
+
Open an issue on the mirror repo.
|
|
70
|
+
|
|
71
|
+
MIT — see LICENSE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Absolute path of the Markdown tree (`docs/`). */
|
|
2
|
+
export declare const docsDir: string;
|
|
3
|
+
/** The agent front door (this package's README). */
|
|
4
|
+
export declare const readme: string;
|
|
5
|
+
/** `docs/m0saic-thesis.md` — the one load-bearing idea. */
|
|
6
|
+
export declare const thesis: string;
|
|
7
|
+
/** `docs/README.md` — the "doing X → read Y" router. */
|
|
8
|
+
export declare const router: string;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The one programmatic surface: where the docs are, for tools that want to
|
|
3
|
+
// point an agent at them (`require.resolve("@m0saic/knowledge")` → this file,
|
|
4
|
+
// `docsDir` → the Markdown tree). The content is the docs themselves.
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const docsDir = path.join(__dirname, "..", "docs");
|
|
7
|
+
module.exports = { docsDir, readme: path.join(__dirname, "..", "README.md"), thesis: path.join(docsDir, "m0saic-thesis.md"), router: path.join(docsDir, "README.md") };
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# `docs/` — the m0saic knowledge base
|
|
2
|
+
|
|
3
|
+
Golden rules and mental models for working in the m0saic ecosystem. This folder is
|
|
4
|
+
**shippable**: it may be published to the public m0saic ecosystem as-is, so new
|
|
5
|
+
engineers can point their agents at it. Read
|
|
6
|
+
[`m0saic-thesis.md`](m0saic-thesis.md) first — the one load-bearing idea.
|
|
7
|
+
|
|
8
|
+
## The moat contract
|
|
9
|
+
|
|
10
|
+
Nothing in this folder may document private engine internals. Deep dives on the
|
|
11
|
+
engine (filtergraph builders, cost-model coefficients, ffmpeg walls and their
|
|
12
|
+
mitigations, private-app internals) live in **`.ai/moat/`** — internal-only, never
|
|
13
|
+
shipped. Public docs here stand alone; where one references an internal deep-dive
|
|
14
|
+
it uses the marked form ``(internal: `.ai/moat/…` — absent in the shipped copy)``
|
|
15
|
+
as plain text, never a markdown link. Moat docs may link here freely; docs here
|
|
16
|
+
must never *depend* on moat content.
|
|
17
|
+
|
|
18
|
+
## Authority hierarchy (from the agent contract §0)
|
|
19
|
+
|
|
20
|
+
1. **handbook/** — canonical truth for DSL grammar, semantics, geometry math
|
|
21
|
+
2. **skills/** — mental models & invariants (subordinate to handbook)
|
|
22
|
+
3. **templates/** — concrete constructs & the authoring surface
|
|
23
|
+
|
|
24
|
+
Handbook wins over skills; skills win over templates. Code wins over all docs —
|
|
25
|
+
found drift? Propose a fix via (internal design history) (agents propose; the owner
|
|
26
|
+
disposes).
|
|
27
|
+
|
|
28
|
+
## Folder map
|
|
29
|
+
|
|
30
|
+
| Folder | Contents | Start with |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| [`handbook/`](handbook/README.md) | DSL grammar + the geometry math (canonical) | `m0-construction-methods.md` |
|
|
33
|
+
| [`skills/`](skills/README.md) | DSL/engine mental models | per-task, see its README |
|
|
34
|
+
| [`templates/`](templates/README.md) | Template contract, construction, authoring | `philosophy-and-contract.md` |
|
|
35
|
+
| `file-formats/` | `.m0` family persistence + the agent-iteration protocol | `m0p-and-custom-field.md` |
|
|
36
|
+
| `runtime/` | CLI usage + author-facing render guidance | `cli-usage.md` |
|
|
37
|
+
|
|
38
|
+
## Doing X → read Y
|
|
39
|
+
|
|
40
|
+
| Task | Read |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Generate / mutate an m0 string | `handbook/m0-construction-methods.md` → `handbook/dsl-rules.md` → `skills/m0saic-string-generation.md` |
|
|
43
|
+
| Any geometry work (splits, grids, gutters) | `handbook/feasibility-precision-quantization.md` (start here — contract §1) |
|
|
44
|
+
| Nesting / composition math | `handbook/composition-arithmetic.md` |
|
|
45
|
+
| Overlays, passthroughs, identity | `skills/overlay-semantics.md`, `skills/passthrough-semantics.md`, `skills/identity.md` |
|
|
46
|
+
| Build a template | `templates/philosophy-and-contract.md` → `templates/construction-strategy.md` → `templates/geometry-recipes.md` |
|
|
47
|
+
| Template perf | `templates/patterns/perf-authoring-rules.md` |
|
|
48
|
+
| Data-driven templates | `templates/data-pipeline.md` |
|
|
49
|
+
| Read/write `.m0` / `.m0c` / `.m0p` / `.m0v` | `file-formats/m0p-and-custom-field.md` |
|
|
50
|
+
| Render via the CLI | `runtime/cli-usage.md` |
|
|
51
|
+
|
|
52
|
+
## House conventions for docs in this tree
|
|
53
|
+
|
|
54
|
+
- **Golden-rule register**: rule → evidence → code pointer (`file:line`). No essays.
|
|
55
|
+
- **Date volatile claims** ("as of 2026-07-27") and ship a one-line re-verification
|
|
56
|
+
grep alongside anything that can drift. Citation density predicts accuracy — the
|
|
57
|
+
docs that named exact files and constants survived audit; the ones that didn't,
|
|
58
|
+
rotted.
|
|
59
|
+
- Code is the source of truth. A doc that contradicts the code is wrong; fix the
|
|
60
|
+
doc (via (internal design history) if you're an agent).
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# `.m0` iteration protocol — one file, one prompt
|
|
2
|
+
|
|
3
|
+
## Mental model
|
|
4
|
+
|
|
5
|
+
A `.m0` / `.m0c` / `.m0p` file is the **atomic unit** of an iteration: ONE geometry, ONE
|
|
6
|
+
question from the writing party, ONE response from the reading party.
|
|
7
|
+
|
|
8
|
+
**Iteration produces NEW files.** The conversation lives in the *directory*, not inside
|
|
9
|
+
any single file. Think of a chess endgame book — each file is a position plus the
|
|
10
|
+
discussion that graded it, and the next move sits in the next file over.
|
|
11
|
+
|
|
12
|
+
Two payoffs:
|
|
13
|
+
|
|
14
|
+
- **Corpus value.** Over time the directory becomes a graded pattern bank: future agents
|
|
15
|
+
browse `(question, geometry, response)` triples and learn what actually worked.
|
|
16
|
+
- **Context survival.** Agent context windows reset; the directory doesn't. Stepping
|
|
17
|
+
back through an old session's files reconstructs the whole design discussion, however
|
|
18
|
+
many resets ago it happened.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Canonical types
|
|
23
|
+
|
|
24
|
+
**`@m0saic/momo-types` (`src/agent.ts`) is the canonical home** — one lightweight,
|
|
25
|
+
dependency-free package for the agent layer, so `@m0saic/dsl-file-formats`, the desktop
|
|
26
|
+
app, and momo's runtime all point at the same upstream instead of maintaining
|
|
27
|
+
structural mirrors.
|
|
28
|
+
|
|
29
|
+
> `@m0saic/momo` (`src/agent/meta.ts`) is now a **re-export shim** kept for
|
|
30
|
+
> back-compat. Import from `momo-types`; momo remains the heavier runtime (agent loop,
|
|
31
|
+
> prompt building) layered on the shared vocabulary. Docs or code still treating
|
|
32
|
+
> `momo/src/agent/meta.ts` as the definition site are stale.
|
|
33
|
+
|
|
34
|
+
| Field | Audience | Shape |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| `note` | reading party (prose) | string |
|
|
37
|
+
| `question` | reading party (the ask) | string |
|
|
38
|
+
| `regions` | downstream router | `stableKey → label` |
|
|
39
|
+
| `context` | downstream router | unknown (JSON) |
|
|
40
|
+
| `response.body` | originating party | string |
|
|
41
|
+
| `response.from` | provenance / routing | `human…` / `agent:<role>` |
|
|
42
|
+
| `response.at` | provenance | ISO 8601 |
|
|
43
|
+
| `comments[]` | human review / provenance | `M0AgentComment[]` |
|
|
44
|
+
|
|
45
|
+
Carried as `# m0agent:<key>: <json-or-prose>` headers in `.m0`, and under the top-level
|
|
46
|
+
`agent` JSON slot in `.m0c` / `.m0p`.
|
|
47
|
+
|
|
48
|
+
Prose fields (`note`, `question`, `response.body`, `comments[].body`) render as
|
|
49
|
+
**markdown** in the Momo FILE pane, and the JSON formats preserve newlines — use short
|
|
50
|
+
lists and tables. The line-based `.m0` format flattens prose to one line, so reach for
|
|
51
|
+
`.m0c` when the question needs real structure.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## The shape: Reddit-style threading
|
|
56
|
+
|
|
57
|
+
Each file is one post:
|
|
58
|
+
|
|
59
|
+
| Slot | Role |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `note` / `question` / `regions` / `context` | the OP's body |
|
|
62
|
+
| `response` | **the** answer — canonical |
|
|
63
|
+
| `comments[]` | the thread below — orbiting discussion |
|
|
64
|
+
|
|
65
|
+
**`response` is single-valued on purpose.** OP + response together are the canonical
|
|
66
|
+
record of one design exchange. Iterating the geometry produces a **new file** (a new
|
|
67
|
+
post), never a second response on this one — because the geometry itself is what
|
|
68
|
+
changed, and the protocol mirrors that.
|
|
69
|
+
|
|
70
|
+
**`comments[]` is explicitly non-canonical.** Append-only by convention; anyone (human
|
|
71
|
+
or agent) may add one to share context, raise a concern, link a related candidate, or
|
|
72
|
+
record a side observation that doesn't merit its own file. Flat array — **no nested
|
|
73
|
+
replies** — ordered chronologically by `at`, falling back to insertion order.
|
|
74
|
+
|
|
75
|
+
> Future agents **route on `response`**. Comments are for human review and provenance.
|
|
76
|
+
> Don't put a verdict in a comment and expect tooling to find it. Mosaic renders
|
|
77
|
+
> comments as URL-hash anchors (`#c-<id>`), so other files and external systems can link
|
|
78
|
+
> a specific post.
|
|
79
|
+
|
|
80
|
+
This is the one place the "single answer" model bends, and it bends deliberately: the
|
|
81
|
+
thread absorbs discussion that would otherwise either pollute the response slot or force
|
|
82
|
+
a spurious new file.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## The loop
|
|
87
|
+
|
|
88
|
+
1. Writing party generates `candidate-N.m0c`, hands over the path.
|
|
89
|
+
2. Reading party opens it — File Details jumps to the agent annotations; `regions`
|
|
90
|
+
hover-highlight in the wireframe.
|
|
91
|
+
3. Reader writes a response, saves. **The same file is rewritten in place.**
|
|
92
|
+
4. Writing party reads the response and generates `candidate-N+1` with new geometry.
|
|
93
|
+
**The old file stays, frozen at its graded state.**
|
|
94
|
+
5. Anyone steps through the directory later to reconstruct the discussion.
|
|
95
|
+
|
|
96
|
+
⚠️ **Never mutate a file that already carries a response.** The verdict is bound to the
|
|
97
|
+
exact geometry it was given; editing the geometry underneath it silently invalidates the
|
|
98
|
+
record and collapses the iteration trail.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Party-agnostic by design
|
|
103
|
+
|
|
104
|
+
`response.from` discriminates the responder — `"human"`, `"human:quentin"`,
|
|
105
|
+
`"agent:claude"`, `"agent:brand-x-stylist"`. Tooling routes on the `human:` / `agent:`
|
|
106
|
+
prefix. One shape covers human↔agent, agent↔agent, and future multi-agent review
|
|
107
|
+
workflows (a brand-trained stylist, a data-viz reviewer, a music-video sensibility
|
|
108
|
+
model).
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Cross-references
|
|
113
|
+
|
|
114
|
+
- **https://github.com/m0saic-project/m0saic-sandbox/blob/main/packages/sandbox/agent.md** — the full operational protocol: file naming,
|
|
115
|
+
`-a`/`-b` forking for parallel sessions, when to start a new session, anti-patterns,
|
|
116
|
+
and the `m0saic open` handoff. **Read it before authoring or iterating a candidate.**
|
|
117
|
+
- `tools/wireframe.mjs` — single-shot wireframe helper for minting a candidate image.
|
|
118
|
+
- `file-formats/m0p-and-custom-field.md` — the `agent` block coexists with `custom.*`:
|
|
119
|
+
`custom` is per-template payload, `agent` is per-iteration metadata. Different
|
|
120
|
+
lifetimes, different owners.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# File Formats: `.m0p` Packs and the `custom.*` Sidecar Pattern
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Reference for m0saic's file-format model. Covers:
|
|
6
|
+
|
|
7
|
+
- When to use `.m0` vs. `.m0c` vs. `.m0p` (see §1's note for the two later arrivals, `.m0g` and `.m0v`).
|
|
8
|
+
- How to read, write, and convert between the formats via `@m0saic/dsl-file-formats`.
|
|
9
|
+
- The `custom: unknown | null` field — the canonical persistence carrier for tool-defined sidecar data.
|
|
10
|
+
- The label and pack validators that ride on top of the formats.
|
|
11
|
+
|
|
12
|
+
These features shipped together in April 2026. They are foundational to v2 work — most v2 features (animation tracks, constraint maps, region asset bindings, mask sets, rank sets, Figma round-trip, SVG round-trip) persist in `custom.*` until convergence justifies promotion to first-class fields.
|
|
13
|
+
|
|
14
|
+
> **Source of truth:** [https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src). Types in [`types.ts`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/types.ts); pack format in [`m0p/m0pFile.ts`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/m0p/m0pFile.ts); conversions in [`conversions.ts`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/conversions.ts); validators in [`validate/`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/validate).
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. The file formats — five, not three (updated 2026-07-26)
|
|
19
|
+
|
|
20
|
+
| Format | Shape | When to use |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `.m0` | Canonical text DSL + lightweight headers (incl. the `m0agent:*` block) | One layout, one canvas, no labels / no derive image / no per-region metadata |
|
|
23
|
+
| `.m0c` | JSON: DSL + StableKey-keyed labels + derive image + meta | One layout, with labels / overlays / derive thumbnail / `custom.*` |
|
|
24
|
+
| `.m0g` | `.m0c`-shaped JSON with `format: "m0g"` + the `M0cGold` `gold` block | A **m0saic golden** ("mogging") — a tried-and-true, signed-off layout; `#mogging` comment-line convention (`types.ts`) |
|
|
25
|
+
| `.m0p` | JSON: pack of `.m0c`-shaped variants under shared identity | Multiple coordinated variants (cross-canvas, brand pack, content set, themed collection) |
|
|
26
|
+
| `.m0v` | JSON: `outputs` / `assets` / `custom` (`src/m0v/m0vFile.ts`) | **Mosaic Vocabulary** — user-tier shared brand language: output presets, palette, typography, asset paths. CLI `--m0v <path>`; `m0saic open` accepts it |
|
|
27
|
+
|
|
28
|
+
`.m0` and `.m0c` are unchanged by the later formats' arrival — each is purely additive.
|
|
29
|
+
This doc covers `.m0`/`.m0c`/`.m0p` in depth; `.m0g` and `.m0v` have their own type
|
|
30
|
+
homes in the same package (conversion helpers for them are not exported — the §3
|
|
31
|
+
matrix below is `.m0`/`.m0c`/`.m0p` only, by design).
|
|
32
|
+
|
|
33
|
+
All JSON formats (and `.m0` via its header block) also carry the top-level
|
|
34
|
+
`agent` slot (`M0AgentMeta`) used by the sandbox iteration protocol — see
|
|
35
|
+
[`m0-iteration-protocol.md`](m0-iteration-protocol.md).
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 2. `.m0p` — multi-variant pack format
|
|
40
|
+
|
|
41
|
+
A single JSON container that bundles multiple `.m0c`-shaped layout variants under one shared identity.
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
type M0pFile = {
|
|
45
|
+
format: "m0p";
|
|
46
|
+
version: 1;
|
|
47
|
+
created: string; // ISO timestamp
|
|
48
|
+
app?: string | null;
|
|
49
|
+
appVersion?: string | null;
|
|
50
|
+
meta?: M0FileMeta | null;
|
|
51
|
+
regions?: M0pRegions | null;
|
|
52
|
+
custom?: unknown | null; // pack-level custom JSON
|
|
53
|
+
variants: Record<string, M0pVariantEntry>;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
type M0pVariantEntry = {
|
|
57
|
+
meta?: M0FileMeta | null; // overrides pack-level when present
|
|
58
|
+
size: { width: number; height: number };
|
|
59
|
+
m0: M0String;
|
|
60
|
+
labels?: Record<StableKey, { text: string }> | null;
|
|
61
|
+
derive?: { image: string | null };
|
|
62
|
+
custom?: unknown | null; // per-variant custom JSON
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Variant keys** validated as `^[a-z0-9][a-z0-9-]*$` (kebab-case). Examples: `desktop`, `mobile`, `square`, `story`.
|
|
67
|
+
|
|
68
|
+
**Pack-level fields are defaults.** Per-variant overrides for `meta` are supported but only emitted when they differ — roundtripping doesn't manufacture spurious overrides.
|
|
69
|
+
|
|
70
|
+
**Pack-level `regions` registry** declares the shared semantic vocabulary (e.g. `headline`, `hero`, `logo`, `cta`) that variants reference *by label text* (not by StableKey — keeping StableKey purely structural).
|
|
71
|
+
|
|
72
|
+
**Deterministic serialization.** Variant keys sorted alphabetically, region keys sorted, label keys sorted by StableKey, DSL canonicalized, fixed field order, 2-space indent + trailing newline. Byte-stable roundtrip.
|
|
73
|
+
|
|
74
|
+
**Forward-compatible.** Unknown fields silently preserved at every level (same posture as `.m0c`).
|
|
75
|
+
|
|
76
|
+
Live type definitions: see `M0pFile`, `M0pVariantEntry`, `M0pRegions`, `M0FileMeta`, `M0cFile`, `M0File` in [`types.ts`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/types.ts). **Trust the types over the snippets above** if they ever drift.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3. The 3×3 conversion matrix
|
|
81
|
+
|
|
82
|
+
`@m0saic/dsl-file-formats` exposes one canonical entry point for every direction:
|
|
83
|
+
|
|
84
|
+
| from \ to | `.m0` | `.m0c` | `.m0p` |
|
|
85
|
+
|---|---|---|---|
|
|
86
|
+
| `.m0` | identity | `upgradeM0ToM0c` | `upgradeM0ToPack` |
|
|
87
|
+
| `.m0c` | `downgradeM0cToM0` ⚠ | identity | `bundleM0cIntoPack` |
|
|
88
|
+
| `.m0p` | `extractVariantAsM0` ⚠ | `extractVariantAsM0c` | identity |
|
|
89
|
+
|
|
90
|
+
⚠ = lossy by design. Named `downgrade*` / `extract*` so the data loss is visible at the call site rather than hidden in an `as`-style cast.
|
|
91
|
+
|
|
92
|
+
All conversions are pure object transforms — no I/O, no async.
|
|
93
|
+
|
|
94
|
+
`upgradeM0ToM0c` / `downgradeM0cToM0` / `upgradeM0ToPack` / `extractVariantAsM0` live in [`conversions.ts`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/conversions.ts). `bundleM0cIntoPack` / `extractVariantAsM0c` live in [`m0p/m0pFile.ts`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/m0p/m0pFile.ts).
|
|
95
|
+
|
|
96
|
+
**Discovery helpers** (also exported from `m0p/m0pFile.ts`): `listVariantKeys(pack)` (alphabetical), `getVariant(pack, key)`, `findVariantBySize(pack, w, h)`.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 4. The `custom: unknown | null` field
|
|
101
|
+
|
|
102
|
+
Both `.m0c` and `.m0p` carry a `custom` field at every level — pack root + per-variant. JSON round-trips byte-stable; the format treats it as opaque.
|
|
103
|
+
|
|
104
|
+
**Why opaque.** Tool-defined metadata that the format spec does not bless. Tools that care read `custom.<key>`; tools that don't ignore it. No validator commitment, no conversion-matrix obligation, no schema enforcement.
|
|
105
|
+
|
|
106
|
+
**The persistence pattern for v2 sidecar data.** Multiple v2 features use `custom.*` keys:
|
|
107
|
+
|
|
108
|
+
| `custom.*` key | What it carries | Owning ticket / surface |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| `custom.animation` | Animation tracks + keyframes | ED-4 (animation timeline) |
|
|
111
|
+
| `custom.constraints` | Per-tile / per-region constraint maps | SL-8 (constraints layer) |
|
|
112
|
+
| `custom.assets` | StableKey → asset binding | ED-10a (asset registry) |
|
|
113
|
+
| `custom.maskSets` | Named subsets of StableKeys | ED-10b (mask editor) |
|
|
114
|
+
| `custom.rankSets` | Named ordered StableKey lists | ED-10c (rank editor) |
|
|
115
|
+
| `custom.figma` | Figma round-trip metadata | XP-4 (Figma plugin) |
|
|
116
|
+
| `custom.svg` | SVG import round-trip metadata | ED-7 / XP-3 |
|
|
117
|
+
|
|
118
|
+
**Promotion rule.** A shape lives in `custom.*` first. Promote to a first-class field only when (a) ≥2 tools have converged on the shape, and (b) a real exchange need exists. This is how the format stays additive without committing to schemas that need to evolve.
|
|
119
|
+
|
|
120
|
+
**Already promoted (first-class per-frame fields).** Several shapes have walked this path and now sit next to `labels` on both `M0cFile` and `M0pVariantEntry`, every one keyed by `StableKey` (structural identity that survives splits / overlays / repacks) — `masks` (`{ localPath, bounds }` inline silhouettes), `fill` (`{ color?, mediaRef? }` rect fill), `rankSets` (named sweep-progress maps), and `insets` (`{ top, right, bottom, left }`, per-edge fractions 0..1 of the frame's cell). **Trust `types.ts` for the live field list.** Notes on `insets` (the newest, shipped 2026-07):
|
|
121
|
+
|
|
122
|
+
- It's the render-time box a source shrinks its cell to — promoted from the engine-only `MosaicSource.placement.inset`. It's the **resolved projection** of `placement.inset`'s `MosaicBoxFrac` superset (`number | {x,y} | per-side`), collapsed to the one four-edge wire form at the extraction boundary (the app's `resolveBoxFrac`), byte-identical to ViewFrame's `insetBoxes` prop. If `MosaicBoxFrac` grows a new authoring form, the `resolveBoxFrac` call sites resolve it — `M0cInset` doesn't change (see `MIRRORED_TYPES.md`).
|
|
123
|
+
- It's the persisted home for **quantization-hostile** layout: quantize cells outward onto a coarse divisor lattice, then recover the exact painted rect at render time via half-pixel-centered fractions (`(n + 0.5) / dim`; the engine floors `frac * dim`) — zero drift at the authored canvas size, ≤1px degradation at other sizes. This is the `placeInsetRects` launder given a file-format home.
|
|
124
|
+
- **Null semantics follow `fill`, not `masks`:** no inner explicit `null` (key absence = "no inset"); all-zero entries are dropped by normalizer and parser.
|
|
125
|
+
- `validateInsets` warns (never errors — the engine clamps): `ORPHANED_INSET`, `INSET_OUT_OF_RANGE` (edge < 0 or ≥ 1), `INSET_COLLAPSES_FRAME` (`top+bottom ≥ 1` or `left+right ≥ 1`). Rolled into `validatePack` as `PackVariantIssues.insetIssues`.
|
|
126
|
+
- **Derived-vs-sidecar precedence, no merge logic:** Make / Compose paint *derived* insets from live sources (`buildGeometryDecor`); Layout paints the *sidecar* (`m0cExtras.insets`). Layout has no sources → no conflict. The Make → Layout handoff converts derived → sidecar once at send time; the Layout → Compose join writes the sidecar back onto `sources[i].placement.inset`. A public `(m0, inset map) → exact rects` adapter is deferred until a real caller appears.
|
|
127
|
+
|
|
128
|
+
**Default value.** `null`. Round-tripping a file without a `custom` field through serialize→parse→serialize is byte-stable.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 5. Label and pack validators
|
|
133
|
+
|
|
134
|
+
**Four** pure validators ship in `@m0saic/dsl-file-formats` ([`validate/`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/validate)): `validateLabels`, `validateFill`, `validateInsets` (§4 above), and `validatePack`. All return structured results — no React, no DOM, no parsing inside. This section details the label + pack pair.
|
|
135
|
+
|
|
136
|
+
Result types: `LabelValidationResult`, `PackValidationResult`, `PackVariantIssues` in [`validate/types.ts`](https://github.com/m0saic-dsl/m0/blob/main/packages/dsl-file-formats/src/validate/types.ts). Empty-result sentinels: `EMPTY_LABEL_RESULT`, `EMPTY_PACK_RESULT`.
|
|
137
|
+
|
|
138
|
+
### `validateLabels`
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
validateLabels({
|
|
142
|
+
validStableKeys: Set<StableKey>,
|
|
143
|
+
labels: Record<StableKey, { text: string }>,
|
|
144
|
+
}): LabelValidationResult;
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Flags labels whose `stableKey` no longer maps to a frame in the layout's parsed frame set. Surfaces "you split the frame I was labeled on, my label is now floating in space."
|
|
148
|
+
|
|
149
|
+
The caller supplies the parsed `validStableKeys` set so editors can reuse a parse they were already going to do (`<ViewFrame>` runs `parseM0StringComplete` on every geometry change; the validator just consumes its output).
|
|
150
|
+
|
|
151
|
+
### `validatePack`
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
validatePack(
|
|
155
|
+
pack: M0pFile,
|
|
156
|
+
opts?: { liveVariantOverride?: ...; parseCache?: ... }
|
|
157
|
+
): PackValidationResult;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Three classes of issue:
|
|
161
|
+
|
|
162
|
+
1. **Region coverage.** Variants missing required regions (per `pack.regions`).
|
|
163
|
+
2. **Region duplicates.** Variants where multiple labels resolve to the same region (case-insensitive duplicate).
|
|
164
|
+
3. **Per-variant orphan labels.** Same shape `validateLabels` produces, scoped per variant.
|
|
165
|
+
|
|
166
|
+
Returns aggregates at the pack level + a per-variant breakdown.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 6. When to use what — decision tree
|
|
171
|
+
|
|
172
|
+
- One layout, one canvas, no metadata → **`.m0`**
|
|
173
|
+
- One layout, with labels / overlays / derive image → **`.m0c`**
|
|
174
|
+
- One layout, with tool-defined sidecar data → **`.m0c` with `custom.*`**
|
|
175
|
+
- Multiple coordinated variants of one design (responsive) → **`.m0p`**
|
|
176
|
+
- Multiple unrelated layouts under shared identity (brand pack, content set) → **`.m0p`**
|
|
177
|
+
- Anything format-doesn't-bless-yet → **`custom.*` on the appropriate format**
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 7. Common mistakes to avoid
|
|
182
|
+
|
|
183
|
+
- **Don't promote a `custom.*` shape to a first-class field early.** Wait for ≥2 tools on the shape.
|
|
184
|
+
- **Don't put random data on the root of `.m0c` or `.m0p`.** It will be silently preserved as an unknown field but won't go through `custom.*` validation hooks.
|
|
185
|
+
- **Don't use StableKeys as region names.** Regions reference labels by *text*, not by StableKey, so labels survive structural edits while regions stay stable.
|
|
186
|
+
- **Don't skip `validateLabels` after structural edits.** Splitting a frame can orphan labels; the validator surfaces this immediately.
|
|
187
|
+
- **Don't rely on `.m0p` variant order.** Serialization sorts variant keys alphabetically. If your tool depends on order, store it explicitly in `custom.*`.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## See also
|
|
192
|
+
|
|
193
|
+
- `../handbook/dsl-rules.md` — DSL grammar for the m0 strings each variant carries.
|
|
194
|
+
- Quality scoring works against any of these formats — internal: `.ai/moat/skills/score-layout-primitive.md`.
|
|
195
|
+
- `../skills/identity.md` — the StableKey contract, overlay namespace, and identity-continuity rules that labels and regions ride on.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# handbook/ — canonical DSL truth
|
|
2
|
+
|
|
3
|
+
The authoritative layer (contract §0): grammar, semantics, and the geometry math.
|
|
4
|
+
On any conflict with skills/ or templates/, this folder wins; the code wins over
|
|
5
|
+
this folder.
|
|
6
|
+
|
|
7
|
+
## Read order
|
|
8
|
+
|
|
9
|
+
1. [`m0-construction-methods.md`](m0-construction-methods.md) — **the entry
|
|
10
|
+
point**: every way to produce an m0, the four currencies, the canonical
|
|
11
|
+
8-rung launder ladder, pairwise discriminators.
|
|
12
|
+
2. [`dsl-rules.md`](dsl-rules.md) — what's legal: surface grammar, tokens,
|
|
13
|
+
canonicalization, the 11 error codes × kind taxonomy, warnings surface.
|
|
14
|
+
3. [`feasibility-precision-quantization.md`](feasibility-precision-quantization.md)
|
|
15
|
+
— will ONE split render, look right, stay balanced: the two independent
|
|
16
|
+
floors, the three drafting modes (§3c), quantization fixes. **Start here for
|
|
17
|
+
any geometry work** (contract §1).
|
|
18
|
+
4. [`composition-arithmetic.md`](composition-arithmetic.md) — will STACKED
|
|
19
|
+
splits work: prime-factor budgets, the 5-smooth invariant, base×fiber,
|
|
20
|
+
hereditary quantization.
|
|
21
|
+
|
|
22
|
+
## Reference
|
|
23
|
+
|
|
24
|
+
- [`precision-tiers.md`](precision-tiers.md) — light primitives / precise heads,
|
|
25
|
+
and the GCD-collapse search.
|
|
26
|
+
- [`dsl-complexity.md`](dsl-complexity.md) — the complexity metrics API
|
|
27
|
+
(`getComplexityMetricsFast`).
|