From 9f7713267cae1344417debff5ead71d433842fae Mon Sep 17 00:00:00 2001 From: gahusb Date: Tue, 16 Jun 2026 07:57:01 +0900 Subject: [PATCH] =?UTF-8?q?docs(plan):=20Phase=201b=20codeblock=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=AA=A8=EB=93=88=ED=99=94=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EA=B3=84=ED=9A=8D=20(17=20=EB=9F=B0=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88,=20=EB=B0=94=EC=9D=B4=ED=8A=B8=20=EB=8F=99?= =?UTF-8?q?=EC=9D=BC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-06-16-codeblock-modularization.md | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-16-codeblock-modularization.md diff --git a/docs/superpowers/plans/2026-06-16-codeblock-modularization.md b/docs/superpowers/plans/2026-06-16-codeblock-modularization.md new file mode 100644 index 0000000..da77b10 --- /dev/null +++ b/docs/superpowers/plans/2026-06-16-codeblock-modularization.md @@ -0,0 +1,127 @@ +# Phase 1b — codeblock 메서드 모듈화 구현 계획 + +> **For agentic workers:** REQUIRED SUB-SKILL: superpowers:executing-plans 로 태스크 단위 구현. 단계는 `- [ ]` 체크박스. + +**Goal:** `gen-slaydeck.mjs` `writeCodeblocks()`의 메서드 161개를 연속-런 모듈 `cb/*.mjs`로 분리하되 출력 `SlayDeckController.codeblock`은 바이트 동일. + +**Architecture:** 단방향 의존 orchestrator→cb→lib. method/prop/codeblock 헬퍼+공유상수를 `lib/codeblock.mjs`로. 메서드는 **원본 순서 보존**을 위해 기능 버킷이 아닌 **연속 구간**으로 나눠 `writeCodeblocks`가 순서대로 spread-concat. prop 103개는 오케스트레이터 유지. + +**Tech Stack:** Node ESM. 검증 = `diffcheck`(codeblock 바이트 동일) + 미러 `node --test`. + +**의존:** Phase 1(#70)의 모듈 gen-slaydeck 위에 스택(`feature/cb-modularization`). #70 머지 후 main에 리베이스. + +--- + +## 🔑 검증 게이트 (모든 Task 공통) +각 추출 후: +``` +node tools/deck/gen-slaydeck.mjs +node tools/verify/diffcheck.mjs +``` +**합격**: `RootDesk/MyDesk/SlayDeckController.codeblock`(+ui·common) **IDENTICAL**. 워킹트리 ` M`은 autocrlf churn → `git checkout --`로 복원, **산출물은 커밋 안 함**(소스만). + +--- + +### Task 1: `lib/codeblock.mjs` — 헬퍼 + 공유 상수 추출 + +**Files:** Create `tools/deck/lib/codeblock.mjs`; Modify `tools/deck/gen-slaydeck.mjs` + +- [ ] **Step 1:** `lib/codeblock.mjs` 생성. gen-slaydeck.mjs에서 이동: + - 함수: `prop`·`method`·`codeblock` (정의 본문 그대로). + - `writeCodeblocks` 지역 상수 9개(현 `:292-300`): `RUN_LENGTH`(5) `GOLD_PER_WIN`(25) `CARD_PRICE`(30) `REST_HEAL`(30) `RELIC_PRICE`(60) `ACT_COUNT`(5) `ACT_MAPS`(['map01'..'map05']) `LOBBY_MAP`('lobby') `LOBBY_SPAWN`('Vector3(-5, 0.03, 0)'). → writeCodeblocks 본문에서 제거(import로 대체). + - 끝에 `export { prop, method, codeblock, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN };` + - ⚠️ `prop`/`method`/`codeblock`이 다른 헬퍼(없음 — 순수)·데이터를 참조하지 않는지 확인. 참조 시 함께 import. + +- [ ] **Step 2:** gen-slaydeck.mjs에 `import { prop, method, codeblock, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from './lib/codeblock.mjs';` 추가(기존 lib import 옆). + +- [ ] **Step 3:** 검증 게이트 → codeblock IDENTICAL → churn 복원. + +- [ ] **Step 4:** 커밋 +``` +git add tools/deck/lib/codeblock.mjs tools/deck/gen-slaydeck.mjs +git commit -m "refactor(cb): lib/codeblock.mjs로 헬퍼·상수 추출 (출력 바이트 동일)" +``` + +--- + +### 메서드 추출 공통 레시피 (Task 2~의 각 런) + +`writeCodeblocks`의 `const combat = codeblock('SlayDeckController','SlayDeckController', [], [\n method('OnBeginPlay', …),\n method('ReqLoadAscension', …),\n … 161개 …\n])` 에서 메서드 배열을 런별로 분리: +1. `tools/deck/cb/.mjs` 생성: +```js +import { method, RUN_LENGTH, GOLD_PER_WIN, CARD_PRICE, REST_HEAL, RELIC_PRICE, ACT_COUNT, ACT_MAPS, LOBBY_MAP, LOBBY_SPAWN } from '../lib/codeblock.mjs'; +import { /* lib/data.mjs 전체 — 자동 파생 */ } from '../lib/data.mjs'; +import { /* lib/ui-helpers.mjs 전체 — 자동 파생 */ } from '../lib/ui-helpers.mjs'; + +export const Methods = [ + method('', `…`, …), + …, // ← 원본 method() 호출 verbatim 이동 + method('', `…`, …), +]; +``` +2. writeCodeblocks의 해당 런 method() 호출 스팬을 제거하고, methods 배열을 spread로 교체: + `codeblock(…, [], [ ...bootMethods, ...stateMethods, …, ...shopMethods ])`. +3. **검증 게이트**(codeblock IDENTICAL) → churn 복원 → 커밋. +4. ⚠️ 메서드가 writeCodeblocks 지역변수/다른 메서드를 **JS레벨로 참조**하면(드묾) undefined throw/diffcheck로 노출 → 그 변수도 lib로 옮기거나 인자화. +- import 이름은 lib export에서 **자동 파생**(누락 방지). 메서드 본문은 Lua 문자열이라 보간(`${RUN_LENGTH}`·`${luaCardsTable(...)}`)만 JS평가. + +### 런 → 모듈 경계 (원본 순서, 161개) +| 모듈 | export | 첫 메서드 → 끝 메서드 | 수 | +|---|---|---|---| +| `cb/boot.mjs` | `bootMethods` | `OnBeginPlay` → `AscStartHpPenalty` | 11 | +| `cb/state.mjs` | `stateMethods` | `HideGameHud` → `CloseBoard` | 12 | +| `cb/soul.mjs` | `soulMethods` | `ShowSoulShop` → `ApplySoulUnlocks` | 11 | +| `cb/charselect.mjs` | `charSelectMethods` | `ShowCharacterSelect` → `SetEntityEnabled` | 5 | +| `cb/run.mjs` | `runMethods` | `StartRun` → `ReviveMonsterEntity` | 6 | +| `cb/deckturn.mjs` | `deckTurnMethods` | `Shuffle` → `RenderPiles` | 8 | +| `cb/deckview.mjs` | `deckViewMethods` | `OpenDeckInspect` → `ApplyAllDeckCardVisual` | 12 | +| `cb/hand.mjs` | `handMethods` | `GetHandSlotX` → `SelectDiscardSlot` | 18 | +| `cb/combat.mjs` | `combatMethods` | `PlayCard` → `ContinueAfterBoss` | 20 | +| `cb/jobs.mjs` | `jobMethods` | `ShowJobChoice` → `SetJob` | 5 | +| `cb/runend.mjs` | `runEndMethods` | `TeleportToActMap` → `EndRun` | 3 | +| `cb/render.mjs` | `renderMethods` | `BuffsLabel` → `RenderRun` | 12 | +| `cb/reward.mjs` | `rewardMethods` | `CardPool` → `PickReward` | 4 | +| `cb/items.mjs` | `itemMethods` | `HasRelic` → `RenderRelics` | 12 | +| `cb/tooltip.mjs` | `tooltipMethods` | `BuildCardKeywordTooltip` → `HideTooltip` | 6 | +| `cb/map.mjs` | `mapMethods` | `ShowMap` → `PickNode` | 7 | +| `cb/shop.mjs` | `shopMethods` | `ShowShop` → `OpenChest` | 9 | + +최종 concat 순서(= 원본): `[ ...bootMethods, ...stateMethods, ...soulMethods, ...charSelectMethods, ...runMethods, ...deckTurnMethods, ...deckViewMethods, ...handMethods, ...combatMethods, ...jobMethods, ...runEndMethods, ...renderMethods, ...rewardMethods, ...itemMethods, ...tooltipMethods, ...mapMethods, ...shopMethods ]`. + +--- + +### Task 2: 런 추출 배치 A (말단부터 — 위험 낮은 순) +**Files:** Create `cb/shop.mjs map.mjs tooltip.mjs items.mjs reward.mjs`; Modify gen-slaydeck.mjs + +- [ ] 레시피로 **shop → map → tooltip → items → reward** 추출·검증·커밋(런 1개당 또는 묶음당 게이트 통과 필수). + +### Task 3: 런 추출 배치 B +**Files:** Create `cb/render.mjs runend.mjs jobs.mjs combat.mjs`; Modify gen-slaydeck.mjs +- [ ] 레시피로 **render → runend → jobs → combat** 추출·검증·커밋. + +### Task 4: 런 추출 배치 C +**Files:** Create `cb/hand.mjs deckview.mjs deckturn.mjs run.mjs`; Modify gen-slaydeck.mjs +- [ ] 레시피로 **hand → deckview → deckturn → run** 추출·검증·커밋. + +### Task 5: 런 추출 배치 D (앞부분 — 마지막) +**Files:** Create `cb/charselect.mjs soul.mjs state.mjs boot.mjs`; Modify gen-slaydeck.mjs +- [ ] 레시피로 **charselect → soul → state → boot** 추출·검증·커밋. 완료 후 writeCodeblocks는 props 배열 + `[ ...17 spreads ]` + write만 남아야 함. + +--- + +### Task 6: 마무리 — RULES + 회귀 + PR + +**Files:** Modify `RULES.md` + +- [ ] **Step 1:** RULES §1의 gen-slaydeck 모듈 설명에 `tools/deck/cb/*.mjs`(메서드)·`tools/deck/lib/codeblock.mjs`(헬퍼·상수) 추가. 단일소스 표/보조 생성기 일관성 유지. +- [ ] **Step 2:** 회귀: `node --test tools/balance/sim-balance.test.mjs` · `node --test tools/map/rogue-map.test.mjs` (exit 0). +- [ ] **Step 3:** 최종 재생성 + 검증 게이트(누적 codeblock IDENTICAL). `git status --short` 산출물 변경 없음. +- [ ] **Step 4:** RULES 커밋 → push → PR(`node tools/git/gitea-pr.mjs create `, UTF-8). PR 제목·본문 한국어(RULES §4). + +--- + +## Self-Review +- **스펙 커버리지**: lib/codeblock(T1) · 메서드 17런 모듈화(T2~5) · prop 유지(범위 명시) · 바이트동일 게이트(공통) · RULES(T6) · 미러회귀(T6). 누락 없음. +- **플레이스홀더**: 런 경계는 첫/끝 메서드로 구체 지정(161개 합), 상수 9개 명시, import 자동 파생. "verbatim 이동"은 리팩터 특성(바이트 검증이 정확성 보장). +- **타입 일관성**: export명(`xMethods`)↔concat spread 일치. lib/codeblock export↔orchestrator/cb import 일치. +- **리스크**: 메서드 JS레벨 외부참조 → diffcheck/throw 즉시 노출, 증분으로 범위 최소. 단방향 의존 순환 없음.