Branch: m1-xpj-tree → main
git.monoexp.com/bajdev/mpckit (go 1.24).internal/xpj (no Wails, no domain knowledge), per build plan 4.1:
file.go): gunzip, split off the five header lines, parse the body; write header + body, gzip level 6 with mtime 0, XFL 0, OS 3 (the same 10 header bytes the device writes). ReadFile / WriteFile, Data(), Clone().node.go, json.go): parsed token by token with json.Decoder + UseNumber(). Objects keep key order (and duplicate keys); numbers keep their original text. Written in the device layout: one key or value per line, no indentation, ": " after keys, [] / {} for empty containers, no trailing newline, < > & / not escaped.NewInt (4), NewFloat (always 96.0, never 96; Python-repr shortest form, matching the reference writer), NewFloat32 (rounds to float32 first: 12.4 → 12.399999618530273), plus string/bool/null/array/object.Get / Set by path (tracks[0].program.drum.instruments[4].layersv[0]), Lookup / SetKey / DeleteKey, array Insert / Append / Remove, deep Clone, Int() / Float() accessors.demo-projects/ to testdata/device/ (build plan section 3 and 10.1); updated the two doc references.json, ensure_ascii=False). None of the device files contain an escape, so the device's own escaping style is unknown.go vet ./... and go test ./... pass.
TestRoundTripDeviceProjects reads DemoBlank, Demo02 and DemoFile and re-encodes each byte-identical to the decompressed original (about 3 MB each), both directly and through gzip and back.testdata/accepted (T1-T3) and testdata/wav-formats (W1, W2).data.version 28, 128 pads, "Sequence 01" at 128 BPM.M2: edit operations in internal/project, matching MpckitT1.xpj / MpckitT3.xpj and rebuilding Demo02.