Skip to content

Per-phrase tiers 2/4: "simplify this phrase" command to derive a lower tier #34

Closed

Description

@cchacs

Part of #3 (the "at minimum" upgrade in the issue). Depends on Per-phrase tiers 1/4.

Authors should not have to hand-duplicate notes per level.

Scope

  • Add a bulk command that derives a lower tier from the existing full tier of a phrase: thin dense chords, drop ornaments and hammer/pull chains, drop the shortest-duration notes first.
  • The result is written into the phrase's per-tier data from 1/4; the full tier is untouched.
  • Make it an undoable command in the editor's command stack.
  • Let the user choose the target tier (and see which tiers exist) from the phrase's context.

Acceptance criteria

  • Running the command on a dense phrase produces a strictly simpler lower tier (fewer notes/chords) without altering the full tier.
  • It is undoable.
  • Tests cover the thinning rules on a fixture phrase.

Out of scope

Hand-authoring individual tiers (3/4).

Activity

  1. pullfrog commented on Oct 2, 2026

    @pullfrog
  2. pullfrog commented on Oct 9, 2026

    @pullfrog

    This shipped already, so there is nothing new to build. Verified against main (973bad0); closing as completed.

    Where it landed. PR #53 (feat/issue-3-per-phrase-difficulty-tiers, merge 145b28b), commits 1ec8384 (pure planner), f8773e1 (command + keybind), with review follow-ups 32bdf23 / bb73aa3 / cdebe79. git merge-base --is-ancestor 1ec8384 origin/main → true.

    Acceptance criteria

    Criterion Where
    Strictly simpler lower tier, full tier untouched planTierSimplification in src/tiers.js:457 derives a rung one difficulty below the current floor; the top tier stays the editable flat chart (src/tiers.js:539-586). Thinning is deriveSimplifiedNotes (src/tiers.js:215: drop hammer_on/pull_off chains, strip bend/slide/tap to load defaults and null bend curves, drop positive sustains under half a local beat) plus deriveSimplifiedChords (src/tiers.js:283: dense chords thin).
    Undoable SimplifyPhraseCmd (src/input.js:946) is executed through S.history.exec and holds the prior tiers/max_difficulty by reference for a verbatim rollback; the runner is _editorSimplifyPhraseAtCursor (src/input.js:1013). Refusals are statuses only and never enter the history.
    Tests cover the thinning rules on a fixture tests/tier_simplify.test.mjs (planner refusals/sourcing), tests/phrase_tier_commands.test.mjs (exec/undo/redo), tests/test_phrase_tier_authoring.py.

    Verification run just now on HEAD

    • node --test tests/tier_simplify.test.mjs tests/phrase_tier_commands.test.mjs → 36 pass / 0 fail.
    • python3 -m pytest tests/test_phrase_tier_authoring.py tests/test_phrase_tiers.py → 29 passed.

    User-facing surface. Alt+P / Add ▸ Markers "Simplify phrase at cursor" (src/shortcuts.js:169, src/menu-bar.js:103), documented in README.md:132-138, docs/USER-GUIDE.md:404-407, and CHANGELOG.md:126-149.

    One scope bullet here — "choose the target tier (and see which tiers exist) from the phrase's context" — is not in this command: it always mints the next rung below the floor. That selection/listing UI is explicitly the subject of the still-open sibling 3/4 #35 ("Switch the editing view between a phrase's tiers", "Show which tiers a phrase has"). The acceptance criteria for this issue are fully met.

    Pullfrog  | View workflow run | via Pullfrog | Using big-pickle (free) | 𝕏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions