Skip to content

Latest commit

 

History

History
396 lines (352 loc) · 27.7 KB

File metadata and controls

396 lines (352 loc) · 27.7 KB

File structure

Top-level layout

Path Purpose
README.md Project overview and quick start
AGENTS.md AI agent coding rules and pointers
CLAUDE.md Claude Code rule manifest (loads style docs)
VERSION CalVer version string
LICENSE.LGPL_v3 Code license
LICENSE.CC_BY_4_0 Content license
build_github_pages.sh Canonical production build into dist/
run_web_server.sh Build then serve dist/ on local network
check_codebase.sh Aggregate lint, typecheck, and test gate
run_fast_checks.sh Umbrella fast gate: build, check_codebase.sh, pytest, content validation (no browser sweep)
run_playwright_tests.sh Front door for every browser test: build as needed, then run npx playwright test against playwright.config.ts (.spec.ts files, including the protocol walker sweep spec)
source_me.sh Bash environment for Python 3.12
package.json Node dev dependencies and npm scripts
tsconfig.json Repo-root TypeScript compiler config (strict)
tsconfig.lint.json Wider typecheck covering tests/ and tools/
playwright.config.ts Playwright test-runner config: testDir: tests/playwright, testMatch: **/*.spec.ts, single chromium project, webServer builds then serves dist/ on one shared random port for every worker
pip_requirements-dev.txt Python dev dependencies (pytest, pyflakes)
eslint.config.js ESLint flat config
REPO_TYPE Repo type marker (typescript)

Key subtrees

src/ - Authored TypeScript runtime

Browser entry points, scene runtime, and shell HUD. All authored; nothing under src/ is generated.

src/
+- dist_entry.tsx              -- bundle entry; DOM-presence router
+- launcher_entry.tsx          -- launcher bundle entry
+- protocol_host_entry.tsx     -- protocol-host bundle entry
+- protocol_host.tsx           -- wires pipeline, renderer, step machine, HUD
+- index.html                  -- bench page (smoke target)
+- scene_viewer_template.html  -- scene viewer HTML template (copied to dist/scene_viewer.html)
+- style.css                   -- stylesheet (copied to dist/)
+- launcher/
|  +- index.html               -- launcher HTML page
|  +- Launcher.tsx             -- Solid protocol-selector component
|  `- main.tsx                 -- launcher Solid mount
+- scene_runtime/
|  +- layout/                  -- multi-pass layout pipeline
|  |  +- run_pipeline.ts       -- top-level pipeline runner
|  |  +- types.ts              -- PipelineResult, ComputedItem, layout types
|  |  +- constants.ts          -- DEFAULT_VIEWPORT, shrink factor
|  |  +- phases.ts              -- phase registry: named phase sequence with read/mutate boundaries
|  |  +- geometry/              -- pure 2D AABB geometry core (no layout state)
|  |  |  +- types.ts            -- Vector, Aabb, Collision, ResolutionCandidate value types
|  |  |  `- collision.ts        -- aabbFromBounds, detectCollision, buildResolutionCandidate, sortResolutionOrder
|  |  +- config/                -- LayoutConfig resolution (global defaults -> scene -> zone -> strategy)
|  |  |  +- types.ts            -- LayoutConfig and related config types
|  |  |  +- resolve_config.ts   -- config precedence resolver
|  |  |  `- index.ts            -- barrel export
|  |  +- diagnostics/           -- severity-graded typed diagnostics and decision metadata
|  |  |  +- severity_model.ts   -- Error / Warning / Review-required severity types
|  |  |  +- payload.ts          -- typed diagnostic payload shapes
|  |  |  +- decision_metadata.ts -- per-scene decision metadata (strategy, packer, shrink, config)
|  |  |  +- offcanvas.ts        -- off-canvas classifier: fully_off_canvas / partial_overflow (report-only, never gates)
|  |  |  `- index.ts            -- barrel export
|  |  +- strategies/            -- PlacementStrategy seam and implementations
|  |  |  +- placement_strategy.ts -- PlacementStrategy interface
|  |  |  +- row_strategy.ts     -- default row strategy
|  |  |  +- pack_strategy.ts    -- overflow packer (engages below threshold or on overflow)
|  |  |  `- index.ts            -- barrel export
|  |  `- (bind_objects, normalize_schema, resolve_inheritance, scale_to_real_world,
|  |      group_by_zone, horizontal_layout, vertical_layout, layout_labels,
|  |      clamp_scene_bounds, footprint, wrap_label, index).ts
|  +- protocol/                -- step machine and protocol drivers
|  |  +- affordance.ts         -- pure affordance-kind mapping (compute_affordance_kind, affordance types)
|  |  +- gesture_registry.ts   -- GESTURE_REGISTRY: per-gesture affordance contract + dispatch_gesture, scene_click_to_command
|  |  +- resolve_entry_scene.ts -- entry-scene resolution + empty-scene guard
|  |  +- target_adapter.ts     -- protocol-target -> DOM identity adapter (resolve_to_placement/object, AmbiguousTargetError)
|  |  +- flatten_sequence_runner.ts -- flattens a sequence_runner into its constituent mini-protocol steps
|  |  +- step_machine.ts       -- pure step machine (no DOM)
|  |  +- validators.ts         -- interaction and step validator dispatch
|  |  +- authored_value_check.ts -- load-time authored-value guard for target_with_value / final_state_matches
|  |  +- gesture_affordance_check.ts -- load-time invariant: authored gesture must be registered + wired (UnaffordancedGestureError)
|  |  +- target_existence_check.ts -- load-time invariant: authored target must exist in the scene
|  |  +- scene_operations.ts   -- routes the five SceneOperation primitives to injected store-backed deps
|  |  +- scene_op_deps.ts      -- SceneOpDeps interface + store-backed factory
|  |  +- walker_debug.ts       -- debug helpers for walkthrough evidence collection
|  |  +- click_resolver.ts     -- DOM click -> step machine
|  |  `- emitter.ts            -- ProtocolShellEmitter, RuntimeEmitterHandle
|  +- state/                   -- Solid signal store for shared scene state
|  |  `- scene_store.ts        -- createSceneStore: object state signals + updaters
|  `- renderer/                -- Solid DOM rendering from PipelineResult
|     +- render_scene.tsx      -- public Solid mount facade (mounts SceneView)
|     +- affordance_candidates.ts -- renderer-layer candidate enumeration (enumerate_candidate_targets)
|     +- scene_view.tsx        -- Solid SceneView (bg, items, labels, guards)
|     +- scene_item.tsx        -- Solid SceneItem (per-item + missing-svg placeholder)
|     +- visual_state_resolver.ts -- state + visual_states -> renderable description
|     +- render_background.ts  -- background (gradient or asset)
|     +- structural_guards.ts  -- six layout validation guards
|     +- inject_svg.ts         -- inline SVG injection from ASSET_SPECS
|     +- svg_manifest_loader.ts -- runtime SVG manifest fetch/cache layer
|     `- index.ts              -- barrel: renderScene, mountScene, SceneView, SceneItem
`- shell/
   +- adapter/
   |  `- types.ts              -- closed seam: ProtocolConfig, ShellViewSnapshot, events, ops
   +- signals.ts               -- Solid signal helpers + subscribeEmitterToSnapshot
   +- hud/
   |  +- ProtocolHud.tsx       -- mounts four region components into named DOM targets
   |  +- type_input.tsx        -- visible type-input affordance (data-type-input / data-type-commit)
   |  `- set_point_editor.tsx  -- shared numeric set-point editor for the adjust gesture (data-adjust-input / data-adjust-commit)
   `- regions/
      +- StepOutline.tsx       -- read-only ordered step cards
      +- TipsBubble.tsx        -- professor-tip bubble
      +- StepCounter.tsx       -- completed/total counter
      `- GuidanceBar.tsx       -- current-step prompt

The framed interface uses six named DOM regions in src/protocol_host_template.html: header (tips + counter), scene (bounded 16:9 panel), outline (step list), and guidance (teal prompt bar). #shell-root is a sibling of #scene-root, never an ancestor.

pipeline/ - Codegen and build scripts

Every script that emits to generated/, assembles bundles, or produces dist/ artifacts. Invoked by package.json pre-hooks and build_github_pages.sh.

File Purpose
gen_object_library.py content/objects/ YAML -> generated/object_library.ts
gen_svg_manifest.py assets/**/*.svg -> generated/svg_manifest.ts (asset_name -> relative file path)
gen_scene_index.py Scene YAML -> generated/scenes.ts + generated/scene_manifest.json; `--missing-svg=strict
gen_protocols.py Protocol YAML -> generated/protocols.ts + generated/protocols_index_slim.ts + generated/protocol_materials.ts (per-protocol material registry from each package materials.yaml)
entity_decode.py Codegen helper: decode_entities() maps authored HTML entities (µ etc.) to Unicode glyphs at emit time; imported by gen_protocols.py and gen_object_library.py so generated/** carries the glyph while source stays ASCII
gen_flow_view.py Protocol YAML -> generated/flow_views/<protocol_name>.txt, a per-protocol audit view (click path, gestures, state changes, transitions); not the design source, see PROTOCOL_AUTHORING_GUIDE.md
build_protocol_index.py Protocol index build helpers
list_protocols.py Reads PROTOCOLS_INDEX; emit writes one dist/<name>.html per protocol
scene_inheritance.py Scene YAML inheritance resolution library (imported by gen_scene_index)
build_main_bundle.mjs esbuild Node API: bundles launcher and protocol-host entries
precompute_layout.mjs Runs the layout engine for every scene at canonical 16:9 (1920x1080) -> generated/precomputed_layout.ts ({ final: ComputedItem[] } per scene). Runs after build_generated.sh.

content/ - Authored YAML

All authored YAML; nothing under content/ is generated or gitignored.

content/
+- objects/                    -- reusable object definitions by kind
|  +- bottle/, equipment/, flask/, pipette/, plate/, rack/, waste/, decoration/
+- base_scenes/                -- shared base scenes (bench, hood, microscope, etc.)
+- protocols/
|  +- cell_culture/            -- cell culture mini-protocols and runners
|  +- sdspage/                 -- SDS-PAGE mini-protocols and runners
|  `- runners/                 -- sequence-runner protocols
+- objects_quarantine/         -- quarantined objects pending restoration review
`- base_scenes_quarantine/     -- quarantined base scenes pending restoration review

Each mini-protocol folder contains:

content/protocols/<cluster>/<protocol_name>/
+- protocol.yaml               -- protocol_type, entry_step, learning block, steps
+- materials.yaml              -- material definitions for this protocol
`- scenes/                     -- per-protocol scene YAML overrides

validation/ - YAML and scene validators

Standalone Python validators. Entry point: validate.py.

validation/
+- validate.py                 -- aggregate entry: runs every validation stage
+- yaml_schema/                -- schema + cross-field rules for protocol, object, scene YAML
+- stepper/                    -- step-flow walker: simulates execution, checks semantics
+- svg/                        -- SVG asset usage audit
+- manual/                     -- human-readable protocol manual renderer
+- scene_lint/                 -- pre-render failure predictor (Group A BLOCKED, Group B advisory)
+- scene_design/               -- composition scorecard (weighted metrics, advisory only)
+- scene_calc/                 -- thin loader of rendered geometry (stats.json) for lint and design; no layout math
+- structure/                  -- layout structural check
`- shared_toolkit/             -- discovery, YAML I/O, findings, reporter, CLI helpers

tests/ - Test suite

Three tiers isolated by conftest.py (collect_ignore = ["e2e", "playwright"]).

tests/
+- conftest.py                 -- pytest config; collect_ignore for e2e and playwright
+- test_*.py                   -- fast pytest: pyflakes, ASCII, indent, shebang, imports, etc.
+- test_*.mjs                  -- Node unit tests (run by node --import tsx --test)
+- TESTS_README.md             -- test-suite overview
+- file_utils.py           -- shared REPO_ROOT helper
+- e2e/                        -- non-browser E2E runners (e2e_*.py, e2e_*.sh)
`- playwright/                 -- browser-driven tests, runner model (@playwright/test)
   +- repo_root.mjs            -- shared REPO_ROOT resolver
   +- smoke.spec.ts            -- broadest test: launcher loads, a protocol card opens a scene
   +- test_*.spec.ts           -- runner specs (framed layout, initial scene, etc.)
   +- helper_*.mjs / .tsx      -- non-test support (scene discovery, render harnesses)
   `- e2e/                     -- full-path walkthroughs
      `- protocol_walkthrough.spec.ts  -- one test() per curriculum protocol (native
                                          Playwright workers) plus a wrong-order negative test

playwright.config.ts (repo root) owns testDir: tests/playwright, testMatch: **/*.spec.ts, and the shared webServer (builds then serves dist/ on one random port for every worker). run_playwright_tests.sh is the front door for every browser test (npx playwright test); super_all_tests.sh's browser step is a single call to it.

Key pytest files:

File Purpose
test_pyflakes_code_lint.py Pyflakes lint gate
test_ascii_compliance.py ASCII source check
test_markdown_links.py Markdown link validity
test_shebangs.py Shebang consistency
test_import_dot.py Forbids relative imports
test_import_requirements.py Third-party imports declared
test_test_naming_conventions.py Test layout and naming
test_spec_docs_no_camelcase_yaml.py Spec doc camelCase gate
test_walker_no_step_branches.py Walker must not branch on step name

Key Node test files:

File Purpose
test_layout_engine.mjs Layout pipeline unit tests
test_step_machine.mjs Step machine unit tests
test_structural_guards.mjs Structural guard unit tests
test_resolve_entry_scene.mjs Entry-scene resolution unit tests
test_visual_state_resolver.mjs Visual-state resolver (formulas, materials, missing-svg)
test_scene_operations.mjs Scene operations unit tests
test_protocol_emitter.mjs Emitter unit tests
test_shell_signals.mjs Shell signal binding tests
test_m2_integration.mjs M2 framed-layout integration
test_material_color.mjs D3 resolver contract: all resolve_color_result success and failure cases
test_subpart_visual_state_renderer.mjs Subpart material-tint renderer: dispatch predicate, fill, transparent empty, degrade path
test_scene_store.mjs Scene store: getSubpartStateField accessor, per-well independent reactivity
test_material_acceptance_cross_layer.mjs Cross-layer acceptance: stepper D1 and TS runtime store accept and reject the same material names
tests/test_layout_offcanvas.mjs Off-canvas classifier unit tests (exercises PipelineResult.offCanvasDiagnostics fully_off_canvas and partial_overflow paths)
tests/test_layout_config.mjs Config-precedence unit tests: 16 behavioral tests covering zone_gap split, scene-level and zone-level overrides, and strategy-local values

assets/ - Source SVG art

assets/equipment/ contains tracked source SVG files for all lab objects. Sidecar *.colormap.json files group element ids for the recolor pipeline. Processed by gen_svg_manifest.py.

tools/ - Developer-only helpers

Scripts that do not appear in any build chain. See CODE_ARCHITECTURE.md for the full list.

Key tools:

File Purpose
tools/normalize_svg_v3.py SVG ingestion-gate normalizer (lxml + tinycss2 + shapely): normalize-or-reject pipeline; run before adding any SVG to assets/; see CODE_ARCHITECTURE.md for support contract and ingestion workflow
svg_to_html_render.mjs Renders an SVG on five color swatches via Playwright Firefox and writes <stem>_render.{html,png} to CWD; use --no-open to skip auto-open
svg_identity_sweep.py Perceptual-hash duplicate/mislabel sweep over assets/**/*.svg; emits a review report
svg_feature_census.py Read-only feature census over the wild SVG corpus (OTHER_REPOS/); counts clipPath/transform/text/etc. per file, cross-tabbed against the v3 verdict; emits docs/active_plans/reports/svg_feature_census.{json,md}
tools/layout_golden_diff.mjs layout:diff / layout:refresh -- ephemeral regression harness; captures a gitignored snapshot at test-results/layout_reference_snapshot.json with provenance and staleness detection; compares engine output after a change
tools/layout_metrics.mjs layout:metrics -- raw per-scene geometry metrics (rectangle-union fill, largest-empty-rect, occupancy, scale proxies, AABB overlap graph, balance) with per-scene overlay
tools/layout_health_report.mjs layout:health -- interprets raw geometry metrics into provisional health categories and a worst-first author scorecard; writes test-results/layout_health/
tools/offcanvas_baseline.mjs Writes docs/active_plans/audits/offcanvas_baseline.md (per-scene off-canvas item counts from PipelineResult.offCanvasDiagnostics)

devel/ - Maintainer scripts

File Purpose
setup_playwright.sh Idempotent Playwright (chromium) install
setup_typescript.sh TypeScript dev environment setup
dist_clean.sh Wipe generated/ and dist/
rotate_changelog.py Changelog rotation (keeps two newest day blocks)
query_changelog.py Changelog search by date, category, keyword
commit_changelog.py Draft commit message from new changelog entries
bump_version.py Version bump helper
ai_polish_review.mjs AI visual-polish reviewer over before/after scene screenshots

docs/ - Documentation

File Purpose
NEWS.md Curated release highlights and announcements
CHANGELOG.md Chronological record of changes
CODE_ARCHITECTURE.md System design, components, and data flow
FILE_STRUCTURE.md This file
INSTALL.md Prerequisites and setup
USAGE.md Build and run instructions
AUTHORS.md Maintainers and contributors
ROADMAP.md Planned work
TODO.md Backlog scratchpad
E2E_TESTS.md E2E test conventions
PLAYWRIGHT_USAGE.md Playwright browser-test usage
PYTEST_STYLE.md Pytest conventions
PYTHON_STYLE.md Python conventions
TYPESCRIPT_STYLE.md TypeScript conventions
MARKDOWN_STYLE.md Markdown formatting rules
REPO_STYLE.md Repo-wide conventions
LAYOUT_REMAINING_WORK.md Scene-by-scene layout and aesthetic remaining work reference
PRIMARY_CONTRACT.md Hard design invariants
PRIMARY_DESIGN.md Design philosophy
PRIMARY_SPEC.md Technical specification
CLAUDE_HOOK_USAGE_GUIDE.md Claude Code permissions hook reference
specs/PROTOCOL_VOCABULARY.md Canonical protocol vocabulary
specs/PROTOCOL_YAML_FORMAT.md Protocol YAML schema reference
specs/PROTOCOL_AUTHORING_GUIDE.md Worked authoring example
specs/PROTOCOL_STEPS.md Step-flow architecture
specs/SCENE_VOCABULARY.md Canonical scene vocabulary
specs/SCENE_YAML_FORMAT.md Scene YAML schema reference
specs/SCENE_ARCHITECTURE.md Scene wiring and runtime
specs/SCENE_METRICS.md Scene-author guide to the layout health report
SCENE_LAYOUT_BASELINE.md Committed, hand-refreshed layout health/diagnostics snapshot taken after the failBuild gate went live
specs/OBJECT_VOCABULARY.md Canonical object vocabulary
specs/OBJECT_YAML_FORMAT.md Object-definition YAML schema reference
specs/LAYOUT_ENGINE.md Layout-engine placement reference
specs/MATERIAL_DESIGN.md Design rationale for scalar color, transparent empty, and the separate identity/amount layers
specs/MATERIAL_VOCABULARY.md Canonical material terms, the settled sentinel/visible classification, and the D1 predicate entry point
specs/MATERIAL_YAML_FORMAT.md materials.yaml schema: entry keys, scalar display_color hex format, D1 predicate, closed-key rule, sentinel exemption
specs/MATERIAL_CONVENTION.md Runtime render-effect and target convention, color resolver typed result, SVG anchor contract, and recolor model
MATERIAL_LINT.md Validator and audit surface: lint rules L1-L10, D3 resolver contract, cross-YAML agreement rule, and validator hook table
specs/SVG_PIPELINE.md SVG asset ownership and pipeline
specs/SCALING_MODEL.md Scaling model notes
specs/WALKTHROUGH_GUIDE.md Real-browser protocol walkthrough guide
specs/SPEC_DESIGN_CHECKLIST.md Author YAML vocabulary lock checklist
active_plans/ In-flight plan documents (active, audits, reports, decisions, workstreams)
archive/ Archived plans and design notes

Generated artifacts

All gitignored (see .gitignore):

Path Source script
generated/object_library.ts gen_object_library.py
generated/svg_manifest.ts gen_svg_manifest.py
generated/svg_placeholder_keys.ts gen_svg_manifest.py (build/test-only placeholder key array)
generated/scenes.ts gen_scene_index.py
generated/scene_manifest.json gen_scene_index.py (per-scene classification, source of truth for scene tooling)
generated/protocols.ts gen_protocols.py
generated/protocols_index_slim.ts gen_protocols.py
generated/protocol_materials.ts gen_protocols.py (per-protocol material registry; keyed by protocol_name)
generated/flow_views/<protocol_name>.txt gen_flow_view.py (per-protocol audit view; not the design source)
generated/precomputed_layout.ts precompute_layout.mjs (PRECOMPUTED_LAYOUT: per-scene { final: ComputedItem[] } at canonical 16:9)
generated/scene_render_stats/<scene>.stats.json renderer-produced scene geometry stats (build evidence consumed by SCENE-LINT/SCENE-DESIGN), written by build_github_pages.sh via scene_to_png.mjs
dist/ build_github_pages.sh (GitHub Pages bundle)
dist/assets/svg/<category>/<name>.svg SVG assets copied by build_github_pages.sh
dist/scene_viewer.html Copied from src/scene_viewer_template.html during build
test-results/ Playwright screenshots and reports
test-results/scenes/<scene>.png, test-results/scenes/summary.json optional human artifacts (PNG screenshots and run report), written only with node tools/scene_to_png.mjs --all --png
node_modules/ npm install output

The generated/ tree is rebuilt from current YAML and SVG sources on every build. Do not place authored files there.

Documentation map

Question Document
How is the system designed? CODE_ARCHITECTURE.md
Where does each file live? This file
What are the hard rules? PRIMARY_CONTRACT.md
What is the YAML schema? specs/PROTOCOL_YAML_FORMAT.md, specs/SCENE_YAML_FORMAT.md, specs/OBJECT_YAML_FORMAT.md
How do I author a protocol? specs/PROTOCOL_AUTHORING_GUIDE.md
How do I set up the repo? INSTALL.md
How do I run the game? USAGE.md
What is planned next? ROADMAP.md and TODO.md

Where to add new work

Type Location
New mini-protocol content/protocols/<cluster>/<name>/ with protocol.yaml, scenes/, materials.yaml
New base scene content/base_scenes/<name>.yaml
New lab object content/objects/<kind>/<name>.yaml
New SVG asset assets/equipment/<name>.svg (run tools/normalize_svg_v3.py first; plus optional <name>.colormap.json)
New pipeline generator pipeline/ (register in package.json pre-hooks; update these two docs)
New shell region src/shell/regions/ (mount in src/shell/hud/ProtocolHud.tsx)
New runtime module src/ (imported from entry or scene runtime)
New validation rule validation/yaml_schema/ or validation/scene_lint/
Fast pytest test tests/test_*.py
Node unit test tests/test_*.mjs
Playwright browser test tests/playwright/*.spec.ts (runner model; see playwright.config.ts)
Full-path walkthrough tests/playwright/e2e/*.spec.ts
Non-browser E2E tests/e2e/e2e_*.py or tests/e2e/e2e_*.sh
Developer utility tools/ (never pipeline/)
Documentation docs/ with SCREAMING_SNAKE_CASE filename
Spec vocabulary docs/specs/
Active plans docs/active_plans/active/, audits/, reports/, decisions/, or workstreams/