Summary
The stored-preview presentation added for #1397 / #1414 (present a terminal/expired proposal's stored diffPreview under a read-only banner instead of a live /diff) diverges between the Paper shell (PaperReviewView.vue) and the Legacy shell (useReviewActions.ts + ReviewProposalCard.vue). All three are pre-existing, cosmetic/copy-only (no correctness or security impact), and were surfaced by a two-lens adversarial review during the #1414 P2 round but left out of that PR's diff as out-of-scope. Tracking here per ADR-0038 (Paper/Legacy no-drift).
Findings
1. Recorded-operations fallback formatting differs across shells (MEDIUM)
This is the common expired path (normal creation flows don't populate diffPreview, so both shells synthesize a listing from the proposal's operations).
- Paper (
frontend/taskdeck-web/src/views/paper/PaperReviewView.vue:233): `${i}. ${formatActionLabel(op.actionType)} · ${op.targetType}…` → "1. Create Card · Card".
- Legacy (
frontend/taskdeck-web/src/components/review/ReviewProposalCard.vue:54): `${i}. ${op.actionType} ${op.targetType}…` → "1. CreateCard Card".
Different label transform (formatActionLabel vs raw actionType) AND separator (· vs space). The same expired proposal reads differently depending on shell. Specs currently bake in the drift (Paper spec asserts 'Create Card'; Legacy spec asserts /1\. CreateCard Card/), so aligning requires updating one shell's format + its spec. Suggested canonical: Paper's formatActionLabel + · (more human-readable; Paper is the go-forward shell).
2. Paper banner claims "stored preview" while showing the synthesized recorded-ops fallback (LOW/MEDIUM)
- Legacy renders an explicit note above its fallback (
ReviewProposalCard.vue:246-248): "No stored preview was captured — showing the proposal's recorded operations."
- Paper's non-revised fallback (
PaperReviewView.vue:1133-1139) has no such note, yet the banner (PaperReviewView.vue:1076) still reads "…showing the stored preview from the original submission" — inaccurate for the recorded-ops fallback (which is synthesized, not a stored preview). Paper does clarify in the revised case (revised-note); only the non-revised case is mislabeled. Add the same clarifying note to Paper for copy accuracy + parity.
3. Banner status wording drift for Applied (LOW)
- Paper
previewReadOnlyLabel (PaperReviewView.vue:216) uses the raw normalized status → "Applied".
- Legacy uses
reviewStatusLabel (ReviewProposalCard.vue:211) → "Applied to board".
Expired/Rejected/Failed/Dismissed labels match; only Applied diverges.
Scope / non-goals
Cosmetic + copy parity only. No behavior, correctness, or access-control change. When picking a canonical form, keep the shared-rule direction (ADR-0038) so the two shells converge rather than each keeping its own idiom.
References
Summary
The stored-preview presentation added for #1397 / #1414 (present a terminal/expired proposal's stored
diffPreviewunder a read-only banner instead of a live/diff) diverges between the Paper shell (PaperReviewView.vue) and the Legacy shell (useReviewActions.ts+ReviewProposalCard.vue). All three are pre-existing, cosmetic/copy-only (no correctness or security impact), and were surfaced by a two-lens adversarial review during the #1414 P2 round but left out of that PR's diff as out-of-scope. Tracking here per ADR-0038 (Paper/Legacy no-drift).Findings
1. Recorded-operations fallback formatting differs across shells (MEDIUM)
This is the common expired path (normal creation flows don't populate
diffPreview, so both shells synthesize a listing from the proposal's operations).frontend/taskdeck-web/src/views/paper/PaperReviewView.vue:233):`${i}. ${formatActionLabel(op.actionType)} · ${op.targetType}…`→"1. Create Card · Card".frontend/taskdeck-web/src/components/review/ReviewProposalCard.vue:54):`${i}. ${op.actionType} ${op.targetType}…`→"1. CreateCard Card".Different label transform (
formatActionLabelvs rawactionType) AND separator (·vs space). The same expired proposal reads differently depending on shell. Specs currently bake in the drift (Paper spec asserts'Create Card'; Legacy spec asserts/1\. CreateCard Card/), so aligning requires updating one shell's format + its spec. Suggested canonical: Paper'sformatActionLabel+·(more human-readable; Paper is the go-forward shell).2. Paper banner claims "stored preview" while showing the synthesized recorded-ops fallback (LOW/MEDIUM)
ReviewProposalCard.vue:246-248): "No stored preview was captured — showing the proposal's recorded operations."PaperReviewView.vue:1133-1139) has no such note, yet the banner (PaperReviewView.vue:1076) still reads "…showing the stored preview from the original submission" — inaccurate for the recorded-ops fallback (which is synthesized, not a stored preview). Paper does clarify in the revised case (revised-note); only the non-revised case is mislabeled. Add the same clarifying note to Paper for copy accuracy + parity.3. Banner status wording drift for Applied (LOW)
previewReadOnlyLabel(PaperReviewView.vue:216) uses the raw normalized status → "Applied".reviewStatusLabel(ReviewProposalCard.vue:211) → "Applied to board".Expired/Rejected/Failed/Dismissed labels match; only Applied diverges.
Scope / non-goals
Cosmetic + copy parity only. No behavior, correctness, or access-control change. When picking a canonical form, keep the shared-rule direction (ADR-0038) so the two shells converge rather than each keeping its own idiom.
References