Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions .github/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
# scorebench release
# scorebench v0.3.4

scorebench is the agent-native workbench for scorekit: a Tauri desktop shell for chat-driven scene authoring, scorekit validation/rendering, project-local memory, and WebAudio playback/visualization.
## Highlights

scorekit remains an external runtime dependency. On first launch, scorebench reports its discovered path, doctor status, machine-readable version compatibility, and scorekit-provided installation hints.
- Adds **蜃景 · Mirage**, a music-reactive cinematic particle imagery with a
72,000-sample gold orbital band, slowly rotating procedural planet,
travelling blue-violet streams, asynchronously twinkling stars, a
steel-blue spectrum landscape, restrained ship motion, volumetric engine
trails, foreground parallax dust, and beat-driven energy pulses.
- Keeps the focal layers clean: the opaque planet occludes the far ring,
planet/ring glow no longer compounds into a glassy atmosphere, shockwaves
fade independently instead of becoming a permanent halo, and the planet
surface separates oceans, continents, lakes, and sparse warm lights without
line primitives.
- Adds a deterministic Mirage showcase harness, dynamics tests, registry
coverage, and a dedicated client-bundle budget.
- Moves the application contract to ScoreKit 0.7, including exact clips,
deterministic automation, independent percussion tracks, live renderer
profile certification, stricter orchestration schema validation, and richer
scene observation.

The release is created as a draft for manual review and publication. Verify `SHA256SUMS` and platform signing/notarization status before publishing. Publishing the release triggers the Homebrew cask update when `HOMEBREW_TAP_TOKEN` is configured.
## Verification

- Frontend type checking and 164 Vitest tests pass.
- The production build and bundle gate pass; Mirage is 33.1 KiB raw / 10.5 KiB
gzip inside its reviewed ceiling.
- Rust formatting, strict Clippy, 179 unit tests, and the Tauri-boundary
integration test pass.

ScoreKit remains an external runtime dependency and is not bundled. On first
launch, scorebench reports its discovered path, doctor status, machine-readable
version compatibility, and ScoreKit-provided installation hints.
15 changes: 11 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
run: cargo test

scorekit-contract:
name: ScoreKit 0.6 contract
name: ScoreKit 0.7 contract
runs-on: ubuntu-latest
steps:
- name: Check out scorebench
Expand All @@ -66,8 +66,8 @@ jobs:
uses: actions/checkout@v5
with:
repository: talkincode/scorekit
# v0.6.0 release commit; pin the immutable contract, not a moving branch.
ref: 5cea04fb75764480e18759674aae4cb8d917a518
# v0.7.0 release commit; pin the immutable contract, not a moving branch.
ref: 9a2c7b0be3e42c91a80c1f4d6c3b028b30828a0a
path: .scorekit-contract

- name: Install native dependencies
Expand All @@ -87,13 +87,20 @@ jobs:
- name: Build pinned ScoreKit
run: cargo build --locked --manifest-path .scorekit-contract/Cargo.toml

- name: Install contract SoundFont
run: >-
make -C .scorekit-contract install-default-soundfont
SCOREKIT_SOUND_LIBRARY_DIR=${{ github.workspace }}/.scorekit-sounds
SCOREKIT_DEFAULT_SOUNDFONT_SOURCE=${{ github.workspace }}/.scorekit-contract/assets/TimGM6mb.sf2

- name: Run non-skippable ScoreKit contract
env:
SCOREBENCH_SCOREKIT: ${{ github.workspace }}/.scorekit-contract/target/debug/scorekit
SCOREBENCH_REQUIRE_SCOREKIT_CONTRACT: "1"
SCOREKIT_SOUND_LIBRARY_DIR: ${{ github.workspace }}/.scorekit-sounds
run: >-
cargo test --manifest-path src-tauri/Cargo.toml
scorekit_06_contract_tools_query_live_capabilities -- --nocapture
scorekit_07_contract_tools_query_live_capabilities -- --nocapture

frontend:
name: Frontend
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ vite.config.ts.timestamp-*
/examples/mood-demo/main.js
/examples/armor-material-lab/main.js
/examples/voyage-demo/main.js
/examples/mirage-demo/main.js

# Per-machine workspace path overrides (see scorekit-workspace.json in the scorekit repo)
scorekit-workspace.local.json
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ The API endpoint, model, context budget, and API key are configured from the in-
`src-tauri/tauri.conf.json` is the application-version source of truth:

```bash
npm run version:set -- 0.1.1
git commit -am "Release 0.1.1"
git tag v0.1.1
git push origin main v0.1.1
npm run version:set -- 0.3.4
git commit -am "Release 0.3.4"
git tag v0.3.4
git push origin main v0.3.4
```

Version tags build macOS (`aarch64` and `x86_64`), Windows, and Linux installers, generate `SHA256SUMS`, and assemble a draft GitHub release. Publishing that release updates the Homebrew cask in `talkincode/homebrew-tap` when `HOMEBREW_TAP_TOKEN` is configured. Apple signing/notarization activates when its repository secrets are present; local and non-macOS builds do not require those secrets. scorekit is discovered at runtime and is installed as a Homebrew cask dependency, but is not bundled.
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/arrangement-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,4 @@ Brief: “Oppressive underground-ruin exploration with an occasional distant ech
| Combat | Restore drums, raise tempo and intensity, and retain the motif |
| Continuous identity | Share motifs and harmony across sections and pass the same material between instruments |

If a brief requires a capability the protocol does not have—such as independent harmony per section, arbitrary automation curves, or free per-note articulation—state the limitation instead of adding imaginary YAML fields.
If a brief requires a capability the protocol does not have—such as independent harmony per section, renderer-specific synth parameters, or free per-note articulation—state the limitation instead of adding imaginary YAML fields. Portable CC1/CC11/CC74/pitch-bend motion belongs in an exact event clip and must follow the live schema.
46 changes: 40 additions & 6 deletions docs-site/src/scene-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,15 @@ tracks:
| `loop` | Whether the output is a seamless loop | Default `false` |
| `harmony` | One Roman-numeral chord per bar | Cycles until the scene ends |
| `motifs` | Named melodic material | Referenced by `melody` tracks |
| `clips` | Stable-ID exact pitched/percussion events and automation | Referenced by `clip` tracks; map order is inert |
| `performance` | Swing, legato, dynamics, and deterministic humanization | Optional |
| `tracks` | Instrument tracks | 1–16, with at most one drum track |
| `tracks` | Instrument tracks | 1–16; at most 15 melodic tracks, while percussion tracks share channel 10 |
| `textures` | Scheduled ambience, field recordings, and sound effects | Optional; portable source names are resolved by a separate texture profile |
| `sections` | Named cues that share the scene's material | Optional; build emits one output per section |

ScoreKit currently builds diatonic triads from the scene scale. Roman-numeral case is conventional: `VI` and `vi` select the same scale degree in the current protocol. This field is not a complete classical-harmony notation system.

## Tracks and the six patterns
## Tracks and the seven patterns

Every track selects an `instrument` and a `pattern`, and carries a stable scene-local `id`:

Expand All @@ -89,18 +90,51 @@ Every track selects an `instrument` and a `pattern`, and carries a stable scene-
| `arpeggio` | Eighth notes in root–third–fifth–third order | Motion, piano or harp figures |
| `bass` | Low roots derived from the current chord | Low-frequency foundation |
| `drums` | A fixed kick, snare, and hi-hat groove | Basic pulse; must use `instrument: drums` |
| `tabla` | A deterministic tabla groove | World-percussion pulse; must use `instrument: tabla` and still obey the single-percussion-track rule |
| `clip` | Plays a named exact event sequence | Authored syncopation, fills, auxiliary percussion, and controller motion |
| `tabla` | A deterministic tabla groove | World-percussion pulse; must use `instrument: tabla` |

Tracks can also define:

- `id`: a stable identifier matching `[a-z][a-z0-9_-]{0,63}`. Required; referenced by section `mute` lists, stems, and MIDI's `--solo` selector — never a positional index, so reordering tracks never breaks a reference.
- `palette`: an optional logical orchestration palette name. Absent uses the active orchestration's `default_palette`; irrelevant when not building with `--renderer sfizz --orchestration ...`. Routing metadata only — it never changes compiled MIDI.
- `intensity`: velocity scaling from 0.0 to 1.0.
- `articulation`: `sustain`, `staccato`, `spiccato`, `pizzicato`, `tremolo`, or `mute`. It selects SFZ samples only; SF2 backends ignore it.
- `clip`: required only for `pattern: clip`; names a compatible root clip.
- `pan`: 0.0 hard left, 0.5 center, 1.0 hard right, compiled to MIDI CC10.
- `reverb`: a 0.0–1.0 MIDI CC91 send. An SFZ patch responds only if it maps the controller.
- `glide`: on `melody` tracks only, the fraction of each note tail that bends toward the next pitch.

Several `drums` or `tabla` tracks may share channel 10 while keeping independent MIDI tracks and stems. Shared-channel `pan` and `reverb` values must agree. ScoreKit 0.7 also exposes exact General MIDI `clavinet` and `synth_brass` identities.

## Exact event clips and automation

Clip, event, lane, and point keys are stable semantic IDs. Reordering them does not change MIDI or semantic diffs:

```yaml
clips:
filtered_stab:
kind: pitched
length_beats: 4
mode: loop
events:
stab_1: { at: 0.5, duration: 0.25, pitch: C4, velocity: 104 }
stab_2: { at: 2.5, duration: 0.25, pitch: Eb4, velocity: 98 }
automation:
filter:
target: cc74
interpolation: linear
points:
closed: { at: 0, value: 16 }
open: { at: 2, value: 112 }
seal: { at: 3.75, value: 16 }
tracks:
- { id: stab, instrument: synth_brass, pattern: clip, clip: filtered_stab }
```

Clips are `pitched` or `percussion`, and play `once` or `loop`. Pitched events use scientific pitch plus duration; percussion events use ScoreKit's frozen General MIDI voice enum. Automation targets are `cc1`, `cc11`, `cc74`, and `pitch_bend`; interpolation is `step` by default or deterministic `linear` on a fixed 60-tick grid.

Loop clips must divide every active scene or section. Events stay inside the clip boundary, and loop automation must return to its initial value. Clip timing ignores swing, legato, and humanization, while track/section intensity and dynamics still scale velocity. For sfizz, the effective leaf profile must declare every active control, and `scorekit profile check` must certify that the patch responds.

## Motifs and scale degrees

A motif is a list of `{ degree, beats }` entries:
Expand Down Expand Up @@ -149,7 +183,7 @@ sources:
library: field-recordings@1.0.0
```

ScoreKit 0.6 also accepts the old path-only binding for build compatibility, but discovery and certification require the structured form. The Agent queries the active profile with exact `inspect_textures` filters before choosing a source; `no_match` means it must change the plan, not invent a key. The observation panel reports missing mappings and a `loop`/`one_shot` mode not declared by the source before build. ScoreKit still performs authoritative validation and mixing. Enabling stems produces aligned texture stems alongside instrument stems.
ScoreKit 0.7 retains the old path-only binding for build compatibility, but discovery and certification require the structured form. The Agent queries the active profile with exact `inspect_textures` filters before choosing a source; `no_match` means it must change the plan, not invent a key. The observation panel reports missing mappings and a `loop`/`one_shot` mode not declared by the source before build. ScoreKit still performs authoritative validation and mixing. Enabling stems produces aligned texture stems alongside instrument stems.

## Performance

Expand Down Expand Up @@ -181,13 +215,13 @@ sections:
- { name: victory, bars: 4, loop: false, mute: [foundation], intensity: 1.1 }
```

A section can change `bars`, `tempo`, `loop`, and overall `intensity`, or silence tracks through the **stable track `id`s** listed in `mute`. Sections inherit the top-level key, harmony, motifs, tracks, and performance. The current protocol cannot replace harmony or motif contents per section.
A section can change `bars`, `tempo`, `loop`, and overall `intensity`, silence tracks through the **stable track `id`s** listed in `mute`, or replace a clip track with `clips: { track_id: clip_id }`. Sections inherit the top-level key, harmony, motifs, clips, tracks, and performance. The current protocol cannot replace harmony or motif contents per section.

## What does not belong in the scene protocol

- SoundFont, SFZ, renderer, orchestration, and recording paths. They belong in build parameters, orchestration/renderer profiles, or texture profiles; scene textures use portable source keys.
- Arbitrary `mood`, `danger`, or `avoid` fields without compile semantics. Keep them in the conversation or `story`.
- Plugin chains, mastering, equalization, or post-processing instructions.
- Arbitrary MIDI events, automation curves, or free-form per-note editing outside the schema.
- Renderer-specific synth parameters, arbitrary MIDI outside the exact-clip protocol, or free-form per-note articulation.

For the complete current field ranges and instrument enum, run `scorekit schema` instead of copying an old list, or consult the [ScoreKit Scene Protocol](https://talkincode.github.io/scorekit/scene-protocol.html).
4 changes: 3 additions & 1 deletion docs-site/src/sound-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Before adopting a custom SF2, remember:
- `articulation` does not switch an SF2 to pizzicato, spiccato, or another sample set. Only SFZ profiles use that field.
- A license may permit music made with a library while forbidding redistribution of the original samples or instrument file.

ScoreKit 0.6's scene vocabulary includes world identities such as `erhu`, `pipa`, `guzheng`, `dizi`, `tabla`, `oud`, `ney`, and `duduk`. They validate as musical identities but do not have an exact General MIDI program, so an SF2 fallback is intentionally rejected. `shakuhachi`, `shamisen`, and `sitar` do have exact GM programs. Run `scorekit inspect-instruments scene.yaml --json` before promising any world identity; use an orchestration with an exact source when the default SF2 cannot provide one.
ScoreKit 0.7's scene vocabulary includes world identities such as `erhu`, `pipa`, `guzheng`, `dizi`, `tabla`, `oud`, `ney`, and `duduk`. They validate as musical identities but do not have an exact General MIDI program, so an SF2 fallback is intentionally rejected. `shakuhachi`, `shamisen`, and `sitar` do have exact GM programs. Run `scorekit inspect-instruments scene.yaml --json` before promising any world identity; use an orchestration with an exact source when the default SF2 cannot provide one.

The current scorebench Render panel does not expose a custom-SoundFont picker, although the Agent/backend build interface supports a `soundfont` parameter. For a fixed project source, configure the ScoreKit sound directory or make the build workflow pass an explicit path rather than copying a large library into the repository.

Expand Down Expand Up @@ -86,6 +86,8 @@ scorekit orchestration check hybrid-cinematic.yaml
scorekit build scene.yaml --renderer sfizz --orchestration hybrid-cinematic.yaml -o out/scene.ogg
```

`schema_version` is required at the orchestration document root. ScoreKit 0.7 rejects a profile that omits it; add `schema_version: 1` rather than relying on an implicit default.

A scene track without a `palette` uses `default_palette`; a track with `palette: solo` routes through the `scoredata-chamber` profile instead, without any DSL field naming a sound source.

## Open sources worth evaluating
Expand Down
4 changes: 2 additions & 2 deletions docs-site/src/working-with-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ You do not need to know every theory term. A phrase such as “a distant memory,
## StylePack, grammar, and orchestration profile are different

- A **StylePack** is a scorebench creative preference package. Built-ins distinguish schema-legal `preferred_instruments` from descriptive `creative_concepts`; neither is the same thing as a Scene routing palette.
- A **grammar profile** is a set of measurable ScoreKit aesthetic checks, such as tempo limits, voice count, and melody rest ratio.
- A **grammar profile** is a set of measurable ScoreKit aesthetic checks, such as tempo limits, voice count, melody rest ratio, compiled percussion onsets/density, and automation activity.
- An **orchestration profile** routes each scene track's logical `palette` (or the orchestration's `default_palette`) to a leaf renderer profile mapping ScoreKit instruments and articulations to local SFZ files for sfizz.
- A **texture profile** maps portable ambience and sound-effect source names to local audio files, independently of the renderer.

StylePack influences choices, grammar checks the compiled music, an orchestration profile controls instrumental timbre per track, and a texture profile binds scheduled recordings. A creative concept must be translated into live-schema instruments; a Scene `palette` may only name a key from the active orchestration. None of these layers replaces the others.
StylePack influences choices, grammar checks the compiled music, an orchestration profile controls instrumental timbre per track, and a texture profile binds scheduled recordings. A creative concept must be translated into live-schema instruments; a Scene `palette` may only name a key from the active orchestration. Exact clips remain portable score semantics, not renderer parameters. When a clip automates an sfizz patch, the leaf profile must declare the control and ScoreKit's profile check must certify that the patch actually responds. None of these layers replaces the others.

## Project files and recovery

Expand Down
Loading
Loading