llm-wiki-kit 0.2.11 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/templates.js CHANGED
@@ -8,18 +8,19 @@ export function rootAgentsPolicy() {
8
8
  This repository uses llm-wiki-kit as a hook-first living Markdown wiki for Codex and Claude Code.
9
9
 
10
10
  - This block supersedes older OMX/OMC/\`omx_wiki/\` LLM Wiki instructions for this repository.
11
- - 평소처럼 Codex 또는 Claude Code 사용한다. 사용자가 별도 \`llm-wiki\` 명령을 외워서 실행해야 하는 흐름을 만들지 않는다.
12
- - 채팅 기억은 임시로 본다. 오래 남길 프로젝트 지식은 \`llm-wiki/\` Markdown에 남긴다.
13
- - \`llm-wiki/raw/\`는 원본 또는 redacted 근거 저장소다. hook envelope append 외에는 원본 capture를 수정하지 않는다.
14
- - \`llm-wiki/wiki/\`는 agent가 관리하는 지식층이다. 결정, 구조, 디버깅, 개념, 절차, 맥락을 여기에 정리한다.
15
- - \`llm-wiki/wiki/memory.md\`는 짧은 핵심 기억이다. 설명 대신 현재 상태와 중요한 문서 링크만 유지한다.
16
- - hook이 주입한 context를 참고하되, 현재 사용자 답변을 먼저 처리한다. 수동 확인이나 정리에는 \`llm-wiki context\`, \`llm-wiki lint\`, \`llm-wiki consolidate\`를 agent 보조 도구로 사용한다.
17
- - hook redacted raw envelope와 작업/결정 중심 live Q&A만 안전하게 남긴다. 단순 답변, 상태 확인, 키워드만 포함된 응답은 live Q&A나 durable wiki 승격하지 않는다. \`wiki/queries\`/\`wiki/decisions\` 자동 승격은 기본값이 아니며, durable 지식은 중요도와 동의 흐름에 따라 agent 기존 정식 wiki 문서에 합친다.
18
- - hook은 종료/시작 경계에서 정말 필요한 정리 후보를 \`llm-wiki/outputs/maintenance/queue.md\`에 남길 있다. 정기 maintenance는 agent-side soft reminder이며, pending 항목은 현재 응답을 지연시키지 않는 범위에서 agent가 병합하거나 done/skipped로 표시한다.
19
- - 문서를 만들기 전에 기존 wiki 문서를 먼저 찾아 갱신한다. 반복해서 사실은 chunked \`outputs/questions/\`에만 두지 말고 적절한 wiki 문서에 합친다.
20
- - 일회성 작업/결정 기록은 필요할 \`llm-wiki/outputs/questions/YYYY-MM-DD/live-qa-001.md\` style chunk에 보존하고, 재사용 가능한 사실/지식은 승인된 경우 \`wiki/architecture/\`, \`wiki/debugging/\`, \`wiki/decisions/\`, \`wiki/concepts/\`, \`procedures/\`에 반영한다.
21
- - 검증 명령, 근거 파일, 불확실한 점을 함께 남긴다. 추론은 추론이라고 표시하고, 모순은 지우지 말고 Open Questions 또는 Contradictions에 남긴다.
22
- - 인증값, token, password, private key, \`.env\` 원문은 저장하지 않는다. 필요한 경우 redacted summary만 남긴다.
11
+ - Use Codex or Claude Code normally. Do not create a workflow where users must remember extra \`llm-wiki\` commands during ordinary work.
12
+ - Language: respond in the user's current prompt language when it is clearly Korean or English. Keep technical identifiers, commands, paths, code, and original error text unchanged. If no prompt language is clear, follow local \`CLAUDE.md\`/\`AGENTS.md\` guidance, then fall back to English.
13
+ - Treat chat memory as temporary. Durable project knowledge belongs in repository Markdown under \`llm-wiki/\`.
14
+ - \`llm-wiki/raw/\` is the immutable or redacted evidence layer. Do not modify raw captures except safe hook envelope append.
15
+ - \`llm-wiki/wiki/\` is the curated knowledge layer managed by the agent. Put decisions, architecture, debugging findings, concepts, procedures, and context there.
16
+ - Keep \`llm-wiki/wiki/memory.md\` short. Link to important documents instead of copying long explanations.
17
+ - Use hook-injected context when helpful, but answer the current user request first. Use \`llm-wiki context\`, \`llm-wiki lint\`, and \`llm-wiki consolidate\` only as agent maintenance helpers.
18
+ - Hooks safely store redacted raw envelopes and work/decision-focused live Q&A. Simple answers, status checks, and keyword-only turns should not be promoted to live Q&A or durable wiki by default.
19
+ - Hooks may queue durable cleanup candidates in \`llm-wiki/outputs/maintenance/queue.md\` at stop/start boundaries. Treat maintenance as a soft agent-side reminder; merge pending items only when relevant and mark them \`done\` or \`skipped\`.
20
+ - Before creating new wiki pages, search existing pages and update the right one when possible. Reusable facts should not stay only in chunked \`outputs/questions/\`.
21
+ - Store one-off work or decision records in \`llm-wiki/outputs/questions/YYYY-MM-DD/live-qa-001.md\` when needed. Merge reusable knowledge into \`wiki/architecture/\`, \`wiki/debugging/\`, \`wiki/decisions/\`, \`wiki/concepts/\`, or \`procedures/\` when approved or clearly important.
22
+ - Record verification commands, evidence files, and uncertainty. Mark inference explicitly and preserve contradictions in Open Questions or Contradictions.
23
+ - Never store credentials, tokens, passwords, private keys, or raw \`.env\` contents. Store only redacted summaries when needed.
23
24
 
24
25
  <!-- llm-wiki-kit:end -->
25
26
  `;
@@ -31,29 +32,35 @@ export function llmWikiAgents() {
31
32
  Generated by llm-wiki-kit ${runtimeVersion()}.
32
33
 
33
34
  ## Purpose
34
- Codex와 Claude Code를 평소처럼 사용하는 동안 living Markdown LLM Wiki 자연스럽게 유지한다.
35
- 사용자가 많은 \`llm-wiki\` 명령을 직접 실행하는 방식이 아니라, agent 작업 필요한 wiki 조회와 정리를 수행하되 현재 사용자 답변을 지연시키지 않는 것이 기본이다.
36
- 규칙은 오래된 OMX/OMC/\`omx_wiki/\` 규칙을 대체한다.
35
+ Maintain a living Markdown LLM Wiki while users work normally in Codex or Claude Code.
36
+ The user should not need to run many \`llm-wiki\` commands manually. The agent checks and maintains wiki context when useful, but the current user answer comes first.
37
+ These rules replace older OMX/OMC/\`omx_wiki/\` rules for this project.
38
+
39
+ ## Language
40
+ - Follow the user's current prompt language when it is clearly Korean or English.
41
+ - If no current prompt language is clear, follow local \`CLAUDE.md\`/\`AGENTS.md\` guidance, then fall back to English.
42
+ - Keep commands, paths, code identifiers, API names, package names, logs, and original error text unchanged.
43
+ - Korean and English users should both be able to use Codex/Claude Code naturally without changing \`llm-wiki\` commands.
37
44
 
38
45
  ## Directories
39
- - \`raw/\`: 원본 또는 redacted 근거 저장소. hook이 redacted envelope를 append하는 경우 외에는 원본 capture를 수정하지 않는다.
40
- - \`wiki/\`: agent가 관리하는 정식 지식 문서. \`wiki/memory.md\`는 hook context에 들어가는 짧은 핵심 기억이다.
41
- - \`outputs/\`: live Q&A, 보고서, 생성물 저장소. 일회성 기록은 여기에 둔다.
42
- - \`procedures/\`: ingest, query, lint, security 같은 운영 규칙.
46
+ - \`raw/\`: immutable or redacted evidence. Do not edit raw captures except safe hook envelope append.
47
+ - \`wiki/\`: curated knowledge pages maintained by the agent. \`wiki/memory.md\` is the short hot index injected into hook context.
48
+ - \`outputs/\`: live Q&A, reports, maintenance candidates, and long generated artifacts. One-off records belong here.
49
+ - \`procedures/\`: operating rules for ingest, query, lint, and security.
43
50
 
44
51
  ## Core Rules
45
- - 사용자는 Claude Code/Codex 평소처럼 사용한다. agent 필요한 wiki 조회와 정리를 자연스럽게 수행하되, 현재 사용자 요청에 대한 답변을 먼저 끝낸다.
46
- - \`raw/\` 원본은 수정하지 않는다. 안전한 hook envelope append만 예외다.
47
- - 근거 없는 내용을 사실처럼 쓰지 않는다. 추론은 명시한다.
48
- - 중요한 주장에는 \`source_ids\`, 파일 경로, 검증 명령 중 하나 이상을 남긴다.
49
- - 오래 남길 내용이 생기면 문서부터 만들지 말고 기존 \`wiki/\` 문서를 먼저 찾아 갱신한다.
50
- - 단순 답변, 상태 확인, 키워드만 포함된 응답, 일회성 대화는 live Q&A, \`wiki/queries\`, maintenance로 승격하지 않는다.
51
- - 반복해서 지식은 중요도와 동의 흐름에 따라 \`wiki/architecture/\`, \`wiki/debugging/\`, \`wiki/decisions/\`, \`wiki/concepts/\`, \`procedures/\`에 합친다.
52
- - hook이 만든 \`outputs/maintenance/queue.md\` pending 항목은 현재 요청과 관련 있거나 review due 안내가 있을 확인하고, 기존 정식 wiki 문서에 병합한 done 또는 skipped로 표시한다.
53
- - 정기 maintenance 자동 수정이 아니라 agent review다. \`SessionStart\`/\`InstructionsLoaded\`에서만 짧게 안내되고, \`UserPromptSubmit\`에서는 사용자가 wiki/maintenance/정리 관련 질문을 한 경우에만 안내된다.
54
- - \`wiki/memory.md\`는 짧게 유지한다. 설명 대신 현재 상태와 중요한 문서 링크를 둔다.
55
- - 모순은 덮어쓰지 말고 \`Contradictions\` 또는 \`Open Questions\`에 보존한다.
56
- - 인증값, token, password, private key, \`.env\` 원문은 wiki에 저장하지 않는다.
52
+ - Users work normally in Claude Code/Codex. The agent performs wiki lookup and maintenance naturally, but answers the current request first.
53
+ - Do not modify \`raw/\` source material except safe hook envelope append.
54
+ - Do not state unsupported claims as facts. Mark inference explicitly.
55
+ - Important claims should include at least one of: \`source_ids\`, file paths, or verification commands.
56
+ - When durable knowledge appears, search existing \`wiki/\` pages before creating a new page.
57
+ - Do not promote simple answers, status checks, keyword-only replies, or one-off chat into live Q&A, \`wiki/queries\`, or maintenance.
58
+ - Merge reusable knowledge into \`wiki/architecture/\`, \`wiki/debugging/\`, \`wiki/decisions/\`, \`wiki/concepts/\`, or \`procedures/\` based on importance and user consent flow.
59
+ - Review \`outputs/maintenance/queue.md\` pending items only when related to the current request or when review is due. Merge into existing durable wiki pages, then mark items \`done\` or \`skipped\`.
60
+ - Periodic maintenance is agent review, not automatic editing. Show only short reminders at \`SessionStart\`/\`InstructionsLoaded\`, and only show prompt-time reminders for wiki/maintenance-related user prompts.
61
+ - Keep \`wiki/memory.md\` short. Use links to current state and important documents instead of long explanations.
62
+ - Preserve contradictions in \`Contradictions\` or \`Open Questions\`; do not overwrite them silently.
63
+ - Do not store credentials, tokens, passwords, private keys, or raw \`.env\` contents in wiki.
57
64
 
58
65
  ## Page Format
59
66
  Use YAML frontmatter when creating wiki pages:
@@ -75,11 +82,11 @@ superseded_by: []
75
82
  \`\`\`
76
83
 
77
84
  ## Operations
78
- - ingest: \`wiki/memory.md\`와 \`wiki/index.md\`를 먼저 읽고, 근거를 확인한 기존 wiki 문서를 우선 갱신한다.
79
- - query: hook 주입한 context 참고하되 현재 답변을 먼저 한다. 수동 명령은 점검용이며 일반 사용 흐름의 필수 단계가 아니다.
80
- - lint: 사용자가 요청했거나 wiki 유지보수 작업일 agent가 쓰는 보조 도구다. turn 실행하지 않는다.
81
- - consolidate: agent가 \`memory.md\`/\`index.md\` generated block을 안전하게 갱신할 쓰는 보조 도구다. 손글씨 영역과 정식 문서 본문은 덮어쓰지 않는다.
82
- - maintenance: \`outputs/maintenance/queue.md\`는 종료/시작 경계에서 생긴 정리 후보 목록이다. 현재 요청을 지연시키지 않는 범위에서 agent가 기존 문서 병합 여부를 판단하고 상태를 갱신한다.
85
+ - ingest: read \`wiki/memory.md\` and \`wiki/index.md\` first, verify new evidence, then prefer updating existing wiki pages.
86
+ - query: use hook-injected context when useful, but answer the current request first. Manual commands are diagnostics, not required daily workflow.
87
+ - lint: agent helper for user-requested or wiki maintenance work. Do not run it every turn.
88
+ - consolidate: safely refresh generated blocks in \`memory.md\`/\`index.md\`. Do not overwrite handwritten sections or curated document bodies.
89
+ - maintenance: \`outputs/maintenance/queue.md\` stores stop/start cleanup candidates. Review and update it only when it does not delay the current user request.
83
90
  `;
84
91
  }
85
92
 
@@ -90,31 +97,31 @@ Generated by llm-wiki-kit.
90
97
 
91
98
  ## Overview
92
99
 
93
- 파일은 living wiki 짧은 지도다. 자세한 설명을 길게 쓰기보다, agent가 다음 작업에서 빠르게 찾아갈 entry point를 유지한다.
100
+ This file is the short navigation map for the living wiki. Keep entry points easy to scan instead of adding long explanations here.
94
101
 
95
102
  ## Main Areas
96
103
 
97
- - [Memory](memory.md) - 짧은 핵심 기억과 주요 entry point.
98
- - [Sources](sources/) - source summary와 source id.
99
- - [Concepts](concepts/) - 재사용 가능한 개념과 용어.
100
- - [Entities](entities/) - 시스템, 모듈, 도구, 서비스, 주요 객체.
101
- - [Decisions](decisions/) - 결정과 근거.
102
- - [Architecture](architecture/) - 구조와 데이터/제어 흐름.
103
- - [Debugging](debugging/) - 원인, 수정, 검증 evidence.
104
- - [Context](context/) - 세션 연속성과 프로젝트 맥락.
105
- - [Queries](queries/) - 재사용 가능한 질문 답변. 일회성 기록은 outputs/questions에 둔다.
104
+ - [Memory](memory.md) - short active memory and durable entry points.
105
+ - [Sources](sources/) - source summaries and source IDs.
106
+ - [Concepts](concepts/) - reusable concepts and terminology.
107
+ - [Entities](entities/) - systems, modules, tools, services, and important objects.
108
+ - [Decisions](decisions/) - decisions and rationale.
109
+ - [Architecture](architecture/) - structure, data flow, and control flow.
110
+ - [Debugging](debugging/) - causes, fixes, and verification evidence.
111
+ - [Context](context/) - session continuity and project context.
112
+ - [Queries](queries/) - reusable question answers. One-off records belong in outputs/questions.
106
113
 
107
114
  ## Operating Notes
108
115
 
109
- - 넓은 질문은 memory index에서 시작한다.
110
- - 문서를 만들기 전에 관련 기존 문서 3-7개를 먼저 확인한다.
111
- - 오래 사실/지식은 기존 정식 문서에 합치고, 작업/결정 중심 일회성 기록은 chunked outputs/questions에 둔다.
112
- - 관련 페이지가 생기면 \`[[page-or-topic]]\` 링크를 추가한다.
116
+ - Start broad questions from memory and this index.
117
+ - Before creating a new page, check 3-7 relevant existing pages.
118
+ - Merge durable facts into existing curated pages. Keep one-off work/decision records in chunked outputs/questions.
119
+ - Add \`[[page-or-topic]]\` links when related pages become useful.
113
120
 
114
121
  <!-- llm-wiki-kit:index-start -->
115
122
  ## Generated Page Map
116
123
 
117
- Agent가 필요할 \`llm-wiki consolidate --workspace <project>\`로 이 generated block을 갱신한다.
124
+ The agent may refresh this generated block with \`llm-wiki consolidate --workspace <project>\`.
118
125
  <!-- llm-wiki-kit:index-end -->
119
126
  `;
120
127
  }
@@ -136,11 +143,11 @@ superseded_by: []
136
143
 
137
144
  # LLM Wiki Memory
138
145
 
139
- 짧은 핵심 기억이다. hook context 들어갈 만큼 작게 유지하고, 설명을 복사하지 말고 깊은 문서로 링크한다.
146
+ Short active memory for hook context. Keep it small and link to deeper documents instead of copying long explanations.
140
147
 
141
148
  ## Current Focus
142
149
 
143
- - 오래 남길 현재 프로젝트 초점을 여기에 짧게 추가한다.
150
+ - Add the current durable project focus here in a few short bullets.
144
151
 
145
152
  ## Durable Entry Points
146
153
 
@@ -150,7 +157,7 @@ superseded_by: []
150
157
  <!-- llm-wiki-kit:memory-start -->
151
158
  ## Generated Memory Map
152
159
 
153
- Agent가 필요할 \`llm-wiki consolidate --workspace <project>\`로 이 generated block을 갱신한다.
160
+ The agent may refresh this generated block with \`llm-wiki consolidate --workspace <project>\`.
154
161
  <!-- llm-wiki-kit:memory-end -->
155
162
  `;
156
163
  }
@@ -166,50 +173,50 @@ export function procedure(name) {
166
173
  const procedures = {
167
174
  'ingest.md': `# Ingest Procedure
168
175
 
169
- 1. \`wiki/memory.md\`와 \`wiki/index.md\`를 먼저 읽는다.
170
- 2. 근거가 있으면 \`raw/inbox/\` 또는 \`raw/sources/\`를 확인한다.
171
- 3. source별 요약이 필요하면 \`wiki/sources/<slug>.md\`를 만들거나 갱신한다.
172
- 4. 문서부터 만들지 말고 관련 concept/entity/decision/architecture/debugging/context 문서를 먼저 찾아 갱신한다.
173
- 5. 중복 문서를 만들지 않는다. 같은 사실이 이미 있으면 기존 문서에 합친다.
174
- 6. 단순 답변과 일회성 대화는 durable wiki로 승격하지 않는다.
175
- 7. 중요한 주장에는 source reference, confidence, memory type, importance, verification status를 남긴다.
176
- 8. durable entry point가 바뀌면 \`wiki/memory.md\`를 짧게 갱신하거나 agent가 \`llm-wiki consolidate\`를 사용한다.
177
- 9. 의미 있는 변화는 \`wiki/log.md\`에 짧게 남긴다.
176
+ 1. Read \`wiki/memory.md\` and \`wiki/index.md\` first.
177
+ 2. If new evidence exists, inspect \`raw/inbox/\` or \`raw/sources/\`.
178
+ 3. Create or update \`wiki/sources/<slug>.md\` only when a source summary is useful.
179
+ 4. Before creating a new page, look for related concept/entity/decision/architecture/debugging/context pages and update those first.
180
+ 5. Do not create duplicates. Merge facts into existing pages when they already exist.
181
+ 6. Do not promote simple answers or one-off chat into durable wiki.
182
+ 7. Important claims should record source references, confidence, memory type, importance, and verification status.
183
+ 8. When durable entry points change, update \`wiki/memory.md\` briefly or use \`llm-wiki consolidate\`.
184
+ 9. Add a short entry to \`wiki/log.md\` for meaningful wiki changes.
178
185
  `,
179
186
  'query.md': `# Query Procedure
180
187
 
181
- 1. 현재 사용자 질문에 먼저 답한다. hook 주입한 context 필요한 만큼만 참고한다.
182
- 2. \`wiki/memory.md\`와 \`wiki/index.md\`에서 시작한다.
183
- 3. 관련 \`wiki/\` 문서를 최소한으로 읽는다.
184
- 4. 정확한 근거가 필요할 때만 raw source를 확인한다.
185
- 5. 검증된 사실과 추론을 분리한다.
186
- 6. 수동 확인이 필요할 때만 \`llm-wiki context "<query>"\`를 쓴다. 과거 episodic query/context까지 봐야 때는 \`--include-episodic\`을 붙이고, archived/superseded page까지 봐야 때만 \`--include-archived\`를 붙인다.
187
- 7. 일회성 답변, 상태 확인, 키워드만 포함된 응답은 durable wiki live Q&A 승격하지 않는다. tool evidence, changed-file evidence, verification, 구조화된 decision/debugging 결론이 있는 작업 turn만 \`outputs/questions/YYYY-MM-DD/live-qa-001.md\` style chunk에 남긴다.
188
- 8. 반복해서 사실/지식은 중요도와 동의 흐름에 따라 \`wiki/architecture/\`, \`wiki/debugging/\`, \`wiki/decisions/\`, \`wiki/concepts/\`, \`procedures/\`에 합친다.
188
+ 1. Answer the current user question first. Use hook-injected context only as needed.
189
+ 2. Start from \`wiki/memory.md\` and \`wiki/index.md\`.
190
+ 3. Read the smallest relevant set of \`wiki/\` documents.
191
+ 4. Inspect raw sources only when exact evidence matters.
192
+ 5. Separate verified facts from inference.
193
+ 6. Use \`llm-wiki context "<query>"\` only when manual inspection is useful. Add \`--include-episodic\` only for historical query/context pages, and \`--include-archived\` only for archived/superseded pages.
194
+ 7. Do not promote one-off answers, status checks, or keyword-only replies to durable wiki or live Q&A. Archive only work turns with tool evidence, changed-file evidence, verification, or structured decision/debugging conclusions.
195
+ 8. Merge reusable facts into \`wiki/architecture/\`, \`wiki/debugging/\`, \`wiki/decisions/\`, \`wiki/concepts/\`, or \`procedures/\` based on importance and user consent flow.
189
196
  `,
190
197
  'lint.md': `# Lint Procedure
191
198
 
192
- \`llm-wiki lint --workspace <project>\`는 agent 필요할 쓰는 wiki 건강 점검 도구다. 사용자가 매번 실행해야 하는 명령이 아니다.
199
+ \`llm-wiki lint --workspace <project>\` is an agent-side wiki health check. Users should not need to run it every turn.
193
200
 
194
- 점검 대상: stale page, orphan page, broken wiki/Markdown link, unsafe source id, secret-like content, missing source, duplicate concept/title, unsupported claim, unresolved contradiction, outdated managed rule, memory budget, page count growth, hidden episodic/context growth, stale/archived discoverability, maintenance review due, oversized legacy live Q&A, oversized live Q&A chunk.
201
+ Checks include stale pages, orphan pages, broken wiki/Markdown links, unsafe source IDs, secret-like content, missing sources, duplicate concepts/titles, unsupported claims, unresolved contradictions, outdated managed rules, memory budget pressure, page-count growth, hidden episodic/context growth, stale/archived discoverability, maintenance review due, oversized legacy live Q&A, and oversized live Q&A chunks.
195
202
 
196
- 정기 maintenance 사용자가 turn 실행할 필요가 없는 agent-side task다. 필요할 agent가 다음 순서로 확인한다:
203
+ Periodic maintenance is an agent-side task, not a per-turn user command. When needed, the agent checks:
197
204
 
198
205
  1. \`llm-wiki lint --workspace <project>\`
199
206
  2. \`llm-wiki maintenance --workspace <project>\`
200
- 3. pending item을 기존 durable page에 병합한 \`done\` 또는 \`skipped\`로 표시한다.
207
+ 3. Merge pending items into existing durable pages, then mark them \`done\` or \`skipped\`.
201
208
  4. \`llm-wiki consolidate --workspace <project> --dry-run\`
202
- 5. 필요할 \`llm-wiki consolidate --workspace <project>\`
209
+ 5. Run \`llm-wiki consolidate --workspace <project>\` when the dry run is acceptable.
203
210
 
204
- 자동 수정은 확실히 kit가 관리하는 영역에만 적용한다. 사용자 편집 가능성이 있는 문서는 덮어쓰지 말고 다음 작업 context에 정리 필요성을 올린다.
211
+ Apply automatic fixes only to clearly managed kit areas. Do not overwrite user-editable documents; surface cleanup needs in the next work context.
205
212
  `,
206
213
  'security.md': `# Security Procedure
207
214
 
208
- - 로컬 프로젝트 wiki에 유용한 작업 맥락은 보존한다.
209
- - 입력이 민감해 보인다는 이유만으로 read/tool call을 막지 않는다.
210
- - token, password, bearer credential, private key, \`.env\` 원문 같은 인증값은 hook payload, summary, context pack, wiki page에 저장하기 전에 redaction한다.
211
- - 민감정보가 wiki에 들어갔을 가능성이 있으면 agent가 \`llm-wiki lint --workspace <project>\`를 사용해 점검한다.
212
- - full raw transcript capture 기본 비활성이다. 프로젝트가 명시적으로 opt-in하고 redaction 경로가 있을 때만 허용한다.
215
+ - Preserve useful local project work context.
216
+ - Do not block reads or tool calls only because input looks sensitive.
217
+ - Redact authentication values such as tokens, passwords, bearer credentials, private keys, and raw \`.env\` contents before writing hook payloads, summaries, context packs, or wiki pages.
218
+ - If sensitive material may have entered the wiki, use \`llm-wiki lint --workspace <project>\`.
219
+ - Full raw transcript capture is disabled by default. Allow it only when a project explicitly opts in and has a redaction path.
213
220
  `,
214
221
  };
215
222
  return procedures[name] || '';
@@ -113,12 +113,22 @@ export async function updateNoticeContext(projectRoot, eventName, options = {})
113
113
 
114
114
  const workspace = resolve(projectRoot || process.cwd());
115
115
  const updateCommand = commandForProject('update', workspace);
116
+ if (options.language === 'ko') {
117
+ return [
118
+ 'LLM Wiki runtime update status:',
119
+ `- current hook runtime: ${notice.installedVersion}; npm registry: ${notice.latestVersion}`,
120
+ '- 현재 요청 처리가 우선이며, 현재 runtime 기능은 계속 동작한다.',
121
+ `- 업데이트/정비를 수행할 때 사용할 명령: \`${updateCommand}\``,
122
+ '- npm 전역 설치 권한 오류가 나면 환경에 맞게 `npm install -g llm-wiki-kit@latest` 또는 `sudo npm install -g llm-wiki-kit@latest` 후 같은 update 명령을 다시 실행한다.',
123
+ '- 이 status만으로 설치나 업데이트를 실행하지 않는다.',
124
+ ].join('\n');
125
+ }
116
126
  return [
117
127
  'LLM Wiki runtime update status:',
118
128
  `- current hook runtime: ${notice.installedVersion}; npm registry: ${notice.latestVersion}`,
119
- '- 현재 요청 처리가 우선이며, 현재 runtime 기능은 계속 동작한다.',
120
- `- 업데이트/정비를 수행할 사용할 명령: \`${updateCommand}\``,
121
- '- npm 전역 설치 권한 오류가 나면 환경에 맞게 `npm install -g llm-wiki-kit@latest` 또는 `sudo npm install -g llm-wiki-kit@latest` 같은 update 명령을 다시 실행한다.',
122
- '- status만으로 설치나 업데이트를 실행하지 않는다.',
129
+ '- The current request comes first, and the current runtime continues to work.',
130
+ `- Use this command only when performing update or maintenance work: \`${updateCommand}\``,
131
+ '- If global npm install hits a permission error, run `npm install -g llm-wiki-kit@latest` or `sudo npm install -g llm-wiki-kit@latest` as appropriate, then rerun the same update command.',
132
+ '- Do not install or update only because this status is present.',
123
133
  ].join('\n');
124
134
  }
package/src/update.js CHANGED
@@ -3,10 +3,10 @@ import { join, resolve } from 'path';
3
3
  import { exists } from './fs-utils.js';
4
4
  import { appendWikiLog } from './project.js';
5
5
  import { install } from './install.js';
6
- import { isWindows } from './platform.js';
6
+ import { commandMatchesRuntime, commandPaths, isWindows, sameResolvedPath } from './platform.js';
7
7
  import { applyProjectTemplateUpdate, inspectProjectState } from './project-state.js';
8
8
  import { knownProjectRoots, recordProject } from './projects.js';
9
- import { binPath, detectInstallSource, packageName, runtimeVersion } from './version.js';
9
+ import { binPath, detectInstallSource, packageName, packageRoot, runtimeVersion } from './version.js';
10
10
 
11
11
  function commandLine(command, args) {
12
12
  return [command, ...args].join(' ');
@@ -115,6 +115,10 @@ function binCommand() {
115
115
  return process.env.LLM_WIKI_KIT_BIN || binPath;
116
116
  }
117
117
 
118
+ function packageSpec(target) {
119
+ return `${packageName()}@${target}`;
120
+ }
121
+
118
122
  function assertCommandOk(result, label) {
119
123
  if (result.status === 0 && !result.error) return;
120
124
  const detail = result.stderr.trim() ||
@@ -125,6 +129,45 @@ function assertCommandOk(result, label) {
125
129
  throw new Error(`${label} failed: ${detail}`);
126
130
  }
127
131
 
132
+ function postUpdateCommand(workspace, options = {}) {
133
+ const command = ['llm-wiki', 'post-update'];
134
+ if (shouldUpdateAllProjects(options)) command.push('--all');
135
+ command.push('--workspace', workspace);
136
+ return command.join(' ');
137
+ }
138
+
139
+ function formatRemediation(workspace, target, options = {}) {
140
+ const install = isWindows(options)
141
+ ? `npm install -g ${packageSpec(target)}`
142
+ : `sudo npm install -g ${packageSpec(target)}`;
143
+ return [
144
+ 'Run the npm install command that owns the active runtime, then reapply hooks/templates:',
145
+ ` ${install}`,
146
+ ` ${postUpdateCommand(workspace, options)}`,
147
+ 'Then verify:',
148
+ ` llm-wiki status --workspace ${workspace}`,
149
+ ].join('\n');
150
+ }
151
+
152
+ function createUpdateVerificationError(message, diagnostics = {}, workspace, target, options = {}) {
153
+ const lines = [
154
+ 'llm-wiki-kit update did not update the active runtime.',
155
+ message,
156
+ ];
157
+ if (diagnostics.registryTarget) lines.push(`- registry target: ${diagnostics.registryTarget}`);
158
+ if (diagnostics.runtimeBefore) lines.push(`- runtime before: ${diagnostics.runtimeBefore}`);
159
+ if (diagnostics.runtimeAfter) lines.push(`- runtime after: ${diagnostics.runtimeAfter}`);
160
+ if (diagnostics.activePackageRoot) lines.push(`- active runtime root: ${diagnostics.activePackageRoot}`);
161
+ if (diagnostics.npmRoot) lines.push(`- npm global root: ${diagnostics.npmRoot}`);
162
+ if (diagnostics.npmPackageRoot) lines.push(`- npm target package root: ${diagnostics.npmPackageRoot}`);
163
+ if (diagnostics.commandPath) lines.push(`- command on PATH: ${diagnostics.commandPath}`);
164
+ if (diagnostics.commandMatchesRuntime !== undefined) {
165
+ lines.push(`- command matches runtime: ${diagnostics.commandMatchesRuntime ? 'yes' : 'no'}`);
166
+ }
167
+ lines.push(formatRemediation(workspace, target, options));
168
+ return Object.assign(new Error(lines.join('\n')), { diagnostics });
169
+ }
170
+
128
171
  async function hasProjectWiki(projectRoot) {
129
172
  return exists(join(projectRoot, 'llm-wiki', 'wiki'));
130
173
  }
@@ -190,6 +233,74 @@ export function compareVersions(a, b) {
190
233
  return left.prerelease > right.prerelease ? 1 : -1;
191
234
  }
192
235
 
236
+ async function npmGlobalInfo(options = {}) {
237
+ const rootResult = await runCommand(npmCommand(), ['root', '-g'], {
238
+ ...options,
239
+ label: 'npm root -g',
240
+ timeout: options.timeout || 30000,
241
+ });
242
+ assertCommandOk(rootResult, 'npm root -g');
243
+ const prefixResult = await runCommand(npmCommand(), ['prefix', '-g'], {
244
+ ...options,
245
+ label: 'npm prefix -g',
246
+ timeout: options.timeout || 30000,
247
+ });
248
+ assertCommandOk(prefixResult, 'npm prefix -g');
249
+ const root = rootResult.stdout.trim().split(/\r?\n/).at(-1) || '';
250
+ const prefix = prefixResult.stdout.trim().split(/\r?\n/).at(-1) || '';
251
+ return {
252
+ root,
253
+ prefix,
254
+ packageRoot: root ? join(root, packageName()) : '',
255
+ };
256
+ }
257
+
258
+ async function commandInfo(options = {}) {
259
+ const paths = await commandPaths('llm-wiki', options);
260
+ const commandPath = paths[0] || null;
261
+ const matchesRuntime = await commandMatchesRuntime(commandPath, binPath, {
262
+ ...options,
263
+ installSource: detectInstallSource(),
264
+ });
265
+ return {
266
+ path: commandPath,
267
+ paths,
268
+ matchesRuntime: Boolean(matchesRuntime),
269
+ };
270
+ }
271
+
272
+ function runtimeSatisfiesTarget(runtime, targetVersion) {
273
+ return compareVersions(runtime, targetVersion) >= 0;
274
+ }
275
+
276
+ function rootMatchesActiveRuntime(npmPackageRoot) {
277
+ return sameResolvedPath(npmPackageRoot, packageRoot) ||
278
+ resolve(npmPackageRoot || '') === resolve(packageRoot);
279
+ }
280
+
281
+ async function preflightRuntimeUpdate(check, workspace, target, options = {}) {
282
+ const npmGlobal = await npmGlobalInfo(options);
283
+ const command = await commandInfo(options);
284
+ if (check.updateAvailable && detectInstallSource() === 'npm' && !rootMatchesActiveRuntime(npmGlobal.packageRoot)) {
285
+ throw createUpdateVerificationError(
286
+ 'The active llm-wiki runtime is not under the npm global root that this update command would modify.',
287
+ {
288
+ registryTarget: check.latestVersion,
289
+ runtimeBefore: check.installedVersion,
290
+ activePackageRoot: packageRoot,
291
+ npmRoot: npmGlobal.root,
292
+ npmPackageRoot: npmGlobal.packageRoot,
293
+ commandPath: command.path,
294
+ commandMatchesRuntime: command.matchesRuntime,
295
+ },
296
+ workspace,
297
+ target,
298
+ options
299
+ );
300
+ }
301
+ return { npmGlobal, command };
302
+ }
303
+
193
304
  export async function checkForUpdate(options = {}) {
194
305
  const target = options.to || 'latest';
195
306
  const installedVersion = runtimeVersion();
@@ -297,9 +408,10 @@ export async function update(options = {}) {
297
408
  }
298
409
 
299
410
  const target = options.to || 'latest';
411
+ const beforeDiagnostics = await preflightRuntimeUpdate(check, workspace, target, options);
300
412
  const shouldRunNpmInstall = check.updateAvailable;
301
413
  const installResult = shouldRunNpmInstall
302
- ? await runCommand(npmCommand(), ['install', '-g', `${packageName()}@${target}`], {
414
+ ? await runCommand(npmCommand(), ['install', '-g', packageSpec(target)], {
303
415
  ...options,
304
416
  label: 'npm install -g',
305
417
  timeout: options.timeout || 120000,
@@ -310,6 +422,25 @@ export async function update(options = {}) {
310
422
  stderr: '',
311
423
  };
312
424
  assertCommandOk(installResult, 'npm install -g');
425
+ const runtimeAfterInstall = runtimeVersion();
426
+ if (shouldRunNpmInstall && !runtimeSatisfiesTarget(runtimeAfterInstall, check.latestVersion)) {
427
+ throw createUpdateVerificationError(
428
+ 'npm install -g exited successfully, but the active runtime version did not change to the registry target.',
429
+ {
430
+ registryTarget: check.latestVersion,
431
+ runtimeBefore: check.installedVersion,
432
+ runtimeAfter: runtimeAfterInstall,
433
+ activePackageRoot: packageRoot,
434
+ npmRoot: beforeDiagnostics.npmGlobal.root,
435
+ npmPackageRoot: beforeDiagnostics.npmGlobal.packageRoot,
436
+ commandPath: beforeDiagnostics.command.path,
437
+ commandMatchesRuntime: beforeDiagnostics.command.matchesRuntime,
438
+ },
439
+ workspace,
440
+ target,
441
+ options
442
+ );
443
+ }
313
444
 
314
445
  const postArgs = [binCommand(), 'post-update', '--workspace', workspace, '--json'];
315
446
  if (shouldUpdateAllProjects(options)) postArgs.push('--all');
@@ -328,13 +459,47 @@ export async function update(options = {}) {
328
459
  });
329
460
  assertCommandOk(postResult, 'post-update');
330
461
  const parsedPostUpdate = parseJsonOutput(postResult.stdout);
462
+ const postRuntimeVersion = parsedPostUpdate?.runtimeVersion || null;
463
+ if (shouldRunNpmInstall && postRuntimeVersion && !runtimeSatisfiesTarget(postRuntimeVersion, check.latestVersion)) {
464
+ throw createUpdateVerificationError(
465
+ 'post-update ran, but it did not run from the registry target runtime.',
466
+ {
467
+ registryTarget: check.latestVersion,
468
+ runtimeBefore: check.installedVersion,
469
+ runtimeAfter: postRuntimeVersion,
470
+ activePackageRoot: packageRoot,
471
+ npmRoot: beforeDiagnostics.npmGlobal.root,
472
+ npmPackageRoot: beforeDiagnostics.npmGlobal.packageRoot,
473
+ commandPath: beforeDiagnostics.command.path,
474
+ commandMatchesRuntime: beforeDiagnostics.command.matchesRuntime,
475
+ },
476
+ workspace,
477
+ target,
478
+ options
479
+ );
480
+ }
481
+ const afterCommand = await commandInfo(options);
482
+ const warnings = [];
483
+ if (!afterCommand.matchesRuntime) {
484
+ warnings.push(`llm-wiki command on PATH does not resolve to the active runtime: ${afterCommand.path || 'not found'}`);
485
+ }
331
486
 
332
487
  return {
333
488
  mode: 'update',
334
489
  workspace,
335
490
  before: check.installedVersion,
336
491
  target,
492
+ latest: check.latestVersion,
493
+ runtimeBefore: check.installedVersion,
494
+ runtimeAfter: runtimeAfterInstall,
495
+ postUpdateRuntime: postRuntimeVersion,
496
+ updateApplied: shouldRunNpmInstall,
497
+ runtimeVerified: runtimeSatisfiesTarget(runtimeAfterInstall, check.latestVersion),
337
498
  scope: shouldUpdateAllProjects(options) ? 'all' : 'current',
499
+ activePackageRoot: packageRoot,
500
+ npmGlobal: beforeDiagnostics.npmGlobal,
501
+ command: afterCommand,
502
+ warnings,
338
503
  npmInstall: {
339
504
  skipped: !shouldRunNpmInstall,
340
505
  stdout: installResult.stdout.trim(),