aboutsummaryrefslogtreecommitdiff
path: root/patterns/collapse-orthogonal-prompts.org
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-05 00:55:21 -0500
committerCraig Jennings <c@cjennings.net>2026-06-05 00:55:21 -0500
commit83bf3cb50c88f91730656a2242141567551063ac (patch)
tree069f0d9d52ac6ffe9c4a97a770be460b01e75cd5 /patterns/collapse-orthogonal-prompts.org
parent3eed2895b2d23d1d8e468aee6f3dfd8122012fe4 (diff)
downloadrulesets-83bf3cb50c88f91730656a2242141567551063ac.tar.gz
rulesets-83bf3cb50c88f91730656a2242141567551063ac.zip
feat(patterns): add cross-project pattern catalog (six seed patterns)
A good interaction-design pattern surfaces in one project, then gets lost, so the next project re-derives it. Pearl shipped six worked examples and the principle they share, but they sat as four raw notes in docs/design/ with nothing making them reusable. I added a patterns/ directory, one file per pattern, each with frontmatter (name, principle, problem, tags, source, examples) and a Problem / Do / Anti-pattern / Applicability / Related body. The six seeds: one-prompt-picker-typed-prefix, transient-state-buttons, no-empty-input-as-meaningful, label-matches-behavior, default-most-common-friction-proportional, collapse-orthogonal-prompts. Patterns 3-6 cross-link as facets of one root principle: 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. The catalog lives in rulesets because every project's agent already pulls from here. A thin claude-rules/patterns.md pointer tells the agent the catalog exists and when to consult it, so it reads one pattern on demand instead of carrying all of them. The pointer auto-installs via the Makefile RULES glob. README.org holds the root principle, the frontmatter contract, and the capture-on-landing/promote-on-review intake cadence. The patterns are .org files with #+KEYWORD frontmatter. The pointer stays .md because the rules layer and the Makefile glob require it. Seed patterns keep their concrete Elisp examples. Generalize on the second caller, not up front.
Diffstat (limited to 'patterns/collapse-orthogonal-prompts.org')
-rw-r--r--patterns/collapse-orthogonal-prompts.org47
1 files changed, 47 insertions, 0 deletions
diff --git a/patterns/collapse-orthogonal-prompts.org b/patterns/collapse-orthogonal-prompts.org
new file mode 100644
index 0000000..ab24a54
--- /dev/null
+++ b/patterns/collapse-orthogonal-prompts.org
@@ -0,0 +1,47 @@
+#+TITLE: Collapse N orthogonal prompts into one enriched prompt
+#+SLUG: collapse-orthogonal-prompts
+#+PRINCIPLE: When prompts compose, show the cross-product with each row labeled as a complete end-state, so the user picks the destination rather than the coordinates.
+#+PROBLEM: Two or more sequential prompts force the user to mentally assemble the combination and to defend against meaningless combinations in code.
+#+TAGS: completing-read prompts cross-product end-state
+#+SOURCE: pearl saved-query-sync-spec.org (sync command), handoff note 2026-05-28
+#+EXAMPLES: pearl saved-query sync, team scope x visibility collapsed to one prompt
+
+* Problem
+
+Two sequential prompts, team scope then shared/personal visibility, make the user assemble the combination in their head. Some combinations are meaningless (personal scope + shared visibility, since there's no team to share with) and have to be defended against in code. Each prompt conveys a coordinate, not the outcome.
+
+* Do
+
+Collapse to 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
+ [ Personal, only I see it ]
+ [ Team: Engineering, only I see it ]
+ [ Team: Marketing, visible to the team ]
+ ...
+ [ Cancel. ]
+#+end_example
+
+One fewer modal moment. Each row reads as its consequence ("visible to the team"), not its mechanism. The meaningless combination simply isn't in the list, so there's nothing to defend against. The default sits on top per [[file:default-most-common-friction-proportional.org][default-most-common-friction-proportional]].
+
+When dimensions compose, each combination is itself a meaningful choice, so show the cross-product and let the user pick the destination, not the coordinates.
+
+* Anti-pattern
+
+Sequential orthogonal prompts the user has to combine mentally, where degenerate combinations exist and must be coded around.
+
+* Applicability
+
+Only when the cross-product is small enough to scan (roughly 5-20 rows). It doesn't work when:
+
+- The cross-product is large (many teams x many statuses becomes a wall).
+- A dimension is re-set independently and often (the user wants to change one without re-picking the rest).
+- A dimension is free text rather than a small enumerable set.
+
+For those, sequential prompts stay right.
+
+* Related
+
+The cross-product form of the root principle. Builds on [[file:label-matches-behavior.org][label-matches-behavior]] (each row accurately labeled) and [[file:default-most-common-friction-proportional.org][default-most-common-friction-proportional]] (default on top).