dsh-model-everything 0.0.0-stage → 0.2.0
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/LICENSE +21 -0
- package/README.en-US.md +332 -0
- package/README.md +332 -3
- package/cordis.patch.yml +20 -0
- package/examples/README.md +48 -0
- package/examples/control-dispatcher.json +113 -0
- package/examples/control-dispatcher.overbudget.json +113 -0
- package/examples/ecommerce-data-model.json +185 -0
- package/examples/order-state-machine.after.json +116 -0
- package/examples/order-state-machine.before.json +101 -0
- package/examples/user-migration.after.json +29 -0
- package/examples/user-migration.before.json +29 -0
- package/gate/locale/en.json +6 -0
- package/gate/locale/zh.json +6 -0
- package/gate/package.json +5 -0
- package/lib/baseline.js +249 -0
- package/lib/compose-tool.js +80 -0
- package/lib/concurrency-tool.js +40 -0
- package/lib/concurrency.js +206 -0
- package/lib/data-engine.js +1141 -0
- package/lib/data-tool.js +87 -0
- package/lib/design-engine.js +1149 -0
- package/lib/design-tool.js +63 -0
- package/lib/engine.js +4343 -0
- package/lib/export-tool.js +78 -0
- package/lib/exporters.js +434 -0
- package/lib/gate.js +274 -0
- package/lib/granularity.js +237 -0
- package/lib/index.js +237 -0
- package/lib/json-value.js +18 -0
- package/lib/model-file.js +48 -0
- package/lib/option-shape.js +62 -0
- package/lib/report-diff-tool.js +63 -0
- package/lib/report-view.js +433 -0
- package/lib/structure-tool.js +91 -0
- package/lib/structure.js +711 -0
- package/lib/tool.js +94 -0
- package/lib/types/baseline.d.ts +65 -0
- package/lib/types/compose-tool.d.ts +7 -0
- package/lib/types/concurrency-tool.d.ts +8 -0
- package/lib/types/concurrency.d.ts +37 -0
- package/lib/types/data-engine.d.ts +211 -0
- package/lib/types/data-tool.d.ts +10 -0
- package/lib/types/design-engine.d.ts +215 -0
- package/lib/types/design-tool.d.ts +11 -0
- package/lib/types/engine.d.ts +494 -0
- package/lib/types/export-tool.d.ts +7 -0
- package/lib/types/exporters.d.ts +37 -0
- package/lib/types/gate.d.ts +91 -0
- package/lib/types/granularity.d.ts +106 -0
- package/lib/types/index.d.ts +45 -0
- package/lib/types/json-value.d.ts +21 -0
- package/lib/types/model-file.d.ts +7 -0
- package/lib/types/option-shape.d.ts +22 -0
- package/lib/types/report-diff-tool.d.ts +8 -0
- package/lib/types/report-view.d.ts +50 -0
- package/lib/types/structure-tool.d.ts +10 -0
- package/lib/types/structure.d.ts +152 -0
- package/lib/types/tool.d.ts +11 -0
- package/lib/types/uml-communication.d.ts +109 -0
- package/lib/types/uml-composite.d.ts +107 -0
- package/lib/types/uml-interaction-overview.d.ts +91 -0
- package/lib/types/uml-profile.d.ts +112 -0
- package/lib/types/uml-structure.d.ts +53 -0
- package/lib/types/uml-syntax.d.ts +296 -0
- package/lib/types/uml-timing.d.ts +152 -0
- package/lib/types/uml-tool.d.ts +12 -0
- package/lib/types/uml-usecase.d.ts +58 -0
- package/lib/types/uml.d.ts +303 -0
- package/lib/uml-communication.js +353 -0
- package/lib/uml-composite.js +442 -0
- package/lib/uml-interaction-overview.js +277 -0
- package/lib/uml-profile.js +373 -0
- package/lib/uml-structure.js +306 -0
- package/lib/uml-syntax.js +545 -0
- package/lib/uml-timing.js +974 -0
- package/lib/uml-tool.js +213 -0
- package/lib/uml-usecase.js +532 -0
- package/lib/uml.js +2110 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +128 -6
- package/skills/model-everything/SKILL.md +450 -0
- package/skills/model-everything/references/dsh-model-schema.md +437 -0
- package/skills/model-everything/references/gap-routing-guide.md +42 -0
- package/skills/model-everything/references/hash-spec.md +152 -0
- package/skills/model-everything/references/logic-verification-guide.md +422 -0
- package/skills/model-everything-datamodel/SKILL.md +130 -0
- package/skills/model-everything-datamodel/references/data-model-guide.md +84 -0
- package/skills/model-everything-datamodel/references/data-model-schema.md +128 -0
- package/skills/model-everything-design/SKILL.md +115 -0
- package/skills/model-everything-interleaving/SKILL.md +63 -0
- package/skills/model-everything-interleaving/SKILL.zh-CN.md +60 -0
- package/skills/model-everything-interleaving/references/concurrency-risk-guide.md +63 -0
- package/skills/model-everything-report-reading/SKILL.md +137 -0
- package/skills/model-everything-report-reading/references/reading-a-report.md +166 -0
- package/skills/model-everything-report-reading/references/reading-a-report.mmd +59 -0
- package/skills/model-everything-structure/SKILL.md +96 -0
- package/skills/model-everything-structure/references/structure-review-guide.md +201 -0
- package/skills/model-everything-uml/SKILL.md +60 -0
- package/skills/model-everything-uml/references/uml-modeling-guide.md +551 -0
- package/src/baseline.ts +288 -0
- package/src/compose-tool.ts +82 -0
- package/src/concurrency-tool.ts +44 -0
- package/src/concurrency.ts +254 -0
- package/src/data-engine.ts +1208 -0
- package/src/data-tool.ts +91 -0
- package/src/design-engine.ts +1263 -0
- package/src/design-tool.ts +68 -0
- package/src/engine.ts +4564 -0
- package/src/export-tool.ts +81 -0
- package/src/exporters.ts +399 -0
- package/src/gate.ts +330 -0
- package/src/granularity.ts +312 -0
- package/src/index.ts +289 -0
- package/src/json-value.ts +20 -0
- package/src/model-file.ts +49 -0
- package/src/option-shape.ts +64 -0
- package/src/report-diff-tool.ts +67 -0
- package/src/report-view.ts +483 -0
- package/src/structure-tool.ts +93 -0
- package/src/structure.ts +786 -0
- package/src/tool.ts +103 -0
- package/src/uml-communication.ts +428 -0
- package/src/uml-composite.ts +520 -0
- package/src/uml-interaction-overview.ts +321 -0
- package/src/uml-profile.ts +439 -0
- package/src/uml-structure.ts +317 -0
- package/src/uml-syntax.ts +764 -0
- package/src/uml-timing.ts +1106 -0
- package/src/uml-tool.ts +230 -0
- package/src/uml-usecase.ts +566 -0
- package/src/uml.ts +2139 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# Logic Verification Guide
|
|
2
|
+
|
|
3
|
+
Deep reference for Phase 2a/2b of this plugin. Load this when the skill triggers escalation to logic-primitive verification. Covers model extraction methodology, probe design patterns, counter-example interpretation, and known limitations.
|
|
4
|
+
|
|
5
|
+
## Model Extraction Methodology
|
|
6
|
+
|
|
7
|
+
### Step 1: Identify the State Machine Boundary
|
|
8
|
+
|
|
9
|
+
Before extracting states, determine what IS and IS NOT part of the machine:
|
|
10
|
+
|
|
11
|
+
- **In**: states the plan explicitly names, events the plan describes, guards the plan states
|
|
12
|
+
- **Out**: hardware-level behavior (register writes, DMA transfers), OS-level scheduling (task switches, priority inversion), external system interactions not described in the plan
|
|
13
|
+
|
|
14
|
+
If the plan doesn't clearly define the boundary, flag it: "Plan does not define state machine scope — model may be incomplete."
|
|
15
|
+
|
|
16
|
+
### Step 2: Extract States
|
|
17
|
+
|
|
18
|
+
Scan the plan for:
|
|
19
|
+
|
|
20
|
+
- Enumerated state types (`typedef enum { ... } xxx_state_t`)
|
|
21
|
+
- Named phases in prose ("the system then enters the RECOVERING phase")
|
|
22
|
+
- Implicit states (error paths described but not named — give them explicit names in the model)
|
|
23
|
+
|
|
24
|
+
**Rule**: If a behavioral section describes a distinct set of actions before a transition, it's a state — even if the plan doesn't label it as one.
|
|
25
|
+
|
|
26
|
+
### Step 3: Extract Transitions
|
|
27
|
+
|
|
28
|
+
For each state, list:
|
|
29
|
+
|
|
30
|
+
- **Explicit transitions**: `state = NEXT_STATE` assignments, `→` arrows in diagrams, prose like "then transitions to X"
|
|
31
|
+
- **Guard conditions**: `if/else` branches that split a single event into multiple next states
|
|
32
|
+
- **Timer-driven transitions**: timeouts, retry delays, cooldown periods
|
|
33
|
+
|
|
34
|
+
**Edge case**: A transition mentioned in prose but missing from the state diagram. Flag it — "Plan describes transition X but state diagram omits it."
|
|
35
|
+
|
|
36
|
+
### Step 4: Identify Invariants
|
|
37
|
+
|
|
38
|
+
Extract every claim that uses absolute language:
|
|
39
|
+
|
|
40
|
+
| Pattern | Example | Invariant to Check |
|
|
41
|
+
|---------|---------|-------------------|
|
|
42
|
+
| "always ..." | "always returns to IDLE" | From every state reachable in ≤K steps, IDLE is reachable |
|
|
43
|
+
| "never ..." | "never enters ACTIVE without power_ready" | ACTIVE is not reachable from any path that hasn't passed through power_ready |
|
|
44
|
+
| "guaranteed ..." | "guaranteed cleanup within 500ms" | Every ERROR→RECOVERING path includes a cooldown transition |
|
|
45
|
+
| "cannot ..." | "cannot deadlock" | No absorbing cycle exists |
|
|
46
|
+
| "all paths ..." | "all paths lead to ERROR on failure" | Every failure event reaches ERROR (not FATAL, not stuck) |
|
|
47
|
+
|
|
48
|
+
### Step 4.5: Write the Natural Language and Pick a Rendering Form
|
|
49
|
+
|
|
50
|
+
Do NOT keep the natural-language explanations in a separate block — integrate them
|
|
51
|
+
into the model presentation so every entry reads like a sentence in the real
|
|
52
|
+
scenario. Write meanings for every state, every event, and every distinct
|
|
53
|
+
(state, event) combination (carry them in the model's `narrative` block:
|
|
54
|
+
`narrative.states`, `narrative.events`, `narrative.scenarios`; the report
|
|
55
|
+
echoes them back). Then render one of three forms:
|
|
56
|
+
|
|
57
|
+
**Form A — integrated transition table (default)**: `STATE(含义)` /
|
|
58
|
+
`event(含义)` / `NEXT(含义)` columns plus a final scenario column, so each
|
|
59
|
+
row is one self-contained sentence. Width discipline: keep meanings short
|
|
60
|
+
(state/event ≤ 6 characters, scenario ≤ 10) and estimate row width (CJK counts
|
|
61
|
+
as 2) to fit the display area — a wrapped row loses column alignment and
|
|
62
|
+
readability collapses. If a row would wrap, shorten meanings; if it still will
|
|
63
|
+
not fit, use Form C.
|
|
64
|
+
|
|
65
|
+
**Form B — sentence blocks (reading-accessible)**: one transition per block,
|
|
66
|
+
scenario sentence first, then a fixed three-line frame (状态…/发生…/进入…). Use
|
|
67
|
+
for detailed confirmation, users with reading difficulties, or ≤ 10 transitions.
|
|
68
|
+
|
|
69
|
+
**Form C — grouped by source state (large machines / narrow panes)**: one
|
|
70
|
+
section per state, each rendered as its own small 3-column table
|
|
71
|
+
(`event(含义)| NEXT(含义)| 场景`); no cross-group column alignment to track.
|
|
72
|
+
Use for ≥ 15 transitions or when the display area is too narrow for Form A. If one
|
|
73
|
+
group's table would still wrap, fall back to a one-line-per-event bullet list for
|
|
74
|
+
that group only.
|
|
75
|
+
|
|
76
|
+
### Step 5: Confirm with User
|
|
77
|
+
|
|
78
|
+
Show the rendered model (the chosen form, symbols + inlined natural language)
|
|
79
|
+
BEFORE writing the harness. Ask:
|
|
80
|
+
|
|
81
|
+
1. Are all states captured?
|
|
82
|
+
2. Are all transitions and guards correct?
|
|
83
|
+
3. Are there undocumented transitions not in the plan?
|
|
84
|
+
4. Is the initial state correct?
|
|
85
|
+
5. Does every entry read correctly — state/event meanings and the (state, event)
|
|
86
|
+
scenario all match the real situation?
|
|
87
|
+
|
|
88
|
+
Only proceed after confirmation. A wrong model produces wrong counter-examples,
|
|
89
|
+
which wastes more time than no verification at all.
|
|
90
|
+
|
|
91
|
+
## Probe Design Patterns
|
|
92
|
+
|
|
93
|
+
Every probe below is implemented by `model_verify`. These patterns are here to read a finding, not to reimplement it.
|
|
94
|
+
|
|
95
|
+
### A1: Unexpected Event Injection
|
|
96
|
+
|
|
97
|
+
For every state, list the events declared anywhere in the machine that this state does not handle. An unhandled event is a silent ignore or undefined behaviour.
|
|
98
|
+
|
|
99
|
+
### A2: Race Interleaving
|
|
100
|
+
|
|
101
|
+
For event pairs that can arrive in the same tick, compare `e1` then `e2` against `e2` then `e1`. A different outcome is order dependence the design must state.
|
|
102
|
+
|
|
103
|
+
### A3: Order Permutation
|
|
104
|
+
|
|
105
|
+
The same question at N events. Up to 5 events permute fully; beyond that the probe samples. More than one terminal state means the outcome depends on arrival order.
|
|
106
|
+
|
|
107
|
+
### A4: Pair Symmetry
|
|
108
|
+
|
|
109
|
+
For paired operations (lock/unlock, start/stop, alloc/free, enable_irq/disable_irq, open/close), search from the initial state for a path that acquires without releasing before it terminates or acquires again. That is a leak or a deadlock.
|
|
110
|
+
|
|
111
|
+
### A5: Boundary Blast
|
|
112
|
+
|
|
113
|
+
Test each counter at 0, 1, max-1, max and max+1. Flag overflow and underflow. Timestamps wrap too: a 32-bit millisecond clock wraps after about 49.7 days, so check every `elapsed_*()` pattern.
|
|
114
|
+
|
|
115
|
+
### A6: Resource Injection
|
|
116
|
+
|
|
117
|
+
For every state and transition, ask what happens when the resource call fails: `malloc` returns NULL, a queue is full, a semaphore times out, a pool is exhausted. No error, fail or retry transition means no recovery path.
|
|
118
|
+
|
|
119
|
+
### A7: Minimal Counter-Example
|
|
120
|
+
|
|
121
|
+
Breadth-first search for the shortest event sequence that violates an invariant. It decides one runtime state at a time, so it fits the state-predicate kinds only. `leads-to`, `sequence`, `atomicity`, `budget` and `probability` assert a property of a whole run and use the search in their own sections (A9-A13).
|
|
122
|
+
|
|
123
|
+
### S8: Monotonic Variables
|
|
124
|
+
|
|
125
|
+
For counters that must move one way only, list the events that change them. An event that moves against the declared direction is a finding.
|
|
126
|
+
|
|
127
|
+
### A8: Idempotent Replay
|
|
128
|
+
|
|
129
|
+
Apply each retryable event twice from every reachable state. A second application that changes state, or cannot happen, is a finding.
|
|
130
|
+
|
|
131
|
+
### A9: Leads-To
|
|
132
|
+
|
|
133
|
+
For a progress claim ("from MIGRATING, eventually DONE"), check every path from the source state. A path that dead-ends or loops before the target fails. A target set is still a universal claim: a branch that reaches none of its members fails.
|
|
134
|
+
|
|
135
|
+
### A10: Sequence Order
|
|
136
|
+
|
|
137
|
+
For an ordered sequence ("backup, then modify, then commit"), search for a path where a later event occurs before an earlier one.
|
|
138
|
+
|
|
139
|
+
### A11: Atomicity
|
|
140
|
+
|
|
141
|
+
For all-or-nothing groups, track whether the atomic event started and whether commit or rollback followed. Leaving the scope, or terminating, before commit or rollback is a violation.
|
|
142
|
+
|
|
143
|
+
### A12: Budget (Worst-Case Path Cost)
|
|
144
|
+
|
|
145
|
+
Give each transition a `cost` and declare a `budget`. The probe reports the shortest path whose accumulated cost exceeds it. A reachable cycle with positive cost means cost grows without bound, which is a violation whatever the budget says. Costs are modeler labels: this checks the model against its budget, not real WCET.
|
|
146
|
+
|
|
147
|
+
### A13: Probability Reachability (DTMC)
|
|
148
|
+
|
|
149
|
+
Give each branch a relative `weight` and declare a `probability` bound. The probe solves P(ever reaching the target) by value iteration and compares it with the bound. Absent weight is 1; weight 0 never fires. This is a qualitative check of the weights, not a measured failure rate.
|
|
150
|
+
|
|
151
|
+
### A14: Deadline (Discrete Tick Clock)
|
|
152
|
+
|
|
153
|
+
Declare which events advance the clock (`tickEvents`) and cap per-state residency with `maxTicks`. A tick that keeps the machine resident past its cap is a deadline miss, and the probe reports the over-residency path. This checks declared deadlines, not execution time.
|
|
154
|
+
|
|
155
|
+
## Counter-Example Interpretation
|
|
156
|
+
|
|
157
|
+
When a probe finds a counter-example, classify it:
|
|
158
|
+
|
|
159
|
+
### True Positive (plan has a real gap)
|
|
160
|
+
|
|
161
|
+
- The counter-example uses only events/states defined in the plan
|
|
162
|
+
- The plan's own rules would agree this is a violation
|
|
163
|
+
- **Action**: Report as a finding with severity based on impact
|
|
164
|
+
|
|
165
|
+
### Model Error (extraction was wrong)
|
|
166
|
+
|
|
167
|
+
- The counter-example depends on a transition the plan doesn't actually define
|
|
168
|
+
- The plan explicitly handles this case but the model extraction missed it
|
|
169
|
+
- **Action**: Fix the model and re-run; do NOT report as a finding
|
|
170
|
+
|
|
171
|
+
### Acceptable Risk (gap is intentional)
|
|
172
|
+
|
|
173
|
+
- The plan acknowledges the gap explicitly ("not handled, system resets")
|
|
174
|
+
- The counter-example requires physically impossible event sequences
|
|
175
|
+
- **Action**: Note in findings but mark as "acknowledged — no fix needed"
|
|
176
|
+
|
|
177
|
+
## Known Limitations
|
|
178
|
+
|
|
179
|
+
### What This Method CAN Detect
|
|
180
|
+
|
|
181
|
+
- Missing transitions and states
|
|
182
|
+
- Deadlock and livelock
|
|
183
|
+
- Violated invariants (the plan's own claims disproven)
|
|
184
|
+
- Race conditions between documented events
|
|
185
|
+
- Unsymmetrical resource pairs
|
|
186
|
+
- Counter/timer boundary issues
|
|
187
|
+
|
|
188
|
+
### What This Method CANNOT Detect
|
|
189
|
+
|
|
190
|
+
- **Implementation bugs**: The C code may have errors not present in the model
|
|
191
|
+
- **Timing-dependent bugs**: the model does not simulate real-time constraints
|
|
192
|
+
- **Compiler/optimization issues**: Volatile omission, reordering, inlining effects
|
|
193
|
+
- **Hardware-specific behavior**: Memory-mapped I/O timing, DMA races, cache coherency
|
|
194
|
+
- **Undocumented behavior**: If the plan doesn't describe a transition, the model can't either
|
|
195
|
+
- **Real concurrency**: The model is single-threaded; true preemptive multitasking bugs are out of scope
|
|
196
|
+
- **Entry/exit actions**: State entry/exit side effects (e.g., `lock()` on enter, `unlock()` on exit) are not modeled as events. A4 Pair Symmetry may miss unbalanced pairs that exist only in entry/exit actions. If the plan describes these, manually extract them as pseudo-events (`ENTER_state`, `EXIT_state`) before running verification. In DSH (`model_verify`), state `onEntry`/`onExit` declarations are modeled natively and A4 treats them as implicit acquire/release events — no manual pseudo-events needed.
|
|
197
|
+
- **Execution cost is modeler-annotated**: transition `cost` (absent = 1) and `budget` invariants are static labels; A12 verifies the model against them. Real execution time/WCET needs binary-level timing analysis (e.g. aiT, RapiTime).
|
|
198
|
+
- **Unverified semantic dimensions**: when model or document vocabulary references hard real time, preemptive concurrency, hybrid control stability, or probability/reliability, this plugin reports informational notes / routes to dedicated tools — it never verifies those claims itself. See `references/gap-routing-guide.md`.
|
|
199
|
+
- **Guard variable scope**: The model treats guard variables as global to the machine. If a guard variable's lifetime is state-scoped (reset on entry) but the model assumes it accumulates globally, boundary-blast results will be wrong. Verify guard variable scope during extraction.
|
|
200
|
+
- **Nested/hierarchical states (Harel statecharts)**: The model only supports flat state machines. Parent/child state nesting, history pseudostates, and orthogonal regions are not supported — flatten them manually before verification.
|
|
201
|
+
- **Cross-machine protocols**: Two interacting state machines are verified independently. Composition bugs (e.g., Machine A sends event E to Machine B, but B is in a state that doesn't handle E) are invisible to single-machine verification. If the plan describes multi-machine interaction, document the protocol contract separately.
|
|
202
|
+
|
|
203
|
+
### Model Fidelity Warning
|
|
204
|
+
|
|
205
|
+
The model is an APPROXIMATION. It models state transitions, not execution semantics. A model that passes every check (S1-S8 structural, A1-A14) means the plan's LOGIC is consistent — NOT that the implementation will work. Always follow logic verification with code-level review.
|
|
206
|
+
|
|
207
|
+
## Refactoring Verification
|
|
208
|
+
|
|
209
|
+
When the document is a refactoring plan (modifying existing logic, not greenfield design), the pipeline adapts to compare BEFORE and AFTER models.
|
|
210
|
+
|
|
211
|
+
### Extraction for Refactoring
|
|
212
|
+
|
|
213
|
+
The BEFORE model comes from **code, not the plan**. The plan may describe the current state inaccurately — verify against the actual implementation:
|
|
214
|
+
|
|
215
|
+
1. Read the relevant source files (state machine dispatch, state enum, handler functions)
|
|
216
|
+
2. Extract the ACTUAL transition logic from code, not from the plan's description of "current behavior"
|
|
217
|
+
3. Extract the AFTER model from the plan as usual
|
|
218
|
+
4. Display both tables AND their model narratives side by side
|
|
219
|
+
|
|
220
|
+
### Comparison Methodology
|
|
221
|
+
|
|
222
|
+
**Behavioral preservation**: For each event sequence accepted by BEFORE, trace the same sequence in AFTER. If AFTER ends in a different state (or rejects the sequence), flag as BEHAVIORAL DELTA. The plan must explicitly document this delta — if it doesn't, it's a regression.
|
|
223
|
+
|
|
224
|
+
**Invariant continuity**: Re-decide every invariant on AFTER, mapped through `stateMapping`. Any invariant that holds on BEFORE but fails on AFTER is a regression — the refactoring broke an existing guarantee. State predicates go through the same reachability search as S7; `leads-to`, `sequence`, `atomicity`, `budget` and `probability` are re-decided by the searches their own probes (A9-A13) use, so continuity agrees with the standalone verdict. A state reference that the mapping drops is reported as a mapped-state warning instead of silently changing the property.
|
|
225
|
+
|
|
226
|
+
**Complexity delta**: Count objectively:
|
|
227
|
+
|
|
228
|
+
- Number of states (BEFORE vs AFTER)
|
|
229
|
+
- Number of transitions
|
|
230
|
+
- Number of guard conditions
|
|
231
|
+
- Maximum path length from INIT to any terminal state
|
|
232
|
+
|
|
233
|
+
If the plan claims "simplification" but the numbers don't decrease, flag as UNSUBSTANTIATED CLAIM.
|
|
234
|
+
|
|
235
|
+
**Deadlock regression**: A refactoring that splits one state into two should not introduce a deadlock path that didn't exist before. Run S2 on AFTER and compare to BEFORE's deadlock report.
|
|
236
|
+
|
|
237
|
+
For before/after comparison, pass the earlier model as `beforeModel` and an optional `stateMapping`; the D1-D4 checks then run after the standard ones.
|
|
238
|
+
|
|
239
|
+
### Common Refactoring Bugs Caught by This Method
|
|
240
|
+
|
|
241
|
+
- **State split introduces dead edge**: Splitting ERROR into ERROR_TRANSIENT and ERROR_PERMANENT creates a new state with no transition from ERROR_TRANSIENT back to RECOVERING
|
|
242
|
+
- **Guard inversion**: Changing `retry < 3` to `retry <= 3` silently adds one more retry — the plan doesn't mention it
|
|
243
|
+
- **Orphaned event**: A transition removed in the refactoring was the only path that handled `power_lost` — the event is now silently ignored in some states
|
|
244
|
+
- **False simplification**: The plan claims "simplified error handling" but merges two states with different recovery paths into one, losing the distinction
|
|
245
|
+
|
|
246
|
+
## Manual Verification Mode
|
|
247
|
+
|
|
248
|
+
When no engine can run (air-gapped machine, locked-down host), execute each check manually. The agent performs the verification using its own reasoning — the methodology is identical, only the execution engine changes.
|
|
249
|
+
|
|
250
|
+
### Size Limit
|
|
251
|
+
|
|
252
|
+
Manual verification is reliable for state machines with **≤ 10 states and ≤ 30 transitions**. For larger machines, manual BFS and cycle detection become error-prone. If the machine exceeds this threshold and no engine can run, either:
|
|
253
|
+
|
|
254
|
+
- Decompose the machine into sub-machines and verify each independently, then check cross-machine contracts manually
|
|
255
|
+
- Flag the size limitation as a finding and recommend running the engine offline from the repository
|
|
256
|
+
|
|
257
|
+
### Prerequisites
|
|
258
|
+
|
|
259
|
+
- Transition table and model narrative have been extracted and confirmed with the user
|
|
260
|
+
- You have the full table in context (from Phase 2 extraction step)
|
|
261
|
+
- **Model validation**: when a host with an engine becomes available, run the extracted model there and compare its findings with the hand-checked ones.
|
|
262
|
+
|
|
263
|
+
### Phase 2a — Manual Structural Checks
|
|
264
|
+
|
|
265
|
+
**S1 Reachability**: Start from INIT. For each state, ask: "Is there any sequence of events from INIT that reaches this state?" Mark each state as reachable or unreachable. Unreachable states are dead code — flag them.
|
|
266
|
+
|
|
267
|
+
**S2 Deadlock**: For each non-terminal state, count outgoing transitions. If count = 0, flag as DEADLOCK. Terminal states are exempt.
|
|
268
|
+
|
|
269
|
+
**S3 Liveness**: Look for cycles in the transition graph that have no exit to a terminal/recovery state. Example: ERROR → RECOVERING → ERROR forms a cycle. If RECOVERING has a transition to IDLE, it's fine. If every transition from the cycle stays in the cycle with no terminal exit, flag as LIVELOCK.
|
|
270
|
+
|
|
271
|
+
**S4 Determinism**: For each state, group transitions by base event name (strip guard suffixes). If two transitions share the same base event and have different targets without different guard conditions, flag as AMBIGUOUS.
|
|
272
|
+
|
|
273
|
+
**S5 Event Completeness**: Collect all unique event names. For each non-terminal state, list which events have no defined transition. Flag any state missing handlers for events that other states define — these will be silently ignored at runtime.
|
|
274
|
+
|
|
275
|
+
**S6 Guard Completeness**: For each transition with a guard (e.g., `timeout (retry<3)` → RETRY), check if the complementary branch is defined (e.g., `timeout (retry≥3)` → FATAL). If only one branch exists with no else/default, flag as INCOMPLETE GUARD.
|
|
276
|
+
|
|
277
|
+
**S7 Invariants**: For each "always/never/guaranteed" claim in the plan, trace every reachable path and verify the claim holds. If you find a counter-example path, quote the plan claim, show the violating path, flag as INVARIANT VIOLATION.
|
|
278
|
+
|
|
279
|
+
### Phase 2b — Manual Adversarial Probes
|
|
280
|
+
|
|
281
|
+
**A1 Unexpected Event**: For each state, list all events defined ANYWHERE in the machine that this state does NOT handle. For each unhandled (state, event) pair, assess: is this event physically possible in this state? If yes, what happens? Silence = undefined behavior. Flag if the plan doesn't document the behavior.
|
|
282
|
+
|
|
283
|
+
**A2 Race Interleaving**: Identify pairs of events that could arrive in the same tick (e.g., timer expiry + message arrival). Trace both orders through the machine. If the final state differs, flag as RACE — the outcome depends on event ordering.
|
|
284
|
+
|
|
285
|
+
**A3 Order Permutation**: Take 3-5 key events and trace all permutations. If different orders lead to different terminal states AND the plan claims independence, flag as ORDER DEPENDENT.
|
|
286
|
+
|
|
287
|
+
**A4 Pair Symmetry**: Identify all `lock/unlock`, `start/stop`, `alloc/free` pairs. Check every path: if a path includes `lock` without a subsequent `unlock`, or `alloc` without `free`, flag as ASYMMETRIC. A quick heuristic: if a transition name contains "lock" (or "start", "alloc"), check that every path from its target state eventually hits the corresponding "unlock" before a terminal state.
|
|
288
|
+
|
|
289
|
+
**A5 Boundary Blast**: For each counter variable mentioned in guards, test values: 0, 1, max-1, max, max+1. Flag any that would cause overflow or undefined behavior. For timestamps, check if `elapsed = now - start` handles wraparound correctly.
|
|
290
|
+
|
|
291
|
+
**A6 Resource Injection**: For each state that appears to allocate (names containing "alloc", "init", "start", "open", "connect", "begin"), check if there is a recovery/error path if the allocation fails. If no recovery exists, flag as RESOURCE VULNERABLE.
|
|
292
|
+
|
|
293
|
+
**A7 Minimal Counter-Example**: For each invariant that failed, find the event sequence that violates it. This is the most useful output — it gives the plan author an exact repro. The searches for state predicates, `sequence`, `atomicity` and `budget` are breadth-first, so their witness is the shortest one; the `leads-to` walk and the `probability` bound report what they found without claiming minimality.
|
|
294
|
+
|
|
295
|
+
### Finding Format
|
|
296
|
+
|
|
297
|
+
Every finding has the same shape, in a report body or quoted in prose:
|
|
298
|
+
|
|
299
|
+
```text
|
|
300
|
+
[CHECK] S1 Reachability
|
|
301
|
+
RESULT: PASS — All 7 states reachable from INIT
|
|
302
|
+
|
|
303
|
+
[CHECK] S3 Liveness
|
|
304
|
+
RESULT: FAIL — Absorbing cycle: ERROR → RECOVERING → ERROR
|
|
305
|
+
EVIDENCE: RECOVERING has only one transition (→ ERROR after cooldown).
|
|
306
|
+
No path from RECOVERING back to IDLE exists.
|
|
307
|
+
SEVERITY: Error — machine can never recover from ERROR state.
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Manual verification takes longer but produces identical-quality findings. The key advantage: it requires zero dependencies and works on any platform.
|
|
311
|
+
|
|
312
|
+
## Method provenance
|
|
313
|
+
|
|
314
|
+
Where each check comes from, and - just as important - where it does not.
|
|
315
|
+
|
|
316
|
+
The distinction below is the one to keep: a **published method** has a definition and a body
|
|
317
|
+
of work behind it, so its result means what that work says it means. An **engineering
|
|
318
|
+
convention** is this plugin's own rule, chosen because it catches something real; nothing
|
|
319
|
+
outside this repository defines it, and it may change without the literature moving. Neither
|
|
320
|
+
is worse, but a reader has to know which one they are holding.
|
|
321
|
+
|
|
322
|
+
| Check | Method | Provenance |
|
|
323
|
+
|---|---|---|
|
|
324
|
+
| S1, S2, S3 | Explicit-state reachability analysis: enumerate the reachable state space, then ask whether a state, a terminal trap, or a closed cycle exists | Published. Clarke & Emerson, *Design and Synthesis of Synchronization Skeletons Using Branching-Time Temporal Logic*, LNCS 131 (1981); Clarke, Grumberg & Peled, *Model Checking*, MIT Press (1999) |
|
|
325
|
+
| A2, A3 | Interleaving semantics, with order permutation as the practical probe for it; the sampling beyond the permutation bound is deliberate weakening of partial-order reduction | Published, with a caveat: Godefroid, *Partial-Order Methods for the Verification of Concurrent Systems*, LNCS 1032 (1996); Holzmann, *The SPIN Model Checker*, Addison-Wesley (2003) |
|
|
326
|
+
| A7 | Breadth-first shortest counterexample over the reachable graph | Published. Standard in explicit-state model checking (above); the BFS-as-minimal-witness idea is in the same tradition |
|
|
327
|
+
| A13 | Discrete-time Markov chain reachability by value iteration | Published. Baier & Katoen, *Principles of Model Checking*, MIT Press (2008), ch. 10 |
|
|
328
|
+
| `model_export` | Translation into the input language of a published checker, so a stronger engine can decide what this one approximates | UPPAAL: Behrmann, David & Larsen, *A Tutorial on UPPAAL*, SFM 2004. PRISM: Kwiatkowska, Norman & Parker, *PRISM 4.0: Verification of Probabilistic Real-Time Systems*, CAV 2011. TLA+: Lamport, *Specifying Systems*, Addison-Wesley (2002). SPIN: Holzmann (2003), above |
|
|
329
|
+
| A5 | Boundary value analysis: 0, 1, max-1, max, max+1 for each counter | Published. Myers, *The Art of Software Testing* (1979) - the technique is textbook; applying it to a model's declared bounds rather than to code is this plugin's shape |
|
|
330
|
+
| D1-D4 | Behaviour preservation across a refactor, decided by re-running the structural and invariant checks on the AFTER model through a state mapping | **Convention.** Regression checking of this kind has no canonical formulation for state machines. The nearest published ideas are regression test selection and metamorphic testing (see the next row), but the D1-D4 semantics are defined here, in this repository, and nowhere else |
|
|
331
|
+
| A4, A8 | Paired-operation symmetry and idempotent replay | **Convention**, in the sense that the *questions* are standard engineering concerns (a lock without an unlock, a retry that is not idempotent) while the *decision procedure* - search for a path that acquires without releasing; apply each retryable event twice - is this plugin's own |
|
|
332
|
+
| A6 | Resource-failure injection: what happens when malloc returns NULL, a queue is full, a pool is exhausted | **Convention.** The concern is fault injection / FMEA in spirit; the model-level check is ours |
|
|
333
|
+
| A14 | Deadlines over a declared discrete tick clock | **Convention.** Discrete-time clocks appear in timed-automata work (UPPAAL, above), but `tickEvents` + `maxTicks` is this repository's notation for them, not a published one |
|
|
334
|
+
| A12 | Path cost against a declared budget | **Convention.** Weighted shortest path is textbook; "this transition costs 1 unless the model says otherwise, and a positive-cost reachable cycle means unbounded cost" is a rule stated here |
|
|
335
|
+
| C1, C2 | Composition of machines: a reachable node where no machine can advance, and a rendezvous that can never fire | **Convention.** Asynchronous product construction is standard; the two specific verdicts and their handshake semantics are defined in this plugin |
|
|
336
|
+
| `model_verify` as a whole | Bounded explicit-state search with the model schema closed by construction | Same provenance as S1-S3, plus one design decision worth naming: the schema rejects unknown keys rather than ignoring them, because a mistyped guard variable reads as an always-false guard. That is a choice about soundness, not a published result |
|
|
337
|
+
|
|
338
|
+
Two notes for a reader deciding how much weight to put on a finding.
|
|
339
|
+
|
|
340
|
+
**The bound is part of the claim.** `maxStates` (default 10000) decides how much of the state
|
|
341
|
+
space was explored, and truncation is reported rather than hidden. A "pass" from a truncated
|
|
342
|
+
search is a statement about the part that was walked, which is why the report carries
|
|
343
|
+
`summary.truncated` and why `*_UNDECIDED` codes exist: absence of a counterexample over a
|
|
344
|
+
bounded walk is not a proof of the property.
|
|
345
|
+
|
|
346
|
+
**This is not the only way to decide these properties.** The plugin takes the explicit-state
|
|
347
|
+
route because it needs to run inside a session with no external toolchain, and because a
|
|
348
|
+
shortest counterexample in the report is what makes a finding actionable. Section
|
|
349
|
+
"What this method does not implement" below names the classical alternatives and why they are
|
|
350
|
+
not here.
|
|
351
|
+
|
|
352
|
+
## What this method does not implement
|
|
353
|
+
|
|
354
|
+
Every entry is a real technique with a body of work behind it. None is present in this plugin.
|
|
355
|
+
Where the plugin has a workaround, it is named; where it does not, the honest answer is that
|
|
356
|
+
the property is not decided here.
|
|
357
|
+
|
|
358
|
+
| Classical method | What it decides that this does not | What this plugin does instead |
|
|
359
|
+
|---|---|---|
|
|
360
|
+
| Symbolic model checking (BDDs, McMillan 1993) | Systems whose state space is far too large to enumerate. This plugin enumerates and truncates | Nothing. A model past `maxStates` is reported truncated, not verified |
|
|
361
|
+
| Bounded model checking over SAT/SMT (Biere et al., 1999) | Bounded-depth properties, and it scales much further than enumeration | Nothing. `model_export` to a checker that does this is the route out |
|
|
362
|
+
| CTL / LTL model checking (Clarke & Emerson 1981; Pnueli 1977) | Arbitrary temporal formulas, including nested and fairness-constrained ones. This plugin decides a fixed set of property shapes | The eight invariant kinds are the way to state a property. Anything they cannot express is not checked |
|
|
363
|
+
| k-induction and IC3/PDR | Unbounded proofs over infinite or very large state spaces | Nothing. Guarantees are relative to the modelled bounds |
|
|
364
|
+
| Abstraction interpretation (Cousot & Cousot, 1977) | Properties of the program the model came from, soundly over all inputs | Nothing at all: this plugin reasons about the *model*, and the model's fidelity to the code is the extractor's responsibility |
|
|
365
|
+
| Theorem proving (Coq, Isabelle, KeY, KIV) | Unbounded arithmetic and data properties, with a proof object | `model_export` to TLA+ covers some of this ground with TLC as the backend |
|
|
366
|
+
| Timed automata / real-time model checking (Alur & Dill 1994; UPPAAL) | Continuous-time deadlines and clock constraints | A14 over a declared discrete tick clock, and export to UPPAAL. The model has no continuous time |
|
|
367
|
+
| Probabilistic model checking beyond reachability (PCTL, MDPs, CSL) | Expected reward, steady-state probability, strategies under nondeterminism | A13 decides "P(ever reaching the target) vs a bound" only. PRISM export is the route to the rest |
|
|
368
|
+
| Symmetry reduction | Collapsing symmetric state spaces to make enumeration feasible | Nothing. A3's permutation sampling is a probe for order dependence, not a reduction |
|
|
369
|
+
| Compositional / assume-guarantee reasoning | Deciding components separately and combining the results | C1/C2 decide two properties of a whole composition, by enumerating the product |
|
|
370
|
+
|
|
371
|
+
## Structural review: what graph theory already answers
|
|
372
|
+
|
|
373
|
+
The structure review (`UML020`-`UML026`) is graph algorithms over a dependency graph: isolated
|
|
374
|
+
nodes, dangling endpoints, cycles, disallowed edges, layer violations, missing required edges.
|
|
375
|
+
That places it firmly inside graph theory, and graph theory has a good deal more to say about
|
|
376
|
+
dependency graphs than this plugin asks it.
|
|
377
|
+
|
|
378
|
+
| Question about a dependency graph | Graph-theoretic formulation | In this plugin? |
|
|
379
|
+
|---|---|---|
|
|
380
|
+
| Is anything unreachable / isolated? | Connectivity, and the degree-0 vertices | Yes - `UML020` |
|
|
381
|
+
| Is there a cycle? | Cycle detection, with the shortest one named | Yes - `UML022` |
|
|
382
|
+
| Does an edge violate a declared dependency rule? | Edge legality against a matrix, and layered DAG constraints | Yes - `UML023`, `UML024`, `UML025` |
|
|
383
|
+
| How tangled is it, in one number? | Cyclomatic complexity (McCabe, 1976) as `E - V + 2P` over the dependency graph | No |
|
|
384
|
+
| What is the smallest set of edges to remove to make it acyclic? | **Minimum feedback arc set.** NP-hard (Garey & Johnson, *Computers and Intractability*, 1979); approximation and fixed-parameter algorithms exist | No. This is the difference between "a cycle exists" and "here is how much coupling you must break" |
|
|
385
|
+
| How should it be partitioned into modules? | Community detection / modularity (Newman & Girvan, 2004), and spectral clustering via the graph Laplacian (Fiedler, 1973) | No. The plugin checks a declared matrix; it does not propose a partition |
|
|
386
|
+
| Which edges are structurally most load-bearing? | Betweenness centrality (Freeman, 1977), and the `k`-core decomposition for layering | No |
|
|
387
|
+
| Are there dependency layers at all, or is it one blob? | Topological ordering, and DAG-ness of the condensed graph | Partly - `UML024` checks a layer matrix the caller declares, rather than deriving layers |
|
|
388
|
+
|
|
389
|
+
None of the five "No" rows is a gap in what the review *claims*: it says it audits the graph
|
|
390
|
+
against a declared matrix, and it does. They are the answer to "what else could be computed
|
|
391
|
+
here", and the feedback arc set row is the one most likely to earn its place, because
|
|
392
|
+
"break these two edges and the architecture becomes acyclic" is actionable in a way that
|
|
393
|
+
"there is a cycle" is not.
|
|
394
|
+
|
|
395
|
+
**On topology specifically.** The user-facing question that prompted this section was whether
|
|
396
|
+
topological methods apply. The honest answer: the dependency analysis here is *graph*-theoretic
|
|
397
|
+
(combinatorial), and that is the established line for architecture review. Genuinely
|
|
398
|
+
*topological* machinery - homology, persistent homology over a filtration, Betti numbers -
|
|
399
|
+
is used on geometric and scientific data, and it does appear in netlist and circuit analysis.
|
|
400
|
+
It is not an established technique for reviewing a UML or dependency diagram, and this
|
|
401
|
+
repository has not evaluated it. Treating a dependency graph as a simplicial complex would
|
|
402
|
+
need a filtration that means something in software terms before any of it could be reported
|
|
403
|
+
as a finding; nobody here has defined one, and inventing one to fill a section would be the
|
|
404
|
+
opposite of what this document is for.
|
|
405
|
+
|
|
406
|
+
## Integration with the Review Pipeline
|
|
407
|
+
|
|
408
|
+
```text
|
|
409
|
+
1. Load model-everything skill
|
|
410
|
+
2. Read plan → Phase 1 (enumerate claims)
|
|
411
|
+
3. Detect behavioral claims → trigger logic-primitive escalation
|
|
412
|
+
4. Load this guide
|
|
413
|
+
5. Run the checks: the native tool when the host has it, otherwise Manual Verification Mode (see above), step by step
|
|
414
|
+
7. Extract model → show transition table → GET USER CONFIRMATION
|
|
415
|
+
8. Run Phase 2a (8 structural primitives) → log results
|
|
416
|
+
9. Run Phase 2b (14 adversarial probes) → log results
|
|
417
|
+
10. Classify counter-examples (true positive / model error / acceptable risk)
|
|
418
|
+
11. Feed confirmed findings into Phase 3 (gap analysis)
|
|
419
|
+
12. Include in Phase 5 (structured output)
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Never skip the check. A verified model based on wrong extraction is worse than no verification — it creates false confidence.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: model-everything-datamodel
|
|
3
|
+
description: "Use when reviewing a schema, a migration or a data guarantee: entities, fields, constraints, uniqueness, referential integrity, data invariants, 'no orphan rows', and before/after equivalence. It runs the data model as a model: key and domain checks, migration coverage, copy consistency, rollback symmetry, and whether a before/after pair actually preserved the data. State machines: model-everything; module dependencies: model-everything-structure; diagrams: model-everything-uml."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Model Everything — Data
|
|
7
|
+
|
|
8
|
+
An unverified data model fails later. Model the schema and the migration, run them, and it becomes clear. Check every data claim before you act on it.
|
|
9
|
+
|
|
10
|
+
## Methodology
|
|
11
|
+
|
|
12
|
+
### Phase 1: Enumerate Data Claims
|
|
13
|
+
|
|
14
|
+
Read the document fully. Extract every verifiable data-model claim:
|
|
15
|
+
|
|
16
|
+
- Entity/table/collection names and fields
|
|
17
|
+
- Field types, nullability, defaults, unique constraints
|
|
18
|
+
- Relationships / foreign keys / referential integrity
|
|
19
|
+
- Data invariants ("always", "never", "must", "guaranteed")
|
|
20
|
+
- Migration claims ("rename field", "drop column", "backfill", "non-breaking")
|
|
21
|
+
- Copy/migration mappings ("source.a → target.x")
|
|
22
|
+
|
|
23
|
+
### Phase 2: Verify Against the Model or Codebase
|
|
24
|
+
|
|
25
|
+
For each claim, run the relevant verification:
|
|
26
|
+
|
|
27
|
+
- **Entity/field names**: compare against actual schema, API contract, or code types
|
|
28
|
+
- **Constraints**: check declared `required`, `unique`, `nullable`, `min/max`, `enum`
|
|
29
|
+
- **Relationships**: check target entity/field exists and `onDelete` is coherent
|
|
30
|
+
- **Migration**: build BEFORE/AFTER DataModelV1 and check migration coverage
|
|
31
|
+
|
|
32
|
+
### Phase 2 Trigger: Escalate to Data Model Verification?
|
|
33
|
+
|
|
34
|
+
Escalate immediately if the document contains ANY of:
|
|
35
|
+
|
|
36
|
+
- Schema/migration changes: added/removed/renamed fields, entities, constraints
|
|
37
|
+
- Data invariants: "all rows must", "counts must match", "no orphans", "never null"
|
|
38
|
+
- Copy/migration mappings: source-to-target field maps
|
|
39
|
+
- Before/after data-model equivalence claims: "non-breaking", "behavior preserved"
|
|
40
|
+
- Refactoring that changes field types, nullability, uniqueness, or relationships
|
|
41
|
+
|
|
42
|
+
## Data Model Verification Pipeline
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
Document claims → Extract DataModelV1 → Runtime check:
|
|
46
|
+
├── DSH + `model_datamodel_verify` tool available → build DataModelV1 → call tool → structured report
|
|
47
|
+
└── No engine available → Manual Verification Mode (references/data-model-guide.md)
|
|
48
|
+
|
|
49
|
+
Refactoring variant:
|
|
50
|
+
Extract BEFORE DataModelV1 + AFTER DataModelV1
|
|
51
|
+
→ Run pipeline on AFTER model (DS/DA checks)
|
|
52
|
+
→ Compare BEFORE vs AFTER (DD1-DD4)
|
|
53
|
+
→ Flag any invariant that held in BEFORE but fails in AFTER
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The **DataModelV1 shape** is in [`references/data-model-schema.md`](references/data-model-schema.md): entities, fields, keys, relationships, invariants, boundary checks, and the optional before/mapping/copy/migration/backup blocks. Those field names are the tool contract. A hand-written model that disagrees with them is rejected, not guessed at.
|
|
57
|
+
|
|
58
|
+
## Checks
|
|
59
|
+
|
|
60
|
+
### DS — Data structure
|
|
61
|
+
|
|
62
|
+
| # | Check | Severity if Violated |
|
|
63
|
+
|:--:|-------|:---:|
|
|
64
|
+
| DS1 | Schema well-formedness | Error |
|
|
65
|
+
| DS2 | Required-field completeness | Error/Warning |
|
|
66
|
+
| DS3 | Relationship integrity | Error |
|
|
67
|
+
| DS4 | Type/nullability consistency | Error/Warning |
|
|
68
|
+
|
|
69
|
+
### DA — Data adversarial probes
|
|
70
|
+
|
|
71
|
+
| # | Check | Severity if Violated |
|
|
72
|
+
|:--:|-------|:---:|
|
|
73
|
+
| DA1 | Null/empty injection | Error |
|
|
74
|
+
| DA2 | Boundary blast | Warning |
|
|
75
|
+
| DA3 | Uniqueness violation | Error/Warning |
|
|
76
|
+
| DA4 | Referential integrity violation | Warning |
|
|
77
|
+
| DA5 | Migration coverage | Error |
|
|
78
|
+
| DA6 | Copy consistency | Error |
|
|
79
|
+
| DA7 | Rollback/backup symmetry | Warning |
|
|
80
|
+
| DA8 | Idempotent constraints | Error/Warning |
|
|
81
|
+
| DA9 | Data monotonic | Error/Warning |
|
|
82
|
+
| DA10 | Data sequence | Error |
|
|
83
|
+
| DA11 | Data leads-to | Error/Warning |
|
|
84
|
+
| DA12 | Data atomicity | Error/Warning |
|
|
85
|
+
|
|
86
|
+
### DD — Before/after data regression
|
|
87
|
+
|
|
88
|
+
| # | Check | Severity if Violated |
|
|
89
|
+
|:--:|-------|:---:|
|
|
90
|
+
| DD1 | Data behavior preservation | Error |
|
|
91
|
+
| DD2 | Data invariant continuity | Error |
|
|
92
|
+
| DD3 | Delta summary | Warning |
|
|
93
|
+
| DD4 | Breaking change regression | Error/Warning |
|
|
94
|
+
|
|
95
|
+
Every `#` in these tables is a report field, not a name. Write what the check found for the
|
|
96
|
+
reader (「回滚与备份不对称」), in their language; keep the id for a report field quoted
|
|
97
|
+
verbatim, a baseline diff or a test name. The full rule is under "Writing the Answer" in the
|
|
98
|
+
`model-everything` skill.
|
|
99
|
+
|
|
100
|
+
## Extraction Rule
|
|
101
|
+
|
|
102
|
+
Before writing any verification code, output a data-model table:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
Entity | Field | Type | Required | Unique | Nullable | Notes
|
|
106
|
+
---------|------------|---------|----------|--------|----------|-------
|
|
107
|
+
User | id | uuid | yes | yes | no | PK
|
|
108
|
+
User | email | string | yes | yes | no |
|
|
109
|
+
Order | userId | uuid | yes | no | no | FK -> User.id
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Show this table to the user and ask for confirmation before generating the harness. The #1 failure mode is extracting the wrong data model.
|
|
113
|
+
|
|
114
|
+
**Exception**: If the user has already told you to proceed without confirmation in this session, do NOT call `ask_user_question`. Instead: (a) cite evidence for every extracted entity/field/constraint, (b) round-trip the filled model back into a table and compare it with the extraction table, and (c) mark the report `UNCONFIRMED`.
|
|
115
|
+
|
|
116
|
+
## When NOT to Escalate
|
|
117
|
+
|
|
118
|
+
Skip data-model verification when:
|
|
119
|
+
|
|
120
|
+
- The document makes no data-behavioral claims (pure API listings, file paths, numeric constants)
|
|
121
|
+
- The change is purely cosmetic (display names, comments)
|
|
122
|
+
- The data model is trivial (single entity, no constraints, no migration)
|
|
123
|
+
- The claim is purely structural (file paths, type names) — Phase 2 grep verification is sufficient
|
|
124
|
+
|
|
125
|
+
## Non-Goals
|
|
126
|
+
|
|
127
|
+
- Not a SQL migration executor (Flyway/Liquibase/Atlas territory)
|
|
128
|
+
- Not a runtime data-quality platform (Great Expectations/Soda territory)
|
|
129
|
+
- Not a general array/object/file-content modeling engine
|
|
130
|
+
- Not a replacement for Atlas/Squawk/Buf/Oasdiff — it is the design-time plan verifier that sits before them
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Data Model Manual Verification Mode
|
|
2
|
+
|
|
3
|
+
Use this when `model_datamodel_verify` is not registered in this deployment. It lays out the DS/DA/DD checks as a structured checklist.
|
|
4
|
+
|
|
5
|
+
## 1. Extract the DataModelV1 table
|
|
6
|
+
|
|
7
|
+
For every entity, list fields, types, nullability, required, unique, primary key, and relationships.
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Entity | Field | Type | Required | Unique | Nullable | Notes
|
|
11
|
+
---------|------------|---------|----------|--------|----------|-------
|
|
12
|
+
User | id | uuid | yes | yes | no | PK
|
|
13
|
+
User | email | string | yes | yes | no |
|
|
14
|
+
Order | userId | uuid | yes | no | no | FK -> User.id
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 2. Structural checklist (DS1-DS4)
|
|
18
|
+
|
|
19
|
+
- [ ] Entity names are unique.
|
|
20
|
+
- [ ] Field names are unique within each entity.
|
|
21
|
+
- [ ] Primary key and unique key fields exist.
|
|
22
|
+
- [ ] Required fields are not nullable.
|
|
23
|
+
- [ ] Relationship targets exist.
|
|
24
|
+
- [ ] `onDelete` values are valid.
|
|
25
|
+
- [ ] `min <= max`, `minLength <= maxLength`.
|
|
26
|
+
|
|
27
|
+
## 3. Adversarial checklist (DA1-DA7)
|
|
28
|
+
|
|
29
|
+
- [ ] Null cannot be injected into required fields.
|
|
30
|
+
- [ ] Empty strings are rejected for required string fields.
|
|
31
|
+
- [ ] Boundary values outside min/max are rejected.
|
|
32
|
+
- [ ] Unique/primary key fields are not nullable.
|
|
33
|
+
- [ ] Referenced fields have compatible types.
|
|
34
|
+
- [ ] Every removed/renamed field has a migration mapping.
|
|
35
|
+
- [ ] Every required target field in a copy pair is mapped.
|
|
36
|
+
- [ ] Every copy pair has a matching backup/restore pair.
|
|
37
|
+
- [ ] Every `idempotent-copy` invariant has a matching copy pair.
|
|
38
|
+
- [ ] Every `idempotent-migration` invariant has a matching migration mapping; split/merge/drop are reviewed as non-idempotent.
|
|
39
|
+
- [ ] Monotonic fields only move in the declared direction.
|
|
40
|
+
- [ ] Sequence steps reference existing copy/migration ids.
|
|
41
|
+
- [ ] Leads-to from/to values exist in enum/status fields.
|
|
42
|
+
- [ ] Atomic steps exist, avoid non-atomic transforms, and have backup/restore coverage where applicable.
|
|
43
|
+
|
|
44
|
+
## 4. Before/after checklist (DD1-DD4)
|
|
45
|
+
|
|
46
|
+
- [ ] Every BEFORE required field still exists in AFTER or has a migration mapping.
|
|
47
|
+
- [ ] BEFORE data invariants still hold in AFTER.
|
|
48
|
+
- [ ] Added/removed entities, fields, relationships are listed.
|
|
49
|
+
- [ ] No new breaking changes: removed required field, optional→required, nullable→non-null, type narrowing, added unique constraint.
|
|
50
|
+
|
|
51
|
+
## 5. Where each class of check comes from
|
|
52
|
+
|
|
53
|
+
The distinction matters for how much weight a finding carries. A **published method** has a
|
|
54
|
+
definition and a body of work behind it, so its result means what that work says it means. A
|
|
55
|
+
**house convention** is this plugin's own rule: the concern is standard, the decision procedure
|
|
56
|
+
is ours, and nothing outside this repository defines it.
|
|
57
|
+
|
|
58
|
+
| Checks | Method | Provenance |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| DS1, DS2 | Key and name uniqueness: a relation's attributes are named, and a candidate key identifies a tuple | Published. Codd, *A Relational Model of Data for Large Shared Data Banks*, CACM 13(6), 1970 |
|
|
61
|
+
| DS3, DA1, DA2 | Domain and null constraints: a required attribute admits no null, and a declared domain excludes values outside it | Published. Codd (1970); Date, *An Introduction to Database Systems* - the constraint taxonomy (`NOT NULL`, `CHECK`, domain) is standard SQL practice |
|
|
62
|
+
| DS4, DA4 | SQL's three-valued logic: a column that is part of a unique or primary key cannot be null, because two nulls are not equal and the uniqueness claim becomes undecidable | Published. The SQL standard's treatment of null in `UNIQUE` and `PRIMARY KEY`; the practical rule is standard schema-review doctrine |
|
|
63
|
+
| DA3, DA5 | Referential integrity and type compatibility of a foreign key with the attribute it references | Published. Codd, *Extending the Database Relational Model to Capture More Meaning*, ACM TODS 1979 (the referential-integrity rule); every SQL implementation states it |
|
|
64
|
+
| DA6, DA7, DA10-DA13 | Migration completeness and idempotence: every removed or renamed field has a mapping, and applying a copy twice changes nothing | **Convention**, in the shape this plugin states it. The concerns are standard schema-migration practice (Fowler's evolutionary database design; the expand/contract pattern); the specific requirement - a mapping per removed field, an invariant per `idempotent-copy` - is defined here |
|
|
65
|
+
| DD1-DD4 | Behaviour preservation across a schema change, decided by re-running the structural and invariant checks on AFTER | **Convention.** There is no canonical formulation for "this migration preserves the invariants". The nearest published ideas are regression test selection and metamorphic testing, but the DD semantics are this repository's |
|
|
66
|
+
| `boundaryChecks`, `migrationMappings`, `backupPairs` | Fields the model declares so the checks above have something to hold it to | **Convention.** The schema is this plugin's; nothing else reads it |
|
|
67
|
+
|
|
68
|
+
Two consequences worth stating plainly. A model that declares no `migrationMappings` has no
|
|
69
|
+
migration completeness to check - that is a `skip`, not a pass. And "the migration preserves
|
|
70
|
+
every invariant" is a claim about the models, not about the database: this plugin compares
|
|
71
|
+
BEFORE and AFTER as declared, and cannot see data that neither model mentions.
|
|
72
|
+
|
|
73
|
+
## 6. Output
|
|
74
|
+
|
|
75
|
+
Append a summary to the plan file:
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
## Data Model Verification
|
|
79
|
+
|
|
80
|
+
- **Depth**: LIGHTWEIGHT / STANDARD / ESCALATED
|
|
81
|
+
- **Checks**: [list DS/DA/DD checks performed]
|
|
82
|
+
- **Findings**: [list]
|
|
83
|
+
- **Confirmed**: yes / UNCONFIRMED
|
|
84
|
+
```
|