aboutsummaryrefslogtreecommitdiff
path: root/inbox
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 /inbox
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.
Diffstat (limited to 'inbox')
-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
6 files changed, 405 insertions, 0 deletions
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.