change: alarm-volume-ramp-restore archived_date: 2026-07-11 status: archived archived_from: openspec/changes/alarm-volume-ramp-restore verification_verdict: "PASS WITH WARNINGS" verify_report_observations: - id: 2342 type: verify-report critical_issues: 0 warnings: 2 (WARNING-1 closed post-verify via commit 79f6f8e; WARNING-2 accepted, documented deviation) suggestions: 4 (non-blocking) artifacts_migrated: - explore.md (root cause analysis A/B/C; B later withdrawn during apply-stage SDK verification) - proposal.md (obs #2302) - spec.md (obs #2308, on-disk delta merged to openspec/specs/native-alarms/spec.md as new domain) - design.md (obs #2310, carries Slice 1 cancellation correction banner) - tasks.md (obs #2316, 44 checkboxes: 29 done, 7 N/A Phase 1 cancelled by design, 8 pending Phase 5 manual QA) - apply-progress.md (obs #2332, Batches 1/2/2b/3 complete; discovery #2335 RESOLVED) - verify-report.md (obs #2342, PASS WITH WARNINGS) phase_status: Phase 1 (FGS Manifest + Runtime Type Fix): CANCELLED - 0/7 tasks, by design (target SDK constants confirmed fictional via javap -constants against android-34/35/36 platform jars + api-versions.xml sweep; existing mediaPlayback|systemExempted confirmed correct; Root Cause B withdrawn) Phase 2 (Kotlin Volume Override Channel Methods): COMPLETE - 9/9 tasks [x] Phase 3 (Dart Volume Override Port + Wiring): COMPLETE - 12/12 tasks [x] Phase 4 (Fade-In Dedup at Handoff): COMPLETE - 5/5 tasks [x] Phase 5 (Manual/On-Device QA): PENDING - 8 tasks [ ] (human gate, not executable by any agent) Phase 6 (Final Static Sweep): COMPLETE - 3/3 tasks [x] test_results: total_changed_lines: "~260-360 estimated (Kotlin 2 files, Dart 3 prod files, 3 Dart test files); Slice 1 shipped 0 lines (cancelled by design)" flutter_analyze: "0 issues (verify session, independently re-run)" targeted_suites: - pantalla_alarma_sonando_test.dart - pantalla_alarma_sonando_dismiss_guard_test.dart - pantalla_alarma_sonando_scaffold_test.dart - servicio_alarmas_android_test.dart - estado_alarmas_snooze_test.dart total_tests_passing: "34/34 targeted (verify session, 2026-07-11); 279/279 full-directory batched run (apply Batch 3, task 6.2, hang-fallback split); 35/35 alarm suites after post-verify fix" post_verify_fix: commit: 79f6f8e what: "WARNING-1 closed: EstadoAlarmas captured in initState() instead of a fresh context.read() inside dispose(), which was throwing (caught, silently logged) on a defunct-widget-context ancestor lookup for any teardown that bypasses _detener()/_posponer(); plus a new dispose-as-sole-caller regression test" evidence: "35/35 alarm suites green, flutter analyze 0 issues" reflected_in_tasks_md: false notes: | Phase 5 (manual/on-device QA) is a mandatory human gate before shipping, 8 tasks (5.1-5.8), requires real or emulated Android 14+ device access. Cannot be completed by any agent. Phase 1 (FGS manifest/runtime type fix) is CANCELLED by design, not a defect: sdd-apply independently verified via `javap -constants` against local android-34/35/36 platform jars plus a full FOREGROUND_SERVICE_TYPE_* sweep of api-versions.xml that FOREGROUND_SERVICE_TYPE_ALARM and android.permission.FOREGROUND_SERVICE_ALARM do not exist anywhere in the Android SDK. The existing mediaPlayback|systemExempted declaration is confirmed the correct, intentional pattern (matches the prior app-quality-and-native-alarms T-S1-03/04 deviation). Root Cause B from exploration is withdrawn; design.md and specs/native-alarms/spec.md both carry correction banners documenting this. Slices 2 and 3 are unaffected and both code-complete. WARNING-1 (dispose()'s restore call site non-functional as a standalone safety net, due to a defunct-widget-context ancestor lookup thrown — and silently caught — whenever dispose() is the first/only caller) was found during sdd-verify and CLOSED post-verify by the orchestrator via commit 79f6f8e: EstadoAlarmas is now captured in initState() rather than re-read via context.read() inside dispose(), plus a new dispose-as-sole-caller regression test. 35/35 alarm suites green, flutter analyze 0 issues. This fix is NOT reflected as a new checkbox in tasks.md (it is an orchestrator-level post-verify fix, not a numbered task) — documented here and in archive-report.md instead. WARNING-2 (task 3.9 has no automated RED/GREEN pair; app.dart's PluriWaveApp entry point hardcodes non-injectable EstadoRadio/EstadoAlarmas instances, so _prearrancarAudioAlarma cannot be exercised via flutter test in isolation) is accepted-documented, not fixed. Verified via source inspection instead (forzarVolumenMediaParaAlarma(1.0) confirmed the first statement in _prearrancarAudioAlarma). Recommended follow-up: add a testable DI seam to PluriWaveApp if genuine automated coverage of this seam is required later. Kotlin work (Phase 2 channel methods, Phase 2b flutterOwnsRing handoff-aware backstop) is code-inspection-verified only (no Android test harness in this repo, flutter build/gradle forbidden throughout). Native handoff-timing behavior will be validated during Phase 5 manual QA, specifically tasks 5.1 and 5.5. ARCHIVE TOOLING CAVEAT: the sdd-archive executor for this change had no Bash/shell tool available (Read/Edit/Write/Glob/mem_* only) and could not run `cp` or delete the source folder. All six on-disk artifacts (explore.md, proposal.md, design.md, tasks.md, verify-report.md, specs/native-alarms/spec.md) were reconstructed into this archive folder via Read-verified Write calls, preserving full content. The original `openspec/changes/alarm-volume-ramp-restore/` folder was NOT deleted and still exists alongside this archive copy — a human or an agent with shell access must remove it to complete the move (see archive-report.md "Archive Integrity").