Skip to content

planning: after a changed answer, take the user to the dependents it made stale #5909

Closed

Description

@kyle-sexton

Severity: high

Problem

When an answer with dependents is changed, the page moves on as if nothing else changed. After a save, send() calls nextNeeding(1) (index.html:1722) and toasts "Saved Q1. Now Q22." (index.html:1725). nextNeeding (index.html:1555-1559) walks rail order from the saved question and takes the next question that needsYou. It does not prefer the questions this save just made stale. The toast names none of them. When Show is set to Open, stale questions are answered, so they fail passes() (index.html:662) and nextNeeding skips them.

The server only marks dependents that already hold a decision (server.py:365-366). Marking undecided dependents is #5796 G3 hole 1. This issue covers what the page does after the save.

Expected

After a save that makes questions stale or upstream-pending:

  • the toast names them ("Q17 and Q54 need review; 7 more wait on them");
  • the next question is the first newly stale descendant, then its descendants in dependency order, as the terminal loop's "Recompute the tree" step does (context/loop.md step 6);
  • this happens whatever the Show filter is.

Suggested fix

Acceptance criteria

  • If changing Q1 makes Q17 and Q54 stale, the page lands on Q17 with a toast naming Q17 and Q54, under Show set to All or Open.
  • A UI test in surface/tests/ covers landing on the stale dependent.

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 2, 2026
  2. kyle-sexton commented on Oct 4, 2026

    @kyle-sexton
    ContributorAuthor

    This was generated by AI during triage.

    Routing: delegable, agent-ready, work-class: scoped (C3, bug fix), priority: medium. The priority is the assessed default. The reporter rated it high, but it blocks no other work and has no deadline.

    Verified against current code:

    • After a decision save, send() moves to nextNeeding(1) and toasts "Saved Qn. Now Qm." It does not compare which questions the save made stale. Basis: verified, plugins/planning/surface/index.html:1688-1727.
    • nextNeeding walks rail order from the saved question and skips any question that fails passes(). Basis: verified, index.html:1555-1559.
    • Under Show: Open, passes() requires an unanswered question, so a stale answered dependent is skipped. Basis: verified, index.html:660-663.
    • The server stales only direct dependents that hold a live decision, so undecided dependents get nothing. Basis: verified, plugins/planning/surface/server.py:364-365. That is feat(planning): interview page does not enforce answer order or react to changed answers like the terminal interview #5796 G3 hole 1, which this issue leaves out.

    Where I looked: the page's send, nextNeeding, firstNeeding, passes, refresh, the server's stale derivation, the terminal loop's "Recompute the tree" step (context/loop.md step 6), docs/out-of-scope/ (nothing matches).

    Cluster check: no shared decision. #5769's open decision 3 (recommended answering order across the frontier) is a different ordering: it governs what to answer first overall, and this issue governs where to go right after a save. #5796 G3 (server cascade) is scoped out by this issue's own body.

    Agent Brief

    Type: Bug
    Summary: After a save that makes other questions stale or upstream-pending, the page names them and takes the user to the first newly stale one, whatever the Show filter is.

    Current behavior:
    After a decision save, the page moves to the next question in rail order that needs the user and passes the current filter. The toast names only that question. The questions the save just made stale are not preferred or named. Under Show: Open they are skipped entirely, because they are answered.

    Desired behavior:

    • On a decision save, the page compares the stale and upstream-pending question sets before and after the post-save refresh.
    • When the save created new stale or upstream-pending questions:
      • The toast names the newly stale ids and counts the newly upstream-pending ones, for example "Saved Q1. Q17 and Q54 need review; 7 more wait on them."
      • The page selects the first newly stale question in dependency (tree) order. Later navigation goes through the other newly stale ones before the general next-needing order.
      • When the current Show filter would hide that question, the page switches the filter to Review, so the selected question is visible in the rail.
    • When the save created none, the behavior stays as it is now.
    • The "typing" branch and the held / noted branches (the page stays on the question) keep staying. They still name the newly stale ids in their toast.

    Key interfaces:

    • send() (the decision path after refresh()), nextNeeding(), passes(), and the Show filter state (S.filter, value review).
    • The page's view of question state (state of stale and upstream-pending from the server).

    Acceptance criteria:

    • If changing Q1 makes Q17 and Q54 stale, the page lands on Q17, with a toast naming Q17 and Q54, under Show: All and under Show: Open. Under Open, the filter switches to Review.
    • A save that stales nothing navigates exactly as before.
    • A UI test in the surface UI test suite covers landing on the stale dependent, and the filter switch.

    Out of scope:

  3. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 4, 2026
  4. kyle-sexton commented on Oct 4, 2026

    @kyle-sexton
    ContributorAuthor

    This was generated by AI during work-loop.

    Ratify autonomous dispatch of this C3 bug-fix item?

    Classification: work-class: scoped (C3), bug-fix-shaped (confirmed at triage this cycle). Intended dispatch: the work-loop worker lane, through /work-items:work, to a draft PR the lane never merges. Once ratified, the lane dispatches the interview-page items #5815, #5908, #5910 and #5911 one at a time, because they edit overlapping page code. First drain is not complete and no item-level ratification exists, so it is queued here. Ratify through /work-items:attend-queue and it dispatches on a later cycle.

    Lane: work-loop, instance melo-worker-1, cycle 1.

  5. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    and removed
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 4, 2026
  6. kyle-sexton commented on Oct 11, 2026

    @kyle-sexton
    ContributorAuthor

    Delivered on branch feat/planning-interview-page-batch in draft PR #7182, one commit for this issue (with Closes #5909).

    A save that makes answers stale lands on the first of them in dependency order, switches Show: Open to Review when needed, names them in the toast, and n visits the rest first.

    Verified: ui_page phase 4 checks the landing, the filter switch, the toast and n. The full surface.test.sh was last run in full before the final page commits; the later commits were checked with the ui_page phases. Its one standing failure (AC34 "user name found") is an environment artifact that also fails on main.

    Left for a human: the PR stays a draft until Kyle flips it to ready, which starts the CI and review lanes.

    The needs-human label was left for Kyle to clear.


    Generated by Claude Code

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

    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions