Split from #36 §1. The keystone library gap: no per-song/per-arrangement difficulty a user can sort, filter, or see before opening the chart. The only existing difficulty signal is the phrase-level max_difficulty ladder (§6.7), which lives inside the chart and only in phrase-aware packs.
Proposal
Add an OPTIONAL difficulty field to each arrangements[] entry in manifest.yaml (§5.2).
arrangements:
- id: lead
name: Lead
file: arrangements/lead.json
difficulty: 6 # OPTIONAL
Why the manifest, not the arrangement JSON (§6): the manifest is the index (§2.2). Library sort/filter must work without parsing every chart file. Per-arrangement placement also gives cross-instrument parity for free — bass / lead / rhythm keep distinct ratings.
Why spec, not just app: difficulty travels with the pack so every host/importer agrees and it survives re-scan. It's metadata about the chart, not the user (passes §9.5).
Mechanics
- Additive OPTIONAL key → MINOR bump →
feedpak_version 1.12.0. Older Readers ignore it (§4.2, §9.4).
- Schema: add
difficulty to the arrangementEntry def in manifest.schema.json (additionalProperties: true already keeps old packs valid; add an explicit constraint).
- Distinct from phrase
max_difficulty (§6.7): that stays the in-chart ladder; this is a single library-facing whole-chart scalar. Document the two as orthogonal.
Open questions (need direction)
- Scale. Recommend integer 1–10 (absolute, sortable, derivable, parity with the integer
max_difficulty). Alternative: coarse beginner/intermediate/advanced enum (simpler, weaker sequencing). Pick one — drives the schema constraint.
- Authored vs derived vs both. A Writer could derive it from note density + tempo (§6.10) + phrase-ladder span (§6.7) + tuning distance. Recommend: store the resolved integer; allow an authored value to override a derived one. If provenance matters, reuse the existing
{engine, model, version} pattern (optional difficulty_source), not a new shape.
- Relationship to
max_difficulty — confirm orthogonal (above).
Blocks: nothing additive. The scale decision (Q1) is the only thing gating the spec PR.
Split from #36 §1. The keystone library gap: no per-song/per-arrangement difficulty a user can sort, filter, or see before opening the chart. The only existing difficulty signal is the phrase-level
max_difficultyladder (§6.7), which lives inside the chart and only in phrase-aware packs.Proposal
Add an OPTIONAL
difficultyfield to eacharrangements[]entry inmanifest.yaml(§5.2).Why the manifest, not the arrangement JSON (§6): the manifest is the index (§2.2). Library sort/filter must work without parsing every chart file. Per-arrangement placement also gives cross-instrument parity for free — bass / lead / rhythm keep distinct ratings.
Why spec, not just app: difficulty travels with the pack so every host/importer agrees and it survives re-scan. It's metadata about the chart, not the user (passes §9.5).
Mechanics
feedpak_version1.12.0. Older Readers ignore it (§4.2, §9.4).difficultyto thearrangementEntrydef inmanifest.schema.json(additionalProperties: truealready keeps old packs valid; add an explicit constraint).max_difficulty(§6.7): that stays the in-chart ladder; this is a single library-facing whole-chart scalar. Document the two as orthogonal.Open questions (need direction)
max_difficulty). Alternative: coarsebeginner/intermediate/advancedenum (simpler, weaker sequencing). Pick one — drives the schema constraint.{engine, model, version}pattern (optionaldifficulty_source), not a new shape.max_difficulty— confirm orthogonal (above).Blocks: nothing additive. The scale decision (Q1) is the only thing gating the spec PR.