Skip to content

Commit a9f3903

Browse files
committed
학습: 자동저장 복원을 언어 독립 셀 상태로 고정
상황: - main d3d857e2의 CI run 30212156544에서 experience job만 web-learning 자동저장 최종 대기 중 timeout으로 실패했다. - 검증기는 data-notebook-active-cell을 조회했지만 NotebookPanel은 class만 렌더링했고, 복원 완료 여부도 한국어 문자열 셀 1 / 1에 결합돼 있었다. - 학습 section 정적 검증기는 현재 제품이 curriculum과 editor 모두에서 진단 내보내기를 숨기는 더 강한 조건 대신 과거의 짧은 조건 문자열을 요구했다. - Landing/Learning packet 문서는 전체 수동 접근성 matrix와 현재 구현 배포 증거의 책임 경계를 구분하지 못했다. 변경: - NotebookPanel의 활성 셀 상태에 data-notebook-active-cell, data-notebook-active-index, data-notebook-cell-count를 추가했다. - 자동저장 브라우저 검증을 표시 문구가 아니라 active index 1과 cell count 1 데이터 계약으로 판정하도록 바꾸고 회귀 테스트를 추가했다. - 학습 section 계약은 curriculum과 editor 양쪽의 진단 내보내기 억제를 현재 TopControls 조건과 동일하게 검사한다. - packet README에 design-system-contract, web-learning, landing-public의 실제 범위와 구현 commit 동일 Pages 배포 원칙을 기록하고, 전체 AT matrix owner를 04로 분리했다. 영향: - Web 학습 reload 후 편집 내용 제거와 1개 셀의 첫 활성 셀 복원을 locale에 관계없이 검증할 수 있다. - curriculum과 notebook editor의 집중 화면에는 진단 내보내기가 다시 노출되지 않는다. - 이번 구현은 Landing/Learning machine migration과 배포 증거 범위만 다루며 contrast, keyboard, screen-reader, Firefox, WebKit, WebView2 전체 검수는 04에 남는다. 검증: - npm run build (editor): 2731 modules, Vite 2.69초, passed. - uv run pytest -q tests/surface/testProductSurfaceContract.py: 19 passed. - verifyNotebookAutosavePlaywright.py --reuse-build: Web restore, Local bounded transition flush, document path ownership passed. - tests/run.py gate web-learning: 472/472 routes, Chromium 10/10, failure 0. - tests/run.py gate landing-public: Chromium 5/5, failure 0. - design-system-contract, docs, root-clean: passed. - tests/run.py preflight: 3/3, 415515ms; backend 1522 passed, 10 skipped, 1 warning, 8 subtests passed. - git diff --cached --check: passed.
1 parent d3d857e commit a9f3903

5 files changed

Lines changed: 35 additions & 9 deletions

File tree

editor/src/components/notebook/notebookPanel.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,13 @@ export function NotebookPanel({
225225
runningBlockId={runningBlockId}
226226
onRunNotebook={onRunNotebook}
227227
/>
228-
<span aria-hidden="true" className="notebookActiveCell">
228+
<span
229+
aria-hidden="true"
230+
className="notebookActiveCell"
231+
data-notebook-active-cell="true"
232+
data-notebook-active-index={selectedBlockIndex >= 0 ? selectedBlockIndex + 1 : 0}
233+
data-notebook-cell-count={document.blocks.length}
234+
>
229235
{activeCellLabel}
230236
</span>
231237
<div className="notebookPendingArea">

mainPlan/astryx-product-experience/01-design-foundation/02-landing-and-learning-migration/README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,21 @@
3636

3737
## 테스트
3838

39-
- `design-system-contract`
40-
- `learning-card-browser`
41-
- `learning-system-readiness`
42-
- Landing desktop screenshot review 완료, mobile/full mode matrix는 후속
39+
- `design-system-contract`: Landing·Learning·Run이 생성된 Astryx token과 공용 SNS registry를 소비하는지 확인한다.
40+
- `web-learning`: 472개 canonical route·lazy payload·sitemap·검색 일치, deep link, 자동 저장 reload, Web Run과 390px/1440px 대표 브라우저 화면을 확인한다.
41+
- `landing-public`: Home·Learn의 Web-first CTA, 실제 media, SEO, hydration과 390px/1440px 반응형 화면을 확인한다.
42+
- 전체 contrast·keyboard·screen-reader·Firefox·WebKit·WebView2 수동 matrix는 [04 visual/accessibility gates](../04-visual-accessibility-gates/)가 소유한다.
43+
44+
## 배포 증거
45+
46+
구현 commit을 먼저 `main`에 push하고 같은 commit을 source로 삼은 `Deploy Pages` run의 build·deploy 성공을 evidence commit에 보존한다. 이전 commit의 성공 배포나 working tree의 로컬 결과를 현재 구현의 배포 증거로 재사용하지 않는다.
4347

4448
## 롤백
4549

4650
URL parser와 initial selection을 함께 되돌린다. Landing 링크만 남겨 깨진 deep link를 만들지 않는다.
4751

4852
## 평가
4953

50-
대표 화면과 472개 canonical direct lesson은 구현됐다. Home·Learn 390px/1440px에서 image/text overlap과 lesson row 가독성을 검토하고 mobile hero 아래 다음 band가 보이도록 교정했다. 전체 접근성 수동 matrix와 실제 Pages 배포가 남아 완료가 아니다.
54+
현재 source에는 실제 제품 capture를 쓰는 Web-first Home, domain별 대표 경로를 우선하는 Learn, 472개 canonical direct lesson, URL 초기 선택과 별도 확인 없는 본문 전환이 구현됐다. Home·Learn과 학습 본문은 390px/1440px에서 image/text overlap, 가로 overflow, 이름 없는 버튼, 깨진 이미지가 0인지 브라우저 gate가 검사한다. Web 학습 자동 저장 검증은 번역된 문구 대신 `data-notebook-active-cell` 의미 표식을 사용해 locale과 무관하게 reload 복원을 판정한다.
55+
56+
이 packet은 clean 구현 commit의 `web-learning`·`landing-public`, 동일 commit의 실제 Pages 배포, 별도 evidence commit과 A→E→B 완료 전이가 모두 확인되기 전까지 진행 상태다. 전체 접근성 수동 matrix는 04의 잔여 범위이며 이 packet에 중복 완료 조건으로 두지 않는다.

tests/learning/verifyLearningSectionCardContract.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,8 @@ def main() -> int:
548548
)
549549
require(
550550
topBarText,
551-
'surface !== "curriculum" && showStatusNotice',
552-
"curriculum diagnostic export suppression",
551+
'surface !== "curriculum" && surface !== "editor" && showStatusNotice',
552+
"curriculum and editor diagnostic export suppression",
553553
failures,
554554
)
555555

tests/surface/testProductSurfaceContract.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,19 @@ def testLearningHomeAndLessonRenderInstructionalVisualsWithoutRevealControls() -
145145
assert "all 8 instructional learning-domain visuals must render" in browserGate
146146

147147

148+
def testNotebookAutosaveUsesLocaleIndependentActiveCellMarker() -> None:
149+
notebookPanel = _read("editor/src/components/notebook/notebookPanel.tsx")
150+
autosaveGate = _read("tests/surface/verifyNotebookAutosavePlaywright.py")
151+
152+
assert 'data-notebook-active-cell="true"' in notebookPanel
153+
assert "data-notebook-active-index={selectedBlockIndex >= 0 ? selectedBlockIndex + 1 : 0}" in notebookPanel
154+
assert "data-notebook-cell-count={document.blocks.length}" in notebookPanel
155+
assert 'querySelector("[data-notebook-active-cell=true]")' in autosaveGate
156+
assert 'activeCell?.dataset.notebookActiveIndex === "1"' in autosaveGate
157+
assert 'activeCell?.dataset.notebookCellCount === "1"' in autosaveGate
158+
assert 'includes("셀 1 / 1")' not in autosaveGate
159+
160+
148161
def testAppDelegatesProductSurfaceSelectionPolicy() -> None:
149162
app = _read("editor/src/App.tsx")
150163
selectionHook = _read("editor/src/hooks/useProductSurfaceSelection.ts")

tests/surface/verifyNotebookAutosavePlaywright.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,8 @@ def main(argv: list[str] | None = None) -> int:
492492
&& editors.every(
493493
editor => !(editor.textContent || "").includes("autosave_round_trip"),
494494
)
495-
&& (activeCell?.textContent || "").includes("셀 1 / 1");
495+
&& activeCell?.dataset.notebookActiveIndex === "1"
496+
&& activeCell?.dataset.notebookCellCount === "1";
496497
}""",
497498
timeout=20_000,
498499
)

0 commit comments

Comments
 (0)