# M44 Company Page View Refactor ## Status - Plan: `M44_COMPANY_PAGE_VIEW_REFACTOR` - Status: `COMPLETE` - Activated: 2026-08-26 - Baseline: `93164c8` (`M43_GUILD_PAGE_VIEW_PILOT_COMPLETE`) - Owner authorization: continuation of the Owner-authorized layered Passive View + Presenter/ViewData + Domain/Application Service architecture. The next bounded extraction is the existing Company management surface already proven by the M16 controller pilot. ## Objective Extract the live DEV-6 Roster and Recruit Detail pages from `entry_shell.gd` into passive, UI-only Views while preserving their current authored composition, stable Recruit identity, selection/focus behavior, dismissal eligibility and return routes. This is a structural migration only; it does not redesign the Company pages or change Company, Market, Contract, Save, economy or localization semantics. ## Why this boundary `ABGCompanyPageController` already owns copied roster/detail facts and the Market-only/last-member dismissal guard. The remaining shell code is therefore presentation and intent wiring, making Roster + Recruit Detail the smallest load-bearing next extraction after M43. Dismissal Review and voluntary Contract Return remain separate shell-owned transaction surfaces and are not included in this plan. ## Target boundary ```text EntryShell / composition root -> CompanyPageController.snapshot() -> presentation-ready Roster / Recruit Detail ViewData -> ABGCompanyRosterPageView / ABGRecruitDetailPageView.render(ViewData) -> explicit selection / detail / dismissal / back intents -> EntryShell application and route boundaries ``` ## Player-visible stopping point - Roster still shows the same framed page, four-or-more stable member rows, selected member facts, Back to Guild, Dismiss and Open Detail controls. - Recruit Detail still shows the same frame, portrait, Profession, Trait, level/XP, equipment and battle-history facts, Back to Roster and Dismiss. - Selection changes only the local selected Recruit identity; detail and dismissal actions preserve the existing callbacks and stable IDs. - Dismiss remains enabled only when the copied Controller says it is eligible; the existing last-member and non-Market reasons remain truthful. - Missing Company/Recruit data renders a deterministic non-interactive fallback and does not mutate persistence. - Normal `100%` landscape output and the existing 44px authored short-screen targets remain unchanged. The Owner's normal-font rule applies; `130%` text-scale frames are supplemental and never a blocker. ## Frozen semantic nodes ### Roster `RosterFrame`, `RosterSafeArea`, `RosterLayout`, `RosterBody`, `RosterList`, `RosterMember0...`, `RosterDetail`, `RosterFooter`, `RosterBackGuild`, `RosterDismiss` and `RosterOpenDetail` remain stable. Each member button keeps its `recruit_id` metadata and portrait/name/fact children. ### Recruit Detail `RecruitDetailFrame`, `RecruitDetailSafeArea`, `RecruitDetailLayout`, `RecruitDetailBody`, `RecruitDetailPortrait`, `RecruitDetailFacts`, `RecruitDetailProfession`, `RecruitDetailTrait`, `RecruitDetailGrowth`, `RecruitDetailEquipment`, `RecruitDetailHistory`, `RecruitDetailFutureReason`, `RecruitDetailFooter`, `RecruitDetailBackRoster` and `RecruitDetailDismiss` remain stable. ## ViewData and intent boundary The Views consume deep-copied data from: - `ABGCompanyPageController.roster_snapshot(company, selected_id)` - `ABGCompanyPageController.recruit_detail_snapshot(company, recruit_id)` The Views emit only: ```text Roster: select_recruit(recruit_id), open_detail(recruit_id), dismiss(recruit_id), back Recruit Detail: dismiss(recruit_id), back ``` No intent carries a mutable Company object. EntryShell remains responsible for loading/saving Company state, dismissal/transaction calls, route transitions, and restoring focus. ## Forbidden View dependencies The new Views must not import or call `GuildContractService`, persistence, `RuntimeContentRegistry`, the compatibility facade, `current_screen`, `entry_shell.gd`, `company_path`, or any EntryShell global. They may use only the passive PageView/foundation helpers, `InitialCompanyArt`, copied ViewData and local presentation helpers. ## Ordered steps ### M44-A — Architecture contract, inventory and immutable baseline (`COMPLETE`) - Freeze the Roster/Recruit Detail node trees, copied Controller boundary, normalized/safe-area policy, focus/touch targets, invalid states and intent map before Runtime product changes. - Record the current M16/DEV-6 normal capture family as the immutable equivalence target at `760x360`/`zh_CN`, `844x390`/`en`, `1280x720`/`zh_CN` and `1280x720`/`en`; retain supplemental text-scale coverage without making it a gate. - Commit and push this activation boundary before adding View code. Acceptance: this plan is the only active implementation plan; tracked source, Company semantics, dismissal transactions and accepted MVP pages are unchanged. Completion record: - Source-bound baseline attempt: `m44-company-baseline/20260826T032132Z-32104`. - Source revision: `93164c87b845d3f0d6f1b64b6d1b06e7c4b8d66d`. - Evidence archive SHA-256: `43028f703434b5fe59a97153635b4a4500623ce7ee317c550c08b74699bcb86d`. - Required markers `ABG_M16_COMPANY_PAGES_OK`, `ABG_DEV6_ROSTER_OK` and `ABG_M16_COMPANY_CAPTURE_OK` each appeared exactly once; strict diagnostics were `0`, eight normal `100%` captures were retained, parsed touch passed, and owned workspace/process cleanup passed. - The first fresh-archive attempt that lacked Godot import preparation is retained as a harness failure only and is not acceptance evidence. The successful attempt imports the project before running the tests. M44-A is closed. M44-B, M44-C and M44-D are now complete. ### M44-B — Passive View extraction (`COMPLETE`) - Add `runtime/entry/views/company_roster_page_view.gd`, `runtime/entry/views/recruit_detail_page_view.gd` and isolated View contract coverage. - Move only Roster/Recruit Detail node construction, local formatting, portraits, focus and hit areas into the Views. - Mount both Views from EntryShell and translate only the six documented intent kinds. Keep `ABGCompanyPageController`, `GuildContractService`, dismissal review, persistence and route semantics outside the Views. Closure: source `19bf1392ce72f744e0fc9de79ef6393d5f165b9b` adds `ABGCompanyRosterPageView` and `ABGRecruitDetailPageView`, mounts both from EntryShell and wires only deferred `select_recruit`/`open_detail`/`dismiss`/ `back` intents. The former Roster/Recruit Detail builders are removed from EntryShell; Company facts, stable Recruit IDs, dismissal eligibility, transactions, persistence and routes remain outside the Views. The isolated View contract and M16/DEV-6/equipment/recovery focused checks pass with strict diagnostics `0` and exact-once markers. M44-C is now the sole `IN_PROGRESS` step. ### M44-C — Focused verification and visual equivalence (`COMPLETE`) - Run the isolated View contract, M16 controller, DEV-6 Roster/Detail and dismissal/equipment/recovery regressions with strict diagnostics `0` and exact-once markers. - Run the source-bound DEV-6 candidate and full MVP first-cycle audit. - Compare the four required normal `100%` Roster and Recruit Detail captures against the M44-A baseline at byte and decoded-pixel level. The existing focused M44-B verification is retained as a prerequisite; this step adds the source-bound DEV-6 candidate, full MVP first-cycle audit and capture-equivalence evidence. Closure: source-bound verification at `687160dd17c1af8b40163af9a060d7792a0d52a2` passes the isolated View contract, M16/DEV-6/equipment/recovery focused checks and the full MVP first-cycle audit with strict diagnostics `0`, exact-once markers, parsed touch and owned cleanup. The DEV-6 candidate reaches the pre-existing `contract_return_test.gd` failure recorded in `M44-I01`; all earlier DEV-1..6 checks pass and the failure reproduces the M44-A baseline, so no Company View scope was expanded. The eight Company Roster/Recruit Detail captures are byte-identical to the M44-A baseline with zero decoded-pixel differences at all four required normal `100%` fixtures. M44-D is now the sole `IN_PROGRESS` step. ### M44-D — Handoff (`COMPLETE`) - Record source-bound evidence in `docs/runtime/M44_COMPANY_PAGE_VIEW_VISUAL_AUDIT.md`. - Close only Roster and Recruit Detail. Dismissal Review, Contract Return, second-cycle systems/content, regions, endgame, device testing, packaging, signing, store/release and human acceptance remain outside this plan. - Update the checkpoint and development ledger, then push the focused closure. Closure: source `687160d` records the source-bound audit, visual-equivalence matrix and `M44-I01` baseline-known boundary in `docs/runtime/M44_COMPANY_PAGE_VIEW_VISUAL_AUDIT.md`. M44 is complete; no later implementation plan is activated by this handoff. ## Issue register | ID | Status | Boundary | | --- | --- | --- | | `M44-I01` | `BASELINE_KNOWN / OUT_OF_SCOPE` | `contract_return_test.gd` fails at the M44-A baseline because the accepted Market surface has no `MarketReturnContract` control; the test then dereferences `active_contract.contract_return_receipts`. This is a pre-existing second-cycle Contract Return issue, not introduced by the Company View extraction. It remains Shell-owned and is excluded from M44. | ## Frozen scope - No visual redesign, static-master editing, new assets/audio/animation or localization rewrite. - No changes to CompanyPageController rules, dismissal/equipment/Contract transactions, Market, Party, Risk, Battle, Save or economy semantics. - No mass rewrite of `entry_shell.gd`, global event bus, reflection service locator or two-way binding framework. - No deletion or staging of compatibility/history files, `.uid`, `.import` or `prototype_incremental/`. - No packaging, iOS export, signing, deployment, store or release work. ## Commit boundaries - `M44-A`: plan/checkpoint/ledger activation and immutable baseline. - `M44-B`: Roster + Recruit Detail Views and EntryShell integration. - `M44-C`: focused verification, capture comparison and evidence. - `M44-D`: handoff/closure. Each boundary must pass its narrowest focused checks and be pushed before the next step becomes `IN_PROGRESS`; a failed check keeps the same step active. ## Final handoff `ABG M44 COMPANY PAGE VIEW PILOT COMPLETE`