@flatkit/compiler 0.35.0 → 0.35.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/dist/analysis.js
CHANGED
|
@@ -176,7 +176,7 @@ function lint(src, ctx = {}) {
|
|
|
176
176
|
if (!knownObjs.has(o)) out.push({ line: s.line, col: s.col, message: `unknown object "${o}" (expected: ${[...knownObjs].join(", ")})` });
|
|
177
177
|
for (const id of a.refs.ids)
|
|
178
178
|
if (!knownIds.has(id))
|
|
179
|
-
out.push({ line: s.line, col: s.col, message: `unknown variable "${id}"${variables.size ? "" :
|
|
179
|
+
out.push({ line: s.line, col: s.col, message: `unknown variable "${id}"${variables.size ? "" : ` \u2014 declare it at the top level of the program: \`var ${id} = 0\``}` });
|
|
180
180
|
} else if (labels && !labels.has(s.name)) {
|
|
181
181
|
out.push({ line: s.line, col: s.col, message: `unknown label "${s.name}"` });
|
|
182
182
|
}
|
|
@@ -1012,4 +1012,4 @@ export {
|
|
|
1012
1012
|
applyFixes,
|
|
1013
1013
|
repairLoop
|
|
1014
1014
|
};
|
|
1015
|
-
//# sourceMappingURL=chunk-
|
|
1015
|
+
//# sourceMappingURL=chunk-W3YUC6BC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/scopeProgram.ts","../src/lint.ts","../src/programDoc.ts","../src/docWalk.ts","../src/check.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// scopeProgram.ts — the \"unified file\" of a scope (the Scene, or a Symbol).\n//\n// Vision: one file = one scope. All the code of a scope fits in ONE text:\n// var … (global variables, root only)\n// when loaded {} (lifecycle of the scope's timeline)\n// every frame {}\n// object \"name\" {} (one block per scripted object of the scope)\n//\n// This is the `.flatink` structure WITHOUT the geometry (which stays visual). This module\n// ONLY deals with the text: splitting the `object` blocks from the rest, and formatting a block.\n// The wiring to the Doc (a single commit) lives in the store, which reuses these functions\n// + scriptDoc/dsl. Pure, no DOM, testable.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** End of the block opened at `open` (index of the matching `}`), ignoring strings and comments. -1 if unclosed. */\nfunction matchBrace(s: string, open: number): number {\n let depth = 0\n for (let i = open; i < s.length; i++) {\n const c = s[i]\n if (c === '\"') { i++; while (i < s.length && s[i] !== '\"') { if (s[i] === '\\\\') i++; i++ }; continue }\n if (c === '/' && s[i + 1] === '/') { while (i < s.length && s[i] !== '\\n') i++; continue }\n if (c === '{') depth++\n else if (c === '}') { depth--; if (depth === 0) return i }\n }\n return -1\n}\n\n/** Splits a scope file: the `object \"name\" { … }` blocks on one side, the REST (var + lifecycle) on the other. */\nexport function splitScopeProgram(text: string): { rest: string; objects: { name: string; body: string }[] } {\n let rest = ''\n let i = 0\n const objects: { name: string; body: string }[] = []\n while (i < text.length) {\n const m = /object\\s+\"((?:[^\"\\\\]|\\\\.)*)\"\\s*\\{/.exec(text.slice(i))\n if (!m) { rest += text.slice(i); break }\n const start = i + m.index\n rest += text.slice(i, start)\n const ob = start + m[0].length - 1 // the opening brace\n const oc = matchBrace(text, ob)\n if (oc < 0) { rest += text.slice(start); break } // unclosed block → left to the rest (diagnostic downstream)\n objects.push({ name: m[1].replace(/\\\\(.)/g, (_, c) => (c === 'n' ? '\\n' : c)), body: text.slice(ob + 1, oc) })\n i = oc + 1\n }\n return { rest, objects }\n}\n\n/** LINTABLE regions of a scope file (the \"rest\" gaps + the `object` bodies), with their\n * 1-based start line in the original text — to lint each piece as pure DSL and\n * reproject the positions. The `object` keyword and its braces are NOT DSL: we skip them. */\nexport function scopeRegions(text: string): { body: string; line: number }[] {\n const lineAt = (off: number) => text.slice(0, off).split('\\n').length\n const regions: { body: string; line: number }[] = []\n let i = 0\n let restStart = 0\n while (i < text.length) {\n const m = /object\\s+\"((?:[^\"\\\\]|\\\\.)*)\"\\s*\\{/.exec(text.slice(i))\n if (!m) break\n const start = i + m.index\n const gap = text.slice(restStart, start)\n if (gap.trim()) regions.push({ body: gap, line: lineAt(restStart) })\n const ob = start + m[0].length - 1\n const oc = matchBrace(text, ob)\n if (oc < 0) break\n regions.push({ body: text.slice(ob + 1, oc), line: lineAt(ob + 1) })\n i = oc + 1\n restStart = i\n }\n const tail = text.slice(restStart)\n if (tail.trim()) regions.push({ body: tail, line: lineAt(restStart) })\n return regions\n}\n\nconst esc = (s: string) => s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n')\nconst indent = (body: string) => body.split('\\n').map((l) => (l.trim() ? ' ' + l : l)).join('\\n')\n\n/** Formats an `object \"name\" { … }` block (body already in DSL). */\nexport function formatObjectBlock(name: string, body: string): string {\n const inner = body.trim()\n return `object \"${esc(name)}\" {\\n${inner ? indent(inner) + '\\n' : ''}}`\n}\n\n/** Assembles a scope file: rest (var + lifecycle) then the object blocks, separated by a blank line. */\nexport function joinScopeProgram(rest: string, objects: { name: string; body: string }[]): string {\n const parts: string[] = []\n if (rest.trim()) parts.push(rest.trim())\n for (const o of objects) if (o.body.trim()) parts.push(formatObjectBlock(o.name, o.body))\n return parts.length ? parts.join('\\n\\n') + '\\n' : ''\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// lint.ts — linter for the FlatInk Script language (batch L3).\n//\n// Builds on the parser (dsl.ts) for syntax errors + positions, then adds\n// SEMANTIC validation, ~free and PURE:\n// • each expression is compiled (compileExpr) → expression syntax error;\n// • referenced functions / member objects / identifiers are checked against\n// the standard environment (expr.ts) + the known variables → \"unknown\";\n// • `go to \"label\"` is checked against the set of known labels.\n//\n// Tolerant and kid-friendly: a variable is \"known\" if it is declared\n// (`let`) OR simply assigned (`x = …`) somewhere in the source, or provided\n// by the caller (document global variables). Labels are only checked\n// if the caller provides their list (otherwise we don't know the universe).\n// ─────────────────────────────────────────────────────────────────────────────\nimport { analyzeExpr, STD_CONSTANTS, STD_FUNCTIONS, STD_IDS, STD_OBJECTS } from '@flatkit/engine/expr'\nimport { packageFunctionNames } from '@flatkit/engine/stdlib'\nimport { parseUnits, type Diagnostic, type ScriptUnit, type TextEdit } from '@flatkit/engine/dsl'\nimport type { Action } from '@flatkit/engine/actions'\n\nexport type LintContext = {\n /** Known variables in addition to those declared/assigned in the source. */\n variables?: Iterable<string>\n /** Known labels (timeline). Absent = we don't check `go to \"…\"`. */\n labels?: Iterable<string>\n /** Known functions in addition to those defined in the source. */\n functions?: Iterable<string>\n /** Scene objects referenceable by name (`Hero.x`) — in addition to mouse/keys. */\n objects?: Iterable<string>\n}\n\n/** Collects the names of ASSIGNED variables (setVar) + loop vars, inside action bodies. */\nfunction collectAssigned(actions: Action[], into: Set<string>): void {\n for (const a of actions) {\n if (a.do === 'setVar') into.add(a.name)\n else if (a.do === 'if') {\n collectAssigned(a.then, into)\n if (a.else) collectAssigned(a.else, into)\n } else if (a.do === 'repeat') collectAssigned(a.body, into)\n else if (a.do === 'repeatRange') { into.add(a.var); collectAssigned(a.body, into) } // i is known in the body\n }\n}\n\n/** Locally known variables: `let` declarations + every assigned variable. */\nexport function localVariables(units: ScriptUnit[]): Set<string> {\n const vars = new Set<string>()\n for (const u of units) {\n if (u.kind === 'declare') vars.add(u.name)\n else if (u.kind === 'event' || u.kind === 'frameActions') collectAssigned(u.body, vars)\n else if (u.kind === 'each') vars.add(u.as) // the index is known in the each bindings\n else if (u.kind === 'interactor') { if (u.varX) vars.add(u.varX); if (u.varY) vars.add(u.varY) } // drag writes these variables\n else if (u.kind === 'drop') collectAssigned(u.body, vars)\n else if (u.kind === 'func') { for (const p of u.func.params) vars.add(p); if (u.func.kind === 'proc') collectAssigned(u.func.body, vars) } // params + assignments\n }\n return vars\n}\n\n/** Detects a `text(` call (whole word) in an expression → only allowed in a `send` payload. */\nconst TEXT_CALL = /\\btext\\s*\\(/\n\n/** A bare assignment (`x =`, `a[i] =`; NOT ==/<=/>=/!=) left inside an expression: the tell-tale of a\n * SECOND statement crammed onto one line (FlatInk ends a statement at the newline, so it got swallowed). */\nconst SECOND_ASSIGN = /[\\w\\]]\\s*=(?![=])/\n\n/** Same tell-tale for the statements that are NOT assignments — `score = score + 1 send \"correct\", 1`\n * swallowed the `send` and reported a bewildering `unexpected character \"\"\"` instead. All of these are\n * RESERVED words (cf. ident.ts), so none can legitimately appear as a name inside an expression. */\nconst SECOND_ACTION = /\\b(send|play|pause|sound|set|go|repeat)\\b/\n\n/** Where the swallowed SECOND statement begins inside the expression text, or -1. `send`-style actions\n * start at their keyword; a swallowed assignment starts at the identifier its `=` belongs to. */\nfunction splitPoint(text: string): number {\n const act = SECOND_ACTION.exec(text)\n if (act) return act.index\n const asg = SECOND_ASSIGN.exec(text)\n if (!asg) return -1\n const upTo = text.slice(0, asg.index + 1) // the char before `=` is the last of the identifier\n const id = /[A-Za-z_$][\\w$]*\\s*$/.exec(upTo)\n return id ? upTo.length - id[0].length : -1\n}\n\n/** The `fix` half of the two-statements diagnostic: replace the expression text with its two lines. */\nfunction withSplit(s: { text: string; line: number; col: number }): { fix?: TextEdit } {\n const at = splitPoint(s.text)\n if (at <= 0) return {}\n const left = s.text.slice(0, at).trimEnd()\n const right = s.text.slice(at).trim()\n if (!left || !right) return {}\n return { fix: { line: s.line, col: s.col, endLine: s.line, endCol: s.col + s.text.length, replacement: `${left}\\n${right}` } }\n}\n\n/** Analyze a DSL source and return all diagnostics (syntax + semantic). */\nexport function lint(src: string, ctx: LintContext = {}): Diagnostic[] {\n const { units, diagnostics, sites } = parseUnits(src)\n const out: Diagnostic[] = [...diagnostics]\n\n const variables = localVariables(units)\n for (const v of ctx.variables ?? []) variables.add(v)\n const knownIds = new Set<string>([...STD_IDS, ...STD_CONSTANTS, ...variables])\n const knownFns = new Set(STD_FUNCTIONS)\n knownFns.add('velocity') // valid inside a spring/smooth target (resolved by the modifier advance); NOT a stdlib\n for (const u of units) {\n if (u.kind === 'func') knownFns.add(u.func.name) // user-defined functions\n else if (u.kind === 'use') for (const name of packageFunctionNames(u.name)) knownFns.add(name) // package functions (bare + qualified)\n }\n for (const f of ctx.functions ?? []) knownFns.add(f)\n const knownObjs = new Set(STD_OBJECTS)\n for (const o of ctx.objects ?? []) knownObjs.add(o) // scene objects (Hero.x…)\n const labels = ctx.labels ? new Set(ctx.labels) : null\n\n for (const s of sites) {\n if (s.kind === 'expr') {\n // `text(…)` is valid ONLY as a `send` payload (consumed by the parser, never\n // exposed as an expression site). Seeing it here = out-of-context use → dedicated error.\n if (TEXT_CALL.test(s.text)) {\n out.push({ line: s.line, col: s.col, message: 'text(\"…\") is only allowed as an argument to \"send\"' })\n continue\n }\n const a = analyzeExpr(s.text)\n if (!a.ok) {\n // #1 footgun: two statements on one line. The 2nd one got swallowed into this expression → a\n // cryptic \"unexpected character = / \\\"\". Detect the leftover statement and NAME it, so the rule\n // (\"one action per line\") is visible from the message rather than only from the docs.\n const leftover = SECOND_ASSIGN.test(s.text) ? 'an assignment' : SECOND_ACTION.test(s.text) ? `\\`${SECOND_ACTION.exec(s.text)![1]} …\\`` : ''\n const message = leftover\n ? `two statements on one line — ${leftover} was swallowed into the expression before it. FlatInk ends a statement at the NEWLINE: put each action on its own line.`\n : `invalid expression: ${a.error}`\n // The repair is mechanical: the boundary is where the SECOND statement starts, and the parser\n // already located it to name it. Split there; anything else about the line stays untouched.\n out.push({ line: s.line, col: s.col, message, ...(leftover ? withSplit(s) : {}) })\n continue\n }\n for (const fn of a.refs.calls) if (!knownFns.has(fn)) out.push({ line: s.line, col: s.col, message: `unknown function \"${fn}\"` })\n for (const o of a.refs.members)\n if (!knownObjs.has(o)) out.push({ line: s.line, col: s.col, message: `unknown object \"${o}\" (expected: ${[...knownObjs].join(', ')})` })\n for (const id of a.refs.ids)\n if (!knownIds.has(id))\n // The hint names the DOCUMENT declaration (`var`, at the top level of the program), because that\n // is the one every scope can read. `let` declares in the scope it sits in — which is why the old\n // hint sent a reader in a circle: they declared with `let`, the binding still could not see it,\n // and the message repeated itself. (Both spellings mean the same thing at the top level of a\n // program; inside an `object` block a declaration is refused outright, with its own message.)\n out.push({ line: s.line, col: s.col, message: `unknown variable \"${id}\"${variables.size ? '' : ` — declare it at the top level of the program: \\`var ${id} = 0\\``}` })\n } else if (labels && !labels.has(s.name)) {\n out.push({ line: s.line, col: s.col, message: `unknown label \"${s.name}\"` })\n }\n }\n\n return out.sort((a, b) => a.line - b.line || a.col - b.col)\n}\n\n/**\n * Lint report ready to feed back to a generator (LLM/CLI): `''` = no issue (the code passes),\n * otherwise one `line:col: message` line per diagnostic. Primitive of the \"generate → lint →\n * fix\" loop: the language fits in few tokens, robustness comes from this feedback, not from context.\n */\nexport function lintReport(src: string, ctx: LintContext = {}): string {\n return lint(src, ctx).map((d) => `${d.line}:${d.col}: ${d.message}`).join('\\n')\n}\n","// -----------------------------------------------------------------------------\n// programDoc.ts — PURE bridge Doc <-> \"scope program\" (text) + lint of a whole Doc.\n//\n// Both the editor AND the CLI need to rebuild the DSL text of a scope (to display it,\n// or to lint it) and to assemble the lint context (variables/labels/functions/objects)\n// FROM a Doc — without depending on the React store. Everything lives here, pure and testable:\n// • `scopeProgram` : Doc fragments -> program text of a scope (round-trip via printUnits);\n// • `docLintContext` : Doc + scope -> LintContext (known names);\n// • `lintDoc` / report : semantic lint of ALL the scopes of a Doc (scene + symbols).\n// -> the CLI gains a `flatc --check`, the editor stops duplicating the logic.\n// -----------------------------------------------------------------------------\nimport type { Doc, EditFrame, Group, Instance } from '@flatkit/types'\nimport { printUnits, type Diagnostic } from '@flatkit/engine/dsl'\nimport { joinScopeProgram, scopeRegions } from './scopeProgram'\nimport { functionsToUnits, importsToUnits, objectToUnits, timelineToUnits, variablesToUnits } from '@flatkit/engine/scriptDoc'\nimport { contextLayers, getScopeTimeline, isContainer, isGroup, isInstance, isText, isImage, isPoseable, isRegion } from '@flatkit/engine/layers'\nimport { importedFunctions } from '@flatkit/engine/stdlib'\nimport { EXPR_CHANNELS, OFFSET_CHANNELS } from '@flatkit/engine/timeline'\nimport { objectNames } from '@flatkit/engine/sceneRefs'\nimport { behaviorRegions } from '@flatkit/engine/flatFormat'\nimport { itemBBox, itemBoundsById, dropZoneBounds, transformBBox, revealGrid } from '@flatkit/engine/groups'\nimport { IDENTITY, apply, compose } from '@flatkit/engine/transform'\nimport { makePathSampler } from '@flatkit/engine/path'\nimport { bboxIntersects } from '@flatkit/engine/bbox'\nimport { lint, localVariables, type LintContext } from './lint'\nimport { forEachAction, forEachExpression } from './docWalk'\nimport { parseUnits } from '@flatkit/engine/dsl'\nimport type { Image, Item, Layer, ParamDef, Region, SymbolDef, Text, Transform } from '@flatkit/types'\n\n/** Rebuilds the \"program\" text of a scope (imports + variables + functions + scene cycle\n * + one `object \"Name\" { … }` block per scripted container with a unique name). Pure, round-trip via printUnits. */\nexport function scopeProgram(doc: Doc, editPath: EditFrame[] = []): string {\n const atRoot = editPath.length === 0\n const items = contextLayers(doc, editPath).flatMap((l) => l.items)\n const nameCount = new Map<string, number>()\n for (const it of items) if (isContainer(it) && it.name) nameCount.set(it.name, (nameCount.get(it.name) ?? 0) + 1)\n const scripted = (it: Group | Instance) => !!doc.interactions?.some((i) => i.targetId === it.id) || !!doc.interactors?.some((i) => i.targetId === it.id) || !!(it.expressions && Object.keys(it.expressions).length)\n const objects = items\n .filter((it): it is Group | Instance => isContainer(it) && !!it.name && nameCount.get(it.name) === 1 && scripted(it))\n .map((it) => ({ name: it.name, body: printUnits(objectToUnits(it.id, doc.interactions, it.expressions, doc.interactors)) }))\n const imports = atRoot ? printUnits(importsToUnits(doc.imports)) : ''\n // A local package (`use \"physics\"` -> physics.flatink) is inlined TWICE into doc.functions: `tick` and the\n // qualified alias `physics.tick` (so both call forms resolve). The alias is not authored source and has NO\n // syntax (`fn physics.tick(s) = …` does not parse) -> never re-emit it, or the reconstructed program fails\n // to parse and `--check` reports phantom errors. The alias stays in `doc.functions`, so `docLintContext`\n // still knows `physics.tick` as a callable name.\n const funcs = atRoot ? printUnits(functionsToUnits((doc.functions ?? []).filter((f) => !f.name.includes('.')))) : ''\n const globals = atRoot ? printUnits(variablesToUnits(doc.variables)) : ''\n const scene = printUnits(timelineToUnits(getScopeTimeline(doc, editPath)))\n const head = [imports, globals, funcs, scene].filter((t) => t.trim()).join('\\n\\n')\n return joinScopeProgram(head, objects)\n}\n\n/** Lint context of a scope: known names (variables, labels, functions, objects) drawn from the Doc.\n * `extraVars` = variables assigned in the OTHER scopes (FlatInk variables are GLOBAL -> known\n * everywhere; avoids a false \"unknown variable\" on a var written elsewhere, e.g. generated by `match`). */\nexport function docLintContext(doc: Doc, editPath: EditFrame[] = [], extraVars?: Iterable<string>): LintContext {\n return {\n // A symbol's own `params` (and state params) are injected into its instance scope at runtime, so they are\n // valid variables in ITS `expr` -- add them, but ONLY to that symbol's scope (resolved from `editPath`),\n // never globally, so a param named in symbol A can't mask a real typo of the same name in symbol B.\n variables: [...Object.keys(doc.variables ?? {}), ...(extraVars ?? []), ...scopeSymbolParams(doc, editPath)],\n labels: (getScopeTimeline(doc, editPath)?.labels ?? []).map((l) => l.name),\n functions: [...(doc.functions ?? []).map((f) => f.name), ...importedFunctions(doc.imports).map((f) => f.name)],\n objects: objectNames(contextLayers(doc, editPath)),\n }\n}\n\n/** Names exposed as variables by the symbol of `editPath` (its `params` + state params), or `[]` for the\n * scene scope / an unresolved path. Mirrors the per-instance scope the runtime and `--preview` build. */\nfunction scopeSymbolParams(doc: Doc, editPath: EditFrame[]): string[] {\n const frame = [...editPath].reverse().find((f): f is Extract<EditFrame, { kind: 'symbol' }> => f.kind === 'symbol')\n const sym = frame ? doc.symbols.find((s) => s.id === frame.symbolId) : undefined\n if (!sym) return []\n return [...(sym.params ?? []).map((p) => p.name), ...(sym.states ?? []).map((s) => s.param)]\n}\n\n/** All the scopes of a Doc: the scene (root) + each symbol of the library. */\nfunction scopes(doc: Doc): { label: string; editPath: EditFrame[] }[] {\n return [{ label: 'scene', editPath: [] }, ...doc.symbols.map((s) => ({ label: s.name, editPath: [{ kind: 'symbol' as const, symbolId: s.id, name: s.name }] }))]\n}\n\n/** Union of the variables ASSIGNED in ALL the scopes (scene + symbols). FlatInk variables are\n * global -> a var written in one scope is legitimate in the others (cross-scope reads). */\nexport function allScopeVariables(doc: Doc): string[] {\n const set = new Set<string>()\n for (const { editPath } of scopes(doc))\n for (const r of scopeRegions(scopeProgram(doc, editPath)))\n for (const v of localVariables(parseUnits(r.body).units)) set.add(v)\n return [...set]\n}\n\n/** Readable name of an item by id (for the messages). */\nfunction itemNameById(doc: Doc, id: string): string | null {\n let found: string | null = null\n const walk = (layers: { items: import('@flatkit/types').Item[] }[]) => {\n for (const l of layers) for (const it of l.items) {\n if (found) return\n if ('name' in it && it.id === id) { found = it.name ?? null; return }\n if (isGroup(it)) walk(it.layers)\n }\n }\n walk(doc.layers)\n return found\n}\n\nconst escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\-]/g, '\\\\$&')\n\n/** Value functions reachable in this Doc whose body reads the LOOP-WRAPPED `time`, directly or through\n * another such function. Only `kind: 'value'` matters — a `proc` is not callable from a channel expression.\n * Fixpoint, so `fn a(t) = b(t)` inherits from `b`. Qualified aliases (`feedback.pulse`) are kept: an author\n * may call either form. */\nfunction functionsReadingTime(doc: Doc): string[] {\n const defs = [...(doc.functions ?? []), ...importedFunctions(doc.imports)].filter((f) => f.kind === 'value')\n const reads = new Set<string>()\n for (;;) {\n const before = reads.size\n for (const f of defs) {\n if (reads.has(f.name)) continue\n const body = f.expr\n // A parameter NAMED `time` would shadow the runtime scalar — then the body's `time` is just an argument.\n if (!f.params.includes('time') && /\\btime\\b/.test(body)) { reads.add(f.name); continue }\n for (const other of reads) if (new RegExp(`\\\\b${escapeRe(other)}\\\\s*\\\\(`).test(body)) { reads.add(f.name); break }\n }\n if (reads.size === before) return [...reads]\n }\n}\n\n/** Top-level arguments of every `name(…)` call in `src`. Depth-aware, so a nested call keeps its own\n * commas: `pulse(max(a, 0), 1)` reads as two arguments, not three. */\nfunction callArguments(src: string, name: string): string[][] {\n const out: string[][] = []\n const re = new RegExp(`(?<![\\\\w.])${escapeRe(name)}\\\\s*\\\\(`, 'g')\n let m: RegExpExecArray | null\n while ((m = re.exec(src))) {\n const args: string[] = []\n let depth = 1\n let start = m.index + m[0].length\n let i = start\n for (; i < src.length; i++) {\n const c = src[i]\n if (c === '(') depth++\n else if (c === ')') { depth--; if (depth === 0) break }\n else if (c === ',' && depth === 1) { args.push(src.slice(start, i)); start = i + 1 }\n }\n args.push(src.slice(start, i))\n out.push(args.map((a) => a.trim()))\n }\n return out\n}\n\n/** Which argument of a feedback function is an INSTANT (a timestamp compared against `clock`):\n * `pulse(since, dur)` → the 1st; `shake(bad, t)` → the 2nd (the 1st is the flag). */\nconst INSTANT_ARG: Record<string, number> = { pulse: 0, shake: 1 }\n\n/** Variables whose value is captured from `time` (`doneAt = time`) — the pre-0.23 timestamp idiom, back\n * when `pulse`/`shake` rode `time` too. A capture that already mentions `clock` is the correct one. */\nfunction timeCapturedVars(doc: Doc): Set<string> {\n const out = new Set<string>()\n forEachAction(doc, (a) => {\n if (a.do === 'setVar' && /\\btime\\b/.test(a.value) && !/\\bclock\\b/.test(a.value)) out.add(a.name)\n })\n return out\n}\n\n/** STRUCTURAL warnings (non-blocking) of a Doc: phantom drop zones, dead variables. */\nexport function docStructureWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n // (a) `when dropped on X` whose zone X does not exist (no item named so) -> the handler can never fire.\n const names = new Set(objectNames(doc.layers))\n for (const it of doc.interactions ?? []) {\n if (it.event === 'drop' && it.over && !names.has(it.over)) {\n const who = itemNameById(doc, it.targetId) ?? it.targetId\n out.push({ scope: 'scene', diag: { line: 1, col: 1, severity: 'warning', message: `unknown drop zone \"${it.over}\" (object \"${who}\") — no item of the scene carries this name` } })\n }\n }\n // (b) global variable never referenced (declared but not found in any scope) -> probably dead.\n const names0 = Object.keys(doc.variables ?? {})\n if (names0.length) {\n // Modifier targets are NOT emitted into scopeProgram (to avoid double-linting them, cf. docModifierWarnings),\n // so collect them here too — else a global used ONLY by a `spring`/`smooth` target reads as \"never used\".\n const modTargets: string[] = []\n const collectMods = (items: Item[]): void => {\n for (const it of items) {\n if (isPoseable(it) && it.modifiers) for (const ch of EXPR_CHANNELS) { const mm = it.modifiers[ch]; if (mm) modTargets.push(mm.target) }\n if (isGroup(it)) for (const l of it.layers) collectMods(l.items)\n }\n }\n for (const l of doc.layers) collectMods(l.items)\n for (const s of doc.symbols ?? []) for (const l of s.layers) collectMods(l.items)\n // Read the DOC, never a text rebuilt from it. `scopeProgram` only re-emits the `object` blocks of items\n // at the ROOT of a scope, so on a composed program whose draggables live inside element groups most of\n // them simply were not there: measured on a 210-line generated activity, 3 blocks out of 11 survived\n // the round-trip, and every variable read only in the other 8 came back \"never used\" -- 20 warnings,\n // all false. The walkers below descend the whole tree, symbols included.\n const used: string[] = [...modTargets]\n forEachExpression(doc, (e) => used.push(e))\n forEachAction(doc, (a) => { for (const v of Object.values(a)) if (typeof v === 'string') used.push(v) })\n // An interactor writes its variables through named SLOTS rather than an expression, and guards itself\n // with `enabled` -- neither is an expression the walkers see. That guard was the reported case.\n for (const i of doc.interactors ?? []) used.push(i.varX ?? '', i.varY ?? '', i.varT ?? '', i.cells ?? '', i.pointX ?? '', i.pointY ?? '', i.enabled ?? '')\n const allText = used.join('\\n')\n for (const name of names0) {\n if (!new RegExp(`(?<![\\\\w-])${escapeRe(name)}(?![\\\\w-])`).test(allText))\n out.push({ scope: 'scene', diag: { line: 1, col: 1, severity: 'warning', message: `global variable \"${name}\" never used (declared, but neither read nor written)` } })\n }\n }\n // (b bis) An `instance \"X\"` that resolved to NO symbol. Compilation keeps the unresolved `@X` marker all\n // the way into the .flatpack, the instance draws nothing, and everything else about the file looks\n // fine — the same family as the phantom drop zone above: a name that points at nothing. Only a\n // warning: compiling a program on its own and supplying its libraries later is a legitimate\n // workflow, and it must keep exiting 0.\n const missing = new Set<string>()\n const scanRefs = (items: Item[]): void => {\n for (const it of items) {\n if (isInstance(it) && it.symbolId.startsWith('@')) missing.add(it.symbolId.slice(1))\n if (isGroup(it)) for (const l of it.layers) scanRefs(l.items)\n }\n }\n for (const l of doc.layers) scanRefs(l.items)\n for (const s of doc.symbols ?? []) for (const l of s.layers) scanRefs(l.items)\n if (missing.size) {\n const names = [...missing].map((n) => `\"${n}\"`).join(', ')\n out.push(warn(`instance resolves to no symbol: ${names} — nothing is drawn where it stands. Pass the .flat library that defines it (\\`flatc <program> <lib.flat>\\`, or place it beside the program), or fix the name.`))\n }\n\n // (c) `time` reaching a channel expression + a SHORT looping timeline → the motion JUMPS on each loop\n // (`time = frame/fps` resets to 0 every `durationFrames`). The monotone `clock` never wraps.\n // A `time` reached THROUGH A FUNCTION counts: the costliest version of this trap was\n // `opacity = pulse(doneAt, 0.9)`, where the wrapping clock sat in the callee's body and the channel\n // text held no `time` at all — so a warning that only grepped the channel said nothing whatsoever.\n const dur = doc.timeline?.durationFrames ?? 60\n const fps = doc.timeline?.fps ?? 24\n if (dur <= 120) { // ≤ 5 s @24fps: short enough that the reset is visible as a periodic jump\n const viaFn = functionsReadingTime(doc)\n const culprits = new Set<string>()\n const scan = (layers: Layer[]) => {\n for (const l of layers) for (const it of l.items) {\n if (isPoseable(it) && it.expressions) for (const k in it.expressions) {\n const expr = it.expressions[k as keyof typeof it.expressions] ?? ''\n if (/\\btime\\b/.test(expr)) culprits.add('`time`')\n for (const fn of viaFn) if (new RegExp(`\\\\b${escapeRe(fn)}\\\\s*\\\\(`).test(expr)) culprits.add(`\\`${fn}()\\`` + ' (which reads `time`)')\n }\n if (isGroup(it)) scan(it.layers)\n }\n }\n scan(doc.layers)\n if (culprits.size) {\n const secs = Math.round((dur / fps) * 10) / 10\n out.push(warn(`a channel expression uses ${[...culprits].join(' and ')}, but the timeline loops every ${secs}s (durationFrames ${dur}) — \\`time\\` resets each loop, so the motion jumps (a one-shot ramp REPLAYS forever). Use the monotone \\`clock\\` (never wraps), drive it by \\`frame/${dur}\\`, or set a longer \\`timeline\\`.`))\n }\n }\n // (d) An instant captured on `time` and handed to `pulse`/`shake`. Both ride the MONOTONE `clock`, so\n // `clock - since` grows without bound and the ramp NEVER fires. Unlike (c) this is loop-LENGTH\n // independent — the two axes never meet however long the timeline is — and it is entirely SILENT:\n // nothing jumps, nothing blinks, and (c) itself stays quiet because the channel text holds no `time`.\n // The 0.21 → 0.23 migration trap: back then `pulse` rode `time` and the mismatch at least showed.\n const captured = timeCapturedVars(doc)\n if (captured.size) {\n const readers = new Map<string, Set<string>>() // variable → the feedback functions reading it as an instant\n forEachExpression(doc, (expr) => {\n for (const fnName of Object.keys(INSTANT_ARG)) {\n for (const args of callArguments(expr, fnName)) {\n const arg = args[INSTANT_ARG[fnName]]\n if (!arg) continue\n // The name may sit INSIDE the argument (`pulse(max(doneAt, 0), 1)`) — match it as a whole word.\n for (const v of captured) {\n if (!new RegExp(`(?<![\\\\w-])${escapeRe(v)}(?![\\\\w-])`).test(arg)) continue\n const seen = readers.get(v) ?? new Set<string>()\n seen.add(fnName)\n readers.set(v, seen)\n }\n }\n }\n })\n for (const [v, fns] of readers) {\n const who = [...fns].map((f) => `\\`${f}()\\``).join(' and ')\n out.push(warn(`\"${v}\" is captured on \\`time\\` but read as an INSTANT by ${who}, which compares it against the monotone \\`clock\\` — the two axes never meet, so the ramp never fires and nothing on screen says so. Capture it with \\`clock\\` instead: \\`${v} = clock\\`.`))\n }\n }\n out.push(...docPaintParamWarnings(doc))\n out.push(...docCelLayerWarnings(doc))\n out.push(...docLayoutWarnings(doc))\n out.push(...docRevealCellWarnings(doc))\n out.push(...docDrawWarnings(doc))\n out.push(...docGestureOptionWarnings(doc))\n out.push(...docFilterCacheWarnings(doc))\n return out\n}\n\n/** The channels folded into the filtered-composite cache SIGNATURE — i.e. the ones whose change busts it:\n * everything that moves the item on screen. DERIVED, not retyped: the signature is the item's placement,\n * so it is exactly the pose channels minus `opacity` (applied at BLIT time, so a pure fade reuses the baked\n * bitmap) plus the additive offsets. A hand-kept copy of a list the player owns is how `--check` came to\n * size a `reveal` grid on the brush while the engine used the grain. */\nconst CACHE_BUSTING_CHANNELS = [...EXPR_CHANNELS.filter((c) => c !== 'opacity'), ...OFFSET_CHANNELS]\n\n/** A CLOCK fed to a PERIODIC function — the shape of a motion that provably never settles.\n *\n * ⚠️ THE WHOLE PRECISION OF THE RULE IS HERE, and a looser test was measured to be useless. Plenty of\n * legitimate bindings mention `clock` on a transform and come to REST, so the cache pays them once and\n * then hits forever:\n * • `rotation = shake(bad, clock)` — `shake` is `bad ? sin(t*40)*4 : 0`, exactly 0 at rest. Every\n * draggable object in a generated activity carries one; flagging them made the rule fire on scenes\n * that were perfectly fine.\n * • `scaleX = 1 + 0.28 * clamp(1 - (clock - landedAt) * 1.6, 0, 1)` — a decay, constant after 0.6 s.\n * A periodic wrapper cannot settle: `sin`, `cos` and `mod` return to their range forever, by construction.\n * That is the difference between a cost paid once and a cost paid sixty times a second. */\n/* Every ever-growing instant counts, not just `clock`: `time` restarts each loop and `frame` counts up,\n * so `dy = 3 * sin(time * 2)` re-bakes exactly as hard as its `clock` twin and used to slip through. */\nconst PERIODIC_CLOCK = /\\b(sin|cos|mod)\\s*\\([^()]*\\b(clock|time|frame)\\b/\n\n/**\n * A `filter` whose SCREEN PLACEMENT never holds still — the one combination that defeats the render cache.\n *\n * Isolating a filter costs an off-screen canvas, a CSS filter and a blit. The player pays that ONCE and\n * keeps the baked bitmap, keyed on the item's full screen placement (`filterCacheSlot`). That saving is the\n * whole reason a scene can afford glows at all.\n *\n * Put a PERIODIC clock motion on a transform channel — on the filtered item OR on any ancestor — and the\n * placement differs every frame, so the key never repeats and the bitmap is re-baked sixty times a second,\n * forever.\n *\n * Measured on a generated activity: a garland swaying on `dy = 3 * sin(clock * 0.55)`, with six glowing\n * lanterns hanging from it. The lanterns themselves were innocent — their own motion settles — but the\n * sway above them re-baked all six glows every frame. Nothing looked wrong; the drag simply stuttered, and\n * the cost was invisible in the source, split across a `filter` on one line and a parent's `dy` fifty\n * lines away.\n *\n * Only a warning, and deliberately so: it is a COST, not a defect, and a still scene may well afford it.\n * But it must be said, because nothing else in the chain can say it — the program compiles, the picture is\n * correct, and only a profiler on a real device tells you where the frame budget went.\n */\nexport function docFilterCacheWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const culprits: string[] = []\n\n /** Does this item move its own placement in a way that never comes to rest? */\n const clockPosed = (it: Item): boolean => {\n if (!isPoseable(it) || !it.expressions) return false\n for (const ch of CACHE_BUSTING_CHANNELS) {\n const expr = it.expressions[ch as keyof typeof it.expressions]\n if (typeof expr === 'string' && PERIODIC_CLOCK.test(expr)) return true\n }\n return false\n }\n\n // `moving` is inherited: the cache signature folds the ACCUMULATED screen transform, so an animated\n // grandparent busts a still child's cache just as surely as its own binding would.\n const walk = (items: Item[], moving: boolean, path: string): void => {\n for (const it of items) {\n const name = ('name' in it && typeof it.name === 'string' && it.name) || it.id\n const here = path ? `${path} › ${name}` : name\n const animated = moving || clockPosed(it)\n if (animated && 'filters' in it && Array.isArray(it.filters) && it.filters.length > 0) {\n culprits.push(here)\n }\n if (isGroup(it)) for (const l of it.layers) walk(l.items, animated, here)\n }\n }\n for (const l of doc.layers) walk(l.items, false, '')\n\n if (culprits.length > 0) {\n const shown = culprits.slice(0, 4).map((n) => `\"${n}\"`).join(', ')\n const more = culprits.length > 4 ? `, and ${culprits.length - 4} more` : ''\n out.push({\n scope: 'scene',\n diag: {\n line: 1,\n col: 1,\n severity: 'warning',\n message:\n `filter under a transform that never stops moving (${shown}${more}) — a periodic \\`clock\\` motion on this item or an ancestor. The filtered-composite cache keys on the screen placement, so it can never hit: the off-screen composition is repaid EVERY FRAME, for as long as the scene is open. ` +\n `Move the animation to \\`opacity\\` (applied at blit, so the cache still hits), drive the transform from a value that SETTLES, or drop the filter.`,\n },\n })\n }\n return out\n}\n/**\n * SILENT DROPS in a cel layer. `resolveLayerAt` draws exactly two things: the current cel's `matter`, and\n * the containers that cel POSES — never the layer's other roster items. Three ways to author a layer that\n * compiles, renders an empty frame, and says nothing:\n * (a) a bare shape (`path`/`circle`/`rect`/…) sitting in a layer that has cels — it belongs inside a\n * cel's `matter { … }` (frame-by-frame drawing) or on a cel-less layer (static decor);\n * (b) a `pose \"X\"` naming no roster item (the parser leaves such a pose id as `@X`) — poses nothing;\n * (c) a roster container/text/image that no cel ever poses — never drawn.\n * All three are the classic \"my drawing vanished\" bug. Warnings (non-blocking).\n */\nexport function docCelLayerWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const checkScope = (scope: string, layers: Layer[]) => {\n const push = (message: string) => out.push({ scope, diag: { line: 1, col: 1, severity: 'warning', message } })\n const visit = (ls: Layer[]): void => {\n for (const l of ls) {\n if (l.cels?.length) {\n const bare = l.items.filter(isRegion)\n if (bare.length) push(`layer \"${l.name}\" has cels, so its ${bare.length} bare shape(s) are NEVER drawn — a cel layer draws only the cel's \\`matter { … }\\` and the containers it poses. Move them into \\`cel N { matter { … } }\\`, or onto a cel-less layer if they are static.`)\n const posed = new Set<string>()\n for (const c of l.cels) for (const p of c.poses) posed.add(p.id)\n for (const id of posed) if (id.startsWith('@')) push(`layer \"${l.name}\": \\`pose \"${id.slice(1)}\"\\` matches no item of this layer — the pose draws nothing (roster: ${l.items.map(itemLabel).join(', ') || 'empty'}).`)\n for (const it of l.items) if (isPoseable(it) && !posed.has(it.id)) push(`layer \"${l.name}\": \"${itemLabel(it)}\" is never posed by a cel — it is never drawn. Add \\`pose \"${itemLabel(it)}\"\\` to the cels where it should show.`)\n // Posed, SKIPPED, then posed again: the item blinked out and back. A cel is a full snapshot, so\n // that is the model working as designed — and it is exactly how an exit is written, which is why\n // a FINAL absence says nothing. But a staggered entrance (three things arriving at three\n // moments) needs `hold` on every cel, and forgetting it makes elements vanish mid-run in\n // silence. That omission is what a program-scene animation trips on, every time.\n const cels = [...l.cels].sort((a, b) => a.frame - b.frame)\n for (const it of l.items) {\n if (!isPoseable(it)) continue\n const at = cels.map((c) => c.poses.some((p) => p.id === it.id))\n const first = at.indexOf(true)\n const last = at.lastIndexOf(true)\n // The hole must sit BETWEEN the first and last pose. Absent before the first is a late\n // ENTRANCE, absent after the last is an EXIT — both are how the model is meant to be used.\n const gap = at.findIndex((on, i) => !on && i > first && i < last)\n if (gap >= 0) {\n push(`layer \"${l.name}\": \"${itemLabel(it)}\" is posed at cel ${cels[first].frame}, absent at cel ${cels[gap].frame}, then posed again at cel ${cels[last].frame} — a cel is a FULL snapshot, so it disappears in between. Add \\`hold\\` to the cels that should carry it forward (\\`cel ${cels[gap].frame} hold { … }\\`), or pose it there.`)\n }\n }\n }\n for (const it of l.items) if (isGroup(it)) visit(it.layers)\n }\n }\n visit(layers)\n }\n checkScope('scene', doc.layers)\n for (const s of doc.symbols) checkScope(s.name, s.layers)\n return out\n}\n\n/**\n * `reveal <p> { cells <array> }` — the grid the player writes into is DERIVED (zone bbox ÷ brush), so the\n * one number the author cannot guess is how many cells to declare. An array of the wrong length loses the\n * writes past its end IN SILENCE (the veil clears where nothing shows). So: state the geometry, every time\n * the sizes disagree, and name the exact declaration to write.\n */\nexport function docRevealCellWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n for (const it of doc.interactors ?? []) {\n if (it.axis !== 'reveal' || !it.cells) continue\n const who = itemNameById(doc, it.targetId) ?? it.targetId\n const declared = Object.hasOwn(doc.variables ?? {}, it.cells) ? doc.variables?.[it.cells] : undefined // hasOwn: a name like `constructor` is not a declaration\n const b = itemBoundsById(doc, it.targetId)\n if (!b) continue // the target itself does not resolve — `object \"X\"` on nothing is already reported\n // THE geometry, from the engine — the same call the player makes. Sizing it here on its own is how the\n // two drifted the day `grain` arrived: this said 300 cells where the engine made 5610, and every write\n // past the end of the advised array was dropped in silence.\n const { cols, rows, total: n } = revealGrid(b, it)\n const from = it.grain && it.grain > 0 ? `grain ${it.grain}` : `brush ${it.grid && it.grid > 0 ? it.grid : 24}`\n const geom = `${cols} x ${rows} = ${n} cells (zone ${Math.round(b.maxX - b.minX)}x${Math.round(b.maxY - b.minY)} px, ${from})`\n if (!Array.isArray(declared)) {\n out.push(warn(`\\`reveal … cells ${it.cells}\\` (object \"${who}\") writes into \"${it.cells}\", which is ${declared === undefined ? 'not declared' : 'a scalar, not an array'} — the scratched grid goes nowhere. Declare it with the grid's size: \\`var ${it.cells} = fill(${n}, 0)\\` — ${geom}, index = row * ${cols} + col.`))\n } else if (declared.length !== n) {\n out.push(warn(`\\`reveal … cells ${it.cells}\\` (object \"${who}\"): the grid is ${geom}, but \"${it.cells}\" holds ${declared.length} — ${declared.length < n ? 'every cell past the end is dropped in silence' : 'the extra cells are never written'}. Declare \\`var ${it.cells} = fill(${n}, 0)\\`, index = row * ${cols} + col.`))\n }\n }\n return out\n}\n\n/**\n * Slots that quietly do nothing on their own: `both ends` without `step` (only a CONTINUOUS trace has an\n * entry end to choose), and a `grain` so much coarser than the brush that a touch can land between two cell\n * centres and clear nothing at all. Both leave a scene that looks written correctly and behaves as if the\n * option had not been typed.\n */\nexport function docGestureOptionWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n for (const it of doc.interactors ?? []) {\n const who = itemNameById(doc, it.targetId) ?? it.targetId\n // A `step` of 0 (or less) is the one number here that does not fall back: the progress may advance by\n // at most `step` px per frame, so nothing can ever advance. The drill draws its guide, the finger\n // follows it, the ink stays empty and `--check` was green — an exercise impossible to complete, in\n // silence. The others below are milder: they are IGNORED, which is its own kind of quiet wrong.\n if (it.axis === 'trace' && it.step !== undefined && !(it.step > 0)) {\n out.push(warn(`\\`step ${it.step}\\` (object \"${who}\") — the progress may grow by at most \\`step\\` px of arc length per frame, so at ${it.step} it can never move and the trace can never be completed. Use the distance a finger may cover between two frames (a quarter of the path is a sane start).`))\n }\n for (const [slot, value] of [['tolerance', it.axis === 'trace' ? it.grid : undefined], ['brush', it.axis === 'reveal' ? it.grid : undefined], ['grain', it.axis === 'reveal' ? it.grain : undefined]] as const) {\n if (value !== undefined && !(value > 0)) {\n out.push(warn(`\\`${slot} ${value}\\` (object \"${who}\") is ignored — a non-positive value falls back to the default, so the number in the source describes nothing. Write the one you mean, or drop the line.`))\n }\n }\n if (it.axis === 'trace' && it.bothEnds && it.step === undefined) {\n out.push(warn(`\\`both ends\\` without \\`step\\` (object \"${who}\") — it picks which END the run is measured from, and a \\`trace\\` without \\`step\\` has no run: its progress is wherever the finger projects, from anywhere. Add \\`step <px>\\` (the max jump between two frames) or drop \\`both ends\\`.`))\n }\n if (it.axis === 'reveal') {\n const brush = it.grid && it.grid > 0 ? it.grid : 24\n if (it.grain && it.grain > brush) {\n out.push(warn(`\\`grain ${it.grain}\\` is coarser than \\`brush ${brush}\\` (object \"${who}\") — a cell is cleared when its CENTRE falls within the brush, so a touch can land between two centres and clear nothing. Keep the grain at or under the brush (a fine grain under a wide finger is the point).`))\n }\n }\n }\n return out\n}\n\n/** `draw` trims the STROKE by arc length — on a shape with no stroke it has nothing to trim, so the ink\n * the author is animating simply never appears (and the fill they DO have is untouched, so the scene\n * looks plausible). */\nexport function docDrawWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const check = (scope: string, r: Region): void => {\n if (r.stroke) return\n if (r.draw == null && !r.drawExpr && r.drawFrom == null && !r.drawFromExpr) return\n out.push({ scope, diag: { line: 1, col: 1, severity: 'warning', message: `\\`draw\\` on a shape with no \\`stroke\\` — it trims the OUTLINE by arc length, so with nothing stroked it changes nothing on screen. Add \\`stroke <color> <width>\\` (an ink trail is usually \\`nofill stroke … cap round\\`).` } })\n }\n const scan = (scope: string, layers: Layer[]): void => {\n for (const l of layers) {\n for (const it of l.items) { if (isRegion(it)) check(scope, it); else if (isGroup(it)) scan(scope, it.layers) }\n for (const c of l.cels ?? []) for (const r of c.matter ?? []) check(scope, r)\n }\n }\n scan('scene', doc.layers)\n for (const s of doc.symbols ?? []) scan(s.name, s.layers)\n return out\n}\n\n/** A scope's declared `color` param names (the only params usable as a paint color). */\nconst colorParamNames = (params?: ParamDef[]): Set<string> => new Set((params ?? []).filter((p) => p.type === 'color').map((p) => p.name))\n\n/**\n * A `color` param used as a paint (`fill`/`stroke`, a gradient **stop** `0:teinte@…`, or a `tint`) that the\n * owning symbol does NOT declare → a SILENT \"dead recolor\" (it falls back to the literal hex, the picker does\n * nothing). Warns per scope, with the param scoped to ITS symbol (the scene declares none). Mirrors how the\n * lint now knows a symbol's params in its `expr`. Non-blocking (a warning), so it never breaks a build.\n */\nexport function docPaintParamWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const checkScope = (scope: string, layers: Layer[], known: Set<string>) => {\n const flag = (param: string, where: string, who?: string) => {\n if (known.has(param)) return\n const hint = known.size ? `declared color params: ${[...known].join(', ')}` : 'this scope declares no color params'\n out.push({ scope, diag: { line: 1, col: 1, severity: 'warning', message: `unknown color param \"${param}\" in ${where}${who ? ` (${who})` : ''} — ${hint}` } })\n }\n const visit = (it: Item) => {\n const who = 'name' in it ? it.name : undefined\n if (isRegion(it)) {\n if (it.fillParam) flag(it.fillParam, 'a fill', who)\n if (it.strokeParam) flag(it.strokeParam, 'a stroke', who)\n const stops = it.paint && it.paint.type !== 'solid' ? it.paint.stops : []\n for (const s of stops) if (s.param) flag(s.param, 'a gradient stop', who)\n }\n if (isPoseable(it) && it.tint?.param) flag(it.tint.param, 'a tint', who)\n if (isGroup(it)) for (const l of it.layers) for (const c of l.items) visit(c) // a group is the same scope; an instance is a separate symbol (linted on its own pass)\n }\n for (const l of layers) for (const it of l.items) visit(it)\n }\n checkScope('scene', doc.layers, new Set())\n for (const s of doc.symbols) checkScope(s.name, s.layers, colorParamNames((s as SymbolDef).params))\n return out\n}\n\nconst warn = (message: string): { scope: string; diag: Diagnostic } => ({ scope: 'scene', diag: { line: 1, col: 1, severity: 'warning', message } })\nconst itemLabel = (it: Item): string => ('name' in it && it.name ? it.name : 'kind' in it ? it.kind : 'path')\n/** Mean advance of a proportional glyph at this text's size — the metric both estimators share. */\nconst glyphAdvance = (t: Text): number => (t.weight && t.weight >= 700 ? 0.56 : 0.52) * t.size\n\n/** Estimated width of the longest line (approximate metric, without canvas). */\nfunction estTextWidth(t: Text): number {\n const advance = glyphAdvance(t)\n let longest = 0\n for (const line of t.content.split('\\n')) longest = Math.max(longest, line.length)\n return longest * advance\n}\n\n/** Bounds of what a `text` actually PAINTS, in parent space -- as opposed to the box it declares.\n * Measured on the deckgen corpus: 36 of 53 warnings were `align center` texts in a comfortable box, where\n * the box crosses the canvas edge and the glyphs sit hundreds of pixels short of it. A box is a layout\n * frame, not ink: `text \"Accepter\" align center box 780 40` is 8 glyphs in the middle of 780 px.\n * A WRAPPED text keeps its box -- there the ink really can fill the width. Anything else is unchanged. */\nfunction inkBBox(doc: Doc, it: Item): ReturnType<typeof itemBBox> {\n const box = itemBBox(doc, it)\n if (!box || !isText(it) || it.wrap || it.textPath) return box\n const estW = estTextWidth(it)\n if (estW >= it.box.w) return box // the ink fills (or overruns) the frame -> the frame IS the measure\n const left = it.align === 'left' ? 0 : it.align === 'right' ? it.box.w - estW : it.box.w / 2 - estW / 2\n return transformBBox({ minX: left, minY: 0, maxX: left + estW, maxY: it.box.h }, it.transform)\n}\n\n/** Greedy word-wrap of a `wrap` text at its box width — the renderer's own rule (break at spaces, and\n * only at spaces). Returns the resulting line count and the widest single word, which is what decides\n * whether anything spills sideways: a word wider than the box has no break point and runs past it. */\nexport function wrapMetrics(t: Text): { lines: number; widestWord: number } {\n const advance = glyphAdvance(t)\n const width = (s: string) => s.length * advance\n let lines = 0\n let widestWord = 0\n for (const paragraph of t.content.split('\\n')) {\n lines++ // an explicit newline always starts a line, empty ones included (they still take height)\n let current = ''\n for (const word of paragraph.split(/\\s+/).filter(Boolean)) {\n widestWord = Math.max(widestWord, width(word))\n const joined = current ? `${current} ${word}` : word\n if (current && width(joined) > t.box.w) { lines++; current = word } else current = joined\n }\n }\n return { lines, widestWord }\n}\n\n/** LAYOUT warnings (non-blocking): canvas overflow, text too wide, overlapping hitboxes.\n * Approximate but without canvas — catches \"blind\" positioning bugs before the render. */\nexport function docLayoutWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const W = doc.width, H = doc.height\n const TOL = 8 // overflow tolerance (px) before alerting\n const r0 = (n: number) => Math.round(n)\n\n // An item whose position is written at RUNTIME — bound to an expression, or dragged directly — has a\n // meaningless static bbox. That rule already existed; what it missed is that it is INHERITED: a label\n // sitting inside a dragged tile is authored around the tile's origin and only lands somewhere real once\n // the tile moves. Measuring it where the file happens to leave it (0,0) reports the whole scene as\n // clipped — the exact noise that would make the pass unusable.\n const dynamicPos = (it: Item) =>\n ('expressions' in it && it.expressions && (it.expressions.x != null || it.expressions.y != null || it.expressions.dx != null || it.expressions.dy != null)) ||\n !!doc.interactors?.some((i) => i.targetId === it.id) // `drag`/`turn`: the pointer decides where it is\n\n // Every text/image of the scene, paired with the WORLD matrix of its PARENT (the space `itemBBox`\n // reports in) and whether any ancestor is runtime-positioned. Both passes below used to read\n // `doc.layers` top level only — and a group is the only thing a behavior block can animate, so most of\n // a real scene lives inside one and was never measured at all.\n const placed: { it: Text | Image; parent: Transform; dynamic: boolean }[] = []\n const collect = (layers: Layer[], matrix: Transform, dynamic: boolean): void => {\n for (const l of layers) for (const it of l.items) {\n if (isText(it) || isImage(it)) placed.push({ it, parent: matrix, dynamic: dynamic || dynamicPos(it) })\n if (isGroup(it)) collect(it.layers, compose(matrix, it.transform), dynamic || dynamicPos(it))\n }\n }\n collect(doc.layers, IDENTITY, false)\n\n // (c) TEXT/IMAGE clipped at the canvas edge. Precise to avoid noise: we ignore `path`/groups\n // (decor that \"bleeds\" on purpose), anything positioned at runtime (see above), and items PARKED\n // entirely off-screen (\"hidden\" pattern).\n for (const { it, parent, dynamic } of placed) {\n if (dynamic || (isText(it) && it.textPath)) continue // path-laid text → §(f), not a box\n const local = inkBBox(doc, it)\n if (!local) continue\n const b = transformBBox(local, parent) // itemBBox is PARENT-space → compose with the ancestors\n const visible = b.maxX > 0 && b.minX < W && b.maxY > 0 && b.minY < H // overlaps the canvas (not parked off-screen)\n const clipped = b.minX < -TOL || b.minY < -TOL || b.maxX > W + TOL || b.maxY > H + TOL\n if (visible && clipped) {\n out.push(warn(`\"${itemLabel(it)}\" clipped at the canvas edge: bbox [${r0(b.minX)},${r0(b.minY)} -> ${r0(b.maxX)},${r0(b.maxY)}] outside 0,0 -> ${W},${H}`))\n }\n }\n\n // (d) Text (without `wrap`) whose estimated width makes it OVERFLOW THE CANVAS -> instruction clipped.\n // (We do NOT compare against `box.w`: without wrap, a text overflows its box harmlessly as long as it\n // fits in the canvas — it is the canvas edge that clips.)\n for (const { it, parent, dynamic } of placed) {\n if (!isText(it) || it.wrap || it.textPath || dynamic) continue\n const estW = estTextWidth(it)\n const left = it.align === 'left' ? 0 : it.align === 'right' ? it.box.w - estW : it.box.w / 2 - estW / 2\n const m = compose(parent, it.transform) // the text's own world matrix: its baseline runs in ITS space\n const p0 = apply(m, { x: left, y: 0 }), p1 = apply(m, { x: left + estW, y: 0 })\n const wl = Math.min(p0.x, p1.x), wr = Math.max(p0.x, p1.x) // left/right edge of the content in world coords\n if (wr > W + TOL || wl < -TOL) {\n // `wrap` breaks at SPACES and nowhere else, so it can do nothing for a single word -- and a giant\n // single word bleeding off the frame is a deliberate gesture in every corpus measured (ghost\n // typography: `1815`, `URUK`, `1429`). Prescribing `wrap` there is advice that cannot be followed.\n const oneWord = !/\\s/.test(it.content.trim())\n const advice = oneWord\n ? ' — `wrap` cannot help: it breaks at spaces, and this is a single word. Intentional if the bleed is the point; otherwise reduce the size or move it in'\n : ' — add \"wrap\"'\n out.push(warn(`text \"${it.content.slice(0, 24)}${it.content.length > 24 ? '…' : ''}\" overflows the canvas (estimated ~${r0(estW)} px, edge ${r0(wl)}->${r0(wr)} outside 0->${W})${advice}`))\n }\n }\n\n // (h) ANY item drawn ENTIRELY outside the canvas. The clipped-at-the-edge pass above deliberately\n // tolerates straddling (decor bleeds on purpose) and skips items parked off-screen — but \"parked\"\n // is only a pattern for something a binding moves back in, and those are excluded as dynamic. A\n // STATIC item wholly off-canvas is never intentional: it is a coordinate mistake, and until now\n // nothing said so for a shape or a group. Measured on a model-written board: the eighth token was\n // laid out past the edge and the whole chain stayed quiet.\n // Two things this must NOT flag, both measured on a real corpus before the rule was let out:\n // • an item PARKED off the TOP-LEFT corner on purpose (`at -999,-999` for a payload holder,\n // `-600,-600` for hidden labels) — the idiom is real, used in 3 of 58 activities measured, and\n // its signature is that BOTH axes are negative. A mistake overshoots one edge;\n // • a DEGENERATE bbox lying along an edge (a hairline rule at y=0 spans `0,0 -> 760,0`), which\n // is on the canvas, not off it — so compare strictly, with the same tolerance as the rest.\n const parked = (b: { maxX: number; maxY: number }) => b.maxX < 0 && b.maxY < 0\n const offCanvas = (b: { minX: number; minY: number; maxX: number; maxY: number }) =>\n (b.maxX < -TOL || b.minX > W + TOL || b.maxY < -TOL || b.minY > H + TOL) && !parked(b)\n // A container's bbox is the UNION of its children's, so it is only static if they all are. Measured on\n // the deckgen corpus: `group \"S0\"` drives nothing but `opacity`, and holds a slide-in whose static `at`\n // parks it off-screen — the union landed off-canvas and the group was reported. The `dynamic` flag was\n // inherited DOWNWARD (a moved parent moves its children) but never upward, which is the other half of\n // the same fact.\n // Computed ONCE, post-order. Asking per item re-walks the subtree every time -- O(n x depth) where one\n // pass suffices. (It is not where this pass spends its time: measured on a 4434-line deck the two shapes\n // are within noise. It is written this way because the other one is quadratic for no reason.)\n const moving = new Set<string>()\n const markMoving = (items: Item[]): boolean => {\n let any = false\n for (const it of items) {\n const inside = isGroup(it) && it.layers.some((l) => markMoving(l.items))\n if (dynamicPos(it) || inside) { moving.add(it.id); any = true }\n }\n return any\n }\n for (const l of doc.layers) markMoving(l.items)\n const movesADescendant = (it: Item): boolean => moving.has(it.id)\n const reportOffCanvas = (items: Item[], matrix: Transform, dynamic: boolean): void => {\n for (const it of items) {\n const isDynamic = dynamic || dynamicPos(it)\n if (!isDynamic && !movesADescendant(it) && !(isText(it) && it.textPath)) {\n const local = itemBBox(doc, it)\n const b = local && transformBBox(local, matrix)\n if (b && offCanvas(b)) {\n // Report the OUTERMOST offender: a group off-canvas takes its whole content with it, and one\n // line about the group is the fix, where one per child is noise.\n out.push(warn(`\"${itemLabel(it)}\" is drawn entirely off-canvas: bbox [${r0(b.minX)},${r0(b.minY)} -> ${r0(b.maxX)},${r0(b.maxY)}], canvas 0,0 -> ${W},${H}. Nothing of it is visible.`))\n continue\n }\n }\n if (isGroup(it)) for (const l of it.layers) reportOffCanvas(l.items, compose(matrix, it.transform), isDynamic)\n }\n }\n for (const l of doc.layers) reportOffCanvas(l.items, IDENTITY, false)\n\n // (g) WRAPPED text taller than its box. Pass (d) skips `wrap` — rightly, since wrapping cannot overflow\n // the box horizontally — but that left wrapped text unmeasured entirely, and what it DOES overflow is\n // the box's height. Same visible defect: an instruction spilling out of its frame is the first thing\n // an eye catches, and the reason a whole activity had to be re-read by a multimodal model.\n for (const { it } of placed) {\n if (!isText(it) || !it.wrap || it.textPath) continue\n const { lines, widestWord } = wrapMetrics(it)\n const label = `${it.content.slice(0, 24).replace(/\\n/g, ' ')}${it.content.length > 24 ? '…' : ''}`\n // ONE line of slack. The estimator has no canvas: it wraps on a mean glyph advance, so it breaks a\n // little early and lands one line long -- measured against skia on five decks (3/4/5 where skia laid\n // 2/3/4). Warning at +1 line meant 36 warnings on a corpus where none matched a defect on screen, and\n // a warning nobody believes is worse than none. Two lines over is a real overflow.\n const tall = (lines - 1) * it.size * it.lineHeight\n if (tall > it.box.h + TOL) {\n out.push(warn(`text \"${label}\" overflows its box: ~${lines} wrapped line(s) ≈ ${r0(lines * it.size * it.lineHeight)} px for a box ${r0(it.box.h)} px tall — raise the box height, shorten the text, or reduce the size`))\n }\n if (widestWord > it.box.w + TOL) {\n out.push(warn(`text \"${label}\" has a word too wide for its box (~${r0(widestWord)} px > ${r0(it.box.w)} px) — a single word cannot be broken, so it spills past the frame whatever \"wrap\" says`))\n }\n }\n\n // (f) Text laid ALONG a path whose estimated run is longer than the path -> trailing glyphs dropped at\n // render (mirrors the canvas-overflow warning, but for the curve). Position-independent -> recurse.\n const pathTexts: Text[] = []\n const walkPathTexts = (layers: Layer[]) => { for (const l of layers) for (const it of l.items) { if (isText(it) && it.textPath) pathTexts.push(it); else if (isGroup(it)) walkPathTexts(it.layers) } }\n walkPathTexts(doc.layers)\n for (const it of pathTexts) {\n const L = makePathSampler(it.textPath!.path).length\n if (L <= 0) continue\n const advance = (it.weight && it.weight >= 700 ? 0.56 : 0.52) * it.size // same metric as estTextWidth\n const glyphs = [...it.content].length\n const eff = Math.max(advance + (it.textPath!.spacing ?? 0), 1) // mirror the renderer's per-glyph floor\n const estW = glyphs * eff\n if (estW > L + TOL) out.push(warn(`text \"${it.content.slice(0, 24)}${it.content.length > 24 ? '…' : ''}\" overflows its path (~${r0(estW)}px > ${r0(L)}px) — trailing glyphs are dropped`))\n }\n\n // (e) Drop zones (`hitbox`) that overlap -> ambiguous drop.\n const zones: { name: string; b: NonNullable<ReturnType<typeof dropZoneBounds>> }[] = []\n const collectZones = (layers: Layer[]) => {\n for (const l of layers) for (const it of l.items) {\n if (isGroup(it) && it.hitbox && it.name) { const b = dropZoneBounds(doc, it.name); if (b) zones.push({ name: it.name, b }) }\n if (isGroup(it)) collectZones(it.layers)\n }\n }\n collectZones(doc.layers)\n for (let i = 0; i < zones.length; i++) for (let j = i + 1; j < zones.length; j++) {\n if (bboxIntersects(zones[i].b, zones[j].b)) out.push(warn(`overlapping hitboxes: \"${zones[i].name}\" and \"${zones[j].name}\" -> ambiguous drop`))\n }\n return out\n}\n\n/** Semantic lint of a whole Doc (all the scopes) -> diagnostics labeled by scope.\n * A scope's text contains `object` blocks (outside DSL) -> we lint each region separately and re-project\n * the lines. `src` = the program SOURCE, when the caller has it (the CLI): the scene scope is then read\n * from it, so positions and scopes describe the author's file. Without it the scene scope falls back to\n * the text rebuilt from the Doc — right for the editor, where that rebuilt text IS the file being edited\n * (cf. CodeEditor.lintFile). Adds the structural warnings (phantom drop zones, dead variables). */\nexport function lintDoc(doc: Doc, src?: string): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const allVars = allScopeVariables(doc) // computed ONCE (global vars -> known in all the scopes)\n for (const { label, editPath } of scopes(doc)) {\n const ctx = docLintContext(doc, editPath, allVars)\n // The SCENE scope is linted from the SOURCE whenever the caller has it (the CLI does). `scopeProgram`\n // rebuilds a text the author never wrote -- no `scene { … }` block -- so its line numbers are offset by\n // that block's height and its scope is always `scene`, never the `object \"X\"` the error is really in.\n // Symbols keep the reconstruction: they come from `.flat` libs, whose source is not this program's.\n const regions = src && editPath.length === 0\n ? behaviorRegions(src)\n : scopeRegions(scopeProgram(doc, editPath)).map((r) => ({ scope: label, body: r.body, line: r.line }))\n for (const r of regions)\n for (const d of lint(r.body, ctx)) {\n const shift = r.line - 1\n // The `fix` carries its own positions, relative to the region text exactly like `d.line`. Shift\n // both or the repair lands somewhere else in the file -- and applies cleanly there, silently.\n const fix = d.fix && { ...d.fix, line: d.fix.line + shift, endLine: d.fix.endLine + shift }\n out.push({ scope: r.scope, diag: { ...d, line: d.line + shift, ...(fix ? { fix } : {}) } })\n }\n }\n out.push(...docStructureWarnings(doc))\n out.push(...docModifierWarnings(doc))\n return out\n}\n\n/** Lint each stateful channel modifier's TARGET expression with its scope's known names (a symbol's params\n * included) — so a typo'd `spring rotation \"crochetXX\"` surfaces as \"unknown variable\" at `--check` time,\n * not a silent NaN at runtime. Also flags out-of-range spring damping (clamped at runtime, but worth noting). */\nexport function docModifierWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const allVars = allScopeVariables(doc)\n for (const { label, editPath } of scopes(doc)) {\n const ctx = docLintContext(doc, editPath, allVars)\n const visit = (items: Item[]): void => {\n for (const it of items) {\n if (isPoseable(it) && it.modifiers) for (const ch of EXPR_CHANNELS) {\n const m = it.modifiers[ch]\n if (!m) continue\n for (const d of lint(`${ch} = ${m.target}`, ctx)) out.push({ scope: label, diag: { ...d, line: 1, col: 1, message: `${m.kind} ${ch}: ${d.message}` } })\n if (m.kind === 'spring' && !(m.damping > 0 && m.damping < 1)) out.push({ scope: label, diag: { line: 1, col: 1, severity: 'warning', message: `spring ${ch}: damping ${m.damping} should be in (0,1) — clamped at runtime` } })\n }\n if (isGroup(it)) for (const l of it.layers) visit(l.items) // a group shares the scope; instances are linted on their own symbol pass\n }\n }\n visit(contextLayers(doc, editPath).flatMap((l) => l.items))\n // `velocity()` is valid ONLY in a modifier target (resolved by the player's stateful advance). scopeProgram\n // emits the scope's REGULAR expressions but NOT modifier targets, so any velocity() here is a misuse.\n if (/\\bvelocity\\s*\\(/.test(scopeProgram(doc, editPath)))\n out.push({ scope: label, diag: { line: 1, col: 1, message: 'velocity() is only valid inside a spring/smooth target, not a plain expression' } })\n }\n return out\n}\n\nconst sev = (d: Diagnostic) => (d.severity === 'warning' ? 'warning' : 'error')\n\n/** Lint report of a Doc ready to display: `''` = no issue, otherwise `[scope] line:col: level: message`.\n * Pass `src` (the program source) to get positions that point INTO IT rather than into a rebuilt program. */\nexport function lintDocReport(doc: Doc, src?: string): string {\n return lintDoc(doc, src).map(({ scope, diag }) => `[${scope}] ${diag.line}:${diag.col}: ${sev(diag)}: ${diag.message}`).join('\\n')\n}\n\n/** `true` if the Doc has at least one ERROR (warnings alone do not block). */\nexport function docHasErrors(doc: Doc, src?: string): boolean {\n return lintDoc(doc, src).some(({ diag }) => sev(diag) === 'error')\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// docWalk.ts — walking the behavior of a Doc: every action, every expression.\n//\n// A Doc scatters its logic across five places (item interactions, direct-manipulation interactors,\n// procedure bodies, the scene timeline's hooks, each symbol's timeline hooks) and its expressions\n// across two more (channel bindings and stateful modifier targets, at any depth in the group tree).\n// Anything that reasons about \"what does this program read / write / emit\" has to visit all of them,\n// and missing one is a silent hole. Collected here once so the linter and the manifest agree.\n// ─────────────────────────────────────────────────────────────────────────────\nimport type { Action, Doc, Item, Layer } from '@flatkit/types'\nimport { isGroup, isPoseable, isRegion, isText } from '@flatkit/engine/layers'\nimport { EXPR_CHANNELS } from '@flatkit/engine/timeline'\n\n/** Every action of a body, nested `if` / `repeat` bodies included. */\nexport function forEachActionIn(actions: Action[] | undefined, fn: (a: Action) => void): void {\n for (const a of actions ?? []) {\n fn(a)\n if (a.do === 'if') { forEachActionIn(a.then, fn); forEachActionIn(a.else, fn) }\n else if (a.do === 'repeat' || a.do === 'repeatRange') forEachActionIn(a.body, fn)\n }\n}\n\n/** Every ACTION of the Doc: item events, procedure bodies, and the load / enter-frame / at-frame hooks\n * of the scene timeline and of every symbol's. */\nexport function forEachAction(doc: Doc, fn: (a: Action) => void): void {\n for (const i of doc.interactions ?? []) forEachActionIn(i.actions, fn)\n for (const f of doc.functions ?? []) if (f.kind === 'proc') forEachActionIn(f.body, fn)\n for (const t of [doc.timeline, ...(doc.symbols ?? []).map((s) => s.timeline)]) {\n if (!t) continue\n forEachActionIn(t.onLoad, fn)\n forEachActionIn(t.onEnterFrame, fn)\n for (const fa of t.frameActions ?? []) forEachActionIn(fa.actions, fn)\n }\n}\n\n/** Every expression an action carries: assigned values, conditions, loop bounds, call arguments, payloads. */\nexport function forEachActionExpression(actions: Action[] | undefined, fn: (expr: string) => void): void {\n forEachActionIn(actions, (a) => {\n if (a.do === 'setVar' || a.do === 'setParam') fn(a.value)\n else if (a.do === 'setIndex') { fn(a.value); fn(a.index) }\n else if (a.do === 'fillVar') { fn(a.count); fn(a.value) }\n else if (a.do === 'if') fn(a.cond)\n else if (a.do === 'repeat') fn(a.count)\n else if (a.do === 'repeatRange') { fn(a.from); fn(a.to) }\n else if (a.do === 'call') for (const arg of a.args) fn(arg)\n else if (a.do === 'send' && a.payload?.kind === 'expr') fn(a.payload.expr)\n else if (a.do === 'send' && a.payload?.kind === 'record') for (const f of a.payload.fields) fn(f.expr)\n })\n}\n\n/** The channel bindings and modifier targets carried by one item. */\nexport function forEachItemExpression(it: Item, fn: (expr: string, channel: string) => void): void {\n if (!isPoseable(it)) return\n if (it.expressions) for (const k of Object.keys(it.expressions)) { const e = it.expressions[k as keyof typeof it.expressions]; if (e) fn(e, k) }\n if (it.modifiers) for (const ch of EXPR_CHANNELS) { const m = it.modifiers[ch]; if (m) fn(m.target, ch) }\n}\n\n/**\n * The per-frame expressions a LEAF carries in its CONTENT rather than in a channel: a dynamic text's\n * `bind`, a text-on-path's animated `start`/`spacing`, a shape's `draw`/`from` stroke extent. They pose\n * nothing — so they are not channels, and `forEachItemExpression` (whose channel list is part of the\n * manifest contract) leaves them alone — but they READ variables every frame. Anything asking \"what does\n * this program read\" has to see them, or a variable used only by a `bind` reads as dead.\n */\nexport function forEachLeafExpression(it: Item, fn: (expr: string) => void): void {\n if (isText(it)) {\n if (it.bind) fn(it.bind)\n if (it.textPath?.startExpr) fn(it.textPath.startExpr)\n if (it.textPath?.spacingExpr) fn(it.textPath.spacingExpr)\n return\n }\n if (isRegion(it)) {\n if (it.drawExpr) fn(it.drawExpr)\n if (it.drawFromExpr) fn(it.drawFromExpr)\n }\n}\n\n/** Every EXPRESSION text of the Doc: channel bindings, modifier targets and leaf content expressions\n * (scene + symbols, nested groups AND the material of animated layers included), plus everything the\n * actions carry. */\nexport function forEachExpression(doc: Doc, fn: (expr: string) => void): void {\n const visit = (items: Item[]): void => {\n for (const it of items) {\n forEachItemExpression(it, (e) => fn(e))\n forEachLeafExpression(it, fn)\n if (isGroup(it)) for (const l of it.layers) { visit(l.items); visitCels(l) }\n }\n }\n // A cel (animated) layer keeps its material in the keyframes, not in `items` — a `draw \"<expr>\"` on a\n // shape that lives on such a layer is only reachable there.\n const visitCels = (l: Layer): void => { for (const c of l.cels ?? []) for (const r of c.matter ?? []) forEachLeafExpression(r, fn) }\n for (const l of doc.layers) { visit(l.items); visitCels(l) }\n for (const s of doc.symbols ?? []) for (const l of s.layers) { visit(l.items); visitCels(l) }\n for (const i of doc.interactions ?? []) forEachActionExpression(i.actions, fn)\n for (const f of doc.functions ?? []) if (f.kind === 'proc') forEachActionExpression(f.body, fn)\n for (const t of [doc.timeline, ...(doc.symbols ?? []).map((s) => s.timeline)]) {\n if (!t) continue\n forEachActionExpression(t.onLoad, fn)\n forEachActionExpression(t.onEnterFrame, fn)\n for (const fa of t.frameActions ?? []) forEachActionExpression(fa.actions, fn)\n }\n}\n\n/** Every named item of the scene tree, with the layers it owns. Positions are deliberately NOT part of\n * this: what a host needs to honour is the set of NAMES, never where the file happens to place them. */\nexport function forEachNamedItem(layers: Layer[], fn: (it: Item) => void): void {\n for (const l of layers) for (const it of l.items) {\n fn(it)\n if (isGroup(it)) forEachNamedItem(it.layers, fn)\n }\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// check.ts — `flatc --check`, as a function.\n//\n// The compiled `Doc` is NOT enough to validate a program. Two whole classes of error live in the\n// SOURCE and are gone by the time the Doc exists:\n// • statements the parser DROPS (an unknown top-level statement, a malformed line inside a block) —\n// a text that is not FlatInk at all compiles to an empty Doc that nothing distinguishes from a\n// valid one;\n// • an `object \"X\" { … }` block that binds to NOTHING (X is a shape, a layer, or absent) — the\n// binding simply never lands, and the Doc holds no trace of the attempt.\n// Both are source-level passes (`behaviorDiagnostics`, `objectTargetDiagnostics`) that the CLI ran and\n// no public call could reach: an integrator validating in a service got a verdict weaker than the same\n// file checked at the prompt, and had to shell out to `flatc` to get the real one.\n//\n// `checkProgram(src)` runs the WHOLE pass — source in, diagnostics out, no filesystem, no subprocess.\n// The CLI calls the same function, so the two cannot drift.\n// ─────────────────────────────────────────────────────────────────────────────\nimport type { Doc } from '@flatkit/types'\nimport type { TextEdit } from '@flatkit/engine/dsl'\nimport { FlatSyntaxError, behaviorDiagnostics, duplicateBindingDiagnostics, objectTargetDiagnostics, sceneOnlyUnitDiagnostics, itemOnlyUnitDiagnostics } from '@flatkit/engine/flatFormat'\nimport { compileFlatpack, type MediaMap } from './compile'\nimport { lintDoc } from './programDoc'\n\n/** One diagnostic, positioned in the AUTHOR'S source. `scope` is `scene` or `object \"Name\"`. `fix` is\n * present only when the repair is MECHANICAL -- see `TextEdit`. */\nexport type CheckDiagnostic = { scope: string; line: number; col: number; severity: 'error' | 'warning'; message: string; fix?: TextEdit }\n\nexport type CheckOptions = {\n /** Text of each `.flat` symbol library the program draws on — the CLI auto-discovers them beside the file. */\n assetSrcs?: string[]\n /** Declared media, by path (only affects the returned Doc; diagnostics do not depend on it). */\n media?: MediaMap\n}\n\nexport type CheckResult = {\n /** `false` as soon as one diagnostic is an error — the exit code of `flatc --check`. Warnings do not block. */\n ok: boolean\n errors: number\n warnings: number\n diagnostics: CheckDiagnostic[]\n /** The diagnostics as `flatc` prints them (`''` when there is nothing to say). */\n report: string\n /** The compiled program, or `null` if the parser rejected the source outright. */\n doc: Doc | null\n}\n\nconst line1 = (d: CheckDiagnostic): string => `[${d.scope}] ${d.line}:${d.col}: ${d.severity}: ${d.message}`\n\n/** The diagnostics as `flatc` prints them: one `[scope] line:col: level: message` per line. */\nexport const formatDiagnostics = (diagnostics: CheckDiagnostic[]): string => diagnostics.map(line1).join('\\n')\n\n/** The two SOURCE-level passes, which read the author's text rather than the compiled Doc. Always errors. */\nfunction sourceDiagnostics(src: string): CheckDiagnostic[] {\n return [...behaviorDiagnostics(src), ...objectTargetDiagnostics(src), ...sceneOnlyUnitDiagnostics(src), ...itemOnlyUnitDiagnostics(src)]\n .map(({ scope, diag }) => ({ scope, line: diag.line, col: diag.col, severity: 'error' as const, message: diag.message, ...(diag.fix ? { fix: diag.fix } : {}) }))\n}\n\n/** Statements that belong to the COMPOSITION half — they are only legal inside `scene { … }`. */\nconst COMPOSITION = new Set(['group', 'layer', 'rect', 'circle', 'ellipse', 'path', 'text', 'image', 'instance', 'mask'])\n\nconst UNEXPECTED = /^unexpected statement \"([a-z]+)\"/\n\n/**\n * One missing `scene { … }` produces one error per composition line — measured at 72 on a 75-line file,\n * and not one of them contains the word `scene`. Every message is accurate: at that point `group` really\n * is not expected. But they describe the SYMPTOM, and the repair pass they are fed cannot infer the cause\n * from seventy-two of them, so it returns the same program. Collapse them into the cause, once.\n *\n * Only when the block is genuinely absent — with a `scene` present, each precise position is what helps.\n */\nfunction collapseMissingScene(diagnostics: CheckDiagnostic[], src: string): CheckDiagnostic[] {\n if (/^[ \\t]*scene[ \\t]*\\{/m.test(src)) return diagnostics\n const stray = diagnostics.filter((d) => COMPOSITION.has(UNEXPECTED.exec(d.message)?.[1] ?? ''))\n if (!stray.length) return diagnostics\n // Once composition is loose at the root, every parse-level complaint in that scope is a knock-on of\n // the same omission — the braces the block would have owned, the lines it would have contained.\n // Semantic findings (an unknown variable, a dead global) are NOT knock-ons and are left alone.\n const knockOn = diagnostics.filter((d) => d.severity === 'error' && /^unexpected statement |^declaration expected/.test(d.message))\n const words = [...new Set(stray.map((d) => UNEXPECTED.exec(d.message)![1]))]\n const first = stray[0]\n const cause: CheckDiagnostic = {\n scope: first.scope,\n line: first.line,\n col: first.col,\n severity: 'error',\n message:\n `${words.map((w) => `\\`${w}\\``).join(', ')} ${words.length > 1 ? 'are SCENE declarations' : 'is a SCENE declaration'}, ` +\n `and this program has no \\`scene { … }\\` block. Composition lives inside it; everything after it is behavior. ` +\n `Wrap the ${stray.length} statement(s) it rejected: \\`scene {\\\\n layer \"art\" { … }\\\\n}\\`.`,\n }\n return [cause, ...diagnostics.filter((d) => !knockOn.includes(d))]\n}\n\n/** `size W H` declared anywhere at the start of a line — the program's canvas. */\nconst SIZE_HEADER = /^[ \\t]*size[ \\t]+-?[\\d.]+[ \\t]+-?[\\d.]+/m\n\n/**\n * A program that never declares `size`. The line is REQUIRED by the format, yet the compiler defaults it\n * to 800x600 without a word — so a document laid out for another canvas is drawn on the wrong one and\n * everything past its edge is clipped away in silence. That silence is not theoretical: a generator\n * omitted the line across its entire corpus for months, undetected. A WARNING rather than an error,\n * because checking a fragment on its own is a legitimate thing to do.\n */\nfunction missingSizeDiagnostic(src: string, doc: Doc): CheckDiagnostic | null {\n if (SIZE_HEADER.test(src)) return null\n return {\n scope: 'scene',\n line: 1,\n col: 1,\n severity: 'warning',\n message: `no \\`size W H\\` line — it is the REQUIRED first statement of a program, and this document silently defaults to ${doc.width}x${doc.height}. Anything laid out past that edge is clipped with nothing to say so. Declare the canvas you drew for.`,\n }\n}\n\n/**\n * Every diagnostic of a program that HAS compiled: the source-level passes, then the semantic lint of the\n * whole Doc (read against `src`, so positions point into the author's file). Exact-duplicate lines are\n * dropped — a scene parse error is legitimately seen by both paths, which now both read the source.\n */\nexport function programDiagnostics(doc: Doc, src: string): CheckDiagnostic[] {\n const out: CheckDiagnostic[] = []\n const seen = new Set<string>()\n const push = (d: CheckDiagnostic) => { const k = line1(d); if (!seen.has(k)) { seen.add(k); out.push(d) } }\n for (const d of sourceDiagnostics(src)) push(d)\n const noSize = missingSizeDiagnostic(src, doc)\n if (noSize) push(noSize)\n for (const { scope, diag } of duplicateBindingDiagnostics(src)) push({ scope, line: diag.line, col: diag.col, severity: 'warning', message: diag.message })\n for (const { scope, diag } of lintDoc(doc, src)) push({ scope, line: diag.line, col: diag.col, severity: diag.severity === 'warning' ? 'warning' : 'error', message: diag.message, ...(diag.fix ? { fix: diag.fix } : {}) })\n // Collapse LAST: the same \"unexpected statement\" is reported by the source pass and by the Doc lint,\n // so folding one of them alone leaves the other's copy behind.\n return collapseMissingScene(out, src)\n}\n\nconst tally = (diagnostics: CheckDiagnostic[], doc: Doc | null): CheckResult => {\n const errors = diagnostics.filter((d) => d.severity === 'error').length\n return { ok: errors === 0, errors, warnings: diagnostics.length - errors, diagnostics, report: formatDiagnostics(diagnostics), doc }\n}\n\n/**\n * Check a `.flatink` program — the same pass as `flatc --check`, on a string. Never throws: a source the\n * parser rejects outright comes back as a diagnostic with `doc: null`, not an exception.\n *\n * ```ts\n * const { ok, report } = checkProgram(srcFromAnLLM)\n * if (!ok) regenerate(report) // the report is the repair prompt\n * ```\n */\nexport function checkProgram(src: string, opts: CheckOptions = {}): CheckResult {\n let doc: Doc\n try {\n doc = compileFlatpack(src, opts.assetSrcs ?? [], opts.media ?? {})\n } catch (e) {\n // A `FlatSyntaxError` knows where it happened and sometimes how to repair itself; anything else still\n // lands at the top of the file rather than inventing coordinates.\n const f = e instanceof FlatSyntaxError ? e : null\n return tally([{ scope: 'scene', line: f?.line ?? 1, col: f?.col ?? 1, severity: 'error', message: `compile error: ${(e as Error).message}`, ...(f?.fix ? { fix: f.fix } : {}) }], null)\n }\n return tally(programDiagnostics(doc, src), doc)\n}\n\n/** Applies every MECHANICAL repair a diagnostic carries, and returns the new source with how many landed.\n * Bottom-up so earlier positions stay valid, and overlapping edits are skipped rather than merged --\n * two fixes touching one line means at least one was computed against text the other rewrote.\n *\n * A multi-line replacement inherits the INDENTATION of the line it replaces: the parser knows the shape\n * of the repair, not how deep the author nests. This is the one rule to know about the output.\n *\n * Meant to run BEFORE handing a failing program back to a model: a missing comma should not cost a whole\n * regeneration. Re-check the result -- `applyFixes` never claims the program is now valid, only that the\n * edits it knew about were applied. */\nexport function applyFixes(src: string, diagnostics: CheckDiagnostic[]): { text: string; applied: number } {\n const lines = src.split('\\n')\n const edits = diagnostics\n .map((d) => d.fix)\n .filter((f): f is TextEdit => !!f)\n .sort((a, b) => b.line - a.line || b.col - a.col)\n let applied = 0\n const touched = new Set<number>()\n for (const e of edits) {\n // A position this text cannot honour is SKIPPED, never applied blind. The diagnostics may have been\n // stored, replayed against a file that moved on, or built by a consumer -- and a non-positive column\n // reaches `slice` as an offset FROM THE END, which silently truncates the line instead of failing.\n if (!Number.isInteger(e.line) || !Number.isInteger(e.endLine) || !Number.isInteger(e.col) || !Number.isInteger(e.endCol)) continue\n if (e.line < 1 || e.col < 1 || e.endCol < 1 || e.endLine > lines.length) continue\n if (e.endLine < e.line || (e.endLine === e.line && e.endCol < e.col)) continue\n let overlaps = false\n for (let l = e.line; l <= e.endLine; l++) if (touched.has(l)) overlaps = true\n if (overlaps) continue\n const indent = /^[ \\t]*/.exec(lines[e.line - 1])![0]\n const body = e.replacement.split('\\n').map((l, i) => (i === 0 ? l : indent + l)).join('\\n')\n const head = lines[e.line - 1].slice(0, e.col - 1)\n const tail = lines[e.endLine - 1].slice(e.endCol - 1)\n lines.splice(e.line - 1, e.endLine - e.line + 1, ...(head + body + tail).split('\\n'))\n for (let l = e.line; l <= e.endLine; l++) touched.add(l)\n applied++\n }\n return { text: lines.join('\\n'), applied }\n}\n\n/** Applies the mechanical repairs until nothing is left to apply, and returns the FINAL text. Pure: it\n * takes a `recheck` and never touches the filesystem, which is the whole guarantee -- the caller writes\n * once, at the end, a text this loop has already re-checked. Writing each pass and reverting on failure\n * would leave a window where the author's file holds a version we already know we do not want.\n *\n * It ITERATES because repairing one error unmasks the next (a run-on interactor line swallows the\n * statements under it), and it accepts a pass only if the error count strictly DROPS -- except that the\n * count legitimately RISES on the first pass of a source that did not parse at all, where a single error\n * was all that was visible. That case never reaches here: it is handled before the Doc exists. */\nexport function repairLoop(\n src: string,\n diagnostics: CheckDiagnostic[],\n recheck: (candidate: string) => CheckDiagnostic[],\n maxPasses = 5,\n): { text: string; applied: number; first: number; errors: number } {\n const errs = (ds: CheckDiagnostic[]) => ds.filter((d) => d.severity === 'error').length\n const first = errs(diagnostics)\n let text = src, applied = 0, errors = first, current = diagnostics\n for (let pass = 0; pass < maxPasses; pass++) {\n const step = applyFixes(text, current)\n if (!step.applied) break\n let after: CheckDiagnostic[]\n try { after = recheck(step.text) } catch { break } // the repair broke the parse outright -> keep the last accepted text\n if (errs(after) >= errors) break\n text = step.text; applied += step.applied; errors = errs(after); current = after\n }\n return { text, applied, first, errors }\n}\n"],"mappings":"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","names":["isGroup","isText","isPoseable","isRegion","EXPR_CHANNELS","parseUnits","isGroup","isPoseable","EXPR_CHANNELS","names","isRegion","isText","indent"]}
|
package/dist/cli/flatc.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
scopeProgram,
|
|
23
23
|
scopeRegions,
|
|
24
24
|
splitScopeProgram
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-W3YUC6BC.js";
|
|
26
26
|
import {
|
|
27
27
|
compileFlatpack,
|
|
28
28
|
packToJSON
|
|
@@ -91,17 +91,20 @@ reveal c { brush 32 grain 8 erase cells grid } // scratch \u2192 c = cleared
|
|
|
91
91
|
when dropped on Zone { \u2026 } // fires on release when the object's center is inside the named zone
|
|
92
92
|
|
|
93
93
|
## Declarations
|
|
94
|
-
|
|
94
|
+
var name = 0 \xB7 var arr = fill(n, v) \xB7 var arr = [a, b, c] // document state: readable EVERYWHERE (bindings included)
|
|
95
|
+
let name = 0 // the same thing at the top level of a program; inside a scope it stays local
|
|
95
96
|
fn name(a, b) = expr // value function (use in expressions)
|
|
96
97
|
fn name() { \u2026 } // procedure (block of actions)
|
|
97
98
|
each "Symbol" as i { opacity = data[i] } // bind every instance of a symbol (i = index)
|
|
98
99
|
use "package" packages: ${PACKAGES.join(" ")} // OPTIONAL: calling a package function imports it automatically
|
|
99
100
|
|
|
100
101
|
## Example
|
|
101
|
-
|
|
102
|
+
var score = 0
|
|
103
|
+
var lit = 0
|
|
102
104
|
every frame { score = score + 1 }
|
|
103
105
|
object "Ball" {
|
|
104
|
-
when clicked {
|
|
106
|
+
when clicked { lit = 1 }
|
|
107
|
+
opacity = lit == 1 ? 1 : 0.4 // a binding READS the document's state
|
|
105
108
|
rotation = atan2(Target.y - self.y, Target.x - self.x) // aim at another object by name
|
|
106
109
|
}`;
|
|
107
110
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/manifest.ts","../src/languageCard.ts","../src/drawingCard.ts","../src/index.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// manifest.ts — \"map of the scene\" for an LLM (and tooling introspection).\n//\n// The language fits in < 2k tokens (see languageCard); the real context cost for an LLM\n// is knowing WHAT IT CAN NAME in THIS scene (objects, assets, variables, functions).\n// `docToManifest` derives this compact block from a Doc — the exact counterpart of references\n// by name (sceneRefs): the model then references only REAL names, and the linter catches the rest.\n//\n// Pure, derived (never stored). ~a few hundred tokens for a real scene.\n// ─────────────────────────────────────────────────────────────────────────────\nimport type { Doc, Group, Image, Instance, ItemEvent, Layer, Text } from '@flatkit/types'\nimport { EXPR_CHANNELS, OFFSET_CHANNELS } from '@flatkit/engine/timeline'\nimport { getSymbol, isGroup, isImage, isInstance, isPoseable, isText } from '@flatkit/engine/layers'\nimport { analyzeExpr } from '@flatkit/engine/expr'\nimport { forEachAction, forEachActionExpression, forEachItemExpression } from './docWalk'\nimport { languageCard } from './languageCard'\nimport { drawingCard } from './drawingCard'\n\n/** Type label of a poseable (hence named) item. */\nfunction kindLabel(doc: Doc, it: Group | Instance | Text | Image): string {\n if (isInstance(it)) { const s = getSymbol(doc, it.symbolId); return s ? `Instance:${s.name}` : 'Instance' }\n if (isText(it)) return 'Text'\n if (isImage(it)) return 'Image'\n return 'Symbol' // Group (\"symbol\" in the UI)\n}\n\n/**\n * A named scene object and the CONTRACT the logic places on it — what a host must honour to reskin the\n * scene without touching its behavior. Deliberately free of coordinates: the names and the roles are the\n * contract, the composition stays entirely the skin's business. (A contract that carried positions would\n * hand every reskin the same layout, which is exactly the failure it exists to prevent.)\n */\nexport type ManifestObject = {\n name: string\n kind: string\n /** Item events the logic handles on it (`click`, `drop`…) — the skin must keep them reachable. */\n events: ItemEvent[]\n /** A `drag`/`turn` interactor targets it: the pointer writes its position, so the skin must not pin it. */\n dragged: boolean\n /** A placement target: something drops on it, or it carries a `hitbox`. Keep the name and a generous box. */\n zone: boolean\n /** Channels the logic drives (bindings and modifier targets) — a skin that sets these fights the logic. */\n channels: string[]\n /** Document variables it reads: the game state a skin can hang its own visuals on. */\n reads: string[]\n}\n\n/** The program's STATE: every variable a skin could meaningfully bind to. Wider than `doc.variables`,\n * which only holds the `var`-declared ones — a variable first assigned in a handler, or written by a\n * `drag` interactor, is just as real at runtime and is often the most interesting one to bind. */\nfunction stateVariables(doc: Doc): Set<string> {\n const out = new Set(Object.keys(doc.variables ?? {}))\n forEachAction(doc, (a) => {\n if (a.do === 'setVar' || a.do === 'setIndex') out.add(a.name)\n else if (a.do === 'repeatRange') out.add(a.var)\n })\n for (const i of doc.interactors ?? []) for (const v of [i.varX, i.varY, i.varT]) if (v) out.add(v)\n return out\n}\n\n/** State variables referenced by an expression — parsed, not grepped, so `open` never matches `reopen`\n * and a name nested inside a call still counts. An unparseable expression yields nothing (the linter\n * reports it; the manifest stays quiet). Runtime scalars (`time`, `mouse.x`) are not state and never\n * appear: they are not something a host can set. */\nfunction readsOf(expr: string, state: Set<string>, into: Set<string>): void {\n const a = analyzeExpr(expr)\n if (!a.ok) return\n for (const id of a.refs.ids) if (state.has(id)) into.add(id)\n}\n\n/** Named scene objects (groups included, library symbols excluded) with their binding contract; first\n * name wins, and nested groups are walked. */\nexport function manifestObjects(doc: Doc): ManifestObject[] {\n const out: ManifestObject[] = []\n const seen = new Set<string>()\n const state = stateVariables(doc)\n const dropZones = new Set((doc.interactions ?? []).filter((i) => i.event === 'drop' && i.over).map((i) => i.over as string))\n const walk = (layers: Layer[]) => {\n for (const l of layers) for (const it of l.items) {\n if (isPoseable(it) && it.name && !seen.has(it.name)) {\n seen.add(it.name)\n const mine = (doc.interactions ?? []).filter((i) => i.targetId === it.id)\n const channels: string[] = []\n const reads = new Set<string>()\n forEachItemExpression(it, (expr, channel) => { channels.push(channel); readsOf(expr, state, reads) })\n for (const i of mine) forEachActionExpression(i.actions, (expr) => readsOf(expr, state, reads))\n out.push({\n name: it.name,\n kind: kindLabel(doc, it),\n events: [...new Set(mine.map((i) => i.event))],\n dragged: !!doc.interactors?.some((i) => i.targetId === it.id),\n zone: dropZones.has(it.name) || (isGroup(it) && !!it.hitbox),\n channels,\n reads: [...reads],\n })\n }\n if (isGroup(it)) walk(it.layers)\n }\n }\n walk(doc.layers)\n return out\n}\n\n/** The events the program EMITS to its host (`send \"…\"`), in order of first appearance, deduped. The\n * other half of the contract: the moments a host — or a skin's motion pass — can react to. */\nexport function manifestEvents(doc: Doc): string[] {\n const events = new Set<string>()\n forEachAction(doc, (a) => { if (a.do === 'send') events.add(a.event) })\n return [...events]\n}\n\n/** One object's contract, as readable clauses. Empty = pure decor the skin owns outright. */\nfunction contractParts(o: ManifestObject): string[] {\n const parts: string[] = []\n if (o.dragged) parts.push('drag')\n if (o.zone) parts.push('zone')\n if (o.events.length) parts.push(`on ${o.events.join('/')}`)\n if (o.channels.length) parts.push(`driven: ${o.channels.join(' ')}`)\n if (o.reads.length) parts.push(`reads: ${o.reads.join(' ')}`)\n return parts\n}\n\n/** Variables → `name=value` (scalar) or `name[len]` (array). */\nfunction manifestVars(doc: Doc): string[] {\n return Object.entries(doc.variables ?? {}).map(([k, v]) => (Array.isArray(v) ? `${k}[${v.length}]` : `${k}=${v}`))\n}\n\n/**\n * Compact map of the scene (objects/assets/variables/functions/packages) — injectable in a prompt.\n * Only non-empty sections appear. The names are the ones the code can reference.\n */\nexport function docToManifest(doc: Doc): string {\n const objs = manifestObjects(doc)\n const assets = (doc.assets ?? []).map((a) => `${a.kind}:${a.id}`)\n const vars = manifestVars(doc)\n const funcs = (doc.functions ?? []).map((f) => `${f.name}(${f.params.join(', ')})`)\n const lines = ['# SCENE', `size: ${doc.width}x${doc.height}`]\n if (objs.length) lines.push(`objects: ${objs.map((o) => `${o.name}(${o.kind})`).join(', ')}`)\n if (assets.length) lines.push(`assets: ${assets.join(', ')}`)\n if (vars.length) lines.push(`vars: ${vars.join(', ')}`)\n if (funcs.length) lines.push(`funcs: ${funcs.join(', ')}`)\n if (doc.imports?.length) lines.push(`packages: ${doc.imports.join(', ')}`)\n // The binding contract, for the objects that carry one — what a skin must honour. No positions: the\n // composition is the skin's to invent, which is precisely what keeps two scenes from looking alike.\n const contract = objs.map((o) => ({ o, parts: contractParts(o) })).filter(({ parts }) => parts.length)\n if (contract.length) {\n lines.push('contract (honour these; the layout is yours):')\n for (const { o, parts } of contract) lines.push(` ${o.name} - ${parts.join(', ')}`)\n }\n const events = manifestEvents(doc)\n if (events.length) lines.push(`events: ${events.join(', ')}`)\n lines.push(`channels: ${EXPR_CHANNELS.join(' ')} (additive offsets: ${OFFSET_CHANNELS.join(' ')} -> pos = at + d)`)\n return lines.join('\\n')\n}\n\n/**\n * EVERYTHING a model needs to write a whole program: both language references (static) + the scene map\n * derived from the Doc. It is the bundle, not the map — if you only want the names this scene can\n * reference (because you already inject the references yourself), that is **`docToManifest(doc)`**, and\n * calling this instead ships the cards a second time.\n *\n * The DRAWING card is included by default. Handed the behavior card alone, a model asked for decor\n * invents a shapes grammar — and what it invents does not compile. Pass `{ drawing: false }` when the\n * model only edits behavior and the prompt budget is tight.\n */\nexport function llmContext(doc: Doc, opts: { drawing?: boolean } = {}): string {\n const cards = opts.drawing === false ? languageCard() : `${languageCard()}\\n\\n${drawingCard()}`\n return `${cards}\\n\\n${docToManifest(doc)}`\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// languageCard.ts — TERSE reference of FlatInk Script, \"system-prompt\" sized.\n//\n// Single source of truth to steer an LLM (or a human in a hurry): condensed\n// grammar + built-ins, ~1k tokens. The function/constant/channel lists are\n// INTERPOLATED from expr/timeline/stdlib → never out of sync with the real engine.\n// To be paired with `docToManifest` (manifest.ts) for the names specific to a scene.\n// ─────────────────────────────────────────────────────────────────────────────\nimport { STD_CONSTANTS, STD_FUNCTIONS } from '@flatkit/engine/expr'\nimport { EXPR_CHANNELS } from '@flatkit/engine/timeline'\nimport { PACKAGES } from '@flatkit/engine/stdlib'\n\n/** Language reference card (static, kept in sync with the engine via STD_*). */\nexport function languageCard(): string {\n return `# FlatInk Script — reference\nNumbers only (0 = false, anything else = true). No string type (only event/label/asset names in quotes). Comment: // to end of line.\nOne statement per line — a newline ends the statement (write \\`x = 1\\` then \\`y = 2\\` on separate lines, not \\`x = 1 y = 2\\`).\n\n## Objects\nobject \"Name\" { … } attaches behavior BY NAME. The name must be a group / instance / text / image — the only things that carry a pose.\nA SHAPE (\\`rect … as \"N\"\\`) or a LAYER cannot be animated: wrap the shape in \\`group \"N\" { layer \"art\" { … } }\\`. (Naming one is a compile error.)\nOpacities MULTIPLY down the tree — do not set \\`opacity 0\\` on the shape to hide it at rest, or the group's fade-in stays invisible.\n\n## Events (attach to an object or to the scene)\nwhen loaded { } // once, on start\nevery frame { } // every frame\nat frame N { } // when the playhead reaches frame N\nwhen clicked|hovered|unhovered|pressed|dragged|released|held { }\n\n## Actions\nplay · pause · go to frame N [and play|and pause] · go to \"label\"\nname = expr // set a variable\narr[i] = expr // write an array slot\narr = fill(n, v) // replace a WHOLE array (the only array-valued assignment; expressions are scalar)\nif cond { } else { } · repeat N times { } · repeat i from A to B { }\nmyProc() · send \"event\"[, expr | text(\"id\") | { a = expr, b … }] · sound \"assetId\"\n\n## Expressions (drive a channel, or compute in an action)\nchannel = expr channels: ${EXPR_CHANNELS.join(' ')} (expression wins over keyframes)\ndx = expr · dy = expr // ADDITIVE offset: final pos = at + (dx, dy) — oscillate AROUND the anchor (dx = 30*sin(time)); absolute x/y REPLACE at\nrotationDeg = expr // sugar for rotation = rad(expr) — author angles in DEGREES (rotation & sin/cos/atan2 are RADIANS)\noperators: + - * / % < > <= >= == != && || ! cond ? a : b\ncontext: time frame clock value · mouse.x mouse.y mouse.dx mouse.dy · keys.Space keys.ArrowLeft … (keys are 1/0, use directly: keys.Space ? … : …)\n time WRAPS every durationFrames (2.5 s by default) — clock is MONOTONE. Timestamps you capture and compare later MUST use clock\n (\\`when wrong { shown = clock }\\` + \\`opacity = pulse(shown, 4)\\`), or the ramp replays on every loop.\nName.x Name.y Name.rotation Name.scaleX Name.scaleY Name.opacity // any named object (identifier name), live on-screen value (read-only)\nself.x self.y self.rotation self.scaleX self.scaleY self.opacity // the object's own channels, in its bindings (no mirror variable)\n\n## Spaces (local vs world)\nself & channels (x, y, rotation…) = LOCAL (relative to parent — what x = … sets). Name.x, mouse.x = WORLD (the stage).\nAt the scene root, local = world (the common case → nothing to think about). If an object is NESTED in a group and you\nrelate it to a world position, convert: toLocalX(x, y) toLocalY(x, y) (world → your space) · toGlobalX/Y (your space → world).\nconstants: ${STD_CONSTANTS.join(' ')}\nfunctions: ${STD_FUNCTIONS.join(' ')}\n\n## Direct manipulation (interactors)\ndrag x, y // object follows the pointer while held → writes vars x, y (bind them: x = vx, y = vy)\n{ enabled <expr> } gates the GESTURE only — when/pressed/released/clicked STILL fire. Guard the body: when released { if done == 0 { … } }\ndragX vx · dragY vy // single-axis\ndrag x, y { confine to Zone snap 10 } // bound to a named object's box · grid snap\nturn a around cx,cy { snap 15 } // dial/knob → a = pivot→cursor angle in RADIANS (pair: rotation = a)\nturnDeg a around cx,cy { snap 15 } // same in DEGREES (pair: rotationDeg = a) · snap is degrees on both\ntrace p along Route { tolerance 30 step 40 } // follow a named guide → p = 0..1 by ARC LENGTH (pair: draw \"p\"). step = a TRACE, not a cursor: without it one press near the finish reports 1\nreveal c { brush 32 grain 8 erase cells grid } // scratch → c = cleared fraction; brush = finger, grain = resolution; erase = the runtime rubs the target out; grid[row*cols+col] = 1 says WHERE\nwhen dropped on Zone { … } // fires on release when the object's center is inside the named zone\n\n## Declarations\nlet name = 0 · let arr = fill(n, v) · let arr = [a, b, c]\nfn name(a, b) = expr // value function (use in expressions)\nfn name() { … } // procedure (block of actions)\neach \"Symbol\" as i { opacity = data[i] } // bind every instance of a symbol (i = index)\nuse \"package\" packages: ${PACKAGES.join(' ')} // OPTIONAL: calling a package function imports it automatically\n\n## Example\nlet score = 0\nevery frame { score = score + 1 }\nobject \"Ball\" {\n when clicked { score = score + 1 }\n rotation = atan2(Target.y - self.y, Target.x - self.x) // aim at another object by name\n}`\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// drawingCard.ts — TERSE reference of the DRAWING half of FlatInk, \"system-prompt\" sized.\n//\n// `languageCard` covers BEHAVIOR (events, channels, expressions) and not one word of the composition:\n// no shapes, no paints, no filters. An integrator handing that card to a model and asking for decor was\n// handing it a reference with nothing about drawing — so the model guessed, and what a model guesses in\n// a DSL does not compile. The two cards are complements: pair them (plus `docToManifest` for the names\n// of a particular scene) whenever a model has to produce a whole `.flatink`.\n//\n// Every ```flatink example below is COMPILED by drawingCard.test.ts. A reference that is copied drifts;\n// one that is compiled cannot. When the grammar moves, that test goes red rather than this card going\n// quietly wrong.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Drawing reference card (composition: shapes, paints, filters, text, clipping). */\nexport function drawingCard(): string {\n return `# FlatInk — drawing (the \\`scene { … }\\` half)\n\nThe unit is the LAYER: \\`layer \"name\" { … }\\`, stacked bottom to top. A layer holds shapes, text, images\nand groups (which nest their own layers). Coordinates are PIXELS in the parent's frame — never percentages.\n\n## Shapes\ncircle <cx> <cy> <r>\nellipse <cx> <cy> <rx> <ry>\nrect <x> <y> <w> <h> [<r>] // r = rounded corners (or <rx> <ry> for distinct)\npath \"M0 0 C40 -20 80 20 120 0 Z\" // raw SVG path data — total freedom\ncircle 100 100 40 as \"Ring\" // name it (right after the geometry) → addressable\n\n## Paint\nfill #rrggbb | #rrggbbaa · nofill\nfill linear(<angle>, 0:#…, 1:#…) // angle: 0 = →, 90 = ↓ ; stops are offset:color\nfill radial(<cx>, <cy>, <r>, 0:#…, 1:#…) // cx/cy/r as 0..1 of the box\nstroke <paint> <width> [cap butt|round|square] [join miter|round|bevel] [miter <n>] [dash a,b]\ndraw <0..1> [from <0..1>] // how much of the OUTLINE is stroked, by ARC LENGTH; \"quoted\" = per-frame expression\nopacity <0..1> // opacities MULTIPLY down the tree\n\n## Filters — on any item, no wrapper group needed\nfilter glow <blur> <color> · filter shadow <dx> <dy> <blur> <color>\nfilter blur <radius> · filter adjust <brightness> <contrast> <saturate> <hue>\n\n## Text\ntext \"…\" at <x>,<y> box <w> <h> font \"sans-serif\" size <n> align center line 1.2 color #… [bold] [italic] [wrap]\ntext \"…\" along \"<shapeId>\" align center start 0.5 // laid along a named shape's curve\nWord-wrap is OPT-IN: without \\`wrap\\`, only an explicit \\\\n breaks a line.\n\n## Images\nimage \"<assetId>\" <w> <h> at <x>,<y> // the asset is declared at the top: asset \"logo\" \"logo.svg\" image\n\n## Clipping\ngroup \"Name\" at x,y clip <x> <y> <w> <h> { … } // rectangular cut, in the group's LOCAL coordinates\nmask layer \"Name\" { <shapes> layer \"c\" { … } } // arbitrary shape: the mask's matter clips its child layers\n\n## The five rules that decide whether it compiles\n1. WORD ORDER IS FIXED: content → \\`as \"…\"\\` → \\`at …\\` → style. So \\`text \"Hi\" at 10,10 box 200 40\\`,\n NEVER \\`text \"Hi\" box 200 40 at 10,10\\`. A shape names itself right after its geometry.\n Stroke options (\\`cap\\`/\\`join\\`/\\`miter\\`/\\`dash\\`) belong to the STROKE and follow it directly:\n \\`nofill stroke #888 2 dash 6,5\\`, not \\`stroke #888 2 nofill dash 6,5\\`.\n2. A COMMENT STARTS WITH \\`//\\`. A \\`#\\` opens a COLOR.\n3. ONE STATEMENT PER LINE.\n4. Anything you intend to ANIMATE must be a \\`group \"Name\" at x,y { layer \"c\" { … } }\\`. An \\`object\\`\n block aimed at a shape or a layer is a compile ERROR — shapes are baked material and carry no pose.\n5. A group's children are positioned RELATIVE to it. Draw them around 0,0 and place the group.\n\n## Examples\n\nA sky and a ground, in two gradients:\n\n\\`\\`\\`flatink\nsize 960 540\nscene {\n layer \"sky\" {\n rect 0 0 960 540 fill linear(90, 0:#1b2a4a, 1:#4a6fa5)\n ellipse 780 90 70 70 fill radial(0.5, 0.5, 0.5, 0:#ffe9a8, 1:#ffe9a800)\n }\n layer \"ground\" {\n path \"M0 430 C240 400 420 460 960 415 L960 540 L0 540 Z\" fill #2e4b34 opacity 0.85\n }\n}\n\\`\\`\\`\n\nA line-art silhouette and a drop shadow:\n\n\\`\\`\\`flatink\nsize 200 400\nscene {\n layer \"tree\" {\n path \"M60 300 L60 180 M60 220 L20 170 M60 230 L100 180\" nofill stroke #23301f 8 cap round\n circle 60 150 60 fill #3f6b3a filter shadow 0 6 12 #00000055\n }\n}\n\\`\\`\\`\n\nA group — the only shape a behavior block can animate:\n\n\\`\\`\\`flatink\nsize 480 320\nscene {\n layer \"life\" {\n group \"Cloud\" at 240,120 {\n layer \"c\" {\n ellipse 0 0 70 26 fill #ffffff opacity 0.22\n ellipse 46 -10 44 22 fill #ffffff opacity 0.18\n }\n }\n }\n}\n\nobject \"Cloud\" {\n dx = 30 * sin(clock)\n}\n\\`\\`\\`\n\nA panel, text, and a clipped porthole:\n\n\\`\\`\\`flatink\nsize 960 540\nscene {\n layer \"panel\" {\n rect 40 40 300 90 24 fill #10141c99 stroke #ffffff33 2\n text \"Workshop\" at 60,66 box 260 40 font \"sans-serif\" size 26 color #f2f6ff\n group \"Porthole\" at 700,300 clip -60 -60 120 120 {\n layer \"c\" { circle 0 0 90 fill linear(0, 0:#0b3d5c, 1:#0f6f92) }\n }\n }\n}\n\\`\\`\\``\n}\n","// @flatkit/compiler -- the FlatInk language and compiler.\n//\n// Parses FlatInk Script (the .flatink DSL) and compiles a program plus its assets into a .flatpack:\n// a playable `Doc` (JSON, with the material already baked). Also ships the `flatc` CLI, via its `bin` -- NOT from this entry, which stays free of Node builtins.\n//\n// The language layer (DSL parser/printer, .flat format) lives in @flatkit/engine and is re-exported\n// here so the compiler package is a single coherent entry point.\n\n// --- Compile a program (+ assets) into a playable .flatpack Doc ---------------\nexport { compileFlatpack, packToJSON, type MediaMap } from './compile'\n\n// --- Check a program the way the CLI does (source in, diagnostics out) --------\nexport { checkProgram, programDiagnostics, formatDiagnostics, applyFixes, repairLoop, type CheckDiagnostic, type CheckOptions, type CheckResult } from './check'\nexport type { TextEdit } from '@flatkit/engine/dsl'\n\n// --- Static analysis: lint a program / a whole Doc ----------------------------\nexport { lint, lintReport, localVariables, type LintContext } from './lint'\nexport {\n lintDoc, lintDocReport, docHasErrors, docLintContext, allScopeVariables,\n scopeProgram, docStructureWarnings, docLayoutWarnings,\n} from './programDoc'\n\n// --- Manifest / LLM context for a Doc -----------------------------------------\nexport { manifestObjects, manifestEvents, docToManifest, llmContext, type ManifestObject } from './manifest'\n\n// --- The reference cards: behavior (languageCard) and composition (drawingCard) -\nexport { languageCard } from './languageCard'\nexport { drawingCard } from './drawingCard'\n\n// --- Scope-program helpers (split/join the per-object behavior blocks) ---------\nexport { splitScopeProgram, scopeRegions, formatObjectBlock, joinScopeProgram } from './scopeProgram'\n\n// --- The flatc CLI entry point (also wired as the `flatc` bin) -----------------\n// `run` (the CLI entry) is deliberately NOT re-exported. It lives in a module that imports `fs`/`path` at\n// the top, so re-exporting it put Node builtins in the root's chunk graph -- and a browser bundle then\n// fails at NAME RESOLUTION (`\"extname\" is not exported by \"__vite-browser-external\"`), before tree-shaking\n// can drop the unused symbol. The root's job is the pure helpers a service or a browser needs\n// (`checkProgram`, `languageCard`, `drawingCard`, `docToManifest`); the CLI's job is the `bin`, which\n// imports `./cli/flatc` directly. `scripts/check-pack.mjs` walks the built chunk graph to keep it that way.\n\n// --- The language layer, re-exported from the engine for convenience ----------\nexport { parseUnits, printUnits } from '@flatkit/engine/dsl'\nexport {\n parseProgram, printProgram, parseProgramFull, printProgramFull,\n parseFlat, parseFlatLib, exportFlatProject,\n} from '@flatkit/engine/flatFormat'\n"],"mappings":"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","names":["EXPR_CHANNELS","EXPR_CHANNELS"]}
|
|
1
|
+
{"version":3,"sources":["../src/manifest.ts","../src/languageCard.ts","../src/drawingCard.ts","../src/index.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// manifest.ts — \"map of the scene\" for an LLM (and tooling introspection).\n//\n// The language fits in < 2k tokens (see languageCard); the real context cost for an LLM\n// is knowing WHAT IT CAN NAME in THIS scene (objects, assets, variables, functions).\n// `docToManifest` derives this compact block from a Doc — the exact counterpart of references\n// by name (sceneRefs): the model then references only REAL names, and the linter catches the rest.\n//\n// Pure, derived (never stored). ~a few hundred tokens for a real scene.\n// ─────────────────────────────────────────────────────────────────────────────\nimport type { Doc, Group, Image, Instance, ItemEvent, Layer, Text } from '@flatkit/types'\nimport { EXPR_CHANNELS, OFFSET_CHANNELS } from '@flatkit/engine/timeline'\nimport { getSymbol, isGroup, isImage, isInstance, isPoseable, isText } from '@flatkit/engine/layers'\nimport { analyzeExpr } from '@flatkit/engine/expr'\nimport { forEachAction, forEachActionExpression, forEachItemExpression } from './docWalk'\nimport { languageCard } from './languageCard'\nimport { drawingCard } from './drawingCard'\n\n/** Type label of a poseable (hence named) item. */\nfunction kindLabel(doc: Doc, it: Group | Instance | Text | Image): string {\n if (isInstance(it)) { const s = getSymbol(doc, it.symbolId); return s ? `Instance:${s.name}` : 'Instance' }\n if (isText(it)) return 'Text'\n if (isImage(it)) return 'Image'\n return 'Symbol' // Group (\"symbol\" in the UI)\n}\n\n/**\n * A named scene object and the CONTRACT the logic places on it — what a host must honour to reskin the\n * scene without touching its behavior. Deliberately free of coordinates: the names and the roles are the\n * contract, the composition stays entirely the skin's business. (A contract that carried positions would\n * hand every reskin the same layout, which is exactly the failure it exists to prevent.)\n */\nexport type ManifestObject = {\n name: string\n kind: string\n /** Item events the logic handles on it (`click`, `drop`…) — the skin must keep them reachable. */\n events: ItemEvent[]\n /** A `drag`/`turn` interactor targets it: the pointer writes its position, so the skin must not pin it. */\n dragged: boolean\n /** A placement target: something drops on it, or it carries a `hitbox`. Keep the name and a generous box. */\n zone: boolean\n /** Channels the logic drives (bindings and modifier targets) — a skin that sets these fights the logic. */\n channels: string[]\n /** Document variables it reads: the game state a skin can hang its own visuals on. */\n reads: string[]\n}\n\n/** The program's STATE: every variable a skin could meaningfully bind to. Wider than `doc.variables`,\n * which only holds the `var`-declared ones — a variable first assigned in a handler, or written by a\n * `drag` interactor, is just as real at runtime and is often the most interesting one to bind. */\nfunction stateVariables(doc: Doc): Set<string> {\n const out = new Set(Object.keys(doc.variables ?? {}))\n forEachAction(doc, (a) => {\n if (a.do === 'setVar' || a.do === 'setIndex') out.add(a.name)\n else if (a.do === 'repeatRange') out.add(a.var)\n })\n for (const i of doc.interactors ?? []) for (const v of [i.varX, i.varY, i.varT]) if (v) out.add(v)\n return out\n}\n\n/** State variables referenced by an expression — parsed, not grepped, so `open` never matches `reopen`\n * and a name nested inside a call still counts. An unparseable expression yields nothing (the linter\n * reports it; the manifest stays quiet). Runtime scalars (`time`, `mouse.x`) are not state and never\n * appear: they are not something a host can set. */\nfunction readsOf(expr: string, state: Set<string>, into: Set<string>): void {\n const a = analyzeExpr(expr)\n if (!a.ok) return\n for (const id of a.refs.ids) if (state.has(id)) into.add(id)\n}\n\n/** Named scene objects (groups included, library symbols excluded) with their binding contract; first\n * name wins, and nested groups are walked. */\nexport function manifestObjects(doc: Doc): ManifestObject[] {\n const out: ManifestObject[] = []\n const seen = new Set<string>()\n const state = stateVariables(doc)\n const dropZones = new Set((doc.interactions ?? []).filter((i) => i.event === 'drop' && i.over).map((i) => i.over as string))\n const walk = (layers: Layer[]) => {\n for (const l of layers) for (const it of l.items) {\n if (isPoseable(it) && it.name && !seen.has(it.name)) {\n seen.add(it.name)\n const mine = (doc.interactions ?? []).filter((i) => i.targetId === it.id)\n const channels: string[] = []\n const reads = new Set<string>()\n forEachItemExpression(it, (expr, channel) => { channels.push(channel); readsOf(expr, state, reads) })\n for (const i of mine) forEachActionExpression(i.actions, (expr) => readsOf(expr, state, reads))\n out.push({\n name: it.name,\n kind: kindLabel(doc, it),\n events: [...new Set(mine.map((i) => i.event))],\n dragged: !!doc.interactors?.some((i) => i.targetId === it.id),\n zone: dropZones.has(it.name) || (isGroup(it) && !!it.hitbox),\n channels,\n reads: [...reads],\n })\n }\n if (isGroup(it)) walk(it.layers)\n }\n }\n walk(doc.layers)\n return out\n}\n\n/** The events the program EMITS to its host (`send \"…\"`), in order of first appearance, deduped. The\n * other half of the contract: the moments a host — or a skin's motion pass — can react to. */\nexport function manifestEvents(doc: Doc): string[] {\n const events = new Set<string>()\n forEachAction(doc, (a) => { if (a.do === 'send') events.add(a.event) })\n return [...events]\n}\n\n/** One object's contract, as readable clauses. Empty = pure decor the skin owns outright. */\nfunction contractParts(o: ManifestObject): string[] {\n const parts: string[] = []\n if (o.dragged) parts.push('drag')\n if (o.zone) parts.push('zone')\n if (o.events.length) parts.push(`on ${o.events.join('/')}`)\n if (o.channels.length) parts.push(`driven: ${o.channels.join(' ')}`)\n if (o.reads.length) parts.push(`reads: ${o.reads.join(' ')}`)\n return parts\n}\n\n/** Variables → `name=value` (scalar) or `name[len]` (array). */\nfunction manifestVars(doc: Doc): string[] {\n return Object.entries(doc.variables ?? {}).map(([k, v]) => (Array.isArray(v) ? `${k}[${v.length}]` : `${k}=${v}`))\n}\n\n/**\n * Compact map of the scene (objects/assets/variables/functions/packages) — injectable in a prompt.\n * Only non-empty sections appear. The names are the ones the code can reference.\n */\nexport function docToManifest(doc: Doc): string {\n const objs = manifestObjects(doc)\n const assets = (doc.assets ?? []).map((a) => `${a.kind}:${a.id}`)\n const vars = manifestVars(doc)\n const funcs = (doc.functions ?? []).map((f) => `${f.name}(${f.params.join(', ')})`)\n const lines = ['# SCENE', `size: ${doc.width}x${doc.height}`]\n if (objs.length) lines.push(`objects: ${objs.map((o) => `${o.name}(${o.kind})`).join(', ')}`)\n if (assets.length) lines.push(`assets: ${assets.join(', ')}`)\n if (vars.length) lines.push(`vars: ${vars.join(', ')}`)\n if (funcs.length) lines.push(`funcs: ${funcs.join(', ')}`)\n if (doc.imports?.length) lines.push(`packages: ${doc.imports.join(', ')}`)\n // The binding contract, for the objects that carry one — what a skin must honour. No positions: the\n // composition is the skin's to invent, which is precisely what keeps two scenes from looking alike.\n const contract = objs.map((o) => ({ o, parts: contractParts(o) })).filter(({ parts }) => parts.length)\n if (contract.length) {\n lines.push('contract (honour these; the layout is yours):')\n for (const { o, parts } of contract) lines.push(` ${o.name} - ${parts.join(', ')}`)\n }\n const events = manifestEvents(doc)\n if (events.length) lines.push(`events: ${events.join(', ')}`)\n lines.push(`channels: ${EXPR_CHANNELS.join(' ')} (additive offsets: ${OFFSET_CHANNELS.join(' ')} -> pos = at + d)`)\n return lines.join('\\n')\n}\n\n/**\n * EVERYTHING a model needs to write a whole program: both language references (static) + the scene map\n * derived from the Doc. It is the bundle, not the map — if you only want the names this scene can\n * reference (because you already inject the references yourself), that is **`docToManifest(doc)`**, and\n * calling this instead ships the cards a second time.\n *\n * The DRAWING card is included by default. Handed the behavior card alone, a model asked for decor\n * invents a shapes grammar — and what it invents does not compile. Pass `{ drawing: false }` when the\n * model only edits behavior and the prompt budget is tight.\n */\nexport function llmContext(doc: Doc, opts: { drawing?: boolean } = {}): string {\n const cards = opts.drawing === false ? languageCard() : `${languageCard()}\\n\\n${drawingCard()}`\n return `${cards}\\n\\n${docToManifest(doc)}`\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// languageCard.ts — TERSE reference of FlatInk Script, \"system-prompt\" sized.\n//\n// Single source of truth to steer an LLM (or a human in a hurry): condensed\n// grammar + built-ins, ~1k tokens. The function/constant/channel lists are\n// INTERPOLATED from expr/timeline/stdlib → never out of sync with the real engine.\n// To be paired with `docToManifest` (manifest.ts) for the names specific to a scene.\n// ─────────────────────────────────────────────────────────────────────────────\nimport { STD_CONSTANTS, STD_FUNCTIONS } from '@flatkit/engine/expr'\nimport { EXPR_CHANNELS } from '@flatkit/engine/timeline'\nimport { PACKAGES } from '@flatkit/engine/stdlib'\n\n/** Language reference card (static, kept in sync with the engine via STD_*). */\nexport function languageCard(): string {\n return `# FlatInk Script — reference\nNumbers only (0 = false, anything else = true). No string type (only event/label/asset names in quotes). Comment: // to end of line.\nOne statement per line — a newline ends the statement (write \\`x = 1\\` then \\`y = 2\\` on separate lines, not \\`x = 1 y = 2\\`).\n\n## Objects\nobject \"Name\" { … } attaches behavior BY NAME. The name must be a group / instance / text / image — the only things that carry a pose.\nA SHAPE (\\`rect … as \"N\"\\`) or a LAYER cannot be animated: wrap the shape in \\`group \"N\" { layer \"art\" { … } }\\`. (Naming one is a compile error.)\nOpacities MULTIPLY down the tree — do not set \\`opacity 0\\` on the shape to hide it at rest, or the group's fade-in stays invisible.\n\n## Events (attach to an object or to the scene)\nwhen loaded { } // once, on start\nevery frame { } // every frame\nat frame N { } // when the playhead reaches frame N\nwhen clicked|hovered|unhovered|pressed|dragged|released|held { }\n\n## Actions\nplay · pause · go to frame N [and play|and pause] · go to \"label\"\nname = expr // set a variable\narr[i] = expr // write an array slot\narr = fill(n, v) // replace a WHOLE array (the only array-valued assignment; expressions are scalar)\nif cond { } else { } · repeat N times { } · repeat i from A to B { }\nmyProc() · send \"event\"[, expr | text(\"id\") | { a = expr, b … }] · sound \"assetId\"\n\n## Expressions (drive a channel, or compute in an action)\nchannel = expr channels: ${EXPR_CHANNELS.join(' ')} (expression wins over keyframes)\ndx = expr · dy = expr // ADDITIVE offset: final pos = at + (dx, dy) — oscillate AROUND the anchor (dx = 30*sin(time)); absolute x/y REPLACE at\nrotationDeg = expr // sugar for rotation = rad(expr) — author angles in DEGREES (rotation & sin/cos/atan2 are RADIANS)\noperators: + - * / % < > <= >= == != && || ! cond ? a : b\ncontext: time frame clock value · mouse.x mouse.y mouse.dx mouse.dy · keys.Space keys.ArrowLeft … (keys are 1/0, use directly: keys.Space ? … : …)\n time WRAPS every durationFrames (2.5 s by default) — clock is MONOTONE. Timestamps you capture and compare later MUST use clock\n (\\`when wrong { shown = clock }\\` + \\`opacity = pulse(shown, 4)\\`), or the ramp replays on every loop.\nName.x Name.y Name.rotation Name.scaleX Name.scaleY Name.opacity // any named object (identifier name), live on-screen value (read-only)\nself.x self.y self.rotation self.scaleX self.scaleY self.opacity // the object's own channels, in its bindings (no mirror variable)\n\n## Spaces (local vs world)\nself & channels (x, y, rotation…) = LOCAL (relative to parent — what x = … sets). Name.x, mouse.x = WORLD (the stage).\nAt the scene root, local = world (the common case → nothing to think about). If an object is NESTED in a group and you\nrelate it to a world position, convert: toLocalX(x, y) toLocalY(x, y) (world → your space) · toGlobalX/Y (your space → world).\nconstants: ${STD_CONSTANTS.join(' ')}\nfunctions: ${STD_FUNCTIONS.join(' ')}\n\n## Direct manipulation (interactors)\ndrag x, y // object follows the pointer while held → writes vars x, y (bind them: x = vx, y = vy)\n{ enabled <expr> } gates the GESTURE only — when/pressed/released/clicked STILL fire. Guard the body: when released { if done == 0 { … } }\ndragX vx · dragY vy // single-axis\ndrag x, y { confine to Zone snap 10 } // bound to a named object's box · grid snap\nturn a around cx,cy { snap 15 } // dial/knob → a = pivot→cursor angle in RADIANS (pair: rotation = a)\nturnDeg a around cx,cy { snap 15 } // same in DEGREES (pair: rotationDeg = a) · snap is degrees on both\ntrace p along Route { tolerance 30 step 40 } // follow a named guide → p = 0..1 by ARC LENGTH (pair: draw \"p\"). step = a TRACE, not a cursor: without it one press near the finish reports 1\nreveal c { brush 32 grain 8 erase cells grid } // scratch → c = cleared fraction; brush = finger, grain = resolution; erase = the runtime rubs the target out; grid[row*cols+col] = 1 says WHERE\nwhen dropped on Zone { … } // fires on release when the object's center is inside the named zone\n\n## Declarations\nvar name = 0 · var arr = fill(n, v) · var arr = [a, b, c] // document state: readable EVERYWHERE (bindings included)\nlet name = 0 // the same thing at the top level of a program; inside a scope it stays local\nfn name(a, b) = expr // value function (use in expressions)\nfn name() { … } // procedure (block of actions)\neach \"Symbol\" as i { opacity = data[i] } // bind every instance of a symbol (i = index)\nuse \"package\" packages: ${PACKAGES.join(' ')} // OPTIONAL: calling a package function imports it automatically\n\n## Example\nvar score = 0\nvar lit = 0\nevery frame { score = score + 1 }\nobject \"Ball\" {\n when clicked { lit = 1 }\n opacity = lit == 1 ? 1 : 0.4 // a binding READS the document's state\n rotation = atan2(Target.y - self.y, Target.x - self.x) // aim at another object by name\n}`\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// drawingCard.ts — TERSE reference of the DRAWING half of FlatInk, \"system-prompt\" sized.\n//\n// `languageCard` covers BEHAVIOR (events, channels, expressions) and not one word of the composition:\n// no shapes, no paints, no filters. An integrator handing that card to a model and asking for decor was\n// handing it a reference with nothing about drawing — so the model guessed, and what a model guesses in\n// a DSL does not compile. The two cards are complements: pair them (plus `docToManifest` for the names\n// of a particular scene) whenever a model has to produce a whole `.flatink`.\n//\n// Every ```flatink example below is COMPILED by drawingCard.test.ts. A reference that is copied drifts;\n// one that is compiled cannot. When the grammar moves, that test goes red rather than this card going\n// quietly wrong.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Drawing reference card (composition: shapes, paints, filters, text, clipping). */\nexport function drawingCard(): string {\n return `# FlatInk — drawing (the \\`scene { … }\\` half)\n\nThe unit is the LAYER: \\`layer \"name\" { … }\\`, stacked bottom to top. A layer holds shapes, text, images\nand groups (which nest their own layers). Coordinates are PIXELS in the parent's frame — never percentages.\n\n## Shapes\ncircle <cx> <cy> <r>\nellipse <cx> <cy> <rx> <ry>\nrect <x> <y> <w> <h> [<r>] // r = rounded corners (or <rx> <ry> for distinct)\npath \"M0 0 C40 -20 80 20 120 0 Z\" // raw SVG path data — total freedom\ncircle 100 100 40 as \"Ring\" // name it (right after the geometry) → addressable\n\n## Paint\nfill #rrggbb | #rrggbbaa · nofill\nfill linear(<angle>, 0:#…, 1:#…) // angle: 0 = →, 90 = ↓ ; stops are offset:color\nfill radial(<cx>, <cy>, <r>, 0:#…, 1:#…) // cx/cy/r as 0..1 of the box\nstroke <paint> <width> [cap butt|round|square] [join miter|round|bevel] [miter <n>] [dash a,b]\ndraw <0..1> [from <0..1>] // how much of the OUTLINE is stroked, by ARC LENGTH; \"quoted\" = per-frame expression\nopacity <0..1> // opacities MULTIPLY down the tree\n\n## Filters — on any item, no wrapper group needed\nfilter glow <blur> <color> · filter shadow <dx> <dy> <blur> <color>\nfilter blur <radius> · filter adjust <brightness> <contrast> <saturate> <hue>\n\n## Text\ntext \"…\" at <x>,<y> box <w> <h> font \"sans-serif\" size <n> align center line 1.2 color #… [bold] [italic] [wrap]\ntext \"…\" along \"<shapeId>\" align center start 0.5 // laid along a named shape's curve\nWord-wrap is OPT-IN: without \\`wrap\\`, only an explicit \\\\n breaks a line.\n\n## Images\nimage \"<assetId>\" <w> <h> at <x>,<y> // the asset is declared at the top: asset \"logo\" \"logo.svg\" image\n\n## Clipping\ngroup \"Name\" at x,y clip <x> <y> <w> <h> { … } // rectangular cut, in the group's LOCAL coordinates\nmask layer \"Name\" { <shapes> layer \"c\" { … } } // arbitrary shape: the mask's matter clips its child layers\n\n## The five rules that decide whether it compiles\n1. WORD ORDER IS FIXED: content → \\`as \"…\"\\` → \\`at …\\` → style. So \\`text \"Hi\" at 10,10 box 200 40\\`,\n NEVER \\`text \"Hi\" box 200 40 at 10,10\\`. A shape names itself right after its geometry.\n Stroke options (\\`cap\\`/\\`join\\`/\\`miter\\`/\\`dash\\`) belong to the STROKE and follow it directly:\n \\`nofill stroke #888 2 dash 6,5\\`, not \\`stroke #888 2 nofill dash 6,5\\`.\n2. A COMMENT STARTS WITH \\`//\\`. A \\`#\\` opens a COLOR.\n3. ONE STATEMENT PER LINE.\n4. Anything you intend to ANIMATE must be a \\`group \"Name\" at x,y { layer \"c\" { … } }\\`. An \\`object\\`\n block aimed at a shape or a layer is a compile ERROR — shapes are baked material and carry no pose.\n5. A group's children are positioned RELATIVE to it. Draw them around 0,0 and place the group.\n\n## Examples\n\nA sky and a ground, in two gradients:\n\n\\`\\`\\`flatink\nsize 960 540\nscene {\n layer \"sky\" {\n rect 0 0 960 540 fill linear(90, 0:#1b2a4a, 1:#4a6fa5)\n ellipse 780 90 70 70 fill radial(0.5, 0.5, 0.5, 0:#ffe9a8, 1:#ffe9a800)\n }\n layer \"ground\" {\n path \"M0 430 C240 400 420 460 960 415 L960 540 L0 540 Z\" fill #2e4b34 opacity 0.85\n }\n}\n\\`\\`\\`\n\nA line-art silhouette and a drop shadow:\n\n\\`\\`\\`flatink\nsize 200 400\nscene {\n layer \"tree\" {\n path \"M60 300 L60 180 M60 220 L20 170 M60 230 L100 180\" nofill stroke #23301f 8 cap round\n circle 60 150 60 fill #3f6b3a filter shadow 0 6 12 #00000055\n }\n}\n\\`\\`\\`\n\nA group — the only shape a behavior block can animate:\n\n\\`\\`\\`flatink\nsize 480 320\nscene {\n layer \"life\" {\n group \"Cloud\" at 240,120 {\n layer \"c\" {\n ellipse 0 0 70 26 fill #ffffff opacity 0.22\n ellipse 46 -10 44 22 fill #ffffff opacity 0.18\n }\n }\n }\n}\n\nobject \"Cloud\" {\n dx = 30 * sin(clock)\n}\n\\`\\`\\`\n\nA panel, text, and a clipped porthole:\n\n\\`\\`\\`flatink\nsize 960 540\nscene {\n layer \"panel\" {\n rect 40 40 300 90 24 fill #10141c99 stroke #ffffff33 2\n text \"Workshop\" at 60,66 box 260 40 font \"sans-serif\" size 26 color #f2f6ff\n group \"Porthole\" at 700,300 clip -60 -60 120 120 {\n layer \"c\" { circle 0 0 90 fill linear(0, 0:#0b3d5c, 1:#0f6f92) }\n }\n }\n}\n\\`\\`\\``\n}\n","// @flatkit/compiler -- the FlatInk language and compiler.\n//\n// Parses FlatInk Script (the .flatink DSL) and compiles a program plus its assets into a .flatpack:\n// a playable `Doc` (JSON, with the material already baked). Also ships the `flatc` CLI, via its `bin` -- NOT from this entry, which stays free of Node builtins.\n//\n// The language layer (DSL parser/printer, .flat format) lives in @flatkit/engine and is re-exported\n// here so the compiler package is a single coherent entry point.\n\n// --- Compile a program (+ assets) into a playable .flatpack Doc ---------------\nexport { compileFlatpack, packToJSON, type MediaMap } from './compile'\n\n// --- Check a program the way the CLI does (source in, diagnostics out) --------\nexport { checkProgram, programDiagnostics, formatDiagnostics, applyFixes, repairLoop, type CheckDiagnostic, type CheckOptions, type CheckResult } from './check'\nexport type { TextEdit } from '@flatkit/engine/dsl'\n\n// --- Static analysis: lint a program / a whole Doc ----------------------------\nexport { lint, lintReport, localVariables, type LintContext } from './lint'\nexport {\n lintDoc, lintDocReport, docHasErrors, docLintContext, allScopeVariables,\n scopeProgram, docStructureWarnings, docLayoutWarnings,\n} from './programDoc'\n\n// --- Manifest / LLM context for a Doc -----------------------------------------\nexport { manifestObjects, manifestEvents, docToManifest, llmContext, type ManifestObject } from './manifest'\n\n// --- The reference cards: behavior (languageCard) and composition (drawingCard) -\nexport { languageCard } from './languageCard'\nexport { drawingCard } from './drawingCard'\n\n// --- Scope-program helpers (split/join the per-object behavior blocks) ---------\nexport { splitScopeProgram, scopeRegions, formatObjectBlock, joinScopeProgram } from './scopeProgram'\n\n// --- The flatc CLI entry point (also wired as the `flatc` bin) -----------------\n// `run` (the CLI entry) is deliberately NOT re-exported. It lives in a module that imports `fs`/`path` at\n// the top, so re-exporting it put Node builtins in the root's chunk graph -- and a browser bundle then\n// fails at NAME RESOLUTION (`\"extname\" is not exported by \"__vite-browser-external\"`), before tree-shaking\n// can drop the unused symbol. The root's job is the pure helpers a service or a browser needs\n// (`checkProgram`, `languageCard`, `drawingCard`, `docToManifest`); the CLI's job is the `bin`, which\n// imports `./cli/flatc` directly. `scripts/check-pack.mjs` walks the built chunk graph to keep it that way.\n\n// --- The language layer, re-exported from the engine for convenience ----------\nexport { parseUnits, printUnits } from '@flatkit/engine/dsl'\nexport {\n parseProgram, printProgram, parseProgramFull, printProgramFull,\n parseFlat, parseFlatLib, exportFlatProject,\n} from '@flatkit/engine/flatFormat'\n"],"mappings":"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","names":["EXPR_CHANNELS","EXPR_CHANNELS"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flatkit/compiler",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.1",
|
|
4
4
|
"description": "The FlatInk language (parser + AST) and compiler (.flatink → .flatpack). Ships the flatc CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Zwyk Studio",
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
"docs"
|
|
58
58
|
],
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@flatkit/
|
|
61
|
-
"@flatkit/
|
|
62
|
-
"@flatkit/
|
|
60
|
+
"@flatkit/engine": "0.35.1",
|
|
61
|
+
"@flatkit/player": "0.35.1",
|
|
62
|
+
"@flatkit/types": "0.35.1"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"skia-canvas": "^3.0.8"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/scopeProgram.ts","../src/lint.ts","../src/programDoc.ts","../src/docWalk.ts","../src/check.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// scopeProgram.ts — the \"unified file\" of a scope (the Scene, or a Symbol).\n//\n// Vision: one file = one scope. All the code of a scope fits in ONE text:\n// var … (global variables, root only)\n// when loaded {} (lifecycle of the scope's timeline)\n// every frame {}\n// object \"name\" {} (one block per scripted object of the scope)\n//\n// This is the `.flatink` structure WITHOUT the geometry (which stays visual). This module\n// ONLY deals with the text: splitting the `object` blocks from the rest, and formatting a block.\n// The wiring to the Doc (a single commit) lives in the store, which reuses these functions\n// + scriptDoc/dsl. Pure, no DOM, testable.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** End of the block opened at `open` (index of the matching `}`), ignoring strings and comments. -1 if unclosed. */\nfunction matchBrace(s: string, open: number): number {\n let depth = 0\n for (let i = open; i < s.length; i++) {\n const c = s[i]\n if (c === '\"') { i++; while (i < s.length && s[i] !== '\"') { if (s[i] === '\\\\') i++; i++ }; continue }\n if (c === '/' && s[i + 1] === '/') { while (i < s.length && s[i] !== '\\n') i++; continue }\n if (c === '{') depth++\n else if (c === '}') { depth--; if (depth === 0) return i }\n }\n return -1\n}\n\n/** Splits a scope file: the `object \"name\" { … }` blocks on one side, the REST (var + lifecycle) on the other. */\nexport function splitScopeProgram(text: string): { rest: string; objects: { name: string; body: string }[] } {\n let rest = ''\n let i = 0\n const objects: { name: string; body: string }[] = []\n while (i < text.length) {\n const m = /object\\s+\"((?:[^\"\\\\]|\\\\.)*)\"\\s*\\{/.exec(text.slice(i))\n if (!m) { rest += text.slice(i); break }\n const start = i + m.index\n rest += text.slice(i, start)\n const ob = start + m[0].length - 1 // the opening brace\n const oc = matchBrace(text, ob)\n if (oc < 0) { rest += text.slice(start); break } // unclosed block → left to the rest (diagnostic downstream)\n objects.push({ name: m[1].replace(/\\\\(.)/g, (_, c) => (c === 'n' ? '\\n' : c)), body: text.slice(ob + 1, oc) })\n i = oc + 1\n }\n return { rest, objects }\n}\n\n/** LINTABLE regions of a scope file (the \"rest\" gaps + the `object` bodies), with their\n * 1-based start line in the original text — to lint each piece as pure DSL and\n * reproject the positions. The `object` keyword and its braces are NOT DSL: we skip them. */\nexport function scopeRegions(text: string): { body: string; line: number }[] {\n const lineAt = (off: number) => text.slice(0, off).split('\\n').length\n const regions: { body: string; line: number }[] = []\n let i = 0\n let restStart = 0\n while (i < text.length) {\n const m = /object\\s+\"((?:[^\"\\\\]|\\\\.)*)\"\\s*\\{/.exec(text.slice(i))\n if (!m) break\n const start = i + m.index\n const gap = text.slice(restStart, start)\n if (gap.trim()) regions.push({ body: gap, line: lineAt(restStart) })\n const ob = start + m[0].length - 1\n const oc = matchBrace(text, ob)\n if (oc < 0) break\n regions.push({ body: text.slice(ob + 1, oc), line: lineAt(ob + 1) })\n i = oc + 1\n restStart = i\n }\n const tail = text.slice(restStart)\n if (tail.trim()) regions.push({ body: tail, line: lineAt(restStart) })\n return regions\n}\n\nconst esc = (s: string) => s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n')\nconst indent = (body: string) => body.split('\\n').map((l) => (l.trim() ? ' ' + l : l)).join('\\n')\n\n/** Formats an `object \"name\" { … }` block (body already in DSL). */\nexport function formatObjectBlock(name: string, body: string): string {\n const inner = body.trim()\n return `object \"${esc(name)}\" {\\n${inner ? indent(inner) + '\\n' : ''}}`\n}\n\n/** Assembles a scope file: rest (var + lifecycle) then the object blocks, separated by a blank line. */\nexport function joinScopeProgram(rest: string, objects: { name: string; body: string }[]): string {\n const parts: string[] = []\n if (rest.trim()) parts.push(rest.trim())\n for (const o of objects) if (o.body.trim()) parts.push(formatObjectBlock(o.name, o.body))\n return parts.length ? parts.join('\\n\\n') + '\\n' : ''\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// lint.ts — linter for the FlatInk Script language (batch L3).\n//\n// Builds on the parser (dsl.ts) for syntax errors + positions, then adds\n// SEMANTIC validation, ~free and PURE:\n// • each expression is compiled (compileExpr) → expression syntax error;\n// • referenced functions / member objects / identifiers are checked against\n// the standard environment (expr.ts) + the known variables → \"unknown\";\n// • `go to \"label\"` is checked against the set of known labels.\n//\n// Tolerant and kid-friendly: a variable is \"known\" if it is declared\n// (`let`) OR simply assigned (`x = …`) somewhere in the source, or provided\n// by the caller (document global variables). Labels are only checked\n// if the caller provides their list (otherwise we don't know the universe).\n// ─────────────────────────────────────────────────────────────────────────────\nimport { analyzeExpr, STD_CONSTANTS, STD_FUNCTIONS, STD_IDS, STD_OBJECTS } from '@flatkit/engine/expr'\nimport { packageFunctionNames } from '@flatkit/engine/stdlib'\nimport { parseUnits, type Diagnostic, type ScriptUnit, type TextEdit } from '@flatkit/engine/dsl'\nimport type { Action } from '@flatkit/engine/actions'\n\nexport type LintContext = {\n /** Known variables in addition to those declared/assigned in the source. */\n variables?: Iterable<string>\n /** Known labels (timeline). Absent = we don't check `go to \"…\"`. */\n labels?: Iterable<string>\n /** Known functions in addition to those defined in the source. */\n functions?: Iterable<string>\n /** Scene objects referenceable by name (`Hero.x`) — in addition to mouse/keys. */\n objects?: Iterable<string>\n}\n\n/** Collects the names of ASSIGNED variables (setVar) + loop vars, inside action bodies. */\nfunction collectAssigned(actions: Action[], into: Set<string>): void {\n for (const a of actions) {\n if (a.do === 'setVar') into.add(a.name)\n else if (a.do === 'if') {\n collectAssigned(a.then, into)\n if (a.else) collectAssigned(a.else, into)\n } else if (a.do === 'repeat') collectAssigned(a.body, into)\n else if (a.do === 'repeatRange') { into.add(a.var); collectAssigned(a.body, into) } // i is known in the body\n }\n}\n\n/** Locally known variables: `let` declarations + every assigned variable. */\nexport function localVariables(units: ScriptUnit[]): Set<string> {\n const vars = new Set<string>()\n for (const u of units) {\n if (u.kind === 'declare') vars.add(u.name)\n else if (u.kind === 'event' || u.kind === 'frameActions') collectAssigned(u.body, vars)\n else if (u.kind === 'each') vars.add(u.as) // the index is known in the each bindings\n else if (u.kind === 'interactor') { if (u.varX) vars.add(u.varX); if (u.varY) vars.add(u.varY) } // drag writes these variables\n else if (u.kind === 'drop') collectAssigned(u.body, vars)\n else if (u.kind === 'func') { for (const p of u.func.params) vars.add(p); if (u.func.kind === 'proc') collectAssigned(u.func.body, vars) } // params + assignments\n }\n return vars\n}\n\n/** Detects a `text(` call (whole word) in an expression → only allowed in a `send` payload. */\nconst TEXT_CALL = /\\btext\\s*\\(/\n\n/** A bare assignment (`x =`, `a[i] =`; NOT ==/<=/>=/!=) left inside an expression: the tell-tale of a\n * SECOND statement crammed onto one line (FlatInk ends a statement at the newline, so it got swallowed). */\nconst SECOND_ASSIGN = /[\\w\\]]\\s*=(?![=])/\n\n/** Same tell-tale for the statements that are NOT assignments — `score = score + 1 send \"correct\", 1`\n * swallowed the `send` and reported a bewildering `unexpected character \"\"\"` instead. All of these are\n * RESERVED words (cf. ident.ts), so none can legitimately appear as a name inside an expression. */\nconst SECOND_ACTION = /\\b(send|play|pause|sound|set|go|repeat)\\b/\n\n/** Where the swallowed SECOND statement begins inside the expression text, or -1. `send`-style actions\n * start at their keyword; a swallowed assignment starts at the identifier its `=` belongs to. */\nfunction splitPoint(text: string): number {\n const act = SECOND_ACTION.exec(text)\n if (act) return act.index\n const asg = SECOND_ASSIGN.exec(text)\n if (!asg) return -1\n const upTo = text.slice(0, asg.index + 1) // the char before `=` is the last of the identifier\n const id = /[A-Za-z_$][\\w$]*\\s*$/.exec(upTo)\n return id ? upTo.length - id[0].length : -1\n}\n\n/** The `fix` half of the two-statements diagnostic: replace the expression text with its two lines. */\nfunction withSplit(s: { text: string; line: number; col: number }): { fix?: TextEdit } {\n const at = splitPoint(s.text)\n if (at <= 0) return {}\n const left = s.text.slice(0, at).trimEnd()\n const right = s.text.slice(at).trim()\n if (!left || !right) return {}\n return { fix: { line: s.line, col: s.col, endLine: s.line, endCol: s.col + s.text.length, replacement: `${left}\\n${right}` } }\n}\n\n/** Analyze a DSL source and return all diagnostics (syntax + semantic). */\nexport function lint(src: string, ctx: LintContext = {}): Diagnostic[] {\n const { units, diagnostics, sites } = parseUnits(src)\n const out: Diagnostic[] = [...diagnostics]\n\n const variables = localVariables(units)\n for (const v of ctx.variables ?? []) variables.add(v)\n const knownIds = new Set<string>([...STD_IDS, ...STD_CONSTANTS, ...variables])\n const knownFns = new Set(STD_FUNCTIONS)\n knownFns.add('velocity') // valid inside a spring/smooth target (resolved by the modifier advance); NOT a stdlib\n for (const u of units) {\n if (u.kind === 'func') knownFns.add(u.func.name) // user-defined functions\n else if (u.kind === 'use') for (const name of packageFunctionNames(u.name)) knownFns.add(name) // package functions (bare + qualified)\n }\n for (const f of ctx.functions ?? []) knownFns.add(f)\n const knownObjs = new Set(STD_OBJECTS)\n for (const o of ctx.objects ?? []) knownObjs.add(o) // scene objects (Hero.x…)\n const labels = ctx.labels ? new Set(ctx.labels) : null\n\n for (const s of sites) {\n if (s.kind === 'expr') {\n // `text(…)` is valid ONLY as a `send` payload (consumed by the parser, never\n // exposed as an expression site). Seeing it here = out-of-context use → dedicated error.\n if (TEXT_CALL.test(s.text)) {\n out.push({ line: s.line, col: s.col, message: 'text(\"…\") is only allowed as an argument to \"send\"' })\n continue\n }\n const a = analyzeExpr(s.text)\n if (!a.ok) {\n // #1 footgun: two statements on one line. The 2nd one got swallowed into this expression → a\n // cryptic \"unexpected character = / \\\"\". Detect the leftover statement and NAME it, so the rule\n // (\"one action per line\") is visible from the message rather than only from the docs.\n const leftover = SECOND_ASSIGN.test(s.text) ? 'an assignment' : SECOND_ACTION.test(s.text) ? `\\`${SECOND_ACTION.exec(s.text)![1]} …\\`` : ''\n const message = leftover\n ? `two statements on one line — ${leftover} was swallowed into the expression before it. FlatInk ends a statement at the NEWLINE: put each action on its own line.`\n : `invalid expression: ${a.error}`\n // The repair is mechanical: the boundary is where the SECOND statement starts, and the parser\n // already located it to name it. Split there; anything else about the line stays untouched.\n out.push({ line: s.line, col: s.col, message, ...(leftover ? withSplit(s) : {}) })\n continue\n }\n for (const fn of a.refs.calls) if (!knownFns.has(fn)) out.push({ line: s.line, col: s.col, message: `unknown function \"${fn}\"` })\n for (const o of a.refs.members)\n if (!knownObjs.has(o)) out.push({ line: s.line, col: s.col, message: `unknown object \"${o}\" (expected: ${[...knownObjs].join(', ')})` })\n for (const id of a.refs.ids)\n if (!knownIds.has(id))\n out.push({ line: s.line, col: s.col, message: `unknown variable \"${id}\"${variables.size ? '' : ' — declare it with \"let\"'}` })\n } else if (labels && !labels.has(s.name)) {\n out.push({ line: s.line, col: s.col, message: `unknown label \"${s.name}\"` })\n }\n }\n\n return out.sort((a, b) => a.line - b.line || a.col - b.col)\n}\n\n/**\n * Lint report ready to feed back to a generator (LLM/CLI): `''` = no issue (the code passes),\n * otherwise one `line:col: message` line per diagnostic. Primitive of the \"generate → lint →\n * fix\" loop: the language fits in few tokens, robustness comes from this feedback, not from context.\n */\nexport function lintReport(src: string, ctx: LintContext = {}): string {\n return lint(src, ctx).map((d) => `${d.line}:${d.col}: ${d.message}`).join('\\n')\n}\n","// -----------------------------------------------------------------------------\n// programDoc.ts — PURE bridge Doc <-> \"scope program\" (text) + lint of a whole Doc.\n//\n// Both the editor AND the CLI need to rebuild the DSL text of a scope (to display it,\n// or to lint it) and to assemble the lint context (variables/labels/functions/objects)\n// FROM a Doc — without depending on the React store. Everything lives here, pure and testable:\n// • `scopeProgram` : Doc fragments -> program text of a scope (round-trip via printUnits);\n// • `docLintContext` : Doc + scope -> LintContext (known names);\n// • `lintDoc` / report : semantic lint of ALL the scopes of a Doc (scene + symbols).\n// -> the CLI gains a `flatc --check`, the editor stops duplicating the logic.\n// -----------------------------------------------------------------------------\nimport type { Doc, EditFrame, Group, Instance } from '@flatkit/types'\nimport { printUnits, type Diagnostic } from '@flatkit/engine/dsl'\nimport { joinScopeProgram, scopeRegions } from './scopeProgram'\nimport { functionsToUnits, importsToUnits, objectToUnits, timelineToUnits, variablesToUnits } from '@flatkit/engine/scriptDoc'\nimport { contextLayers, getScopeTimeline, isContainer, isGroup, isInstance, isText, isImage, isPoseable, isRegion } from '@flatkit/engine/layers'\nimport { importedFunctions } from '@flatkit/engine/stdlib'\nimport { EXPR_CHANNELS, OFFSET_CHANNELS } from '@flatkit/engine/timeline'\nimport { objectNames } from '@flatkit/engine/sceneRefs'\nimport { behaviorRegions } from '@flatkit/engine/flatFormat'\nimport { itemBBox, itemBoundsById, dropZoneBounds, transformBBox, revealGrid } from '@flatkit/engine/groups'\nimport { IDENTITY, apply, compose } from '@flatkit/engine/transform'\nimport { makePathSampler } from '@flatkit/engine/path'\nimport { bboxIntersects } from '@flatkit/engine/bbox'\nimport { lint, localVariables, type LintContext } from './lint'\nimport { forEachAction, forEachExpression } from './docWalk'\nimport { parseUnits } from '@flatkit/engine/dsl'\nimport type { Image, Item, Layer, ParamDef, Region, SymbolDef, Text, Transform } from '@flatkit/types'\n\n/** Rebuilds the \"program\" text of a scope (imports + variables + functions + scene cycle\n * + one `object \"Name\" { … }` block per scripted container with a unique name). Pure, round-trip via printUnits. */\nexport function scopeProgram(doc: Doc, editPath: EditFrame[] = []): string {\n const atRoot = editPath.length === 0\n const items = contextLayers(doc, editPath).flatMap((l) => l.items)\n const nameCount = new Map<string, number>()\n for (const it of items) if (isContainer(it) && it.name) nameCount.set(it.name, (nameCount.get(it.name) ?? 0) + 1)\n const scripted = (it: Group | Instance) => !!doc.interactions?.some((i) => i.targetId === it.id) || !!doc.interactors?.some((i) => i.targetId === it.id) || !!(it.expressions && Object.keys(it.expressions).length)\n const objects = items\n .filter((it): it is Group | Instance => isContainer(it) && !!it.name && nameCount.get(it.name) === 1 && scripted(it))\n .map((it) => ({ name: it.name, body: printUnits(objectToUnits(it.id, doc.interactions, it.expressions, doc.interactors)) }))\n const imports = atRoot ? printUnits(importsToUnits(doc.imports)) : ''\n // A local package (`use \"physics\"` -> physics.flatink) is inlined TWICE into doc.functions: `tick` and the\n // qualified alias `physics.tick` (so both call forms resolve). The alias is not authored source and has NO\n // syntax (`fn physics.tick(s) = …` does not parse) -> never re-emit it, or the reconstructed program fails\n // to parse and `--check` reports phantom errors. The alias stays in `doc.functions`, so `docLintContext`\n // still knows `physics.tick` as a callable name.\n const funcs = atRoot ? printUnits(functionsToUnits((doc.functions ?? []).filter((f) => !f.name.includes('.')))) : ''\n const globals = atRoot ? printUnits(variablesToUnits(doc.variables)) : ''\n const scene = printUnits(timelineToUnits(getScopeTimeline(doc, editPath)))\n const head = [imports, globals, funcs, scene].filter((t) => t.trim()).join('\\n\\n')\n return joinScopeProgram(head, objects)\n}\n\n/** Lint context of a scope: known names (variables, labels, functions, objects) drawn from the Doc.\n * `extraVars` = variables assigned in the OTHER scopes (FlatInk variables are GLOBAL -> known\n * everywhere; avoids a false \"unknown variable\" on a var written elsewhere, e.g. generated by `match`). */\nexport function docLintContext(doc: Doc, editPath: EditFrame[] = [], extraVars?: Iterable<string>): LintContext {\n return {\n // A symbol's own `params` (and state params) are injected into its instance scope at runtime, so they are\n // valid variables in ITS `expr` -- add them, but ONLY to that symbol's scope (resolved from `editPath`),\n // never globally, so a param named in symbol A can't mask a real typo of the same name in symbol B.\n variables: [...Object.keys(doc.variables ?? {}), ...(extraVars ?? []), ...scopeSymbolParams(doc, editPath)],\n labels: (getScopeTimeline(doc, editPath)?.labels ?? []).map((l) => l.name),\n functions: [...(doc.functions ?? []).map((f) => f.name), ...importedFunctions(doc.imports).map((f) => f.name)],\n objects: objectNames(contextLayers(doc, editPath)),\n }\n}\n\n/** Names exposed as variables by the symbol of `editPath` (its `params` + state params), or `[]` for the\n * scene scope / an unresolved path. Mirrors the per-instance scope the runtime and `--preview` build. */\nfunction scopeSymbolParams(doc: Doc, editPath: EditFrame[]): string[] {\n const frame = [...editPath].reverse().find((f): f is Extract<EditFrame, { kind: 'symbol' }> => f.kind === 'symbol')\n const sym = frame ? doc.symbols.find((s) => s.id === frame.symbolId) : undefined\n if (!sym) return []\n return [...(sym.params ?? []).map((p) => p.name), ...(sym.states ?? []).map((s) => s.param)]\n}\n\n/** All the scopes of a Doc: the scene (root) + each symbol of the library. */\nfunction scopes(doc: Doc): { label: string; editPath: EditFrame[] }[] {\n return [{ label: 'scene', editPath: [] }, ...doc.symbols.map((s) => ({ label: s.name, editPath: [{ kind: 'symbol' as const, symbolId: s.id, name: s.name }] }))]\n}\n\n/** Union of the variables ASSIGNED in ALL the scopes (scene + symbols). FlatInk variables are\n * global -> a var written in one scope is legitimate in the others (cross-scope reads). */\nexport function allScopeVariables(doc: Doc): string[] {\n const set = new Set<string>()\n for (const { editPath } of scopes(doc))\n for (const r of scopeRegions(scopeProgram(doc, editPath)))\n for (const v of localVariables(parseUnits(r.body).units)) set.add(v)\n return [...set]\n}\n\n/** Readable name of an item by id (for the messages). */\nfunction itemNameById(doc: Doc, id: string): string | null {\n let found: string | null = null\n const walk = (layers: { items: import('@flatkit/types').Item[] }[]) => {\n for (const l of layers) for (const it of l.items) {\n if (found) return\n if ('name' in it && it.id === id) { found = it.name ?? null; return }\n if (isGroup(it)) walk(it.layers)\n }\n }\n walk(doc.layers)\n return found\n}\n\nconst escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\-]/g, '\\\\$&')\n\n/** Value functions reachable in this Doc whose body reads the LOOP-WRAPPED `time`, directly or through\n * another such function. Only `kind: 'value'` matters — a `proc` is not callable from a channel expression.\n * Fixpoint, so `fn a(t) = b(t)` inherits from `b`. Qualified aliases (`feedback.pulse`) are kept: an author\n * may call either form. */\nfunction functionsReadingTime(doc: Doc): string[] {\n const defs = [...(doc.functions ?? []), ...importedFunctions(doc.imports)].filter((f) => f.kind === 'value')\n const reads = new Set<string>()\n for (;;) {\n const before = reads.size\n for (const f of defs) {\n if (reads.has(f.name)) continue\n const body = f.expr\n // A parameter NAMED `time` would shadow the runtime scalar — then the body's `time` is just an argument.\n if (!f.params.includes('time') && /\\btime\\b/.test(body)) { reads.add(f.name); continue }\n for (const other of reads) if (new RegExp(`\\\\b${escapeRe(other)}\\\\s*\\\\(`).test(body)) { reads.add(f.name); break }\n }\n if (reads.size === before) return [...reads]\n }\n}\n\n/** Top-level arguments of every `name(…)` call in `src`. Depth-aware, so a nested call keeps its own\n * commas: `pulse(max(a, 0), 1)` reads as two arguments, not three. */\nfunction callArguments(src: string, name: string): string[][] {\n const out: string[][] = []\n const re = new RegExp(`(?<![\\\\w.])${escapeRe(name)}\\\\s*\\\\(`, 'g')\n let m: RegExpExecArray | null\n while ((m = re.exec(src))) {\n const args: string[] = []\n let depth = 1\n let start = m.index + m[0].length\n let i = start\n for (; i < src.length; i++) {\n const c = src[i]\n if (c === '(') depth++\n else if (c === ')') { depth--; if (depth === 0) break }\n else if (c === ',' && depth === 1) { args.push(src.slice(start, i)); start = i + 1 }\n }\n args.push(src.slice(start, i))\n out.push(args.map((a) => a.trim()))\n }\n return out\n}\n\n/** Which argument of a feedback function is an INSTANT (a timestamp compared against `clock`):\n * `pulse(since, dur)` → the 1st; `shake(bad, t)` → the 2nd (the 1st is the flag). */\nconst INSTANT_ARG: Record<string, number> = { pulse: 0, shake: 1 }\n\n/** Variables whose value is captured from `time` (`doneAt = time`) — the pre-0.23 timestamp idiom, back\n * when `pulse`/`shake` rode `time` too. A capture that already mentions `clock` is the correct one. */\nfunction timeCapturedVars(doc: Doc): Set<string> {\n const out = new Set<string>()\n forEachAction(doc, (a) => {\n if (a.do === 'setVar' && /\\btime\\b/.test(a.value) && !/\\bclock\\b/.test(a.value)) out.add(a.name)\n })\n return out\n}\n\n/** STRUCTURAL warnings (non-blocking) of a Doc: phantom drop zones, dead variables. */\nexport function docStructureWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n // (a) `when dropped on X` whose zone X does not exist (no item named so) -> the handler can never fire.\n const names = new Set(objectNames(doc.layers))\n for (const it of doc.interactions ?? []) {\n if (it.event === 'drop' && it.over && !names.has(it.over)) {\n const who = itemNameById(doc, it.targetId) ?? it.targetId\n out.push({ scope: 'scene', diag: { line: 1, col: 1, severity: 'warning', message: `unknown drop zone \"${it.over}\" (object \"${who}\") — no item of the scene carries this name` } })\n }\n }\n // (b) global variable never referenced (declared but not found in any scope) -> probably dead.\n const names0 = Object.keys(doc.variables ?? {})\n if (names0.length) {\n // Modifier targets are NOT emitted into scopeProgram (to avoid double-linting them, cf. docModifierWarnings),\n // so collect them here too — else a global used ONLY by a `spring`/`smooth` target reads as \"never used\".\n const modTargets: string[] = []\n const collectMods = (items: Item[]): void => {\n for (const it of items) {\n if (isPoseable(it) && it.modifiers) for (const ch of EXPR_CHANNELS) { const mm = it.modifiers[ch]; if (mm) modTargets.push(mm.target) }\n if (isGroup(it)) for (const l of it.layers) collectMods(l.items)\n }\n }\n for (const l of doc.layers) collectMods(l.items)\n for (const s of doc.symbols ?? []) for (const l of s.layers) collectMods(l.items)\n // Read the DOC, never a text rebuilt from it. `scopeProgram` only re-emits the `object` blocks of items\n // at the ROOT of a scope, so on a composed program whose draggables live inside element groups most of\n // them simply were not there: measured on a 210-line generated activity, 3 blocks out of 11 survived\n // the round-trip, and every variable read only in the other 8 came back \"never used\" -- 20 warnings,\n // all false. The walkers below descend the whole tree, symbols included.\n const used: string[] = [...modTargets]\n forEachExpression(doc, (e) => used.push(e))\n forEachAction(doc, (a) => { for (const v of Object.values(a)) if (typeof v === 'string') used.push(v) })\n // An interactor writes its variables through named SLOTS rather than an expression, and guards itself\n // with `enabled` -- neither is an expression the walkers see. That guard was the reported case.\n for (const i of doc.interactors ?? []) used.push(i.varX ?? '', i.varY ?? '', i.varT ?? '', i.cells ?? '', i.pointX ?? '', i.pointY ?? '', i.enabled ?? '')\n const allText = used.join('\\n')\n for (const name of names0) {\n if (!new RegExp(`(?<![\\\\w-])${escapeRe(name)}(?![\\\\w-])`).test(allText))\n out.push({ scope: 'scene', diag: { line: 1, col: 1, severity: 'warning', message: `global variable \"${name}\" never used (declared, but neither read nor written)` } })\n }\n }\n // (b bis) An `instance \"X\"` that resolved to NO symbol. Compilation keeps the unresolved `@X` marker all\n // the way into the .flatpack, the instance draws nothing, and everything else about the file looks\n // fine — the same family as the phantom drop zone above: a name that points at nothing. Only a\n // warning: compiling a program on its own and supplying its libraries later is a legitimate\n // workflow, and it must keep exiting 0.\n const missing = new Set<string>()\n const scanRefs = (items: Item[]): void => {\n for (const it of items) {\n if (isInstance(it) && it.symbolId.startsWith('@')) missing.add(it.symbolId.slice(1))\n if (isGroup(it)) for (const l of it.layers) scanRefs(l.items)\n }\n }\n for (const l of doc.layers) scanRefs(l.items)\n for (const s of doc.symbols ?? []) for (const l of s.layers) scanRefs(l.items)\n if (missing.size) {\n const names = [...missing].map((n) => `\"${n}\"`).join(', ')\n out.push(warn(`instance resolves to no symbol: ${names} — nothing is drawn where it stands. Pass the .flat library that defines it (\\`flatc <program> <lib.flat>\\`, or place it beside the program), or fix the name.`))\n }\n\n // (c) `time` reaching a channel expression + a SHORT looping timeline → the motion JUMPS on each loop\n // (`time = frame/fps` resets to 0 every `durationFrames`). The monotone `clock` never wraps.\n // A `time` reached THROUGH A FUNCTION counts: the costliest version of this trap was\n // `opacity = pulse(doneAt, 0.9)`, where the wrapping clock sat in the callee's body and the channel\n // text held no `time` at all — so a warning that only grepped the channel said nothing whatsoever.\n const dur = doc.timeline?.durationFrames ?? 60\n const fps = doc.timeline?.fps ?? 24\n if (dur <= 120) { // ≤ 5 s @24fps: short enough that the reset is visible as a periodic jump\n const viaFn = functionsReadingTime(doc)\n const culprits = new Set<string>()\n const scan = (layers: Layer[]) => {\n for (const l of layers) for (const it of l.items) {\n if (isPoseable(it) && it.expressions) for (const k in it.expressions) {\n const expr = it.expressions[k as keyof typeof it.expressions] ?? ''\n if (/\\btime\\b/.test(expr)) culprits.add('`time`')\n for (const fn of viaFn) if (new RegExp(`\\\\b${escapeRe(fn)}\\\\s*\\\\(`).test(expr)) culprits.add(`\\`${fn}()\\`` + ' (which reads `time`)')\n }\n if (isGroup(it)) scan(it.layers)\n }\n }\n scan(doc.layers)\n if (culprits.size) {\n const secs = Math.round((dur / fps) * 10) / 10\n out.push(warn(`a channel expression uses ${[...culprits].join(' and ')}, but the timeline loops every ${secs}s (durationFrames ${dur}) — \\`time\\` resets each loop, so the motion jumps (a one-shot ramp REPLAYS forever). Use the monotone \\`clock\\` (never wraps), drive it by \\`frame/${dur}\\`, or set a longer \\`timeline\\`.`))\n }\n }\n // (d) An instant captured on `time` and handed to `pulse`/`shake`. Both ride the MONOTONE `clock`, so\n // `clock - since` grows without bound and the ramp NEVER fires. Unlike (c) this is loop-LENGTH\n // independent — the two axes never meet however long the timeline is — and it is entirely SILENT:\n // nothing jumps, nothing blinks, and (c) itself stays quiet because the channel text holds no `time`.\n // The 0.21 → 0.23 migration trap: back then `pulse` rode `time` and the mismatch at least showed.\n const captured = timeCapturedVars(doc)\n if (captured.size) {\n const readers = new Map<string, Set<string>>() // variable → the feedback functions reading it as an instant\n forEachExpression(doc, (expr) => {\n for (const fnName of Object.keys(INSTANT_ARG)) {\n for (const args of callArguments(expr, fnName)) {\n const arg = args[INSTANT_ARG[fnName]]\n if (!arg) continue\n // The name may sit INSIDE the argument (`pulse(max(doneAt, 0), 1)`) — match it as a whole word.\n for (const v of captured) {\n if (!new RegExp(`(?<![\\\\w-])${escapeRe(v)}(?![\\\\w-])`).test(arg)) continue\n const seen = readers.get(v) ?? new Set<string>()\n seen.add(fnName)\n readers.set(v, seen)\n }\n }\n }\n })\n for (const [v, fns] of readers) {\n const who = [...fns].map((f) => `\\`${f}()\\``).join(' and ')\n out.push(warn(`\"${v}\" is captured on \\`time\\` but read as an INSTANT by ${who}, which compares it against the monotone \\`clock\\` — the two axes never meet, so the ramp never fires and nothing on screen says so. Capture it with \\`clock\\` instead: \\`${v} = clock\\`.`))\n }\n }\n out.push(...docPaintParamWarnings(doc))\n out.push(...docCelLayerWarnings(doc))\n out.push(...docLayoutWarnings(doc))\n out.push(...docRevealCellWarnings(doc))\n out.push(...docDrawWarnings(doc))\n out.push(...docGestureOptionWarnings(doc))\n out.push(...docFilterCacheWarnings(doc))\n return out\n}\n\n/** The channels folded into the filtered-composite cache SIGNATURE — i.e. the ones whose change busts it:\n * everything that moves the item on screen. DERIVED, not retyped: the signature is the item's placement,\n * so it is exactly the pose channels minus `opacity` (applied at BLIT time, so a pure fade reuses the baked\n * bitmap) plus the additive offsets. A hand-kept copy of a list the player owns is how `--check` came to\n * size a `reveal` grid on the brush while the engine used the grain. */\nconst CACHE_BUSTING_CHANNELS = [...EXPR_CHANNELS.filter((c) => c !== 'opacity'), ...OFFSET_CHANNELS]\n\n/** A CLOCK fed to a PERIODIC function — the shape of a motion that provably never settles.\n *\n * ⚠️ THE WHOLE PRECISION OF THE RULE IS HERE, and a looser test was measured to be useless. Plenty of\n * legitimate bindings mention `clock` on a transform and come to REST, so the cache pays them once and\n * then hits forever:\n * • `rotation = shake(bad, clock)` — `shake` is `bad ? sin(t*40)*4 : 0`, exactly 0 at rest. Every\n * draggable object in a generated activity carries one; flagging them made the rule fire on scenes\n * that were perfectly fine.\n * • `scaleX = 1 + 0.28 * clamp(1 - (clock - landedAt) * 1.6, 0, 1)` — a decay, constant after 0.6 s.\n * A periodic wrapper cannot settle: `sin`, `cos` and `mod` return to their range forever, by construction.\n * That is the difference between a cost paid once and a cost paid sixty times a second. */\n/* Every ever-growing instant counts, not just `clock`: `time` restarts each loop and `frame` counts up,\n * so `dy = 3 * sin(time * 2)` re-bakes exactly as hard as its `clock` twin and used to slip through. */\nconst PERIODIC_CLOCK = /\\b(sin|cos|mod)\\s*\\([^()]*\\b(clock|time|frame)\\b/\n\n/**\n * A `filter` whose SCREEN PLACEMENT never holds still — the one combination that defeats the render cache.\n *\n * Isolating a filter costs an off-screen canvas, a CSS filter and a blit. The player pays that ONCE and\n * keeps the baked bitmap, keyed on the item's full screen placement (`filterCacheSlot`). That saving is the\n * whole reason a scene can afford glows at all.\n *\n * Put a PERIODIC clock motion on a transform channel — on the filtered item OR on any ancestor — and the\n * placement differs every frame, so the key never repeats and the bitmap is re-baked sixty times a second,\n * forever.\n *\n * Measured on a generated activity: a garland swaying on `dy = 3 * sin(clock * 0.55)`, with six glowing\n * lanterns hanging from it. The lanterns themselves were innocent — their own motion settles — but the\n * sway above them re-baked all six glows every frame. Nothing looked wrong; the drag simply stuttered, and\n * the cost was invisible in the source, split across a `filter` on one line and a parent's `dy` fifty\n * lines away.\n *\n * Only a warning, and deliberately so: it is a COST, not a defect, and a still scene may well afford it.\n * But it must be said, because nothing else in the chain can say it — the program compiles, the picture is\n * correct, and only a profiler on a real device tells you where the frame budget went.\n */\nexport function docFilterCacheWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const culprits: string[] = []\n\n /** Does this item move its own placement in a way that never comes to rest? */\n const clockPosed = (it: Item): boolean => {\n if (!isPoseable(it) || !it.expressions) return false\n for (const ch of CACHE_BUSTING_CHANNELS) {\n const expr = it.expressions[ch as keyof typeof it.expressions]\n if (typeof expr === 'string' && PERIODIC_CLOCK.test(expr)) return true\n }\n return false\n }\n\n // `moving` is inherited: the cache signature folds the ACCUMULATED screen transform, so an animated\n // grandparent busts a still child's cache just as surely as its own binding would.\n const walk = (items: Item[], moving: boolean, path: string): void => {\n for (const it of items) {\n const name = ('name' in it && typeof it.name === 'string' && it.name) || it.id\n const here = path ? `${path} › ${name}` : name\n const animated = moving || clockPosed(it)\n if (animated && 'filters' in it && Array.isArray(it.filters) && it.filters.length > 0) {\n culprits.push(here)\n }\n if (isGroup(it)) for (const l of it.layers) walk(l.items, animated, here)\n }\n }\n for (const l of doc.layers) walk(l.items, false, '')\n\n if (culprits.length > 0) {\n const shown = culprits.slice(0, 4).map((n) => `\"${n}\"`).join(', ')\n const more = culprits.length > 4 ? `, and ${culprits.length - 4} more` : ''\n out.push({\n scope: 'scene',\n diag: {\n line: 1,\n col: 1,\n severity: 'warning',\n message:\n `filter under a transform that never stops moving (${shown}${more}) — a periodic \\`clock\\` motion on this item or an ancestor. The filtered-composite cache keys on the screen placement, so it can never hit: the off-screen composition is repaid EVERY FRAME, for as long as the scene is open. ` +\n `Move the animation to \\`opacity\\` (applied at blit, so the cache still hits), drive the transform from a value that SETTLES, or drop the filter.`,\n },\n })\n }\n return out\n}\n/**\n * SILENT DROPS in a cel layer. `resolveLayerAt` draws exactly two things: the current cel's `matter`, and\n * the containers that cel POSES — never the layer's other roster items. Three ways to author a layer that\n * compiles, renders an empty frame, and says nothing:\n * (a) a bare shape (`path`/`circle`/`rect`/…) sitting in a layer that has cels — it belongs inside a\n * cel's `matter { … }` (frame-by-frame drawing) or on a cel-less layer (static decor);\n * (b) a `pose \"X\"` naming no roster item (the parser leaves such a pose id as `@X`) — poses nothing;\n * (c) a roster container/text/image that no cel ever poses — never drawn.\n * All three are the classic \"my drawing vanished\" bug. Warnings (non-blocking).\n */\nexport function docCelLayerWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const checkScope = (scope: string, layers: Layer[]) => {\n const push = (message: string) => out.push({ scope, diag: { line: 1, col: 1, severity: 'warning', message } })\n const visit = (ls: Layer[]): void => {\n for (const l of ls) {\n if (l.cels?.length) {\n const bare = l.items.filter(isRegion)\n if (bare.length) push(`layer \"${l.name}\" has cels, so its ${bare.length} bare shape(s) are NEVER drawn — a cel layer draws only the cel's \\`matter { … }\\` and the containers it poses. Move them into \\`cel N { matter { … } }\\`, or onto a cel-less layer if they are static.`)\n const posed = new Set<string>()\n for (const c of l.cels) for (const p of c.poses) posed.add(p.id)\n for (const id of posed) if (id.startsWith('@')) push(`layer \"${l.name}\": \\`pose \"${id.slice(1)}\"\\` matches no item of this layer — the pose draws nothing (roster: ${l.items.map(itemLabel).join(', ') || 'empty'}).`)\n for (const it of l.items) if (isPoseable(it) && !posed.has(it.id)) push(`layer \"${l.name}\": \"${itemLabel(it)}\" is never posed by a cel — it is never drawn. Add \\`pose \"${itemLabel(it)}\"\\` to the cels where it should show.`)\n // Posed, SKIPPED, then posed again: the item blinked out and back. A cel is a full snapshot, so\n // that is the model working as designed — and it is exactly how an exit is written, which is why\n // a FINAL absence says nothing. But a staggered entrance (three things arriving at three\n // moments) needs `hold` on every cel, and forgetting it makes elements vanish mid-run in\n // silence. That omission is what a program-scene animation trips on, every time.\n const cels = [...l.cels].sort((a, b) => a.frame - b.frame)\n for (const it of l.items) {\n if (!isPoseable(it)) continue\n const at = cels.map((c) => c.poses.some((p) => p.id === it.id))\n const first = at.indexOf(true)\n const last = at.lastIndexOf(true)\n // The hole must sit BETWEEN the first and last pose. Absent before the first is a late\n // ENTRANCE, absent after the last is an EXIT — both are how the model is meant to be used.\n const gap = at.findIndex((on, i) => !on && i > first && i < last)\n if (gap >= 0) {\n push(`layer \"${l.name}\": \"${itemLabel(it)}\" is posed at cel ${cels[first].frame}, absent at cel ${cels[gap].frame}, then posed again at cel ${cels[last].frame} — a cel is a FULL snapshot, so it disappears in between. Add \\`hold\\` to the cels that should carry it forward (\\`cel ${cels[gap].frame} hold { … }\\`), or pose it there.`)\n }\n }\n }\n for (const it of l.items) if (isGroup(it)) visit(it.layers)\n }\n }\n visit(layers)\n }\n checkScope('scene', doc.layers)\n for (const s of doc.symbols) checkScope(s.name, s.layers)\n return out\n}\n\n/**\n * `reveal <p> { cells <array> }` — the grid the player writes into is DERIVED (zone bbox ÷ brush), so the\n * one number the author cannot guess is how many cells to declare. An array of the wrong length loses the\n * writes past its end IN SILENCE (the veil clears where nothing shows). So: state the geometry, every time\n * the sizes disagree, and name the exact declaration to write.\n */\nexport function docRevealCellWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n for (const it of doc.interactors ?? []) {\n if (it.axis !== 'reveal' || !it.cells) continue\n const who = itemNameById(doc, it.targetId) ?? it.targetId\n const declared = Object.hasOwn(doc.variables ?? {}, it.cells) ? doc.variables?.[it.cells] : undefined // hasOwn: a name like `constructor` is not a declaration\n const b = itemBoundsById(doc, it.targetId)\n if (!b) continue // the target itself does not resolve — `object \"X\"` on nothing is already reported\n // THE geometry, from the engine — the same call the player makes. Sizing it here on its own is how the\n // two drifted the day `grain` arrived: this said 300 cells where the engine made 5610, and every write\n // past the end of the advised array was dropped in silence.\n const { cols, rows, total: n } = revealGrid(b, it)\n const from = it.grain && it.grain > 0 ? `grain ${it.grain}` : `brush ${it.grid && it.grid > 0 ? it.grid : 24}`\n const geom = `${cols} x ${rows} = ${n} cells (zone ${Math.round(b.maxX - b.minX)}x${Math.round(b.maxY - b.minY)} px, ${from})`\n if (!Array.isArray(declared)) {\n out.push(warn(`\\`reveal … cells ${it.cells}\\` (object \"${who}\") writes into \"${it.cells}\", which is ${declared === undefined ? 'not declared' : 'a scalar, not an array'} — the scratched grid goes nowhere. Declare it with the grid's size: \\`var ${it.cells} = fill(${n}, 0)\\` — ${geom}, index = row * ${cols} + col.`))\n } else if (declared.length !== n) {\n out.push(warn(`\\`reveal … cells ${it.cells}\\` (object \"${who}\"): the grid is ${geom}, but \"${it.cells}\" holds ${declared.length} — ${declared.length < n ? 'every cell past the end is dropped in silence' : 'the extra cells are never written'}. Declare \\`var ${it.cells} = fill(${n}, 0)\\`, index = row * ${cols} + col.`))\n }\n }\n return out\n}\n\n/**\n * Slots that quietly do nothing on their own: `both ends` without `step` (only a CONTINUOUS trace has an\n * entry end to choose), and a `grain` so much coarser than the brush that a touch can land between two cell\n * centres and clear nothing at all. Both leave a scene that looks written correctly and behaves as if the\n * option had not been typed.\n */\nexport function docGestureOptionWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n for (const it of doc.interactors ?? []) {\n const who = itemNameById(doc, it.targetId) ?? it.targetId\n // A `step` of 0 (or less) is the one number here that does not fall back: the progress may advance by\n // at most `step` px per frame, so nothing can ever advance. The drill draws its guide, the finger\n // follows it, the ink stays empty and `--check` was green — an exercise impossible to complete, in\n // silence. The others below are milder: they are IGNORED, which is its own kind of quiet wrong.\n if (it.axis === 'trace' && it.step !== undefined && !(it.step > 0)) {\n out.push(warn(`\\`step ${it.step}\\` (object \"${who}\") — the progress may grow by at most \\`step\\` px of arc length per frame, so at ${it.step} it can never move and the trace can never be completed. Use the distance a finger may cover between two frames (a quarter of the path is a sane start).`))\n }\n for (const [slot, value] of [['tolerance', it.axis === 'trace' ? it.grid : undefined], ['brush', it.axis === 'reveal' ? it.grid : undefined], ['grain', it.axis === 'reveal' ? it.grain : undefined]] as const) {\n if (value !== undefined && !(value > 0)) {\n out.push(warn(`\\`${slot} ${value}\\` (object \"${who}\") is ignored — a non-positive value falls back to the default, so the number in the source describes nothing. Write the one you mean, or drop the line.`))\n }\n }\n if (it.axis === 'trace' && it.bothEnds && it.step === undefined) {\n out.push(warn(`\\`both ends\\` without \\`step\\` (object \"${who}\") — it picks which END the run is measured from, and a \\`trace\\` without \\`step\\` has no run: its progress is wherever the finger projects, from anywhere. Add \\`step <px>\\` (the max jump between two frames) or drop \\`both ends\\`.`))\n }\n if (it.axis === 'reveal') {\n const brush = it.grid && it.grid > 0 ? it.grid : 24\n if (it.grain && it.grain > brush) {\n out.push(warn(`\\`grain ${it.grain}\\` is coarser than \\`brush ${brush}\\` (object \"${who}\") — a cell is cleared when its CENTRE falls within the brush, so a touch can land between two centres and clear nothing. Keep the grain at or under the brush (a fine grain under a wide finger is the point).`))\n }\n }\n }\n return out\n}\n\n/** `draw` trims the STROKE by arc length — on a shape with no stroke it has nothing to trim, so the ink\n * the author is animating simply never appears (and the fill they DO have is untouched, so the scene\n * looks plausible). */\nexport function docDrawWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const check = (scope: string, r: Region): void => {\n if (r.stroke) return\n if (r.draw == null && !r.drawExpr && r.drawFrom == null && !r.drawFromExpr) return\n out.push({ scope, diag: { line: 1, col: 1, severity: 'warning', message: `\\`draw\\` on a shape with no \\`stroke\\` — it trims the OUTLINE by arc length, so with nothing stroked it changes nothing on screen. Add \\`stroke <color> <width>\\` (an ink trail is usually \\`nofill stroke … cap round\\`).` } })\n }\n const scan = (scope: string, layers: Layer[]): void => {\n for (const l of layers) {\n for (const it of l.items) { if (isRegion(it)) check(scope, it); else if (isGroup(it)) scan(scope, it.layers) }\n for (const c of l.cels ?? []) for (const r of c.matter ?? []) check(scope, r)\n }\n }\n scan('scene', doc.layers)\n for (const s of doc.symbols ?? []) scan(s.name, s.layers)\n return out\n}\n\n/** A scope's declared `color` param names (the only params usable as a paint color). */\nconst colorParamNames = (params?: ParamDef[]): Set<string> => new Set((params ?? []).filter((p) => p.type === 'color').map((p) => p.name))\n\n/**\n * A `color` param used as a paint (`fill`/`stroke`, a gradient **stop** `0:teinte@…`, or a `tint`) that the\n * owning symbol does NOT declare → a SILENT \"dead recolor\" (it falls back to the literal hex, the picker does\n * nothing). Warns per scope, with the param scoped to ITS symbol (the scene declares none). Mirrors how the\n * lint now knows a symbol's params in its `expr`. Non-blocking (a warning), so it never breaks a build.\n */\nexport function docPaintParamWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const checkScope = (scope: string, layers: Layer[], known: Set<string>) => {\n const flag = (param: string, where: string, who?: string) => {\n if (known.has(param)) return\n const hint = known.size ? `declared color params: ${[...known].join(', ')}` : 'this scope declares no color params'\n out.push({ scope, diag: { line: 1, col: 1, severity: 'warning', message: `unknown color param \"${param}\" in ${where}${who ? ` (${who})` : ''} — ${hint}` } })\n }\n const visit = (it: Item) => {\n const who = 'name' in it ? it.name : undefined\n if (isRegion(it)) {\n if (it.fillParam) flag(it.fillParam, 'a fill', who)\n if (it.strokeParam) flag(it.strokeParam, 'a stroke', who)\n const stops = it.paint && it.paint.type !== 'solid' ? it.paint.stops : []\n for (const s of stops) if (s.param) flag(s.param, 'a gradient stop', who)\n }\n if (isPoseable(it) && it.tint?.param) flag(it.tint.param, 'a tint', who)\n if (isGroup(it)) for (const l of it.layers) for (const c of l.items) visit(c) // a group is the same scope; an instance is a separate symbol (linted on its own pass)\n }\n for (const l of layers) for (const it of l.items) visit(it)\n }\n checkScope('scene', doc.layers, new Set())\n for (const s of doc.symbols) checkScope(s.name, s.layers, colorParamNames((s as SymbolDef).params))\n return out\n}\n\nconst warn = (message: string): { scope: string; diag: Diagnostic } => ({ scope: 'scene', diag: { line: 1, col: 1, severity: 'warning', message } })\nconst itemLabel = (it: Item): string => ('name' in it && it.name ? it.name : 'kind' in it ? it.kind : 'path')\n/** Mean advance of a proportional glyph at this text's size — the metric both estimators share. */\nconst glyphAdvance = (t: Text): number => (t.weight && t.weight >= 700 ? 0.56 : 0.52) * t.size\n\n/** Estimated width of the longest line (approximate metric, without canvas). */\nfunction estTextWidth(t: Text): number {\n const advance = glyphAdvance(t)\n let longest = 0\n for (const line of t.content.split('\\n')) longest = Math.max(longest, line.length)\n return longest * advance\n}\n\n/** Bounds of what a `text` actually PAINTS, in parent space -- as opposed to the box it declares.\n * Measured on the deckgen corpus: 36 of 53 warnings were `align center` texts in a comfortable box, where\n * the box crosses the canvas edge and the glyphs sit hundreds of pixels short of it. A box is a layout\n * frame, not ink: `text \"Accepter\" align center box 780 40` is 8 glyphs in the middle of 780 px.\n * A WRAPPED text keeps its box -- there the ink really can fill the width. Anything else is unchanged. */\nfunction inkBBox(doc: Doc, it: Item): ReturnType<typeof itemBBox> {\n const box = itemBBox(doc, it)\n if (!box || !isText(it) || it.wrap || it.textPath) return box\n const estW = estTextWidth(it)\n if (estW >= it.box.w) return box // the ink fills (or overruns) the frame -> the frame IS the measure\n const left = it.align === 'left' ? 0 : it.align === 'right' ? it.box.w - estW : it.box.w / 2 - estW / 2\n return transformBBox({ minX: left, minY: 0, maxX: left + estW, maxY: it.box.h }, it.transform)\n}\n\n/** Greedy word-wrap of a `wrap` text at its box width — the renderer's own rule (break at spaces, and\n * only at spaces). Returns the resulting line count and the widest single word, which is what decides\n * whether anything spills sideways: a word wider than the box has no break point and runs past it. */\nexport function wrapMetrics(t: Text): { lines: number; widestWord: number } {\n const advance = glyphAdvance(t)\n const width = (s: string) => s.length * advance\n let lines = 0\n let widestWord = 0\n for (const paragraph of t.content.split('\\n')) {\n lines++ // an explicit newline always starts a line, empty ones included (they still take height)\n let current = ''\n for (const word of paragraph.split(/\\s+/).filter(Boolean)) {\n widestWord = Math.max(widestWord, width(word))\n const joined = current ? `${current} ${word}` : word\n if (current && width(joined) > t.box.w) { lines++; current = word } else current = joined\n }\n }\n return { lines, widestWord }\n}\n\n/** LAYOUT warnings (non-blocking): canvas overflow, text too wide, overlapping hitboxes.\n * Approximate but without canvas — catches \"blind\" positioning bugs before the render. */\nexport function docLayoutWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const W = doc.width, H = doc.height\n const TOL = 8 // overflow tolerance (px) before alerting\n const r0 = (n: number) => Math.round(n)\n\n // An item whose position is written at RUNTIME — bound to an expression, or dragged directly — has a\n // meaningless static bbox. That rule already existed; what it missed is that it is INHERITED: a label\n // sitting inside a dragged tile is authored around the tile's origin and only lands somewhere real once\n // the tile moves. Measuring it where the file happens to leave it (0,0) reports the whole scene as\n // clipped — the exact noise that would make the pass unusable.\n const dynamicPos = (it: Item) =>\n ('expressions' in it && it.expressions && (it.expressions.x != null || it.expressions.y != null || it.expressions.dx != null || it.expressions.dy != null)) ||\n !!doc.interactors?.some((i) => i.targetId === it.id) // `drag`/`turn`: the pointer decides where it is\n\n // Every text/image of the scene, paired with the WORLD matrix of its PARENT (the space `itemBBox`\n // reports in) and whether any ancestor is runtime-positioned. Both passes below used to read\n // `doc.layers` top level only — and a group is the only thing a behavior block can animate, so most of\n // a real scene lives inside one and was never measured at all.\n const placed: { it: Text | Image; parent: Transform; dynamic: boolean }[] = []\n const collect = (layers: Layer[], matrix: Transform, dynamic: boolean): void => {\n for (const l of layers) for (const it of l.items) {\n if (isText(it) || isImage(it)) placed.push({ it, parent: matrix, dynamic: dynamic || dynamicPos(it) })\n if (isGroup(it)) collect(it.layers, compose(matrix, it.transform), dynamic || dynamicPos(it))\n }\n }\n collect(doc.layers, IDENTITY, false)\n\n // (c) TEXT/IMAGE clipped at the canvas edge. Precise to avoid noise: we ignore `path`/groups\n // (decor that \"bleeds\" on purpose), anything positioned at runtime (see above), and items PARKED\n // entirely off-screen (\"hidden\" pattern).\n for (const { it, parent, dynamic } of placed) {\n if (dynamic || (isText(it) && it.textPath)) continue // path-laid text → §(f), not a box\n const local = inkBBox(doc, it)\n if (!local) continue\n const b = transformBBox(local, parent) // itemBBox is PARENT-space → compose with the ancestors\n const visible = b.maxX > 0 && b.minX < W && b.maxY > 0 && b.minY < H // overlaps the canvas (not parked off-screen)\n const clipped = b.minX < -TOL || b.minY < -TOL || b.maxX > W + TOL || b.maxY > H + TOL\n if (visible && clipped) {\n out.push(warn(`\"${itemLabel(it)}\" clipped at the canvas edge: bbox [${r0(b.minX)},${r0(b.minY)} -> ${r0(b.maxX)},${r0(b.maxY)}] outside 0,0 -> ${W},${H}`))\n }\n }\n\n // (d) Text (without `wrap`) whose estimated width makes it OVERFLOW THE CANVAS -> instruction clipped.\n // (We do NOT compare against `box.w`: without wrap, a text overflows its box harmlessly as long as it\n // fits in the canvas — it is the canvas edge that clips.)\n for (const { it, parent, dynamic } of placed) {\n if (!isText(it) || it.wrap || it.textPath || dynamic) continue\n const estW = estTextWidth(it)\n const left = it.align === 'left' ? 0 : it.align === 'right' ? it.box.w - estW : it.box.w / 2 - estW / 2\n const m = compose(parent, it.transform) // the text's own world matrix: its baseline runs in ITS space\n const p0 = apply(m, { x: left, y: 0 }), p1 = apply(m, { x: left + estW, y: 0 })\n const wl = Math.min(p0.x, p1.x), wr = Math.max(p0.x, p1.x) // left/right edge of the content in world coords\n if (wr > W + TOL || wl < -TOL) {\n // `wrap` breaks at SPACES and nowhere else, so it can do nothing for a single word -- and a giant\n // single word bleeding off the frame is a deliberate gesture in every corpus measured (ghost\n // typography: `1815`, `URUK`, `1429`). Prescribing `wrap` there is advice that cannot be followed.\n const oneWord = !/\\s/.test(it.content.trim())\n const advice = oneWord\n ? ' — `wrap` cannot help: it breaks at spaces, and this is a single word. Intentional if the bleed is the point; otherwise reduce the size or move it in'\n : ' — add \"wrap\"'\n out.push(warn(`text \"${it.content.slice(0, 24)}${it.content.length > 24 ? '…' : ''}\" overflows the canvas (estimated ~${r0(estW)} px, edge ${r0(wl)}->${r0(wr)} outside 0->${W})${advice}`))\n }\n }\n\n // (h) ANY item drawn ENTIRELY outside the canvas. The clipped-at-the-edge pass above deliberately\n // tolerates straddling (decor bleeds on purpose) and skips items parked off-screen — but \"parked\"\n // is only a pattern for something a binding moves back in, and those are excluded as dynamic. A\n // STATIC item wholly off-canvas is never intentional: it is a coordinate mistake, and until now\n // nothing said so for a shape or a group. Measured on a model-written board: the eighth token was\n // laid out past the edge and the whole chain stayed quiet.\n // Two things this must NOT flag, both measured on a real corpus before the rule was let out:\n // • an item PARKED off the TOP-LEFT corner on purpose (`at -999,-999` for a payload holder,\n // `-600,-600` for hidden labels) — the idiom is real, used in 3 of 58 activities measured, and\n // its signature is that BOTH axes are negative. A mistake overshoots one edge;\n // • a DEGENERATE bbox lying along an edge (a hairline rule at y=0 spans `0,0 -> 760,0`), which\n // is on the canvas, not off it — so compare strictly, with the same tolerance as the rest.\n const parked = (b: { maxX: number; maxY: number }) => b.maxX < 0 && b.maxY < 0\n const offCanvas = (b: { minX: number; minY: number; maxX: number; maxY: number }) =>\n (b.maxX < -TOL || b.minX > W + TOL || b.maxY < -TOL || b.minY > H + TOL) && !parked(b)\n // A container's bbox is the UNION of its children's, so it is only static if they all are. Measured on\n // the deckgen corpus: `group \"S0\"` drives nothing but `opacity`, and holds a slide-in whose static `at`\n // parks it off-screen — the union landed off-canvas and the group was reported. The `dynamic` flag was\n // inherited DOWNWARD (a moved parent moves its children) but never upward, which is the other half of\n // the same fact.\n // Computed ONCE, post-order. Asking per item re-walks the subtree every time -- O(n x depth) where one\n // pass suffices. (It is not where this pass spends its time: measured on a 4434-line deck the two shapes\n // are within noise. It is written this way because the other one is quadratic for no reason.)\n const moving = new Set<string>()\n const markMoving = (items: Item[]): boolean => {\n let any = false\n for (const it of items) {\n const inside = isGroup(it) && it.layers.some((l) => markMoving(l.items))\n if (dynamicPos(it) || inside) { moving.add(it.id); any = true }\n }\n return any\n }\n for (const l of doc.layers) markMoving(l.items)\n const movesADescendant = (it: Item): boolean => moving.has(it.id)\n const reportOffCanvas = (items: Item[], matrix: Transform, dynamic: boolean): void => {\n for (const it of items) {\n const isDynamic = dynamic || dynamicPos(it)\n if (!isDynamic && !movesADescendant(it) && !(isText(it) && it.textPath)) {\n const local = itemBBox(doc, it)\n const b = local && transformBBox(local, matrix)\n if (b && offCanvas(b)) {\n // Report the OUTERMOST offender: a group off-canvas takes its whole content with it, and one\n // line about the group is the fix, where one per child is noise.\n out.push(warn(`\"${itemLabel(it)}\" is drawn entirely off-canvas: bbox [${r0(b.minX)},${r0(b.minY)} -> ${r0(b.maxX)},${r0(b.maxY)}], canvas 0,0 -> ${W},${H}. Nothing of it is visible.`))\n continue\n }\n }\n if (isGroup(it)) for (const l of it.layers) reportOffCanvas(l.items, compose(matrix, it.transform), isDynamic)\n }\n }\n for (const l of doc.layers) reportOffCanvas(l.items, IDENTITY, false)\n\n // (g) WRAPPED text taller than its box. Pass (d) skips `wrap` — rightly, since wrapping cannot overflow\n // the box horizontally — but that left wrapped text unmeasured entirely, and what it DOES overflow is\n // the box's height. Same visible defect: an instruction spilling out of its frame is the first thing\n // an eye catches, and the reason a whole activity had to be re-read by a multimodal model.\n for (const { it } of placed) {\n if (!isText(it) || !it.wrap || it.textPath) continue\n const { lines, widestWord } = wrapMetrics(it)\n const label = `${it.content.slice(0, 24).replace(/\\n/g, ' ')}${it.content.length > 24 ? '…' : ''}`\n // ONE line of slack. The estimator has no canvas: it wraps on a mean glyph advance, so it breaks a\n // little early and lands one line long -- measured against skia on five decks (3/4/5 where skia laid\n // 2/3/4). Warning at +1 line meant 36 warnings on a corpus where none matched a defect on screen, and\n // a warning nobody believes is worse than none. Two lines over is a real overflow.\n const tall = (lines - 1) * it.size * it.lineHeight\n if (tall > it.box.h + TOL) {\n out.push(warn(`text \"${label}\" overflows its box: ~${lines} wrapped line(s) ≈ ${r0(lines * it.size * it.lineHeight)} px for a box ${r0(it.box.h)} px tall — raise the box height, shorten the text, or reduce the size`))\n }\n if (widestWord > it.box.w + TOL) {\n out.push(warn(`text \"${label}\" has a word too wide for its box (~${r0(widestWord)} px > ${r0(it.box.w)} px) — a single word cannot be broken, so it spills past the frame whatever \"wrap\" says`))\n }\n }\n\n // (f) Text laid ALONG a path whose estimated run is longer than the path -> trailing glyphs dropped at\n // render (mirrors the canvas-overflow warning, but for the curve). Position-independent -> recurse.\n const pathTexts: Text[] = []\n const walkPathTexts = (layers: Layer[]) => { for (const l of layers) for (const it of l.items) { if (isText(it) && it.textPath) pathTexts.push(it); else if (isGroup(it)) walkPathTexts(it.layers) } }\n walkPathTexts(doc.layers)\n for (const it of pathTexts) {\n const L = makePathSampler(it.textPath!.path).length\n if (L <= 0) continue\n const advance = (it.weight && it.weight >= 700 ? 0.56 : 0.52) * it.size // same metric as estTextWidth\n const glyphs = [...it.content].length\n const eff = Math.max(advance + (it.textPath!.spacing ?? 0), 1) // mirror the renderer's per-glyph floor\n const estW = glyphs * eff\n if (estW > L + TOL) out.push(warn(`text \"${it.content.slice(0, 24)}${it.content.length > 24 ? '…' : ''}\" overflows its path (~${r0(estW)}px > ${r0(L)}px) — trailing glyphs are dropped`))\n }\n\n // (e) Drop zones (`hitbox`) that overlap -> ambiguous drop.\n const zones: { name: string; b: NonNullable<ReturnType<typeof dropZoneBounds>> }[] = []\n const collectZones = (layers: Layer[]) => {\n for (const l of layers) for (const it of l.items) {\n if (isGroup(it) && it.hitbox && it.name) { const b = dropZoneBounds(doc, it.name); if (b) zones.push({ name: it.name, b }) }\n if (isGroup(it)) collectZones(it.layers)\n }\n }\n collectZones(doc.layers)\n for (let i = 0; i < zones.length; i++) for (let j = i + 1; j < zones.length; j++) {\n if (bboxIntersects(zones[i].b, zones[j].b)) out.push(warn(`overlapping hitboxes: \"${zones[i].name}\" and \"${zones[j].name}\" -> ambiguous drop`))\n }\n return out\n}\n\n/** Semantic lint of a whole Doc (all the scopes) -> diagnostics labeled by scope.\n * A scope's text contains `object` blocks (outside DSL) -> we lint each region separately and re-project\n * the lines. `src` = the program SOURCE, when the caller has it (the CLI): the scene scope is then read\n * from it, so positions and scopes describe the author's file. Without it the scene scope falls back to\n * the text rebuilt from the Doc — right for the editor, where that rebuilt text IS the file being edited\n * (cf. CodeEditor.lintFile). Adds the structural warnings (phantom drop zones, dead variables). */\nexport function lintDoc(doc: Doc, src?: string): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const allVars = allScopeVariables(doc) // computed ONCE (global vars -> known in all the scopes)\n for (const { label, editPath } of scopes(doc)) {\n const ctx = docLintContext(doc, editPath, allVars)\n // The SCENE scope is linted from the SOURCE whenever the caller has it (the CLI does). `scopeProgram`\n // rebuilds a text the author never wrote -- no `scene { … }` block -- so its line numbers are offset by\n // that block's height and its scope is always `scene`, never the `object \"X\"` the error is really in.\n // Symbols keep the reconstruction: they come from `.flat` libs, whose source is not this program's.\n const regions = src && editPath.length === 0\n ? behaviorRegions(src)\n : scopeRegions(scopeProgram(doc, editPath)).map((r) => ({ scope: label, body: r.body, line: r.line }))\n for (const r of regions)\n for (const d of lint(r.body, ctx)) {\n const shift = r.line - 1\n // The `fix` carries its own positions, relative to the region text exactly like `d.line`. Shift\n // both or the repair lands somewhere else in the file -- and applies cleanly there, silently.\n const fix = d.fix && { ...d.fix, line: d.fix.line + shift, endLine: d.fix.endLine + shift }\n out.push({ scope: r.scope, diag: { ...d, line: d.line + shift, ...(fix ? { fix } : {}) } })\n }\n }\n out.push(...docStructureWarnings(doc))\n out.push(...docModifierWarnings(doc))\n return out\n}\n\n/** Lint each stateful channel modifier's TARGET expression with its scope's known names (a symbol's params\n * included) — so a typo'd `spring rotation \"crochetXX\"` surfaces as \"unknown variable\" at `--check` time,\n * not a silent NaN at runtime. Also flags out-of-range spring damping (clamped at runtime, but worth noting). */\nexport function docModifierWarnings(doc: Doc): { scope: string; diag: Diagnostic }[] {\n const out: { scope: string; diag: Diagnostic }[] = []\n const allVars = allScopeVariables(doc)\n for (const { label, editPath } of scopes(doc)) {\n const ctx = docLintContext(doc, editPath, allVars)\n const visit = (items: Item[]): void => {\n for (const it of items) {\n if (isPoseable(it) && it.modifiers) for (const ch of EXPR_CHANNELS) {\n const m = it.modifiers[ch]\n if (!m) continue\n for (const d of lint(`${ch} = ${m.target}`, ctx)) out.push({ scope: label, diag: { ...d, line: 1, col: 1, message: `${m.kind} ${ch}: ${d.message}` } })\n if (m.kind === 'spring' && !(m.damping > 0 && m.damping < 1)) out.push({ scope: label, diag: { line: 1, col: 1, severity: 'warning', message: `spring ${ch}: damping ${m.damping} should be in (0,1) — clamped at runtime` } })\n }\n if (isGroup(it)) for (const l of it.layers) visit(l.items) // a group shares the scope; instances are linted on their own symbol pass\n }\n }\n visit(contextLayers(doc, editPath).flatMap((l) => l.items))\n // `velocity()` is valid ONLY in a modifier target (resolved by the player's stateful advance). scopeProgram\n // emits the scope's REGULAR expressions but NOT modifier targets, so any velocity() here is a misuse.\n if (/\\bvelocity\\s*\\(/.test(scopeProgram(doc, editPath)))\n out.push({ scope: label, diag: { line: 1, col: 1, message: 'velocity() is only valid inside a spring/smooth target, not a plain expression' } })\n }\n return out\n}\n\nconst sev = (d: Diagnostic) => (d.severity === 'warning' ? 'warning' : 'error')\n\n/** Lint report of a Doc ready to display: `''` = no issue, otherwise `[scope] line:col: level: message`.\n * Pass `src` (the program source) to get positions that point INTO IT rather than into a rebuilt program. */\nexport function lintDocReport(doc: Doc, src?: string): string {\n return lintDoc(doc, src).map(({ scope, diag }) => `[${scope}] ${diag.line}:${diag.col}: ${sev(diag)}: ${diag.message}`).join('\\n')\n}\n\n/** `true` if the Doc has at least one ERROR (warnings alone do not block). */\nexport function docHasErrors(doc: Doc, src?: string): boolean {\n return lintDoc(doc, src).some(({ diag }) => sev(diag) === 'error')\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// docWalk.ts — walking the behavior of a Doc: every action, every expression.\n//\n// A Doc scatters its logic across five places (item interactions, direct-manipulation interactors,\n// procedure bodies, the scene timeline's hooks, each symbol's timeline hooks) and its expressions\n// across two more (channel bindings and stateful modifier targets, at any depth in the group tree).\n// Anything that reasons about \"what does this program read / write / emit\" has to visit all of them,\n// and missing one is a silent hole. Collected here once so the linter and the manifest agree.\n// ─────────────────────────────────────────────────────────────────────────────\nimport type { Action, Doc, Item, Layer } from '@flatkit/types'\nimport { isGroup, isPoseable, isRegion, isText } from '@flatkit/engine/layers'\nimport { EXPR_CHANNELS } from '@flatkit/engine/timeline'\n\n/** Every action of a body, nested `if` / `repeat` bodies included. */\nexport function forEachActionIn(actions: Action[] | undefined, fn: (a: Action) => void): void {\n for (const a of actions ?? []) {\n fn(a)\n if (a.do === 'if') { forEachActionIn(a.then, fn); forEachActionIn(a.else, fn) }\n else if (a.do === 'repeat' || a.do === 'repeatRange') forEachActionIn(a.body, fn)\n }\n}\n\n/** Every ACTION of the Doc: item events, procedure bodies, and the load / enter-frame / at-frame hooks\n * of the scene timeline and of every symbol's. */\nexport function forEachAction(doc: Doc, fn: (a: Action) => void): void {\n for (const i of doc.interactions ?? []) forEachActionIn(i.actions, fn)\n for (const f of doc.functions ?? []) if (f.kind === 'proc') forEachActionIn(f.body, fn)\n for (const t of [doc.timeline, ...(doc.symbols ?? []).map((s) => s.timeline)]) {\n if (!t) continue\n forEachActionIn(t.onLoad, fn)\n forEachActionIn(t.onEnterFrame, fn)\n for (const fa of t.frameActions ?? []) forEachActionIn(fa.actions, fn)\n }\n}\n\n/** Every expression an action carries: assigned values, conditions, loop bounds, call arguments, payloads. */\nexport function forEachActionExpression(actions: Action[] | undefined, fn: (expr: string) => void): void {\n forEachActionIn(actions, (a) => {\n if (a.do === 'setVar' || a.do === 'setParam') fn(a.value)\n else if (a.do === 'setIndex') { fn(a.value); fn(a.index) }\n else if (a.do === 'fillVar') { fn(a.count); fn(a.value) }\n else if (a.do === 'if') fn(a.cond)\n else if (a.do === 'repeat') fn(a.count)\n else if (a.do === 'repeatRange') { fn(a.from); fn(a.to) }\n else if (a.do === 'call') for (const arg of a.args) fn(arg)\n else if (a.do === 'send' && a.payload?.kind === 'expr') fn(a.payload.expr)\n else if (a.do === 'send' && a.payload?.kind === 'record') for (const f of a.payload.fields) fn(f.expr)\n })\n}\n\n/** The channel bindings and modifier targets carried by one item. */\nexport function forEachItemExpression(it: Item, fn: (expr: string, channel: string) => void): void {\n if (!isPoseable(it)) return\n if (it.expressions) for (const k of Object.keys(it.expressions)) { const e = it.expressions[k as keyof typeof it.expressions]; if (e) fn(e, k) }\n if (it.modifiers) for (const ch of EXPR_CHANNELS) { const m = it.modifiers[ch]; if (m) fn(m.target, ch) }\n}\n\n/**\n * The per-frame expressions a LEAF carries in its CONTENT rather than in a channel: a dynamic text's\n * `bind`, a text-on-path's animated `start`/`spacing`, a shape's `draw`/`from` stroke extent. They pose\n * nothing — so they are not channels, and `forEachItemExpression` (whose channel list is part of the\n * manifest contract) leaves them alone — but they READ variables every frame. Anything asking \"what does\n * this program read\" has to see them, or a variable used only by a `bind` reads as dead.\n */\nexport function forEachLeafExpression(it: Item, fn: (expr: string) => void): void {\n if (isText(it)) {\n if (it.bind) fn(it.bind)\n if (it.textPath?.startExpr) fn(it.textPath.startExpr)\n if (it.textPath?.spacingExpr) fn(it.textPath.spacingExpr)\n return\n }\n if (isRegion(it)) {\n if (it.drawExpr) fn(it.drawExpr)\n if (it.drawFromExpr) fn(it.drawFromExpr)\n }\n}\n\n/** Every EXPRESSION text of the Doc: channel bindings, modifier targets and leaf content expressions\n * (scene + symbols, nested groups AND the material of animated layers included), plus everything the\n * actions carry. */\nexport function forEachExpression(doc: Doc, fn: (expr: string) => void): void {\n const visit = (items: Item[]): void => {\n for (const it of items) {\n forEachItemExpression(it, (e) => fn(e))\n forEachLeafExpression(it, fn)\n if (isGroup(it)) for (const l of it.layers) { visit(l.items); visitCels(l) }\n }\n }\n // A cel (animated) layer keeps its material in the keyframes, not in `items` — a `draw \"<expr>\"` on a\n // shape that lives on such a layer is only reachable there.\n const visitCels = (l: Layer): void => { for (const c of l.cels ?? []) for (const r of c.matter ?? []) forEachLeafExpression(r, fn) }\n for (const l of doc.layers) { visit(l.items); visitCels(l) }\n for (const s of doc.symbols ?? []) for (const l of s.layers) { visit(l.items); visitCels(l) }\n for (const i of doc.interactions ?? []) forEachActionExpression(i.actions, fn)\n for (const f of doc.functions ?? []) if (f.kind === 'proc') forEachActionExpression(f.body, fn)\n for (const t of [doc.timeline, ...(doc.symbols ?? []).map((s) => s.timeline)]) {\n if (!t) continue\n forEachActionExpression(t.onLoad, fn)\n forEachActionExpression(t.onEnterFrame, fn)\n for (const fa of t.frameActions ?? []) forEachActionExpression(fa.actions, fn)\n }\n}\n\n/** Every named item of the scene tree, with the layers it owns. Positions are deliberately NOT part of\n * this: what a host needs to honour is the set of NAMES, never where the file happens to place them. */\nexport function forEachNamedItem(layers: Layer[], fn: (it: Item) => void): void {\n for (const l of layers) for (const it of l.items) {\n fn(it)\n if (isGroup(it)) forEachNamedItem(it.layers, fn)\n }\n}\n","// ─────────────────────────────────────────────────────────────────────────────\n// check.ts — `flatc --check`, as a function.\n//\n// The compiled `Doc` is NOT enough to validate a program. Two whole classes of error live in the\n// SOURCE and are gone by the time the Doc exists:\n// • statements the parser DROPS (an unknown top-level statement, a malformed line inside a block) —\n// a text that is not FlatInk at all compiles to an empty Doc that nothing distinguishes from a\n// valid one;\n// • an `object \"X\" { … }` block that binds to NOTHING (X is a shape, a layer, or absent) — the\n// binding simply never lands, and the Doc holds no trace of the attempt.\n// Both are source-level passes (`behaviorDiagnostics`, `objectTargetDiagnostics`) that the CLI ran and\n// no public call could reach: an integrator validating in a service got a verdict weaker than the same\n// file checked at the prompt, and had to shell out to `flatc` to get the real one.\n//\n// `checkProgram(src)` runs the WHOLE pass — source in, diagnostics out, no filesystem, no subprocess.\n// The CLI calls the same function, so the two cannot drift.\n// ─────────────────────────────────────────────────────────────────────────────\nimport type { Doc } from '@flatkit/types'\nimport type { TextEdit } from '@flatkit/engine/dsl'\nimport { FlatSyntaxError, behaviorDiagnostics, duplicateBindingDiagnostics, objectTargetDiagnostics, sceneOnlyUnitDiagnostics, itemOnlyUnitDiagnostics } from '@flatkit/engine/flatFormat'\nimport { compileFlatpack, type MediaMap } from './compile'\nimport { lintDoc } from './programDoc'\n\n/** One diagnostic, positioned in the AUTHOR'S source. `scope` is `scene` or `object \"Name\"`. `fix` is\n * present only when the repair is MECHANICAL -- see `TextEdit`. */\nexport type CheckDiagnostic = { scope: string; line: number; col: number; severity: 'error' | 'warning'; message: string; fix?: TextEdit }\n\nexport type CheckOptions = {\n /** Text of each `.flat` symbol library the program draws on — the CLI auto-discovers them beside the file. */\n assetSrcs?: string[]\n /** Declared media, by path (only affects the returned Doc; diagnostics do not depend on it). */\n media?: MediaMap\n}\n\nexport type CheckResult = {\n /** `false` as soon as one diagnostic is an error — the exit code of `flatc --check`. Warnings do not block. */\n ok: boolean\n errors: number\n warnings: number\n diagnostics: CheckDiagnostic[]\n /** The diagnostics as `flatc` prints them (`''` when there is nothing to say). */\n report: string\n /** The compiled program, or `null` if the parser rejected the source outright. */\n doc: Doc | null\n}\n\nconst line1 = (d: CheckDiagnostic): string => `[${d.scope}] ${d.line}:${d.col}: ${d.severity}: ${d.message}`\n\n/** The diagnostics as `flatc` prints them: one `[scope] line:col: level: message` per line. */\nexport const formatDiagnostics = (diagnostics: CheckDiagnostic[]): string => diagnostics.map(line1).join('\\n')\n\n/** The two SOURCE-level passes, which read the author's text rather than the compiled Doc. Always errors. */\nfunction sourceDiagnostics(src: string): CheckDiagnostic[] {\n return [...behaviorDiagnostics(src), ...objectTargetDiagnostics(src), ...sceneOnlyUnitDiagnostics(src), ...itemOnlyUnitDiagnostics(src)]\n .map(({ scope, diag }) => ({ scope, line: diag.line, col: diag.col, severity: 'error' as const, message: diag.message, ...(diag.fix ? { fix: diag.fix } : {}) }))\n}\n\n/** Statements that belong to the COMPOSITION half — they are only legal inside `scene { … }`. */\nconst COMPOSITION = new Set(['group', 'layer', 'rect', 'circle', 'ellipse', 'path', 'text', 'image', 'instance', 'mask'])\n\nconst UNEXPECTED = /^unexpected statement \"([a-z]+)\"/\n\n/**\n * One missing `scene { … }` produces one error per composition line — measured at 72 on a 75-line file,\n * and not one of them contains the word `scene`. Every message is accurate: at that point `group` really\n * is not expected. But they describe the SYMPTOM, and the repair pass they are fed cannot infer the cause\n * from seventy-two of them, so it returns the same program. Collapse them into the cause, once.\n *\n * Only when the block is genuinely absent — with a `scene` present, each precise position is what helps.\n */\nfunction collapseMissingScene(diagnostics: CheckDiagnostic[], src: string): CheckDiagnostic[] {\n if (/^[ \\t]*scene[ \\t]*\\{/m.test(src)) return diagnostics\n const stray = diagnostics.filter((d) => COMPOSITION.has(UNEXPECTED.exec(d.message)?.[1] ?? ''))\n if (!stray.length) return diagnostics\n // Once composition is loose at the root, every parse-level complaint in that scope is a knock-on of\n // the same omission — the braces the block would have owned, the lines it would have contained.\n // Semantic findings (an unknown variable, a dead global) are NOT knock-ons and are left alone.\n const knockOn = diagnostics.filter((d) => d.severity === 'error' && /^unexpected statement |^declaration expected/.test(d.message))\n const words = [...new Set(stray.map((d) => UNEXPECTED.exec(d.message)![1]))]\n const first = stray[0]\n const cause: CheckDiagnostic = {\n scope: first.scope,\n line: first.line,\n col: first.col,\n severity: 'error',\n message:\n `${words.map((w) => `\\`${w}\\``).join(', ')} ${words.length > 1 ? 'are SCENE declarations' : 'is a SCENE declaration'}, ` +\n `and this program has no \\`scene { … }\\` block. Composition lives inside it; everything after it is behavior. ` +\n `Wrap the ${stray.length} statement(s) it rejected: \\`scene {\\\\n layer \"art\" { … }\\\\n}\\`.`,\n }\n return [cause, ...diagnostics.filter((d) => !knockOn.includes(d))]\n}\n\n/** `size W H` declared anywhere at the start of a line — the program's canvas. */\nconst SIZE_HEADER = /^[ \\t]*size[ \\t]+-?[\\d.]+[ \\t]+-?[\\d.]+/m\n\n/**\n * A program that never declares `size`. The line is REQUIRED by the format, yet the compiler defaults it\n * to 800x600 without a word — so a document laid out for another canvas is drawn on the wrong one and\n * everything past its edge is clipped away in silence. That silence is not theoretical: a generator\n * omitted the line across its entire corpus for months, undetected. A WARNING rather than an error,\n * because checking a fragment on its own is a legitimate thing to do.\n */\nfunction missingSizeDiagnostic(src: string, doc: Doc): CheckDiagnostic | null {\n if (SIZE_HEADER.test(src)) return null\n return {\n scope: 'scene',\n line: 1,\n col: 1,\n severity: 'warning',\n message: `no \\`size W H\\` line — it is the REQUIRED first statement of a program, and this document silently defaults to ${doc.width}x${doc.height}. Anything laid out past that edge is clipped with nothing to say so. Declare the canvas you drew for.`,\n }\n}\n\n/**\n * Every diagnostic of a program that HAS compiled: the source-level passes, then the semantic lint of the\n * whole Doc (read against `src`, so positions point into the author's file). Exact-duplicate lines are\n * dropped — a scene parse error is legitimately seen by both paths, which now both read the source.\n */\nexport function programDiagnostics(doc: Doc, src: string): CheckDiagnostic[] {\n const out: CheckDiagnostic[] = []\n const seen = new Set<string>()\n const push = (d: CheckDiagnostic) => { const k = line1(d); if (!seen.has(k)) { seen.add(k); out.push(d) } }\n for (const d of sourceDiagnostics(src)) push(d)\n const noSize = missingSizeDiagnostic(src, doc)\n if (noSize) push(noSize)\n for (const { scope, diag } of duplicateBindingDiagnostics(src)) push({ scope, line: diag.line, col: diag.col, severity: 'warning', message: diag.message })\n for (const { scope, diag } of lintDoc(doc, src)) push({ scope, line: diag.line, col: diag.col, severity: diag.severity === 'warning' ? 'warning' : 'error', message: diag.message, ...(diag.fix ? { fix: diag.fix } : {}) })\n // Collapse LAST: the same \"unexpected statement\" is reported by the source pass and by the Doc lint,\n // so folding one of them alone leaves the other's copy behind.\n return collapseMissingScene(out, src)\n}\n\nconst tally = (diagnostics: CheckDiagnostic[], doc: Doc | null): CheckResult => {\n const errors = diagnostics.filter((d) => d.severity === 'error').length\n return { ok: errors === 0, errors, warnings: diagnostics.length - errors, diagnostics, report: formatDiagnostics(diagnostics), doc }\n}\n\n/**\n * Check a `.flatink` program — the same pass as `flatc --check`, on a string. Never throws: a source the\n * parser rejects outright comes back as a diagnostic with `doc: null`, not an exception.\n *\n * ```ts\n * const { ok, report } = checkProgram(srcFromAnLLM)\n * if (!ok) regenerate(report) // the report is the repair prompt\n * ```\n */\nexport function checkProgram(src: string, opts: CheckOptions = {}): CheckResult {\n let doc: Doc\n try {\n doc = compileFlatpack(src, opts.assetSrcs ?? [], opts.media ?? {})\n } catch (e) {\n // A `FlatSyntaxError` knows where it happened and sometimes how to repair itself; anything else still\n // lands at the top of the file rather than inventing coordinates.\n const f = e instanceof FlatSyntaxError ? e : null\n return tally([{ scope: 'scene', line: f?.line ?? 1, col: f?.col ?? 1, severity: 'error', message: `compile error: ${(e as Error).message}`, ...(f?.fix ? { fix: f.fix } : {}) }], null)\n }\n return tally(programDiagnostics(doc, src), doc)\n}\n\n/** Applies every MECHANICAL repair a diagnostic carries, and returns the new source with how many landed.\n * Bottom-up so earlier positions stay valid, and overlapping edits are skipped rather than merged --\n * two fixes touching one line means at least one was computed against text the other rewrote.\n *\n * A multi-line replacement inherits the INDENTATION of the line it replaces: the parser knows the shape\n * of the repair, not how deep the author nests. This is the one rule to know about the output.\n *\n * Meant to run BEFORE handing a failing program back to a model: a missing comma should not cost a whole\n * regeneration. Re-check the result -- `applyFixes` never claims the program is now valid, only that the\n * edits it knew about were applied. */\nexport function applyFixes(src: string, diagnostics: CheckDiagnostic[]): { text: string; applied: number } {\n const lines = src.split('\\n')\n const edits = diagnostics\n .map((d) => d.fix)\n .filter((f): f is TextEdit => !!f)\n .sort((a, b) => b.line - a.line || b.col - a.col)\n let applied = 0\n const touched = new Set<number>()\n for (const e of edits) {\n // A position this text cannot honour is SKIPPED, never applied blind. The diagnostics may have been\n // stored, replayed against a file that moved on, or built by a consumer -- and a non-positive column\n // reaches `slice` as an offset FROM THE END, which silently truncates the line instead of failing.\n if (!Number.isInteger(e.line) || !Number.isInteger(e.endLine) || !Number.isInteger(e.col) || !Number.isInteger(e.endCol)) continue\n if (e.line < 1 || e.col < 1 || e.endCol < 1 || e.endLine > lines.length) continue\n if (e.endLine < e.line || (e.endLine === e.line && e.endCol < e.col)) continue\n let overlaps = false\n for (let l = e.line; l <= e.endLine; l++) if (touched.has(l)) overlaps = true\n if (overlaps) continue\n const indent = /^[ \\t]*/.exec(lines[e.line - 1])![0]\n const body = e.replacement.split('\\n').map((l, i) => (i === 0 ? l : indent + l)).join('\\n')\n const head = lines[e.line - 1].slice(0, e.col - 1)\n const tail = lines[e.endLine - 1].slice(e.endCol - 1)\n lines.splice(e.line - 1, e.endLine - e.line + 1, ...(head + body + tail).split('\\n'))\n for (let l = e.line; l <= e.endLine; l++) touched.add(l)\n applied++\n }\n return { text: lines.join('\\n'), applied }\n}\n\n/** Applies the mechanical repairs until nothing is left to apply, and returns the FINAL text. Pure: it\n * takes a `recheck` and never touches the filesystem, which is the whole guarantee -- the caller writes\n * once, at the end, a text this loop has already re-checked. Writing each pass and reverting on failure\n * would leave a window where the author's file holds a version we already know we do not want.\n *\n * It ITERATES because repairing one error unmasks the next (a run-on interactor line swallows the\n * statements under it), and it accepts a pass only if the error count strictly DROPS -- except that the\n * count legitimately RISES on the first pass of a source that did not parse at all, where a single error\n * was all that was visible. That case never reaches here: it is handled before the Doc exists. */\nexport function repairLoop(\n src: string,\n diagnostics: CheckDiagnostic[],\n recheck: (candidate: string) => CheckDiagnostic[],\n maxPasses = 5,\n): { text: string; applied: number; first: number; errors: number } {\n const errs = (ds: CheckDiagnostic[]) => ds.filter((d) => d.severity === 'error').length\n const first = errs(diagnostics)\n let text = src, applied = 0, errors = first, current = diagnostics\n for (let pass = 0; pass < maxPasses; pass++) {\n const step = applyFixes(text, current)\n if (!step.applied) break\n let after: CheckDiagnostic[]\n try { after = recheck(step.text) } catch { break } // the repair broke the parse outright -> keep the last accepted text\n if (errs(after) >= errors) break\n text = step.text; applied += step.applied; errors = errs(after); current = after\n }\n return { text, applied, first, errors }\n}\n"],"mappings":"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","names":["isGroup","isText","isPoseable","isRegion","EXPR_CHANNELS","parseUnits","isGroup","isPoseable","EXPR_CHANNELS","names","isRegion","isText","indent"]}
|