Skip to content

fix(#2889): key isTrackComplete off the highest-order checkpoint - #2892

Merged
jung-thomas merged 1 commit into
DEVfrom
worktree-issue-2889-highest-checkpoint
Oct 23, 2026
Merged

jung-thomas merged 1 commit into
DEVfrom
worktree-issue-2889-highest-checkpoint

Conversation

@jung-thomas

Copy link
Copy Markdown
Contributor

Closes #2889. Follow-up to #2887 (PR #2888), finding M1.

Problem

AppSpace.vue isTrackComplete marked a segmented track complete when any checkpoint unlocked (checkpoints.some(c => isSegmentItemUnlocked(c))). For every track shape authored today this agrees with the old flat rule, but a track with a non-terminal plain CHECKPOINT (authored at a lower order than later tutorials) would be flagged complete as soon as that early checkpoint unlocked — while downstream tutorials remained incomplete.

Fix

Prize-aware restriction rather than a naive highest-order-only rule (which would have regressed the authored lane-prize case):

  • lane-prize checkpoints (prizeId set) are authored to earn the reward the moment their single lane finishes → any unlocked one completes the track (keeps some semantics);
  • plain downstream checkpoints (no prizeId) are joins → only the terminal (highest-order) one completes the track. allSegmentItems flattens segments in authored ascending-order order, so the last non-prize checkpoint is the highest-order one.

Tests

New describe('AppSpace track completion aggregate (#2889)') block in AppSpace.segments.test.ts exercising isTrackComplete/progressPercent over fork payloads (previously only covered indirectly via the barcode tests):

  • non-terminal plain checkpoint unlocked, downstream incomplete → not complete (this guard fails against the old some() rule — verified by temporarily reverting);
  • terminal checkpoint unlocked → complete;
  • lane-prize unlocked with a locked downstream checkpoint → complete (guards against an over-eager highest-order-only regression);
  • all checkpoints locked → not complete.

8/8 tests pass locally (npx vitest run hugo-apps/src/app-space/__tests__/AppSpace.segments.test.ts).

Severity

Minor / latent — not reachable under current authoring conventions; safe follow-up to #2888.

🤖 Generated with Claude Code

App Space `isTrackComplete` marked a segmented track complete when ANY
checkpoint unlocked (`checkpoints.some(isSegmentItemUnlocked)`). For a
hypothetical track with a non-terminal plain CHECKPOINT (authored at a
lower order than later tutorials), that early checkpoint unlocking would
flag the whole track complete while downstream work remained.

Make the rule prize-aware instead of a naive highest-order restriction:
- lane-prize checkpoints (prizeId set) are authored to earn the reward
  the moment their single lane finishes → ANY unlocked one completes the
  track (keeps `some` semantics);
- plain downstream checkpoints (no prizeId) are joins → only the TERMINAL
  (highest-order) one completes the track.

Add client unit tests for isTrackComplete/progressPercent over fork
payloads (the aggregate rule was previously only exercised indirectly via
the barcode tests): the non-terminal-checkpoint bug guard fails against
the old `some()` rule, and a lane-prize-only payload guards against an
over-eager highest-order-only regression.

Follow-up to #2887 (PR #2888), finding M1.
@jung-thomas
jung-thomas merged commit 716fdf5 into DEV Oct 23, 2026
5 checks passed
@jung-thomas
jung-thomas deleted the worktree-issue-2889-highest-checkpoint branch October 23, 2026 11:03
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