@flatkit/compiler 0.28.0 → 0.29.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
@@ -20,7 +20,7 @@ import {
20
20
  scopeProgram,
21
21
  scopeRegions,
22
22
  splitScopeProgram
23
- } from "./chunk-ZAQUEPIX.js";
23
+ } from "./chunk-MZ4V72XM.js";
24
24
  import "./chunk-KXKX2RMX.js";
25
25
  export {
26
26
  allScopeVariables,
@@ -465,6 +465,17 @@ function docCelLayerWarnings(doc) {
465
465
  for (const c of l.cels) for (const p of c.poses) posed.add(p.id);
466
466
  for (const id of posed) if (id.startsWith("@")) push(`layer "${l.name}": \`pose "${id.slice(1)}"\` matches no item of this layer \u2014 the pose draws nothing (roster: ${l.items.map(itemLabel).join(", ") || "empty"}).`);
467
467
  for (const it of l.items) if (isPoseable2(it) && !posed.has(it.id)) push(`layer "${l.name}": "${itemLabel(it)}" is never posed by a cel \u2014 it is never drawn. Add \`pose "${itemLabel(it)}"\` to the cels where it should show.`);
468
+ const cels = [...l.cels].sort((a, b) => a.frame - b.frame);
469
+ for (const it of l.items) {
470
+ if (!isPoseable2(it)) continue;
471
+ const at = cels.map((c) => c.poses.some((p) => p.id === it.id));
472
+ const first = at.indexOf(true);
473
+ const last = at.lastIndexOf(true);
474
+ const gap = at.findIndex((on, i) => !on && i > first && i < last);
475
+ if (gap >= 0) {
476
+ 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} \u2014 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 { \u2026 }\`), or pose it there.`);
477
+ }
478
+ }
468
479
  }
469
480
  for (const it of l.items) if (isGroup2(it)) visit(it.layers);
470
481
  }
@@ -670,11 +681,11 @@ function docHasErrors(doc, src) {
670
681
  }
671
682
 
672
683
  // src/check.ts
673
- import { behaviorDiagnostics, duplicateBindingDiagnostics, objectTargetDiagnostics } from "@flatkit/engine/flatFormat";
684
+ import { behaviorDiagnostics, duplicateBindingDiagnostics, objectTargetDiagnostics, sceneOnlyUnitDiagnostics } from "@flatkit/engine/flatFormat";
674
685
  var line1 = (d) => `[${d.scope}] ${d.line}:${d.col}: ${d.severity}: ${d.message}`;
675
686
  var formatDiagnostics = (diagnostics) => diagnostics.map(line1).join("\n");
676
687
  function sourceDiagnostics(src) {
677
- return [...behaviorDiagnostics(src), ...objectTargetDiagnostics(src)].map(({ scope, diag }) => ({ scope, line: diag.line, col: diag.col, severity: "error", message: diag.message }));
688
+ return [...behaviorDiagnostics(src), ...objectTargetDiagnostics(src), ...sceneOnlyUnitDiagnostics(src)].map(({ scope, diag }) => ({ scope, line: diag.line, col: diag.col, severity: "error", message: diag.message }));
678
689
  }
679
690
  var COMPOSITION = /* @__PURE__ */ new Set(["group", "layer", "rect", "circle", "ellipse", "path", "text", "image", "instance", "mask"]);
680
691
  var UNEXPECTED = /^unexpected statement "([a-z]+)"/;
@@ -762,4 +773,4 @@ export {
762
773
  programDiagnostics,
763
774
  checkProgram
764
775
  };
765
- //# sourceMappingURL=chunk-ZAQUEPIX.js.map
776
+ //# sourceMappingURL=chunk-MZ4V72XM.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 } 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/** 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 out.push({ line: s.line, col: s.col, message })\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 } from '@flatkit/engine/timeline'\nimport { objectNames } from '@flatkit/engine/sceneRefs'\nimport { behaviorRegions } from '@flatkit/engine/flatFormat'\nimport { itemBBox, dropZoneBounds, transformBBox } 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, 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 const allText = [...scopes(doc).map(({ editPath }) => scopeProgram(doc, editPath)), ...modTargets].join('\\n')\n for (const name of names0) {\n const m = allText.match(new RegExp(`(?<![\\\\w-])${escapeRe(name)}(?![\\\\w-])`, 'g'))\n if ((m?.length ?? 0) <= 1) 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 return out\n}\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/** 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/** 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. */\nfunction 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 = itemBBox(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 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}) — add \"wrap\"`))\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 const reportOffCanvas = (items: Item[], matrix: Transform, dynamic: boolean): void => {\n for (const it of items) {\n const isDynamic = dynamic || dynamicPos(it)\n if (!isDynamic && !(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 const tall = lines * 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(tall)} 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) for (const d of lint(r.body, ctx)) out.push({ scope: r.scope, diag: { ...d, line: d.line + r.line - 1 } })\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 } 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 === '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/** Every EXPRESSION text of the Doc: channel bindings and modifier targets (scene + symbols, nested\n * groups included), plus everything the 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 if (isGroup(it)) for (const l of it.layers) visit(l.items)\n }\n }\n for (const l of doc.layers) visit(l.items)\n for (const s of doc.symbols ?? []) for (const l of s.layers) visit(l.items)\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 { behaviorDiagnostics, duplicateBindingDiagnostics, objectTargetDiagnostics, sceneOnlyUnitDiagnostics } 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\"`. */\nexport type CheckDiagnostic = { scope: string; line: number; col: number; severity: 'error' | 'warning'; message: string }\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)]\n .map(({ scope, diag }) => ({ scope, line: diag.line, col: diag.col, severity: 'error' as const, message: diag.message }))\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 })\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 // The parser gives up without a position (it stops at the offending token, not at a line) — report it\n // at the top of the file rather than inventing coordinates.\n return tally([{ scope: 'scene', line: 1, col: 1, severity: 'error', message: `compile error: ${(e as Error).message}` }], null)\n }\n return tally(programDiagnostics(doc, src), doc)\n}\n"],"mappings":"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","names":["isGroup","isPoseable","EXPR_CHANNELS","parseUnits","isGroup","isPoseable","EXPR_CHANNELS","names"]}
@@ -3,7 +3,7 @@ import {
3
3
  formatDiagnostics,
4
4
  lintDocReport,
5
5
  programDiagnostics
6
- } from "./chunk-ZAQUEPIX.js";
6
+ } from "./chunk-MZ4V72XM.js";
7
7
  import {
8
8
  compileFlatpack,
9
9
  packToJSON
@@ -525,4 +525,4 @@ function run(argv) {
525
525
  export {
526
526
  run
527
527
  };
528
- //# sourceMappingURL=chunk-Z36EDKPW.js.map
528
+ //# sourceMappingURL=chunk-UACAURLD.js.map
package/dist/cli/flatc.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  run
3
- } from "../chunk-Z36EDKPW.js";
4
- import "../chunk-ZAQUEPIX.js";
3
+ } from "../chunk-UACAURLD.js";
4
+ import "../chunk-MZ4V72XM.js";
5
5
  import "../chunk-KXKX2RMX.js";
6
6
  export {
7
7
  run
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-Z36EDKPW.js";
3
+ } from "./chunk-UACAURLD.js";
4
4
  import {
5
5
  allScopeVariables,
6
6
  checkProgram,
@@ -23,7 +23,7 @@ import {
23
23
  scopeProgram,
24
24
  scopeRegions,
25
25
  splitScopeProgram
26
- } from "./chunk-ZAQUEPIX.js";
26
+ } from "./chunk-MZ4V72XM.js";
27
27
  import {
28
28
  compileFlatpack,
29
29
  packToJSON
package/docs/README.md CHANGED
@@ -36,7 +36,7 @@ Read in order if you're new, or jump to a topic:
36
36
 
37
37
  1. **[Getting started](getting-started.md)** — your first `.flatink`, compiled and played.
38
38
  2. **[Scene & drawing](scene-and-drawing.md)** — layers, shapes, text, images, paints, filters, transforms.
39
- 3. **[Animating a symbol](animating-symbols.md)** — the timeline/cel/pose model, `rotate`/`scale`/`spin`, pivots, tweens, easing.
39
+ 3. **[Animating with keyframes](animating-symbols.md)** — the timeline/cel/pose model, in a `.flat` symbol AND in a program scene: pivots, tweens, easing, `hold`.
40
40
  4. **[Behavior & interactions](behavior-and-interactions.md)** — events, actions, drag/drop, interactors, feedback.
41
41
  5. **[Expressions & stdlib](expressions-and-stdlib.md)** — the expression language, math, `self`/`mouse`/`time`, and the `use "…"` packages.
42
42
  6. **[Tooling](tooling.md)** — the `flatc` CLI: compile, render, headless play, gesture scripts, CI.
@@ -1,6 +1,6 @@
1
- # Animating a symbol (`.flat`)
1
+ # Animating with keyframes
2
2
 
3
- > How a `.flat` symbol moves over time: the **timeline / cel / pose** model (Flash-style), the `pose`
3
+ > The **timeline / cel / pose** model (Flash-style), the `pose`
4
4
  > keywords (`rotate`, `scale`, `opacity`, `spin`…), pivots, tweens, and how to preview the result.
5
5
  > If you only need static composition, see [Scene & drawing](scene-and-drawing.md).
6
6
 
@@ -147,6 +147,52 @@ Two other ways to author the same thing, when the drawings already exist as obje
147
147
  > `flatc --check` warns about it, and about the two sibling silent drops: a `pose "X"` naming no roster
148
148
  > item, and a roster item that no cel ever poses.
149
149
 
150
+ ## The same cels animate a PROGRAM's scene
151
+
152
+ Everything above is written with a `symbol` around it, because that is where a reusable animation lives.
153
+ It is not a restriction: **a layer inside `scene { … }` takes cels too**, and they ride the program's own
154
+ timeline. That is how you animate a title card, a staggered entrance, a slide — anything that belongs to
155
+ one document rather than to a reusable asset.
156
+
157
+ ```flatink
158
+ size 960 540
159
+ background #0f1420
160
+ timeline 24 240
161
+
162
+ scene {
163
+ layer "slide" {
164
+ group "Title" at 64,180 pivot 0,0 { layer "c" { text "Jeanne d'Arc" at 0,0 font "Georgia, serif" size 64 align left color #f3e6c8 box 700 80 } }
165
+ group "Sub" at 64,270 pivot 0,0 { layer "c" { text "Orleans, 1429" at 0,0 font "Georgia, serif" size 28 align left color #c8a24a box 500 40 } }
166
+ group "Mark" at 64,340 pivot 0,0 { layer "c" { rect 0 0 120 4 2 fill #c8a24a } }
167
+
168
+ cel 0 tween ease easeOut { pose "Title" at 64,194 opacity 0 }
169
+ cel 12 hold tween ease easeOut { pose "Title" at 64,180 opacity 1 pose "Sub" at 64,284 opacity 0 }
170
+ cel 24 hold tween ease easeOut { pose "Sub" at 64,270 opacity 1 pose "Mark" scaleX 0 }
171
+ cel 36 hold { pose "Mark" scaleX 1 }
172
+ }
173
+ }
174
+
175
+ object "Sub" {
176
+ dy = 3 * sin(clock * 1.2)
177
+ }
178
+ ```
179
+
180
+ Three things arrive in turn, each easing in, and the subtitle keeps breathing afterwards. Note what does
181
+ the work:
182
+
183
+ - **`hold` on every cel after the first.** A cel is a full snapshot, so a cel that does not pose the
184
+ title makes the title vanish. `hold` carries forward everything the cel does not mention — which for a
185
+ staggered entrance means *every* cel but the first. Forget it and elements disappear mid-run;
186
+ `--check` reports it (see [presence across cels](#presence-across-cels--a-cel-is-a-full-snapshot)).
187
+ - **Frames may be fractional.** A deck thinks in seconds: `cel 28.8` is 1.2 s at 24 fps.
188
+ - **Keyframes and expressions COMPOSE.** The cels drive `Sub`'s position and opacity; the `dy` binding
189
+ adds an offset on top of whatever the keyframe resolved. Keyframes for the choreography, expressions
190
+ for what never stops — that is the division of labour, and `dx`/`dy` exist so the second never
191
+ overwrites the first.
192
+
193
+ Written as expressions instead, that slide is three `clamp((time - t0) / dur, 0, 1)` formulas per
194
+ element, per channel — a keyframe engine, retyped. Reach for cels first.
195
+
150
196
  ## Driving a channel with an expression (`expr`)
151
197
 
152
198
  Instead of keyframes you can bind a channel to an expression on the container itself:
@@ -115,7 +115,15 @@ object "Piece" {
115
115
  ```
116
116
 
117
117
  - `drag x, y` / `dragX x` / `dragY y` — the gesture writes the position into your variables.
118
- - `{ confine to <Zone> }` clamp · `{ snap <grid> }` pixel-snap · `{ enabled <expr> }` active only while the expression ≠ 0 (a dynamic lock — no ternary needed).
118
+ - **One option per LINE** inside the block — they are statements, not a comma list:
119
+ ```
120
+ drag px, py {
121
+ confine to Board
122
+ snap 20
123
+ enabled locked == 0
124
+ }
125
+ ```
126
+ `confine to <Zone>` clamps to a named item, `snap <grid>` snaps in pixels, `enabled <expr>` is active only while the expression is not 0 (a dynamic lock — no ternary needed).
119
127
  - ⚠️ **`enabled` gates the GESTURE, not the handlers.** Once it is off the object stops being draggable, but
120
128
  `when pressed` / `when released` / `when clicked` **still fire** on it. Guard the handler body yourself
121
129
  (`when released { if done == 0 { … } }`) whenever it must run only while the gesture is live. (A `link`'s
@@ -48,7 +48,7 @@
48
48
  - `circle <cx> <cy> <r>`
49
49
  - `ellipse <cx> <cy> <rx> <ry>`
50
50
  - `rect <x> <y> <w> <h>` · `… <r>` (uniform rounded corners) · `… <rx> <ry>`
51
- No more hand-computing the k = 0.5523·r Bézier constant.
51
+ No more hand-computing the k = 0.5523·r Bezier constant.
52
52
  - **`filter` on a path**: accepted (`path "…" fill #000 filter glow 6 #fff`). No need to wrap
53
53
  in a `group` just to add a shadow/glow. (Also works on group/image/text.)
54
54
  - **`linear(angle, …)` gradient**: `0` = → (left to right), `90` = ↓ (top to bottom).
@@ -76,7 +76,14 @@
76
76
 
77
77
  ## Animation (pose / cel / timeline)
78
78
 
79
- > Full guide: **[Animating a symbol](animating-symbols.md)**. The sharp edges:
79
+ > Full guide: **[Animating with keyframes](animating-symbols.md)**. The sharp edges:
80
+
81
+ - **Cels are NOT symbol-only.** A layer inside a program's `scene { … }` takes them too, riding the
82
+ program's timeline — that is how a title card or a staggered entrance is written. Every doc example
83
+ happens to wrap them in a `symbol`, and a whole deck generator concluded they were unavailable and
84
+ hand-compiled `clamp((time - t0) / dur, 0, 1)` for every element and channel instead. Frames may be
85
+ fractional (`cel 28.8` = 1.2 s @24fps), and bindings compose on top: cels choreograph, `dx`/`dy` add
86
+ what never stops.
80
87
 
81
88
  - **`pose` rotates/scales in human units**: `pose "G" rotate 90 scale 2` — **degrees** and multipliers,
82
89
  **around the group's `pivot`**. No hand-written `matrix(cosθ, sinθ, …)`, no radians. `scaleX`/`scaleY`
@@ -112,7 +119,7 @@
112
119
  fill #e33 } }` — that IS how you author **frame-by-frame** (a new `matter` per cel; it holds until the
113
120
  next one, `morph` tweens the shape). A static element belongs on a **cel-less layer**. `--check` warns
114
121
  on all three silent drops: a bare shape in a cel layer, a `pose "X"` matching no roster item, and a
115
- roster item no cel poses. See [Animating a symbol](animating-symbols.md).
122
+ roster item no cel poses. See [Animating with keyframes](animating-symbols.md).
116
123
  - **Render order**: in an animated layer the **matter draws BEHIND the posed containers**, and
117
124
  declaration order between the matter and an animated `group` is NOT preserved. To put a static
118
125
  shape in front of an animation, give it its own **layer above** (or wrap it in a group).
@@ -129,7 +136,7 @@
129
136
  time — the object moves *inside* a fixed canvas, it does not "jump". No need for an invisible anchor.
130
137
  - **Exposed interface** (`params {}` / `states {}`): a symbol can publish typed params (color/number/bool,
131
138
  `fill <param>`) and named states (`states door { closed at 0 open at 24 }`, driven by `Name.param = open`).
132
- See [Animating a symbol](animating-symbols.md). Restyle/tune without touching internals.
139
+ See [Animating with keyframes](animating-symbols.md). Restyle/tune without touching internals.
133
140
  - **A container shows only on cels that pose it** — a cel is a full snapshot, so a container omitted from a
134
141
  cel disappears there (that's how a symbol *exits*). For a container that stays put: declare it on its own
135
142
  **cel-less layer** (always shown, declared once), or use **`cel N hold { … }`** to carry the previous
@@ -1,3 +1,4 @@
1
+ <!-- english-check-ignore-file — the sample string is deliberately accented: it is what this page is about (an embedded face rendering accented glyphs). -->
1
2
  # Embedding the player: loading embedded fonts
2
3
 
3
4
  A `.flatink` can **embed its fonts** so a deck is self-contained:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flatkit/compiler",
3
- "version": "0.28.0",
3
+ "version": "0.29.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/types": "0.28.0",
61
- "@flatkit/engine": "0.28.0",
62
- "@flatkit/player": "0.28.0"
60
+ "@flatkit/player": "0.29.1",
61
+ "@flatkit/engine": "0.29.1",
62
+ "@flatkit/types": "0.29.1"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "skia-canvas": "^3.0.8"
@@ -66,7 +66,11 @@ tint <color> <amount(0..1)> // Flash-style tint
66
66
  nohit // drawn but ignored by hit-test
67
67
  ```
68
68
 
69
- ## Animation — timeline / cel / pose (in a `symbol`)
69
+ ## Animation — timeline / cel / pose
70
+
71
+ Cels are how anything moves on a timeline, and they work in BOTH halves: inside a `symbol` (a reusable
72
+ animated asset) **and inside a program's `scene { … }`** (a title card, a staggered entrance, a slide).
73
+ Do not hand-write `clamp((time - t0) / dur, 0, 1)` per channel — that is a keyframe engine, retyped.
70
74
 
71
75
  A symbol owns a **timeline**; an animated **layer** is a track of **cels** (keyframes). Each cel lists
72
76
  the **poses** of containers declared once in the layer roster, plus (optionally) the layer's **matter**
@@ -93,6 +97,28 @@ pose "Name" [at x,y] [rotate <deg>] [scale s | scaleX sx scaleY sy]
93
97
  - `pose` units are **human**: degrees, multipliers, around the group's **`pivot`**.
94
98
  - A `pose` is a **patch**: it only overrides channels it names (keeps declared position/scale/etc.).
95
99
 
100
+ ### The same cels, in a program's scene
101
+
102
+ ```
103
+ size 960 540
104
+ timeline 24 240
105
+ scene {
106
+ layer "slide" {
107
+ group "Title" at 64,180 pivot 0,0 { layer "c" { text "Title" at 0,0 font "Georgia, serif" size 64 align left color #f3e6c8 box 700 80 } }
108
+ group "Sub" at 64,270 pivot 0,0 { layer "c" { text "Subtitle" at 0,0 font "Georgia, serif" size 28 align left color #c8a24a box 500 40 } }
109
+ cel 0 tween ease easeOut { pose "Title" at 64,194 opacity 0 }
110
+ cel 12 hold tween ease easeOut { pose "Title" at 64,180 opacity 1 pose "Sub" at 64,284 opacity 0 }
111
+ cel 24 hold { pose "Sub" at 64,270 opacity 1 }
112
+ }
113
+ }
114
+ object "Sub" { dy = 3 * sin(clock * 1.2) }
115
+ ```
116
+
117
+ - **`hold` on every cel but the first**, or a cel that does not pose an element makes it VANISH.
118
+ - **Frames may be fractional**: `cel 28.8` is 1.2 s at 24 fps — a deck thinks in seconds.
119
+ - **Keyframes and bindings COMPOSE**: cels choreograph, `dx`/`dy` add what never stops. The binding
120
+ offsets the keyframed position instead of replacing it.
121
+
96
122
  ### Frame-by-frame — one DRAWING per cel (`matter`)
97
123
 
98
124
  A cel can carry the layer's drawing in a `matter { … }` block. A new one per cel = classic cel animation:
@@ -145,7 +171,9 @@ Actions (one per line): `<var> = <expr>` · `arr[i] = <expr>` · `if/else if/els
145
171
 
146
172
  Drag & interactors (each writes into your vars; all accept `{ enabled <expr> }`):
147
173
  ```
148
- drag x, y [{ confine to <Zone> · snap <grid> · enabled <expr> }] // dragX / dragY too
174
+ drag x, y [{ confine to <Zone>
175
+ snap <grid>
176
+ enabled <expr> }] // ONE OPTION PER LINE. dragX / dragY too
149
177
  turn <angle> around <x>,<y> [{ snap <deg> }] // → <angle> in RADIANS → rotation = <angle> directly
150
178
  turnDeg <angle> around <x>,<y> [{ snap <deg> }] // → <angle> in DEGREES → pair with rotationDeg = <angle>
151
179
  trace <progress> along <Group> [{ tolerance <px> }]// follow a path → 0..1 monotone
@@ -41,7 +41,7 @@ Style: `fill #rrggbb | nofill` · `stroke #rgb <w> [cap round][join round][dash
41
41
  `fill linear(90, 0:#a, 1:#b)` (0=→,90=↓) · `fill radial(0.5,0.5,0.5, 0:#fff,1:#000)` ·
42
42
  `filter glow <blur> <color> | shadow <dx> <dy> <blur> <color> | blur <r>` · `tint <color> <amt>` · `nohit`.
43
43
 
44
- ## Animation (in a symbol): timeline / cel / pose
44
+ ## Animation: timeline / cel / pose — in a `symbol` AND in a program's `scene`
45
45
  ```
46
46
  symbol "Wheel" {
47
47
  timeline 24 24 // fps, durationFrames (loops [0,dur))
@@ -56,6 +56,10 @@ symbol "Wheel" {
56
56
  pose "Name" [at x,y] [rotate deg] [scale s | scaleX sx scaleY sy] [opacity o] [spin cw|ccw] [turns n]
57
57
  ```
58
58
  - `ease linear|easeIn|easeOut|easeInOut|cubic(a,b,c,d)` on a cel.
59
+ - **A `scene` layer takes cels too** — that is how a title card or a staggered entrance is written. Put
60
+ `hold` on every cel but the first (a cel is a full snapshot: unposed = invisible), use fractional
61
+ frames for seconds (`cel 28.8` = 1.2 s @24), and let `dx`/`dy` bindings add motion ON TOP of the
62
+ keyframes. Never hand-write `clamp((time - t0)/dur, 0, 1)` per channel.
59
63
  - States: `states door { closed at 0 open at 24 initial closed transition 12 ease easeInOut }`
60
64
  → param drives the playhead (`door=0`→f0, `door=0.5`→f12). Driven by `Name.door = open`.
61
65
  - Expr channel on a container: `group "Fan" pivot 0,0 expr rotation "turns(time)" { … }` (RADIANS).
@@ -67,7 +71,8 @@ Actions (one per line): `<var> = <expr>` · `arr[i] = <expr>` · `if/else if/els
67
71
  `repeat i from a to b {}` · `play`/`pause` · `go to frame n [and play]` · `send "evt" [, <expr> | , text("id") | , { a = <expr>, b }]` · `sound "id"`.
68
72
  Drag/interactors (write into your vars; all take `{ enabled <expr> }`):
69
73
  ```
70
- drag x, y [{ confine to <Zone> · snap <grid> }] // then USE them: x = px y = py
74
+ drag x, y [{ confine to <Zone>
75
+ snap <grid> }] // ONE OPTION PER LINE. Then USE them: x = px, y = py
71
76
  turn <angle> around x,y · trace <progress> along <Group> · reveal <progress>
72
77
  link endX,endY,target to <Group> // target = hit index 1..n (0=none), WORLD coords
73
78
  ```
@@ -76,7 +76,10 @@ Functions: `fn dist(ax,ay,bx,by) = hypot(ax-bx, ay-by)` (value) · `fn reset() {
76
76
 
77
77
  ```
78
78
  object "Piece" {
79
- drag px, py { confine to Board · snap 20 } // dragX / dragY for one axis
79
+ drag px, py {
80
+ confine to Board
81
+ snap 20
82
+ } // one option per LINE. dragX / dragY for one axis
80
83
  x = px y = py // USE the vars it writes
81
84
  when dropped on Slot at pointer { placed = 1 }
82
85
  }
@@ -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 } 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/** 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 out.push({ line: s.line, col: s.col, message })\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 } from '@flatkit/engine/timeline'\nimport { objectNames } from '@flatkit/engine/sceneRefs'\nimport { behaviorRegions } from '@flatkit/engine/flatFormat'\nimport { itemBBox, dropZoneBounds, transformBBox } 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, 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 const allText = [...scopes(doc).map(({ editPath }) => scopeProgram(doc, editPath)), ...modTargets].join('\\n')\n for (const name of names0) {\n const m = allText.match(new RegExp(`(?<![\\\\w-])${escapeRe(name)}(?![\\\\w-])`, 'g'))\n if ((m?.length ?? 0) <= 1) 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 return out\n}\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 }\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/** 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/** 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. */\nfunction 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 = itemBBox(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 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}) — add \"wrap\"`))\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 const reportOffCanvas = (items: Item[], matrix: Transform, dynamic: boolean): void => {\n for (const it of items) {\n const isDynamic = dynamic || dynamicPos(it)\n if (!isDynamic && !(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 const tall = lines * 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(tall)} 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) for (const d of lint(r.body, ctx)) out.push({ scope: r.scope, diag: { ...d, line: d.line + r.line - 1 } })\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 } 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 === '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/** Every EXPRESSION text of the Doc: channel bindings and modifier targets (scene + symbols, nested\n * groups included), plus everything the 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 if (isGroup(it)) for (const l of it.layers) visit(l.items)\n }\n }\n for (const l of doc.layers) visit(l.items)\n for (const s of doc.symbols ?? []) for (const l of s.layers) visit(l.items)\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 { behaviorDiagnostics, duplicateBindingDiagnostics, objectTargetDiagnostics } 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\"`. */\nexport type CheckDiagnostic = { scope: string; line: number; col: number; severity: 'error' | 'warning'; message: string }\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)]\n .map(({ scope, diag }) => ({ scope, line: diag.line, col: diag.col, severity: 'error' as const, message: diag.message }))\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 })\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 // The parser gives up without a position (it stops at the offending token, not at a line) — report it\n // at the top of the file rather than inventing coordinates.\n return tally([{ scope: 'scene', line: 1, col: 1, severity: 'error', message: `compile error: ${(e as Error).message}` }], null)\n }\n return tally(programDiagnostics(doc, src), doc)\n}\n"],"mappings":"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","names":["isGroup","isPoseable","EXPR_CHANNELS","parseUnits","isGroup","isPoseable","EXPR_CHANNELS","names"]}