Show each decision's relationship to the document #367
- MA
## Why
A decision relates to the document's prose in one of four deliberate states: linked, pending, deliberately empty, or orphaned. Only linked had an affordance (an invisible hover target labelled "show in plan"). The other three looked identical in the Decisions tab and on the in-document settled line. "Show source in chat" also appeared on cards with no Chat source and did nothing when clicked.
## What changed
- Resolved cards show one quiet `text-xs` note at the start of the actions footer, and the in-document settled line shows the same note: - **Linked:** "Show in document" (ghost button). Hover highlights the prose, click reveals and pins it, using the existing `highlight`/`reveal`. It is now the only control on the card that jumps to the document. The answer block is no longer a second button. - **Pending:** a dot and a label, the same on the document line and the Decisions card. "Linking…" (pulsing dot) means the Planner still has to review where the decision lives. "Writing up…" appears only while a conversation decision's paragraph is being written. "Not linked yet" (dot without a pulse) appears when no Planner is available (`AGENT=off`), so the card doesn't promise work that won't happen. - **Empty:** "No related text", tertiary. - **Orphaned:** "Related text was removed" in the warning ink. On the settled line it keeps Reopen; Planner-anchored orphans now get it too. - `QuestionnaireStore.relations()` derives the state from the anchor sets (`reason: "orphaned"` outranks pending; trusted anchors that don't resolve locally yet count as pending, not empty). `Relation` lives in `@chopin/question`. - Resolved card footers get a little bottom padding (`--spacing` × 2.5). - "show in plan" accessible names now say "show in document". - "Show source in chat" only renders when the card's thread has a source (`hasCardSource` predicate from the workspace, also used by the resolved-decision popover).
## Screenshots
Seeded document with one decision in each state (linked, pending, empty, orphaned).
**Decisions tab, before / after**
 
**Phone, after**

**In-document settled lines, before / after** (linked collapses into its margin marker)
 
**Show source in chat on a card with no source, before / after**
 
## Verification
45 focused relation, anchor, and icon tests, `bun run types`, `bun run ci`, and `bun run build` pass on the restacked branch. GitHub's browser suite will run on the final published head. The reviewed dynamic-owner hashes were renewed after checking the integrated source.
The later #376 write-up integration is prepared locally and has a focused regression test for a linked relation after a failed prose job.
- MA
**Review:** Changes needed (minor; none blocking)
Checked in a browser (seed with all four states, AGENT=off, desktop 1440 and phone 390) and against AGENTS.md "Questions, comments, and anchors".
**Looks right** - The four states render distinctly and calmly in both Decisions cards and in-document lines: Linked "Show in document", Pending "Linking…" with a quiet dot, Empty "No related text", Orphaned in warning ink. Copy says "document". Phone footers fit without wrapping. - `relations()` derivation matches the domain: orphaned outranks pending, anchored-but-unresolved is pending (editor not caught up), zero anchors and not pending is empty (reviewed, no prose). `cardRelation` ORDER is consistent with it. - `hasCardSource` gating: no "Show source in chat" without a source thread. - Reopen on Planner-anchored orphaned decisions: the server's reopen only requires status `answered` and is not limited to conversation-origin prose, so offering it is permitted. Note that it just reopens the question. The prose re-placement in service-reopen.ts only runs for `record.prose`, so the button is a recovery path, not a relink.
**Findings** 1. `question-view.tsx:505` and `resolved-actions.tsx`: a resolved card with `places > 0` now has two controls that do the same thing, the answer block (`Related`, aria "... show in document") and the new "Show in document" note. That is two tab stops and two focus/hover highlights for one action. Suggest: make the note the only control, or render the answer block non-interactive when a note is present. (Verified by code. My seed has `places = 0` for the linked card in the Decisions tab, so I did not see it rendered.) 2. `relation-note.tsx` pending: "Linking…" is indefinite with `AGENT=off` (seen in the document and Decisions tab; no way out other than Reopen). It is honest but promises work that will never happen. Suggest the host passes a neutral state or label when the Planner is unavailable (e.g. `pending` prop already exists: "Not linked yet"), rather than a timeout, which would misreport a slow Planner as done. 3. `questionnaire.tsx` SettledLine: conversation-origin cards with no relation entry show "Writing up…" while the same card in the Decisions tab shows "Linking…". Same state, two words; fine if intentional, but worth one line in the PR. 4. Resolved-card footer sits tight to the card's bottom edge (note and Discard/Reopen almost touch the border, desktop and phone). Likely pre-existing padding, but the note makes it more visible. 5. CI: only `format, lint, types, tests` fails, and only on design-contract review hashes (plan-editor.tsx:346/357, resolved-layer.tsx:254/639/246, questionnaire.tsx:343/512/196, question-view.tsx:451/452/468/564, resolved-actions.tsx:24). Acceptable per the audit rules.
- MA
Thanks. All four points are fixed in f2689e3d:
1. **One control per action.** When a card shows the linked note, the answer block is plain text again (`places` isn't passed to `Resolved`), so the note is the only tab stop and the only hover highlight. A unit test checks that a linked resolved card has exactly one "show in document" control. The `sidecar.e2e.ts` click now targets the note. 2. **No Planner.** The workspace passes `planner={agent}` to both the Decisions tab and the PlanEditor. When it's false, pending reads "Not linked yet" and the dot doesn't pulse. There's no timeout. 3. **One word per state.** "Linking…" means the Planner still has to review where the decision lives. "Writing up…" appears only while a conversation decision's paragraph is being written (`origin === "conversation" && !hasProse`). The label is chosen once in `QuestionnaireCard`, so the document line and the Decisions card always match. The PR body states this rule. 4. **Footer spacing.** The resolved-card footer now has `padding-block-end: calc(var(--spacing) * 2.5)`.
I've updated the review hashes in the PR body. #376 (`WriteupStatus`) integration is now a one-line swap, also noted in the body.
- MA
Follow-up in the latest commit: the e2e run showed that conversation write-ups still run with `AGENT=off`, so "Writing up…" now takes precedence over "Not linked yet". "Not linked yet" only replaces "Linking…", the anchor review that needs the Planner. CI: e2e and container pass. Validation fails only on the design-contract review hashes listed in the body.
MaggieAppletonreferenced this in Show the real write-up state on decided conversation decisions #376last month on GitHub
MaggieAppletonreferenced this in Keep the settled decision icon full size when its text wraps #393last month on GitHub
MaggieAppletonhead-ref-force-pushed 5a2fd5914dcdlast month on GitHub
MaggieAppletonauto-rebase-enabledlast month on GitHub
MaggieAppletonmerged 383a25877af0last month on GitHub
MaggieAppletonhead-ref-deletedlast month on GitHub