Fix task-state availability and production diagnostics - #110
Fix task-state availability and production diagnostics#110sambitcreate wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
ℹ️ No critical issues — one minor robustness gap inline and one pre-existing observation.
Reviewed changes
- Authoritative task replay —
replayTodoStatenow scans the whole current Pi branch and validates only the newest non-isErrortodo result, so a newer valid checkpoint supersedes corrupt ancestors while a corrupt newest checkpoint still fails closed. - Honest durable tracking — chat-open and generation share
loadDurableTodoSnapshot; journalless turns omit the durable tool and publishstorage_not_enabled, corrupt replay publishesinvalid_snapshot, and tool output is re-validated against the reader contract before generation-local mutation. - Rollout refresh and cohort preservation —
PiUpgradeRolloutStore.load()re-reads and validates policy on every call, serializes first reads, publishes initial JSON with a no-overwritelink, andadvance()preservesactivatedAtwhen widening pastnew_chats. - Privacy-preserving diagnostics — error projection traverses bounded cause chains through own descriptors only (no getters or
stack), adds closedcauseCode/httpStatusevidence, distinguishes renderer exceptions and cancellations from process crashes and failures, classifies provider failures before outcome redaction, and records content-free todo/MCP evidence.
ℹ️ Durable renderer referenceId never reaches the journal (pre-existing)
The renderer diagnostic event stores durableReferenceId as fields.referenceId, but the field normalizer redacts the UUID before the SAFE_REFERENCE check runs, so the value is silently dropped and production reports cannot be correlated to their journal evidence. This predates the PR — flagging it because this change is hardening exactly that event.
Technical details
# Durable renderer reference ids never persist
## Affected sites
- `main/handlers/diagnostics.ts:108` — generates `durableReferenceId = RD-${randomUUID()}`.
- `main/handlers/diagnostics.ts:120` — stores it as `fields.referenceId`.
- `main/services/diagnostics-contract.ts:181` — `UUID_VALUE` rewrites the UUID to `[REDACTED ID]` inside `sanitizeDiagnosticText`.
- `main/services/diagnostics-contract.ts:184,278` — `SAFE_REFERENCE` then rejects `RD-[REDACTED ID]`, so `normalizeDiagnosticFields` drops the field.
## Required outcome
- Either persist a correlatable durable reference or stop generating and displaying one.
## Suggested approach (optional)
- Validate `referenceId` against `SAFE_REFERENCE` before the generic scrubber, or exempt it from `UUID_VALUE`/`LONG_IDENTIFIER`.
## Verification
- `normalizeDiagnosticFields({ referenceId: "RD-e20a0162-266b-49ab-ae0a-078f74efe71c" })` returns `undefined`; `sanitizeDiagnosticText` yields `RD-[REDACTED ID]`.
## Open questions for the human (optional)
- Is this already tracked separately? It is not introduced by this PR.ℹ️ Nitpicks
atomicPrivateJson(..., exclusive)now requires hard-link support for first policy creation, so a link-less userData volume (some SMB/exFAT or restricted mounts) would failload()where the previousopen(..., "wx")succeeded. Low risk for standard macOS/Windows/Linux userData and the atomicity win is real — noting it only so the tradeoff is explicit.
DeepSeek Flash | 𝕏
|
Addressed both actionable Pullfrog observations: fc96b21 closes failed-advance policy observation, and 6f3bf77 preserves main-generated RD-UUIDv4 references through journal normalization with an exact structural grammar. Each follow-up received three fresh DeepSeek V4.1 Flash reviews (30 reviews total); full npm test, diagnostics/compaction suites, typecheck, lint and production diagnostics E2E passed. The hard-link requirement is an accepted atomic-publication tradeoff consistent with existing repository storage patterns. Please recheck the updated head. |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Rollout observation latch —
PiUpgradeRolloutStore.readCurrentnow marks the store as having observed a valid policy on every validated parse, so a failedadvance()can no longer let a laterload()silently recreate a deleted policy; theENOENTinitialization branch rechecks the latch after asynchronous work, and a deterministic overlapping-load regression test covers the sequence. - Durable renderer references —
normalizeDiagnosticFieldsadmits the exactRD-<UUIDv4>grammar forreferenceIdbefore the generic ID redactor, so main-generated durable references persist and correlate in the journal; the new test confirms newline/URL/Bearer-wrapped values still drop.
DeepSeek Flash | 𝕏
|
Final verification on 6f3bf77: verify, Deterministic Electron E2E, changed-area detection and Pullfrog all succeeded; Android was correctly skipped. Pullfrog’s incremental review reports no new issues and its rollout thread is resolved. Both review follow-ups are separate commits, and 30 independent DeepSeek V4.1 Flash adversarial reviews are complete. Working tree clean; PR ready for merge. |

Summary
Fix the confirmed task-state and production-diagnostics defects found while investigating the desktop “Tasks unavailable” banner.
Separate fixes
Review process
Each fix received three independent
opencode-go/deepseek-v4.1-flashadversarial reviews. Rollout and diagnostics received additional three-review rounds after fixing edge cases found during review. Review lenses covered correctness/integration, hostile inputs/races/privacy, and behavioral coverage.Verification
npm testnpm run test:todonpm run test:compactionnpm run test:diagnosticsnpm run type-checknpm run lintnpm run buildnpm run test:e2e:diagnostics:productionDesktop todo IPC has no iOS/Android consumers. Portable provider-failure and shared-server contracts remain compatible.
Scope of the evidence
The old production logs discarded the causes of some provider, renderer, MCP and shutdown errors, so those historical causes remain unknown. This PR improves future diagnostic evidence. Production rollout advancement is a receipt-validated operator action; storage-disabled chats gain durable tracking when their cohort is enabled. These source changes reach the installed app through the normal release process.