Skip to content

fix(panel): re-read the summary while a run is shown as running - #382

Draft
lamemustafa wants to merge 2 commits into
masterfrom
tapish-codex/panel-refresh-while-running
Draft

lamemustafa wants to merge 2 commits into
masterfrom
tapish-codex/panel-refresh-while-running

Conversation

@lamemustafa

@lamemustafa lamemustafa commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #368. A run becomes interrupted by the clock alone: a dead worker writes nothing and never removes its lease, so no storage event fires. The panel refreshed its summary only on mount and on storage.onChanged, so a panel left open across a worker death kept rendering the run as in progress, with no retry control, until it was reopened. The owner hit exactly this live on 2026-09-16 ("reopened, retry button is there now").

An interval re-reads the summary every ten seconds only while the summary shows a run as running, and stops once it settles.

Root Cause / Decision Record

  • Premise verified in the issue: no timer existed anywhere in the popup or options entrypoints; mount and storage.onChanged were the only refresh paths.
  • Why a panel-side timer (argued on fix(panel): a run that becomes interrupted while the panel is open never re-renders #368): the MV3 objection applies to service-worker timers, not an extension page's. A hidden page's timers are throttled, which degrades this to "updates when you return", which is what reopening already did. Rejected: a heartbeat write (a second liveness signal beside the lease), and having the worker settle the projection on wake (the worker is dead; that is the premise).
  • Self-limiting. Gated on either summary's status === "running": an idle surface never polls, and the effect's cleanup clears the interval when the status changes or the surface unmounts.
  • Ten seconds. The lease is judged stale after thirty; ten puts the interruption on screen within about forty. Each tick is one local PACK_GET_FILED_RETURNS_FLOW_SUMMARY read: no network, no storage write.
  • The reader's selection is kept. The timer calls refreshFlowSummary() without adopting the saved run's scope, like the return-to-panel refresh.

Scope

  • Runtime: src/entrypoints/popup/use-pack-popup-controller.ts (one exported constant, one gated effect).
  • Tests: tests/popup/use-pack-popup-controller.test.tsx: re-reads and renders the interruption with no storage event (all-supported and single-return), stops after settling, never polls when idle.
  • Docs/governance: none.
  • Explicitly out of scope: the related note on fix(panel): a run that becomes interrupted while the panel is open never re-renders #368 that a stale lease also blocks Clear local Pack data (hasUnresolvedFiledReturnsRecoveryState in src/background/local-data.ts). The acknowledge path clears it first, so it is friction rather than a lockout; separate change.

Held for a live run

AGENTS.md requires a live authenticated run for runtime changes, and the issue asked that this one be watched doing its job rather than inferred. Draft until then. The check: start a full-year run with the panel open, stop the service worker, leave the panel open, and confirm the retry control appears within about forty seconds without reopening.

Pack Workflow Preflight

  • pnpm workflow:preflight was run before editing/push, or the skip reason is documented.
  • This PR was opened from a Pack branch, not master.
  • I checked latest master Pack AGENTS guidance or recorded the stale-guidance warning.
  • PR body keeps the required Pack privacy/review/verification checklist visible.

Sanchika Adoption Gate

Not applicable: no Sanchika adoption.

  • If this PR consumes @sanchika/* packages or copied Sanchika guidance, I
    read sanchika/docs/adoption-pack.md in the coordinated parent worktree.
  • If this PR consumes Sanchika, it links ComplyEaze and Axal completion evidence
    and records the Sanchika commit or copied guidance used.
  • This PR does not import ../sanchika, sanchika/packages/*/src, or parent
    source paths.

Privacy And Data-Flow Impact

  • No new browser permissions.
  • No new host permissions.
  • No new network calls.
  • No analytics, telemetry, ads, or session replay.
  • No credential, OTP, CAPTCHA, cookie, token, GST file, or taxpayer-data capture.
  • Public copy and privacy declarations are updated if behaviour changed — no user-facing copy changed.

Sensitive Surface Review

  • Current tab / portal target binding is preserved or intentionally changed.
  • Download completion remains evidence-backed and fail-closed.
  • Ambiguous side-effect delivery cannot be reported as confirmed success.
  • Service-worker durability impact is understood and documented.
  • Real taxpayer data, local paths, raw URLs/referrers, and portal HTML are absent from the diff.

Chrome Web Store Impact

  • This PR does not expand beyond the existing Chrome Web Store V0 listing unless every gate in docs/PUBLICATION_READINESS.md is checked.
  • Full fiscal year remains source-only and excluded from the next packaged Store build until its evidence gates are recorded.
  • Store copy, README status, Privacy QA, and reviewer instructions were reviewed if user-facing behavior changed — no user-facing copy changed.
  • CI ZIP creation, provenance, and protected publishing are treated as release evidence, not manual store-submission sign-off.
  • PR title uses Conventional Commits so Release Please can bump Pack after merge.

Verification

  • pnpm install --frozen-lockfile
  • pnpm audit --audit-level high
  • pnpm exec wxt prepare
  • pnpm exec prettier --check .
  • pnpm exec eslint . --max-warnings 0
  • pnpm exec tsc --noEmit
  • pnpm exec vitest run
  • pnpm exec wxt build
  • node scripts/verify-extension-package.mjs .output/chrome-mv3
  • pnpm exec wxt zip
  • node scripts/verify-extension-zip.mjs
  • node scripts/write-release-provenance.mjs
  • node scripts/verify-github-release-assets.mjs --tag <tag> --zip <zip> --checksum <sha256> --provenance <json> when release assets exist
  • node scripts/publish-chrome-web-store.mjs --zip .output/<zip> --provenance .output/pack-release-provenance.v1.json --publisher-id <id> --dry-run true
  • git diff --check
  • pnpm review:gate -- --strict-head-review --wait-head-review-ms 180000 before merge/readiness claim; a missing Codex review blocks readiness:

Artifact Evidence

  • CI run:
  • ZIP artifact:
  • ZIP SHA-256:
  • Clean source/tag or head SHA:

PR Review Follow-Up

  • GitHub Actions completed.
  • Autogenerated Codex/bot review comments inspected after checks completed for the latest head SHA.
  • Inline review threads are resolved, outdated, or answered with evidence.
  • No commits were pushed after the last required human/bot review without re-review.
  • Any follow-up PRs or issues are listed here instead of being left implicit.
Thread/comment Disposition Commit or evidence
Local Sonnet review: both summary paths leave running once the lease is stale; no forever-polling path confirmed toAllSupportedFullFiscalYearSummary and activeRunSummary (30s window)
Local Sonnet review: epoch guard, error-source gating, scope kept, panel uses this hook, local-only reads confirmed cited in review
Low (pre-existing): applyFlowResponse's failure branch does not bump summaryRefreshEpoch, so a timer read racing a failed action applies a slightly older read. A failed action writes no summary, so nothing fresher is overwritten; storage.onChanged already has the same exposure follow-up, not blocking recorded here

Screenshots

Use synthetic data only.

Verification detail

Exit codes captured directly: prettier 0 · eslint 0 · tsc 0 · build 0 · package verification 0 · git diff --check 0 · workflow preflight passed.

Popup and panel suites: Test Files 27 passed (27), Tests 411 passed (411). The full suite is left to CI because of tonight's machine load.

Driven to failure, each on its own: removing the gate fails the idle and settled tests; dropping the all-supported condition fails its test; dropping the single-return condition fails its test; not clearing the interval fails the settled test.

🤖 Generated with Claude Code

lamemustafa and others added 2 commits September 17, 2026 04:31
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The running-to-interrupted transition is a pure function of the clock, so
no storage event fires and an open panel kept rendering a dead run with
no exit. A timer gated on a running summary re-reads it every ten seconds
and stops once the run settles.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(panel): a run that becomes interrupted while the panel is open never re-renders

1 participant