@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.
- package/README.md +29 -2
- package/REFERENCE_ROUTING.md +10 -1
- package/extensions/compaction-language.ts +5 -3
- package/extensions/developer.ts +170 -7
- package/extensions/references/behavior-preserving-structural-change.md +10 -2
- package/extensions/skills.ts +6 -2
- package/extensions/state.ts +136 -34
- package/extensions/tui.ts +5 -0
- package/package.json +1 -1
- package/skills/doctor/SKILL.md +284 -0
- package/skills/model/SKILL.md +6 -2
- package/skills/model/references/problem-modeling.md +13 -3
- package/skills/sketch/SKILL.md +11 -3
- package/skills/sketch/reference-policy.json +13 -3
- package/skills/sketch/references/evidence-preserving-boundaries.md +200 -0
- package/skills/verify/SKILL.md +5 -2
- package/skills/verify/references/verifier-selection-and-pass-but-wrong.md +12 -1
|
@@ -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
|
|
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,
|
|
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": "
|
|
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.
|
package/skills/verify/SKILL.md
CHANGED
|
@@ -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,
|
|
78
|
-
|
|
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
|