@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,134 @@
1
+ # Generic Operations And Languages
2
+
3
+ Use this reference when several representations must coexist additively, or
4
+ when ordinary data and functions are becoming a small language with its own
5
+ evaluation semantics.
6
+
7
+ ## Two Axes Of Generic Operations
8
+
9
+ Write the matrix before choosing classes, visitors, multimethods, or a registry:
10
+
11
+ | Representation | `charge` | `refund` | `describe` |
12
+ | --- | --- | --- | --- |
13
+ | Card | method | method | method |
14
+ | Bank transfer | method | unsupported | method |
15
+ | Store credit | method | method | method |
16
+
17
+ There are two independent pressures:
18
+
19
+ - horizontal: higher-level operations should not know representation fields;
20
+ - vertical: adding a representation should not require editing every old
21
+ representation package.
22
+
23
+ One possible data-directed surface is:
24
+
25
+ ```text
26
+ register(kind, operation, method)
27
+ applyGeneric(operation, taggedValue, ...args)
28
+ ```
29
+
30
+ Specify duplicate registration, missing method, load order, type transitions,
31
+ and error visibility. Then add a fake representation. Existing callers and old
32
+ representation modules should remain unchanged. If only two stable variants
33
+ exist, a local conditional may be cheaper and clearer.
34
+
35
+ ## Coercion And Meaning Preservation
36
+
37
+ For mixed representations, draw paths:
38
+
39
+ ```text
40
+ Integer -> Rational -> Decimal
41
+ Money(USD) -X-> Money(EUR) without an exchange-rate context
42
+ ```
43
+
44
+ For each edge state preserved meaning and lost ability: precision, identity,
45
+ order, metadata, or capability. Choose direct operation, coercion, canonical
46
+ representation, or explicit rejection. A convenient path that silently loses
47
+ meaning is not genericity.
48
+
49
+ ## Symbolic Data Boundary
50
+
51
+ When code inspects formulas, queries, or rules, represent notation as data:
52
+
53
+ ```text
54
+ Expr = Number(value) | Variable(name) | Sum(left, right) | Product(left, right)
55
+ ```
56
+
57
+ Algorithms use predicates/selectors/constructors or pattern matching on this
58
+ semantic definition, not string indexes. Constructors may own simplification:
59
+
60
+ ```text
61
+ makeSum(0, x) -> x
62
+ makeSum(x, 0) -> x
63
+ makeSum(x, y) -> Sum(x, y)
64
+ ```
65
+
66
+ That policy must be explicit because it changes the representation while
67
+ preserving intended expression meaning.
68
+
69
+ ## When Data Becomes A Language
70
+
71
+ A rule table, query builder, workflow schema, or configuration is a language
72
+ only when it has:
73
+
74
+ ```text
75
+ primitives: smallest valid expressions
76
+ combination: how expressions form larger expressions
77
+ abstraction: how recurring expressions receive reusable names
78
+ validation: well-formed versus invalid programs
79
+ evaluation: what an expression means in an environment
80
+ errors: parse, validation, runtime, and unsupported behavior
81
+ evolution: versioning, migrations, and compatibility
82
+ ```
83
+
84
+ Worked policy DSL sketch:
85
+
86
+ ```text
87
+ Policy = Allow(Role) | HasTag(Tag) | All(List<Policy>) | Any(List<Policy>)
88
+
89
+ evaluate(Allow("admin"), env) = env.user.role == "admin"
90
+ evaluate(All([]), env) = true
91
+ evaluate(All([p, ...rest]), env) = evaluate(p, env) && evaluate(All(rest), env)
92
+ ```
93
+
94
+ Define invalid states, such as an unknown role or empty `Any`, rather than
95
+ letting a host-language exception become language semantics.
96
+
97
+ ## Evaluator Boundary
98
+
99
+ Keep the evaluator contract distinct from syntax:
100
+
101
+ ```text
102
+ evaluate : Program x Environment -> Result | LanguageError
103
+ ```
104
+
105
+ State evaluation order, scope, effects, termination limits, and resource
106
+ budgets. A mathematically equivalent rewrite may not preserve host-language
107
+ short-circuiting, effects, or exceptions.
108
+
109
+ Do not build a DSL when ordinary typed data plus functions keep policy more
110
+ visible. The evaluator, migrations, debugging tools, and error messages are
111
+ product code, not free infrastructure.
112
+
113
+ ## Artifact
114
+
115
+ ```text
116
+ Variant-operation matrix:
117
+ Representation barrier:
118
+ Registration/dispatch and unsupported policy:
119
+ Conversion graph and preserved meaning:
120
+ Language primitives/combinations/abstractions:
121
+ Validation and evaluator contract:
122
+ Errors, effects, versioning, and limits:
123
+ Fake variant or example program check:
124
+ Simpler ordinary-data alternative:
125
+ ```
126
+
127
+ ## Source Trace
128
+
129
+ - *Structure and Interpretation of Computer Programs*, Second Edition,
130
+ sections 2.4-2.5 and chapters 4-5: multiple representations, generic
131
+ operations, data-directed programming, symbolic data, metalinguistic
132
+ abstraction, evaluators, and explicit machines.
133
+ - Hillel Wayne, *Logic for Programmers*, version 0.14.0, May 4, 2026:
134
+ model/runtime distinctions and ability-guarantee tradeoffs.
@@ -0,0 +1,171 @@
1
+ # Processes, State, And Time
2
+
3
+ Use this reference when returned values alone do not describe correctness. The
4
+ same procedure text can generate recursive, iterative, tree-shaped, delayed, or
5
+ stateful processes with different time, space, order, and failure behavior.
6
+
7
+ ## Procedure Versus Process
8
+
9
+ Trace a representative execution:
10
+
11
+ ```text
12
+ procedure: retry(operation, 3)
13
+ process:
14
+ attempt 1 -> retryable failure -> wait 100 ms
15
+ attempt 2 -> retryable failure -> wait 200 ms
16
+ attempt 3 -> success
17
+ ```
18
+
19
+ Record:
20
+
21
+ ```text
22
+ result
23
+ work generated at each step
24
+ deferred work or stack growth
25
+ state retained or duplicated
26
+ time/space scale
27
+ ordering and failure surface
28
+ ```
29
+
30
+ A recursive tree walk and an iterative queue walk may return the same nodes but
31
+ have different stack, ordering, and memory contracts. A fluent one-line pipeline
32
+ may materialize three full collections. Short procedure text is not evidence of
33
+ a cheap or simple process.
34
+
35
+ ## State Means History Matters
36
+
37
+ Compare two calls with identical explicit input:
38
+
39
+ ```text
40
+ account.withdraw(40) -> Accepted
41
+ account.withdraw(40) -> Rejected
42
+ ```
43
+
44
+ If prior interactions explain the difference, state is part of the contract.
45
+ Fill:
46
+
47
+ ```text
48
+ required history: accepted deposits and withdrawals
49
+ sufficient summary: current balance
50
+ owner: account instance
51
+ writers: deposit and withdraw
52
+ identity: two equal balances may be different accounts
53
+ aliases: references that observe the same mutation
54
+ order law: sufficient-funds check and balance update are one transition
55
+ ```
56
+
57
+ Local state is modular when it hides a coherent history behind a small
58
+ interface. It is hazardous when aliases, retries, concurrency, or persistence
59
+ make the history owner unclear.
60
+
61
+ ## Explicit State Machine Alternative
62
+
63
+ Represent time as data when transitions need review, replay, or distribution:
64
+
65
+ ```text
66
+ Payment = Created | Authorizing(attempt) | Authorized(id) | Failed(reason)
67
+
68
+ transition(Created, Authorize) -> Authorizing(1)
69
+ transition(Authorizing(n), Retryable) -> Authorizing(n + 1)
70
+ transition(Authorizing(_), Approved(id)) -> Authorized(id)
71
+ transition(Authorized(_), Approved(_)) -> invalid or idempotent policy
72
+ ```
73
+
74
+ State the unchanged part of each transition and cover stale, duplicate,
75
+ reordered, retried, and concurrent events. A correct enum is not a correct
76
+ history model.
77
+
78
+ ## Event Order And Atomicity
79
+
80
+ For concurrent withdrawal, the forbidden interleaving is:
81
+
82
+ ```text
83
+ A reads 100
84
+ B reads 100
85
+ A writes 20 after withdrawing 80
86
+ B writes 20 after withdrawing 80
87
+ ```
88
+
89
+ Both calls appear accepted although 160 was withdrawn. The order law is not
90
+ “serialize everything”; it is:
91
+
92
+ ```text
93
+ read balance -> check funds -> write next balance
94
+ ```
95
+
96
+ must behave as one protected transition for a given account. Choose a lock,
97
+ transaction, queue, compare-and-swap loop, or merge policy only after stating
98
+ that law and its waiting/fairness cost.
99
+
100
+ ## Streams And Logs
101
+
102
+ An explicit stream/log represents successive states or events:
103
+
104
+ ```text
105
+ events -> fold(transition, initialState) -> currentState
106
+ ```
107
+
108
+ It improves replay, audit, time travel, merge reasoning, and functional
109
+ composition. It also creates retention, ordering, identity, versioning, and
110
+ reconstruction-cost obligations. Choose it when history is product evidence,
111
+ not merely because mutation is unfashionable.
112
+
113
+ For delayed streams also record demand:
114
+
115
+ ```text
116
+ producer pace
117
+ consumer pace
118
+ buffer/backpressure
119
+ single-use versus replayable
120
+ failure and cancellation
121
+ ```
122
+
123
+ ## Pull, Transform, Push Process Check
124
+
125
+ ```text
126
+ pull: where external time and failure enter
127
+ transform: domain computation and its data contract
128
+ push: effect interpretation, idempotency, and partial failure
129
+ apex: coordinator that owns the whole process outcome
130
+ ```
131
+
132
+ The separation is false when pull retries silently alter transform semantics or
133
+ push performs an unreported partial success. Conversely, splitting one atomic
134
+ transaction into these phases may violate the actual invariant.
135
+
136
+ ## Process/State Artifact
137
+
138
+ ```text
139
+ Procedure promise:
140
+ Representative process trace:
141
+ Shape and time/space cost:
142
+ Required history and sufficient summary:
143
+ State or log owner and writers:
144
+ Identity and alias behavior:
145
+ Order/atomicity law:
146
+ Retry, stale, duplicate, and concurrency policy:
147
+ Alternative representation considered:
148
+ Evidence and residual risk:
149
+ ```
150
+
151
+ ## Failure Diagnosis
152
+
153
+ - Result tests pass but stack, buffering, or order matters: add a process-shaped
154
+ verifier.
155
+ - Same call changes but no history is named: revise the state contract.
156
+ - A state machine lists states but not events and next states: derive the
157
+ transition relation.
158
+ - All work is serialized: narrow the protected order law.
159
+ - A log is proposed without replay/audit/merge pressure: local state may be the
160
+ smaller honest model.
161
+ - A pipeline stage hides effects: expose the phase or rename the process
162
+ honestly.
163
+
164
+ ## Source Trace
165
+
166
+ - *Structure and Interpretation of Computer Programs*, Second Edition,
167
+ chapters 1 and 3: procedure/process distinction, state and assignment,
168
+ identity and sharing, concurrency, constraints, delayed evaluation, and
169
+ streams.
170
+ - Zachary Tellman, *Elements of Clojure*, 2019: units of computation and the
171
+ construction of pull-transform-push processes.
@@ -0,0 +1,245 @@
1
+ # Responsibility And Variation
2
+
3
+ Use this reference when a real change exposes misplaced knowledge, repeated
4
+ arguments, data clumps, conditional dispatch, type transitions, object creation,
5
+ or uncertainty about which collaboration should absorb variation.
6
+
7
+ ## Begin With The Change
8
+
9
+ Do not design toward classes, polymorphism, or a factory in advance. State the
10
+ accepted change and show where the current code resists it. A smell identifies a
11
+ point of attack, not the final architecture.
12
+
13
+ Keep a simple concrete solution when it remains understandable and cheap to
14
+ change. A more elaborate design is justified by localized future change, not by
15
+ lower line count or the prestige of a pattern.
16
+
17
+ ## Inventory Responsibilities
18
+
19
+ Describe what the current unit:
20
+
21
+ - knows;
22
+ - calculates or decides;
23
+ - coordinates;
24
+ - creates;
25
+ - sends to collaborators;
26
+ - changes for independent reasons.
27
+
28
+ Write wishful pseudocode in messages rather than field manipulation. A message
29
+ asks a receiver that owns relevant knowledge to do work. Repeatedly pulling data
30
+ out of one object so another can decide what it means is evidence of misplaced
31
+ responsibility.
32
+
33
+ ## Smells As Design Evidence
34
+
35
+ Inspect smells on the accepted change path:
36
+
37
+ - a value repeatedly passed through methods that already belong to one concept;
38
+ - several fields or parameters that move as a data clump;
39
+ - conditionals that select behavior by a stable domain variant;
40
+ - methods that mostly inspect another unit's data;
41
+ - a coordinator that both chooses a variant and implements each variant;
42
+ - object construction mixed into domain collaboration;
43
+ - a chain of navigation that exposes collaborator structure.
44
+
45
+ The sketch should show how one concrete movement would make the change local.
46
+ Do not clean unrelated smells to make the design look complete.
47
+
48
+ ## Extracting A Responsibility
49
+
50
+ A candidate unit is credible when data and behavior form a coherent concept with
51
+ its own reason to change. State:
52
+
53
+ ```text
54
+ Responsibility: what the unit owns
55
+ Knowledge: data or history required to fulfill it
56
+ Messages: minimal caller-visible protocol
57
+ Hidden detail: mechanics callers stop knowing
58
+ Creation: who constructs or selects it
59
+ Representative change: change that becomes local
60
+ Rejected placement: why the old owner was wrong
61
+ ```
62
+
63
+ Move callers gradually when old and new forms can coexist. The implementation
64
+ protocol owns those edits; this reference only shapes the target collaboration.
65
+
66
+ Immutability often makes an extracted value easier to share and reason about,
67
+ but it is not mandatory when identity or local history is the product model.
68
+
69
+ ## Variation And Substitution
70
+
71
+ Use polymorphism only when variants share a real role and callers can send the
72
+ same message without knowing the concrete type. State the role contract and
73
+ unsupported cases.
74
+
75
+ A subtype or implementation must preserve caller expectations. A special case
76
+ that raises, changes return meaning, or requires stronger preconditions may not
77
+ belong under the common role. Model old and new contracts before claiming safe
78
+ substitution.
79
+
80
+ Conditionals are not categorically wrong. Keep them when the variation is local,
81
+ finite, readable, and unlikely to grow independently. Replace them when new
82
+ accepted variants repeatedly force old behavior owners to change.
83
+
84
+ ## Type Transitions
85
+
86
+ When one domain value leads to another kind of value, model the transition as a
87
+ domain relation rather than scattered numeric or string manipulation. State:
88
+
89
+ - current type and next type;
90
+ - operation or event causing the transition;
91
+ - preserved meaning;
92
+ - boundary or terminal behavior;
93
+ - whether the target selects itself or a collaborator decides.
94
+
95
+ Transitions that violate a common role may require a narrower protocol or an
96
+ explicit result type instead of inheritance.
97
+
98
+ ## Object Creation And Factories
99
+
100
+ Creation policy belongs at a boundary where variant information is available.
101
+ Keep domain collaborators dependent on the role they use, not on class-name or
102
+ registration mechanics.
103
+
104
+ Factory designs form a continuum: a concrete conditional, configurable mapping,
105
+ registration, self-registration, or automatic discovery each moves knowledge
106
+ and adds operational cost. Compare:
107
+
108
+ - who knows available variants;
109
+ - how a new variant is introduced;
110
+ - unsupported and duplicate registration behavior;
111
+ - load order, reflection, naming, and deployment assumptions;
112
+ - testability and failure visibility.
113
+
114
+ Choose the least powerful mechanism that satisfies real extension pressure.
115
+ Pushing construction to the edge often removes the need for an elaborate
116
+ factory inside the domain.
117
+
118
+ ## Dependency Direction And Navigation
119
+
120
+ High-level product behavior should depend on stable roles rather than concrete
121
+ variant mechanics. Inject a dependency when it represents a caller-chosen
122
+ collaborator, not merely to make every object configurable.
123
+
124
+ Long navigation chains reveal structural knowledge. Prefer asking the first
125
+ meaningful collaborator for the domain result, but do not add forwarding methods
126
+ that only hide an unchanged data path. The receiving responsibility must become
127
+ more coherent.
128
+
129
+ ## Tests As Role Evidence
130
+
131
+ Choose units to test by public responsibility and cost of failure, not by one
132
+ test file per class. Use integration evidence for collaborations and focused
133
+ unit evidence for stable role contracts or difficult cases.
134
+
135
+ Fakes are useful when they express the same role without importing irrelevant
136
+ context. Tests that echo implementation structure, duplicate the same behavior
137
+ at every layer, or preserve obsolete context inhibit redesign.
138
+
139
+ ## Complete Example: Move Discount Knowledge
140
+
141
+ Accepted change: subscriptions now support a partner discount in addition to a
142
+ student discount. Current `Checkout` receives `student`, `partner`, `country`,
143
+ and `subtotal`, then selects and calculates every discount itself.
144
+
145
+ ### Inventory the current owner
146
+
147
+ ```text
148
+ Checkout knows:
149
+ customer flags, discount precedence, formulas, country exclusions
150
+ Checkout decides:
151
+ which discount applies
152
+ Checkout coordinates:
153
+ pricing, payment, receipt
154
+ Checkout changes when:
155
+ discount policy, payment flow, or receipt flow changes
156
+ ```
157
+
158
+ The problem is not the conditional alone. Discount knowledge and behavior have
159
+ a different reason to change from checkout coordination.
160
+
161
+ ### Write wished messages
162
+
163
+ ```text
164
+ discount = discountPolicy.for(customer, country)
165
+ payable = discount.applyTo(subtotal)
166
+ checkout.charge(payable)
167
+ ```
168
+
169
+ Candidate responsibility:
170
+
171
+ ```text
172
+ Responsibility: choose and apply the accepted discount policy
173
+ Knowledge: eligibility, precedence, exclusions, calculation
174
+ Messages: for(customer, country); applyTo(money)
175
+ Hidden detail: flags and formula selection
176
+ Creation: composition root supplies current policy set
177
+ Representative change: add partner eligibility and formula locally
178
+ ```
179
+
180
+ If student and partner discounts share `applyTo(Money) -> Money` with the same
181
+ preconditions and result meaning, they may honor one role. If partner discount
182
+ requires an asynchronous provider lookup, it cannot silently substitute for a
183
+ pure discount. The boundary may instead return an eligibility decision or move
184
+ the lookup to the pull phase.
185
+
186
+ A local finite rule table may remain clearer than a class per discount. Add a
187
+ factory or registry only if creation or extension pressure is real. Constructing
188
+ the policy set at the edge keeps `Checkout` independent without inventing
189
+ discovery.
190
+
191
+ Smallest implementation surface:
192
+
193
+ ```text
194
+ 1. characterize current student behavior with responsibility-level examples
195
+ 2. introduce DiscountPolicy behind the existing result
196
+ 3. move one policy calculation while keeping Checkout behavior green
197
+ 4. add partner behavior through the same caller-visible contract
198
+ 5. inspect whether the role remains coherent; stop at the stable landing
199
+ ```
200
+
201
+ This reference shapes the collaboration. The direct execution protocol owns the
202
+ sender-by-sender mutation, and `abstraction-review` decides whether the candidate
203
+ is stable enough to keep.
204
+
205
+ ## Sketch Output
206
+
207
+ ```text
208
+ Change pressure: accepted change exposing the design issue
209
+ Current responsibility inventory: knows, decides, coordinates, creates
210
+ Point of attack: concrete smell on the change path
211
+ Wished messages: collaboration in domain language
212
+ Candidate ownership: data, behavior, hidden detail, reason to change
213
+ Variation model: role, variants, substitution and unsupported cases
214
+ Creation boundary: selection knowledge and factory tradeoff
215
+ Checks: behavior, role, integration, and pass-but-wrong cases
216
+ First item: smallest implementation step
217
+ Deferred: patterns or variants not yet supported by evidence
218
+ ```
219
+
220
+ ## Failure Checks
221
+
222
+ - a pattern or class hierarchy is selected before the change is stated;
223
+ - responsibility is inferred from duplicated syntax alone;
224
+ - an extracted object has no knowledge or reason to change of its own;
225
+ - polymorphism hides incompatible contracts;
226
+ - a factory solves hypothetical discovery or registration needs;
227
+ - dependency injection adds configuration without isolating real variation;
228
+ - navigation is hidden by forwarding methods without moving responsibility;
229
+ - tests freeze current internals rather than verify roles and behavior.
230
+
231
+ ## Source Trace
232
+
233
+ - Sandi Metz, Katrina Owen, and TJ Stankus, *99 Bottles of OOP*, Second
234
+ Edition, version 2.2.2, 2024: chapters 3-9 on listening to change, smells and
235
+ points of attack, responsibility extraction, argument removal, immutability,
236
+ Liskov substitution, conditional-to-polymorphic movement, type transitions,
237
+ factories, wishful pseudocode, dependency inversion, Law of Demeter, creation
238
+ at the edge, and responsibility-focused testing.
239
+ - Harold Abelson and Gerald Jay Sussman with Julie Sussman, *Structure and
240
+ Interpretation of Computer Programs*, Second Edition, MIT Press, 1996:
241
+ multiple representations, generic operations, data-directed programming, and
242
+ additivity.
243
+ - Zachary Tellman, *Elements of Clojure*, 2019: indirection cost, module
244
+ assumptions, and the distinction between cohesive components and adaptable
245
+ interfaces.
@@ -11,10 +11,11 @@ addition to visible behavior.
11
11
  - Verifier Ladder
12
12
  - Execution Versus Relevance
13
13
  - Pass-But-Wrong Search
14
+ - Test Design And Cost
14
15
  - Structural Degradation
15
16
  - Feedback Classification
16
17
  - Residual Risk And Stop Checks
17
- - Compact Example
18
+ - Complete Evidence Example
18
19
 
19
20
  ## Claim Before Check
20
21
 
@@ -104,6 +105,31 @@ current checks while violating the intended meaning. Look for:
104
105
  When a plausible shape remains cheap to test, add the smallest distinguishing
105
106
  fixture. Otherwise record it as residual risk instead of broadening the claim.
106
107
 
108
+ ## Test Design And Cost
109
+
110
+ Tests are design evidence only when their boundary and maintenance cost remain
111
+ useful. Prefer tests that expose public responsibility and product meaning over
112
+ tests that echo private method structure.
113
+
114
+ Choose the unit by the claim:
115
+
116
+ - focused examples for stable responsibility and boundary cases;
117
+ - role or contract tests when several implementations must substitute;
118
+ - integration tests for collaborations, creation, persistence, and wiring;
119
+ - properties when many examples share a generatable rule;
120
+ - stateful fixtures when history, retry, order, or identity matters.
121
+
122
+ Do not require one test layer per class. Loose coupling may make a smaller unit
123
+ economical to test, while simple forwarding or framework glue may be better
124
+ covered by a larger behavior check. Fakes should remove irrelevant context while
125
+ preserving the collaborator role; mocks that restate call internals create an
126
+ echo chamber.
127
+
128
+ Delete or reorganize tests only when the remaining evidence still supports the
129
+ same claims. Redundancy is sometimes cheap insurance and sometimes obsolete
130
+ context that prevents a design from moving. State which claim each retained test
131
+ protects.
132
+
107
133
  ## Structural Degradation
108
134
 
109
135
  Behavior may pass while the change weakens the code's ability to preserve the
@@ -153,7 +179,7 @@ Verification is complete enough when:
153
179
  Do not claim total correctness from a finite evidence set. State the strongest
154
180
  claim justified now.
155
181
 
156
- ## Compact Example
182
+ ## Complete Evidence Example
157
183
 
158
184
  ```text
159
185
  Claim: recurring schedules without an end date remain valid.
@@ -166,4 +192,36 @@ Residual: timezone behavior remains unverified and is not included in the
166
192
  supported claim.
167
193
  ```
168
194
 
169
- The correct result is a narrower supported claim, not an unqualified "done."
195
+ Now attempt a wrong implementation that always emits `recurring-open` whenever
196
+ `endDate` is absent. It passes the open-recurring row but also misclassifies a
197
+ one-time schedule whose UI omitted an optional display field. Add a one-time row
198
+ with the same absence shape but a different recurrence discriminator. This
199
+ fixture fails the plausible wrong rule while remaining at the public conversion
200
+ boundary.
201
+
202
+ Map the broader completion claim:
203
+
204
+ | Claim | Verifier | What it can still miss |
205
+ | --- | --- | --- |
206
+ | semantic variants convert correctly | focused table test | persisted legacy shapes not in the table |
207
+ | public type accepts intended callers | typecheck plus real caller build | runtime external input |
208
+ | legacy saved schedules remain readable | migration fixture through persistence adapter | unknown production corruption |
209
+ | UI shows the converted meaning | interaction test or manual run | timezone/environment variance |
210
+ | package contains the changed source | packed-tarball inspection and fresh install | registry propagation delay |
211
+
212
+ If only the first row is executed, report only the first claim. The correct
213
+ result is a narrower supported statement, not an unqualified “done.”
214
+
215
+ ## Source Trace
216
+
217
+ - Hillel Wayne, *Logic for Programmers*, version 0.14.0, May 4, 2026:
218
+ strong and weak tests, partial specifications, structural properties,
219
+ property-based testing, contracts, and proof limitations.
220
+ - Sandi Metz, Katrina Owen, and TJ Stankus, *99 Bottles of OOP*, Second
221
+ Edition, version 2.2.2, 2024: chapters 2 and 9 on cost-effective tests,
222
+ avoiding implementation echo, choosing units, unit versus integration tests,
223
+ context independence, fakes, role verification, and obsolete-test removal.
224
+ - Matthias Felleisen, Robert Bruce Findler, Matthew Flatt, and Shriram
225
+ Krishnamurthi, *How to Design Programs, Second Edition*, MIT Press, 2018:
226
+ representative examples and tests as successive constraints in a design
227
+ recipe.