docs(openspec): cancel alarm FGS slice, the alarm service type never existed
Build & Deploy PluriWave / Análisis de código (push) Successful in 34s
Build & Deploy PluriWave / Build APK + AAB release (push) Successful in 1m43s

Apply-stage SDK verification (javap on android-34/35/36 platform jars
plus api-versions.xml) proved FOREGROUND_SERVICE_TYPE_ALARM and the
FOREGROUND_SERVICE_ALARM permission are fictional constants. The
existing mediaPlayback|systemExempted declaration is the documented
correct pattern for an alarm app holding exact-alarm permissions, so
slice 1 ships no code and root cause B is withdrawn. Spec, design,
and tasks amended with the evidence; volume-override and fade-dedup
slices proceed unaffected.
This commit is contained in:
2026-07-11 01:22:18 +02:00
parent 39693ce995
commit 43f61d7c21
3 changed files with 27 additions and 4 deletions
@@ -1,5 +1,19 @@
# Design: Alarm Volume Ramp & Device-Volume Immunity # Design: Alarm Volume Ramp & Device-Volume Immunity
> **SLICE 1 CANCELLED — CORRECTION (2026-07-11, apply-stage SDK verification).**
> The first two Architecture Decisions below are built on constants that DO NOT EXIST in the
> Android SDK: `FOREGROUND_SERVICE_TYPE_ALARM` and `android.permission.FOREGROUND_SERVICE_ALARM`
> are fictional (verified via `javap -constants` on the local android-34/35/36 platform jars and a
> full `api-versions.xml` sweep — 13 real FGS types, no alarm variant; constants are additive, so
> absence in 36 rules out 34/35). The existing `mediaPlayback|systemExempted` declaration is the
> documented correct pattern for an alarm-clock app holding exact-alarm permissions starting an FGS
> from an AlarmManager broadcast, and the prior `app-quality-and-native-alarms` deviation
> (T-S1-03/04) that kept it was right. Slice 1 ships NO code change. Root Cause B from the
> exploration is withdrawn; the user-visible bug is fully attributed to Root Cause A (media-stream
> steady state), addressed by Slices 2 and 3, which are independent and unaffected.
> Evidence trail: engram `sdd/alarm-volume-ramp-restore/apply-progress` (#2332) and project
> discovery `android/fgs-alarm-type-nonexistent` (#2333).
## Technical Approach ## Technical Approach
Three independent, rollback-isolated slices realizing proposal #2302. Kotlin owns the manifest fix and a new ring-scoped `STREAM_MUSIC` override (no Flutter volume plugin exists; `MainActivity` already owns the audio channels). Dart drives lifecycle: it invokes override at ring start and restore from the already-centralized exit points. The existing 5%->`alarma.volumen` Dart player ramp is kept; only the audible fade-in *driver* is deduped at handoff. Normal radio playback and `ServicioAudioSession` ducking (S3-R1) are never touched — the override fires only while a ring is active. Kotlin is code-inspection + mandatory on-device QA (flutter build forbidden); Dart follows strict TDD. Three independent, rollback-isolated slices realizing proposal #2302. Kotlin owns the manifest fix and a new ring-scoped `STREAM_MUSIC` override (no Flutter volume plugin exists; `MainActivity` already owns the audio channels). Dart drives lifecycle: it invokes override at ring start and restore from the already-centralized exit points. The existing 5%->`alarma.volumen` Dart player ramp is kept; only the audible fade-in *driver* is deduped at handoff. Normal radio playback and `ServicioAudioSession` ducking (S3-R1) are never touched — the override fires only while a ring is active. Kotlin is code-inspection + mandatory on-device QA (flutter build forbidden); Dart follows strict TDD.
@@ -4,15 +4,15 @@
### Requirement: Manifest declares alarm-eligible foreground service ### Requirement: Manifest declares alarm-eligible foreground service
`PluriWaveAlarmService` in `AndroidManifest.xml` MUST use `foregroundServiceType="mediaPlayback|alarm"` and the app MUST declare `FOREGROUND_SERVICE_ALARM`, so the service is eligible to start on Android 14+ (API 34+) from a broadcast receiver. **CORRECTED (2026-07-11, apply-stage SDK verification)**: the originally specified `foregroundServiceType="mediaPlayback|alarm"` + `FOREGROUND_SERVICE_ALARM` permission are FICTIONAL — neither constant exists anywhere in the Android SDK (verified via `javap -constants` on android-34/35/36 platform jars and `api-versions.xml`; 13 real FGS types, no alarm variant). The existing declaration `foregroundServiceType="mediaPlayback|systemExempted"` is the documented correct pattern for an alarm-clock app holding exact-alarm permissions that starts a foreground service from an AlarmManager broadcast on API 34+. The prior `app-quality-and-native-alarms` deviation (T-S1-03/04) that kept `systemExempted` was right. No manifest or runtime change ships in this change; the requirement is re-scoped to the service-start behavior below.
#### Scenario: Manifest declares required FGS type and permission #### Scenario: Manifest keeps the verified-correct FGS declaration
**Testability**: static/grep-verifiable **Testability**: static/grep-verifiable
- GIVEN the built `AndroidManifest.xml` - GIVEN the built `AndroidManifest.xml`
- WHEN the `PluriWaveAlarmService` `<service>` element is inspected - WHEN the `PluriWaveAlarmService` `<service>` element is inspected
- THEN `android:foregroundServiceType` MUST contain `alarm` - THEN `android:foregroundServiceType` MUST be `mediaPlayback|systemExempted`
- AND a `<uses-permission android:name="android.permission.FOREGROUND_SERVICE_ALARM"/>` MUST exist - AND the runtime `startForeground` type constants in `PluriWaveAlarmService.kt` MUST match the manifest declaration
#### Scenario: Native service starts from broadcast context on Android 14+ #### Scenario: Native service starts from broadcast context on Android 14+
**Testability**: manual on-device QA (Android 14+; agent cannot install/verify) **Testability**: manual on-device QA (Android 14+; agent cannot install/verify)
@@ -28,9 +28,18 @@ Chain strategy: pending
## Phase 1: FGS Manifest + Runtime Type Fix (Slice 1 — code-inspection + manual QA) ## Phase 1: FGS Manifest + Runtime Type Fix (Slice 1 — code-inspection + manual QA)
> **PHASE CANCELLED (orchestrator, 2026-07-11)** — resolution of the BLOCKED note below: the
> target constants are fictional (verified against the local SDK), the existing
> `mediaPlayback|systemExempted` declaration is confirmed correct, and Root Cause B is withdrawn.
> Tasks 1.1-1.7 ship no code. See the correction banner in design.md and the amended Requirement
> in specs/native-alarms/spec.md. Slices 2 and 3 proceed unaffected.
- [ ] 1.1 Edit `android/app/src/main/AndroidManifest.xml:57` — change `PluriWaveAlarmService` `android:foregroundServiceType` from `"mediaPlayback|systemExempted"` to `"mediaPlayback|alarm"`. - [ ] 1.1 Edit `android/app/src/main/AndroidManifest.xml:57` — change `PluriWaveAlarmService` `android:foregroundServiceType` from `"mediaPlayback|systemExempted"` to `"mediaPlayback|alarm"`.
- [ ] 1.2 Edit `android/app/src/main/AndroidManifest.xml:6` — replace `<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED"/>` with `<uses-permission android:name="android.permission.FOREGROUND_SERVICE_ALARM"/>`. - [ ] 1.2 Edit `android/app/src/main/AndroidManifest.xml:6` — replace `<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED"/>` with `<uses-permission android:name="android.permission.FOREGROUND_SERVICE_ALARM"/>`.
- [ ] 1.3 Edit `PluriWaveAlarmService.kt:118-119` — change `startForeground` type constants from `FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK or FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED` to `FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK or FOREGROUND_SERVICE_TYPE_ALARM`. 1.1-1.3 are ONE atomic unit — a manifest-only or runtime-only edit leaves the API 34+ exception alive; do not split across commits. - [ ] 1.3 Edit `PluriWaveAlarmService.kt:118-119` — change `startForeground` type constants from `FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK or FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED` to `FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK or FOREGROUND_SERVICE_TYPE_ALARM`. 1.1-1.3 are ONE atomic unit — a manifest-only or runtime-only edit leaves the API 34+ exception alive; do not split across commits.
> **BLOCKED (sdd-apply, 2026-07-11):** `FOREGROUND_SERVICE_TYPE_ALARM` / `android.permission.FOREGROUND_SERVICE_ALARM` do NOT exist in the Android SDK. Verified via `javap -constants` against `android.content.pm.ServiceInfo` and `android.Manifest$permission` in the local `android-34`/`android-35`/`android-36` platform `android.jar`s, plus a full `FOREGROUND_SERVICE_TYPE_*` field sweep of `api-versions.xml`. The only FGS types that exist through API 36 are: camera, connectedDevice, dataSync, health, location, manifest, mediaPlayback, mediaProcessing, mediaProjection, microphone, phoneCall, remoteMessaging, shortService, specialUse, systemExempted — no `alarm` variant. Edits 1.1-1.3 were applied then reverted (`git checkout --`) to avoid landing an unresolved-Kotlin-reference / invalid-manifest-enum compile break that `flutter analyze` cannot catch (Dart-only) and that this task explicitly forbids validating via `flutter build`/gradle. This reconfirms the identical finding already recorded in `app-quality-and-native-alarms` (T-S1-03/T-S1-04), which used `systemExempted`/`FOREGROUND_SERVICE_SYSTEM_EXEMPTED` for the same reason — see design #2310's own "Open Questions" section, which flagged but did not resolve this before approval. Design #2310 / tasks #2316 need correction before Slice 1 can proceed: either identify a real SDK-backed fix for the API 34+ `ForegroundServiceTypeException`, or confirm `systemExempted` was already correct and the actual Slice 1 defect (if any) lies elsewhere. Working tree is clean — no diff left on either file.
- [ ] 1.4 Static check: `rg 'foregroundServiceType' android/app/src/main/AndroidManifest.xml` shows `alarm`, not `systemExempted`, on the `PluriWaveAlarmService` line. - [ ] 1.4 Static check: `rg 'foregroundServiceType' android/app/src/main/AndroidManifest.xml` shows `alarm`, not `systemExempted`, on the `PluriWaveAlarmService` line.
- [ ] 1.5 Static check: `rg 'FOREGROUND_SERVICE_ALARM|FOREGROUND_SERVICE_SYSTEM_EXEMPTED' android/app/src/main/AndroidManifest.xml` shows `FOREGROUND_SERVICE_ALARM` present and `FOREGROUND_SERVICE_SYSTEM_EXEMPTED` absent. - [ ] 1.5 Static check: `rg 'FOREGROUND_SERVICE_ALARM|FOREGROUND_SERVICE_SYSTEM_EXEMPTED' android/app/src/main/AndroidManifest.xml` shows `FOREGROUND_SERVICE_ALARM` present and `FOREGROUND_SERVICE_SYSTEM_EXEMPTED` absent.
- [ ] 1.6 Static check: `rg 'FOREGROUND_SERVICE_TYPE_ALARM|FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED' android/.../PluriWaveAlarmService.kt` shows `TYPE_ALARM` present and `TYPE_SYSTEM_EXEMPTED` absent — confirms manifest/runtime match (Requirement: Manifest declares alarm-eligible FGS, Scenario "Manifest declares required FGS type and permission"). - [ ] 1.6 Static check: `rg 'FOREGROUND_SERVICE_TYPE_ALARM|FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED' android/.../PluriWaveAlarmService.kt` shows `TYPE_ALARM` present and `TYPE_SYSTEM_EXEMPTED` absent — confirms manifest/runtime match (Requirement: Manifest declares alarm-eligible FGS, Scenario "Manifest declares required FGS type and permission").