gitifact 0.7.1 → 0.8.1
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.
- package/README.md +44 -28
- package/dist/THIRD_PARTY_NOTICES.txt +213 -0
- package/dist/browser/assets/Banner-c1hFCLs8.js +1 -0
- package/dist/browser/assets/Grid-BrUBBmhu.js +1 -0
- package/dist/browser/assets/HoverCard-D6keobP0.js +1 -0
- package/dist/browser/assets/{Markdown-68DgpF6D.js → Markdown-Droxhk-G.js} +3 -3
- package/dist/browser/assets/MetadataListItem-C3SqHyk0.js +1 -0
- package/dist/browser/assets/PretendardVariable-CJuje-Rk.woff2 +0 -0
- package/dist/browser/assets/Selector-D_xYW7R_.js +2 -0
- package/dist/browser/assets/Tab-VVHagF2Z.js +1 -0
- package/dist/browser/assets/{Table-GZptlOQa.js → Table-D4v8xCrw.js} +2 -2
- package/dist/browser/assets/TimestampHoverCard-qfGbCkoP.js +1 -0
- package/dist/browser/assets/Token-BLd8-jfF.js +1 -0
- package/dist/browser/assets/about-DeUi-_2z.js +3 -0
- package/dist/browser/assets/activity-CiuGYDQ8.jpg +0 -0
- package/dist/browser/assets/activity-timeline-BEeyw2GA.css +1 -0
- package/dist/browser/assets/activity-timeline-bFoqFwVu.js +2 -0
- package/dist/browser/assets/changelog-Brd1Ninm.js +2 -0
- package/dist/browser/assets/commit-CiMtFlZl.js +4 -0
- package/dist/browser/assets/commit-DVyOH45R.css +1 -0
- package/dist/browser/assets/contributor-2mkEa2Wo.css +1 -0
- package/dist/browser/assets/contributor-C_IskSHq.js +1 -0
- package/dist/browser/assets/contributors-CPdOQKMF.css +1 -0
- package/dist/browser/assets/contributors-CbwXLc7M.js +1 -0
- package/dist/browser/assets/contributors._email-BRfre3dw.js +1 -0
- package/dist/browser/assets/contributors.index-CV84owW7.js +1 -0
- package/dist/browser/assets/dashboard-CMSj2wu3.css +1 -0
- package/dist/browser/assets/dashboard.index-CQdr7hsf.js +1 -0
- package/dist/browser/assets/document-BZmiLx-e.js +2 -0
- package/dist/browser/assets/document-DEGaf2yT.css +1 -0
- package/dist/browser/assets/document-Drgtj94X.css +1 -0
- package/dist/browser/assets/document-JLY2-z8S.js +19 -0
- package/dist/browser/assets/feature-requirements-CA8f9Bcf.jpg +0 -0
- package/dist/browser/assets/features-Cj41kcXf.js +4 -0
- package/dist/browser/assets/features-g3j2elTj.css +1 -0
- package/dist/browser/assets/features._featureId-BgFHsRcy.js +1 -0
- package/dist/browser/assets/features.index-Ca0rzFW6.js +1 -0
- package/dist/browser/assets/getting-started-CgL3Vi9o.js +1 -0
- package/dist/browser/assets/getting-started-DQwukRnd.css +1 -0
- package/dist/browser/assets/git-B7oxggGB.js +1 -0
- package/dist/browser/assets/git-D_wcK2vC.css +1 -0
- package/dist/browser/assets/{gitifact-logo-DPewkDQ4.svg → gitifact-logo-B5c-L14Z.svg} +5 -5
- package/dist/browser/assets/index-CmU7dwFQ.css +1 -0
- package/dist/browser/assets/index-DWRGm9YO.js +48 -0
- package/dist/browser/assets/instructions-2OUMP-vh.css +1 -0
- package/dist/browser/assets/instructions-D3cdAPD3.js +1 -0
- package/dist/browser/assets/instructions._instructionId-BkT14646.js +1 -0
- package/dist/browser/assets/instructions.agents-B3jLRl1u.js +1 -0
- package/dist/browser/assets/instructions.index-8qlhSXoy.js +1 -0
- package/dist/browser/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/dist/browser/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/dist/browser/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dist/browser/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dist/browser/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/dist/browser/assets/lazyRouteComponent-JkRa2CHo.js +1 -0
- package/dist/browser/assets/page-header-CPL7myjo.js +1 -0
- package/dist/browser/assets/page-header-atX8Nsmd.css +1 -0
- package/dist/browser/assets/project-instructions-DsWrw-nY.jpg +0 -0
- package/dist/browser/assets/records-Dk3shbYl.css +1 -0
- package/dist/browser/assets/records-page-B4Al3fIQ.js +1 -0
- package/dist/browser/assets/records-page-D2F1WJrh.css +1 -0
- package/dist/browser/assets/records._recordId-Chn1SO5R.js +1 -0
- package/dist/browser/assets/records.commits._commit-D4Wk4i_m.js +1 -0
- package/dist/browser/assets/records.index-CViTeD08.js +1 -0
- package/dist/browser/assets/records.working-BsHKMIz-.js +1 -0
- package/dist/browser/assets/request-state-oiWyP9c-.js +1 -0
- package/dist/browser/assets/search-BCYi0CBz.js +1 -0
- package/dist/browser/assets/search-palette-D0ctICJy.js +561 -0
- package/dist/browser/assets/{page-header-ClRsIf4A.css → search-palette-DpmGOAIg.css} +1 -1
- package/dist/browser/assets/settings-BDVKHrS8.js +1 -0
- package/dist/browser/assets/useInfiniteQuery-Bn_R13Ih.js +1 -0
- package/dist/browser/assets/useKeyboardHint-lSxUw5Qj.js +1 -0
- package/dist/browser/favicon.svg +5 -5
- package/dist/browser/gitifact-logo.svg +4 -4
- package/dist/browser/index.html +15 -14
- package/dist/browser/licenses/jetbrains-mono.txt +93 -0
- package/dist/browser/licenses/pretendard.txt +94 -0
- package/dist/i18n/en/block.md +25 -25
- package/dist/i18n/en/changelog.md +44 -0
- package/dist/i18n/en/docs/commit.md +23 -22
- package/dist/i18n/en/docs/design.md +45 -26
- package/dist/i18n/en/docs/instructions.md +94 -0
- package/dist/i18n/en/docs/migrate.md +140 -0
- package/dist/i18n/en/docs/records.md +82 -0
- package/dist/i18n/en/docs/spec.md +68 -31
- package/dist/i18n/en/docs/workflow.md +23 -17
- package/dist/i18n/en/docs/writing.md +46 -15
- package/dist/i18n/ko/block.md +28 -28
- package/dist/i18n/ko/changelog.md +209 -165
- package/dist/i18n/ko/docs/commit.md +21 -20
- package/dist/i18n/ko/docs/design.md +44 -25
- package/dist/i18n/ko/docs/instructions.md +94 -0
- package/dist/i18n/ko/docs/migrate.md +140 -0
- package/dist/i18n/ko/docs/records.md +82 -0
- package/dist/i18n/ko/docs/spec.md +66 -29
- package/dist/i18n/ko/docs/workflow.md +24 -18
- package/dist/i18n/ko/docs/writing.md +46 -15
- package/dist/main.js +4953 -3240
- package/package.json +1 -1
- package/dist/browser/assets/Grid-DlI9bhVm.js +0 -1
- package/dist/browser/assets/MetadataListItem-Bvdm7SCW.js +0 -1
- package/dist/browser/assets/TimestampHoverCard-_VKbn1Py.js +0 -1
- package/dist/browser/assets/about-LBmmoJtj.js +0 -3
- package/dist/browser/assets/activity-DRgs2s8a.jpg +0 -0
- package/dist/browser/assets/activity-paVxugse.js +0 -1
- package/dist/browser/assets/changelog-DMndHW2p.js +0 -2
- package/dist/browser/assets/contributors._email-Ch0pZAte.js +0 -1
- package/dist/browser/assets/contributors.index-BwSL0x8o.js +0 -1
- package/dist/browser/assets/document-Ceyg9sKE.js +0 -11
- package/dist/browser/assets/document-ChObsStB.css +0 -1
- package/dist/browser/assets/feature-requirements-Ci6Hez1P.jpg +0 -0
- package/dist/browser/assets/features._featureId-DtlIpe3Y.js +0 -1
- package/dist/browser/assets/features.index-CsxYbWGn.js +0 -1
- package/dist/browser/assets/getting-started-7e77o6gE.css +0 -1
- package/dist/browser/assets/getting-started-LVh16CZ8.js +0 -1
- package/dist/browser/assets/git-DF8OMSPX.css +0 -1
- package/dist/browser/assets/git-H0K9dpC3.js +0 -1
- package/dist/browser/assets/index-DClmARNh.js +0 -48
- package/dist/browser/assets/index-DJrBgKkG.css +0 -1
- package/dist/browser/assets/page-header-sbYRXZP4.js +0 -531
- package/dist/browser/assets/product-BIGIVBUa.js +0 -10
- package/dist/browser/assets/product-DNaVAIwO.css +0 -1
- package/dist/browser/assets/product.index-vzVtG_rC.js +0 -1
- package/dist/browser/assets/project-wiki-BBWDVTfk.jpg +0 -0
- package/dist/browser/assets/request-state-J0QLm_8G.js +0 -1
- package/dist/browser/assets/requirements-POF-07kZ.js +0 -1
- package/dist/browser/assets/settings-eas7Zq56.js +0 -1
- package/dist/browser/assets/wiki-fpAHbhnh.js +0 -1
- package/dist/browser/assets/wiki._documentId-DJ7LAi8J.js +0 -1
- package/dist/browser/assets/wiki.index-DJ7LAi8J.js +0 -1
- package/dist/i18n/en/docs/wiki.default.md +0 -27
- package/dist/i18n/en/docs/wiki.md +0 -43
- package/dist/i18n/ko/docs/wiki.default.md +0 -27
- package/dist/i18n/ko/docs/wiki.md +0 -43
|
@@ -1,52 +1,71 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: 기능 설계 형식
|
|
3
|
+
description: 설계 축과 파일 나누기, 프론트매터, 다이어그램, 개정 방식
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
설계는 기능 폴더의 `design/` 아래 파일들이며, 그 기능의 요구사항을 구현하는 구조와 처리 방식을 설명한다. 파일 하나가 설계의 한 관점(축)을 맡는다.
|
|
7
|
+
|
|
8
|
+
## 축과 파일 나누기
|
|
9
|
+
|
|
10
|
+
| 파일 | 다루는 것 |
|
|
11
|
+
| :--- | :--- |
|
|
12
|
+
| `overview.md` (필수) | 범위와 접근 방식, 구성 요소와 경계, 미결 사항 |
|
|
13
|
+
| `data.md` | 저장 형식, 데이터 구조와 관계, 캐시, 상태와 수명 |
|
|
14
|
+
| `interface.md` | 명령·API·계약, 입력과 출력, 다른 모듈과의 경계 |
|
|
15
|
+
| `ui.md` | 화면 구성과 경로, 표시 흐름, 상호작용 |
|
|
16
|
+
| `errors.md` | 오류 처리, 입력 검증, 복구, 검사 범위 |
|
|
17
|
+
|
|
18
|
+
설계가 하나라도 있으면 `overview.md`가 있어야 한다. 나머지 축은 권장이며, 필요한 축만 만든다. 기능이 작아 각 관점이 한두 문단이면 `overview.md` 하나로 둔다. 한 관점이 여러 절 분량이 되거나 다른 관점과 따로 고쳐지면 그 축의 파일로 옮긴다. 빈 축 파일이나 양식만 채운 파일을 만들지 않는다. 표에 없는 관점이 필요하면 소문자·숫자·하이픈 slug로 파일을 더 둘 수 있다.
|
|
2
19
|
|
|
3
|
-
|
|
20
|
+
같은 내용을 두 파일에 적지 않는다. `overview.md`는 다른 축의 세부를 요약해 반복하지 않고, 어떤 축 파일이 있는지 읽는 사람이 알 수 있으면 충분하다.
|
|
4
21
|
|
|
5
22
|
## 파일 구조
|
|
6
23
|
|
|
7
|
-
|
|
24
|
+
파일은 `gitifact specs new design <기능>/<축> --title "<제목>" --description "<한 줄>"`로 만든다. CLI가 D- ID를 발급하고 `order`를 같은 폴더의 최댓값+10으로 매기며 `draft: true`를 붙인다. 본문을 채운 뒤 `draft: true` 줄을 지우고 `gitifact check`로 확인한다. ID를 직접 만들지 않는다.
|
|
8
25
|
|
|
9
26
|
```markdown
|
|
10
27
|
---
|
|
11
|
-
id:
|
|
28
|
+
id: D-CLI가발급한값
|
|
29
|
+
title: 게시물 저장 구조
|
|
30
|
+
description: 게시물과 첨부 파일의 저장 형식과 삭제 시 정리 순서
|
|
31
|
+
order: 20
|
|
32
|
+
requirements:
|
|
33
|
+
- R-관련요구사항의실제값
|
|
12
34
|
sources:
|
|
13
|
-
-
|
|
14
|
-
path: ../../wiki/architecture.md
|
|
35
|
+
- id: I-따른지침의실제값
|
|
15
36
|
note: 계층 구조와 의존 방향
|
|
16
37
|
- title: 라이브러리 문서
|
|
17
38
|
url: https://example.test/docs
|
|
18
39
|
---
|
|
19
40
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## 개요
|
|
23
|
-
구현할 범위와 접근 방식.
|
|
24
|
-
|
|
25
|
-
## 처리 흐름
|
|
26
|
-
<!-- gitifact-ref: R-관련요구사항의실제값 -->
|
|
27
|
-
입력부터 결과까지의 핵심 흐름.
|
|
41
|
+
게시물은 ...
|
|
28
42
|
```
|
|
29
43
|
|
|
30
|
-
위 문장은 구조 설명이다. 실제
|
|
44
|
+
위 ID와 문장은 구조 설명이다. 실제 값으로 채우고 예시를 그대로 저장하지 않는다.
|
|
31
45
|
|
|
32
|
-
|
|
46
|
+
- **`title`·`description`:** 필수이며 한 줄이다. 제목은 본문에 `#`로 다시 쓰지 않는다. 본문 절은 `##`부터 쓰고 gitifact 주석을 넣지 않는다.
|
|
47
|
+
- **`order`:** 기능을 이해하기 좋은 순서로 매긴다. overview가 맨 앞이고 기본은 data → interface → ui → errors 순이다. 같은 폴더에서 겹치면 안 된다.
|
|
48
|
+
- **`requirements`:** 이 파일이 실제로 설명하는 요구사항의 R- ID만 적는다. 한 요구사항을 여러 설계 파일이 가리켜도 된다. 기능 전체의 요구사항을 모든 파일에 복사하지 않는다.
|
|
49
|
+
- **`sources`:** 이 파일이 근거로 삼은 문서다. 저장소 안의 문서는 `{id, note?}`로 ID만, 외부 자료는 `{title, url, note?}`로 적는다. 브라우저는 이 목록을 참고 문서 카드로 보여 준다. 외부 페이지의 제목이나 미리보기는 가져오지 않는다.
|
|
33
50
|
|
|
34
|
-
|
|
51
|
+
본문의 상대 링크(`../../../assets/flow.png` 등)는 이 파일 기준 경로로 쓰며 브라우저가 해당 대상으로 연결한다. 문서 사이의 관계는 링크가 아니라 프론트매터로 나타낸다.
|
|
35
52
|
|
|
36
|
-
|
|
53
|
+
## 본문 작성
|
|
37
54
|
|
|
38
|
-
|
|
55
|
+
본문의 문체는 `gitifact guide show writing`을 따른다. 본문에는 지금의 구조와 동작을 쓴다. 확정한 것, 구현에서 관측한 것, 제안을 구분한다.
|
|
39
56
|
|
|
40
|
-
|
|
57
|
+
설계는 결정 표를 두지 않는다. 여러 안 중 하나를 고른 결정은 그 맥락과 검토한 대안과 함께 결정기록으로 남기고 본문에는 고른 결과만 규칙으로 쓴다(`gitifact guide show records`). 설계를 고치기 전에 `gitifact records list --doc <D-ID>`로 그 설계의 결정 흐름을 읽어, 이미 고르지 않은 안을 다시 제안하지 않는다. 바뀐 경위·날짜·옛 방식도 본문이 아니라 기록에 둔다.
|
|
41
58
|
|
|
42
|
-
|
|
59
|
+
다이어그램은 종류 고르기와 작성 규칙을 `gitifact guide show writing`에서 따르고, 그림이 설명하는 축의 파일에 둔다. 축마다 잘 맞는 종류가 있다. data는 `erDiagram`과 캐시·읽기 흐름의 `flowchart`, interface는 구성 요소 사이 요청의 `sequenceDiagram`, ui는 화면 상태의 `stateDiagram-v2`, errors는 실패와 복구 흐름에 쓴다.
|
|
43
60
|
|
|
44
|
-
|
|
61
|
+
설계를 쓰기 전에 AGENTS.md 색인에서 작업 영역의 지침을 읽고, 따른 지침은 `sources`에 올린다. 지침에 있는 내용은 설계에 다시 쓰지 않는다. 설계에는 이 기능에만 해당하는 것만 쓴다. 지침은 설계를 가리키지 않으므로 관계는 이 한 방향으로만 적는다. 설계가 지침의 기준과 어긋나면 지침을 먼저 고칠지 사용자와 정한다.
|
|
45
62
|
|
|
46
|
-
|
|
63
|
+
## 언제 쓰는가
|
|
47
64
|
|
|
48
|
-
|
|
65
|
+
새 기능을 정리할 때 요구사항과 설계를 함께 쓰는 것이 기본이다. 사용자가 요구사항만 요청하면 따르고, 설계가 없는 기존 기능에 일괄로 만들지 않는다. 단계별 승인을 강제하지 않으며 중요한 불명확함만 질문한다.
|
|
49
66
|
|
|
50
67
|
## 개정
|
|
51
68
|
|
|
52
|
-
개정
|
|
69
|
+
개정 전에 그 기능의 설계 파일들과 관련 요구사항을 읽고 영향을 받는 파일만 고친다. 바뀐 문장은 고쳐 쓰고 '전에는 …했다'는 문장을 덧붙이지 않는다. 바뀐 경위는 결정기록에 쓰고 과거 원문은 Git이 보존한다. 결정이 바뀌면 본문의 규칙을 고치고 새 결정기록을 쓴다. 요구사항을 바꾸면 그것을 가리키는 설계도 검토하고(`gitifact specs show <R-ID>`의 "가리키는 문서"), 설계만 바뀌면 요구사항을 억지로 고치지 않는다.
|
|
70
|
+
|
|
71
|
+
한 파일이 커져 축을 나누거나 합칠 때는 문장을 옮기기만 하고 같은 커밋에서 내용을 고치지 않는다. 옮긴 뒤 옛 파일의 문장이 새 파일들에 빠짐없이 있는지 대조한다. 파일을 옮겨도 ID는 그대로 두고, 지운 파일의 `requirements`가 남은 파일로 옮겨졌는지 확인한다. 옮기기만 한 커밋에는 결정기록을 쓰지 않아도 된다.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 프로젝트 지침 형식
|
|
3
|
+
description: 작업별 지침 폴더의 형식, AGENTS.md 색인, 명세와의 관계, 에셋과 커밋
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
프로젝트 지침은 이 프로젝트에서 어떻게 일하는지를 담는다. 아키텍처 규칙, 여러 기능에 걸친 결정, 문체, 검증 절차가 여기에 들어간다. 요구사항은 무엇을 만들지, 설계는 한 기능을 어떻게 만들지를 말하고, 지침은 기능과 무관하게 일하는 방식을 말한다. 기능별 동작은 명세에 두고 지침에 반복하지 않는다.
|
|
7
|
+
|
|
8
|
+
## 폴더와 파일
|
|
9
|
+
|
|
10
|
+
지침 하나는 `.gitifact/instructions/<이름>/` 폴더다. 이름은 소문자·숫자·하이픈 80자까지다. 폴더의 `index.md`가 지침 문서이고, 긴 내용은 같은 폴더의 `references/` 아래 참고 파일로 나눈다. `index.md`에는 늘 지킬 짧은 규칙과, 어떤 작업 때 어느 참고 파일을 읽을지의 색인을 상대 링크로 둔다. 에이전트는 `index.md`와 목록의 제목·설명만 보고 이번 작업에 필요한 참고 파일만 연다.
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
.gitifact/instructions/
|
|
14
|
+
cli-architecture/
|
|
15
|
+
index.md 지침 문서 (I-)
|
|
16
|
+
references/
|
|
17
|
+
checklist.md 긴 목록
|
|
18
|
+
verification/
|
|
19
|
+
index.md
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
새 지침은 CLI로 만든다. CLI가 `I-` ID를 발급하고 프론트매터를 채우며 `draft: true`를 붙인다. 본문을 채운 뒤 이 줄을 지우고 `gitifact check`로 확인한다.
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
gitifact instructions new code-review --title "코드 리뷰" --description "리뷰에서 확인할 것과 보고 형식. 변경을 리뷰할 때 쓴다."
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
---
|
|
30
|
+
id: I-CLI가발급한값
|
|
31
|
+
title: 코드 리뷰
|
|
32
|
+
description: 리뷰에서 확인할 것과 보고 형식. 변경을 리뷰할 때 쓴다.
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
규칙과 이유. 긴 목록은 [references/checklist.md](references/checklist.md)에 둔다.
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
위 ID와 문장은 구조 설명이다. `index.md`의 프론트매터는 `id`·`title`·`description`만 두고 모두 필수다. `description`에는 무엇을 담는지와 어떤 작업 때 읽는지를 함께 쓴다. 제목은 본문에 `#`로 다시 쓰지 않으며, 본문 절은 `##`부터 쓰고 gitifact 주석을 넣지 않는다. 본문의 문체는 `gitifact guide show writing`을 따른다.
|
|
39
|
+
|
|
40
|
+
`index.md`가 아닌 Markdown 파일(참고 파일)은 프론트매터에 `title`과 `description`만 두며 둘 다 필수다. ID·`order`·`draft`는 없다. 소속은 폴더가, 순서는 경로가 정한다. 참고 파일은 CLI 명령 없이 직접 만든다. `description`에는 무엇을 담는지와 어떤 작업 때 읽는지를 쓴다. 프론트매터가 없거나 다른 키가 있으면 `check`의 문제다. 본문은 검사하지 않는다.
|
|
41
|
+
|
|
42
|
+
```markdown
|
|
43
|
+
---
|
|
44
|
+
title: 리뷰 체크리스트
|
|
45
|
+
description: 리뷰에서 확인할 항목 전체. 큰 변경이나 보안에 닿는 변경을 리뷰할 때 읽는다.
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
항목들
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
이미지 같은 Markdown이 아닌 파일은 프론트매터 없이 둔다.
|
|
52
|
+
|
|
53
|
+
이미 있는 지침은 파일을 직접 고친다. 이름을 바꿀 때는 폴더를 옮기고 ID를 유지하며, 지울 때는 폴더를 지운다. 지운 지침을 설계의 `sources`가 가리키고 있으면 그 설계도 고쳐야 `check`가 통과한다. `index.md`가 없는 지침 폴더는 `INSTRUCTION_INDEX_REQUIRED` 문제다.
|
|
54
|
+
|
|
55
|
+
## AGENTS.md 색인
|
|
56
|
+
|
|
57
|
+
에이전트는 모든 세션에서 AGENTS.md를 읽는다. 어떤 작업 때 어느 지침을 읽을지는 AGENTS.md의 GITIFACT 블록 밖에 짧게 적는다. 블록은 CLI가 갱신하므로 색인을 블록 안에 쓰지 않는다.
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
## 작업별 지침
|
|
61
|
+
|
|
62
|
+
- CLI 코드를 바꿀 때: `.gitifact/instructions/cli-architecture/index.md`
|
|
63
|
+
- 변경을 검증하거나 커밋하기 전: `.gitifact/instructions/verification/index.md`
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
지침을 만들거나 이름을 바꾸거나 지우면 색인도 함께 고친다. 매 세션 필요한 짧은 사실은 AGENTS.md에 두고, 특정 작업 때만 필요한 내용은 지침에 둔다.
|
|
67
|
+
|
|
68
|
+
## 명세와의 관계
|
|
69
|
+
|
|
70
|
+
지침은 명세를 가리키지 않는다. 지침은 여러 기능에 걸친 지식이라, 한 기능의 명세에 묶이면 명세가 바뀔 때 함께 낡는다. 설계가 따른 지침을 `sources`에 `{id: I-…}`로 올리는 한 방향만 둔다. 지침 폴더의 Markdown이 `.gitifact/spec/` 아래를 링크하면 `INSTRUCTION_SPEC_LINK` 문제다. 저장 형식을 설명하는 경로 패턴을 코드 블록 안에 쓰는 것은 링크가 아니다.
|
|
71
|
+
|
|
72
|
+
지침 사이의 링크와 에셋으로 가는 링크는 이 파일 기준 상대 경로로 쓴다. 예: `../verification/index.md`, `../../assets/diagrams/flow.png`. 대상이 없는 링크는 `check`와 `changes list`가 `MISSING_LINK_TARGET` 경고로 알린다.
|
|
73
|
+
|
|
74
|
+
## 결정
|
|
75
|
+
|
|
76
|
+
지침은 결정 표나 결정 기록 파일을 스스로 두지 않는다. 여러 기능에 걸친 구조·기술 선택은 지침 본문에 규칙으로 쓰고, 그 맥락과 검토한 대안은 그 지침을 가리키는 결정기록으로 남긴다(`gitifact guide show records`). 지침을 고치기 전에 `gitifact records list --doc <I-ID>`로 결정 흐름을 읽는다. 결정이 바뀌면 본문의 규칙을 고치고 새 결정기록을 쓴다.
|
|
77
|
+
|
|
78
|
+
지침을 새로 만들거나 넓히면 설계들에서 같은 내용을 `gitifact specs list --q`로 찾아 지운다. 지운 설계의 `sources`에 그 지침을 더하고, 옮긴 사실을 결정기록 하나로 남긴다(`docs`에 지침과 고친 설계들).
|
|
79
|
+
|
|
80
|
+
## 에셋
|
|
81
|
+
|
|
82
|
+
이미지·PDF 등 Markdown이 아닌 파일은 지침 폴더 안이나 `.gitifact/assets/` 아래에 둔다. 한 지침만 쓰는 파일은 그 폴더에, 여러 문서가 함께 쓰는 파일은 assets에 둔다. assets의 권장 확장자는 png·jpg·gif·webp·svg·pdf, 권장 크기는 파일당 1MB·전체 50MB 이하다. 넘어도 커밋은 되며 `check`와 `changes list`가 `ASSET_SIZE`·`ASSET_EXTENSION`·`ASSETS_TOTAL_SIZE` 경고로 알린다. 어떤 문서도 참조하지 않는 assets 파일은 `UNREFERENCED_ASSET`으로 알린다.
|
|
83
|
+
|
|
84
|
+
## 커밋
|
|
85
|
+
|
|
86
|
+
지침의 변경은 `index.md`의 변경이다. 결정기록의 `docs`에 지침의 I- ID를 적는다. 폴더 안 다른 파일도 `paths`에 담아 함께 커밋할 수 있고, 그 파일만 바뀐 것에는 기록을 요구하지 않는다(`gitifact guide show commit`).
|
|
87
|
+
|
|
88
|
+
## 에이전트
|
|
89
|
+
|
|
90
|
+
- 요구사항·설계·코드를 바꾸기 전에 AGENTS.md 색인에서 작업 영역에 맞는 지침을 찾아 읽고 따른다. 맞는 지침이 없으면 없다고 보고 진행한다.
|
|
91
|
+
- `gitifact instructions list`는 AGENTS.md가 있는지와, 지침마다 딸린 파일의 경로·제목·설명을 보인다. 지침은 `instructions show <이름>`으로 `index.md`를, `instructions show <이름> --file references/<파일>`로 딸린 파일을 읽는다.
|
|
92
|
+
- 요청이 지침과 어긋나면 진행 전에 알린다. 지침을 바꿀지는 사용자와 정한다.
|
|
93
|
+
- 여러 기능에 걸친 규칙이나 결정을 새로 정하면 지침에 남길지 제안한다. 사용자가 동의하면 기존 지침을 고치거나 `gitifact instructions new`로 만들고 AGENTS.md 색인을 함께 고친다.
|
|
94
|
+
- 0.7의 위키(`.gitifact/wiki/`)는 0.8.0에서 지침으로 바뀌었다. 위키 페이지가 남아 있으면 `check`가 `WIKI_REMOVED`로 알린다. 옮기는 절차는 `gitifact guide show migrate`를 따른다.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 0.7 프로젝트 전환
|
|
3
|
+
description: schemaVersion 2 프로젝트를 0.8.0 문서 형식으로 옮기는 절차, 검증, 전환 커밋
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
사용자가 0.7 형식(`.gitifact/config.json`의 `schemaVersion: 2`) 프로젝트를 0.8.0 문서 형식(schemaVersion 3)으로 옮겨 달라고 하면 이 절차를 따른다. CLI에는 변환 명령이 없으므로 에이전트가 옛 파일을 직접 읽고 새 구조로 쓴다. 끝나면 "보고" 절의 형식으로 알린다.
|
|
7
|
+
|
|
8
|
+
이 지침에서 `gitifact`는 이 지침을 출력한 CLI(0.8.0 이상)의 실행 방법이다. 0.7.x CLI는 쓰지 않는다. 0.8.0 CLI는 schemaVersion 2 프로젝트의 조회를 거부하므로, 3절에서 설정을 바꾸기 전까지는 파일을 직접 읽는다.
|
|
9
|
+
|
|
10
|
+
## 1. 시작 전에 확인할 것
|
|
11
|
+
|
|
12
|
+
- `git status`가 깨끗해야 한다. 커밋되지 않은 변경이나 staging이 있으면 멈추고 사용자에게 알린다.
|
|
13
|
+
- 옛 형식으로 `.gitifact/`를 고친 **열린 브랜치**가 있으면 전환 전에 합치라고 사용자에게 알리고, 합칠지 계속할지 확인받는다. 전환 뒤에 옛 형식 브랜치를 합치면 두 형식이 섞이고 `gitifact check`가 실패한다.
|
|
14
|
+
- 전환은 마지막에 한 커밋으로 남긴다. 커밋 권한이 있는지 사용자에게 확인한다. 가능하면 새 브랜치에서 작업하고 검증 뒤 합친다.
|
|
15
|
+
- 새 형식은 이 지침의 3절이 전부 설명한다. 형식이 헷갈리면 프로젝트 밖의 빈 Git 저장소에서 `gitifact init`과 `gitifact specs new feature|requirement|design|instruction …`를 실행해 CLI가 만드는 뼈대를 보고, `gitifact check`로 맞는지 확인한다.
|
|
16
|
+
|
|
17
|
+
## 2. 옛 형식 읽기
|
|
18
|
+
|
|
19
|
+
| 옛 파일 | 형식 |
|
|
20
|
+
| :--- | :--- |
|
|
21
|
+
| `.gitifact/spec/<기능>/requirements.md` | 프론트매터 `id: S-…`, 본문 첫 줄 `# 기능 제목`. `# 제목`과 첫 `## ` 사이에 문단이 있으면 그것이 기능의 소개다. 요구사항마다 `## 요구사항 제목` 다음 줄에 `<!-- gitifact-req: R-… -->`, 그 아래부터 다음 `## `까지(코드 블록 안 제외)가 요구사항 본문 |
|
|
22
|
+
| `.gitifact/spec/<기능>/design.md` (있을 때) | 프론트매터 `id`(기능과 같은 S-)와 선택적 `sources`(`title`, `path` 또는 `url`, `note`). 본문 첫 줄 `# 설계 제목`, 절 아래에 `<!-- gitifact-ref: R-…[, R-…] -->` |
|
|
23
|
+
| `.gitifact/spec/<기능>/history.jsonl` | 한 줄에 `{"id":"H-…","requirements":[R-…],"designs":[S-…]?,"documents":[W-…]?,"reason":"…"}` |
|
|
24
|
+
| `.gitifact/wiki/**/*.md` | 프론트매터 `id: W-…`, 본문 첫 줄 `# 페이지 제목` |
|
|
25
|
+
| `.gitifact/wiki/history.jsonl` | 위와 같은 이유 줄. 대상은 주로 `documents` |
|
|
26
|
+
|
|
27
|
+
시작 전에 개수를 세어 둔다: 기능(`requirements.md`) 수, 요구사항(`gitifact-req` 주석) 수, 설계(`design.md`) 수, 위키 페이지 수. 4절에서 대조한다.
|
|
28
|
+
|
|
29
|
+
## 3. 새 구조로 옮기기
|
|
30
|
+
|
|
31
|
+
모든 구조 정보는 프론트매터에만 둔다. 본문에는 `#` 제목과 `<!-- gitifact-` 주석을 쓰지 않는다(코드 블록 안은 예외). 제목(`title`)은 200자, 설명(`description`)은 300자 이하의 한 줄이며 모두 필수다.
|
|
32
|
+
|
|
33
|
+
1. **설정:** `.gitifact/config.json`의 `schemaVersion`을 3으로 바꾼다. `baseline`은 그대로 둔다.
|
|
34
|
+
2. **기능:** `.gitifact/spec/<기능>/index.md`를 만든다.
|
|
35
|
+
```markdown
|
|
36
|
+
---
|
|
37
|
+
id: S-… # 옛 requirements.md의 id 그대로
|
|
38
|
+
title: 기능 제목 # 옛 # 제목 그대로
|
|
39
|
+
description: 이 기능이 무엇인지 한 줄
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
(옛 파일의 소개 문단이 있으면 그대로, 없으면 이 기능의 범위와 목적을 한두 문장으로 쓴다. 본문은 필수)
|
|
43
|
+
```
|
|
44
|
+
3. **요구사항:** 요구사항마다 `.gitifact/spec/<기능>/requirements/<slug>.md`를 만든다. slug는 제목을 나타내는 영어 소문자·숫자·하이픈(80자 이하)이다. `order`는 옛 파일의 순서대로 10, 20, 30…이다. 본문은 옛 요구사항 본문을 **한 글자도 바꾸지 않고** 옮긴다(`###` 소제목도 그대로). 본문 앞뒤의 빈 줄만 잘라 낸다.
|
|
45
|
+
```markdown
|
|
46
|
+
---
|
|
47
|
+
id: R-…
|
|
48
|
+
title: 요구사항 제목
|
|
49
|
+
description: 무엇을 요구하는지 한 줄
|
|
50
|
+
order: 10
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
(옛 본문 그대로)
|
|
54
|
+
```
|
|
55
|
+
4. **설계:** 옛 design.md가 있는 기능마다 `gitifact specs new design <기능>/overview --title "<옛 설계 제목>" --description "<한 줄>"`을 실행해 D- ID를 받는다. 이 명령이 만든 `design/overview.md`의 본문을 옛 설계 본문(첫 줄 `# 설계 제목`은 뺀다)으로 바꾸고 `draft: true` 줄을 지운다. 이어서:
|
|
56
|
+
- 옛 본문의 `<!-- gitifact-ref: … -->` 줄은 지우고, 거기 적힌 R- ID를 모두 모아 중복 없이 프론트매터 `requirements`에 적는다.
|
|
57
|
+
- 옛 `sources`는 `path`면 그 경로가 가리키는 위키 페이지의 W- ID로 `- id: W-…`(`note`가 있으면 함께), `url`이면 `- title: …` / `url: …`로 옮긴다. W-는 5단계에서 그 페이지를 옮긴 지침의 I-로 바뀐다.
|
|
58
|
+
- 본문의 나머지는 바꾸지 않는다. `specs new`가 넣은 `order: 10`은 그대로 둔다. 설계를 관점별 파일(data, interface, ui, errors 등)로 나누는 것은 전환 커밋에서 하지 않는다. 옮긴 본문을 대조할 수 있게 overview 하나로 옮기고, 나누기는 전환 뒤 별도 커밋으로 `gitifact guide show design`에 따라 한다.
|
|
59
|
+
- 결과의 프론트매터는 이 모양이다. 새 형식의 참고 문서에는 `title`이 없으므로, 위키 페이지를 가리키던 옛 `title`은 사라진다.
|
|
60
|
+
```markdown
|
|
61
|
+
---
|
|
62
|
+
id: D-…
|
|
63
|
+
title: 옛 설계 제목
|
|
64
|
+
description: 한 줄
|
|
65
|
+
order: 10
|
|
66
|
+
requirements:
|
|
67
|
+
- R-…
|
|
68
|
+
- R-…
|
|
69
|
+
sources:
|
|
70
|
+
- id: I-…
|
|
71
|
+
note: 옛 note (있을 때)
|
|
72
|
+
- title: 외부 문서 제목
|
|
73
|
+
url: https://…
|
|
74
|
+
---
|
|
75
|
+
```
|
|
76
|
+
5. **위키 → 지침:** 0.8.0에서 위키는 프로젝트 지침으로 바뀌었다(`gitifact guide show instructions`). 위키 페이지가 `.gitifact/wiki/`에 남아 있으면 `check`가 `WIKI_REMOVED`로 막으므로 모든 페이지를 지침 폴더로 옮긴다. 옮기기 전에 어느 페이지가 어느 지침의 어느 파일이 되는지 표로 사용자에게 보여 주고 확인받는다. 사용자가 묶음을 바꾸면 그대로 따른다.
|
|
77
|
+
|
|
78
|
+
| 옛 위치 | 새 위치 |
|
|
79
|
+
| :--- | :--- |
|
|
80
|
+
| `wiki/README.md`(운영 방침·진입 페이지) | `init`이 만든 기본 방침(결정 기록을 `adr/`에 쌓는다는 내용) 그대로면 옮기지 않고 지운다. 프로젝트가 고쳤으면 루트 페이지처럼 지침 `overview`의 `index.md`로 옮긴다. 그 안의 위키 운영 규칙을 AGENTS.md로 옮길지는 6절에서 정한다 |
|
|
81
|
+
| 루트 페이지 `wiki/<이름>.md` | 지침 `<이름>`의 `index.md`. 대문자 이름은 소문자로 바꾼다(`ARCHITECTURE.md` → `architecture`) |
|
|
82
|
+
| 최상위 폴더 `wiki/<폴더>/` | 지침 `<폴더>`. 폴더의 `README.md`가 있으면 그것이 `index.md`, 나머지 페이지는 `references/<폴더 안 경로>` |
|
|
83
|
+
| 루트 페이지와 같은 이름의 폴더 | 한 지침으로 합친다. 루트 페이지가 `index.md`다 |
|
|
84
|
+
|
|
85
|
+
- 지침마다 `gitifact instructions new <이름> --title "<제목>" --description "<한 줄>"`을 실행해 I- ID를 받는다. 제목은 `index.md`가 될 페이지의 옛 제목이다. 그런 페이지가 없는 폴더는 폴더가 담은 주제로 제목을 짓는다(예: `handbook` → 작업 안내서). description에는 무엇을 담는지와 어떤 작업 때 읽는지를 쓴다.
|
|
86
|
+
- `index.md`가 될 페이지는 옛 본문의 첫 줄 `# 제목`을 빼고 나머지를 바꾸지 않고 옮긴다. `specs new`가 만든 본문을 이것으로 바꾸고 `draft: true` 줄을 지운다. 폴더에 `index.md`가 될 페이지가 없으면 본문에 references 파일마다 옛 제목과 링크를 한 줄씩 적는다.
|
|
87
|
+
- references로 옮기는 페이지는 옛 본문을 그대로(`# 제목` 줄 포함) 옮기고, 프론트매터의 `id: W-…`를 `title`(옛 `# 제목`)과 `description`(무엇을 담는지와 어떤 작업 때 읽는지 한 줄)으로 바꾼다. 참고 파일에는 ID가 없다.
|
|
88
|
+
- 위키 폴더에 있던 이미지 등 Markdown이 아닌 파일은 그것을 쓰는 지침 폴더로 옮긴다.
|
|
89
|
+
- 지침은 명세를 가리킬 수 없다(`INSTRUCTION_SPEC_LINK`). 옮긴 파일에서 `.gitifact/spec/` 아래로 가는 링크는 `[글자](경로)`를 링크 글자만 남긴다. 다른 상대 링크는 6단계에서 새 위치에 맞게 고친다.
|
|
90
|
+
- 4단계에서 위키 페이지 W-를 가리킨 설계 `sources`는 그 페이지가 옮겨 간 지침의 I-로 바꾼다. 한 설계가 같은 지침을 두 번 가리키게 되면 하나로 합치고 note를 `; `로 잇는다.
|
|
91
|
+
- 옛 W- ID는 문서에서 사라지고 0.7 커밋의 이유에만 남는다.
|
|
92
|
+
- 위키의 결정 기록(ADR) 페이지를 결정기록 파일로 바꾸거나 지침을 다시 묶는 일은 전환 커밋에서 하지 않는다. 옮긴 본문을 대조할 수 있게 그대로 옮기고, 다듬기는 전환 뒤 별도 커밋으로 한다.
|
|
93
|
+
6. **상대 링크:** 요구사항·설계가 새 경로로 옮겨졌으므로, 문서 본문의 상대 링크 중 옛 `requirements.md`·`design.md`를 가리키거나 파일 위치가 바뀌어 깨지는 것을 새 경로로 고친다(요구사항·설계 본문은 한 단계 깊어졌다). 위키 페이지로 가던 링크는 그 페이지가 옮겨 간 지침 파일로, 옮긴 지침 파일 안의 링크는 새 위치 기준으로 고친다. 링크를 고치는 것 외에 본문을 다듬지 않는다.
|
|
94
|
+
7. **이유:** 옛 history.jsonl의 이유는 옮기지 않는다. 0.7 커밋에 남아 있어 전환 뒤에도 이력(`records list --doc`, 브라우저)에 그대로 보인다. 0.8.0에서 새로 생기는 변경의 이유는 결정기록으로 남긴다(`gitifact guide show records`). 전환 커밋에는 결정기록을 쓰지 않는다. 전환 커밋은 이력에서 숨겨진다.
|
|
95
|
+
8. **옛 파일 삭제:** 모든 `.gitifact/spec/<기능>/requirements.md`, `design.md`, `history.jsonl`과, 5단계에서 페이지를 모두 옮긴 `.gitifact/wiki/` 폴더 전체(`wiki/history.jsonl` 포함)를 일반 파일 삭제로 지운다. `git rm`은 staging을 만들어 5절의 커밋이 거부되므로 쓰지 않는다. 이미 staging됐다면 `git restore --staged <경로>`로 푼다.
|
|
96
|
+
|
|
97
|
+
기계적인 부분(파일 나누기, 위키 페이지 옮기기)은 일회성 스크립트로 해도 된다. 스크립트는 프로젝트 밖에 두고 커밋하지 않는다. slug·description·기능 본문은 내용을 읽고 직접 쓴다. 기능·요구사항·지침·참고 파일마다 description이 하나씩 필요하므로 전환에서 가장 큰 일이다(기능 18개·요구사항 45개·지침 5개면 68개). description은 그 문서가 무엇을 요구하거나 다루는지를 목록에서 한 줄로 알아볼 수 있게 쓴다. 제목을 되풀이하지 말고 사용자 스토리나 첫 문단의 핵심을 줄인다.
|
|
98
|
+
|
|
99
|
+
**예외로 허용되는 것:** 평소에는 ID를 CLI만 발급하고 커밋된 이유를 고치지 않는다. 이번 전환에서만 기존 S-·R- ID를 옮겨 적는다. 새 ID를 지어내지 않는다(설계 D-와 지침 I-는 `specs new`로 받는다).
|
|
100
|
+
|
|
101
|
+
## 4. 검증
|
|
102
|
+
|
|
103
|
+
1. `gitifact check`가 `문제 없음`이어야 한다. 문제가 있으면 고친다.
|
|
104
|
+
2. 2절에서 센 개수와 대조한다: 기능 수 = `index.md` 수, 요구사항 수, 설계 수(기능별 `design/overview.md`), 위키 페이지 수(5단계 표의 `index.md`와 references 파일 수의 합). 문서는 `gitifact specs list --format json`과 `gitifact instructions list --format json`으로 센다.
|
|
105
|
+
3. 옛 ID가 모두 새 문서에 있는지 확인한다. 옛 ID는 `git grep -ohE '(S|R)-[a-z2-7]{10}' HEAD -- .gitifact`의 정의 위치(프론트매터 `id`, `gitifact-req` 주석)에서, 새 ID는 `gitifact specs list --format json`의 `documents[].id`에서 모은다. `.gitifact/wiki/`와 `history.jsonl` 파일이 남지 않았고 설계 `sources`에 W-가 없어야 한다.
|
|
106
|
+
4. `gitifact changes list`의 마지막에 `문서 검사: 문제 없음`이 나와야 한다. 이 시점의 다른 출력은 전환에서 정상이다: 옛 형식은 새 파서로 읽히지 않으므로 모든 문서가 `created`로 나온다. 새로 만든 문서에는 결정기록이 필요 없다. 커밋을 막지 않는다.
|
|
107
|
+
|
|
108
|
+
## 5. 커밋
|
|
109
|
+
|
|
110
|
+
`gitifact changes list`가 알려 준 입력 파일 경로에 JSON을 쓰고 `gitifact changes commit --file <그 경로>`를 실행한다. 먼저 `--dry-run`으로 확인한다. `paths`는 `git status --porcelain --untracked-files=all`에 나오는 경로 전부다(`.gitifact/cache/`는 스스로 제외되어 나오지 않는다). `evidence`에는 사용자가 전환과 커밋을 요청한 말을 인용한다.
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"paths": ["<바뀌거나 새로 생기거나 지워진 모든 경로: .gitifact/config.json, 새 문서들, 지운 옛 파일들>"],
|
|
115
|
+
"message": "chore(gitifact): migrate to the 0.8.0 document format",
|
|
116
|
+
"authorization": { "basis": "user-request", "evidence": "<사용자가 전환과 커밋을 요청한 말>" },
|
|
117
|
+
"migration": true
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- 전환 커밋은 경로를 5,000개까지 받는다(일반 커밋은 128개). 5,000개를 넘으면 여러 커밋으로 나누고, 모든 커밋에 `migration: true`를 넣어 이력에서 숨긴다.
|
|
122
|
+
- `migration: true`가 있어야 `Gitifact-Migration: 0.8.0` 트레일러가 붙는다. 이 커밋이 이력의 경계가 되어, 그 이전 활동은 뷰어에서 그대로 보이고 이 커밋은 활동에 나오지 않는다.
|
|
123
|
+
- 결정기록은 넣지 않는다. 0.7 이유는 0.7 커밋에서 읽힌다.
|
|
124
|
+
- 지운 옛 파일도 `paths`에 넣어야 한다. 빠지면 CLI가 거부한다.
|
|
125
|
+
|
|
126
|
+
## 6. 전환 뒤 정리
|
|
127
|
+
|
|
128
|
+
- 에이전트 지침 파일의 GITIFACT 블록을 `gitifact update`로 새 버전에 맞춘다. 블록 밖의 프로젝트 지침(AGENTS.md, CLAUDE.md 등)에 `spec working`, `spec save`, `spec commit`, `docs <topic>` 같은 옛 명령이 있으면 새 명령(`specs`·`instructions`·`records`의 `list`·`show`·`new`, `check`, `changes list`·`commit`, `guide show`)으로 바꿔 별도 커밋으로 남길지 사용자에게 묻는다.
|
|
129
|
+
- 0.7.x 브라우저가 만든 옛 색인 `<git 공용 폴더>/gitifact/`(보통 `.git/gitifact/`)가 있으면 지워도 된다고 알린다. 0.8.0은 쓰지 않으며, 지우는 것은 사용자에게 맡긴다.
|
|
130
|
+
- 0.8.0의 캐시는 `.gitifact/cache/`에 생기고 스스로 Git에서 제외된다. 첫 조회는 이력을 처음부터 읽어 몇 초 걸릴 수 있다.
|
|
131
|
+
- 지침 `overview`로 옮긴 위키 README에 위키 운영 규칙(무엇을 어디에 쌓는지)이 있으면, 그 규칙을 AGENTS.md나 해당 지침으로 옮길지 사용자와 정한다. 이어서 AGENTS.md의 GITIFACT 블록 밖에 지침 색인을 적는다: 지침마다 어떤 작업 때 읽는지 한 줄(`gitifact guide show instructions`의 "AGENTS.md 색인"). 전환 커밋과 별도 커밋으로 남길지 사용자에게 묻는다.
|
|
132
|
+
- references로 옮긴 결정 기록(ADR)을 결정기록(`gitifact guide show records`)으로 바꾸고 지침 본문에는 지키는 규칙만 남기는 정리, 지침을 다시 묶는 정리는 사용자와 정해 별도 커밋으로 한다. 전환 커밋은 숨겨지므로 이 커밋에서 쓴 결정기록이 이력에 보인다.
|
|
133
|
+
- 전환 커밋에서는 본문을 다듬지 않았으므로, 지침이나 명세 본문에 `requirements.md`·`spec save` 같은 옛 형식 서술이나 위키를 가리키는 문장이 남아 있을 수 있다. 찾은 위치를 보고하고, 고치는 것은 사용자와 정해 별도 커밋으로 한다.
|
|
134
|
+
|
|
135
|
+
## 7. 보고
|
|
136
|
+
|
|
137
|
+
- 옮긴 개수: 기능·요구사항·설계·위키 페이지(옛 개수와 함께), 위키 페이지가 옮겨 간 지침 표
|
|
138
|
+
- `check` 결과와 대조 결과
|
|
139
|
+
- 고친 상대 링크, 옮기지 못했거나 판단이 필요했던 것
|
|
140
|
+
- 커밋 해시(했다면), 남은 정리(지침의 옛 명령, 옛 색인)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 결정기록 형식
|
|
3
|
+
description: 결정기록을 쓰는 때, 파일 형식과 섹션, 초안에서 커밋까지, 읽는 법
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
결정기록은 문서가 왜 지금 모양이 됐는지를 남긴다. 문서 본문에는 지금 유효한 내용만 있으므로, 본문이 스스로 설명하지 못하는 맥락과 고른 안을 기록으로 둔다. 기록은 한 번 커밋하면 고치지 않는다. 결정이 바뀌면 새 기록을 쓰고, 한 문서의 기록을 시간순으로 읽으면 결정의 흐름이 보인다.
|
|
7
|
+
|
|
8
|
+
## 쓰는 때
|
|
9
|
+
|
|
10
|
+
| 경우 | 기록 |
|
|
11
|
+
| :--- | :--- |
|
|
12
|
+
| 기존 요구사항·설계·지침의 내용을 바꾸거나 지움 | 쓴다. 옛 내용이 사라지므로 맥락을 남길 곳이 기록뿐이다 |
|
|
13
|
+
| 새로 만들거나 바꾸면서 여러 안 중 하나를 고름 | 쓴다. 검토한 대안은 문서 본문에 두지 않는다 |
|
|
14
|
+
| 새 요구사항을 그냥 추가 | 쓰지 않는다. 사용자 스토리가 이유다 |
|
|
15
|
+
| 다른 결정에 딸려 고친 문서 | 따로 쓰지 않는다. 원래 결정의 `docs`에 그 문서를 더한다 |
|
|
16
|
+
| 오타, 문장 다듬기 | 쓰지 않는다 |
|
|
17
|
+
|
|
18
|
+
결정은 내린 순간에 기록한다. 커밋할 때 대화를 되짚어 쓰면 검토한 대안 같은 맥락이 사라진다. 한 작업에서 결정을 여러 번 하면 기록도 여럿이다.
|
|
19
|
+
|
|
20
|
+
## 파일
|
|
21
|
+
|
|
22
|
+
기록 하나는 `.gitifact/records/<yyyymmdd>/<DR-ID>.md` 파일 하나다. CLI로 만든다. CLI가 ID를 발급하고 오늘 날짜 폴더(그날 첫 기록 때 생긴다)에 필수 섹션과 `draft: true`를 넣어 쓴다.
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
gitifact records new --title "삭제한 게시물의 30일 보관" --docs R-…,D-…
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```markdown
|
|
29
|
+
---
|
|
30
|
+
id: DR-CLI가발급한값
|
|
31
|
+
title: 삭제한 게시물의 30일 보관
|
|
32
|
+
docs:
|
|
33
|
+
- R-바뀐요구사항의실제값
|
|
34
|
+
- D-바뀐설계의실제값
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 맥락
|
|
38
|
+
|
|
39
|
+
실수로 지운 글을 되살려 달라는 문의가 한 달에 20건가량 들어온다.
|
|
40
|
+
|
|
41
|
+
## 결정
|
|
42
|
+
|
|
43
|
+
지운 게시물은 30일 동안 휴지통에 두고, 그 뒤 정리 작업이 영구 삭제한다.
|
|
44
|
+
|
|
45
|
+
## 검토한 대안
|
|
46
|
+
|
|
47
|
+
- 즉시 영구 삭제(복구 요청을 받을 수 없다)
|
|
48
|
+
- 기간 없이 보관(저장 공간이 계속 는다)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
위 ID와 문장은 구조 설명이다. 섹션을 채운 뒤 `draft: true` 줄을 지운다. 이 줄이 남은 기록은 커밋할 수 없다.
|
|
52
|
+
|
|
53
|
+
- **`title`:** 80자 이내의 한 줄이다. 브라우저의 결정기록 화면과 `records list --doc`에서 기록의 이름이 된다. 대상과 동작을 뜻하는 명사로 끝나는 짧은 구로 쓴다(예: `섹션 500자 제한`, `문서 안 결정 표 폐지`, `커밋당 결정 하나 권장`). `~한다`·`~하기`로 끝내지 않고, 주제만 적지 않으며(`섹션 길이`가 아니라 `섹션 500자 제한`), 이유는 섹션에 둔다.
|
|
54
|
+
- **`docs`:** 이 기록이 설명하는 문서의 ID다. 지우는 문서의 ID도 적을 수 있다. 딸려 고친 문서도 여기에 더한다.
|
|
55
|
+
- **작성자·시각:** 파일에 쓰지 않는다. 기록을 더한 커밋에서 읽는다.
|
|
56
|
+
|
|
57
|
+
| 섹션 | 필수 | 내용 |
|
|
58
|
+
| :--- | :--- | :--- |
|
|
59
|
+
| 맥락 | 예 | 무엇 때문에 결정이 필요했는지. 문제, 요청, 제약 |
|
|
60
|
+
| 결정 | 예 | 무엇을 하기로 했는지 |
|
|
61
|
+
| 검토한 대안 | 아니오 | 실제로 검토하고 고르지 않은 안과 그 까닭 |
|
|
62
|
+
|
|
63
|
+
본문은 이 `##` 섹션으로만 쓴다. 섹션 제목은 한국어(`## 맥락`)나 영어(`## Context`)로 쓴다. 목록에 없는 섹션과 두 번 나오는 섹션은 `check`의 문제다. 검토한 대안은 실제로 따져 본 안이 있을 때만 쓰고 억지로 지어내지 않는다. 요구사항을 바꾸는 기록처럼 대안이 없으면 이 섹션을 뺀다.
|
|
64
|
+
|
|
65
|
+
## 분량
|
|
66
|
+
|
|
67
|
+
맥락과 결정은 각각 2~5문장으로 쓴다. 맥락에는 무엇이 문제였는지(드러난 현상과 잰 수치), 누가 무엇을 요청했는지, 지켜야 할 제약을 담는다. 결정에는 무엇을 하기로 했는지와 어디까지 적용하는지, 예외를 담는다. 근거가 없는 내용으로 문장 수를 채우지 않는다. 섹션 하나가 500자를 넘으면 `check`의 문제(`RECORD_SECTION_TOO_LONG`)다. 검토한 대안은 한 줄에 하나씩, 고르지 않은 까닭은 괄호로 짧게 쓴다. 경위, 측정 과정, 옛 방식의 설명은 쓰지 않는다. API 필드, 구현 절차, 테스트 기록은 기록에 옮기지 않고 설계나 커밋에 둔다. 긴 설명이 필요하면 그 내용은 설계나 지침 본문에 두고 기록에는 요지만 남긴다. 문체는 `gitifact guide show writing`을 따른다.
|
|
68
|
+
|
|
69
|
+
## 커밋
|
|
70
|
+
|
|
71
|
+
기록 파일은 설명하는 문서와 같은 커밋에 담는다. 커밋 입력의 `paths`에 기록 파일을 넣는다(`gitifact guide show commit`). 커밋 하나에 결정 하나를 기본으로 하며, 그 결정의 문서·코드·테스트를 함께 담는다. 한 파일이 두 결정에 걸치면 두 기록을 한 커밋에 담는다. `changes list`가 기록마다 설명하는 문서와 두 기록이 함께 설명하는 문서를 보여 준다.
|
|
72
|
+
|
|
73
|
+
커밋한 기록은 고치거나 지우지 않는다. 고치면 `check`가 `RECORD_ALTERED`로 알리고 커밋이 거부된다. HEAD대로 되돌리고, 바뀐 결정은 새 기록으로 쓴다.
|
|
74
|
+
|
|
75
|
+
## 읽기
|
|
76
|
+
|
|
77
|
+
| 명령 | 쓰는 때 |
|
|
78
|
+
| :--- | :--- |
|
|
79
|
+
| `gitifact records list --doc <ID>` | 문서를 바꾸기 전에 그 문서의 결정 흐름을 읽는다. 기록마다 제목과 섹션, 커밋이 나온다 |
|
|
80
|
+
| `gitifact records show <DR-ID>` | 기록 하나의 원문과 그것을 더한 커밋을 본다 |
|
|
81
|
+
|
|
82
|
+
`.gitifact/records/`의 파일을 모두 읽거나 grep하지 않는다. 기록은 날짜와 ID로만 놓여 있어 문서별로 모으려면 전부 읽어야 한다. `records list --doc`은 캐시의 색인으로 바로 찾는다.
|
|
@@ -1,21 +1,41 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: 요구사항 형식
|
|
3
|
+
description: 기능과 요구사항 파일의 구조, 프론트매터, 사용자 스토리와 수용 조건, 만들기·고치기·옮기기
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
기능 하나는 `.gitifact/spec/<기능>/` 폴더 하나다. 기능 소개는 `index.md`, 요구사항은 `requirements/<slug>.md`에 하나씩, 설계는 `design/` 아래 파일들(`gitifact guide show design`)이다. 문서가 왜 바뀌었는지는 결정기록(`.gitifact/records/`)이 남긴다(`gitifact guide show records`).
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
.gitifact/spec/posts/
|
|
10
|
+
index.md 기능 소개 (S-)
|
|
11
|
+
requirements/
|
|
12
|
+
create.md 요구사항 하나 (R-)
|
|
13
|
+
delete.md
|
|
14
|
+
design/
|
|
15
|
+
overview.md 설계 (D-)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 만들기
|
|
2
19
|
|
|
3
|
-
|
|
20
|
+
파일은 CLI로 만든다. CLI가 ID를 발급하고 프론트매터를 채우며 본문 뼈대를 쓴다.
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
gitifact specs new feature posts --title "게시물 관리" --description "게시물을 쓰고 고치고 지우는 기능"
|
|
24
|
+
gitifact specs new requirement posts/create --title "게시물 등록" --description "작성자가 제목과 내용으로 게시물을 저장한다"
|
|
25
|
+
```
|
|
4
26
|
|
|
5
|
-
|
|
27
|
+
만든 파일에는 `draft: true`가 붙는다. 본문을 채운 뒤 이 줄을 지우고 `gitifact check`로 확인한다. 이 줄이 남아 있으면 `check`와 `changes commit`이 실패한다. ID를 직접 만들거나 다른 문서의 ID를 복사하지 않는다.
|
|
6
28
|
|
|
7
|
-
|
|
29
|
+
## 파일 구조
|
|
8
30
|
|
|
9
31
|
```markdown
|
|
10
32
|
---
|
|
11
|
-
id:
|
|
33
|
+
id: R-CLI가발급한값
|
|
34
|
+
title: 게시물 등록
|
|
35
|
+
description: 작성자가 제목과 내용으로 게시물을 저장한다
|
|
36
|
+
order: 10
|
|
12
37
|
---
|
|
13
38
|
|
|
14
|
-
# 게시물 관리
|
|
15
|
-
|
|
16
|
-
## 게시물 등록
|
|
17
|
-
<!-- gitifact-req: R-CLI가발급한값 -->
|
|
18
|
-
|
|
19
39
|
게시물 작성자로서, 작성한 글을 나중에 다시 확인하기 위해 제목과 내용을 저장하고 싶다.
|
|
20
40
|
|
|
21
41
|
### 수용 조건
|
|
@@ -24,32 +44,47 @@ id: S-CLI가발급한값
|
|
|
24
44
|
기대 동작: 시스템은 제목 입력 안내를 표시하고 저장을 중단합니다.
|
|
25
45
|
```
|
|
26
46
|
|
|
27
|
-
위 ID
|
|
47
|
+
위 ID와 문장은 구조 설명이며 유효한 입력이 아니다.
|
|
28
48
|
|
|
29
|
-
|
|
49
|
+
- **`id`:** CLI가 발급한 값이다. 기능은 `S-`, 요구사항은 `R-`, 뒤는 소문자 base32 10자다. 파일을 옮기거나 제목을 바꿔도 그대로 둔다.
|
|
50
|
+
- **`title`·`description`:** 필수이며 한 줄이다. 제목은 본문에 `#`로 다시 쓰지 않는다. 설명은 목록(`specs list`)에서 본문을 열지 않고도 무엇인지 알 수 있게 쓴다.
|
|
51
|
+
- **`order`:** 요구사항에만 있다. 기능 안에서 사용 흐름에 맞는 순서로 매기고, 같은 기능에서 겹치면 안 된다. `specs new`는 그 폴더의 최댓값+10을 넣으므로 사이에 끼울 자리가 남는다.
|
|
52
|
+
- **본문:** 비워 둘 수 없다. `#` 제목과 gitifact 주석(`<!-- gitifact-… -->`)을 쓰지 않는다. 기능 `index.md`의 본문은 그 기능이 무엇이고 어디까지인지를 한두 문단으로 쓴다.
|
|
30
53
|
|
|
31
|
-
|
|
54
|
+
프론트매터에 다른 키를 두지 않는다. 문서 사이의 관계는 설계의 `requirements`·`sources`로 나타내고, 요구사항이 어느 기능에 속하는지는 폴더가 정한다.
|
|
32
55
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"operations": [
|
|
37
|
-
{ "type": "create", "feature": "posts", "title": "게시물 관리" },
|
|
38
|
-
{ "type": "add", "feature": "posts", "title": "게시물 등록", "body": "게시물 작성자로서, 작성한 글을 나중에 다시 확인하기 위해 제목과 내용을 저장하고 싶다.\n\n### 수용 조건\n\n1. 조건: 사용자가 제목을 비운 채 저장을 요청합니다.\n 기대 동작: 시스템은 제목 입력 안내를 표시하고 저장을 중단합니다." },
|
|
39
|
-
{ "type": "set-design", "feature": "posts", "title": "게시물 관리 설계", "body": "## 개요\n\n합의한 구현 방향과 범위.\n\n## 구조와 데이터\n\n실제 구현에 필요한 구성 요소와 저장 방식." }
|
|
40
|
-
]
|
|
41
|
-
}
|
|
42
|
-
```
|
|
56
|
+
다른 문서로 가는 링크는 이 파일 기준 상대 경로로 쓴다(요구사항에서 에셋으로는 `../../../assets/flow.png`). 브라우저가 해당 페이지로 연결한다. 대상이 없으면 `check`와 `changes list`가 `MISSING_LINK_TARGET` 경고로 알린다. 경고는 커밋을 막지 않는다.
|
|
57
|
+
|
|
58
|
+
## 읽기
|
|
43
59
|
|
|
44
|
-
명령
|
|
60
|
+
| 명령 | 쓰는 때 |
|
|
61
|
+
| :--- | :--- |
|
|
62
|
+
| `gitifact specs list [--feature <기능>]` | 기능·요구사항·설계의 ID·제목·설명을 본문 없이 본다 |
|
|
63
|
+
| `gitifact specs list --uncovered` | 어떤 설계도 다루지 않는 요구사항을 찾는다. `--without-design`은 설계 없는 기능, `--draft`는 초안이 남은 문서다 |
|
|
64
|
+
| `gitifact specs list --changed-since <날짜\|커밋>` | 그 뒤에 바뀐 문서를 찾는다. `--author`, `--sort updated`와 함께 쓴다 |
|
|
65
|
+
| `gitifact specs list --q <검색어>` | 제목이나 설명에 없는 내용을 본문에서 찾는다 |
|
|
66
|
+
| `gitifact specs show <ID…>` | 고른 문서의 원문과 그 문서를 가리키는 설계를 본다. `--ref <커밋>`은 그 시점의 원문이다 |
|
|
67
|
+
| `gitifact records list --doc <ID>` | 그 문서가 왜 바뀌어 왔는지 결정기록과 커밋을 본다 |
|
|
45
68
|
|
|
46
|
-
|
|
69
|
+
목록은 20개씩(기본 정렬은 기능 20개와 그 문서 전부씩) 보인다. 끝에 나온 `--after <값>`으로 다음 페이지를, `--all`로 전부를 본다. 커밋하지 않은 문서는 줄 끝에 추가·변경·삭제 예정이 붙고, 지운 문서는 커밋할 때까지 삭제 예정으로 남는다. 목록의 조건으로 고른 뒤 필요한 문서만 `show`로 읽는다. 목록은 `--fields id,title`처럼 필요한 열만, `--format json`으로도 받는다. 전체 파일을 grep하거나 모두 여는 것보다 적게 읽는다.
|
|
47
70
|
|
|
48
|
-
|
|
71
|
+
## 고치기·옮기기·지우기
|
|
72
|
+
|
|
73
|
+
파일을 직접 고친다. 저장 명령은 없다. 고친 뒤에는 `gitifact check`로 형식과 참조를 확인한다.
|
|
74
|
+
|
|
75
|
+
| 작업 | 방법 |
|
|
76
|
+
| :--- | :--- |
|
|
77
|
+
| 내용 고치기 | 파일의 `title`·`description`·본문을 고친다. ID는 그대로 둔다 |
|
|
78
|
+
| 다른 기능으로 옮기기 | 파일을 그 기능의 `requirements/`로 옮기고 ID를 유지한다. 옮긴 곳의 순서에 맞게 `order`를 고친다 |
|
|
79
|
+
| slug 바꾸기 | 파일 이름만 바꾼다. ID와 내용은 그대로다 |
|
|
80
|
+
| 지우기 | 파일을 지운다. 그 요구사항을 가리키던 설계의 `requirements`에서 ID를 빼야 `check`가 통과한다 |
|
|
81
|
+
| 기능 이름(폴더) 바꾸기 | 폴더를 옮긴다. `index.md`의 S- ID는 그대로다 |
|
|
82
|
+
|
|
83
|
+
옮기거나 이름을 바꿀 때 새 ID로 복제하지 않는다. 지운 ID를 다른 문서에 다시 쓰지 않는다. 요구사항을 바꾸면 그것을 가리키는 설계도 확인한다(`specs show <R-ID>`의 "가리키는 문서").
|
|
49
84
|
|
|
50
85
|
## 기능으로 묶는 기준
|
|
51
86
|
|
|
52
|
-
사용자에게 의미 있는 응집된 기능으로
|
|
87
|
+
사용자에게 의미 있는 응집된 기능으로 묶는다. 코드 모듈이나 DDD 계층을 그대로 복제하지 않는다. 새 기능을 만들기 전에 기존 기능에 넣을 수 있는지 먼저 확인한다. 기능 제목은 기능 이름 그대로 쓰고 "요구사항" 같은 접미어를 붙이지 않는다. slug와 폴더 이름은 소문자·숫자·하이픈이다.
|
|
53
88
|
|
|
54
89
|
## 사용자 스토리와 수용 조건
|
|
55
90
|
|
|
@@ -57,6 +92,8 @@ id: S-CLI가발급한값
|
|
|
57
92
|
|
|
58
93
|
사용자 스토리 아래에는 `### 수용 조건`과 번호별 `조건: / 기대 동작:` 형식을 유지한다. 파일 경로·ID·저장 규약으로 사용자 목표를 대신하지 않는다. 별도로 필요한 확정 제약은 `### 범위와 제약`에 두고, 내부 구현 방식은 설계에 둔다. 역할·목표·이유는 대화와 확인한 맥락에 근거하며, 모르는 동기를 만들어 문형을 채우지 않는다. 의미를 결정할 정보가 부족하면 필요한 부분만 질문한다.
|
|
59
94
|
|
|
60
|
-
새 요구사항과 요청받아 개정하는 요구사항에 적용한다. 기존 문서를 정리할 때 ID·확정된 제약·수용 조건의 의미를 보존하고, 이번 작업과 무관한 요구사항을 일괄 개정하지 않는다.
|
|
95
|
+
새 요구사항과 요청받아 개정하는 요구사항에 적용한다. 기존 문서를 정리할 때 ID·확정된 제약·수용 조건의 의미를 보존하고, 이번 작업과 무관한 요구사항을 일괄 개정하지 않는다. 다 쓴 뒤에는 스토리의 역할·목표·이유가 드러나는지, 수용 조건이 그 목표의 성공·실패를 판정하는지 대조한다. CLI는 특정 문장이나 사용자 의도를 강제·검증하지 않는다.
|
|
96
|
+
|
|
97
|
+
본문의 문체는 `gitifact guide show writing`을 따른다. 그 문서의 문체 규칙은 위 사용자 스토리 문형과 `조건: / 기대 동작:` 형식을 대체하지 않는다.
|
|
61
98
|
|
|
62
|
-
대화 중에는
|
|
99
|
+
대화 중에는 파일을 다듬는다. 기존 요구사항을 바꾸거나 여러 안 중 하나를 고르면 그때 결정기록 초안을 쓴다(`gitifact guide show records`). 새 요구사항을 추가하기만 하면 기록은 필요 없다. 코드와 테스트를 고치는 동안 달라진 요구사항은 마지막 합의 내용으로 맞춘다.
|