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.
Files changed (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.en-US.md +332 -0
  3. package/README.md +332 -3
  4. package/cordis.patch.yml +20 -0
  5. package/examples/README.md +48 -0
  6. package/examples/control-dispatcher.json +113 -0
  7. package/examples/control-dispatcher.overbudget.json +113 -0
  8. package/examples/ecommerce-data-model.json +185 -0
  9. package/examples/order-state-machine.after.json +116 -0
  10. package/examples/order-state-machine.before.json +101 -0
  11. package/examples/user-migration.after.json +29 -0
  12. package/examples/user-migration.before.json +29 -0
  13. package/gate/locale/en.json +6 -0
  14. package/gate/locale/zh.json +6 -0
  15. package/gate/package.json +5 -0
  16. package/lib/baseline.js +249 -0
  17. package/lib/compose-tool.js +80 -0
  18. package/lib/concurrency-tool.js +40 -0
  19. package/lib/concurrency.js +206 -0
  20. package/lib/data-engine.js +1141 -0
  21. package/lib/data-tool.js +87 -0
  22. package/lib/design-engine.js +1149 -0
  23. package/lib/design-tool.js +63 -0
  24. package/lib/engine.js +4343 -0
  25. package/lib/export-tool.js +78 -0
  26. package/lib/exporters.js +434 -0
  27. package/lib/gate.js +274 -0
  28. package/lib/granularity.js +237 -0
  29. package/lib/index.js +237 -0
  30. package/lib/json-value.js +18 -0
  31. package/lib/model-file.js +48 -0
  32. package/lib/option-shape.js +62 -0
  33. package/lib/report-diff-tool.js +63 -0
  34. package/lib/report-view.js +433 -0
  35. package/lib/structure-tool.js +91 -0
  36. package/lib/structure.js +711 -0
  37. package/lib/tool.js +94 -0
  38. package/lib/types/baseline.d.ts +65 -0
  39. package/lib/types/compose-tool.d.ts +7 -0
  40. package/lib/types/concurrency-tool.d.ts +8 -0
  41. package/lib/types/concurrency.d.ts +37 -0
  42. package/lib/types/data-engine.d.ts +211 -0
  43. package/lib/types/data-tool.d.ts +10 -0
  44. package/lib/types/design-engine.d.ts +215 -0
  45. package/lib/types/design-tool.d.ts +11 -0
  46. package/lib/types/engine.d.ts +494 -0
  47. package/lib/types/export-tool.d.ts +7 -0
  48. package/lib/types/exporters.d.ts +37 -0
  49. package/lib/types/gate.d.ts +91 -0
  50. package/lib/types/granularity.d.ts +106 -0
  51. package/lib/types/index.d.ts +45 -0
  52. package/lib/types/json-value.d.ts +21 -0
  53. package/lib/types/model-file.d.ts +7 -0
  54. package/lib/types/option-shape.d.ts +22 -0
  55. package/lib/types/report-diff-tool.d.ts +8 -0
  56. package/lib/types/report-view.d.ts +50 -0
  57. package/lib/types/structure-tool.d.ts +10 -0
  58. package/lib/types/structure.d.ts +152 -0
  59. package/lib/types/tool.d.ts +11 -0
  60. package/lib/types/uml-communication.d.ts +109 -0
  61. package/lib/types/uml-composite.d.ts +107 -0
  62. package/lib/types/uml-interaction-overview.d.ts +91 -0
  63. package/lib/types/uml-profile.d.ts +112 -0
  64. package/lib/types/uml-structure.d.ts +53 -0
  65. package/lib/types/uml-syntax.d.ts +296 -0
  66. package/lib/types/uml-timing.d.ts +152 -0
  67. package/lib/types/uml-tool.d.ts +12 -0
  68. package/lib/types/uml-usecase.d.ts +58 -0
  69. package/lib/types/uml.d.ts +303 -0
  70. package/lib/uml-communication.js +353 -0
  71. package/lib/uml-composite.js +442 -0
  72. package/lib/uml-interaction-overview.js +277 -0
  73. package/lib/uml-profile.js +373 -0
  74. package/lib/uml-structure.js +306 -0
  75. package/lib/uml-syntax.js +545 -0
  76. package/lib/uml-timing.js +974 -0
  77. package/lib/uml-tool.js +213 -0
  78. package/lib/uml-usecase.js +532 -0
  79. package/lib/uml.js +2110 -0
  80. package/locale/en.json +6 -0
  81. package/locale/zh.json +6 -0
  82. package/package.json +128 -6
  83. package/skills/model-everything/SKILL.md +450 -0
  84. package/skills/model-everything/references/dsh-model-schema.md +437 -0
  85. package/skills/model-everything/references/gap-routing-guide.md +42 -0
  86. package/skills/model-everything/references/hash-spec.md +152 -0
  87. package/skills/model-everything/references/logic-verification-guide.md +422 -0
  88. package/skills/model-everything-datamodel/SKILL.md +130 -0
  89. package/skills/model-everything-datamodel/references/data-model-guide.md +84 -0
  90. package/skills/model-everything-datamodel/references/data-model-schema.md +128 -0
  91. package/skills/model-everything-design/SKILL.md +115 -0
  92. package/skills/model-everything-interleaving/SKILL.md +63 -0
  93. package/skills/model-everything-interleaving/SKILL.zh-CN.md +60 -0
  94. package/skills/model-everything-interleaving/references/concurrency-risk-guide.md +63 -0
  95. package/skills/model-everything-report-reading/SKILL.md +137 -0
  96. package/skills/model-everything-report-reading/references/reading-a-report.md +166 -0
  97. package/skills/model-everything-report-reading/references/reading-a-report.mmd +59 -0
  98. package/skills/model-everything-structure/SKILL.md +96 -0
  99. package/skills/model-everything-structure/references/structure-review-guide.md +201 -0
  100. package/skills/model-everything-uml/SKILL.md +60 -0
  101. package/skills/model-everything-uml/references/uml-modeling-guide.md +551 -0
  102. package/src/baseline.ts +288 -0
  103. package/src/compose-tool.ts +82 -0
  104. package/src/concurrency-tool.ts +44 -0
  105. package/src/concurrency.ts +254 -0
  106. package/src/data-engine.ts +1208 -0
  107. package/src/data-tool.ts +91 -0
  108. package/src/design-engine.ts +1263 -0
  109. package/src/design-tool.ts +68 -0
  110. package/src/engine.ts +4564 -0
  111. package/src/export-tool.ts +81 -0
  112. package/src/exporters.ts +399 -0
  113. package/src/gate.ts +330 -0
  114. package/src/granularity.ts +312 -0
  115. package/src/index.ts +289 -0
  116. package/src/json-value.ts +20 -0
  117. package/src/model-file.ts +49 -0
  118. package/src/option-shape.ts +64 -0
  119. package/src/report-diff-tool.ts +67 -0
  120. package/src/report-view.ts +483 -0
  121. package/src/structure-tool.ts +93 -0
  122. package/src/structure.ts +786 -0
  123. package/src/tool.ts +103 -0
  124. package/src/uml-communication.ts +428 -0
  125. package/src/uml-composite.ts +520 -0
  126. package/src/uml-interaction-overview.ts +321 -0
  127. package/src/uml-profile.ts +439 -0
  128. package/src/uml-structure.ts +317 -0
  129. package/src/uml-syntax.ts +764 -0
  130. package/src/uml-timing.ts +1106 -0
  131. package/src/uml-tool.ts +230 -0
  132. package/src/uml-usecase.ts +566 -0
  133. 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
+ ```