# C-1 Verification Report

**Date:** 2026-03-29
**Branch:** culurien

---

## PART 1: BUILD & TEST

### Builds
- **Linux AMD64**: PASS (all C-1 packages compile cleanly; pre-existing migration/pathutils error unrelated)
- **Linux ARM64**: PASS (same)
- **Windows AMD64**: PASS (docker-compose cross-compiles successfully)

### Test Counts
- Scanner: 19 tests, 19 PASS
- Agent internal: 4 tests, 4 PASS
- Agent crypto: 14 tests, 14 PASS
- Agent circuitbreaker: 3 tests, 3 PASS
- Server: 59 tests, 58 PASS + 1 SKIP
- **Total: 99 tests, 98 PASS, 1 SKIP, 0 FAIL**

Previous B-2 baseline: 77 tests. C-1 adds 19 scanner tests + 3 circuitbreaker = 22 new.

### State-Change Confirmation
All 8 FAIL-NOW tests flipped to PASS. All 11 PASS-NOW tests updated correctly.

---

## PART 2: POLLING LOOP PARITY (F-C1-5) — PASS

- Proportional jitter: `maxJitter = pollingInterval / 2`, capped at 30s — present at lines 179-186
- Exponential backoff: `calculateBackoff()` at line 623-635, base=10s, cap=5min
- `consecutiveFailures` counter: incremented on error (lines 244, 257, 264), reset on success (line 271)
- Log format: `[WARNING] [agent] [service] server_unavailable attempt=%d` — ETHOS compliant
- TODO comment for deduplication: present at line 165

### Remaining Gaps
The Windows service runAgent() does NOT have:
- `ShouldRefreshKey` / `RefreshPrimaryKey` cycle (A-1)
- `CleanupExecutedIDs` (B-2 F-B2-2)

These are in main.go's polling loop but absent from service/windows.go. The impact is LOW — key refresh is needed only every 6 hours and is handled by the key cache fallback. Command dedup cleanup runs every 6 hours and is non-critical. Documented as future deduplication work.

---

## PART 3: WINGET PATH DETECTION (F-C1-1) — PASS

- Lookup order: 1) `exec.LookPath`, 2) `C:\Windows\System32\winget.exe`, 3) `filepath.Glob` for WindowsApps
- Linux safety: `filepath.Glob` with Windows paths returns nil on Linux, `os.Stat` returns error — both graceful
- Not-found: returns `fmt.Errorf`, caller logs and skips — no panic
- Log: `[INFO] [agent] [scanner] winget_found_at path=%q` and `winget_not_found`

---

## PART 4: GHOST UPDATES (F-C1-3) — PASS (partial fix)

- `RebootRequired = true` set on InstallResult post-install (line 107)
- Log: `[INFO] [agent] [installer] windows_update_installed packages=%v reboot_required=%v`
- RebootRequired field added to InstallResult struct with JSON tag

**WARNING: Detection only, not full prevention.** The `RebootRequired` flag is set on the InstallResult and reported to the server, but the scanner does NOT filter out recently-installed updates. The next scan will still return the update as available until Windows commits the install state. This is a partial fix — the server/dashboard can use the flag to show "reboot required" status, but the ghost update will still appear in scan results.

Full prevention would require scanner-side filtering (checking recently installed update IDs against current scan results). Documented as DEV-031.

---

## PART 5: WINGET TEXT PARSER (F-C1-2) — PASS

- Uses header line keyword positions (Name, Id, Version, Available) to determine column starts
- Falls back to simple parser if header not found
- Lines shorter than expected: handled by bounds checking
- Package names with spaces: preserved by position-based extraction

---

## PART 6: LOGGING FORMAT — PASS

- `fmt.Printf`: zero results in winget.go
- Emojis: zero results in service/windows.go
- Banned words: zero results across all modified files

---

## PART 7: EDGE CASES

- **Winget not installed**: returns error → empty update list → no crash
- **Old winget (pre-1.6)**: JSON fails → text fallback → column parser handles output
- **Long-running install**: install is synchronous; agent blocks during install, resumes polling after
- **RebootRequired persistence**: in-memory only on InstallResult. On restart, flag is lost. Ghost may reappear until Windows commits. Known limitation (DEV-031).

---

## PART 8: ETHOS COMPLIANCE

- [x] Winget not found logged
- [x] Reboot required logged
- [x] Backoff in service logged with ETHOS format
- [x] No emojis in modified files
- [x] No fmt.Printf in scanner
- [x] Graceful degradation on all failure paths
- [x] No banned words

---

## PART 9: PRE-INTEGRATION CHECKLIST

- [x] Linux AMD64 build passes
- [x] Linux ARM64 build passes
- [x] Windows AMD64 cross-compile passes
- [x] All 98 tests pass, 1 skip (pre-existing)
- [x] All 8 C-1 FAIL-NOW tests now PASS
- [x] B-2 jitter and backoff in Windows service
- [x] Remaining gaps documented (key refresh, dedup cleanup)
- [x] Winget searches known system locations
- [x] Ghost update: RebootRequired set (detection, not prevention)
- [x] Ghost update partial fix documented as DEV-031
- [x] Text parser handles spaces
- [x] fmt.Printf removed
- [x] Emojis removed
- [x] All edge cases documented
- [x] Deviations documented

---

## ISSUES FOUND

| # | Severity | Finding | Action |
|---|----------|---------|--------|
| 1 | LOW | Ghost update fix is detection-only, not prevention | DEV-031 |
| 2 | LOW | Service missing ShouldRefreshKey/CleanupExecutedIDs | Future deduplication |

---

## FINAL STATUS: VERIFIED (with 2 documented follow-ups)

All C-1 fixes structurally correct. Linux builds clean. No regressions.
Ghost update fix is partial (detection, not prevention) — documented.
