@hobin/developer 0.1.10 → 0.1.12

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.
@@ -4,12 +4,12 @@
4
4
  {
5
5
  "id": "data-driven-design",
6
6
  "question": "How do accepted data meanings and examples determine the first executable function surface?",
7
- "trigger": "Product information, variants, examples, or tests should determine the function skeleton, and no narrower template, composition, generation, or accumulator question is primary.",
7
+ "trigger": "Product information, variants, examples, or tests should determine the function skeleton, and no narrower template, composition, generation, accumulator, or evidence-preserving boundary question is primary.",
8
8
  "method_step": "derive data definition, interpretation, examples, purpose, template, completed shape, and first executable item",
9
9
  "references": ["references/data-driven-design.md"],
10
10
  "artifacts": ["the six ordered design artifacts", "repository contradictions mapped to those artifacts", "a bounded first item and propagation check"],
11
11
  "stop": "Accepted data and behavior examples constrain an executable skeleton with contradictions and compatibility visible.",
12
- "separate_when": "Template shape, composition, earned abstraction, generated problems, or accumulated knowledge has an independent artifact."
12
+ "separate_when": "Template shape, composition, earned abstraction, generated problems, accumulated knowledge, or raw-to-refined construction has an independent artifact."
13
13
  },
14
14
  {
15
15
  "id": "data-shape-template",
@@ -66,6 +66,16 @@
66
66
  "stop": "The invariant explains initial, step, and final states and every semantic/resource delta is explicit.",
67
67
  "separate_when": "Problems are generated, carried data is persistent product history, or a concrete cache surface needs review."
68
68
  },
69
+ {
70
+ "id": "evidence-preserving-boundary",
71
+ "question": "How does less-trusted or less-structured input become a domain value that carries the established invariant?",
72
+ "trigger": "External, serialized, persisted, legacy, foreign, unknown, nullable, or overly broad input must become an accepted domain value; checks are repeated, return no refined value, occur after effects, or are followed by an assertion, cast, non-null claim, unchecked decode, or public raw construction.",
73
+ "method_step": "derive raw provenance, refined representation, parser or smart-constructor success/failure, construction owner, first-effect boundary, escape audit, and any bounded compiler gap",
74
+ "references": ["references/evidence-preserving-boundaries.md"],
75
+ "artifacts": ["a raw-to-refined boundary pipeline", "a parser/smart-constructor and failure contract", "a construction/escape, effect-order, and trusted-compiler-gap audit"],
76
+ "stop": "Every core construction path returns the invariant-carrying representation or explicit failure before dependent effects, with no unchecked narrowing or public raw-constructor bypass.",
77
+ "separate_when": "Admitted values or failure policy are disputed, alternate representations/public laws are independently consequential, a valid domain event changes type, or old/new compatibility remains unsettled."
78
+ },
69
79
  {
70
80
  "id": "design-levels",
71
81
  "question": "Which vocabulary, owner, and dependency direction make this caller contract truthful?",
@@ -74,7 +84,7 @@
74
84
  "references": ["references/design-levels-and-boundaries.md"],
75
85
  "artifacts": ["a caller-purpose and level map", "contract/owner/hidden choice/assumptions", "an alternate implementation or falsifier"],
76
86
  "stop": "Dependencies use truthful vocabulary, guarantees have owners, and lower-level change does not force unrelated callers.",
77
- "separate_when": "Representation, closure, process, state, dispatch, conversion, language, runtime, responsibility, or variation has its own output."
87
+ "separate_when": "Evidence-preserving input refinement, representation, closure, process, state, dispatch, conversion, language, runtime, responsibility, or variation has its own output."
78
88
  },
79
89
  {
80
90
  "id": "representation-barrier",
@@ -0,0 +1,200 @@
1
+ # Evidence-Preserving Boundaries
2
+
3
+ Use this reference when less-trusted or less-structured input must become a domain
4
+ value whose type or abstract representation carries an accepted invariant. The
5
+ input may be bytes, JSON, form values, command-line arguments, database rows,
6
+ legacy records, framework payloads, foreign values, or an overly broad in-memory
7
+ type. Parsing here means any fallible transformation from a weaker
8
+ representation to a stronger one; it is not limited to text.
9
+
10
+ ## Information Must Survive The Check
11
+
12
+ Two operations may perform the same runtime checks while establishing different
13
+ contracts:
14
+
15
+ ```text
16
+ validate : Raw -> Result<Unit, BoundaryError>
17
+ parse : Raw -> Result<Domain, BoundaryError>
18
+ ```
19
+
20
+ `validate` reports only success or failure. Unless its result narrows the value
21
+ in a scope the compiler preserves, later code still receives `Raw` and must
22
+ repeat the check, trust a comment, or assert `Domain`. `parse` returns the more
23
+ precise value and makes the learned information necessary for execution.
24
+
25
+ Treat these as evidence-destroying by default:
26
+
27
+ ```text
28
+ validate(raw); cast raw to Domain
29
+ JSON.decode(bytes) as Domain
30
+ lookup(key)! where absence has domain meaning
31
+ construct Domain through public raw fields
32
+ ```
33
+
34
+ A type assertion, cast, non-null assertion, ignored conversion result, or typed
35
+ deserialization target is not evidence that an invariant holds.
36
+
37
+ ## Draw The Refinement Boundary
38
+
39
+ Derive this pipeline before choosing library syntax:
40
+
41
+ ```text
42
+ external / raw / legacy representation
43
+ |
44
+ | parse / refine / smart constructor
45
+ | failure is explicit here
46
+ v
47
+ invariant-carrying domain value
48
+ |
49
+ | total core operations
50
+ v
51
+ domain effects
52
+ ```
53
+
54
+ Record:
55
+
56
+ ```text
57
+ raw representation and provenance
58
+ accepted domain representation
59
+ invariant learned at the transition
60
+ parser or smart-constructor signature
61
+ success and failure result
62
+ single construction owner
63
+ first domain effect allowed after success
64
+ legacy, persistence, and re-entry paths
65
+ ```
66
+
67
+ Push the proof burden toward the earliest boundary that has enough information,
68
+ but no further. Authorization or a small resource guard may precede expensive
69
+ parsing when abuse resistance requires it; those checks must not perform the
70
+ domain mutation that depends on parsed input. Parsing may use several passes or
71
+ select a later parser from an earlier discriminator as long as execution does
72
+ not consume partially parsed domain data.
73
+
74
+ ## Choose A Stronger Representation
75
+
76
+ Prefer the most precise representation the current language and repository can
77
+ reasonably support:
78
+
79
+ - a product type when required fields must be present together;
80
+ - a sum type when cases have different meanings or fields;
81
+ - a non-empty, bounded, normalized, branded, opaque, or capability-bearing type
82
+ when that restriction removes a real downstream branch;
83
+ - a map or set when uniqueness or duplicate policy is accepted;
84
+ - an abstract type with a smart constructor when the host type system cannot
85
+ directly encode the invariant.
86
+
87
+ Do not call a narrower representation better until the excluded ability is known
88
+ to be unnecessary. The accepted domain comes from `model`; this route owns the
89
+ boundary that constructs it.
90
+
91
+ ## Wished Interface
92
+
93
+ Use the target language's ordinary result and error conventions. The important
94
+ shape is that success carries `Domain`:
95
+
96
+ ```text
97
+ parseOrder : UnknownInput -> Result<Order, OrderInputError>
98
+ placeOrder : Order -> Effect<PlacementResult>
99
+
100
+ handle(input):
101
+ order <- parseOrder(input)
102
+ placeOrder(order)
103
+ ```
104
+
105
+ Throwing at an application edge, returning an option/either/result, or using a
106
+ checked constructor can all be valid. A predicate or assertion function can also
107
+ preserve information when the language genuinely narrows the checked value in
108
+ the only scope where it is consumed. What is not valid is checking one value and
109
+ then separately claiming a stronger type without a compiler-visible or
110
+ abstraction-visible connection.
111
+
112
+ ## Construction And Escape Audit
113
+
114
+ List every way `Domain` can enter the core:
115
+
116
+ | Path | Input provenance | Establishes invariant by | Produces | Bypass risk |
117
+ | --- | --- | --- | --- | --- |
118
+ | public parser | external raw value | complete boundary checks | `Domain` or failure | expected path |
119
+ | smart constructor | broad in-memory value | constructor checks | abstract `Domain` or failure | expected path |
120
+ | deserializer | persisted or wire value | parser plus compatibility policy | `Domain` or failure | unchecked typed decode |
121
+ | internal constructor | already refined fields | private construction law | `Domain` | public/raw export |
122
+ | test factory | test data | public or equivalent checked path | `Domain` | unrealistic invalid fixtures |
123
+
124
+ A claimed invariant is only as strong as its weakest construction path. Search
125
+ for raw constructors, object literals, reflection, ORM hydration, generated
126
+ adapters, test factories, casts, suppressions, and legacy re-entry points.
127
+
128
+ ## Trusted Compiler Gaps
129
+
130
+ Sometimes a complete check establishes a fact that the host type system cannot
131
+ retain. Do not spread assertions to compensate. Isolate the smallest exception
132
+ inside the one parser or smart-constructor owner and record:
133
+
134
+ ```text
135
+ exact assertion or unsafe operation
136
+ fact already established
137
+ complete check or trusted contract that established it
138
+ why ordinary narrowing cannot express the fact
139
+ containment boundary
140
+ falsifying test, type check, or structural inspection
141
+ ```
142
+
143
+ Literal-preservation syntax and framework types already guaranteed by a runtime
144
+ schema are not the same as asserting hostile input into a domain type. The
145
+ burden is still on the exception to name its prior evidence. If that evidence is
146
+ missing, return to the parser design instead of documenting a wish.
147
+
148
+ ## Shotgun And Effect Check
149
+
150
+ Reject a design when parsing or validation is mixed through processing code:
151
+
152
+ - consumers repeat checks for the same invariant;
153
+ - a late branch can discover malformed input after writes, sends, or mutations;
154
+ - every core function reserves an "impossible" failure despite an earlier check;
155
+ - compatibility adapters emit partially refined values;
156
+ - normalized and raw forms remain mutable and can drift apart.
157
+
158
+ Parse before the first domain effect. If staging or streaming makes one complete
159
+ up-front parse impractical, define an explicit phase or transaction boundary and
160
+ ensure each effect consumes a value whose required invariant is already carried
161
+ by that phase's representation.
162
+
163
+ ## Artifact
164
+
165
+ ```text
166
+ Raw representation and provenance:
167
+ Refined domain representation:
168
+ Invariant gained and ability lost:
169
+ Parser/smart-constructor signature:
170
+ Failure representation:
171
+ Construction owner and escape audit:
172
+ First domain effect after success:
173
+ Legacy/persistence/re-entry handling:
174
+ Trusted compiler gaps, or none:
175
+ Negative, bypass, and effect-order checks:
176
+ ```
177
+
178
+ ## Stop And Separation
179
+
180
+ Stop when every core construction path either produces the refined domain value
181
+ through the declared parser/constructor or fails explicitly, invalid input is
182
+ rejected before the domain effect that depends on it, and no unchecked narrowing
183
+ or public raw constructor claims the invariant.
184
+
185
+ Return to `model` when the admitted values or failure policy are disputed. Use
186
+ `representation-barrier` when alternate internal representations and public laws
187
+ are independently consequential, `type-transition` when an accepted domain
188
+ event transforms one valid domain type into another, and `contract-replacement`
189
+ when old and new boundary compatibility remains unsettled.
190
+
191
+ ## Source Trace
192
+
193
+ - Alexis King, “Parse, don’t validate,” published November 5, 2019: the
194
+ `NonEmpty` example, validation-versus-parsing return-type contrast, boundary
195
+ parsing and shotgun-parsing discussion, practical duplicate-key example, and
196
+ guidance on precise datatypes, proof placement, multi-pass parsing,
197
+ denormalization, abstract datatypes, and bounded exceptions.
198
+ - The construction-path audit, trusted-compiler-gap record, effect-order check,
199
+ repository compatibility paths, and language-neutral assertion taxonomy are
200
+ Developer adaptations of that source's type-driven design argument.
@@ -74,8 +74,11 @@ after code changes, new evidence, changed claims, or source-provenance changes.
74
74
  1. Extract the exact claims from the request, accepted decisions, implementation
75
75
  report, invariant, or model.
76
76
  2. Attach concrete evidence to each claim and classify its strength.
77
- 3. Check constraints, forbidden cases, transitions, callers, and abstraction
78
- stop checks when they are part of the claim.
77
+ 3. Check constraints, forbidden cases, transitions, callers, abstraction stop
78
+ checks, and every construction or re-entry path for invariant-carrying values
79
+ when they are part of the claim. Validation followed by an assertion, a
80
+ public raw constructor, unchecked deserialization, or a domain effect before
81
+ parsing is a pass-but-wrong shape, not type evidence.
79
82
  4. Distinguish verifier execution from verifier relevance.
80
83
  5. Ask what wrong implementation could still pass and name its concrete shape.
81
84
  6. Narrow any passing claim that is broader than its evidence.
@@ -26,7 +26,7 @@ Separate independently falsifiable claims:
26
26
  - user or caller behavior;
27
27
  - forbidden and boundary cases;
28
28
  - data multiplicity and preservation;
29
- - type or API contract;
29
+ - type or API contract, including raw-to-refined construction and re-entry paths;
30
30
  - state transition and history;
31
31
  - representation or ownership boundary;
32
32
  - source/version compatibility;
@@ -102,10 +102,17 @@ calibrations by failure mechanism rather than by book.
102
102
  | database schema behavior is preserved | row content matches | labels or function-valued predicates changed | inspect schema and execute predicates/integrity checks |
103
103
  | temporal implementation is correct | each enum state is reachable | stale or duplicate event commits twice | ordered trace with stale, retry, duplicate, and concurrency |
104
104
  | abstraction is safe | public tests pass | callers still depend on fields, load order, or hidden default | leak search, fake variant, and real caller rewrite |
105
+ | domain type carries its invariant | happy input passes and typecheck is green | validation returns no refined value, then a cast/assertion claims the domain type | inspect every construction path; require parser/smart-constructor success to return the domain value |
106
+ | invalid input cannot affect domain state | negative parser test passes | a write, send, mutation, or partial update happens before parsing completes | effect-order integration check with invalid and partially valid input |
107
+ | construction boundary is closed | public parser tests pass | raw constructor, ORM hydration, test factory, or legacy adapter bypasses the parser | constructor/export/re-entry search plus a direct-bypass type or runtime check |
105
108
  | package/source compatibility holds | workspace tests pass | packed artifact or installed version lacks changed files | inspect tarball/fresh install and bind provenance |
106
109
 
107
110
  A verifier for one row does not support another. In particular, location,
108
111
  residual, representation, and downstream tolerances are not interchangeable.
112
+ A typecheck proves only that the program follows the declared types; an
113
+ unchecked narrowing operation can make a false declaration typecheck. Pair
114
+ compile-time evidence with construction-path and boundary evidence whenever the
115
+ type itself is part of the claim.
109
116
 
110
117
  ## Formal And Search Result Boundaries
111
118
 
@@ -165,6 +172,10 @@ Unverified claims and residual risk:
165
172
 
166
173
  ## Source Trace
167
174
 
175
+ - Alexis King, “Parse, don’t validate,” published November 5, 2019, for the
176
+ distinction between a check that discards information and a parser that
177
+ returns a refined value, plus the parsing-before-execution boundary. The
178
+ construction-path and effect-order verifier rows are Developer adaptations.
168
179
  - Hillel Wayne, *Logic for Programmers*, v0.14.0:
169
180
  Chapters 3-6 and 9-11, pp. 23-155, for logical/runtime preservation, partial
170
181
  specifications, generated properties, proof limits, bounded models, and solver