Skip to content

Caregiver Matching Assignment Gap Mining

Scope: source-mining continuation only. Legacy source-refs/ code is behavior evidence, not implementation code to copy. This page stays separate from source-feature-checklist.md and caregiver-settlement-gap-mining.md; it is merge-ready evidence for caregiver matching, assignment, multi-caregiver contract, caregiver grade, and wage settlement migration gaps.

Use these modern names when migrating the source behavior:

  • CaregiverMatchingProfile: mother preference, pet, personality, and free-text matching inputs.
  • CaregiverCandidateSnapshot: ranked caregiver card with score, branch scope, grade, distance, transport evidence, profile text, and exclusion facts.
  • RequestedCaregiverSelection: mother-selected named caregiver path requiring branch consultation and service-grade uplift.
  • CaregiverAssignmentDecision: branch/HQ final selected caregiver, candidate evidence shown at decision time, actor, reason, and policy version.
  • CareTeamContract: one reservation care team with primary caregiver, ordered assistant caregiver member terms, provider-count basis, service period, and contract document projection.
  • CaregiverAssignmentTerm: date-bounded caregiver assignment, role, handoff order, grade snapshot, and replacement link.
  • CaregiverGradeSnapshot: grade code and score basis frozen when used for matching, assignment, quote, or payout.
  • CaregiverWageQuoteLine: calculated wage basis by assignment key, role, tax policy, service days, options, and overrides.
  • CaregiverPayoutInstruction: frozen payable instruction with amount, tax, bank account reference, memo, and payout status.
  • CaregiverPayoutAcknowledgement: branch deposit and caregiver receipt state, separated from reservation status.
flowchart LR
  MotherInputs[CaregiverMatchingProfile] --> Candidate[CaregiverCandidateSnapshot]
  Requested[RequestedCaregiverSelection] --> Policy[RequestedCaregiverPolicyDecision]
  Candidate --> Decision[CaregiverAssignmentDecision]
  Candidate --> Conflict[CaregiverAssignmentConflictPolicy]
  Conflict --> Decision
  Policy --> Decision
  Decision --> Team[CareTeamContract]
  Team --> Term[CaregiverAssignmentTerm]
  Term --> Grade[CaregiverGradeSnapshot]
  Grade --> GradeHistory[CaregiverGradeRecalculationHistory]
  Term --> Wage[CaregiverWageQuoteLine]
  Wage --> Payout[CaregiverPayoutInstruction]
  Payout --> Ack[CaregiverPayoutAcknowledgement]
  Team --> Docs[CareTeamDocumentProjection]
  • Customer smart-matching step 1 persists religion, pet information, pet-together flag, and ranked preferences, then advances process state. Evidence: source-refs/sanmopia_web/application/controllers/api/Service.php:576-640.
  • Customer smart-matching step 2 deletes and rewrites caregiver personality answers plus free-text preference memo. Evidence: source-refs/sanmopia_web/application/controllers/api/Service.php:643-670.
  • Customer apply/check-data chooses recommendation grades by service detail: special/live-in allows special or premium, premium allows premium, else all grades; it asks Manager_matching_model::getRecommendManagerWithDueTime(...) for five branch-scoped candidates. Evidence: source-refs/sanmopia_web/application/controllers/Service.php:594-623.
  • Customer recommendation screen explicitly says recommended caregivers are not directly selected by the customer, and final caregiver is confirmed two days before service. Evidence: source-refs/sanmopia_web/application/views/service/reservation_check_data.php:33-56, source-refs/sanmopia_web/application/views/service/reservation_check_data.php:150-205.
  • Legacy survey screen still exposes a named caregiver search; choosing one posts reservation[manager_no], while the page warns that selecting a named caregiver automatically applies one service-grade uplift. Evidence: source-refs/sanmopia_web/application/views/survey/a19.php:27-107, source-refs/sanmopia_web/application/views/survey/a19.php:146-190.

Modern gap: split customer-visible CaregiverCandidateSnapshot from final CaregiverAssignmentDecision. A recommendation card is a provisional customer display artifact. It cannot become a final assignment without branch actor, availability proof, selected-caregiver policy proof, and service-date proof.

  • Web Manager_matching_model::getRecommendManagerByReservationId() ranks by preference plus personality score, requires active/non-deleted preference rows, checks MANAGER_SCHEDULE_CHECK_FN(...), filters branch and grade, uses random tie seed by user id, then sorts by distance when coordinates exist. Evidence: source-refs/sanmopia_web/application/models/Manager_matching_model.php:166-228, source-refs/sanmopia_web/application/models/Manager_matching_model.php:248-307.
  • Admin Matching_model::getRecommendManagerByReservationId() does similar ranking and additionally excludes pet-allergy caregivers when reservation pet info exists. Evidence: source-refs/sanmopia-admin/application/models/Matching_model.php:44-124.
  • Admin Matching_model::getRecommendManagerWithDueTime() loads cached transport times, calculates missing times via odsaylib, but the DB replace is commented out and final ordering currently uses score, not transport time. Evidence: source-refs/sanmopia-admin/application/models/Matching_model.php:724-862.
  • Admin candidate detail modal reads selected reservation id, caregiver id, displayed score, matching info, preference answer matching, distance, and cached transport time. Evidence: source-refs/sanmopia-admin/application/controllers/ajax/Reservation.php:31-65.
  • Admin search path rebuilds candidate filters from reservation service detail, branch, search string, and date window. Evidence: source-refs/sanmopia-admin/application/controllers/Reservation.php:538-577.
  • Admin ranking still uses random tie ordering and score-first ordering while transport-time persistence is incomplete. Evidence: source-refs/sanmopia-admin/application/models/Matching_model.php:752-862. Migration must make tie-breaker seed, distance, transport provider, and score-vs-travel priority explicit policy inputs instead of hidden SQL ordering.

Progress 2026-07-04: backend now has sanmopia_caregiver_candidate_snapshots plus SupabaseCaregiverCandidateSnapshotRepository, so score components, distance, transport provider result, fallback reason, pet exclusion, schedule check, grade filter, branch scope, source request key, and ranking policy version are persisted as frozen evidence. Later assignment detail can now read this snapshot instead of mutable caregiver profile rows.

Improvement note: transport evidence is mixed into a function named for due time, but source ranking still sorts by score. Modern optimizer inputs should store both transportDurationMinutes and rankingPolicyVersion, then make score-vs-transport priority explicit.

  • Admin reservation detail loads five matching candidates and matching preferences for the reservation detail screen. Evidence: source-refs/sanmopia-admin/application/controllers/Reservation.php:330-360.
  • Reservation::saveReservationData() saves broad reservation edits in one action, including main caregiver id, assistant caregiver ids, service dates, payment dates, address coordinates, add-days, and baby details. Evidence: source-refs/sanmopia-admin/application/controllers/Reservation.php:650-875.
  • Reservation_model::saveReservationManager() marks other-area assignments when caregiver branch differs, logs main caregiver replacement, and mutates RESERVATION_TB.MANAGER_ID_FK. Evidence: source-refs/sanmopia-admin/application/models/Reservation_model.php:2170-2222.
  • ajax/Reservation::manager_history() reads separate main and sub-caregiver log tables, with SORT for assistant slots. Evidence: source-refs/sanmopia-admin/application/controllers/ajax/Reservation.php:180-209.

Modern gap: CaregiverAssignmentDecision needs command-specific writes instead of one broad reservation-save action. Assignment should emit decision id, actor, selected candidate snapshot id, assignment reason, source rerun id, branch scope, other-area flag, replacement chain, and impacted payout/contract effects. Current backend collaboration path now applies caregiver_assignment.roster into sanmopia_reservation_caregiver_assignments, keyed by contract_assignment_key and preserving role, handoff order, grade, planned service days, term dates, and assigned Supabase user id. Assignment conflict policy now blocks explicit unavailable-window, overlap, and replacement continuity violations before final assignment. assignment_optimizer_inputs now prepares travel freshness, fairness/rotation workload, replacement continuity, assistant slot order, and same-caregiver cross-slot exclusion as backend-owned facts instead of UI arithmetic. Candidate snapshot Supabase persistence is now present. Remaining gap is durable assignment-decision source exposure, OR-Tools adapter/API ingestion, and generated OpenAPI/TypeScript/ frontend conflict UX. Next backend slice: assignment command accepts candidateSnapshotId, expected revision, idempotency key, and reason; loads CaregiverCandidateSnapshotRepository.find_by_snapshot_id(); rejects missing, stale, or caregiver-mismatched snapshots; and copies frozen score components, branch scope, grade, distance, transport duration, matching request key, and ranking policy version into CaregiverCandidateEvidence without rereading mutable caregiver profile rows. Legacy "0점" must become explicit zero-score override evidence, not null recomputation.

Additional source-mined optimizer evidence:

  • Reservation_manager_trans_info_model.php:13-87 owns the real travel-time cache write path: missing cache calls ODSAY and stores TIME, while the matching list can still fall back to ODSAY_MAX_TIME.
  • Reservation.php:538-577 maps service detail strings to manager classes (GENERAL, SPECIAL, PREMIUM) during modal search. This must become server-owned class eligibility, not UI/search endpoint branching.
  • Reservation_model.php:2166-2303 writes primary assignment, other-area flag, primary replacement log, assistant SORT, assistant replacement log, and assistant deletion side effects.
  • reservation_detail.js:586-629 blocks duplicate primary/sub caregiver picks only in the browser. Backend optimizer and assignment command validation must enforce uniqueness across all primary/assistant slots.
  • Hidden source constants still needing abstraction: candidate limit 5, RAND(userId) / RAND(reservationId) seed behavior, "0점" score sentinel, green UI marker, earth radius 6371, ODSAY_MAX_TIME, and Korean service-detail/baby-count strings such as 바우처, 스페셜, 입주, 프리미엄, 쌍둥이, 삼둥이, 사태아, 셋째아 이상, and 넷째아 이상.
  • Admin reservation detail treats voucher twins/triplets/quadruplets and DELIVERY_COUNT as the source of provider count. The UI shows fixed “다태아 제공인력 선택” radio buttons and computes sub-caregiver count from 셋째아 이상, 넷째아 이상, and 넷째아 이상(관리사4명). Evidence: source-refs/sanmopia-admin/application/views/reservation_status/reservation_detail.php:45-60, source-refs/sanmopia-admin/application/views/reservation_status/reservation_detail.php:840-861.
  • Main caregiver label changes to “선임 관리사” when a multi-caregiver voucher case exists; assistant slots render as “담당 관리사 A/B/…” with change history buttons and fsenior-manager-name[i] fields. Evidence: source-refs/sanmopia-admin/application/views/reservation_status/reservation_detail.php:1145-1188.
  • Reservation_model::saveReservationSubManager() stores assistant caregivers in RESERVATION_SUB_MANAGER_TB by SORT, logs replacements in RESERVATION_SUB_MANAGER_LOG_TB, and deletes linked sub payment/salary rows when clearing a slot. Evidence: source-refs/sanmopia-admin/application/models/Reservation_model.php:2224-2303.
  • Customer mypage concatenates selected primary and sub-caregiver names in the caregiver header, renders cards for each assigned caregiver, creates sub-caregiver report data, and exposes separate sub-caregiver bank account info for direct service-balance payment. Evidence: source-refs/sanmopia_web/application/controllers/MyReservation.php:120-144, source-refs/sanmopia_web/application/views/mypage/reservation_detail.php:260-380, source-refs/sanmopia_web/application/views/mypage/reservation_detail.php:470-568.
  • Contract/export code writes provider count and main/sub caregiver names into voucher documents and export forms. Evidence: source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:872-930, source-refs/sanmopia-admin/application/models/Spreadsheet_model.php:3528-3650.

Modern migration: CareTeamContract now has backend domain/application and TS-client contract foundations for one ordered roster, not source-specific main/sub tables. It validates exactly one primary caregiver, unlimited ordered assistant member terms, assignment-key uniqueness, handoff-order uniqueness, effective windows, provider-count basis, grade snapshot reference, and document member projection. Remaining work is Supabase persistence/API binding, document-template integration, report obligation binding, account references, and payout terms that all share the stable assignment keys.

Improvement note: clearing a sub-caregiver slot in source filters linked delete queries by the posted empty $subManagerId, not clearly by the previous slot caregiver. Migration should model explicit RemoveAssistantCaregiver with slot id, previous assignment key, and expected current caregiver.

  • Manager detail reads manual class code, Korean class label, legacy GRADE_SCORE, star score, branch/headquarters score fields, and additive grade score from GET_MANAGER_GRADE_SCORE_FN(...). Evidence: source-refs/sanmopia-admin/application/models/Manager_model.php:115-152.
  • Manager list computes display grade score as GRADE_SCORE + ADD_SCORE for old caregivers, but only ADD_SCORE for new caregivers. Evidence: source-refs/sanmopia-admin/application/models/Manager_model.php:677-725.
  • Grade class is mutable through Manager_model::updateClass() and read from MANAGER_CLASS_TB. Evidence: source-refs/sanmopia-admin/application/models/Manager_model.php:1618-1630, source-refs/sanmopia-admin/application/models/Manager_model.php:2182-2192.
  • Admin manager detail screen separately edits HQ score, branch score, and grade class. Evidence: source-refs/sanmopia-admin/application/views/manager/manager_detail.php:400-470.
  • Evaluation aggregation caps each score item by max score and intends to cap combined career/other-working score, but the final cap mutates the local $row variable rather than writing back to $result[$managerId]. Evidence: source-refs/sanmopia-admin/application/models/Manager_evaluation_model.php:641-724.
  • Ajax score-detail rendering recalculates capped score history in the controller before returning table rows. Evidence: source-refs/sanmopia-admin/application/controllers/ajax/ManagerEvaluation.php:146-228. Migration must expose backend-owned CaregiverPerformanceScorecard entries with original score, capped score, before/after totals, score-type cap, and policy version so UI never recomputes grade history.

Modern gap: CaregiverGradeSnapshot should freeze grade code, grade label, manual override, scorecard id, score components, old/new caregiver rule, and policy version at the moment a grade is used for matching, contract, or wage. Backend now persists recalculation history and exposes API/HTTP reads for operator audit. 2026-07-07 follow-up: backend commit baa1a1a adds CaregiverProfileScoreRevisionPolicy and PlanCaregiverProfileScoreRevisionPayload so profile-save branch/HQ score clamps and old/new caregiver grade-score basis are backend-owned. Source GRADE_SCORE, ADD_SCORE, OLD_MANAGER_FL, manager_score_branch, and manager_score_danbee are rejected at the contract boundary. Remaining gap is scheduled recalculation execution, mismatch warning UX, class-change command audit, and tying history entries to every grade snapshot used by assignment or payout.

Improvement note: move score aggregation into a tested CaregiverPerformanceScorecard policy. Do not let mutable MANAGER_CLASS_CD_FK silently change already-issued recommendations, contracts, or payout quotes. Ubiquitous naming now separates CaregiverPerformanceScorecard capped rows from CaregiverPerformanceSeasonScorecard published season snapshots and CareDeliveryPerformanceScorecard care-delivery earned points, so later matching and payout code does not bind to the wrong scorecard concept.

PriorityStatusModern ubiquitous nameHidden source evidenceFeature gap
P0PartialCaregiverPerformanceSeasonScorecardsource-refs/sanmopia-admin/application/controllers/cli/Manager.php:22-120, source-refs/sanmopia-admin/application/controllers/cli/Manager.php:123-237Legacy daily cron grants score rows from PHP and DB-trigger sources, then auto-adjusts caregiver class from current score thresholds while skipping premium caregivers. Modern scorecard recalculation still needs scheduled execution, class-adjustment proposal/audit, premium-exclusion reason, mismatch warning rows, and idempotent rerun control.
P1PendingCaregiverAwardScoreboardsource-refs/sanmopia-admin/application/controllers/cli/Cache.php:12-33, source-refs/sanmopia-admin/application/models/Win_the_race_model.php:163-315, source-refs/sanmopia-admin/application/models/Win_the_race_model.php:318-441, source-refs/sanmopia-manager/application/models/Win_the_race_model.php:28-57, source-refs/sanmopia-manager/application/models/Win_the_race_model.php:87-110, source-refs/sanmopia-manager/application/views/winTheRace/index.php:158-260”Win the Race” is a yearly caregiver award scoreboard, not normal matching grade. It caches per-year rankings in Redis, uses work score, rating score, and referral score, gives tie ranks, exposes caregiver-facing rank/points/award rules, and keeps prior-year cache for about one year. Modern backend needs a published award-season projection with cache/version metadata, tie policy, award bands, referral-settlement eligibility, and caregiver-visible read model.
  • Caregiver app pay list includes only completed or settlement reservations, covers both primary and sub caregivers, then calculates salary at read time. Evidence: source-refs/sanmopia-manager/application/models/Reservation_model.php:13-82, source-refs/sanmopia-manager/application/controllers/Other.php:223-294.
  • calcSalary(...) identifies primary vs sub caregiver, reads main/sub payment info, tax type, voucher add price, service-balance overrides, Saturday/holiday additions, custom main pay, custom sub pay, and returns display lines without freezing them. Evidence: source-refs/sanmopia-manager/application/helpers/salary_helper.php:8-227.
  • Caregiver pay detail displays base pay, after-tax base pay, voucher add pay, option pay, total pay, final pay, and memo. Evidence: source-refs/sanmopia-manager/application/views/pay_info_detail.php:167-263.
  • Admin salary tax/memo persistence only stores reservation id, caregiver id, TAX_TYPE, MEMO, and update date; missing rows default tax type to four insurance and memo to blank for primary plus sub caregivers. Evidence: source-refs/sanmopia-admin/application/models/Reservation_manager_salary_model.php:21-52, source-refs/sanmopia-admin/application/models/Reservation_manager_salary_model.php:112-180.
  • Tax constants define four insurance, 3.3% income tax, and the 0.033 tax rate. Evidence: source-refs/sanmopia-admin/application/config/constants.php:272-274, source-refs/sanmopia-manager/application/config/constants.php:144-152.
  • Admin salary completion changes main payment rows or sub payment rows, stamps deposit dates, can insert missing payment rows as a fallback, and auto-moves reservation to done when salary and service-balance flags are complete. Evidence: source-refs/sanmopia-admin/application/controllers/Manager.php:986-1027, source-refs/sanmopia-admin/application/controllers/Manager.php:1300-1335, source-refs/sanmopia-admin/application/models/Reservation_model.php:2945-3146.
  • Caregiver app service-balance confirmation has separate primary and sub-caregiver acknowledgement paths. Evidence: source-refs/sanmopia-manager/application/models/Reservation_model.php:352-410, source-refs/sanmopia-manager/application/views/schedule/schedule_info.php:130-175.
  • The manager portal acknowledgement is a raw PUT /reservation/data switch: JavaScript posts type=payment or type=sub_payment plus service_type, the controller dispatches on the string, and the model stamps type-3 customer payment rows plus branch-manager payment flags. The sub-caregiver path updates SUB_PAYMENT_STATUS_ID_FK by reservation id only, so modern acknowledgement must require assignment key/current roster revision instead of reservation-id-only mutation. Evidence: source-refs/sanmopia-manager/static/js/schedule/schedule_info.js:1-95, source-refs/sanmopia-manager/application/controllers/Reservation.php:6-77, source-refs/sanmopia-manager/application/models/Reservation_model.php:247-270, source-refs/sanmopia-manager/application/models/Reservation_model.php:351-411.

Modern migration: CaregiverCompensationQuoteLine and CaregiverPayoutInstruction freeze amount basis before caregiver display. CareTeamContract can now feed compensation quote seeds directly, so ordered care-team member terms become backend-owned quote lines by assignment key, role, handoff order, grade, planned days, rate rule, tax terms, and explicit override inputs. Bank-account edit proof now persists as CaregiverPayoutDestinationChangeAudit; remaining work is API/auth/runtime binding for manager, branch, and HQ screens plus richer tax formula explainability.

Improvement note: source salary completion can create missing payment rows at button click time. Modern code should create payout instructions idempotently when settlement enters payout-ready state, then block completion if required instructions or acknowledgements are missing.

  • Add CaregiverMatchingProfile intake events for pet, religion, preference ranking, personality answers, and free-text memo.
  • Add backend CaregiverCandidateSnapshot and MatchingOptimizationInput foundation with score, grade, branch, pet exclusion, schedule conflict, distance, transport, deterministic tie-breaker facts, and ranking-policy evidence. Profile preference answers now export MatchingProfileCompatibilityInput, so profile compatibility signals are not confused with reservation-level optimizer inputs. Backend assignment-decision foundation now stores selected candidate snapshot id and evidence references; durable candidate snapshot persistence and recommendation-set persistence now freeze per-candidate evidence plus operator-visible ordered result sets. Profile-text projection, API/client exposure, and assignment-decision binding remain open.
  • Add CaregiverCandidateOrderingPolicy parity foundation for legacy score, distance, and transit ordering. Backend commit 05832cd makes CaregiverCandidateOrderingPolicy the canonical domain name while keeping CandidateRankingPolicy as a compatibility alias. The policy freezes score, distance, travel-duration, deterministic tie-breaker component order, source evidence keys, and the replacement for source RAND(userId) / RAND(reservationId) ties. Source paths still limit candidate count after score ordering, then distance-sort in one path while due-time matching computes transit but can still score-sort; backend commit f07313b adds CaregiverCandidateRecommendationSet persistence for reservation revision, service dates, branch/class/search scope, candidate limit, optimization input, optimization decision, ranked/excluded counts, and full snapshot payloads. Remaining runtime work must add travel freshness/failure policy, remove raw SQL search/date interpolation, and bind assignment API/UI to ordered recommendation sets. Persistent-worker evidence: source-refs/sanmopia-admin/application/models/Matching_model.php:44-124, source-refs/sanmopia-admin/application/models/Matching_model.php:724-862, and source-refs/sanmopia-admin/application/models/Reservation_manager_trans_info_model.php:13-87 show pet exclusion, candidate limit, random tie seeds, branch/class filters, ODSAY fallback, cache replacement, and score-first ordering all need explicit policy fixtures and snapshot fields.
  • Add CaregiverMatchingPolicy for grade/class eligibility and ranking chain. Status: Partial. Evidence: source-refs/sanmopia_web/application/controllers/api/Service.php:576-640, source-refs/sanmopia-admin/application/controllers/Reservation.php:538-577, source-refs/sanmopia_web/application/models/Manager_matching_model.php:166-228, source-refs/sanmopia-admin/application/models/Matching_model.php:44-124. Source behavior: service detail strings and age tiers decide class filters (바우처, 입주, 스페셜, 프리미엄, 쌍둥이/셋째아 이상/넷째아 이상) in query paths and ranking keeps score-first logic while transport is advisory. Modern migration now moves this into backend-owned CaregiverServiceProfile, CaregiverClassEligibilityPolicy, CaregiverClassEligibilityRule, CaregiverClassEligibilityDecision, and CaregiverMatchingPolicy with source-parity policy version source_caregiver_matching_v1. The TS contract exposes the same policy shape through packages/ts-client/src/types/caregiver-matching.ts so UI cannot branch on raw Korean service-detail strings. Supabase now persists policy versions in sanmopia_caregiver_matching_policies and class eligibility rules in sanmopia_caregiver_class_eligibility_rules, with generated DB types and a source-parity seed for the legacy score/distance/transport policy. Backend now exposes GET /caregiver-matching-policies/active and the TS contract validates the active policy response plus effectiveOn query path so UI and optimizer clients consume the same Supabase-backed policy snapshot. Remaining work: operator policy editor, OR-Tools adapter ingestion, and assignment command binding.
  • Add RequestedCaregiverSelection and RequestedCaregiverPolicyDecision foundation for named caregiver search, service-grade uplift, consultation-required uncertainty, and hard rejection. Backend domain reuses CaregiverMatchingPolicy.candidate_fit_for instead of duplicating grade/availability/segment/day/branch checks, and contract payloads expose decision_code, blocking codes, consultation reasons, and accepted_for_assignment.
  • Add backend CaregiverAssignmentDecision foundation for branch/HQ final assignment with actor, source candidate snapshot, reason, audit evidence, and replacement link. Append-only persistence, authenticated branch/HQ command API, current-roster/history reads, broad-save rejection, and downstream invalidation now exist. Caregiver-owned accept/reject is implemented on the P06 readiness branches; strict phase acceptance still needs a live actor run and retained media packet.
  • Add backend CaregiverAvailabilityWindow and CaregiverAssignmentConflict foundation with explicit unavailable and overlapping-assignment reason codes before final assignment.
  • Add CareTeamContract with provider count basis, primary caregiver, ordered assistant member terms, role labels, handoff order, grade snapshot reference, effective windows, and document projection. Backend domain/application models and TS-client validators now reject duplicate assignment keys, duplicate handoff orders, missing primary caregiver, and overlapping same-caregiver terms without imposing a hard provider limit.
  • Add backend CaregiverAssignmentTerm replacement-continuity and slot invalidation foundation so primary/assistant replacements target stable assignment keys without source slot naming leaking into the domain.
  • Add CaregiverGradeSnapshot, recalculation history linkage, and tested scorecard policy before using grade in matching, assignment, quote, or payout. Backend scorecard cap projection now exists under backend-repo/src/sanmopia_modernization/domain/caregiver_performance_recognition/features/caregiver_scorecard/ and application read models expose capped rows without UI recomputation. The published season contract now uses CaregiverPerformanceSeasonScorecard, while grade recalculation inputs use CareDeliveryPerformanceScorecard. Backend profile-score revision foundation now clamps branch/HQ submitted scores, freezes configured max-score evidence, freezes old/new caregiver additive grade basis, rejects source score fields, and emits matching/payout invalidation flags. Backend evaluation ledger foundation now sorts score rows by applied_on then fact_code, preserves original-vs-capped score evidence, exposes before/after cumulative totals, rejects legacy ajax display fields, and keeps monthly-career plus other-working under one combined cap without UI recomputation. Remaining work: persist score-revision audit rows and capped ledger rows, add class-change command audit, and connect grade snapshots to matching, assignment, quote, and payout reads.
  • Add CaregiverCompensationQuoteLine and CaregiverPayoutInstruction so caregiver pay pages never recalculate from mutable reservation rows. Backend quote/payout/read-model foundations exist, and QuoteCareTeamCaregiverCompensationCommand now quotes directly from CareTeamContract member terms without the legacy reservation-assignment aggregate. SupabaseCareTeamCompensationSourceReader now reads accepted rows from sanmopia_reservation_caregiver_assignments as ordered, compensation-ready care-team facts, rejecting missing grade or non-integral planned-day data instead of allowing UI fallback math. The authenticated CareTeamCompensationSourceApi and /care-team-compensation-sources/{reservationBookingId} HTTP route now build the reader from the caller access token so Supabase RLS remains caller-scoped instead of service-role scoped. Runtime composition now wires the route into build_sanmopia_backend_app_from_env() and prefers SUPABASE_PUBLISHABLE_KEY/SUPABASE_ANON_KEY for caller-JWT Data API reads when present. Remaining work: generated OpenAPI/client exposure and manager/branch/HQ operational screens.
  • Add CaregiverPayoutAcknowledgement for branch deposit and caregiver receipt, including main/sub role and reservation completion continuation. Evidence: source-refs/sanmopia-manager/application/helpers/salary_helper.php:8-227 and source-refs/sanmopia-manager/application/views/pay_info_detail.php:167-263. Source behavior: manager pay display is calculated from current reservation rows, role/sort, custom pay overrides, service-balance overrides, voucher pure add-ons, Saturday/holiday option labels, tax election, and the 2022-03-29 tax/add-on cutover. Modern gap: payout acknowledgement must reference immutable CaregiverPayoutInstruction and CaregiverCompensationQuote rows, not rerun salary helper math at read time.
  • Add regression tests for transport ranking policy, assistant slot removal, grade cap behavior, named-caregiver service uplift, multi-caregiver document names, and payout instruction idempotency.

2026-07-07 Crew Mining: Matching Runtime Gaps

Section titled “2026-07-07 Crew Mining: Matching Runtime Gaps”
feature_idlane_ownersource_evidenceddd_aggregatecommand_querypersistencecontracte2e_proofstatus
SFC-20260707-MATCH-001backendsource-refs/sanmopia-admin/application/models/Matching_model.php:44-124, :144-173, :724-862; source-refs/sanmopia-admin/application/controllers/Reservation.php:542-577caregiver_assignment / CaregiverCandidateRecommendationSetFindCaregiverCandidateRecommendationsQuerysanmopia_caregiver_candidate_recommendation_sets exists; runtime search writer missingCaregiverCandidateRecommendationSetPayloadnonefoundation
SFC-20260707-MATCH-002backendsource-refs/sanmopia-admin/application/models/Reservation_manager_trans_info_model.php:13-87; source-refs/sanmopia-admin/application/models/Matching_model.php:782-834caregiver_assignment / CaregiverTravelEvidenceSnapshot, TravelEvidenceFreshnessPolicyRefreshCaregiverTravelEvidenceCommand pendingBackend foundation: a93332b; sanmopia_caregiver_travel_evidence_snapshots exists; runtime provider writer missingCaregiverTravelEvidenceSnapshotPayload, TravelEvidenceFreshnessPolicyPayloadnonefoundation
SFC-20260707-MATCH-003backendsource-refs/sanmopia-admin/application/controllers/Reservation.php:332-360, :542-577; source-refs/sanmopia-admin/application/models/Matching_model.php:101-118, :743-753caregiver_assignment / CaregiverClassEligibilityDecisionResolveCaregiverClassEligibilityQuerypolicy foundation onlyCaregiverMatchingPolicyPayloadnonefoundation
SFC-20260707-MATCH-004backendsource-refs/sanmopia-admin/application/models/Matching_model.php:50-78, :126-140, :232-288, :724-758; source-refs/sanmopia-admin/application/models/Manager_model.php:2038-2088, :2146-2180; source-refs/sanmopia-admin/application/controllers/Reservation.php:650-681, :834-875; source-refs/sanmopia-admin/application/models/Reservation_model.php:2165-2222, :2224-2303caregiver_assignment / CaregiverScheduleProof, CaregiverScheduleConflictPolicy, CaregiverAvailabilityWindowRevisionCheckCaregiverAssignmentConflictQuery; RecordCaregiverAvailabilityWindowCommand pendingBackend foundation: 66f6afa; Supabase persistence: 251ab72; sanmopia_caregiver_schedule_proofs existsCaregiverScheduleProofPayload, CaregiverScheduleConflictPolicyPayloadnoneruntime_wired
SFC-20260707-MATCH-005backendsource-refs/sanmopia-admin/application/models/Reservation_model.php:2165-2222, :2224-2303; source-refs/sanmopia-admin/application/models/Reservation_model.php:57-115caregiver_assignment / CaregiverAssignmentDecision, CareTeamAssignmentHistoryReadModel, CareTeamCurrentRosterReadModelAssignCaregiverFromCandidateSnapshotCommand; GetCareTeamAssignmentHistoryQuery; GetCareTeamCurrentRosterQuery; GET /care-team-assignment-histories/{reservationBookingId}; GET /care-team-current-rosters/{reservationBookingId}; POST /care-team-assignment-decisions/assign-from-candidate-snapshotBackend foundation: 1258920; Supabase persistence: fc90660; Command binding: 5d5514a; History read model: 66ff4cd; History API: df11386; Current roster API: 2c52e1b; Downstream invalidation dispatch: 39a8eba; Protected command API: 6758b30; sanmopia_caregiver_assignment_decisions exists; sanmopia_care_team_document_projection_invalidations existsCaregiverAssignmentDecisionPayload; CareTeamAssignmentHistoryReadModelPayload; CareTeamAssignmentHistoryResponse; CareTeamCurrentRosterResponse; AssignCaregiverFromCandidateSnapshotRequest; CareTeamAssignmentCommandResponse; public OpenAPI/TS contracts 24497f0, 19892e2, 495d5ccfocused backend tests for protected assignment command API, assignment invalidation dispatch, payout refresh queue handoff, document invalidation receipt persistence, and contract pnpm checkruntime_wired
SFC-20260707-MATCH-006backendsource-refs/sanmopia-admin/application/models/Reservation_model.php:2240-2303; source-refs/sanmopia-admin/application/models/Reservation_sub_manager_model.php:23-45caregiver_assignment / CareTeamRosterAssignmentDecision, CareTeamAssignmentHistoryReadModel, CareTeamCurrentRosterReadModelAssignCaregiverFromCandidateSnapshotCommand; ClearAssistantCaregiverSlotCommand; GetCareTeamAssignmentHistoryQuery; GetCareTeamCurrentRosterQuery; GET /care-team-assignment-histories/{reservationBookingId}; GET /care-team-current-rosters/{reservationBookingId}; POST /care-team-assignment-decisions/clear-assistant-slotBackend foundation: 1258920; Supabase persistence: fc90660; Command binding: 5d5514a; Clear binding: e0ff283; History read model: 66ff4cd; History API: df11386; Current roster API: 2c52e1b; Downstream invalidation dispatch: 39a8eba; Protected command API: 6758b30; sanmopia_caregiver_assignment_decisions stores roster id per row; sanmopia_care_team_document_projection_invalidations stores document stale signalsCareTeamRosterAssignmentDecisionPayload; CareTeamAssignmentHistoryReadModelPayload; CareTeamAssignmentHistoryResponse; CareTeamCurrentRosterResponse; ClearAssistantCaregiverSlotRequest; CareTeamAssignmentCommandResponse; public OpenAPI/TS contracts 24497f0, 19892e2, 495d5ccfocused backend tests for protected clear command API, assignment invalidation dispatch, payout refresh queue handoff, document invalidation receipt persistence, and contract pnpm checkruntime_wired

SFC-20260707-MATCH-002 Travel Evidence Notes

Section titled “SFC-20260707-MATCH-002 Travel Evidence Notes”

Source cache fields are only RESERVATION_ID_FK, MANAGER_ID_FK, and TIME. Reservation_manager_trans_info_model::getReservationManagerTransInfo() reads TIME by reservation and caregiver, otherwise calls ODSAY and replace() writes those three fields. ODSAY input is the first reservation service address LONGITUDE/LATITUDE as start coordinates and caregiver MANAGER_TB.LONGITUDE / LATITUDE as end coordinates. Provider output uses status and totalTime; provider failure becomes ODSAY_MAX_TIME, while missing reservation address returns false and the public getter returns 0.

The matching list path reads RESERVATION_MANAGER_TRANS_INFO_TB rows for the candidate caregiver ids and reservation id. Missing rows trigger inline ODSAY calls using the candidate row coordinates, but the DB replace() is commented out there, so those computed values are request-local only. Existing ODSAY_MAX_TIME rows do not refresh because the re-fetch flag is commented out. Final ordering in this path still sorts by resultScore, not travel time, so travel evidence is advisory source data unless the modern policy explicitly weights it.

Modern acceptance proof: CaregiverTravelEvidenceSnapshot must persist provider, reservation booking id, caregiver profile id, reservation address evidence key, caregiver address evidence key, start/end coordinate facts, duration minutes, fallback code, provider status, source cache key, freshness deadline, and computed-at timestamp. RefreshCaregiverTravelEvidenceCommand must invalidate or supersede snapshots when reservation service address, caregiver address/profile coordinates, assignment policy version, or provider failure policy changes. Consumers must reject stale travel evidence, distinguish missing-address from provider-failure fallback, and copy the selected travel evidence id into CaregiverCandidateEvidence before assignment.

Backend foundation a93332b adds CaregiverTravelEvidenceSnapshot, TravelEvidenceFreshnessPolicy, Pydantic payloads, Supabase migration sanmopia_caregiver_travel_evidence_snapshots, generated Supabase table types, and repository save/load tests. The replacement freezes reservation/caregiver address revisions, coordinate fingerprints, provider result/failure evidence, fallback reason, measured/expiry timestamps, and source evidence keys so old ODsay cache values cannot silently survive address/profile changes. Remaining proof: provider-neutral travel refresh command, live ODSay/adapter binding, recommendation-set integration, final assignment evidence copy, and E2E matching smoke.

SFC-20260707-MATCH-004 Schedule Proof Notes

Section titled “SFC-20260707-MATCH-004 Schedule Proof Notes”

Source candidate search calls MANAGER_SCHEDULE_CHECK_FN(...) = 1, while the older PHP denied-date and checkManagerSchedule() filters are commented out. Manager_model::checkManagerSchedule() scans primary assignment rows only and uses weak edge checks that collapse some overlap cases to equality. Denied-window mutation (addDenied / updateDenied) writes MANAGER_DENIED_TB directly with reason/start/end only; it has no actor, expected revision, invalidation event, or assignment-proof refresh. Final manager and sub-manager assignment writes service dates and caregiver ids directly without rechecking the same schedule proof.

Backend foundation 66f6afa adds CaregiverScheduleInterval, CaregiverScheduleProof, CaregiverScheduleConflictPolicy, and Pydantic payloads. The replacement uses one inclusive date-overlap rule for unavailable windows and existing assignment intervals, freezes schedule revision and source evidence, and returns typed blocking codes instead of a raw boolean DB function. Runtime follow-up 251ab72 persists schedule proofs in sanmopia_caregiver_schedule_proofs with generated Supabase table types and a repository keyed by proof id or candidate/service window. Remaining proof: availability-window event persistence, assistant-slot overlap evidence, availability-window mutation commands with actor/revision, recommendation API integration, final assignment command guard, and E2E matching smoke.

SFC-20260707-MATCH-005/006 Assignment Decision Notes

Section titled “SFC-20260707-MATCH-005/006 Assignment Decision Notes”

Source final assignment is written through broad reservation save paths. The primary caregiver write posts fmanager-id and mutates RESERVATION_TB.MANAGER_ID_FK; assistant caregivers are stored in RESERVATION_SUB_MANAGER_TB by positional SORT and can be inserted, updated, or deleted by array index. The source history table records old/new manager ids but does not carry candidate snapshot, schedule proof, actor reason, policy version, roster revision, or downstream payout/document invalidation evidence.

The assistant-slot clear path has a concrete migration defect: after deleting the sub-manager row, the source code attempts to delete branch-sub-manager and salary rows using the empty submitted manager id instead of the previous slot caregiver. Modern clear/replacement must therefore key downstream invalidation by stable assignment key and previous assignment key, never by a browser slot index or an empty posted id.

Backend foundation 1258920 adds CaregiverAssignmentDecision, CareTeamRosterAssignmentDecision, typed decision kinds for primary assignment, assistant replacement, and assistant clear, assignment-scope invalidation targets, expected reservation/roster revisions, actor/reason/idempotency evidence, candidate snapshot and schedule proof requirements, and strict Pydantic payloads that reject legacy manager_id, sub_manager_sort, fmanager-id, and related source field names. Remaining proof: Supabase append-only assignment-decision persistence, current roster projection, later broad-save guard, recommendation writer binding, payout/document projection invalidation worker, assignment-history read model, and E2E branch/HQ assignment smoke.

Runtime follow-up fc90660 adds CareTeamAssignmentDecisionRepository, SupabaseCareTeamAssignmentDecisionRepository, Supabase table sanmopia_caregiver_assignment_decisions, generated Supabase table types, schema/codegen/access-control tests, and repository save/load tests. The table keeps assignment decision id, roster decision id, reservation booking id, decision kind, role, handoff order, target/previous assignment key, expected reservation and roster revisions, actor/reason/idempotency, selected candidate snapshot, schedule proof, invalidation count, and full decision snapshot under service-role-only RLS.

Runtime follow-up 5d5514a adds AssignCaregiverFromCandidateSnapshotCommand under application/caregiver_assignment/features/care_team_contract. The command loads the frozen CaregiverCandidateSnapshot, rejects missing, stale, caregiver-mismatched, or matching-request-mismatched snapshots, then writes a CareTeamRosterAssignmentDecision through CareTeamAssignmentDecisionRepository. Orchestration-side DecideCaregiverAssignmentFromCandidateSnapshotHandler stays limited to legacy care-delivery evidence compatibility, so reservation_orchestration no longer cross-imports the caregiver_assignment application/domain ownership. Primary assignment and assistant replacement now persist with target assignment key, previous assignment key when applicable, selected candidate snapshot, schedule proof, expected reservation/roster revisions, actor/reason/idempotency, and payout/document invalidation targets. Verification: focused assignment pytest, care-team domain/contract pytest, Supabase repository pytest, ruff, Tach dependency/interface/external gates, and Vulture confidence-100 scan. Remaining runtime follow-up: current roster projection, later broad-save guard, payout/document invalidation worker, assignment-history read model, assistant clear command binding, and E2E branch/HQ assignment smoke.

Runtime follow-up e0ff283 adds ClearAssistantCaregiverSlotCommand under the same care-team contract application slice. The command accepts a cleared_assignment_key, maps it to both target and previous assignment key, and persists a CLEAR_ASSISTANT_SLOT roster decision without candidate snapshot or schedule proof. This blocks the source defect where assistant clear side effects could be keyed by an empty submitted manager id instead of the previous slot identity. care_team_assignment_invalidation_targets() is now shared by assign and clear commands, removing duplicated projection-target construction. Verification: focused assignment pytest, care-team domain/contract pytest, Supabase repository pytest, ruff, Tach dependency/interface/external gates, and Vulture confidence-100 scan. Remaining runtime follow-up: current roster projection, later broad-save guard, payout/document invalidation worker, assignment-history read model, and E2E branch/HQ assignment smoke.

Runtime follow-up 66ff4cd adds CareTeamAssignmentHistoryReadModel, GetCareTeamAssignmentHistoryQuery, GetCareTeamAssignmentHistoryHandler, and CareTeamAssignmentHistoryReadModelPayload. The read model uses CareTeamAssignmentDecisionRepository.find_roster_decisions_by_reservation_booking_id() to expose assignment decisions already persisted by assign/clear commands, then orders entries by roster revision, roster decision id, and assignment decision id. It carries decision kind, role, handoff order, target/previous assignment key, candidate snapshot id, schedule proof id, actor/reason/idempotency, evidence keys, invalidation targets, and latest roster revision. Shared candidate-snapshot test support removes duplicate candidate fixture code across assignment-command and history tests. Verification: focused assignment/history pytest, care-team domain/contract pytest, Supabase repository pytest, ruff, Tach dependency/interface/external gates, and Vulture confidence-100 scan. Remaining runtime follow-up: current roster projection, later broad-save guard, payout/document invalidation worker, and E2E branch/HQ assignment smoke.

Runtime follow-up df11386 exposes assignment history through CareTeamAssignmentHistoryApi and GET /care-team-assignment-histories/{reservationBookingId}. The route derives a Supabase user through bearer auth, rejects withdrawn member sessions, then reads sanmopia_caregiver_assignment_decisions with a caller-scoped Supabase token so RLS remains active instead of bypassing operator visibility. It returns camelCase history entries with decision kind, role, assignment keys, roster revisions, actor/reason/idempotency, evidence keys, and invalidation targets. Shared assignment-history test support now feeds both application and HTTP tests, removing duplicated primary/replacement/clear setup code. Public contract commit 24497f0 adds CareTeamAssignmentHistoryResponse, path helper careTeamAssignmentHistoryPath(), response validators, JSON Schema, and OpenAPI path coverage. Verification: focused assignment-history API/HTTP pytest, care-team compensation boundary regression tests, Supabase assignment-decision repository tests, main_test, ruff, Tach dependency/interface/external gates, Vulture confidence-100 scan, and contract pnpm check. Later current-roster API and broad-save guard follow-ups leave payout/document invalidation worker and E2E branch/HQ assignment smoke open.

Runtime follow-up 2c52e1b adds CareTeamCurrentRosterReadModel, GetCareTeamCurrentRosterQuery, GetCareTeamCurrentRosterHandler, CareTeamCurrentRosterApi, and GET /care-team-current-rosters/{reservationBookingId}. The projection folds append-only assignment decisions into active roster slots: assign_primary replaces any prior active primary, replace_assistant_slot removes the previous assignment key and same assistant handoff slot before adding the replacement, and clear_assistant_slot removes the target/previous assistant assignment without relying on source SORT, empty submitted manager ids, or browser state. The route uses the same caller-scoped Supabase assignment-decision repository as history, so RLS remains active for operator-visible current roster reads. Contract follow-up 19892e2 exposes CareTeamCurrentRosterResponse, careTeamCurrentRosterPath(), response validators, JSON Schema, OpenAPI, and generated dist artifacts. Verification: current-roster application/API/HTTP pytest, assignment-history regression tests, Supabase assignment-decision repository pytest, main_test, ruff, Tach dependency/interface/external gates, Vulture confidence-100 scan, and contract pnpm check. Remaining runtime follow-up after the later broad-save guard: payout/document invalidation worker and E2E branch/HQ assignment smoke.

Runtime follow-up ef0a510 retires caregiver assignment broad-save writes from ReservationCollaborationCommand: mutation kind caregiver_assignment and any caregiver_assignment.* change-set field now fail with ReservationCollaborationError before collaboration commit persistence. This closes the source path where a one-submit reservation save could overwrite MANAGER_ID_FK or positional assistant SORT data after care-team assignment facts had already been modeled as append-only decisions. Public contract follow-up 936ed47 adds the same rejection to the TypeScript commit validator and reservation_collaboration_commit.schema.json; journal/read schemas keep historical enum compatibility. Runtime backstop 068632e adds adapter and SQL wrapper guards so direct SupabaseReservationCollaborationCommitStore or sanmopia_commit_reservation_collaboration(...) calls also reject caregiver_assignment broad-save payloads before touching Supabase RPC persistence. Verification: reservation-collaboration domain/application/HTTP and Supabase adapter pytest, SQL migration assertions, ruff, Tach dependency/interface/external gates, Vulture confidence-100 scan, and contract pnpm check. Remaining runtime follow-up: payout/document invalidation worker and E2E branch/HQ assignment smoke.

Runtime follow-up 39a8eba adds standardized care-team assignment downstream invalidation. AssignCaregiverFromCandidateSnapshotHandler and ClearAssistantCaregiverSlotHandler dispatch typed invalidation requests only after roster persistence succeeds. The application model now has stable CareTeamAssignmentDownstreamInvalidationTargetCode and CareTeamAssignmentDownstreamInvalidationStatus enums instead of raw bridge strings. CareTeamAssignmentProjectionInvalidationRequester fail-fast rejects unknown targets, queues care_team_assignment_changed refreshes through the existing admin caregiver payout projection PGMQ requester, and records document projection invalidation through RecordCareTeamDocumentProjectionInvalidationCommand in the document_reporting/features/service_use_contract slice. Backend follow-up 5dd338b keeps that receipt and also queues a typed render_care_team_document_projection workload to Supabase PGMQ queue sanmopia_document_rendering, carrying assignment key, source evidence, actor, reason, and render idempotency key. Backend follow-up 3cdc86a consumes those messages through SupabaseCareTeamDocumentRenderProcessor, retries while the frozen render source row is not ready, renders through the printable document handler, and stores the artifact after source/idempotency/definition checks. Verification: assignment/clear dispatch pytest, document invalidation receipt pytest, payout queue handoff pytest, render processor pytest, ruff, Tach dependency/interface/external gates, and Vulture confidence-100 scan. Remaining runtime follow-up: E2E branch/HQ assignment smoke, render-source producer binding from roster/projection revision, and storage/access grant issuance.

Runtime follow-up 6758b30 binds the final assignment command surface to FastAPI. POST /care-team-assignment-decisions/assign-from-candidate-snapshot and POST /care-team-assignment-decisions/clear-assistant-slot derive the actor from Supabase bearer auth, reject withdrawn sessions, check SpiceDB assign_caregiver on the reservation booking, then write through service-role Supabase repositories for frozen candidate snapshots and append-only assignment decisions. The command API does not accept actorId from the request body. Document projection invalidation receipts are now persisted in sanmopia_care_team_document_projection_invalidations with RLS enabled and service-role-only grants, so later document render workers can consume durable stale-contract signals instead of hidden UI state. Public contract follow-up 495d5cc exposes the two command paths, bearer header helper, assign/clear request validators, command response validator, JSON Schema, and OpenAPI paths. Verification: protected command API/HTTP pytest, document invalidation Supabase adapter pytest, assignment invalidation regressions, document render queue processor pytest, ruff, Tach dependency/interface/external gates, Vulture confidence-100 scan, and contract pnpm check. Remaining runtime follow-up: live E2E branch/HQ assignment smoke against a seeded reservation plus frozen render-source producer and access-grant binding.

2026-07-20 P06 Caregiver Response Readiness

Section titled “2026-07-20 P06 Caregiver Response Readiness”

Backend 952bccca and contract b881604 add caregiver-owned assignment accept/reject after branch assignment. New assignment starts at pending_acceptance; only accepted assignment creates one schedule obligation per billable service occurrence and binds the primary caregiver to the booking. Revision checks, advisory-lock idempotency, altered-replay rejection, actor ownership, append-only evidence, RLS, and service-role-only RPC execute are server-owned. Schedule, reservation worklist, and compensation readers now consume only accepted assignments.

Verification: contract pnpm check passed 485 tests; backend focused gate passed 45; Tach exact returned zero diagnostics; Tach impact selection passed 2,853 and deselected 3,660 unaffected tests; Vulture confidence 100 found no production candidate. Supabase PostgreSQL transaction smoke printed P06 caregiver assignment response smoke passed, then rolled back. Post-check proved response tables and revision column absent and original stage assignment counts unchanged.

Status remains technical readiness, not P06 PASS. Missing strict evidence: seeded branch operator assignment, authenticated caregiver accept/reject, cross-actor denial, replay/stale conflict, retained UI screenshots/WebP, and cleanup manifest.

2026-07-21 P06 Self-Scoped Task UI Readiness

Section titled “2026-07-21 P06 Self-Scoped Task UI Readiness”

Backend 443c989c adds authenticated self-scoped GET /caregiver-assignment-response-tasks, persists the source assignment decision on the pending projection, and rejects a response whose decision no longer owns the current assignment. Contract d232992 publishes the additive task list path, types, validators, JSON Schema, and OpenAPI after merging the latest P04 contract lineage. Frontend 8183ed9 adds an Astro SSR mobile card, same-origin accept/reject endpoint, server-side cookie token binding, and contract-validated response handling.

Focused frontend tests passed 8; Astro check reported zero errors and production build passed. Backend Tach selected 1,132 affected tests and deselected 5,394; all selected tests passed. Vulture confidence 100 found no production candidate. Contract check passed 524 TypeScript and 91 Python tests.

The retained PNG and animated WebP are documented in P06 관리사 배정 응답 UI 준비. They are isolated browser harness evidence, not an actual Supabase actor run. P06 therefore remains BLOCKED until branch assignment, caregiver accept and reject, denial, replay/conflict, primary-state, and cleanup are proved together.

  1. Candidate snapshot, branch assignment decision, and caregiver response are separated in backend/contract readiness. Missing proof is live actor HTTP/UI execution, retained media, and cleanup evidence.
  2. Named caregiver selection has backend policy decisions, but still needs Supabase persistence/API binding and source survey/search UI wiring.
  3. CareTeamContract foundation, Supabase compensation-source reader, caller-JWT HTTP binding, and accepted-assignment gating exist. Document-template, mother/caregiver workspace, daily-report, and payout projections still need the same stable assignment keys.
  4. Caregiver grade is mutable and score logic has policy drift; freeze grade snapshots and move score math into tested policy.
  5. Caregiver wage settlement recalculates at read time and backfills payment rows during completion; migrate to payout-ready instructions plus separate acknowledgements.