From b0894f000dc262028665380f902a354d7c034ea9 Mon Sep 17 00:00:00 2001 From: "sungkuk.chae-at-471112812288" <76669236+cskwork@users.noreply.github.com> Date: Wed, 23 Sep 2026 09:41:27 +0900 Subject: [PATCH 1/4] feat: area pages record how a figure is calculated (v0.16.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - templates/area.md gains an optional Numbers (ํ†ต๊ณ„ ์‚ฐ์ •) section between Business rules and How it works: one line per on-screen count, rate, score or chart figure, numbered N1... with the same permanence rules as a business rule (P-number) - Extended only where omitting N-numbers would leave figures unprotected: templates/spec.md's Business rules touched section, ship's retrospective area-candidate instruction, templates/harvest.md's Area candidates format, and AGENTS.md rule 4's knowledge-filing table - README.md / README.ko.md: one mention each in the product-area paragraph and the memory-tree comment - kb.sh untouched: the Rules count stays P-only, no correctness gap ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- AGENTS.md | 1 + README.ko.md | 4 ++-- README.md | 4 ++-- VERSION | 2 +- log/changelog-v0.16.0.md | 51 ++++++++++++++++++++++++++++++++++++++++ skills/5-ship/SKILL.md | 4 +++- templates/area.md | 7 ++++++ templates/harvest.md | 6 +++-- templates/spec.md | 1 + 9 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 log/changelog-v0.16.0.md diff --git a/AGENTS.md b/AGENTS.md index 428ba86..8409a28 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -148,6 +148,7 @@ archives the feature to `.sdlc/archive//`. | What | Where | Written by | |---|---|---| | A product's business rule (์ •์ฑ…) โ€” "a submitted answer cannot be edited" | `memory/areas/.md` Business rules, numbered P1โ€ฆ (templates/area.md) | close merge, shipped only | + | How an on-screen count, rate, score or chart figure is calculated | the same page's Numbers, numbered N1โ€ฆ (templates/area.md) | close merge, shipped only | | What changed in an area, when | the area page's History, one line per feature | close merge, shipped only | | A fact that holds for one area only | the area page's How it works | close merge | | A term, or a system fact/constraint that spans areas | `memory/DOMAIN.md` (100 lines max) | close merge | diff --git a/README.ko.md b/README.ko.md index 5b52b32..5758fa6 100644 --- a/README.ko.md +++ b/README.ko.md @@ -145,7 +145,7 @@ agent APPROVED: intent of claims-status (.sdlc/work/claims-status/intent.md) โ”‚ โ”œโ”€โ”€ POLICY.md # ์‚ฌ๋žŒ์ด ์„ ์–ธํ•œ ํ•˜๋“œ ๋ฃฐ, ์—์ด์ „ํŠธ๋Š” ์ „์‚ฌ๋งŒ โ”‚ โ”œโ”€โ”€ INDEX.md # ๊ตํ›ˆ ํฌ์ธํ„ฐ, 50์ค„ ์ดํ•˜ โ”‚ โ”œโ”€โ”€ DOMAIN.md # ์—ฌ๋Ÿฌ ์ œํ’ˆ ์˜์—ญ์— ๊ฑธ์นœ ์šฉ์–ด ยท ์‚ฌ์‹ค ยท ์ œ์•ฝ -โ”‚ โ”œโ”€โ”€ areas/.md # ์ œํ’ˆ ์˜์—ญ(์›น์•ฑ์€ ๋ฉ”๋‰ด)๋งˆ๋‹ค ํ•œ ์žฅ: ์—…๋ฌด ์ •์ฑ… P1โ€ฆ ยท ๋™์ž‘ ยท ๋ณ€๊ฒฝ ์ด๋ ฅ +โ”‚ โ”œโ”€โ”€ areas/.md # ์ œํ’ˆ ์˜์—ญ(์›น์•ฑ์€ ๋ฉ”๋‰ด)๋งˆ๋‹ค ํ•œ ์žฅ: ์—…๋ฌด ์ •์ฑ… P1โ€ฆ ยท ํ†ต๊ณ„ ์‚ฐ์ • N1โ€ฆ(์„ ํƒ) ยท ๋™์ž‘ ยท ๋ณ€๊ฒฝ ์ด๋ ฅ โ”‚ โ””โ”€โ”€ lessons/-.md โ”œโ”€โ”€ work// # ์—ด๋ฆฐ ํ”ผ์ฒ˜๋งŒ โ”‚ โ”œโ”€โ”€ origin.md # ์š”์ฒญ ๋‹น์‹œ์˜ ํ‹ฐ์ผ“ ยท ๊ธฐํš์„œ ์Šค๋ƒ…์ƒท โ€” intent ๊ฒŒ์ดํŠธ๊ฐ€ ๊ฒฐํ•ฉ @@ -169,7 +169,7 @@ agent APPROVED: intent of claims-status (.sdlc/work/claims-status/intent.md) **๊ธฐ๋ก์„ ์–ด๋””์— ๋‘˜์ง€๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •ํ•ฉ๋‹ˆ๋‹ค.** ๊ธฐ๋ณธ๊ฐ’์€ ํ”„๋กœ์ ํŠธ ์ž‘์—… ์‚ฌ๋ณธ ์•ˆ์ด๊ณ , `init.sh . --area ~/knowledge`๋ฅผ ์“ฐ๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ํด๋” ์•„๋ž˜ `/<๋‹จ์œ„์ด๋ฆ„>-<์ฒดํฌ์•„์›ƒ ์‹๋ณ„์ž>/`์— ์ €์žฅํ•˜๊ณ  `.sdlc`๋ฅผ ๊ทธ๊ณณ์œผ๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ฒดํฌ์•„์›ƒ๋งˆ๋‹ค ์ €์žฅ์†Œ๊ฐ€ ํ•˜๋‚˜์”ฉ์ด๋ฏ€๋กœ ์›ŒํฌํŠธ๋ฆฌ ๋‘ ๊ฐœ๊ฐ€ ์Šน์ธ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š” ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค. ์˜์—ญ์ด ํ”„๋กœ์ ํŠธ ์•ˆ์— ์žˆ๊ฑฐ๋‚˜ ํ”„๋กœ์ ํŠธ๊ฐ€ ์˜์—ญ ์•ˆ์— ์žˆ์„ ๋•Œ, ๋‹ค๋ฅธ ์ฒดํฌ์•„์›ƒ์ด ์ด๋ฏธ ๊ทธ ์ €์žฅ์†Œ๋ฅผ ์†Œ์œ ํ•  ๋•Œ, ์‹ค์ œ `.sdlc` ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ด๋ฏธ ์žˆ์„ ๋•Œ(์ž๋™์œผ๋กœ ์˜ฎ๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค), ๋งํฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์„ ๋•Œ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์“ฐ์ง€ ์•Š๊ณ  ๋ถ„๋ช…ํžˆ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ์ด ์†Œ์œ ๊ถŒ์€ init ์‹œ์ ๋ฟ ์•„๋‹ˆ๋ผ ์‹คํ–‰ ์‹œ์ ์—๋„ ๋‹ค์‹œ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. `/PROJECT`์— ์ ํžŒ ์ฒดํฌ์•„์›ƒ์ด ์ง€๊ธˆ ์‹คํ–‰ ์ค‘์ธ ์ฒดํฌ์•„์›ƒ๊ณผ ๋‹ค๋ฅด๋ฉด `check-gate.sh`, `approve.sh`, `close.sh`, `status.sh`, `tools/auto.sh`, `tools/verify.sh`, `tools/handoff.sh`๊ฐ€ ํŒ์ •์„ ๋‚ด๋ฆฌ๊ฑฐ๋‚˜ ์ƒํƒœ๋ฅผ ์“ฐ๊ธฐ ์ „์— ๊ฑฐ๋ถ€ํ•˜๋ฏ€๋กœ, ์‹ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•œ ์ž‘์—… ์‚ฌ๋ณธ(`cp -R`, rsync, ๋Œ€๋ถ€๋ถ„์˜ ๋ฐฑ์—… ๋ณต์›)์ด ๋‹ค๋ฅธ ์ฒดํฌ์•„์›ƒ์˜ ๊ฒŒ์ดํŠธ๋ฅผ ์—ด๊ฑฐ๋‚˜ ๊ทธ ํ”ผ์ฒ˜๋ฅผ ๋‹ซ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฝ๊ธฐ๋Š” ์ด ์ œ์•ฝ์„ ๋ฐ›์ง€ ์•Š์•„ `tools/kb.sh show|search|list`๋Š” ๊ทธ๋Œ€๋กœ ์“ธ ์ˆ˜ ์žˆ๊ณ , ์†Œ์œ ๊ถŒ์„ ์ž๋™์œผ๋กœ ์˜ฎ๊ธฐ๊ฑฐ๋‚˜ ๋‹ค์‹œ ๋ฌถ๋Š” ์ผ์€ ์—†์Šต๋‹ˆ๋‹ค. ์–ด๋А ์ชฝ์„ ๊ณ ๋ฅด๋“  **์ €์žฅ์†Œ ๋ฐฑ์—…์€ ์‚ฌ์šฉ์ž์˜ ๋ชซ์ž…๋‹ˆ๋‹ค.** git์ด ๋” ์ด์ƒ ๋Œ€์‹ ํ•ด ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -**์ง€์‹์€ ์ œํ’ˆ ์˜์—ญ๋ณ„๋กœ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.** ์›น์•ฑ์ด๋ฉด ์ œํ’ˆ ์˜์—ญ์€ ๋ฉ”๋‰ด ํ•˜๋‚˜์ด๊ณ  ๋ฉ”๋‰ด ๊ฒฝ๋กœ(`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`)๋กœ ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ๋ชจ๋“ˆ, API, ๋ฐฐ์น˜ ์ž‘์—…, CLI ๋ช…๋ น์ž…๋‹ˆ๋‹ค. ์ œํ’ˆ ์˜์—ญ๋งˆ๋‹ค `memory/areas/.md` ํ•œ ์žฅ์ด ์žˆ๊ณ , ์—ฌ๊ธฐ์— ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹ˆ์–ด๋„ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์žฅ์œผ๋กœ ์“ด ์—…๋ฌด ์ •์ฑ…(P1, P2โ€ฆ), ๋™์ž‘ ๋ฐฉ์‹, ๊ทธ ์˜์—ญ์„ ๋ฐ”๊พผ ํ”ผ์ฒ˜๋ณ„ ์ด๋ ฅ ํ•œ ์ค„์ด ๋‹ด๊น๋‹ˆ๋‹ค. ํ”ผ์ฒ˜์˜ `summary.md`๋Š” `Area:` ์ค„๋กœ ์ œํ’ˆ ์˜์—ญ์„ ์ ๊ณ , spec์€ ์–ด๋–ค ์ •์ฑ…์„ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜ ๋ฐ”๊พธ๋Š”์ง€ ๋ฐํžˆ๊ณ , Side effects ๊ฒ€์ฆ์ž๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์•„์•ผ ํ•  ์ •์ฑ…์ด ๊ทธ๋Œ€๋กœ์ธ์ง€ ๋‹ค์‹œ ํ™•์ธํ•˜๋ฉฐ, close ๋ณ‘ํ•ฉ์ด ์ƒˆ๋กœ ์ƒ๊ธฐ๊ฑฐ๋‚˜ ๋ฐ”๋€ ์ •์ฑ…์„ ํŽ˜์ด์ง€์— ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค. `tools/kb.sh show "ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ"`(๋˜๋Š” ํŽ˜์ด์ง€ ํŒŒ์ผ ์ด๋ฆ„)์€ ๊ทธ ํŽ˜์ด์ง€์™€ ๊ทธ ์ œํ’ˆ ์˜์—ญ์„ ๋ฐ”๊พผ ํ”ผ์ฒ˜๋ฅผ ํ•จ๊ป˜ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. +**์ง€์‹์€ ์ œํ’ˆ ์˜์—ญ๋ณ„๋กœ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.** ์›น์•ฑ์ด๋ฉด ์ œํ’ˆ ์˜์—ญ์€ ๋ฉ”๋‰ด ํ•˜๋‚˜์ด๊ณ  ๋ฉ”๋‰ด ๊ฒฝ๋กœ(`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`)๋กœ ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ๋ชจ๋“ˆ, API, ๋ฐฐ์น˜ ์ž‘์—…, CLI ๋ช…๋ น์ž…๋‹ˆ๋‹ค. ์ œํ’ˆ ์˜์—ญ๋งˆ๋‹ค `memory/areas/.md` ํ•œ ์žฅ์ด ์žˆ๊ณ , ์—ฌ๊ธฐ์— ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹ˆ์–ด๋„ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์žฅ์œผ๋กœ ์“ด ์—…๋ฌด ์ •์ฑ…(P1, P2โ€ฆ), ๋™์ž‘ ๋ฐฉ์‹, ๊ทธ ์˜์—ญ์„ ๋ฐ”๊พผ ํ”ผ์ฒ˜๋ณ„ ์ด๋ ฅ ํ•œ ์ค„์ด ๋‹ด๊น๋‹ˆ๋‹ค. ๊ฑด์ˆ˜ยท๋น„์œจยท์ ์ˆ˜ยท์ฐจํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์˜์—ญ์€ ํ†ต๊ณ„ ์‚ฐ์ •(N1, N2โ€ฆ) ์„น์…˜๋„ ๊ฐ€์ง€๋ฉฐ, ํ™”๋ฉด์˜ ์ˆ˜์น˜ ํ•˜๋‚˜๋งˆ๋‹ค ๋ฌด์—‡์„ ์„ธ๋Š”์ง€์™€ ์ถœ์ฒ˜๋ฅผ ํ•œ ์ค„๋กœ ๋‚จ๊น๋‹ˆ๋‹ค โ€” ์—…๋ฌด ์ •์ฑ…๊ณผ ๊ฐ™์€ ์˜์†์„ฑยท์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ํ”ผ์ฒ˜์˜ `summary.md`๋Š” `Area:` ์ค„๋กœ ์ œํ’ˆ ์˜์—ญ์„ ์ ๊ณ , spec์€ ์–ด๋–ค ์ •์ฑ…์ด๋‚˜ ์ˆ˜์น˜๋ฅผ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜ ๋ฐ”๊พธ๋Š”์ง€ ๋ฐํžˆ๊ณ , Side effects ๊ฒ€์ฆ์ž๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์•„์•ผ ํ•  ๊ฒƒ์ด ๊ทธ๋Œ€๋กœ์ธ์ง€ ๋‹ค์‹œ ํ™•์ธํ•˜๋ฉฐ, close ๋ณ‘ํ•ฉ์ด ์ƒˆ๋กœ ์ƒ๊ธฐ๊ฑฐ๋‚˜ ๋ฐ”๋€ ์ •์ฑ…ยท์ˆ˜์น˜๋ฅผ ํŽ˜์ด์ง€์— ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค. `tools/kb.sh show "ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ"`(๋˜๋Š” ํŽ˜์ด์ง€ ํŒŒ์ผ ์ด๋ฆ„)์€ ๊ทธ ํŽ˜์ด์ง€์™€ ๊ทธ ์ œํ’ˆ ์˜์—ญ์„ ๋ฐ”๊พผ ํ”ผ์ฒ˜๋ฅผ ํ•จ๊ป˜ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. **๊ธฐ๋ก์„ ๋‹ค์‹œ ์ฝ๋Š” ๋„๊ตฌ๋Š” `tools/kb.sh`์ž…๋‹ˆ๋‹ค.** `index`๋Š” ๋ชฉ์ฐจ ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ญ๋‹ˆ๋‹ค(`init.sh`์™€ `close.sh`๊ฐ€ ์ž๋™์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค). ํŽ˜์ด์ง€๋Š” ์ •์ฑ… ์ˆ˜ยท๋งˆ์ง€๋ง‰ ๋ณ€๊ฒฝยทํ”ผ์ฒ˜๋ฅผ ๋‹ด์€ ์ œํ’ˆ ์˜์—ญ ํ‘œ, ์ƒํƒœยท๋‚ ์งœยท์ œํ’ˆ ์˜์—ญยทํƒœ๊ทธ๋ฅผ ๋‹ด์€ ๊ฐœ์š” ํ‘œ(์ตœ์‹ ์ˆœ), ์•„์ง close๊ฐ€ ๋ณ‘ํ•ฉํ•˜์ง€ ์•Š์€ harvest ๋ชฉ๋ก, ํ”ผ์ฒ˜๋ณ„ ์ ˆ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค. `show `๋Š” ํ”ผ์ฒ˜ ํ•˜๋‚˜๋ฅผ ์š”์•ฝ๋ณธ์œผ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๋ชฉํ‘œ, `summary.md`(์ œํ’ˆ ์˜์—ญยท๋ฌด์—‡์ด ๋ฌธ์ œ์˜€๋‚˜ยทBefore โ†’ Afterยทํ™•์ธ ๋ฐฉ๋ฒ•์„ ๋‹ด๋Š”, ๊ณ„์† ๊ฐฑ์‹ ํ•˜๋„๋ก ๋งŒ๋“  ์œ ์ผํ•œ ๊ธฐ๋ก), ๋ฐฐํฌ ์ƒํƒœ, ๋ณ‘ํ•ฉ๋˜์ง€ ์•Š์€ harvest ํ›„๋ณด, ๊ตํ›ˆ ์ œ๋ชฉ์ด ๋จผ์ € ๋‚˜์˜ค๊ณ  ํŒŒ์ผ ๊ฒฝ๋กœ๋Š” ๋งˆ์ง€๋ง‰์ž…๋‹ˆ๋‹ค. `search "<๋ฌธ์ž์—ด>"`์€ ์—ด๋ฆฐ ํ”ผ์ฒ˜์™€ ๋‹ซํžŒ ํ”ผ์ฒ˜, ์ง€์† ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ถœ๋ ฅ๋Ÿ‰์„ ์ œํ•œํ•œ ๋ฌธ์ž์—ด ๊ฒ€์ƒ‰์„ ํ•˜๊ณ , `harvest [--stale <์ผ์ˆ˜>]`๋Š” harvest.md๊ฐ€ ์•„์ง memory/์— ๋“ค์–ด๊ฐ€์ง€ ์•Š์€ ์—ด๋ฆฐ ํ”ผ์ฒ˜๋ฅผ ์œ ํœด ๊ธฐ๊ฐ„๊ณผ ํ•จ๊ป˜ ๋‚˜์—ดํ•ฉ๋‹ˆ๋‹ค(์œ ํœด ์ƒํƒœ๊ฐ€ ์˜ค๋ž˜๋œ ํ”ผ์ฒ˜๋Š” close ์—†์ด ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค โ€” AGENTS.md ๊ทœ์น™ 4). `--area <ํด๋”>`๋ฅผ ๋ถ™์ด๋ฉด ๊ทธ ํด๋” ์•ˆ์˜ ๋ชจ๋“  ์ €์žฅ์†Œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๊ฐ™์€ ์ผ์„ ํ•˜๋ฉฐ, ์›๋ž˜ ์ฒดํฌ์•„์›ƒ์ด ์‚ฌ๋ผ์ง„ ํ”ผ์ฒ˜๋„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €์žฅ์†Œ config.md์— `index_style: obsidian`์„ ์ ์œผ๋ฉด Obsidian ๋ณผํŠธ์šฉ frontmatter์™€ ์ธ๋ผ์ธ `#ํƒœ๊ทธ`๋ฅผ ๋ง๋ถ™์ž…๋‹ˆ๋‹ค. ์ƒ์„ฑ ์‹œ๊ฐ์€ ์ ˆ๋Œ€ ์“ฐ์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‚ด์šฉ์ด ๊ฐ™์œผ๋ฉด diff๋„ ์ƒ๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ข…๋ฃŒ ์ฝ”๋“œ๋Š” `0` ์ฐพ์Œ, `1` ์—†์Œ, `2` ์‚ฌ์šฉ๋ฒ• ์˜ค๋ฅ˜ ๋˜๋Š” ๊ฑฐ๋ถ€์ž…๋‹ˆ๋‹ค. diff --git a/README.md b/README.md index f025bd4..2d56793 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ Per feature, inside the **target project**: โ”‚ โ”œโ”€โ”€ POLICY.md # human-declared hard rules; agents transcribe only โ”‚ โ”œโ”€โ”€ INDEX.md # โ‰ค50 lines of lesson pointers โ”‚ โ”œโ”€โ”€ DOMAIN.md # terms ยท facts and constraints that span areas -โ”‚ โ”œโ”€โ”€ areas/.md # one per product area (web app: one menu): business rules P1โ€ฆ ยท how it works ยท history +โ”‚ โ”œโ”€โ”€ areas/.md # one per product area (web app: one menu): business rules P1โ€ฆ ยท numbers N1โ€ฆ (optional) ยท how it works ยท history โ”‚ โ””โ”€โ”€ lessons/-.md โ”œโ”€โ”€ work// # OPEN features only โ”‚ โ”œโ”€โ”€ origin.md # the ticket / ๊ธฐํš์„œ as requested โ€” bound by the intent gate @@ -169,7 +169,7 @@ Per feature, inside the **target project**: **Where the records live is your choice.** By default they sit in the project's working copy. `init.sh . --area ~/knowledge` puts them in a folder you choose instead โ€” `/-/`, with `.sdlc` linked to it, one store per checkout so two worktrees never share approvals. The area is refused if it sits inside the project (or the project inside it), if another checkout already owns that store, if a real `.sdlc` directory is already there (nothing is ever relocated for you), or if the link cannot be made. That ownership is re-checked at RUNTIME, not only at init: `check-gate.sh`, `approve.sh`, `close.sh`, `status.sh`, `tools/auto.sh`, `tools/verify.sh` and `tools/handoff.sh` refuse before any verdict or write when `/PROJECT` names a different checkout, so a copied working copy (`cp -R`, rsync and most restores keep the symlink) can neither open another checkout's gate nor close its features. Reading is never bound that way: `tools/kb.sh show|search|list` still works, and nothing is ever re-bound or moved for you. Whichever you choose, **the store is yours to back up** โ€” git no longer does it for you. -**Knowledge is filed by product area.** For a web app an area is one menu, named by its menu path (`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`); for other software a module, API, job, or CLI command. Each area has one page, `memory/areas/.md`: its business rules numbered P1, P2โ€ฆ in sentences a non-developer can read, how it works, and a history line per feature that changed it. A feature's `summary.md` names its area on an `Area:` line, the spec states which rules it keeps or changes, the Side effects verifier re-checks the rules it should not have touched, and the close merge files new or changed rules on the page. `tools/kb.sh show "ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ"` (or the page's file name) prints the page with the features that changed it. +**Knowledge is filed by product area.** For a web app an area is one menu, named by its menu path (`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`); for other software a module, API, job, or CLI command. Each area has one page, `memory/areas/.md`: its business rules numbered P1, P2โ€ฆ in sentences a non-developer can read, how it works, and a history line per feature that changed it. An area that shows counts, rates, scores or charts also gets a Numbers section, N1, N2โ€ฆ, one line per figure recording what it counts and its source โ€” the same permanence and treatment as a business rule. A feature's `summary.md` names its area on an `Area:` line, the spec states which rules or figures it keeps or changes, the Side effects verifier re-checks the ones it should not have touched, and the close merge files new or changed rules and figures on the page. `tools/kb.sh show "ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ"` (or the page's file name) prints the page with the features that changed it. **Reading the records back** is `tools/kb.sh`: `index` regenerates the contents page (`init.sh` and `close.sh` do it for you) โ€” the product areas with their rule count, last change and features, an overview table by state, date, area and tags, newest first, the harvests no close has merged yet, then one section per feature; `show ` prints one feature as a digest โ€” goal, its `summary.md` (area, what was wrong, before โ†’ after, how to check, the one record meant to be kept current), delivery, unmerged harvest candidates, lesson titles, then the paths; `search ""` does a bounded literal search over open and closed features plus durable memory; `harvest [--stale ]` lists open features whose harvest.md is not in memory yet, with idle time (a stale one may be merged without closing โ€” AGENTS.md rule 4); and `--area ` does any of these across every store in that folder โ€” including features whose checkout no longer exists. `index_style: obsidian` in the store's config.md adds frontmatter and inline `#tags` for a vault; no timestamp is ever written, so an unchanged page produces no diff. Exit codes: `0` found, `1` nothing found, `2` usage error or refusal. diff --git a/VERSION b/VERSION index 86dd09a..cfe6c00 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.15.0 +v0.16.0 diff --git a/log/changelog-v0.16.0.md b/log/changelog-v0.16.0.md new file mode 100644 index 0000000..f0223f1 --- /dev/null +++ b/log/changelog-v0.16.0.md @@ -0,0 +1,51 @@ +# v0.16.0 โ€” area pages record how a figure is calculated + +v0.15.0 gave a product area one home for its business rules (P-numbers). A +menu that shows counts, rates, scores or charts had nowhere to say what a +number on screen actually means โ€” "what is counted, out of what, real-time +or batch" lived in someone's head or nowhere. This release adds an optional +Numbers section to the area page, numbered N1โ€ฆ with the same permanence and +filing rules as a business rule. Gates, approvals, the `--json` schema, and +`kb.sh`'s rule count are unchanged. + +## Changes + +- **`templates/area.md`** gains an optional **Numbers (ํ†ต๊ณ„ ์‚ฐ์ •)** section + between Business rules and How it works: one line per on-screen figure, + named as the screen labels it, recording what it counts, out of what, + whether it is real-time or batch (job, refresh, data-as-of), its source, + and who set it. Delete the section for an area with no figures. N-numbers + follow the P-number rules: permanent, a changed figure is edited in place, + a retired one stays struck through. +- **The loop treats a figure like a business rule** wherever omitting it + would leave it unprotected: + - `templates/spec.md`'s "Business rules touched" section gains a sibling + line for numbers touched (kept/changed/new), so the Side effects + verifier re-checks a figure it did not set out to change, the same way + it already re-checks a P-number. + - Ship's retrospective (`skills/5-ship/SKILL.md`) writes a figure a + feature sets, changes, or retires as an area candidate, same as a + business rule. + - `templates/harvest.md`'s Area candidates format gains the `N` + line shape the close merge numbers, next to the existing `P` one. + - AGENTS.md rule 4's "what goes where" table gains a row: a figure's + calculation method files to the area page's Numbers, written by the + close merge on a shipped close only โ€” same as a business rule. +- **README.md / README.ko.md**: the "Knowledge is filed by product area" + paragraph and the memory-tree comment now mention the optional Numbers + section. + +## Compatibility + +An area page with no Numbers section is unaffected: the section is +optional and `kb.sh`'s Rules column stays a P-number count only (a store +with only P-numbers renders identically to before). No script parses the +`N:` line; filing it is an instruction to the agent, exactly like a +`P:` line. + +## Validation + +- `bash gates/selftest.sh` โ†’ `SELFTEST PASS` (unchanged; the smoke test + does not exercise the Numbers section, and this change does not touch + the scripts it does cover โ€” gate mechanics, lazymode, close proof, + product-area filing by menu path). diff --git a/skills/5-ship/SKILL.md b/skills/5-ship/SKILL.md index 0fb0661..f036324 100644 --- a/skills/5-ship/SKILL.md +++ b/skills/5-ship/SKILL.md @@ -69,7 +69,9 @@ AGENTS.md rule 4). **Every business rule this feature set, changed, or retired is an area candidate** โ€” the rule in one testable sentence, its source (the origin, the spec R-item or compact intent O-item), the P-number it changes or retires โ€” plus one -history line per area it changed. Then finish the feature's `summary.md`: +history line per area it changed. **A figure the area page shows a Numbers +section for is treated the same way**: the N-number it sets, changes, or +retires, named on screen, with what it counts and its source. Then finish the feature's `summary.md`: `Status` says only what delivery.md confirms (a pushed review branch is not a deployment), Before โ†’ After and How to check match what was actually built and proven, Remember holds the one thing worth knowing next time. diff --git a/templates/area.md b/templates/area.md index a03db05..2f7e3f3 100644 --- a/templates/area.md +++ b/templates/area.md @@ -22,6 +22,13 @@ - ~~P3: ~~ โ€” retired YYYY-MM-DD by : Not POLICY.md โ€” that file holds the human's rules for agents. --> +## Numbers (ํ†ต๊ณ„ ์‚ฐ์ •) + + ## How it works + Rules, figures, and history merge only when the feature closes shipped; + a stale merge leaves them here (rule 4). The merge numbers a new rule + or figure. --> ## Domain candidates - P1: kept ยท P3: changed โ†’ R2 ยท P4: retired โ†’ R5 ยท new rule โ†’ R6 +- N1: kept ยท N2: changed โ†’ R2 ยท new figure โ†’ R6 ## What stays untouched - U1: ; checked by From 4ceb1871bf824ca8912ae8d3cadd8361c6566429 Mon Sep 17 00:00:00 2001 From: "sungkuk.chae-at-471112812288" <76669236+cskwork@users.noreply.github.com> Date: Wed, 23 Sep 2026 12:56:51 +0900 Subject: [PATCH 2/4] feat: area pages named by menu path, laid out reader first (v0.16.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - File name = menu path: the Menu line with each " > " written " - " and any of / \ : * ? " < > | replaced with "-" (๊ต์‚ฌ > ํ•™์ƒ > ํ•™๊ธ‰ ๋ถ„์„ โ†’ memory/areas/๊ต์‚ฌ - ํ•™์ƒ - ํ•™๊ธ‰ ๋ถ„์„.md). The ASCII kebab-case instruction is gone; AGENTS.md rule 4 and ship's retrospective tell the close merge the rule when it creates a page - tools/kb.sh finds a page by file name, by Menu, or by the file name a Menu gives (kb_area_file); still refuses /, \ and a leading . as a file lookup; contents-page links percent-encode space % ( ) [ ] # < > (kb_area_href) so they open in GitHub and Obsidian; becomes a section label so show prints the plain part first, evidence last; an unfilled "- P1: <...>" template line is not counted or printed - templates/area.md is reader first: plain rules, numbers, how it works and history on top; Where and one "P1 โ€” source ยท set by ยท [verified]" evidence line per rule/figure inside a
block at the bottom; a retired rule's reason lives on its evidence line. Headings unchanged - harvest.md, ship SKILL, AGENTS.md table: sources go to the evidence line - selftest covers a Hangul menu-named page with spaces (lookup by Menu and file name, percent-encoded link, rule count ignores evidence/retired lines, path lookup refused) - changelog v0.16.0 extended with a compatibility note: ASCII-named pages keep working; how to rename ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- AGENTS.md | 16 ++++++--- README.ko.md | 4 +-- README.md | 4 +-- gates/selftest.sh | 15 ++++++++ init.sh | 2 +- log/changelog-v0.16.0.md | 74 +++++++++++++++++++++++++++++++++++----- skills/5-ship/SKILL.md | 17 +++++---- templates/area.md | 68 +++++++++++++++++++++++------------- templates/harvest.md | 8 +++-- tools/kb.sh | 57 +++++++++++++++++++++++-------- 10 files changed, 200 insertions(+), 65 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8409a28..ae98475 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -147,8 +147,9 @@ archives the feature to `.sdlc/archive//`. | What | Where | Written by | |---|---|---| - | A product's business rule (์ •์ฑ…) โ€” "a submitted answer cannot be edited" | `memory/areas/.md` Business rules, numbered P1โ€ฆ (templates/area.md) | close merge, shipped only | + | A product's business rule (์ •์ฑ…) โ€” "a submitted answer cannot be edited" | `memory/areas/.md` Business rules, numbered P1โ€ฆ, one plain sentence each (templates/area.md) | close merge, shipped only | | How an on-screen count, rate, score or chart figure is calculated | the same page's Numbers, numbered N1โ€ฆ (templates/area.md) | close merge, shipped only | + | Where a rule or figure came from, and the code behind the area | the same page's evidence block at the bottom (`
`): `P1 โ€” source ยท set by ยท [verified]`, the Where line | close merge | | What changed in an area, when | the area page's History, one line per feature | close merge, shipped only | | A fact that holds for one area only | the area page's How it works | close merge | | A term, or a system fact/constraint that spans areas | `memory/DOMAIN.md` (100 lines max) | close merge | @@ -160,7 +161,12 @@ archives the feature to `.sdlc/archive//`. named by its menu path (`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`); otherwise a module, API, job, or CLI command โ€” not the `--area` knowledge folder of rule 7. summary.md's `Area:` line and the page's `Menu:` line use the same words, - which is how `kb.sh` links them. DOMAIN over its limit: move + which is how `kb.sh` links them. The page's file name is that Menu with + each ` > ` written ` - ` and any of `/ \ : * ? " < > |` replaced with `-` + (`๊ต์‚ฌ > ํ•™์ƒ > ํ•™๊ธ‰ ๋ถ„์„` โ†’ `memory/areas/๊ต์‚ฌ - ํ•™์ƒ - ํ•™๊ธ‰ ๋ถ„์„.md`). + An area page reads reader first: rules, figures, how it works and history + in plain language on top; every source, verification, and code identifier + in the evidence block at the bottom. DOMAIN over its limit: move area-specific facts to their area page. INDEX over its limit: merge near-duplicates, drop superseded entries, replace promoted ones (skills/6-maintain). @@ -168,8 +174,10 @@ archives the feature to `.sdlc/archive//`. stages and researchers append candidates โ€” one line each โ€” to `.sdlc/work//harvest.md` (templates/harvest.md). At close, merge every candidate into its row above โ€” creating an area page from the - template when none exists, numbering new rules, adding the feature's - History line to each area it changed โ€” then delete harvest.md. Business + template when none exists (file named by its menu path, as above), + numbering new rules, putting each rule's or figure's source on its + evidence line, adding the feature's History line to each area it + changed โ€” then delete harvest.md. Business rules and History describe what the product DOES, so they merge only when the feature closes `shipped`: any other close drops them (summary.md keeps the story), and a stale merge leaves them in harvest.md for that close; diff --git a/README.ko.md b/README.ko.md index 5758fa6..3bad008 100644 --- a/README.ko.md +++ b/README.ko.md @@ -145,7 +145,7 @@ agent APPROVED: intent of claims-status (.sdlc/work/claims-status/intent.md) โ”‚ โ”œโ”€โ”€ POLICY.md # ์‚ฌ๋žŒ์ด ์„ ์–ธํ•œ ํ•˜๋“œ ๋ฃฐ, ์—์ด์ „ํŠธ๋Š” ์ „์‚ฌ๋งŒ โ”‚ โ”œโ”€โ”€ INDEX.md # ๊ตํ›ˆ ํฌ์ธํ„ฐ, 50์ค„ ์ดํ•˜ โ”‚ โ”œโ”€โ”€ DOMAIN.md # ์—ฌ๋Ÿฌ ์ œํ’ˆ ์˜์—ญ์— ๊ฑธ์นœ ์šฉ์–ด ยท ์‚ฌ์‹ค ยท ์ œ์•ฝ -โ”‚ โ”œโ”€โ”€ areas/.md # ์ œํ’ˆ ์˜์—ญ(์›น์•ฑ์€ ๋ฉ”๋‰ด)๋งˆ๋‹ค ํ•œ ์žฅ: ์—…๋ฌด ์ •์ฑ… P1โ€ฆ ยท ํ†ต๊ณ„ ์‚ฐ์ • N1โ€ฆ(์„ ํƒ) ยท ๋™์ž‘ ยท ๋ณ€๊ฒฝ ์ด๋ ฅ +โ”‚ โ”œโ”€โ”€ areas/<๋ฉ”๋‰ด ๊ฒฝ๋กœ>.md # ์ œํ’ˆ ์˜์—ญ(์›น์•ฑ์€ ๋ฉ”๋‰ด)๋งˆ๋‹ค ํ•œ ์žฅ, ์˜ˆ: "ํ•™์Šต - ํ‰๊ฐ€ - ์ œ์ถœ.md": ์—…๋ฌด ์ •์ฑ… P1โ€ฆ ยท ํ†ต๊ณ„ ์‚ฐ์ • N1โ€ฆ(์„ ํƒ) ยท ๋™์ž‘ ยท ๋ณ€๊ฒฝ ์ด๋ ฅ ยท ๊ทผ๊ฑฐ(์ ‘ํž˜) โ”‚ โ””โ”€โ”€ lessons/-.md โ”œโ”€โ”€ work// # ์—ด๋ฆฐ ํ”ผ์ฒ˜๋งŒ โ”‚ โ”œโ”€โ”€ origin.md # ์š”์ฒญ ๋‹น์‹œ์˜ ํ‹ฐ์ผ“ ยท ๊ธฐํš์„œ ์Šค๋ƒ…์ƒท โ€” intent ๊ฒŒ์ดํŠธ๊ฐ€ ๊ฒฐํ•ฉ @@ -169,7 +169,7 @@ agent APPROVED: intent of claims-status (.sdlc/work/claims-status/intent.md) **๊ธฐ๋ก์„ ์–ด๋””์— ๋‘˜์ง€๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ •ํ•ฉ๋‹ˆ๋‹ค.** ๊ธฐ๋ณธ๊ฐ’์€ ํ”„๋กœ์ ํŠธ ์ž‘์—… ์‚ฌ๋ณธ ์•ˆ์ด๊ณ , `init.sh . --area ~/knowledge`๋ฅผ ์“ฐ๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๊ณ ๋ฅธ ํด๋” ์•„๋ž˜ `/<๋‹จ์œ„์ด๋ฆ„>-<์ฒดํฌ์•„์›ƒ ์‹๋ณ„์ž>/`์— ์ €์žฅํ•˜๊ณ  `.sdlc`๋ฅผ ๊ทธ๊ณณ์œผ๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ฒดํฌ์•„์›ƒ๋งˆ๋‹ค ์ €์žฅ์†Œ๊ฐ€ ํ•˜๋‚˜์”ฉ์ด๋ฏ€๋กœ ์›ŒํฌํŠธ๋ฆฌ ๋‘ ๊ฐœ๊ฐ€ ์Šน์ธ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•˜๋Š” ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค. ์˜์—ญ์ด ํ”„๋กœ์ ํŠธ ์•ˆ์— ์žˆ๊ฑฐ๋‚˜ ํ”„๋กœ์ ํŠธ๊ฐ€ ์˜์—ญ ์•ˆ์— ์žˆ์„ ๋•Œ, ๋‹ค๋ฅธ ์ฒดํฌ์•„์›ƒ์ด ์ด๋ฏธ ๊ทธ ์ €์žฅ์†Œ๋ฅผ ์†Œ์œ ํ•  ๋•Œ, ์‹ค์ œ `.sdlc` ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์ด๋ฏธ ์žˆ์„ ๋•Œ(์ž๋™์œผ๋กœ ์˜ฎ๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค), ๋งํฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์„ ๋•Œ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์“ฐ์ง€ ์•Š๊ณ  ๋ถ„๋ช…ํžˆ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค. ์ด ์†Œ์œ ๊ถŒ์€ init ์‹œ์ ๋ฟ ์•„๋‹ˆ๋ผ ์‹คํ–‰ ์‹œ์ ์—๋„ ๋‹ค์‹œ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. `/PROJECT`์— ์ ํžŒ ์ฒดํฌ์•„์›ƒ์ด ์ง€๊ธˆ ์‹คํ–‰ ์ค‘์ธ ์ฒดํฌ์•„์›ƒ๊ณผ ๋‹ค๋ฅด๋ฉด `check-gate.sh`, `approve.sh`, `close.sh`, `status.sh`, `tools/auto.sh`, `tools/verify.sh`, `tools/handoff.sh`๊ฐ€ ํŒ์ •์„ ๋‚ด๋ฆฌ๊ฑฐ๋‚˜ ์ƒํƒœ๋ฅผ ์“ฐ๊ธฐ ์ „์— ๊ฑฐ๋ถ€ํ•˜๋ฏ€๋กœ, ์‹ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•œ ์ž‘์—… ์‚ฌ๋ณธ(`cp -R`, rsync, ๋Œ€๋ถ€๋ถ„์˜ ๋ฐฑ์—… ๋ณต์›)์ด ๋‹ค๋ฅธ ์ฒดํฌ์•„์›ƒ์˜ ๊ฒŒ์ดํŠธ๋ฅผ ์—ด๊ฑฐ๋‚˜ ๊ทธ ํ”ผ์ฒ˜๋ฅผ ๋‹ซ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฝ๊ธฐ๋Š” ์ด ์ œ์•ฝ์„ ๋ฐ›์ง€ ์•Š์•„ `tools/kb.sh show|search|list`๋Š” ๊ทธ๋Œ€๋กœ ์“ธ ์ˆ˜ ์žˆ๊ณ , ์†Œ์œ ๊ถŒ์„ ์ž๋™์œผ๋กœ ์˜ฎ๊ธฐ๊ฑฐ๋‚˜ ๋‹ค์‹œ ๋ฌถ๋Š” ์ผ์€ ์—†์Šต๋‹ˆ๋‹ค. ์–ด๋А ์ชฝ์„ ๊ณ ๋ฅด๋“  **์ €์žฅ์†Œ ๋ฐฑ์—…์€ ์‚ฌ์šฉ์ž์˜ ๋ชซ์ž…๋‹ˆ๋‹ค.** git์ด ๋” ์ด์ƒ ๋Œ€์‹ ํ•ด ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -**์ง€์‹์€ ์ œํ’ˆ ์˜์—ญ๋ณ„๋กœ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.** ์›น์•ฑ์ด๋ฉด ์ œํ’ˆ ์˜์—ญ์€ ๋ฉ”๋‰ด ํ•˜๋‚˜์ด๊ณ  ๋ฉ”๋‰ด ๊ฒฝ๋กœ(`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`)๋กœ ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ๋ชจ๋“ˆ, API, ๋ฐฐ์น˜ ์ž‘์—…, CLI ๋ช…๋ น์ž…๋‹ˆ๋‹ค. ์ œํ’ˆ ์˜์—ญ๋งˆ๋‹ค `memory/areas/.md` ํ•œ ์žฅ์ด ์žˆ๊ณ , ์—ฌ๊ธฐ์— ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹ˆ์–ด๋„ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์žฅ์œผ๋กœ ์“ด ์—…๋ฌด ์ •์ฑ…(P1, P2โ€ฆ), ๋™์ž‘ ๋ฐฉ์‹, ๊ทธ ์˜์—ญ์„ ๋ฐ”๊พผ ํ”ผ์ฒ˜๋ณ„ ์ด๋ ฅ ํ•œ ์ค„์ด ๋‹ด๊น๋‹ˆ๋‹ค. ๊ฑด์ˆ˜ยท๋น„์œจยท์ ์ˆ˜ยท์ฐจํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์˜์—ญ์€ ํ†ต๊ณ„ ์‚ฐ์ •(N1, N2โ€ฆ) ์„น์…˜๋„ ๊ฐ€์ง€๋ฉฐ, ํ™”๋ฉด์˜ ์ˆ˜์น˜ ํ•˜๋‚˜๋งˆ๋‹ค ๋ฌด์—‡์„ ์„ธ๋Š”์ง€์™€ ์ถœ์ฒ˜๋ฅผ ํ•œ ์ค„๋กœ ๋‚จ๊น๋‹ˆ๋‹ค โ€” ์—…๋ฌด ์ •์ฑ…๊ณผ ๊ฐ™์€ ์˜์†์„ฑยท์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ํ”ผ์ฒ˜์˜ `summary.md`๋Š” `Area:` ์ค„๋กœ ์ œํ’ˆ ์˜์—ญ์„ ์ ๊ณ , spec์€ ์–ด๋–ค ์ •์ฑ…์ด๋‚˜ ์ˆ˜์น˜๋ฅผ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜ ๋ฐ”๊พธ๋Š”์ง€ ๋ฐํžˆ๊ณ , Side effects ๊ฒ€์ฆ์ž๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์•„์•ผ ํ•  ๊ฒƒ์ด ๊ทธ๋Œ€๋กœ์ธ์ง€ ๋‹ค์‹œ ํ™•์ธํ•˜๋ฉฐ, close ๋ณ‘ํ•ฉ์ด ์ƒˆ๋กœ ์ƒ๊ธฐ๊ฑฐ๋‚˜ ๋ฐ”๋€ ์ •์ฑ…ยท์ˆ˜์น˜๋ฅผ ํŽ˜์ด์ง€์— ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค. `tools/kb.sh show "ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ"`(๋˜๋Š” ํŽ˜์ด์ง€ ํŒŒ์ผ ์ด๋ฆ„)์€ ๊ทธ ํŽ˜์ด์ง€์™€ ๊ทธ ์ œํ’ˆ ์˜์—ญ์„ ๋ฐ”๊พผ ํ”ผ์ฒ˜๋ฅผ ํ•จ๊ป˜ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. +**์ง€์‹์€ ์ œํ’ˆ ์˜์—ญ๋ณ„๋กœ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.** ์›น์•ฑ์ด๋ฉด ์ œํ’ˆ ์˜์—ญ์€ ๋ฉ”๋‰ด ํ•˜๋‚˜์ด๊ณ  ๋ฉ”๋‰ด ๊ฒฝ๋กœ(`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`)๋กœ ๋ถ€๋ฆ…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์†Œํ”„ํŠธ์›จ์–ด๋Š” ๋ชจ๋“ˆ, API, ๋ฐฐ์น˜ ์ž‘์—…, CLI ๋ช…๋ น์ž…๋‹ˆ๋‹ค. ์ œํ’ˆ ์˜์—ญ๋งˆ๋‹ค ํŽ˜์ด์ง€๊ฐ€ ํ•œ ์žฅ ์žˆ๊ณ , ํŒŒ์ผ ์ด๋ฆ„์€ ๋ฉ”๋‰ด ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค โ€” `memory/areas/ํ•™์Šต - ํ‰๊ฐ€ - ์ œ์ถœ.md`(` > `๋Š” ` - `๋กœ, `/ \ : * ? " < > |`๋Š” `-`๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค). ํŽ˜์ด์ง€๋Š” ์ฝ๋Š” ์‚ฌ๋žŒ ์šฐ์„ ์ž…๋‹ˆ๋‹ค. ์œ„์—๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹ˆ์–ด๋„ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์žฅ์œผ๋กœ ์“ด ์—…๋ฌด ์ •์ฑ…(P1, P2โ€ฆ), ๋™์ž‘ ๋ฐฉ์‹, ๊ทธ ์˜์—ญ์„ ๋ฐ”๊พผ ํ”ผ์ฒ˜๋ณ„ ์ด๋ ฅ ํ•œ ์ค„์ด ์˜ค๊ณ , ์ถœ์ฒ˜ยท๊ฒ€์ฆยท์ฝ”๋“œ ์œ„์น˜๋Š” ๋ชจ๋‘ ๋งจ ์•„๋ž˜ ์ ‘ํžŒ ๊ทผ๊ฑฐ ๋ธ”๋ก์— ๋‘ก๋‹ˆ๋‹ค. ๊ฑด์ˆ˜ยท๋น„์œจยท์ ์ˆ˜ยท์ฐจํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์˜์—ญ์€ ํ†ต๊ณ„ ์‚ฐ์ •(N1, N2โ€ฆ) ์„น์…˜๋„ ๊ฐ€์ง€๋ฉฐ, ํ™”๋ฉด์˜ ์ˆ˜์น˜ ํ•˜๋‚˜๋งˆ๋‹ค ๋ฌด์—‡์„ ์„ธ๋Š”์ง€์™€ ์ถœ์ฒ˜๋ฅผ ํ•œ ์ค„๋กœ ๋‚จ๊น๋‹ˆ๋‹ค โ€” ์—…๋ฌด ์ •์ฑ…๊ณผ ๊ฐ™์€ ์˜์†์„ฑยท์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ํ”ผ์ฒ˜์˜ `summary.md`๋Š” `Area:` ์ค„๋กœ ์ œํ’ˆ ์˜์—ญ์„ ์ ๊ณ , spec์€ ์–ด๋–ค ์ •์ฑ…์ด๋‚˜ ์ˆ˜์น˜๋ฅผ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜ ๋ฐ”๊พธ๋Š”์ง€ ๋ฐํžˆ๊ณ , Side effects ๊ฒ€์ฆ์ž๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์•„์•ผ ํ•  ๊ฒƒ์ด ๊ทธ๋Œ€๋กœ์ธ์ง€ ๋‹ค์‹œ ํ™•์ธํ•˜๋ฉฐ, close ๋ณ‘ํ•ฉ์ด ์ƒˆ๋กœ ์ƒ๊ธฐ๊ฑฐ๋‚˜ ๋ฐ”๋€ ์ •์ฑ…ยท์ˆ˜์น˜๋ฅผ ํŽ˜์ด์ง€์— ์˜ฌ๋ฆฝ๋‹ˆ๋‹ค. `tools/kb.sh show "ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ"`(๋˜๋Š” ํŽ˜์ด์ง€ ํŒŒ์ผ ์ด๋ฆ„)์€ ๊ทธ ํŽ˜์ด์ง€์™€ ๊ทธ ์ œํ’ˆ ์˜์—ญ์„ ๋ฐ”๊พผ ํ”ผ์ฒ˜๋ฅผ ํ•จ๊ป˜ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. **๊ธฐ๋ก์„ ๋‹ค์‹œ ์ฝ๋Š” ๋„๊ตฌ๋Š” `tools/kb.sh`์ž…๋‹ˆ๋‹ค.** `index`๋Š” ๋ชฉ์ฐจ ํŽ˜์ด์ง€๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ญ๋‹ˆ๋‹ค(`init.sh`์™€ `close.sh`๊ฐ€ ์ž๋™์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค). ํŽ˜์ด์ง€๋Š” ์ •์ฑ… ์ˆ˜ยท๋งˆ์ง€๋ง‰ ๋ณ€๊ฒฝยทํ”ผ์ฒ˜๋ฅผ ๋‹ด์€ ์ œํ’ˆ ์˜์—ญ ํ‘œ, ์ƒํƒœยท๋‚ ์งœยท์ œํ’ˆ ์˜์—ญยทํƒœ๊ทธ๋ฅผ ๋‹ด์€ ๊ฐœ์š” ํ‘œ(์ตœ์‹ ์ˆœ), ์•„์ง close๊ฐ€ ๋ณ‘ํ•ฉํ•˜์ง€ ์•Š์€ harvest ๋ชฉ๋ก, ํ”ผ์ฒ˜๋ณ„ ์ ˆ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค. `show `๋Š” ํ”ผ์ฒ˜ ํ•˜๋‚˜๋ฅผ ์š”์•ฝ๋ณธ์œผ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๋ชฉํ‘œ, `summary.md`(์ œํ’ˆ ์˜์—ญยท๋ฌด์—‡์ด ๋ฌธ์ œ์˜€๋‚˜ยทBefore โ†’ Afterยทํ™•์ธ ๋ฐฉ๋ฒ•์„ ๋‹ด๋Š”, ๊ณ„์† ๊ฐฑ์‹ ํ•˜๋„๋ก ๋งŒ๋“  ์œ ์ผํ•œ ๊ธฐ๋ก), ๋ฐฐํฌ ์ƒํƒœ, ๋ณ‘ํ•ฉ๋˜์ง€ ์•Š์€ harvest ํ›„๋ณด, ๊ตํ›ˆ ์ œ๋ชฉ์ด ๋จผ์ € ๋‚˜์˜ค๊ณ  ํŒŒ์ผ ๊ฒฝ๋กœ๋Š” ๋งˆ์ง€๋ง‰์ž…๋‹ˆ๋‹ค. `search "<๋ฌธ์ž์—ด>"`์€ ์—ด๋ฆฐ ํ”ผ์ฒ˜์™€ ๋‹ซํžŒ ํ”ผ์ฒ˜, ์ง€์† ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ถœ๋ ฅ๋Ÿ‰์„ ์ œํ•œํ•œ ๋ฌธ์ž์—ด ๊ฒ€์ƒ‰์„ ํ•˜๊ณ , `harvest [--stale <์ผ์ˆ˜>]`๋Š” harvest.md๊ฐ€ ์•„์ง memory/์— ๋“ค์–ด๊ฐ€์ง€ ์•Š์€ ์—ด๋ฆฐ ํ”ผ์ฒ˜๋ฅผ ์œ ํœด ๊ธฐ๊ฐ„๊ณผ ํ•จ๊ป˜ ๋‚˜์—ดํ•ฉ๋‹ˆ๋‹ค(์œ ํœด ์ƒํƒœ๊ฐ€ ์˜ค๋ž˜๋œ ํ”ผ์ฒ˜๋Š” close ์—†์ด ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค โ€” AGENTS.md ๊ทœ์น™ 4). `--area <ํด๋”>`๋ฅผ ๋ถ™์ด๋ฉด ๊ทธ ํด๋” ์•ˆ์˜ ๋ชจ๋“  ์ €์žฅ์†Œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๊ฐ™์€ ์ผ์„ ํ•˜๋ฉฐ, ์›๋ž˜ ์ฒดํฌ์•„์›ƒ์ด ์‚ฌ๋ผ์ง„ ํ”ผ์ฒ˜๋„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €์žฅ์†Œ config.md์— `index_style: obsidian`์„ ์ ์œผ๋ฉด Obsidian ๋ณผํŠธ์šฉ frontmatter์™€ ์ธ๋ผ์ธ `#ํƒœ๊ทธ`๋ฅผ ๋ง๋ถ™์ž…๋‹ˆ๋‹ค. ์ƒ์„ฑ ์‹œ๊ฐ์€ ์ ˆ๋Œ€ ์“ฐ์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‚ด์šฉ์ด ๊ฐ™์œผ๋ฉด diff๋„ ์ƒ๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ข…๋ฃŒ ์ฝ”๋“œ๋Š” `0` ์ฐพ์Œ, `1` ์—†์Œ, `2` ์‚ฌ์šฉ๋ฒ• ์˜ค๋ฅ˜ ๋˜๋Š” ๊ฑฐ๋ถ€์ž…๋‹ˆ๋‹ค. diff --git a/README.md b/README.md index 2d56793..5a41802 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ Per feature, inside the **target project**: โ”‚ โ”œโ”€โ”€ POLICY.md # human-declared hard rules; agents transcribe only โ”‚ โ”œโ”€โ”€ INDEX.md # โ‰ค50 lines of lesson pointers โ”‚ โ”œโ”€โ”€ DOMAIN.md # terms ยท facts and constraints that span areas -โ”‚ โ”œโ”€โ”€ areas/.md # one per product area (web app: one menu): business rules P1โ€ฆ ยท numbers N1โ€ฆ (optional) ยท how it works ยท history +โ”‚ โ”œโ”€โ”€ areas/.md # one per product area (web app: one menu), e.g. "ํ•™์Šต - ํ‰๊ฐ€ - ์ œ์ถœ.md": business rules P1โ€ฆ ยท numbers N1โ€ฆ (optional) ยท how it works ยท history ยท evidence (folded) โ”‚ โ””โ”€โ”€ lessons/-.md โ”œโ”€โ”€ work// # OPEN features only โ”‚ โ”œโ”€โ”€ origin.md # the ticket / ๊ธฐํš์„œ as requested โ€” bound by the intent gate @@ -169,7 +169,7 @@ Per feature, inside the **target project**: **Where the records live is your choice.** By default they sit in the project's working copy. `init.sh . --area ~/knowledge` puts them in a folder you choose instead โ€” `/-/`, with `.sdlc` linked to it, one store per checkout so two worktrees never share approvals. The area is refused if it sits inside the project (or the project inside it), if another checkout already owns that store, if a real `.sdlc` directory is already there (nothing is ever relocated for you), or if the link cannot be made. That ownership is re-checked at RUNTIME, not only at init: `check-gate.sh`, `approve.sh`, `close.sh`, `status.sh`, `tools/auto.sh`, `tools/verify.sh` and `tools/handoff.sh` refuse before any verdict or write when `/PROJECT` names a different checkout, so a copied working copy (`cp -R`, rsync and most restores keep the symlink) can neither open another checkout's gate nor close its features. Reading is never bound that way: `tools/kb.sh show|search|list` still works, and nothing is ever re-bound or moved for you. Whichever you choose, **the store is yours to back up** โ€” git no longer does it for you. -**Knowledge is filed by product area.** For a web app an area is one menu, named by its menu path (`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`); for other software a module, API, job, or CLI command. Each area has one page, `memory/areas/.md`: its business rules numbered P1, P2โ€ฆ in sentences a non-developer can read, how it works, and a history line per feature that changed it. An area that shows counts, rates, scores or charts also gets a Numbers section, N1, N2โ€ฆ, one line per figure recording what it counts and its source โ€” the same permanence and treatment as a business rule. A feature's `summary.md` names its area on an `Area:` line, the spec states which rules or figures it keeps or changes, the Side effects verifier re-checks the ones it should not have touched, and the close merge files new or changed rules and figures on the page. `tools/kb.sh show "ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ"` (or the page's file name) prints the page with the features that changed it. +**Knowledge is filed by product area.** For a web app an area is one menu, named by its menu path (`ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ`); for other software a module, API, job, or CLI command. Each area has one page, named by its menu path โ€” `memory/areas/ํ•™์Šต - ํ‰๊ฐ€ - ์ œ์ถœ.md` (each ` > ` written ` - `; any of `/ \ : * ? " < > |` becomes `-`). The page reads reader first: its business rules numbered P1, P2โ€ฆ in sentences a non-developer can read, how it works, and a history line per feature that changed it; every source, verification, and code location sits in a folded evidence block at the bottom. An area that shows counts, rates, scores or charts also gets a Numbers section, N1, N2โ€ฆ, one line per figure recording what it counts and its source โ€” the same permanence and treatment as a business rule. A feature's `summary.md` names its area on an `Area:` line, the spec states which rules or figures it keeps or changes, the Side effects verifier re-checks the ones it should not have touched, and the close merge files new or changed rules and figures on the page. `tools/kb.sh show "ํ•™์Šต > ํ‰๊ฐ€ > ์ œ์ถœ"` (or the page's file name) prints the page with the features that changed it. **Reading the records back** is `tools/kb.sh`: `index` regenerates the contents page (`init.sh` and `close.sh` do it for you) โ€” the product areas with their rule count, last change and features, an overview table by state, date, area and tags, newest first, the harvests no close has merged yet, then one section per feature; `show ` prints one feature as a digest โ€” goal, its `summary.md` (area, what was wrong, before โ†’ after, how to check, the one record meant to be kept current), delivery, unmerged harvest candidates, lesson titles, then the paths; `search ""` does a bounded literal search over open and closed features plus durable memory; `harvest [--stale ]` lists open features whose harvest.md is not in memory yet, with idle time (a stale one may be merged without closing โ€” AGENTS.md rule 4); and `--area ` does any of these across every store in that folder โ€” including features whose checkout no longer exists. `index_style: obsidian` in the store's config.md adds frontmatter and inline `#tags` for a vault; no timestamp is ever written, so an unchanged page produces no diff. Exit codes: `0` found, `1` nothing found, `2` usage error or refusal. diff --git a/gates/selftest.sh b/gates/selftest.sh index aa602c0..583db19 100755 --- a/gates/selftest.sh +++ b/gates/selftest.sh @@ -67,6 +67,21 @@ LC_ALL=en_US.UTF-8 bash "$kit/tools/kb.sh" index >/dev/null grep -qF '| [๋ช…๋‹จ > ๋‚ด๋ณด๋‚ด๊ธฐ](memory/areas/roster.md) | 1 | โ€” | f1 |' .sdlc/README.md || fail "area table wrong: $(grep '๋ช…๋‹จ' .sdlc/README.md)" out=$(bash "$kit/tools/kb.sh" show "๋ช…๋‹จ > ๋‚ด๋ณด๋‚ด๊ธฐ") case "$out" in (*"P1: ํ˜„์žฌ ํ•™๊ธฐ๋งŒ"*) ;; (*) fail "show did not print the rule: $out";; esac +# a page named by its menu path (" > " โ†’ " - "), reader first: plain rules on +# top, evidence in
at the bottom โ€” evidence lines do not count as rules +mkdir -p .sdlc/work/f3; printf -- '- Area: ๊ต์‚ฌ > ํ•™์ƒ > ํ•™๊ธ‰ ๋ถ„์„\n' > .sdlc/work/f3/summary.md +printf -- '%s\n' '# Area: ๊ต์‚ฌ > ํ•™์ƒ > ํ•™๊ธ‰ ๋ถ„์„' '- Menu: ๊ต์‚ฌ > ํ•™์ƒ > ํ•™๊ธ‰ ๋ถ„์„' '## Business rules (์ •์ฑ…)' \ + '- P1: ์ž๊ธฐ ํ•™๊ธ‰๋งŒ ๋ณธ๋‹ค' '- P2: ์ „ํ•™์ƒ์€ ๋น ์ง„๋‹ค' '- ~~P3: ์ง€๋‚œ ํ•™๊ธฐ๋„ ๋ณด์ธ๋‹ค~~' '## History' '- 2026-09-01 f3 โ€” ์ฐธ์—ฌ์œจ ์ถ”๊ฐ€' \ + '
' '๊ทผ๊ฑฐ ยท ์ฝ”๋“œ ์œ„์น˜ (๊ฐœ๋ฐœ์ž์šฉ)' '' '- Where: ClassAnalysis#get' \ + '- P1 โ€” source: ๊ธฐํš์„œ ยท set by f3' '- P3 โ€” retired 2026-09-01 by f3: ์ •์ฑ… ๋ณ€๊ฒฝ' '' '
' > ".sdlc/memory/areas/๊ต์‚ฌ - ํ•™์ƒ - ํ•™๊ธ‰ ๋ถ„์„.md" +LC_ALL=en_US.UTF-8 bash "$kit/tools/kb.sh" index >/dev/null +grep -qF '| [๊ต์‚ฌ > ํ•™์ƒ > ํ•™๊ธ‰ ๋ถ„์„](memory/areas/๊ต์‚ฌ%20-%20ํ•™์ƒ%20-%20ํ•™๊ธ‰%20๋ถ„์„.md) | 2 | 2026-09-01 | f3 |' .sdlc/README.md \ + || fail "menu-named page row wrong: $(grep '๊ต์‚ฌ' .sdlc/README.md)" +for q in "๊ต์‚ฌ > ํ•™์ƒ > ํ•™๊ธ‰ ๋ถ„์„" "๊ต์‚ฌ - ํ•™์ƒ - ํ•™๊ธ‰ ๋ถ„์„"; do + out=$(bash "$kit/tools/kb.sh" show "$q") || fail "show '$q' found no page" + case "$out" in (*"P1: ์ž๊ธฐ ํ•™๊ธ‰๋งŒ"*"๊ทผ๊ฑฐ ยท ์ฝ”๋“œ ์œ„์น˜ (๊ฐœ๋ฐœ์ž์šฉ):"*"Where: ClassAnalysis#get"*) ;; (*) fail "show '$q' not reader first: $out";; esac +done +bash "$kit/tools/kb.sh" show "../areas/roster" >/dev/null 2>&1 && fail "area lookup followed a path" echo "ok: knowledge by product area" echo "SELFTEST PASS" diff --git a/init.sh b/init.sh index ca585fb..b7cf26f 100755 --- a/init.sh +++ b/init.sh @@ -303,7 +303,7 @@ EOF [ -f .sdlc/memory/DOMAIN.md ] || cat > .sdlc/memory/DOMAIN.md <<'EOF' # Domain knowledge โ€” how THIS system works: terms and facts that span areas -# (โ‰ค100 lines; over โ†’ move area-specific facts to memory/areas/.md) +# (โ‰ค100 lines; over โ†’ move area-specific facts to memory/areas/.md) # ONE writer: the close step. Mid-loop candidates stage in the feature's # work//harvest.md and merge here at close (AGENTS.md rule 4). # Facts carry [verified: how โ€” YYYY-MM-DD]. Recency wins: a merge candidate diff --git a/log/changelog-v0.16.0.md b/log/changelog-v0.16.0.md index f0223f1..ab9f6a4 100644 --- a/log/changelog-v0.16.0.md +++ b/log/changelog-v0.16.0.md @@ -1,12 +1,16 @@ -# v0.16.0 โ€” area pages record how a figure is calculated +# v0.16.0 โ€” area pages: figures, menu-path file names, reader-first layout v0.15.0 gave a product area one home for its business rules (P-numbers). A menu that shows counts, rates, scores or charts had nowhere to say what a number on screen actually means โ€” "what is counted, out of what, real-time or batch" lived in someone's head or nowhere. This release adds an optional Numbers section to the area page, numbered N1โ€ฆ with the same permanence and -filing rules as a business rule. Gates, approvals, the `--json` schema, and -`kb.sh`'s rule count are unchanged. +filing rules as a business rule. It also names each area page by its menu +path, so the file list reads like the product's menus, and lays the page out +reader first: plain language on top for a non-developer, every source, +verification, and code location folded into an evidence block at the +bottom. Gates, approvals, and the `--json` schema are unchanged; `kb.sh`'s +rule count still counts only the live `- P:` rules. ## Changes @@ -31,12 +35,63 @@ filing rules as a business rule. Gates, approvals, the `--json` schema, and - AGENTS.md rule 4's "what goes where" table gains a row: a figure's calculation method files to the area page's Numbers, written by the close merge on a shipped close only โ€” same as a business rule. +- **An area page is named by its menu path.** The file name is the Menu + line with each ` > ` written ` - `, and any character a Windows or macOS + file name may not hold (`/ \ : * ? " < > |`) replaced with `-`: Menu + `๊ต์‚ฌ > ํ•™์ƒ > ํ•™๊ธ‰ ๋ถ„์„` โ†’ `memory/areas/๊ต์‚ฌ - ํ•™์ƒ - ํ•™๊ธ‰ ๋ถ„์„.md`. The + "ASCII kebab-case file name" instruction is gone from `templates/area.md`, + AGENTS.md rule 4, the READMEs, and `init.sh`'s DOMAIN.md header; the + close merge (AGENTS.md rule 4, `skills/5-ship`) is told the rule when it + creates a page. +- **`tools/kb.sh`** finds an area page by its file name, by its Menu line, + or by the file name a Menu gives (`kb_area_file`); a name holding `/` or + `\`, or starting with `.`, is still never looked up as a file. The + contents page's Product areas links percent-encode space `%` `(` `)` `[` + `]` `#` `<` `>` (`kb_area_href`) so a link to `๊ต์‚ฌ - ํ•™์ƒ - ํ•™๊ธ‰ ๋ถ„์„.md` + opens in GitHub and Obsidian; Hangul bytes stay as written. `kb_body` + prints a `โ€ฆ` line as a section label, so `show` prints + the page top first and the evidence block last, under + `๊ทผ๊ฑฐ ยท ์ฝ”๋“œ ์œ„์น˜ (๊ฐœ๋ฐœ์ž์šฉ):` โ€” the part the line bound cuts first. The + Rules column no longer counts an unfilled template line `- P1: <โ€ฆ>`, + and `show` drops such a line (`-