@kaydash9999/banker-plugins 0.21.0 → 0.23.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 (129) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +69 -0
  4. package/PRIVACY.md +8 -3
  5. package/README.md +78 -15
  6. package/bin/banker.js +154 -32
  7. package/bin/lib/codex-hooks.mjs +123 -20
  8. package/bin/lib/codex-names.mjs +4 -0
  9. package/bin/lib/codex-routes.mjs +204 -0
  10. package/bin/lib/command-skill.cjs +50 -0
  11. package/bin/lib/telemetry-config.mjs +2 -1
  12. package/codex/command-skills/front-qa/SKILL.md +56 -0
  13. package/codex/command-skills/setup/SKILL.md +87 -0
  14. package/codex/hooks.json +29 -0
  15. package/codex/manifest.json +18 -15
  16. package/codex/skills/graceful-pause/SKILL.md +2 -2
  17. package/codex/skills/progress/scripts/progress.mjs +44 -14
  18. package/codex/skills/teamwork/SKILL.md +137 -0
  19. package/codex/skills/teamwork/scripts/teamwork.mjs +957 -0
  20. package/codex/transform-matrix.md +5 -3
  21. package/commands/setup.md +2 -2
  22. package/hooks/obsidize-hook.mjs +75 -32
  23. package/hooks/telemetry-count-codex.mjs +303 -35
  24. package/hooks/update-fetch.mjs +2 -1
  25. package/hooks/update-notify.mjs +146 -13
  26. package/package.json +3 -1
  27. package/skills/3d-intro-build/SKILL.md +101 -20
  28. package/skills/3d-intro-build/references/NOTICE.md +9 -2
  29. package/skills/3d-intro-build/references/assemble.mjs +113 -22
  30. package/skills/3d-intro-build/references/azure-adapter.mjs +110 -24
  31. package/skills/3d-intro-build/references/clip-post.mjs +443 -0
  32. package/skills/3d-intro-build/references/dive-mode.mjs +299 -0
  33. package/skills/3d-intro-build/references/intro-fixes.css +11 -0
  34. package/skills/3d-intro-build/references/prompts.md +51 -4
  35. package/skills/3d-intro-build/references/scrub-engine.js +1 -0
  36. package/skills/3d-intro-build/references/step-nav.css +29 -0
  37. package/skills/3d-intro-build/references/step-nav.js +277 -106
  38. package/skills/3d-intro-build/references/verify-intro.mjs +387 -32
  39. package/skills/3d-intro-build/references/verify.md +6 -0
  40. package/skills/3d-intro-build/references/video-pool.mjs +142 -12
  41. package/skills/3d-intro-setup/SKILL.md +20 -7
  42. package/skills/3d-intro-setup/references/azure-adapter.mjs +110 -24
  43. package/skills/3d-intro-setup/references/video-pool.mjs +142 -12
  44. package/skills/all-in-one/SKILL.md +125 -86
  45. package/skills/anti-drm/SKILL.md +1 -1
  46. package/skills/anti-drm/scripts/instruction-toggle.mjs +57 -4
  47. package/skills/arch-diagram/build_pptx_template.py +47 -28
  48. package/skills/audit-web-page/SKILL.md +1 -1
  49. package/skills/audit-web-page/harness.py +0 -1
  50. package/skills/lineage/lineage.py +1435 -533
  51. package/skills/motion-graphic-make/SKILL.md +1 -1
  52. package/skills/obsidizer/SKILL.md +20 -5
  53. package/skills/omc-patch/SKILL.md +1 -1
  54. package/skills/payload-mon/SKILL.md +2 -2
  55. package/skills/play-qa/SKILL.md +7 -5
  56. package/skills/progress-mon/README.md +162 -0
  57. package/skills/progress-mon/SKILL.md +165 -0
  58. package/skills/progress-mon/assets/fixture/README.md +1 -0
  59. package/skills/progress-mon/assets/fixture/arch.json +33 -0
  60. package/skills/progress-mon/assets/fixture/commits.json +7 -0
  61. package/skills/progress-mon/assets/fixture/config.json +30 -0
  62. package/skills/progress-mon/assets/fixture/events.jsonl +7 -0
  63. package/skills/progress-mon/assets/fixture/flow.json +44 -0
  64. package/skills/progress-mon/assets/fixture/items.json +14 -0
  65. package/skills/progress-mon/assets/fixture/req-spec.json +31 -0
  66. package/skills/progress-mon/assets/fixture/reqs.json +11 -0
  67. package/skills/progress-mon/assets/fixture/variants/arch-auto/arch.json +58 -0
  68. package/skills/progress-mon/assets/fixture/variants/check-auto/arch.json +15 -0
  69. package/skills/progress-mon/assets/fixture/variants/check-overlap/arch.json +14 -0
  70. package/skills/progress-mon/assets/fixture/variants/history-manual/config.json +13 -0
  71. package/skills/progress-mon/assets/fixture/variants/history-manual/items.json +7 -0
  72. package/skills/progress-mon/assets/fixture/variants/workflow-wide/flow.json +35 -0
  73. package/skills/progress-mon/assets/fixture/workflows/wf_ex1/agent-a01.jsonl +1 -0
  74. package/skills/progress-mon/assets/fixture/workflows/wf_ex1/agent-a02.jsonl +1 -0
  75. package/skills/progress-mon/assets/fixture/workflows/wf_ex1/agent-a03.jsonl +1 -0
  76. package/skills/progress-mon/assets/fixture/workflows/wf_ex1/agent-a04.jsonl +1 -0
  77. package/skills/progress-mon/assets/fixture/workflows/wf_ex1/journal.jsonl +7 -0
  78. package/skills/progress-mon/references/arch.md +280 -0
  79. package/skills/progress-mon/references/authoring.md +199 -0
  80. package/skills/progress-mon/references/config.md +115 -0
  81. package/skills/progress-mon/references/flow.md +75 -0
  82. package/skills/progress-mon/references/inventory.md +58 -0
  83. package/skills/progress-mon/references/items.md +74 -0
  84. package/skills/progress-mon/references/req-spec.md +74 -0
  85. package/skills/progress-mon/references/reqs.md +30 -0
  86. package/skills/progress-mon/scripts/index.js +31 -0
  87. package/skills/progress-mon/scripts/pm-check.mjs +526 -0
  88. package/skills/progress-mon/scripts/pm-config.mjs +341 -0
  89. package/skills/progress-mon/scripts/pm-data.mjs +394 -0
  90. package/skills/progress-mon/scripts/pm-html.mjs +77 -0
  91. package/skills/progress-mon/scripts/pm-memory.mjs +308 -0
  92. package/skills/progress-mon/scripts/pm-render.mjs +1644 -0
  93. package/skills/progress-mon/scripts/pm-server.mjs +735 -0
  94. package/skills/progress-mon/scripts/pm-sources.mjs +501 -0
  95. package/skills/progress-mon/scripts/progress-mon.mjs +167 -0
  96. package/skills/ralph-qa/SKILL.md +105 -16
  97. package/skills/ralph-qa/references/gate-evidence.mjs +457 -0
  98. package/skills/ralph-qa/references/payload-scan.mjs +19 -2
  99. package/skills/ralph-qa/references/run-folder.mjs +299 -0
  100. package/skills/ralph-qa/references/seat-payload.mjs +60 -13
  101. package/skills/ralph-qa/references/seat-run.mjs +159 -155
  102. package/skills/remains/SKILL.md +2 -1
  103. package/skills/remains/scripts/boxes.mjs +6 -2
  104. package/skills/rfp-author/scripts/md2docx.py +63 -34
  105. package/skills/setup-bypass-permissions/SKILL.md +2 -2
  106. package/skills/setup-bypass-permissions/scripts/codex-config.mjs +19 -8
  107. package/skills/setup-bypass-permissions/scripts/fallback/bypass-permissions.py +66 -15
  108. package/skills/setup-mcp/SKILL.md +1 -1
  109. package/skills/setup-omc-hud/SKILL.md +2 -1
  110. package/skills/setup-omc-hud/assets/codex-config.mjs +19 -8
  111. package/skills/smart-compact/SKILL.md +1 -1
  112. package/skills/smart-compact/scripts/codex-gate.mjs +2 -1
  113. package/skills/theme-selection/SKILL.md +1 -1
  114. package/skills/tone-compact/SKILL.md +1 -1
  115. package/skills/tone-compact/scripts/instruction-toggle.mjs +57 -4
  116. package/skills/ultra-chain/SKILL.md +34 -16
  117. package/skills/ultra-chain/references/chain-ledger.mjs +111 -3
  118. package/skills/ultra-init/SKILL.md +30 -22
  119. package/skills/ultra-ui-qa/SKILL.md +1 -1
  120. package/skills/ultraqa/NOTICE.md +34 -0
  121. package/skills/ultraqa/SKILL.md +196 -0
  122. package/skills/ultraqa/references/gate-evidence.mjs +457 -0
  123. package/skills/ultraqa/references/run-folder.mjs +299 -0
  124. package/skills/ultraqa/references/tmux-drive.md +52 -0
  125. package/skills/ultraqa/references/uqa-run.mjs +339 -0
  126. package/skills/update-banker/SKILL.md +32 -7
  127. package/skills/vertical-pptx/SKILL.md +1 -1
  128. package/skills/vertical-pptx/build_a4p.js +20 -2
  129. package/skills/vertical-pptx/build_a4p.py +560 -359
@@ -0,0 +1,199 @@
1
+ # init 작성 지침
2
+
3
+ init 절차(SKILL.md)에서 에이전트가 4탭 자료를 쓸 때 따르는 기준. 목표 밀도는 이 문서 안에서 확인한다: 아래 "밀도 하한" 표의 수(구성도 영역 5, 상자 20, 연결 15, workflow 흐름 2, 흐름당 단계 7 등)와 "좋은 예" 의 꼴(상자 설명 2~3줄과 칩과 근거, 연결마다 `파일:줄`, 흐름마다 실패 분기와 3문장 설명).
4
+ 숫자 하한은 보조 점검이다. 하한을 채워도 아래 좋은 예보다 얇으면(설명 한 줄, 근거 없음, 분기 없음) 보충한다.
5
+
6
+ ## 순서
7
+
8
+ 1. 읽기 예산 안에서 코드를 읽는다
9
+ 2. `inventory.json` 에 실제 구성요소, 흐름, 외부, 읽은 파일을 적는다(`references/inventory.md`)
10
+ 3. `config.json` 의 `title`, `shortName`, `stories` 를 채운다
11
+ 4. `req-spec.json`, `reqs.json`, `flow.json`, `arch.json` 을 쓴다. 좌표는 쓰지 않는다
12
+ 5. `check` 로 검사한다. FAIL 0 까지 최대 3회. `WARN density` 가 남으면 한 번 더 보충(SKILL.md init 절차 8, 9)
13
+
14
+ ## 밀도 하한
15
+
16
+ | 탭 | 항목 | 하한 | `check` 의 이름 |
17
+ |---|---|---|---|
18
+ | 구성도 | 영역 | 5 | `arch 영역` |
19
+ | 구성도 | 상자 | 20 | `arch 상자` |
20
+ | 구성도 | 상자 설명 | 상자마다 2~3줄(아래 "설명 줄 수") | `arch 상자설명` |
21
+ | 구성도 | 연결 | 15 | `arch 연결` |
22
+ | 구성도 | 연결 근거 | 연결마다 `refs`(`파일:줄`) | `arch 연결근거` |
23
+ | 구성도 | 범례, 주 흐름, 장면 | `legend` 1 이상, `main` 1 이상, `scenes` 5 이상 | `arch 범례`, `주흐름`, `장면` |
24
+ | workflow | 흐름 | 2 | `workflow 흐름` |
25
+ | workflow | 흐름당 단계 | 7 | `workflow 단계:<흐름 id>` |
26
+ | workflow | 단계 설명 | 단계마다 2~3줄(아래 "설명 줄 수") | `workflow 단계설명` |
27
+ | workflow | 행위자, 근거 | 단계마다 `actor`, `refs` | `workflow 행위자`, `단계근거` |
28
+ | workflow | 실패 분기, 외부 | 흐름마다 `branches` 1 이상, `externals` 1 이상 | `workflow 실패분기`, `외부` |
29
+ | workflow | 흐름 설명 | 흐름마다 `note` 3문장(시작 명령, 실패 처리, 근거) | `workflow 흐름설명` |
30
+ | 구현요건 | 요구 | 요구마다 원문 `text` 와 근거 `source` | `req 요구` |
31
+ | 구현요건 | 교차 대응 | 명세마다 AC 1 이상. 스토리가 있으면 AC 를 거쳐 담당 스토리 1 이상 | `req 명세AC`, `명세스토리` |
32
+ | 구현요건 | 비고 | `state` 를 적은 명세는 `note`(판정 근거) | `req 비고` |
33
+ | 진척도 | 기타 항목 | 항목마다 `note`(근거 커밋, 결과). 문제점이 없으면 `--issue` 를 빼고 실행(칸은 빈칸) | `history 비고` |
34
+
35
+ - 미달은 `WARN density <탭> <항목> <값>/<하한>` 한 줄씩. 종료 코드에 영향 없음
36
+ - 대상마다 재는 항목은 줄 끝에 `: ` 와 못 채운 대상을 붙인다. 앞 10개, 넘으면 `외 n`
37
+
38
+ | 항목 | 붙는 이름 | 예 |
39
+ |---|---|---|
40
+ | `arch 상자설명` | 상자 id(줄 수) | `n3(1줄), n7(4줄)` |
41
+ | `arch 연결근거` | 연결 id(없으면 `<from>-<to>`) | `e-req` |
42
+ | `workflow 단계설명` | `<흐름 id>/<단계 id>(줄 수)` | `build/b3(1줄)` |
43
+ | `workflow 행위자`, `단계근거` | `<흐름 id>/<단계 id>` | `build/b3` |
44
+ | `workflow 실패분기`, `외부` | 흐름 id | `deploy` |
45
+ | `workflow 흐름설명` | 흐름 id(문장 수) | `deploy(2문장)` |
46
+ | `req 요구` | json 경로 | `users[2]` |
47
+ | `req 명세AC`, `명세스토리`, `비고` | json 경로 | `users[0].specs[3]` |
48
+ | `history 비고` | 항목 key | `docs-1` |
49
+
50
+ - 수만 재는 항목(영역, 상자, 연결, 범례, 주흐름, 장면, 흐름, `단계:<흐름 id>`)은 이름을 붙이지 않는다. 수를 늘린다
51
+ - 하한을 채운 항목은 줄을 내지 않는다. 값을 보려면 자료에서 직접 센다
52
+ - 자동 배치의 `이름표 덮음`, `이름표가 그림 밖` WARN 은 배치 조언이고 실패가 아니다(자동 배치 선은 상자를 돌아감). 연결을 하한 아래로 줄여 없애지 않는다. 줄이는 법은 `references/arch.md` 의 "자동 배치 WARN 줄이기"
53
+ - `check` 끝에 `density <탭> ok|low` 4줄(history, req, workflow, arch)
54
+ - 밀도는 init 이 만든 자료 폴더(`state.json` 의 `memory`)나 `inventory.json` 이 있을 때만 잰다
55
+
56
+ ## 설명 줄 수
57
+
58
+ - 줄 수는 화면과 같은 줄바꿈 결과다. 글자 수가 아니다. `check` 가 같은 계산으로 잰다
59
+ - 구성도 상자
60
+ - 자동 배치의 상자 폭은 영역마다 같다. 그 영역에서 가장 넓게 필요한 상자(긴 이름, 긴 칩, 설명의 긴 낱말)에 맞춘다. 최소 160 px
61
+ - 160 px 상자의 한 줄은 띄어쓰기 포함 약 14자. 2줄은 약 15~28자, 3줄은 약 29~42자
62
+ - 화면은 기본 2줄만 그린다. 3줄 설명은 그 상자에 `"lines": 3` 을 쓴다. 안 쓰면 `WARN arch.json nodes[i] 설명 잘림`
63
+ - 이름이나 칩 하나가 길면 그 영역의 모든 상자가 넓어져 설명이 1줄로 줄 수 있다. 이름과 칩을 짧게 쓴다
64
+ - workflow 단계: 상자 폭 176 px 고정. 한 줄 약 14자. 2~3줄은 약 15~42자
65
+ - 화면은 3줄까지 그린다. 단계 이름이 상자에 안 들어가 두 줄이 되어도 설명은 3줄까지(상자가 15 px 늘어남). 이름 한 줄은 한글 약 9자와 띄어쓰기 3칸까지
66
+ - `check` 의 `(n줄)` 이 1이면 늘리고, 4 이상이면 줄인다
67
+
68
+ ## 작은 저장소 예외
69
+
70
+ - 하한 = min(위 하한, 실제 수). 실제 수는 `inventory.json` 에서 센다
71
+ - 영역 min(5, 구성요소 수), 상자 min(20, 구성요소 수)
72
+ - 흐름 min(2, 흐름 수), 흐름당 단계 min(7, 그 흐름 `steps`)
73
+ - 연결 min(15, `arch.json` 에 그린 상자 수 - 1). 구성요소 수가 아니라 실제로 그린 `nodes` 수다
74
+ - `inventory.json` 의 `path`, `evidence` 가 저장소에 없으면 FAIL. 수를 줄여 하한을 피하지 못한다
75
+ - `inventory.json` 이 없으면 위 하한을 그대로 쓴다
76
+ - 예외는 숫자 하한에만 쓴다. 상자 설명 줄 수, 근거, 분기, 비고 같은 꼴은 작아도 같다
77
+
78
+ ## 읽기 예산
79
+
80
+ | 순서 | 읽을 것 | 상한 |
81
+ |---|---|---|
82
+ | 1 | README, 기여 안내, 패키지 매니페스트(`package.json`, `pyproject.toml` 등), CI 설정 | 전부 |
83
+ | 2 | 폴더 목록 깊이 2(`node_modules`, `.git`, 빌드 산출물 제외) | 전부 |
84
+ | 3 | 진입점과 최상위 모듈의 주 파일 | 20개 |
85
+ | 4 | 명령, 스크립트, 빌드와 배포 정의(`scripts`, `Makefile`, `*.cmd`, 워크플로 YAML) | 15개 |
86
+ | 5 | 연결 근거 `파일:줄` 을 얻기 위한 검색(import, 호출, 설정 키) | 검색 결과 줄만 |
87
+ | 6 | 시험 폴더 목록과 시험 이름 | 목록만 |
88
+ | 7 | `git log --oneline -200` | 1회 |
89
+
90
+ - 합계 상한: 파일 60개 또는 600 KB. 넘으면 최상위 폴더 단위로 대표 파일만 읽고 `inventory.json` 에 그 폴더를 구성요소 하나로 적는다
91
+ - 상한에 드는 것과 들지 않는 것
92
+
93
+ | 읽은 꼴 | 파일 수 | 바이트 | `read` 에 적음 |
94
+ |---|---|---|---|
95
+ | 파일 전체를 엶 | 1 | 파일 크기 | 예 |
96
+ | 파일 일부(줄 범위)를 엶 | 1 | 실제로 읽은 부분 | 예 |
97
+ | 검색 결과 줄(순서 5) | 안 듦 | 안 듦 | 아니오 |
98
+ | 폴더 목록, 시험 이름 목록, `git log`(순서 2, 6, 7) | 안 듦 | 안 듦 | 아니오 |
99
+
100
+ - 같은 파일을 여러 번 열어도 파일 수는 1. 바이트는 읽은 부분을 모두 더한다
101
+ - 읽은 파일(전체와 일부)은 모두 `inventory.json` 의 `read` 에 적는다
102
+ - 비밀값 파일(`.env`, 키 파일, 크레덴셜)은 읽지 않는다. 자료에 값을 옮기지 않는다
103
+
104
+ ## 크기 상한
105
+
106
+ | 항목 | 상한 | 넘으면 |
107
+ |---|---|---|
108
+ | workflow 흐름 | 6 | `check` WARN |
109
+ | 흐름당 단계 | 15 | WARN |
110
+ | 구성도 상자 | 60 | WARN |
111
+ | 구성도 연결 | 60 | WARN |
112
+
113
+ - 넘을 것 같으면 흐름을 나누지 말고 묶는다(비슷한 단계 합치기, 보조 구성요소를 칩 `items` 로)
114
+
115
+ ## 자료 없음 탈출구
116
+
117
+ - 3회 고친 뒤에도 FAIL 이 남는 탭은 그 탭 파일만 지운다. 화면은 "자료 없음" 과 스키마 문서 경로를 보인다
118
+ - 근거가 없어 쓸 수 없는 탭은 처음부터 쓰지 않는다. 지어내지 않는다
119
+ - 구현요건 탭의 요구 원문은 아래 순서로 찾는다. 앞 순서에 있으면 뒤 순서는 쓰지 않는다
120
+
121
+ | 순서 | 원문 출처 | `source` 예 |
122
+ |---|---|---|
123
+ | 1 | 요구 문서, 명세, 이슈, 설계 문서 | `docs/spec.md:10-24` |
124
+ | 2 | README 의 기능 목록, 사용법 절 | `README.md:31-38` |
125
+ | 3 | 명령 도움말 문구, 패키지 매니페스트 `description`, 진입점 머리 주석 | `src/cli.js:5-20` |
126
+
127
+ - 셋 모두 없으면 `req-spec.json`, `reqs.json` 을 쓰지 않는다(구현요건 탭 "자료 없음")
128
+ - 코드와 시험은 요구 원문이 아니다. 명세의 판정 근거(`note`)로만 쓴다
129
+ - 사용자에게 남은 FAIL, 지운 탭, 밀도 미달 수치를 보고한다
130
+
131
+ ## 좋은 예
132
+
133
+ 아래는 실제 플러그인 코드베이스를 이 지침대로 쓴 자료에서 뽑은 것이다. 이 수준이 기준이다.
134
+
135
+ 구성도 상자: 설명 2~3줄, 칩, 근거
136
+
137
+ ```json
138
+ { "id": "cc", "zone": "user", "label": "Claude Code", "kind": "런타임",
139
+ "detail": "플러그인을 읽고 훅 이벤트를 보내며 Skill 도구로 SKILL.md 를 펼침",
140
+ "items": ["훅 3종", "mods 2.1.289+"], "refs": ["hooks/hooks.json:3-60", "hooks/register.mjs:50-52"], "lines": 3 }
141
+ ```
142
+
143
+ 구성도 연결: 종류, 짧은 이름표, 설명, 근거
144
+
145
+ ```json
146
+ { "id": "e-setup", "from": "user", "to": "bankerjs", "kind": "control", "label": "banker setup",
147
+ "detail": "npm 설치 뒤 setup 실행", "refs": ["README.md:198-199", "bin/banker.js:420-435"] }
148
+ ```
149
+
150
+ 구성도 범례: 주 흐름, 다른 길, 망에 닿는 곳, 문서와 다른 곳
151
+
152
+ ```json
153
+ ["요청 길(주황 굵은 선): 사용자, Claude Code, ultra-chain, ralph-qa, seat-run, 외부 LLM 차례. 이 차례로 상자가 빛남",
154
+ "망에 닿는 것은 분리 실행한 업데이트 확인기, 외부 좌석, 유료 API 뿐",
155
+ "문서와 다른 곳: README 훅 표에 progress-fallback 없음(README.md:236-240)"]
156
+ ```
157
+
158
+ workflow 흐름: 제목에 시작과 끝, 설명 3문장
159
+
160
+ ```json
161
+ { "id": "skill", "title": "스킬 호출: /banker:ultra-chain 에서 최종 보고까지", "color": "#6a1b9a",
162
+ "note": "/banker:ultra-chain <과제> 로 시작(skills/ultra-chain/SKILL.md:7). 단계마다 게이트를 지나야 다음 단계로 가고, 멈춤 조건이면 사유를 남기고 멈춤(SKILL.md:452-460). 실행 기록은 chain-ledger.mjs 가 events.jsonl 에 씀(SKILL.md:129-141)." }
163
+ ```
164
+
165
+ workflow 단계, 분기, 외부
166
+
167
+ ```json
168
+ { "id": "c1", "label": "사전 점검", "detail": "저장소 루트, 작업 트리, OMC 판, 박스 접속, 브라우저를 확인해 기록",
169
+ "actor": "ultra-chain SKILL.md", "refs": ["skills/ultra-chain/SKILL.md:166-189"] }
170
+ { "from": "c1", "to": "", "when": "루트 아님: 멈춤", "note": "세션이 저장소 루트가 아니면 멈춤 (skills/ultra-chain/SKILL.md:168)" }
171
+ { "id": "x2", "label": "test-boxes", "linkTo": "c1", "note": "remains 의 boxes.mjs probe (SKILL.md:96, 181-183)" }
172
+ ```
173
+
174
+ 구현요건: 요구 원문과 출처, 명세마다 AC 와 근거
175
+
176
+ ```json
177
+ { "text": "Claude Code 마켓플레이스 두 줄로 설치", "source": "README.md:31-38",
178
+ "specs": [
179
+ { "text": "/plugin marketplace add 와 /plugin install 로 설치", "acs": ["AC-1"], "note": "README.md:31-32, .claude-plugin/marketplace.json:9" },
180
+ { "text": "plugin.json 판이 단일 원천. sync-version 이 전파하고 --check 가 어긋남을 막음", "acs": ["AC-4"], "note": "scripts/sync-version.js:24-45, package.json:10" } ] }
181
+ ```
182
+
183
+ 진척도 비고와 문제점(`note` 명령 또는 `item --note --issue`)
184
+
185
+ ```json
186
+ { "B6": { "note": "0.8.0 opt-in 초안을 업데이트 알림과 기본 켜짐 카운팅으로 재구성. 0.9.0 개인화 알림",
187
+ "issue": "hooks.json:2 설명은 엔드포인트 없으면 무동작이라 하나 기본 엔드포인트가 있음(telemetry-config.mjs:214)" } }
188
+ ```
189
+
190
+ ## 나쁜 예
191
+
192
+ | 나쁜 예 | 고칠 점 |
193
+ |---|---|
194
+ | `"detail": "서버"` | 무엇을 받고 무엇을 내는지 2~3줄 |
195
+ | 연결에 `refs` 없음 | import 나 호출 위치 `파일:줄` |
196
+ | 흐름 `note` 한 문장 | 시작 명령, 실패 처리, 근거 3문장 |
197
+ | 분기 없는 흐름 | 실제 실패 경로(종료 코드, 재시도, 멈춤)를 찾아 적음 |
198
+ | 분기 `when` 이 긴 문장 | 표는 짧게(`설정 없음: 멈춤`), 근거는 `note` |
199
+ | 명세 `state: "done"` 에 `note` 없음 | 확인한 시험이나 코드 위치 |
@@ -0,0 +1,115 @@
1
+ # config.json
2
+
3
+ 자료 폴더(`.omc/progress-mon/`, Codex `.omx/progress-mon/`)의 설정 파일. `init` 이 기본값으로 만들고, 있으면 그대로 둔다.
4
+ 형식이 틀린 칸은 기본값으로 읽고 `check` 가 `FAIL config.json <경로> <이유>` 로 알린다. `start`, `export` 는 형식 오류가 있으면 종료 1.
5
+
6
+ 실행 중 서버는 요청마다 `config.json` 을 보고, 바뀌었으면 다시 읽는다. 그래서 `stories`, `commitRegex`, `title` 같은 값은 다음 응답에 반영된다. 형식 오류가 생기면 화면은 오류 목록을 보이고, 고치면 돌아온다.
7
+ `port`, `portStrict`, `hosts` 만은 서버를 다시 띄워야 적용된다(`stop` 뒤 `start`). 바뀐 채로 서버가 떠 있으면 `status` 가 경고 줄을 낸다.
8
+
9
+ ## 키
10
+
11
+ | 키 | 형식 | 기본 | 뜻 |
12
+ |---|---|---|---|
13
+ | `schema` | 1 | 1 | 형식 판 |
14
+ | `title` | 빈 문자열이 아닌 문자열 | `<폴더 이름> 진척도` | 화면 제목(h1) |
15
+ | `shortName` | 빈 문자열이 아닌 문자열 | 폴더 이름 | 탭 제목, 구성도 그림 이름. init 절차에서 `title` 과 함께 정한다(폴더 이름이 프로젝트 이름과 다를 때가 많음) |
16
+ | `port` | 1024~65535 정수 | 30000 | `start` 의 첫 포트. 차 있으면 다음 빈 포트(최대 +99). 0(OS 선택)은 받지 않음(아래 "포트와 주소") |
17
+ | `portStrict` | 참, 거짓 | 거짓 | 참이면 `--port-strict` 와 같음. 포트가 차 있으면 다른 포트로 비켜 가지 않고 종료 1 |
18
+ | `hosts` | 사설 IPv4 목록 | `[]` | 127.0.0.1 에 더해 바인드할 주소. `start --host <ip>` 가 저장 |
19
+ | `refreshSec` | 5~3600 정수 | 30 | 진척도, 구현요건 탭 자동 갱신 간격(초) |
20
+ | `stages` | `"auto"` 또는 `[{id, label}]` | `"auto"` | 단계 목록. `"auto"` 는 events 출처가 있으면 ultra-chain 10단계, 없으면 빈 목록 |
21
+ | `stories` | `[{id, name}]` | `[]` | 스토리 목록(순서대로 표시). 비면 스토리 판정, 스토리 표, 진척률을 생략 |
22
+ | `commitRegex` | 정규식 문자열, 이름 그룹 `id` | 없음 | 커밋 제목의 스토리 판정을 바꿈 |
23
+ | `agentLabelPattern` | 정규식 문자열, 캡처 그룹 없음 | 없음 | 진행 중 에이전트 라벨의 스토리 판정을 바꿈 |
24
+ | `sources.events` | `"auto"`, 경로, `null` | `"auto"` | ultra-chain 실행 기록. `"auto"` 는 `<project>/.omc/ultra-chain/*/events.jsonl`(Codex `.omx`) 가운데 수정 시각 최신. 상대 경로는 프로젝트 루트 기준. `null` 은 읽지 않음 |
25
+ | `sources.git` | 참, 거짓 | 참 | git log 읽기 |
26
+ | `sources.gitMax` | 양의 정수 | 5000 | 읽는 커밋 수 상한 |
27
+ | `sources.workflowDirs` | `"auto"` 또는 경로 목록 | Claude Code `"auto"`, Codex `[]` | Claude Code 워크플로 journal 루트 목록 |
28
+ | `sources.agentStaleMin` | 양의 정수 | 15 | 이 분 넘게 멈춘 에이전트 파일은 진행 중에서 뺌 |
29
+ | `sources.journalMaxAgeH` | 양의 정수 | 24 | 이 시간 넘게 멈춘 journal 은 진행 중 스캔에서 뺌 |
30
+ | `sources.journalMaxSessions` | 0 이상 정수 | 20 | 진행 중 스캔에 쓰는 최근 루트 수. 0 은 상한 없음 |
31
+ | `text.reqRule` | 문자열 | 일반 판정 설명 | 구현요건 탭 머리의 판정 규칙 문구. 기본 문구 그대로이고 담당 스토리 칸이 없으면(스토리가 없고 AC 에 담당 스토리도 없음) 명세의 `state` 로 판정한다는 문구가 대신 보임 |
32
+ | `text.plannedPrefix` | 문자열 | `예정` | 구성도 칩에서 예정(아직 구현 안 됨)을 뜻하는 접두 |
33
+
34
+ - 모르는 키는 무시한다
35
+ - `stages`, `stories` 의 id 는 겹치면 안 된다
36
+ - 단계 행과 스토리 행은 `stage`, `story` 명령으로도 늘어난다(설정에 없는 id 는 처음 나온 순서로 뒤에 붙음)
37
+
38
+ ## workflowDirs
39
+
40
+ - 경로 하나는 workflows 루트. 그 아래 실행 폴더마다 `journal.jsonl`, `agent-<id>.jsonl` 이 있다
41
+ - `"auto"` 는 `CLAUDE_CONFIG_DIR` 또는 `~/.claude` 의 `projects/<slug>/<세션>/subagents/workflows` 를 읽기만 한다
42
+ - slug: 프로젝트 절대 경로에서 영문자와 숫자 밖의 글자를 `-` 로 바꾼 것. 대소문자 무시로 비교
43
+ - 찾은 루트가 0개면 `status`, `check` 가 `WARN workflowDirs auto: 찾은 폴더 0`
44
+ - `WARN workflowDirs auto: 찾은 폴더 0` 은 Claude Code 워크플로를 이 프로젝트에서 아직 돌리지 않았으면 정상이다. 실패가 아니고 종료 코드에 영향이 없다
45
+ - 이 WARN 을 끄려면 `"sources": { "workflowDirs": [] }`. 빈 목록은 journal 을 읽지 않는다. 진행 중 에이전트 행과 에이전트 라벨의 스토리 시작 시각도 사라진다
46
+ - 나중에 워크플로를 쓰면 `"auto"` 로 되돌린다
47
+ - 스토리 시작 시각은 상한 없이 모든 루트에서, 진행 중 에이전트는 `journalMaxSessions`, `journalMaxAgeH`, `agentStaleMin` 안에서 찾는다
48
+
49
+ ## 스토리 판정
50
+
51
+ | 쓰는 곳 | 규칙(기본) | 설정으로 바꿈 |
52
+ |---|---|---|
53
+ | 커밋 제목 | 설정 id 를 긴 것부터 보아, 제목이 id 로 시작하고 뒤가 `:`, `(`, 공백이거나 소문자 한 자 뒤 `:`, `(`, 공백 | `commitRegex` 의 그룹 `id` 값이 설정 id 와 같을 때 |
54
+ | 스토리 시작 시각(에이전트 라벨) | 라벨을 `-` 로 나눈 토큰을 왼쪽부터 보아 id 와 정확히 같은 첫 토큰 | 없음 |
55
+ | 진행 중 스토리(에이전트 라벨) | 토큰을 왼쪽부터 보아 처음 맞는 토큰에서 멈춤. 토큰이 id 로 시작하고 바로 뒤가 끝이거나 숫자가 아니면 맞음. 같은 토큰에 맞는 id 가 둘 이상이면 긴 id | `agentLabelPattern` 의 첫 일치 값이 설정 id 와 같을 때 |
56
+ | 에이전트 행 숨김 | 진행 중 스토리로 잡힌 라벨만 숨김 | `agentLabelPattern` 이 있으면 일치가 있는 라벨은 스토리가 아니어도 숨김 |
57
+
58
+ - 예: 스토리 `A1`, `A2` 의 커밋 제목 `A1: 화면`, `A2(1/2): 설정`, `A2b: 보충` 은 각각 A1, A2, A2
59
+ - `stories` 가 비고 `story` 로 더한 것도 없으면 판정을 끈다
60
+ - id 는 정규식으로 만들 때 escape 한다(`A.1` 같은 id 도 안전)
61
+ - 제약
62
+ - id 에 `-` 가 들어 있으면 토큰 판정이 안 된다. `check` 가 WARN. id 를 바꾸거나 `agentLabelPattern` 을 쓴다
63
+ - 글자로 끝나는 id 는 넓게 잡힌다. id `auth` 는 토큰 `author` 에 맞는다(뒤 글자가 숫자가 아님). 이런 id 를 쓰면 `agentLabelPattern` 을 권한다
64
+ - `commitRegex`, `agentLabelPattern` 은 컴파일 검사를 거친다. 실패, `commitRegex` 의 `(?<id>` 없음, `agentLabelPattern` 의 캡처 그룹 있음은 FAIL
65
+
66
+ `commitRegex` 예(제목 `feat(A3): ...`):
67
+
68
+ ```json
69
+ { "commitRegex": "^\\w+\\((?<id>A\\d+)\\):" }
70
+ ```
71
+
72
+ `agentLabelPattern` 예(라벨 `impl-A12-r1` 의 `A12`):
73
+
74
+ ```json
75
+ { "agentLabelPattern": "A\\d+" }
76
+ ```
77
+
78
+ ## 예
79
+
80
+ ```json
81
+ {
82
+ "schema": 1,
83
+ "title": "예시 앱 진척도",
84
+ "shortName": "example-app",
85
+ "port": 30000,
86
+ "refreshSec": 30,
87
+ "stages": "auto",
88
+ "stories": [
89
+ { "id": "A1", "name": "기본 화면" },
90
+ { "id": "A2", "name": "설정 읽기" }
91
+ ],
92
+ "sources": { "events": "auto", "git": true, "workflowDirs": "auto" },
93
+ "text": { "plannedPrefix": "예정" }
94
+ }
95
+ ```
96
+
97
+ ## 포트와 주소
98
+
99
+ - 바인드: 127.0.0.1 을 포트 P 에. `EADDRINUSE` 면 P+1(최대 +99, strict 면 종료 1). 추가 주소(`hosts`, `--host`)는 같은 포트에
100
+ - 포트 0(OS 선택)은 `--port`, `port` 모두 받지 않는다(1024~65535). 포트를 고르는 법
101
+
102
+ | 경우 | 할 일 |
103
+ |---|---|
104
+ | 보통 | `--port` 를 빼고 `start`. `port`(기본 30000)부터 빈 포트를 찾아 쓰고 출력 URL 에 실제 포트가 나온다 |
105
+ | 정해진 포트 범위를 피해야 함(시험, 다른 서버) | OS 가 고른 빈 포트를 먼저 얻어 `--port` 로 넘긴다(아래 명령) |
106
+ | 늘 같은 포트여야 함(방화벽 규칙) | `port` 를 정하고 `portStrict: true` |
107
+
108
+ ```
109
+ node -e "const s=require('net').createServer().listen(0,'127.0.0.1',()=>{console.log(s.address().port);s.close()})"
110
+ ```
111
+
112
+ - 출력이 1024 미만이면 다시 실행한다
113
+ - 얻은 포트를 그 사이 다른 프로세스가 잡으면 `start` 는 다음 빈 포트로 비켜 가고 알림 줄을 낸다. URL 은 `start` 출력의 것을 쓴다
114
+ - 추가 주소가 인터페이스에 없을 때: 이번 `--host` 면 종료 1, `hosts` 에서 온 주소면 그 주소만 경고하고 127.0.0.1 로 계속
115
+ - 재사용: 상태 파일 PID 와 신원 응답 PID 가 같으면 이 프로젝트 서버. `--host` 가 실행 중 주소와 다르거나, strict 인데 실행 중 포트가 요청 포트와 다르면 종료 1("stop 먼저")
@@ -0,0 +1,75 @@
1
+ # flow.json
2
+
3
+ workflow 탭의 실행 흐름. 흐름(lane)마다 SVG 그림 하나. 좌표 키는 없다. 배치는 항상 자동이다.
4
+
5
+ ## 스키마
6
+
7
+ ```json
8
+ {
9
+ "note": "코드를 읽고 모은 두 흐름(읽은 파일은 inventory.json). 근거 줄 번호는 저장소 루트 기준.",
10
+ "lanes": [
11
+ {
12
+ "id": "build",
13
+ "title": "빌드: npm run build 에서 dist 까지",
14
+ "color": "#6a1b9a",
15
+ "note": "npm run build 로 시작(package.json:7). 실패하면 그 단계에서 멈추고 종료 1. 근거는 scripts/build.mjs 와 CI 설정.",
16
+ "steps": [
17
+ { "id": "b1", "label": "설정 읽기", "detail": "build.config.json 을 읽고 대상 목록과 출력 폴더를 정함", "actor": "scripts/build.mjs", "refs": ["scripts/build.mjs:10-24"] },
18
+ { "id": "b2", "label": "번들", "detail": "esbuild 로 진입점마다 번들을 만들고 소스맵을 씀", "actor": "esbuild", "refs": ["scripts/build.mjs:30-58"] }
19
+ ],
20
+ "branches": [
21
+ { "from": "b1", "to": "", "when": "설정 없음: 멈춤", "note": "build.config.json 이 없으면 종료 1 (scripts/build.mjs:12)" }
22
+ ],
23
+ "externals": [
24
+ { "id": "x1", "label": "npm 레지스트리", "linkTo": "b2", "note": "의존성 설치 때만 (package-lock.json)" }
25
+ ]
26
+ }
27
+ ],
28
+ "scenes": [
29
+ { "n": 1, "sec": 1.5, "lane": "build", "focus": ["b1", "b2"], "caption": "설정을 읽고 번들을 만듦" }
30
+ ]
31
+ }
32
+ ```
33
+
34
+ | 키 | 형식 | 필수 | 뜻 |
35
+ |---|---|---|---|
36
+ | `note` | 문자열 | 아니오 | 탭 머리 설명 |
37
+ | `lanes[].id` | 문자열 | 예 | 흐름 id(겹침 FAIL) |
38
+ | `lanes[].title` | 문자열 | 예 | 흐름 제목 |
39
+ | `lanes[].color` | `#rrggbb` | 아니오 | 흐름 색. 그 밖은 FAIL, 화면은 기본 색 |
40
+ | `lanes[].note` | 문자열 | 밀도 | 흐름 설명 3문장(시작 명령, 실패 처리, 근거). 문장 끝 온점에서 줄바꿈 |
41
+ | `steps[].id` | 문자열 | 예 | 흐름 안 단계 id(겹침 FAIL) |
42
+ | `steps[].label` | 문자열 | 예 | 단계 이름. 상자에 안 들어가면 두 줄 |
43
+ | `steps[].detail` | 문자열 | 예 | 설명. 상자 안 최대 3줄 |
44
+ | `steps[].actor` | 문자열 | 예 | 행위자(파일, 도구, 사람) |
45
+ | `steps[].refs` | 문자열 배열 | 밀도 | 근거 `파일:줄`. 마우스를 올리면 보임 |
46
+ | `steps[].planned` | 참, 거짓 | 아니오 | 예정(점선 상자, "예정" 표기) |
47
+ | `steps[].alone` | 참, 거짓 | 아니오 | 앞 단계와 잇지 않음(다른 진입점) |
48
+ | `branches[]` | `{from, to, when, note?}` | 밀도 | 실패, 예외 분기. 상자 아래 빨간 표. `to` 가 빈 문자열이면 흐름 끝 |
49
+ | `externals[]` | `{id, label, linkTo, note?, planned?}` | 밀도 | 외부 구성요소. 상자 위 회색 표, `planned` 면 주황 |
50
+ | `scenes[]` | `{n, sec, lane, focus, caption}` | 아니오 | 장면 대본. `lane` 이 빈 문자열이면 전체, `focus` 는 그 흐름의 단계 id |
51
+
52
+ - 상자 id 는 `<흐름 id>-<단계 id>`. 장면과 상자를 잇는 열쇠다
53
+
54
+ ## 배치
55
+
56
+ - 한 줄에 상자 5개, 줄마다 방향을 바꾸는 지그재그. 상자 176 x 92 px
57
+ - 분기 표가 아래 줄 상자나 외부 표와 겹치면 그 줄 간격만 늘린다
58
+ - 단계 이름은 14px 굵은 글꼴 폭 추정(한글 14, 공백 5, 영문은 글자별 6~14 px)으로 상자 안에 정말 안 들어갈 때만 두 줄로 바꾼다
59
+ - 한 줄 한도: 이름 시작(상자 왼쪽 + 32)부터 상자 테두리 안쪽(176 - 2)까지. 예정 단계는 "예정" 표기 앞 4 px 까지
60
+ - 두 줄이면 설명을 한 줄(15 px) 내린다. 설명은 3줄까지 그대로 두고, 내린 설명이 3줄이면 그 상자를 15 px 늘린다(다음 줄도 그만큼 내려감)
61
+
62
+ ## check 항목
63
+
64
+ | 검사 | 결과 |
65
+ |---|---|
66
+ | 형식, 필수 키, id 겹침, 분기 `from`/`to` 와 외부 `linkTo` 의 단계, 장면 `lane`/`focus`, 색 | FAIL |
67
+ | 분기 표가 아래 줄 상자와 겹침, 외부 표와 분기 표 겹침, 이름 둘째 줄과 설명 첫 줄 겹침 | FAIL |
68
+ | 분기 표가 이웃 칸의 분기 표나 분기 세로선과 겹침, 외부 표가 이웃 칸 외부 표와 겹침 | FAIL(글을 줄임) |
69
+ | 분기 표 폭이 194 px 를 넘고 같은 줄 오른쪽 이웃 칸에 상자가 있음 | WARN |
70
+ | 한 상자 외부 표 합계 폭이 176 px 를 넘음 | WARN |
71
+ | 단계 이름이 두 줄로도 넘침 | WARN |
72
+ | 흐름 6개, 흐름당 단계 15개 초과 | WARN(크기 지침) |
73
+
74
+ - 겹침은 가로와 세로 모두 1 px 이상일 때만. 변이 닿기만 하면 겹침 아님
75
+ - 분기 표 글(`when`)과 외부 표 글(`label`)은 짧게. 길면 겹침 FAIL 이 난다. 자세한 근거는 `note`
@@ -0,0 +1,58 @@
1
+ # inventory.json
2
+
3
+ init 때 에이전트가 읽기 예산 안에서 찾은 실제 구성요소, 흐름, 외부 시스템, 읽은 파일. 밀도 하한 계산과 작은 저장소 예외의 근거다(`references/authoring.md`). 화면에는 나오지 않는다.
4
+
5
+ ## 스키마
6
+
7
+ ```json
8
+ {
9
+ "components": [
10
+ { "name": "API 서버", "path": "server/app.js" },
11
+ { "name": "웹 화면", "path": "web/src" },
12
+ { "name": "PostgreSQL", "path": "server/db.js" }
13
+ ],
14
+ "flows": [
15
+ { "name": "빌드: npm run build", "steps": 6, "evidence": "scripts/build.mjs" },
16
+ { "name": "요청 처리: GET /api/orders", "steps": 8, "evidence": "server/routes/orders.js:10-80" }
17
+ ],
18
+ "externals": [
19
+ { "name": "PostgreSQL", "evidence": "server/db.js:5" }
20
+ ],
21
+ "read": ["README.md", "package.json", "server/app.js", "web/src/App.tsx"]
22
+ }
23
+ ```
24
+
25
+ | 키 | 형식 | 필수 | 뜻 |
26
+ |---|---|---|---|
27
+ | `components` | `[{name, path}]` | 예 | 구성요소(모듈, 실행 파일, 서비스, 설정, 외부 시스템). `path` 는 저장소 안 실제 경로(파일이나 폴더). 외부 시스템은 저장소 밖이라 그것을 부르거나 설정하는 저장소 안 파일을 `path` 에 적는다 |
28
+ | `flows` | `[{name, steps, evidence}]` | 예 | 실제 실행 흐름(명령, 빌드, 배포, 요청 처리). `steps` 는 0 이상 정수, `evidence` 는 근거 파일 |
29
+ | `externals` | `[{name, evidence}]` | 예 | 외부 시스템. `evidence` 는 그것을 부르는 파일 |
30
+ | `read` | 경로 배열 | 아니오 | 실제로 연 파일(전체와 일부). 검색 결과로만 본 파일은 적지 않는다(`references/authoring.md` 의 "읽기 예산") |
31
+
32
+ - 경로는 프로젝트 루트 기준 상대 경로. `파일:줄`, `파일:줄-줄` 이면 줄 번호를 떼고 존재를 본다
33
+ - 모르는 키는 무시한다
34
+
35
+ ## check 항목
36
+
37
+ | 검사 | 결과 |
38
+ |---|---|
39
+ | JSON 형식, `components`, `flows`, `externals` 가 배열 | FAIL |
40
+ | `path`, `evidence` 가 저장소에 없음(외부 시스템 구성요소 포함) | FAIL `inventory.json <json 경로> 경로 없음: <값>` |
41
+ | `flows[].steps` 가 0 이상 정수가 아님 | FAIL |
42
+ | `read` 가 배열이 아님 | FAIL |
43
+
44
+ ## 하한 계산
45
+
46
+ | 하한 | 식 |
47
+ |---|---|
48
+ | 구성도 영역 | min(5, `components` 수) |
49
+ | 구성도 상자 | min(20, `components` 수) |
50
+ | 구성도 연결 | min(15, `arch.json` 에 그린 상자(`nodes`) 수 - 1). `components` 수나 낮춘 상자 하한이 아님 |
51
+ | workflow 흐름 | min(2, `flows` 수) |
52
+ | workflow 흐름당 단계 | 단계가 많은 흐름부터 `steps` 가 많은 `flows` 와 짝지어 min(7, 그 `steps`) |
53
+
54
+ ## 작성 지침
55
+
56
+ - 실제로 있는 것만 적는다. 하한을 낮추려고 빼지 않는다. 큰 저장소는 하한을 넘어야 하고, 넘지 못하면 이 파일이 그 이유(실제 구성요소 수)를 보여야 한다
57
+ - 폴더 하나를 대표 파일만 읽었으면 그 폴더를 구성요소 하나로 적는다
58
+ - 구성도 상자와 workflow 단계는 이 목록에서 나와야 한다. 목록에 없는 것을 그리지 않는다
@@ -0,0 +1,74 @@
1
+ # items.json 과 진척도 탭
2
+
3
+ 진척도 탭의 수동 기록. `item`, `note`, `stage`, `story` 명령만 쓴다. 손으로 고치지 않는다.
4
+
5
+ ## 스키마
6
+
7
+ ```json
8
+ {
9
+ "notes": { "stage:build": { "note": "근거 커밋 1a2b3c4", "issue": "" }, "A1": { "note": "시험 12건 통과" } },
10
+ "items": [
11
+ { "key": "docs-1", "t": "2026-10-29T03:00:00Z", "s": "2026-10-29T01:00:00Z", "status": "done", "text": "설치 문서 갱신", "note": "README.md 3절", "issue": "", "hash": "5d6e7f8" }
12
+ ],
13
+ "storyCommits": { "A2": { "hash": "9f8e7d6", "t": "2026-10-29T02:00:00Z", "name": "설정 읽기" } },
14
+ "storyStates": { "A3": { "status": "doing", "t": "2026-10-29T02:30:00Z" } },
15
+ "stageEvents": [ { "t": "2026-10-29T00:00:00Z", "stage": "build", "status": "started" } ]
16
+ }
17
+ ```
18
+
19
+ | 키 | 형식 | 쓰는 명령 |
20
+ |---|---|---|
21
+ | `notes` | `{<key>: {note?, issue?}}`. key 는 `stage:<단계 id>` 또는 스토리 id | `note` |
22
+ | `items` | `[{key, t, s?, status, text, note?, issue?, hash?}]`. `status` 는 `todo`, `doing`, `done`. `s` 는 시작 시각(doing 으로 기록한 시각), `hash` 는 커밋 해시 | `item` |
23
+ | `storyCommits` | `{<스토리 id>: {hash, t, name?}}`. 문자열 해시만 있어도 읽음. 진척도 표 commit Hash 칸의 유일한 수동 출처 | `story --commit` |
24
+ | `storyStates` | `{<스토리 id>: {status, t, name?}}`. `status` 는 `todo`, `doing`, `done` | `story --status` |
25
+ | `stageEvents` | `[{t, stage, status, label?}]`. `status` 는 `started`, `done`, `skipped`, `failed`, `stopped` | `stage` |
26
+
27
+ - 모르는 키는 그대로 둔다
28
+
29
+ ## 명령
30
+
31
+ | 명령 | 동작 |
32
+ |---|---|
33
+ | `item --key <k> --status <s> --text <t> [--note <t>] [--issue <t>] [--at <ISO>] [--commit <hash>]` | 같은 key 는 대체하고 시작 시각 `s` 는 유지. 새 key 는 끝에 추가. `s` 는 `doing` 으로 기록할 때만 정함(처음부터 `done`, `todo` 면 없음). `--at` 이 있으면 지금 대신 그 시각을 `t` 로(`doing` 이면 `s` 도). `--commit` 은 7~40자 16진 해시를 `hash` 에. `--commit` 이 없으면 있던 `hash` 를 유지 |
34
+ | `note --key <k> [--note <t>] [--issue <t>]` | 그 key 의 칸만 대체. 빈 값(`--issue ""`)은 그 칸을 지움 |
35
+ | `stage --id <id> --status <s> [--label <t>]` | `stageEvents` 에 한 줄 추가. 설정에 없는 id 는 새 단계 행(이름은 `--label` 또는 id) |
36
+ | `story --id <id> --status <s> [--name <t>]` | `storyStates` 의 그 id 를 대체 |
37
+ | `story --id <id> --commit <hash> [--name <t>]` | `storyCommits` 의 그 id 를 대체. 해시는 4~40자 16진. 제목에 id 가 없는 커밋을 스토리 완료로 셈 |
38
+
39
+ - 쓰기는 잠금(`items.json.lock`) 안에서 다시 읽고 바꾼 칸만 고친 뒤 임시 파일에 써서 rename 한다. 성공한 쓰기는 모두 남는다. 경쟁이 매우 심하면 일부 쓰기가 최대 5초 기다린 뒤 잠금 메시지와 함께 종료 1 할 수 있다(다시 실행)
40
+ - 잠금이 5초 안에 풀리지 않으면 종료 1. 출력에 잠금 경로, pid, createdAt 이 나온다. 그 프로세스가 끝났는데 남아 있으면 잠금 파일을 지운 뒤 다시 실행
41
+ - 기록된 pid 가 죽었고 createdAt 이 5초보다 오래된 잠금은 스스로 정리한다. 정리는 정리 잠금(`items.json.lock.break`)을 쥔 프로세스 하나만 하고, 처음 본 잠금과 pid, 무작위 값, createdAt 이 같을 때만 지운다
42
+
43
+ ## 시각
44
+
45
+ - 새로 쓰는 시각(`t`, `s`)은 Z 붙은 UTC ISO 8601 `YYYY-MM-DDTHH:MM:SSZ`
46
+ - `s` 는 항목이 `doing` 이 된 시각. 이미 있으면 바꾸지 않는다. `s` 가 없는 항목(처음부터 `done` 이나 `todo`)은 소요시간이 "-"
47
+ - 옛 판이 쓴 자료에는 `s` 와 `t` 가 같은 `done` 항목이 있다(처음부터 `done` 으로 기록한 항목). 이 줄은 소요시간이 "0:00" 으로 보인다. "-" 로 보이게 하려면 그 항목의 `s` 를 지운다
48
+ - `item --at <ISO>`: 날짜, 시각, 시간대(`Z` 또는 `+09:00`)가 모두 있어야 한다(예 `2026-10-20T12:34:56+09:00`, 초는 선택). 그 밖은 종료 1. 지난 커밋은 `git log --format=%cI` 의 커밋 시각을 그대로 넘긴다. 저장은 위 UTC Z 형식
49
+ - `item --commit <hash>`: 7~40자 16진 해시. 그 밖은 종료 1. 손으로 쓴 `hash` 가 이 꼴이 아니면 `check` 가 FAIL. 지난 커밋은 `git log --format=%h` 의 해시를 함께 넘긴다(`--at <%cI> --commit <%h>`)
50
+ - Z 없는 19자 옛 형식(`YYYY-MM-DDTHH:MM:SS`)은 서버를 실행한 환경의 현지 시각으로 읽는다(옛 진척도 서버와 같음). 옛 자료에는 UTC 값을 Z 없이 쓴 줄도 섞여 있다. 그 줄도 현지로 읽어 옛 화면과 같은 시각을 낸다(시차만큼 이르게 보임)
51
+ - Z 나 시차(`+09:00`)가 붙은 시각은 그 값 그대로 읽는다
52
+ - 손으로 적을 때는 Z 를 붙여 UTC 로 적거나 시차를 붙인다. Z 없는 19자는 서버 시간대가 바뀌면 다른 시각이 된다
53
+ - 화면 표시는 서버를 실행한 환경의 시간대
54
+
55
+ ## 진척도 탭 판정
56
+
57
+ | 행 | 상태 |
58
+ |---|---|
59
+ | 단계 | events 출처와 `stageEvents` 를 시각 순으로 합침. 단계마다 마지막 기록이 상태(완료 뒤 다시 `started` 면 진행 중). `started` 진행 중, `done`, `skipped` 완료, `failed`, `stopped` 진행 중(비고 "멈춤"), 기록 없음 예정 |
60
+ | 스토리 | 커밋(제목 판정 또는 `storyCommits`) 있으면 완료, 없으면 `storyStates`, 없으면 진행 중 에이전트가 있으면 진행 중, 그 밖 예정 |
61
+ | 에이전트 | 워크플로 journal 에서 끝나지 않은 에이전트. 스토리로 잡힌 라벨은 숨김(`references/config.md`) |
62
+ | 기타 | `items` 그대로. 소요시간은 `s` 가 있을 때만(`doing` 은 지금까지, `done` 은 `t` 까지) |
63
+
64
+ - 진척률: 완료 스토리 수 / 스토리 수(`스토리 n/m 완료 (p%)` 와 막대). `storyStates` 의 `done` 도 완료
65
+ - 스토리가 없으면 단계 행과 기타 행으로 센다(`항목 n/m 완료 (p%)` 와 막대). 에이전트 행은 세지 않는다
66
+ - 표에 그릴 행(단계, 스토리, 기타 항목)이 하나도 없을 때만 "단계와 스토리 기록 없음" 안내 한 줄. 기록이 없는 까닭(events.jsonl 없음, stories 비어 있음)과 기록 명령(`stage`, `story`, `item`)을 적는다
67
+ - 소요시간이 모두 "-" 이면 그 열 머리글을 꺾지 않는다(좁은 칸에서 한 글자씩 꺾이지 않게)
68
+ - 스토리와 단계가 모두 없으면 표 전체에서 한글 낱말 가운데를 꺾지 않는다(공백에서만 줄 바꿈). 내용 칸이 좁아져도 "작성" 이 "작/성" 으로 나뉘지 않게
69
+ - 표 열: 순번, 시각, 소요시간, 상태, 내용, commit Hash, 문제점, 비고. 문제점은 `issue`, 비고는 `note`
70
+ - commit Hash 칸: 스토리 행은 완료 커밋(커밋 제목 판정 또는 `storyCommits`), 기타 행은 `hash`(`item --commit`)의 앞 7자리. 단계, 에이전트 행은 늘 빈칸. `notes` 에는 해시 칸이 없다
71
+
72
+ ## events.jsonl(ultra-chain 실행 기록)
73
+
74
+ 한 줄에 하나: `{"t":"2026-10-28T00:00:00Z","stage":"research","status":"started"}`. `status` 는 `stage` 명령과 같은 값. 깨진 줄은 건너뛴다.
@@ -0,0 +1,74 @@
1
+ # req-spec.json
2
+
3
+ 구현요건 탭의 요구와 기능 명세. 에이전트가 init 절차에서 쓴다. 근거 AC 와 담당 스토리는 `reqs.json`(`references/reqs.md`).
4
+
5
+ ## 스키마
6
+
7
+ ```json
8
+ {
9
+ "excluded": "범위에서 뺀 것: 외부 결제 연동(별도 저장소). 근거 파일:줄은 저장소 루트 기준.",
10
+ "users": [
11
+ {
12
+ "text": "설정 파일 하나로 서버 포트와 제목을 바꿈",
13
+ "source": "README.md:12-18",
14
+ "specs": [
15
+ { "text": "config.json 의 port 를 읽어 바인드", "acs": ["AC-3"], "note": "src/config.js:40-52" },
16
+ { "text": "형식이 틀린 칸은 기본값과 경고", "acs": ["AC-4"], "state": "part", "note": "경고만 있고 기본값 대체 없음(src/config.js:60)" }
17
+ ]
18
+ }
19
+ ],
20
+ "stories": { "A1": ["기본 화면", "목록과 상세 화면, 빈 상태 안내"], "A2": "설정 읽기" }
21
+ }
22
+ ```
23
+
24
+ | 키 | 형식 | 필수 | 뜻 |
25
+ |---|---|---|---|
26
+ | `users` | 배열 | 예 | 요구 묶음. 요구 원문 단위 |
27
+ | `users[].text` | 문자열 | 예 | 요구 원문(문서나 이슈의 문장을 줄여 씀) |
28
+ | `users[].source` | 문자열 | 밀도 | 원문 근거 `파일:줄` |
29
+ | `users[].specs` | 배열 | 예 | 기능 명세 |
30
+ | `specs[].text` | 문자열 | 예 | 기능 명세 한 줄 |
31
+ | `specs[].acs` | 문자열 배열 | 아니오 | 근거 AC id. `reqs.json` 의 `acs[].id` 에 있어야 함 |
32
+ | `specs[].state` | `done`, `part`, `doing`, `todo`, `unv`, `excl`, `none` | 아니오 | 따로 판정한 결과. 스토리 판정보다 앞섬 |
33
+ | `specs[].note` | 문자열 | `state` 가 있으면 밀도 | 판정 근거(`파일:줄`, 시험 이름) |
34
+ | `stories` | `{id: [이름, 내용]}` 또는 `{id: 이름}` | 아니오 | 아래 스토리 표. id 는 `config.json` 의 `stories` 와 맞춤 |
35
+ | `excluded` | 문자열 | 아니오 | 범위에서 뺀 것. 판정 규칙 문구 뒤에 붙음 |
36
+
37
+ - 모르는 키는 무시한다
38
+ - `state` 값의 화면 이름: `done` 완료, `part` 일부, `doing` 진행 중, `todo` 미구현, `unv` 미검증, `excl` 대상 제외, `none` 명세 없음
39
+
40
+ ## 판정 순서
41
+
42
+ | 순서 | 조건 | 결과 |
43
+ |---|---|---|
44
+ | 1 | 명세에 `state` 있음 | 그 `state` |
45
+ | 2 | `acs` 가 있고 대응 스토리가 있음 | 담당 스토리가 모두 완료면 완료, 일부면 일부, 남은 스토리에 진행 중이 있으면 진행 중, 완료가 없으면 미구현 |
46
+ | 3 | `acs` 가 있고 대응 스토리가 없음(스토리 없는 프로젝트 포함) | 미검증 |
47
+ | 4 | `acs` 가 비고 `state` 없음 | 명세 없음 |
48
+
49
+ - 묶음 상태: 대상 제외를 뺀 명세로 아래 차례의 첫 줄. 모두 대상 제외면 대상 제외
50
+ 1. 모두 완료면 완료
51
+ 2. 진행 중이 있으면 진행 중
52
+ 3. 완료나 일부가 있으면 일부
53
+ 4. 모두 명세 없음이면 명세 없음
54
+ 5. 모두 미검증이나 명세 없음이면 미검증
55
+ 6. 그 밖 미구현
56
+ - 완료율: 완료 / (명세 수 - 대상 제외)
57
+ - 판정 규칙 문구는 `config.json` 의 `text.reqRule`. 기본 문구 그대로이고 담당 스토리 칸이 없으면(스토리가 없고 AC 에 담당 스토리도 없음) `state` 판정 문구가 대신 보인다
58
+ - 담당 스토리 칸이 없으면(스토리 없는 프로젝트) "구현 여부" 머리글을 꺾지 않는다
59
+
60
+ ## 작성 지침
61
+
62
+ - 요구는 원문 단위로 묶는다. 출처가 README 의 기능 목록이면 항목 하나가 요구 하나
63
+ - 명세마다 AC 를 1개 이상 단다. 스토리가 있으면 그 AC 가 `reqs.json` 에서 담당 스토리 1개 이상을 가리키게 한다
64
+ - 스토리가 없는 프로젝트: 명세마다 `state` 와 `note` 를 쓴다. 아래 표로 고른다
65
+
66
+ | 확인한 것 | `state` | `note` |
67
+ |---|---|---|
68
+ | 명세를 구현한 코드를 읽어 `파일:줄` 로 확인 | `done` | 코드 `파일:줄`. 이름이 맞는 시험이 있으면 시험 이름을 덧붙임 |
69
+ | 코드에 일부만 있음 | `part` | 있는 부분 `파일:줄` 과 빠진 것 |
70
+ | 시험 이름만 봄(코드를 읽지 않음), 또는 아무것도 확인 못 함 | `unv` | 본 시험 이름이나 "근거 못 찾음" |
71
+
72
+ - init 은 시험을 실행하지 않는다. 시험 이름은 보조 근거다. 시험 이름만으로 `done` 을 쓰지 않는다
73
+ - `note` 에는 근거 `파일:줄` 이나 시험 이름을 쓴다. 추측을 쓰지 않는다
74
+ - `check` 검사: 형식, `state` 값, `acs` 가 `reqs.json` 에 있음. `reqs.json` 이 없는데 `acs` 가 있으면 WARN(미검증으로 판정)
@@ -0,0 +1,30 @@
1
+ # reqs.json
2
+
3
+ 구현요건 탭의 AC 목록과 AC 별 담당 스토리. `req-spec.json`(`references/req-spec.md`)의 `specs[].acs` 가 이 id 를 가리킨다.
4
+
5
+ ## 스키마
6
+
7
+ ```json
8
+ {
9
+ "acs": [
10
+ { "id": "AC-3", "title": "config.json 의 port 로 바인드", "stories": ["A2"], "tests": "test/config.test.js port" },
11
+ { "id": "AC-4", "title": "형식 오류는 기본값과 경고", "stories": ["A2", "A3"] }
12
+ ]
13
+ }
14
+ ```
15
+
16
+ | 키 | 형식 | 필수 | 뜻 |
17
+ |---|---|---|---|
18
+ | `acs` | 배열 | 예 | AC 목록 |
19
+ | `acs[].id` | 문자열 | 예 | AC id. 겹치면 FAIL |
20
+ | `acs[].stories` | 문자열 배열 | 아니오 | 담당 스토리 id. 비거나 없으면 그 AC 의 명세는 미검증 |
21
+ | `acs[].title`, `acs[].tests` | 문자열 | 아니오 | 사람이 읽는 설명. 화면에는 id 만 |
22
+
23
+ - 모르는 키(`generated`, `gaps`, `auditSummary` 등)는 허용하고 무시한다
24
+ - `stories` 의 id 는 `config.json` 의 `stories`, `story` 명령으로 더한 id, `req-spec.json` 의 `stories` 키 가운데 하나여야 한다. 없으면 `FAIL reqs.json acs[i].stories 스토리 없음: <id>`
25
+
26
+ ## 작성 지침
27
+
28
+ - AC 는 확인할 수 있는 문장으로 쓴다(입력, 기대 결과). 시험이 있으면 `tests` 에 이름
29
+ - 스토리가 있는 프로젝트: AC 마다 담당 스토리를 1개 이상. 커밋 제목이 스토리 id 로 시작하면 완료 판정이 자동이다
30
+ - 스토리가 없는 프로젝트: `stories` 를 비우고 `req-spec.json` 의 명세마다 `state` 와 `note` 로 판정한다