@kybird/llm-wiki 0.3.0 → 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.
package/README.md CHANGED
@@ -47,20 +47,21 @@ That's it. The agent does the rest.
47
47
  | `llm-wiki compile list` | Show raw logs not yet compiled — header date **or** content hash (`compile-state.json`), so same-day appends are caught too |
48
48
  | `llm-wiki compile index` | Rebuild `doc/wiki/index.md` (with aliases and answers), regenerate `compile-state.json`, and sync the QMD index. **This is a "compile complete" declaration** — run it after the wiki-compile skill's phases, not instead of them |
49
49
  | `llm-wiki lint` | Broken links, **evidence back-matching** (hash refs & `### Error` quotes must exist verbatim in `doc/raw/`), uncompiled concepts, metadata, staleness |
50
- | `llm-wiki board` / `board report` | Derived kanban view / dashboard (done:abandoned ratio, trend, QA reverts, waiting queue) |
50
+ | `llm-wiki board` / `board report` | Derived kanban view (text only, no flags) / dashboard (done:abandoned ratio, trend, QA reverts, waiting queue) |
51
51
  | `llm-wiki board video` | Replay `activity.jsonl` into a board timelapse MP4 (requires the `video/` Remotion project; CPU render, no GPU) |
52
- | `llm-wiki card new/show/edit` | Create and edit cards — the CLI is the only writer (sentinel-safe sections) |
52
+ | `llm-wiki monitor [--port <n>]` | Live read-only board view at `http://127.0.0.1:<n>` (default 4747) — who claimed what and for how long (`zcode · 14분`), claim expiry, REVIEW questions, gates/dependency waits, the terminal pile (종결 적체 — newest done/superseded/abandoned with timestamps), and an activity stream. A **milestone panel** (purpose axis, plan.md 3.8) shows in-progress milestones expanded with their member cards and completed ones collapsed with progress click a milestone to read its Goal (the plan's 대의) and full member list. Click any card (columns, terminal pile, activity rows) to read the full card file. Polls every 2s (re-renders only on change); the page renders agent-authored text via `textContent` only. Starting one while another monitor already listens is **idempotent** — exit 0, same URL (a port held by anything else fails with guidance). **The CLI stays the only writer** — every non-GET method gets a 405; the server keeps no state |
53
+ | `llm-wiki card new/show/edit` | Create and edit cards — the CLI is the only writer (sentinel-safe sections). `--kind milestone` creates a milestone card (the plan's 대의 lives in its Goal; not pickable, auto-completes when all members terminate); `--milestone "<title>"` attaches a card to one — membership is frontmatter, milestone progress is derived, never stored (plan.md 3.8) |
53
54
  | `llm-wiki pick --claim <name> [--card <title>]` | Atomically claim the next eligible card (lock, WIP limit, dependencies, claim expiry). `--card` claims a specific card by title — every gate still applies: a blocked pick prints why and leaves all files untouched, an unknown title fails (exit 1) |
54
55
  | `llm-wiki handoff <title> --question "…"` | Park a card for human judgment and release the claim |
55
- | `llm-wiki done <title> --result "…"` | Complete a card — Result is required |
56
+ | `llm-wiki done <title> --result "…"` | Complete a card — Result is required. Completing the last member auto-completes its milestone |
56
57
  | `llm-wiki supersede <title> --by a,b` | Replace a card by children; the parent dissolves into `superseded/` |
57
58
  | `llm-wiki abandon <title> --reason "…"` | Discard — reason required, and auto-logged to `doc/raw/` as anti-pattern material |
58
59
  | `llm-wiki reopen <title> --why "…"` | QA: revert a fake-done card back to doing |
59
60
  | `llm-wiki wait [--for handoff\|done\|any\|stall] [--since <ISO>] [--timeout <s>] [--stall-min <m>] [--json]` | Block until a board event, then exit — **exit codes are the contract: 0 = event (one line to stdout), 2 = timeout (nothing printed), 1 = error**; callers re-arm on 2 and act on 0. `--for` picks the event (`handoff` default; `stall` fires after `--stall-min` minutes of silence, default 20). `--since` (default: now) is checked *before* waiting starts, so events that piled up while the caller was busy are returned immediately. Read-only; timestamp-based (survives wholesale `activity.jsonl` rewrites), skips broken lines, waits for the file to exist, `fs.watch` + 5s poll fallback (junction-safe) |
60
61
 
61
- `search`, `lint`, `compile list|index`, `board`, `pick` accept `--json` (a `{schemaVersion: 1, kind: …}` envelope for scripts and skills). `wait --json` is different by design: it prints the matched event itself as one JSON line (or a `{action: "stall", …}` line), because callers parse that line directly.
62
+ `search`, `lint`, `compile list|index`, `board report`, `pick` accept `--json` (a `{schemaVersion: 1, kind: …}` envelope for scripts and skills). `wait --json` is different by design: it prints the matched event itself as one JSON line (or a `{action: "stall", …}` line), because callers parse that line directly.
62
63
 
63
- Any subcommand accepts `--help`/`-h` anywhere in its args: it prints that command's usage and exits 0 without touching the board — exploring a command must never mutate cards. Every card command also rejects unknown flags (`모르는 플래그`), so a typo'd flag fails loudly instead of silently no-oping.
64
+ Any subcommand accepts `--help`/`-h` anywhere in its args: it prints that command's usage and exits 0 without touching the board — exploring a command must never mutate cards. Every board and card command also rejects unknown flags (`모르는 플래그`), so a typo'd flag fails loudly instead of silently no-oping.
64
65
 
65
66
  ```bash
66
67
  # overnight re-arm loop: wake on the next handoff parked after midnight; silent exit 2 after an hour
package/bin/llm-wiki.js CHANGED
@@ -7,6 +7,7 @@ const { compile } = require('../lib/wiki-compile');
7
7
  const { lint } = require('../lib/wiki-lint');
8
8
  const { init } = require('../lib/init');
9
9
  const kanbanCmd = require('../lib/kanban-cmd');
10
+ const kanbanMonitor = require('../lib/kanban-monitor');
10
11
  const kanbanWait = require('../lib/kanban-wait');
11
12
  const skills = require('../lib/skills');
12
13
  const { findDocRoot } = require('../lib/find-doc-root');
@@ -31,20 +32,29 @@ Skills (git channel — prompt edits without npm publish, plan.md 6.2):
31
32
  [--skill <name>] sync one skill only
32
33
 
33
34
  Kanban (cards are files; CLI is the only writer):
34
- llm-wiki board [--html] [--json] Derived board view (columns, WIP, queue) / static HTML
35
+ llm-wiki board Derived board view (columns, WIP, queue) text only, no flags
35
36
  llm-wiki board report Dashboard (done:abandoned ratio, trend, reverts)
36
37
  llm-wiki board video Timelapse of board activity → MP4 (needs video/ project)
37
- llm-wiki card new "<title>" Create card (--goal, --ac, --depends, --not-before)
38
+ llm-wiki monitor [--port <n>] Live read-only board view at http://127.0.0.1:<n>
39
+ (default 4747) — claims, elapsed, gates, activity;
40
+ the CLI stays the only writer (405 on writes)
41
+ llm-wiki card new "<title>" Create card (--goal, --ac, --depends, --not-before;
42
+ --kind milestone = milestone card, --milestone "<t>"
43
+ attaches to one — plan-level grouping, plan.md 3.8)
38
44
  llm-wiki card show <title> Print card file
39
45
  llm-wiki card edit <title> Sentinel-safe edits; unknown/blank flags fail, output
40
46
  says what changed (--goal/--plan/--ac/--add-ac/
41
47
  --check-ac/--note/--renew-claim/--depends/
42
- --add-depends/--remove-depends)
48
+ --add-depends/--remove-depends/--milestone)
49
+ --milestone (re)groups an active card under a
50
+ milestone card
43
51
  llm-wiki pick --claim <name> [--card <title>]
44
52
  Atomically claim the next eligible card (locks, WIP, deps);
45
- --card names a specific card — gates are never bypassed
53
+ --card names a specific card — gates are never bypassed;
54
+ milestone cards are never picked (plan.md 3.8)
46
55
  llm-wiki handoff <title> --question "…" Park for human judgment, release claim
47
- llm-wiki done <title> --result "…" Complete (Result required)
56
+ llm-wiki done <title> --result "…" Complete (Result required). Completing the
57
+ last member auto-completes its milestone (3.8)
48
58
  llm-wiki supersede <title> --by a,b Replace by children (parent dissolves)
49
59
  llm-wiki abandon <title> --reason "…" Discard (reason required, never deleted)
50
60
  llm-wiki reopen <title> --why "…" QA: revert a fake-done card to doing
@@ -62,7 +72,7 @@ Optional:
62
72
  command ("autoUpdate": false in llm-wiki.config.json,
63
73
  or LLM_WIKI_NO_AUTO_UPDATE=1, to opt out)
64
74
  --json Machine-readable output: {schemaVersion: 1, kind: ...}
65
- (search, lint, compile list|index)
75
+ (search, lint, compile list|index, board report, pick)
66
76
  LLM_WIKI_ROOT=/path Override doc/ root location
67
77
  llm-wiki.config.json { "projectName": "...", "collections": {...},
68
78
  "hooksPath": "templates/githooks",
@@ -70,10 +80,11 @@ Optional:
70
80
  }
71
81
 
72
82
  const [, , subcommand, ...rest] = process.argv;
73
- // --json/--html은 어느 위치에 와도 플래그로 뽑아낸다 (검색어 문자열에서 제외).
83
+ // --json은 어느 위치에 와도 플래그로 뽑아낸다 (검색어 문자열에서 제외). board는
84
+ // --json/--html을 받지 않는다 — 추출된 사실을 dispatch 너머 명령에 넘겨 명시적으로
85
+ // 실패시킨다(전역 선추출이 validateFlags를 우회하게 두면 조용한 no-op 성공이 된다).
74
86
  const jsonRequested = rest.includes('--json');
75
- const htmlRequested = rest.includes('--html');
76
- const args = rest.filter(a => a !== '--json' && a !== '--html');
87
+ const args = rest.filter(a => a !== '--json');
77
88
 
78
89
  // 가드 — 탐색용 호출이 보드를 건드리지 못하게(2026-09-11·12 사고). 부작용 있는
79
90
  // 서브커맨드를 확인하려고 `pick --help`를 쳤다가 실제로 카드를 집는 일을 원천
@@ -83,7 +94,7 @@ const args = rest.filter(a => a !== '--json' && a !== '--html');
83
94
  // (kanban-cmd의 USAGE)에서 온다. 전용 문자열이 없는 읽기 전용 명령(search 등)은
84
95
  // 전체 사용법으로 대신한다. return으로 자연 종료한다 — Windows 파이프 stdout은
85
96
  // 비동기라 process.exit은 마지막 줄을 지울 수 있다(kanban-wait 교훈).
86
- const KNOWN_SUBCOMMANDS = ['search', 'compile', 'lint', 'init', 'skills', 'board', 'card',
97
+ const KNOWN_SUBCOMMANDS = ['search', 'compile', 'lint', 'init', 'skills', 'board', 'monitor', 'card',
87
98
  'pick', 'handoff', 'done', 'supersede', 'abandon', 'reopen', 'resume', 'wait'];
88
99
  if (KNOWN_SUBCOMMANDS.includes(subcommand) && (args.includes('--help') || args.includes('-h'))) {
89
100
  const usageKey = subcommand === 'card' && ['new', 'show', 'edit'].includes(args[0]) ? `card ${args[0]}` : subcommand;
@@ -125,8 +136,16 @@ switch (subcommand) {
125
136
  break;
126
137
  case 'board':
127
138
  if (args[0] === 'report') kanbanCmd.boardReport({ json: jsonRequested });
128
- else if (args[0] === 'video') kanbanCmd.boardVideo({ rest: args });
129
- else kanbanCmd.boardView({ rest: args, json: jsonRequested, html: htmlRequested });
139
+ else if (args[0] === 'video') kanbanCmd.boardVideo({ rest: args, json: jsonRequested });
140
+ else kanbanCmd.boardView({ rest: args, json: jsonRequested });
141
+ break;
142
+ case 'monitor':
143
+ // auto-update 트리거 목록에 없다 — stdout 첫 줄이 URL 계약이라 배너가 깨면
144
+ // 안 된다(wait 제외와 같은 이유). monitor는 async(멱등 재사용 검사)다.
145
+ kanbanMonitor.monitor({ rest: args, json: jsonRequested }).catch(e => {
146
+ console.error(`✗ ${e.message}`);
147
+ process.exit(1);
148
+ });
130
149
  break;
131
150
  case 'card':
132
151
  kanbanCmd.dispatchCard(args);