v0.2.47 — sdivi-rust v0.2.47 — Eleven new pattern categories and the multi-category dispatch framework
sdivi-rust v0.2.47 — Eleven new pattern categories and the multi-category dispatch framework
This release lands the M34–M47 milestone batch, which more than doubles the
pattern measurement surface — from eight categories to nineteen — on the back of
a new multi-category call-dispatch framework. The headline is the CALL_DISPATCH
precedence registry (M34) and the eleven categories it makes possible:
framework_hooks, decorators, null_safety, schema_validation,
state_store, collection_pipelines, http_routing, testing,
serialization, concurrency, and comprehensions. Two existing categories
(resource_management, error_handling) are enriched with cross-language node
kinds, and the WASM consumer surface gains a strict TypeScript typecheck guard.
snapshot_version stays at "1.0". The snapshot JSON shape, pattern_metrics
field shapes, and the DivergenceSummary structure are all unchanged. What
changes is the per-category instance distribution on the next snapshot after
upgrade — see "Impact on existing baselines" below.
Highlights
- M34 — multi-category call-dispatch framework.
classify_hint's
call_expression/callarm now iterates aconst CALL_DISPATCHregistry
instead of a hand-ordered if-chain. Precedence is a first-class, tested
contract (slots P1–P11); the canonical table lives in
docs/pattern-categories.md. Behaviour for the pre-existing categories is
identical — no snapshot diff from this milestone alone. - M35 —
framework_hooks. TS/JScall_expressioncallees matching
^use[A-Z](React/Vue/Svelte built-ins plus the custom-hook ecosystem). - M36.1 / M36.2 —
decorators. TS/JSdecoratornodes (M36.1, one instance
per decorator line) and Pythondecorated_definitionnodes (M36.2,
wrapper-granularity — one per decorated definition). Node-kind-only; every
decorator counts regardless of name. - M37 —
null_safety. TS/JSoptional_chain(a?.b,arr?.[0]) and TS
non_null_expression(el!). Optional calls (fn?.()) emitcall_expression
and are not counted; nullish coalescing (??) is deferred. - M38 —
schema_validation. Zod / Yup / Valibot / Superstruct
namespace-anchored calls and the Zod.safeParse(call (TS/JS), plus Pydantic
field-constraint calls (Field/constr/conint) in Python. Slot P4. - M39 —
state_store. Redux / RTK, React-Redux hooks, Zustand, Jotai /
Recoil, MobX, Preact/Angular/Solid signals —^-anchored at callee start.
Slot P5. Precedence reassignment:useSelector/useDispatch/useStore
move fromframework_hookstostate_store(more specific wins). - M40 —
collection_pipelines..map/.filter/.reduce/.flatMap/
.forEach/.find/.some/.every/.flatmember calls on any receiver.
Slot P10 (broadest member-call category). Receiver type is indistinguishable
from callee text — treated as acceptable entropy noise. - M41 —
http_routing. Server-side route registration on known router
handles: Express/Koa/Fastify/Hono (TS/JS), net/http + Gin/Echo/Gorilla (Go),
Flask/FastAPIadd_url_rule(Python). Slot P7. Precedence note:
app.get(...)/router.post(...)move fromdata_accesstohttp_routing;
client calls (axios.get,fetch) staydata_access. - M42 —
testing. BDD globals, lifecycle hooks,expect(...), and the full
Jest/Vitest helper set (TS/JS);testing.Tmethods (Go);unittest.TestCase
assertions (Python). Slot P2. The bucket is empty when test paths are
scope_excluded. - M43 —
serialization.JSON.parse/stringify,structuredClone(TS/JS);
json/pickleload/dump (Python);encoding/jsonMarshal/Unmarshal/encoder
(Go). Slot P3. Bare.parse(is excluded (collides with schema validators). - M44 —
concurrency. Gogo_statement/select_statement, plus
multi-future coordination calls —Promise.all/allSettled/race/any(TS/JS) and
asyncio.gather/create_task/wait/as_completed/run(Python) at slot P11.
promise.then/catch/finallychains stay inasync_patterns. - M45.1 —
resource_managementenriched. Pythonwith_statement, Go
defer_statement, Javatry_with_resources_statement. Pure node-kind; no new
category. - M45.2 —
error_handlingenriched. Pythonexcept_clause(per arm), Java
catch_clause(per arm), andthrow_statement(per site). Pure node-kind.
Double-count semantic: atrywith 3exceptarms yields 1
try_statement+ 3except_clause= 4 instances (intentional — more arms =
higher entropy signal). - M46 —
comprehensions. Pythonlist_comprehension,set_comprehension,
dictionary_comprehension, andgenerator_expression. Nested comprehensions
each emit their own node. - M47 — WASM consumer-surface typecheck guard (CI). The WASM workflow now
tsc --noEmit-typechecks the published examples against the freshly generated
.d.tsunder strict settings, with a self-verifying negative fixture asserting
that the previously-brokenawait init()and object-as-Mappatterns fail to
typecheck. Prevents the binding's documented usage from drifting from its types.
list_categories() now returns 19 entries:
async_patterns, class_hierarchy, collection_pipelines, comprehensions,
concurrency, data_access, decorators, error_handling, framework_hooks,
http_routing, logging, null_safety, resource_management,
schema_validation, serialization, state_management, state_store,
testing, type_assertions.
Impact on existing baselines
The category contract grows (additive), but the per-category instance counts and
entropy values shift materially on the first snapshot taken after upgrade:
- Eleven categories transition from zero to non-zero on repos using the
relevant idioms (count-introduction events). Per-language details and worked
before/after examples are inMIGRATION_NOTES.md. - Two precedence reassignments move counts between existing buckets:
useSelector/useDispatch/useStore(framework_hooks→state_store,
M39) andapp.get/router.post-style route registration (data_access→
http_routing, M41). resource_managementanderror_handlingcounts grow on Python/Go/Java
as the newly-routed node kinds enter their buckets (M45.1/M45.2).
Threshold gates (sdivi check) tuned against pre-M34 baseline numbers may trip
on the next snapshot. The escape hatch is unchanged: set
[thresholds.overrides.<category>] with an expires date inside your migration
window to defer recalibration until you have retuned. The M20 cross-architecture
threshold epsilon is far smaller than these instance-count shifts and will not
absorb them.
What did not change
snapshot_versionis still"1.0". ThePatternCatalogJSON shape,
pattern_metricsfield names, andDivergenceSummarystructure are unchanged.- No new
.sdivi/config.tomlkeys.[thresholds.overrides.<new-category>]
blocks are legal under the existing category-agnostic override loader and the
existingexpires-required rule. - Public API is additive: the eleven new category names, the
CALL_DISPATCH
precedence registry, and the enriched node-kind routing.category_for_node_kind
andclassify_hintsignatures are unchanged. - Foreign extractors that emit
PatternInstanceInputdirectly are unaffected —
their inputs determine their outputs. - WASM dependency invariant (Rule 21) holds: no
tree-sitter/walkdir/ignore/
rayon/tempfilein thesdivi-corewasm32 dependency tree. - Snapshot atomic-write, retention, exit-code, and determinism contracts
unchanged. Same repo state + same seed still produces bit-identical output
(a different bit-identical output than pre-M34).
Install
# crates.io
cargo install sdivi-cli
# pre-built binary (Linux x86_64 example)
curl -Lo sdivi https://github.com/GeoffGodwin/sdivi-rust/releases/download/v0.2.47/sdivi-x86_64-unknown-linux-gnu
chmod +x sdivi && mv sdivi ~/.local/bin/
# WASM / npm
npm install @geoffgodwin/sdivi-wasm@0.2.47Documentation
- Pattern category contract: https://github.com/GeoffGodwin/sdivi-rust/blob/main/docs/pattern-categories.md
- Migration notes: https://github.com/GeoffGodwin/sdivi-rust/blob/main/MIGRATION_NOTES.md
- CHANGELOG: https://github.com/GeoffGodwin/sdivi-rust/blob/main/CHANGELOG.md
Released under Apache 2.0.
Full Changelog: v0.2.23...v0.2.47