sonamu 0.8.21 → 0.8.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/api/config.d.ts +1 -1
  2. package/dist/api/config.d.ts.map +1 -1
  3. package/dist/api/config.js +1 -1
  4. package/dist/api/sonamu.d.ts +1 -1
  5. package/dist/api/sonamu.d.ts.map +1 -1
  6. package/dist/api/sonamu.js +14 -19
  7. package/dist/cone/cone-generator.js +29 -16
  8. package/dist/database/base-model.js +2 -2
  9. package/dist/database/db.d.ts +1 -1
  10. package/dist/database/db.d.ts.map +1 -1
  11. package/dist/database/db.js +1 -1
  12. package/dist/syncer/syncer.js +2 -2
  13. package/dist/testing/dev-test-routes.d.ts.map +1 -1
  14. package/dist/testing/dev-test-routes.js +4 -1
  15. package/dist/testing/global-setup.d.ts.map +1 -1
  16. package/dist/testing/global-setup.js +1 -4
  17. package/dist/ui/api.d.ts.map +1 -1
  18. package/dist/ui/api.js +11 -11
  19. package/dist/ui-web/assets/index-BrQKU3j9.css +1 -0
  20. package/dist/ui-web/assets/{index-DP968oXY.js → index-DIasN3Gt.js} +47 -47
  21. package/dist/ui-web/index.html +2 -2
  22. package/package.json +3 -3
  23. package/src/api/config.ts +1 -1
  24. package/src/api/sonamu.ts +15 -20
  25. package/src/cone/cone-generator.ts +39 -19
  26. package/src/database/base-model.ts +1 -1
  27. package/src/database/db.ts +1 -1
  28. package/src/skills/AGENTS.md +11 -1
  29. package/src/skills/sonamu/SKILL.md +42 -149
  30. package/src/skills/sonamu/cdd.md +172 -517
  31. package/src/skills/sonamu/cone.md +3 -4
  32. package/src/skills/sonamu/fixture-cli.md +1 -1
  33. package/src/skills/sonamu/workflow.md +72 -80
  34. package/src/syncer/syncer.ts +1 -1
  35. package/src/testing/dev-test-routes.ts +3 -0
  36. package/src/testing/global-setup.ts +0 -4
  37. package/src/ui/api.ts +6 -15
  38. package/dist/ui-web/assets/index-B7gc0Ygb.css +0 -1
  39. package/src/skills/project/business-logic.md +0 -270
  40. package/src/skills/project/requirements.md +0 -160
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/sonamu-ui/setting.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>{{projectName}}: Sonamu UI</title>
8
- <script type="module" crossorigin src="/sonamu-ui/assets/index-DP968oXY.js"></script>
9
- <link rel="stylesheet" crossorigin href="/sonamu-ui/assets/index-B7gc0Ygb.css">
8
+ <script type="module" crossorigin src="/sonamu-ui/assets/index-DIasN3Gt.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/sonamu-ui/assets/index-BrQKU3j9.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonamu",
3
- "version": "0.8.21",
3
+ "version": "0.8.23",
4
4
  "description": "Sonamu — TypeScript Fullstack API Framework",
5
5
  "keywords": [
6
6
  "typescript",
@@ -124,9 +124,9 @@
124
124
  "vite": "7.3.0",
125
125
  "vitest": "^4.0.10",
126
126
  "@sonamu-kit/hmr-hook": "^0.4.1",
127
- "@sonamu-kit/tasks": "^0.2.0",
127
+ "@sonamu-kit/hmr-runner": "^0.1.1",
128
128
  "@sonamu-kit/ts-loader": "^2.1.3",
129
- "@sonamu-kit/hmr-runner": "^0.1.1"
129
+ "@sonamu-kit/tasks": "^0.2.0"
130
130
  },
131
131
  "devDependencies": {
132
132
  "@biomejs/biome": "^2.3.13",
package/src/api/config.ts CHANGED
@@ -83,7 +83,7 @@ export type SonamuConfig<TSinkId extends string = string, TFilterId extends stri
83
83
  targets: string[]; // "web", "app" 등
84
84
  };
85
85
 
86
- database?: {
86
+ database: {
87
87
  // 데이터베이스(pg는 pg 모듈, pgnative는 pg-native 모듈의 설치가 필요합니다.)
88
88
  database?: "pg" | "pgnative";
89
89
  // 기본 데이터베이스 이름
package/src/api/sonamu.ts CHANGED
@@ -144,7 +144,11 @@ class SonamuClass {
144
144
  }
145
145
 
146
146
  private _workflows: WorkflowManager | null = null;
147
- get workflows(): WorkflowManager | null {
147
+ get workflows(): WorkflowManager {
148
+ if (this._workflows === null) {
149
+ throw new Error("Sonamu has not been initialized");
150
+ }
151
+
148
152
  return this._workflows;
149
153
  }
150
154
 
@@ -200,10 +204,8 @@ class SonamuClass {
200
204
  const { loadConfig } = await import("./config");
201
205
  this.config = await loadConfig(this.apiRootPath);
202
206
  // sonamu.config.ts 기본값 설정
203
- if (this.config.database) {
204
- this.config.database.database = this.config.database.database ?? "pg";
205
- this.config.database.defaultOptions.client = this.config.database.database ?? "pg";
206
- }
207
+ this.config.database.database = this.config.database.database ?? "pg";
208
+ this.config.database.defaultOptions.client = this.config.database.database ?? "pg";
207
209
 
208
210
  // 로깅 설정
209
211
  const { configureLogTape } = await import("../logger/configure");
@@ -214,13 +216,11 @@ class SonamuClass {
214
216
  }
215
217
 
216
218
  // DB 로드
217
- if (this.config.database) {
218
- const { DB } = await import("../database/db");
219
- this.dbConfig = DB.generateDBConfig(this.config.database);
220
- if (!doSilent) {
221
- const chalk = (await import("chalk")).default;
222
- console.log(chalk.green("DB Config Loaded!"));
223
- }
219
+ const { DB } = await import("../database/db");
220
+ this.dbConfig = DB.generateDBConfig(this.config.database);
221
+ if (!doSilent) {
222
+ const chalk = (await import("chalk")).default;
223
+ console.log(chalk.green("DB Config Loaded!"));
224
224
  }
225
225
 
226
226
  // Entity 로드
@@ -1306,11 +1306,6 @@ class SonamuClass {
1306
1306
  }
1307
1307
 
1308
1308
  private async initializeWorkflows(options: SonamuTaskOptions | undefined) {
1309
- // database 설정이 없으면 WorkflowManager를 초기화하지 않음
1310
- if (!this.config.database) {
1311
- return;
1312
- }
1313
-
1314
1309
  const { WorkflowManager } = await import("../tasks/workflow-manager");
1315
1310
  // NOTE: @sonamu-kit/tasks 안에선 knex config를 수정하기 때문에 connection이 아닌 config 째로 보냅니다.
1316
1311
  this._workflows = new WorkflowManager(DB.getDBConfig("w"));
@@ -1326,7 +1321,7 @@ class SonamuClass {
1326
1321
  };
1327
1322
 
1328
1323
  if (enableWorker) {
1329
- this._workflows?.setupWorker({
1324
+ this.workflows.setupWorker({
1330
1325
  ...defaultWorkerOptions,
1331
1326
  ...options.workerOptions,
1332
1327
  });
@@ -1339,7 +1334,7 @@ class SonamuClass {
1339
1334
 
1340
1335
  server.addHook("onClose", async () => {
1341
1336
  await options.lifecycle?.onShutdown?.(server);
1342
- await this.workflows?.destroy();
1337
+ await this.workflows.destroy();
1343
1338
  await this.destroy();
1344
1339
  });
1345
1340
 
@@ -1363,7 +1358,7 @@ class SonamuClass {
1363
1358
  server
1364
1359
  .listen({ port, host })
1365
1360
  .then(async () => {
1366
- await this.workflows?.startWorker();
1361
+ await this.workflows.startWorker();
1367
1362
  await options.lifecycle?.onStart?.(server);
1368
1363
  })
1369
1364
  .catch(async (err) => {
@@ -84,35 +84,55 @@ function getApiKey(): string {
84
84
  }
85
85
 
86
86
  /**
87
- * 프로젝트 루트의 .claude/skills/project/*.md 파일들을 읽어 컨텍스트로 반환합니다.
87
+ * 도메인별 {domain}.contract.md와 architecture.md 읽어 컨텍스트로 반환합니다.
88
88
  *
89
- * requirements.md 프로젝트의 비즈니스 요구사항과 도메인 지식을 담은 파일들을
90
- * cone 생성 LLM에게 전달하여 현실적인 메타데이터를 생성하도록 합니다.
89
+ * - contract/{domain}/{domain}.contract.md: 도메인 규칙과 결정 근거 (주 참조 대상)
90
+ * - .claude/skills/project/architecture.md: 엔티티 설계 구조 (보조 참조)
91
+ *
92
+ * cone 생성 시 LLM에게 전달하여 도메인 맥락에 맞는 메타데이터를 생성하도록 합니다.
91
93
  */
92
94
  function readProjectSkills(): string {
93
95
  try {
94
96
  const { Sonamu } = require("../api");
95
97
  const projectRoot = Sonamu.appRootPath;
96
- const skillsDir = path.join(projectRoot, ".claude", "skills", "project");
97
-
98
- if (!fs.existsSync(skillsDir)) {
99
- return "";
100
- }
98
+ const contents: string[] = [];
101
99
 
102
- const files = fs
103
- .readdirSync(skillsDir)
104
- .filter((f: string) => f.endsWith(".md"))
105
- .sort();
106
- if (files.length === 0) {
107
- return "";
100
+ // contract/**/*.contract.md 수집
101
+ const contractDir = path.join(projectRoot, "contract");
102
+ if (fs.existsSync(contractDir)) {
103
+ const domains = fs
104
+ .readdirSync(contractDir, { withFileTypes: true })
105
+ .filter((d) => d.isDirectory())
106
+ .map((d) => d.name);
107
+
108
+ for (const domain of domains) {
109
+ const domainDir = path.join(contractDir, domain);
110
+ const contractFiles = fs
111
+ .readdirSync(domainDir)
112
+ .filter((f: string) => f.endsWith(".contract.md"));
113
+
114
+ for (const file of contractFiles) {
115
+ const filePath = path.join(domainDir, file);
116
+ const content = fs.readFileSync(filePath, "utf-8").trim();
117
+ if (content) {
118
+ contents.push(`--- contract/${domain}/${file} ---\n${content}`);
119
+ }
120
+ }
121
+ }
108
122
  }
109
123
 
110
- const contents: string[] = [];
111
- for (const file of files) {
112
- const filePath = path.join(skillsDir, file);
113
- const content = fs.readFileSync(filePath, "utf-8").trim();
124
+ // .claude/skills/project/architecture.md 보조 참조
125
+ const architecturePath = path.join(
126
+ projectRoot,
127
+ ".claude",
128
+ "skills",
129
+ "project",
130
+ "architecture.md",
131
+ );
132
+ if (fs.existsSync(architecturePath)) {
133
+ const content = fs.readFileSync(architecturePath, "utf-8").trim();
114
134
  if (content) {
115
- contents.push(`--- ${file} ---\n${content}`);
135
+ contents.push(`--- architecture.md ---\n${content}`);
116
136
  }
117
137
  }
118
138
 
@@ -415,7 +415,7 @@ export class BaseModelClass<
415
415
  const { default: SqlParser } = await import("node-sql-parser");
416
416
  const parser = new SqlParser.Parser();
417
417
  const parsedQuery = parser.astify(countPuri.toQuery(), {
418
- database: Sonamu.config.database?.database,
418
+ database: Sonamu.config.database.database,
419
419
  });
420
420
 
421
421
  const leftJoinTables = getJoinTables(parsedQuery, ["LEFT JOIN"]);
@@ -157,7 +157,7 @@ export class DBClass {
157
157
  this.workerDBs.clear();
158
158
  }
159
159
 
160
- public generateDBConfig(config: NonNullable<SonamuConfig["database"]>): SonamuDBConfig {
160
+ public generateDBConfig(config: SonamuConfig["database"]): SonamuDBConfig {
161
161
  const defaultKnexConfig: Partial<DatabaseConfig> = assign(
162
162
  {
163
163
  client: "postgresql",
@@ -68,4 +68,14 @@ Read the listed skill file before attempting any workaround or fix in these situ
68
68
  | Writing or modifying a `@upload` method | `api.md` |
69
69
  | Database query returning unexpected results | `puri.md` |
70
70
  | Migration error or schema change | `migration.md` |
71
- | Spec status gate or testRef validation failing | `cdd.md` |
71
+ | Starting AC+Claim-based development or writing a Claim | `cdd.md` |
72
+ | Applying Auth Guards or handling session/permission logic | `auth.md` |
73
+ | Implementing polymorphic relations with `entity_type` + `entity_id` pattern | `entity-relations.md` |
74
+ | Writing Puri SELECT / WHERE / JOIN / FTS / pgvector queries | `puri.md` |
75
+ | Implementing `@upload` file upload or deciding parameter pattern | `api.md`, `framework-change.md` |
76
+ | Reading or writing files under `contract/rules/` | `cdd.md` |
77
+ | Implementing `BaseAgentClass` or `@tools` decorator | `ai-agents.md` |
78
+ | Implementing background jobs or cron scheduling | `tasks.md` |
79
+ | Batch-saving relation data (upsert) | `upsert.md` |
80
+ | Adding a new entity or enum and registering i18n keys | `i18n.md` |
81
+ | Implementing pgvector embeddings or vector search | `vector.md` |
@@ -26,13 +26,13 @@ Sonamu 프레임워크로 프로젝트를 개발하기 위한 Claude Code skill
26
26
  ## 개발 흐름
27
27
 
28
28
  ```
29
- PHASE 0: 프로젝트 생성 및 초기 설정 (프로젝트 생성 → requirements.md/business-logic.md 작성 → auth generate → Users 시퀀스 설정)
30
- PHASE 0.5: Contract Spec 작성 (main.contract.json → 도메인별 contract spec → 사용자 검토 완료)
31
- PHASE 1: 엔티티 설계 (사용자와 함께 설계 확인)
32
- PHASE 2: 엔티티 생성 및 마이그레이션 (entity.json + migration + cone + scaffolding)
33
- PHASE 3: 테스트 및 API 구현 (batch별 테스트 API 구현 반복)
34
- PHASE 4: Fixture 생성 (사용자 승인 후 LLM으로 생성)
35
- PHASE 5: Frontend 개발 (batch별 진행, 사용자 확인)
29
+ PHASE 0: 프로젝트 생성 및 초기 설정 (프로젝트 생성 → 도메인 식별 → auth generate → Users 시퀀스 설정)
30
+ PHASE 1: 도메인 Logic 문서화 (도메인별 contract/{domain}/*.contract.md 작성 → 사용자 확인 완료)
31
+ PHASE 2: 엔티티 설계 (사용자와 함께 설계 확인)
32
+ PHASE 3: 엔티티 생성 및 마이그레이션 (entity.json + migration + cone + scaffolding)
33
+ PHASE 4: 테스트 및 API 구현 (contractClaim→AC→implement 반복)
34
+ PHASE 5: Fixture 생성 (사용자 승인 후 LLM으로 생성)
35
+ PHASE 6: Frontend 개발 (batch별 진행, 사용자 확인)
36
36
  ```
37
37
 
38
38
  **상세 내용:** `workflow.md` 참조
@@ -44,14 +44,14 @@ PHASE 5: Frontend 개발 (batch별 진행, 사용자 확인)
44
44
  | 사용자 지시 | 시작 PHASE | 전제 조건 확인 |
45
45
  |------------|------------|----------------|
46
46
  | "새 프로젝트 만들어줘" | PHASE 0 | — |
47
- | "contract 작성해줘" / "spec 작성해줘" | PHASE 0.5 | requirements.md, business-logic.md 존재 |
48
- | "엔티티 추가해줘" / "엔티티 생성해줘" | PHASE 1 | 프로젝트 존재, dev 서버 실행 중, skills/project/ 문서 읽기, contract/spec 완료 |
49
- | "테스트 작성해줘" / "API 구현해줘" | PHASE 3 | entity.json 존재, migration 완료, scaffolding 완료 |
50
- | "fixture 생성해줘" | PHASE 4 | 테스트 통과, cone.note 존재 확인 |
51
- | "프론트엔드 개발해줘" | PHASE 5 | API 구현 완료 |
47
+ | "contract 작성해줘" / "도메인 분석해줘" | PHASE 1 | 도메인 목록 식별 완료 |
48
+ | "엔티티 추가해줘" / "엔티티 생성해줘" | PHASE 2 | 프로젝트 존재, dev 서버 실행 중, contract/**/*.contract.md 읽기, PHASE 1 완료 |
49
+ | "테스트 작성해줘" / "API 구현해줘" | PHASE 4 | entity.json 존재, migration 완료, scaffolding 완료 |
50
+ | "fixture 생성해줘" | PHASE 5 | 테스트 통과, cone.note 존재 확인 |
51
+ | "프론트엔드 개발해줘" | PHASE 6 | API 구현 완료, contract/**/*.contract.md 확인 |
52
52
 
53
53
  **중간 진입 시 규칙:**
54
- 1. `skills/project/` 하위 문서(requirements.md, architecture.md, business-logic.md)가 있으면 반드시 먼저 읽는다
54
+ 1. `contract/**/*.contract.md` 및 `skills/project/architecture.md`가 있으면 반드시 먼저 읽는다
55
55
  2. 해당 PHASE의 전제 조건이 충족되었는지 확인한다
56
56
  3. 충족되지 않으면 사용자에게 알리고 필요한 단계부터 진행한다
57
57
  4. 해당 PHASE 내에서는 `workflow.md`의 넘버링된 Step을 순서대로 진행한다. 어떤 Step도 건너뛰지 않고, 자체 판단으로 병합하지 않는다
@@ -62,159 +62,52 @@ PHASE 5: Frontend 개발 (batch별 진행, 사용자 확인)
62
62
 
63
63
  ### CRITICAL: 작업 시작 전 필수 확인
64
64
 
65
- **프로젝트 작업을 시작하기 전에 반드시 `skills/project/` 하위의 모든 문서를 읽으세요.**
65
+ **프로젝트 작업을 시작하기 전에 반드시 다음 문서를 읽으세요.**
66
66
 
67
67
  ```
68
- skills/project/
69
- ├── requirements.md # 요구사항 정의
70
- ├── architecture.md # 엔티티 설계 + 시스템 아키텍처
71
- └── business-logic.md # 사용자 권한별 비즈니스 로직
72
- ```
73
-
74
- ### 문서 작성 시점
75
-
76
- #### 1. requirements.md
77
- **언제:** 사용자로부터 요구사항을 받았을 때
78
- **내용:**
79
- - 프로젝트 목표 및 배경
80
- - 기능 요구사항 (FR)
81
- - 비기능 요구사항 (NFR)
82
- - 제약사항 및 전제조건
83
-
84
- **예시:**
85
- ```markdown
86
- # 요구사항 정의
87
-
88
- ## 프로젝트 목표
89
- 온라인 병원 예약 시스템
68
+ contract/
69
+ └── {domain}/
70
+ └── {domain}.contract.md # PHASE 1: 도메인 규칙 + 결정 근거 (영구 문서, 코드 변경 시 함께 갱신)
90
71
 
91
- ## 기능 요구사항
92
- 1. 환자가 의사를 검색하고 예약할 수 있어야 함
93
- 2. 의사가 진료 일정을 관리할 수 있어야 함
94
- ...
72
+ .claude/skills/project/
73
+ └── architecture.md # 엔티티 설계 + 시스템 아키텍처
95
74
 
96
- ## 사용자 유형
97
- - 관리자: 시스템 전체 관리
98
- - 의사: 진료 일정, 환자 기록 관리
99
- - 환자: 예약, 진료 내역 조회
100
- - 병원: 의사 관리, 통계 확인
75
+ tmp/claims/ # 진행 중 Claim YAML (완료 후 폐기)
101
76
  ```
102
77
 
103
- #### 2. architecture.md
104
- **언제:** 엔티티를 설계하거나 시스템 아키텍처를 논의할 때
105
- **내용:**
106
- - Entity 구조 및 관계 설계
107
- - 데이터베이스 스키마
108
- - API 엔드포인트 설계
109
- - 시스템 컴포넌트 구조
78
+ **Ground truth는 코드다.** `*.contract.md`는 코드 결정의 근거 기록이지 선행 정의서가 아니다. 코드와 `*.contract.md`가 충돌하면 코드를 우선한다.
110
79
 
111
- **예시:**
112
- ```markdown
113
- # 시스템 아키텍처
114
-
115
- ## 엔티티 설계
116
-
117
- ### User (사용자)
118
- - id: number (PK)
119
- - username: string
120
- - email: string
121
- - role: enum (admin, doctor, patient, hospital)
122
-
123
- ### Doctor (의사)
124
- - id: number (PK)
125
- - user_id: number (FK → User)
126
- - specialty: string
127
- - hospital_id: number (FK → Hospital)
128
-
129
- ### Appointment (예약)
130
- - id: number (PK)
131
- - patient_id: number (FK → User)
132
- - doctor_id: number (FK → Doctor)
133
- - appointment_date: datetime
134
- - status: enum (pending, confirmed, cancelled)
135
-
136
- ## 관계
137
- - User ← Doctor (BelongsToOne)
138
- - User ← Appointment.patient (BelongsToOne)
139
- - Doctor ← Appointment.doctor (BelongsToOne)
140
- ```
80
+ ### 도메인 `*.contract.md`
141
81
 
142
- #### 3. business-logic.md
143
- **언제:** 사용자 권한별 비즈니스 로직을 정의할 때
144
- **내용:**
145
- - 각 사용자 유형(role)별 권한
146
- - 비즈니스 규칙 및 제약사항
147
- - 상태 전이 규칙
148
- - 검증 로직
82
+ 도메인 규칙을 응집된 형태로 기술하고, 코드만으로는 파악하기 어려운 결정 근거를 함께 기록한다.
149
83
 
150
- **예시:**
151
84
  ```markdown
152
- # 비즈니스 로직
153
-
154
- ## 사용자 권한
155
-
156
- ### 관리자 (admin)
157
- - 모든 데이터 CRUD 가능
158
- - 사용자 role 변경 가능
159
- - 시스템 설정 관리
160
-
161
- ### 의사 (doctor)
162
- - 자신의 일정 관리 (CRUD)
163
- - 예약 확인/취소
164
- - 환자 진료 기록 조회/작성
165
- - 다른 의사 데이터 조회 불가
166
-
167
- ### 환자 (patient)
168
- - 의사 검색 및 조회
169
- - 예약 생성/조회/취소 (자신의 예약만)
170
- - 자신의 진료 기록 조회
171
- - 다른 환자 데이터 접근 불가
172
-
173
- ### 병원 (hospital)
174
- - 소속 의사 관리
175
- - 병원 통계 조회
176
- - 소속 의사의 예약 현황 조회
177
-
178
- ## 예약 상태 전이
179
- pending → confirmed (의사 확인)
180
- pending → cancelled (환자/의사 취소)
181
- confirmed → cancelled (환자/의사 취소, 24시간 전까지만)
182
-
183
- ## 비즈니스 규칙
184
- 1. 예약은 진료 24시간 전까지만 취소 가능
185
- 2. 의사는 동시에 2개 이상 예약 불가
186
- 3. 환자는 같은 의사에게 1주일에 1번만 예약 가능
187
- ```
85
+ # {도메인} 비즈니스 로직
188
86
 
189
- ### 문서 업데이트 규칙
87
+ ## 규칙
88
+ - 환불은 결제 후 7일 이내만 가능 [근거: PG사 정책]
89
+ - 주문 상태 전환: 대기 → 확인 → 배송 → 완료
190
90
 
191
- **CRITICAL: 설계 변경 시 즉시 문서 업데이트**
91
+ ## 워크플로우
92
+ 1. ...
93
+ ```
192
94
 
193
- 1. **대화 설계가 변경되면:**
194
- - 해당 문서를 즉시 업데이트
195
- - 변경 이유와 컨텍스트를 기록
95
+ **두 가지 개발 경로:**
96
+ - **신규**: `*.contract.md` 작성 → Claim → AC(테스트명) → implement (TDD 방식)
97
+ - **변경**: 코드 수정 → Claim 등록 → `*.contract.md` 확인/갱신 (변경 근거 기록)
196
98
 
197
- 2. **변경 기록 형식:**
198
- ```markdown
199
- ## 변경 이력
99
+ **갱신 규칙:**
100
+ - 코드 변경 시 영향받는 도메인 규칙을 확인하고 `*.contract.md`도 함께 업데이트
101
+ - 변경 이유와 결정 근거를 함께 기록 — 이것이 `*.contract.md`를 살아있게 유지
200
102
 
201
- ### 2026-02-10: Appointment 상태 필드 추가
202
- **변경 내용:** status 필드 추가 (pending, confirmed, cancelled)
203
- **이유:** 예약 취소 기능 추가 요청
204
- **영향:** Appointment 엔티티, API 응답 구조 변경
205
- ```
103
+ ### architecture.md
206
104
 
207
- 3. **문서 일관성 유지:**
208
- - Entity 변경 architecture.md 업데이트
209
- - 권한 규칙 변경 → business-logic.md 업데이트
210
- - 요구사항 추가/변경 → requirements.md 업데이트
105
+ **언제:** 엔티티를 설계하거나 시스템 아키텍처를 논의할 때
106
+ **내용:** Entity 구조 관계 설계, 데이터베이스 스키마, 시스템 컴포넌트 구조
211
107
 
212
108
  ### Compacting 후에도 안전
213
109
 
214
- **문서가 파일로 영속화되어 있어서:**
215
- - 대화가 압축(compacting)되어도 프로젝트 맥락 유지
216
- - 언제든 문서를 다시 읽어 일관성 있게 작업 가능
217
- - 설계 결정의 히스토리 추적 가능
110
+ 문서가 파일로 영속화되어 있어서 대화가 압축(compacting)되어도 프로젝트 맥락이 유지된다.
218
111
 
219
112
  ---
220
113
 
@@ -223,7 +116,7 @@ confirmed → cancelled (환자/의사 취소, 24시간 전까지만)
223
116
  | Skill | 파일 | 용도 |
224
117
  |-------|------|------|
225
118
  | **전체 워크플로우** | `workflow.md` | **엔티티 설계 → Frontend 개발 7단계 가이드** |
226
- | **CDD (Contract-Driven Dev)** | `cdd.md` | **main.contract.json, 도메인 contract, spec 작성 절차** |
119
+ | **CDD (AC+Claim 기반 개발)** | `cdd.md` | **`*.contract.md`(도메인 규칙), AC(테스트 이름), Claim(작업 지시서) 3종 체계** |
227
120
  | 프로젝트 생성 | `create-sonamu.md` | create-sonamu CLI 옵션 |
228
121
  | 프로젝트 초기화 | `project-init.md` | 프로젝트 생성 여부 확인, 대화 흐름 |
229
122
  | 프로젝트 설정 | `config.md` | .env, sonamu.config.ts 설정 |
@@ -262,7 +155,7 @@ confirmed → cancelled (환자/의사 취소, 24시간 전까지만)
262
155
  | 작업 | 참고 Skill |
263
156
  |------|-----------|
264
157
  | **처음부터 전체 시스템 개발** | **workflow.md (7단계 마스터 가이드)** |
265
- | **Contract/Spec 작성** | **cdd.md** |
158
+ | **도메인 Logic 문서화 / AC+Claim 기반 개발** | **cdd.md** |
266
159
  | 프로젝트 생성 | create-sonamu, project-init |
267
160
  | 프로젝트 설정 | config |
268
161
  | Sonamu 로컬 개발 설정 | config |