Skip to content

feat(web): in-browser chunk.json capture tool (ADR-0026) - #67

Merged
PhysShell merged 7 commits into
mainfrom
claude/modest-maxwell-0zecwn
Jun 17, 2026
Merged

feat(web): in-browser chunk.json capture tool (ADR-0026)#67
PhysShell merged 7 commits into
mainfrom
claude/modest-maxwell-0zecwn

Conversation

@PhysShell

@PhysShell PhysShell commented Jun 17, 2026

Copy link
Copy Markdown
Owner

What

A minimal, phone-friendly capture tool on the web playground: load a tab/MIDI → pick a track → assign rights + tags + quality + reviewer → preview phrase boundaries → download <id>.chunk.json. Collect the files and fold them into the corpus with griff manifest — no in-browser persistence or assembly.

Carves a thin, download-only path out of ADR-0024's "corpus curation / persistence on web — later" (see ADR-0026). The full S8 web curation dock (IndexedDB, split/merge/rename, boundary editing, ensemble) stays deferred.

How

  • Reuses griff-core, no schema fork. New #[wasm_bindgen] exports build_chunk_json / detect_boundaries_json call the same boundary + structure/gesture/complexity code as griff curate and serialize a real corpus::ChunkMeta via serde_json — byte-compatible with what griff manifest reads.
  • tag_palette_json feeds the tag picker from SwancoreTag::all_variants(), so the UI's labels and indices can't drift from the enum.
  • created_at/updated_at are supplied by the page, keeping the wasm a pure function of its inputs (SPEC §6 determinism).
  • Capture panel (hidden until a tab loads) across index.html / app.js / style.css.

Tests / gates

  • Strict TDD: red → green commits per AGENTS.md (failing tests committed before each pub fn).
  • build_chunk_json output round-trips back into corpus::ChunkMeta; the rights assertions pin the non-derivable provenance datum S5 requires at curation time.
  • 16/16 web tests, clippy -D warnings clean, host and wasm32-unknown-unknown release builds green.

Deploy

The capture UI reaches the live Pages site on merge to main (web.yml deploys from main).

🤖 Generated with Claude Code

https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95


Generated by Claude Code

Summary by CodeRabbit

  • New Features
    • Added a “Capture · chunk.json” panel to the web playground to generate and download per-track chunk.json metadata files.
    • Added phrase-boundary detection for the selected track, with a preview/count shown in the capture UI.
    • Added a tag palette and capture inputs for tags, quality flags, reviewer decision, rights/acquisition info, tuning, and timestamps.
  • Documentation
    • Added an Architecture Decision Record (ADR-0026) describing the minimal in-browser chunk capture workflow.

claude added 6 commits June 17, 2026 13:25
Carve a thin, download-only capture path out of ADR-0024's "corpus
curation / persistence on web — later". Two wasm-bindgen exports will
reuse griff-core (boundaries + structure/gesture/complexity) and
serialize a real corpus::ChunkMeta, so the output is byte-compatible
with what `griff manifest` reads. In-browser persistence, editing
actions, and ensemble capture remain deferred to the S8 web dock.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95
Red phase (AGENTS.md TDD): failing tests for the not-yet-written capture
functions — parse_indices, build_chunk_meta_record, chunk_to_json,
boundaries_to_json. The ChunkMeta round-trip test pins byte-compatibility
with what `griff manifest` deserializes; the rights assertions pin the
non-derivable provenance datum S5 requires at curation time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95
Two wasm-bindgen exports reuse griff-core exactly as `griff curate`:
- detect_boundaries_json(track): previews S4 phrase cuts with the same
  PPQN-scaled detector config the CLI uses.
- build_chunk_json(track, …): measures structure/gesture/complexity +
  boundaries and serializes a real corpus::ChunkMeta via serde_json, so
  the bytes are byte-compatible with what `griff manifest` reads.

created_at/updated_at are passed in, so the wasm is a pure function of
its inputs (SPEC §6 determinism). Greens the ADR-0026 capture tests:
15/15 web tests pass, clippy -D warnings clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95
Red phase: the capture UI needs the swancore tag list to label its tag
picker, and the indices must line up with what build_chunk_json parses.
Test asserts one snake_case entry per SwancoreTag::all_variants().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95
Serializes SwancoreTag::all_variants() to a JSON array of wire names so
the browser's tag picker labels and indices come from Rust, not a
hand-copied list that could drift from the enum. 16/16 web tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95
A capture section, hidden until a tab loads, annotates the selected
track with rights (status/acquisition/redistributable/notes), tags,
quality flags, cohort, and reviewer decision, previews phrase
boundaries, and downloads <id>.chunk.json via build_chunk_json — ready
to fold into the corpus with `griff manifest`.

The tag picker is populated from tag_palette_json so its labels and
indices come straight from SwancoreTag, not a hand-copied list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d298e972-9273-4fbc-9974-52a5912d1102

📥 Commits

Reviewing files that changed from the base of the PR and between 7860feb and 808ffcd.

📒 Files selected for processing (2)
  • web/static/app.js
  • web/static/index.html
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/static/index.html
  • web/static/app.js

📝 Walkthrough

Walkthrough

Adds ADR-0026 documenting a minimal download-only in-browser chunk.json capture tool. The implementation adds serde_json to the web crate, extends web/src/lib.rs with three wasm_bindgen exports (tag_palette_json, detect_boundaries_json, build_chunk_json), and adds a hidden capture panel to the web playground via HTML, CSS, and JS updates.

Changes

In-browser chunk.json capture tool (ADR-0026)

Layer / File(s) Summary
Decision record and ADR index
docs/adr/0026-web-chunk-capture-tool.md, docs/adr/README.md
ADR-0026 documents the download-only scope carve-out, the decision to reuse griff-core via wasm_bindgen with serde_json schema alignment, no IndexedDB persistence, page-supplied timestamps, deferred S8 features, and is registered in the ADR index.
WASM ChunkMeta assembly, serialization, and entrypoints
web/Cargo.toml, web/src/lib.rs
Adds serde_json dependency; adds imports for corpus/boundary types; implements source-format detection, PPQN-scaled boundary detection, index/enum parsing, and ChunkMeta assembly; serializes to pretty JSON with {"error":...} envelopes; exposes tag_palette_json, detect_boundaries_json, and build_chunk_json as wasm_bindgen exports; adds unit tests for index parsing, field mapping, serde round-trips, error envelopes, and tag palette completeness.
Browser capture panel: HTML, CSS, and JS wiring
web/static/index.html, web/static/style.css, web/static/app.js
Inserts hidden #capture section with all chunk metadata and rights form fields; adds capture panel CSS; updates wasm imports; adds DOM bindings and fileName/current state; reveals panel on file load; wires populateTagPalette, boundary detection, and chunk download handlers.

Sequence Diagram

sequenceDiagram
  participant User
  participant appjs as app.js
  participant WASM as lib.rs (wasm_bindgen)
  participant Core as griff_core

  User->>appjs: upload score file
  appjs->>WASM: tag_palette_json()
  WASM-->>appjs: palette JSON → populate multi-selects
  appjs->>appjs: unhide `#capture` panel, set default title

  User->>appjs: click "Detect Boundaries"
  appjs->>WASM: detect_boundaries_json(track)
  WASM->>Core: scale BoundaryConfig to PPQN, run boundary detection
  Core-->>WASM: phrase boundary list
  WASM-->>appjs: {"boundaries": [...]} or {"error": ...}
  appjs->>User: display bounds in `#capBounds`

  User->>appjs: click "Download chunk.json"
  appjs->>WASM: build_chunk_json(track, id, title, ..., created_at, updated_at)
  WASM->>Core: assemble ChunkMeta with boundaries, tags, rights
  Core-->>WASM: ChunkMeta
  WASM-->>appjs: {"ok": {<ChunkMeta JSON>}} or {"error": ...}
  appjs->>User: trigger <id>.chunk.json download
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PhysShell/griff#66: Adds RightsInfo and boundary filling to ChunkMeta and a manifest builder that reads the *.chunk.json files this PR produces via build_chunk_json.

Poem

🐇 Hop, hop — a little form appears,
Pick your tags, your rights, your tuning clear.
Press detect, the boundaries align,
Then download JSON — oh, how divine!
No IndexedDB, just a tidy file,
griff manifest will sort the rest meanwhile. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(web): in-browser chunk.json capture tool (ADR-0026)' accurately and concisely describes the main change—adding an in-browser chunk.json capture tool to the web playground, with ADR reference for context.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/modest-maxwell-0zecwn

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/static/app.js`:
- Around line 89-91: The capture title field (els.capTitle) is only auto-filled
when it is empty, so loading a second file leaves the previous file's title in
place. Update the file loading logic to always reset and populate the capTitle
value with the new file's name by removing the conditional check
(!els.capTitle.value) and directly assigning file.name.replace(/\.[^.]+$/, '')
to els.capTitle.value whenever a new source file is loaded.
- Around line 132-142: In the detectBoundaries() function, after successfully
parsing the WASM result and confirming there is no error in the res object,
clear the previous error message by calling capMsg() with an appropriate message
(likely an empty string or success message) before updating
els.capBounds.textContent with the new boundary detection results. This ensures
that any stale error styling or messages from previous failed detections are
cleared before displaying the successful detection feedback.

In `@web/static/index.html`:
- Around line 152-153: The elements with ids capBounds and capStatus are
dynamically updated but lack ARIA live region attributes, preventing screen
readers from announcing changes to users. Add the aria-live attribute set to
"polite" to both the capBounds output element and the capStatus paragraph
element to enable screen reader announcements of dynamic updates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 66ce0bb8-e4bd-43bd-a7bb-b7db3462aac0

📥 Commits

Reviewing files that changed from the base of the PR and between 4a9f487 and 7860feb.

📒 Files selected for processing (7)
  • docs/adr/0026-web-chunk-capture-tool.md
  • docs/adr/README.md
  • web/Cargo.toml
  • web/src/lib.rs
  • web/static/app.js
  • web/static/index.html
  • web/static/style.css

Comment thread web/static/app.js
Comment thread web/static/app.js
Comment thread web/static/index.html Outdated
- loadFile: always retitle from the newly loaded source and clear stale
  boundary/status text, so loading a second file can no longer carry the
  previous file's title into the next chunk.json (Major).
- detectBoundaries: clear any prior error message before showing the
  boundary count, so success and a stale failure can't both be on screen.
- index.html: mark #capBounds / #capStatus as polite ARIA live regions so
  screen readers announce boundary-detection and capture outcomes (Major).

Static-asset-only change; host + wasm32 builds and the 16 web tests are
unaffected. node --check passes on app.js.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TTUbGjzD8ysnVnCJnZJE95
@PhysShell
PhysShell merged commit 0063122 into main Jun 17, 2026
1 check passed
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