Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
7cbf155
CLI の `.mxl` / `.mscz` file I/O 対応と ZIP 処理の共通化
igapyon Apr 16, 2026
0617c7d
Merge pull request #173 from igapyon/tiga0415jcc
igapyon Apr 16, 2026
d36fe6c
CLI の UTF-8 デコードを `TextDecoder` ベースに変更し、関連ドキュメントを更新
igapyon Apr 16, 2026
94e9c21
Merge pull request #174 from igapyon/tiga0416jbj
igapyon Apr 16, 2026
204e7cb
CLI を `convert` / `render` / `state` 軸へ拡張し、`state` 初期コマンドと診断基盤を追加
igapyon Apr 17, 2026
e67da45
Merge pull request #175 from igapyon/tiga0416jde
igapyon Apr 17, 2026
9d91226
CLI 再構築を前進し、`state` selector targeting と stage-aware diagnostics を追加
igapyon Apr 17, 2026
ee97e5f
Merge pull request #176 from igapyon/tiga0417wce
igapyon Apr 17, 2026
7367d36
CLI 実装を整理し、コマンド分岐・入出力処理・diagnostics 組み立てを共通化
igapyon Apr 17, 2026
10f541b
Merge pull request #177 from igapyon/tiga0417wdj
igapyon Apr 17, 2026
35b3477
CLI 互換対応を upstream に取り込み、landing page 文言と ZIP/selector 回帰テストを更新
igapyon Apr 17, 2026
14cdc02
Merge pull request #178 from igapyon/tiga0417xbd
igapyon Apr 17, 2026
22ca78f
CLI API の selector 正規化まわりに型ガードを追加
igapyon Apr 17, 2026
d20c8ab
Merge pull request #179 from igapyon/tiga0418gbj
igapyon Apr 17, 2026
5a014ce
CLI に `abc -> midi` / `MEI` / `LilyPond` の MusicXML 相互変換を追加し、関連ドキュメント…
igapyon Apr 17, 2026
2a3df2b
Merge pull request #180 from igapyon/tiga0418gdc
igapyon Apr 17, 2026
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
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,34 @@ mikuscore is for converting, inspecting, and handing score data off.

### CLI

Current CLI is `convert`-first.
Current CLI centers on `convert`, `render`, and an initial `state` family.

For `musicxml` and `musescore`, plain-text `stdin` / `stdout` paths are handled as UTF-8 text, while `.mxl` / `.mscz` compression stays on file-path I/O.

Examples:

- `npm run cli -- convert --from abc --to musicxml --in score.abc --out score.musicxml`
- `npm run cli -- convert --from musicxml --to abc --in score.musicxml --out score.abc`
- `npm run cli -- convert --from midi --to musicxml --in score.mid --out score.musicxml`
- `npm run cli -- convert --from musicxml --to midi --in score.musicxml --out score.mid`
- `npm run cli -- convert --from mei --to musicxml --in score.mei --out score.musicxml`
- `npm run cli -- convert --from musicxml --to mei --in score.musicxml --out score.mei`
- `npm run cli -- convert --from lilypond --to musicxml --in score.ly --out score.musicxml`
- `npm run cli -- convert --from musicxml --to lilypond --in score.musicxml --out score.ly`
- `npm run cli -- convert --from musescore --to musicxml --in score.mscx --out score.musicxml`
- `npm run cli -- convert --from musicxml --to musescore --in score.musicxml --out score.mscx`
- `npm run cli -- convert --from musicxml --to abc --in score.mxl --out score.abc`
- `npm run cli -- convert --from musescore --to musicxml --in score.mscz --out score.mxl`
- `npm run cli -- convert --from musicxml --to musescore --in score.musicxml --out score.mscz`
- `npm run cli -- render svg --in score.musicxml --out score.svg`
- `npm run cli -- render svg --from abc --in score.abc --out score.svg`
- `npm run cli -- state summarize --in score.musicxml`
- `npm run cli -- state inspect-measure --measure 1 --in score.musicxml`
- `npm run cli -- state validate-command --in score.musicxml --command-file command.json`
- `npm run cli -- state apply-command --in score.musicxml --command-file command.json --out score.next.musicxml`
- `npm run cli -- state diff --before score.before.musicxml --after score.after.musicxml`

For `state validate-command` / `state apply-command`, command payloads may target notes either by `targetNodeId` / `anchorNodeId` or by `selector` / `anchor_selector` derived from `state inspect-measure`.

For CLI and development details, see `docs/DEVELOPMENT.md` and `docs/spec/CLI_STEP1.md`.

Expand Down
226 changes: 219 additions & 7 deletions TODO.md

Large diffs are not rendered by default.

56 changes: 54 additions & 2 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,27 @@ Generated HTML note:

## CLI Notes

Current CLI uses a `convert`-first command surface.
Current CLI uses a `convert` / `render` / initial `state` command surface.

Available commands:

- `mikuscore convert --from abc --to musicxml`
- `mikuscore convert --from musicxml --to abc`
- `mikuscore convert --from midi --to musicxml`
- `mikuscore convert --from musicxml --to midi`
- `mikuscore convert --from mei --to musicxml`
- `mikuscore convert --from musicxml --to mei`
- `mikuscore convert --from lilypond --to musicxml`
- `mikuscore convert --from musicxml --to lilypond`
- `mikuscore convert --from musescore --to musicxml`
- `mikuscore convert --from musicxml --to musescore`
- `mikuscore render svg`
- `mikuscore render svg --from abc ...`
- `mikuscore state summarize`
- `mikuscore state inspect-measure`
- `mikuscore state validate-command`
- `mikuscore state apply-command`
- `mikuscore state diff`

Input/output contract:

Expand All @@ -54,23 +64,59 @@ Input/output contract:
- omitted `--in` reads from `stdin`
- `--out <file>` writes to file
- omitted `--out` writes to `stdout`
- `--out -` writes to `stdout` explicitly
- text conversions use text input/output
- MIDI input/output uses binary input/output
- current MuseScore CLI scope is `.mscx`-style text, not compressed `.mscz`
- for file input, `--from musicxml` accepts `.musicxml`, `.xml`, and `.mxl`
- for file input, `--from musescore` accepts `.mscx` and `.mscz`
- for file output, `--to musicxml` writes `.mxl` when `--out` ends with `.mxl`
- for file output, `--to musescore` writes `.mscz` when `--out` ends with `.mscz`
- `stdin` / `stdout` remain text-only for `musicxml` and `musescore`
- `render svg` also accepts `--from abc` as a one-shot path while still routing internally through canonical `MusicXML`
- `state` commands operate on canonical `MusicXML`
- `state validate-command` / `state apply-command` accept command payloads that target notes either by `targetNodeId` / `anchorNodeId` or by `selector` / `anchor_selector`
- `--diagnostics text|json` is available across current command families
- plain-text CLI decode for `musicxml` / `musescore` is kept on UTF-8 `TextDecoder` rather than Node-only `Buffer`, so the same entrypoint can be runtime-compiled in isolated bundle environments
- usage failures now use a distinct CLI error path from processing failures

Examples:

- `npm run cli -- --help`
- `npm run cli -- convert --help`
- `npm run cli -- render --help`
- `npm run cli -- state --help`
- `npm run cli -- convert --from abc --to musicxml --in score.abc --out score.musicxml`
- `npm run cli -- convert --from musicxml --to abc --in score.musicxml --out score.abc`
- `npm run cli -- convert --from midi --to musicxml --in score.mid --out score.musicxml`
- `npm run cli -- convert --from musicxml --to midi --in score.musicxml --out score.mid`
- `npm run cli -- convert --from mei --to musicxml --in score.mei --out score.musicxml`
- `npm run cli -- convert --from musicxml --to mei --in score.musicxml --out score.mei`
- `npm run cli -- convert --from lilypond --to musicxml --in score.ly --out score.musicxml`
- `npm run cli -- convert --from musicxml --to lilypond --in score.musicxml --out score.ly`
- `npm run cli -- convert --from musescore --to musicxml --in score.mscx --out score.musicxml`
- `npm run cli -- convert --from musicxml --to musescore --in score.musicxml --out score.mscx`
- `npm run cli -- convert --from musicxml --to abc --in score.mxl --out score.abc`
- `npm run cli -- convert --from musescore --to musicxml --in score.mscz --out score.mxl`
- `npm run cli -- convert --from musicxml --to musescore --in score.musicxml --out score.mscz`
- `npm run cli -- render svg --in score.musicxml --out score.svg`
- `npm run cli -- render svg --from abc --in score.abc --out score.svg`
- `npm run cli -- state summarize --in score.musicxml`
- `npm run cli -- state inspect-measure --measure 12 --in score.musicxml`
- `npm run cli -- state validate-command --in score.musicxml --command-file command.json`
- `npm run cli -- state apply-command --in score.musicxml --command-file command.json --out score.next.musicxml`
- `npm run cli -- state diff --before score.before.musicxml --after score.after.musicxml`
- `state inspect-measure` output can be fed back into `state validate-command` / `state apply-command` via `selector` / `anchor_selector` payload fields
- `cat score.abc | npm run cli -- convert --from abc --to musicxml`

Observed sibling-project direction:

- `mikuproject` CLI grew in a way that intentionally resembles the earlier `mikuscore` CLI surface
- because of that, similarities are expected and should be read as family resemblance, not accidental convergence
- `mikuproject` has also evolved beyond the earlier `mikuscore` baseline, and that direction contains many reusable ideas
- the parts most worth reusing back into `mikuscore` are infrastructure patterns first, not the larger command count itself
- initial reuse is now present in the current CLI via centralized help output, `CliUsageError` / `CliProcessingError`, explicit `--out -`, optional `--diagnostics text|json`, and the first `state` family entrypoints
- if `mikuscore` CLI behavior changes in those areas, update `mikuscore-skills` assumptions as well because downstream agent workflows are sensitive to stderr/stdout and exit-code contracts

## Documentation Map

Contribution and repository policy docs:
Expand Down Expand Up @@ -105,6 +151,12 @@ Specification docs:
- `docs/spec/MIDI_IO.md`
- `docs/spec/ABC_IO.md`
- `docs/spec/CLI_STEP1.md`
- `docs/spec/CLI_DIAGNOSTICS_FIRSTCUT.md`
- `docs/spec/CLI_HELP_FIRSTCUT.md`
- `docs/spec/CLI_REBUILD_PLAN.md`
- `docs/spec/CLI_RENDER_FIRSTCUT.md`
- `docs/spec/CLI_TAXONOMY_FIRSTCUT.md`
- `docs/spec/CLI_STATE_FIRSTCUT.md`
- `docs/spec/TEST_MATRIX.md`

Future notes:
Expand Down
30 changes: 30 additions & 0 deletions docs/future/AI_JSON_INTERFACE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,43 @@ Those files should be read as design/archive material unless and until this work
- Prefer bounded, validation-friendly exchange rather than unconstrained rewrite.
- Reassess whether JSON is actually better than `ABC` for the target workflow before reviving the interface.

## Multi-layer design note

If this area is resumed, the design should not be framed only as "an AI feature".

The stronger lesson from the related `mikuproject` work is that the same contract may need to serve three layers at once:

- human CLI users
- Agent Skills or other tool-mediated callers
- downstream generative-AI interaction that sits behind those tool callers

That implies several desirable properties:

- command names and phases should remain understandable to a human operator
- stdio behavior should remain composable in ordinary shell workflows
- diagnostics should have a machine-readable form when the caller is an agent or another program
- AI-facing exchange should prefer bounded projections, validation, and staged apply flows over unconstrained whole-document rewrites
- handoff units should be small enough for reliable AI interaction, not only convenient for a human at a terminal

For `mikuscore`, one strong candidate is to keep the actual mutation contract close to the existing core command catalog rather than inventing a separate whole-measure rewrite model.

That would mean:

- human-facing CLI phases may still look like `state inspect` / `state validate` / `state apply`
- but the machine-facing payload inside those phases may compile down to bounded commands such as `change_to_pitch` or `change_duration`

This does not mean `mikuscore` should copy the `mikuproject` AI command tree directly.

It means future AI-facing interface work should be judged partly by how well it serves all three layers together, not only by whether a single AI prompt can produce an output.

## Re-entry conditions

Revisit this only when there is a concrete implementation need such as:

- a stable tool-mediated AI workflow
- clear bounded edit operations that benefit from a machine-facing contract
- evidence that the added interface meaningfully improves reliability over the current ABC-centered flow
- a plausible CLI or tool contract that remains legible for human users while also serving agent-mediated workflows

## Editorial rule

Expand Down
177 changes: 172 additions & 5 deletions docs/future/CLI_ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,21 @@
## Status

- Step 1 first cut exists.
- CLI infrastructure hardening first cut now exists:
- centralized help output
- usage-error vs processing-error separation
- `--out -`
- `--diagnostics text|json`
- Initial Step 2 MIDI pairs now exist as a first cut.
- Initial Step 3 MuseScore text pairs now exist as a first cut.
- Initial Step 3 MuseScore pairs now exist as a first cut, including `.mscz` / `.mxl` file I/O support.
- Initial `render svg` support now exists as a first cut.
- Initial one-shot `render svg --from abc` support now exists as a first cut.
- Initial `state` family first cut now exists:
- `state summarize`
- `state inspect-measure`
- `state validate-command`
- `state apply-command`
- `state diff`
- This file tracks likely next-step expansion only.
- This is a future note, not a current normative contract.

Expand All @@ -17,26 +29,181 @@ Current implemented Step 1 scope:
- `mikuscore convert --from musicxml --to abc`
- `mikuscore convert --from midi --to musicxml`
- `mikuscore convert --from musicxml --to midi`
- `mikuscore convert --from mei --to musicxml`
- `mikuscore convert --from musicxml --to mei`
- `mikuscore convert --from lilypond --to musicxml`
- `mikuscore convert --from musicxml --to lilypond`
- `mikuscore convert --from musescore --to musicxml`
- `mikuscore convert --from musicxml --to musescore`
- `mikuscore render svg`
- `mikuscore render svg --from abc`
- `mikuscore state summarize`
- `mikuscore state inspect-measure`
- `mikuscore state validate-command`
- `mikuscore state apply-command`
- `mikuscore state diff`
- `mikuscore --help`
- `mikuscore convert --help`
- `mikuscore render --help`
- `mikuscore state --help`

Current Step 1 policy is defined in:

- `docs/spec/CLI_STEP1.md`

## Planned Direction

The CLI family is expected to grow along two tracks:
The current CLI is still `convert`-first, but the next taxonomy candidate is broader:

- convert-oriented commands
- render-oriented commands
- `convert`
- `render`
- `state`

`MusicXML` remains canonical underneath.

This means:

- `convert` handles interchange with external formats
- `render` handles derived outputs such as SVG
- `state` handles canonical `MusicXML` state inspection, validation, patch-style mutation, and other light edit-oriented workflows

This is intentionally closer to the successful `mikuproject` style of separating command responsibility at the top level.

At the same time, `mikuscore` should keep `convert --from ... --to ...` for format-pair scaling, rather than exploding the command surface into one fixed command per format pair.

In other words:

- top-level command taxonomy should become more structured
- format-pair selection inside `convert` should likely stay option-based

## Shared CLI Pattern

The `mikuproject` CLI command family was developed in a shape that intentionally resembles `mikuscore`.

So the relationship here is not "import a foreign command system into `mikuscore`".

It is closer to:

- `mikuscore` established the early `convert`-first CLI pattern
- `mikuproject` expanded that style into a larger command tree
- `mikuproject` later evolved that pattern in ways that are often worth studying back in `mikuscore`
- `mikuscore` can reuse those infrastructure lessons without changing its product identity

For specification work, `mikuproject` should therefore be treated as an evolved sibling implementation of the same general CLI style.

The important nuance is:

- similarity alone does not mean `mikuscore` should copy the larger command surface
- but the direction of `mikuproject` evolution is strong evidence for which CLI infrastructure ideas scale well in practice

The most reusable infrastructure lessons are:

- separate usage failures from processing failures, with distinct exit-code policy
- centralize help text generation instead of scattering inline help branches
- support `--out -` explicitly as stdout, not only omitted `--out`
- add optional structured diagnostics such as `--diagnostics text|json`
- validate stdin/file input combinations consistently before command execution
- keep the main artifact on `stdout` and diagnostics on `stderr`, including machine-readable diagnostics when requested

For `mikuscore`, these are more urgent than broadening the command family again.

In other words, the next CLI step is likely infrastructure hardening before major surface expansion.

## Near-Term Candidate

The earlier CLI infrastructure pass has now landed as a first cut.

The next strongest near-term candidate is to deepen the current `state` family and tighten documentation/current-contract alignment around the now-implemented `convert` / `render` / `state` surface.

Likely next slices are:

- improve current-facing docs to reflect implemented behavior more directly
- decide whether `state inspect-measure` target identity should stay session-scoped `nodeId` based
- deepen `state diff` beyond the current shallow summary if clearer user value emerges
- decide when or whether to introduce patch envelopes after the single-command path has proven itself

## Candidate Top-Level Taxonomy

If the CLI is rebuilt while compatibility cost is still low, the strongest current candidate is:

- `mikuscore convert ...`
- `mikuscore render ...`
- `mikuscore state ...`

Suggested role split:

- `convert`
- external interchange only
- example: `mikuscore convert --from abc --to musicxml`
- `render`
- derived artifact generation
- example: `mikuscore render svg --in score.musicxml`
- a user-facing one-shot `ABC -> SVG` flow may still be offered here even if it internally routes through `ABC -> MusicXML -> SVG`
- `state`
- canonical `MusicXML` inspection and mutation
- future examples: `state summarize`, `state validate`, `state diff`, `state apply-patch`

This shape matches several goals at once:

- preserve `MusicXML` as the canonical state
- avoid multiplying fixed format-pair commands
- give small edit features and diff-based workflows a natural home
- align better with human CLI use, Agent Skills, and future tool-mediated AI workflows

The current first-cut specification notes for this direction are:

- `docs/spec/CLI_TAXONOMY_FIRSTCUT.md`
- `docs/spec/CLI_RENDER_FIRSTCUT.md`
- `docs/spec/CLI_STATE_FIRSTCUT.md`
- `docs/spec/CLI_DIAGNOSTICS_FIRSTCUT.md`
- `docs/spec/CLI_HELP_FIRSTCUT.md`
- `docs/spec/CLI_REBUILD_PLAN.md`

## State Family And Core Command Alignment

`mikuscore` already has an internal command model for bounded score edits:

- `change_to_pitch`
- `change_duration`
- `insert_note_after`
- `delete_note`
- `split_note`

So the CLI should not invent a second unrelated edit model.

At the same time, those command names do not need to become top-level CLI verbs.

The more coherent direction is:

- keep top-level CLI responsibility split as `convert` / `render` / `state`
- let `state` expose phase-oriented commands such as inspect, validate, diff, and apply
- let payloads inside those `state` commands carry the existing core command names

In practice, that suggests a shape such as:

- `mikuscore state summarize`
- `mikuscore state inspect-measure`
- `mikuscore state validate-command`
- `mikuscore state apply-command`
- `mikuscore state diff`

or, if batching several core commands together becomes useful:

- `mikuscore state validate-patch`
- `mikuscore state apply-patch`

with payloads that contain one or more existing core commands.

This keeps the command-line taxonomy consistent with the rest of the CLI while preserving the already-designed internal edit semantics.

In other words:

- the CLI surface should be organized around workflow phases
- the payload schema should reuse the current core command catalog
- `mikuscore` should avoid creating separate top-level verbs like `mikuscore change-to-pitch ...`

That separation is important because it keeps human-facing command discovery manageable while still giving agents and other tools a precise mutation contract.

## Step 2 Candidate Scope

Implemented first-cut Step 2 additions:
Expand All @@ -58,7 +225,7 @@ Implemented first-cut Step 3 additions:

Rationale:

- current CLI MuseScore scope is `.mscx`-style text; compressed `.mscz` handling is still outside the CLI contract
- CLI file I/O now accepts compressed `.mxl` / `.mscz` at the path boundary while keeping `stdin` / `stdout` text-only
- `svg` is better modeled as render output, not as the same class of interchange export as `abc` / `musicxml` / `midi`

## Facade Growth Path
Expand Down
Loading
Loading