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

225 lines
10 KiB
Markdown

# 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`