aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-28 03:31:59 -0500
committerCraig Jennings <c@cjennings.net>2026-05-28 03:31:59 -0500
commitaf9316c03a8699ddd49e9206578da86c5e8b9347 (patch)
tree2a616648aa90c0828e1d07006d08ac4540d70cbe
parent684b27360320868ce2c24b4513c1f806ac4b6b7e (diff)
downloadrulesets-af9316c03a8699ddd49e9206578da86c5e8b9347.tar.gz
rulesets-af9316c03a8699ddd49e9206578da86c5e8b9347.zip
chore(session): snapshot WIP, session-context, and inbox arrivals
Bundles end-of-session state across three concerns. claude-templates/.ai/workflows/open-tasks.org: in-flight restructure of Next Mode into a two-question output (cascade + friction filter), +62 lines. Separate from the iteration-history work that landed in 55adf6e and 684b273. .ai/session-context.org: live session record covering startup through the iteration-history backfill. Captures the no-approvals mode and the full spec-review/spec-response cycle on the working draft. inbox/: five new arrivals from this session: four pearl notes (pattern catalog, prompts-ux, spec-review implementation, prompt collapse) plus one .emacs.d note (whats-next + task-audit). A sixth file, PROCESSED-prefixed, represents mid-handling state on the open-tasks friction-cascade suggestion from earlier in the session.
-rw-r--r--.ai/session-context.org172
-rw-r--r--claude-templates/.ai/workflows/open-tasks.org62
-rw-r--r--inbox/2026-05-28-0124-from-.emacs.d-suggestion-whats-next-auto-considers-task-audit.org86
-rw-r--r--inbox/2026-05-28-0138-from-pearl-rulesets-open-tasks-archive-done.org29
-rw-r--r--inbox/2026-05-28-0155-from-pearl-rulesets-followup-prompts-ux.org69
-rw-r--r--inbox/2026-05-28-0226-from-pearl-rulesets-spec-review-implementation.org53
-rw-r--r--inbox/2026-05-28-0303-from-pearl-rulesets-followup-collapse-prompts.org88
-rw-r--r--inbox/PROCESSED-2026-05-28-0117-from-.emacs.d-suggestion-open-tasks-hybrid-friction-cascade.org80
8 files changed, 623 insertions, 16 deletions
diff --git a/.ai/session-context.org b/.ai/session-context.org
new file mode 100644
index 0000000..c15f4ad
--- /dev/null
+++ b/.ai/session-context.org
@@ -0,0 +1,172 @@
+#+TITLE: Session Context
+#+DATE: 2026-05-28
+
+* Summary
+
+** Active Goal
+
+** Decisions
+
+** Data Collected / Findings
+
+** Files Modified
+
+** Next Steps
+
+* Session Log
+
+** 2026-05-28 00:55 CDT — Startup + inbox triage
+
+Clean startup (no crash-recovery file). Rulesets + project repo current, templates synced, no reminders/pending decisions, task-review staleness 0, language bundle clean (no bundle in rulesets), cross-agent queue empty.
+
+Inbox held 4 files:
+1. pearl handoff 2026-05-27 23:31 — UI pattern standardization meta-question (cross-project pattern travel)
+2. pearl follow-up 2026-05-28 00:03 — third worked example (no-empty-input-as-meaningful)
+3. .emacs.d suggestion 2026-05-28 00:14 — add "recommendation at item 1" convention to interaction.md
+4. Codex spec 2026-05-28 — generic agent runtime support v0 (runtime-neutral rulesets)
+
+Craig chose option 1: process item 3 now (small, scoped, has proposed wording), file the rest as tasks before starting.
+
+** 2026-05-28 01:10 CDT — Filed remainder as tasks
+
+Moved 3 inbox files into docs/design/ so the task bodies' file: links survive:
+- inbox/2026-05-28-generic-agent-runtime-spec.org → docs/design/2026-05-28-generic-agent-runtime-spec.org
+- inbox/2026-05-27-2331-from-pearl-rulesets-handoff-ui-patterns.org → docs/design/2026-05-27-pattern-catalog-pearl-notes.org
+- inbox/2026-05-28-0003-from-pearl-rulesets-followup-no-empty-input.org → docs/design/2026-05-28-pattern-catalog-no-empty-input.org
+
+Added two TODOs to todo.org under Rulesets Open Work, both [#C], both LAST_REVIEWED 2026-05-28:
+- Cross-project pattern catalog :spec:thinking: — pairs the two pearl handoffs; open design questions captured; pearl available for spec-review iterations.
+- Generic agent runtime support — Codex spec v0 :spec:design: — links to moved spec; flags Codex's recommended Phase 1 (AI_AGENT_ID + session-context.d/) as the immediate-correctness slice independent of the broader refactor.
+
+Staleness still 0 after the additions. Mid-session inbox arrival noted but not processed: 2026-05-28-reconstruct-spec-workflow-history.org (1170 bytes, flagged for end-of-session or next inbox cycle).
+
+Next: implement the .emacs.d suggestion — add "Order Options with the Recommendation at Item 1" section to claude-rules/interaction.md (Craig pre-approved the draft).
+
+** 2026-05-28 01:30 CDT — No-approvals mode + three commits pushed
+
+Craig invoked no-approvals mode: no per-commit approval gates for the remainder of the session, /review-code and /voice personal still mandatory, stop only on a real question (recommendation as item 1) or when done. Craig asked me to create .ai/project-workflows/no-approvals.org capturing this contract, then follow it.
+
+While I was preparing the interaction.md edit, Craig himself added the "Order options with the recommendation at item 1" subsection — as an H3 inside the existing "No Popup Menus for Choices" section (better placement than my proposed H2). Wording covers the same trigger/skip/last-option ground; I committed his edit verbatim. The .emacs.d inbox file was deleted as processed.
+
+Three commits, all pushed to origin/main (adce315..96f0a5f):
+- e27bf57 feat(workflows): add no-approvals.org project workflow
+- 1777773 docs(rules): add recommendation-at-item-1 convention to interaction.md
+- 96f0a5f chore(intake): file pearl pattern-catalog and codex runtime spec as TODOs
+
+Each ran /review-code (all Approve, no Critical/Important) and /voice personal walked inline (clean — no em-dashes, semicolons, fragments).
+
+** 2026-05-28 01:35 CDT — Surfacing question: org-drill inbox vs Craig's WIP
+
+Read the inbox arrival 2026-05-28-reconstruct-spec-workflow-history.org (org-drill asking whether rulesets can backfill iteration-history sections for the spec-review/spec-response workflow files themselves, using rulesets' session history as evidence). Discovered the request directly overlaps Craig's uncommitted WIP — he is currently adding the "Review and iteration history" REQUIREMENT to both workflow files (spec-review.org +18 lines establishing the section spec; spec-response.org +26 lines adding the same on the response side; open-tasks.org +62 lines on a separate friction-cascade restructure).
+
+The org-drill backfill request can't ride on top of in-flight requirement work without conflict. Surfacing as a real question for Craig: defer, do alongside, or skip.
+
+Inbox not touched (file still present); Craig's WIP untouched.
+
+** 2026-05-28 01:36 CDT — Craig picked option 1; filed as TODO + pushed
+
+Filed the org-drill backfill request as ** TODO [#C] under Rulesets Open Work, tagged :docs:followup:, with the dependency on Craig's WIP committal explicitly stated. Deleted the inbox file. LAST_REVIEWED 2026-05-28, staleness still 0.
+
+Commit 80775e7 chore(intake): file org-drill iteration-history backfill as TODO. /review-code Approve, /voice personal walked clean. Pushed to origin/main (96f0a5f..80775e7).
+
+Another inbox arrival mid-stream noted but untouched: 2026-05-28-0124-from-.emacs.d-suggestion-whats-next-auto-considers-task-audit.org (6036 bytes). Out of scope for this turn — Craig's directive was scoped to the org-drill request.
+
+Planned work is fully done (4 commits this session, all pushed). Not auto-wrapping per the no-approvals contract — wrap-up stays Craig's call.
+
+** 2026-05-28 01:50 CDT — Iteration-history backfill phases 1-4 (read-only research + draft)
+
+Craig asked "as you recommend" for the iteration-history backfill TODO. Ran phases 1-4 (read-only research + drafting) without touching the workflow files.
+
+Evidence base assembled:
+- git log --follow on both workflow files: one commit each (7f2aea1, 2026-05-23)
+- Full body of 7f2aea1 (rich provenance — names all 5 tightening edits, the 3 research subagents, the close-read findings)
+- Session record .ai/sessions/2026-05-24-03-10-spec-workflows-memory-sync-and-ai-kb-reviews.org (contains both the install pass AND the cross-project ai-kb application that validated the loop)
+- INDEX entries
+- Craig's current uncommitted WIP via git diff (the 2026-05-28 Iteration-3 requirement addition)
+
+Three iterations identified per file, all gathered with confidence ratings (HIGH where commit/session-backed, INFERRED on the original drafts' "why" pressure + the trigger sequencing for Iteration 3). Plus cross-project applications noted as deployment evidence but flagged as belonging in ai-kb.org's own history, not these workflow files'.
+
+Output: working/spec-workflows-iteration-history-backfill/draft-entries.org (untracked). Includes draft entries for both files, evidence base, confidence ratings, a recommendation to splice once WIP commits, suggested splice plan, and 4 open questions for Craig (labeling convention, section placement, granularity, INFERRED-line treatment).
+
+Phases 5-6 await Craig's judgment + WIP commit. Working dir not committed (per working-files convention — it ships flat into the workflow files on completion, dir gets deleted).
+
+** 2026-05-28 01:55 CDT — Handoff confirmed; standing by
+
+Craig picked option 1: he reviews the draft entries + answers the 4 open questions + commits his WIP, then I splice (single follow-up commit, working dir deleted). Standing by — nothing else queued.
+
+** 2026-05-28 02:40 CDT — Codex review came back; spec-response cycle complete
+
+Craig handed off to Codex for review of draft-entries.org. Codex's review file landed at working/spec-workflows-iteration-history-backfill/draft-entries-review.org (verdict: Not ready; two blocking findings on correctness).
+
+Ran the spec-response workflow against it:
+- Phase 0: oriented on the working draft + review file
+- Phase 1: read the whole review before touching the spec
+- Phase 2: dispositions assigned to every finding (5 accepts; 2 modified to preserve original-draft detail Codex's rewrites had compressed out)
+- Phase 3: N/A (single spec under review)
+- Phase 4: applied edits to draft-entries.org — fixed both blocking correctness issues (spec-review Iteration 2 split; spec-response Iteration 2 "Three edits" with file-specific content), added Codex's two medium points and the UX trim guidance to the splice plan, added a Review-dispositions section + a Review-and-iteration-history section (Draft 1 / Review 1 / Response 1)
+- Phase 5: deleted the review file per workflow exit criterion; updating session log now
+
+Verdict: Ready-with-caveats. The 4 open questions for Craig remain (iteration labeling, section placement, granularity, INFERRED-line treatment) — those are the caveats. Both blocking correctness issues resolved.
+
+Working dir state: just draft-entries.org. Still uncommitted (working files don't ship until splice). Codex's review file deleted per spec-response Phase 5.
+
+Next: Craig answers the 4 open questions + commits his WIP. Then phase 6 splice + working dir cleanup + single commit.
+
+** 2026-05-28 02:55 CDT — Codex Round 2; spec-response cycle round 2
+
+Codex re-reviewed the post-Response-1 draft. Verdict: Ready-with-caveats. No high or medium findings. Three accepts (optional INDEX path polish; test-strategy verification steps for splice closure; canonical/mirror distinction stays).
+
+Spec-response cycle round 2:
+- Applied the INDEX path polish in the evidence list
+- Added item 6 to the splice plan covering the three verification steps Codex named (7-field check per entry, canonical/mirror diff, git-diff-scope confirmation)
+- Renamed "Codex review 2026-05-28" → "Codex Review 1" in dispositions for symmetry; added a "Codex Review 2" disposition section
+- Added Review 2 + Response 2 entries to the Review-and-iteration-history section
+- Deleted the round-2 review file per spec-response Phase 5
+
+Status unchanged: Ready-with-caveats. The 4 open questions for Craig remain the only caveats — no further reviewer-discoverable issues expected.
+
+** 2026-05-28 03:13 CDT — All 4 open questions answered; Response 3 applied
+
+Walked Craig through the 4 open questions one by one. His answers:
+
+1. *Labeling:* compound-id heading "timestamp — contributor — role". Rejected sequence labels (Draft 1, Review 1, etc.) on the grounds that sequence implies ordering it can't reliably carry under branching. Compound id is opaque — nothing more should be read into it.
+2. *Placement:* literal bottom of each file.
+3. *Iteration 2 granularity:* combined "reviewer + responder" entry — honest to single-pass evidence.
+4. *INFERRED whys:* replaced with direct rationale. Iteration 1 (linear-emacs drafts) was motivated by division-of-labor by comparative advantage (Craig's time on user scenarios + direction-setting; agents on structured technical review). Iteration 3 (requirement addition) was motivated by needing scannable processing state inside spec content — file mtime / created-time was the only signal, silly and error-prone.
+
+Response 3 applied all 4 answers to the draft:
+- Restructured 6 entries (3 iterations × 2 files) to compound-id heading shape
+- Updated top-of-file entry-shape description to match
+- Flagged that Craig's uncommitted WIP entry-shape requirement needs a small adjustment to match (drop Iteration + Date as separate body fields; the heading-as-compound-id covers them)
+- Renamed Open Questions → Agreed Decisions, with each resolution recorded
+- Added a Response 3 history entry inside the draft's own iteration history
+- Iteration 3 timestamps remain placeholders ([commit-time pending]) until WIP lands
+
+Draft status: Ready. Pending only: Craig's WIP commit + .ai/ mirror sync, then splice into the two workflow files. Splice plan items 1-6 in the draft cover the splice procedure including the 7-field check (now compound-id-heading + 3 body fields), canonical-vs-mirror diff verification, and intended-files-only check.
+
+** 2026-05-28 03:25 CDT — Craig delegated commit + splice; two commits pushed
+
+Craig: "commit the changes for me please. then splice the iteration history into both files."
+
+Executed both. Open-tasks.org left uncommitted per scope (Craig's separate WIP, not part of the iteration-history work).
+
+Commit A — 55adf6e feat(workflows): add iteration-history requirement to spec workflows:
+- Entry-shape adjustment in both canonical workflow files: replaced the old list (Iteration / Date / Contributor / Role / What / Why / Artifacts as separate body fields) with the compound-id form Craig settled (heading-as-timestamp+contributor+role + 3 body fields)
+- Rsynced canonical → mirror so both copies byte-identical
+- 4 files staged: claude-templates/.ai/workflows/{spec-review,spec-response}.org + .ai/workflows/{spec-review,spec-response}.org
+- /review-code Approve, /voice personal walked clean
+- Pushed (e83e323..55adf6e)
+
+Commit B — 684b273 feat(workflows): backfill iteration history in spec workflows:
+- Added new "* Review and iteration history" section at literal bottom of both canonical workflow files (after Research notes on spec-review.org; after Updates and Learnings on spec-response.org)
+- Each file got 4 entries: Draft 1 (linear-emacs, 2026-05-23 placeholder), Review-and-Fold (7f2aea1, 2026-05-23 12:59:31), Requirement addition (55adf6e, 2026-05-28 03:22:25), This backfill (2026-05-28 03:23:01)
+- Rsynced canonical → mirror, byte-identical
+- Deleted the working/spec-workflows-iteration-history-backfill/ directory and its parent (empty)
+- Closed the org-drill backfill TODO in todo.org (DONE [#C], CLOSED [2026-05-28 Thu])
+- 5 files staged: 4 workflow files + todo.org
+- /review-code Approve, /voice personal walked clean
+- Pushed (55adf6e..684b273)
+
+Verification: =diff -u= canonical vs mirror confirmed byte-identical on both files in both commits. =git diff= scope confirmed only intended files (no incidental working notes). 7-field entry-shape — actually 4 with the compound-id reform — present in every entry across both files.
+
+org-drill backfill TODO complete. Open-tasks.org WIP still uncommitted (Craig's separate change). Iteration-history requirement now live in both workflow files plus mirror; future spec reviews under either workflow will add their own entries per the new requirement.
diff --git a/claude-templates/.ai/workflows/open-tasks.org b/claude-templates/.ai/workflows/open-tasks.org
index b07f352..7143aea 100644
--- a/claude-templates/.ai/workflows/open-tasks.org
+++ b/claude-templates/.ai/workflows/open-tasks.org
@@ -118,61 +118,89 @@ For tasks Craig says are NOT done, leave them as-is.
** Next Mode
-Apply the prioritization cascade in order. Stop at the first matching step:
+Next Mode answers two questions in one output: "what matters most right now?" (the cascade, importance/urgency) and "what shape of task can I actually finish?" (the friction filter, effort + autonomy). The user picks the row that matches the state of their day.
-*** 1. In-Progress Tasks
+*** Step 1 — Cascade recommendation (importance/urgency)
+
+Apply the prioritization cascade in order. Stop at the first matching step. This is the importance/urgency answer.
+
+**** 1. In-Progress Tasks
- Look for tasks marked =DOING= or partially complete.
- *If found:* Recommend that task (always finish what's started).
- *If user declines:* Continue to next step.
-*** 2. Active Reminders
+**** 2. Active Reminders
- Review notes.org Active Reminders (already in the Phase A snapshot).
- *If found:* Recommend reminder task.
- *If user declines:* Add to =todo.org= per Phase B (if not already there), then continue.
-*** 3. Deadline-Driven Tasks
+**** 3. Deadline-Driven Tasks
- Scan =todo.org= for tasks with explicit deadlines.
- *If found:* Recommend the task with the closest deadline.
- *If none:* Continue to next step.
-*** 4. V2MOM Method Order (if applicable)
+**** 4. V2MOM Method Order (if applicable)
If =todo.org= is structured with V2MOM methods:
- Method 1 priority A tasks first.
- Then Method 2 priority A, Method 3 priority A, etc.
- Then Method 1 priority B, Method 2 priority B, etc.
- Continue pattern through priorities C and D.
-*** 5. Simple Priority Order
+**** 5. Simple Priority Order
If =todo.org= is a flat list:
- Evaluate all priority A tasks, pick most important.
- If no priority A, evaluate priority B tasks.
- Continue through priorities C and D.
-*** 6. All Tasks Complete
+**** 6. All Tasks Complete
If no tasks remain: report "All done — no open tasks in =todo.org=."
-*** Handling Multiple Tasks at Same Level
+**** Handling Multiple Tasks at Same Level
When multiple tasks share priority/method position, pick one based on:
1. *Blocks other work* — dependencies matter.
2. *Recently discussed* — mentioned in recent conversation.
3. *Most foundational* — enables other tasks.
-4. *If truly uncertain* — show 2-3 options and let Craig choose.
+4. *If truly uncertain* — show 2-3 options and let the user choose.
+
+*** Step 2 — Friction filter (effort + autonomy)
+
+Independently of the cascade, scan the open-task set for tasks tagged =:quick:= and =:solo:=. Build three ranked picks:
+
+- *Quick + solo* — the top task carrying BOTH tags. Smallest effort × highest autonomy = lowest friction. Ideal for a 20-minute window or a flagging-energy moment.
+- *Quick only* — the top task carrying =:quick:= but not =:solo:=. Small but needs the user's preference / hardware / sign-off.
+- *Solo only* — the top task carrying =:solo:= but not =:quick:=. Bounded scope that Claude can finish end-to-end, but not a short job.
+
+Within each row, pick a single task per the same-level tie-breakers above (blocks-other-work, recently-discussed, most-foundational). If a row has no tasks, omit it rather than padding.
+
+The friction filter is the override path. When the cascade winner is partially blocked, hardware-dependent, or simply too large for the user's current state, one of the friction rows is what they pick instead.
*** Output Format
-Keep the recommendation concise but informative:
+Pair the cascade recommendation with the friction block beneath it. Recommendation-at-item-1 convention applies to the friction rows — quick+solo first, since it's the strongest low-friction pick.
#+begin_example
-Next: Fix org-noter reliability (Method 1, Priority A, 8/18 complete)
-Reason: Blocks daily reading/annotation workflow
+Cascade recommendation (importance/urgency):
+- Fix org-noter reliability — [#A], Method 1, 8/18 complete, blocks daily reading/annotation
+
+If you want lower friction instead:
+1. Quick + solo: Bump linter config — [#C] :quick:solo:, ~15 min
+2. Quick: Confirm new dirvish setup — [#B] :quick:, needs your eye
+3. Solo: Refactor config-utilities — [#B] :solo:, bounded but multi-hour
#+end_example
-Include:
+Include for each row:
- Task name / description.
-- One-line reasoning (which cascade step matched and why).
-- Progress indicator (for V2MOM-structured todos).
+- Priority + tag cluster.
+- One-line reasoning. For the cascade row, name which cascade step matched. For friction rows, an effort hint when one is obvious.
+- Progress indicator (for V2MOM-structured todos) on the cascade row only.
+
+**** Edge cases
+
+- *Empty friction block.* If no =:quick:= or =:solo:= tagged tasks exist in the open set, omit the friction block entirely. Present only the cascade recommendation.
+- *Dedupe.* If the cascade recommendation IS the same task as one of the friction rows (e.g. it's =:quick:solo:= and also won the cascade), show it once at the top with both labels. Don't list it twice.
+- *Decline behavior.* If the user declines the cascade recommendation, drop straight to the friction block as the natural next prompt. Do not fall through to lower-cascade-tier tasks; the friction filter IS the override.
* Resolving a Task — Format Reference
@@ -204,8 +232,10 @@ Key elements:
4. *Creating =todo.org= entries for pure informational reminders* — use judgment in Phase B.
5. *Using a table for the task list* — Craig prefers flat bulleted lists in list mode.
6. *Skipping the cascade order in next mode* — the cascade exists to override subjective choice with objective criteria; respect it.
-7. *Recommending more than one task in next mode* — be decisive. Only show 2-3 if truly uncertain after applying the same-level tie-breakers.
+7. *Recommending more than one task in the cascade row* — be decisive on the cascade. The friction block is a 3-row choice by design, but the cascade row is single-pick.
8. *Re-querying =todo.org= during Phase C* — the snapshot from Phase A is canonical; don't re-read.
+9. *Skipping the friction block when the cascade winner isn't actionable.* The friction filter is the override path; don't fall through to lower-cascade-tier tasks if a =:quick:= or =:solo:= task is what's actually needed.
+10. *Padding the friction block when a row is empty.* If no task carries both =:quick:= and =:solo:=, omit that row entirely. Don't promote a =:quick:=-only task into the =:quick:solo:= slot.
* Living Document
diff --git a/inbox/2026-05-28-0124-from-.emacs.d-suggestion-whats-next-auto-considers-task-audit.org b/inbox/2026-05-28-0124-from-.emacs.d-suggestion-whats-next-auto-considers-task-audit.org
new file mode 100644
index 0000000..4e3e6fd
--- /dev/null
+++ b/inbox/2026-05-28-0124-from-.emacs.d-suggestion-whats-next-auto-considers-task-audit.org
@@ -0,0 +1,86 @@
+#+TITLE: Suggestion — what's-next should auto-consider task-audit and run when warranted
+#+FROM: dotemacs (~/.emacs.d)
+#+DATE: 2026-05-28
+
+* Suggestion
+
+Extend =claude-templates/.ai/workflows/open-tasks.org= Next Mode with a pre-step: before producing the cascade + friction output, evaluate whether a =task-audit= is warranted and offer to run it first. The user shouldn't have to remember to schedule audits — they get triggered by the workflow when needed.
+
+* Why
+
+Task-audit is the "is each task factually accurate?" workflow. Its value compounds with drift: as sessions land changes, as deadlines pass, as referenced files move, the open-task body content drifts out of sync with reality. Today the user has to remember to invoke =task-audit= explicitly. In practice that means audits happen rarely and the open-task set accumulates stale claims.
+
+The =task-review= workflow already runs daily as a habit. The =task-audit= workflow runs roughly never. Coupling audit to "what's next" closes that gap — every time the user asks the system to recommend work, the system checks whether the recommendation is being made over stale facts and offers to clean up first.
+
+* The criteria for "warranted"
+
+Hybrid: temporal threshold OR state-signal detection. Either trips it.
+
+** Temporal threshold
+
+Track =:LAST_AUDIT:= in =notes.org= under a new "Workflow State" section (or, alternately, as a single-line marker like =# LAST_AUDIT: YYYY-MM-DD= at the bottom of =notes.org=). If absent, treat as "never run." If older than 14 days, the threshold trips.
+
+The threshold value (14 days) is a starting point — projects with high churn could tune it down, low-churn projects up. Lives as a per-project knob in =notes.org=.
+
+** State-signal scan
+
+During Phase A's existing snapshot, check these cheap signals:
+
+1. *Reminder-vs-task mismatch.* Active Reminder names a task or completion target that doesn't appear in =todo.org= (or vice versa: =todo.org= names a reminder that isn't in =notes.org='s Active Reminders).
+2. *Passed scheduled date.* A task with a =SCHEDULED:= or =DEADLINE:= date earlier than today, still =TODO= or =DOING=, no completion log.
+3. *"Waiting on X" matches a completed X.* Task body contains a phrase like "waiting on", "after X ships", "blocked by"; the recent session summaries (already in the snapshot) log the named X as shipped.
+4. *Reference to deleted artifact.* A task body's =file:= link points to a path that doesn't exist (use a single existence check per linked path).
+5. *Sub-task DONE coverage.* A task with many sub-tasks where >75% are DONE/CANCELLED but the parent is still =TODO= or =DOING= — a likely promotion candidate.
+
+Any one signal trips the audit-warranted flag. Signals 1–3 are cheap. Signal 4 needs filesystem access (still cheap per-task). Signal 5 is a counting pass.
+
+** Combined
+
+Audit warranted if (temporal threshold tripped) OR (any state signal tripped).
+
+* Proposed Phase A addition
+
+Add to the Phase A parallel batch (after the existing 4 reads):
+
+5. Read the =:LAST_AUDIT:= marker from =notes.org= (or note its absence).
+
+* Proposed new section: Phase A.1 — Audit warranted?
+
+Between Phase A and Phase B, evaluate the warranted check from the snapshot. If tripped, surface to the user with numbered options:
+
+#+begin_example
+Task-audit looks worth running before this recommendation:
+- Temporal: <N> days since last audit (threshold 14)
+- Signal: <specific finding, e.g. "L46 reminder names 'fix X' but no task matches">
+
+1. Run task-audit first — fixes the facts, then I'll come back to next-task
+2. Skip the audit — proceed straight to what's next
+3. Run audit but only the autonomous half (factual updates) — defer the judgment calls to a later session
+#+end_example
+
+If not tripped, proceed silently to Phase B.
+
+* Refreshing :LAST_AUDIT:
+
+When =task-audit= runs from anywhere, its Phase C should stamp =:LAST_AUDIT:= to today's date in =notes.org=. The trigger has to live in =task-audit.org= so it works for the manual invocation too, not just the chained-from-whats-next path. That's a one-line addition to that workflow's Phase D close-out.
+
+* Implementation order
+
+Two coupled changes that should land together:
+
+1. =task-audit.org= Phase D — stamp =:LAST_AUDIT:= on completion (date format =YYYY-MM-DD= for trivial parsing).
+2. =open-tasks.org= — add the Phase A read, the new Phase A.1 evaluate-warranted block, and a "Common Mistakes" entry "Running the cascade over stale facts — always evaluate audit-warranted first; let the user override."
+
+If only one of the two lands, the feature is broken — the stamp wouldn't get set without the audit edit; the audit-warranted check would fail without the read. Land them as a pair.
+
+* Open questions
+
+- Storage location for =:LAST_AUDIT:= — a top-of-notes.org property line, a dedicated "Workflow State" subsection in notes.org, or a sibling =.ai/workflow-state.org= file. (The sibling file is cleanest if more workflow-state markers accumulate; notes.org is fine for one or two.)
+- Threshold value — 14 days is a defensible default but should be a per-project knob. Naming the knob: a top-of-notes.org line =# AUDIT_THRESHOLD_DAYS: 14= alongside the marker?
+- Should the audit run automatically (no prompt) when both signals AND threshold trip? The recommendation-first convention argues for prompting with item 1 = "yes run it" rather than silent auto-run, since "what's next" is interactive anyway.
+
+* Source
+
+Drafted from the dotemacs session 2026-05-28. The user's framing: "I won't really ever have to think about the task-audit workflow." This suggestion answers that — by hooking it to the workflow the user already invokes.
+
+References the prior two rulesets suggestions (=2026-05-28-0014-from-.emacs.d-...= for recommendation-first option ordering, and =2026-05-28-0117-from-.emacs.d-...= for the open-tasks.org hybrid output shape). The auto-audit pre-step is the third leg of the same triple — together they make "what's next" the single point of entry for task-level work.
diff --git a/inbox/2026-05-28-0138-from-pearl-rulesets-open-tasks-archive-done.org b/inbox/2026-05-28-0138-from-pearl-rulesets-open-tasks-archive-done.org
new file mode 100644
index 0000000..fd6687b
--- /dev/null
+++ b/inbox/2026-05-28-0138-from-pearl-rulesets-open-tasks-archive-done.org
@@ -0,0 +1,29 @@
+#+TITLE: open-tasks workflow should run --archive-done before reading
+#+DATE: [2026-05-28 Thu]
+#+SOURCE: pearl session 2026-05-28
+
+* The gap
+
+=workflows/open-tasks.org= (the "what's next" / "list open tasks" workflow that merged in the older =whats-next.org=) reads =todo.org='s =* Project Open Work= section in Phase A and skips =* Project Resolved=. That's correct in principle, but in practice a level-2 task that completed during the session sits as =** DONE= under =Open Work= until something archives it. The cleanup tool's =--archive-done= sweep is what moves it to =Resolved=, and only =workflows/clean-todo.org= and the wrap-up workflow currently run it.
+
+The consequence: between cleanups, =open-tasks.org= can surface a freshly-DONE task as a "what's next" candidate. The reconcile phase doesn't filter on TODO state. In a session where Craig shipped a few things and immediately asks "what's next," he gets recommendations that include work he just finished.
+
+* Proposed fix
+
+Add an =--archive-done= sweep as the first step of =open-tasks.org='s Phase A, before the parallel reads. One line:
+
+#+begin_src bash
+emacs --batch -q -l .ai/scripts/todo-cleanup.el --archive-done todo.org
+#+end_src
+
+Then Phase A's read of =todo.org= sees a clean Open Work section and the reconciliation works against current state.
+
+The cost is a few hundred milliseconds at the start of every "what's next" invocation. The win is recommendations that never include DONE work.
+
+* Optional refinement
+
+If the workflow ever runs in a context where Craig actively does *not* want write side effects (a read-only dry run, a presentation mode), gate the sweep behind a check. The default invocation should still archive — the dry-run case is the exception.
+
+* Triggered by
+
+2026-05-28 pearl session, after marking several VERIFY tests DONE inline during a verify walk-through. Craig flagged that the next "what's next" would see those still in Open Work until the next cleanup.
diff --git a/inbox/2026-05-28-0155-from-pearl-rulesets-followup-prompts-ux.org b/inbox/2026-05-28-0155-from-pearl-rulesets-followup-prompts-ux.org
new file mode 100644
index 0000000..cc2cb77
--- /dev/null
+++ b/inbox/2026-05-28-0155-from-pearl-rulesets-followup-prompts-ux.org
@@ -0,0 +1,69 @@
+#+TITLE: Pattern catalog — two more worked examples from pearl prompts
+#+DATE: [2026-05-28 Thu]
+#+SOURCE: pearl session 2026-05-28, follow-up to earlier UI-patterns notes
+
+* Two more pattern examples landed today
+
+Both shipped in pearl as commit =505e707= on 2026-05-28. They sharpen earlier catalog candidates rather than introducing a new direction.
+
+* Pattern 4: "The prompt label should match what the prompt does"
+
+** Before
+
+Pearl's filter-builder prompts and saved-query prompts both carried the same sentinel string at the top: =[ None. ]=. The label was uniform but the *behavior* was two different things:
+
+- For filter dimensions (team, state, project, labels, assignee), picking the sentinel meant "no constraint on this dimension." Every value matches. That's *any*, not *none*.
+- For the saved-query pick prompts (delete, run), picking the sentinel meant "don't act on anything." That's *cancel*, not *none* or *any*.
+
+Craig caught this on 2026-05-28 during verify: "when does the choice presented in completing read say 'none' when the choice actually means 'any'? Find all these instances and a way to correct them."
+
+** After
+
+Two distinct sentinel constants with labels that match their behavior:
+
+- =[ Any. ]= for filter dimensions
+- =[ Cancel. ]= for pick-an-existing-thing prompts
+
+A generic =pearl--with-sentinel SENTINEL CANDIDATES= helper lets each call site pick the label that fits. The predicate that recognizes opt-out (=pearl--filter-sentinel-value-p=) matches either sentinel or empty/nil so the downstream logic is uniform.
+
+** Why for the catalog
+
+This is the "no hidden affordances" pattern from the earlier note ([[file:2026-05-28-0003-from-pearl-rulesets-followup-no-empty-input.org]]) sharpened with a second rule: *if the affordance is visible, its label has to match what picking it does*. Visibility without accuracy is its own problem. A label that says "none" when the behavior is "any" is no better than an invisible empty-input idiom — both leave the user holding the wrong model.
+
+Catalog shape suggestion: this is the same principle as Pattern 3, in a follow-up form. Either a single entry that captures both halves (visible + accurate) or two cross-linked entries.
+
+* Pattern 5: "Default the most-common choice, not always 'yes'"
+
+** Refinement of an earlier idea
+
+In yesterday's discussion of yes/no prompts, the working principle was "default the choice to 'yes' so RET takes it." Craig pushed back today: "what I'm after is having the most common or preferred option be the one on top, not just 'yes' all the time."
+
+** What that looks like in code
+
+A new =pearl--read-yes-no PROMPT &optional DEFAULT= helper takes the default as an argument. The candidate list is ordered with the default first so the most-common choice is what the user sees at the top, the framework highlights it, and RET takes it without typing.
+
+For pearl's three non-destructive yes/no prompts (open-issues-only, save-filter-locally, save-N-fields-across-M-issues), the default happens to be "yes" in each case because each is a do-the-thing-the-user-asked confirmation. But the helper signature makes the *next* prompt where "no" is more common a one-arg change, not a special case.
+
+** Companion rule: friction proportional to consequence
+
+The destructive yes/no prompts (delete issue, delete saved query, delete comment) deliberately stay as =yes-or-no-p=. Typing "yes" is a safety feature there, not friction to remove. The catalog entry should name this companion rule explicitly so the principle doesn't read as "always default-yes."
+
+** Why for the catalog
+
+This is a refinement of Pattern 3 ("no empty input as meaningful") rather than a new pattern. The cleaner phrasing is something like *the prompt's default is the choice the user most often wants, and the level of friction is proportional to the cost of the choice*. Two halves, one principle.
+
+* Cumulative shape
+
+After today's work, the catalog has five candidate patterns from pearl, all converging on the same underlying principle:
+
+1. One-prompt picker with typed prefix (from 2026-05-27)
+2. Transient state-buttons (from 2026-05-27, Craig's external reference)
+3. No empty input as meaningful (from 2026-05-28, earlier today)
+4. The prompt label matches what the prompt does (today's first refinement)
+5. Default the most-common choice, with friction proportional to consequence (today's second refinement)
+
+Patterns 1, 3, 4, 5 are arguably one principle in four shapes: *the choices the user has should all be on-screen, accurately labeled, ordered by what they'll most often want, with friction sized to the cost of being wrong*. Worth thinking about whether the catalog wants one entry that captures all four with worked examples, or four separate entries that cross-link. The single-principle-multiple-shapes form may scan more cleanly once five-plus patterns have accumulated.
+
+* Standing by
+
+Same as the earlier notes: spec-reviews welcome when the rulesets discussion produces a concrete shape.
diff --git a/inbox/2026-05-28-0226-from-pearl-rulesets-spec-review-implementation.org b/inbox/2026-05-28-0226-from-pearl-rulesets-spec-review-implementation.org
new file mode 100644
index 0000000..5af3502
--- /dev/null
+++ b/inbox/2026-05-28-0226-from-pearl-rulesets-spec-review-implementation.org
@@ -0,0 +1,53 @@
+#+TITLE: spec-review.org should enumerate implementation tasks for todo.org
+#+DATE: [2026-05-28 Thu]
+#+SOURCE: pearl session 2026-05-28
+
+* The gap
+
+=workflows/spec-review.org= Phase 6 says "log deferred work to =todo.org=: v1 implementation = [#B] ... vNext/someday = [#D]." That covers *deferred* items (vNext) and a passing mention of v1 implementation, but it doesn't ask the workflow to enumerate, in the review output, the *concrete tasks* that fully implementing and testing the spec would require. The result: a spec gets marked =Ready=, the reviewer hands off, and the next session has to re-derive the task breakdown from the spec text rather than reading a ready-made list.
+
+For specs that decompose cleanly into commits (which is most of them now that the =Implementation phases= convention from =issue-sources-spec.org= has spread), the breakdown is *already in the spec*. The workflow just needs to lift it into the review output in a form that drops straight into =todo.org=.
+
+* Proposed addition to Phase 6
+
+After the existing "log deferred work to todo.org" sentence, add a structured step:
+
+#+begin_src org
+,*** Step: Enumerate the implementation tasks
+
+Read the spec's =Implementation phases= section (or equivalent commit/phase breakdown). For each phase, produce a =[#B] TODO= entry as it would appear in =todo.org=, including:
+
+- Subject line (descriptive topic, kebab-case slug, conventional-commit style).
+- Tags (=:feature:= / =:bug:= / =:refactor:= / =:test:= and any of =:quick:= / =:solo:= / =:discuss:= that apply).
+- One-line body: what lands in this phase.
+- Pointer back to the spec.
+
+Add a final =[#B] TODO= entry for the test surface that lands alongside the commits (unit tests, integration tests, manual-verify checklist). If the spec's =Acceptance criteria= section enumerates verifiable behaviors, mirror them as the manual-verify entries.
+
+Append the enumerated entries to the review file under a new heading:
+
+,* Implementation tasks (drop-in for todo.org)
+The full list of todo.org entries that fully implementing and testing this spec would require. Copy-paste into =todo.org='s =* $Project Open Work= header. Each entry is independently shippable per the spec's commit decomposition.
+
+If the spec doesn't have an =Implementation phases= section, this step is the prompt to ask the author to add one before assigning =Ready=. A spec without a phase breakdown is hard to plan against and harder to review the implementation of.
+#+end_src
+
+The step lives inside Phase 6 because it's part of "update tracking," but the output is sized to drop straight into =todo.org= — Craig (or the next agent) copy-pastes rather than re-deriving. The format mirrors =todo-format.md= (terse heading + body, tags on the heading line, no sentence-shaped headings).
+
+* Why this matters
+
+Three concrete wins:
+
+1. *Hand-off is one paste, not a re-read.* The reviewer already understands the spec well enough to assign a rubric. They're the right person to enumerate the work. Doing it in the review file means the spec-response author (or implementer) doesn't re-derive the breakdown from the spec narrative.
+
+2. *Forces a spec to be implementable in pieces.* If the reviewer can't write the implementation-tasks list, the spec doesn't have a clean phase decomposition. That's a spec-shape problem worth surfacing before =Ready=. The step is its own implementation-readiness check.
+
+3. *Closes the loop on =Acceptance criteria=.* Specs often have a numbered acceptance list and a separate commit decomposition. Mirroring the acceptance numbers as manual-verify task entries ensures every claim gets a check — the verify list isn't an afterthought.
+
+* Merge-with-pending note
+
+I noticed three uncommitted edits in =claude-templates/.ai/workflows/= (open-tasks, spec-response, spec-review) when I rsynced templates earlier today. If there's already a pending recommendation thread for =spec-review.org=, merge this addition with it rather than treating them as separate proposals. The change is additive (new step inside an existing phase, new review-file section), so it should compose with most other changes cleanly.
+
+* Triggered by
+
+2026-05-28 pearl session, while writing =docs/saved-query-sync-spec.org= and entering its sprint-review cycle. Craig: "update the spec review workflow such that it also lists all the actual tasks it would enter in todo.org to fully implement and test the functionality of the spec." Worked example landed at the bottom of =docs/saved-query-sync-spec.org= showing what the section looks like in practice.
diff --git a/inbox/2026-05-28-0303-from-pearl-rulesets-followup-collapse-prompts.org b/inbox/2026-05-28-0303-from-pearl-rulesets-followup-collapse-prompts.org
new file mode 100644
index 0000000..bef4516
--- /dev/null
+++ b/inbox/2026-05-28-0303-from-pearl-rulesets-followup-collapse-prompts.org
@@ -0,0 +1,88 @@
+#+TITLE: Pattern catalog — collapse N orthogonal prompts into one enriched prompt
+#+DATE: [2026-05-28 Thu]
+#+SOURCE: pearl session 2026-05-28, third follow-up to UI-patterns thread
+
+* Pattern 6 (or refinement of 4): "Collapse N orthogonal prompts into one enriched prompt where each candidate is a complete end-state"
+
+Shipped as a design decision in =docs/saved-query-sync-spec.org= on 2026-05-28 during sprint review. Sharpens earlier catalog candidates rather than introducing a new direction.
+
+** The trigger
+
+Craig, while reviewing the spec's sync-saved-query-to-linear command: "have we informed the user if this choice is consequential in any way? this almost feels as if we can collapse two levels together by adding more information to each individual choice."
+
+The spec originally proposed two sequential prompts:
+1. Team scope: =[ Personal. ]= / Engineering / Marketing / ...
+2. Shared visibility: personal / shared
+
+Four orthogonal combinations the user had to mentally assemble:
+- Personal scope + personal visibility = "just me, no team"
+- Personal scope + shared visibility = doesn't quite make sense (no team to share with)
+- Team scope + personal visibility = "team-scoped but only I see it"
+- Team scope + shared visibility = "team-scoped and team-visible" (the typical sync intent)
+
+** The collapse
+
+One prompt where each candidate spells out the complete end-state:
+
+#+begin_example
+Where does this view live?
+ [ Team: Engineering, visible to the team ] <- default when :team Engineering in filter
+ [ Personal, only I see it ]
+ [ Team: Engineering, only I see it ]
+ [ Team: Marketing, visible to the team ]
+ [ Team: Marketing, only I see it ]
+ ...
+ [ Cancel. ]
+#+end_example
+
+Same logical surface (N teams × 2 visibility + 1 personal). One fewer modal moment. Meaningless combination (personal + shared) absent from the list. Default at the top per the existing most-common-on-top pattern.
+
+** What changed by the collapse
+
+- Two prompts went to one. Smaller stack of decisions to track.
+- Each option is now self-explanatory. "Visible to the team" reads as the consequence, not the mechanism.
+- The default conveys *what will happen*, not just *which radio button is selected*.
+- The degenerate combination doesn't have to be defended against in code -- it's not in the candidate list.
+
+** Why for the catalog
+
+This is a third worked form of the principle that's emerging across the pearl catalog notes:
+
+#+begin_quote
+The choices the user has should all be on screen, accurately labeled, ordered by what they'll most often want, with friction sized to the cost of being wrong.
+#+end_quote
+
+Previous catalog candidates touch parts of it:
+- Pattern 3 (no empty input as meaningful): visible choices, no hidden idioms.
+- Pattern 4 (prompt label matches behavior): accurate labels.
+- Pattern 5 (default the most-common choice): right ordering, with safety-proportional friction.
+
+This pattern (collapse N orthogonal prompts into one enriched prompt) is the *cross-product* form. When two or more prompts compose, each combination IS its own meaningful choice, and the user thinks about end-states, not dimensions. So show the cross-product, label each row with its end-state, and let the user pick destination rather than coordinates.
+
+** Applicability gate
+
+The collapse only works when the cross-product is small enough to scan (5-20 rows comfortably). For N=2 dimensions × M values, that's 2M to N×M rows depending on whether all combinations are meaningful.
+
+It doesn't work when:
+- The cross-product is large (many teams, many statuses, many priorities -- the candidate list becomes a wall).
+- Dimensions are independently and frequently re-set (the user wants to change one without re-picking the rest).
+- One dimension is "free text" (not a small enumerable set).
+
+For those cases the sequential-prompts shape stays appropriate.
+
+** Cumulative shape after this entry
+
+The pearl catalog now has six worked candidates:
+
+1. One-prompt picker with typed prefix (2026-05-27)
+2. Transient state-buttons (Craig's external reference; magit-transient)
+3. No empty input as meaningful (2026-05-28)
+4. The prompt label matches what the prompt does (2026-05-28)
+5. Default the most-common choice; friction sized to consequence (2026-05-28)
+6. Collapse N orthogonal prompts into one enriched prompt (this note, 2026-05-28)
+
+Patterns 1, 3, 4, 5, 6 are arguably one principle in five shapes. The catalog might want a single root entry (the principle stated once) with five cross-linked worked examples; or six tightly-cross-linked separate entries. The single-principle-multiple-shapes form scans more cleanly as the count grows; six independent entries fragments the underlying idea.
+
+* Standing by
+
+Spec reviews welcome when the rulesets discussion produces a concrete shape. Pearl's docs/saved-query-sync-spec.org now sits at =Ready=; implementation can start whenever Craig says.
diff --git a/inbox/PROCESSED-2026-05-28-0117-from-.emacs.d-suggestion-open-tasks-hybrid-friction-cascade.org b/inbox/PROCESSED-2026-05-28-0117-from-.emacs.d-suggestion-open-tasks-hybrid-friction-cascade.org
new file mode 100644
index 0000000..43bb0ba
--- /dev/null
+++ b/inbox/PROCESSED-2026-05-28-0117-from-.emacs.d-suggestion-open-tasks-hybrid-friction-cascade.org
@@ -0,0 +1,80 @@
+#+TITLE: Suggestion — hybrid output shape for open-tasks.org Phase C Next Mode
+#+FROM: dotemacs (~/.emacs.d)
+#+DATE: 2026-05-28
+
+* Suggestion
+
+Update =claude-templates/.ai/workflows/open-tasks.org= Phase C → Next Mode to present two outputs together: the existing importance/urgency cascade recommendation up top, plus a 3-option friction filter underneath ranked by =:quick:solo:= > =:quick:= > =:solo:=. The user picks the row that matches their current state.
+
+The current cascade picks one task by importance/urgency (DOING > Active Reminders > Deadlines > priority order). That works when Craig is sharp and has time. It fails when the winner is a partially-blocked decision, hardware-dependent verify, or large refactor — the recommendation gets declined and the cascade falls through. The friction filter sidesteps that mismatch by surfacing tasks Craig can actually finish given a 20-minute window or a flagging-energy moment.
+
+Replacing the cascade entirely (which was the literal first proposal in the dotemacs session) drops the cascade's teeth on deadlines and priority — an =[#A]= deadline-tomorrow task that lacks =:quick:= or =:solo:= would go invisible. The hybrid preserves the cascade's importance/urgency forcing while adding the friction-based override path.
+
+* Why
+
+Two reinforcing effects, both surfaced in the dotemacs session 2026-05-28 (taskaudit + task-review):
+
+1. =:quick:= and =:solo:= tagging coverage is growing. The =task-review.org= workflow already assesses both tags on every review pass, so the friction filter degrades gracefully today (small set, growing over time) rather than catastrophically (empty list if no tags exist yet).
+
+2. The cascade and the friction filter answer different questions. Cascade = "what matters most?" Friction filter = "what shape of task can I actually finish right now?" The hybrid lets Craig pick the question to answer based on the state of his day.
+
+The proposed shape also pairs cleanly with the just-suggested "recommendation at item 1" convention (separate inbox drop, =2026-05-28-0014-from-.emacs.d-suggestion-numbered-options-recommendation-first.org=) — the friction block is exactly the kind of inline-numbered choice list that convention is meant for.
+
+* Proposed Phase C → Next Mode rewrite
+
+Replace the existing "Apply the prioritization cascade in order. Stop at the first matching step:" through the cascade's six steps with two sections:
+
+** Step 1 — Cascade recommendation (importance/urgency)
+
+Apply the prioritization cascade in order. Stop at the first matching step. This is the importance/urgency answer — what matters most right now.
+
+(Steps 1–6 unchanged from current workflow: DOING, Active Reminders, Deadline-driven, V2MOM, Simple priority, All done.)
+
+Present as a single task with the matched cascade step in the reason line.
+
+** Step 2 — Friction filter (effort + autonomy)
+
+Independently of the cascade, scan the open-task set for tasks tagged =:quick:= and =:solo:=. Build three ranked picks:
+
+- Quick + solo: the top task carrying both tags
+- Quick: the top task carrying =:quick:= only
+- Solo: the top task carrying =:solo:= only
+
+Within each row, pick the single task per the same-level tie-breakers already defined (blocks-other-work, recently-discussed, most-foundational). If a row has no tasks, omit it rather than padding.
+
+** Output shape
+
+#+begin_example
+Cascade recommendation (importance/urgency):
+- <task> — [#priority], <cascade-reason>
+
+If you want lower friction instead:
+1. Quick + solo: <task> — [#priority], ~<est>
+2. Quick: <task> — [#priority], ~<est>
+3. Solo: <task> — [#priority]
+#+end_example
+
+The cascade recommendation reads as the "answer" — what Craig probably wants if his day is going well. The friction block reads as the override — what he picks when the cascade winner isn't actionable in this moment. The 3 rows are numbered with item 1 (=:quick:solo:=) as the strongest friction pick, per the numbered-options-with-recommendation-first convention.
+
+* Edge cases
+
+- If the friction filter has zero rows (no =:quick:= or =:solo:= tasks in the open set), omit the friction block entirely and present only the cascade recommendation.
+- If the cascade recommendation and the =:quick:solo:= row are the same task, dedupe — show it once at the top with both labels.
+- If Craig declines the cascade recommendation, drop to the friction block as the natural next prompt (rather than continuing through the cascade) — the friction filter IS the override path.
+
+* Update to "Common Mistakes" section
+
+Add:
+
+- *Skipping the friction block when the cascade recommendation isn't actionable.* The friction block is the override path; don't fall through to lower-cascade-tier tasks if a =:quick:= or =:solo:= task is what's actually needed.
+- *Recommending more than one task in the friction block.* One task per row (quick+solo / quick / solo), not a per-row shortlist.
+
+The existing "Recommending more than one task in next mode" mistake should be tightened to mean the cascade recommendation only — the friction block is by design a 3-row choice.
+
+* Adoption shape
+
+Additive to the existing workflow — cascade logic survives unchanged in Step 1; the friction filter is a new Step 2 with bounded scope. Every project's existing =todo.org= continues to work; tag coverage grows naturally via =task-review.org=.
+
+* Source
+
+Drafted from the dotemacs session 2026-05-28. Adjudicated decision: hybrid (option 1) chosen over literal-replace (option 2) and separate-trigger (option 3). Discussion captured in the session log.