Files
aetherbound-guild/docs/plans/M44_COMPANY_PAGE_VIEW_REFACTOR.md
T

10 KiB

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

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:

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