project-librarian 0.2.1 → 0.4.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.
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.classifyMigrationUnit = classifyMigrationUnit;
4
+ exports.storageToMigrationKind = storageToMigrationKind;
5
+ const taxonomyAreas = [
6
+ {
7
+ id: "research-sources",
8
+ label: "Research / Source Evidence",
9
+ storage: "sources",
10
+ targetSlug: "research-sources",
11
+ keywords: ["source", "sources", "reference", "references", "citation", "bibliography", "research", "paper", "article", "link", "출처", "참고", "자료", "근거", "링크", "리서치", "논문"],
12
+ },
13
+ {
14
+ id: "decision-record",
15
+ label: "Decision Record",
16
+ storage: "decisions",
17
+ targetSlug: "decision-records",
18
+ keywords: ["adr", "decision", "decisions", "rationale", "tradeoff", "trade-off", "alternative", "rejected", "accepted", "decided", "결정", "의사결정", "기각", "대안", "트레이드오프", "선택", "채택"],
19
+ },
20
+ {
21
+ id: "strategy",
22
+ label: "Strategy / Business Context",
23
+ storage: "canonical",
24
+ targetSlug: "strategy-context",
25
+ keywords: ["vision", "mission", "strategy", "business model", "market", "positioning", "competitive", "gtm", "pricing", "roadmap", "비전", "미션", "전략", "시장", "포지셔닝", "경쟁", "사업", "가격", "로드맵"],
26
+ },
27
+ {
28
+ id: "product-requirements",
29
+ label: "Product Requirements",
30
+ storage: "canonical",
31
+ targetSlug: "product-requirements",
32
+ keywords: ["prd", "requirement", "requirements", "feature", "features", "function", "functional", "scope", "goal", "goals", "acceptance", "use case", "기능", "기능명세", "요구사항", "요건", "범위", "목표", "수용기준", "유스케이스", "서비스기획", "기획"],
33
+ },
34
+ {
35
+ id: "user-flow",
36
+ label: "User Flow / Journey",
37
+ storage: "canonical",
38
+ targetSlug: "user-flows",
39
+ keywords: ["user flow", "flow", "journey", "scenario", "persona", "story", "navigation", "screen flow", "유저플로우", "사용자 흐름", "사용자 여정", "시나리오", "페르소나", "스토리", "화면흐름", "동선"],
40
+ },
41
+ {
42
+ id: "ux-content",
43
+ label: "UX / Content",
44
+ storage: "canonical",
45
+ targetSlug: "ux-content",
46
+ keywords: ["ux", "interaction", "wireframe", "copy", "content", "microcopy", "empty state", "error state", "accessibility", "i18n", "사용성", "인터랙션", "와이어프레임", "카피", "콘텐츠", "빈상태", "오류상태", "접근성", "문구"],
47
+ },
48
+ {
49
+ id: "design-system",
50
+ label: "Design System / UI",
51
+ storage: "canonical",
52
+ targetSlug: "design-system",
53
+ keywords: ["design", "ui", "component", "prototype", "figma", "style guide", "brand", "visual", "layout", "디자인", "컴포넌트", "프로토타입", "스타일가이드", "브랜드", "시각", "레이아웃"],
54
+ },
55
+ {
56
+ id: "data-analytics",
57
+ label: "Data / Analytics",
58
+ storage: "canonical",
59
+ targetSlug: "data-analytics",
60
+ keywords: ["data", "schema", "database", "db", "erd", "entity", "event", "metric", "analytics", "kpi", "tracking", "데이터", "스키마", "디비", "엔티티", "이벤트", "지표", "분석", "트래킹"],
61
+ },
62
+ {
63
+ id: "api-contract",
64
+ label: "API Contract",
65
+ storage: "canonical",
66
+ targetSlug: "api-contracts",
67
+ keywords: ["api", "endpoint", "request", "response", "rest", "graphql", "webhook", "sdk", "openapi", "swagger", "인증", "토큰", "요청", "응답", "엔드포인트", "웹훅", "api명세", "api 명세"],
68
+ },
69
+ {
70
+ id: "engineering-architecture",
71
+ label: "Engineering / Architecture",
72
+ storage: "canonical",
73
+ targetSlug: "engineering-architecture",
74
+ keywords: ["architecture", "system", "service", "module", "implementation", "tech stack", "dependency", "infra", "deployment", "queue", "cache", "아키텍처", "시스템", "서비스", "모듈", "구현", "기술스택", "인프라", "배포", "큐", "캐시"],
75
+ },
76
+ {
77
+ id: "security-legal",
78
+ label: "Security / Legal",
79
+ storage: "canonical",
80
+ targetSlug: "security-legal",
81
+ keywords: ["security", "privacy", "permission", "role", "auth", "authorization", "compliance", "legal", "terms", "consent", "보안", "개인정보", "권한", "역할", "인가", "인증", "준수", "법무", "약관", "동의"],
82
+ },
83
+ {
84
+ id: "policy",
85
+ label: "Policy / Governance",
86
+ storage: "canonical",
87
+ targetSlug: "policy-governance",
88
+ keywords: ["policy", "rule", "moderation", "governance", "sla", "retention", "eligibility", "refund", "정책", "규칙", "운영정책", "거버넌스", "보관", "자격", "환불"],
89
+ },
90
+ {
91
+ id: "qa",
92
+ label: "QA / Test",
93
+ storage: "canonical",
94
+ targetSlug: "qa-test-plan",
95
+ keywords: ["qa", "test", "testing", "validation", "verification", "bug", "edge case", "regression", "acceptance test", "테스트", "검증", "품질", "버그", "엣지케이스", "회귀", "테스트케이스"],
96
+ },
97
+ {
98
+ id: "release-ops",
99
+ label: "Release / Operations",
100
+ storage: "canonical",
101
+ targetSlug: "release-operations",
102
+ keywords: ["release", "launch", "operation", "runbook", "monitoring", "alert", "incident", "support", "cs", "migration", "rollout", "릴리즈", "출시", "운영", "런북", "모니터링", "알림", "장애", "고객지원", "마이그레이션"],
103
+ },
104
+ {
105
+ id: "business-ops",
106
+ label: "Business Operations",
107
+ storage: "canonical",
108
+ targetSlug: "business-operations",
109
+ keywords: ["sales", "marketing", "crm", "customer success", "finance", "billing", "invoice", "contract", "영업", "마케팅", "고객성공", "재무", "청구", "계약", "정산"],
110
+ },
111
+ {
112
+ id: "wiki-meta",
113
+ label: "Wiki Operations / Meta",
114
+ storage: "meta",
115
+ targetSlug: "wiki-operations",
116
+ keywords: ["wiki", "documentation", "document taxonomy", "canonical", "source of truth", "lint", "doctor", "위키", "문서화", "문서체계", "정본", "정보구조", "린트", "닥터"],
117
+ },
118
+ ];
119
+ function slugPart(value, maxLength = 36) {
120
+ return value.toLowerCase().replace(/[^a-z0-9가-힣ぁ-んァ-ン一-龥]+/g, "-").replace(/^-|-$/g, "").slice(0, maxLength) || "migration";
121
+ }
122
+ function legacyStem(legacyPath) {
123
+ return slugPart(legacyPath.replace(/\.(md|mdx)$/i, "").split(/[\\/]+/).pop() ?? legacyPath);
124
+ }
125
+ function fallbackStorageFromLegacyPath(legacyPath) {
126
+ if (/^meta\//.test(legacyPath))
127
+ return "meta";
128
+ if (/^decisions\//.test(legacyPath))
129
+ return "decisions";
130
+ if (/^sources\//.test(legacyPath))
131
+ return "sources";
132
+ return "canonical";
133
+ }
134
+ function keywordScore(haystack, keyword) {
135
+ const normalized = keyword.toLowerCase();
136
+ const escaped = normalized.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
137
+ if (/^[a-z0-9 -]+$/.test(normalized)) {
138
+ const matches = haystack.match(new RegExp(`\\b${escaped}\\b`, "g"));
139
+ return matches ? matches.length : 0;
140
+ }
141
+ return haystack.includes(normalized) ? 1 : 0;
142
+ }
143
+ function areaScore(area, haystack) {
144
+ return area.keywords.reduce((sum, keyword) => sum + keywordScore(haystack, keyword), 0);
145
+ }
146
+ function targetPath(storage, base, targetSlug) {
147
+ return `wiki/${storage}/${slugPart(base, 32)}-${targetSlug}.md`;
148
+ }
149
+ function classifyMigrationUnit(input) {
150
+ const haystack = [
151
+ legacyStem(input.legacyPath),
152
+ input.heading,
153
+ input.headingPath.join(" "),
154
+ input.summary,
155
+ input.content,
156
+ ].join("\n").toLowerCase();
157
+ const scored = taxonomyAreas
158
+ .map((area) => ({ area, score: areaScore(area, haystack) }))
159
+ .filter((item) => item.score > 0)
160
+ .sort((left, right) => right.score - left.score || left.area.id.localeCompare(right.area.id));
161
+ const fallbackStorage = fallbackStorageFromLegacyPath(input.legacyPath);
162
+ const best = scored[0]?.area ?? {
163
+ id: "unclassified",
164
+ label: "Needs Human Review",
165
+ storage: fallbackStorage,
166
+ targetSlug: "migration-review",
167
+ keywords: [],
168
+ };
169
+ const bestScore = scored[0]?.score ?? 0;
170
+ const secondScore = scored[1]?.score ?? 0;
171
+ const confidence = bestScore >= 3 && bestScore > secondScore ? "high" : bestScore >= 1 && bestScore >= secondScore ? "medium" : "low";
172
+ const base = legacyStem(input.legacyPath);
173
+ const reason = confidence === "low"
174
+ ? "no strong taxonomy signal; human review required"
175
+ : `matched ${best.label}${secondScore > 0 && bestScore === secondScore ? " with overlapping signals" : ""}`;
176
+ return {
177
+ area: best.id,
178
+ label: best.label,
179
+ storage: best.storage,
180
+ target: targetPath(best.storage, base, best.targetSlug),
181
+ confidence,
182
+ reason,
183
+ };
184
+ }
185
+ function storageToMigrationKind(storage) {
186
+ if (storage === "decisions")
187
+ return "decision";
188
+ if (storage === "sources")
189
+ return "source";
190
+ if (storage === "meta")
191
+ return "meta";
192
+ return "canonical";
193
+ }
package/dist/templates.js CHANGED
@@ -1,8 +1,67 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.starterFiles = exports.decisionPolicy = exports.wikiOperatingModel = exports.inboxIndexBlock = exports.glossaryIndexBlock = exports.glossary = exports.index = exports.startup = exports.metadata = exports.wikiAgentsSection = exports.cursorRule = exports.geminiSection = exports.claudeSection = exports.agentsSection = void 0;
3
+ exports.defaultStarterFilePaths = exports.starterFiles = exports.documentTaxonomy = exports.decisionPolicy = exports.wikiOperatingModel = exports.inboxIndexBlock = exports.glossaryIndexBlock = exports.glossary = exports.index = exports.startup = exports.metadata = exports.wikiAgentsSection = exports.cursorRule = exports.geminiSection = exports.claudeSection = exports.STARTUP_TLDR_MAX_CHARS = exports.startupTldrSyncLabel = exports.codeEvidenceTrustContract = exports.wikiTrustContract = void 0;
4
+ exports.extractStartupTldr = extractStartupTldr;
5
+ exports.agentsSection = agentsSection;
4
6
  const workspace_1 = require("./workspace");
5
- exports.agentsSection = `<!-- PROJECT-WIKI-FIRST:START -->
7
+ // B4 (gated on B2, which ships in the same phase): a single-sentence trust
8
+ // contract in the managed AGENTS.md block. It is the substitution mechanism that
9
+ // stops repo-wide re-verification greps; the --doctor router-truth rule (B2)
10
+ // guards against trusting a stale router.
11
+ exports.wikiTrustContract = "Wiki decision documents are authoritative for project decisions: do not re-verify them against the repository unless directly conflicting code evidence appears, since the `--doctor` router-truth rule guards against stale routers.";
12
+ // B4 analogue for code evidence: a single-sentence trust contract making the
13
+ // code-evidence tool/report outputs authoritative for code-structure questions,
14
+ // gated on the same staleness check the tools surface (`--code-status` /
15
+ // `code_status`). Mirrors wikiTrustContract scale; kept budget-conscious. The
16
+ // closing clause is the scale-conditional guidance (2026-06-12 decision, stageR1
17
+ // evidence): on small repos simple lookups measured cheaper via direct reads.
18
+ exports.codeEvidenceTrustContract = "Code-evidence tool and report outputs (`--code-impact`, `--code-report`, and the `project-librarian mcp` tools) are authoritative for code-structure questions: do not re-verify them with repo-wide greps unless `--code-status`/`code_status` reports staleness; on small repos below the measured scale threshold, prefer direct reads over these tools for simple lookups (measured cheaper at small scale).";
19
+ // B1 fallback: label for the auto-synced startup TL;DR sub-block embedded in the
20
+ // managed AGENTS.md marker section. Non-interactive `codex exec` does not run
21
+ // SessionStart hooks (measured 2026-06-10), so AGENTS.md is the only startup
22
+ // context carrier there; the sync stays TL;DR-only per token discipline.
23
+ exports.startupTldrSyncLabel = "Startup TL;DR (auto-synced for non-interactive sessions; source: wiki/startup.md)";
24
+ // Hard cap on the extracted TL;DR text embedded in AGENTS.md. The startup hook
25
+ // budget is 3500 chars for the full wiki/startup.md; the TL;DR sub-section must
26
+ // stay well under that so the managed block remains token-efficient. 2000 chars is
27
+ // a documented hard bound: it leaves headroom for frontmatter, other sections, and
28
+ // the AGENTS.md surrounding content. Per the no-fallback rule, we NEVER truncate —
29
+ // if the extracted bullets exceed this limit the sync fails loudly so the author
30
+ // knows to trim the TL;DR.
31
+ exports.STARTUP_TLDR_MAX_CHARS = 2000;
32
+ // Extract the `## TL;DR` bullet list from a startup.md body (TL;DR section ONLY —
33
+ // never Recent Decisions or Project State). Returns the `- ` bullet lines between
34
+ // the `## TL;DR` heading and the next `## ` heading. Throws loudly when the
35
+ // startup body has no `## TL;DR` section, that section has no bullets, or the
36
+ // extracted text exceeds STARTUP_TLDR_MAX_CHARS (no fallback, no silent truncation).
37
+ function extractStartupTldr(startupMarkdown) {
38
+ const match = startupMarkdown.match(/^##\s+TL;DR[^\n]*\n([\s\S]*?)(?=\n##\s|(?![\s\S]))/m);
39
+ if (!match) {
40
+ throw new Error("cannot sync startup TL;DR into AGENTS.md: wiki/startup.md has no \"## TL;DR\" section");
41
+ }
42
+ const bullets = (match[1] ?? "")
43
+ .split(/\r?\n/)
44
+ .map((line) => line.trimEnd())
45
+ .filter((line) => /^\s*-\s+\S/.test(line));
46
+ if (bullets.length === 0) {
47
+ throw new Error("cannot sync startup TL;DR into AGENTS.md: the wiki/startup.md \"## TL;DR\" section has no bullet items");
48
+ }
49
+ const result = bullets.join("\n");
50
+ if (result.length > exports.STARTUP_TLDR_MAX_CHARS) {
51
+ throw new Error(`cannot sync startup TL;DR into AGENTS.md: extracted TL;DR is ${result.length} chars, which exceeds the ${exports.STARTUP_TLDR_MAX_CHARS}-char limit; trim the ## TL;DR section in wiki/startup.md`);
52
+ }
53
+ return result;
54
+ }
55
+ // Build the managed AGENTS.md marker section. The startup TL;DR is synced in as a
56
+ // clearly labeled sub-block (B1 fallback) so non-interactive Codex sessions, which
57
+ // never run the SessionStart hook, still receive compact startup context; the
58
+ // trust contract sentence (B4) is appended to the during-conversation rules. Only
59
+ // this marker block changes; user content outside the markers is untouched, and
60
+ // because the section is built deterministically from the current startup TL;DR a
61
+ // re-run with unchanged startup yields the same section ("exists" via
62
+ // upsertMarkedSection).
63
+ function agentsSection(startupTldr) {
64
+ return `<!-- PROJECT-WIKI-FIRST:START -->
6
65
  ## Wiki-First Planning
7
66
 
8
67
  This project uses \`./wiki\` as the durable project-planning source of truth.
@@ -13,13 +72,21 @@ At the start of every session:
13
72
  2. Review \`wiki/index.md\` as the router for which files to read next.
14
73
  3. Read detailed \`wiki/canonical/\`, \`wiki/decisions/\`, \`wiki/meta/\`, and \`wiki/sources/\` files on demand only when the current question needs them.
15
74
 
75
+ ### ${exports.startupTldrSyncLabel}
76
+
77
+ ${startupTldr}
78
+
16
79
  During conversation:
17
80
 
18
81
  - Update \`./wiki\` in the same turn when project planning content is added, changed, or removed.
82
+ - Classify new project-planning content with \`wiki/meta/document-taxonomy.md\` before writing or consolidating it.
19
83
  - Do not store non-project LLM memory, assistant preferences, collaboration reminders, or workflow instructions in project wiki canonical or decision docs.
20
84
  - Follow \`wiki/AGENTS.md\` for detailed rules when editing files under \`wiki/\`.
21
85
  - Let \`.githooks/prepare-commit-msg\` append wiki trailers automatically for staged wiki, hook, AGENTS, or project-librarian files.
86
+ - ${exports.wikiTrustContract}
87
+ - ${exports.codeEvidenceTrustContract}
22
88
  <!-- PROJECT-WIKI-FIRST:END -->`;
89
+ }
23
90
  exports.claudeSection = `<!-- PROJECT-WIKI-CLAUDE:START -->
24
91
  # Claude Code Project Instructions
25
92
 
@@ -79,6 +146,14 @@ Storage boundaries:
79
146
  - Do not store non-project LLM memory, assistant preferences, collaboration reminders, or workflow instructions in \`canonical/\` or \`decisions/\`; use root \`AGENTS.md\`, compatibility instruction files, hooks, rules, or skills instead.
80
147
  - During migration review, preserve useful meaning while converting it to the current wiki structure. Legacy files, sections, blocks, and wording may be retained when review confirms they belong in the new topic shape and remain current project truth. Do not link to or cite \`wiki_legacy*\` from the new wiki; cite current-project evidence when possible and keep unresolved or ambiguous material in migration inboxes.
81
148
 
149
+ Classification rules:
150
+
151
+ - Before adding or consolidating project content, classify it with \`meta/document-taxonomy.md\`.
152
+ - Write current agreement to the narrowest durable canonical document that fits the taxonomy; do not append unrelated material to \`canonical/project-brief.md\`.
153
+ - If one input crosses several lifecycle areas, split it into separate canonical updates and link the related pages.
154
+ - If the input explains why a direction changed, update the relevant decision log or Decision Pack in addition to canonical truth.
155
+ - If an external artifact is the better source of truth (for example Figma, OpenAPI, ERD, issue tracker, or code), keep a concise canonical summary and link the external source as the authoritative location.
156
+
82
157
  Update rules:
83
158
 
84
159
  - Every wiki knowledge markdown file should include compact metadata with \`status\`, \`updated\`, \`scope\`, \`read_budget\`, \`decision_ref\`, and \`review_trigger\`. This \`wiki/AGENTS.md\` instruction file is excluded from that wiki-page metadata requirement.
@@ -117,14 +192,12 @@ exports.startup = `${(0, exports.metadata)("startup-router", "short", "wiki/meta
117
192
  - At session start, read only this file and \`wiki/index.md\` first; read detailed files on demand.
118
193
  - Project canonical content language is not fixed by this bootstrap. The LLM should choose the language that best matches the user and project context.
119
194
  - Update the wiki in the same turn when project-planning content changes.
195
+ - Classify new project-planning content with \`wiki/meta/document-taxonomy.md\` before writing or consolidating it.
120
196
 
121
197
  ## Read On Demand
122
198
 
123
199
  - [[index]]: document router.
124
- - [[canonical/project-brief]]: read only when product direction, audience, scope, success criteria, or core scenarios matter.
125
- - [[canonical/open-questions]]: read only when unresolved questions or next clarification items matter.
126
- - [[canonical/assumptions]]: read only when temporary assumptions or unverified premises matter.
127
- - [[canonical/risks]]: read only when risks, revisit triggers, or uncertainty matter.
200
+ - [[meta/document-taxonomy]]: read only when classifying or reorganizing project wiki content.
128
201
 
129
202
  ## Project State
130
203
 
@@ -179,22 +252,7 @@ This file is a router, not a file to expand into every answer. Read only the fil
179
252
 
180
253
  ## Canonical
181
254
 
182
- - [[canonical/project-brief]]
183
- - Read: product direction, audience, scope, success criteria, core scenarios.
184
- - Update: product, audience, scope, or success criteria changes.
185
- - Token budget: medium.
186
- - [[canonical/open-questions]]
187
- - Read: unresolved questions or next clarifications.
188
- - Update: questions are added, answered, or moved.
189
- - Token budget: short.
190
- - [[canonical/assumptions]]
191
- - Read: temporary assumptions or unverified premises.
192
- - Update: assumptions are added, validated, or retired.
193
- - Token budget: short.
194
- - [[canonical/risks]]
195
- - Read: risks, revisit triggers, uncertainty.
196
- - Update: risks are added, mitigated, or resolved.
197
- - Token budget: short.
255
+ No empty canonical starter pages are created by default. Create focused pages under \`wiki/canonical/\` only when durable project truth exists, then route them here or with \`--refresh-index\`.
198
256
 
199
257
  ## Project Decisions
200
258
 
@@ -202,18 +260,14 @@ This file is a router, not a file to expand into every answer. Read only the fil
202
260
  - Read: recent important project decisions.
203
261
  - Update: a decision belongs in startup context.
204
262
  - Token budget: short.
263
+ - [[decisions/README]]
264
+ - Read: decision directory structure or decision routing conventions.
265
+ - Update: decision directory conventions change.
266
+ - Token budget: short.
205
267
  - [[decisions/log]]
206
268
  - Read: project decision timing matters.
207
269
  - Update: a trivial decision needs timestamp tracking.
208
270
  - Token budget: on-demand.
209
- - [[decisions/decision-pack-template]]
210
- - Read: creating a Decision Pack.
211
- - Update: Decision Pack format changes.
212
- - Token budget: short.
213
- - [[decisions/full-adr-template]]
214
- - Read: creating a Full ADR.
215
- - Update: Full ADR format changes.
216
- - Token budget: short.
217
271
 
218
272
  ## Wiki Meta
219
273
 
@@ -221,6 +275,10 @@ This file is a router, not a file to expand into every answer. Read only the fil
221
275
  - Read: wiki operation, hooks, bootstrap, maintenance, language policy.
222
276
  - Update: wiki operation or startup behavior changes.
223
277
  - Token budget: medium.
278
+ - [[meta/document-taxonomy]]
279
+ - Read: classifying, writing, consolidating, splitting, or reorganizing project wiki content.
280
+ - Update: wiki information architecture or service-documentation categories change.
281
+ - Token budget: medium.
224
282
  - [[meta/decision-policy]]
225
283
  - Read: decision level, ADR need, canonical/decision split.
226
284
  - Update: decision classification or ADR criteria changes.
@@ -281,6 +339,7 @@ exports.wikiOperatingModel = `${(0, exports.metadata)("wiki-meta", "medium", "wi
281
339
  - Operating documents generated by bootstrap are English by default.
282
340
  - Project canonical content language is selected from user/project context, not hardcoded by this bootstrap.
283
341
  - Search, index refresh, inbox capture, and lifecycle checks are explicit script modes.
342
+ - New project content is classified through [[meta/document-taxonomy]] before it is written or consolidated.
284
343
 
285
344
  ## Purpose
286
345
 
@@ -299,6 +358,18 @@ Karpathy's LLM Wiki pattern favors a continuously maintained markdown wiki over
299
358
  5. Router: read/update/token-budget guidance in \`wiki/index.md\`.
300
359
  6. Wiki meta: operating rules, decision policy, bootstrap, migration, lint, and language policy under \`wiki/meta/\`.
301
360
 
361
+ ## Content Classification Procedure
362
+
363
+ Before writing or reorganizing project-planning content:
364
+
365
+ 1. Identify the content's lifecycle area with [[meta/document-taxonomy]].
366
+ 2. Decide whether the content is current truth, decision rationale, source evidence, an unresolved candidate, or a wiki operating rule.
367
+ 3. Write current truth to the narrowest relevant \`canonical/\` page, decision rationale to \`decisions/\`, source notes to \`sources/\`, candidates to \`inbox/\`, and wiki operating rules to \`meta/\`.
368
+ 4. Split multi-area inputs instead of making one catch-all document.
369
+ 5. Link upstream and downstream pages when the content derives from another artifact or produces another artifact.
370
+
371
+ Do not treat \`canonical/project-brief.md\` as a default dumping ground. It should summarize direction, audience, scope, and success criteria; detailed product, policy, UX, data, engineering, QA, release, or operations truth should move into focused pages when it grows.
372
+
302
373
  ## Language Policy
303
374
 
304
375
  - Bootstrap-generated operating documents are English.
@@ -371,6 +442,106 @@ Use a Full ADR when the decision affects product direction, architecture, public
371
442
  - Do not inject full canonical or decision bodies into startup context.
372
443
  - Read long decision files only when \`wiki/index.md\` routing says they are relevant.
373
444
  `;
445
+ exports.documentTaxonomy = `${(0, exports.metadata)("wiki-meta", "medium", "wiki/meta/wiki-ops-v1-decisions.md", "wiki information architecture, documentation categories, or content classification rules change")}
446
+ # Document Taxonomy
447
+
448
+ ## TL;DR
449
+
450
+ - Classify new project-planning content before writing it into the wiki.
451
+ - Use this page to classify content into \`canonical/\`, \`decisions/\`, \`sources/\`, \`inbox/\`, or \`meta/\`.
452
+ - Keep \`canonical/project-brief.md\` compact; move detailed truth into focused canonical pages.
453
+ - Preserve derivation links: evidence -> strategy -> requirements -> design/data/engineering -> QA -> release/operations -> feedback.
454
+
455
+ ## Top-Level Flow
456
+
457
+ \`\`\`text
458
+ 0. Source-of-truth governance
459
+ -> 1. Research and evidence
460
+ -> 2. Strategy and business model
461
+ -> 3. Product scope and requirements
462
+ -> 4. Policies and rules
463
+ -> 5. UX and content
464
+ -> 6. Design
465
+ -> 7. Data and analytics
466
+ -> 8. Engineering
467
+ -> 9. Security, legal, compliance
468
+ -> 10. QA and verification
469
+ -> 11. Release and operations
470
+ -> 12. Business operations
471
+ -> 13. Improvement, migration, and end-of-life
472
+ -> next product scope, policy, or roadmap change
473
+ \`\`\`
474
+
475
+ ## Storage Decision
476
+
477
+ | Content Type | Store In | Notes |
478
+ | --- | --- | --- |
479
+ | Current valid project truth | \`wiki/canonical/\` | Split by topic and read frequency. |
480
+ | Why a choice was made | \`wiki/decisions/\` | Use log, Decision Pack, or ADR by impact. |
481
+ | Source material or summarized evidence | \`wiki/sources/\` | Keep links, checked dates, and applicability. |
482
+ | Unreviewed or ambiguous material | \`wiki/inbox/\` | Do not treat as canonical truth. |
483
+ | Wiki operation, taxonomy, hooks, migration, lint, language rules | \`wiki/meta/\` | Keep outside project canonical truth. |
484
+ | Better external source of truth | External artifact plus a concise wiki route | Examples: Figma, OpenAPI, ERD, Jira, code. |
485
+
486
+ ## Lifecycle Areas
487
+
488
+ | Area | Put Here | Usually Derives From | Usually Produces |
489
+ | --- | --- | --- | --- |
490
+ | 0. Governance | source-of-truth map, owners, RACI, approval flow, change rules, glossary, state dictionary, assumptions, risk register | team/process constraints | routing, ownership, conflict resolution |
491
+ | 1. Research | market, competitor, user interviews, VOC, analytics, legal/regulatory, technical feasibility, cost, vendor, accessibility research | raw discovery | strategy, risks, sources |
492
+ | 2. Strategy | service overview, vision, problem, target users, personas, jobs-to-be-done, value offer, positioning, business model, KPI/OKR, success/stop criteria, roadmap, MVP, non-goals | research | PRD, roadmap, scope |
493
+ | 3. Product | PRD, user stories, use cases, priorities, backlog rules, acceptance criteria, feature spec, exceptions, state definitions, notification rules, search/filter/sort rules, admin requirements | strategy and policy | UX, API, data, QA |
494
+ | 4. Policy | operations policy, auth/account, permissions, pricing, payment/refund, coupon/credit, content moderation, notifications, retention/deletion, abuse response, support, EOL | business model, law, risks | feature constraints, API rules, CS/ops |
495
+ | 5. UX and Content | IA, sitemap, user flow, task flow, screen list, wireframes, screen specs, content model, UX writing, empty/error states, help/FAQ, localization, SEO, accessibility criteria | product and policy | design, frontend, QA |
496
+ | 6. Design | brand guide, design principles, design system, component spec, responsive rules, interaction spec, prototype, design QA | UX and brand | UI implementation, design QA |
497
+ | 7. Data and Analytics | ERD, data dictionary, classification, ownership/stewardship, event taxonomy, metric definitions, funnels, data quality, lineage, export/import, anonymization, dashboards | product, policy, KPI | schemas, events, reports |
498
+ | 8. Engineering | architecture, technology decisions, API/OpenAPI, integrations, webhooks/idempotency, state machines, jobs/cron, error codes, env vars, secrets, local dev, conventions, branch/release strategy, CI/CD, feature flags, dependencies, migrations, performance, scalability, FinOps | product, UX, data, policy | implementation and verification |
499
+ | 9. Security/Legal | security requirements, threat model, privacy rules, privacy impact, terms, privacy policy, audit logs, permission history, internal access controls, key rotation, vulnerability response, licenses, vendor and DPA documents | data, architecture, law | controls, tests, release gates |
500
+ | 10. QA | test strategy, QA scenarios, test cases, regression checklist, UAT, browser/device matrix, accessibility tests, performance tests, security tests, data quality tests, design QA, quality gates | requirements, design, engineering | release approval |
501
+ | 11. Release/Ops | release plan, deployment procedure, rollback, release notes, operator manual, runbooks, monitoring, observability, SLO/SLA, on-call/escalation, incident response, backup/restore, DR/BCP, recurring checks | QA and infrastructure | stable operation |
502
+ | 12. Business Ops | CS macros, support policy, training, sales/adoption guide, CRM rules, onboarding playbook, churn/offboarding, admin operations, communication templates, revenue recognition, tax/invoice, partner operations | policy, release, sales motion | customer-facing operation |
503
+ | 13. Improvement/EOL | VOC summary, retrospectives, experiments, experiment results, cohort/retention analysis, feature deprecation, migration/data transfer, service end-of-life | operations and analytics | next PRD, policy, roadmap |
504
+
505
+ ## Writing Rule
506
+
507
+ When a new note arrives:
508
+
509
+ 1. Identify the lifecycle area and storage location.
510
+ 2. Update an existing focused page when the topic already has a canonical home.
511
+ 3. Create a new focused page only when the topic is durable, likely to be read independently, or too large for its current page.
512
+ 4. Add an \`index.md\` route when the page becomes durable.
513
+ 5. Add upstream/downstream links in prose or tables when one artifact derives from another.
514
+ 6. Record decision rationale separately when the change explains why the project chose one option over another.
515
+
516
+ ## Page Shape
517
+
518
+ Use this shape for focused canonical pages unless a domain-specific shape is clearly better:
519
+
520
+ \`\`\`md
521
+ ---
522
+ status: active
523
+ updated: YYYY-MM-DD
524
+ scope: project-canonical
525
+ read_budget: short|medium|on-demand
526
+ decision_ref: none|wiki/decisions/...
527
+ review_trigger: what should cause this page to change
528
+ ---
529
+
530
+ # <Topic>
531
+
532
+ ## TL;DR
533
+
534
+ - Current agreement in one to five bullets.
535
+
536
+ ## Current Truth
537
+
538
+ ## Upstream Inputs
539
+
540
+ ## Downstream Artifacts
541
+
542
+ ## Open Questions
543
+ \`\`\`
544
+ `;
374
545
  exports.starterFiles = {
375
546
  "wiki/README.md": `${(0, exports.metadata)("wiki-entry", "short", "wiki/meta/wiki-ops-v1-decisions.md", "top-level wiki structure changes")}
376
547
  # Project Wiki
@@ -381,10 +552,7 @@ This directory is the durable project-planning source of truth. Keep product dir
381
552
 
382
553
  - [[startup]]
383
554
  - [[index]]
384
- - [[canonical/project-brief]]
385
- - [[canonical/open-questions]]
386
- - [[canonical/assumptions]]
387
- - [[canonical/risks]]
555
+ - [[meta/document-taxonomy]]
388
556
  `,
389
557
  "wiki/canonical/project-brief.md": `${(0, exports.metadata)("project-canonical", "medium", "none", "product direction, audience, scope, success criteria, or language choice changes")}
390
558
  # Project Brief
@@ -502,17 +670,18 @@ No project decisions yet.
502
670
  ## TL;DR
503
671
 
504
672
  - This Decision Pack records accepted wiki operating choices for project-librarian.
505
- - It covers wiki structure, startup hook scope, metadata, language policy, git hook behavior, migration review, and inbox handling.
673
+ - It covers wiki structure, document taxonomy, startup hook scope, metadata, language policy, git hook behavior, migration review, and inbox handling.
506
674
  - Project product decisions belong in \`wiki/decisions/\`, while these operating decisions stay in \`wiki/meta/\`.
507
675
 
508
676
  Status: accepted
509
677
  Scope: wiki operation
510
- Canonical: [[meta/operating-model]], [[meta/decision-policy]]
678
+ Canonical: [[meta/operating-model]], [[meta/decision-policy]], [[meta/document-taxonomy]]
511
679
 
512
680
  | Date | Decision | Rationale | Rejected Alternative | Revisit Trigger | Canonical Link |
513
681
  | --- | --- | --- | --- | --- | --- |
514
682
  | ${workspace_1.today} | Keep the wiki root at \`./wiki\`. | Planning docs live with the project. | External docs only. | Another tool cannot read \`./wiki\` or the team needs another path. | [[meta/operating-model]] |
515
683
  | ${workspace_1.today} | Split \`canonical/\` and \`decisions/\`. | Current truth and decision history are easier to scan when separated. | A single mixed docs directory. | The structure proves too heavy for small projects. | [[meta/decision-policy]] |
684
+ | ${workspace_1.today} | Classify new wiki content through a service-lifecycle document taxonomy before writing or consolidating it. | Agents need a structural contract for deciding whether content is strategy, product, policy, UX, design, data, engineering, security/legal, QA, release/ops, business ops, or improvement/EOL truth. | Let agents append new content to whichever existing page is nearby. | The taxonomy becomes too heavy for small projects or repeatedly misroutes content. | [[meta/document-taxonomy]], [[meta/operating-model]] |
516
685
  | ${workspace_1.today} | Inject only \`startup.md\` and \`index.md\` through Codex, Claude Code, Cursor, and Gemini CLI startup hooks; route detailed files Read On Demand. | Full canonical and decision bodies waste startup tokens. | Always read detailed canonical and decision files first. | Important context is repeatedly missed at startup. | [[startup]], [[index]] |
517
686
  | ${workspace_1.today} | Use metadata headers on wiki knowledge pages. | Agents and humans can quickly judge status, scope, budget, and review triggers. | Body-only conventions. | Header maintenance costs more than it saves. | [[meta/operating-model]] |
518
687
  | ${workspace_1.today} | Keep wiki operating docs in \`wiki/meta/\`. | Project truth stays focused on product/project content. | Store operating docs in \`canonical/\` or \`decisions/\`. | Meta docs become hard to discover. | [[meta/operating-model]] |
@@ -523,6 +692,7 @@ Canonical: [[meta/operating-model]], [[meta/decision-policy]]
523
692
  | ${workspace_1.today} | Migration may mark rows \`needs-human-review\`. | Ambiguous, risky, or high-impact legacy content should not be closed automatically. | Force every migrated row into adopted/rejected/resolved. | Human review queues become too large. | [[meta/operating-model]] |
524
693
  | ${workspace_1.today} | Capture stores candidates in \`wiki/inbox/\`. | Useful ideas are not lost, but unreviewed content does not become canonical truth. | Save all conversation content directly into canonical docs. | Inbox content is frequently abandoned. | [[meta/operating-model]] |
525
694
  `,
695
+ "wiki/meta/document-taxonomy.md": exports.documentTaxonomy,
526
696
  "wiki/decisions/decision-pack-template.md": `${(0, exports.metadata)("project-decision-template", "short", "wiki/meta/decision-policy.md", "decision pack format changes", "template")}
527
697
  # <Topic> v<N> Decisions
528
698
 
@@ -571,3 +741,11 @@ Checked: ${workspace_1.today}
571
741
  - \`wiki/meta/\` stores wiki operating rules and operating decisions.
572
742
  `,
573
743
  };
744
+ exports.defaultStarterFilePaths = new Set([
745
+ "wiki/README.md",
746
+ "wiki/decisions/README.md",
747
+ "wiki/decisions/log.md",
748
+ "wiki/decisions/recent.md",
749
+ "wiki/meta/document-taxonomy.md",
750
+ "wiki/sources/karpathy-llm-wiki.md",
751
+ ]);
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.conceptIdForFile = conceptIdForFile;
4
+ exports.wikiConceptType = wikiConceptType;
5
+ exports.conceptFromPage = conceptFromPage;
6
+ exports.readWikiConcepts = readWikiConcepts;
7
+ const wiki_files_1 = require("./wiki-files");
8
+ const workspace_1 = require("./workspace");
9
+ function conceptIdForFile(file) {
10
+ return file.replace(/^wiki\//, "").replace(/\.(md|mdx)$/i, "");
11
+ }
12
+ function wikiConceptType(file, scope) {
13
+ if (scope === "startup-router" || file === "wiki/startup.md")
14
+ return "Startup Router";
15
+ if (scope === "wiki-router" || file === "wiki/index.md" || /^wiki\/indexes\//.test(file))
16
+ return "Wiki Router";
17
+ if (scope === "project-canonical" || /^wiki\/canonical\//.test(file))
18
+ return "Project Canonical Concept";
19
+ if (scope === "project-decisions" || /^wiki\/decisions\//.test(file))
20
+ return "Project Decision";
21
+ if (scope === "source-summary" || /^wiki\/sources\//.test(file))
22
+ return "Source Summary";
23
+ if (scope === "wiki-meta" || /^wiki\/meta\//.test(file))
24
+ return "Wiki Operations Concept";
25
+ if (/^migration-/.test(scope) || /^wiki\/migration\//.test(file))
26
+ return "Migration Ledger";
27
+ if (scope === "inbox" || /^wiki\/inbox\//.test(file))
28
+ return "Project Candidate";
29
+ return "Wiki Concept";
30
+ }
31
+ function conceptFromPage(file, text) {
32
+ const scope = (0, workspace_1.metadataValue)(text, "scope") || "-";
33
+ const tldr = (0, wiki_files_1.firstTldrBullet)(text);
34
+ return {
35
+ budget: (0, workspace_1.metadataValue)(text, "read_budget") || "-",
36
+ conceptId: conceptIdForFile(file),
37
+ description: tldr || (0, wiki_files_1.compactSummary)(text),
38
+ file,
39
+ reviewTrigger: (0, workspace_1.metadataValue)(text, "review_trigger"),
40
+ scope,
41
+ status: (0, workspace_1.metadataValue)(text, "status") || "-",
42
+ timestamp: (0, workspace_1.metadataValue)(text, "updated"),
43
+ title: (0, wiki_files_1.wikiTitleForFile)(file, text),
44
+ type: wikiConceptType(file, scope),
45
+ };
46
+ }
47
+ function readWikiConcepts(files = (0, wiki_files_1.wikiMarkdownFiles)()) {
48
+ return files.map((file) => conceptFromPage(file, (0, workspace_1.read)(file)));
49
+ }