githubnext/chopinPublic

Let's compose rich plans together

Add a bounded wireframe language parser #431

MergedMaggieAppletonmerged 2 commits intomainfromrefs/pull/431/head
  1. MA

    ## Context

    The Planner currently sketches interfaces as box-drawing text, which breaks at narrow widths and can't be styled or edited. This is the first of five PRs that add a `wireframe` fence: an indented outline of interface parts, rendered as token-styled inert DOM.

    This PR is the parser only. No editor rendering, server validation or Planner prompt changes.

    - PR 2: editor preview (`kind "wireframe"`, lazy view, light/dark tokens, invalid → plain fallback, gallery specimen) - PR 3: server validator, Planner authoring guidance ("never box-drawing art"), skill docs - PR 4: annotations and narrow-width polish for tabs, nav, image, input - PR 5: source-span selection and visual edits through the printer

    ## Language

    ```wireframe panel "Implementation" header button "Approve and build this plan" #approve primary text "Build on Laptop · 4f2a9c01" muted disclosure "0 of 2 tasks complete" open card badge "queued" tone=info title "Parse wireframe fences" list - Unknown kinds report a line number row flow card "Plan" stack card "Build" card "Test" note "Starts the run" -> #approve ```

    Each line is two-space indentation, a kind, an optional `"label"` (escapes `\"`, `\\`, `\n`), an optional `#id`, bare flags, `key=value` properties (bare or quoted), and for notes `-> #id` or `-> kind`. List-like kinds (`list`, `tabs`, `nav`) hold `- item` lines. One table in `wireframe/schema.ts` defines the label rule, children (blocks, items or none), flags and properties for each of the 17 kinds, so later PRs extend it in one place. `row flow` joins siblings with connectors; a `stack` inside it is a parallel column.

    The parser returns `{ ok: true, wireframe }` or `{ ok: false, problems: [{ line, message }] }`. Nodes carry `span: { start, end }` source lines covering their descendants. `printWireframe` writes canonical text that parses back to the same tree. `resolveWireframeTarget` finds a note's target. Everything is exported from `@chopin/diagrams` and the lightweight `@chopin/diagrams/wireframe` subpath.

    ## Bounds

    - 64 KiB source (checked before splitting), 400 parts (nodes plus items), depth 10, 200 characters per label, item or property value, 40-character ids, at most 20 problems. - Never evaluated. Each line is scanned once with no backtracking-prone patterns. Problems echo at most a short prefix of hostile tokens. User input never throws. - One problem per line. Lines under a rejected line are still checked but not attached, so one mistake doesn't cascade. - Note targets must resolve to exactly one part. An ambiguous kind target asks for an `#id` instead of guessing.

    ## Tests

    - `packages/diagrams/src/wireframe/parse.test.ts`: the Implementation sample with full spans, every problem type with line numbers, limits, adversarial input timing. - `packages/diagrams/src/wireframe/print.test.ts`: canonical fixed points, canonicalising messy source, AST equality ignoring spans, and 300 seeded generated trees that round-trip.

    `bun test`, `bun run types` and `bun run ci` pass locally. One full-suite run hit an unrelated Atomic harness timeout that passes on its own.

    🤖 Generated with [Claude Code](https://claude.com/claude-code)

  2. MaggieAppletonauto-rebase-enabledlast month on GitHub

  3. MaggieAppletonreferenced this in Validate wireframe fences and teach the Planner to write them #433last month on GitHub

  4. MaggieAppletonmerged dce9a4fa3d9alast month on GitHub

  5. MaggieAppletonclosedlast month on GitHub

  6. MaggieAppletonhead-ref-deletedlast month on GitHub

  7. MaggieAppletonreferenced this in Draw wireframe fences as chromeless, inert blueprints #436last month on GitHub