Repository navigation
Closed
Labels
app/pm-stackpm-stack (Pad/Grist) in developing-today/codepm-stack (Pad/Grist) in developing-today/codeeffort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/featureNew feature or capability requestNew feature or capability requestmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/humanFiled directly by a humanFiled directly by a humanstatus:done
Description
Finding
The delegation design (pm-stack-needs-drew-actions-design-2026-10-26.md §2, §4.1, §6 step 5) introduces a state the rest of the stack must join consistently: a needsDrew item whose delegation.status is proposal-ready (or unable). The simple path — proposal published, Drew approves from /attention, pass applies it — is covered by the UI and delegation-execution slices. The seams are not:
- The item can expire out of the section (24h unobserved rule) or be resolved by another path while a proposal is still on display; an approve click then targets a ghost.
- Drew can approve on a stale page render while a newer run has already replaced or withdrawn the proposal.
- A rejection reason, an inability return, and a re-delegation must compose: reject → delegate again → new proposal must not be confused with the rejected one.
- /today and the front-door overview count needsDrew items — a proposal-ready item is still Drew's item and must count and badge as such everywhere, not just on /attention.
Proposal
A small, explicit state-handling slice:
- Proposal identity: a proposal is identified by (item id +
delegation.runId+delegation.updatedAt); approve/reject actions carry that triple in their payload, and the consumer applies ONLY if it still matches the currently published proposal — a mismatch isrejectedwith note "proposal superseded/withdrawn", never a silent apply. - Expiry/withdrawal: when the pass withdraws a proposal (item resolved elsewhere, proposal replaced), it publishes the item once with the delegation transition recorded, or expires it with the withdrawal in
actions[]; the dashboard renders any pending approve/reject action on a vanished proposal as "no longer applicable" from the actions join, not as pending forever. - One rendering rule everywhere: proposal-ready and unable items render/count as needsDrew with their state badge on /attention, /today's banner, and the front-door overview (impl(aggregator): make / the stack front door - overview of all projects, attention, health, quotas (board moves to /board) #1134) — no surface may drop or double-count them.
- Re-delegation after rejection: the pass must mark a materially-new proposal (new runId) and the card shows "second first pass — previous rejected: " so Drew can see what changed.
Acceptance
- Race test (fixture consumer): approve action carrying a stale (runId, updatedAt) → rejected with the superseded note; the current proposal is untouched.
- Expiry test: item expires while proposal-ready → pending proposal actions render "no longer applicable"; no surface counts a ghost item.
- Cross-surface test: one proposal-ready + one unable item in a fixture section → /attention, /today banner, and overview counts agree (2 needsDrew, badges shown).
- Reject → re-delegate → new proposal renders with the previous rejection reason visible.
Refs: #1184 (epic), #1152 (actions store), #1134 (front-door counts). Design: pm-stack-needs-drew-actions-design-2026-10-26.md §2.1, §6.
Acceptance criteria
- A proposal carries a stable identity (item + run/proposal id) so an approve always targets the proposal Drew saw; approving a superseded, withdrawn, or expired proposal is a visible no-op with an explanation, never a silent apply.
- Reject → re-delegate produces a new proposal that cannot be confused with the rejected one (identity + history visible), and rejection reasons / inability returns compose with re-delegation per the design (§2, §4.1, §6 step 5).
- needsDrew counts agree across /today, the front-door overview, and /attention while proposals expire, are replaced, or are resolved by another path (cross-surface count check).
- Race cases are covered by tests or a scripted verification: expire-while-displayed, approve-on-stale-render, resolve-by-other-path-while-proposed.
Metadata
Metadata
Assignees
Labels
app/pm-stackpm-stack (Pad/Grist) in developing-today/codepm-stack (Pad/Grist) in developing-today/codeeffort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/featureNew feature or capability requestNew feature or capability requestmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/humanFiled directly by a humanFiled directly by a humanstatus:done
Activity
developing-today commentedon Oct 27, 2026
CODE-416
dezren39 commentedon Oct 27, 2026
Intake review
Fleet monitor intake pass (protocol §5), 2026-10-27.
Still live: verified this run — issue is OPEN, no merged PR references or closes it (0 closing-PR references), and it was filed within the last day, so nothing has had time to supersede it.
Related: Design: pm-stack-needs-drew-actions-design-2026-10-26.md §2/§4.1/§6. Sibling slices: #1290 (item contract), #1292 (delegation execution), #1291 (/attention UI).
Notes / risks: The seams issue of the delegation set — the happy path is covered by #1291/#1292; this one owns the races. Risk: fixing counts in one surface only; the acceptance check is deliberately cross-surface. Effort/m: state-join work across aggregator + orchestrator.
Suggested approach: Suggested approach: proposal identity first (everything keys off it), then expiry/supersede guards at apply time, then the cross-surface count reconciliation.
Labels normalized this pass; acceptance criteria appended to the body (original text preserved verbatim above it).
dezren39 commentedon Oct 27, 2026
Agent note — pickup (needs-user action layer build). Picked up as part of the #1290–#1293 slice on top of the landed triage write path (PR #1346/#1350, main
f9c9ffdb, 228 tests). Spec:pm-stack-needs-drew-actions-design-2026-10-26.mdincl. both decision updates (standing auto toggle ON for decision/missing-info/approval classes, access/policy never auto; role-based naming — new identifiers usewhyUser, no new Drew-named fields; legacyneedsDrewarray name untouched). Sequencing: contract → UI → consumer (orchestration-pass cron step) → seam hardening. Self-merge per PR when CI green; deploy + bounded live proof (first-pass only, no approval, no live auto execution) at the end.Merge pull request #1367 from developing-today/pm/needs-user-ui
dezren39 commentedon Oct 27, 2026
Agent note — complete. Proposal review state handling is built and live (PRs #1365 + #1367).
delegation.runId,delegation.updatedAt); approve/reject payloads carry the triple and the POST boundary refuses a stale triple as "proposal superseded/withdrawn" (also enforced consumer-side in the pass body). A newer proposal supersedes — the old one never renders as a second item.userwith the reason recorded; a re-proposal renders as "second first pass — previous rejected: " (render-tested).queue-discovery-design-pick, runorch-2026-10-27T09:05:40Z) is pending for the user with working Approve/Reject controls carrying the exact identity — left unapproved by design.