- Added tests for transient SQLite errors in emergency_handler_test.go. - Introduced validation tests for provider errors in notification_provider_handler_validation_test.go. - Implemented helper tests for settings handling in settings_handler_helpers_test.go. - Expanded backup_handler_test.go to include SQLite database setup and validation. - Improved system_permissions_handler_test.go with additional path repair tests. - Updated backup_service_test.go to ensure proper database handling and error checks during backup operations. - Refined import_handler_test.go with additional session validation tests.
8.7 KiB
PR #666 Patch Coverage Recovery Spec (Approval-Ready)
Date: 2026-02-16 Owner: Planning Agent Status: Draft for Supervisor approval (single coherent plan)
1) Scope Decision (Unified)
In Scope
- Backend unit-test additions only, targeting changed patch lines in backend handlers/services/utils.
- Minimum-risk posture: prioritize test-only additions in files already touched by PR #666 before opening any new test surface.
- Coverage validation using current backend coverage task/script.
Out of Scope
- E2E/Playwright, integration, frontend, Docker, and security scan remediation.
E2E Decision for this task
- E2E is explicitly out-of-scope for this patch-coverage remediation.
- Rationale: target metric is Codecov patch lines on backend changes; E2E adds runtime risk/cycle time without direct line-level patch closure.
Scope Reconciliation with Current Implementation (PR #666)
Confirmed already touched backend test files:
backend/internal/api/handlers/import_handler_test.gobackend/internal/api/handlers/settings_handler_helpers_test.gobackend/internal/api/handlers/emergency_handler_test.gobackend/internal/services/backup_service_test.gobackend/internal/api/handlers/backup_handler_test.gobackend/internal/api/handlers/system_permissions_handler_test.gobackend/internal/api/handlers/notification_provider_handler_validation_test.go
Optional/deferred (not yet touched in current remediation pass):
backend/internal/util/permissions_test.gobackend/internal/services/notification_service_json_test.gobackend/internal/services/backup_service_rehydrate_test.gobackend/internal/api/handlers/security_handler_coverage_test.go
2) Single Source of Truth for Success
Authoritative success metric:
- Codecov PR patch status (
lines) is the source of truth for this task.
Relationship to codecov.yml:
coverage.status.patch.default.target: 100%andrequired: falsemeans patch status is advisory in CI.- For this plan, we set an internal quality gate: patch lines >= 85% (minimum), preferred >= 87% buffer.
- Local script output (
go tool cover) remains diagnostic; pass/fail is decided by Codecov patchlinesafter upload.
3) Feasibility Math and Coverage-Line Budget
Given baseline:
- Patch coverage =
60.84011% - Missing patch lines =
578
Derived totals:
- Let total patch lines =
T 578 = T * (1 - 0.6084011)=>T ≈ 1476- Currently covered lines
C0 = 1476 - 578 = 898
Required for >=85%:
C85 = ceil(0.85 * 1476) = 1255- Additional covered lines required:
1255 - 898 = 357
Budget by phase (line-coverage gain target):
| Phase | Target line gain | Cumulative gain target | Stop/Go threshold |
|---|---|---|---|
| Phase 1 | +220 | +220 | Stop if <+170; re-scope before Phase 2 |
| Phase 2 | +100 | +320 | Stop if <+70; activate residual plan |
| Phase 3 (residual closure) | +45 | +365 | Must reach >=+357 total |
Notes:
- Planned total gain
+365gives+8lines safety over minimum+357. - If patch denominator changes due to rebase/new touched lines, recompute budget before continuing.
4) Target Files/Functions (Concise, Specific)
Primary hotspots (Phase 1 focus, aligned to touched tests first):
backend/internal/api/handlers/system_permissions_handler.goRepairPermissions,repairPath,normalizePath,pathHasSymlink,isWithinAllowlist,mapRepairErrorCode
backend/internal/services/backup_service.goRestoreBackup,extractDatabaseFromBackup,unzipWithSkip,RehydrateLiveDatabase,GetAvailableSpace
backend/internal/api/handlers/settings_handler.goUpdateSetting,PatchConfig,validateAdminWhitelist,syncAdminWhitelistWithDB
backend/internal/api/handlers/import_handler.goGetStatus,Upload,Commit,Cancel,safeJoin
backend/internal/api/handlers/backup_handler.goRestore,isSQLiteTransientRehydrateError
backend/internal/api/handlers/emergency_handler.goSecurityReset,disableAllSecurityModules,upsertSettingWithRetry
backend/internal/api/handlers/notification_provider_handler.goisProviderValidationError, provider validation branches
Secondary hotspots (Phase 2 focus, optional/deferred expansion):
backend/internal/api/handlers/security_handler.go(GetStatus,latestConfigApplyState)backend/internal/util/permissions.go(CheckPathPermissions,MapSaveErrorCode,MapDiagnosticErrorCode)backend/internal/services/notification_service.go(sendJSONPayload,TestProvider,RenderTemplate)
5) Execution Phases with Strict Stop/Go and De-Scoping Rules
Phase 0 - Baseline Lock
Actions:
- Run
Test: Backend with Coveragetask (.github/skills/scripts/skill-runner.sh test-backend-coverage). - Record baseline patch lines from Codecov PR view and local artifact
backend/coverage.txt.
Go gate:
- Baseline captured and denominator confirmed.
Stop gate:
- If patch denominator changed by >5% from 1476, pause and recompute budgets before coding.
Phase 1 - High-yield branch closure
Actions:
- Extend existing tests only in:
backend/internal/api/handlers/system_permissions_handler_test.gobackend/internal/services/backup_service_test.gobackend/internal/api/handlers/backup_handler_test.gobackend/internal/api/handlers/emergency_handler_test.gobackend/internal/api/handlers/settings_handler_helpers_test.gobackend/internal/api/handlers/import_handler_test.gobackend/internal/api/handlers/notification_provider_handler_validation_test.go
Go gate:
- Achieve >=
+170covered patch lines and no failing backend tests.
Stop gate:
- If <
+170, do not proceed; re-scope to only highest delta-per-test functions.
Phase 2 - Secondary branch fill
Actions:
- Extend tests in:
backend/internal/api/handlers/security_handler_coverage_test.gobackend/internal/util/permissions_test.gobackend/internal/services/backup_service_rehydrate_test.gobackend/internal/services/notification_service_json_test.go
Go gate:
- Additional >=
+70covered patch lines in this phase.
Stop gate:
- If <
+70, skip low-yield areas and move directly to residual-line closure.
Phase 3 - Residual-line closure (minimum-risk)
Actions:
- Work only uncovered/partial lines still shown in Codecov patch details.
- Add narrow table-driven tests to existing files; no new harness/framework.
Go gate:
- Reach total >=
+357covered lines and patch >=85%.
Stop gate:
- If a residual branch requires production refactor, de-scope it and log as follow-up.
Global de-scope rules (all phases)
- No production code changes unless a test proves a correctness bug.
- No new test framework, no integration/E2E expansion, no unrelated cleanup.
- No edits outside targeted backend test and directly related helper files.
6) Current Tasks/Scripts (Deprecated references removed)
Use these current commands/tasks only:
- Backend coverage (preferred):
Test: Backend with Coverage- command:
.github/skills/scripts/skill-runner.sh test-backend-coverage
- command:
- Equivalent direct script:
bash scripts/go-test-coverage.sh - Optional backend unit quick check:
Test: Backend Unit Tests- command:
.github/skills/scripts/skill-runner.sh test-backend-unit
- command:
Deprecated tasks are explicitly out-of-plan (for this work):
Security: CodeQL Go Scan (DEPRECATED)Security: CodeQL JS Scan (DEPRECATED)
7) Residual Uncovered Lines Handling (Beyond hotspot table)
After each phase, run a residual triage loop:
- Export remaining uncovered/partial patch lines from Codecov patch detail.
- Classify each residual line into one of:
validation/error mappingpermission/role guardfallback/retrylow-value defensive log/telemetry
- Apply closure rule:
- First three classes: add targeted tests in existing suite.
- Last class: close only if deterministic and cheap; otherwise de-scope with rationale.
- Maintain a residual ledger in the PR description:
- line(s), owning function, planned test, status (
closed/de-scoped), reason.
- line(s), owning function, planned test, status (
Exit condition:
- No unclassified residual lines remain.
- Any de-scoped residual lines have explicit follow-up items.
8) Acceptance Criteria (Unified)
- One coherent plan only (this document), no conflicting statuses.
- E2E explicitly out-of-scope for this patch-coverage task.
- Success is measured by Codecov patch
lines; local statement output is diagnostic only. - Feasibility math and phase budgets remain explicit and tracked against actual deltas.
- All phase stop/go gates enforced; de-scope rules followed.
- Only current tasks/scripts are referenced.
- Residual uncovered lines are either closed with tests or formally de-scoped with follow-up.
- Scope remains reconciled with touched files first; deferred files are only pulled in if phase gates require expansion.