Skip to content

Implement velocity-testkit: in-memory reference backend + conformance TCK - #5

Merged
wolpert merged 1 commit into
mainfrom
velocity-testkit
Jul 19, 2026
Merged

Implement velocity-testkit: in-memory reference backend + conformance TCK#5
wolpert merged 1 commit into
mainfrom
velocity-testkit

Conversation

@wolpert

@wolpert wolpert commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

velocity-testkit — the in-memory reference velocity-spi backend and the mandatory conformance
TCK. This proves the freshly-frozen SPI is actually implementable (the architect's core concern) and
gives every future backend (JDBI, Redis, …) the harness it must pass (ADR 0004, NFR-13/18,
acceptance #3).

What's in it

  • InMemoryVelocityBackend — thread-safe, EXACT, ATOMIC reference backend implementing
    VelocityBackend + Count/Sum/DistinctStore + Sliding/TumblingSupport + SeedSupport. Injectable
    Clock (the backend is the clock authority per ADR 0003); a raw-event store computes each window at
    read time — sliding = (now-D, now], tumbling = aligned bucket [start, end). apply returns one
    PerFeature per (intent × the feature's windows) and its value already reflects the write
    (read-your-write). A down/unsupported result is a distinguishable Failure, never a silent 0.
  • Conformance TCK (tck/*Scenarios, shipped in src/main so backends reuse it): 27 scenario
    methods across Count/Sum/Distinct/Sliding/Tumbling/Seed/Capability/Purge that advance the clock and
    assert real windowed values, aging-out / bucket-reset, seeded ≡ recorded merge (acceptance #16),
    unsupported-window → Failure(UNSUPPORTED_WINDOW), and declaration↔implementation agreement.
  • InMemoryVelocityBackendTck drives all 27 scenarios; 48 tests, coverage 97.8% line /
    87% branch
    (gate 80/70) — met by genuinely exercising the backend, not padding.

SPI change

Comment-only: a javadoc clarification on CountStore/SumStore/DistinctStore apply* that the
result is one PerFeature per (intent × window). No signature/type change — the frozen contract
is preserved (git diff velocity-spi is javadoc-only).

Review

Implemented against a precise spec, then reviewed by the repo's change-validator agent (CLAUDE.md
working model). VERDICT: APPROVE — it verified the TCK is genuinely adversarial ("would fail a
silent-zero backend, a windowing-ignorer, or a wrong-capability backend"), the in-memory backend is
correct (incl. a 16-thread atomicity test), and coverage is honestly met. Its one worth-fixing nit —
unused testkit deps (jackson/caffeine/slf4j) — is fixed in this PR.

Follow-up (non-blocking, noted by the reviewer)

TCK completeness isn't framework-enforced — a future backend author could forget to wire a scenario.
Worth a later abstract @TestFactory/base or a documented checklist so downstream backends can't
under-wire. Not required now (the in-memory adapter wires all 27).

./gradlew :velocity-spi:build :velocity-testkit:buildBUILD SUCCESSFUL.

🤖 Generated with Claude Code

… TCK

Proves the frozen velocity-spi contract is implementable and provides the
harness every backend (JDBI/Redis) must pass (ADR 0004, NFR-13/18, acceptance #3).

- InMemoryVelocityBackend: thread-safe, EXACT, ATOMIC reference backend
  implementing VelocityBackend + Count/Sum/DistinctStore + Sliding/TumblingSupport
  + SeedSupport. Injectable Clock (backend is the clock authority); raw-event
  store computed per window at read; sliding = (now-D, now], tumbling = aligned
  bucket; apply returns one PerFeature per (intent x feature window) and its value
  already reflects the write (read-your-write); down/unsupported -> distinguishable
  Failure, never a silent 0.
- Conformance TCK (tck/*Scenarios, in src/main so backends reuse it): Count/Sum/
  Distinct/Sliding/Tumbling/Seed/Capability/Purge scenarios (27 methods) that
  advance the clock and assert real windowed values, aging-out / bucket-reset,
  seeded==recorded merge (acceptance #16), unsupported-window Failure, and
  declaration<->implementation agreement.
- InMemoryVelocityBackendTck drives all 27 scenarios; 48 tests total; coverage
  97.8% line / 87% branch (gate 80/70).
- velocity-spi: comment-only javadoc clarification on apply* result cardinality
  (one PerFeature per intent x window); no signature/type change.

Validated by the change-validator agent: VERDICT APPROVE ("this TCK would fail a
broken backend"). Removed unused testkit deps (jackson/caffeine/slf4j) per the
review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wolpert
wolpert enabled auto-merge July 19, 2026 00:10
@wolpert
wolpert merged commit 0a0c4c5 into main Jul 19, 2026
3 checks passed
@wolpert
wolpert deleted the velocity-testkit branch July 19, 2026 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant