Commit Graph

103 Commits

Author SHA1 Message Date
Leo 249d0c8d51 docs(readme): self-hosted 快速開始改成完整流程(CF 註冊 → 裝 wrangler/acr → init 全自動)
- 步驟 1-4:申請 CF 帳號(含找 Account ID / 建 API Token 三權限表)→ 裝 wrangler → 裝 acr → acr init --self-hosted
- 附 init 實際輸出畫面(建 KV → 下載 wasm → 部署 19 Worker → seed recipe)
- 強調:用戶不需懂 git/tinygo,預編譯 wasm 從 GitHub 拉、用自己的 CF token 部署到自己帳號
- 最後手動 wrangler secret put ENCRYPTION_KEY(誠實標不自動化)
- CLI 指令表加 acr update

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 21:47:38 +08:00
Leo fb2d0b0c2d feat(self-hosted): acr init --self-hosted installer + recipe push 把關 + commit 部署 wasm
讓任何 CC 用自己的 CF 帳號一鍵 self-host arcrun(戰法轉 self-hosted 開源)。

Task 1 — acr init --self-hosted installer(用戶只給 CF Account ID + token,其餘自動):
- cli/src/lib/cf-api.ts: CfAccountClient(驗 token / 建 KV 冪等 / 建 R2 / 查 workers.dev subdomain)
- cli/src/lib/deploy.ts: 從 GitHub codeload tarball 拉部署物 → 注入用戶 KV id → wrangler deploy
  (tier1 component-builds 先、tier2 cypher-executor/registry 後;部分失敗誠實回報不假綠)
- cli/src/lib/api-recipe-seeds.ts: 10 個現役 API recipe 種子(KBDB 採 Supabase 模式)
- cli/src/commands/init.ts: initSelfHosted() 改寫成 installer 流程
- cli/src/commands/update.ts: acr update(拉新 ref 重部署)
- cypher-executor/scripts/seed-api-recipes.ts: prod 補灌腳本

Task 2 — recipe 入庫把關(封鎖自製零件後,CC 唯一能擴充的是 recipe):
- cli/src/commands/recipe.ts: 新增 probeRecipeEndpoint 打通檢查(提醒級不硬擋,
  含模板誠實說明待 run 才知,401/403 標多半缺 credential 非 bug)
- 資料外流提醒沿用既有 obtainExposureConsent(非 TTY 拒絕)

部署物產製:commit 預編譯 wasm 進 repo(推翻 rule 05「wasm 不 commit」):
- .gitignore: 放行 .component-builds/**/component.wasm(registry 中間產物仍排除)
- 只 commit 19 個正當零件 wasm;claude_api / km_writer / kbdb_upsert_block 排除
  (非薄殼、是把工作流硬塞進零件,違反 DECISIONS §1,待降級)
- rule 05 同步記錄此慣例變更 + 膨脹 trade-off

SDD: sdk-and-website/self-hosted-init.md(installer 定案)、
     component-gatekeeping/recipe-push-gatekeeping.md(recipe 把關)
README 重寫成單一 self-hosted 路徑。CLI typecheck exit 0。

未完(待 richblack):push 此 commit 到 GitHub 後 codeload 才拿得到 wasm;
用第二 CF 帳號端對端驗收 acr init --self-hosted。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 18:44:41 +08:00
Leo 51d40ee515 fix(data-exfil-warning): 移除 CLI 旗標後門 + 修 hook 誤判(閉環修正)
richblack 2026-05-30:arcrun 是 AI 的工具,AI 自己能加旗標 = 自己批准自己 = 閘門虛設
(違 DECISIONS §7 執行者不能驗證自己)。

- 移除 --confirm-exposure / --suppress-warning(CLI lib/commands/index.ts)
- 唯一通過 = 人類 TTY 互動輸入資源名;「以後不再問」改互動中詢問;非 TTY 一律拒絕「交給人類」
- hook 移除旗標放行捷徑 + 錨定指令開頭(修誤判:commit message 含字串不再被擋)

驗證:真執行=2、cd&&執行=2、commit/echo含字串=0、creds/run/ls=0;非TTY→RC1「交給人類」;CLI build 綠。
self-hosted 誠實限制:AI 直接動其 CF KV 仍可假造,無100%防法,閘門價值=拉高門檻+留痕究責。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 17:15:45 +08:00
Leo 1b36b091a5 feat(mindset): arcrun-mindset Skill + 06-mindset rules(M1 + 步驟7 mindset)
richblack 要的正式 Skill:
- skills/arcrun-mindset/SKILL.md — 給用戶專案 AI 操盤手的世界觀(DECISIONS §7 層三):
  工作流是default/零件稀有例外、AI→工具非工具→AI、arcrun不做授權、暴露需人類同意、
  誠實(不假綠/不假裝防偽/不代替人類確認/完成=客觀證據)
- .claude/rules/06-mindset.md — arcrun repo 內 CC 開發時讀(掛 CLAUDE.md 索引 + SessionStart hook)

完成 data-exfil-warning M1(誠實限制寫進 mindset)+ BACKLOG 步驟7 arcrun-mindset Skill。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 16:15:42 +08:00
Leo 9593268ea6 fix(cypher-executor): 實際移除 SVC_AI_TRANSFORM_* 型別宣告(前一 commit 漏改)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 15:17:02 +08:00
Leo 495857aebd fix(cypher-executor): 移除已刪 ai_transform 的 service binding(修 deploy 失敗)
Phase 2 刪了 ai_transform_compile/run 零件 + wrangler delete 對應 worker,但 cypher-executor
wrangler.toml 仍有 SVC_AI_TRANSFORM_COMPILE/RUN service binding,導致 deploy 報
"referenced Worker not found"(code 10143),data-exfil-warning 的 A 一直沒生效。

- wrangler.toml 移除兩個失效 [[services]]
- types.ts 移除對應 Bindings 型別宣告

deploy 成功後線上驗證:recipe push 無 consent → 403(A 生效);kbdb_get 回歸 200。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 15:15:50 +08:00
Leo f9071d153b fix(data-exfil-warning): 補上 pre-bash hook 偵測(前一 commit Edit 失敗漏掉)
前一 commit message 提及 hook 但實際因 Edit old_string 不匹配未寫入。本 commit 補上:
- pre-bash-guard 偵測 acr push / acr recipe push 無 --confirm-exposure/--suppress-warning → exit 2
- 精準排除 acr creds push(上傳加密 cred 是保護非暴露)、acr run/list 不誤擋
- 驗證:push/recipe push 無旗標=2、帶旗標=0、creds push/run/list=0

e2e(wrangler dev --local)三態全綠:webhook 無consent→403 / 帶consent→201 /
同wf再部署→201(首次問記住);recipe push 無consent→403 + 保護入口訊息。
tasks V3/V4/V6 標記。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 15:08:07 +08:00
Leo 5165884b40 merge: 資料外流警示(暴露動作需人類明示同意)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 14:46:32 +08:00
Leo 3e92d4acf6 feat(data-exfil-warning): 資料外流警示 — 暴露動作需人類明示同意
新 SDD .agents/specs/data-exfil-warning/(richblack review 過)。
觸發策略:只在「資料變成可被外部呼叫」時警示(webhook 部署 / recipe push),
不管出站打別人 API(高頻低風險)。

- C 同意憑證(exposure-consent.ts):ExposureConsent{confirmed_by_human, understood,
  confirmed_at, suppress_future};同意=法律憑證,存 record 可審
- A API 層:webhook 部署 + recipe push 首次需 consent,缺→403;首次問記住(server 端)
- B CLI(exposure-warning.ts):仿 GCP 刪 project,要打資源名確認(比 y/n 硬);
  --confirm-exposure(非互動)/ --suppress-warning(不再警示,本選擇也 log);
  非 TTY 無旗標→拒絕(AI 不替人類確認暴露);本機 config 記住已同意(不重問)
- H hook:pre-bash 偵測 acr push/recipe push 無旗標→exit 2(creds push/run 不誤擋)
- 警示是「保護措施入口」:提示 arcrun 可幫加認證/權限/限流(資安優勢)

驗收:非 TTY 拒絕未送出(exit1)、hook 精準擋放、tsc 雙邊綠。

⚠️ A+B 必須一起 deploy(API 層擋 + CLI 帶 consent),否則 push 中間狀態壞。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 14:45:43 +08:00
Leo 5178a6666f merge: Phase 3 零件投稿把關(registry 靜態把關 + PR 方向)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 13:42:46 +08:00
Leo 7d8cbe4299 docs: Phase 3 收尾 — §8 釐清零件投稿走 PR、BACKLOG 記新需求
- DECISIONS §8 釐清:執行鏈路(高頻)不依賴 CI;零件投稿(稀有)走 PR/CI 是例外、不違反精神
  (CF Workers 不能 runtime 編譯 wasm,CI 是唯一能跑 wasm 又執行者碰不到的 venue)
- BACKLOG 步驟 4 收尾(投稿改 PR,標已做/不做/未來搬 CI)
- BACKLOG 步驟 5 被 PR 方向取代;新增步驟 5b 資料外流警示(先做,需新 SDD)
- BACKLOG 待決策加:用戶 API 保護機制(入站認證,資安優勢)、recipe/part/function 架構釐清
- component-gatekeeping tasks.md 收尾狀態

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 13:42:46 +08:00
Leo 913ed79faa docs(gatekeeping): 方向修正 — 零件投稿走 GitHub PR,廢 registry self-service
richblack 2026-05-30 決定:零件投稿管道 = GitHub PR(稀有低頻事件、人 review
merge、CI 跑驗收),不是 registry submit API self-service。

理由:primitive 極少、未來絕大部分是 recipe → 新增零件稀有,不需 self-service
自動化管道。PR 天然滿足每道閘門(merge=人類閘門、CI 跑 G1/G3/Gherkin/覆蓋檢查),
且 CI 能 runtime 跑 wasm,繞開 CF Workers 不能 runtime 編譯 wasm 的 venue 牆。

黃金向量(Claude.ai 建議):價值保留、實作降級為人工核對 + B 覆蓋檢查(純靜態),
不做機器自動重跑(為不存在的規模做的過度工程 + 撞 venue 牆)。

作廢:registry submit 當主投稿管道、四路 self-service、平台 sandbox 重跑、
acr parts publish 加人類閘門。保留搬 CI:G1/G3/G4/覆蓋檢查邏輯。
已 commit 的 registry G0/G1/G3 保留不刪(G1/G3 邏輯被 CI 複用)。

§8 釐清(待確認改 DECISIONS):§8 不依賴 CI 指執行鏈路(高頻);零件投稿稀有,
走 PR/CI 不違反。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 13:07:46 +08:00
Leo 93bb4d3327 feat(registry): Phase 3 G0 人類閘門(submit 端強制人類確認 + 舉證)
- submitComponent 加 SubmitOptions(human_confirmation + gherkin_evidence + skip_acceptance)
- G0 閘門:非 skip_acceptance 的新投稿,缺 human_confirmation(confirmed_by_human
  + 非空 reason_why_not_workflow)→ 退稿指回「先試工作流,需人類確認」
- human_confirmation + gherkin_evidence 寫進 KV metadata(軌跡可審)
- components route 從 multipart/JSON 解析這些欄位傳入
- backfill(skip_acceptance)不受閘門影響

design 命名修正:投稿走既有 acr parts publish(非另建指令,符合「修改現有不重建」)。

待續: G0-CLI(acr parts publish 互動式問人類)、G4-CLI(本地跑 Gherkin + evidence)、
R5(MVP_COMPONENTS.txt 白名單 + 本機 hook)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 18:03:49 +08:00
Leo 202a5ab8d6 feat(registry): Phase 3 零件投稿靜態把關 + component-gatekeeping SDD
新 SDD .agents/specs/component-gatekeeping/(richblack 確認,含 venue 修訂 + 信任模型)。

registry 端靜態把關(CF Worker 可跑,不執行 wasm):
- G1 detectFakeComponent: 外部 URL/domain + http_request 子集偵測,硬擋退稿指回 recipe
- G3 wasmImports: 解析 wasm import section,只准 wasi_snapshot_preview1 + u6u 白名單
- G5/G6: unimplemented_steps 明列 gherkin/cold_start/runtime_compat,不假綠(§3c/§7)
- gherkin_evidence 一致性驗證(投稿者本地跑,registry 不重跑——CF 禁 runtime 編譯 wasm)

把關範圍:公共庫 + self-hosted 私人庫同一套(design §0.0)。
信任模型(design §4.5):Gherkin 全綠≠安全;純 WASI 沙箱框死能力才是發佈底氣;
第一期 evidence 可造假(誠實標明),平台重跑列未來。

hook: pre-write-guard 白名單加 component-gatekeeping / component-registry-canon SDD 目錄。

測試: sandboxAcceptance.test.ts 4 綠(含 G1 假零件被擋)。

待續(同 SDD): G4 CLI 投稿指令本地跑 Gherkin、G0 人類閘門、R5 白名單+本機 hook。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 17:53:03 +08:00
Leo fdb62e8b27 merge: Phase 2 降級假零件成 recipe + Phase 1 credential 修復
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 16:32:16 +08:00
Leo 17a076d35c feat(arcrun): Phase 2 降級假零件成 recipe + credential 鏈路修復
Phase 1(credential 注入鏈路):
- 修 auth_static_key ENCRYPTION_KEY 漂移根因(見 docs/incidents)
- component-loader: readBodyOnce() 修 "Body has already been used"

Phase 2(降級假零件成 recipe,registry/components 33→22):
- 引擎: RecipeDefinition 加 auth_service(多 recipe 共用一把 auth)
  auth-dispatcher 先查 recipe.auth_service 再 fallback componentId
- 引擎: auth_static_key inject.path + makeRecipeRunner {{auth.K}}
  (endpoint 可插 secret,解 telegram 類 URL-path token)
- 引擎: makeRecipeRunner auto-body 剔除 _ 前綴內部欄位
- 降級並刪除: kbdb_{get,create_block,patch_block,delete,ingest}
  gmail/telegram/line_notify/google_sheets(改建為 recipe)
- 刪除: ai_transform_{compile,run}(Arcrun 是 AI 呼叫的工具,
  工作流不該內嵌 AI 節點回頭呼叫 AI)
- deferred(源碼暫留): claude_api/km_writer(交 Mira 收成工作流)、
  kbdb_upsert_block(交 KBDB 出 upsert endpoint)

文件: DECISIONS.md(工作流是 default/建零件人類閘門/AI→工具)、
BACKLOG.md、auth-recipe.md §七、docs/incidents 加密 key 漂移

驗收: KBDB get/create/ingest/delete 2xx;telegram auth 注入綠;
gmail/sheets/line recipe 正確但缺 credential 未驗收;
kbdb patch 403 為 KBDB 端 bug(已交 kbdb/docs)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 16:18:18 +08:00
Leo 8c1dedaa2f chore(cypher-executor): 清除 KBDB-specific TS 邏輯與 WASM 白名單違規項
- 刪除 src/lib/kbdb-partner.ts(整檔)
- routes/auth.ts:移除 kbdb-partner import + 3 處 ensureKbdbPartner/revokeKbdbPartner 呼叫
- wrangler.toml:刪除 KBDB_BASE_URL 與 KBDB_INTERNAL_TOKEN 註解
- lib/component-loader.ts:WASM_HTTP_RUNNER_IDS 移除 claude_api + 6 個 kbdb_*;
  doc comment / wasmWorkerUrl 範例 / 第 7 步註解全部清掉 Phase 3 與 kbdb 字樣
- types.ts:Bindings 移除 KBDB_BASE_URL 宣告
- graph-executor.ts:註解範例改為非 kbdb 等效描述

同捎(分開議題,一起進):
- .gitignore 刪除
- webhooks-named.ts:resumable-workflow ?async=1 分支(waitUntil + 202)

tsc --noEmit 通過。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 19:39:01 +08:00
Leo 3de4cff014 fix(mira/feed): soften wiki status badge — 30min 不算漏了
leo 反饋:『現在出現大量的漏了,是不是出錯?』
調查:watcher 一直在跑,但 cron 5min 一輪 × 一輪最多 20 raws,
21 個剛清的假處理 + 14 個歷史舊 raw 排隊處理需要多輪 cron。

舊邏輯 30 min 就標 ⚠️ 漏了 太兇,給用戶『系統壞了』錯覺。
新邏輯:
  - < 6 min:  處理中
  - 6 min ~ 6h: ○ 等待(含 ↻ 立即優先)   ← 新增
  - > 6h: ⚠️ 漏了 ↻ (跟 wiki_giveup_scanner 6h 閾值對齊)
  - wiki-give-up tag: 🚫 放棄 ↻

對齊 scanner 邏輯:6h 前 watcher 仍會自動重試,這時間內顯示等待。
過 6h 才算真卡。
2026-05-17 19:22:21 +08:00
Leo c950778fdf feat(mira/feed): WikiStatusBadge 加 🚫 放棄 狀態 + ↻ 重試
對應 wiki_giveup_scanner workflow (mira repo) 標 wiki-give-up tag 的 raw:
顯示 🚫 放棄 ↻ 按鈕,hover 解釋。點擊清 tag + 強制重 trigger。

leo 2026-05-17 反饋 C 落地:watcher 一直 fail 的 raw 不會無限重試了,
6h+ scanner 標給棄、UI 顯示給棄、用戶可手動修。
2026-05-17 11:36:54 +08:00
Leo 175a290730 feat(mira/feed): WikiStatusBadge 加手動重試按鈕
leo 2026-05-17 反饋:「漏了的要怎麼做?會自己慢慢完成還是要手動下令?」

自動行為解釋:
  mira_feed_watcher cron 每 5 min 掃 tags=[] 的 raw 自動重試。
  但若已被 mark wiki-processed (假處理),watcher 永遠跳過 → 需手動。

互動加:
  - ⚠️ 漏了 變按鈕,click → 清 tag + 立即 trigger wiki_synthesis
  -  wiki 旁加小 ↻ icon,給「tag 標完成但實際沒 wiki」的情況用
  - 點擊後 1 分鐘內顯示「 重試中」防 spam

UX 細節:
  - title hover 解釋每個狀態跟動作
  - retry 同時清 tag + 直接 trigger(不等下個 cron tick)
  - 失敗 fail silently (catch all),1 min 後可再試

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 11:26:24 +08:00
Leo 475c95aaae feat(kbdb_upsert_block): add create_only flag (#2 stub support)
leo 反饋 2026-05-17:「至少建一個 placeholder 給未來累積」
但 upsert 預設 PATCH 既有會把完整 wiki 覆寫成 stub。

新 input field:create_only (bool, default false)
  - false (預設):既有 → PATCH (傳統 upsert 行為)
  - true:既有 → return action='exists' 不動,避免 stub 覆寫 full wiki

用於 wiki_synthesis V3.1 referenced_entities → ensure_stub_wiki_page 場景。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 11:07:31 +08:00
Leo 7dae958dbe feat(mira/wiki): backlinks section — 顯示提到此 entity 的 raw notes (#2 leo 反饋)
leo 2026-05-17 反饋:「從這本書的條目應該反向連到那篇筆記去,
如果在 Logseq 會放在下方列表提到這個條目的其他內容」

實作:
- 撈所有 content === entity 的 wiki-page (V3 一次寫入會建多個 wiki-page
  per raw mention)
- 從每個 wiki-page tags_json 取 raw:XXX tag → unique raw_ids
- fetch 對應 raw blocks → render 「📎 提到此 entity 的筆記」section
  每條 link 跳 /mira/feed#page=...
- 顯示前 100 字 preview,全文 hover title
- 樣式:左 border + 暗色背景 (區分於主內容)

對應 wiki_synthesis V3 (commit 63ac4c9 mira) 的 wiki-page tags raw:XXX
標記設計:每篇 raw 提到某 entity 時,create_wiki_page 都會寫一個新的
wiki-page (page_name 同名),tags 含 raw:{raw_id}。反查 wiki 對應 raw
不靠 KBDB graph 反向 index,純走客戶端 wiki-page list filter。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 10:40:40 +08:00
Leo 4fd2d3ba6c fix(cypher-executor): FOREACH iter plural 變體 (entity → entities)
舊 getIterableFromContext 只試 'key+s',遇 irregular plural 不命中:
  entity + s = entitys ≠ entities (Claude 真實 output)

加變體:
  - key + 's'                       (paragraph → paragraphs)
  - key.replace(/y$/, 'ies')        (entity → entities)
  - key.replace(/(s|x|z|ch|sh)$/, '$1es')  (box → boxes)
  - key (singular fallback)

對應 mira wiki_synthesis V3 multi-entity 升級需求。
2026-05-17 10:34:12 +08:00
Leo efdd75cbdc feat(mira/feed): WikiStatusBadge — 顯示貼文 wiki 合成狀態 (leo 2026-05-17 反饋)
leo 反饋:「沒有符號顯示是否已建立 wiki,不知道是出錯了還是要等下一批」

新 component WikiStatusBadge 顯示在 PostCard header 來源/時間旁邊:
-  wiki    — tags 含 wiki-processed
-  處理中  — 貼 < 6 分鐘前(cron 5 分鐘一輪,可能還沒撈到)
- ○ 排隊    — 6-30 分鐘(等下一個 tick)
- ⚠️ 漏了? — > 30 分鐘還沒處理(可能 wiki_synthesis 失敗)

Mira 自己貼文(type=wiki-page from showMira)不顯示 — 它本身就是 wiki。
資料來源純 client-side:mainBlocksList[0].tags_json + doc.created_at。
未來可加 click → 跳對應 wiki page,或 hover 顯示 entity 預覽。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 09:53:19 +08:00
Leo a7d36933e6 feat(cypher-executor): trigger_workflow status paused_awaiting_resume → running_async (LI roadmap 自評)
第一份 arcrun-roadmap (block e924c231) 提的建議:
  「paused_awaiting_resume 容易被誤讀成掛起出問題,
    考慮改成更清楚的 status(如 completed_with_checkpoint)」

我採折衷命名:running_async — 強調「workflow 已接受,正在背景跑」,
不像 completed_with_checkpoint 容易被誤讀為已完成。

範圍:
- trigger_workflow component-loader.ts status field rename
- AGENTS.md §6 common errors table 同步
- arcrun-mcp arcrun_run_workflow tool 回傳 status 同步
- error_code (telemetry classification) 仍保留 paused_awaiting_resume
  (SDD §1.4 error_code enum '可加不可刪' 承諾)

向下相容性:status 是 user-facing field,前面 dogfood 只有 weekly_review
一個 consumer 用 trigger_workflow,已同步更新。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 21:54:41 +08:00
Leo 8b54ebb68a feat(cypher-executor): step-level telemetry (LI roadmap 2026-W19 建議)
對應第一份 arcrun-roadmap (block id e924c231) 提的:
  「mira_feed_watcher 執行時間偏長(~35秒),無 error 資訊
    建議:加入 checkpoint/step-level telemetry,監測瓶頸」

新增 TelemetryEvent:
  - node_success — 單一 Component node 跑完
  - node_failure — 單一 Component node 失敗

寫入點:GraphExecutor.executeNode catch + 最終 trace.push 之後
  - 只記 node.type === 'Component'(Input/Output 跳過避免噪音)
  - 含 workflow_name + component_id + duration_ms + (error_code on fail)
  - fire-and-forget, 不擋主流程

實測(wiki_synthesis trigger 後):
  - 4 個 node_success blocks 寫入 KBDB (4 個 kbdb_get)
  - duration 範圍 653ms-2003ms,立刻看到誰是瓶頸
  - paused 的 classify (claude_api) 不算 success(trace 已記 paused 狀態)

下次 weekly_review compose_review 會看到 component-level breakdown,
能寫出「kbdb_get 平均 X ms、claude_api 平均 Y ms」等更細的分析。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 21:47:15 +08:00
Leo 8e985684f9 feat(cypher-executor): magic vars {{_today}} / {{_iso_week}} / {{_now}} 等
對應 LI SDD M2.x improvement,源自 Claude (我) 透過 arcrun_report_feedback
寫的 feedback block c47bf70b 提的「需要內建變數展開」需求。完整閉環:

  AI 用 MCP tool 報 bug → KBDB 收 feedback → AI 自己看 → 自己修補 → deploy

新增 cypher-executor/src/lib/magic-vars.ts:
  - _today / _yesterday / _now / _now_unix / _now_unix_s
  - _iso_week (2026-W20) / _iso_week_num / _iso_year
  - _yyyymm / _yyyymmdd
  - _year / _month / _day / _hour / _minute / _second(zero-padded)
  - _weekday (0-6, 0=日) / _iso_weekday (1-7, 1=一)
  全部 UTC,避免 worker 跨時區誤判

GraphExecutor.execute() 入口注入:
  ctxWithMagic = { ...initialContext, ...buildMagicVars() }
  順序確保 magic vars 永遠 win(防 user 不小心用 _ prefix)

不違反 §2.2(cypher-executor TS 禁實作 secret/JWT 業務邏輯):
  magic vars 是公開時間常數,跟既有 interpolateString 的 ctx 變數展開
  同層,純 orchestrator routing 職責。

AGENTS.md §10.5 加 magic vars 完整表 + weekly archive 範例。

實測(commit 後 deploy + 觸發 weekly_review):
  - KBDB 新建 roadmap-2026-W20 block 正確展開 page_name
  - roadmap-latest 同步更新(雙寫 pattern)
  - 證明 weekly archive 從此真能累積歷史,不再固定 latest 覆蓋

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 21:20:52 +08:00
Leo ef406d714a docs(llm-interface): tasks.md 進度更新 — M1/M2.1/M3/M4 主體完成 2026-05-16 17:37:43 +08:00
Leo 37379b71bc feat(scripts): 本機 CI/CD + registry-to-KBDB 同步 (跳過 GH Actions)
對應 leo 2026-05-16 GH Actions 配額被停 + LI SDD M3.4。

scripts/local-deploy.sh — 本機 deploy 取代 GH Actions
  - 複製 .github/workflows/deploy.yml 的 discover 邏輯
  - git diff 過濾,只 deploy 改到的 worker
  - 連動:registry/components/{X} 改了,重 build .component-builds/{X}/component.wasm
  - 分 tier1 (components) / tier2 (orchestration),依序 deploy
  - 支援:--all / --dry-run / --base <ref> / 指定 target 名稱
  - 部署前 wrangler whoami 健康檢查
  - 失敗清單彙整不中斷其他 deploy

scripts/sync-registry-to-kbdb.py — LI SDD M3.4
  - registry/examples/ → KBDB type=workflow-example (page_name=example-{slug})
  - registry/skills/ → KBDB type=agent-skill (page_name=skill-{slug})
  - 走 kbdb-upsert-block.arcrun.dev (idempotent,page_name 為 key)
  - 從 ARCRUN_API_KEY env var 或 polaris/mira/.env 取金鑰
  - 支援:--dry-run / --examples-only / --skills-only

實測:
  - sync 第一次:10 examples + 5 skills 全 created
  - 第二次:全 updated (idempotent ✓)
  - KBDB type=workflow-example / agent-skill 都看得到完整 content + tags

意義:
  - 申訴 GH Actions 期間,leo / Claude Code 可本機 deploy 不卡
  - 即使 GH 永久不通也能 ship
  - sync script 之後也能加進 cron 或 git hook 自動化

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 17:28:16 +08:00
Leo 4e7880c1cb fix(cypher-executor): /executions/paused 走 per-user index (強 consistent)
對應 LI SDD M2.1 修補。

問題:原 /executions/paused 走 EXEC_CONTEXT.list({prefix:'paused_run:'})。
CF KV list 是強 eventual consistent (30-60s 延遲),剛 paused 的 workflow
list 不會立刻看到。本機 wrangler kv list 也回 [],但 KV.get 同 task_id
能即時拿到 — 證實 list vs get 一致性層級不同。

修補:persistPausedRun 額外維護 per-user index `paused_idx:{api_key}`
(JSON Array),是單一 KV.get 拿全列表,**強 consistent 無延遲**。
consumePausedRun 同步從 index 移除。

新 helper:
- listPausedRunsByApiKey(kv, apiKey, limit) — 走 index
- PausedIndexEntry type — task_id / run_id / paused_node_id / workflow_name /
  expires_at / persisted_at

實測:trigger 後立刻 list 即時看到 paused (commit 前是 0)

副作用:index 寫入 + delete 都是 fire-and-forget 在 consume path,失敗
不擋主流程。Index entries 上限 100 防無限長。每次 read 過濾 expired。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 17:15:16 +08:00
Leo 10834ef9bb ci: 加 paths-ignore + landing concurrency cancel (省 GH Actions minutes)
對應 leo 2026-05-16 Actions 配額用爆 → 全面瘦身 CI trigger。

deploy.yml (Workers):
  既有:worker-level git diff filter(只 deploy 改到的 worker)
  新增:workflow-level paths-ignore — doc-only commit 完全不啟動 workflow
        排除:**.md / AGENTS.md / .agents/** / docs/** / registry/examples/** /
              registry/skills/** / .gitignore / LICENSE
  之前每個 doc push 都觸發 discover job 吃 ~1 min。
  本輪 LI 開發 ~10 doc-only commit = 省 ~10 min

deploy-landing.yml (Pages):
  既有:paths filter ('landing/**') 
  新增:concurrency cancel-in-progress (原 false → true)
  landing build ~3 min 是大頭,連續 push 取消舊 build 省最多
2026-05-16 16:46:40 +08:00
Leo 3892dc3a9b docs(AGENTS): 更新 LI M2.2 + M3 新 tool / examples / skills 引用
對應 LI SDD M2.2 + M3.3 + M3.1 完成。

- Step 1 加 arcrun_search_examples / arcrun_list_skills 用法
- Step 3/4/5/6 改用 arcrun_* tool prefix
- 新增 Step 7:報 feedback
- §7「不確定的時候」全部更新成 arcrun_* tool 名
- 新增「過渡期 tool 命名注意」說明:arcrun_* 主用、u6u_* 舊規範保留、
  u6u_deploy_workflow 壞掉建議改 arcrun_push_workflow
2026-05-16 16:41:35 +08:00
Leo ce693b4de1 ci: deploy.yml concurrency cancel-in-progress
leo 2026-05-16 帳號 Actions 用爆配額被 disable。連續 push 時舊跑會被
新跑取代,省 50%+ minutes。

代價:在中段 push 後 +30 秒內再 push 第三次,第二次跑被取消(不會部署)。
LI 開發階段可接受 — 開發頻率高、最終 push 才需要真實部署。

未來若需要每次都跑(例如生產穩定期),改回 false。
2026-05-16 16:39:59 +08:00
Leo 388c193ae7 docs(registry): seed 10 examples + 5 skills (LI SDD M3.1 + M3.3)
對應 .agents/specs/llm-interface/ Milestone 3.1 + 3.3。

registry/examples/ — 10 個可直接 push 的 workflow 範本:
  starter:    webhook-to-http
  common:     cron-watcher, llm-classify, rag-search-answer, daily-digest
  external:   email-summary (gmail+claude+telegram), pdf-to-blocks,
              github-issue-bot
  advanced:   parallel-fanout (trigger_workflow fan-out),
              error-retry (try_catch+wait pattern)

  每個含:workflow.yaml(可直接 push)+ description.md(解決什麼問題 /
  改成你自己的 / 學到什麼)+ tags.json(搜尋用)

registry/skills/ — 5 個 AI playbook(markdown):
  build_watcher_workflow            — cron + filter + trigger 模式
  debug_paused_workflow             — claude_api callback paused 怎麼追
  migrate_http_to_trigger_workflow  — 從 self-fetch 換 trigger_workflow
  rag_with_arcrun                   — KBDB + claude_api 組裝 RAG
  add_new_wasm_component            — TinyGo 寫 + 部署全流程

兩者差異:
  examples = 可直接拿來改的 YAML
  skills = 面對 X 問題該怎麼想 + 該用哪個 example

兩者後續:CI 自動同步進 KBDB(type=workflow-example / type=agent-skill),
MCP arcrun_search_examples / arcrun_list_skills 走 KBDB semantic search。
(CI sync 是 M3.4 工作)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 16:33:54 +08:00
Leo 989fbeb9ac feat(cypher-executor): /executions/* introspection (LI SDD M2.1)
對應 .agents/specs/llm-interface/ Milestone 2.1。給 AI debug 用的執行
狀態檢視端點。3 個新路由:

GET /executions/paused
  - 列當前 api_key 下所有 paused workflow(等 callback resume)
  - 走 EXEC_CONTEXT KV `paused_run:*` prefix scan,過濾 state.api_key
  - 回 [{task_id, run_id, paused_node_id, workflow_name, expires_at}]
  - 限 limit 100,避免 KV N+1 爆

GET /executions/:task_id
  - 看單一 paused state 細節(trace_so_far / paused_context / pending_result)
  - 隔離租戶(state.api_key !== 用戶 ak → 回 not_found 不洩漏存在性)
  - 回完整 state JSON

GET /workflows/:name/executions
  - 列某 workflow 最近 N 次執行 verdict(走 ANALYTICS_KV stats:{name}:* prefix)
  - 先驗 workflow 屬該 api_key
  - 按 timestamp 後綴 desc sort

統一 error contract(LI SDD §1.3 / §1.4 規範):
- ok: bool
- error_code: enum (auth_missing / not_found / internal_error)
- human_message: 描述
- next_actions: 陣列,給 AI 看的下一步
- hints: 成功時的 next-step 建議

不影響既有路由 contract。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 15:58:35 +08:00
Leo 04ed722591 chore: gitignore .swarm/ + ruvector.db (Claude Code local artifacts)
之前 M1.2 telemetry commit 不小心把 cypher-executor/src/.swarm/ 跟 ruvector.db
commit 進去。這些是 Claude Code 自己的本地工具產物,不該入庫。

- 加 .gitignore 樣式:.swarm/ / ruvector.db / **/.swarm/ / **/ruvector.db
- 撤回上次 commit 進去的 5 個檔案

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 15:35:55 +08:00
Leo d04e34ea35 feat(cypher-executor): implicit telemetry (LI SDD M1.2)
對應 .agents/specs/llm-interface/ Milestone 1.2。

新增 lib/telemetry.ts:
- hashApiKey(): SHA-256 截 16 hex 字元(不可逆,可聚合)
- recordTelemetry(): fetch fire-and-forget 寫 KBDB type=agent-telemetry block
- 設計:不阻擋主流程,錯誤 console.warn 不 throw
- 用 ctx.waitUntil 確保即使主 request 已回,背景仍會跑完

寫入點 3 處:
1. routes/webhooks-named.ts POST /webhooks/named (deploy) → deploy_success
2. routes/webhooks-named.ts POST /webhooks/named/:name/trigger →
   executeWebhookGraph 帶 ctx + userAgent,內部記 run_success / run_fail
3. routes/validate.ts POST /validate → validation_error (含 schema_failed / edge_node_missing)

executeWebhookGraph 簽名擴張:可選 ctx + userAgent,舊 caller (scheduled /
trigger_workflow / anonymous webhook) 不傳也 OK(telemetry 仍寫但無 ctx 加持)。

paused (workflow 因 claude_api 等等 callback resume) 算 run_success,
不污染 fail metric。

types.ts: 加 PLATFORM_API_KEY env (可選) + re-export ExecutionContext

不違反「業務邏輯走 WASM」鐵律:telemetry 是 orchestrator 觀測自身的能力,
跟 trigger_workflow / scheduled() 同類。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 15:33:35 +08:00
Leo 56973558e2 docs(arcrun): AGENTS.md v1 — AI onboarding (LI SDD M1.1)
對應 SDD .agents/specs/llm-interface/ M1.1。

LI (LLM Interface) 第一份文件:任何 AI agent 載入這份就能用 arcrun,
不用讀 SDD 內部架構、不用 grep codebase、不用問人。

包含:
- 30 秒「what is arcrun」
- MCP 連線配置(Claude Desktop / Cursor / 自製 agent 通用)
- 5 個核心概念(Component / Cypher binding / FOREACH / Paused-resume / api_key)
- 你的第一個 workflow(list → validate → push → run → trace 5 步)
- URL 慣例 + CF self-fetch 死鎖警示
- 常見錯誤 + error_code → 下一步 mapping
- 「不確定的時候」標準流程
- report_feedback 規範(**必做**)
- KBDB 速覽 + cron watcher 範例
- meta-規範:寫 workflow 的 AI 自己的習慣

901 words / 263 lines(控制在 5-8K tokens 內),純繁體中文。

CI 自動同步 KBDB block (type=agent-onboarding) 之後再做(M1.1 另一個 subtask)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 15:28:05 +08:00
Leo 180cef26c7 docs: rename SDD folders u6u-* → arcrun-* + update cross-refs
對應 SDD arcrun/.agents/specs/llm-interface/ M5.6(之前列為 backlog 連動)。
leo 2026-05-16 拍板 u6u 整體退場後,順手把兩個 SDD 也改名。

- .agents/specs/u6u-core-mvp/ → arcrun-core-mvp/
- .agents/specs/u6u-platform-evolution/ → arcrun-platform-evolution/
- CLAUDE.md / .claude/rules/00-sdd-protocol.md / 04-current-progress.md /
  llm-interface SDD 內所有跨 SDD 引用同步更新

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 15:24:22 +08:00
Leo 5d99302681 docs(llm-interface): apply leo's decisions — drop u6u + finally.click
leo 2026-05-16 拍板(除 dual-hostname 外照原設計):
1. MCP URL: 單一 mcp.arcrun.dev,mcp.finally.click 直接退場(不並存)
   - 理由:finally.click 是還沒申請新網址的暫用,那是一個服務,arcrun 是底層
2. u6u branding 整體退場:
   - u6u-mcp repo → arcrun-mcp
   - u6u-gui repo → arcrun-gui
   - u6u_* tool prefix → arcrun_*
   - 一次切換,不留 alias,不留 deprecation 期
   - 理由:u6u 不存在了

SDD 三件套同步更新:
- requirements.md: 開放問題章節改決策紀錄;移除「保留 15 tool deprecation」自相矛盾
- design.md: §1.1 命名 + §6 migration plan + §8 決策表全部改成「單一切換」
- tasks.md: M5 重組成 6 個 sub-step(準備 / repo rename / tool rename / 舊 URL 退場 / 文件 / 連動 SDD 追蹤)

連動但不在本 SDD 範圍:
- matrix/arcrun/.agents/specs/u6u-core-mvp/ 改名
- matrix/arcrun/.agents/specs/u6u-platform-evolution/ 改名
(M5.6 列出,另起 task 追蹤)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 15:09:48 +08:00
Leo c2a2f82ade docs(arcrun): SDD llm-interface — AI 操盤手使用體驗 first-class
設計動機:3 天 mira dogfood 累積 14 個痛點,7 個純粹是 LI 缺失。
arcrun 過去設計集中在「人」(u6u-gui / docs),AI 對 arcrun 的可用性
沒被當第一公民。

SDD 三件套(matrix/arcrun/.agents/specs/llm-interface/):

requirements.md
  - personas(Claude Code 主力 / 用戶私人 agent / SDK 使用者)
  - 範圍涵蓋 5 系統(cypher-executor / registry / u6u-mcp / u6u-gui / kbdb)
  - 10 個 FR:onboarding / CRUD 對等 / dry-run / 結構化 trace /
    可程式化 error / feedback tool / implicit telemetry /
    skill blocks / examples / weekly closed loop
  - 5 個 NFR:相容 / 多 transport / error contract 穩定 /
    feedback exportable / coverage 量化

design.md
  - 5 層 LI 模型:AGENTS.md / arcrun-mcp / Skills / Examples / Telemetry
  - 25 個 MCP tool 完整清單分 5 類
  - error_code enum v1
  - coverage matrix(GUI 動作 vs MCP / 31 cypher-executor 路由 vs LI)
  - 完整 AGENTS.md 模板
  - u6u-mcp → arcrun-mcp migration plan(90 天 deprecation)
  - weekly_review workflow YAML 範本

tasks.md
  - 5 個 milestone(M1 收 data / M2 gap-fill / M3 skill+examples /
    M4 closed loop / M5 rename)
  - 估算 23 個工作日 (~5 週)
  - M1 是硬前置(不收 data 改了也不知道對沒)

Audit 基準(用 4 個並行 Explore agent 整理):
  - cypher-executor: 31 HTTP 路由,9 個 AI-essential
  - u6u-mcp: 15 tool,缺 update/delete/history/validate/feedback
  - u6u-gui: 8 個人類動作可對等 LI / 3 個視覺類不需
  - kbdb: 50 路由 13 group,LI 走 abstracted tool 不直接 expose

同步更新 .claude/rules/04-current-progress.md SDD 索引。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 14:58:21 +08:00
Leo 521624261d fix(cypher-executor): trigger_workflow paused 不算失敗
watcher 實測 8/8 raw 跑通後發現 wait=true 把 wiki_synthesis paused
(claude_api 等 callback resume 的正常狀態)回報成 success:false,造成
watcher 看起來「5/8 失敗」實際是「正在背景跑」。

改成:
- isPaused 偵測「workflow paused at node X」error 字串
- isPaused → success:true, status:'paused_awaiting_resume'
- 完整完成 → status:'completed'
- 真失敗 → status:'failed'

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 14:04:12 +08:00
Leo b8ecef0b41 feat(cypher-executor): trigger_workflow 內建零件 — 繞 CF self-fetch
mira_feed_watcher 之前用 http_request 自打 cypher.arcrun.dev / 自身 workers.dev URL
都被 CF self-fetch 防護擋(Worker→自身的 subrequest 攔截)。

新增 `trigger_workflow` 內建 orchestration 零件:
- 在 createComponentLoader 最前面攔截 component_id === 'trigger_workflow'
- 從 WEBHOOKS KV 撈 `{api_key}:wf:{name}` 拿 graph
- 動態 import 避循環依賴
- in-process 呼叫 executeWebhookGraph,沒有任何外部 HTTP
- 預設 wait=true(claude_api paused 仍視為 success 回傳)

不違反「業務邏輯走 WASM」鐵律:trigger_workflow 是 orchestrator 自己的 routing
能力(像既有的 CALLS_SUBFLOW),不是業務邏輯。

對應 mira_feed_watcher.yaml 同步改用此零件(在 polaris/mira/ repo)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 13:54:26 +08:00
Leo 1084e0102a fix(mira): wikilink autocomplete 5s cache + 開下拉時 refetch
leo 反饋:30s TTL 太久,wiki_synthesis 後台跑出新 entity,autocomplete 撈不到。
- TTL 30s → 5s
- WikilinkAutocomplete 在 matchInfo 從 null → 有值時主動 invalidate refetch
- 順手把 yaml-parser 對 FOREACH iterator relation 命名變體(「對每個 X」/「FOREACH X」)放行,graph-builder 早就支援,validate 卻擋掉

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 13:37:03 +08:00
Leo 7da1eb6d65 feat(mira): [[entity]] wikilink — 顯式建檔 + autocomplete + render link
對應 tasks.md backlog #12 / design.md §3.6.2。leo 反饋:要像 Logseq 那樣
寫 [[X]] 立刻建檔,下次 [[X 自動補完,render 變連結。

helpers:
- parseWikilinks(text) → 抽 [[X]] entity list
- fetchAllEntityNames(apiKey) → 合 index-entry + wiki-page entity 名稱
- getEntityNamesCached → 30s session cache for autocomplete
- ensureEntitiesExist → 新 entity 立刻建 wiki-page placeholder
  - tags 含 entity-type:book/url/concept(guessEntityType 推測:《》→ book / http → url)
  - source: leo-explicit
- expandWikilinks(text) → render 時把 [[X]] 轉 markdown link to /mira/wiki/wiki-X

UI:
- <WikilinkAutocomplete>:textarea cursor 在 `[[query` 未閉合時,下拉顯示既存
  entity(substring filter)+「⊕ 建立 [[query]]」option,↑↓選 / Enter 確認 /
  Esc 取消。fixed-position below textarea bottom(cursor tracking 留下輪)
- PostComposer compact + popup 兩個 textarea 都掛 autocomplete
- EditingArea(PostEditor / BlockEditor / ReplyLine / PageReplyComposer 共用)
  加 apiKey prop,內部 textarea + popup 都掛 autocomplete

submit hook:
- PostComposer.submit:postBlockId 建好後 ensureEntitiesExist(wikilinks)
- BlockEditor.submitReply / ReplyLine.submitReply 同樣建檔
- 在 wiki_synthesis trigger 前先建,避免 race

render:
- markdown.tsx expandWikilinks 取代 stripLogseqMeta 前處理(兩階段)
- 內部 wiki link(/mira/wiki/...)不開 _target=_blank(不離開頁面)

留下輪:metadata 補完 (作者/出版社) / cursor tracking / PostEditor.save 也建檔
2026-05-16 12:08:28 +08:00
Leo d6bff9d551 fix(mira): reply @mira indicator + RAG match 寬鬆化
leo 試用反饋:

bug:reply 中 @mira 「看起來無效」
- 真正 root cause: trigger 確實 fire,但 thinking indicator 沒亮起 → leo 沒看到回應
  以為失敗(其實 mira 後台跑 30s+ 才回)
- 修:MiraTriggerContext 把 thinking trigger 抽成 context callback
  PostComposer / PostEditor / BlockEditor / ReplyLine 五個 @mira 觸發點
  都呼叫 triggerThinking?.(docPageName) 啟動 5s polling

bug:RAG 抓不到 entity(leo 寫《李飛飛的視界之旅》沒被識別)
- 之前只看 type=index-entry,且嚴格 substring。新建 wiki 還沒 index-entry
  時就漏;entity 名稱跟貼文文字稍微不同也漏
- 修 fetchRelevantWikiContext:
  - 平行撈 index-entry + wiki-page 兩種,合併 entity set
  - 雙向匹配:entity 完整 substring postContent(嚴格) OR
    entity 內 3+ 字片段在 postContent 出現(寬鬆,中文友善)
  - top 5(從 3 增加),給 mira 更多上下文
2026-05-16 11:43:28 +08:00
Leo 94368ec981 fix(mira): 4 bug — popup 在 edit / 思考 indicator 條件 / RAG / edit @mira
leo 試用 P0 後反饋的 4 個問題:

bug #1: popup 編輯時沒有,更擠
- EditingArea 元件加 ⇱ 放大 button + popup overlay(共用 PostComposer 的 popup pattern)
- 影響:所有 edit / reply 模式現在都有放大編輯

bug #2: Mira 思考中很久(即使沒 @mira)
- root cause: onAiTriggered(pageName) 在 PostComposer 永遠 fire,會在每篇貼文觸發
  thinking indicator UI
- 修:移到 if (hasMiraMention) 分支內。沒 @mira → 不顯示 thinking
- wiki_synthesis 仍每篇都跑(背景靜默)但不顯示 thinking,避免 leo 誤會

bug #3: Mira reply 不知道有 wiki,無狀態
- 加 fetchRelevantWikiContext: 撈所有 type=index-entry blocks,用 entity 名稱
  keyword match against post content,取 top 3 整篇 markdown 餵進 prompt
- prompt 加規則「如果 leo 提到的 entity 你已有 wiki 知識,請主動引用」
- 對應 leo「應該以擁有知識庫的專人來回覆」

bug #4: edit 時 @mira 沒反應
- PostEditor.save / BlockEditor.saveEdit / ReplyLine.save 三處都加 hasMiraMention 偵測
- 條件:新內容含 @mira 且舊版沒有 → 觸發(避免重複編輯重複 trigger)

placeholder 加 hint「@mira 呼叫 Mira 回覆」。
2026-05-16 11:07:34 +08:00
Leo 8d4c3a3464 feat(mira): P0 河道完善 3 task — Mira 頭像 / @mira 選擇性回覆 / 編輯器 popup
對應 tasks.md backlog #5a / #5b / #5c(leo 2026-05-16 P0),design.md §3.6.5。

#5a Mira 發文獨立頭像
- 新 MiraAvatar 元件(紫色漸層圓 + 🤖 emoji)
- isMiraSource() 判斷 post 來源是 leo(km-writer-direct/logseq/mobile/web/tg/rss)
  還是 mira(ai-* / mira-* / 其他 test sources)
- PostCard header:showMira ? Mira 頭像 + 名「Mira」 : leo 頭像 + leo 名

#5b @mira 選擇性回覆(撤回每篇 auto-reply)
- 新 hasMiraMention() regex:偵測文字含 @mira(前後可有標點)
- PostComposer / BlockEditor / ReplyLine 三處 submit:只有 @mira 時 triggerAiReply
- triggerAiReply prompt 加 topic 抽取(@mira 後第一段到標點)+ scope hint
- wiki_synthesis trigger 跟 @mira 無關,每篇都跑(KB 副本同步)
- 不擋手動筆記(leo 隨手寫不需要 mira 每篇都回)

#5c 編輯器 popup 放大
- composer 加 ⇱ 放大按鈕 → 切到 fullscreen overlay popup
- popup 含大 textarea + 同 markdown toolbar + 同 submit 邏輯
- ⌘+Enter 發布、Esc 收起、外點 backdrop 收起
- 對應 leo「寫長文 textarea 太小」需求

CSS 加 .mira-avatar-mira / .mira-composer-popup-* 系列。
TS check pass。
2026-05-16 10:35:32 +08:00
Leo 0f2a00e0d5 ci(landing): auto-deploy to CF Pages on push to main
接好 leo 反饋的「Pages auto-deploy 沒接」坑。新增 .github/workflows/deploy-landing.yml:
- push 到 main 且 landing/ 有變動 → build + 部署
- workflow_dispatch 也可手動觸發
- 用既有的 CLOUDFLARE_API_TOKEN / CLOUDFLARE_ACCOUNT_ID secrets
- 用 cloudflare/wrangler-action@v3 標準 action

下次 leo 推 landing 改動就會自動 deploy,不用 wrangler pages deploy 手動跑。
2026-05-16 09:29:57 +08:00
Leo 3689f30409 fix(mira): [pageName] h1 顯示 entity 名 + listing dedupe by entity
兩個 leo 反饋的 UI bug:

1. wiki/[pageName] 對 index-entry 渲染時,h1 用 block.content(整篇 markdown)
   會把整個內容塞進 h1。改:wiki-page 用 content 當 entity 名;其他類型
   (index-entry/schema/log)用 page_name 剝 `wiki-` / `index-` prefix。

2. listing「Wiki Pages (21)」累積式設計造成同 entity 多版顯示為多張卡,雜亂。
   改:用 useMemo dedupe by entity(content)— 每 entity 一張卡顯示最新版,
   標題顯示「N 版累積」當 N>1。原始 21 筆 → 現在約 6-7 個 unique entity。
2026-05-16 09:03:45 +08:00