Phase 42: cancellation gap-fill — freed slots propose nearby due recalls (D-2)#252
Merged
Conversation
…k (Phase 42, D-2) - cancelAppointment (single CANCELLED chokepoint) now gates on prior CONFIRMED status + slot within GAP_FILL_WINDOW_DAYS (default 21, env-overridable) and raises an internal task-centre proposal — post-commit, try-wrapped, never blocks the cancellation, no outbound messaging, nothing auto-booked - new pure lib/gap-fill/gap-fill.ts: window gate, priority, deep-link builder (Phase 33/40 /appointments/new param contract incl. the yard-must-belong-to-customer rule), task title/notes builders - cancellation-fill ranking gains the multi-horse-yard preference: each extra due horse at a yard credits 3 km off effective distance (capped at 3 mates); distinct-horse counting; candidates without yard data rank exactly as before. Cancelling customer's own horses excluded from the pool; yardCustomerId surfaced for safe deep links - task centre: TaskCentreItem carries sourceType/sourceId; gap-fill tasks deep-link to the cancelled appointment and render a live candidate shortlist (top 5: name, yard, distance, recall type, overdue badge, competition badge, Book link) via new GapFillSuggestionList; TaskCard gains a children slot - FillSuggestions panel rows gain the same Book-this-slot deep link - appointment detail cancel flow shows a small dismissible notice linking to the task centre when a proposal was created - EN/FR keys under new gapFill namespace (10 + 10) https://claude.ai/code/session_01VzJJTUcvzZgS9jN8aap9iv
…elivered - docs/BUILD_PLAN.md — Phase 42 entry: detection hook, ranking design (multi-horse-yard credit: 3 km per extra distinct due horse, capped at 3 mates), task-centre proposal surface, deep-link contract, gate results (2,621 → 2,655 tests), unchanged scope-out deferrals - docs/JUN10_OVERNIGHT_BUILD.md — §6 row and deferred note D-2 flipped to delivered (WP-B pull surface + Phase 42 push half), pointing at the build-plan entry https://claude.ai/code/session_01VzJJTUcvzZgS9jN8aap9iv
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b3c6c4a. Configure here.
…e pass-through Bugbot finding on #252: rescheduleAppointment runs the same post-cancel gap-fill hook and its API response carries gapFill, but only the cancel handler read it — rescheduling a near CONFIRMED slot raised the task with no in-flow pointer. RescheduleResult now declares the field, the page surfaces the same notice from both handlers, and a service test pins the pass-through. Also appends tonight's git-proxy + gate-plumbing lessons to .claude/memory.md. https://claude.ai/code/session_01VzJJTUcvzZgS9jN8aap9iv
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Phase 42 — Cancellation gap-fill (June-10 deferral D-2)
Overnight multi-agent build authorised by Freddie (2026-06-12). When a CONFIRMED appointment within the next 21 days (env-overridable
GAP_FILL_WINDOW_DAYS) is cancelled, the freed slot no longer evaporates: a task-centre task proposes the top-5 nearby due-recall candidates. The vet stays the decision-maker — nothing is auto-booked, no customer is contacted.Design
rescheduleService.cancelAppointment(verified as the onlyCANCELLEDwriter, so reschedules inherit it — intended: the old slot is genuinely freed; idempotency prevents task stacking). Runs post-commit and try-wrapped: a gap-fill failure can never mask a committed cancellation.lib/(haversine on stored coordinates — zero Google API calls): urgency bucket → competition flag → effective distance (with a multi-horse-yard credit of 3 km per extra distinct due horse, capped at 3 — the credit can't beat urgency/competition tiers) → soonest due./appointments/newprefill contract with the freed date; "Gap-fill suggestions created" notice in the cancel flow links to/tasks.Taskmodel (sourceType='AppointmentGapFill'is both UI discriminator and dedup key; renaming it later would be a data migration — pinned by a test).Verification
Gates all green in the build worktree: lint ✓ typecheck ✓ prisma validate ✓ build ✓, tests 2,621 → 2,655 (+34) (ranking weights, hook fires/doesn't-fire matrix, idempotency, deep-link params, task-centre mapping). EN/FR
gapFillnamespace parity 10=10.Notes for reviewers
toISOString().slice(0,10)convention (same as follow-up presets) — a 00:00–01:00 CH-time slot prefills the prior UTC date; pre-existing convention, not introduced here.docs/JUN10_OVERNIGHT_BUILD.mdedits with the Phase 43 PR (adjacent deferral rows) — I'll rebase whichever merges second.Suggested merge order tonight: #PR44 → #PR43 → Phase 41 → this. Final merge with Richard / Freddie as always.
https://claude.ai/code/session_01VzJJTUcvzZgS9jN8aap9iv
Generated by Claude Code