Skip to content

v0.2.47 — sdivi-rust v0.2.47 — Eleven new pattern categories and the multi-category dispatch framework

Choose a tag to compare

@GeoffGodwin GeoffGodwin released this 02 Jun 15:00
· 8 commits to main since this release

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/call arm now iterates a const CALL_DISPATCH registry
    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/JS call_expression callees matching
    ^use[A-Z] (React/Vue/Svelte built-ins plus the custom-hook ecosystem).
  • M36.1 / M36.2 — decorators. TS/JS decorator nodes (M36.1, one instance
    per decorator line) and Python decorated_definition nodes (M36.2,
    wrapper-granularity — one per decorated definition). Node-kind-only; every
    decorator counts regardless of name.
  • M37 — null_safety. TS/JS optional_chain (a?.b, arr?.[0]) and TS
    non_null_expression (el!). Optional calls (fn?.()) emit call_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 from framework_hooks to state_store (more specific wins).
  • M40 — collection_pipelines. .map/.filter/.reduce/.flatMap/
    .forEach/.find/.some/.every/.flat member 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/FastAPI add_url_rule (Python). Slot P7. Precedence note:
    app.get(...)/router.post(...) move from data_access to http_routing;
    client calls (axios.get, fetch) stay data_access.
  • M42 — testing. BDD globals, lifecycle hooks, expect(...), and the full
    Jest/Vitest helper set (TS/JS); testing.T methods (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/pickle load/dump (Python); encoding/json Marshal/Unmarshal/encoder
    (Go). Slot P3. Bare .parse( is excluded (collides with schema validators).
  • M44 — concurrency. Go go_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/finally chains stay in async_patterns.
  • M45.1 — resource_management enriched. Python with_statement, Go
    defer_statement, Java try_with_resources_statement. Pure node-kind; no new
    category.
  • M45.2 — error_handling enriched. Python except_clause (per arm), Java
    catch_clause (per arm), and throw_statement (per site). Pure node-kind.
    Double-count semantic: a try with 3 except arms yields 1
    try_statement + 3 except_clause = 4 instances (intentional — more arms =
    higher entropy signal).
  • M46 — comprehensions. Python list_comprehension, set_comprehension,
    dictionary_comprehension, and generator_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.ts under strict settings, with a self-verifying negative fixture asserting
    that the previously-broken await init() and object-as-Map patterns 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 in MIGRATION_NOTES.md.
  • Two precedence reassignments move counts between existing buckets:
    useSelector/useDispatch/useStore (framework_hooksstate_store,
    M39) and app.get/router.post-style route registration (data_access
    http_routing, M41).
  • resource_management and error_handling counts 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_version is still "1.0". The PatternCatalog JSON shape,
    pattern_metrics field names, and DivergenceSummary structure are unchanged.
  • No new .sdivi/config.toml keys. [thresholds.overrides.<new-category>]
    blocks are legal under the existing category-agnostic override loader and the
    existing expires-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
    and classify_hint signatures are unchanged.
  • Foreign extractors that emit PatternInstanceInput directly are unaffected —
    their inputs determine their outputs.
  • WASM dependency invariant (Rule 21) holds: no tree-sitter/walkdir/ignore/
    rayon/tempfile in the sdivi-core wasm32 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.47

Documentation

Released under Apache 2.0.

Full Changelog: v0.2.23...v0.2.47