# M2.5 JC4880 / FLX4 release - 2026-10-06

Status: **published M2.5 for JC4880 / DDJ-FLX4; verified 2026-10-06**.

## Scope and authorization

The operator explicitly authorized completing and publishing M2.5, for
JC4880 / DDJ-FLX4 / PCM5102A MAIN / FLX4 headphone cue. Previous design is
retained. A-L shared-core integration and adapted modules from collaborator
[kayrozen](https://github.com/kayrozen) retain their provenance in
[the integration ledger](../FORK_IMPROVEMENTS.md). Default artwork uses the
operator-supplied Pajoniiir logo.

The operator explicitly waives a new 180-minute soak for the final M2.5 image:
`izostaviti ćemo 180 min soak jer nismo ništa na zvuku radili`.
Audio/deck/DSP implementation is unchanged from the accepted v91; later
ordinary-build code changes concern artwork presentation and startup diagnostics.
Diagnostic fault flags remain OFF. This is an **image-specific release
exception**, not a new long-soak PASS or transfer of v91's soak to M2.5.
Short final-image OTA, startup, USB, UI and listening checks remain required.

## Existing evidence and remaining scope

- Clean candidate `M2.4-111-ge09e9ca4` passed signed OTA/startup, controller and
  storage recovery, real-cover/default-logo/page transitions and a
  62.4187612-second dual-playing test with zero strict fault deltas and clean
  operator-confirmed MAIN/D1/D2 cue. See the
  [candidate record](M2_5_DEFAULT_ARTWORK_20261006.md).
- Stopped USB media removal/reinsert subsequently restores Library/artwork
  normally, confirmed by the operator.
- Focused v91 library checks additionally cover catalog consistency, title
  handoff, stale-request rejection, artwork/memory-cue visibility and navigation
  of `untitled playlist`; source metadata correspondence is not established.
- Full title/downbeat/PWV4 export comparison, nested playlist order,
  source-cue reimport/restore/cross-media isolation, delayed/corrupt artwork,
  advanced touch/shift and active-removal variants remain NOT RUN.
- JC1060/DDJ-400/real Link peers remain development configurations awaiting
  hardware acceptance. Recorder and SD experiments remain OFF. APTA is separate.
- The public Web Profile Builder v4 deployment is outside this firmware release.

## Frozen source and reproducible build

- Source: `20f1c3f04a615209ae25e9bbdae649d0f5b44e8d`.
- Annotated `M2.5` tag object: `e34b9c8989da72e233851aece5c0f3c3074c700f`;
  peel matches source. The tag is immutable; later documentation commits do
  not replace the release image.
- Fresh clean local `main-deck-p4` build passed on ESP-IDF 6.0.2. Ordinary
  preview/recorder/storage/fault-injection flags are OFF; dependency lock unchanged.
- [Exact-source CI](https://github.com/dvucinozd/Pajoniiir/actions/runs/37401972853)
  passed all eight jobs: P4 regular/recorder/preview, JC1060
  regular/PSRAM/recorder/preview and host regressions. This includes both board
  budgets/locks and software profile/UI/network gates; it is not JC1060 hardware acceptance.
- Application size 2,576,432 bytes is below the unchanged `0x380000` limit.
  Package validation checked descriptor/project, clean Git version, chip,
  configuration, signed bundle and signed release manifest (key `rel-001`).

## Final installed-image acceptance

Signed OTA returned HTTP 200/rebooting. The PC WLAN disconnected during reboot,
so the first 45-second HTTP observation window timed out. Connecting its saved
Pajoniiir profile restored access; no extra device reboot/reset was performed.
API and saved journal subsequently confirm **M2.5 / ota_1 / boot 618**, startup
ready, both USB paths present and zero allocation failures.

The final image ran **62.622211 seconds** of measured dual playback, with D1
`FUN FUN - HAPPY STATION (CLUB MIX) (℗1983 / ©2010)` and D2 `Red For Love {320}`.
Both were playing in the end snapshot; output submitted 10,774 new USB blocks.
All measured strict deltas were zero: PCM1/PCM2 underrun, output late, locked
backend reads, USB packet failure/lost frames/drop/overflow/active underflow,
host daemon/recovery/queue, runtime queue and service-log drop. Idle USB
underflow is excluded by the explicit active-playback baseline, not reset.
No data-loss latch or watchdog ISR was observed. Both decks were stopped
at completion, and current firmware API still reports M2.5 / ota_1.

The operator answered **`sve je uredno`** to the final tagged-image question
covering Overview and MAIN/D1/D2 CUE. Listening acceptance is PASS.

Playback samples: minimum internal free 100,315 bytes, minimum DMA free 60,771,
largest internal/DMA block 31,744, minimum PSRAM free 23,570,084. All 12 resource
samples report startup ready and zero allocation/critical-allocation failures.
Final stack minima by published task index: 2,824 / 20,544 / 20,536 / 2,860 /
2,860 / 13,572 / 6,804 / 13,660 / 2,344 bytes. The diagnostic log was downloaded
only after both decks stopped. Its retained historical crash dump is not
a new M2.5 crash; current boot and watchdog evidence remain unchanged.

**New 180-minute M2.5 soak: explicitly WAIVED, not PASS.** Earlier v91
segmented-soak and functional results remain evidence for their exact image.

## Immutable artifacts and public verification

| Artifact | Bytes | SHA-256 |
| --- | --- | --- |
| `main-deck-p4.bin` | 2,576,432 | `7aaab31d4a7c00990939cb9ccecb04aba1cba463b1db919d168477c7df3210ba` |
| `main-deck-p4.ddjota` | 2,576,620 | `44db191c1785168781e9b2893cac6dda1b92a20a5342c328d7fbfdbbd8707e27` |
| `manifest.json` | 644 | `61d5520a99e28e40ce5205e3ce6c5e4d213c657c975cbb7ec098594583ca97d6` |
| `manifest.sig` | 64 | `fe49ac6c3597add921107f1f026cb8e6352f95392d1a59002d2b95e9341a2c42` |
| Public `latest.json` | 210 | `0066575e5c9b91b83dd39c928e532f263408627df29ebce55b1b699406f1c7a9` |

[GitHub M2.5](https://github.com/dvucinozd/Pajoniiir/releases/tag/M2.5)
is public, non-draft, non-prerelease, published at `2026-10-06T02:10:02Z`.
All four GitHub assets were downloaded and matched the package hashes.
All four [versioned HTTPS assets](https://ota.pajoniiir.eu/M2.5/main-deck-p4.ddjota)
were independently downloaded and matched the same hashes. Verified FTPS used
CA/hostname validation and encrypted data; the versioned artifacts were staged
before atomically promoting [latest.json](https://ota.pajoniiir.eu/latest.json).
The public HTTPS channel was downloaded afterwards and exactly matches the
packaged M2.5 size/hash/path. Temporary encrypted upload credential was removed.
An unauthenticated public GitHub bundle download also matched the signed bundle
hash after publication. The production pull-manifest parser accepted the actual
HTTPS channel as newer than v91 and equal to installed M2.5, preventing a
duplicate offer. This host policy check does not claim an Internet pull install.

Previous immutable `M2.4-91-g75136aef` artifacts and the pre-promotion channel
snapshot remain available for signed service rollback. App-only OTA does not
migrate partitions. No JC1060 channel or Web Profile Builder deployment changed.

Raw build/package/CI/download/device evidence is retained under
`D:/Documents/.codex-reviews/Pajoniiir-M25-release-20261006`, including
`audio-final`, `artifact-hashes.json`, `public-github-release.json`,
`public-latest.json`, `resource-summary.json` and `final-diagnostic.log`.
Saved diagnostic journal SHA-256:
`885c023b9e13f17d968bd2a93da9b4438fd8953d5079d7741f1e09b6760e555d`.
Documentation integrity passed (83 Markdown/HTML files, 134 retired paths),
as did `git diff --check`. This documentation update does not modify M2.5's tag.
