T7 — Household Restructure Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: superpowers:subagent-driven-development. Steps use
- [ ]checkboxes. Status: DRAFT — paired withdocs/superpowers/specs/2026-06-24-t7-household-restructure-design.md. Build only after the user reviews the spec. Open-question defaults are resolved below (flagged ⚐ — user may override).
Goal: Household tab = read-only member-profile tiles (each holding individual goals) + a Family Goals section; member management moves to its own page under More → Account; goal request→approve wired end to end.
Architecture: UI + thin layers only — the SDK domain (roles, goals, wallet) is fully built. New GoalsRepository (thin), new blocs depend on repositories (never the facade directly / never drift/supabase). auto_route for the new routes.
Tech Stack: Flutter 3.44 / Dart 3.9 (FVM), bloc, auto_route, the existing DS atoms + flow-test harness (MocksContainer/testAppBuilder).
Global Constraints
- Layering: Bloc → Repository →
client_sdkfacade → Service. Presentation never imports drift/supabase/client_sdk/src. Goal rules stay inEconomyService. - Approval gate is
MemberKind.isParental(not the admin role).approveGoal({id, actingMemberId})requires a parentalactingMemberId. - GoalScope:
family⇒memberId == null;member⇒memberId != null. - Anti-corruption git guardrails (from the T4–T8 build): no
git reset/checkout <path>/clean/stash/add -A; explicitgit add <file>; nobuild_runner --delete-conflicting-outputs(scope--build-filter+ restore clobbered*.g.dart/router.gr.dart/state.g.dartsiblings from HEAD); before commit verify NO*_test.dartdeletions; the app test suite count MUST stay ≥ the phase's baseline. - i18n: new user-facing strings go through
Strings(avoid the T5 hardcoded-string drift). Immutability viacopyWith. a11y floor on every surface. - Branch:
feat/t7-household-restructureoffmain.
Resolved open-question defaults (⚐ = user may override)
- ⚐ watchGoals: ADD
Stream<List<Goal>> watchGoals({String? memberId, bool includeArchived})to the facade (consistent withwatchMembers/watchChores). If the user prefers, fall back to one-shotgetGoals+ refresh-on-mutation. - ⚐ Approval surface: requested goals appear (a) on the MemberProfile as a "Pending your OK" affordance to a parental viewer, and (b) as a small Household-level "N goal requests" badge. Acting (approving) member = the resolved current parental member (until SP2 auth lands, use the household's first
MemberKind.isParentalmember). - Members-management entry: More → Account group → Members (user-confirmed: own page under More/Account).
- ⚐ Role editing: include
MemberRoleediting (admin/helper/member chips, admin-only) on the management editor. Can be made read-only if the user prefers to defer.
Phase 1: Goal foundation (repository + optional watch + bloc)
Files:
- Create:
app/lib/outside/repositories/goals/goals_repository.dart - Modify (⚐ if watchGoals approved):
packages/client_sdk/lib/src/client/{client.dart,client_impl.dart}+services/economy_service.dart(+ the in-memory/cached/local adapters' goal read) to addwatchGoals. - Create:
app/lib/inside/blocs/goals/{bloc.dart,state.dart,events.dart} - Register the repository in the app runner (
RepositoriesAll). - Test:
app/test/unit/goals_bloc_test.dart,app/test/unit/goals_repository_test.dart(+ SDK test if watchGoals added).
Interfaces — Produces: GoalsRepository delegating createGoal/getGoals/requestGoal/approveGoal/completeGoal/archiveGoal/restoreGoal/updateGoal/goalProgress (+ watchGoals); GoalsBloc exposing family goals + per-member goals, with lifecycle events (request/approve/complete/archive/create/update).
- TDD the repository delegates + the bloc lifecycle transitions (family vs member filtering; parental-only approve; request→active). Mirror
HouseholdRepository+ an existing bloc. - Wire into the runner; analyze clean; app suite ≥ baseline; commit.
Phase 2: Members-management page (More → Account)
Files:
- Create:
app/lib/inside/routes/authenticated/members_management/page.dart(full CRUD list + add/edit/remove). - Move/refactor: T5's
members/member_editor_sheet.dartediting here; extend with role grants (admin/helper/member chips, admin-only ⚐) + remove (wire the missing remove path). - Modify:
more/page.dart→ add an Account section with a Members entry →MembersManagementRoute.router.dart→ add the route (under More). Regenerate router (scoped). - Test:
app/test/flows/members_management_test.dart.
Interfaces — Consumes: HouseholdRepository.{watchMembers,addMember,updateMember,removeMember,setMemberHomePlace}.
- TDD: open More → Account → Members; add/edit/remove a member; grant a role (admin-only gate); home-room + watch-only still editable. Run → fix → green.
- Router regen + restore clobbered siblings; analyze clean; suite ≥ baseline; commit.
Phase 3: Household tab → read-only profile tiles + Family Goals
Files:
-
Modify:
household/page.dart→ replace the inline editable members list with read-only profile tiles (avatar/emoji, name, age/role, a wallet glance viawalletOf, a🎯 N goalschip) that route toMemberProfileRoute; add a Family Goals card (GoalsBloc,scope == family) with add/edit; keep existing house config. -
Modify:
members_bloc.dart→ split read (tiles) from the management CRUD (now in Phase 2). -
Test:
app/test/flows/household_profiles_test.dart. -
TDD: Household shows profile tiles (goal-count chip + wallet glance) + a Family Goals section; tapping a tile routes to the profile; family-goal add works. Green.
-
analyze clean; suite ≥ baseline; commit.
Phase 4: MemberProfile page
Files:
- Create:
app/lib/inside/routes/authenticated/member_profile/page.dart+ a profile bloc (or reuse GoalsBloc + a member read). - Modify:
router.dart→MemberProfileRoutenested under the Household tab (param: memberId). Regenerate (scoped). - Test:
app/test/flows/member_profile_test.dart.
Interfaces — Consumes: HouseholdRepository (member read), walletOf(memberId), GoalsRepository (member-scoped goals).
- TDD: profile shows identity (name/emoji/age/traits/home-room/watch-only) + roles (read) + wallet glance (spend/save/give) + personal goals (
scope==member, memberId==this) with add + the request affordance. Green. - Router regen + restore siblings; analyze clean; suite ≥ baseline; commit.
Phase 5: Goal request → approve flow
Files:
-
Modify: the MemberProfile + Household — surface
requestedgoals (⚐ MemberProfile "Pending your OK" + Household badge); wirerequestGoal(member proposes) →approveGoal({id, actingMemberId})(parental approve) →active. -
Modify: resolve the acting parental member (household first-parental until SP2).
-
Test:
app/test/flows/goal_request_approve_test.dart+ unit coverage for the parental-only approve gate. -
TDD: a member requests a goal (→ requested, shows in the queue); a parental member approves (→ active, leaves the queue); a non-parental acting member is rejected. Green.
-
analyze clean; suite ≥ baseline; commit. Then final whole-branch review (flutter-reviewer) → finishing-a-development-branch.
Self-review notes
- Coverage: the spec's 6 build items map to phases — GoalsRepository/watchGoals (P1), Members-management+roles (P2), Household tiles+Family Goals (P3), MemberProfile+wallet glance+personal goals (P4), request→approve (P5). ✅
- Reuse: member editor + DS atoms + flow harness reused; net-new = members-management page, MemberProfile page, GoalsRepository/bloc.
- Risks: router/codegen clobber (Global Constraint covers restore); the T5→management relocation must keep existing T5 tests green (adjust, don't delete); the acting-member resolution is a placeholder until SP2 auth.