Skip to content

refactor(core): decouple snapshot type from engine (v0.3.2) - #10

Merged
eagle-head merged 2 commits into
mainfrom
refactor/structural-fixes-time-snapshot-types
Jul 11, 2026
Merged

refactor(core): decouple snapshot type from engine (v0.3.2)#10
eagle-head merged 2 commits into
mainfrom
refactor/structural-fixes-time-snapshot-types

Conversation

@eagle-head

Copy link
Copy Markdown
Owner

Description

Structural, internal-only refactor of @timekeeper-countdown/core, plus the lockstep v0.3.2 patch release of both packages. No public API or behavior change — this is a PATCH (verified by a release-readiness audit: the moved type stays barrel-exported with an identical shape, and the only touched behavior is an unreachable, non-exported internal guard).

  • Decouple the snapshot type from the engine — move the CountdownSnapshot interface out of api/countdown-engine.ts into a dedicated leaf module src/model/countdown-snapshot.ts, removing the format/ → api/ layer inversion. It is still re-exported from the package root barrel with a byte-identical six-field shape, so consumers importing it from @timekeeper-countdown/core are unaffected.
  • Consolidate the time-validity guard — collapse the three repeated guards in runtime/time-providers.ts into one module-private isValidTime(), restoring the MAX_SAFE_INTEGER upper bound the fallback path had dropped. Internal only (createSafeTimeProvider is not exported) and unreachable for a real Date.now().
  • Single source of truth for the snapshot test double — the published testing-utils buildSnapshot now delegates to the engine's canonical buildSnapshot, so it can no longer drift from production (same parts / isRunning / isCompleted rules). Signature and output unchanged.
  • Tests — add property and contract suites (time-provider coercion boundaries; snapshot-double vs. engine equivalence) and expand the per-unit mutation suites. Core: 453 tests.
  • Docs — document the new src/model and src/time/clamp modules in CLAUDE.md; clarify in CONTRIBUTING that the Node 22 prerequisite is the build/dev toolchain, while the published packages support Node ≥ 18 at runtime.

Type of Change

  • Refactoring (no functional changes)
  • Chore (dependencies, CI, build, etc.) — lockstep v0.3.2 version bump

How to Test

  1. npm install
  2. bin/quality-gate.sh — full gate (build + format:check + lint + typecheck + test) is green: core 453 tests, react 18.
  3. Confirm the public type still resolves from the barrel: import type { CountdownSnapshot } from '@timekeeper-countdown/core' (type-only, unchanged shape).

Checklist

  • My code follows the project's code style
  • I have added/updated tests for my changes
  • npm run lint passes
  • npm run typecheck passes
  • npm run test passes
  • I have followed the commit convention
  • I have updated the CHANGELOG (packages/*/CHANGELOG.md) — recorded as an internal-only note for the 0.3.2 release (not a user-facing change), and mirrored in docs/changelog.md
  • I have updated documentation if needed (CLAUDE.md, CONTRIBUTING.md)

Move the CountdownSnapshot interface out of api/countdown-engine.ts
into a leaf module (src/model/countdown-snapshot.ts), removing the
format/ -> api/ layer inversion. The public API is unchanged: the
type is still re-exported from the package root barrel with an
identical six-field shape, so consumers importing it from
@timekeeper-countdown/core are unaffected.

Two sibling structural fixes ride along:

- Collapse the three repeated time-validity guards in
  runtime/time-providers.ts into one module-private isValidTime(),
  restoring the <= MAX_SAFE_INTEGER upper bound the fallback path had
  dropped. This is internal only (createSafeTimeProvider is not
  exported) and unreachable for a real Date.now().
- Make the published testing-utils buildSnapshot delegate to the
  engine's canonical buildSnapshot, so the test double can no longer
  drift from production (single source of truth for parts, isRunning
  and isCompleted). Its signature and output are unchanged.

Add property and contract tests (time-provider coercion boundaries;
snapshot-double/engine equivalence) and expand the per-unit mutation
suites.

Also document the src/model and src/time/clamp modules in CLAUDE.md
and clarify in CONTRIBUTING that the Node 22 prerequisite is the
build/dev toolchain, while the published packages support Node >= 18
at runtime.
@eagle-head eagle-head added refactor Code refactoring (no feature or fix) release Version bump / release labels Jul 11, 2026
@eagle-head eagle-head self-assigned this Jul 11, 2026
@eagle-head
eagle-head merged commit 131e533 into main Jul 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Code refactoring (no feature or fix) release Version bump / release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant