P1/P2 Consolidated Backlog — code-verified
Date: 2026-06-28
Branch: feat/mvp1-personas-authz @ 777cd36 (== main)
Purpose: Single deduplicated, code-verified punch-list that the fix-loop burns down. Each
item is classified DONE / FIX-NOW / DECIDE-THEN-FIX / DEFERRED-BY-DESIGN and (for code items)
checked against the current tree so we don't re-fix shipped work.
Sources merged:
- Persona-lens gap review —
docs/decisions/2026-06-25-persona-lens-gap-review.md(M/D/H/A/O/C/X items). Predates the now-merged ① Personas & Authorization sub-project (bd99f24..5248f01, 24 commits) — many gaps are CLOSED by ①. - Token-economy pre-build decisions —
app/test-gallery/authored/developer/architecture/features/token-economy.md§7–§8. - ① security-review follow-ups —
.superpowers/sdd/progress.md(Phase 8 final review: "0 crit/important; 4 minors; 5 deferrals; 2 HARD gates"),task-16/17-report.md,phase4b-report.md. - Closed domain-gaps (re-verify only) —
.superpowers/sdd/p1p2-audit.md, 16 items closed atb7b2b30("P1/P2 audit 16/16").
Verification method: graphify subgraph queries + targeted reads of authorizer.dart,
capability.dart, reward.dart, activity.dart, economy_service.dart, and the route/repository
tree. Every DONE claim cites the symbol verified.
Summary table
| ID | Source | Title | Bucket | Size | Risk |
|---|---|---|---|---|---|
| D-1 | PL A1/O2/X2 | Zero-last-admin + zero-last-owner guards + transfer-ownership | DONE | — | — |
| D-2 | PL O1/C1 (core) | Owner/Admin/Helper capability model (distinct overlays) | DONE | — | — |
| D-3 | PL X3 (core) | COPPA consent owner-bound + child-only + actor-auth + child-PII profile gate | DONE | — | — |
| D-4 | PL X8 (cap) | Helper holds approveCompletion capability | DONE | — | — |
| D-5 | PL H2 (model) | MemberAccess expiry model + Authorizer param enforcement | DONE | — | — |
| D-6 | PL (supervised) | superviseAction capability + principalMemberId approval path | DONE | — | — |
| D-7 | PL X9 (events) | AuthzEventSink — 5 no-PII authz events | DONE | — | — |
| D-8 | ① review | App authz UI: AdminGuard + /governance + RoleOwnerBloc + consent + TermsSessionGate | DONE | — | — |
| D-9 | TE | ActivityGate enforced + EarningsSplit auto-split + append-only ledger/zero-floor | DONE | — | — |
| D-10 | DG P2-F | Goal requestGoal/completeGoal preconditions (status == active) | DONE | — | — |
| D-11 | DG 16 items | Domain-gap punch-list closed @ b7b2b30 (re-verify checklist below) | DONE | — | re-verify |
| FN-1 | PL X8 | Approval.resolvedBy = helperManual + widen completion guard to require(approveCompletion) | FIX-NOW | M | low |
| FN-2 | PL O1/C1 | Truth personas/admin/dynamics/code docs to the shipped capability model | FIX-NOW | S | low (doc) |
| FN-3 | PL M1 | Place watch-only as a Member sub-state in personas.md | FIX-NOW | S | low (doc) |
| FN-4 | PL A3 | Reconcile co-parent "delegated scopes" → full admin in context.md | FIX-NOW | S | low (doc) |
| LD-1 | TE §8 | Restore description on Reward + Activity | DECIDE→FIX | M | LOW |
| LD-2 | TE §8 | Activity.category typed enum vs free-text | DECIDE→FIX | S | LOW |
| LD-3 | TE §8 | Reward.kind (activity|item) restore? | DECIDE→FIX | S | LOW |
| LD-4 | TE §8 | Gate reset cadence (one-time vs daily/weekly re-lock) | DECIDE→FIX | S | LOW |
| LD-5 | TE §8 | Gate granularity (per-activity vs per-kid) | DECIDE→FIX | S | LOW |
| LD-6 | TE §8 | Gate status visibility ("locked — finish X") | DECIDE→FIX | S | LOW |
| LD-7 | TE §8 | tithe flag → give-bucket wiring | DECIDE→FIX | S | LOW |
| LD-8 | PL H1 | MemberKind slot for non-parent adult (grandparent/babysitter/tutor) | DECIDE→FIX | M | LOW |
| LD-9 | PL X1 | State roles per-membership + owner/billing scope across houses | DECIDE→FIX | S | LOW (doc) |
| HS-1 | PL C1/O1 | Ratify capability-matrix + Owner-vs-Admin semantics | DECIDE→FIX | S | HIGH |
| HS-2 | PL M3/X4 | Intra-household per-member visibility (RLS-shaped) | DECIDE→FIX | L | HIGH |
| HS-3 | PL A2/X3 | Guardian-vs-admin decoupling / non-parental admin | DECIDE→FIX | M | HIGH |
| HS-4 | TE §8 | Earn auto-split vs "Unallocated" bucket | DECIDE→FIX | L | HIGH |
| DF-1 | PL H2/C2/D2 | member_access persistence + standalone (babysitter) helper invite (NFR-AUTHZ-10) | DEFERRED | — | — |
| DF-2 | PL M2 / 7d | Supervised-action UX (kid on shared device) → MVP-2 | DEFERRED | — | — |
| DF-3 | ① review | Approval.principalMemberId field (codegen follow-up) | DEFERRED | — | — |
| DF-4 | PL X9 | AuthzEventSink provider wiring + auto-fire at gate sites + audit-log surface | DEFERRED | — | — |
| DF-5 | ① review | Consent-lifecycle (retention/tombstoning/shadow-ToS/erasure cascade/cross-house) | DEFERRED | — | — |
| DF-6 | PL X5 | Peer / self-governed mode (research-only) | DEFERRED | — | — |
| DF-7 | PL X6 | PIN ownership / profile-switching → MVP-2 kid-mode | DEFERRED | — | — |
| DF-8 | PL X7 | TV/kiosk display identity + privacy scope → MVP-2 | DEFERRED | — | — |
| DF-9 | PL M4 | Aging-up (13/18) transition hook | DEFERRED | — | — |
| DF-10 | PL H3 | Helper completion-approval notifications (notifications surface unbuilt) | DEFERRED | — | — |
| DF-11 | PL H4 | Helper visibility of child photo proofs (photo submission unbuilt) | DEFERRED | — | — |
| DF-12 | PL H5 | Therapist persona (future Helper sub-variant) | DEFERRED | — | — |
| DF-13 | PL O3/O4 | Free-tier billing surface + non-owner-admin paywall (billing unbuilt) | DEFERRED | — | — |
| DF-14 | PL §5-H | Backup/restore admin-vs-owner export (backup unbuilt) | DEFERRED | — | — |
| HARD-1 | ① review | Child FINANCIAL-PII gate (ledger/approvals/spend_requests/redemptions/token_batches) | DEFERRED (legal) | — | — |
| HARD-2 | ① review | Child consent re-capture on terms/privacy version bump (checkConsentCurrency) | DEFERRED (legal) | — | — |
Counts: 11 DONE, 4 FIX-NOW, 13 DECIDE (9 low-risk / 4 high-stakes), 16 DEFERRED (incl. 2 HARD COPPA gates).
DONE — verified shipped (drop from actionable list)
Every claim cites the symbol verified via graphify/read. ① = the merged Personas & Authorization sub-project (
bd99f24..5248f01).
- D-1 — Zero-last-admin/owner guards + transfer-ownership (closes PL A1, O2, X2).
Schema triggers landed Phase 2b (
infra/supabase/migrations/202606260000xx, zero-last-owner / zero-last-admin + child-consent gate, hardened in 2c). Facade verbstransferOwnership,grantOwner,revokeOwner,setRoleexist onclient.dart+client_impl.dartandHouseholdRepository(verified). Dart parity covered bypackages/client_sdk/test/services/household_service_authz_test.dart,test/cloud/authz_rls_test.dart,test/client/governance_facade_test.dart. - D-2 — Owner/Admin/Helper capability model — distinct overlays (closes PL O1/C1 at the code level).
packages/client_sdk/lib/src/models/capability.dartenum (40 capabilities) +services/authorizer.dartsets:_ownerCaps = {manageBilling, deleteHousehold, manageOwners, captureConsent, revokeConsent},_adminCaps(config + approvals),_helperCaps,_parentalOnlyCaps,_baseSelfCaps,_selfEconomyCaps;can/require/capabilitiesFor. Owner is NOT drawn as an Admin-superset — it is a separate overlay (if (m.owner) caps.addAll(_ownerCaps)), which is the resolution the persona-lens O1 asked for. Most❓matrix cells are resolved in code:approveSpendRequest/approveGoalRequestadmin-only;moveOwnFunds/viewOwnWallet/createOwnGoalbase-self; base Member has noviewHouseholdAll. - D-3 — COPPA consent binding (closes PL X3 core).
services/consent_service.dart:captureConsent/revokeConsentare owner-only (_ownerCaps), target must be a child (MemberKind.child), actor must be auth-linked (actor.authUserId != null); staticassertChildDataAllowedis the child-PII gate (throwsConsentRequired). SDK twin of the liveassert_child_goal_consenttrigger; wired intoEconomyService.createGoal/updateGoalandHouseholdService.setMemberTraits/setMemberCountry. Append-onlyconsentslog + immutability hardening live (Phase 2a–2c,ConsentRecord/ConsentPort). - D-4 — Helper completion-approval at the capability level (closes the capability half of PL X8).
Capability.approveCompletionis in both_adminCaps(authorizer.dart:82) and_helperCaps(authorizer.dart:94). The "Helper can approve a job" matrix cell is therefore resolved. Residual is FN-1 (attribution enum + service-guard widening). - D-5 — MemberAccess expiry model (closes PL H2 groundwork).
models/member_access.dart(memberId,expiresAt); Authorizer enforces expiry via param. Persistence table + babysitter UI deferred → DF-1. - D-6 — Supervised-action SDK path.
Capability.superviseAction+ optionalprincipalMemberIdonApprovalService.approve/autoApproveCompletion(Task 16,supervised_action_test.dart). Child-on-shared-device UX deferred → DF-2; attribution field → DF-3. - D-7 — Authz observability events.
services/authz_event_sink.dart:AuthzEventSink+AuthzEvent+NoOpAuthzEventSink; 5 events (authz_decision,authz_escalation_blocked,consent_state_changed,child_pii_write_rejected,supervised_action_committed), opaque-id-only payloads, fire-and-forgetsafeEmit(Task 17 + Phase 5+6 fix). Real provider wiring → DF-4. - D-8 — App authz UI.
routes/guards/admin_guard.dart(Authorizer().can(manageRoles)→canAccessAdmin = owner || can(manageRoles)),/governancepage +RoleOwnerBloc+role_owner_editor_sheet+consent_capture_sheet,shell/terms_session_gate.dart(TermsSessionGate) +TermsGateBloc,CurrentMemberRepositoryresolver. Admin hub at/adminwith Roles&owners / Rooms / Household-settings / Houses active. - D-9 — Token-economy enforced loop.
models/activity_gate.dart(first-class per-activity gate,requiredChoreId+minTokenBalance, enforced inEconomyService._enforceActivityGates,activityGatingflag-gated);models/earnings_split.dart(3 buckets give/save/spend, auto-split on approve, nobankbucket); append-onlyLedgerEntry+ zero-floor debit (service + SQL). - D-10 — Goal lifecycle preconditions (closes DG P2-F / SP1-c).
economy_service.dart:requestGoalguardsstatus != GoalStatus.active→ throws;completeGoalguardsstatus != GoalStatus.active;approveGoalguardsrequested+ parental. Covered bytest/services/economy_goal_lifecycle_test.dart. (The originalp1p2-audit.mdflagged these as missing — they were subsequently added and closed atb7b2b30.) - D-11 — 16 domain-gap items closed @
b7b2b30. See Domain-gap re-verify checklist below.
FIX-NOW — clear code fix, no open product decision
- FN-1 — Wire helper-completion attribution (PL X8 residual).
Capability is already there (D-4); what's missing is (a) the attribution enum value and (b) the
service guard still being parental-only.
- Files:
packages/client_sdk/lib/src/models/approval.dart(+approval.g.dartregen),services/approval_service.dart, plus doc twinsarchitecture/.../dynamics.md,code.md,features/token-economy.md(theresolvedByenum row). - Approach: add
ResolvedBy.helperManual; change the completion-approval gate from_requireParentalto_requireCapability(..., Capability.approveCompletion); stamphelperManualwhen the resolver holds helper-not-parental. - Size M. Deps: none (capability shipped). Note: needs build_runner (CI codegen).
- Files:
- FN-2 — Truth the persona docs to the shipped capability model (PL O1/C1, conflicts A/B/D).
Code already resolved Owner-vs-Admin (D-2); the docs are stale.
- Files:
architecture/features/personas.md(matrix Owner column + "effective vs overlay" framing),admin.md,dynamics.mdflow 1,code.md(Approval.resolvedBy). - Approach: rewrite the matrix as effective capability with a separate "what each overlay adds" line; Owner column = billing/ownership overlay only.
- Size S (doc). Deps: ratified by HS-1 (but the doc edit is truthing to code, so it may proceed).
- Files:
- FN-3 — Place watch-only in the persona model (PL M1, conflict G).
Code is done (
HouseholdMember.watchOnly+assignableMembers()filter); onlypersonas.mdlacks the placement.- Files:
architecture/features/personas.md(MemberStatus/overlay discussion). - Approach: define watch-only as a Member sub-state — tracked, excluded from assignment + active-roster, no login. Size S (doc).
- Files:
- FN-4 — Reconcile co-parent "delegated scopes" (PL A3, conflict C).
context.mdshows "Co-parent (delegated scopes)" butpersonas.md/admin.mdtreat coParent as full isParental admin (matches code:MemberKind.coParentunions_adminCaps).- Files:
architecture/.../context.md. - Approach: delete the "delegated/limited scopes" actor language for MVP-1 (coParent = full admin); leave a one-line note that scoped delegation is a post-MVP option. Size S (doc).
- Files:
DECIDE-THEN-FIX
Low-risk / reversible — safe to apply the recommended default in-loop
- LD-1 — Restore
descriptiononReward+Activity(TE §8). Verified dropped:reward.darthas nodescription/kind;activity.darthascategorybut nodescription. Rec: restore on both (additive nullableString?). Rationale: POC had it, it's purely additive, and the catalog forms need it. Code: add field +props+copyWith+ snake_case mapper on the cloud/in-memory adapters +Reward.g.dart/Activity.g.dartregen + a Supabase column migration. Reversible. Size M. - LD-2 —
Activity.categoryenum vs free-text (TE §8). Currently free-textString?(verified). Rec: keep free-text for MVP-1. Rationale: YAGNI — a typedActivityCategoryenum is a later filterable/themeable refinement; free-text unblocks the form now. Code: no change (status quo). Reversible (enum can wrap later). Size S. - LD-3 —
Reward.kind(activity|item) restore? (TE §8). Verified dropped. Rec: keep dropped. Rationale: the rebuild already models rewards and activities as separate entities, sokindis redundant. Code: no change. Reversible. Size S. - LD-4 — Gate reset cadence (TE §8). Current: chore-completion gate is satisfied by any approved
completion ever (one-time-permanent; no period scoping). Rec: keep one-time for MVP-1; add
daily/weekly re-lock in the activity-gating slice. Rationale: matches shipped behaviour; re-lock is
a
periodfield onActivityGatelater. Code: no change now. Reversible. Size S. - LD-5 — Gate granularity (TE §8). Current: per-activity household-wide gate (verified
ActivityGate.activityId). Rec: keep per-activity for MVP-1; per-kid named gates are a POC pattern to revisit. Code: no change. Reversible. Size S. - LD-6 — Gate status visibility (TE §8). UI contract, no SDK change. Rec: show the locked reason ("finish Tidy room") to both child and parent in the catalog when the gate UI is built. Rationale: neurodiversity-affirming clarity. Applies when the catalog browse UI ships. Size S.
- LD-7 —
titheflag → give-bucket (TE §8).titheis UI-only today (no SDK behaviour). Rec: leavegiveconfigured purely viaEarningsSplit; do not wiretithefor MVP-1. Rationale:EarningsSplit.givealready routes a give share; a second control is redundant. Code: no change. Reversible. Size S. - LD-8 —
MemberKindslot for a non-parent adult (PL H1). TodayMemberKind ∈ {parent, coParent, child}; a grandparent/babysitter/tutor maps to none, though Helper is already a role (MemberRole.helper) decoupled from kind. Rec: addMemberKind.otherAdult(tracked adult, not a legal guardian) and keep Helper as a role overlay. Rationale: gives non-parent adults a valid identity without overloadingparent. Code: add enum value + handle incapabilitiesFor/ any exhaustive switches + wire mappers. Reversible-ish (additive enum). Size M. - LD-9 — Multi-house role/owner scoping in docs (PL X1). Code already keys roles per
HouseholdMembermembership and the RLS helpers are per-household. Rec: state "roles + owner are per-household membership; one subscription per account managing N homes" inpersonas.md/roles-permissions.md/household.md. Code: no change (doc-truthing). Size S.
High-stakes / hard-to-reverse — require explicit user sign-off
- HS-1 — Ratify the capability-matrix + Owner-vs-Admin semantics (PL C1/O1). Code shipped a
specific resolution (D-2): Owner = distinct billing/ownership overlay
{manageBilling, deleteHousehold, manageOwners, captureConsent, revokeConsent}; Admin = config + job/spend/goal approvals; Helper =approveCompletion+viewHouseholdAll; base Member = self caps only. Rec: ratify as-shipped, then FN-2 truths the docs. Sign-off because changing the matrix later means rewriting capability sets + RLS + the authz test suite. - HS-2 — Intra-household per-member visibility (PL M3/X4). Capability layer already withholds
viewHouseholdAllfrom base members, but the data layer RLS is household-wide ("everyone in the house sees everyone"). A teen Member cannot hide wallet/goals/timeline from siblings; dashboards show every member's chips. Rec: for MVP-1 keep household-wide RLS (no per-member row hiding) but honour the capability scoping in read UIs; design a member-visibility scope as a fast-follow before multi-teen households are common. Sign-off because per-member RLS is expensive to retrofit. - HS-3 — Guardian-vs-admin decoupling / non-parental admin (PL A2/X3). Consent is currently bound
to Owner (a parental guardian:
owner ⇒ isParental), andadminrequiresisParental. Rec: KEEPadmin ⇒ isParentalfor MVP-1 and keep consent on Owner; DEFER non-parental admin (teen manager) to self-governed mode (DF-6); DEFER cross-house consent (divorced parents) and the fulleraseChildDataerasure-on-behalf cascade (DF-5). Sign-off because it's COPPA-legal-shaped. - HS-4 — Earn routing: auto-split vs "Unallocated" bucket (TE §8). Current: earn auto-splits at
approve via
EarningsSplit(give/save/spend, no bank). The POC'sbank/Unallocated maps to the ② Money "Unallocated envelope" draft and changes the earn side of the ledger loop. Rec: keep auto-split for MVP-1; treat Unallocated as ② Money rework, settled jointly with that page. Sign-off + coordinate with ② because it reshapes the ledger crediting path.
DEFERRED-BY-DESIGN
Out of scope now; one-line reason + unblock trigger. We are pre-alpha with NO real minor data, so the two HARD COPPA gates are intentionally not yet built.
- DF-1 —
member_accesspersistence + standalone (babysitter) helper invite (PL H2/C2/D2, NFR-AUTHZ-10). Model + Authorizer-param enforcement shipped (D-5); schema table + untracked-helper invite UI deferred. Unblocks: when a babysitter-only (non-member, time-boxed) invite flow is built. Also: widenapprovals_update+ledger_entries_insertRLS (migration20260612000002_tier0_domain.sql, currently gated onparental_household_ids()) to admit a helper-role member for completion-kind rows when helper cloud identity (DF-1) lands. Until then the helper-completion dual gate is SDK-only (CB-02 widenedCapability.approveCompletioninApprovalService; the Postgres twin is intentionally NOT yet widened). This is latent-safe: with no standalone helper cloud identity, every cloud write today runs under the parental account-holder's auth, so a non-parental helper can never exercise the SDK-only path against the DB. RW-08 (Money S2) adds a second same-shape widening: when DF-1 lands, widenledger_entries_insertto admit a member's OWNmove-kind rows (member_id = self, the paired debit+credit legs ofLedgerService.moveFunds) alongside the helper-completion widening — todaymoveFundsruns under the same parental auth, so the SDK-only self-move gate (Capability.moveOwnFunds) is latent-safe. - DF-2 — Supervised-action UX / shadow-child acting-for (PL M2 / Phase-7d). SDK ready
(
principalMemberId); child-on-shared-device UX → MVP-2 (kid-mode + TV wiring). - DF-3 —
Approval.principalMemberIdfield. Supervised attribution usesresolvedByMemberIdfor now; the dedicated field needs codegen. Unblocks: next approval-model codegen pass. - DF-4 — AuthzEventSink provider wiring + audit-log surface (PL X9). Sink + 5 events shipped
(D-7) with a no-op default; real provider + auto-fire
child_pii_write_rejectedat theEconomyService/HouseholdServicestatic gate sites + a user-facing audit-log surface deferred. Unblocks: when analytics/observability provider is config-enabled. - DF-5 — Consent lifecycle follow-ons (① review). Post-erasure retention/tombstoning,
shadow-member ToS ordering, full
eraseChildDatacascade, cross-house consent. Unblocks: before real minor data / erasure requests. - DF-6 — Peer / self-governed mode (PL X5).
governanceMode {familyGuardian, peer, solo}axis; research-only (docs/decisions/2026-06-25-self-governed-modes-single-user-peer.md). - DF-7 — PIN ownership / profile-switching (PL X6). → MVP-2 kid-mode-pin-lock.
- DF-8 — TV/kiosk display identity + privacy scope (PL X7). → MVP-2 TV/kiosk.
- DF-9 — Aging-up 13/18 transitions (PL M4). Capture an age-transition hook; ties to continuous kid identity. Unblocks: when eligibility transitions (Admin/self-governance) are built.
- DF-10 — Helper completion-approval notifications (PL H3). Notifications surface is unbuilt (Admin "Notifications" is a coming-soon row). Unblocks: when notifications ship → route to helpers.
- DF-11 — Helper visibility of child photo proofs (PL H4).
ChoreSubmissionhas no photo field yet (note-only). Unblocks: when photo submission ships → gate non-guardian helper visibility. - DF-12 — Therapist persona (PL H5). Future Helper sub-variant (scoped read-only/export).
- DF-13 — Free-tier billing surface + non-owner-admin paywall (PL O3/O4). Owner assignment at signup is done (creator → owner+admin); billing/subscription is unbuilt (Admin "Billing & plan" coming-soon). Unblocks: when subscription tiers ship.
- DF-14 — Backup/restore admin-vs-owner export (PL §5-H). Backup-restore-portability is unbuilt.
- HARD-1 — Child FINANCIAL-PII gate (① review, HARD COPPA gate). The consent gate covers PROFILE
writes (traits/country/goals) but not ledger earn credits / approvals / spend_requests /
redemptions / token_batches (named in
task-16-report.md). HARD gate required before any real minor financial data. Unblocks: before the first real minor's financial data is stored. - HARD-2 — Child consent re-capture on terms/privacy version bump (① review, HARD COPPA gate).
checkConsentCurrency/ re-consent transitions areTODO(consent-lifecycle). HARD gate required before real minor data. Unblocks: before a ToS/privacy version bump that affects existing minors.
Domain-gap re-verify checklist (D-11 — 16 items closed @ b7b2b30)
Do NOT re-implement. One-line smoke-check that each is wired into the current tree (and reachable
on the cloud app/lib/main_cloud_auth.dart path):
| ID | Item | Smoke-check |
|---|---|---|
| P1-A | Chore editor UI + assignedMemberIds picker | routes/authenticated/chore_editor/page.dart + blocs/chore_editor/bloc.dart reachable from Catalog FAB |
| P1-B | Today expectations filtered by assignedMemberIds | blocs/today_chores/bloc.dart _resolveDoneStates filters chore.assignedMemberIds (empty = all) |
| P1-C | Member editor (displayName/homePlaceId/watchOnly) | routes/authenticated/member_profile/page.dart + blocs/member_profile/bloc.dart expose home-room + watch-only |
| P1-D | setMemberHomePlace on facade | HouseholdRepository.setMemberHomePlace → client.dart (verified present) |
| P1-E | assignableMembers() on facade | HouseholdRepository.assignableMembers (verified present) |
| P1-F | Today excludes watchOnly from _kids + eligibility | blocs/today_chores/bloc.dart _onStarted + _BountiesSection._eligibleKids |
| P2-A | Per-room assignee picker | chore_editor roomAssignees map editor |
| P2-B | membersForRoom on facade + print path | ChoresRepository.membersForRoom (verified present) + print/printable_chore_list.dart |
| P2-C | Per-member step editor + step sign-off | chore_editor stepsPerMember editor + today_chore_row drill-down (Chore.stepsForMember) |
| P2-D | sweepExpiredTempBonuses facade + daily rollover | facade method + caller in app/lib/app/builder.dart startup/rollover |
| P2-E | today_chore_row uses effectiveTokens(now) not tokenValue | token pill calls chore.effectiveTokens(DateTime.now()) |
| P2-F | requestGoal/completeGoal status == active preconditions | economy_service.dart (VERIFIED DONE) |
| P2-G | Goals page (kid request + parent approval) | lives in member_profile page/bloc + repositories/goals/goals_repository.dart (no standalone /goals route — verify wiring) |
| P2-H | Multi-per-day bounty repeat-claim | blocs/today_chores/bloc.dart claimable filter uses completionCountToday < maxPerDay for multiPerDay |
| P2-I | Recommend dialog (stub-wired, empty-state) | recommend on facade + ChoresRepository.recommend (verified) → entry point dialog |
| P2-J | membersForRoom callers pass assignableMembers() | ChoresRepository/print path forwards assignableMembers() output |
Execution order (FIX-NOW + LOW-RISK DECIDE)
Dependency-ordered: SDK/facade/model changes before the docs and UI contracts that describe them. Pure decisions with no code (CB-04..CB-08) can be ratified at any point.
| CB | Item | Title | Bucket | Size |
|---|---|---|---|---|
| CB-01 | LD-1 | Restore description on Reward + Activity (model + adapters + migration + codegen) | DECIDE→FIX (low) | M |
| CB-02 | FN-1 | Approval.resolvedBy = helperManual + widen completion guard to require(approveCompletion) | FIX-NOW | M |
| CB-03 | LD-8 | Add MemberKind.otherAdult + keep Helper as a role overlay | DECIDE→FIX (low) | M |
| CB-04 | LD-2 | Ratify Activity.category = free-text for MVP-1 (no code) | DECIDE→FIX (low) | S |
| CB-05 | LD-3 | Ratify Reward.kind stays dropped (no code) | DECIDE→FIX (low) | S |
| CB-06 | LD-4 | Ratify gate reset = one-time-permanent for MVP-1 (no code) | DECIDE→FIX (low) | S |
| CB-07 | LD-5 | Ratify gate granularity = per-activity for MVP-1 (no code) | DECIDE→FIX (low) | S |
| CB-08 | LD-7 | Ratify tithe stays UI-only; give via EarningsSplit (no code) | DECIDE→FIX (low) | S |
| CB-09 | LD-6 | Gate status visibility contract (show locked reason to child + parent) | DECIDE→FIX (low) | S |
| CB-10 | FN-2 | Truth personas/admin/dynamics/code docs to the shipped capability model | FIX-NOW | S |
| CB-11 | FN-3 | Place watch-only as a Member sub-state in personas.md | FIX-NOW | S |
| CB-12 | FN-4 | Reconcile co-parent "delegated scopes" → full admin in context.md | FIX-NOW | S |
| CB-13 | LD-9 | State roles per-membership + owner/billing scope across houses (docs) | DECIDE→FIX (low) | S |
Gated on user sign-off (NOT in the auto-loop): HS-1, HS-2, HS-3, HS-4 (see High-stakes section). FN-2/CB-10 truths docs to shipped code, so it may run before HS-1 ratification; if the user changes the model in HS-1, re-run CB-10.