llm-wiki-kit 0.2.9 → 0.2.11
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/README.md +10 -7
- package/docs/concepts.md +10 -8
- package/docs/integrations/claude-code.md +1 -1
- package/docs/integrations/codex.md +2 -2
- package/docs/manual.md +37 -8
- package/docs/operations.md +25 -3
- package/package.json +1 -1
- package/src/capture-policy.js +19 -19
- package/src/cli.js +19 -2
- package/src/consolidate.js +62 -29
- package/src/live-qa.js +321 -0
- package/src/maintenance.js +97 -2
- package/src/project.js +2 -26
- package/src/templates.js +19 -10
- package/src/wiki-lint.js +96 -9
- package/src/wiki-search.js +84 -19
- package/src/wiki-visibility.js +76 -0
package/README.md
CHANGED
|
@@ -89,11 +89,11 @@ The installed hooks:
|
|
|
89
89
|
- inject functional compact context at session start, instructions loaded, and prompt submit. The hook still uses `wiki/memory.md`, `wiki/index.md`, relevant wiki search results, maintenance signals, update status, and any compact recovery packet; it formats only the useful parts so user-visible hook context does not look like a raw debug dump.
|
|
90
90
|
- remove Codex-facing legacy `oh-my-codex:wiki`/`omx_wiki` surfaces at session start so `llm-wiki/` remains the active wiki implementation
|
|
91
91
|
- record small redacted raw event envelopes and per-turn state
|
|
92
|
-
- capture decision points,
|
|
93
|
-
- before compaction, classify the current turn and save a redacted checkpoint for meaningful or durable
|
|
92
|
+
- capture meaningful work and structured decision points, including tool evidence, changed files, and verification notes
|
|
93
|
+
- before compaction, classify the current turn and save a redacted checkpoint only for meaningful work, structured decisions, or explicit durable requests; explicit durable candidates also get a maintenance queue item when no durable wiki update is detected
|
|
94
94
|
- after compaction, store the redacted compact summary only; if pre-compact preservation failed, prepare a recovery packet for the next legal model-visible context hook
|
|
95
95
|
- allow tool calls to proceed without secret/PII-based hook blocking
|
|
96
|
-
- update `llm-wiki/outputs/questions/YYYY-MM-DD
|
|
96
|
+
- update chunked `llm-wiki/outputs/questions/YYYY-MM-DD/live-qa-001.md` style archives only for meaningful work or structured decision turns
|
|
97
97
|
- avoid automatic `wiki/queries/` and `wiki/decisions/` promotion in the default answer-first mode
|
|
98
98
|
- queue durable cleanup candidates only for explicit documentation requests that were not reflected in durable wiki files, or when stale turn state is recovered
|
|
99
99
|
- recover stale per-turn state into that queue on the next session start or prompt submit when the previous stop hook did not complete
|
|
@@ -112,6 +112,7 @@ Most users should not need these during daily Claude Code/Codex work. They exist
|
|
|
112
112
|
- Diagnostics: `llm-wiki doctor`, `llm-wiki status`, `llm-wiki version`
|
|
113
113
|
- Manual: `llm-wiki manual`
|
|
114
114
|
- Agent maintenance helpers: `llm-wiki context`, `llm-wiki lint`, `llm-wiki consolidate`, `llm-wiki maintenance`
|
|
115
|
+
- Live Q&A archive helper: `llm-wiki archive-questions --workspace <project> [--date YYYY-MM-DD] [--dry-run]`
|
|
115
116
|
- Cleanup: `llm-wiki uninstall`
|
|
116
117
|
|
|
117
118
|
`llm-wiki manual` prints the full package manual from `docs/manual.md`. Keep that document current when adding public commands, options, hook behavior, directory conventions, security policy, or update flows.
|
|
@@ -126,13 +127,15 @@ Installed npm runtimes also perform a cached update notice check from hooks whil
|
|
|
126
127
|
|
|
127
128
|
`llm-wiki post-update --workspace <project>` reapplies the current runtime's hook entries and safe managed template updates without running `npm install -g`. Use `post-update --all --workspace <search-root>` to reapply templates across discovered project roots.
|
|
128
129
|
|
|
129
|
-
`llm-wiki context "<query>"` prints the full debug view of the layered context sources used by hooks. Hook injection may render those sources as functional compact context for Codex and Claude, but this CLI stays verbose so maintainers can inspect retrieval, snippets, memory, index, and
|
|
130
|
+
`llm-wiki context "<query>"` prints the full debug view of the layered context sources used by hooks. Hook injection may render those sources as functional compact context for Codex and Claude, but this CLI stays verbose so maintainers can inspect retrieval, snippets, memory, index, expansion behavior, and context budget metadata. Daily use should rely on hook injection. By default, episodic `wiki/queries/`, `wiki/context/`, and `session-log` pages are excluded from search unless they were promoted with `memory_type: semantic` or `procedural` and `importance >= 4`; use `--include-episodic` only when debugging old automatic records. Archived or superseded pages are hidden unless `--include-archived` is requested, while stale pages remain searchable with lower score.
|
|
130
131
|
|
|
131
|
-
`llm-wiki lint` checks wiki health and detects outdated managed rules from older kit versions. Agents may use it before/after meaningful wiki maintenance.
|
|
132
|
+
`llm-wiki lint` checks wiki health and detects outdated managed rules from older kit versions. It also warns when `memory.md` is near budget, wiki page count nears the search cap, hidden episodic/context pages accumulate, or stale/archived pages lack supersession/link discoverability. Agents may use it before/after meaningful wiki maintenance.
|
|
132
133
|
|
|
133
|
-
`llm-wiki consolidate` refreshes only generated marker blocks in `wiki/memory.md` and `wiki/index.md`. It is an agent maintenance helper, not a command users should run after every turn.
|
|
134
|
+
`llm-wiki consolidate` refreshes only generated marker blocks in `wiki/memory.md` and `wiki/index.md`. Generated maps keep durable non-archived pages, hide default episodic records, skip stale/archived/superseded pages, and report those counts in dry-run output. It is an agent maintenance helper, not a command users should run after every turn.
|
|
134
135
|
|
|
135
|
-
`llm-wiki maintenance` prints the pending queue from `llm-wiki/outputs/maintenance/queue.md`. Hooks create only selective candidates; the active agent should merge reusable items into existing durable wiki pages and mark queue items `done` or `skipped` without delaying unrelated user answers.
|
|
136
|
+
`llm-wiki maintenance` prints the pending queue and review due status from `llm-wiki/outputs/maintenance/queue.md`. Hooks create only selective candidates; the active agent should merge reusable items into existing durable wiki pages and mark queue items `done` or `skipped` without delaying unrelated user answers. Periodic maintenance is a soft agent-side reminder, not a user command loop.
|
|
137
|
+
|
|
138
|
+
`llm-wiki archive-questions` splits older legacy `llm-wiki/outputs/questions/YYYY-MM-DD-live-qa.md` files into the chunked `llm-wiki/outputs/questions/YYYY-MM-DD/` layout. It preserves the original under `outputs/questions/archive/originals/` with a SHA-256 sidecar and replaces the legacy file with a short pointer stub. Use `--dry-run` first when reviewing a large archive.
|
|
136
139
|
|
|
137
140
|
`llm-wiki projects --workspace /apps` lists project roots that already have `llm-wiki-kit` state or an older `llm-wiki/wiki/index.md`, and shows the update commands to run. `llm-wiki update --workspace /apps` updates the global runtime once, then reapplies managed templates across every known or discovered project root under `/apps`.
|
|
138
141
|
|
package/docs/concepts.md
CHANGED
|
@@ -18,11 +18,12 @@ The important behavior is a loop:
|
|
|
18
18
|
2. `memory.md`, `index.md`, and relevant wiki context are injected automatically with an answer-first instruction.
|
|
19
19
|
3. The user works normally; no extra command loop is required.
|
|
20
20
|
4. Hooks gather redacted prompt/tool/result summaries.
|
|
21
|
-
5. At stop/session end, hooks append redacted live Q&A only for
|
|
22
|
-
6.
|
|
23
|
-
7.
|
|
24
|
-
8.
|
|
25
|
-
9.
|
|
21
|
+
5. At stop/session end, hooks append redacted chunked live Q&A only for turns with work evidence or structured decision/debugging conclusions.
|
|
22
|
+
6. Simple answers, status checks, and keyword-only responses stay out of live Q&A and durable wiki by default.
|
|
23
|
+
7. Durable wiki promotion is selective: explicit record/document requests should be handled by the active agent in existing wiki pages; the hook queues review only when such a request was not reflected in durable files.
|
|
24
|
+
8. At the next start/prompt after an abrupt shutdown, hooks can recover stale turn state into `outputs/maintenance/queue.md`.
|
|
25
|
+
9. When reusable knowledge appears, the active Claude Code/Codex agent folds approved facts into existing durable wiki pages instead of leaving everything as one-off Q&A.
|
|
26
|
+
10. Future sessions start from the improved wiki instead of relying on long chat history.
|
|
26
27
|
|
|
27
28
|
The kit is a template/runtime repository. It must not centralize project wiki contents.
|
|
28
29
|
|
|
@@ -39,7 +40,8 @@ The maintenance loop is intentionally layered:
|
|
|
39
40
|
|
|
40
41
|
- `memory.md`: short hot index for current durable facts.
|
|
41
42
|
- `index.md`: broad navigation map.
|
|
42
|
-
- MiniSearch + wikilinks: retrieval over durable `wiki/**/*.md`, with episodic `wiki/queries
|
|
43
|
+
- MiniSearch + wikilinks: retrieval over durable `wiki/**/*.md`, with episodic `wiki/queries/`, `wiki/context/`, and `session-log` pages hidden by default unless promoted or `--include-episodic` is requested; archived/superseded pages stay preserved but hidden unless `--include-archived` is requested.
|
|
43
44
|
- `outputs/maintenance/queue.md`: selective reminders for explicit durable requests that need review, plus stale turn recovery.
|
|
44
|
-
- `lint`: finds broken links, stale pages, duplicates, metadata gaps, secret-like content,
|
|
45
|
-
- `
|
|
45
|
+
- `lint`: finds broken links, stale pages, duplicates, metadata gaps, secret-like content, outdated managed rules, memory/page-count budget pressure, hidden episodic growth, and stale/archived discoverability gaps.
|
|
46
|
+
- `maintenance`: reports `reviewDue` only when periodic thresholds are met; hook reminders are soft and limited to session start/instructions loaded or maintenance-related prompts.
|
|
47
|
+
- `consolidate`: agent helper that refreshes generated blocks in `memory.md` and `index.md` while preserving handwritten notes, keeping default query/context/session pages out of the durable generated maps, and skipping stale/archived/superseded pages.
|
|
@@ -44,7 +44,7 @@ The hook records redacted turn summaries but does not deny tool calls only becau
|
|
|
44
44
|
|
|
45
45
|
At `SessionStart`/`InstructionsLoaded`, the hook first attempts a safe managed-template refresh, recovers stale turn state into `outputs/maintenance/queue.md`, performs a cached npm update notice check for npm installs, then injects functional compact context. The context still uses `llm-wiki/wiki/memory.md`, `llm-wiki/wiki/index.md`, relevant wiki/search state, operating rules, maintenance signals, passive runtime update status, and managed-template cleanup notes; the hook formats those signals so they are usable if shown in the Claude Code UI. At `UserPromptSubmit`, it recovers stale turn state, searches wiki pages with MiniSearch or substring fallback, expands one-hop wikilinks, redacts context fields, performs the same cached update notice check, and injects the smallest useful functional compact context set. Update notice cache is scoped by npm command, and maintenance reminders are shown only when the prompt is wiki/maintenance related or matches a queue topic.
|
|
46
46
|
|
|
47
|
-
`PostToolUse` and `PostToolBatch` record redacted tool summaries in the same turn buffer. `PreCompact` classifies the current turn before compaction: simple turns record only a context note,
|
|
47
|
+
`PostToolUse` and `PostToolBatch` record redacted tool summaries in the same turn buffer. `PreCompact` classifies the current turn before compaction: simple turns record only a context note, work-evidence or structured-decision turns write a chunked live Q&A checkpoint, and explicit durable candidates write a maintenance queue item only when no durable wiki update is detected. The checkpoint can include only a bounded redacted transcript tail, never the full raw transcript or raw `transcript_path`. Compaction is not blocked; if checkpoint storage fails, the hook records a compact recovery packet for the next legal context-injection event. `PostCompact` stores the redacted compact summary as a context note and prepares any pending recovery packet without returning model-visible context directly. In the default `answer-first` mode, `SubagentStop` does not create live Q&A, query, decision, or maintenance files. `Stop` and `SessionEnd` append chunked live Q&A only for work-evidence or structured-decision turns and do not auto-create `wiki/queries/` or `wiki/decisions/`. If the user explicitly asked to record or document durable knowledge and no durable wiki update is detected, `Stop`/`SessionEnd` queue a pending maintenance item for agent review. `Stop` and `SessionEnd` then clear the per-session turn buffer; `SubagentStop` does not.
|
|
48
48
|
|
|
49
49
|
Set `LLM_WIKI_KIT_AUTO_PROJECT_UPDATE=0` only while diagnosing automatic managed-template refresh behavior.
|
|
50
50
|
Set `LLM_WIKI_KIT_UPDATE_NOTICE=0` only while suppressing the cached passive runtime update status.
|
|
@@ -33,9 +33,9 @@ Expected behavior:
|
|
|
33
33
|
- `UserPromptSubmit` recovers stale turn state, searches project wiki pages with MiniSearch or substring fallback, expands one-hop wikilinks, redacts context fields, performs the same cached update notice check, and injects the smallest useful functional compact context set. Update notice cache is scoped by npm command, and maintenance reminders are shown only when the prompt is wiki/maintenance related or matches a queue topic.
|
|
34
34
|
- `PreToolUse` records redacted tool summaries without blocking tool calls.
|
|
35
35
|
- `PostToolUse` records redacted tool summaries in a turn buffer.
|
|
36
|
-
- `PreCompact` classifies the current turn before compaction. Simple turns record only a context note;
|
|
36
|
+
- `PreCompact` classifies the current turn before compaction. Simple turns record only a context note; work-evidence or structured-decision turns write a chunked live Q&A checkpoint; explicit durable candidates write a maintenance queue item only when no durable wiki update is detected. The checkpoint can include only a bounded redacted transcript tail, never the full raw transcript or raw `transcript_path`. Compaction is not blocked; if checkpoint storage fails, the hook records a compact recovery packet for the next legal context-injection event.
|
|
37
37
|
- `PostCompact` stores the redacted compact summary as a context note and prepares any pending compact recovery packet. It does not return `hookSpecificOutput.additionalContext`, because Codex `PostCompact` only supports common output fields.
|
|
38
|
-
- In the default `answer-first` mode, `SubagentStop` does not create live Q&A, query, decision, or maintenance files. `Stop` appends live Q&A only for
|
|
38
|
+
- In the default `answer-first` mode, `SubagentStop` does not create live Q&A, query, decision, or maintenance files. `Stop` appends chunked live Q&A only for work-evidence or structured-decision turns and does not auto-create `wiki/queries/` or `wiki/decisions/`.
|
|
39
39
|
- If the user explicitly asked to record or document durable knowledge and no durable wiki update is detected, `Stop` queues a pending maintenance item for agent review.
|
|
40
40
|
- `Stop` clears the per-session turn buffer after recording. `SubagentStop` leaves the parent turn buffer available for the final stop event.
|
|
41
41
|
|
package/docs/manual.md
CHANGED
|
@@ -63,9 +63,9 @@ llm-wiki/
|
|
|
63
63
|
설치된 hook은 다음 일을 자동으로 수행한다.
|
|
64
64
|
|
|
65
65
|
- session start, instructions loaded, prompt submit 시점에 functional compact context를 주입한다. `wiki/memory.md`, `wiki/index.md`, 관련 wiki 검색 결과, maintenance signal, update status, compact recovery packet은 계속 사용하되 사용자 화면에 보일 수 있는 hook context는 필요한 정보 중심으로 정제한다.
|
|
66
|
-
- pre compact 시점에는 현재 turn을 분류하고, simple turn은 context note만 남기며,
|
|
66
|
+
- pre compact 시점에는 현재 turn을 분류하고, simple turn은 context note만 남기며, 실제 작업 evidence가 있거나 구조화된 decision 결과가 있는 turn만 redacted live Q&A checkpoint로 남긴다. 명시적 durable 기록 요청이 durable wiki에 반영되지 않았을 때만 maintenance queue 후보를 남긴다. 저장 실패 시에도 compact는 진행시키고, 중요한 내용만 recovery packet으로 준비한다.
|
|
67
67
|
- prompt/tool/result summary를 redaction한 뒤 turn buffer에 기록한다.
|
|
68
|
-
- 의미 있는
|
|
68
|
+
- 의미 있는 작업/결정 turn만 `outputs/questions/YYYY-MM-DD/live-qa-001.md` 같은 chunked live Q&A archive에 남긴다.
|
|
69
69
|
- 기본 answer-first mode에서는 `wiki/queries/`와 `wiki/decisions/`를 매 turn 자동 생성하지 않는다.
|
|
70
70
|
- 사용자가 명시적으로 문서화/기록을 요청했는데 durable wiki 반영이 없으면 `outputs/maintenance/queue.md`에 정리 후보를 남긴다.
|
|
71
71
|
- 이전 session이 깨끗하게 종료되지 않았을 때 stale turn state를 maintenance queue로 복구할 수 있다.
|
|
@@ -86,9 +86,9 @@ LLM_WIKI_KIT_CAPTURE_MODE=answer-first
|
|
|
86
86
|
|
|
87
87
|
`answer-first` mode는 현재 답변을 우선한다.
|
|
88
88
|
|
|
89
|
-
- 단순 Q&A
|
|
90
|
-
-
|
|
91
|
-
- explicit durable request가
|
|
89
|
+
- 단순 Q&A, 상태 확인, 키워드만 포함된 답변은 durable wiki나 live Q&A archive로 승격하지 않는다.
|
|
90
|
+
- tool evidence, changed-file evidence, verification, 구조화된 `Decision:`/`Root cause:` 같은 결론이 있는 turn은 live Q&A archive에 남길 수 있다.
|
|
91
|
+
- explicit durable request가 durable wiki에 반영되지 않았을 때만 selective maintenance queue를 만든다.
|
|
92
92
|
- reusable fact는 active agent가 기존 wiki 문서에 병합한다.
|
|
93
93
|
|
|
94
94
|
과거 호환용 eager mode도 남아 있다.
|
|
@@ -271,6 +271,7 @@ llm-wiki context "auth architecture" --workspace /path/to/project --json
|
|
|
271
271
|
llm-wiki context "auth architecture" --workspace /path/to/project --limit 8
|
|
272
272
|
llm-wiki context "auth architecture" --workspace /path/to/project --no-expand
|
|
273
273
|
llm-wiki context "auth architecture" --workspace /path/to/project --include-episodic
|
|
274
|
+
llm-wiki context "auth architecture" --workspace /path/to/project --include-archived
|
|
274
275
|
```
|
|
275
276
|
|
|
276
277
|
읽는 자료:
|
|
@@ -281,7 +282,7 @@ llm-wiki context "auth architecture" --workspace /path/to/project --include-epis
|
|
|
281
282
|
- MiniSearch 또는 substring fallback 결과
|
|
282
283
|
- strong match의 one-hop wikilink neighbors
|
|
283
284
|
|
|
284
|
-
기본 검색은 episodic `wiki/queries
|
|
285
|
+
기본 검색은 durable semantic/procedural page를 우선하고, episodic `wiki/queries/`, `wiki/context/`, `session-log` 계열은 숨긴다. 해당 page가 `memory_type: semantic|procedural`이고 `importance >= 4`이면 promoted durable page로 취급한다. `status: archived` 또는 `superseded_by`가 있는 page도 기본 검색에서 제외하며, 필요한 조사 때만 `--include-archived`로 복구한다. `status: stale` page는 보존하고 검색할 수 있지만 score를 낮춘다. JSON 출력에는 memory/index/hit/snippet budget metadata가 포함된다.
|
|
285
286
|
|
|
286
287
|
### `llm-wiki lint`
|
|
287
288
|
|
|
@@ -302,8 +303,13 @@ llm-wiki lint --workspace /path/to/project
|
|
|
302
303
|
- secret-like content
|
|
303
304
|
- duplicate aliases/titles
|
|
304
305
|
- stale pages and orphan candidates
|
|
306
|
+
- `memory.md` near-budget/oversized 상태
|
|
307
|
+
- wiki page count가 search cap에 근접했는지
|
|
308
|
+
- default-hidden episodic/context/session page 성장
|
|
309
|
+
- stale/archived page의 supersession/link discoverability
|
|
305
310
|
- outdated managed rules/templates
|
|
306
311
|
- stale or oversized maintenance queue
|
|
312
|
+
- oversized legacy live Q&A files or oversized live Q&A chunks
|
|
307
313
|
|
|
308
314
|
broken links, invalid source IDs, secret-like content는 error이며 exit code 1을 반환한다. metadata/discoverability gap은 warning이다.
|
|
309
315
|
|
|
@@ -321,7 +327,7 @@ llm-wiki consolidate --workspace /path/to/project --dry-run
|
|
|
321
327
|
- `wiki/memory.md`의 generated memory map
|
|
322
328
|
- `wiki/index.md`의 generated page map
|
|
323
329
|
|
|
324
|
-
handwritten content는 보존한다. malformed marker block은 덮어쓰지 않고 건너뛴다. 기본 `query`, `context`, `session-log` page는 explicit durable metadata가 없으면 generated map에서 제외한다.
|
|
330
|
+
handwritten content는 보존한다. malformed marker block은 덮어쓰지 않고 건너뛴다. generated map에는 durable non-archived page만 넣는다. `stale`, `archived`, `superseded_by` page는 보존하지만 generated map에서는 제외한다. 기본 `query`, `context`, `session-log` page는 explicit durable metadata가 없으면 generated map에서 제외한다. `--dry-run` 결과는 indexed durable pages, hidden episodic pages, archived/stale/superseded skipped counts를 보고한다.
|
|
325
331
|
|
|
326
332
|
### `llm-wiki maintenance`
|
|
327
333
|
|
|
@@ -332,7 +338,30 @@ llm-wiki maintenance --workspace /path/to/project
|
|
|
332
338
|
llm-wiki maintenance --workspace /path/to/project --json
|
|
333
339
|
```
|
|
334
340
|
|
|
335
|
-
이 명령은 page merge를 자동 수행하지 않는다. active agent가 pending item을 읽고, 가장 가까운 durable wiki 문서에 병합한 뒤 queue item을 `done` 또는 `skipped`로 표시한다.
|
|
341
|
+
이 명령은 page merge를 자동 수행하지 않는다. 정기 maintenance는 agent-side task이며 사용자가 매 turn 실행할 필요가 없다. active agent가 pending item을 읽고, 가장 가까운 durable wiki 문서에 병합한 뒤 queue item을 `done` 또는 `skipped`로 표시한다.
|
|
342
|
+
|
|
343
|
+
JSON 출력에는 `reviewDue`, `reviewReasons`, `pendingCount`, `stalePendingCount`, `health`, `recommendedCommands`가 포함된다. Review due 조건은 마지막 review 후 14일 경과, pending 5개 이상, stale/result-missing pending item, lint warning/error, `memory.md` near-budget 이상, wiki page count가 search cap의 80% 이상인 경우다. Hook은 due 상태를 `SessionStart`/`InstructionsLoaded`에서만 짧게 보여주고, `UserPromptSubmit`에서는 사용자가 wiki/maintenance/정리 관련 질문을 했을 때만 보여준다. 현재 답변을 중단하거나 정리를 강제하지 않는다.
|
|
344
|
+
|
|
345
|
+
### `llm-wiki archive-questions`
|
|
346
|
+
|
|
347
|
+
legacy daily live Q&A 파일을 chunked archive layout으로 분할한다.
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
llm-wiki archive-questions --workspace /path/to/project --dry-run
|
|
351
|
+
llm-wiki archive-questions --workspace /path/to/project --date 2026-06-07
|
|
352
|
+
llm-wiki archive-questions --workspace /path/to/project --date 2026-06-07 --json
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
대상은 `outputs/questions/YYYY-MM-DD-live-qa.md` 형식의 기존 파일이다. 실행하면 원본은 `outputs/questions/archive/originals/` 아래에 SHA-256 sidecar와 함께 보존하고, 새 기록은 `outputs/questions/YYYY-MM-DD/index.md`와 `live-qa-001.md` style chunk들로 나눈다. 기존 top-level 파일은 새 위치를 가리키는 짧은 stub로 대체한다. `--dry-run`은 어떤 파일도 쓰지 않고 split 계획만 출력한다.
|
|
356
|
+
|
|
357
|
+
Agent checklist:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
llm-wiki lint --workspace /path/to/project
|
|
361
|
+
llm-wiki maintenance --workspace /path/to/project
|
|
362
|
+
llm-wiki consolidate --workspace /path/to/project --dry-run
|
|
363
|
+
llm-wiki consolidate --workspace /path/to/project
|
|
364
|
+
```
|
|
336
365
|
|
|
337
366
|
### `llm-wiki uninstall`
|
|
338
367
|
|
package/docs/operations.md
CHANGED
|
@@ -104,6 +104,7 @@ llm-wiki context "search phrase" --workspace /path/to/project
|
|
|
104
104
|
llm-wiki lint --workspace /path/to/project
|
|
105
105
|
llm-wiki consolidate --workspace /path/to/project
|
|
106
106
|
llm-wiki maintenance --workspace /path/to/project
|
|
107
|
+
llm-wiki archive-questions --workspace /path/to/project --dry-run
|
|
107
108
|
```
|
|
108
109
|
|
|
109
110
|
`status` is offline and answers whether the local installation is internally consistent:
|
|
@@ -143,7 +144,9 @@ After a plain `npm install -g llm-wiki-kit@latest`, existing hooks keep working
|
|
|
143
144
|
|
|
144
145
|
Daily use should be Claude Code/Codex first. The user should not need to run a chain of `llm-wiki` commands while working. Hooks inject context automatically, but the current user answer takes priority over wiki cleanup. The active agent updates durable wiki pages when reusable project knowledge appears and the turn's importance or user consent justifies persistence. Hook context policy is function-first: memory, search, maintenance, and update signals remain available, while user-visible context is formatted as functional compact context instead of a raw dump.
|
|
145
146
|
|
|
146
|
-
In the default `LLM_WIKI_KIT_CAPTURE_MODE=answer-first` mode, `Stop` and `SessionEnd` append live Q&A only for meaningful work turns.
|
|
147
|
+
In the default `LLM_WIKI_KIT_CAPTURE_MODE=answer-first` mode, `Stop` and `SessionEnd` append live Q&A only for meaningful work evidence or structured decision turns. Simple answers, status checks, and keyword-only responses are not archived. Live Q&A uses chunked files under `llm-wiki/outputs/questions/YYYY-MM-DD/` and rolls over by line/byte budget. Hooks do not auto-create `wiki/queries/` or `wiki/decisions/`. If the user explicitly asked for recording/documentation and no durable wiki update is detected, a pending cleanup candidate is written to `llm-wiki/outputs/maintenance/queue.md`. `PreCompact` performs the same answer-first classification before context compaction: simple turns get only a context note, archive-worthy turns get a live Q&A checkpoint, and explicit durable candidates get a checkpoint plus queue item only when needed. If checkpoint storage fails, compaction still proceeds and the hook prepares an important-only compact recovery packet for the next legal context-injection event. `SessionStart` and `UserPromptSubmit` also recover stale per-turn state into the same queue when the previous stop hook did not complete. `SessionStart` injects a one-item queue summary; `UserPromptSubmit` injects a soft reminder only when the prompt is wiki/maintenance related or matches a queue topic. This is a recovery and reminder layer, not a full transcript capture path.
|
|
148
|
+
|
|
149
|
+
Use `llm-wiki archive-questions --workspace <project> --dry-run` to review splitting legacy `outputs/questions/YYYY-MM-DD-live-qa.md` files into the chunked layout. Running it without `--dry-run` preserves the original under `outputs/questions/archive/originals/` with a checksum sidecar and replaces the legacy file with a pointer stub.
|
|
147
150
|
|
|
148
151
|
Pre-compact preservation defaults to `LLM_WIKI_KIT_PRECOMPACT_ENFORCEMENT=limited`, but compaction is never blocked by llm-wiki-kit. `limited` and `soft` emit non-blocking failure warnings, and `off` suppresses failure output. `LLM_WIKI_KIT_PRECOMPACT_TRANSCRIPT_TAIL_BYTES` controls the small bounded transcript tail used for checkpoint context. Authentication values and the raw transcript path are redacted before storage.
|
|
149
152
|
|
|
@@ -157,7 +160,7 @@ Pre-compact preservation defaults to `LLM_WIKI_KIT_PRECOMPACT_ENFORCEMENT=limite
|
|
|
157
160
|
- one-hop wikilink neighbors for the strongest matches
|
|
158
161
|
- redacted output fields for query text, memory/index/log excerpts, hit paths, titles, snippets, matched terms, and link expansion metadata
|
|
159
162
|
|
|
160
|
-
Default context search
|
|
163
|
+
Default context search prioritizes durable semantic/procedural pages. It hides episodic `wiki/queries/`, `wiki/context/`, and `session-log` pages unless they were explicitly promoted with `memory_type: semantic` or `procedural` and `importance >= 4`. It also hides `status: archived` and `superseded_by` pages unless `--include-archived` is requested. `status: stale` pages remain searchable but receive a lower score. JSON output includes memory/index/hit/snippet budget metadata so maintainers can see how much context each layer consumed. Use `--include-episodic` only when debugging historical automatic query pages:
|
|
161
164
|
|
|
162
165
|
Use it only when you want to inspect what the next agent turn should see:
|
|
163
166
|
|
|
@@ -166,6 +169,7 @@ llm-wiki context "auth architecture" --workspace /path/to/project
|
|
|
166
169
|
llm-wiki context "auth architecture" --workspace /path/to/project --json
|
|
167
170
|
llm-wiki context "auth architecture" --workspace /path/to/project --limit 8 --no-expand
|
|
168
171
|
llm-wiki context "auth architecture" --workspace /path/to/project --include-episodic
|
|
172
|
+
llm-wiki context "auth architecture" --workspace /path/to/project --include-archived
|
|
169
173
|
```
|
|
170
174
|
|
|
171
175
|
`llm-wiki lint` checks Markdown wiki health without modifying files:
|
|
@@ -179,6 +183,10 @@ llm-wiki context "auth architecture" --workspace /path/to/project --include-epis
|
|
|
179
183
|
- secret-like content patterns such as tokens, password assignments, bearer credentials, and private keys
|
|
180
184
|
- duplicate aliases or titles
|
|
181
185
|
- stale pages and orphan candidates
|
|
186
|
+
- `memory.md` near-budget or oversized state
|
|
187
|
+
- wiki page count near the default search cap
|
|
188
|
+
- default-hidden episodic/context/session page growth
|
|
189
|
+
- stale/archived pages without supersession metadata or links
|
|
182
190
|
- outdated managed rules/templates from earlier `llm-wiki-kit` versions
|
|
183
191
|
- stale or oversized maintenance queues
|
|
184
192
|
|
|
@@ -188,7 +196,10 @@ Broken links, invalid source IDs, and secret-like content are errors and return
|
|
|
188
196
|
|
|
189
197
|
- refreshes the generated block inside `wiki/memory.md`
|
|
190
198
|
- refreshes the generated block inside `wiki/index.md`
|
|
199
|
+
- keeps only durable non-archived pages in generated maps
|
|
200
|
+
- skips `stale`, `archived`, and `superseded_by` pages from generated maps while preserving them on disk
|
|
191
201
|
- excludes default `query`, `context`, and `session-log` pages from generated maps unless they are explicitly durable (`memory_type: semantic` or `procedural`, `importance >= 4`)
|
|
202
|
+
- reports indexed durable pages, hidden episodic pages, and archived/stale/superseded skipped counts, including in `--dry-run`
|
|
192
203
|
- skips malformed generated marker blocks instead of overwriting them
|
|
193
204
|
- preserves handwritten content outside marker blocks
|
|
194
205
|
- appends a log entry when files change
|
|
@@ -196,7 +207,18 @@ Broken links, invalid source IDs, and secret-like content are errors and return
|
|
|
196
207
|
|
|
197
208
|
Agents may run `consolidate` after meaningful wiki growth. Users should not need to run it after every turn.
|
|
198
209
|
|
|
199
|
-
`llm-wiki maintenance --workspace <project>` prints queue counts and the first pending items. It does not merge wiki pages by itself; the active agent should review pending items, update the closest existing durable wiki document, then mark the queue item `done` or `skipped`.
|
|
210
|
+
`llm-wiki maintenance --workspace <project>` prints queue counts, review due status, and the first pending items. It does not merge wiki pages by itself; the active agent should review pending items, update the closest existing durable wiki document, then mark the queue item `done` or `skipped`. Periodic maintenance is an agent-side task, not something users need to run after every turn.
|
|
211
|
+
|
|
212
|
+
`llm-wiki maintenance --workspace <project> --json` includes `reviewDue`, `reviewReasons`, `pendingCount`, `stalePendingCount`, `health`, and `recommendedCommands`. Review is due when the last review is older than 14 days, pending queue size reaches 5, stale or result-missing pending items exist, lint has warnings/errors, `memory.md` is near budget, or wiki page count reaches 80% of the search cap. Hook reminders are soft: `SessionStart`/`InstructionsLoaded` may show a short due note, while `UserPromptSubmit` shows it only for wiki/maintenance/cleanup-related prompts. The reminder never blocks the current answer.
|
|
213
|
+
|
|
214
|
+
Recommended agent checklist:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
llm-wiki lint --workspace /path/to/project
|
|
218
|
+
llm-wiki maintenance --workspace /path/to/project
|
|
219
|
+
llm-wiki consolidate --workspace /path/to/project --dry-run
|
|
220
|
+
llm-wiki consolidate --workspace /path/to/project
|
|
221
|
+
```
|
|
200
222
|
|
|
201
223
|
When a new runtime sees an older project, `SessionStart`/`InstructionsLoaded` automatically reapplies safe managed template updates. Files that are clearly generated by older kit versions are refreshed. Files that look user-edited are preserved and surfaced to the active agent as cleanup context instead of being overwritten. Set `LLM_WIKI_KIT_AUTO_PROJECT_UPDATE=0` only while diagnosing automatic template refresh behavior.
|
|
202
224
|
|
package/package.json
CHANGED
package/src/capture-policy.js
CHANGED
|
@@ -2,7 +2,9 @@ const NOT_CAPTURED = '(not captured)';
|
|
|
2
2
|
|
|
3
3
|
const EXPLICIT_DURABLE_RE = /(?:기록해|기록해줘|문서화|문서화해|wiki에\s*남겨|위키에\s*남겨|wiki[^.\n]{0,40}(?:남겨|저장|기록)|위키[^.\n]{0,40}(?:남겨|저장|기록)|remember\s+this|save\s+this|document\s+this|record\s+this|persist\s+this)/i;
|
|
4
4
|
|
|
5
|
-
const DURABLE_KEYWORD_RE = /(?:
|
|
5
|
+
const DURABLE_KEYWORD_RE = /(?:root cause|architecture|policy|procedure|decision|decided|migration|security|디버깅|원인|아키텍처|구조|정책|절차|결정|선택|채택|확정)/i;
|
|
6
|
+
|
|
7
|
+
const DURABLE_CONCLUSION_RE = /(?:^|\n)\s*(?:Decision|Decided|Policy|Procedure|Root cause|Resolution|Fix|Verification|결정|정책|절차|원인|해결|수정|검증)\s*[::-]/i;
|
|
6
8
|
|
|
7
9
|
const MAINTENANCE_QUERY_RE = /(?:llm-wiki|wiki|위키|maintenance|maintain|문서|문서화|기록|정리|consolidate|lint|queue|AGENTS\.md)/i;
|
|
8
10
|
|
|
@@ -44,6 +46,11 @@ export function hasDurableKeyword(value) {
|
|
|
44
46
|
return DURABLE_KEYWORD_RE.test(text);
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
export function hasDurableConclusion(value) {
|
|
50
|
+
const text = typeof value === 'string' ? value : entrySearchText(value);
|
|
51
|
+
return DURABLE_CONCLUSION_RE.test(text);
|
|
52
|
+
}
|
|
53
|
+
|
|
47
54
|
export function isMaintenanceRelatedQuery(query, pendingItems = []) {
|
|
48
55
|
const text = capturedText(query);
|
|
49
56
|
if (!text) return false;
|
|
@@ -107,37 +114,30 @@ export function classifyTurn(entry, eventName = '') {
|
|
|
107
114
|
const hasWork = Boolean(work);
|
|
108
115
|
const hasFiles = Boolean(changedFiles);
|
|
109
116
|
const hasVerification = Boolean(verification);
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
!hasFiles &&
|
|
115
|
-
!hasVerification &&
|
|
116
|
-
question.length <= 120 &&
|
|
117
|
-
result.length <= 800 &&
|
|
118
|
-
!durableKeyword;
|
|
119
|
-
|
|
120
|
-
if (simple) {
|
|
117
|
+
const hasWorkEvidence = hasWork || hasFiles || hasVerification;
|
|
118
|
+
const durableConclusion = hasDurableConclusion(text);
|
|
119
|
+
|
|
120
|
+
if (hasWorkEvidence) {
|
|
121
121
|
return {
|
|
122
|
-
kind: '
|
|
123
|
-
archive:
|
|
122
|
+
kind: hasDetectedDurableWikiChange(entry) ? 'durable-updated' : 'work',
|
|
123
|
+
archive: true,
|
|
124
124
|
suggestDurable: false,
|
|
125
125
|
queueIfMissingDurable: false,
|
|
126
126
|
};
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
if (
|
|
129
|
+
if (durableConclusion) {
|
|
130
130
|
return {
|
|
131
|
-
kind: '
|
|
131
|
+
kind: 'decision',
|
|
132
132
|
archive: true,
|
|
133
|
-
suggestDurable:
|
|
133
|
+
suggestDurable: false,
|
|
134
134
|
queueIfMissingDurable: false,
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
return {
|
|
139
|
-
kind:
|
|
140
|
-
archive:
|
|
139
|
+
kind: 'simple',
|
|
140
|
+
archive: false,
|
|
141
141
|
suggestDurable: false,
|
|
142
142
|
queueIfMissingDurable: false,
|
|
143
143
|
};
|
package/src/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import { migrate } from './migrate.js';
|
|
|
12
12
|
import { postUpdate, update } from './update.js';
|
|
13
13
|
import { buildContextPack, formatContextPack } from './wiki-search.js';
|
|
14
14
|
import { formatLintResult, runLint } from './wiki-lint.js';
|
|
15
|
+
import { archiveQuestions, formatArchiveQuestionsResult } from './live-qa.js';
|
|
15
16
|
|
|
16
17
|
function parseOptions(args) {
|
|
17
18
|
const options = {};
|
|
@@ -32,6 +33,13 @@ function parseOptions(args) {
|
|
|
32
33
|
} else if (arg === '--to') {
|
|
33
34
|
options.to = optionValue(arg, i);
|
|
34
35
|
i += 1;
|
|
36
|
+
} else if (arg === '--date') {
|
|
37
|
+
const value = optionValue(arg, i);
|
|
38
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
39
|
+
throw new Error('--date must use YYYY-MM-DD');
|
|
40
|
+
}
|
|
41
|
+
options.date = value;
|
|
42
|
+
i += 1;
|
|
35
43
|
} else if (arg === '--timeout-ms') {
|
|
36
44
|
const value = optionValue(arg, i);
|
|
37
45
|
const timeout = Number(value);
|
|
@@ -70,6 +78,8 @@ function parseOptions(args) {
|
|
|
70
78
|
options.expand = false;
|
|
71
79
|
} else if (arg === '--include-episodic') {
|
|
72
80
|
options.includeEpisodic = true;
|
|
81
|
+
} else if (arg === '--include-archived') {
|
|
82
|
+
options.includeArchived = true;
|
|
73
83
|
} else if (arg === '--replace-hooks') {
|
|
74
84
|
options.replaceHooks = true;
|
|
75
85
|
} else if (arg === '--all') {
|
|
@@ -116,10 +126,11 @@ Usage:
|
|
|
116
126
|
llm-wiki hook claude <EventName>
|
|
117
127
|
llm-wiki bootstrap --workspace <project>
|
|
118
128
|
llm-wiki migrate --workspace <project>
|
|
119
|
-
llm-wiki context "<query>" --workspace <project> [--limit 5] [--no-expand] [--include-episodic]
|
|
129
|
+
llm-wiki context "<query>" --workspace <project> [--limit 5] [--no-expand] [--include-episodic] [--include-archived]
|
|
120
130
|
llm-wiki lint --workspace <project>
|
|
121
131
|
llm-wiki consolidate --workspace <project> [--dry-run]
|
|
122
132
|
llm-wiki maintenance --workspace <project> [--json]
|
|
133
|
+
llm-wiki archive-questions --workspace <project> [--date YYYY-MM-DD] [--dry-run] [--json]
|
|
123
134
|
`);
|
|
124
135
|
return;
|
|
125
136
|
}
|
|
@@ -234,7 +245,13 @@ Usage:
|
|
|
234
245
|
|
|
235
246
|
if (command === 'maintenance') {
|
|
236
247
|
const projectRoot = resolve(options.workspace || process.cwd());
|
|
237
|
-
printJsonOrText(await maintenanceSummary(projectRoot, options), options, formatMaintenanceResult);
|
|
248
|
+
printJsonOrText(await maintenanceSummary(projectRoot, { ...options, includeLint: true }), options, formatMaintenanceResult);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (command === 'archive-questions') {
|
|
253
|
+
const projectRoot = resolve(options.workspace || process.cwd());
|
|
254
|
+
printJsonOrText(await archiveQuestions(projectRoot, options), options, formatArchiveQuestionsResult);
|
|
238
255
|
return;
|
|
239
256
|
}
|
|
240
257
|
|
package/src/consolidate.js
CHANGED
|
@@ -5,6 +5,14 @@ import { hasSecretLikeText, isSensitivePath, normalizeForStorage } from './redac
|
|
|
5
5
|
import { indexPage, memoryPage } from './templates.js';
|
|
6
6
|
import { collectWikiPages } from './wiki-model.js';
|
|
7
7
|
import { runLint } from './wiki-lint.js';
|
|
8
|
+
import {
|
|
9
|
+
isArchivedPage,
|
|
10
|
+
isEpisodicLayerPage,
|
|
11
|
+
isPromotedDurablePage,
|
|
12
|
+
isStalePage,
|
|
13
|
+
isSupersededPage,
|
|
14
|
+
pageImportance,
|
|
15
|
+
} from './wiki-visibility.js';
|
|
8
16
|
|
|
9
17
|
export const MEMORY_START = '<!-- llm-wiki-kit:memory-start -->';
|
|
10
18
|
export const MEMORY_END = '<!-- llm-wiki-kit:memory-end -->';
|
|
@@ -37,37 +45,53 @@ function pageReference(page) {
|
|
|
37
45
|
return `[[${pageTarget(page)}|${page.title}]]`;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
|
-
function importance(page) {
|
|
41
|
-
const value = Number(page.frontmatter.importance || 0);
|
|
42
|
-
return Number.isFinite(value) ? value : 0;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
48
|
function isPromotableEpisodicPage(page) {
|
|
46
|
-
return
|
|
49
|
+
return isPromotedDurablePage(page);
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
) {
|
|
61
|
-
|
|
52
|
+
function classifyGeneratedPages(pages) {
|
|
53
|
+
const stats = {
|
|
54
|
+
durablePages: 0,
|
|
55
|
+
memoryPages: 0,
|
|
56
|
+
hiddenEpisodicPages: 0,
|
|
57
|
+
archivedSkippedPages: 0,
|
|
58
|
+
staleSkippedPages: 0,
|
|
59
|
+
supersededSkippedPages: 0,
|
|
60
|
+
sensitiveSkippedPages: 0,
|
|
61
|
+
};
|
|
62
|
+
const candidates = [];
|
|
63
|
+
for (const page of pages) {
|
|
64
|
+
if (['wiki/index.md', 'wiki/log.md', 'wiki/memory.md'].includes(page.rel)) continue;
|
|
65
|
+
if (isSensitivePath(page.rel) || isSensitivePath(page.title) || hasSecretLikeText(`${page.rel}\n${page.title}\n${page.content}`)) {
|
|
66
|
+
stats.sensitiveSkippedPages += 1;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (isArchivedPage(page)) {
|
|
70
|
+
stats.archivedSkippedPages += 1;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (isSupersededPage(page)) {
|
|
74
|
+
stats.supersededSkippedPages += 1;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (isStalePage(page)) {
|
|
78
|
+
stats.staleSkippedPages += 1;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (isEpisodicLayerPage(page) && !isPromotableEpisodicPage(page)) {
|
|
82
|
+
stats.hiddenEpisodicPages += 1;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
candidates.push(page);
|
|
62
86
|
}
|
|
63
|
-
|
|
87
|
+
stats.durablePages = candidates.length;
|
|
88
|
+
return { candidates, stats };
|
|
64
89
|
}
|
|
65
90
|
|
|
66
91
|
function sortedPages(pages) {
|
|
67
92
|
return pages
|
|
68
|
-
.filter(isGeneratedBlockCandidate)
|
|
69
93
|
.sort((a, b) => {
|
|
70
|
-
const importanceDiff =
|
|
94
|
+
const importanceDiff = pageImportance(b) - pageImportance(a);
|
|
71
95
|
if (importanceDiff !== 0) return importanceDiff;
|
|
72
96
|
const typeDiff = String(a.type || '').localeCompare(String(b.type || ''));
|
|
73
97
|
if (typeDiff !== 0) return typeDiff;
|
|
@@ -75,12 +99,16 @@ function sortedPages(pages) {
|
|
|
75
99
|
});
|
|
76
100
|
}
|
|
77
101
|
|
|
78
|
-
function buildGeneratedMemoryBlock(pages) {
|
|
79
|
-
const
|
|
102
|
+
function buildGeneratedMemoryBlock(pages, stats) {
|
|
103
|
+
const allCandidates = sortedPages(pages);
|
|
104
|
+
const candidates = allCandidates.slice(0, 25);
|
|
105
|
+
stats.memoryPages = candidates.length;
|
|
80
106
|
const lines = [
|
|
81
107
|
'## Generated Memory Map',
|
|
82
108
|
'',
|
|
83
|
-
`-
|
|
109
|
+
`- Durable pages indexed: ${allCandidates.length}`,
|
|
110
|
+
`- Hidden episodic pages: ${stats.hiddenEpisodicPages}`,
|
|
111
|
+
`- Skipped archived/stale/superseded pages: ${stats.archivedSkippedPages}/${stats.staleSkippedPages}/${stats.supersededSkippedPages}`,
|
|
84
112
|
];
|
|
85
113
|
if (candidates.length === 0) {
|
|
86
114
|
lines.push('- No durable pages found yet.');
|
|
@@ -91,7 +119,7 @@ function buildGeneratedMemoryBlock(pages) {
|
|
|
91
119
|
const metadata = [
|
|
92
120
|
page.type || 'unknown',
|
|
93
121
|
page.memoryType ? `memory:${page.memoryType}` : '',
|
|
94
|
-
|
|
122
|
+
pageImportance(page) > 0 ? `importance:${pageImportance(page)}` : '',
|
|
95
123
|
page.confidence ? `confidence:${page.confidence}` : '',
|
|
96
124
|
].filter(Boolean).join(', ');
|
|
97
125
|
lines.push(`- ${pageReference(page)}${metadata ? ` - ${metadata}` : ''}`);
|
|
@@ -111,7 +139,7 @@ function buildGeneratedIndexBlock(pages) {
|
|
|
111
139
|
const lines = [
|
|
112
140
|
'## Generated Page Map',
|
|
113
141
|
'',
|
|
114
|
-
`-
|
|
142
|
+
`- Durable pages indexed: ${candidates.length}`,
|
|
115
143
|
];
|
|
116
144
|
if (groups.size === 0) {
|
|
117
145
|
lines.push('- No durable pages found yet.');
|
|
@@ -142,6 +170,7 @@ async function updateMarkedFile(projectRoot, rel, initialContent, startMarker, e
|
|
|
142
170
|
export async function runConsolidate(projectRoot, options = {}) {
|
|
143
171
|
const lintResult = await runLint(projectRoot, { maxFiles: options.maxFiles || 1000 });
|
|
144
172
|
const pages = await collectWikiPages(projectRoot, { maxFiles: options.maxFiles || 1000 });
|
|
173
|
+
const { candidates, stats } = classifyGeneratedPages(pages);
|
|
145
174
|
const changed = [];
|
|
146
175
|
const skipped = [];
|
|
147
176
|
|
|
@@ -151,7 +180,7 @@ export async function runConsolidate(projectRoot, options = {}) {
|
|
|
151
180
|
memoryPage(),
|
|
152
181
|
MEMORY_START,
|
|
153
182
|
MEMORY_END,
|
|
154
|
-
buildGeneratedMemoryBlock(
|
|
183
|
+
buildGeneratedMemoryBlock(candidates, stats),
|
|
155
184
|
options,
|
|
156
185
|
);
|
|
157
186
|
if (memoryChange?.changed) changed.push(memoryChange.changed);
|
|
@@ -163,7 +192,7 @@ export async function runConsolidate(projectRoot, options = {}) {
|
|
|
163
192
|
indexPage(),
|
|
164
193
|
INDEX_START,
|
|
165
194
|
INDEX_END,
|
|
166
|
-
buildGeneratedIndexBlock(
|
|
195
|
+
buildGeneratedIndexBlock(candidates),
|
|
167
196
|
options,
|
|
168
197
|
);
|
|
169
198
|
if (indexChange?.changed) changed.push(indexChange.changed);
|
|
@@ -182,6 +211,7 @@ export async function runConsolidate(projectRoot, options = {}) {
|
|
|
182
211
|
dryRun: Boolean(options.dryRun),
|
|
183
212
|
changed,
|
|
184
213
|
skipped,
|
|
214
|
+
counts: stats,
|
|
185
215
|
lint: {
|
|
186
216
|
ok: finalLintResult.ok,
|
|
187
217
|
errorCount: finalLintResult.errorCount,
|
|
@@ -197,6 +227,9 @@ export function formatConsolidateResult(result) {
|
|
|
197
227
|
`- dry run: ${result.dryRun ? 'yes' : 'no'}`,
|
|
198
228
|
`- changed: ${result.changed.length ? result.changed.map((item) => item.path).join(', ') : 'none'}`,
|
|
199
229
|
`- skipped: ${result.skipped?.length ? result.skipped.map((item) => `${item.path} (${item.reason})`).join(', ') : 'none'}`,
|
|
230
|
+
`- durable pages indexed: ${result.counts?.durablePages ?? 0}`,
|
|
231
|
+
`- hidden episodic pages: ${result.counts?.hiddenEpisodicPages ?? 0}`,
|
|
232
|
+
`- skipped archived/stale/superseded: ${result.counts?.archivedSkippedPages ?? 0}/${result.counts?.staleSkippedPages ?? 0}/${result.counts?.supersededSkippedPages ?? 0}`,
|
|
200
233
|
`- lint errors: ${result.lint.errorCount}`,
|
|
201
234
|
`- lint warnings: ${result.lint.warningCount}`,
|
|
202
235
|
].join('\n');
|