Skip to content

feat(visualize): scene-graph contract, four renderers, and skill surface - #21

Open
harrymove-ctrl wants to merge 10 commits into
docs/visualize-skill-designfrom
feat/visualize-skill
Open

harrymove-ctrl wants to merge 10 commits into
docs/visualize-skill-designfrom
feat/visualize-skill

Conversation

@harrymove-ctrl

Copy link
Copy Markdown
Contributor

Implements deliverable 1 of the cmk:visualize design, up to but not including the dogfood pass.

Base branch is docs/visualize-skill-design, not main. This is stacked on #20 so the design docs stay in their own review. Retarget to main once #20 merges.

What this is

cmk:visualize renders a codebase as a map you can discuss with an agent. The model's only output is a validated JSON scene graph; fixed renderers draw it. Citations are enforced by the validator, so an uncited node or edge cannot reach a picture.

What is here

  1. The contract. scene-graph.schema.json plus validate.mjs. Enforces the eight top-level fields, rejects any node or edge with an empty citations array, rejects edges naming unknown nodes, pins the folded and gaps item shapes, and caps nesting depth at 3.
  2. Four renderers over one dataset. renderSvg for static output, renderHtml for interactive, with isometric, flat, and three-d projections. Both refuse to render an invalid document and report the validation errors instead.
  3. The skill surface. SKILL.md at 66 lines, references/analysis.md, references/scene-graph.md, eval.json, TESTS.md.
  4. A test harness. Node 22's built-in runner, wired as npm test and added to Frontend CI. Zero new dependencies.

This is the kit's first code-carrying skill. The renderer bundle is vanilla, offline, and build-free, because cmk:agent-vendors forbids a package referencing anything outside itself.

What is NOT here

Task 6 of the plan: the real scene graph of this repo, and registration in lib/skills.ts and the plugin manifest. The skill therefore does not yet appear on /skills, and nothing has pointed it at a real codebase yet. That is the next commit, not a follow-up ticket.

Defects found and fixed during implementation

All five were defects in the plan, not in the execution:

  1. node --test <dir> does not work; Node treats a bare directory as an entry point. Replaced with a glob.
  2. The validator ignored repo, diagramType, and altitude though the schema declared them required. A document omitting all three returned valid: true.
  3. JSON.stringify(doc) was embedded raw inside a <script> tag. Any label or snippet containing </script truncated the payload, killed the interactive page, and opened a script-injection path. Verified broken and then verified fixed in a real browser against a hostile document.
  4. The style projections lived inside a browser-side string no test could execute, so making all three identical would have left every test green.
  5. The folded and gaps item shapes were unspecified in schema, validator, and docs, so a differently-keyed entry validated cleanly and rendered undefined into the explainer panel.

Deferred, recorded not dropped

  1. A tautological assertion in one regression test, beside a real parse-based one that does the work.
  2. No fallback for projections[doc.style]. Deliberately not added: a silent fallback would mask the drift it guards against.
  3. No test exercises a nested child graph missing top-level fields at depth > 0.

Verification

38/38 tests, ESLint clean, tsc --noEmit clean, skill-lint: OK, npm run build green.

Beyond the suite, the interactive renderer was checked in a real browser: clicking a dot shows the payload snippet with its own file:line, the three projections produce measurably different geometry (three-d compresses column spacing from 150px to 132px between rows while flat holds at 150px), and the rendered page makes zero external requests.

TESTS.md contains no results. The pressure-test runs have not been performed, and the file says so rather than presenting invented ones.

hien-p added 10 commits August 19, 2026 02:21
Reviewer found validateSceneGraph never checked doc.repo, doc.diagramType,
or doc.altitude despite the schema declaring all three required, so a
document omitting them passed as valid. Enforce them following the
existing error-message style, and make the schema drift test actually
call validateSceneGraph for every schema-required field instead of only
comparing hardcoded literals.
The scene-graph payload was embedded via raw JSON.stringify, so a node
label, citation, or sample containing the literal substring </script>
would truncate the script element early: JSON.parse fails client-side,
the inspector/dots/click wiring never runs, and the remainder of the
payload becomes a live executing script (injection).

Add an exported embedJson helper that escapes < as \u003c (still
valid JSON, round-trips exactly) and use it at the one call site.
Add a regression test that renders a label containing </script>,
extracts the embedded payload, and asserts it parses back to the
original content.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants