@hobin/developer 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +61 -20
  2. package/SOURCES.md +104 -0
  3. package/extensions/developer.ts +202 -44
  4. package/extensions/references/behavior-preserving-structural-change.md +149 -0
  5. package/extensions/skills.ts +1 -16
  6. package/extensions/state.ts +96 -10
  7. package/extensions/tui.ts +140 -25
  8. package/package.json +11 -25
  9. package/skills/abstraction-review/references/field-card.md +7 -0
  10. package/skills/abstraction-review/references/recipe-cards.md +67 -0
  11. package/skills/abstraction-review/references/repair-table.md +5 -0
  12. package/skills/model/SKILL.md +6 -1
  13. package/skills/model/references/problem-modeling.md +294 -235
  14. package/skills/model/references/worked-models-and-specialized-techniques.md +218 -0
  15. package/skills/naming-judgment/SKILL.md +5 -3
  16. package/skills/naming-judgment/references/domain-naming.md +202 -0
  17. package/skills/schedule/SKILL.md +1 -1
  18. package/skills/schedule/references/structural-change-timing.md +80 -13
  19. package/skills/signal/SKILL.md +2 -2
  20. package/skills/signal/references/structural-movement.md +202 -0
  21. package/skills/sketch/SKILL.md +35 -8
  22. package/skills/sketch/references/abstraction-barriers-and-closure.md +160 -0
  23. package/skills/sketch/references/abstraction-composition-and-state.md +184 -0
  24. package/skills/sketch/references/composition-generative-recursion-and-accumulators.md +196 -0
  25. package/skills/sketch/references/data-driven-design.md +177 -0
  26. package/skills/sketch/references/data-shape-template-catalog.md +241 -0
  27. package/skills/sketch/references/generic-operations-and-languages.md +134 -0
  28. package/skills/sketch/references/processes-state-and-time.md +171 -0
  29. package/skills/sketch/references/responsibility-and-variation.md +245 -0
  30. package/skills/verify/references/verifier-selection-and-pass-but-wrong.md +61 -3
  31. package/skills/naming-judgment/references/elements-of-clojure-naming.md +0 -74
  32. package/skills/signal/references/flocking-and-structural-movement.md +0 -157
  33. package/skills/sketch/references/design-recipe-and-abstraction-barriers.md +0 -169
@@ -0,0 +1,196 @@
1
+ # Composition, Generative Recursion, And Accumulators
2
+
3
+ Use this reference after the base data recipe when structure alone does not
4
+ finish the design. It distinguishes four moves that are often blurred together:
5
+ designing an auxiliary, abstracting completed designs, generating new
6
+ subproblems, and remembering knowledge that traversal would otherwise lose.
7
+
8
+ ## Design By Composition
9
+
10
+ Write a wishful top level before helper bodies:
11
+
12
+ ```text
13
+ publishableTasks(tasks):
14
+ return sortByPriority(onlyReady(normalize(tasks)))
15
+ ```
16
+
17
+ For each wished operation, run the full small recipe:
18
+
19
+ ```text
20
+ purpose: what subproblem it solves
21
+ contract: input and output meanings
22
+ examples: representative success and boundary cases
23
+ template: derived from its data
24
+ reason: why it is a distinct subproblem
25
+ ```
26
+
27
+ An auxiliary is earned when it solves a separate domain subproblem, processes a
28
+ referenced data definition, or generalizes a problem that the direct design
29
+ exposes. “The original function is long” is not an independent purpose.
30
+
31
+ ## Abstraction From Completed Examples
32
+
33
+ Start with at least two correct concrete designs that share a template.
34
+
35
+ ```text
36
+ sum(numbers):
37
+ Empty -> 0
38
+ Node(first, rest) -> first + sum(rest)
39
+
40
+ allReady(tasks):
41
+ Empty -> true
42
+ Node(first, rest) -> first.ready && allReady(rest)
43
+ ```
44
+
45
+ Align corresponding positions:
46
+
47
+ | Role | `sum` | `allReady` |
48
+ | --- | --- | --- |
49
+ | base | `0` | `true` |
50
+ | item projection | identity | `task.ready` |
51
+ | combine | `+` | `&&` |
52
+
53
+ Only now is a fold-shaped candidate visible:
54
+
55
+ ```text
56
+ fold(sequence, base, project, combine)
57
+ ```
58
+
59
+ The shared template is evidence, not approval. Check that the roles have stable
60
+ meaning, old functions become simple calls, process/cost does not accidentally
61
+ change, and one realistic new case fits without adding flags. `abstraction-review`
62
+ owns the promotion decision.
63
+
64
+ ## Structural Versus Generative Recursion
65
+
66
+ Structural recursion consumes pieces selected directly from the input data
67
+ definition. Generative recursion creates a new problem by domain knowledge.
68
+
69
+ ```text
70
+ structural: totalEstimate(rest)
71
+ // rest is a field in Node(Task, Tasks)
72
+
73
+ generative: binarySearch(sorted, lower, midpoint - 1)
74
+ // the next interval is calculated, not selected from a data field
75
+ ```
76
+
77
+ Misclassifying the second as structural hides the algorithm idea and its
78
+ termination obligation.
79
+
80
+ ## Generative Recursion Recipe
81
+
82
+ Answer four questions before the body:
83
+
84
+ ```text
85
+ trivial: which problems have a direct answer?
86
+ generate: how are new subproblems produced?
87
+ solve/combine: how do recursive answers form this answer?
88
+ terminate: why do generated problems approach a trivial case?
89
+ ```
90
+
91
+ Worked binary-search sketch:
92
+
93
+ ```text
94
+ search(sorted, target, low, high):
95
+ if low > high:
96
+ return NotFound // trivial
97
+
98
+ mid = floor((low + high) / 2) // generation knowledge
99
+ if sorted[mid] == target:
100
+ return Found(mid) // trivial
101
+ if target < sorted[mid]:
102
+ return search(sorted, target, low, mid - 1)
103
+ return search(sorted, target, mid + 1, high)
104
+ ```
105
+
106
+ Process examples must show generated intervals:
107
+
108
+ ```text
109
+ [0, 6] -> [4, 6] -> [4, 4] -> Found(4)
110
+ [0, 0] -> [1, 0] -> NotFound
111
+ ```
112
+
113
+ Termination measure: `high - low + 1` is a natural number for non-trivial
114
+ calls, and each recursive call strictly decreases it. If no decreasing measure
115
+ is known, state the possible non-termination boundary rather than asserting
116
+ that the input “gets smaller.”
117
+
118
+ ## Accumulator Recipe
119
+
120
+ Do not begin by adding an extra parameter. First identify the lost knowledge or
121
+ repeated work in a conventional design.
122
+
123
+ Example pressure: repeatedly appending to the end while reversing a sequence
124
+ reprocesses prior results. Introduce `seenReversed` with an invariant:
125
+
126
+ ```text
127
+ original == reverse(seenReversed) ++ remaining
128
+ ```
129
+
130
+ Trace the relation:
131
+
132
+ ```text
133
+ original [a,b,c], remaining [a,b,c], seenReversed []
134
+ original [a,b,c], remaining [b,c], seenReversed [a]
135
+ original [a,b,c], remaining [c], seenReversed [b,a]
136
+ original [a,b,c], remaining [], seenReversed [c,b,a]
137
+ ```
138
+
139
+ The invariant determines initialization, update, and result:
140
+
141
+ ```text
142
+ reverse(items):
143
+ loop(remaining, seenReversed):
144
+ Empty -> seenReversed
145
+ Node(first, rest) -> loop(rest, prepend(first, seenReversed))
146
+ return loop(items, Empty)
147
+ ```
148
+
149
+ Check the invariant at three points:
150
+
151
+ 1. initialization relates the original input to the initial accumulator;
152
+ 2. one transition preserves the relationship;
153
+ 3. the base case plus the invariant implies the promised result.
154
+
155
+ Different invariants create different algorithms. Choose the simplest invariant
156
+ that solves observed pressure; an accumulator with no stated meaning is hidden
157
+ state.
158
+
159
+ ## Iterative Refinement
160
+
161
+ When a required case cannot be expressed or a forbidden case remains possible,
162
+ change the data definition and propagate the change through:
163
+
164
+ ```text
165
+ data examples
166
+ -> behavior examples
167
+ -> templates
168
+ -> implementations
169
+ -> tests
170
+ -> serialized/public compatibility surfaces
171
+ ```
172
+
173
+ A local type edit is incomplete when old persisted forms or callers remain in
174
+ circulation.
175
+
176
+ ## Failure Diagnosis
177
+
178
+ | Symptom | Repair |
179
+ | --- | --- |
180
+ | wished helper has no examples or independent purpose | inline it or run its own recipe |
181
+ | abstraction is derived from one function | complete another concrete design first |
182
+ | abstract parameters are implementation fragments | restate stable variation roles |
183
+ | generated recursive call lacks an algorithm idea | return to structural template or state generation rule |
184
+ | termination says only “smaller” | provide a well-founded measure or explicit divergence boundary |
185
+ | accumulator is added for style | show lost knowledge, repeated work, or process pressure |
186
+ | accumulator update is guessed | derive it from the invariant |
187
+
188
+ ## Source Trace
189
+
190
+ - [*How to Design Programs*, official living edition](https://htdp.org/2026-5-28/Book/index.html):
191
+ design by composition, abstraction from concrete functions, generative
192
+ recursion and termination, accumulators and invariants, and iterative
193
+ refinement.
194
+ - Harold Abelson and Gerald Jay Sussman with Julie Sussman, *Structure and
195
+ Interpretation of Computer Programs*, Second Edition, MIT Press, 1996:
196
+ wishful procedure decomposition, higher-order abstraction, and process shape.
@@ -0,0 +1,177 @@
1
+ # Data-Driven Design
2
+
3
+ Use this reference when product information should determine the program shape.
4
+ The central insight is concrete: **a data definition is a construction rule for
5
+ valid values, and that same rule determines the first honest function
6
+ template**. Code shape should not be guessed from framework files or a favorite
7
+ pattern when the cases are already present in the data.
8
+
9
+ ## The Six-Artifact Recipe
10
+
11
+ Produce these artifacts in order. Each one catches a different error.
12
+
13
+ ```text
14
+ 1. data definition + interpretation
15
+ 2. representative data examples
16
+ 3. signature + purpose + executable stub
17
+ 4. behavior examples
18
+ 5. template derived only from the data definition
19
+ 6. completed function + checks
20
+ ```
21
+
22
+ The order is diagnostic, not ceremonial. If the template has no branch for a
23
+ required case, repair the data definition. If the template exposes all required
24
+ ingredients but the result is wrong, repair the completed body. If no template
25
+ ingredient can express the purpose, design an auxiliary with its own recipe.
26
+
27
+ In an existing repository, recover the same artifacts from schemas, types,
28
+ fixtures, callers, UI states, persistence, and tests. Do not copy pedagogical
29
+ comments into production merely to imitate the recipe.
30
+
31
+ ## Complete Example: Let The Variants Write The Skeleton
32
+
33
+ Requirement: show the customer-facing instruction for a fulfillment method.
34
+
35
+ ### 1. Define and interpret the data
36
+
37
+ ```text
38
+ Fulfillment =
39
+ Pickup(storeId) // collect from this store
40
+ | Delivery(address) // send to this address
41
+ | Locker(lockerId) // collect from this locker
42
+
43
+ Excluded: a fulfillment value with none or several of these variants.
44
+ ```
45
+
46
+ This is not merely a union type. Its interpretation says the three variants are
47
+ different product meanings, so silently merging branches would lose policy.
48
+
49
+ ### 2. Construct one value from every clause
50
+
51
+ ```text
52
+ Pickup("gangnam")
53
+ Delivery("12 Teheran-ro")
54
+ Locker("L-17")
55
+ ```
56
+
57
+ If a valid example cannot be constructed, the definition is unusable. Add
58
+ boundary examples when fields have their own restrictions.
59
+
60
+ ### 3. State what the function computes
61
+
62
+ ```text
63
+ instruction : Fulfillment -> Text
64
+ purpose: produce the instruction a customer should follow
65
+ stub: instruction(method) = ""
66
+ ```
67
+
68
+ The purpose says *what*, not “inspect the tag and branch.”
69
+
70
+ ### 4. Work behavior examples before implementation
71
+
72
+ ```text
73
+ instruction(Pickup("gangnam"))
74
+ == "Pick up at gangnam"
75
+ instruction(Delivery("12 Teheran-ro"))
76
+ == "Deliver to 12 Teheran-ro"
77
+ instruction(Locker("L-17"))
78
+ == "Collect from locker L-17"
79
+ ```
80
+
81
+ ### 5. Derive, do not invent, the template
82
+
83
+ One data clause becomes one branch. Fields in that clause become available
84
+ ingredients.
85
+
86
+ ```text
87
+ instruction(method):
88
+ match method:
89
+ Pickup(storeId) -> ... storeId ...
90
+ Delivery(address) -> ... address ...
91
+ Locker(lockerId) -> ... lockerId ...
92
+ ```
93
+
94
+ The strings and formatting policy do not come from the data shape; the purpose
95
+ and examples supply them. The branch structure and accessible fields do.
96
+
97
+ ### 6. Complete and check
98
+
99
+ ```text
100
+ instruction(method):
101
+ match method:
102
+ Pickup(storeId) -> "Pick up at " + storeId
103
+ Delivery(address) -> "Deliver to " + address
104
+ Locker(lockerId) -> "Collect from locker " + lockerId
105
+ ```
106
+
107
+ Run all three examples. Then try a fake fourth variant. A compiler failure or
108
+ explicit missing branch reveals the exact extension point; a catch-all returning
109
+ an empty string would hide it.
110
+
111
+ ## Select The Specific Recipe
112
+
113
+ Read only the detail that matches the unresolved design question:
114
+
115
+ | Evidence | Read | Expected artifact |
116
+ | --- | --- | --- |
117
+ | atomic values, intervals, itemizations, records, recursive or mutually recursive data, multiple complex inputs, complex outputs, or event loops | [Data-Shape Template Catalog](data-shape-template-catalog.md) | a template whose branches, selectors, recursive positions, and delegations correspond to the data definition |
118
+ | wished helpers, several completed concrete functions, generated subproblems, termination uncertainty, repeated work, or lost traversal knowledge | [Composition, Generative Recursion, And Accumulators](composition-generative-recursion-and-accumulators.md) | separately designed auxiliaries, a justified abstraction, a generation template plus termination argument, or an accumulator invariant |
119
+
120
+ These documents extend this recipe; they do not replace the six artifacts.
121
+
122
+ ## Existing-Code Recovery
123
+
124
+ Use this recovery table rather than assuming the declared type is complete.
125
+
126
+ | Artifact | Repository evidence | Typical contradiction |
127
+ | --- | --- | --- |
128
+ | data definition | schema, type, constructors, persisted samples | runtime contains a legacy or impossible-looking shape |
129
+ | interpretation | product copy, callers, docs, analytics meaning | two same-shaped values mean different things |
130
+ | data examples | fixtures, factories, production samples | only the happy variant has an example |
131
+ | behavior examples | tests, screenshots, API examples | expected output encodes an undocumented default |
132
+ | template | branches, selectors, traversal, delegation | catch-all hides a meaningful clause |
133
+ | completed body | implementation | code needs information absent from the data model |
134
+
135
+ When evidence conflicts, keep the contradiction visible. `model` owns disputed
136
+ validity or policy; this reference shapes the implementable surface once the
137
+ meaning is accepted.
138
+
139
+ ## Sketch Output
140
+
141
+ ```text
142
+ Purpose: result in product language
143
+ Data: valid clauses, interpretation, excluded values
144
+ Data examples: at least one per clause and meaningful boundary
145
+ Behavior examples: input -> expected result with rationale
146
+ Template: branches, selectors, recursive calls, and delegations derived from data
147
+ Wish list: separately designed subproblems
148
+ Checks: examples, properties, boundaries, and compatibility evidence
149
+ First item: smallest executable step implied by the template
150
+ Deferred: abstractions or policies not yet earned
151
+ ```
152
+
153
+ ## Failure Diagnosis
154
+
155
+ | Symptom | Return to |
156
+ | --- | --- |
157
+ | valid product case has no representation | data definition and interpretation |
158
+ | data clause has no example | data examples |
159
+ | tests describe traversal rather than result | purpose and behavior examples |
160
+ | branch has no corresponding data clause | template derivation |
161
+ | recursive call is on an arbitrary “smaller” value | structural versus generative recursion recipe |
162
+ | helper has a body but no independent purpose | wish-list design |
163
+ | abstraction precedes comparable completed designs | abstraction-from-examples recipe |
164
+ | changed type ignores stored/public older forms | existing-code recovery and compatibility model |
165
+
166
+ ## Source Trace
167
+
168
+ - Matthias Felleisen, Robert Bruce Findler, Matthew Flatt, and Shriram
169
+ Krishnamurthi, *How to Design Programs, Second Edition*, MIT Press, 2018,
170
+ and the [official living edition](https://htdp.org/2026-5-28/Book/index.html):
171
+ information analysis, data definitions and interpretations, examples,
172
+ signatures and purpose statements, templates, implementations, tests, and
173
+ iterative refinement.
174
+ - Harold Abelson and Gerald Jay Sussman with Julie Sussman, *Structure and
175
+ Interpretation of Computer Programs*, Second Edition, MIT Press, 1996:
176
+ wishful decomposition and the distinction between procedure text and the
177
+ process it generates.
@@ -0,0 +1,241 @@
1
+ # Data-Shape Template Catalog
2
+
3
+ Use this catalog after the six-artifact recipe in
4
+ [Data-Driven Design](data-driven-design.md). Its core rule is:
5
+
6
+ ```text
7
+ data clause -> function branch
8
+ compound field -> selector or destructured value
9
+ self-reference -> natural recursive call at that exact position
10
+ reference to B -> delegation to B's template at that exact position
11
+ ```
12
+
13
+ The template inventories available ingredients. The purpose and examples decide
14
+ how to combine them.
15
+
16
+ ## Atomic And Fixed-Size Data
17
+
18
+ For an atomic value, the template contains the parameter and relevant domain
19
+ constants. There is no structural decomposition to invent.
20
+
21
+ ```text
22
+ Celsius = Number interpreted as a measured temperature
23
+
24
+ alertLevel : Celsius -> Level
25
+ alertLevel(celsius) = ... celsius ... FREEZE_POINT ... HEAT_LIMIT ...
26
+ ```
27
+
28
+ Intervals add meaningful partitions only when behavior changes at their
29
+ boundaries:
30
+
31
+ ```text
32
+ alertLevel(celsius):
33
+ if celsius < 0 -> ...
34
+ else if celsius < 35 -> ...
35
+ else -> ...
36
+ ```
37
+
38
+ Do not branch on arbitrary numeric ranges merely because a conditional is
39
+ possible. Each range needs a product interpretation and boundary examples.
40
+
41
+ ## Itemizations And Enumerations
42
+
43
+ For a finite set of alternatives, create one branch and one behavior example per
44
+ meaningful clause. The complete fulfillment example in the parent reference is
45
+ the canonical shape.
46
+
47
+ Template:
48
+
49
+ ```text
50
+ Result = Success(value) | Rejected(reason) | Retryable(delay)
51
+
52
+ render(result):
53
+ match result:
54
+ Success(value) -> ... value ...
55
+ Rejected(reason) -> ... reason ...
56
+ Retryable(delay) -> ... delay ...
57
+ ```
58
+
59
+ Merge two clauses only when their product meaning, not merely their current body,
60
+ is the same. A catch-all branch is suspicious when adding a variant should force
61
+ a new decision.
62
+
63
+ ## Structures And Records
64
+
65
+ A record groups a fixed natural whole. List only fields relevant to the purpose;
66
+ the template is not permission to expose every stored field.
67
+
68
+ ```text
69
+ Schedule = Schedule(start, end, timezone)
70
+
71
+ duration(schedule):
72
+ ... schedule.start ... schedule.end ...
73
+ ```
74
+
75
+ `timezone` remains absent because elapsed duration does not need it. If the
76
+ function unexpectedly needs recurrence policy, either the purpose is broader
77
+ than stated or the data definition lacks information.
78
+
79
+ ## Self-Referential Data
80
+
81
+ A valid self-referential definition has at least one non-recursive clause from
82
+ which values can be constructed and at least one recursive clause that creates
83
+ larger values.
84
+
85
+ ```text
86
+ Tasks = Empty | Node(Task, Tasks)
87
+ interpretation: a finite ordered task sequence
88
+ ```
89
+
90
+ Construct examples from the base outward:
91
+
92
+ ```text
93
+ Empty
94
+ Node(Task("review", 20), Empty)
95
+ Node(Task("write", 40), Node(Task("review", 20), Empty))
96
+ ```
97
+
98
+ For `totalEstimate`, derive the template mechanically:
99
+
100
+ ```text
101
+ totalEstimate(tasks):
102
+ match tasks:
103
+ Empty -> ...
104
+ Node(first, rest) ->
105
+ ... first ... totalEstimate(rest) ...
106
+ ```
107
+
108
+ Why that recursive call? The `Node` clause contains one `Tasks` field named
109
+ `rest`; the template therefore contains one natural recursive call on `rest`.
110
+ The completed function follows from examples:
111
+
112
+ ```text
113
+ totalEstimate(tasks):
114
+ match tasks:
115
+ Empty -> 0
116
+ Node(first, rest) -> first.minutes + totalEstimate(rest)
117
+ ```
118
+
119
+ Test at least two recursive layers. Recursing on `dropEveryOther(rest)` or a
120
+ newly partitioned list is not structurally derived; use the generative-recursion
121
+ recipe instead.
122
+
123
+ ## Mutually Referential Data
124
+
125
+ When definitions refer to each other, derive a family of templates with a
126
+ delegation wherever the reference occurs.
127
+
128
+ ```text
129
+ Document = Document(List<Section>)
130
+ Section = Section(title, List<Block>, List<Section>)
131
+ Block = Paragraph(text) | Image(src)
132
+ ```
133
+
134
+ For a word-count sketch:
135
+
136
+ ```text
137
+ countDocument(document):
138
+ combine map(countSection, document.sections)
139
+
140
+ countSection(section):
141
+ combine map(countBlock, section.blocks)
142
+ map(countSection, section.children)
143
+
144
+ countBlock(block):
145
+ match block:
146
+ Paragraph(text) -> words(text)
147
+ Image(src) -> 0
148
+ ```
149
+
150
+ The reference graph, not convenience, determines the delegations. An oversized
151
+ function with nested tags usually means the template family was collapsed.
152
+
153
+ ## Two Complex Inputs
154
+
155
+ Do not automatically multiply every clause. Decide how the two values move.
156
+
157
+ ### One input controls
158
+
159
+ `applyDiscounts(cart, rules)` traverses the cart while `rules` is constant or
160
+ queried. Derive the traversal from `Cart`; treat `Rules` as domain knowledge.
161
+
162
+ ### Inputs move in lockstep
163
+
164
+ `sameShape(leftTree, rightTree)` compares corresponding nodes. State the shape
165
+ relation and branch on paired cases:
166
+
167
+ ```text
168
+ (Leaf, Leaf)
169
+ (Node, Node) -> recurse on corresponding children
170
+ (Leaf, Node) or (Node, Leaf) -> false
171
+ ```
172
+
173
+ ### Inputs vary independently
174
+
175
+ Collision policy between `UserRole` and `ResourceState` may need the meaningful
176
+ cross-product or a decision table. Write all relevant combinations explicitly;
177
+ do not hide them in nested defaults.
178
+
179
+ The smell is not “two loops.” It is an unstated relationship between the input
180
+ shapes.
181
+
182
+ ## Functions That Produce Complex Data
183
+
184
+ The output definition constrains constructors just as the input definition
185
+ constrains selectors.
186
+
187
+ ```text
188
+ Notice = Info(text) | Warning(text) | Blocked(reason)
189
+
190
+ classify(order):
191
+ ... -> Info(...)
192
+ ... -> Warning(...)
193
+ ... -> Blocked(...)
194
+ ```
195
+
196
+ Work expected output values before choosing constructors. If several output
197
+ variants are valid, the unresolved choice is policy, not implementation freedom.
198
+
199
+ ## Interactive Programs
200
+
201
+ Define the world state before handlers:
202
+
203
+ ```text
204
+ World = Editing(draft) | Saving(draft, requestId) | Failed(draft, reason)
205
+
206
+ onEvent : World x Event -> World
207
+ view : World -> UI
208
+ stop : World -> Boolean
209
+ ```
210
+
211
+ Then write event traces, not only snapshots:
212
+
213
+ ```text
214
+ Editing("a") --Save--> Saving("a", 7)
215
+ Saving("a", 7) --Saved(7)--> Editing("a")
216
+ Saving("a", 7) --Saved(6)--> Saving("a", 7) // stale response ignored
217
+ ```
218
+
219
+ The handlers derive branches from both the world and event definitions. If
220
+ correctness depends on history beyond `World`, refine the state or hand the
221
+ temporal rule to `model`.
222
+
223
+ ## Diagnosis
224
+
225
+ | Symptom | Likely repair |
226
+ | --- | --- |
227
+ | branch does not correspond to a data clause | remove it or repair the data definition |
228
+ | selector is used outside its clause | restore the clause guard or use a better representation |
229
+ | recursive call has no self-reference | classify as generative recursion or remove it |
230
+ | self-reference has no recursive call | explain why that portion is intentionally ignored |
231
+ | mutually referential logic is one giant conditional | derive one template per definition |
232
+ | two complex inputs create accidental nested loops | state controlling, lockstep, or independent relation |
233
+ | event handler cannot distinguish stale events | add identity/history to the world model |
234
+
235
+ ## Source Trace
236
+
237
+ - [*How to Design Programs*, official living edition](https://htdp.org/2026-5-28/Book/index.html):
238
+ the recipes for atomic data, intervals, itemizations, structures,
239
+ self-referential and intertwined definitions, multiple complex inputs,
240
+ complex outputs, and world programs. The examples here are adapted to ordinary
241
+ product code and are not copied from the book.