038 — Collapse ProposalReader into PolledReader<Proposal[]>
What to build
Mirror of issue 037 for the Proposal catalog. ProposalReader (src/api/proposals.ts) is the same shape as PolledReader<T>. useProposals (src/hooks/useProposals.ts) is a 22-line rename hop.
Collapse: tauriProposalReader and fixtureProposalReader return PolledReader<readonly Proposal[]>; useProposals is deleted; callers use usePolledReader<readonly Proposal[]>.
Changes
src/api/proposals.ts — delete ProposalReader (or alias to PolledReader<readonly Proposal[]>). Keep ProposalDecisionResult, ProposalEdit, ProposalWriter — those are write-side, unrelated.
src/api/tauriProposalReader.ts — return PolledReader<readonly Proposal[]>. Rename list → read.
src/api/fixtureProposalReader.ts — same rename.
src/hooks/useProposals.ts — delete.
src/hooks/useAppState.ts (line 29) — call usePolledReader(proposalReader); destructure value as proposals. ProposalsState becomes PolledState<readonly Proposal[]>.
src/hooks/useAppState.test.tsx — update if reader signatures changed.
Out of scope
- Focus and caps pipelines (037, 039).
- Generic factory (040).
ProposalWriter — unchanged.
Completion promise
The Proposal catalog flows through one reader interface and one polling hook. ProposalReader and useProposals no longer exist; reads go directly through usePolledReader<readonly Proposal[]>.
Acceptance criteria
Blocked by
037 — same pattern, do Focus first to validate the call-site shape.
038 — Collapse
ProposalReaderintoPolledReader<Proposal[]>What to build
Mirror of issue 037 for the Proposal catalog.
ProposalReader(src/api/proposals.ts) is the same shape asPolledReader<T>.useProposals(src/hooks/useProposals.ts) is a 22-line rename hop.Collapse:
tauriProposalReaderandfixtureProposalReaderreturnPolledReader<readonly Proposal[]>;useProposalsis deleted; callers useusePolledReader<readonly Proposal[]>.Changes
src/api/proposals.ts— deleteProposalReader(or alias toPolledReader<readonly Proposal[]>). KeepProposalDecisionResult,ProposalEdit,ProposalWriter— those are write-side, unrelated.src/api/tauriProposalReader.ts— returnPolledReader<readonly Proposal[]>. Renamelist→read.src/api/fixtureProposalReader.ts— same rename.src/hooks/useProposals.ts— delete.src/hooks/useAppState.ts(line 29) — callusePolledReader(proposalReader); destructurevalueasproposals.ProposalsStatebecomesPolledState<readonly Proposal[]>.src/hooks/useAppState.test.tsx— update if reader signatures changed.Out of scope
ProposalWriter— unchanged.Completion promise
The Proposal catalog flows through one reader interface and one polling hook.
ProposalReaderanduseProposalsno longer exist; reads go directly throughusePolledReader<readonly Proposal[]>.Acceptance criteria
ProposalReaderinterface deleted (or aliased only).src/hooks/useProposals.tsdeleted.tauriProposalReaderandfixtureProposalReaderreturnPolledReader<readonly Proposal[]>.useAppState.tsusesusePolledReaderdirectly for proposals.task checkgreen.Blocked by
037 — same pattern, do Focus first to validate the call-site shape.