Skip to content

Commit b996dd9

Browse files
mbreiserclaude
andcommitted
docs: update CLAUDE.md for Experiment Designer v0.8
Update architecture docs, editor tabs, shared helpers, YAML export, filmstrip lane view, and key implementation notes for v0.8 changes. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 1775a89 commit b996dd9

1 file changed

Lines changed: 34 additions & 14 deletions

File tree

CLAUDE.md

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -438,14 +438,18 @@ The following UI improvements were made on 2026-02-02 and need testing on GitHub
438438

439439
## Experiment Designer
440440

441-
### Architecture (v0.6 — 2026-04-01)
442-
- 3-zone layout: settings panel (280px left), editor with tab bar (flex right), timeline (bottom strip)
441+
### Architecture (v0.8 — 2026-04-08)
442+
- 3-zone layout: settings panel (280px left), editor with tab bar (flex right), filmstrip with lane view (bottom)
443443
- Single `<script type="module">` importing from `js/arena-configs.js`, `js/protocol-yaml.js`, `js/plugin-registry.js`
444444
- Data model: `experiment` object with `experiment_info`, `arena_info`, `rig_path`, `plugins[]`, `experiment_structure`, phases with `commands[]`, and `conditions[]` with `commands[]`
445445

446446
### Shared Modules
447447
- **`js/protocol-yaml.js`** — YAML parser (`simpleYAMLParse` with inline comment stripping), v1/v2 generators, string helpers. Dual-export (window.ProtocolYAML + ES6 module). Used by HTML, both test files.
448+
- `yamlStr(str)` — double-quotes strings for YAML
449+
- `yamlPath(str)` — single-quotes paths (no escape sequences, safe for Windows backslashes)
448450
- **`js/plugin-registry.js`** — Built-in plugin definitions (LEDControllerPlugin: 7 commands, BiasPlugin: 6 commands), controller command definitions (6 commands), lookup functions for dropdown population. Dual-export.
451+
- Plugin config fields use `rigDefined: true` for fields already in rig YAML (ip, port) — these are NOT auto-included in exports
452+
- `createPluginEntry()` skips fields with empty string defaults
449453

450454
### Data Model (v2 commands)
451455
Conditions and phases use **command arrays** as the primary data model:
@@ -470,37 +474,53 @@ experiment.rig_path = "./configs/rigs/test_rig_1.yaml"
470474
```
471475
Helper functions: `cmdFindTrialParams(commands)`, `condGetDuration(cond)`, `condGetPattern(cond)`, `phaseGetDuration(phase)`.
472476

477+
**Shared command helpers** (used by Commands tab, Table view, and phase editor):
478+
- `buildAddCommandOptions()` — returns HTML `<option>`/`<optgroup>` string for add-command dropdowns
479+
- `createCommandFromSelectValue(value)` — parses `"controller:trialParams"` / `"wait:wait"` / `"plugin:backlight:setRedLEDPower"` into a command object
480+
- `createPluginCommand(pluginName, commandName)` — builds plugin command with default params from registry schema
481+
473482
### YAML Export (v2)
474483
- Generates protocol v2 via `generateV2Protocol()` from `js/protocol-yaml.js`
475484
- `rig:` field replaces inline `arena_info`
476-
- `plugins:` section lists enabled plugins with class/config
485+
- **Paths use single quotes** via `yamlPath()` (pattern_library, rig, script_path) — prevents Windows backslash escape issues
486+
- `plugins:` section lists enabled plugins with class/config — only user-set config values are exported (empty = omit)
477487
- Conditions export full command arrays including plugin commands with params
478488
- Phases export command arrays directly
479489

480490
### Editor Tabs
481-
Three tabs in the right panel, all views of the same data model:
482-
1. **Visual** — Command card editor with color-coded cards (green=controller, gray=wait, blue=plugin), inline field editing, "Add Command" dropdown from plugin registry
483-
2. **Table** — Spreadsheet view with collapsible sections (pretrial, conditions with ITI, posttrial), type badges, param display
484-
3. **Timeline** — SVG multi-lane visualization per condition: controller spans, plugin event markers, wait bars, time axis. Read-only with hover tooltips.
491+
Two tabs in the right panel, both views of the same data model:
492+
1. **Commands** (was "Visual" in v0.6) — Command card editor with color-coded cards (green=controller, gray=wait, blue=plugin), inline field editing, "Add Command" dropdown, up/down reorder arrows, delete buttons
493+
2. **Table** — Fully editable spreadsheet view with collapsible sections, inline field editing, add/move/delete commands, condition reorder/remove, Expand All/Collapse All buttons
494+
495+
### Bottom Filmstrip + Lane View
496+
The bottom timeline area is a unified scroll container:
497+
- **Block strip**: Colored blocks (green=condition, gray=phase, dark=ITI) with drag-to-reorder conditions
498+
- **Lane view**: Always-visible SVG showing controller spans (green bars), plugin events (blue dots), and wait bars (gray) across all blocks
499+
- **Fixed lane labels**: Left column (70px) with lane names stays visible during scroll
500+
- Block strip and lane SVG share the same scroll parent for perfect alignment
501+
- Block widths use `Math.max(48, duration * pxPerSecond)` — lane SVG must match this + account for 2px CSS gap between blocks
502+
- Clicking any filmstrip block switches to the Commands tab
485503

486504
### Key Implementation Notes
487505
- **Must use `<script type="module">`** to import shared modules
488506
- Mode 2 (Constant Rate): `gain` fixed at 0, `frame_rate` editable
489507
- Mode 4 (Closed-Loop): `frame_rate` fixed at 0, `gain` editable
490-
- `handleTrackClick` must explicitly call `renderTimelineView()` and `renderTableView()` after `renderEditor()` to keep all tabs in sync
491-
- Timeline `computeLaneData()`: trialParams fires controller autonomously (doesn't advance clock), wait advances clock, plugin commands are instantaneous
508+
- `handleTrackClick` calls `switchEditorTab('commands')` then `renderEditor()` — always shows Commands tab on block click
509+
- `computeLaneData()`: trialParams fires controller autonomously (doesn't advance clock), wait advances clock, plugin commands are instantaneous
510+
- **Phase initialization must deep-clone**: `{ include: false, commands: JSON.parse(JSON.stringify(DEFAULT_PHASE.commands)) }` — shallow spread shares the commands array reference
511+
- Plugin config uses `setPluginConfig()` helper that deletes empty values and removes config object when empty
492512

493513
### Related Files
494-
- `experiment_designer.html` — Main tool (v0.6)
495-
- `experiment_designer_quickstart.html` — Step-by-step guide
496-
- `js/protocol-yaml.js` — Shared YAML parser/generator
497-
- `js/plugin-registry.js` — Plugin definitions + command schemas
514+
- `experiment_designer.html` — Main tool (v0.8)
515+
- `experiment_designer_quickstart.html` — Step-by-step guide (v0.8)
516+
- `js/protocol-yaml.js` — Shared YAML parser/generator (added `yamlPath`)
517+
- `js/plugin-registry.js` — Plugin definitions + command schemas (updated defaults)
498518
- `tests/test-protocol-roundtrip.js` — 130 CI checks (9 suites, v1+v2)
499519
- `tests/generate-roundtrip-protocol.js` — YAML + manifest generator for MATLAB
500520
- `tests/fixtures/v2_*.yaml` — V2 YAML test fixtures from maDisplayTools
501521
- `docs/experiment-designer-v06-testing.md` — Manual testing checklist
502522
- `docs/protocol-roundtrip-testing.md` — Roundtrip testing architecture
503-
- GitHub Issue: [#33](https://github.com/reiserlab/webDisplayTools/issues/33)
523+
- GitHub Issues: [#33](https://github.com/reiserlab/webDisplayTools/issues/33), [#53](https://github.com/reiserlab/webDisplayTools/issues/53) (hover tooltips), [#54](https://github.com/reiserlab/webDisplayTools/issues/54) (undo/redo)
504524

505525
## Planning Best Practices
506526

0 commit comments

Comments
 (0)