Skip to content

Commit 2b91062

Browse files
committed
과제방 HTTP surface를 제거하고 09 repository simplification을 종료한다
상황: 09의 마지막 범위는 `/api/classroom` HTTP 410 tombstone 제거였다. 계획은 안내를 담은 release를 한 번 게시한 뒤 지우는 것이었으나, 조사 결과 tombstone은 736bb9f(2026-07-23)에서 생겼고 이를 포함한 tag가 0개라 호환 창이 시작조차 하지 않았다. 사용자가 호환 release 없이 지금 닫기로 결정해 남은 범위를 전부 실행한다. 직전 commit이 도입한 두 phase 상태기계는 다시 열리지 않을 창을 위한 죽은 추상이 되므로 함께 걷어낸다. verifyPlanFactAudit는 감사 대상 initiative 경로를 하드코딩하고 있어 폴더 삭제 후 대상 0건으로 조용히 통과하는 거짓 green 상태였다. 변경: - src/codaro/api/classroomRetirementRouter.py를 삭제하고 server.py의 include_router, api/__init__.py의 import와 __all__ 항목을 제거했다. createServerApp() route table을 실제로 만들어 160개 route 중 classroom 경로가 0건임을 확인했다. - 직전 commit의 phase 머신러리를 철거했다. contracts/classroomRetirement.json, src/codaro/classroomRetirement.py, testClassroomRetirementWindow.py를 삭제하고 artifactOwners.yml 등록을 해제한 뒤 3개 런타임 생성물을 재생성했다. 그 작업에서 실제 결함이었던 부분만 남겼다. createClassroomRetirementRouter를 FORBIDDEN_SYMBOLS에 넣어 재유입을 영구 차단한다. - verifyClassroomRemoved.py를 단일 영구 계약으로 되돌렸다. active classroom source 0건, `/api/classroom` HTTP surface 0건, local migration 5개 연산 유지. REMOVED_PATHS에 삭제한 tombstone 경로를 추가하고 FORBIDDEN_ROUTE_TOKENS 검사를 새로 넣었다. - testClassroomArchive.py의 410 응답 단언을 실제 createServerApp() route table 검사로 교체했다. 빈 FastAPI에 404를 확인하는 형태는 무엇도 증명하지 못해 쓰지 않았다. - verifyPlanFactAudit.py의 INITIATIVE 하드코딩을 mainPlan/ 전체 순회로 바꿨다. initiative가 삭제돼도 대상 0건으로 통과하지 않고, 새 initiative는 등록 없이 감사된다. report에 activeInitiatives를 추가했다. - mainPlan/astryx-product-experience 트리를 삭제했다. 09가 마지막 workstream이라 mainPlan 규칙 7에 따라 initiative 폴더까지 지우고 mainPlan/README.md 활성 행을 비웠다. - 410을 현재 상태로 서술하던 문서를 정리했다. assignment-room.md는 호환 창 처리 결과를 기록으로 남기고, ssot-map.md·frontend-product-surface.md·testing-and-gates.md· tests/run.py gate 설명·contracts/README.md에서 tombstone 행과 문단을 제거했다. branding.md의 삭제된 설계 SSOT 포인터를 영구 owner로 교체했다. 영향: v0.0.12에서 쓰던 `/api/classroom` URL은 안내 응답 대신 404를 받는다. 호환 안내를 게시 없이 닫는 결정이며 assignment-room.md에 사실대로 기록했다. 기존 로컬 데이터 경로는 영향이 없다. audit, export, verify, purge CLI와 archive schema, purge ledger는 그대로 유지된다. mainPlan에 활성 이니셔티브가 없어졌고 남은 제품 작업은 영구 계약과 상시 gate가 소유한다. 검증: uv run python -X utf8 tests/run.py preflight -> 3/3 통과(root-clean, docs, backend 422s). gate removed-learning-concepts, architecture-boundary, plan-quality, repository-simplification -> 4/4 통과. uv run pytest -q tests/migrations/testClassroomArchive.py -> 12 passed. uv run python -X utf8 docs/skills/ops/tools/genProductContracts.py --check -> 7 files ok. syncAgentsMd.py --check -> ok. git diff --check -> 공백 오류 없음. 편집 문서 U+2014 0건. createServerApp() 실측: 총 route 160개, classroom 경로 0개. evaluation-contract gate는 깨끗한 worktree를 요구해 이 commit 뒤 재판정한다.
1 parent 566d293 commit 2b91062

25 files changed

Lines changed: 121 additions & 950 deletions

File tree

‎contracts/README.md‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
| `masteryPolicy.v1.json` | 단계 전이, retrieval window, clock anomaly 허용 오차 계약 | Python reference reducer와 TypeScript 동형 reducer |
2626
| `runRouteState.schema.json` | 공개 레슨, Web Run, Local 사이의 lesson identity, path, runtime, durable history 계약 | Landing handoff와 공용 editor route adapter |
2727
| `webCompatibilityC0.json` | 기존 `/codaro/app/` 제품 tree의 source·build·hash·response type 고정 계약 | Pages C0 build, C1 조립, deployed crawl |
28-
| `classroomRetirement.json` | 제거된 `/api/classroom`의 HTTP 410 호환 창이 열려 있는지 닫혔는지 고정하는 release 사실 | `verifyClassroomRemoved.py`의 phase 판정 |
2928

3029
학습 실행 증거는 `learningArtifactDescriptor.schema.json`을 공용 진입점으로 사용한다. 일반 파일·폴더와 달리 표와 이미지는 전용 schema에서 내용 구조까지 검증한다.
3130

@@ -36,5 +35,3 @@
3635
`CreditGranted.evidenceTime`은 실행 증거가 관측한 시각이고 `appendReceiptAt`은 canonical writer가 처음 수락한 시각이다. import는 두 값을 다시 쓰지 않는다. delayed retrieval은 두 시간축이 모두 window 안에 있고 경과 차이가 `masteryPolicy.v1.json`의 허용 오차 안일 때만 credit을 받는다. 역행·future skew·경과 불일치는 `ClockAnomaly`로 projection에 남고 해당 credit은 보류된다.
3736

3837
`webCompatibilityC0.json`은 `/codaro/app/`의 source commit, LF build 조건, deployed tree hash와 response type을 고정한다. Pages는 이 commit만 별도 checkout해 `/app/`을 만들고 `verifyWebCompatibilityC0.py`가 632개 파일의 exact tree identity와 배포 crawl을 검사한다. 정식 release archive URL·SHA-256은 명시적 release가 실행될 때만 채운다.
39-
40-
`classroomRetirement.json`은 tombstone을 언제 지워도 되는지가 code가 아니라 release 사건에 달려 있다는 사실을 저장소 안에 고정한다. `firstReleaseWithTombstone`이 `null`이면 호환 창이 열려 있어 410 router와 wiring이 있어야 하고, 게시된 release tag를 채우면 창이 닫혀 router와 모든 wiring이 없어야 한다. 그래서 이 필드를 채우는 commit이 곧 tombstone 제거 commit이다. tag를 fetch하지 않는 CI checkout에서는 선언이 유일한 판정 근거이며, tag를 읽을 수 있는 환경에서는 선언과 실제 release 이력의 drift까지 검사한다.

‎contracts/artifactOwners.yml‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,6 @@ artifacts:
8484
- .github/workflows/pages.yml
8585
- docs/skills/ops/tools/verifyWebCompatibilityC0.py
8686
- tests/product/verifyReleaseResearchOperations.py
87-
- artifactId: classroom-retirement
88-
role: source
89-
owner: product-release
90-
sourcePath: contracts/classroomRetirement.json
91-
surfacePaths:
92-
- src/codaro/classroomRetirement.py
93-
- tests/architecture/verifyClassroomRemoved.py
94-
- tests/architecture/testClassroomRetirementWindow.py
9587
- artifactId: learning-event
9688
role: source
9789
owner: learning-runtime

‎contracts/classroomRetirement.json‎

Lines changed: 0 additions & 36 deletions
This file was deleted.

‎docs/skills/architecture/assignment-room.md‎

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
id: assignment-room
33
title: Retired Assignment Room
4-
description: Removed classroom feature boundary, local archive migration, and one-release HTTP retirement contract.
4+
description: Removed classroom feature boundary, retired HTTP surface, and local archive migration contract.
55
category: architecture
66
section: learning
77
order: 216
@@ -17,28 +17,16 @@ whenToUse: classroom 참조를 발견했거나 기존 `~/.codaro/classroom` 데
1717

1818
## 남아 있는 경계
1919

20-
- `/api/classroom`과 모든 하위 HTTP 경로는 한 호환 release 동안 `410 Gone`만 반환한다.
21-
- 응답은 local-owner CLI의 audit, export, verify, purge 명령만 안내한다.
22-
- HTTP로 archive를 만들거나 내려받지 않는다.
23-
- `src/codaro/api/classroomRetirementRouter.py`는 호환 안내만 담당한다.
24-
- `tests/architecture/verifyClassroomRemoved.py`가 active classroom source, symbol, frontend import 재유입을 차단한다.
20+
- `/api/classroom`과 모든 하위 HTTP 경로는 존재하지 않는다. 제품은 이 접두사로 어떤 route도 서비스하지 않는다.
21+
- 기존 데이터는 HTTP가 아니라 local-owner CLI의 audit, export, verify, purge 명령으로만 다룬다.
22+
- `tests/architecture/verifyClassroomRemoved.py`가 active classroom source, symbol, HTTP surface 재유입을 차단한다.
23+
- `tests/migrations/testClassroomArchive.py`가 실제 `createServerApp()` route table에 classroom 경로가 없는지 확인하고 migration 동작을 회귀한다.
2524

26-
## 호환 창 phase
25+
## HTTP 호환 창 처리 기록
2726

28-
tombstone을 언제 지워도 되는지는 code 상태가 아니라 release 사건이 결정한다. 그 사건은 `contracts/classroomRetirement.json`이 저장소 사실로 선언하고, `src/codaro/classroomRetirement.py`가 phase를 판정한다.
27+
과제방 제거 당시 한 release 동안 HTTP `410 Gone` 안내를 유지하는 호환 창을 계획했다. 실제로는 그 안내를 담은 release가 게시되지 않았고, tombstone router는 게시 전에 제거했다. active classroom을 마지막으로 게시한 release는 `v0.0.12`이며, 그 버전의 URL을 그대로 호출하면 안내 응답 대신 `404`를 받는다. 기존 로컬 데이터 이관 경로는 이 결정과 무관하게 CLI로 유지된다.
2928

30-
| phase | 선언 | gate가 요구하는 것 |
31-
| --- | --- | --- |
32-
| `compatibility` | `firstReleaseWithTombstone: null` | tombstone router가 존재하고 `server.py`와 `api/__init__.py`에 등록돼 있으며 410·`classroom_retired`·CLI 안내를 담는다 |
33-
| `removal` | `firstReleaseWithTombstone: "<게시된 tag>"` | tombstone router와 모든 wiring이 없다 |
34-
35-
두 phase 모두 active classroom 재유입 금지와 local archive migration 보존을 똑같이 요구한다.
36-
37-
호환 창을 닫는 절차는 하나다. 410 안내가 포함된 release가 실제로 게시된 뒤, `firstReleaseWithTombstone`에 그 tag를 적고 같은 commit에서 router와 wiring을 지운다. 필드를 채우는 행위가 제거를 허용하는 동시에 요구하므로 선언과 tree가 어긋난 중간 상태는 gate가 막는다.
38-
39-
release tag를 읽을 수 있는 환경에서는 선언과 실제 이력의 drift도 검사한다. 아직 게시되지 않은 tag를 미리 적으면 실패하고, 반대로 tombstone이 이미 게시됐는데 선언이 `null`로 남아 있어도 실패한다. tag를 fetch하지 않는 shallow checkout에서는 선언이 유일한 판정 근거가 되며 drift 검사만 생략된다.
40-
41-
현재 상태는 `compatibility`다. active classroom은 `v0.0.12`가 마지막으로 게시했고, 410 안내를 포함한 release는 아직 없다.
29+
호환 안내를 다시 넣지 않는다. 재유입은 gate 실패로 처리한다.
4230

4331
## 로컬 데이터 이관
4432

@@ -70,12 +58,8 @@ codaro classroom purge --archive <archive.zip> --confirm-hash <sha256> --reason
7058
| archive audit/export/verify/purge | `src/codaro/migrations/classroomArchive.py` |
7159
| archive schema | `contracts/classroomArchive.schema.json` |
7260
| migration ledger schema | `contracts/classroomMigrationLedger.schema.json` |
73-
| HTTP 410 경계 | `src/codaro/api/classroomRetirementRouter.py` |
74-
| 호환 창 선언 | `contracts/classroomRetirement.json` |
75-
| 호환 창 phase 판정 | `src/codaro/classroomRetirement.py` |
76-
| migration 회귀 | `tests/migrations/testClassroomArchive.py` |
61+
| migration 회귀와 HTTP surface 부재 | `tests/migrations/testClassroomArchive.py` |
7762
| 제거 회귀 | `tests/architecture/verifyClassroomRemoved.py` |
78-
| phase 회귀 | `tests/architecture/testClassroomRetirementWindow.py` |
7963

8064
## 재도입 규칙
8165

‎docs/skills/architecture/frontend-product-surface.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Codaro의 프론트는 두 폴더 경계로 나눈다.
9898
- 현재 학습: `curricula/` 레슨 트리, YAML에서 전개된 학습 셀, 셀 바로가기 TOC, 접을 수 있는 Codaro 패널
9999
- 노트북: 빈 코드 셀, Python/Markdown 셀, 셀 바로 아래 실행 결과, 필요할 때 여는 Codaro 패널
100100
- 자동화: 검증된 셀/recipe를 저장하고 예약하는 두 번째 loop. `Codaro 자동화`, `나만의 자동화`, 태스크 예약과 실행 상태를 보여준다.
101-
- 과제방의 frontend와 active backend 도메인은 제거했다. 학습 실행·검증·진도 event는 classroom API, session, outbox를 import하지 않는다. 한 호환 release의 HTTP `410 Gone` 안내와 local-owner archive migration만 제품 밖 경계에 남는다.
101+
- 과제방의 frontend와 active backend 도메인은 제거했다. 학습 실행·검증·진도 event는 classroom API, session, outbox를 import하지 않는다. `/api/classroom` HTTP surface도 없으며 local-owner archive migration만 제품 밖 경계에 남는다.
102102
- tool call과 컨텍스트는 사용자가 검토해야 할 때 action log/diff/detail로 열 수 있게 한다. 학습 화면의 기본 우측 패널로 고정하지 않는다.
103103

104104
## 결정

‎docs/skills/architecture/ssot-map.md‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,8 @@ Codaro에서 기준 파일은 아래 순서로 본다. 같은 의미의 규칙
9898
| retired assignment room architecture | `docs/skills/architecture/assignment-room.md` | 제거된 과제방 경계와 local-owner 데이터 이관 계약 |
9999
| classroom archive migration | `src/codaro/migrations/classroomArchive.py` | 기존 `~/.codaro/classroom` audit, export, verify, purge와 crash recovery |
100100
| classroom archive schemas | `contracts/classroomArchive.schema.json`, `contracts/classroomMigrationLedger.schema.json` | archive와 purge ledger 형식 |
101-
| classroom retirement router | `src/codaro/api/classroomRetirementRouter.py` | 한 호환 release의 HTTP `410 Gone` 안내 경계 |
102-
| classroom compatibility window | `contracts/classroomRetirement.json`, `src/codaro/classroomRetirement.py` | tombstone 존치·제거를 가르는 release 사실 선언과 phase 판정 |
103-
| classroom migration regression | `tests/migrations/testClassroomArchive.py` | count/hash, redaction, exact-hash purge, lock과 crash recovery 회귀 |
104-
| classroom removal regression | `tests/architecture/verifyClassroomRemoved.py`, `tests/architecture/testClassroomRetirementWindow.py`, `tests/learning/verifyRemovedLearningConcepts.py` | active backend/frontend/source와 학습 side effect 재유입 차단, 호환 창 양쪽 phase 계약 |
101+
| classroom migration regression | `tests/migrations/testClassroomArchive.py` | count/hash, redaction, exact-hash purge, lock과 crash recovery 회귀, 실제 app route table의 classroom 경로 0건 |
102+
| classroom removal regression | `tests/architecture/verifyClassroomRemoved.py`, `tests/learning/verifyRemovedLearningConcepts.py` | active backend/frontend/source, `/api/classroom` HTTP surface와 학습 side effect 재유입 차단 |
105103

106104
## Automation System
107105

‎docs/skills/ops/foundation/testing-and-gates.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ uv run python -X utf8 tests/run.py gate attempts
168168
| `curriculum-top-tier-audit` | fast | 작성·의존성·구조 커버리지와 strong evidence·전이·회상 coverage를 분리해 검사하며, 하나라도 top-tier 필수 영역을 충족하지 못하면 실패한다. |
169169
| `curriculum-weakness-audit` | fast | 레슨 단위 약점(plan orphan, exercise/check 누락, hint 부재 등)을 Curriculum OS taxonomy 위에서 점검한다. |
170170
| `curriculum-executability` | fast | 모든 레슨의 snippet/solution을 누적 namespace에서 실행해 환경 무관 코드 결함(real-bug, yaml-load-error, undeclared-package)이 0인지 검사한다. missing-package/cascade/runtime-other는 정보성. |
171-
| `removed-learning-concepts` | fast | 제거된 학습자 예측과 active classroom 구현이 다시 들어오지 않고 로컬 archive migration이 남는지, `contracts/classroomRetirement.json`이 선언한 호환 창 phase대로 410 안내가 존재하거나 제거됐는지 검사한다. |
171+
| `removed-learning-concepts` | fast | 제거된 학습자 예측, active classroom 구현과 `/api/classroom` HTTP surface가 다시 들어오지 않고 로컬 archive migration만 남는지 검사한다. |
172172
| `repository-simplification` | fast | legacy 랜딩 수기 HTML·가짜 product frame, 미사용 curriculum illustration source, 추적된 landing 생성 module, Landing/editor 조립 파일의 도메인 ownership 재유입을 검사한다. |
173173
| `playwright-curriculum-runtime` | fast | Playwright 학습 트랙의 structured YAML 계약과 예제/정답 코드가 실제 Chromium에서 실행되는지 확인한다. |
174174
| `onboarding-browser` | surface | 브라우저에서 첫 화면 fallback, Provider 연결 행동, provider 연결 후 실제 응답 상태를 확인한다. |

‎docs/skills/ops/product/branding.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ whenToUse: 새 UI 컴포넌트 추가, 색/반지름/그림자 변경, 랜딩/
3939

4040
# Astryx 전환 규칙
4141

42-
- 활성 설계 SSOT는 `mainPlan/astryx-product-experience/README.md`다.
42+
- 설계 SSOT는 `assets/brand/designSystem/`의 토큰·컴포넌트 manifest와 `docs/skills/architecture/`의 제품 표면 계약이다. 임시 TODO 트리가 아니라 이 영구 계약과 상시 gate가 규칙을 소유한다.
4343
- 전환 순서는 product contract → design foundation → product shell → surface migration → quality release다.
4444
- migration이 끝나기 전 현재 editor의 shadcn token은 호환 기준으로만 유지한다. 새 색상, 반지름, 그림자, 별도 UI primitive를 이 layer에 추가하지 않는다.
4545
- 목표 공용 source는 `assets/brand/designSystem/tokens.json`이며 landing과 editor는 생성된 mirror를 사용한다. 한 제품 표면이 다른 표면의 내부 CSS나 컴포넌트를 직접 import하지 않는다.

‎editor/src/lib/generatedContracts/artifactOwnership.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Generated by docs/skills/ops/tools/genProductContracts.py.
22
// Source SHA-256: 4679b9c14619d69672ff06da0291dd45c71b100ee6e8a0b5698fb96cd55eb113
3-
// Owners SHA-256: 24aa69c76ebee1efb3951f5f6beed854b702952874fd321b1a5e170c9a1bcdd7
3+
// Owners SHA-256: eb4f5781e730dde1767c512c26f66b592da714f44596076139075353ffa15d67
44
export const ARTIFACT_OWNERSHIP_CONTRACT_SHA256 = "4679b9c14619d69672ff06da0291dd45c71b100ee6e8a0b5698fb96cd55eb113" as const;
5-
export const ARTIFACT_OWNERSHIP_OWNERS_SHA256 = "24aa69c76ebee1efb3951f5f6beed854b702952874fd321b1a5e170c9a1bcdd7" as const;
5+
export const ARTIFACT_OWNERSHIP_OWNERS_SHA256 = "eb4f5781e730dde1767c512c26f66b592da714f44596076139075353ffa15d67" as const;
66

77
export type ArtifactRole = "source" | "generated" | "packaged" | "evidence";
88

‎launcher/codaro-launcher/src/generated_contracts/artifact_ownership.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// Generated by docs/skills/ops/tools/genProductContracts.py.
22
// Source SHA-256: 4679b9c14619d69672ff06da0291dd45c71b100ee6e8a0b5698fb96cd55eb113
3-
// Owners SHA-256: 24aa69c76ebee1efb3951f5f6beed854b702952874fd321b1a5e170c9a1bcdd7
3+
// Owners SHA-256: eb4f5781e730dde1767c512c26f66b592da714f44596076139075353ffa15d67
44
use serde::{Deserialize, Serialize};
55

66
pub const ARTIFACT_OWNERSHIP_CONTRACT_SHA256: &str = "4679b9c14619d69672ff06da0291dd45c71b100ee6e8a0b5698fb96cd55eb113";
7-
pub const ARTIFACT_OWNERSHIP_OWNERS_SHA256: &str = "24aa69c76ebee1efb3951f5f6beed854b702952874fd321b1a5e170c9a1bcdd7";
7+
pub const ARTIFACT_OWNERSHIP_OWNERS_SHA256: &str = "eb4f5781e730dde1767c512c26f66b592da714f44596076139075353ffa15d67";
88

99
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1010
#[serde(rename_all = "camelCase")]

0 commit comments

Comments
 (0)