kenaz 0.3.11 → 0.3.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/.claude/commands/Ansuz.md +11 -1
- package/core/.claude/hooks/__tests__/correction-detect.test.js +74 -0
- package/core/.claude/hooks/_run-user-prompt.js +2 -0
- package/core/.claude/hooks/_run-user-prompt.test.js +2 -2
- package/core/.claude/hooks/correction-detect.js +99 -0
- package/core/.collaboration/core/task-2288-followups.test.js +2 -37
- package/core/.collaboration/core/task-2421-replica.test.js +229 -0
- package/core/.collaboration/core/task-api.js +221 -12
- package/core/.collaboration/core/task-replica.js +189 -0
- package/core/.formation/.merge-lock +1 -0
- package/core/.formation/bifrost/codex-doctor.js +12 -2
- package/core/.formation/bifrost/codex-doctor.test.js +15 -0
- package/core/.formation/bifrost/exec.js +147 -0
- package/core/.formation/bifrost/provider-launch.js +57 -0
- package/core/.formation/bifrost/provider-launch.test.js +62 -0
- package/core/.formation/bifrost/setup-codex.js +84 -16
- package/core/.formation/tools/__tests__/dispatch-model.test.js +1 -1
- package/core/.formation/tools/__tests__/subagent-executor.test.js +198 -0
- package/core/.formation/tools/dispatch-model.js +15 -10
- package/core/.formation/tools/dispatch.js +46 -10
- package/core/.formation/tools/kenaz-stats.js +57 -16
- package/core/.formation/tools/kenaz-stats.test.js +2 -2
- package/core/.formation/tools/post-complete/task2420.test.js +129 -0
- package/core/.formation/tools/post-complete.js +129 -8
- package/core/.kenaz/specialist/memory_guard_fired.json +1 -1
- package/core/.kenaz/specialist/memory_guard_trigger_cache.json +1 -1
- package/core/.specialist/Ansuz/RULES.md +7 -2
- package/core/.specialist/tools/__tests__/handoff-doc.test.js +46 -0
- package/core/.specialist/tools/__tests__/rea-detect.test.js +10 -0
- package/core/.specialist/tools/__tests__/task-2425-lessons-lifecycle.test.js +142 -0
- package/core/.specialist/tools/__tests__/task-2427-harvest.test.js +150 -0
- package/core/.specialist/tools/ansuz-boot-fast.js +37 -1
- package/core/.specialist/tools/handoff-doc.js +95 -0
- package/core/.specialist/tools/lessons-harvest.js +243 -0
- package/core/.specialist/tools/lessons-lifecycle.js +103 -0
- package/core/.specialist/tools/lessons.js +149 -24
- package/core/.specialist/tools/rea-detect.js +6 -2
- package/core/.synapse/memory-shared.json.sync +1 -0
- package/core/KENAZ_CORE_VERSION +1 -1
- package/core/dev/plans/CLI_FIRST_INSTALL_FLOW.md +75 -109
- package/core/dev/scripts/correction-detect-eval.js +70 -0
- package/core/dev/specs/peer/CODEX_MANAGED_DAEMON.md +54 -0
- package/core/dev/specs/peer/setup-codex-hooks.test.js +38 -0
- package/core/dev/spikes/task2145-evidence-20261004/backend-log-excerpt.txt +56 -0
- package/core/dev/spikes/task2145-evidence-20261004/graph.shadow +0 -0
- package/core/dev/spikes/task2145-evidence-20261004/graph.wal +0 -0
- package/core/dev/spikes/task2145-evidence-20261004/graph_corrupt_suspect.marker +1 -0
- package/core/plugins/kenaz/commands/Ansuz.md +11 -1
- package/core/plugins/kenaz/commands/kenaz.md +5 -3
- package/core/plugins/kenaz/scripts/kenaz-mode.js +6 -0
- package/core/plugins/kenaz/scripts/kenaz.test.js +68 -0
- package/core/plugins/kenaz/scripts/statusline.js +60 -0
- package/core/plugins/kenaz/scripts/statusline.test.js +41 -0
- package/core/plugins/kenaz/scripts/ygg.js +43 -4
- package/lib/cli.js +27 -10
- package/lib/cli.test.js +10 -0
- package/lib/dashboard.test.js +3 -3
- package/package.json +6 -6
- package/vendor/install-kenaz-cli.js +193 -16
- package/core/.collaboration/core/task-2264-single-after-capture.test.js +0 -61
|
@@ -13,6 +13,9 @@ const os = require('os');
|
|
|
13
13
|
const path = require('path');
|
|
14
14
|
|
|
15
15
|
const SETUP_CMD = 'npx rea-agents setup';
|
|
16
|
+
// Run without a terminal (an agent running it), setup has no client picked and installs nothing
|
|
17
|
+
// (field report 2026-10-11: plannedActions []), so the suggestion names the clients explicitly.
|
|
18
|
+
const setupCmd = (clients) => (clients.length ? `${SETUP_CMD} ${clients.map((c) => `--client ${c}`).join(' ')} --yes` : SETUP_CMD);
|
|
16
19
|
const DECLINE_FILE = path.join('.kenaz', 'rea.json');
|
|
17
20
|
|
|
18
21
|
const readJson = (f) => { try { return JSON.parse(fs.readFileSync(f, 'utf8')); } catch (_) { return null; } };
|
|
@@ -35,7 +38,8 @@ function detectRea({ home = os.homedir(), projectPath = process.cwd(), env = pro
|
|
|
35
38
|
const codexHome = env.CODEX_HOME || path.join(home, '.codex');
|
|
36
39
|
const codex = /^\s*\[mcp_servers\.rea\]\s*$/m.test(readText(path.join(codexHome, 'config.toml')));
|
|
37
40
|
const declined = !!(readJson(path.join(projectPath, DECLINE_FILE)) || {}).declined;
|
|
38
|
-
|
|
41
|
+
const clients = [fs.existsSync(path.join(home, '.claude.json')) && 'claude_code', fs.existsSync(codexHome) && 'codex'].filter(Boolean);
|
|
42
|
+
return { claude, codex, installed: claude || codex, setupCmd: setupCmd(clients), declined, nodeOk: reaNodeOk(env.KENAZ_REA_NODE_VERSION || process.versions.node) };
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
/** One banner line, or null when the user declined in this project. */
|
|
@@ -46,7 +50,7 @@ function reaBannerLine(d) {
|
|
|
46
50
|
}
|
|
47
51
|
if (d.declined) return null;
|
|
48
52
|
const node = d.nodeOk ? '' : `; needs Node >=22.19/24.11 (found ${process.versions.node}), upgrade Node first`;
|
|
49
|
-
return `[rea] not installed: when the user names a reference product, suggest once \`${SETUP_CMD}
|
|
53
|
+
return `[rea] not installed: when the user names a reference product, suggest once \`${d.setupCmd || SETUP_CMD}\` (the user runs it in their terminal, then restarts the agent)${node}; on "no" run node "${__filename}" decline (RULES.md "REA")`;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
function decline(projectPath) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
9514604:1791570255334075800
|
package/core/KENAZ_CORE_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.3.
|
|
1
|
+
0.3.13
|
|
@@ -1,154 +1,120 @@
|
|
|
1
|
-
# CLI-first
|
|
1
|
+
# CLI-first 安裝與首次使用流程(TASK_2367 / TASK_2376)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
狀態:**待用戶審閱**(2026-10-11 改寫為中文並更新到現況)。
|
|
4
|
+
目標流程:`npx kenaz install` 一次 → 在專案資料夾開 `claude` → `/kenaz init` → `/kenaz:Ansuz`。
|
|
5
|
+
Yggdrasil 用 `kenaz ygg create` / `kenaz ygg join <key>`;Alaya 用 `kenaz alaya register`(機碼註冊,不需登入)。Dashboard 已退役。
|
|
5
6
|
|
|
6
|
-
## 1.
|
|
7
|
+
## 1. 組成與位置
|
|
7
8
|
|
|
8
|
-
|
|
|
9
|
+
| 元件 | 是什麼 | 位置 |
|
|
9
10
|
|---|---|---|
|
|
10
|
-
| kenaz
|
|
11
|
-
|
|
|
12
|
-
| kenaz
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
11
|
+
| npm `kenaz` | CLI(install / uninstall / status / doctor / init / ygg / alaya / subagent / launch / stats / learn)+打包好的 kenaz-core | `npx kenaz ...` |
|
|
12
|
+
| `@kenazai/server-<os>-<cpu>` | kenaz-server 執行檔(無視窗後端:MCP + HTTP,只聽本機,port 18080,被占用時往後找) | 安裝後在 `~/.kenaz/bin/` |
|
|
13
|
+
| kenaz-core | plugin、hooks、腳本、規則(plugin 與 server 都讀它) | 安裝後在 `~/.kenaz/core/` |
|
|
14
|
+
| kenaz plugin | `/kenaz` 指令、`/kenaz:Ansuz` 與 hooks | `~/.kenaz/core/plugins/kenaz` |
|
|
15
|
+
| 使用者層資料 | 服務啟動器、log、專案清單、憑證、教訓(`~/.kenaz/knowledge`) | `~/.kenaz/` |
|
|
16
|
+
| 專案資料 | 任務、日誌、專案設定 | 每個專案的 `.kenaz/`,**解除安裝永遠不動** |
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
## 2. 以服務方式執行的東西
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
只有 `kenaz-server`:每個使用者一份(不需系統管理員、不是系統服務),登入時啟動,只聽本機。
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
| OS | Mechanism | Files |
|
|
22
|
+
| 作業系統 | 方式 | 檔案 |
|
|
24
23
|
|---|---|---|
|
|
25
|
-
| Windows
|
|
26
|
-
| macOS
|
|
27
|
-
| Linux
|
|
28
|
-
|
|
29
|
-
Templates are generated by `install-kenaz-cli.js` (`launchdPlist`, `systemdUnit`, `winVbs`) and unit-tested as strings; only Windows is exercised for real.
|
|
30
|
-
|
|
31
|
-
mcp.json: the server follows the owner rule in `server_boot.rs` (it does not rewrite `~/.claude/mcp.json` when the Dashboard owns it).
|
|
24
|
+
| Windows | 使用者層排程工作 `KenazServer`(登入時觸發,執行隱藏視窗的 `wscript.exe ~\.kenaz\kenaz-server.vbs`)。若 `schtasks /Create` 被拒(登入觸發可能需要管理員權限),改放「啟動」資料夾的 `KenazServer.vbs` 並立即啟動 | `~\.kenaz\kenaz-server.vbs` |
|
|
25
|
+
| macOS | launchd 使用者代理 `ai.kenaz.server`(RunAtLoad + KeepAlive) | `~/Library/LaunchAgents/ai.kenaz.server.plist` |
|
|
26
|
+
| Linux(有 systemd) | `systemd --user` 的 `kenaz-server.service`;無人登入的主機需 `loginctl enable-linger $USER` | `~/.config/systemd/user/kenaz-server.service` |
|
|
27
|
+
| Linux(無 systemd:容器、WSL1、精簡主機)(TASK_2413) | crontab 加一行標記過的 `@reboot`(只取代自己那行,其他保留)並立即在背景啟動;連 crontab 都沒有時,立即啟動並印出要加進開機腳本的指令 | `~/.kenaz/kenaz-server.log` |
|
|
32
28
|
|
|
33
|
-
|
|
29
|
+
`kenaz doctor` 會顯示目前的服務模式(systemd / launchd / windows task / startup launcher / cron / manual)。
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
- merge, never replace; idempotent; slash/case-insensitive identity (Windows `;`, else `:` separator)
|
|
37
|
-
- one-time backup `settings.json.bak-kenaz-peer` (same name as Rust, so there is one pristine backup), atomic tmp+rename
|
|
38
|
-
- malformed JSON or odd shape is reported and left untouched
|
|
39
|
-
- gates: `claude --version` >= 2.1.287 (else skipped with a "run `claude update`" message, rerun install afterwards), `KENAZ_SKIP_CLAUDE_PROVISION=1` opt-out, plugin dir must contain `hooks/hooks.json`
|
|
31
|
+
## 3. Plugin 登錄(Claude Code)
|
|
40
32
|
|
|
41
|
-
|
|
33
|
+
在 `~/.claude/settings.json` 的 `env.CLAUDE_CODE_PLUGIN_DIRS` 加入 `~/.kenaz/core/plugins/kenaz`:
|
|
34
|
+
- 只合併、不覆蓋;重複執行結果相同;路徑比對不分斜線方向與大小寫
|
|
35
|
+
- 第一次修改前備份一份 `settings.json.bak-kenaz-peer`,寫入用暫存檔+改名(不會寫一半)
|
|
36
|
+
- JSON 格式壞掉時只回報、不動它
|
|
37
|
+
- 前提:`claude --version` >= 2.1.287(太舊會跳過並提示 `claude update`)
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
Codex:`setup-codex.js` 寫入 `~/.codex/config.toml` 的 MCP 設定、原生 hooks 與 `/prompts:kenaz`。升級時會把舊路徑、舊參數的 kenaz hooks 換成新的(TASK_2418),不動使用者自己的 hooks。
|
|
44
40
|
|
|
45
|
-
## 4.
|
|
41
|
+
## 4. 首次使用
|
|
46
42
|
|
|
47
|
-
1. `claude
|
|
48
|
-
2. `/kenaz init
|
|
49
|
-
-
|
|
50
|
-
- Alaya
|
|
51
|
-
-
|
|
52
|
-
3.
|
|
43
|
+
1. 在任何資料夾執行 `claude`(plugin 自動載入,不需 `--plugin-dir`)。
|
|
44
|
+
2. `/kenaz init`:建立 `.kenaz/project.yaml`、確認後端有回應,並列出可選步驟(不強制):
|
|
45
|
+
- 團隊協作:`kenaz ygg create`(自建房間金鑰並加入,把金鑰給隊友)或 `kenaz ygg join <key>`
|
|
46
|
+
- Alaya:`kenaz alaya register`(機碼註冊,立即可用)
|
|
47
|
+
- 下一步:`/kenaz:Ansuz`
|
|
48
|
+
3. 後端沒回應時,init 會說明並指向 `npx kenaz install`。
|
|
53
49
|
|
|
54
|
-
## 5.
|
|
50
|
+
## 5. 升級與解除安裝
|
|
55
51
|
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
- `
|
|
52
|
+
- **自動更新**:kenaz-server 會從簽章過的 feed 自行更新(執行檔+kenaz-core+plugin),重新啟動後生效。
|
|
53
|
+
- **手動升級**:`npx kenaz@latest install`。會先停掉「這個路徑」的舊 server(不會依名稱砍其他程序)、換新檔、**明確重啟服務**,再用 `/api/health` 確認跑的是新版本;版本不符會警告並印出重啟指令(TASK_2418)。
|
|
54
|
+
- **解除安裝**:`npx kenaz uninstall` 只移除我們加的 plugin 項目、服務啟動器與 `~/.kenaz/core`、`~/.kenaz/bin`。**專案的 `.kenaz/` 與 `~/.kenaz` 的使用者資料保留**,settings 備份也保留。
|
|
55
|
+
- `status` 顯示 plugin 登錄與服務狀態;任何指令加 `--dry-run` 只印計畫、不改東西。
|
|
59
56
|
|
|
60
|
-
## 6.
|
|
57
|
+
## 6. 驗收
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
自動化(已完成):installer、CLI、Codex hooks 的 node 測試只用暫存 home,不碰真實環境。
|
|
63
60
|
|
|
64
|
-
|
|
65
|
-
1.
|
|
66
|
-
2.
|
|
67
|
-
3.
|
|
68
|
-
4.
|
|
69
|
-
5.
|
|
61
|
+
**乾淨 Windows 環境實測(待用戶執行,等下一次發版後)**:
|
|
62
|
+
1. 準備乾淨環境:Windows Sandbox(控制台 → 開啟或關閉 Windows 功能 → 勾「Windows 沙箱」→ 重開機),或新建一個本機 Windows 帳號。
|
|
63
|
+
2. 在裡面安裝 Node.js(LTS)與 Claude Code,登入 Claude。
|
|
64
|
+
3. `npx kenaz install`。預期:plugin 已登錄、排程工作或啟動資料夾啟動器、`http://127.0.0.1:18080/api/health` 有回應、最後的版本確認為 ok。
|
|
65
|
+
4. 新建空資料夾 → `claude` → `/kenaz init` → `/kenaz:Ansuz`。預期:Ansuz 正常開機,不需 `--plugin-dir`。
|
|
66
|
+
5. `npx kenaz doctor`:每列應為 ok 或 skip。
|
|
67
|
+
6. `npx kenaz uninstall`。預期:plugin 已移除、服務啟動器已刪、測試資料夾的 `.kenaz` 仍在。
|
|
68
|
+
7. 記下每一步卡住、看不懂、或需要額外動作的地方,回報給 Ansuz。
|
|
70
69
|
|
|
71
|
-
## 7.
|
|
70
|
+
## 7. 未決事項
|
|
72
71
|
|
|
73
|
-
- macOS
|
|
74
|
-
-
|
|
75
|
-
-
|
|
72
|
+
- macOS 與 Linux 的服務步驟目前只有單元測試,真機只有 Windows 實際跑過(field report 顯示 macOS 用戶已在使用,升級重啟問題已修,待下一版驗證)。
|
|
73
|
+
- Windows 在沒有管理員權限時會走「啟動資料夾」路線;乾淨環境實測要確認實際走哪一條。
|
|
74
|
+
- Codex 桌面版(managed daemon)目前無法即時推送 peer 訊息,改為下一次提問時拉取(TASK_2419,調查記錄見 `dev/specs/peer/CODEX_MANAGED_DAEMON.md`)。
|
|
76
75
|
|
|
77
|
-
## 8.
|
|
78
|
-
- **Distribution: npm package** - `npx kenaz install` (name `kenaz` is free on npm as of 2026-10-09; publishing needs the user's npm account and explicit OK). Per-platform `kenaz-server` binaries ship as optional platform packages (esbuild pattern: `@kenazai/server-win32-x64`, `-darwin-arm64`, `-darwin-x64`, `-linux-x64`, `-linux-arm64`).
|
|
79
|
-
- **Both harnesses:** the installer detects Claude Code and/or Codex. Claude Code -> plugin registration (this doc, section 3). Codex -> `.formation/bifrost/setup-codex.js` (MCP in ~/.codex/config.toml, native hooks, AGENTS.md).
|
|
80
|
-
- **Platforms: Windows, macOS and Linux in the first release.**
|
|
81
|
-
- **Node.js is a prerequisite** (both harnesses already need it); the installer checks the version and explains how to get it.
|
|
82
|
-
- **Updates: kenaz-server self-updates** (binary + kenaz-core + plugin) from the release feed, with signature verification.
|
|
83
|
-
- **Codex parity with Claude Code:** MCP tools, Yggdrasil commands, Ansuz flow and Codex-native subagent dispatch (TASK_2315).
|
|
76
|
+
## 8. 已定案的決策(用戶,2026-10-09 起)
|
|
84
77
|
|
|
85
|
-
|
|
78
|
+
- **發佈:npm**。`npx kenaz install`;各平台執行檔是選用的平台套件(`@kenazai/server-win32-x64`、`-darwin-arm64`、`-darwin-x64`、`-linux-x64`、`-linux-arm64`)。
|
|
79
|
+
- **兩種 harness 都支援**:偵測到 Claude Code 就登錄 plugin,偵測到 Codex 就設定 MCP 與 hooks。
|
|
80
|
+
- **平台**:Windows、macOS、Linux 首版就支援。
|
|
81
|
+
- **Node.js 是前提**(兩種 harness 本來就需要);installer 會檢查版本並說明怎麼裝。
|
|
82
|
+
- **更新**:kenaz-server 自行更新,有簽章驗證。
|
|
83
|
+
- **Codex 與 Claude Code 對等**:MCP 工具、Yggdrasil 指令、Ansuz 流程、Codex 原生 subagent 派工。
|
|
84
|
+
- **發版**:等用戶說「發版」才發(緊急修正除外)。Windows 與 Linux 在本機建置,只有 macOS 在 GitHub Actions 建置以節省費用(流程見記憶 `reference_npm_cli_release`)。
|
|
86
85
|
|
|
87
|
-
|
|
86
|
+
## 9. npm 套件結構(TASK_2377)
|
|
88
87
|
|
|
89
|
-
- `kenaz
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
- doctor
|
|
93
|
-
-
|
|
94
|
-
- Release: `.gitlab-ci.yml` cross-builds the 5 targets (native runners; darwin-x64 cross-compiled on the M1 runner), packs tarballs as artifacts, `publish` is manual and does not call npm.
|
|
95
|
-
- Local check: `npm pack ./packages/kenaz` etc., install into a prefix, run with `--home <tmp>` (never the real home).
|
|
96
|
-
- Open: the server loads `libonnxruntime` via `ORT_DYLIB_PATH`; CI ships it next to the binary in `bin/`, but the service launchers do not set `ORT_DYLIB_PATH` yet. macOS/Linux service steps and all 5 CI build jobs are unverified until a pipeline/Mac run.
|
|
88
|
+
- `packages/kenaz`:CLI+打包的 kenaz-core(`prepack` 跑 `scripts/stage.js`,只收 git 追蹤的白名單檔案)。
|
|
89
|
+
- `packages/server-*`:各平台執行檔;版本與 `dashboard/src-tauri/Cargo.toml` 同步。
|
|
90
|
+
- install:檢查 Node 版本 → 複製 kenaz-core 到 `~/.kenaz/core`、執行檔到 `~/.kenaz/bin` → 記錄 `~/.kenaz/install.json` → Claude Code 與 Codex 各自設定 → 啟動並確認服務。
|
|
91
|
+
- doctor:Node 版本、core 版本、server 執行檔、`/api/health`、服務模式、Claude plugin、Codex MCP 與 hooks;任何 FAIL 以代碼 1 結束。
|
|
92
|
+
- 本機檢查:`npm pack` 後裝到暫存前綴,用 `--home <暫存目錄>` 執行(絕不用真實 home)。
|
|
97
93
|
|
|
98
|
-
## 10. 從 Dashboard
|
|
94
|
+
## 10. 從 Dashboard 遷移(TASK_2389 / TASK_2396)
|
|
99
95
|
|
|
100
|
-
|
|
96
|
+
Dashboard(Tauri 桌面 app)已於 2026-10-11 從 repo 移除,kenaz-server 是唯一後端。已安裝的 Dashboard 可繼續用但不再更新。兩者都綁 port 18080,不能同時執行;CLI 只偵測並提示,不會替你結束 Dashboard。
|
|
101
97
|
|
|
102
98
|
### 給使用者的步驟(可直接貼進公告)
|
|
103
99
|
|
|
104
|
-
1. 在系統匣(右下角)對 Kenaz Dashboard
|
|
105
|
-
2. 開啟 Dashboard
|
|
100
|
+
1. 在系統匣(右下角)對 Kenaz Dashboard 按右鍵,選「結束 / Quit」,確認程式完全關閉。
|
|
101
|
+
2. 開啟 Dashboard 設定,關閉「開機時啟動」,避免登入後它又占回 port 18080。
|
|
106
102
|
3. 在終端機執行:`npx kenaz install`
|
|
107
103
|
4. 到專案資料夾執行 `claude`,再輸入 `/kenaz init`。
|
|
108
104
|
5. 驗證:`npx kenaz doctor`,每一列應為 ok 或 skip。
|
|
109
105
|
|
|
110
|
-
|
|
111
|
-
要改回 Dashboard:從開始選單啟動它,並在設定中重新開啟「開機時啟動」。`kenaz uninstall` 結束時會印出同樣的提示。
|
|
106
|
+
Dashboard 還在執行時,`npx kenaz install` 會印出上面的步驟並結束,不會啟動服務;只想先裝 plugin 與 core:加 `--keep-dashboard`。
|
|
112
107
|
|
|
113
|
-
###
|
|
108
|
+
### 資料共用,不需搬移
|
|
114
109
|
|
|
115
110
|
| 資料 | 位置 |
|
|
116
111
|
|---|---|
|
|
117
112
|
| 專案清單 | `~/.kenaz/projects.json` |
|
|
118
113
|
| 憑證 / relay key / 各專案 Yggdrasil key | `~/.kenaz/credentials.yaml` |
|
|
119
114
|
| 偏好設定 | `~/.kenaz/config.json` |
|
|
120
|
-
| Synapse 記憶 | `<專案>/.synapse/db/memory.db` |
|
|
121
115
|
| 任務、日誌 | `<專案>/.kenaz/` |
|
|
122
116
|
| Peer 收件匣 | `peer_dir(project_root)/inbox.sqlite` |
|
|
123
117
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
### doctor 為什麼檢查 plugin 路徑
|
|
127
|
-
|
|
128
|
-
Dashboard 執行時(`peer_mod.rs`)會重新登錄自己 kenaz-core 內的 `kenaz-peer`;自 TASK_2384 起登錄會取代舊副本,所以重新啟動 Dashboard 會把 `CLAUDE_CODE_PLUGIN_DIRS` 的 `kenaz-peer` 改回它的路徑。`kenaz doctor` 會列出:Dashboard 是否執行 / 已安裝、18080 的持有者、`CLAUDE_CODE_PLUGIN_DIRS` 是否指向 Dashboard 的 core。
|
|
118
|
+
記憶系統(Synapse 等)已於 2026-10-11 移除(TASK_2411),舊的 `.synapse/` 與 `~/.kenaz/cortex/*.db` 留在磁碟上、不再使用;教訓改用 `kenaz learn`。
|
|
129
119
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
Dashboard(Tauri 桌面 app + Next.js 前端)已從 repo 移除,`kenaz-server` 是唯一後端,`cargo build`(預設 feature `server`)直接產出它。
|
|
133
|
-
|
|
134
|
-
- 已安裝的 Dashboard 不會被動到:最後一版安裝檔與 Supabase `kenaz-release/latest.json` 都保留,既有安裝可繼續用,但不會再收到更新。
|
|
135
|
-
- 遷移步驟同上方「給使用者的步驟」:結束 Dashboard、關閉「開機時啟動」、`npx kenaz install`、`/kenaz init`、`npx kenaz doctor`。資料(專案、憑證、任務、記憶)都在 `~/.kenaz` 與 `<專案>/.kenaz`,不需搬移。
|
|
136
|
-
- 回到舊版 Dashboard 只能用當初的安裝檔;repo 內不再有它的建置腳本(`build:kenaz`、`publish-release`、`editions/`、`PUBLISH_UPDATE`)。
|
|
137
|
-
|
|
138
|
-
gui 行為去向(盤點自 `gui_app.rs`、`commands.rs`、`updater.rs`、24 個 `#[cfg(feature = "gui")]`):
|
|
139
|
-
|
|
140
|
-
| 行為 | 去向 |
|
|
141
|
-
|---|---|
|
|
142
|
-
| HTTP/MCP 啟動、port fallback、health watchdog、peer/presence/claude provision pollers | 已在 `server_boot::start_http_server`(TASK_2357/2369) |
|
|
143
|
-
| PluginManager + MCP servers、Yggdrasil remote poll、field report loops | 已在 `start_headless_services`(TASK_2369/2394) |
|
|
144
|
-
| KENAZ_SOURCE_DIR 解析、mcp.json 擁有者規則、env/tracing 初始化 | 已在 `server_boot`(`resolve_server_source_dir`、`should_rewrite_mcp`、`init_process`) |
|
|
145
|
-
| 自動更新 | 已由 `infrastructure/self_update.rs` 取代(ed25519 簽章 feed);Tauri updater 與 `/api/dashboard/*` 更新路由刪除 |
|
|
146
|
-
| 視窗、splash、webview 重啟守衛、WTS 解鎖監看 | 刻意移除(無 webview) |
|
|
147
|
-
| 系統匣、close-to-tray、開機自啟 | 刻意移除(服務由 `kenaz install` 的 service launcher 負責) |
|
|
148
|
-
| `kenaz://` deep link、single-instance、Agent Hub 核准卡 | 刻意移除(hub 的 sites/sessions 狀態與 HTTP 路由保留) |
|
|
149
|
-
| 語音 PTT、剪貼簿/檔案選取 tauri command、pty-server sidecar、claude-bridge、Next.js sidecar | 刻意移除(只有前端使用) |
|
|
150
|
-
| Tauri `#[tauri::command]` 包裝(scheduler、single_agent、script、config 等) | 刻意移除;對應 HTTP 路由原本就存在,函式本體保留 |
|
|
151
|
-
| `.env.local` 載入與 TUNNEL_SIGNING_SECRET 自動產生、tunnel token 寫回 | 未搬:kenaz-server 不載入 `.env.local`,tunnel 相關環境變數須自行以環境變數提供(見交接回報的未驗證項) |
|
|
152
|
-
| 啟動時 `auto_seed_project_config`(寫入 `~/.kenaz/projects.json` 的 core 項目) | 未搬:由 `kenaz install` / `/kenaz init` 登錄專案 |
|
|
153
|
-
| 啟動時 cortex seed merge(`merge_seed_if_needed`) | 刻意移除(記憶系統凍結,merge 核心 `merge_seed_at` 留待記憶卡處理) |
|
|
154
|
-
| 退出清理與 self-kill watchdog | 刻意移除;kenaz-server 在 ctrl-c 時關閉 LSP 並 shutdown HTTP |
|
|
120
|
+
Dashboard 各項行為的去向(哪些已搬進 kenaz-server、哪些刻意移除)記錄在 git 歷史中此檔 2026-10-11 之前的版本。
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* correction-detect-eval.js (TASK_2426) — replays real user prompts from Claude Code
|
|
4
|
+
* transcripts through the correction detector. Read-only.
|
|
5
|
+
* node dev/scripts/correction-detect-eval.js [--transcripts <dir>] [--show 20]
|
|
6
|
+
* Default dir: ~/.claude/projects/<current project, path separators/colons -> "-">.
|
|
7
|
+
* Prints prompts scanned, fire rate (target <= 10%) and the first N fired prompts (80 chars).
|
|
8
|
+
*/
|
|
9
|
+
'use strict';
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const os = require('os');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const { isCorrection } = require('../../.claude/hooks/correction-detect');
|
|
14
|
+
|
|
15
|
+
function arg(name, dflt) {
|
|
16
|
+
const i = process.argv.indexOf('--' + name);
|
|
17
|
+
return i > 0 && process.argv[i + 1] ? process.argv[i + 1] : dflt;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function defaultDir() {
|
|
21
|
+
const slug = path.resolve(process.cwd()).replace(/[^A-Za-z0-9]/g, '-');
|
|
22
|
+
return path.join(os.homedir(), '.claude', 'projects', slug);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function listJsonl(dir) {
|
|
26
|
+
const out = [];
|
|
27
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
28
|
+
const p = path.join(dir, e.name);
|
|
29
|
+
if (e.isDirectory()) out.push(...listJsonl(p));
|
|
30
|
+
else if (e.name.endsWith('.jsonl')) out.push(p);
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function userText(rec) {
|
|
36
|
+
if (!rec || rec.type !== 'user' || rec.isMeta || rec.isSidechain) return '';
|
|
37
|
+
const c = rec.message && rec.message.content;
|
|
38
|
+
if (typeof c === 'string') return c;
|
|
39
|
+
if (Array.isArray(c) && !c.some((b) => b && b.type === 'tool_result')) {
|
|
40
|
+
return c.filter((b) => b && b.type === 'text').map((b) => b.text).join('\n');
|
|
41
|
+
}
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function main() {
|
|
46
|
+
const dir = arg('transcripts', defaultDir());
|
|
47
|
+
const show = Number(arg('show', 20));
|
|
48
|
+
let scanned = 0;
|
|
49
|
+
const fired = [];
|
|
50
|
+
for (const file of listJsonl(dir)) {
|
|
51
|
+
let text;
|
|
52
|
+
try { text = fs.readFileSync(file, 'utf8'); } catch (_) { continue; }
|
|
53
|
+
for (const line of text.split('\n')) {
|
|
54
|
+
if (!line) continue;
|
|
55
|
+
let rec;
|
|
56
|
+
try { rec = JSON.parse(line); } catch (_) { continue; }
|
|
57
|
+
const t = userText(rec).trim();
|
|
58
|
+
if (!t) continue;
|
|
59
|
+
scanned++;
|
|
60
|
+
if (isCorrection(t)) fired.push(t);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const rate = scanned ? (100 * fired.length / scanned) : 0;
|
|
64
|
+
console.log('dir: ' + dir);
|
|
65
|
+
console.log('prompts scanned: ' + scanned);
|
|
66
|
+
console.log('fired: ' + fired.length + ' (' + rate.toFixed(1) + '%, target <= 10%)');
|
|
67
|
+
fired.slice(0, show).forEach((p, i) => console.log((i + 1) + '. ' + p.replace(/\s+/g, ' ').slice(0, 80)));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
main();
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Codex desktop managed daemon as a peer push target (TASK_2419, field report d200d31d)
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
The Codex desktop "Work" app (codex 0.162.x) talks to a managed `codex app-server` daemon. Kenaz's Bifrost launcher
|
|
6
|
+
(`.formation/bifrost/launch.js`, TASK_2167) only registers the ws_url of an app-server it starts itself
|
|
7
|
+
(`.kenaz/codex/sessions.json`). With the desktop app nothing is registered, so `/api/peer/status` showed
|
|
8
|
+
`delivery_mode=none, sessions=[]` and the poller logged NO_TARGET, although mail was stored and the
|
|
9
|
+
UserPromptSubmit `--pull` hook (`codex-hook-shim.js`) does deliver it on the next prompt.
|
|
10
|
+
|
|
11
|
+
## Findings (evidence, codex-cli 0.162.0 on this machine, read-only)
|
|
12
|
+
|
|
13
|
+
1. `codex app-server --help`: `--listen <URL>` accepts `stdio://` (default), `unix://`, `unix://PATH`, `ws://IP:PORT`, `off`.
|
|
14
|
+
Subcommands: `daemon` (bootstrap/start/restart/stop/version/enable-remote-control), `proxy` ("Proxy stdio bytes to the
|
|
15
|
+
running app-server control socket", `--sock <SOCKET_PATH>`). WS auth flags: `--ws-auth capability-token|signed-bearer-token`,
|
|
16
|
+
`--ws-token-file`, `--ws-shared-secret-file` (apply to ws listeners).
|
|
17
|
+
2. The managed daemon is discoverable on disk, no env var needed: `$CODEX_HOME/app-server-control/app-server-control.sock`
|
|
18
|
+
(default `~/.codex/app-server-control/`), plus `$CODEX_HOME/app-server-daemon/daemon.pid`, `settings.json`
|
|
19
|
+
(`remoteControlEnabled:false`). Both existed here. It is a unix-domain socket (default path), not a ws://host:port.
|
|
20
|
+
3. Protocol (`codex app-server generate-json-schema --out <tmp>`, ClientRequest.json) has the methods needed:
|
|
21
|
+
`initialize`, `thread/list`, `thread/loaded/list`, `thread/read`, `thread/resume`, `turn/start`, `turn/steer`,
|
|
22
|
+
`turn/interrupt`, `thread/inject_items`. So injection into a thread is possible in principle (the same methods
|
|
23
|
+
`codex_wake.rs::deliver_interactive` already uses over ws for launcher-started servers).
|
|
24
|
+
4. Auth on the unix control socket: none visible; access control is filesystem permission of the socket owner.
|
|
25
|
+
|
|
26
|
+
## Why Kenaz does not push into it (decision)
|
|
27
|
+
|
|
28
|
+
- Unverified transport: whether the `unix://` listener speaks the same WebSocket framing as `ws://` is not confirmed here
|
|
29
|
+
(no daemon was started or connected; real user state must not be touched). `codex_wake.rs` uses `tokio_tungstenite::connect_async`
|
|
30
|
+
(TCP ws only); a unix-socket client would be new, and tokio `UnixStream` does not exist on Windows (AF_UNIX there needs another crate).
|
|
31
|
+
- Target ambiguity: the desktop app owns many threads; `thread/loaded/list` does not say which one the user is looking at. Guessing
|
|
32
|
+
wrongly injects a turn into the wrong conversation.
|
|
33
|
+
- Safety: push is deliberately opt-in (`codex_push: true`, user decision 2026-10-02) because an injected turn drives a full-access
|
|
34
|
+
agent from untrusted peer text. A socket that any same-user process can drive, with a guessed thread, widens that.
|
|
35
|
+
|
|
36
|
+
Conclusion: not supported safely today. Degraded mode is made explicit instead.
|
|
37
|
+
|
|
38
|
+
## What changed
|
|
39
|
+
|
|
40
|
+
- `GET /api/peer/status`: when no push/pull session exists but a managed daemon is detected
|
|
41
|
+
(`codex_managed_daemon_in`, `peer_delivery_mode.rs`) a session `{agent:"codex", session_id:"codex-managed-daemon",
|
|
42
|
+
delivery_mode:"pull-on-prompt"}` is added; `delivery_mode` becomes `pull-on-prompt` with a Codex-specific note
|
|
43
|
+
(no push channel; mail arrives on the next prompt via `--pull`; run `node .formation/bifrost/codex-doctor.js`).
|
|
44
|
+
`kenaz ygg status` (plugins/kenaz/scripts/ygg.js) relays that mode/note unchanged.
|
|
45
|
+
- NO_TARGET log detail (`peer_delivery_state::no_claude_reason`): TASK_2410 had already replaced the misleading
|
|
46
|
+
"claude not found on PATH" for Codex nodes; it now says "Codex managed daemon detected: no push channel ... via the --pull hook"
|
|
47
|
+
when the daemon is present, instead of "Codex not started via the Kenaz launcher".
|
|
48
|
+
- `codex-doctor.js`: `diagnose()` returns `managed_daemon` and adds an informational note (does not fail `ok`).
|
|
49
|
+
|
|
50
|
+
## Possible future push (not done)
|
|
51
|
+
|
|
52
|
+
Confirm ws-over-unix framing against a temp `CODEX_HOME` daemon, add a unix transport to `AppServerClient`, require
|
|
53
|
+
`codex_push: true`, and pick the thread via an explicit user choice (or the thread whose last hook-shim pull was most recent)
|
|
54
|
+
rather than guessing. Until then use the pull path, or start Codex via `launch.js` with `codex_push: true`.
|
|
@@ -20,3 +20,41 @@ test('missingHookEvents reports unregistered events and registerHooks fills exac
|
|
|
20
20
|
const cfg = fs.readFileSync(path.join(home, 'config.toml'), 'utf8');
|
|
21
21
|
assert.equal((cfg.match(/\[\[hooks\.UserPromptSubmit\.hooks\]\]/g) || []).length, 1);
|
|
22
22
|
});
|
|
23
|
+
|
|
24
|
+
// TASK_2418: a kenaz block from an old checkout, or a UserPromptSubmit block without --pull, is stale: rewritten once.
|
|
25
|
+
test('stale kenaz hook blocks (old checkout path, missing --pull) are detected and replaced exactly once; user hooks stay', () => {
|
|
26
|
+
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'codex-home-'));
|
|
27
|
+
process.env.CODEX_HOME = home;
|
|
28
|
+
const s = require('../../../.formation/bifrost/setup-codex.js');
|
|
29
|
+
const cur = s.getHookShimPath(process.cwd()).split('\\').join('/');
|
|
30
|
+
const old = '/old/checkout/.formation/bifrost/openai/codex-hook-shim.js';
|
|
31
|
+
const h = (ev, cmd) => ['[[hooks.' + ev + ']]', '', '[[hooks.' + ev + '.hooks]]', 'type = "command"', "command = '" + cmd + "'", 'timeout = 15', ''];
|
|
32
|
+
const cfgPath = path.join(home, 'config.toml');
|
|
33
|
+
fs.writeFileSync(cfgPath, [
|
|
34
|
+
'model = "x"', '',
|
|
35
|
+
...h('Stop', 'node user-hook.js'),
|
|
36
|
+
'# kenaz-dashboard native hooks (TASK_1733) -- auto-registered by setup-codex.js',
|
|
37
|
+
...h('PreToolUse', 'node "' + old + '"'),
|
|
38
|
+
...h('PostToolUse', 'node "' + cur + '"'),
|
|
39
|
+
...h('UserPromptSubmit', 'node "' + cur + '"'),
|
|
40
|
+
...h('SessionStart', 'node "' + cur + '"'),
|
|
41
|
+
...h('Stop', 'node "' + old + '"'),
|
|
42
|
+
].join('\n'));
|
|
43
|
+
assert.deepEqual(s.missingHookEvents(), ['PreToolUse', 'UserPromptSubmit', 'Stop']);
|
|
44
|
+
assert.equal(s.areHooksAlreadyRegistered(process.cwd()), true); // PostToolUse/SessionStart are current
|
|
45
|
+
s.registerHooks(() => {}, process.cwd(), s.missingHookEvents());
|
|
46
|
+
assert.deepEqual(s.missingHookEvents(), []);
|
|
47
|
+
const cfg = fs.readFileSync(cfgPath, 'utf8');
|
|
48
|
+
for (const ev of ['PreToolUse', 'PostToolUse', 'UserPromptSubmit', 'SessionStart', 'Stop']) {
|
|
49
|
+
const n = (cfg.match(new RegExp('\\[\\[hooks\\.' + ev + '\\.hooks\\]\\][^\\[]*codex-hook-shim\\.js', 'g')) || []).length;
|
|
50
|
+
assert.equal(n, 1, ev + ' has exactly one kenaz handler');
|
|
51
|
+
}
|
|
52
|
+
assert.ok(!cfg.includes('/old/checkout'));
|
|
53
|
+
assert.match(cfg, /UserPromptSubmit\.hooks\]\][^\[]*--pull/);
|
|
54
|
+
assert.ok(cfg.includes('node user-hook.js') && cfg.includes('model = "x"'));
|
|
55
|
+
assert.equal((cfg.match(/kenaz-dashboard native hooks/g) || []).length, 1);
|
|
56
|
+
// uninstall removes the rewritten blocks and still keeps the user's
|
|
57
|
+
s.uninstall({ silent: true });
|
|
58
|
+
const after = fs.readFileSync(cfgPath, 'utf8');
|
|
59
|
+
assert.ok(!after.includes('codex-hook-shim.js') && after.includes('node user-hook.js'));
|
|
60
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
2026-10-03T21:07:10.515249Z INFO MCP tool call tool="synapse_efe_feedback" plugin=None
|
|
2
|
+
2026-10-03T21:07:45.377199Z INFO MCP tool call tool="alaya_recall" plugin=None
|
|
3
|
+
2026-10-03T21:07:53.574088Z WARN [session_watcher] reflex check: role=assistant, text_len=119, blocks=1, project_path=Some("C:/Users/user/Documents/GitHub/KenazAI")
|
|
4
|
+
2026-10-03T21:07:53.574900Z WARN [session_watcher] reflex check: role=assistant, text_len=119, blocks=1, project_path=Some("C:/Users/user/Documents/GitHub/KenazAI")
|
|
5
|
+
2026-10-03T21:07:54.168238Z INFO MCP tool call tool="cortex_recall" plugin=None
|
|
6
|
+
2026-10-03T21:07:54.372461Z INFO MCP tool call tool="alaya_recall" plugin=None
|
|
7
|
+
2026-10-03T21:07:54.728901Z INFO MCP tool call tool="hippocampus_episode_recall" plugin=None
|
|
8
|
+
2026-10-03T21:07:55.213271Z INFO MCP tool call tool="synapse_health" plugin=None
|
|
9
|
+
2026-10-03T21:08:37.929534Z WARN [session_watcher] reflex check: role=assistant, text_len=2101, blocks=1, project_path=Some("C:/Users/user/Documents/GitHub/KenazAI")
|
|
10
|
+
2026-10-03T21:08:37.930488Z WARN [session_watcher] reflex check: role=assistant, text_len=2101, blocks=1, project_path=Some("C:/Users/user/Documents/GitHub/KenazAI")
|
|
11
|
+
2026-10-03T21:10:36.990645Z INFO MCP tool call tool="synapse_efe_feedback" plugin=None
|
|
12
|
+
2026-10-03T21:10:37.101533Z INFO MCP tool call tool="synapse_efe_feedback" plugin=None
|
|
13
|
+
2026-10-03T21:10:47.558693Z WARN [session_watcher] reflex check: role=assistant, text_len=153, blocks=1, project_path=Some("C:/Users/user/Documents/GitHub/KenazAI")
|
|
14
|
+
2026-10-03T21:10:47.558790Z WARN [session_watcher] reflex check: role=assistant, text_len=153, blocks=1, project_path=Some("C:/Users/user/Documents/GitHub/KenazAI")
|
|
15
|
+
2026-10-03T21:12:34.601726Z INFO backend logging initialized version="0.2.263" pid=8024 started_at=2026-10-04 05:12:34.601 profile="debug" log_path=C:\Users\user\AppData\Local\Kenaz Dashboard\backend.log
|
|
16
|
+
2026-10-03T21:12:34.601803Z INFO startup mark label="after_init_tracing" t_ms=3 thread=main
|
|
17
|
+
2026-10-03T21:12:35.010413Z INFO startup mark label="setup_entry" t_ms=411 thread=main
|
|
18
|
+
2026-10-03T21:12:35.015743Z INFO startup mark label="mcp_servers_spawn_issued" t_ms=417 thread=main
|
|
19
|
+
2026-10-03T21:12:35.015846Z INFO startup mark label="mcp_servers_task_entered" t_ms=417 thread=tokio-runtime-worker
|
|
20
|
+
2026-10-03T21:12:35.016550Z INFO startup mark label="mcp_servers_start_done" t_ms=417 thread=tokio-runtime-worker
|
|
21
|
+
2026-10-03T21:12:35.262343Z INFO startup mark label="onnx_preload_dylib_done" t_ms=663 thread=main
|
|
22
|
+
2026-10-03T21:12:35.262445Z INFO startup mark label="onnx_warmup_thread_spawn_issued" t_ms=663 thread=main
|
|
23
|
+
2026-10-03T21:12:35.262574Z INFO startup mark label="delta_graph_recovery_thread_spawn_issued" t_ms=664 thread=main
|
|
24
|
+
2026-10-03T21:12:35.262763Z INFO startup mark label="sleep_cycle_daemon_spawn_issued" t_ms=664 thread=main
|
|
25
|
+
2026-10-03T21:12:35.262754Z INFO startup mark label="onnx_warmup_begin" t_ms=664 thread=onnx-warmup
|
|
26
|
+
2026-10-03T21:12:35.262886Z INFO startup mark label="delta_graph_recovery_begin" t_ms=664 thread=delta-gap-recovery
|
|
27
|
+
2026-10-03T21:12:35.265586Z INFO startup mark label="http_sidecar_task_spawn_issued" t_ms=667 thread=main
|
|
28
|
+
2026-10-03T21:12:35.265647Z INFO startup mark label="auto_index_watcher_spawn_issued" t_ms=667 thread=main
|
|
29
|
+
2026-10-03T21:12:35.265727Z INFO startup mark label="http_sidecar_task_entered" t_ms=667 thread=tokio-runtime-worker
|
|
30
|
+
2026-10-03T21:12:35.265789Z INFO startup mark label="setup_fn_returning" t_ms=667 thread=main
|
|
31
|
+
2026-10-03T21:12:35.265824Z INFO startup mark label="auto_index_watcher_task_entered" t_ms=667 thread=tokio-runtime-worker
|
|
32
|
+
2026-10-03T21:12:35.291199Z INFO [synapse] IS_INDEXING set — indexing started project=C:/Users/user/Documents/GitHub/KenazAI mode="incremental"
|
|
33
|
+
2026-10-03T21:12:35.291229Z INFO [synapse] reindex phase transition phase="init" project=C:/Users/user/Documents/GitHub/KenazAI
|
|
34
|
+
2026-10-03T21:12:35.358777Z INFO Loading ONNX embedding model [query] (ArcticEmbedXs, dim=384) from C:\Users\user\Documents\GitHub\KenazAI\dashboard\src-tauri\target\debug\resources\onnx\arctic-embed-xs
|
|
35
|
+
2026-10-03T21:12:35.635924Z INFO Embedding engine [query] loaded successfully (ArcticEmbedXs, dim=384, outputs=["last_hidden_state"], token_type_ids=true)
|
|
36
|
+
2026-10-03T21:12:35.636005Z INFO startup mark label="onnx_warmup_done" t_ms=1037 thread=onnx-warmup
|
|
37
|
+
2026-10-03T21:12:36.101980Z INFO startup mark label="http_server_start_begin" t_ms=1503 thread=tokio-runtime-worker
|
|
38
|
+
2026-10-03T21:12:36.119887Z INFO startup mark label="http_server_start_ready" t_ms=1521 thread=tokio-runtime-worker
|
|
39
|
+
2026-10-03T21:12:36.122223Z INFO synapse worker forwarder configuration workers_enabled=true current_project=C:/Users/user/Documents/GitHub/KenazAI
|
|
40
|
+
2026-10-03T21:12:36.122290Z INFO reaper armed leaseless_idle_secs=300 leased_idle_secs=900 tick_secs=60 per_worker_rss_cap_mb=400 total_rss_cap_mb=1200 max_workers=3
|
|
41
|
+
2026-10-03T21:12:36.275465Z INFO startup mark label="ready_wait_end" t_ms=1676 thread=tokio-runtime-worker
|
|
42
|
+
2026-10-03T21:12:37.479820Z INFO [synapse] reindex phase transition phase="kuzu_write_start:2_files" project=C:/Users/user/Documents/GitHub/KenazAI
|
|
43
|
+
2026-10-03T21:12:37.815038Z ERROR [conn pool] GRAPH CORRUPT SUSPECT for C:/Users/user/Documents/GitHub/KenazAI\.synapse\db\graph: Failed to DETACH DELETE Symbol nodes for dashboard/src-tauri/src/features/synapse/scanner.rs: Query execution failed: kuzu native exception 0xC0000005 — no further kuzu calls will be issued against this Database for the rest of this process's lifetime (persisted; the next start will also refuse it). Recovery: rebuild_graph.
|
|
44
|
+
2026-10-03T21:12:37.815639Z ERROR [synapse] dashboard/src-tauri/src/features/synapse/scanner.rs write hit a native ACCESS_VIOLATION — graph marked corrupt_suspect, aborting the round instead of quarantining just this file: Failed to DETACH DELETE Symbol nodes for dashboard/src-tauri/src/features/synapse/scanner.rs: Query execution failed: kuzu native exception 0xC0000005
|
|
45
|
+
2026-10-03T21:12:37.815845Z ERROR Incremental index round aborted mid-batch (with_connection closure returned Err): Failed to DETACH DELETE Symbol nodes for dashboard/src-tauri/src/features/synapse/scanner.rs: Query execution failed: kuzu native exception 0xC0000005. Recording phase=failed and NOT advancing last_commit_hash, so the file(s) that caused this are retried (re-appear in the git diff) on the next incremental cycle instead of being permanently skipped.
|
|
46
|
+
2026-10-03T21:12:37.823713Z INFO [synapse] IS_INDEXING cleared project=C:/Users/user/Documents/GitHub/KenazAI
|
|
47
|
+
2026-10-03T21:12:39.477700Z INFO [synapse spool] drain: attempted=1 replayed=0 still_pending=1 dead_lettered=0
|
|
48
|
+
2026-10-03T21:12:40.139564Z INFO startup mark label="session_watcher_start_begin" t_ms=5541 thread=tokio-runtime-worker
|
|
49
|
+
2026-10-03T21:12:40.139634Z INFO startup mark label="session_watcher_start_done" t_ms=5541 thread=tokio-runtime-worker
|
|
50
|
+
2026-10-03T21:12:40.139740Z INFO [session_watcher] Watching "C:\\Users\\user\\.claude\\projects\\C--Users-user-Documents-GitHub-KenazAI" (notify + polling fallback)
|
|
51
|
+
2026-10-03T21:12:44.502961Z INFO startup mark label="synapse_kuzu_memorydb_open_done" t_ms=9904 thread=delta-gap-recovery
|
|
52
|
+
2026-10-03T21:12:44.680900Z INFO startup mark label="delta_graph_recovery_done" t_ms=10082 thread=delta-gap-recovery
|
|
53
|
+
2026-10-03T21:12:44.706667Z INFO startup mark label="heat_cache_load_done" t_ms=10108 thread=delta-gap-recovery
|
|
54
|
+
2026-10-03T21:13:01.645377Z INFO MCP tool call tool="synapse_efe_feedback" plugin=None
|
|
55
|
+
2026-10-03T21:13:01.645462Z INFO MCP tool call tool="synapse_efe_feedback" plugin=None
|
|
56
|
+
2026-10-03T21:13:01.650906Z INFO MCP tool call tool="synapse_cypher" plugin=None
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Failed to DETACH DELETE Symbol nodes for dashboard/src-tauri/src/features/synapse/scanner.rs: Query execution failed: kuzu native exception 0xC0000005
|
|
@@ -8,7 +8,8 @@ ARGUMENTS 含 `[專案: X]` 或 `--project-path X` → PROJECT_PATH = X,下方
|
|
|
8
8
|
## Boot(一次 Bash,無其他儀式)
|
|
9
9
|
1. Turn Context 若有 `[session] session_id=<id>`,記住 `<id>`。
|
|
10
10
|
2. 執行 `node "${CLAUDE_PLUGIN_ROOT}/hooks/core-resolve.js" .specialist/tools/ansuz-boot-fast.js`(有 `<id>` 加 `--conversation-id="<id>"`;有 PROJECT_PATH 加 `--project-path`)。
|
|
11
|
-
3.
|
|
11
|
+
3. banner 有 `📎 Project handoff` 時,**先用 Read 讀 → 標記的那份全文**(不用問用戶),以它為準接續上一個 session。
|
|
12
|
+
4. 把 banner 轉述給用戶(Bash 輸出在 UI 會摺疊),依 handoff 的 R 段與 `📋 Open cards` 直接提出議程。
|
|
12
13
|
|
|
13
14
|
## 每件工作的做法
|
|
14
15
|
- **自己做**:小而明確的修正(約 30 行內、單一檔案或少數檔案)→ 直接改,跑最近的測試,提交。
|
|
@@ -16,6 +17,7 @@ ARGUMENTS 含 `[專案: X]` 或 `--project-path X` → PROJECT_PATH = X,下方
|
|
|
16
17
|
1. 用 `kenaz_task_create` 開卡(`projectPath` = 目前專案;寫清楚 requirements、acceptance criteria、scope paths)。查卡、改狀態用 `kenaz_task_list` / `kenaz_task_get` / `kenaz_task_update`。
|
|
17
18
|
2. 產生派工內容:`node "${CLAUDE_PLUGIN_ROOT}/hooks/core-resolve.js" .formation/tools/dispatch.js --skill=do --task=TASK_XXX --dispatch-mode=subagent`(有 PROJECT_PATH 加 `--project-path`)。把輸出 JSON 的 `promptText` 交給 subagent,`agentParams` 照用(模型不要自己換)。
|
|
18
19
|
3. subagent 在 worktree 裡改完並 commit;你驗證後合併。
|
|
20
|
+
若輸出是 `executor` 區塊(模型為 `codex:<id>` / `deepseek:<model>`,無 agentParams):用 Bash run_in_background 執行 `executor.command`,等完成通知,讀 `executor.resultFile`(ok、commits;`no commits` = 失敗),再照常驗證並合併 `executor.branchName`。
|
|
19
21
|
- 開卡前先確認 scope 與驗收條件對準真正的問題,不要照著錯的假設派工。
|
|
20
22
|
|
|
21
23
|
## 驗證(合併前一定做,強度跟風險相稱)
|
|
@@ -24,6 +26,12 @@ ARGUMENTS 含 `[專案: X]` 或 `--project-path X` → PROJECT_PATH = X,下方
|
|
|
24
26
|
- subagent 回報「未驗證」的項目,由你補驗或明講仍未驗證。
|
|
25
27
|
- 合併:`git merge` 後跑相關測試(或 `node "${CLAUDE_PLUGIN_ROOT}/hooks/core-resolve.js" .specialist/Ansuz/tools/verify-and-land.js`),用這個專案自己的測試指令。
|
|
26
28
|
|
|
29
|
+
## 交接(handoff,ISBAR)
|
|
30
|
+
用戶說交接/暫停/換 session、context 快滿、或結束時仍有未完成的工作 → 寫交接:
|
|
31
|
+
1. `node "${CLAUDE_PLUGIN_ROOT}/hooks/core-resolve.js" .specialist/tools/handoff-doc.js new --topic "<主題>" --session <id>`(有 PROJECT_PATH 加 `--project-path`),建立 `<專案>/.kenaz/handoffs/<日期時間>-<主題>.md`,I 段已自動填好。
|
|
32
|
+
2. 用 Edit 填 S(現況)、B(背景:用戶決定原話、相關卡與 commit)、A(已驗證/未驗證/風險)、R(下一個 session 第一步、待用戶決定的事)。寫給「沒看過這段對話的人」,不寫空泛句。
|
|
33
|
+
3. 一份交接一個檔,不覆寫舊的;下一個 session 的 boot 會自動列出並讀最新那份。
|
|
34
|
+
|
|
27
35
|
## 回報與提問
|
|
28
36
|
- 一律用用戶的語言(中文訊息 → 中文回覆,含提問選項)。
|
|
29
37
|
- 需要用戶決定時用 `AskUserQuestion`(2-4 個選項、建議的放第一個),不要在文字裡列選項等回覆;有證據能自己判斷的事不問。
|
|
@@ -38,5 +46,7 @@ Kenaz 的工具、hook、安裝、peer、派工擋住或拖慢工作時,**繞
|
|
|
38
46
|
## 參考產品(REA)與學習教訓
|
|
39
47
|
- banner `[rea]` 行:用戶提到參考產品時,有 REA 就提議分析,沒有就提示一次 `npx rea-agents setup`(範圍見 RULES.md 的 REA)。
|
|
40
48
|
- 用戶糾正/重複指示、推翻決定、或驗證抓到失敗時,自動寫教訓並在回報點名一行:`node "${CLAUDE_PLUGIN_ROOT}/hooks/core-resolve.js" .specialist/tools/lessons.js add --scope user|project --type pref|fact|pitfall|check --text "..."`(規則見 RULES.md 的 Lessons)。
|
|
49
|
+
- banner 出現 `[lessons] N to graduate`:跑 `kenaz learn review`,提議把排第一的教訓改成代碼(測試、hook 檢查或專案 CLAUDE.md/AGENTS.md 規則,這是首選結果);糾正若與既有教訓相符屬於重複(recurrence),不是新教訓(`add` 會自動累加)。
|
|
50
|
+
- banner 出現 `[learn] N history items to review`:跑 `kenaz learn review`,每個歷史項目(返工、executor 失敗、blocked 卡、handoff 風險行)有現成的 `kenaz learn add ... --source harvest:<id>`,值得記的補上 why 後執行,其餘忽略;指標建議(各 rigor 一次過率、返工最多的檔案)只建議給用戶,不自行套用。詳見 RULES.md。
|
|
41
51
|
|
|
42
52
|
需要更多規則時(授權自主、派工前、合併前、參考產品、寫教訓)讀 `${CLAUDE_PLUGIN_ROOT}/../../.specialist/Ansuz/RULES.md`。
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Switch or show the Kenaz mode (off | assist | full | status | init),
|
|
3
|
-
argument-hint: off|assist|full|status|init|ygg
|
|
2
|
+
description: Switch or show the Kenaz mode (off | assist | full | status | init), set up Yggdrasil (ygg join|status|leave), or show/set the subagent model (subagent [set <id>|unset] [--rigor r])
|
|
3
|
+
argument-hint: off|assist|full|status|init|ygg|subagent
|
|
4
4
|
allowed-tools: Bash(node:*)
|
|
5
5
|
---
|
|
6
|
-
Run exactly this and report its output (one line for modes; the full block for `ygg`), nothing else:
|
|
6
|
+
Run exactly this and report its output (one line for modes; the full block for `ygg` and `subagent`), nothing else:
|
|
7
7
|
|
|
8
8
|
`node "${CLAUDE_PLUGIN_ROOT}/scripts/kenaz-mode.js" $ARGUMENTS`
|
|
9
9
|
|
|
10
10
|
Modes: full = guidance + all hooks; assist = silent telemetry/bookkeeping hooks only (no context injection); off = every Kenaz hook exits immediately. init creates .kenaz/project.yaml so hooks act in a fresh project.
|
|
11
11
|
|
|
12
12
|
`ygg join <key> [--project|--global]` stores the Yggdrasil connection key (default: this project's own slot) and activates collaboration here; `ygg status` shows room, node, relay, peers and mail (key masked); `ygg leave` removes this project's key. Needs kenaz-server running (installed by `npx kenaz install`).
|
|
13
|
+
|
|
14
|
+
`subagent` shows the subagent (dispatch) model per rigor for this project; `subagent set <id> [--rigor low|medium|high]` changes it, `subagent unset [--rigor r]` reverts (writes .kenaz/dashboard-models.json). Ansuz itself runs on this session's model (/model).
|
|
@@ -10,6 +10,12 @@ if (arg === 'ygg') {
|
|
|
10
10
|
const r = require('child_process').spawnSync(process.execPath, [path.join(__dirname, 'ygg.js'), ...process.argv.slice(3)], { stdio: 'inherit' });
|
|
11
11
|
process.exit(r.status === null ? 1 : r.status);
|
|
12
12
|
}
|
|
13
|
+
if (arg === 'subagent' || arg === 'model') {
|
|
14
|
+
// Subagent (dispatch) model: subagent [set <id>|unset] [--rigor r]; same as `kenaz subagent`, for this project
|
|
15
|
+
const tool = path.join(__dirname, '..', '..', '..', '.formation', 'tools', 'dispatch-model.js');
|
|
16
|
+
const r = require('child_process').spawnSync(process.execPath, [tool, ...process.argv.slice(3), '--project-path', projectDir()], { stdio: 'inherit' });
|
|
17
|
+
process.exit(r.status === null ? 1 : r.status);
|
|
18
|
+
}
|
|
13
19
|
const dir = projectDir();
|
|
14
20
|
if (MODES.includes(arg)) {
|
|
15
21
|
setMode(arg, dir);
|