@spectrabrain/eds 0.1.0 → 0.2.0

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 (62) hide show
  1. package/AI.md +13 -63
  2. package/AI_CONTEXT.json +26 -95
  3. package/CHANGELOG.md +70 -4
  4. package/CONSUMER_AGENT.md +86 -164
  5. package/FRONTEND_CONVENTIONS.md +252 -0
  6. package/QUICKSTART.md +24 -29
  7. package/README.md +29 -73
  8. package/TAILWIND_V4.md +52 -184
  9. package/TOKEN_CONTEXT.md +79 -36
  10. package/consumer/align/templates/components.json +21 -0
  11. package/consumer/align/templates/env.mock +1 -0
  12. package/consumer/align/templates/eslint.config.js +35 -0
  13. package/consumer/align/templates/package.scripts.json +10 -0
  14. package/consumer/align/templates/prettierignore +2 -0
  15. package/consumer/align/templates/prettierrc.json +7 -0
  16. package/consumer/align/templates/src/app/App.tsx +16 -0
  17. package/consumer/align/templates/src/app/main.tsx +27 -0
  18. package/consumer/align/templates/src/app/providers/ErrorBoundary.tsx +58 -0
  19. package/consumer/align/templates/src/app/providers/ErrorHandler.tsx +29 -0
  20. package/consumer/align/templates/src/app/router/index.tsx +23 -0
  21. package/consumer/align/templates/src/app/styles/index.css +2 -0
  22. package/consumer/align/templates/src/mocks/browser.ts +5 -0
  23. package/consumer/align/templates/src/mocks/handlers.ts +4 -0
  24. package/consumer/align/templates/src/shared/api/index.ts +23 -0
  25. package/consumer/align/templates/src/shared/api/queryClient.ts +24 -0
  26. package/consumer/align/templates/src/shared/lib/eventBus.ts +44 -0
  27. package/consumer/align/templates/src/shared/lib/utils/index.ts +6 -0
  28. package/consumer/align/templates/src/vite-env.d.ts +2 -0
  29. package/consumer/align/templates/tsconfig.json +22 -0
  30. package/consumer/align/templates/vite.config.babel.ts +36 -0
  31. package/consumer/align/templates/vite.config.rolldown.ts +35 -0
  32. package/consumer/align-analysis.mjs +1159 -0
  33. package/consumer/align-plan.mjs +377 -0
  34. package/consumer/align-rules.mjs +473 -0
  35. package/consumer/align.mjs +401 -0
  36. package/consumer/cli.mjs +90 -40
  37. package/consumer/css-root.mjs +24 -4
  38. package/consumer/doctor.mjs +47 -21
  39. package/consumer/generate-tailwind.mjs +41 -1
  40. package/consumer/init.mjs +39 -25
  41. package/consumer/managed-block.mjs +11 -5
  42. package/consumer/paths.mjs +69 -14
  43. package/consumer/register-scripts.mjs +17 -12
  44. package/consumer/scan-classes.mjs +24 -5
  45. package/consumer/sync.mjs +35 -13
  46. package/consumer/update-agent-context.mjs +63 -7
  47. package/consumer-postinstall.mjs +8 -7
  48. package/dist/components/Button/README.md +66 -95
  49. package/dist/components/Button/spec.json +19 -138
  50. package/dist/components.css +102 -366
  51. package/dist/index.d.mts +20 -18
  52. package/dist/index.d.ts +20 -18
  53. package/dist/index.js +301 -1
  54. package/dist/index.mjs +301 -1
  55. package/dist/tokens.css +30 -0
  56. package/dist/tokens.d.mts +7 -3
  57. package/dist/tokens.d.ts +7 -3
  58. package/dist/tokens.js +301 -1
  59. package/dist/tokens.json +360 -0
  60. package/dist/tokens.mjs +301 -1
  61. package/llms.txt +20 -14
  62. package/package.json +3 -1
package/CONSUMER_AGENT.md CHANGED
@@ -1,60 +1,45 @@
1
1
  # EVA Design System 소비처 AI 계약
2
2
 
3
- 이 문서는 `@spectrabrain/eds`를 설치한 React 웹 저장소의 AI 코딩 에이전트와 자동화 도구를 위한 실행 계약입니다. 설치된 패키지 버전의 공개 문서와 TypeScript contract를 최종 기준으로 사용합니다. 필수 읽기는 package root의 `QUICKSTART.md` 하나이며, 이 문서는 setup·sync·doctor를 다룰 때 읽습니다.
4
-
5
- ## 설치 직후 읽는 순서
6
-
7
- 문서 이름이 소비처의 로컬 문서와 충돌할 수 있으므로 `require.resolve("@spectrabrain/eds/package.json")`로 설치된 package root를 먼저 찾고, 그 경로에서 읽습니다. 일반적인 설치에서는 `node_modules/@spectrabrain/eds`가 package root입니다. `AI_CONTEXT.json`은 읽기 경로와 기계용 canonical manifest를 찾는 라우팅 파일이며, 자연어 규칙은 Markdown 문서를 기준으로 합니다. `readOrder`의 `file`은 package root 상대 경로이고 `specifier`는 `require.resolve`에 쓰는 export subpath입니다. `dist/` 아래 파일은 `dist/components/Button/spec.json`처럼 `file` 경로로 읽거나 `@spectrabrain/eds/components/Button/spec.json`처럼 `specifier`로 resolve합니다.
8
-
9
- 1. package root의 `QUICKSTART.md`를 읽습니다. 필수이며 4 KB 이하입니다.
10
- 2. `AI_CONTEXT.json`의 `readOrder`에서 아래 문서의 조건을 확인하고 해당하는 문서만 읽습니다.
11
- 3. setup·sync·doctor를 다룰 때 이 문서를 읽습니다.
12
- 4. 공개 범위와 금지 사례를 확인할 때 `AI.md`를 읽습니다.
13
- 5. token을 직접 고를 때 `TOKEN_CONTEXT.md`를 읽습니다.
14
- 6. Tailwind CSS v4를 다룰 때 `TAILWIND_V4.md`를 읽습니다.
15
- 7. 컴포넌트를 사용할 때는 package root의 `dist/components/<Component>/README.md`와 `dist/components/<Component>/spec.json`을 읽습니다. 현재 컴포넌트 이름은 `AI_CONTEXT.json`의 `components` 배열에 있습니다.
16
- 8. `llms.txt` 인덱스로 공개 문서가 더 있는지 확인합니다.
17
-
18
- 문서에 없는 prop·variant·상태·token·deep import는 추측하지 않습니다.
19
-
20
- `npm install`만 끝난 저장소에는 setup이 아직 적용되지 않았을 수 있습니다. 소비처 `AGENTS.md`에 아래 managed block이 없거나 `npm run eds:doctor`가 실패하면 UI 작업보다 먼저 `npm run sync:eds`를 실행합니다.
3
+ 이 문서는 `@spectrabrain/eds`를 설치한 React 웹 저장소에서 setup·sync·doctor·`eds align`·버전 업데이트를 다루는 AI 코딩 에이전트를 위한 실행 계약입니다. UI 작업 규칙은 package root(`require.resolve("@spectrabrain/eds/package.json")`의 디렉터리)의 `QUICKSTART.md`에 있습니다.
21
4
 
22
5
  ## 소비처 `AGENTS.md` managed block
23
6
 
24
- `npm run sync:eds`가 소비처 저장소의 루트 `AGENTS.md`에 아래 block을 삽입하고 갱신합니다. 파일이 없으면 만들고, 기존 파일의 marker 밖 내용은 보존합니다. sync는 BEGIN marker 바로 다음 줄에 설치된 버전을 나타내는 `<!-- EDS:VERSION x.y.z -->` 줄을 추가하므로 아래 템플릿에는 버전 줄이 없습니다. marker가 중복되거나 한 쪽만 있으면 아무 파일도 쓰지 않고 실패합니다.
25
-
26
- 템플릿의 `npm run ` 접두는 sync가 감지한 패키지 매니저의 runner(`pnpm `, `yarn `, `bun run `)로 바꿔 씁니다. 그래서 소비처 `AGENTS.md`의 block에는 그 저장소에서 실제로 동작하는 명령이 들어가며, `eds doctor`도 같은 runner로 렌더링한 block과 비교합니다. 이 문서의 나머지 명령도 같은 방식으로 바꿔 읽습니다.
7
+ `npm run sync:eds`가 sync를 실행한 package 디렉터리(`package.json`이 있는 곳)의 `AGENTS.md`에 아래 block을 넣고 갱신합니다. 파일이 없으면 만들고, block이 없으면 파일 끝에 추가하며, 있으면 그 자리에서 갱신합니다. marker 밖 내용은 보존합니다. sync는 BEGIN marker 바로 다음 줄에 설치된 버전을 나타내는 `<!-- EDS:VERSION x.y.z -->` 줄을 추가하고, `npm run ` 접두를 감지한 패키지 매니저의 runner(`pnpm `, `yarn `, `bun run `)로 바꿔 씁니다. marker가 중복되거나 한쪽만 있으면 아무 파일도 쓰지 않고 실패합니다.
27
8
 
28
9
  ```md
29
10
  <!-- EDS:BEGIN -->
30
11
  ## EVA Design System 사용 규칙
31
12
 
32
- - EDS package root는 `require.resolve("@spectrabrain/eds/package.json")` 또는 `node_modules/@spectrabrain/eds`입니다. UI 작업 전에 그 경로의 `QUICKSTART.md`를 읽고, 추가 문서는 `AI_CONTEXT.json`의 조건에 해당할 때만 읽습니다.
33
- - 이 block이 없거나 `npm run eds:doctor`가 실패하면 UI 작업보다 먼저 `npm run sync:eds`를 실행합니다.
34
- - 제공되는 EDS 컴포넌트를 유사한 자체 구현보다 우선 사용합니다. 새 코드와 수정 중인 코드에서는 `Button`을 먼저 검토합니다. 소비처 저장소 규칙이 특정 컴포넌트를 지정하더라도 EDS에 같은 역할의 컴포넌트가 있으면 EDS를 먼저 선택하고, 소비처 규칙이 접근성·보안·제품 요구사항인 경우에만 그것을 우선합니다.
35
- - 색상은 `text-eds-fg-*`, `bg-eds-bg-*`, `border-eds-stroke-*`를 사용합니다. typography는 `eds-typography-*`를 사용합니다.
36
- - raw 색상·typography 값, 임의 CSS variable, 패키지 비공개 경로를 만들거나 복사하지 않습니다.
37
- - 정확한 공개 token이 없으면 `fg/bg/stroke` 역할, 상태, 행동 의미, `neutral` 순서로 가까운 공개 token을 선택합니다.
38
- - 새 UI 스타일은 Tailwind `className`을 우선 작성합니다. `index.css`에 컴포넌트별 규칙을 추가하지 않습니다.
39
- - EDS에 없는 컴포넌트를 구현할 때도 공개 semantic color·typography와 소비처 Tailwind 기본 spacing·radius를 사용합니다.
40
- - 작업 결과에 변경 파일, 최종 사용한 EDS component·token, typecheck·test·build 결과를 기록합니다.
13
+ - JSX·CSS·`className`을 만들거나 고치는 작업(UI 작업) 전에 EDS package root(`require.resolve("@spectrabrain/eds/package.json")`의 디렉터리, 보통 `node_modules/@spectrabrain/eds`)의 `QUICKSTART.md`를 읽습니다. Button 선택표, 명령, doctor 실패 시 조치가 있습니다.
14
+ - 사용자의 명시적 요청이 이 block보다 우선하며, 요청 범위의 코드부터 적용합니다. 같은 역할의 EDS 컴포넌트(현재 `Button`)가 있으면 자체 구현이나 소비처 규칙이 지정한 로컬 컴포넌트보다 EDS를 먼저 선택하고, 소비처 규칙이 접근성·보안·제품 요구를 이유로 명시한 경우에만 그것을 우선합니다.
15
+ - `AI_CONTEXT.json.components` → component README → `spec.json` → TypeScript contract 순으로 존재 여부를 확인합니다. 필요한 contract가 맞으면 EDS component를 쓰고, 목록에 없거나 맞지 않으면 소비처 로컬 UI를 구현합니다. 색상·typography·spacing·radius는 raw 값 대신 공개 token으로 지정하며, Tailwind에서는 `text-eds-fg-*`·`bg-eds-bg-*`·`border-eds-stroke-*`·`eds-typography-*`·`p-eds-spacing-0-5`·`rounded-eds-radius-1`, 그 밖에서는 `var(--eds-color-*)`·`cssVar("spacing-0.5")` 같은 API를 씁니다.
16
+ - UI 작업을 끝내기 전에 이 `AGENTS.md`가 있는 디렉터리에서 `npm run eds:doctor`를 실행해 `[EDS] synced with` 줄을 확인합니다. 이 줄이 없으면 `QUICKSTART.md` 「완료 기준」의 순서로 고칩니다.
17
+ - UI 작업의 완료 보고에 변경 파일, 사용한 EDS component·token, typecheck·build·doctor 결과를 적습니다.
18
+ - 이 block은 `npm run sync:eds`가 다시 씁니다. 소비처 규칙은 block 밖에 적습니다.
41
19
  <!-- EDS:END -->
42
20
  ```
43
21
 
44
- 이 block은 EDS package의 `postinstall`이 삽입하지 않습니다. `npm run sync:eds`가 삽입·갱신하며, 소비처 담당자가 저장소의 기존 규칙과 함께 diff를 검토합니다. 다음 EDS 버전으로 업데이트할 때도 block 안쪽과 버전 줄만 바뀌고 block 밖의 저장소 규칙은 보존됩니다.
22
+ block은 postinstall이 아니라 `npm run sync:eds`가 넣으며, 소비처 담당자가 저장소의 기존 규칙과 함께 diff를 검토합니다. EDS를 업데이트할 때도 block 안쪽과 버전 줄만 바뀝니다.
23
+
24
+ block이 에이전트에게 전달되는 경로는 도구마다 다릅니다. Codex는 git 루트부터 작업 디렉터리까지의 `AGENTS.md`를 읽고 기본 32 KiB를 넘는 뒷부분을 자르며, 같은 디렉터리의 `AGENTS.override.md`가 있으면 그것만 읽습니다. Claude Code는 `CLAUDE.md`·`.claude/CLAUDE.md`·`CLAUDE.local.md`가 있으면 `AGENTS.md` 대신 그 파일을 읽으므로 sync가 `CLAUDE.md`(없으면 `.claude/CLAUDE.md`)에 import를 넣습니다. Gemini CLI는 기본 설정에서 `GEMINI.md`만 읽습니다. sync와 doctor는 block이 전달되지 않을 수 있는 경우(Claude·Gemini 지시 파일 없음, `CLAUDE.local.md`만 있음, `AGENTS.override.md`, block이 32 KiB 밖, monorepo 하위 package)를 exit code에 영향이 없는 `note:`로 알리고, 루트 지시 파일에 넣을 문장을 함께 출력합니다.
45
25
 
46
26
  ## 첫 setup 절차
47
27
 
48
- 기본 패키지를 설치하고 동기화합니다.
28
+ 소비처 `AGENTS.md`에 EDS managed block이 없으면 UI 작업보다 먼저 이 절차를 진행합니다. `@spectrabrain/eds`를 dependencies에 선언할 앱 package 디렉터리(그 앱의 `package.json`이 있는 곳)에서 패키지를 설치하고 `init`으로 script 등록과 첫 sync를 실행합니다. `init`은 postinstall 실행 여부와 관계없이 동작하며, 현재 `package.json`이 `@spectrabrain/eds`를 선언하지 않으면 아무것도 쓰지 않고 exit 2로 끝납니다.
49
29
 
50
- ```sh
51
- npm install @spectrabrain/eds
52
- npm run sync:eds
53
- ```
30
+ | 패키지 매니저 | 실행할 명령 | `init`의 추가 동작 |
31
+ | --- | --- | --- |
32
+ | npm | `npm install @spectrabrain/eds && npx @spectrabrain/eds init` | npm 12 이상이면 `allowScripts["@spectrabrain/eds"]: true`(이름만, 버전 pin 없음)를 키가 없을 때만 기록합니다. `--no-allow-scripts`로 건너뜁니다. |
33
+ | pnpm | `pnpm add @spectrabrain/eds && pnpm exec eds init` | 추가 설정이 필요 없습니다. 설치 중 postinstall은 `init` 안내만 출력합니다. |
34
+ | yarn berry(`.yarnrc.yml`이 있거나 `yarn.lock`이 `__metadata:`로 시작) | `yarn add @spectrabrain/eds && yarn eds init`(검증 `미결`) | yarn berry는 `pre`·`post` hook을 실행하지 않으므로 `typecheck`·`build` script 앞에 `eds doctor && `를 붙이라고 안내하며, 그 script를 직접 고치지는 않습니다. `enableScripts`·`dependenciesMeta` 승인은 선택 사항이며 사용자가 결정할 항목으로 완료 보고에 적습니다. |
35
+ | yarn classic | `yarn add @spectrabrain/eds && yarn eds init`(검증 `미결`) | 추가 안내가 없습니다. |
36
+ | bun | `bun add @spectrabrain/eds && bunx @spectrabrain/eds init`(검증 `미결`) | `trustedDependencies` 승인은 선택 사항이며, bun의 기본 신뢰 목록을 대체하므로 사용자가 결정할 항목으로 완료 보고에 적습니다. |
37
+
38
+ yarn berry의 기본 Plug'n'Play 설치에는 `node_modules/@spectrabrain/eds`가 없으며 지원 여부는 `미결`입니다. sync와 doctor는 `.pnp.cjs`를 발견하면 `note:`로 알리며, 이때 `nodeLinker`를 바꾸기 전에 저장소 담당자에게 확인합니다.
54
39
 
55
- 설치와 최초 동기화를 한 번에 실행하려면 `npm install @spectrabrain/eds && npm run sync:eds`를 사용합니다.
40
+ EDS CLI는 가장 가까운 lockfile(현재 디렉터리부터 git 루트까지)로 패키지 매니저를 판별하고, lockfile이 없을 때만 실행한 runner를 따릅니다. `npx`와 `bunx`에는 항상 `@spectrabrain/eds`를 적습니다. npm registry의 `eds`는 EDS와 무관한 패키지라서, 로컬 bin이 없는 위치에서 `npx eds`를 실행하면 그 패키지가 설치되어 실행됩니다.
56
41
 
57
- npm 10·11에서는 EDS package의 `postinstall`이 소비처 `package.json`에만 다음 script를 등록합니다. 다른 파일은 만들거나 바꾸지 않습니다.
42
+ `init`이 등록하는 script는 어느 환경에서도 같습니다.
58
43
 
59
44
  ```json
60
45
  {
@@ -67,164 +52,101 @@ npm 10·11에서는 EDS package의 `postinstall`이 소비처 `package.json`에
67
52
  }
68
53
  ```
69
54
 
70
- - `sync:eds`와 `eds:doctor`는 항상 등록합니다. 같은 이름의 script가 `eds sync`·`eds doctor`를 포함한 명령(예: `EDS_DOCTOR=warn eds doctor`)이면 호환으로 보고 그대로 둡니다. 다른 명령이면 덮어쓰지 않고 안내만 출력하며 설치는 실패하지 않습니다. 이 경우 `eds doctor`가 `scripts:` 항목으로 보고합니다. 이전 EDS 버전이 등록한 알려진 `sync:eds` 명령은 `eds sync`로 바꾸고, 이전 runner를 가리키던 `update:eds-agent-context`·`generate:eds-tailwind`는 제거합니다. 소비처가 직접 작성한 명령은 그대로 둡니다.
71
- - `pretypecheck`·`prebuild`는 소비처에 `typecheck`·`build` script가 있고 같은 이름의 pre-hook이 없을 때만 등록합니다. 이미 다른 pre-hook이 있으면 그대로 두고 안내만 출력합니다. `predev`에는 연결하지 않습니다.
72
- - 소비처 `package.json`에 `workspaces`가 있으면 그 디렉터리는 앱이 아니라 workspace root이므로 script를 등록하지 않고, `@spectrabrain/eds`에 의존하는 앱 package 안에서 `npx eds init`을 실행하도록 안내만 출력합니다. pnpm으로 설치할 때는 pnpm이 설치 중에 이루어진 `package.json` 편집을 버리므로 postinstall은 등록하지 않고 `pnpm exec eds init` 실행을 안내합니다.
73
-
74
- ### 의존성 install script를 실행하지 않는 환경
75
-
76
- npm 12, pnpm 10, yarn berry, bun은 기본 설정에서 의존성의 install script를 실행하지 않으므로 postinstall 등록이 일어나지 않으며, `npm install --ignore-scripts`를 사용하는 환경도 같습니다. 이 경우 설치 뒤 다음 명령으로 같은 script를 등록하고 첫 동기화까지 실행합니다. 설치가 끝난 저장소에서는 `npx eds init`도 같은 CLI를 실행합니다.
77
-
78
- ```sh
79
- npx @spectrabrain/eds init
80
- ```
81
-
82
- `init`은 `npm_config_user_agent`(없으면 lockfile 이름)로 패키지 매니저를 판별하고, 등록하는 script 값은 어느 환경에서도 위 JSON과 같습니다. 패키지 매니저별 추가 동작은 다음과 같습니다.
83
-
84
- | 패키지 매니저 | `init`의 추가 동작 |
85
- | --- | --- |
86
- | npm 12 이상 | 소비처 `package.json`에 `allowScripts["@spectrabrain/eds"]: true`(이름만, 버전 pin 없음)를 키가 없을 때만 기록하고 기록한 내용을 출력합니다. 이후 설치·업그레이드에서 postinstall이 자동 실행됩니다. `--no-allow-scripts`로 이 기록을 건너뜁니다. |
87
- | pnpm | 파일을 쓰지 않고 `pnpm approve-builds` 또는 `pnpm.onlyBuiltDependencies` 설정 snippet을 출력합니다. |
88
- | bun | `trustedDependencies` 설정 안내를 출력합니다. 이 필드를 설정하면 bun의 기본 신뢰 목록이 대체되므로 함께 경고합니다. |
89
- | yarn berry | `enableScripts`·`dependenciesMeta` 설정 안내를 출력합니다. yarn berry는 `pre`·`post` hook을 실행하지 않으므로 `typecheck`·`build` script 앞에 `eds doctor && `를 직접 붙이라는 안내도 출력하며, `init`이 그 script를 수정하지는 않습니다. |
90
-
91
- `npm exec -- @spectrabrain/eds init --no-sync`는 script만 등록하고 `npm run sync:eds` 실행을 안내합니다. `init`에 옵션을 넘길 때는 npm이 옵션을 자기 설정으로 해석하지 않도록 `npm exec --` 뒤에 적습니다. `init`은 현재 디렉터리에 `package.json`과 설치된 `@spectrabrain/eds`가 있어야 하며, 없으면 안내와 함께 실패합니다.
92
-
93
- `npx eds init --print-ci gitlab` 또는 `--print-ci github`는 CI에서 `npx eds doctor`를 실행하는 job snippet을 출력합니다. 파일은 쓰지 않으며 소비처가 CI 설정에 직접 붙입니다.
94
-
95
- ## Tailwind root와 sync 적용 순서
96
-
97
- `eds sync`와 `eds doctor`는 환경 변수 `EDS_TAILWIND_ROOT`, 소비처 `package.json`의 `eds.tailwindRoot`, 자동 검출 순서로 Tailwind root를 정합니다. 자동 검출은 `@import "tailwindcss"`가 있는 소비처 CSS 파일 하나를 root로 사용하며, `@import "tailwindcss/theme.css"`·`@import "tailwindcss/utilities.css"`와 `@import url("tailwindcss")` 형태도 인식하고 `/* */` 주석 안의 import는 세지 않습니다. `node_modules`, `dist`, `build`, `.git`, `storybook-static`, `coverage`와 생성 파일은 후보에서 제외합니다. 후보가 2개 이상이면 후보 목록을 출력하고 아무 파일도 쓰지 않은 채 실패하므로, 다음처럼 root를 한 번 지정합니다.
98
-
99
- ```sh
100
- EDS_TAILWIND_ROOT=src/app/styles/index.css npm run sync:eds
101
- ```
102
-
103
- `EDS_TAILWIND_ROOT`로 sync에 성공하면 sync가 소비처 `package.json`에 `"eds": { "tailwindRoot": "src/app/styles/index.css" }`를 기록하므로, 이후 `eds doctor`, `eds sync`, `pretypecheck`·`prebuild` hook은 환경 변수 없이 같은 root를 사용합니다. `--dry-run`은 기록할 내용만 출력합니다. `EDS_TAILWIND_ROOT`나 `eds.tailwindRoot`가 존재하지 않는 파일을 가리키면 exit 2로 실패하고 경로를 고치거나 키를 제거하라고 안내합니다.
55
+ - `sync:eds`·`eds:doctor`가 없으면 등록합니다. 같은 이름의 script가 `eds sync`·`eds doctor`를 포함하면(예: `EDS_DOCTOR=warn eds doctor`) 그대로 두고, 다른 명령이면 덮어쓰지 않고 안내만 출력하며 `eds doctor`가 `scripts:` 항목으로 보고합니다. 이전 EDS 버전이 등록한 알려진 명령은 새 명령으로 바꿉니다.
56
+ - `pretypecheck`·`prebuild`는 소비처에 `typecheck`·`build` script가 있고 같은 이름의 pre-hook이 없을 때만 등록합니다. 이미 다른 pre-hook이 있으면 그대로 두고, 출력된 명령대로 기존 hook 앞에 `eds doctor && `를 붙입니다.
57
+ - npm 10·11과, `init`이 `allowScripts`를 기록한 npm 12 이상에서는 EDS의 `postinstall`이 설치 중에 같은 script를 등록하고 다른 파일은 쓰지 않습니다. 소비처 `package.json`에 `workspaces`가 있으면 등록하지 않고 앱 package 안에서 `init`을 실행하도록 안내하며, pnpm 설치에서는 pnpm이 설치 중의 `package.json` 편집을 버리므로 `pnpm exec eds init`을 안내합니다.
58
+ - `--no-sync`는 script만 등록하고(npm 12 이상은 `allowScripts`도 기록) sync는 실행하지 않습니다(`npx @spectrabrain/eds init --no-sync`).
59
+ - `init --print-ci github` 또는 `--print-ci gitlab`(예: `npx @spectrabrain/eds init --print-ci github`)은 이 저장소의 패키지 매니저로 install과 `eds doctor`를 실행하는 CI job snippet을 출력만 합니다. 출력은 고치지 않고 그대로 붙입니다.
104
60
 
105
- 후보가 0개이고 `EDS_TAILWIND_ROOT`와 `eds.tailwindRoot`도 없으면 Tailwind를 사용하지 않는 저장소로 보고 Tailwind 배선을 건너뜁니다. `src/styles/eds-tokens.css`를 만들지 않고 CSS root도 고치지 않으며 안내 한 줄만 출력합니다. 이 상태에서 `eds doctor`는 Tailwind 관련 항목을 보고하지 않습니다.
61
+ setup은 `npm run eds:doctor`가 `[EDS] synced with` 줄을 출력하면 완료입니다. 담당자가 첫 sync 전에 `CLAUDE.md`·`AGENTS.md`에 넣은 EDS 안내 줄(`README.md` 「설치」)이 남아 있으면 block과 겹치므로 지웁니다. 같은 이름의 다른 script를 바꾸거나 marker 밖 기존 내용을 고쳐야 할 때는 쓰기 전에 사용자에게 확인합니다.
106
62
 
107
- sync는 모든 변경을 먼저 계산한 뒤 다음 순서로 씁니다. 계산 중 실패하면 어떤 파일도 바꾸지 않습니다.
63
+ ## Tailwind root 결정
108
64
 
109
- 1. `src/styles/eds-tokens.css`를 생성하고, Tailwind root의 마지막 Tailwind import(`@import "tailwindcss";` 또는 `tailwindcss/theme.css`·`tailwindcss/utilities.css`) 바로 다음 줄에 `@import "@spectrabrain/eds/styles.css";`와 생성 CSS의 상대 경로 `@import`를 추가합니다. 주석 처리된 import는 이미 있는 import로 세지 않습니다. 같은 파일이 이미 import되어 있으면 다시 추가하지 않습니다.
110
- 2. `src/` 아래 JS·TS 파일에서 `eds-tokens.css`를 import하는 줄을 제거합니다. Tailwind는 JS에서 import한 CSS를 compile하지 않기 때문입니다. `@spectrabrain/eds/styles.css`의 기존 JS import는 유지합니다.
111
- 3. `AGENTS.md` managed block을 삽입하거나 갱신합니다. fenced code block(```` ``` ````·`~~~`) 안의 marker는 예시로 보고 무시하며, 그 밖의 marker가 불균형하면 개수와 첫 marker의 줄 번호를 출력하고 실패합니다.
112
- 4. `CLAUDE.md`가 있을 때만 `@AGENTS.md` import 줄을 한 번 추가합니다. 파일이 없으면 만들지 않으며, `@./AGENTS.md` 줄이 이미 있거나 `CLAUDE.md`가 `AGENTS.md`와 같은 파일(symlink)이면 추가하지 않습니다.
113
- 5. `GEMINI.md`가 있을 때만 `@./AGENTS.md` import 줄을 같은 규칙으로 한 번 추가합니다. Gemini CLI가 기본으로 읽는 파일이 `GEMINI.md`이기 때문이며, Codex·Cursor·Copilot·Windsurf는 `AGENTS.md`를 직접 읽습니다.
65
+ `eds sync`와 `eds doctor`는 환경 변수 `EDS_TAILWIND_ROOT`, 소비처 `package.json`의 `eds.tailwindRoot`, 자동 검출 순서로 Tailwind root CSS를 정합니다. 자동 검출은 `@import "tailwindcss"`(`tailwindcss/theme.css`·`tailwindcss/utilities.css`, `@import url("tailwindcss")` 포함)가 있는 CSS 파일 하나를 root로 쓰며, 주석 안의 import와 `node_modules`·`dist`·`build`·`coverage`·`storybook-static`, 점(`.`)으로 시작하는 디렉터리는 제외합니다.
114
66
 
115
- managed block, `CLAUDE.md`·`GEMINI.md` import, CSS import는 대상 파일의 줄바꿈(CRLF·LF)을 따라 쓰고, 생성 CSS는 LF로 씁니다.
67
+ - 후보가 2개 이상이면 아무 파일도 쓰지 않고 exit 2로 끝납니다. 어느 파일이 root인지 사용자에게 확인한 뒤(확인할 때 후보마다 앱 진입점, 예: `src/main.tsx`가 그 파일을 import하는지 직접 찾아 함께 알려 줍니다) `EDS_TAILWIND_ROOT=<root CSS 경로> npm run sync:eds`(예: `EDS_TAILWIND_ROOT=src/app/styles/index.css npm run sync:eds`)로 한 번 지정합니다. sync는 성공하면 이 경로를 소비처 `package.json`의 `"eds": { "tailwindRoot": "…" }`에 기록하고, 이후 doctor·sync·hook이 환경 변수 없이 같은 root를 씁니다. 기록된 경로나 `EDS_TAILWIND_ROOT`가 없는 파일을 가리키면 exit 2입니다.
68
+ - 후보가 없고 지정도 없으면 Tailwind를 쓰지 않는 저장소로 보고 Tailwind 배선을 건너뜁니다. 이때 sync는 `AGENTS.md` managed block과, 파일이 있을 때 `CLAUDE.md`·`GEMINI.md`의 import만 갱신합니다. doctor는 Tailwind 항목 대신 `note:` 한 줄을 출력하고 EDS font import는 계속 점검합니다. Tailwind를 쓰지 않는 저장소는 앱 진입점(예: `src/main.tsx`)에서 `@spectrabrain/eds/styles.css`를 import합니다.
69
+ - CSS가 `@tailwind` 지시어를 쓰는 Tailwind CSS v3 저장소도 후보가 없는 것으로 보고, sync와 doctor가 `Tailwind CSS v3 detected` note를 출력합니다. 이 저장소에서는 `EDS_TAILWIND_ROOT`를 지정하지 않고(v3 파일을 가리키면 exit 2) 앱 진입점의 `styles.css` import와 `var(--eds-*)`·`cssVar()`를 쓰며, Tailwind CSS v4 업그레이드는 사용자에게 확인한 뒤 진행합니다.
116
70
 
117
- `src/index.css`가 root이면 결과는 다음과 같습니다.
71
+ ## sync가 쓰는 파일
118
72
 
119
- ```css
120
- @import "tailwindcss";
121
- @import "@spectrabrain/eds/styles.css";
122
- @import "./styles/eds-tokens.css";
123
- ```
124
-
125
- `src/app/styles/index.css`가 root이면 생성 CSS의 위치를 기준으로 상대 경로가 달라집니다.
126
-
127
- ```css
128
- @import "tailwindcss";
129
- @import "@spectrabrain/eds/styles.css";
130
- @import "../../styles/eds-tokens.css";
131
- ```
132
-
133
- 생성 CSS의 `@theme inline`에는 공개 color alias와 함께 `--font-sans: var(--eds-typography-body1-fontFamily);` 한 줄이 들어가므로 Tailwind의 기본 sans font가 Pretendard가 됩니다.
73
+ sync는 모든 변경을 먼저 계산하고, 계산 중 하나라도 실패하면 어떤 파일도 바꾸지 않습니다. 쓰는 내용은 다음과 같습니다.
134
74
 
135
- `@spectrabrain/eds/styles.css`는 어떤 CSS나 JS·TS 소스가 이미 import하고 있으면 추가하지 않습니다. `@spectrabrain/eds/tokens.css`, `@spectrabrain/eds/components.css`, `@spectrabrain/eds/fonts.css`가 모두 import되어 있는 경우도 같습니다. `tokens.css`와 `components.css`만 import되어 있고 `fonts.css`가 없으면 sync가 Tailwind root에 `@import "@spectrabrain/eds/fonts.css";`를 추가합니다.
75
+ 1. `src/styles/eds-tokens.css`를 생성하고, Tailwind root의 마지막 Tailwind import 바로 다음 줄에 `@import "@spectrabrain/eds/styles.css";`와 생성 CSS의 상대 경로 `@import`를 추가합니다. 이미 있는 import는 다시 추가하지 않습니다. 생성 CSS의 `@theme inline`에는 공개 color·spacing·radius alias와 `--font-sans: var(--eds-typography-body1-fontFamily);`가 들어갑니다. root CSS 예시는 `TAILWIND_V4.md`에 있습니다.
76
+ 2. `src/` 아래 JS·TS 파일에서 `eds-tokens.css`를 import하는 줄을 제거합니다. Tailwind는 JS에서 import한 CSS를 compile하지 않기 때문입니다.
77
+ 3. `AGENTS.md` managed block을 넣거나 갱신합니다.
78
+ 4. `CLAUDE.md`가 있으면 `@AGENTS.md`, `CLAUDE.md` 없이 `.claude/CLAUDE.md`가 있으면 `@../AGENTS.md`, `GEMINI.md`가 있으면 `@./AGENTS.md` import를 `<!-- EDS:CLAUDE:BEGIN/END -->`·`<!-- EDS:GEMINI:BEGIN/END -->` marker로 감싸 파일 끝에 한 번 추가합니다. sync는 이 marker로 import를 찾으므로 marker와 import를 함께 유지합니다. 파일이 없으면 만들지 않고, `AGENTS.md`와 같은 파일(symlink)이면 추가하지 않습니다.
136
79
 
137
- `npm run sync:eds -- --only tailwind`와 `npm run sync:eds -- --only agents`는 해당 부분만 적용하고, `--dry-run`은 파일을 쓰지 않고 `would write <경로>`만 출력합니다. 두 옵션 모두 검증은 전체를 수행합니다. 파일을 쓴 sync는 `[EDS] Synced with @spectrabrain/eds@<version>. Review the diff (AGENTS.md, CSS imports, src/styles/eds-tokens.css) before committing; the AGENTS.md block lists the rules.`로 끝나므로 diff를 검토한 뒤 커밋하고, 바꿀 것이 없으면 `[EDS] Already synced with @spectrabrain/eds@<version>.`을 출력합니다.
80
+ `@spectrabrain/eds/styles.css`는 CSS나 JS·TS 소스가 이미 import하고 있으면 다시 추가하지 않습니다. `tokens.css`·`components.css`·`fonts.css`가 모두 import되어 있어도 같으며, `tokens.css`와 `components.css`만 있고 `fonts.css`가 없으면 root에 `@import "@spectrabrain/eds/fonts.css";`를 추가합니다.
138
81
 
139
- 기존 전역 CSS와 Tailwind 설정은 보존합니다. 새 컴포넌트의 고유한 표현은 전역 stylesheet보다 Tailwind `className`을 우선 사용합니다.
82
+ `npm run sync:eds -- --only tailwind`와 `npm run sync:eds -- --only agents`는 해당 부분만 쓰고, `--dry-run`은 쓸 경로만 출력합니다. 두 옵션을 써도 Tailwind root 판정과 marker 검사는 모두 수행하므로, root 후보가 2개 이상이면 `--only agents`도 exit 2로 끝납니다. 파일을 쓴 sync는 쓴 파일을 `[EDS] wrote <경로>` 줄로 나열한 뒤 그 파일을 변경에 포함하고 doctor를 실행하라는 줄로 끝나고, 바꿀 것이 없으면 `Already synced`로 끝납니다.
140
83
 
141
84
  ## font 정책
142
85
 
143
86
  EDS text style은 font family `Pretendard`를 참조하며, 이 family는 `@spectrabrain/eds/fonts.css`가 선언합니다. 따라서 EDS의 `fonts.css`는 생략할 수 없습니다.
144
87
 
145
88
  - 기본 구성은 `@spectrabrain/eds/styles.css` 하나입니다. `fonts.css`, `tokens.css`, `base.css`, `components.css`를 순서대로 불러옵니다.
146
- - 개별 파일로 구성할 때는 `@spectrabrain/eds/tokens.css`, `@spectrabrain/eds/components.css`, `@spectrabrain/eds/fonts.css`를 함께 import합니다. `@spectrabrain/eds/base.css`는 `:where(html)`에 body1 font family를 지정하는 선택 파일이며, 소비처가 `html`의 `font-family`를 직접 관리한다면 생략할 수 있습니다.
147
- - 소비처가 CDN·`<link>`·자체 `@font-face`로 Pretendard를 따로 불러오는 구성은 EDS `fonts.css`를 대체하지 못합니다. 다른 family 이름으로 선언된 Pretendard는 EDS text style이 참조하지 않기 때문입니다. 이 경우에도 EDS `fonts.css`를 유지하고, 중복 선언은 소비처가 정리합니다.
89
+ - 개별 파일로 구성할 때는 `@spectrabrain/eds/tokens.css`, `@spectrabrain/eds/components.css`, `@spectrabrain/eds/fonts.css`를 함께 import합니다. `@spectrabrain/eds/base.css`는 `:where(html)`에 body1 font family를 지정하는 선택 파일이며, 소비처가 `html`의 `font-family`를 직접 정한다면 생략합니다. `base.css`는 cascade layer 밖의 specificity 0 규칙이므로, 소비처가 layer 밖에 둔 `html`·`body` font-family 선언이 우선하고 `@layer` 안에 둔 `html` 규칙(Tailwind v4 포함)보다는 `base.css`가 우선합니다.
90
+ - CDN·`<link>`·자체 `@font-face`로 불러온 Pretendard는 EDS `fonts.css`를 대체하지 못합니다. 다른 family 이름으로 선언된 Pretendard는 EDS text style이 참조하지 않기 때문입니다. 이 경우에도 EDS `fonts.css`를 유지합니다. 다른 출처의 Pretendard는 EDS 동작에 영향이 없고 EDS가 아닌 스타일이 쓸 수 있으므로, 사용자가 요청할 때만 정리합니다.
148
91
 
149
- `eds doctor`는 `@spectrabrain/eds/styles.css`와 `@spectrabrain/eds/fonts.css`가 CSS·JS·TS 어디에서도 import되지 않으면 `missing:`으로 보고합니다. `index.html`이나 CSS에서 다른 출처의 Pretendard를 함께 참조하고 있으면 `note:` 한 줄을 출력하며, 이 줄은 exit code에 영향을 주지 않습니다.
92
+ `eds doctor`는 `@spectrabrain/eds/styles.css`와 `@spectrabrain/eds/fonts.css`가 CSS·JS·TS 어디에서도 import되지 않으면 `missing:`으로 보고합니다. HTML·CSS에서 EDS import 밖에 `Pretendard`를 언급하는 줄이 있으면 `note:`를 출력하며, 이 줄은 exit code에 영향을 주지 않습니다.
150
93
 
151
94
  ## `eds:doctor` 점검
152
95
 
153
- `npm run eds:doctor`는 아무 파일도 쓰지 않고 `npm run sync:eds`가 무언가를 바꿀지 판정합니다. postinstall 또는 `init`이 등록한 `pretypecheck`·`prebuild` hook이 같은 점검을 typecheck·build 전에 실행합니다.
154
-
155
- - exit 0은 동기화된 상태입니다. `[EDS] synced with @spectrabrain/eds@<version>: ...` 한 줄을 출력합니다.
156
- - exit 1은 고칠 항목이 있는 상태입니다. `sync:eds`·`eds:doctor` script 미등록이나 다른 명령으로의 등록, `src/styles/eds-tokens.css` 누락·구버전, root CSS import 누락, JS에 남은 `eds-tokens.css` import, 소스의 `eds-*` class 중 공개 token이 없는 이름(`unknown: <파일:줄> <class>`), EDS font import 누락, `AGENTS.md` block 누락·불량·구버전, `CLAUDE.md`의 `@AGENTS.md` 줄 누락, `GEMINI.md`의 `@./AGENTS.md` 줄 누락을 `[EDS] <종류>: ...` 줄로 출력한 뒤 `[EDS] Run npm run sync:eds to fix.`와 `[EDS] Then read the AGENTS.md managed block and QUICKSTART.md in the package root before UI work.` 두 줄로 끝납니다. `sync:eds`가 `eds sync`를 실행하지 않는 상태면 첫 줄은 `[EDS] Run npx eds sync to fix.`가 됩니다. 안내한 명령을 실행한 뒤 두 문서를 읽습니다. 줄바꿈(CRLF·LF) 차이만 있는 파일은 stale로 보지 않습니다.
157
- - exit 2는 판정할 수 없는 상태입니다. `@spectrabrain/eds`가 설치되지 않았거나, 소비처 `package.json`을 읽을 수 없거나, Tailwind root 후보가 2개 이상이거나, `EDS_TAILWIND_ROOT` 또는 `package.json`의 `eds.tailwindRoot`가 존재하지 않는 파일을 가리키는 경우입니다. 설치 상태, `EDS_TAILWIND_ROOT`, `eds.tailwindRoot`를 확인합니다.
158
-
159
- `npm run eds:doctor -- --warn`은 같은 출력에 exit 0으로 끝나며 `EDS_DOCTOR=warn`과 같습니다. `EDS_DOCTOR=off`는 출력 없이 exit 0으로 끝납니다. hook 때문에 typecheck·build가 막히면 원인을 고치는 것을 우선하고 `--warn`은 임시로만 사용합니다.
160
-
161
- `npm run eds:doctor -- --scan`은 여기에 더해 Tailwind 기본 팔레트(`text-red-500`), `white`·`black`, 임의 색(`bg-[#…]`) class를 `raw: <파일:줄> <class>` 줄로 나열합니다. 정보 제공용이라 exit code를 바꾸지 않으며, 새 코드에 raw 색이 남지 않았는지 검토할 때 사용합니다. `unknown:`과 `raw:` 검사는 Tailwind root가 있는 저장소에서만 실행합니다.
162
-
163
- ## 소비처 온보딩
164
-
165
- 소비처 저장소의 `CLAUDE.md` 또는 `AGENTS.md` 상단에 다음 한 줄을 담당자가 직접 넣습니다. 이 줄은 `npm install`만 끝난 상태에서도 AI가 설치된 계약을 먼저 읽고 sync를 실행하게 합니다.
166
-
167
- > package.json에 `@spectrabrain/eds`가 있으면 UI 작업 전에 `node_modules/@spectrabrain/eds/QUICKSTART.md`를 먼저 읽고, `npm run eds:doctor`가 실패하면 `npm run sync:eds`를 먼저 실행합니다.
168
-
169
- `CLAUDE.md`가 있는 저장소에서는 `npm run sync:eds`가 파일 끝에 `<!-- EDS:CLAUDE:BEGIN -->`와 `<!-- EDS:CLAUDE:END -->` 사이의 `@AGENTS.md` 한 줄을 한 번만 추가해 Claude Code가 `AGENTS.md`의 managed block을 함께 읽게 합니다. `CLAUDE.md`가 없으면 만들지 않고, `@./AGENTS.md`가 이미 있거나 `CLAUDE.md`가 `AGENTS.md`의 symlink이면 추가하지 않습니다. `GEMINI.md`가 있으면 같은 방식으로 `<!-- EDS:GEMINI:BEGIN -->`와 `<!-- EDS:GEMINI:END -->` 사이에 `@./AGENTS.md`를 추가해 Gemini CLI도 block을 읽게 합니다. Codex·Cursor·Copilot·Windsurf는 `AGENTS.md`를 직접 읽으므로 추가 파일이 필요 없습니다.
96
+ `npm run eds:doctor`는 파일을 쓰지 않고 sync 상태, script 등록, EDS font import, 소스의 `eds-*` class 이름을 점검합니다. postinstall 또는 `init`이 등록한 `pretypecheck`·`prebuild` hook이 같은 점검을 typecheck·build 전에 실행합니다. yarn berry는 이 hook을 실행하지 않으므로 `typecheck`·`build` 앞에 붙인 `eds doctor`가 같은 역할을 합니다.
170
97
 
171
- ## AI 작업 프로토콜
172
-
173
- 각 UI 작업은 다음 순서로 수행합니다.
174
-
175
- 1. 요청 범위와 소비처의 `AGENTS.md`, 테스트·보안·접근성 규칙을 확인합니다.
176
- 2. `QUICKSTART.md`를 읽고, `AI_CONTEXT.json`의 조건에 따라 필요한 Markdown 문서와 JSON manifest만 추가로 읽습니다.
177
- 3. 화면의 행동·정보 위계를 먼저 정하고, 해당 역할의 EDS component와 semantic token을 선택합니다.
178
- 4. 선택한 공개 contract로 표현할 수 있는지 확인한 뒤 Tailwind `className` 중심으로 구현합니다.
179
- 5. 새 token·prop·variant·상태를 발명하지 않고, exact token이 없을 때만 `AI_CONTEXT.json`의 nearest-token 순서를 적용합니다.
180
- 6. 변경 후 관련 typecheck·test·build와 `npm run eds:doctor` 결과를 확인합니다.
181
- 7. 완료 보고에 변경 파일, 최종 component·token, 실행한 검증을 남깁니다.
182
-
183
- 문서 설명과 JSON manifest가 충돌하면 공개 token 이름·component prop·접근성 동작은 JSON manifest와 TypeScript contract를 우선합니다. 사용자의 요구사항, 소비처 저장소 규칙, 접근성·보안 제약은 EDS 권고보다 항상 우선합니다. 다만 위 managed block은 sync가 소비처 `AGENTS.md`에 넣는 소비처 규칙의 일부이므로, 컴포넌트 선택은 block의 tie-break 문장을 따릅니다. 소비처 규칙이 특정 컴포넌트를 지정하더라도 EDS에 같은 역할의 컴포넌트가 있으면 EDS를 먼저 선택하고, 그 규칙이 접근성·보안·제품 요구사항일 때만 소비처 규칙을 우선합니다.
184
-
185
- 다음 상황에서는 임의 구현을 계속하지 않고 범위를 멈춰 확인합니다.
186
-
187
- - 공개 manifest에 없는 prop·variant·상태를 요구받은 경우
188
- - 의미 역할에 맞는 공개 token이 없고 가까운 역할도 선택할 수 없는 경우
189
- - Tailwind root 후보가 2개 이상인데 `EDS_TAILWIND_ROOT`도 `package.json`의 `eds.tailwindRoot`도 없는 경우
190
- - 기존 소비처 규칙과 EDS setup이 충돌해 파일을 안전하게 보존할 수 없는 경우
98
+ | exit | 의미 |
99
+ | --- | --- |
100
+ | 0 | `[EDS] synced with` 줄이 나오면 동기화된 상태입니다. `--warn`·`EDS_DOCTOR`로 얻은 exit 0에는 이 줄이 없으며 완료가 아닙니다. |
101
+ | 1 | 고칠 항목이 있습니다. 항목마다 `[EDS] <종류>: …` 줄과 조치를 출력하고, 다음에 실행할 명령(script가 없으면 `init`, sync로 고칠 줄이 있으면 sync) 한 줄과 다시 실행하라는 줄로 끝납니다. |
102
+ | 2 | 판정할 수 없는 상태입니다. `@spectrabrain/eds`를 찾을 수 없거나(소비처 `package.json`이 깨진 경우 포함), EDS `package.json`을 읽을 수 없거나, 옵션이 잘못되었거나, Tailwind root 후보가 2개 이상이거나, `EDS_TAILWIND_ROOT`·`eds.tailwindRoot`가 없는 파일이나 Tailwind CSS v3 파일을 가리키거나 `eds.tailwindRoot`가 빈 값·문자열이 아닌 값인 경우입니다. 출력 메시지가 올바른 형식을 안내합니다. |
191
103
 
192
- ## 작업 우선순위
104
+ 각 `[EDS]` 줄 끝의 조치를 따릅니다. 고치는 순서는 `scripts:` → sync → 나머지이며, 항목별 조치는 다음과 같습니다.
193
105
 
194
- 1. 사용자의 명시적인 요구사항과 제품의 접근성·보안·기능 규칙을 지킵니다.
195
- 2. 현재 저장소의 `AGENTS.md`, `README.md`, 테스트와 기존 컴포넌트 계약을 확인합니다. 로컬 컴포넌트를 지정한 규칙과 EDS 컴포넌트가 겹치면 managed block의 tie-break를 따릅니다.
196
- 3. 설치된 EDS의 공개 문서와 TypeScript contract를 확인합니다.
197
- 4. 기능이 일치하는 EDS component와 semantic token을 우선 선택합니다.
198
- 5. EDS에 없는 기능만 소비처에서 구현하고, 구현에도 공개 token과 Tailwind className을 사용합니다.
106
+ | 항목 | 조치 |
107
+ | --- | --- |
108
+ | `missing:`·`stale:`·`legacy:`(생성 CSS, root CSS import, `AGENTS.md` block, `CLAUDE.md`·`GEMINI.md` import) | `npm run sync:eds`로 고칩니다(`sync:eds`가 등록되지 않았으면 `npx @spectrabrain/eds sync`). |
109
+ | `missing:` EDS font import(Tailwind root가 없는 저장소) | 앱 진입점에서 `@spectrabrain/eds/styles.css`를 import합니다. 이 경우 sync는 CSS를 고치지 않습니다. |
110
+ | `scripts:` | 등록되지 않았으면 「첫 setup 절차」의 `init`으로 등록합니다(init이 sync까지 실행합니다). 같은 이름의 다른 script이면 init이 덮어쓰지 않으므로, 그 script가 `eds sync`·`eds doctor`를 실행하도록 고치거나 이름을 바꾼 뒤 init을 실행합니다. |
111
+ | `unknown: <파일:줄> <class>` | 공개 token이 없는 `eds-*` class입니다. Tailwind는 이런 class를 조용히 버리므로 `src/styles/eds-tokens.css`에 있는 class로 고칩니다. class 이름은 color token이 `<utility>-eds-<이름>`, `typography-<style>-*`가 `eds-typography-<style>`, spacing·radius가 `p-eds-spacing-0-5`·`rounded-eds-radius-1`처럼 되는 규칙으로 만들어집니다. |
112
+ | `invalid:` | `AGENTS.md`의 EDS marker가 중복되거나 한쪽만 있습니다. sync는 이 상태를 고치지 않습니다. 출력에 적힌 줄에서 BEGIN 한 줄과 그 뒤의 END 한 줄만 남기고 나머지 marker 줄을 지운 뒤 sync를 다시 실행합니다. |
199
113
 
200
- 기존 레거시 구현을 한 번에 교체하지 않습니다. 수정 범위에 포함된 코드와 새 코드부터 계약을 적용합니다. 기존 local Button wrapper는 EDS `Button` contract로 표현할 수 없는 기능이 있을 때만 유지합니다.
114
+ `npm run eds:doctor -- --warn`과 `EDS_DOCTOR=warn`은 같은 출력에 warn mode 경고를 더하고 exit 0으로 끝나며, `EDS_DOCTOR=off`는 출력 없이 exit 0으로 끝납니다. 이 설정은 hook을 잠시 풀어야 할 때 사용자가 쓰는 것이며, 이 상태의 exit 0은 완료가 아닙니다.
201
115
 
202
- ## token 선택 규칙
116
+ `npm run eds:doctor -- --scan`은 Tailwind 기본 팔레트(`text-red-500`), `white`·`black`, 임의 색(`bg-[#…]`) class를 `raw: <파일:줄> <class>` 줄로 나열합니다. 정보 제공용이라 exit code를 바꾸지 않습니다. `unknown:`과 `raw:` 검사는 Tailwind root가 있는 저장소에서 Tailwind class만 봅니다. CSS·inline style의 `var(--eds-*)` 참조는 검사하지 않습니다.
203
117
 
204
- - 색상 역할은 `fg`, `bg`, `stroke`를 먼저 결정합니다.
205
- - 그다음 행동 의미와 상태(`brand`, `neutral`, `critical`, `informative`, `positive`, `warning`, `disabled`, `hover`, `focus`)를 맞춥니다.
206
- - exact token이 없으면 `fg/bg/stroke` 역할, 상태(`primary`, `weak`, `disabled`, `hover`, `focus`), 행동 의미, `neutral` 순서로 가까운 공개 token을 선택합니다.
207
- - token 이름과 CSS variable은 `@spectrabrain/eds/tokens.json`과 `@spectrabrain/eds/tokens`의 공개 목록만 사용합니다.
118
+ ## 프로토타입 정렬
208
119
 
209
- text style은 font family, font weight, font size, line height, letter spacing을 한 preset으로 적용합니다. 하나의 속성만 임의로 바꿔 기존 의미를 해석하지 않습니다.
120
+ 사용자가 AI 바이브코딩으로 만든 Vite + React 프로토타입을 EVA 프론트엔드 구조로 정리하라고 요청하면, 코드를 옮기기 전에 `npx @spectrabrain/eds align`(pnpm은 `pnpm exec eds align`, yarn은 `yarn eds align`)을 실행하고 생성된 `.eds/align/PLAN.md`를 단계대로 따릅니다. 이 명령은 소스 파일을 바꾸지 않고 계획과 템플릿만 쓰며, 규칙은 `FRONTEND_CONVENTIONS.md`에 있습니다.
210
121
 
211
- ## 컴포넌트 규칙
122
+ - EDS가 설치된 frontend package에서 실행하며 git commit이 하나 이상 있어야 합니다. git 저장소나 commit이 없으면 저장소 생성과 첫 commit은 사용자에게 요청합니다. 현재 디렉터리가 React package가 아니면 하위 package를 찾고, 후보가 여럿이면 `--frontend <dir>`로 지정합니다. 그 경우 `PLAN.md`의 명령은 모두 frontend package 디렉터리에서 실행합니다. `--dry-run`은 쓸 파일만 출력합니다.
123
+ - frontend package의 `.eds/align/`에 `PLAN.md`(단계와 완료 기준), `NOTES.md`(작업 기록), `state.json`(기준 commit과 보호 경로), `templates/`(이 저장소의 경로로 채운 설정·소스 템플릿)를 씁니다. 디렉터리 안의 `.gitignore`가 디렉터리 전체를 제외하므로 commit에 들어가지 않습니다.
124
+ - 다시 실행하면 기준 commit과 `NOTES.md`를 유지하고 `PLAN.md`와 `templates/`만 새로 씁니다. 처음부터 다시 하려면 `.eds/align/`을 지운 뒤 실행합니다.
125
+ - 보호 경로는 backend 디렉터리(`server`, `backend`, `api`, `supabase` 등), backend 옆의 `shared`, backend·배포 설정 파일, frontend package 밖의 모든 파일입니다. backend를 실행하는 script와 backend 코드가 쓰는 의존성도 기록합니다. 실행 시점에 이미 있던 uncommitted 변경은 기준으로 기록합니다.
212
126
 
213
- 컴포넌트를 구현하기 전에 해당 README와 `spec.json`의 API·사용 맥락·접근성 계약을 읽습니다. 문서에 없는 prop이나 상태를 `className`, inline style, 임의 CSS로 우회하지 않습니다.
127
+ `npx @spectrabrain/eds align --check`는 파일을 쓰지 않고 점검합니다. `.eds/align/`이 없으면 보호 경로 점검 없이 컨벤션만 점검하므로, 정렬이 끝난 저장소에서 구조 규칙을 다시 확인할 때도 씁니다. 오류는 `[EDS] <종류>: …`, 경고는 `[EDS] warning <종류>: …` 줄로 출력하며, 경고는 exit code를 바꾸지 않습니다.
214
128
 
215
- `Button`은 행동의 의미와 위계를 기준으로 선택합니다. `brand/solid`는 핵심 행동, `neutral/solid`는 일반 주요 행동, `neutral/outline`은 취소·닫기·수정 같은 보조 작업, `neutral/weak`는 초기화·갱신·되돌리기처럼 부담이 낮은 반복 행동에 사용합니다. 되돌리기 어려운 삭제·초기화는 `critical/weak`를 먼저 검토합니다. `neutral/link`는 탐색에만 사용합니다.
129
+ | exit | 의미 |
130
+ | --- | --- |
131
+ | 0 | 오류가 없습니다. 출력의 `Also required` 명령이 모두 exit 0이어야 끝납니다. 경고는 고치거나 이유를 기록합니다(`.eds/align/`이 있으면 `NOTES.md`, 없으면 작업 보고). |
132
+ | 1 | 고칠 오류가 있습니다. |
133
+ | 2 | 판정할 수 없습니다(Vite + React 앱이 아님, frontend package를 정할 수 없음, 기준 commit이나 `state.json`을 읽을 수 없음 등). 출력 메시지가 원인과 조치를 알려 주므로 그대로 따릅니다. |
216
134
 
217
- icon-only 버튼은 accessible name을 확인하고, 비동기 처리 중인 버튼은 공개 `loading` contract를 사용합니다. Button 내부 시각 스타일을 `className`으로 덮어쓰지 않습니다. 이름으로 지정하는 lucide 아이콘은 `spec.json`의 `api.iconNames` 목록만 사용하며, 목록 밖 아이콘은 `icon`·`startIcon`·`endIcon`에 ReactElement로 전달합니다.
135
+ | 종류 | 의미 |
136
+ | --- | --- |
137
+ | `protected:`·`outside:` | 기준 commit 이후 보호 경로나 frontend package 밖의 파일이 바뀌었습니다. |
138
+ | `backend-script:`·`backend-dependency:` | backend를 실행하는 script가 바뀌었거나 backend 코드가 쓰는 의존성이 지워졌습니다. |
139
+ | `structure:`·`language:`·`import:` | FSD 계층, TypeScript 전환, import 방향 규칙을 어겼습니다. slice 이름·segment 위치와 widget 간 import는 경고입니다. |
140
+ | `dependency:`·`config:`·`script:` | 교체할 라이브러리가 남았거나, 표준 라이브러리·설정·script가 없거나, lint 도구가 템플릿보다 오래되었습니다. `lucide-react` 선언 버전이 EDS와 다르면 경고입니다. |
141
+ | `pattern:`·`agents:` | 항상 경고입니다. 직접 `fetch()`·axios 호출, default export, `+`로 이어 붙인 한국어 문장 같은 코드 패턴이거나, `AGENTS.md`가 아직 `FRONTEND_CONVENTIONS.md`를 가리키지 않는 상태(PLAN 8단계에서 해소)입니다. |
218
142
 
219
143
  ## 버전 업데이트
220
144
 
221
- EDS 버전을 업데이트한 뒤 다음 명령을 실행해 Tailwind root의 import, 공개 token alias, managed block과 버전 줄을 함께 갱신하고 결과를 점검합니다.
222
-
223
- ```sh
224
- npm run sync:eds
225
- npm run eds:doctor
226
- ```
145
+ EDS 버전을 올렸으면 다음 순서로 진행합니다.
227
146
 
228
- `eds:doctor`는 생성 CSS의 header와 `AGENTS.md`의 버전 줄이 설치된 버전과 다르면 `stale:`로 보고하고 exit 1로 끝나므로, sync를 빠뜨린 업데이트는 `pretypecheck`·`prebuild` hook에서 드러납니다. 생성 파일의 변경을 검토하고 소비처의 typecheck·lint·test·build를 실행합니다. `sync:eds`는 소비처 CI에서 명시적으로 실행할 수 있으며, EDS package의 `postinstall`은 이를 자동 실행하지 않습니다.
147
+ 1. sync 전에 `AGENTS.md`의 `<!-- EDS:VERSION x.y.z -->` 줄에서 이전 버전을 확인합니다. 이미 sync했다면 `git diff AGENTS.md`의 삭제된 버전 줄에서 확인합니다.
148
+ 2. package root의 `CHANGELOG.md`(`@spectrabrain/eds/CHANGELOG.md`)에서 이전 버전보다 높은 절만 읽고, 각 항목이 요구하는 소비처 조치를 모두 적용합니다. 새 항목은 `소비처 조치:`로 시작합니다.
149
+ 3. `npm run sync:eds`로 Tailwind root의 import, 공개 token alias, managed block과 버전 줄을 갱신하고, `npm run eds:doctor`가 `[EDS] synced with` 줄을 출력하는지 확인합니다.
150
+ 4. 제거되거나 이름이 바뀐 token은 `CHANGELOG.md`에서 이름을 확인하고, Tailwind class는 doctor의 `unknown:` 항목에서, `cssVar()` 호출은 typecheck 오류에서, CSS·inline style의 `var(--eds-<이름>)`은 `tokens.json`의 `cssVariable` mapping과 대조해 고칩니다. dotted public name은 CSS reference에서만 점을 escape합니다. 새로 쓸 수 있는 class는 `src/styles/eds-tokens.css`의 diff에서 확인합니다.
229
151
 
230
- 바뀐 내용은 package root의 `CHANGELOG.md`(`@spectrabrain/eds/CHANGELOG.md`)에서 확인합니다. 작업 보고에는 업데이트된 EDS 버전, 생성 파일, 새로 사용할 수 있는 class, 제거되거나 이름이 바뀐 공개 token, 검증 결과를 남깁니다.
152
+ 생성 CSS의 header나 `AGENTS.md`의 버전 줄이 설치된 버전과 다르면 doctor가 `stale:`로 보고하므로, sync를 빠뜨린 업데이트는 `pretypecheck`·`prebuild` hook(yarn berry는 `typecheck`·`build` 앞의 `eds doctor`)에서 드러납니다. 작업 보고에는 올린 EDS 버전, 적용한 소비처 조치, 바뀐 파일, 새로 쓸 수 있는 class, 제거되거나 이름이 바뀐 공개 token, 검증 결과를 남깁니다.