_onDispositivoCambiado() bootstrapped a device-level preset entry for every never-seen device id, including the built-in speaker. That persistent level-3 entry masked later global-preset edits (level 3 beats level 4 on every resolution), so disconnecting a BT device or cold-starting without one could leave the EQ stuck on an outdated copy instead of the current global preset. The base speaker is now excluded from the first-seen bootstrap: disconnect and cold start always resolve through the live hierarchy. BT/wired/USB devices keep their bootstrap behavior unchanged.
194 lines
9.6 KiB
Markdown
194 lines
9.6 KiB
Markdown
# Archive Report: EQ Device Disconnect / Cold-Start Revert
|
||
|
||
**Change**: eq-device-disconnect-revert
|
||
**Archive Date**: 2026-07-10
|
||
**Artifact Store Mode**: hybrid
|
||
**Status**: ARCHIVED
|
||
|
||
---
|
||
|
||
## Verification Verdict
|
||
|
||
**PASS WITH WARNINGS**
|
||
|
||
- **Critical Issues**: 0
|
||
- **Warnings**: 1
|
||
- **Suggestions**: 3
|
||
- **Tests Passed**: 43/43 (target file), 68/68 (target + regression suite)
|
||
- **Tasks Complete**: 15/16 (Phase 5.1 intentionally pending as non-blocking manual gate)
|
||
|
||
---
|
||
|
||
## Change Summary
|
||
|
||
**Scope**: EQ device disconnect handling and cold-start resolution guarantee
|
||
|
||
**What was changed**:
|
||
- Added first-seen bootstrap guard in `_onDispositivoCambiado()` to exclude `altavozInterno` (base speaker) from device-preset caching, ensuring the base device always resolves live through the 4-level hierarchy (matrix → station → device → global)
|
||
- Added 5 new test cases (D.1–D.5) covering disconnect revert, cold-start guarantees, connect-disconnect-reconnect cycles, station/matrix override interaction, and toggle-off invariance
|
||
- All changes isolated to `lib/estado/estado_ecualizador.dart` (~9 lines modified) and `test/estado/estado_ecualizador_test.dart` (~214 lines added)
|
||
|
||
**Why it matters**:
|
||
- Fixes a correctness gap: disconnect and cold-start events now explicitly re-resolve and apply the EQ preset, not coincidentally
|
||
- Closes a L3-masks-L4 bug: base speaker can no longer be pinned by a stale device-level entry from the old bootstrap
|
||
- Maintains full byte-for-byte compatibility when multi-device EQ is disabled
|
||
|
||
---
|
||
|
||
## Engram Artifacts (Observation IDs for Traceability)
|
||
|
||
All SDD artifacts persisted to Engram project `pluriwave` for cross-session recovery and audit trail:
|
||
|
||
| Artifact | Topic Key | Observation ID | Created | Details |
|
||
|----------|-----------|----------------|---------|---------|
|
||
| **Proposal** | `sdd/eq-device-disconnect-revert/proposal` | #2301 | 2026-07-10 17:53:45 | Intent, scope, approach, risks, rollback plan |
|
||
| **Spec (Delta)** | `sdd/eq-device-disconnect-revert/spec` | #2306 | 2026-07-10 17:59:15 | 5 formal requirements, 6 scenarios; no prior main spec existed |
|
||
| **Design** | `sdd/eq-device-disconnect-revert/design` | #2303 | 2026-07-10 17:58:01 | 6 architecture decisions, bootstrap guard fix, testing strategy |
|
||
| **Tasks** | `sdd/eq-device-disconnect-revert/tasks` | #2315 | 2026-07-10 18:11:25 | Phases 1–5, review workload forecast (Low risk, single PR) |
|
||
| **Apply Progress** | `sdd/eq-device-disconnect-revert/apply-progress` | #2323 | 2026-07-10 19:02:32 | Phases 1–4 complete (15 tasks), TDD cycle evidence, deviations log |
|
||
| **Verify Report** | `sdd/eq-device-disconnect-revert/verify-report` | #2325 | 2026-07-10 23:38:59 | Completeness, spec compliance, coherence, TDD compliance, assertions, issues found |
|
||
|
||
**This Archive Report** will be persisted to Engram as:
|
||
- **Topic Key**: `sdd/eq-device-disconnect-revert/archive-report`
|
||
- **Type**: architecture
|
||
- **Project**: pluriwave
|
||
|
||
---
|
||
|
||
## Spec Merge Status
|
||
|
||
### Delta Spec → Main Spec
|
||
|
||
| Action | File | Result |
|
||
|--------|------|--------|
|
||
| **Create** | `openspec/specs/multi-device-eq/spec.md` | ✅ Created (no prior spec existed; delta copied as full spec) |
|
||
|
||
**Content merged**: 5 ADDED Requirements with 6 scenarios (no MODIFIED or REMOVED entries). All requirements cover disconnect/cold-start revert behavior within the 4-level EQ hierarchy. On-disk delta spec at `openspec/changes/eq-device-disconnect-revert/specs/multi-device-eq/spec.md` was used as authoritative source (post-verify refinement applied by orchestrator to resolve WARNING-1 wording drift).
|
||
|
||
---
|
||
|
||
## Filesystem Archive Structure
|
||
|
||
**Move completed**: `openspec/changes/eq-device-disconnect-revert/` → `openspec/changes/archive/2026-07-10-eq-device-disconnect-revert/`
|
||
|
||
**Contents preserved**:
|
||
- ✅ `proposal.md` — Intent and approach
|
||
- ✅ `design.md` — Architecture decisions and bootstrap guard fix
|
||
- ✅ `tasks.md` — Phases 1–5 with task checklist
|
||
- ✅ `specs/multi-device-eq/spec.md` — Full delta spec (5 requirements)
|
||
- ✅ `verify-report.md` — Completeness, spec compliance, TDD compliance
|
||
- ✅ `state.yaml` — DAG state (archived status recorded)
|
||
- ✅ `archive-report.md` — This document
|
||
|
||
**Artifacts NOT in openspec/**:
|
||
- Engram artifacts remain in Engram at topic keys listed above (not moved; persisted independently)
|
||
|
||
---
|
||
|
||
## Issue Tracking and Resolutions
|
||
|
||
### Verification WARNING (1)
|
||
|
||
**WARNING-1: Spec Text / Implementation Divergence on Requirement 2**
|
||
|
||
- **Description**: Spec scenario literally states `presetsDispositivo['builtin_speaker']` is bootstrapped to the global preset with the implication the entry is created. Implementation (matching Design Decision #2) NEVER creates that entry — the `esBase` guard unconditionally skips the bootstrap block.
|
||
- **Status**: ✅ RESOLVED (post-verify spec refinement)
|
||
- **Resolution**: The on-disk spec file at `openspec/changes/eq-device-disconnect-revert/specs/multi-device-eq/spec.md` was edited by the orchestrator post-verify to correct the THEN clause: now states no entry is ever created and resolution always falls through to the hierarchy. This is functionally correct and safer than the literal wording.
|
||
- **Proof**: Test D.2 asserts `presetsDispositivo.containsKey('builtin_speaker')` is `false` — proves no entry exists, and the edit aligns the spec with this proven behavior.
|
||
|
||
### Verification SUGGESTIONS (3)
|
||
|
||
**SUGGESTION-1**: Reconcile spec text per WARNING-1 resolution (already done in on-disk file; no action needed).
|
||
|
||
**SUGGESTION-2**: Apply-progress TDD Cycle Evidence table uses 3-column format (RED/GREEN/REFACTOR) instead of full 5-column strict-TDD template. Substance is present; format nitpick for future runs.
|
||
|
||
**SUGGESTION-3**: Pre-existing `cambiarPresetPrincipal()` hierarchy-bypass (applies raw global instead of re-resolving) observed during apply, noted as tracked tech debt. Out of scope for this change; recommend a follow-up ticket.
|
||
|
||
---
|
||
|
||
## Non-Blocking Items
|
||
|
||
**Task 5.1: On-Device Manual Sanity Check — PENDING**
|
||
|
||
- **Description**: Connect BT/USB device with own preset, disconnect (verify revert to base), reconnect (verify return to device preset)
|
||
- **Status**: Intentionally unchecked
|
||
- **Reason**: Non-automatable human gate requiring real hardware; verified via automated unit tests (D.1–D.5) to be theoretically sound
|
||
- **Blocking the release?**: No. Can be executed anytime on real hardware as a confidence check; not required for PR merge.
|
||
|
||
---
|
||
|
||
## Tech Debt Carried Forward
|
||
|
||
**Pre-existing `cambiarPresetPrincipal()` Bypass**
|
||
|
||
- **Description**: The `cambiarPresetPrincipal()` method immediately calls `audio.aplicarPresetActivo(preset)`, bypassing `_resolverPresetActivo()` and applying the raw global preset directly without re-resolving the hierarchy. This could allow a station or matrix override to be transiently bypassed for one apply call.
|
||
- **Scope**: Out of scope for this change; pre-existing behavior unrelated to disconnect/cold-start revert
|
||
- **Recommendation**: Follow-up ticket to refactor `cambiarPresetPrincipal` to push through `_resolverPresetActivo()` for hierarchy consistency
|
||
|
||
---
|
||
|
||
## Review Workload Impact
|
||
|
||
| Metric | Value |
|
||
|--------|-------|
|
||
| Estimated changed lines (from task forecast) | 130–160 |
|
||
| Actual changed lines (via git) | ~221 (9 lib + 214 test) |
|
||
| 400-line budget risk | Low |
|
||
| Chained PRs recommended | No |
|
||
| Delivery strategy applied | ask-on-risk → single PR (no split needed) |
|
||
|
||
---
|
||
|
||
## Completeness Checklist
|
||
|
||
| Item | Status | Notes |
|
||
|------|--------|-------|
|
||
| Proposal read and logged | ✅ | #2301 |
|
||
| Spec read and merged | ✅ | #2306 → openspec/specs/multi-device-eq/spec.md |
|
||
| Design read and verified | ✅ | #2303, all 6 decisions followed |
|
||
| Tasks read and tracked | ✅ | #2315, 15/16 complete |
|
||
| Apply progress read | ✅ | #2323, Phases 1–4 complete |
|
||
| Verify report read and resolved | ✅ | #2325, PASS WITH WARNINGS, WARNING resolved in spec |
|
||
| All artifacts moved to archive | ✅ | Filesystem and Engram copies established |
|
||
| State recorded (archived) | ✅ | state.yaml written with status and notes |
|
||
| Archive report created | ✅ | This document (both filesystem and Engram) |
|
||
|
||
---
|
||
|
||
## SDD Cycle Complete
|
||
|
||
This change has successfully completed all phases:
|
||
|
||
1. ✅ **Explore** — Investigated device-event handling and revert semantics
|
||
2. ✅ **Propose** — Defined scope and approach
|
||
3. ✅ **Spec** — Formal 5-requirement specification with 6 scenarios
|
||
4. ✅ **Design** — Architecture decisions and bootstrap guard detail
|
||
5. ✅ **Tasks** — Breakdown with phases, forecast, and completeness tracking
|
||
6. ✅ **Apply** — Implemented with Strict TDD (15/16 tasks automated, 1/16 manual gate)
|
||
7. ✅ **Verify** — PASS WITH WARNINGS (43/43 tests, 0 CRITICAL, 1 WARNING resolved)
|
||
8. ✅ **Archive** — All artifacts consolidated, spec merged, change moved to archive
|
||
|
||
**Ready for**: Next change or release planning
|
||
|
||
---
|
||
|
||
## Artifact Links
|
||
|
||
- **Main spec**: `openspec/specs/multi-device-eq/spec.md`
|
||
- **Archived change folder**: `openspec/changes/archive/2026-07-10-eq-device-disconnect-revert/`
|
||
- **Engram topic keys** (full content via mem_get_observation):
|
||
- Proposal: `sdd/eq-device-disconnect-revert/proposal` (#2301)
|
||
- Spec: `sdd/eq-device-disconnect-revert/spec` (#2306)
|
||
- Design: `sdd/eq-device-disconnect-revert/design` (#2303)
|
||
- Tasks: `sdd/eq-device-disconnect-revert/tasks` (#2315)
|
||
- Apply Progress: `sdd/eq-device-disconnect-revert/apply-progress` (#2323)
|
||
- Verify Report: `sdd/eq-device-disconnect-revert/verify-report` (#2325)
|
||
- Archive Report: `sdd/eq-device-disconnect-revert/archive-report` (this document)
|
||
|
||
---
|
||
|
||
**Archived by**: SDD Archive Phase (haiku model)
|
||
**Date**: 2026-07-10 (ISO format)
|
||
**Project**: pluriwave
|
||
**Mode**: Hybrid (Engram + OpenSpec filesystem)
|