Skip to content

[Frontend][Review] Stale revision load can certify an empty list after a persisted non-current save (#2215 residual) #2449

Description

@Chris0Jeky

Where. frontend/taskdeck-web/src/composables/useProposalRevisions.ts, the saveRevision early return for a non-current save (main line ~140; PR #2441 line ~153). Found by the independent verification of a Codex P1 thread on PR #2441; the gap pre-exists that PR (main has the identical early return), so it is tracked here rather than fixed in the PR.

Race. A save POST for proposal A is in flight. The reviewer navigates A → B → A. Each switch bumps saveGeneration and loadGeneration, and the return to A issues a fresh revisions GET whose server-side read can execute before the POST commits, so it returns an empty list. The POST then resolves; current is false, and the persisted-but-not-current branch returns without bumping loadGeneration. The stale GET resolves last: its generation still matches, so it writes revisionCount = 0, latestRevision = null, revisionsLoaded = true, certifying "A has no revisions" although one is persisted.

Effect. For a zero-original-operation proposal the view shows the false "invalid, no operations" surface and the Apply guard short-circuits with the zero-op toast; editablePayload falls back to the original operations. No data is lost server-side. The indeterminate path in #2441 invalidates on the same condition; the persisted path does not, which is the asymmetry.

Smallest fix (not applied). In the non-current persisted branch, when activeProposal.value?.id === proposalId, bump loadGeneration, set revisionsLoaded = false, and re-issue loadRevisionState(proposalId) after the POST resolved so it observes the commit. Do not increment revisionCount (the watcher already zeroed it for the reopened session). Add a spec that interleaves a slow createRevision with A→B→A and a stale getRevisions resolution.

Severity. Compound window (slow save surviving two selections, GET snapshot before commit, GET resolving after the POST continuation). Non-blocking under the causal bar; part of #2215's residual list.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Priority IIThe active direction's next tranche: wedge capabilities, significant defects, near-term hardening.bugSomething isn't workingfrontendPrimary implementation impact in Vue/TypeScript UI and client runtime.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions