PRD 視角 · 用戶流程圖

用戶的每個選擇,
對應什麼系統行為?

三條主要流程:init 三選一改類別(folder vs LLM)刷新週報(flag 矩陣)。 每個節點都標出:用戶輸入 → 系統做什麼 → 預期產出 → 副作用 → 下一步該幹嘛。

用戶動作(指令/輸入)
決策點 / 分支
系統內部操作
快取 / 持久層
用戶可見產出

A · init 後的每一步

ccstory init 是一次性決策。三個選項對應三種「初始信任 LLM 的程度」—— Quick 信 LLM 看 folder 命名、Deep 信 LLM 看每個 session 內容、Skip 完全靠 keyword。

用戶輸入
ccstory init
沒帶 flag → 進互動式選單
系統提問
[Y] Quick  ·  [n] Deep  ·  [s] Skip
三選一
選 [Y]
分支 1 · QUICK
--quick  ~10 秒
系統做的事
① 掃過去 30 天 sessions
② 收集 {folder: [first_user_text]}
③ 一次 claude -p 整批分類
寫進哪
~/.ccstory/config.toml
[categories] block
舊 config 自動備份 .bak-<ts>
產出 / 看到
「Proposed category buckets」表格
bucket · count · projects
下一步
ccstory week
適合 folder 命名清楚的人
選 [n]
分支 2 · DEEP
--deep  ~1-3 分鐘
系統做的事
① 取樣最近 7d 內 ≤ 200 個 session
② 每天平均配額 + active_sec 排序
③ batch claude -p per-session 判斷
④ majority vote 折算回 folder 規則
寫進哪
~/.ccstory/config.toml (folder rules)
~/.ccstory/cache.db (per-session bucket)
兩處同時寫,下次跑全是 cache hit
產出 / 看到
Proposed buckets 表(majority 後的 folder 對應)
+ 提示「cached N sessions」
下一步
ccstory week
適合 folder 是品牌名 / catch-all 的人
選 [s]
分支 3 · SKIP
--skip  瞬時,無 LLM
系統做的事
scaffold 一份模板 config.toml
[categories] 留空
內建 DEFAULT_RULES 接手
寫進哪
~/.ccstory/config.toml(template)
cache.db 不會生
產出 / 看到
「Wrote template config (no LLM call)」
沒有 bucket 提案表
下一步
ccstory week 走內建 keyword
適合:離線、不信 LLM、想自己編 config

三選一的 PRD 對照

分支 耗時 用了 LLM? 寫進 cache.db? 寫進 config.toml? 下次 ccstory week 的影響
Quick ~10s 是(1 次 batch) 是(folder rules) folder rule 命中的直接定案;未命中走 layer 2 LLM(第一次跑會 call)
Deep ~1-3min 是(per-session batch) 是(per-session) 是(folder rules) folder rule + LLM cache 同時就緒 → 第一次跑就全 cache hit
Skip 瞬時 是(空 template) 完全靠內建 DEFAULT_RULES + layer 2 fresh LLM call(hybrid 預設)
關鍵設計差異:Deep 是唯一會主動寫 session_content_buckets 快取的分支。 Quick / Skip 後的第一次 ccstory week,folder 沒命中的 session 還是會走一次 LLM——只是不會跑 200 個那麼多。

B · 改 category 流程(folder vs LLM 雙 lane)

用戶看到 recap 想改類別時,會碰到 ccstory 最容易誤解的設計: category 是兩層。CLI / config 改的是 folder layer; LLM layer 只能透過清快取 + 重跑來「重新被分類」。

Lane 1 · Folder 規則(layer 1)
用戶輸入
ccstory category set research ai-proj
或直接編 ~/.ccstory/config.toml
系統做
① 寫入 [categories] table
自動 invalidate aggregate / comparison narrative cache
不動 session_content_buckets
影響快取
config.toml 即時生效
narrative cache 失效 → 下次跑會重生 3 句總結
下次跑 ccstory week
folder 命中的 session 立即重分類
layer 1 永遠優先勝過 layer 2
→ 不用加 --refresh
VS
Lane 2 · LLM 內容分類(layer 2)
用戶輸入
沒有 per-session 手動指令
只能透過下列方式「請 LLM 重判」
三種觸發力度
--refresh(清本期間 cache)
--refresh-all(清光)
init --deep(force_refresh batch)
系統做
invalidate_content_buckets(sids)
→ 刪 session_content_buckets 對應 row
→ 下次跑 resolver 標 needs_llm
影響快取
session_content_buckets 被刪掉的 row 不見了
下次跑時 Pass 2 會重 call LLM
下次跑 ccstory week
Pass 1 folder rule 先過一輪
Pass 2 沒命中的 batch claude -p
新結果寫回 cache → 之後永久 hit
兩條 lane 最終都匯流到同一個 resolver
Resolver Priority Chain
1. user_rule  →  2. llm_cache  →  3. fallback
hybrid (預設):1→2→3  ·  content:跳過 1  ·  folder:跳過 2

用戶意圖 → 該打哪個指令

用戶意圖 打的指令 為什麼
my-project 永遠歸到 research ccstory category set research my-project folder rule = layer 1,永遠勝出。下次跑即時生效。
讓 LLM 重新看內容判斷(不動 pin) ccstory week --refresh 清本週 LLM cache。folder rule 還是優先;沒 pin 的部分重 call LLM。
連 pin 的也讓 LLM 重判一次 ccstory week --classify content --refresh content 模式跳過 layer 1,--refresh 強制 LLM 重 call。
新增了一個 bucket,要套到歷史 session ccstory week --refresh-all 整表 DELETE,LLM 才會在新 bucket 體系下重判。
大改 folder 命名規則想重來 ccstory init --deep 重採樣 + force_refresh batch + 寫回 folder rule + cache。
對「特定一個 session」推翻 LLM 判斷 ⚠ 沒有此功能 目前只能升級到 folder 層 pin(影響該 folder 全部 session)。
最容易踩雷的 case:你新增一個 research bucket、 希望歷史 session「該屬於 research 的」自動歸位。但 LLM cache 是 per session_id 永久 hit,之前在「沒 research」的時代被判成 coding 的 session 不會自己改過來——你必須 --refresh-all 強制重判。

C · 刷新週報的 pipeline + flag 矩陣

ccstory week 時,底下走 7 個 stage。每個 stage 都會被特定 flag 影響、 決定要不要走 LLM、要不要寫快取。

1
Parse
~/.claude/projects/**/*.jsonl
切出每個 session
無 flag 影響
2
Window filter
留下 [since, until] 區間
本地時區午夜對齊
window 參數
3
Backfill narrative
補 per-session 一行旁白
預設用 first_user_msg
--llm-narrative
--minimal
4
Resolve bucket
Pass 1 folder rule
Pass 2 batch LLM
--classify
--refresh
--refresh-all
5
Rollup
依 bucket 加總
active hours, cost
無 flag 影響
6
Synthesis
1 次 claude -p
3 句 overall narrative
--no-aggregate
--no-compare-narrative
7
Render
terminal card + markdown
~/.ccstory/reports/
--for=obsidian
--reports-dir

七個用戶意圖 → 對應的指令組合

用戶意圖 指令 影響的 stage 預期
「平常週報,越快越好」 ccstory week 3 fallback / 4 cache hit / 6 cache hit < 1 秒(第二次起)
「年度回顧,潤稿到極致」 ccstory week --llm-narrative 3 走 claude -p ~40s × N session(顯示 ETA,可 Ctrl+C)
「只要數字,不要旁白」 ccstory week --minimal 跳過 stage 3 + 6 最快路徑,純表格
「改完 category 想看新結果」 ccstory week --refresh 清 stage 4 快取 本期間 LLM 重判一次
「讓 LLM 重新審視所有 session」 ccstory week --classify content --refresh-all stage 4 跳 folder + 全清快取 ~40s × N session,重新分桶
「丟進 Obsidian vault」 ccstory week --for=obsidian --reports-dir ~/vault/recaps stage 7 換 flavor YAML frontmatter + [[wikilinks]]
「不想看 vs 上週的對比」 ccstory week --no-compare 跳過 comparison stage(不在 7-stage 主線,但會跑) 純當期報告

PRD 視角:跑一次 ccstory week 的完整時間軸

T+0s
用戶打 ccstory week。系統印「Parsing sessions and token usage…」
T+0.2s
Stage 1-2:讀完 jsonl,過濾出窗口內的 session。終端機印 ✓ 74 sessions · 3,692 turns
T+0.4s
Stage 3:先撈 session_summaries 快取。cache hit 的不動; miss 的——預設用 first_user_msg fallback,幾乎瞬間。
↪ if --llm-narrative
miss 的 session 改走 claude -p,逐個跑 ~40s。會印 ETA 警告 + Rich progress bar,可 Ctrl+C 中斷。
T+0.6s
Stage 4 · Pass 1:每個 session 跑 resolver。命中 folder rule 的直接定案。
↪ if 有 needs_llm 的 session
Stage 4 · Pass 2:把 needs_llm 的 batch 成「一次」claude -p。 印「Content-classifying N session(s)」+ status spinner。結果寫回 session_content_buckets 表,下次跑 cache hit。
T+1s
Stage 5:依 bucket 加總 active hours / cost / turns。 印 ✓ resolved into N categories
↪ if not --no-aggregate
Stage 6:一次 claude -p 跨所有 bucket 寫 3 句 overall narrative。 cache key 是「session id 集合 + label」,沒變不重 call。
↪ if 不是 ccstory all
Comparison stage(不在 7 主線):跑 compare_to_previous, 生 vs 上期的 deltas + 旁白。可用 --no-compare 整段跳過。
T+1.5s
Stage 7:渲染。終端機印卡片 + 寫 ~/.ccstory/reports/recap-2026-W20.md。 最後一行 breadcrumb:「Bucket looks wrong? ccstory category set …
用戶看到 bucket 分錯 → 回到 Section B 改類別 → --refresh → 回來再跑一次。 這是 ccstory 的核心 feedback loop。
三個 stage 是 LLM 入口(cyan 邊框那三個): Stage 3(per-session 旁白)、Stage 4(per-session 分類)、Stage 6(per-period 總結)。 每個都有獨立 cache。Stage 4 cache 用 session_id 為 key 是 forever cache; Stage 3 cache 同理;Stage 6 cache 用 (label + 規則指紋) 為 key,改 category 會自動失效

把三段流程串起來:典型新用戶 7 天

Day 1
pipx install ccstoryccstory init → 選 [Y] Quick。 看到提案 bucket 表,覺得「coding 包太雜」。
Day 1+5min
ccstory week。看到 coding 53%。覺得有個 folder research-ai-tools 應該歸到 research。
Day 1+10min
ccstory category set research research-ai-toolsccstory week --refresh。看到 research 17% 出現了。滿意。
Day 2-6
每天工作,~/.claude/projects/ 自動長新 jsonl。ccstory 不會主動跑。
Day 7 (週日晚)
ccstory week。新的一週、cache hit 為主、< 1 秒跑完。 卡片 + markdown 報告當作週報素材。
某次升級 Claude Code,覺得 LLM 模型可能變強了 → ccstory week --refresh-all 一次性重判全歷史。