Skip to content

fix(queen): issue proof must fail closed after reset, failed refresh and superseded checks #1392

Description

@dmitrii-f-t27

Problem

The Queen issue-proof reader (Corona and Memory) is meant to fail closed: a closed issue is honey only while exact canonical evidence is observed at the current default-branch HEAD. A static review of apps/website found two paths where an old positive verdict survives an explicit reset or a failed refresh. Both paths are in the shared infrastructure that #1371 connects for Memory; the review does not claim #1371 introduced them.

  1. A failed refresh keeps the old positive row in every layer above the reader.
    • queenRepositoryWorld.ts loadWorldIssueDetailsCached: fresh=true resets only the repository proof. If the GitHub issue read then fails, the old detailsCache row (coverage t27) stays, and the next non-fresh call inside the 60 s TTL returns it.
    • QueenCellStage.tsx reports the error locally but never withdraws the row it previously sent through onObserved.
    • QueenCatalogHive.tsx keeps the previous observed rows when the world reload fails; QueenUniverse.tsx RepositoryWorld keeps the previous snapshot rows. The map keeps painting coverage t27.
  2. An older in-flight check can repopulate a cleared cache. In queenIssueProof.ts, request A starts verifying HEAD₁; invalidateIssueProof runs and request B fails (unknown); A then finishes and unconditionally runs cache.set, so later reads get A's proof with a fresh observedAt. Deleting the Map entry does not cancel A, and the abort check runs only after the cache write.

Expected behaviour

  • A verdict may be written to a cache or returned as positive only when (verified) ∧ (the request is still the current generation for that repository) ∧ (the caller has not aborted). Anything else is unknown.
  • invalidateIssueProof and the start of every new verification advance a per-repository generation; a superseded check ends as unknown. Concurrent callers of the same generation share one in-flight check, so two views of the same world cannot disagree.
  • A refresh (explicit or after TTL) first removes the old details row; a failed refresh never leaves a positive row behind. On failure every observed layer (cell stage → hive observed, universe snapshot) withdraws coverage/proof and keeps only the lifecycle as the last observation.
  • Ordinary delay inside the agreed TTL after the last successful observation stays acceptable; the bug is a proof that comes back after an explicit reset or a failed refresh.

Spec first

apps/website/specs/queen/issue_proof_refresh.t27: a sealed truth table for publishing a positive (verified × current generation × live caller) and for keeping an observed positive (refresh succeeded × latest request). Generated TS constants and conformance vectors are consumed by the reader, the details cache and the UI layers.

Done when

Review source: owner-provided static review of head ecc3708; the four affected files are byte-identical at 846ccb3.

Activity

  1. added a commit that references this issue on Oct 4, 2026
    1b176df
  2. dmitrii-f-t27 commented on Oct 4, 2026

    @dmitrii-f-t27
    ContributorAuthor

    Spec, reproducing tests and fix are in #1390 at 1b176df (62/62 local website gate). The PR now closes this issue together with #1389.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions