@pghoya2956/livemap 1.1.1 → 1.3.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.
- package/CHANGELOG.md +143 -0
- package/README.md +24 -7
- package/budget/view-budget.spec.mjs +198 -0
- package/docs/adapter-contract.md +52 -4
- package/docs/issue-codes.md +159 -0
- package/docs/migrate.md +15 -0
- package/docs/semantic-authoring.md +158 -3
- package/docs/semantic-schema.md +65 -8
- package/docs/test-results.md +189 -0
- package/docs/view-budget.md +19 -1
- package/package.json +1 -1
- package/site/map.css +80 -0
- package/site/map.js +9 -9
- package/src/adapters/deploy.mjs +19 -8
- package/src/adapters/router.mjs +34 -22
- package/src/adapters/tasks.mjs +322 -29
- package/src/adapters/testreport.mjs +115 -19
- package/src/adapters/tests.mjs +5 -1
- package/src/check.mjs +102 -28
- package/src/cli.mjs +68 -13
- package/src/derive.mjs +124 -16
- package/src/init.mjs +52 -3
- package/src/lib/closure.mjs +143 -0
- package/src/lib/graph.mjs +7 -3
- package/src/lib/issues.mjs +164 -0
- package/src/lib/judgments.mjs +128 -0
- package/src/lib/literals.mjs +103 -0
- package/src/lib/md-blocks.mjs +113 -0
- package/src/lib/reading.mjs +55 -0
- package/src/link.mjs +76 -0
- package/src/reporters/node-results.mjs +33 -0
- package/src/results.mjs +187 -0
- package/src/test-report.mjs +47 -11
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# 이슈 코드
|
|
2
|
+
|
|
3
|
+
`livemap check`가 내는 문제마다 안정 코드, 대상, 근거 줄, 허용 처리가 붙는다. 이 문서가 코드의 뜻과 허용 처리의 정본이다. 코드 이름은 1.x 동안 바꾸거나 지우지 않고 더하기만 한다. 언제 원문을 고치고 언제 판정하는지는 이 코드를 받는 에이전트 절차가 정한다. 엔진은 원문과 판정 파일을 고치지 않는다.
|
|
4
|
+
|
|
5
|
+
## 출력
|
|
6
|
+
|
|
7
|
+
`livemap check`의 텍스트 출력은 1.1.1 줄 문구를 그대로 둔다. 새 코드(아래 첫 표) 중 같은 코드가 6건 이상이면 `△ tasks.ambiguous-ref 32건(단계 17): livemap check --json`처럼 한 줄로 묶는다. 괄호 안 수는 서로 다른 대상 수다. 기존 check 줄과 코드 표에 없는 코드는 묶지 않는다.
|
|
8
|
+
|
|
9
|
+
`livemap check --json`은 stdout에 JSON 하나만 낸다. 빌드 중 어댑터가 찍은 줄과 "프로젝트 어댑터가 참조 어댑터를 가림" 알림은 stderr로 간다. 종료 코드는 텍스트 출력과 같다(오류가 있으면 1).
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"schema": 1,
|
|
14
|
+
"engine": "1.2.0",
|
|
15
|
+
"errors": 0,
|
|
16
|
+
"warnings": 1,
|
|
17
|
+
"problems": [
|
|
18
|
+
{
|
|
19
|
+
"level": "warn",
|
|
20
|
+
"code": "tasks.questions-open-done",
|
|
21
|
+
"msg": "작업 문서: 완료 작업에 닫히지 않은 잔여 질문 1",
|
|
22
|
+
"subject": { "kind": "task", "id": "20260101-sample" },
|
|
23
|
+
"anchors": [{ "file": "tasks/20260101-sample/spec/final.md", "line": 12, "excerpt": "| OQ-02 | 남은 질문 |" }],
|
|
24
|
+
"resolutions": ["judge"],
|
|
25
|
+
"judgmentDraft": { "task": "20260101-sample", "questions": { "items": [{ "id": "OQ-02", "state": null, "at": null }] } }
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- `problems`는 수준(error 먼저), 코드, 첫 근거 줄의 파일, 줄 순으로 정렬한다. 나머지가 같으면 check 순서를 지킨다.
|
|
32
|
+
- `msg`는 텍스트 출력의 기호 뒤 문구와 같다.
|
|
33
|
+
- `subject`는 `{ kind, id }`이고 대상이 하나로 정해지지 않는 문제(고아 목록 등)는 `null`이다. `kind`는 그래프 노드 종류 이름(`task`, `step`, `journey`, `milestone`은 로드맵 항목, `release`는 마일스톤)이나 `adapter`·`config`다.
|
|
34
|
+
- `anchors`는 `{ file, line, excerpt? }` 배열이다. `line`이 `null`이면 파일 단위 근거다. `excerpt`는 120 코드 포인트까지 자른다.
|
|
35
|
+
- `resolutions` 값: `source`(원문을 규칙대로 고침), `judge`(판정 파일), `config`(설정), `code`(프로젝트 코드), `engine`(엔진 결함 보고).
|
|
36
|
+
- `judgmentDraft`는 판정으로 처리할 수 있는 문제에만 있다(아래 「판정 초안」).
|
|
37
|
+
|
|
38
|
+
`livemap check --strict`는 `tasks.*`·`judgment.*` 경고를 오류로 센다. 텍스트 줄 기호가 `✗`로 바뀌고 JSON의 `level`이 `error`가 된다. 과거 작업 채우기가 끝났는지 한 번 확인할 때 쓰고, 배포를 막는 CI 잡에는 배선하지 않는다.
|
|
39
|
+
|
|
40
|
+
## 판정 초안(judgmentDraft)
|
|
41
|
+
|
|
42
|
+
처리에 `judge`가 있는 작업 문서 문제는 `judgmentDraft`를 싣는다. 판정 파일(`semantic-authoring.md` 「판정 파일」)의 모양에서 원문을 읽어야 정할 값(`at`, `as`, `state`, `planFile`)을 `null`로 둔 초안이다.
|
|
43
|
+
|
|
44
|
+
| 코드 | 초안 |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `tasks.unread-definition`(표 첫 칸 결정) | `{ task, lines: [{ at: null, as: null, id }] }` |
|
|
47
|
+
| `tasks.unread-definition`(잔여 질문 행) | `{ task, questions: { items: [{ id, state: null, at: null }] } }`. `id`는 칸 원문의 번호 모양 그대로(`OQ-04·OQ-05` 행은 둘, `R-OQ-01`·`OQ-H2b`는 하나) |
|
|
48
|
+
| `tasks.unread-checklist`(계획 파일 불분명) | `{ task, planFile: null }` |
|
|
49
|
+
| `tasks.questions-unknown`(잔여 질문 절 없음) | `{ task, questions: { none: { at: null } } }` |
|
|
50
|
+
| `tasks.questions-open-done`(닫히지 않은 질문) | `{ task, questions: { items: [{ id, state: null, at: null }] } }` |
|
|
51
|
+
| `judgment.stale`(근거 조각 사라짐) | 낡은 판정 항목(`at: null`)과 `candidates: [{ file, line, excerpt }]`(같은 파일에서 그 번호를 가진 줄) |
|
|
52
|
+
|
|
53
|
+
`judgment.invalid`에는 초안이 없다. 파일 모양 문제는 파일 전체를, 근거 조각 문제는 그 항목만 적용하지 않으며 위반마다 한 건이다. 대상은 `{ kind: 'judgment', id: <작업 폴더> }`이고 첫 근거는 판정 파일(줄 `null`), 나머지는 근거 파일이다. `judgment.stale`이 난 판정이 맡던 규칙 문제(같은 줄의 후보, 같은 번호의 `tasks.questions-open-done`)는 다시 내지 않는다.
|
|
54
|
+
|
|
55
|
+
## 커밋 전 훅(check --staged)
|
|
56
|
+
|
|
57
|
+
`livemap check --staged`는 스테이징된 파일 중 작업 설정 `dir` 바로 아래 `<8자리 날짜>-` 작업 폴더 안 파일, 장부 파일(작업 설정 `index`), `map/judgments/*.json`만 대상으로 본다. 목록은 `git diff --cached --name-only --relative --no-renames`에서 얻는다.
|
|
58
|
+
|
|
59
|
+
- 오류로 세는 문제는 코드가 `tasks.`·`judgment.`로 시작하고 대상이 작업·장부·판정 파일이면서, 대상이 스테이징된 작업 폴더·판정 파일이거나 근거 줄이 스테이징된 대상 파일에 있는 것이다. 나머지 문제는 보이지 않는다.
|
|
60
|
+
- `tasks.ambiguous-ref`는 대상이 여정 단계이고 고칠 곳이 여정 파일이라 세지 않는다. 코드만 바꾼 커밋과 과거 작업의 남은 문제는 막지 않는다.
|
|
61
|
+
- 대상 파일이 없거나 git 저장소가 아니면 빌드하지 않고 종료 코드 0이다.
|
|
62
|
+
- 출력은 문제마다 `✗ <코드> <문구>`, `처리:`, `근거:`(파일:줄과 원문 조각), `판정 초안(judgmentDraft):` 한 줄 JSON이고, 끝 줄이 `map check --staged: 오류 n (…)`와 처리 안내다. 통과는 `map check --staged: 통과 (대상 파일 n)`, 대상 없음은 `map check --staged: 대상 없음`, git 저장소가 아니면 `map check --staged: git 저장소 아님, 건너뜀`이다. `--json`을 함께 주면 `check --json`과 같은 모양으로 낸다.
|
|
63
|
+
- 오류가 있으면 종료 코드 1이라 커밋이 멈춘다. 멈춘 출력을 받은 에이전트 세션이 원문을 식별자 줄 규칙대로 고치거나 판정 파일을 써서 스테이징하고 다시 커밋한다. `--no-verify`로 넘기지 않는다.
|
|
64
|
+
|
|
65
|
+
`livemap init`이 `.githooks/pre-commit`(`npx --no livemap check --staged`)을 만들고 `git config core.hooksPath .githooks`를 둔다. 이미 다른 `core.hooksPath`, 훅 관리자(`.husky`, lefthook 설정, `.pre-commit-config.yaml`), `.git/hooks/pre-commit`, 내용이 다른 `.githooks/pre-commit`이 있으면 덮지 않고 그 설정에 넣을 한 줄을 출력한다. `core.hooksPath`는 git 설정이라 클론마다 한 번 `livemap init`을 돌린다.
|
|
66
|
+
|
|
67
|
+
## 어댑터가 코드를 붙이는 법
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
g.issue('warn', '작업 문서', '완료 작업에 닫히지 않은 잔여 질문 1', {
|
|
71
|
+
code: 'tasks.questions-open-done',
|
|
72
|
+
subject: { kind: 'task', id: '20260101-sample' },
|
|
73
|
+
anchors: [{ file: 'tasks/20260101-sample/spec/final.md', line: 12, excerpt: '| OQ-02 | 남은 질문 |' }],
|
|
74
|
+
resolutions: ['judge'],
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- 세 인자 호출(1.1.0 계약)은 그대로 받고 check에서 코드 `adapter.issue`가 된다.
|
|
79
|
+
- 넷째 인자는 객체이고 키는 `code`·`subject`·`anchors`·`resolutions`·`judgmentDraft`만 쓴다. 모르는 키가 있으면 `throw`한다. `code`는 `<영역>.<이름>`(소문자·숫자·하이픈) 모양이어야 한다. 아래 표에 있는 코드는 표의 수준과 `level`이 같아야 한다. 형식이 틀리면 `throw`하고 그 어댑터는 failed가 된다.
|
|
80
|
+
- `subject`·`anchors`·`resolutions`를 빼면 `null`·`[]`·표의 처리 값이 들어간다. 표에 없는 프로젝트 코드는 처리 기본값이 `[]`다.
|
|
81
|
+
- 넷째 인자를 준 문제만 `graph.json`·`data.json` `issues[]`에 `code`·`subject`·`anchors`·`resolutions`(있으면 `judgmentDraft`)가 더해진다.
|
|
82
|
+
|
|
83
|
+
## 1.2.0 새 코드
|
|
84
|
+
|
|
85
|
+
| 코드 | 수준 | 대상 | 처리 | 뜻 |
|
|
86
|
+
|---|---|---|---|---|
|
|
87
|
+
| `tasks.unread-definition` | warn | 작업 | source·judge | 스펙 final 표 첫 칸의 DEC 번호, 잔여 질문 절에서 첫 칸이 번호 하나가 아닌 행 |
|
|
88
|
+
| `tasks.unread-checklist` | warn | 작업 | source·judge | 계획 파일이 없는 작업에 체크박스를 가진 루트 md가 둘 이상 |
|
|
89
|
+
| `tasks.stage-unknown` | warn | 작업 | source | 진행·대기 작업에 파이프라인 문서가 없음 |
|
|
90
|
+
| `tasks.questions-unknown` | warn | 작업 | source·judge | 스펙 final에 잔여 질문 절이 없음 |
|
|
91
|
+
| `tasks.questions-open-done` | warn | 작업 | judge | 완료 작업의 잔여 질문 행이 계획 항목으로 닫히지 않음 |
|
|
92
|
+
| `tasks.index-section-unknown` | warn | 장부 | source | 표시어가 없는 절에 작업 링크 행이 있음 |
|
|
93
|
+
| `tasks.ambiguous-ref` | warn | 단계 | source | 여정 refs 번호를 정의한 작업이 둘 이상 |
|
|
94
|
+
| `judgment.invalid` | error | 판정 파일 | judge | JSON·스키마 위반, 없는 파일·폴더, 조각을 가진 줄이 여럿, 번호 없는 근거 줄 |
|
|
95
|
+
| `judgment.stale` | warn | 판정 파일 | judge | 근거 조각을 가진 줄이 원문에 없음 |
|
|
96
|
+
| `router.unknown-api` | warn | 화면 | code·config | 리터럴 경로에 맞는 API 노드가 없음 |
|
|
97
|
+
| `router.hookapi-redundant` | warn | 설정 | config | hookApi 항목이 리터럴로도 연결됨(지워도 됨), 설정 키 하나에 한 건 |
|
|
98
|
+
| `router.hookapi-only` | warn | 설정 | code·config | hookApi로만 연결되는 항목, 설정 키 하나에 한 건 |
|
|
99
|
+
| `journey.api-not-observed` | warn | 단계 | source·code | 여정 `apis`에 있으나 어느 화면에서도 관측되지 않음 |
|
|
100
|
+
|
|
101
|
+
## 1.3.0 새 코드
|
|
102
|
+
|
|
103
|
+
로드맵 선행의 흐름을 보는 경고 두 건이다. 문장은 `data.json`의 `roadmap[].problems`에 실리고 로드맵 화면 카드의 경고 줄로 보인다. `check`는 둘 다 경고(`△`)로 내므로 CI를 막지 않는다. 판정 규칙은 로드맵 화면 트리(`ui/lib/tree.js`)와 같다. 1.2.0 새 코드처럼 6건 이상을 한 줄로 묶지 않는다.
|
|
104
|
+
|
|
105
|
+
| 코드 | 수준 | 대상 | 처리 | 뜻 |
|
|
106
|
+
|---|---|---|---|---|
|
|
107
|
+
| `roadmap.dep-cycle` | warn | 로드맵 항목 | source | 선행이 돌고 돌아 자기에게 되돌아온다. 순환에 든 항목마다 `선행 순환: {id} → {id} → …`(자기에서 시작해 선행 → 후속 방향으로 돌아오는 가장 짧은 경로). 순환 항목을 선행으로 가진 뒤쪽 항목에는 싣지 않는다 |
|
|
108
|
+
| `roadmap.milestone-backward` | warn | 로드맵 항목 | source | 마일스톤 절이 있을 때 선행이 항목보다 오른쪽 열(마일스톤 절 순서, 미배정·없는 id는 맨 오른쪽)에 있다. 엣지마다 항목 쪽에 `마일스톤 순서 역행: {선행 id}({마일스톤}) → {항목 id}({마일스톤})`. `{마일스톤}`은 마일스톤 id이고 미배정이면 `마일스톤 없음`이다. 고치는 방법은 둘이다 — 파일에서 마일스톤 절 순서를 바꾸거나, 그 항목의 선행을 고친다 |
|
|
109
|
+
|
|
110
|
+
## 1.1.1 check 줄의 코드
|
|
111
|
+
|
|
112
|
+
문구는 1.1.1과 같다. 괄호 안 문구는 줄의 앞부분이다.
|
|
113
|
+
|
|
114
|
+
| 코드 | 수준 | 대상 | 처리 | 뜻 |
|
|
115
|
+
|---|---|---|---|---|
|
|
116
|
+
| `adapter.failed` | error | 어댑터 | code·engine | 어댑터가 throw함("어댑터 실패 …") |
|
|
117
|
+
| `adapter.issue` | 어댑터가 정함 | 어댑터 | — | 어댑터가 코드 없이 `g.issue` 세 인자로 낸 문제 |
|
|
118
|
+
| `floor.below` | error | 설정 | code·config·engine | 노드 수가 `floors` 바닥값 미만("바닥값 미달 …") |
|
|
119
|
+
| `journey.duplicate-id` | error | 여정 | source | 여정 id 중복 |
|
|
120
|
+
| `journey.no-steps` | error | 여정 | source | 여정에 장면 없음 |
|
|
121
|
+
| `journey.actor-unknown` | warn | 여정 | source | 여정·장면 배우가 배우 사전에 없음 |
|
|
122
|
+
| `step.duplicate-id` | error | 여정 | source | 한 여정 안에서 장면 id 중복 |
|
|
123
|
+
| `step.intent-empty` | warn | 단계 | source | 장면 intent 비어 있음 |
|
|
124
|
+
| `step.route-missing` | error | 단계 | source·code | 장면이 가리키는 라우트 없음 |
|
|
125
|
+
| `step.ref-unresolved` | error | 단계 | source | 장면 refs 번호를 정의한 작업 없음(참조 미해결) |
|
|
126
|
+
| `step.screen-not-live` | error | 단계 | source·code | 장면은 동작인데 화면이 실데이터가 아님 |
|
|
127
|
+
| `step.screen-live-early` | warn | 단계 | source | 장면은 planned·next인데 화면은 동작 |
|
|
128
|
+
| `step.no-evidence` | error | 단계 | source·code | 동작 주장에 관측 근거 없음 |
|
|
129
|
+
| `step.review-stale` | warn | 단계 | source | 장면 확인일 뒤 화면 변경(확인 필요) |
|
|
130
|
+
| `step.warning` | 문구에 따름 | 단계 | source | 위 규칙에 맞지 않는 장면 경고 문구(대체 코드) |
|
|
131
|
+
| `step.unknown-status` | error | 단계 | source | 장면 상태 어휘가 아님 |
|
|
132
|
+
| `step.planned-has-screen` | warn | 단계 | source | planned 장면에 화면이 있음 |
|
|
133
|
+
| `step.capture-missing` | warn | 단계 | source | 장면 캡처 파일 없음 |
|
|
134
|
+
| `roadmap.duplicate-id` | error | 로드맵 항목 | source | 로드맵 id 중복 |
|
|
135
|
+
| `roadmap.scene-missing` | error | 로드맵 항목 | source | 항목이 가리키는 장면 없음 |
|
|
136
|
+
| `roadmap.task-missing` | error | 로드맵 항목 | source | 항목이 가리키는 작업 폴더 없음 |
|
|
137
|
+
| `roadmap.dep-missing` | error | 로드맵 항목 | source | 선행 항목 없음 |
|
|
138
|
+
| `roadmap.unknown-status` | error | 로드맵 항목 | source | 항목 상태 어휘가 아님 |
|
|
139
|
+
| `roadmap.milestone-missing` | error | 로드맵 항목 | source | 항목이 가리키는 마일스톤 없음 |
|
|
140
|
+
| `roadmap.problem` | error | 로드맵 항목 | source | 위 규칙에 맞지 않는 로드맵 오류 문구(대체 코드) |
|
|
141
|
+
| `roadmap.running-no-task` | warn | 로드맵 항목 | source | 진행인데 작업 폴더가 없음 |
|
|
142
|
+
| `roadmap.running-no-milestone` | warn | 로드맵 항목 | source | 진행인데 마일스톤 없음 |
|
|
143
|
+
| `roadmap.running-open-deps` | warn | 로드맵 항목 | source | 진행인데 선행 미완 |
|
|
144
|
+
| `milestone.no-id` | error | 마일스톤 | source | 마일스톤 id 없음 |
|
|
145
|
+
| `milestone.duplicate-id` | error | 마일스톤 | source | 마일스톤 id 중복 |
|
|
146
|
+
| `milestone.unknown-status` | error | 마일스톤 | source | 마일스톤 상태 어휘가 아님 |
|
|
147
|
+
| `milestone.bad-date` | error | 마일스톤 | source | 완료일·목표일 날짜 형식 |
|
|
148
|
+
| `milestone.problem` | error | 마일스톤 | source | 위 규칙에 맞지 않는 마일스톤 오류 문구(대체 코드) |
|
|
149
|
+
| `milestone.done-open-items` | warn | 마일스톤 | source | 완료인데 미완료 항목 |
|
|
150
|
+
| `milestone.all-items-done` | warn | 마일스톤 | source | 항목이 모두 완료인데 상태가 완료 아님 |
|
|
151
|
+
| `milestone.running-items` | warn | 마일스톤 | source | 다음·대기·이후인데 진행 항목이 있음 |
|
|
152
|
+
| `milestone.no-items` | warn | 마일스톤 | source | 묶인 항목 없음 |
|
|
153
|
+
| `milestone.completed-on-mismatch` | warn | 마일스톤 | source | 완료일과 상태가 맞지 않음 |
|
|
154
|
+
| `milestone.warning` | warn | 마일스톤 | source | 위 규칙에 맞지 않는 마일스톤 경고 문구(대체 코드) |
|
|
155
|
+
| `milestone.multiple-running` | warn | 마일스톤 | source | 진행 마일스톤이 둘 이상 |
|
|
156
|
+
| `orphan.screens` | warn | 화면 | source | 여정에 없는 화면 |
|
|
157
|
+
| `orphan.apis` | warn | API | code·source | 어느 화면도 부르지 않는 API |
|
|
158
|
+
| `orphan.tests` | warn | 검사 | code | 라우트·API에 붙지 않는 검사 |
|
|
159
|
+
| `deploy.behind-unknown` | warn | 배포 | config | 배포 sha가 main 이력에 없어 뒤처짐을 계산하지 못함 |
|
package/docs/migrate.md
CHANGED
|
@@ -20,3 +20,18 @@
|
|
|
20
20
|
- 끝으로 `npm run map:budget`이 통과하고 스크린샷 `map/.out/overview-1440.png`이 전환 전과 같은 정보를 보이는지 본다.
|
|
21
21
|
|
|
22
22
|
로컬에서 고친 엔진을 끼워 볼 때는 `npm install --no-save --install-links <엔진 저장소 경로>`를 쓴다. `--install-links` 없이 폴더를 설치하면 심링크가 되어 예산 설정이 `@playwright/test`를 엔진 저장소 쪽에서 찾다 실패한다.
|
|
23
|
+
|
|
24
|
+
## 1.x → 2.0.0(예고)
|
|
25
|
+
|
|
26
|
+
2.0.0은 아직 나오지 않았다. 1.2.0까지 폐기를 예고했거나 1.x 호환 때문에 남긴 항목을 모아 지울 예정이다. 목록은 바뀔 수 있고, 판이 나오면 이 절을 이행 절차로 바꾼다. 1.x에서 미리 옮겨 두면 2.0.0 올림이 설정·참조 수정 없이 끝난다.
|
|
27
|
+
|
|
28
|
+
| 항목 | 2.0.0 예정 | 1.x에서 미리 할 일 |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| 설정 `router.hookApi` | 키를 지운다. 화면→API는 리터럴 관측만 쓴다 | `livemap check`의 `router.hookapi-redundant` 항목을 설정에서 지우고, `router.hookapi-only` 항목은 화면 코드가 경로 리터럴을 쓰게 고친다 |
|
|
31
|
+
| `data.json` `tasks[].dec`·`oq`, `overview.json` `counts.oq` | 지운다 | 화면·스크립트가 `openQuestions`·`counts.openQuestions`를 읽게 한다 |
|
|
32
|
+
| 1.0.1 잔여 필드(`line`, `running`, `waiting`, `tasks`, 최상위 `openQuestions`, `areas`, `recent`, `roadmap[]`) | 지운다 | `overview.json` 1.1.0 필드를 읽는다 |
|
|
33
|
+
| 결정·계획 항목 노드 id | 전역 번호(`DEC-57`)에서 `<작업 폴더>#<번호>`로 | 여정 `refs`를 `<작업 폴더>#<번호>` 한정 참조로 적는다(`tasks.ambiguous-ref` 0) |
|
|
34
|
+
| 노드 종류 이름 | `milestone` → `roadmapItem`, `release` → `milestone` | 프로젝트 어댑터·스크립트가 노드 종류 이름에 기대는 곳을 찾아 둔다 |
|
|
35
|
+
| 여정 파일 | md 여정 어댑터를 더할 수 있다 | 없음 |
|
|
36
|
+
| 읽기 상태 강제 | `partial`·`stale`·`unknown`을 기본으로 오류로 셀지 정한다 | `livemap check --strict`로 과거 작업 채우기가 끝났는지 본다 |
|
|
37
|
+
| `config.json` `engine` | `2` | 2.0.0으로 올리는 커밋에서 바꾼다. 엔진은 major가 다르면 멈추고 이 문서를 가리킨다 |
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
| 여정 파일(`semantic`) | 배우·목표·장면과 장면 상태 |
|
|
10
10
|
| 로드맵(`roadmap.file`) | 로드맵 항목과 마일스톤(아래 「로드맵과 마일스톤」) |
|
|
11
11
|
| 작업 장부(`tasks.index`) | 지금 실행 중·대기 중인 작업 |
|
|
12
|
-
| 작업 폴더 문서(`tasks.dir`) | 스펙·계획의 결정(DEC)·계획 항목(PN)·열린 질문 |
|
|
12
|
+
| 작업 폴더 문서(`tasks.dir`) | 스펙·계획의 결정(DEC)·계획 항목(PN)·열린 질문(아래 「작업 문서」) |
|
|
13
|
+
| 판정 파일(`map/judgments/`) | 규칙이 못 읽은 과거 작업 줄의 뜻(아래 「판정 파일」, 1.2.0부터) |
|
|
13
14
|
|
|
14
15
|
## 화면 어휘
|
|
15
16
|
|
|
@@ -65,7 +66,7 @@
|
|
|
65
66
|
- `screens` — 코드에 실제로 있는 라우트만. 없는 라우트는 `check`가 오류로 막는다. 여러 라우트를 한 장면에 둘 수 있다.
|
|
66
67
|
- `apis` — 화면에서 유도되지 않는 API를 명시할 때만.
|
|
67
68
|
- `capture` — `<config.captures.site>/<id>.jpg`(기본 `map/captures/<id>.jpg`). 없으면 장면 카드가 빈 칸으로 그려지고 `check`가 경고한다.
|
|
68
|
-
- `refs` — `DEC-nn`·`PN-nn`
|
|
69
|
+
- `refs` — `DEC-nn`·`PN-nn` 등 작업 문서 번호(정의한 작업으로 자동 연결), `<작업 폴더>#<번호>` 한정 참조(1.2.0부터), 위키 결정 slug(`decisions/<slug>.md`). 해결되지 않는 DEC/PN·한정 참조는 오류다. 규칙은 아래 「번호 참조와 한정 참조」.
|
|
69
70
|
- `reviewedAt` — 사람이 이 장면을 마지막으로 확인한 날. 그 뒤 화면 파일이 바뀌면 "확인 필요" 경고가 뜬다. 상태를 바꿀 때 같이 갱신한다.
|
|
70
71
|
- `actor` — 장면 단위 배우가 여정 배우와 다를 때만(예: 예약 여정 안의 "리조트 접수함").
|
|
71
72
|
- `actors` — 배우 사전. 여정·장면의 `actor`는 이 사전의 키를 적고, 화면은 값(이름)을 보인다. 사전이 있는데 여정 `actor`나 여정과 다른 장면 `actor`가 키에 없으면 `check`가 경고한다(1.1.0부터, `△ <여정 제목>: 배우 사전에 없는 값 <값>` 또는 `△ <여정 제목> › <장면 이름>: 배우 사전에 없는 값 <값>`). 사전이 없으면 검사하지 않는다. 경고라 종료 코드는 바뀌지 않는다. 사전에 키를 더하거나 `actor`를 사전 키로 고친다.
|
|
@@ -90,6 +91,109 @@
|
|
|
90
91
|
- 여정에 없는 화면은 "미분류"로 센다. 화면을 어딘가 억지로 넣기보다, 정말 어느 여정에도 안 속하면 그 화면이 필요한지 묻는다.
|
|
91
92
|
- `next`는 스펙도 없는 것이다. 스펙이 생기면 `planned`, 화면이 생기면 `mock`, 실데이터가 붙으면 `live`. 각 전이는 병합과 같은 커밋에서 적는다.
|
|
92
93
|
|
|
94
|
+
## 작업 문서
|
|
95
|
+
|
|
96
|
+
tasks 어댑터(`tasks.dir`, `tasks.index`)가 작업 폴더 문서에서 결정·계획 항목·열린 질문·단계·상태를 읽는 규칙이다(1.2.0). 엔진은 줄 모양으로만 읽고 원문을 고치지 않는다. 규칙이 못 읽은 줄은 조용히 0으로 세지 않고 "?"와 `tasks.*` 이슈(`issue-codes.md`)로 드러낸다. 백틱·물결 코드 펜스 안 줄은 읽지 않으므로 규칙 모양의 예시 줄은 펜스 안에 둔다.
|
|
97
|
+
|
|
98
|
+
### 파일 역할과 대체 규칙
|
|
99
|
+
|
|
100
|
+
| 역할 | 파일 |
|
|
101
|
+
|---|---|
|
|
102
|
+
| 스펙 | `spec/initial.md`, `spec/review-log.md`, `spec/final.md`. `spec/final.md`가 없고 작업 폴더 루트에 `final.md`가 있으면 그 파일을 스펙 final로 읽고 `specFile`·`readingNotes.spec`에 남긴다 |
|
|
103
|
+
| 계획 | `task_plan.md`, 없으면 `plan.md`. 둘 다 없으면 체크박스를 가진 루트 md가 하나일 때 그 파일(대체 규칙, 예: 단일 `spec.md`). 둘 이상이면 `tasks.unread-checklist`이고, 판정 파일 `planFile`이 고른다 |
|
|
104
|
+
| 단계 문서 | `phase/*.md`, `execution/*.md`, `verification.md`, `phase-verification.md`(단계 판정은 1.1.1 규칙 그대로) |
|
|
105
|
+
| 판정 | `map/judgments/<작업 폴더>.json`(아래 「판정 파일」) |
|
|
106
|
+
| 장부 | `tasks.index` |
|
|
107
|
+
|
|
108
|
+
`spec/`·`phase/`·`execution/` 안 체크박스는 계획 항목 후보가 아니다. 계획 파일이 있는 작업의 다른 루트 md 체크박스도 후보가 아니다.
|
|
109
|
+
|
|
110
|
+
### 식별자 줄 규칙
|
|
111
|
+
|
|
112
|
+
| 값 | 규칙이 읽는 줄 | 규칙이 못 읽어 이슈가 되는 줄 |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| 결정(스펙 final에서만 셈) | 목록 항목의 머리가 번호 하나: `- DEC-7 …`, `- **DEC-7** …`. 취소선 `~~DEC-7~~`은 폐기한 정의라 세지 않는다 | 스펙 final 표 첫 칸의 DEC 번호(`\| DEC-1 \|`, `\| DEC-1·DEC-2 \|`) → `tasks.unread-definition`. 제목 줄 DEC와 계획 파일의 DEC 줄(`## Decisions Made` 옮겨 적기)은 세지도 후보로 보지도 않는다 |
|
|
115
|
+
| 계획 항목(계획 파일에서만 셈) | 체크박스 목록 항목 전부. 머리 번호가 `[A-Z]{1,4}[0-9]?-[0-9]+` 모양(`PN-01`, `P0-01`, `DP-01`, `SR-01`)이면 그 번호의 정의로 둔다 | 계획 파일 없이 체크박스를 가진 루트 md가 둘 이상 → `tasks.unread-checklist` |
|
|
116
|
+
| 잔여 질문 | 제목에 "잔여"와 "질문"(또는 remaining과 question)이 든 절의 첫 표에서 첫 칸이 `OQ-<숫자>` 하나인 행. 첫 칸이 대시·"없음"인 행과, 표 대신 `없음:`으로 시작하는 한 줄은 0으로 읽는다. 그 절 밖의 `## 열린 질문` 표는 검토에서 답한 질문 기록이라 세지 않는다 | 첫 칸이 번호 하나가 아닌 행(`OQ-04·OQ-05`, `OQ-B1`, `~~OQ-01~~`, `R-OQ-01`) → `tasks.unread-definition`. 스펙 final에 절이 없으면 `tasks.questions-unknown` |
|
|
117
|
+
| 질문 닫힘 | 체크한 계획 항목의 설명(머리 번호·slug·실행 주체 표시 뒤 첫 콜론 다음)이 같은 번호로 시작함(`- [x] P0-04 oq01-x-vs-y: OQ-01 합의: …`, 숫자 앞 0 무시). 설명 중간의 언급은 닫힘으로 보지 않는다 | 완료 작업에 닫히지 않은 행 → `tasks.questions-open-done` |
|
|
118
|
+
| 단계 | 1.1.1 규칙(파이프라인 문서 유무) | 파이프라인 문서가 없으면 `reading.stage`가 `unknown`, 진행·대기 작업이면 `tasks.stage-unknown` |
|
|
119
|
+
|
|
120
|
+
새 작업을 쓸 때는 이렇게 적으면 판정이 필요 없다.
|
|
121
|
+
|
|
122
|
+
```markdown
|
|
123
|
+
## 결정 사항
|
|
124
|
+
|
|
125
|
+
- DEC-1 [결정 제목]: 근거
|
|
126
|
+
- ~~DEC-2~~ [폐기한 결정]: 근거
|
|
127
|
+
|
|
128
|
+
## 잔여 열린 질문
|
|
129
|
+
|
|
130
|
+
| ID | 질문 | 처리 권장 단계 |
|
|
131
|
+
|----|------|--------------|
|
|
132
|
+
| OQ-04 | 남은 질문 | 계획 |
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
질문이 없으면 표 대신 `없음: <근거>` 한 줄을 둔다. 계획 파일에서 잔여 질문 하나를 항목 하나로 옮기고 설명을 그 번호로 시작하면(`- [ ] P0-04 oq04-slug: OQ-04 합의: …`) 체크할 때 질문이 닫힌다.
|
|
136
|
+
|
|
137
|
+
1.1.1 필드와의 관계: `dec`는 새 문법(굵게 포함, 취소선 제외)으로 세고 화면에서는 뺐다. `oq`는 1.1.1 규칙(표 행 수) 그대로 두고 화면은 `openQuestions`를 쓴다. `pnDone`·`pnOpen`은 계획 파일(대체 규칙 포함)의 체크박스 전부다. `dec`·`oq`는 2.0.0 삭제 후보다.
|
|
138
|
+
|
|
139
|
+
### 장부 상태
|
|
140
|
+
|
|
141
|
+
- 장부 표에서 어느 칸이든 `(<폴더>/` 또는 `(<폴더>)` 링크를 가진 행만 센다. 문단 속 언급은 세지 않는다.
|
|
142
|
+
- 행을 감싼 절 제목의 표시어(대소문자 무시)로 상태를 정한다. 폐기 `폐기`·`cancel`·`abandon`, 완료 `완료`·`complete`·`done`·`shipped`, 대기 `대기`·`중단`·`보류`·`paused`·`blocked`, 진행 `진행`·`실행 장부`·`in progress`·`현재`·`active`. 한 제목에 여럿이면 이 순서로 앞선 것을 쓴다. 가장 깊은 제목부터 위로 올라가 표시어가 처음 나오는 제목을 쓴다.
|
|
143
|
+
- 같은 작업이 여러 절에 있으면 폐기, 진행, 완료, 대기 순으로 앞선 상태다. 계획 문서 머리의 `**폐기**`와 완료 행의 `**폐기**` 표시는 1.1.1처럼 폐기다.
|
|
144
|
+
- 표시어가 없는 절의 작업 링크 행은 상태를 정하지 않고 `tasks.index-section-unknown`이다.
|
|
145
|
+
- 장부 노드(개요 "실행 중"·"대기")는 1.1.1 절 이름 규칙(`현재 실행 장부`, `실행 대기·중단`) 그대로다.
|
|
146
|
+
|
|
147
|
+
### 번호 참조와 한정 참조
|
|
148
|
+
|
|
149
|
+
- 여정 `refs`의 번호(`DEC-57`, `PN-15`, `P0-03`, `SR-01` 모양)는 그 번호를 정의한 작업으로 잇는다. 결정·계획 항목 노드 id는 1.x 동안 전역 번호이고, 같은 번호를 정의한 작업은 결정 노드 `definers`에 모두 실린다.
|
|
150
|
+
- 정의한 작업이 하나면 그 작업으로 잇는다. 둘 이상이면 폴더 이름 순 첫 작업으로 잇되 읽기 상태가 `partial`이고 `tasks.ambiguous-ref`가 난다.
|
|
151
|
+
- 모호하면 `20260914-booking#DEC-57`처럼 작업 폴더를 붙인 한정 참조로 적는다. 그 폴더가 그 번호를 정의하지 않았으면 기존 "참조 미해결" 오류다.
|
|
152
|
+
- `DEC`·`PN`·`P<숫자>` 밖의 접두어가 풀리지 않으면 오류 대신 "번호 참조 대상 없음" 경고다. 잔여 질문 번호(`OQ-28`)는 정의로 보지 않아 이 경고가 된다.
|
|
153
|
+
- 노드 id를 `<폴더>#<번호>`로 바꾸는 일은 2.0.0 후보다.
|
|
154
|
+
|
|
155
|
+
### 판정 파일
|
|
156
|
+
|
|
157
|
+
규칙이 줄 모양으로 뜻을 정할 수 없는 곳(표로 적은 결정, 답이 난 질문, 계획 파일이 불분명한 작업)을 에이전트나 사람이 판정해 `map/judgments/<작업 폴더>.json`에 적는다. 원문 보존이 필요한 완료·폐기 작업에 쓰고, 진행 중인 작업은 원문을 위 규칙대로 고친다. 엔진은 판정 파일을 읽고 원문과 대조만 한다. 사람은 커밋 diff로 판정을 검토한다.
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"schema": 1,
|
|
162
|
+
"task": "20260101-booking",
|
|
163
|
+
"by": "agent",
|
|
164
|
+
"lines": [
|
|
165
|
+
{ "at": { "file": "tasks/20260101-booking/spec/final.md", "text": "| DEC-1 | 결제 링크는 서버에서 만들고" }, "as": "definition", "id": "DEC-1" }
|
|
166
|
+
],
|
|
167
|
+
"questions": {
|
|
168
|
+
"items": [
|
|
169
|
+
{ "id": "OQ-28", "state": "resolved", "at": { "file": "tasks/20260102-signup/spec.md", "text": "초대(OQ-28) 종결됨.** 계정 없는 이메일로 초대" } }
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
"note": "가입 작업이 검사로 닫음"
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
| 필드 | 값 | 적용 |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `schema` | `1` | 해당 없음 |
|
|
179
|
+
| `task` | 파일 이름과 같은 작업 폴더 이름 | 해당 없음 |
|
|
180
|
+
| `by` | `agent`·`human` | 화면 "판정" 표시에 함께 보인다 |
|
|
181
|
+
| `planFile` | 작업 폴더 기준 md 경로 | 그 파일의 체크박스를 계획 항목으로 센다. 체크 여부는 원문을 따른다 |
|
|
182
|
+
| `lines[]` | `{ at, as, id }`, `as`는 `definition`·`ignore` | `definition`은 정의를 더하고(`id` 필수, 근거 줄에 그 번호가 있어야 함) `ignore`는 그 줄을 후보에서 뺀다. 참조·옮겨 적기·예시는 `ignore`로 적고 까닭은 `note`에 쓴다 |
|
|
183
|
+
| `questions.none` | `{ at }` | 열린 질문 0. `items`와 함께 쓰지 않는다 |
|
|
184
|
+
| `questions.items[]` | `{ id, state, at }`, `id`는 원문 표기 그대로(`OQ-B1` 허용), `state`는 `open`·`resolved` | 그 번호의 규칙 판정을 덮는다. 잔여 질문 절이 없는 작업은 `items`가 열린 질문 목록이 된다 |
|
|
185
|
+
| `note` | 문장 | 작업 상세에 보인다 |
|
|
186
|
+
|
|
187
|
+
- 근거 조각 `at`: `file`은 프로젝트 기준 경로, `text`는 그 파일의 한 줄 안에 그대로 들어 있는 20자(코드 포인트) 이상 조각이다. 줄 번호는 쓰지 않으므로 위에 줄이 더해져도 판정이 살아 있다.
|
|
188
|
+
- 조각을 가진 줄이 하나면 적용하고 값의 읽기 상태가 `judged`다. 0개면 `judgment.stale`(원문이 바뀜)이고 값은 규칙 값으로 돌아가며 상태는 `stale`이다. 둘 이상이면 `judgment.invalid`(조각을 늘린다)다.
|
|
189
|
+
- 근거는 판정하는 작업이나 그 일을 닫은 작업의 폴더 문서에서 고른다. 장부·로드맵·위키는 계속 고쳐지므로 근거로 삼으면 곧 낡는다. 엔진은 위치를 강제하지 않는다.
|
|
190
|
+
- 파일 모양이 틀리면(JSON, 필드 형식, 없는 폴더·`planFile`, `none`과 `items` 동시) 파일 전체를 적용하지 않고, 근거 조각이 틀린 항목은 그 항목만 적용하지 않는다. 둘 다 `judgment.invalid`(error, 종료 코드 1)다. 모르는 키는 무시한다.
|
|
191
|
+
- 적용 순서는 규칙 읽기, `planFile`, `lines`, `questions`, 읽기 상태다. 판정은 체크박스의 체크 여부, 장부 상태, 단계를 바꾸지 못한다.
|
|
192
|
+
- `check --json`의 `tasks.*` 문제는 `judgmentDraft`(판정 초안)를 싣는다. `at`·`as`·`state`를 채우면 판정 파일이 된다. `judgment.stale`의 초안은 같은 파일에서 그 번호를 가진 줄을 `candidates`로 싣는다.
|
|
193
|
+
- 판정은 근거 줄이 있다는 것만 증명하고 뜻이 옳은지는 증명하지 않는다. 그래서 판정 값은 작업 상세와 더보기에 "판정"으로 보인다.
|
|
194
|
+
|
|
195
|
+
작업 문서를 고친 커밋에서 판정이 낡지 않게 `livemap init`이 커밋 전 훅을 설치한다(README 「커밋 전 훅」). 스테이징한 작업 폴더·판정 파일에 걸린 `tasks.*`·`judgment.*` 문제가 있으면 커밋이 멈추고 출력에 판정 초안이 나온다.
|
|
196
|
+
|
|
93
197
|
## 등급과 상태의 관계
|
|
94
198
|
|
|
95
199
|
상태는 사람이 적는 주장이고 등급은 코드가 뒷받침하는 정도다. `live` 장면에만 붙는다.
|
|
@@ -99,7 +203,7 @@
|
|
|
99
203
|
| D | 여정 파일의 주장뿐. 화면이 실데이터가 아님 → 경고 |
|
|
100
204
|
| C | 모든 화면이 실데이터(스캔 관측) |
|
|
101
205
|
| B | 그 화면·API·함수를 다루는 검사 파일이 있음 |
|
|
102
|
-
| A | 그
|
|
206
|
+
| A | 그 검사 파일 중 하나 이상이 최신 결과에서 1건 이상 돌고 실패 0(`npm run test:report`). 최신은 결과 커밋 뒤 문서 경로 밖 변경이 없다는 뜻이다(1.2.0, `test-results.md`) |
|
|
103
207
|
|
|
104
208
|
`live`라고 적었는데 D가 나오면 주장이 틀린 것이다. 상태를 `mock`으로 내리거나 화면을 고친다. 상황판은 둘 중 무엇이 맞는지 판단하지 않고 어긋남만 보여준다.
|
|
105
209
|
|
|
@@ -188,3 +292,54 @@
|
|
|
188
292
|
| 경고 | 완료인데 `완료일` 없음, 또는 완료가 아닌데 `완료일` 있음 | `마일스톤 {제목}: 완료일과 상태가 맞지 않음` |
|
|
189
293
|
| 경고 | 진행 마일스톤 2개 이상 | `진행 마일스톤 {n}개: {제목들}` |
|
|
190
294
|
| 경고 | 마일스톤이 있는데 진행 항목에 `마일스톤` 키 없음 | `로드맵 {항목 제목}: 진행인데 마일스톤 없음` |
|
|
295
|
+
| 경고 | 선행이 항목보다 오른쪽 열에 있음(1.3.0, 아래 「로드맵 화면의 열」 문안 4) | `로드맵 {항목 제목}: 마일스톤 순서 역행: {선행 id}({마일스톤}) → {항목 id}({마일스톤})` |
|
|
296
|
+
|
|
297
|
+
### 로드맵 화면의 열(1.3.0)
|
|
298
|
+
|
|
299
|
+
로드맵 화면은 항목을 노드, 선행을 선으로 잇는 트리를 카드 목록 위에 그린다. 아래 네 문안은 화면 코드(`ui/lib/tree.js`)와 엔진 경고 문장이 따르는 규칙이다.
|
|
300
|
+
|
|
301
|
+
#### 문안 1: 열 모드 판정
|
|
302
|
+
|
|
303
|
+
로드맵 화면의 트리는 열을 세로로 놓는다. 열이 무엇을 뜻하는지는 로드맵 파일이 정한다.
|
|
304
|
+
|
|
305
|
+
`## 마일스톤:` 절이 **한 건이라도 있으면** 열 하나가 마일스톤 하나다. 항목은 `- 마일스톤: <id>`로 가리킨 열에 든다. 선행 깊이는 열 안의 세로 순서만 정한다.
|
|
306
|
+
|
|
307
|
+
절이 **한 건도 없으면** 열 하나가 선행 깊이 한 단계다. 깊이 0이 첫 열이고 오름차순으로 오른쪽으로 간다. 깊이는 선행이 없으면 0, 있으면 `1 + max(선행들의 깊이)`다.
|
|
308
|
+
|
|
309
|
+
두 모드가 같은 함수로 내는 것은 선행 깊이, 잠김 판정, 조상·자손 집합, 순환 판정이다. 모드는 열을 무엇으로 나눌지만 가른다.
|
|
310
|
+
|
|
311
|
+
#### 문안 2: 열 순서
|
|
312
|
+
|
|
313
|
+
마일스톤 모드에서 열의 좌우 순서는 **로드맵 파일에 `## 마일스톤:` 절이 나온 차례**다. 화면은 선행 관계에 맞춰 열을 다시 정렬하지 않는다.
|
|
314
|
+
|
|
315
|
+
정본은 마크다운이다. 사람이 적은 시대 순서를 화면이 뒤집으면 그림이 정본을 부정한다. 순서를 바꾸려면 파일에서 절을 옮긴다.
|
|
316
|
+
|
|
317
|
+
절 순서는 항목의 순서와 자동 id에 영향을 주지 않는다. 엔진은 항목 절만 세어 순서를 매긴다.
|
|
318
|
+
|
|
319
|
+
층 모드에서 열 순서는 깊이 0부터 오름차순이고 사람이 정할 여지가 없다.
|
|
320
|
+
|
|
321
|
+
#### 문안 3: 미배정 열
|
|
322
|
+
|
|
323
|
+
`- 마일스톤:` 키가 없거나, 값이 비었거나, 없는 마일스톤 id를 가리키는 항목은 **맨 오른쪽 "마일스톤 없음" 열**에 모인다. 카드 목록이 쓰는 묶음 이름과 같다.
|
|
324
|
+
|
|
325
|
+
없는 id를 가리킨 경우 엔진은 `data.json`에 그 값을 그대로 두고 `로드맵 {항목 제목}: 마일스톤 없음 {id}` 문장을 따로 낸다. 화면이 마일스톤 목록에 없는 id를 미배정으로 본다. 화면은 그래도 선다.
|
|
326
|
+
|
|
327
|
+
미배정 항목이 0건이면 이 열을 만들지 않는다. 항목을 전부 마일스톤에 배정할 필요는 없다.
|
|
328
|
+
|
|
329
|
+
#### 문안 4: 역행 경고
|
|
330
|
+
|
|
331
|
+
파일 순서는 선행 방향을 보장하지 않는다. 오른쪽 열 항목이 왼쪽 열 항목의 선행이 되면 그 엣지는 오른쪽에서 왼쪽으로 흐른다.
|
|
332
|
+
|
|
333
|
+
엔진은 그런 엣지마다 문장 하나를 낸다.
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
마일스톤 순서 역행: {선행 id}({마일스톤}) → {항목 id}({마일스톤})
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
화면은 그 엣지를 점선에 `--amber`로 그리고 범례에 "마일스톤 순서를 거스르는 선행" 한 줄을 둔다. 경고이고 오류가 아니다. 화면은 멈추지 않는다. 고치는 방법은 둘이다 — 파일에서 마일스톤 절 순서를 바꾸거나, 그 항목의 선행을 고친다.
|
|
340
|
+
|
|
341
|
+
문장은 항목 쪽 경고 줄에 붙는다. `{마일스톤}`은 마일스톤 id이고, 미배정 항목(맨 오른쪽 열)이 선행이면 그 자리는 `마일스톤 없음`이다.
|
|
342
|
+
|
|
343
|
+
#### 선행 순환
|
|
344
|
+
|
|
345
|
+
선행이 돌고 돌아 자기에게 되돌아오면 순환이다. 엔진은 순환에 든 항목마다 `로드맵 {항목 제목}: 선행 순환: {id} → {id} → …`(자기에서 시작해 돌아오는 가장 짧은 경로) 경고를 낸다. 층 모드 화면은 순환 항목을 마지막 열 다음 열에 모으고, 마일스톤 모드는 자기 열에 둔다. 순환 선은 점선이다. 마일스톤 절과 상관없이 나오는 경고다.
|
package/docs/semantic-schema.md
CHANGED
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
| function | 생성(migration) | name | DB 함수. 읽고 쓰는 테이블, BFF 사용 여부 |
|
|
18
18
|
| table | 생성(migration) | schema.name | 저장 구조 |
|
|
19
19
|
| migration | 생성(migration) | file | migration 파일 하나. 만드는 테이블·함수, grant·RLS 수, 마지막 변경 |
|
|
20
|
-
| test | 생성(tests
|
|
21
|
-
| testreport | 생성(JUnit 리포트) | last | 마지막 검사 실행의
|
|
20
|
+
| test | 생성(tests/, 결과 JSON) | file | 검사 파일. 다루는 라우트·API, 마지막 실행(`lastRun`) |
|
|
21
|
+
| testreport | 생성(결과 JSON, 없으면 JUnit 리포트) | last | 마지막 검사 실행의 건수·실패·건너뜀, 결과가 최신인지와 검사 신호(`test-results.md`) |
|
|
22
22
|
| commit | 생성(git) | sha | 최근 변경. 건드린 파일 → 영향받는 화면·여정 |
|
|
23
|
-
| decision | 생성(위키 index, 작업
|
|
24
|
-
| task | 생성(작업 폴더 `tasks.dir
|
|
23
|
+
| decision | 생성(위키 index, 작업 문서, 판정 파일) | file 또는 번호 | 위키 결정 페이지와 상태(current/proposed/superseded). 작업 문서의 결정 번호와 계획 항목 번호(완료 여부)도 이 종류로 두고, 정의한 작업을 `definers`에 싣는다 |
|
|
24
|
+
| task | 생성(작업 폴더 `tasks.dir`, 판정 파일) | 폴더 이름 | 작업 하나. 제목·단계(스펙 초안~검증)·상태·결정 수·계획 항목 완료/미완·열린 질문 수와 각 값의 읽기 상태. 계획 항목은 계획 파일(대체 규칙 포함)에서만, 결정·잔여 질문은 스펙 final에서만 센다(`semantic-authoring.md` 「작업 문서」) |
|
|
25
25
|
| ledger | 생성(tasks/index.md) | 행 | 지금 실행 중·대기 중인 작업 |
|
|
26
26
|
| deploy | 생성(git·배포 매니페스트) | head, 배포 대상 | 브랜치 머리 커밋, 매니페스트 이미지 태그의 sha와 뒤처진 커밋 수 |
|
|
27
27
|
| milestone | 손(로드맵 `## 제목` 절) | id | 로드맵 항목. 순서·상태·진행 방식·장면·작업·선행·결정 대기·완료 기준·마일스톤, git 이력에서 계산한 완료일(`completedAt`)·결정 대기 시작일(`waitingSince`) |
|
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
- journey → step (순서)
|
|
33
33
|
- step → screen (shows): `screens: [route]`
|
|
34
34
|
- step → api (uses): 명시(`apis`) 또는 screen을 거쳐 유도
|
|
35
|
-
- screen → api (calls): 페이지와 그
|
|
35
|
+
- screen → api (calls): 페이지와 그 import 닫힘의 `/api/` 문자열 리터럴을 모든 어댑터 뒤 연결 단계가 API 노드에 대응(1.2.0). 설정에 `router.hookApi`가 있으면 hook 이름 대응표로 이은 엣지도 더한다(2.0.0에서 폐기)
|
|
36
36
|
- api → function (invokes): BFF 핸들러 블록의 `rpc/<name>`
|
|
37
37
|
- function → table (touches): 함수 본문에서 알려진 테이블 이름 스캔
|
|
38
38
|
- test → screen | api (covers): 검사 파일의 `goto('/…')`·`'/api/…'` 문자열
|
|
39
39
|
- commit → screen | api | function (touches): 파일 경로 → 노드(페이지 파일·닫힘·server.mjs·migration)
|
|
40
40
|
- milestone → task (tracks): 로드맵 항목의 `작업`. 장면·선행은 derive에서 해석하고 없으면 check 오류
|
|
41
41
|
- release → milestone (contains): 로드맵 항목의 `마일스톤` 키. 없는 마일스톤 id면 엣지 없이 check 오류
|
|
42
|
-
- task → decision (defines): 작업 문서의
|
|
43
|
-
- step → decision (refs): `refs: ["DEC-57", "PN-15", "trust-boundary"]`. derive가 문자열로 해석한다:
|
|
42
|
+
- task → decision (defines): 작업 문서의 결정 목록 줄·계획 파일 체크박스의 머리 번호, 판정 파일 `lines` definition
|
|
43
|
+
- step → decision (refs): `refs: ["DEC-57", "20260914-booking#PN-15", "trust-boundary"]`. derive가 문자열로 해석한다: 번호는 그 번호를 정의한 작업(defines)으로(정의 작업이 여럿이면 `tasks.ambiguous-ref`), `<폴더>#<번호>`는 그 작업의 정의로, 나머지는 위키 결정 slug로 찾는다
|
|
44
44
|
|
|
45
45
|
## 상태 규칙
|
|
46
46
|
|
|
@@ -53,7 +53,64 @@
|
|
|
53
53
|
|
|
54
54
|
## 문제 기록(issues)
|
|
55
55
|
|
|
56
|
-
어댑터가 `g.issue(level, label, message)`로 낸 오류·경고는 노드가 아니라 `graph.json`·`data.json` 최상위 `issues[]`에 `{level, label, message, adapter}`로 남는다(1.1.0부터, `adapter-contract.md`).
|
|
56
|
+
어댑터가 `g.issue(level, label, message, detail?)`로 낸 오류·경고는 노드가 아니라 `graph.json`·`data.json` 최상위 `issues[]`에 `{level, label, message, adapter}`로 남는다(1.1.0부터, `adapter-contract.md`). 넷째 인자를 준 문제는 `code`·`subject`·`anchors`·`resolutions`(있으면 `judgmentDraft`)를 더 싣는다(1.2.0, 코드 표는 `issue-codes.md`).
|
|
57
|
+
|
|
58
|
+
## 읽기 상태
|
|
59
|
+
|
|
60
|
+
1.2.0부터 값마다 어떻게 읽었는지를 함께 싣는다. 노드 `props.reading`은 `{ 필드: 상태 }`, `props.readingNotes`는 `{ 필드: 이유 문장 }`이다.
|
|
61
|
+
|
|
62
|
+
| 상태 | 뜻 | 화면 |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `observed` | 생산자의 구조화된 출력(결과 JSON)이나 livemap 소유 형식에서 읽음 | 값 |
|
|
65
|
+
| `rule` | 규칙으로 읽었고 같은 범위의 후보 줄이 모두 읽힘. 적지 않은 필드의 기본값 | 값 |
|
|
66
|
+
| `judged` | 판정 파일이 값을 채우거나 고쳤고 근거 조각이 확인됨 | 값, 작업 상세와 더보기에 "판정" |
|
|
67
|
+
| `partial` | 규칙으로 읽었지만 안 읽힌 후보 줄이나 뜻 확인이 필요한 행이 있음 | 값 뒤 "?"(예: `48/61?`) |
|
|
68
|
+
| `stale` | 판정 근거 조각이 원문에서 사라졌거나 검사 결과 뒤 코드가 바뀜 | "?" |
|
|
69
|
+
| `unknown` | 소스가 없거나 형식 밖 | "?" |
|
|
70
|
+
| `none` | 대상이 없음(체크박스 없는 조사 작업 등) | 빈 칸 |
|
|
71
|
+
|
|
72
|
+
| 필드 | 상태 규칙 |
|
|
73
|
+
|---|---|
|
|
74
|
+
| 작업 `plan` | 계획 파일이나 대체 규칙으로 읽으면 `rule`, 판정 `planFile`이면 `judged`, 계획 파일이 없고 체크박스를 가진 루트 md가 둘 이상이면 `unknown`, 체크박스가 없으면 `none` |
|
|
75
|
+
| 작업 `openQuestions` | 잔여 질문 절을 읽으면 `rule`. 첫 칸이 번호 하나가 아닌 행이 있거나 완료 작업에 닫히지 않은 행이 있으면 `partial`. 스펙 final에 절이 없으면 `unknown`, `spec/initial.md`만 있으면 검토 전이라 `unknown`(이슈 없음). 스펙이 없거나 폐기 작업이면 `none`. 판정이 덮으면 `judged` |
|
|
76
|
+
| 작업 `stage` | 파이프라인 문서로 정하면 `rule`, 없으면 `unknown` |
|
|
77
|
+
| 검사 `count` | 최신 결과가 있으면 `observed`, 제목이 `${`를 가진 템플릿 문자열인 호출이 있으면 `partial`, 나머지 `rule` |
|
|
78
|
+
| 검사 `lastRun` | 최신 결과면 `observed`, 결과가 낡았으면 `stale`, 결과가 없거나 결과에 그 파일이 없으면 `unknown` |
|
|
79
|
+
| 화면 `apis` | 모든 리터럴이 API 노드에 맞고 hookApi로만 붙은 항목이 없으면 `rule`, 아니면 `partial` |
|
|
80
|
+
| 배포 `behind` | 계산하면 `rule`, 매니페스트 sha가 이력에 없거나 git 이력을 못 읽으면 `unknown` |
|
|
81
|
+
|
|
82
|
+
합계는 구성 요소 중 하나라도 `partial`·`stale`·`unknown`이면 `partial`이다. `none`은 합계에서 빼고, 나머지가 섞이면 `judged`, `rule`, `observed` 순으로 약한 근거를 쓴다. 개요의 "?" 옆에는 이유 분류 문구만 쓰고, 파일·줄이 든 이유 문장은 작업 상세와 더보기에 글자로 보인다.
|
|
83
|
+
|
|
84
|
+
## 1.2.0에서 더한 생성물 필드
|
|
85
|
+
|
|
86
|
+
필드를 더하기만 했고 1.1.1 필드의 이름·위치는 그대로다.
|
|
87
|
+
|
|
88
|
+
| 생성물 | 필드 | 뜻 |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `graph.json` 노드 `task` | `reading`, `readingNotes` | 작업 `plan`·`openQuestions`·`stage`(대체 규칙이면 `spec`) 읽기 상태와 이유 |
|
|
91
|
+
| | `readLines` | 엔진이 센 줄 `{ 파일: [줄 번호] }` |
|
|
92
|
+
| | `openQuestions`, `openQuestionIds` | 열린 잔여 질문 수(못 읽으면 `null`)와 번호 |
|
|
93
|
+
| | `planFile`, `specFile` | 읽은 계획 파일과 스펙 final(대체 규칙·판정 포함), 없으면 `null` |
|
|
94
|
+
| | `judged`, `judgment` | 판정 파일 경로와 `{ by, note, applied, stale, invalid }`, 판정 파일이 없으면 둘 다 `null` |
|
|
95
|
+
| `graph.json` 노드 `decision` | `definers`, `definedAt` | 그 번호를 정의한 작업 이름 목록, 정의 줄 `{ task, file, line }` 목록 |
|
|
96
|
+
| | `struck` | 취소선 정의만 있는 번호면 `true` |
|
|
97
|
+
| `graph.json` 노드 `test` | `lastRun`의 `failed`·`skipped`·`pending`·`flaky`(Playwright만)·`runner`·`sha`·`at`·`tags` | 결과 JSON의 파일별 값. 1.1.1 `passed`·`tests`·`fresh`는 그대로이고 `passed`는 `failed === 0`이다. `tags`는 파일에 붙은 러너 태그다 |
|
|
98
|
+
| | `runCount`, `reading`, `readingNotes` | 결과의 실행 수, `count`·`lastRun` 읽기 상태와 낡은 이유 |
|
|
99
|
+
| `graph.json` 노드 `screen` | `apiLiterals[]` | `{ path, open?, file, line, matched }`. 관측한 `/api/` 리터럴과 연결 단계가 맞춘 API 노드 id |
|
|
100
|
+
| | `hookApiKeys` | 설정에 `router.hookApi`가 있을 때 그 화면이 쓴 대응표 키 |
|
|
101
|
+
| | `reading`, `readingNotes` | `apis` 읽기 상태와 맞지 않는 리터럴·hookApi로만 붙은 API(3개까지) |
|
|
102
|
+
| `graph.json` 노드 `deploy` | `behindManifestOnly`, `reading`, `readingNotes` | 뒤처짐에서 뺀 매니페스트 전용 커밋 수, `behind` 읽기 상태 |
|
|
103
|
+
| `graph.json` 노드 `testreport:last` | `signal`, `runs` | 검사 신호(`ok`·`fail`·`stale`·`none`)와 실행 목록 |
|
|
104
|
+
| `graph.json`·`data.json` `issues[]` | `code`, `subject`, `anchors`, `resolutions`, `judgmentDraft` | 넷째 인자를 준 문제에만(`adapter-contract.md`, `issue-codes.md`) |
|
|
105
|
+
| `data.json` `tasks[]` | `reading`, `readingNotes`, `openQuestions`, `openQuestionIds`, `planFile`, `specFile`, `judged`, `judgment` | 노드와 같다. `readLines`는 싣지 않는다 |
|
|
106
|
+
| `data.json` `tests[]` | `reading`, `readingNotes` | 노드와 같다 |
|
|
107
|
+
| `data.json` `screens[]` | `reading` | 노드와 같다(이유 문장은 노드에만) |
|
|
108
|
+
| `data.json` | `testRuns[]` | `{ runner, source, sha, at, exit, fresh }`. 결과 JSON의 `dirtyPaths`는 싣지 않는다 |
|
|
109
|
+
| `data.json` | `readings` | `{ values: { 상태: 건수 }, fields: { '<노드 종류>.<필드>': { 상태: 건수 } } }` |
|
|
110
|
+
| `data.json` | `judgments[]` | `{ task, file, by, note, applied, stale, invalid }` |
|
|
111
|
+
| `overview.json` | `counts.openQuestions` | 열린 잔여 질문 합계. 1.1.1 `counts.oq`와 최상위 `openQuestions`는 그대로 남는다 |
|
|
112
|
+
| `overview.json` | `counts.reading` | `{ plans, openQuestions, tests, grades }` 개요 수치의 읽기 상태(경로·파일명 없음). `grades`는 검사 `lastRun`과 화면 `apis`의 합계다 |
|
|
113
|
+
| `overview.json` | `tasks[].openQuestions`, `tasks[].reading` | 작업별 열린 질문 수와 읽기 상태(식별자 없음) |
|
|
57
114
|
|
|
58
115
|
## 다른 프로젝트에 옮길 때 바꾸는 것
|
|
59
116
|
|