draken 0.1.5 → 0.2.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.
Files changed (301) hide show
  1. package/ACCEPTANCE.md +31 -0
  2. package/CHANGELOG.md +33 -0
  3. package/CONTRIBUTING.md +129 -0
  4. package/MEMORY.md +98 -0
  5. package/PERSONA.md +67 -0
  6. package/README.md +156 -78
  7. package/SETUP.md +111 -0
  8. package/SOURCES.md +75 -0
  9. package/TRAY.md +54 -0
  10. package/VOICE.md +118 -0
  11. package/dist/auth/middleware.d.ts +3 -1
  12. package/dist/auth/middleware.d.ts.map +1 -1
  13. package/dist/auth/middleware.js +20 -15
  14. package/dist/auth/middleware.js.map +1 -1
  15. package/dist/cli.js +77 -58
  16. package/dist/cli.js.map +1 -1
  17. package/dist/db/agent-migration.d.ts +7 -0
  18. package/dist/db/agent-migration.d.ts.map +1 -0
  19. package/dist/db/agent-migration.js +36 -0
  20. package/dist/db/agent-migration.js.map +1 -0
  21. package/dist/db/evidence.d.ts +37 -0
  22. package/dist/db/evidence.d.ts.map +1 -0
  23. package/dist/db/evidence.js +110 -0
  24. package/dist/db/evidence.js.map +1 -0
  25. package/dist/db/pointer-migration.d.ts +7 -0
  26. package/dist/db/pointer-migration.d.ts.map +1 -0
  27. package/dist/db/pointer-migration.js +117 -0
  28. package/dist/db/pointer-migration.js.map +1 -0
  29. package/dist/db/retained-text.d.ts +8 -0
  30. package/dist/db/retained-text.d.ts.map +1 -0
  31. package/dist/db/retained-text.js +36 -0
  32. package/dist/db/retained-text.js.map +1 -0
  33. package/dist/db/schema.d.ts +1 -5
  34. package/dist/db/schema.d.ts.map +1 -1
  35. package/dist/db/schema.js +200 -55
  36. package/dist/db/schema.js.map +1 -1
  37. package/dist/db/snapshot-pointers.d.ts +5 -0
  38. package/dist/db/snapshot-pointers.d.ts.map +1 -0
  39. package/dist/db/snapshot-pointers.js +174 -0
  40. package/dist/db/snapshot-pointers.js.map +1 -0
  41. package/dist/memory/automatic.d.ts +38 -0
  42. package/dist/memory/automatic.d.ts.map +1 -0
  43. package/dist/memory/automatic.js +155 -0
  44. package/dist/memory/automatic.js.map +1 -0
  45. package/dist/memory/context.d.ts +12 -0
  46. package/dist/memory/context.d.ts.map +1 -0
  47. package/dist/memory/context.js +59 -0
  48. package/dist/memory/context.js.map +1 -0
  49. package/dist/memory/embedding-pool.d.ts +28 -0
  50. package/dist/memory/embedding-pool.d.ts.map +1 -0
  51. package/dist/memory/embedding-pool.js +135 -0
  52. package/dist/memory/embedding-pool.js.map +1 -0
  53. package/dist/memory/embedding-worker.d.ts +2 -0
  54. package/dist/memory/embedding-worker.d.ts.map +1 -0
  55. package/dist/memory/embedding-worker.js +32 -0
  56. package/dist/memory/embedding-worker.js.map +1 -0
  57. package/dist/memory/index.d.ts +26 -0
  58. package/dist/memory/index.d.ts.map +1 -0
  59. package/dist/memory/index.js +283 -0
  60. package/dist/memory/index.js.map +1 -0
  61. package/dist/memory/model.d.ts +15 -0
  62. package/dist/memory/model.d.ts.map +1 -0
  63. package/dist/memory/model.js +152 -0
  64. package/dist/memory/model.js.map +1 -0
  65. package/dist/memory/service.d.ts +8 -0
  66. package/dist/memory/service.d.ts.map +1 -0
  67. package/dist/memory/service.js +217 -0
  68. package/dist/memory/service.js.map +1 -0
  69. package/dist/memory/sources.d.ts +15 -0
  70. package/dist/memory/sources.d.ts.map +1 -0
  71. package/dist/memory/sources.js +87 -0
  72. package/dist/memory/sources.js.map +1 -0
  73. package/dist/memory/stamps.d.ts +13 -0
  74. package/dist/memory/stamps.d.ts.map +1 -0
  75. package/dist/memory/stamps.js +101 -0
  76. package/dist/memory/stamps.js.map +1 -0
  77. package/dist/memory/storage.d.ts +5 -0
  78. package/dist/memory/storage.d.ts.map +1 -0
  79. package/dist/memory/storage.js +107 -0
  80. package/dist/memory/storage.js.map +1 -0
  81. package/dist/memory/types.d.ts +68 -0
  82. package/dist/memory/types.d.ts.map +1 -0
  83. package/dist/memory/types.js +8 -0
  84. package/dist/memory/types.js.map +1 -0
  85. package/dist/memory/worker.d.ts +2 -0
  86. package/dist/memory/worker.d.ts.map +1 -0
  87. package/dist/memory/worker.js +82 -0
  88. package/dist/memory/worker.js.map +1 -0
  89. package/dist/npm-cli.d.ts +4 -0
  90. package/dist/npm-cli.d.ts.map +1 -0
  91. package/dist/npm-cli.js +36 -0
  92. package/dist/npm-cli.js.map +1 -0
  93. package/dist/pi/runtime.d.ts +34 -0
  94. package/dist/pi/runtime.d.ts.map +1 -0
  95. package/dist/pi/runtime.js +210 -0
  96. package/dist/pi/runtime.js.map +1 -0
  97. package/dist/pi/setup.d.ts +5 -0
  98. package/dist/pi/setup.d.ts.map +1 -0
  99. package/dist/pi/setup.js +147 -0
  100. package/dist/pi/setup.js.map +1 -0
  101. package/dist/routes/auth.d.ts.map +1 -1
  102. package/dist/routes/auth.js +3 -1
  103. package/dist/routes/auth.js.map +1 -1
  104. package/dist/routes/live-voice.d.ts +3 -0
  105. package/dist/routes/live-voice.d.ts.map +1 -0
  106. package/dist/routes/live-voice.js +49 -0
  107. package/dist/routes/live-voice.js.map +1 -0
  108. package/dist/routes/{browse.d.ts → memory.d.ts} +1 -1
  109. package/dist/routes/memory.d.ts.map +1 -0
  110. package/dist/routes/memory.js +18 -0
  111. package/dist/routes/memory.js.map +1 -0
  112. package/dist/routes/{tasks.d.ts → sync.d.ts} +1 -1
  113. package/dist/routes/sync.d.ts.map +1 -0
  114. package/dist/routes/sync.js +127 -0
  115. package/dist/routes/sync.js.map +1 -0
  116. package/dist/routes/{projects.d.ts → voice.d.ts} +1 -1
  117. package/dist/routes/voice.d.ts.map +1 -0
  118. package/dist/routes/voice.js +35 -0
  119. package/dist/routes/voice.js.map +1 -0
  120. package/dist/server-state.d.ts +30 -0
  121. package/dist/server-state.d.ts.map +1 -0
  122. package/dist/server-state.js +113 -0
  123. package/dist/server-state.js.map +1 -0
  124. package/dist/server-status.d.ts +7 -0
  125. package/dist/server-status.d.ts.map +1 -0
  126. package/dist/server-status.js +34 -0
  127. package/dist/server-status.js.map +1 -0
  128. package/dist/server.d.ts +5 -1
  129. package/dist/server.d.ts.map +1 -1
  130. package/dist/server.js +148 -46
  131. package/dist/server.js.map +1 -1
  132. package/dist/sources/adapters.d.ts +15 -0
  133. package/dist/sources/adapters.d.ts.map +1 -0
  134. package/dist/sources/adapters.js +159 -0
  135. package/dist/sources/adapters.js.map +1 -0
  136. package/dist/sources/registry.d.ts +17 -0
  137. package/dist/sources/registry.d.ts.map +1 -0
  138. package/dist/sources/registry.js +56 -0
  139. package/dist/sources/registry.js.map +1 -0
  140. package/dist/sync/collector.d.ts +3 -0
  141. package/dist/sync/collector.d.ts.map +1 -0
  142. package/dist/sync/collector.js +284 -0
  143. package/dist/sync/collector.js.map +1 -0
  144. package/dist/sync/cost.d.ts +7 -0
  145. package/dist/sync/cost.d.ts.map +1 -0
  146. package/dist/sync/cost.js +31 -0
  147. package/dist/sync/cost.js.map +1 -0
  148. package/dist/sync/jsonl.d.ts +34 -0
  149. package/dist/sync/jsonl.d.ts.map +1 -0
  150. package/dist/sync/jsonl.js +161 -0
  151. package/dist/sync/jsonl.js.map +1 -0
  152. package/dist/sync/manager.d.ts +12 -0
  153. package/dist/sync/manager.d.ts.map +1 -0
  154. package/dist/sync/manager.js +211 -0
  155. package/dist/sync/manager.js.map +1 -0
  156. package/dist/sync/normalize.d.ts +22 -0
  157. package/dist/sync/normalize.d.ts.map +1 -0
  158. package/dist/sync/normalize.js +107 -0
  159. package/dist/sync/normalize.js.map +1 -0
  160. package/dist/sync/pi-output.d.ts +33 -0
  161. package/dist/sync/pi-output.d.ts.map +1 -0
  162. package/dist/sync/pi-output.js +186 -0
  163. package/dist/sync/pi-output.js.map +1 -0
  164. package/dist/sync/pi.d.ts +15 -0
  165. package/dist/sync/pi.d.ts.map +1 -0
  166. package/dist/sync/pi.js +149 -0
  167. package/dist/sync/pi.js.map +1 -0
  168. package/dist/sync/recap.d.ts +25 -0
  169. package/dist/sync/recap.d.ts.map +1 -0
  170. package/dist/sync/recap.js +118 -0
  171. package/dist/sync/recap.js.map +1 -0
  172. package/dist/sync/references.d.ts +10 -0
  173. package/dist/sync/references.d.ts.map +1 -0
  174. package/dist/sync/references.js +50 -0
  175. package/dist/sync/references.js.map +1 -0
  176. package/dist/sync/source-files.d.ts +16 -0
  177. package/dist/sync/source-files.d.ts.map +1 -0
  178. package/dist/sync/source-files.js +56 -0
  179. package/dist/sync/source-files.js.map +1 -0
  180. package/dist/sync/store.d.ts +36 -0
  181. package/dist/sync/store.d.ts.map +1 -0
  182. package/dist/sync/store.js +359 -0
  183. package/dist/sync/store.js.map +1 -0
  184. package/dist/sync/summary-budget.d.ts +19 -0
  185. package/dist/sync/summary-budget.d.ts.map +1 -0
  186. package/dist/sync/summary-budget.js +39 -0
  187. package/dist/sync/summary-budget.js.map +1 -0
  188. package/dist/sync/tree.d.ts +69 -0
  189. package/dist/sync/tree.d.ts.map +1 -0
  190. package/dist/sync/tree.js +599 -0
  191. package/dist/sync/tree.js.map +1 -0
  192. package/dist/tray/controller.d.ts +51 -0
  193. package/dist/tray/controller.d.ts.map +1 -0
  194. package/dist/tray/controller.js +178 -0
  195. package/dist/tray/controller.js.map +1 -0
  196. package/dist/tray/launcher.d.ts +3 -0
  197. package/dist/tray/launcher.d.ts.map +1 -0
  198. package/dist/tray/launcher.js +47 -0
  199. package/dist/tray/launcher.js.map +1 -0
  200. package/dist/tray/native.d.ts +12 -0
  201. package/dist/tray/native.d.ts.map +1 -0
  202. package/dist/tray/native.js +93 -0
  203. package/dist/tray/native.js.map +1 -0
  204. package/dist/tray/processes.d.ts +5 -0
  205. package/dist/tray/processes.d.ts.map +1 -0
  206. package/dist/tray/processes.js +99 -0
  207. package/dist/tray/processes.js.map +1 -0
  208. package/dist/tray/worker.d.ts +4 -0
  209. package/dist/tray/worker.d.ts.map +1 -0
  210. package/dist/tray/worker.js +150 -0
  211. package/dist/tray/worker.js.map +1 -0
  212. package/dist/types.d.ts +212 -20
  213. package/dist/types.d.ts.map +1 -1
  214. package/dist/voice/continuation.d.ts +25 -0
  215. package/dist/voice/continuation.d.ts.map +1 -0
  216. package/dist/voice/continuation.js +94 -0
  217. package/dist/voice/continuation.js.map +1 -0
  218. package/dist/voice/legacy-history.d.ts +5 -0
  219. package/dist/voice/legacy-history.d.ts.map +1 -0
  220. package/dist/voice/legacy-history.js +34 -0
  221. package/dist/voice/legacy-history.js.map +1 -0
  222. package/dist/voice/live-context.d.ts +14 -0
  223. package/dist/voice/live-context.d.ts.map +1 -0
  224. package/dist/voice/live-context.js +137 -0
  225. package/dist/voice/live-context.js.map +1 -0
  226. package/dist/voice/live.d.ts +37 -0
  227. package/dist/voice/live.d.ts.map +1 -0
  228. package/dist/voice/live.js +448 -0
  229. package/dist/voice/live.js.map +1 -0
  230. package/package.json +49 -16
  231. package/public/assets/index-CYz_kpAp.js +126 -0
  232. package/public/assets/index-DmRid5xE.css +1 -0
  233. package/public/assets/index-Ymd62i3g.js +40 -0
  234. package/public/assets/persona-C_m1CVKe.css +1 -0
  235. package/public/assets/persona-XbLvCqRT.js +1 -0
  236. package/public/assets/scene-CBV2oPhA.js +3854 -0
  237. package/public/index.html +6 -8
  238. package/public/persona/THREE-LICENSE.txt +21 -0
  239. package/public/persona/call-poster.webp +0 -0
  240. package/public/persona/reference.jpg +0 -0
  241. package/public/persona/sample.wav +0 -0
  242. package/public/persona.html +7 -0
  243. package/runtime/pi/package-lock.json +1549 -0
  244. package/runtime/pi/package.json +12 -0
  245. package/tests/fixtures/voice-question.wav +0 -0
  246. package/tray/assets/error.ico +0 -0
  247. package/tray/assets/error.png +0 -0
  248. package/tray/assets/running.ico +0 -0
  249. package/tray/assets/running.png +0 -0
  250. package/tray/assets/starting.ico +0 -0
  251. package/tray/assets/starting.png +0 -0
  252. package/tray/assets/stopped.ico +0 -0
  253. package/tray/assets/stopped.png +0 -0
  254. package/tray/assets/stopping.ico +0 -0
  255. package/tray/assets/stopping.png +0 -0
  256. package/tray/macos.js +72 -0
  257. package/tray/windows.ps1 +104 -0
  258. package/voice/realtime/README.md +84 -0
  259. package/voice/realtime/backend.mjs +81 -0
  260. package/voice/realtime/native.mjs +210 -0
  261. package/voice/realtime/peer.d.mts +15 -0
  262. package/voice/realtime/peer.mjs +116 -0
  263. package/voice/realtime/probe-browser.mjs +81 -0
  264. package/voice/realtime/probe-server.mjs +86 -0
  265. package/voice/realtime/probe.html +11 -0
  266. package/voice/realtime/probe.mjs +42 -0
  267. package/voice/realtime/rpc.mjs +118 -0
  268. package/voice/realtime/setup.mjs +32 -0
  269. package/voice/tls.mjs +49 -0
  270. package/dist/db/queries.d.ts +0 -16
  271. package/dist/db/queries.d.ts.map +0 -1
  272. package/dist/db/queries.js +0 -91
  273. package/dist/db/queries.js.map +0 -1
  274. package/dist/docker/dockerfile.d.ts +0 -50
  275. package/dist/docker/dockerfile.d.ts.map +0 -1
  276. package/dist/docker/dockerfile.js +0 -160
  277. package/dist/docker/dockerfile.js.map +0 -1
  278. package/dist/docker/manager.d.ts +0 -42
  279. package/dist/docker/manager.d.ts.map +0 -1
  280. package/dist/docker/manager.js +0 -421
  281. package/dist/docker/manager.js.map +0 -1
  282. package/dist/git/status.d.ts +0 -76
  283. package/dist/git/status.d.ts.map +0 -1
  284. package/dist/git/status.js +0 -332
  285. package/dist/git/status.js.map +0 -1
  286. package/dist/routes/browse.d.ts.map +0 -1
  287. package/dist/routes/browse.js +0 -49
  288. package/dist/routes/browse.js.map +0 -1
  289. package/dist/routes/git.d.ts +0 -9
  290. package/dist/routes/git.d.ts.map +0 -1
  291. package/dist/routes/git.js +0 -338
  292. package/dist/routes/git.js.map +0 -1
  293. package/dist/routes/projects.d.ts.map +0 -1
  294. package/dist/routes/projects.js +0 -220
  295. package/dist/routes/projects.js.map +0 -1
  296. package/dist/routes/tasks.d.ts.map +0 -1
  297. package/dist/routes/tasks.js +0 -313
  298. package/dist/routes/tasks.js.map +0 -1
  299. package/draken.dockerfile.template +0 -18
  300. package/public/assets/index-3ngsG5kF.css +0 -1
  301. package/public/assets/index-B3YSD0ee.js +0 -252
package/README.md CHANGED
@@ -1,115 +1,193 @@
1
- <p align="center">
2
- <img src="site/img/logo.png" width="140" alt="Draken">
3
- </p>
1
+ <p align="center"><img src="site/img/logo.png" width="100" alt="Draken"></p>
4
2
 
5
- <h1 align="center">Draken</h1>
3
+ # Draken — engineering sync
6
4
 
7
- <p align="center">
8
- <img src="site/img/scene1-web.jpg" width="600" alt="Draken - Async Claude Code Dashboard">
9
- </p>
5
+ A local-first engineering sync across your **pi, Codex CLI and Claude Code sessions**. Session readers are agent-neutral; summarization still runs through pi.
10
6
 
11
- ### What is this???
7
+ > Draken is a read-only companion, not a task runner. It replaces the old Docker/Claude dashboard and does not launch coding workers or schedule tasks. Voice calls use only **ChatGPT live voice**, through a separate native sign-in to the same paid account. The previous local speech engine has been removed; historical call records are preserved. Voice sends audio to OpenAI; generated transcripts are not verified claims or exact playback records; see [VOICE.md](VOICE.md). Calls include a local animated **3D dragon persona**, with a standalone `/persona.html` preview; see [PERSONA.md](PERSONA.md).
8
+ >
9
+ > **Large histories now use a cached summary tree:** cheaper-model parsing and reconciliation, followed by a stronger-model verdict. The old raw-evidence snapshot cutoff is removed. This is still lossy model compression, not independent verification. See [ROADMAP.md](ROADMAP.md) for remaining quality evaluation and community research.
12
10
 
13
- One more Agent orchestrator that I build for myself.
11
+ **Sync with Draken → talk it through → keep a short recap.**
14
12
 
15
- It might be buggy and it might be weird.
13
+ The home page is compact history cards. Each sync has its own `/syncs/:id` URL, with the full briefing, conversations, notes and evidence behind it. **Search history** (`/history`) adds local semantic + keyword retrieval across retained older records, with dated source links. It prepares itself automatically—no enable/update buttons or search-mode choices. Progress counts only new or changed passages, with cached history shown separately and a measured time estimate. Local indexing reuses existing vectors and uses up to two embedding lanes/six CPU threads on sufficiently capable machines; smaller machines stay single-lane. Text questions and calls use it by default. See [MEMORY.md](MEMORY.md) for source scope, first-use download and limitations.
16
14
 
17
- But it fit my needs.
15
+ For a plain-English guide to the code, with diagrams and reasons for the main design choices, see [ARCHITECTURE.md](ARCHITECTURE.md). The [standalone visual guide](docs/architecture.html) opens in a browser without connecting to Draken; it contains no live data or app controls.
18
16
 
19
- ### WHY?
17
+ Draken remembers which evidence a finished sync covered, what you decided, and what remains open. Reading logs or generating a response does **not** advance that checkpoint.
20
18
 
21
- I often work on multiple projects simualtaniously and quite asynchrounously, and quite often I just want to submit a task for Claude in Private repo and return to it later.
22
- I can use github integration with Claude, or Tmux sessions, but first one is lacking full machine access to run whatever it wants to achieve a task.
23
- And tmux require ssh/machine access, so it doesn't really work when I commute or visiting at event.
19
+ ## Install and start
24
20
 
25
- The vision for Draken is that's asyncronous by nature and every interation with it is a single container run which completes and exits, the only artifact it produces is visible via `git diff`.
26
- Context is preserved via sessions and threads in UI, so you can have few async sessions and interact with them.
21
+ Requires Node.js **22.19+** and npm. Session-log indexing and evidence review do not require a model or pi executable. Generated briefings and discussion use **pi 1.4+**. Existing configured pi works unchanged; otherwise **`draken setup`** installs a pinned private runtime and **`draken login`** opens pi’s own authentication interface. See [SETUP.md](SETUP.md) for the full first-run flow, private directories and recovery.
27
22
 
28
- ---
23
+ > **Version note:** these instructions are for **Draken 0.2.0**. Versions **0.1.6 and earlier** are the old task dashboard, not this application. Back up your original agent logs and Draken data before upgrading; see [what changed](CHANGELOG.md).
29
24
 
30
- ## Install
25
+ ```sh
26
+ npm install -g draken@0.2.0
27
+ draken
28
+ ```
31
29
 
32
- ### Quick Start (npx)
30
+ Open **http://127.0.0.1:40333**. Every launch prints the URL and setup instructions. Keep the terminal open; Ctrl+C stops the server, while closing the browser does not. A normal loopback launch needs **no dashboard login or auth setup**. No Docker or Claude installation is needed.
33
31
 
34
- ```bash
35
- # Install prerequisites
36
- npm install -g @anthropic-ai/claude-code
37
- claude login # Authenticate with Anthropic
32
+ In another terminal, configure your summary runtime and, optionally, voice:
38
33
 
39
- # Run Draken (local dev, no auth)
40
- DRAKEN_NO_AUTH=true npx draken
34
+ ```sh
35
+ draken setup # Confirm private pi installation; --yes for explicit unattended consent
36
+ draken login # Inside pi: /login, follow prompts, then /quit
37
+ draken doctor # Local version/model-credential checks, not a provider request
38
+ draken voice setup # Optional voice: install the pinned native helper
39
+ draken voice login # Separate official ChatGPT sign-in
40
+ draken voice status # Local prerequisites, not an audio test
41
+ draken status # Find the saved server address and verify its live instance
42
+ draken tray # Optional macOS/Windows desktop companion (preview)
41
43
  ```
42
44
 
43
- Open http://localhost:40333
45
+ On macOS/Windows desktops, `draken tray` adds a background menu-bar/notification-area icon with status, Open, and owned-server Start/Stop controls. After it reports readiness, the terminal can close. Existing servers are monitored, never taken over. This first version does not register startup at login or replace the pi/voice login flows. Linux/headless use remains the foreground server plus `draken status`. See [TRAY.md](TRAY.md) for lifecycle rules and target-platform qualification still required.
44
46
 
45
- ### VPS Deployment
47
+ Run setup/login as the server’s user with the same environment. `draken status` remembers the server’s LAN address/port automatically; only a custom `DRAKEN_DATA_DIR` needs to be repeated. Home shows first-run or missing-prerequisite instructions; **Settings → Runtime & sign-in** always exposes them. Click **Check setup again** after login. Setup uses a shipped dependency lockfile and never silently installs at startup, copies existing credentials, changes global pi or authenticates through another coding agent. Model/voice access is not proved by credential presence.
46
48
 
47
- ```bash
48
- # 1. Install Node.js 18+ and Docker
49
- curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
50
- sudo apt-get install -y nodejs
51
- curl -fsSL https://get.docker.com | sh
52
- sudo usermod -aG docker $USER
49
+ 1. Set up [ChatGPT voice](VOICE.md) once. Use localhost or trusted HTTPS.
50
+ 2. Click **Sync with Draken**. Draken scans, freezes all available entries, summarizes earlier conversations, prepares the briefing, then starts the call on the same visible page. Browser microphone permission may still be required. This is one explicit action, not an automatic call on page load.
51
+ 3. Talk. Ending the call requests a short, cached recap; it never saves decisions or marks evidence reviewed.
52
+ 4. Return home for compact cards, or open any `/syncs/:id` independently. Reopening/reloading a URL never starts capture. **Call Draken** resumes discussion of that frozen snapshot without collecting later activity.
53
+ 5. If useful, expand the detail sections to inspect the briefing/evidence, ask in text, or explicitly save **Decisions** and **Carry into the next sync**. **Mark reviewed** is separate and optional before starting another sync; only that explicit action advances coverage.
53
54
 
54
- # 2. Install and authenticate Claude CLI
55
- npm install -g @anthropic-ai/claude-code
56
- claude login
55
+ **Settings** in the top bar is available on every page. **Settings → Automatically index history** optionally scans and prepares local search in the background while the server is running. It is off by default and survives restarts when enabled. Checks run once a minute while idle; background batches require at least 64 changed source records, with no timed flush. Smaller pending batches are prepared on demand when you sync, start a call or search. Foreground syncs/calls/searches take priority; completed embeddings survive cancellation. This is local scanning/embedding only, not automatic summaries, transcription, new syncs or review. The final aggregation still runs on Sync with Draken. First use may download the pinned search model. New sessions from enabled agents are selected by default; per-agent and per-session exclusions remain respected.
57
56
 
58
- # 3. Set credentials and run
59
- export DRAKEN_USERNAME=admin
60
- export DRAKEN_PASSWORD=your-secure-password
61
- export DRAKEN_JWT_SECRET=$(openssl rand -hex 32)
57
+ **Settings → Agents & sessions** shows each supported agent’s configured directories, recorded sessions, workspace/file paths, last recorded changes, unreviewed counts, inclusion choices and missing-source status. **Scan enabled agents** explicitly refreshes this inventory; opening Settings only reads recorded metadata and directory presence. Readers support **pi v3 JSONL, self-contained Codex CLI rollouts and Claude Code transcripts**. Codex and Claude history require explicit per-agent opt-in; existing pi choices are preserved. The panel shows directory presence separately from recorded sessions, not an installation claim. Summaries still use pi. See [SOURCES.md](SOURCES.md) for paths, supported layouts, migration and limitations. Source selection/scanning lives in this settings panel. A fresh installation includes all indexed history; an existing fixed baseline is preserved. There are no ordinary model/budget controls or extra inference permission checkboxes. Failed preparation keeps its snapshot and cached work; retry explicitly. Opening a link after preparation requires an explicit call click.
62
58
 
63
- npx draken
64
- ```
59
+ Closing the browser preserves the running job; reloading reconnects to progress. Restarting the server preserves the snapshot and completed summary nodes, but interrupts an active model call; retry to resume from cache. Discarding a sync leaves its evidence uncovered and retains the conversation in history. Failed ordinary text-model calls do not save a partial exchange or mark anything reviewed. Records from the retired local engine retain their original playback qualifications. Live calls retain ordered generated/interrupted transcripts and supplied context sources, without claiming exact playback or agreement. Reload ends the call and never resumes microphone capture automatically.
65
60
 
66
- For HTTPS, put behind a reverse proxy:
67
- ```bash
68
- # Caddy (automatic HTTPS)
69
- sudo caddy reverse-proxy --from draken.yourdomain.com --to localhost:40333
70
- ```
61
+ An old capped snapshot must be explicitly **expanded to full history** before generating another briefing. Expansion rescans, preserves decisions/discussion and existing citation IDs, archives the obsolete briefing, and establishes a new snapshot time. It does not invoke models or advance coverage.
62
+
63
+ ### Model integration
71
64
 
72
- ### From Source
65
+ For briefings, conversation recaps and text discussion, Draken invokes `pi --print` with all tools, extensions, MCP, skills, templates, context-file discovery, and session persistence disabled. It runs outside project checkouts and never resumes or writes to your coding sessions. Credentials stay with the selected pi profile—your existing installation or Draken’s private `pi/agent` directory. Pi owns authentication and refresh; Draken does not copy auth files or implement provider login flows.
73
66
 
74
- ```bash
75
- git clone https://github.com/mehanig/draken.git
76
- cd draken
67
+ - **Summary model:** defaults to `openai/gpt-6-luna`. Override with `DRAKEN_PI_SUMMARY_MODEL`; there is no automatic fallback to the stronger model.
68
+ - **Final model:** defaults to `openai/gpt-6-astra`. Override with `DRAKEN_PI_FINAL_MODEL` or the legacy `DRAKEN_PI_MODEL`.
69
+ - Model and budget controls are intentionally absent from the UI for now. Existing syncs retain their saved settings; the advanced `/api/syncs/:id/models` PATCH endpoint remains available for changing an open sync.
70
+ - Selectors use pi's `provider/model` syntax. Catalog presence does not guarantee your subscription/API credential can access that model. Both models must support ordinary text generation; the summary model must reliably emit JSON.
71
+ - **Invocation ceiling:** `DRAKEN_PI_MAX_INVOCATIONS` defaults to 120 per briefing/question, including prior-conversation recaps, schema-repair attempts and the final verdict. This limits model-generating pi subprocess invocations, not local setup/status checks, provider-internal retries, tokens, or dollars. Exhaustion stops the run without losing cached work.
77
72
 
78
- npm install && cd client && npm install && cd ..
79
- npm run build && cd client && npm run build && cd ..
73
+ ### Summary tree
80
74
 
81
- DRAKEN_NO_AUTH=true npm start
75
+ ```text
76
+ all eligible entries in a frozen snapshot
77
+ → larger chronological batches within sessions Luna
78
+ → global reconciliation across batches Luna
79
+ extra levels only when combined input is too large
80
+ → compact summaries + original evidence excerpts
81
+ → one current-status briefing Astra
82
82
  ```
83
83
 
84
- ---
84
+ The default Luna path targets **96,000 locally estimated tokens per batch**, instead of 100 entries / 48,000 characters. A 2,000-entry/1 MB planning ceiling bounds allocation, not snapshot coverage. The complete request—including system instructions, short reference labels, metadata and background—is checked before inference, and oversized planned leaves are split without omitting entries. Multiple leaves normally need one global reconciliation: no mandatory session-merge, topic-routing or topic-merge passes. A single compact leaf goes directly to the final step. Processing remains serial for predictable cancellation and quotas.
85
+
86
+ Token planning uses pinned local `gpt-tokenizer@4.1.0` / `o200k_base`, **an estimate rather than a verified GPT-6 server tokenizer or billed usage**. Full input estimates add 20% plus 8,192 tokens of headroom. Planned leaves stay within 160,000 padded tokens; the hard request envelope is 192,000 / 1.5 MB, with 64 KB of output. These limits stay conservatively below pi's currently advertised 272,000 context, despite OpenAI's larger published 1,050,000-token capacity. The pi catalog is not modified; million-token requests are not assumed qualified. Unknown/operator-selected summary models keep their existing conservative tree and limits.
87
+
88
+ Larger Luna summaries allow up to 96 observations / 24 limitations / 96,000 canonical JSON characters, still at most 16 references per observation. The model is instructed to stay below 60 KB of UTF-8 output (the transport stops at 64 KB); canonical storage has extra room because short citation labels expand to longer source IDs. They aim for much shorter output without dropping distinct work or qualifications. Before Astra, roots must fit 12,000 estimated tokens with provenance and 96 distinct sources. One additional compacting node is allowed, with the usual bounded repair; failure stops visibly rather than looping, dropping entries or silently enlarging the final request. The complete final input is capped at 64,000 padded estimated tokens, preserving original-evidence checks without transferring the raw transcript to the expensive model.
89
+
90
+ Summaries carry structured states, source IDs, and limitations. Models receive short request-local labels (`S1`, `S2`, etc.; `O1`, `O2` for grouping), which are strictly mapped back to canonical source IDs before caching. Reference fields are translated, not source text; unknown IDs are never guessed or silently dropped. Prompts reconcile earlier plans against later results and preserve contradictions. Validation rejects invented source IDs, invalid schemas, and topic groupings that omit or duplicate observations. Every pending entry must pass through a successful leaf before a final verdict is attempted. That is an **input-processing guarantee, not proof that every fact survived compression**.
91
+
92
+ A schema failure gets one repair attempt containing a bounded prefix of the rejected response, the specific validation error, and the allowed labels. Empty evidence, unknown IDs, and excess distinct citations are separate errors. When citation count is the only problem, the retry selects references only for the overfull observations instead of rewriting the whole summary. Claims, states, limitations and already-valid citation lists remain unchanged. Selections must come from each observation's original candidates and still pass the 16-reference limit; nothing is blindly truncated, guessed or silently accepted. Citation-only repair preserves those fields and the two-invocation ceiling. Large-batch citation repair supplies complete candidate observations rather than duplicating the rejected response. If repair still fails, generation **stops**—it is not an ongoing job. The UI offers **Resume generation**, which directly continues using valid cached work. The short-label upgrade can reuse previously validated v1 leaf summaries.
93
+
94
+ Nodes are cached by content fingerprints, model selector, prompt text/version, and node type. Source IDs are independent of sync-local E/C citations, so identical inputs can reuse cache across retries and discarded snapshots. The new planner reuses validated v1/v2 leaf-cache islands and only repacks contiguous uncached ranges; existing cache rows are not wiped. Unchanged closed batches reuse their keys when history is appended; an unfinished tail and affected reconciliation are recomputed. Changed selection/background can still move boundaries. There is no endlessly rewritten project-memory summary.
95
+
96
+ Each run also retains metadata-only request timings, model/task/stage and repair status, input/output sizes, local token estimates, and completion/failure/cancellation state. No prompts or source excerpts go into this telemetry. **Model request timing** in the tree expands these details. Elapsed time includes pi startup, provider waiting and generation; these are not separately measured, and a completed subprocess result can still fail validation. Planning token estimates are not billed usage; real-history speed/quality comparisons remain unqualified. Existing runs acquire an empty metrics array through an additive migration; no histories, notes, coverage or embeddings are reset.
97
+
98
+ Each sync card and detail page shows **Est. cost** for its preparation: chunk summaries, consolidation, preparation-time prior recaps, final briefing, and retries/rebuilds for that sync. Later questions, voice calls, standalone conversation recaps and local embeddings are excluded. Preparation consumes pi's bounded JSON event stream and saves only numeric usage, returned model names and the catalog-based USD estimate alongside existing metrics—not raw events, prompts, thinking or signatures. Reasoning is a subset of output, not an extra charge; provider cache reads/writes are distinct from Draken cache hits (which make no new request). The total uses prices reported at call time, never today's prices applied to old calls. **This is an API-equivalent estimate, not a subscription charge, quota measurement or provider invoice.** Missing/zero-filled usage or unavailable catalog pricing stays unavailable; mixed or interrupted records show a partial subtotal. Older syncs cannot be honestly backfilled from the padded planning estimates.
99
+
100
+ The final model receives bounded summaries, raw verification excerpts, saved decisions, and recent conversation—not the entire transcript. Questions additionally retrieve up to 16 raw snapshot entries and automatically receive a bounded hybrid-search packet from retained earlier history, with separate global H citations. The local index prepares and updates itself as needed; wider history is not added to the frozen snapshot. Final citation validation checks reference existence, not whether every claim is actually supported.
101
+
102
+ The manager is a **read-only conversation**, not a worker. Its responses distinguish intent, attempts, agent-reported implementation, and observed validation, with clickable evidence references. Model-generated claims still need human review. Draken does not independently run tests or verify Git/CI/deployment state.
103
+
104
+ ### Conversation memory and cards
105
+
106
+ The new workflow freezes the three most recent non-discarded syncs' briefing, discussion and explicit notes at snapshot creation. Their full supplied text passes through cached bounded map/reduce recap jobs; it does not silently select only the final messages. This remains **lossy summarization**, not exhaustive recall or independent verification. Recaps are 1–5 short lines (at most 600 characters), labelled historical summaries rather than agreement. Old source IDs are not treated as this snapshot's citations. Original histories remain available at their own URLs.
107
+
108
+ The card shows a short recap, or an explicitly labelled briefing preview until one exists, with its body clamped to three visual lines. A changed conversation marks an older recap as stale. Closing the call UI requests an asynchronous recap using the cheap model (maximum 32 invocations, also bounded by the sync's saved ceiling); interrupted browser exits cannot guarantee that request. **Make recap / Refresh recap** retries explicitly, and the next sync recomputes changed prior inputs from cache. Recaps never change notes, source snapshots or coverage. No scheduled provider-summary inference is introduced; optional background work only prepares local search. Native recall can reuse these prior-sync recaps, but cannot quote original words from them; historical lookup automatically retrieves retained original excerpts across sessions and syncs through the local hybrid index, separately from frozen discussion and recaps; see [MEMORY.md](MEMORY.md).
109
+
110
+ The migration adds presentation/recap-cache tables and removes the single-open-sync index without rewriting original rows. Once multiple open snapshots exist, do not blindly downgrade to the old one-open-sync schema. ChatGPT is the only voice engine. Removing the old engine does not remove its historical records, and updating the app does not require restoring an old database.
111
+
112
+ ## What “since last sync” means
113
+
114
+ - **Indexed** means a complete JSONL entry has been read locally.
115
+ - **Included** means that entry is already held by an open snapshot. A new sync skips it, even though it is not reviewed. Multiple independently open syncs are allowed; discarding one releases its unreviewed entries.
116
+ - **Covered** means that entry was in a snapshot you explicitly finished reviewing.
117
+ - Indexing, model calls, saving notes, and cancelled/failed calls never mark evidence covered.
118
+ - A sync is immutable with respect to source activity: later arrivals cannot slip behind its checkpoint.
119
+ - A fresh one-click workflow initializes the baseline to all history; existing baselines are preserved. Entries older than that baseline are excluded from new activity, not falsely marked reviewed; they may still provide background context. The baseline does not move on subsequent syncs. There is no baseline-reset UI yet.
120
+ - A new snapshot includes **all eligible, unreviewed indexed entries not held by another open sync** from the selected sources/history baseline, with no count or character cutoff. The UI paginates evidence without omitting it from processing. Scanner safety limits and excerpt truncation still apply.
121
+ - If tree generation was started, finishing is blocked until compression and a valid final reply succeed. Failed/unprocessed evidence remains pending; you do not finish a partial tree as though it represented the whole snapshot.
122
+ - Earlier branch context is included separately (up to roughly 24,000 characters) and never counted as new progress.
123
+ - New one-click snapshots receive the **three most recent non-discarded syncs** as frozen recaps and saved notes, including unfinished conversations labelled unreviewed. The legacy API retains its last-10-completed-sync decision memory. The latest carry-forward list persists until edited; older lists are historical. Full conversations remain in SQLite; ordinary text questions include the latest 12 current-sync messages, with bounded excerpts.
124
+
125
+ ### Session handling
126
+
127
+ Default pi source: `~/.pi/agent/sessions/**/*.jsonl` (v3). Opt-in Codex roots are `~/.codex/sessions` and `~/.codex/archived_sessions`; opt-in Claude Code root is `~/.claude/projects`. Enable sources in **Settings → Agents & sessions**, then **Scan enabled agents**. [SOURCES.md](SOURCES.md) describes the adapters and source-only, agent-neutral schema.
128
+
129
+ The collector:
130
+
131
+ - Advances byte offsets only over complete LF-terminated records, including safe handling of split UTF-8 characters.
132
+ - Reports malformed records and unsupported versions rather than inventing activity.
133
+ - Follows persisted parent links for pi and Claude Code, and append chronology for supported Codex rollouts. Unsupported rollback/external-prefix layouts fail visibly rather than guessing the active history.
134
+ - Keeps compaction and branch summaries as background, not new accomplishments.
135
+ - Applies pi active-branch context edits when preparing new evidence. Already-created sync snapshots remain historical records.
136
+ - Deduplicates inherited entries across forks and repeated scans.
137
+ - Detects file replacement/truncation and reconciles the local index without rewriting source files.
138
+ - Excludes missing/disabled sources and Draken's own data directory. It does not follow source symlinks.
139
+
140
+ Current limits: discovery is eight directories deep; each scan reads up to 32 MiB per source and a record must fit within the 8 MiB safety limit. Warnings explain when a file needs attention or another scan. Source excerpts are capped at 6,000 characters; truncation is visible. Unknown entry types retain tree linkage but are not automatically considered activity.
141
+
142
+ ## Privacy and deployment
143
+
144
+ Session logs can contain private source code, prompts, command output, and credentials.
145
+
146
+ - **Provider-model use starts through Sync with Draken, preparation/retry, Ask, Call or recap actions.** The combined action prepares previous recaps and a new briefing before calling; closing the call UI requests a derived recap. Voice turns do not invoke pi. Calls open a persistent OpenAI audio session at call start; idle/quota accounting is not established. There is no separate permission checkbox. Scanning and reading evidence stay local. History lookup automatically prepares/updates a local embedding index when needed; first use downloads pinned public weights. Text questions and calls receive relevant historical excerpts by default through their existing model. Merely opening a page performs no embedding inference; an explicitly enabled server-side background indexing schedule runs independently of browsing.
147
+ - Thinking blocks, system prompts, images, and opaque signatures are not indexed. Tool-call arguments are minimized; common secret patterns are redacted. **This is best-effort, not a guarantee that the remaining text is safe to share.** Inspect evidence and exclude sensitive sessions before calling a provider.
148
+ - SQLite contains verified live-session and frozen-snapshot pointers, cached summaries, run metadata, decisions and conversations—not copies of original agent entry bodies. It lives outside the checkout in `~/.draken/draken.db` by default. **Original agent JSONL files are the authoritative archive, including for old snapshots.** Back up both those files and Draken's private state. Missing/changed originals are labelled unavailable; discussion and notes remain accessible, but generating replies, calling or reviewing that snapshot requires restoring its evidence. Search stores passage hashes, unique vectors, source links and contentless keyword postings, not passage bodies. See [MEMORY.md](MEMORY.md) for migration and storage details. There is no in-app retention/purge UI yet.
149
+ - The server defaults to loopback with **no dashboard login**. Explicitly configured credentials (or `DRAKEN_NO_AUTH=false`) retain authentication even on loopback. Local API access still rejects cross-origin requests and unexpected Host headers.
150
+ - A LAN bind is different from loopback: other devices can reach the server, read session history, and trigger model usage. Non-loopback bindings require authentication. Configure credentials, set `DRAKEN_HOST`, and use an HTTPS reverse proxy preserving Host/Origin or the optional built-in TLS listener. [VOICE.md](VOICE.md) covers trusted LAN microphone access. No-auth mode remains loopback-only.
151
+ - No telemetry, update checks, remote fonts, or third-party browser scripts.
152
+
153
+ ### Configuration
154
+
155
+ Environment variables are read from the process environment; `.env` is **not** automatically loaded. See `.env.example`.
156
+
157
+ | Variable | Default / purpose |
158
+ |---|---|
159
+ | `DRAKEN_NO_AUTH` | Unset: no login on loopback unless credentials are configured. `false` forces login; `true` explicitly disables it on loopback only |
160
+ | `DRAKEN_USERNAME` | Dashboard username when auth is enabled |
161
+ | `DRAKEN_PASSWORD` | Dashboard password when auth is enabled |
162
+ | `DRAKEN_JWT_SECRET` | Signing secret when auth is enabled; use a strong random value |
163
+ | `DRAKEN_HOST` | `127.0.0.1` |
164
+ | `DRAKEN_PORT` | `40333` |
165
+ | `DRAKEN_DATA_DIR` | `~/.draken` |
166
+ | `DRAKEN_PI_SESSIONS_DIR` | `~/.pi/agent/sessions`; override for custom pi storage |
167
+ | `DRAKEN_CODEX_SESSIONS_DIR` | Override Codex transcript root; otherwise uses `CODEX_HOME` (default `~/.codex`) sessions and archived_sessions |
168
+ | `DRAKEN_CLAUDE_SESSIONS_DIR` | Override Claude transcript root; otherwise uses `CLAUDE_CONFIG_DIR` (default `~/.claude`)/projects |
169
+ | `DRAKEN_PI_BIN` | Explicit summarization executable override, not a shell command; otherwise use the selected private runtime or `pi` on PATH |
170
+ | `DRAKEN_PI_SUMMARY_MODEL` | `openai/gpt-6-luna`; summary-model override |
171
+ | `DRAKEN_PI_FINAL_MODEL` | `openai/gpt-6-astra`; final-model override |
172
+ | `DRAKEN_PI_MODEL` | Legacy final-model override, used when `DRAKEN_PI_FINAL_MODEL` is unset |
173
+ | `DRAKEN_PI_MAX_INVOCATIONS` | `120`, bounded to 1–500; server-side default |
174
+ | `DRAKEN_PI_TIMEOUT_MS` | `180000` per invocation, bounded to 1–600 seconds |
175
+
176
+ Native voice setup and TLS environment settings are documented in [VOICE.md](VOICE.md). No new paid voice service is required.
177
+
178
+ ## Visual identity
85
179
 
86
- ## Features
180
+ Draken shares GifGun's blocky Bauhaus style: concrete-gray surfaces, square black borders, hard purple shadows, bold headings, and restrained primary-color accents. The dragon logo stays Draken's own. See [DESIGN.md](DESIGN.md) for the shared palette and rules.
87
181
 
88
- - **Multi-project** — Manage multiple codebases from one dashboard
89
- - **Docker isolation** — Each task runs in its own container
90
- - **Real-time logs** — Stream Claude's output via SSE
91
- - **Session continuity** — Follow up on previous tasks
92
- - **Git integration** — View status and diffs in the UI
93
- - **Auth** — JWT-based for secure deployment
182
+ ## Compatibility
94
183
 
95
- ## Configuration
184
+ This is not a drop-in replacement for the old Docker/Claude task dashboard or its APIs. Legacy `projects`/`tasks` tables and historical call records are retained where applicable; old task conversations are not automatically imported. Back up original agent logs and private Draken state before upgrading. Do not use an old binary as a migration rollback.
96
185
 
97
- | Variable | Required | Description |
98
- |----------|----------|-------------|
99
- | `DRAKEN_USERNAME` | For deployment | Web UI username |
100
- | `DRAKEN_PASSWORD` | For deployment | Web UI password |
101
- | `DRAKEN_JWT_SECRET` | For deployment | JWT signing secret (32+ chars) |
102
- | `DRAKEN_NO_AUTH` | No | Set `true` to disable auth |
103
- | `ANTHROPIC_API_KEY` | If no OAuth | Alternative to `claude login` |
186
+ ## Contributing and qualification
104
187
 
105
- ## Usage
188
+ Source builds, development commands, test/probe instructions and the code map live in [CONTRIBUTING.md](CONTRIBUTING.md). They are not needed for normal npm installation.
106
189
 
107
- 1. **Add a project** — Browse and select a folder
108
- 2. **Generate Dockerfile** — One-time setup per project
109
- 3. **Run a task** — Enter a prompt, Claude works in container
110
- 4. **View logs** — Real-time output streaming
111
- 5. **Follow up** — Continue the conversation
112
- 6. **Check git diff** — Review changes before committing
190
+ See [ACCEPTANCE.md](ACCEPTANCE.md) for automated gates, a short human product checklist and focused high-risk review areas. The public landing page lives in `site/`; merging changes there to `master` triggers the existing website deployment workflow. npm publication and application deployment are separate steps.
113
191
 
114
192
  ## License
115
193
 
package/SETUP.md ADDED
@@ -0,0 +1,111 @@
1
+ # First run and private pi setup
2
+
3
+ Draken uses **pi for summaries, preparation recaps and text discussion**, regardless of which coding agent produced the imported history. It does not implement provider OAuth, translate another agent's credentials, or run Claude/Codex to summarize.
4
+
5
+ > **Version note:** this guide is for **Draken 0.2.0**. Versions **0.1.6 and earlier** are the old task dashboard. Before upgrading, back up your original agent logs and Draken data; see [what changed](CHANGELOG.md).
6
+
7
+ ## Install and start
8
+
9
+ Install Node.js **22.19+** with npm, then run:
10
+
11
+ ```sh
12
+ npm install -g draken@0.2.0
13
+ draken
14
+ ```
15
+
16
+ Installation does not launch a server or register a background service. `draken` runs in the foreground, prints its address and next steps on **every launch**, and serves the browser UI. Keep that terminal open; **Ctrl+C stops Draken**, while closing the browser does not. Run commands below in another terminal, or stop the server and restart afterward.
17
+
18
+ - `draken tray`: optional macOS/Windows desktop preview. Starts a detached tray companion with Open and owned-server Start/Stop controls, so the terminal can close after readiness. An existing server stays with its original launcher. There is no automatic login registration, setup/login, or Linux tray. See [TRAY.md](TRAY.md) for lifecycle and qualification details.
19
+ - `draken status`: finds this data directory’s last successfully started server automatically—including LAN binds and custom ports—and checks its live instance identity. It also prints the HTTPS browser URL when available. You do not need to repeat `DRAKEN_HOST`/`DRAKEN_PORT`; explicit overrides still work. For a nondefault data directory, use the same `DRAKEN_DATA_DIR`. This is connectivity, not model/voice readiness or a process-management command.
20
+ - The server atomically saves a private, credential-free `server-state.json` after binding successfully. The record stays after shutdown so status checks the last address, but a saved PID/address alone never counts as running. Stale records and mismatched live instances fail visibly.
21
+ - `draken doctor`: checks the selected pi executable, version and configured model credentials. It does not create the application database, generate text or verify provider access/billing. A non-ready result exits nonzero.
22
+ - A duplicate launch on an occupied HTTP/HTTPS port exits **before opening the database or recovering interrupted runs**.
23
+
24
+ Loopback (`http://127.0.0.1:40333`) needs no dashboard login by default. LAN exposure still requires configured dashboard authentication and trusted HTTPS for microphone access. There is no automatic firewall change or certificate trust installation.
25
+
26
+ ## When pi is not installed
27
+
28
+ Run these **on the server, as its operating-system user, with the same environment**—especially `DRAKEN_DATA_DIR`, `DRAKEN_PI_BIN` and model settings:
29
+
30
+ ```sh
31
+ draken setup
32
+ draken login
33
+ ```
34
+
35
+ `draken setup` explains the destination and asks for confirmation. In an unattended terminal, `draken setup --yes` is explicit installation consent; npm package installation, server startup and browser requests never run it automatically.
36
+
37
+ The installer uses the shipped `runtime/pi/package.json` and **package-lock.json**, with pi **1.5.0**, resolved npm dependency versions and integrity hashes. It runs `npm ci --ignore-scripts --omit=dev`, without audit/funding requests or user npm configuration. No global packages or PATH entries are changed. Dependencies come from the npm registry; this is an explicit network download, not a model request.
38
+
39
+ The 1.5.0 lock replaces the previously shipped 1.4.0 lock with affected `undici`/`minimatch` dependencies. Updating Draken does **not** silently replace an already selected runtime: run `draken setup` explicitly to select the new private runtime while retaining the same private credential directory. External pi installations remain operator-managed. A clean audit of the shipped lock does not certify an older selected or external installation.
40
+
41
+ Default layout (under `DRAKEN_DATA_DIR` when overridden):
42
+
43
+ ```text
44
+ ~/.draken/pi/
45
+ runtime/1.5.0-<lock-hash>/ immutable selected runtime directory
46
+ selected.json small, atomically replaced runtime selection
47
+ agent/ pi's private configuration and auth.json
48
+ home/ private child HOME and npm cache
49
+ workspace/ empty, non-project login working directory
50
+ ```
51
+
52
+ Installation is staged and exclusively locked. Selection changes only after successful installation and executable checks. Re-running setup reuses the qualified runtime. Existing credentials and previous runtime directories are retained; a failed install never substitutes an unrelated runtime. Unexpected symlinked private directories/configuration are refused. This is configuration separation, **not an operating-system sandbox**.
53
+
54
+ ## Let pi own login
55
+
56
+ `draken login` opens pi's existing terminal interface, using the selected runtime/profile. It requires a real interactive terminal. Inside pi:
57
+
58
+ ```text
59
+ /login
60
+ ```
61
+
62
+ Choose the provider/method offered by pi and follow its prompts. For Draken's default OpenAI models, `/login openai` selects that provider's flow. On a headless server, follow pi's printed URL and paste the redirect/code when pi asks. Finish with:
63
+
64
+ ```text
65
+ /quit
66
+ ```
67
+
68
+ Draken does **not** pass `/login` as a model prompt, capture the login transcript in its database, or provide its own credential form. Pi handles the provider's OAuth/API-key flow, persistence and subsequent refresh. Managed processes use `PI_CODING_AGENT_DIR=<data>/pi/agent` and a private HOME; unrelated provider keys, pi session ownership, custom environment overrides and preload hooks are not inherited. Managed login and generation disable tools, MCP, extensions, skills, project instructions and session persistence. These login sessions are not imported as engineering evidence.
69
+
70
+ Afterward, run `draken doctor`, or click **Check setup again** on Home or in Settings. Checks use pi's bounded `auth check --model … --json --no-refresh` protocol, never its credential-printing options. **Credentials configured is not proof that the provider will accept them, that a particular model is available to the account, or that usage is free.** The actual request can still fail normally.
71
+
72
+ Draken's summary/final model configuration remains unchanged. Signing in to an unrelated provider does not automatically replace the selected models. Use the existing advanced `DRAKEN_PI_SUMMARY_MODEL` and `DRAKEN_PI_FINAL_MODEL` settings if required; restart with the same environment for diagnostics and generation.
73
+
74
+ ## Existing pi users
75
+
76
+ Starting Draken does not switch an existing installation or copy its credentials:
77
+
78
+ 1. An explicit `DRAKEN_PI_BIN` always wins, including its existing `PI_CODING_AGENT_DIR` configuration. Private setup refuses to replace this override; fix/unset it first if you want managed pi.
79
+ 2. Without that override, an explicitly selected private runtime is used.
80
+ 3. Otherwise Draken uses `pi` on PATH, retaining its normal configuration.
81
+
82
+ `draken setup` explicitly selects managed pi; it does not import the existing profile. `draken login` identifies the selected profile before opening it. A broken private selection fails visibly instead of silently falling back to global pi or another provider. The server reads the selection for subsequent requests; changing runtime does not rewrite in-flight requests or frozen snapshots.
83
+
84
+ ## Native voice is separate
85
+
86
+ For the main sync-and-call action:
87
+
88
+ ```sh
89
+ draken voice setup
90
+ draken voice login
91
+ draken voice status
92
+ ```
93
+
94
+ These commands install the pinned native helper, open its official ChatGPT device login, and check local prerequisites. No development tools are needed. Voice keeps its existing dedicated account under `~/.draken/realtime`; **pi tokens are not copied or converted**. Status is structural helper/sign-in metadata, not a real audio/provider qualification. Optional developer audio probes are documented in [CONTRIBUTING.md](CONTRIBUTING.md) and require explicit provider consent.
95
+
96
+ ## Browser instructions and history
97
+
98
+ Home shows first-run guidance when no syncs exist, and a setup notice whenever summary/voice prerequisites cannot be confirmed. Settings always exposes **Runtime & sign-in**. The main Sync action waits for configuration and rejects known-missing summary prerequisites before scanning/freezing a new snapshot. Existing evidence, source scanning, notes and history remain accessible.
99
+
100
+ Choose **Settings → Agents & sessions**. Enable the history sources you want and use **Scan enabled agents**, or let the next explicit sync scan them. Source roots and permissions are independent of the private summarization runtime: installing pi does not enable Codex/Claude histories or change the original pi archive. See [SOURCES.md](SOURCES.md).
101
+
102
+ Opening these instructions checks local metadata only. It does not install packages, refresh OAuth tokens, download embeddings, generate a summary, create a snapshot, acquire a microphone, or mark work reviewed. An independently opted-in background indexing schedule keeps its existing behavior.
103
+
104
+ ## Recovery and maintenance
105
+
106
+ - Incomplete setup: retry the explicit command. If a `setup.lock` remains after a crash, inspect its PID and confirm no setup process is running before removing **that lock only**. Remove abandoned `.install-*` staging directories only after the installer has stopped.
107
+ - An incomplete versioned runtime is never overwritten under a running process. Move the indicated runtime directory aside, then retry setup. **Do not delete `agent/` to repair runtime code.**
108
+ - Private dependency upgrades belong to a qualified Draken update and a new shipped lockfile—not an automatic `pi update`. Old runtime directories are retained until explicitly cleaned up.
109
+ - Back up private credentials securely along with Draken state and the original source archives. Do not commit them, include them in npm packages, or paste them into diagnostics.
110
+
111
+ For source builds and automated qualification, see [CONTRIBUTING.md](CONTRIBUTING.md). Normal installation does not require cloning the repository or building the application.
package/SOURCES.md ADDED
@@ -0,0 +1,75 @@
1
+ # Agent history sources
2
+
3
+ Draken reads **pi, Codex CLI and Claude Code** JSONL histories. These are source adapters, not coding-agent execution engines. It does not run Codex/Claude to import their logs, copy their credentials, execute recorded tools, or change the source files. **Summaries, recaps and text replies still use the existing isolated, tool-free pi runner and its configured models.** ChatGPT native voice remains separate.
4
+
5
+ ## Settings and discovery
6
+
7
+ Open **Settings → Agents & sessions**. Each adapter shows its configured directories, directory-presence status, recorded sessions, native IDs, workspace/file paths, inclusion choices and missing-source status. A directory being present does not establish that an executable is installed, logged in, or that every file has been parsed.
8
+
9
+ - Existing pi sessions and exclusions survive the migration. Pi history is enabled by default.
10
+ - **Codex and Claude history are off until explicitly enabled.** An existing background-indexing preference does not silently gain access to new transcripts.
11
+ - Enabling an agent persists its permission; it does not itself scan, download a model, summarize, create a sync or acquire a microphone. The next explicit scan/sync, or an already opted-in background schedule, may read its logs.
12
+ - **Scan enabled agents** discovers and parses enabled roots only. New sessions from enabled agents are selected by default. Each session can be excluded independently.
13
+ - Disabled agents are excluded from new snapshots and historical retrieval. Disabling does not rewrite existing frozen snapshots or erase discussions, notes or derived files.
14
+ - Merely opening/polling Settings reads database metadata and directory existence, not transcript bodies.
15
+
16
+ | Agent | Default roots | Explicit override |
17
+ |---|---|---|
18
+ | pi | `~/.pi/agent/sessions` | `DRAKEN_PI_SESSIONS_DIR` |
19
+ | Codex CLI | `$CODEX_HOME/sessions` and `$CODEX_HOME/archived_sessions`, with `CODEX_HOME` defaulting to `~/.codex` | `DRAKEN_CODEX_SESSIONS_DIR` selects one root instead |
20
+ | Claude Code | `$CLAUDE_CONFIG_DIR/projects`, with the config directory defaulting to `~/.claude` | `DRAKEN_CLAUDE_SESSIONS_DIR` |
21
+
22
+ The overview API retains its old `session_root` field as a read-only pi compatibility field; new consumers use `agents[].roots` and each session's `agent`/`external_id`.
23
+
24
+ Root overrides are server environment settings, not arbitrary filesystem paths supplied by browser requests. The worker receives an explicit per-agent root allowlist, not credentials or the server environment. Directory traversal is bounded to eight levels. Source symlinks are not followed during discovery; record reads verify real-path containment, regular-file identity, header/session identity, raw bytes and hashes. At most 32 MiB is admitted per file per scan; complete LF-terminated records are bounded to 8 MiB. Partial tails wait for another scan.
25
+
26
+ ## Adapter recipes
27
+
28
+ All three adapters minimize excerpts and apply the existing versioned redaction/clipping rules. Thinking, opaque signatures, system/developer instructions, images, audio and arbitrary write-file payloads are not source evidence. Tool requests preserve bounded intent/paths rather than file bodies; tool results remain qualified observations, not independent verification of the whole project. Redaction is best-effort, not a guarantee that transcripts are secret-free.
29
+
30
+ ### pi
31
+
32
+ The existing v3 header, entry IDs/parents, active branch, context edits and background-summary behavior are unchanged. Existing normalization versions remain available to reconstruct older snapshots exactly. Existing IDs, event keys and reference identities are not renamed merely to add an agent label.
33
+
34
+ ### Codex CLI
35
+
36
+ Supported self-contained rollout logs begin with `session_meta` carrying `payload.id` and `payload.cwd`. The adapter reads `response_item` user/assistant text, bounded function/custom-tool intent, tool output, compaction background and interruption status. Duplicate `event_msg` user/assistant transcript echoes are not imported a second time. Reasoning and request-context records are ignored.
37
+
38
+ Codex records do not always have message IDs. Physical offsets identify occurrences within a file; event identities are content/agent-domain hashes, and frozen evidence pins exact record bytes. Chronology is append order, not an invented parent tree.
39
+
40
+ **External `history_base` references, rollback replay and event-only layouts without response-item evidence are not supported by this recipe.** Such files fail visibly rather than guessing an inherited prefix or presenting abandoned turns as current. They require a separately qualified adapter extension. Unknown provider payloads are not automatically promoted to activity.
41
+
42
+ ### Claude Code
43
+
44
+ Supported transcript records carry `sessionId`, `uuid`, `cwd`, timestamps and message content. UUID/parent links select the persisted conversation branch; linked compact boundaries preserve earlier history, and compact summaries stay background. Progress/request metadata may bridge parent links but cannot select a new conversation branch by itself. A sidechain's recorded agent ID, or first sidechain message UUID, separates subagent files that share their parent's `sessionId`.
45
+
46
+ The reader does not parse `history.jsonl`, credentials, project memory files or feedback bundles. Superseded/orphaned transcript copies are not treated as new sessions. Mixed session identities, conflicting bodies under one UUID and unlinked compact boundaries fail visibly instead of dropping earlier evidence or guessing attribution. Synthetic fixtures cover the supported layouts; that is not a claim of compatibility with every past/future Claude release or third-party exporter.
47
+
48
+ ## Generic schema and migration
49
+
50
+ The canonical schema uses:
51
+
52
+ - `agent_sources`: persistent per-agent enablement, separate from automatic indexing.
53
+ - `agent_sessions`: stable Draken ID, agent kind, native `external_id`, source path, workspace, selection, missing status, file identity, offsets and current branch.
54
+ - `agent_entries`: stable numeric IDs, session/entry identities, chronological/branch metadata, versioned parser and normalization recipes, verified raw-record pointers and projected lengths. No copied original transcript bodies.
55
+
56
+ `source_schema=agents-v1` accompanies the existing source-only storage marker. Startup performs the old-table rename and any necessary pointer conversion **inside one SQLite transaction**. `pi_sessions` and `pi_entries` become `agent_sessions` and `agent_entries`; there are no duplicate tables or writable compatibility aliases. Existing pi IDs, numeric sequences, snapshots, discussions, notes, review coverage and summary caches remain intact. A failure rolls back, not partially converts or guesses.
57
+
58
+ New non-pi session IDs are namespaced (`codex:<id>`, `claude:<id>`, `claude:<id>:<subagent>`). Agent-domain event hashes prevent equal native IDs in different agents from sharing review coverage. Legacy pi IDs remain unchanged for compatibility.
59
+
60
+ Existing pi frozen pointers retain their v1 recipe. Foreign-source v2 pointers additionally pin agent, native identity and parser version. Reads reconstruct from the authoritative original file, verify its original hash, role, timestamp and projected text, and reject changed/missing originals. Current mutable branch state cannot redirect an older snapshot.
61
+
62
+ The separate contentless FTS/vector schema and pinned embedding fingerprint are unchanged. Migration does not re-embed existing pi history. Adding genuinely new admitted Codex/Claude text creates normal delta work; unchanged compatible vectors remain reusable. The background threshold remains **64 changed source records, with no timed small-batch flush**.
63
+
64
+ ## Durability and qualification
65
+
66
+ Back up **all enabled agents' original logs and Draken's private state**. Agent retention/purge commands can remove the originals that frozen evidence still needs; Draken does not override those policies or retain a hidden text copy. Conversations and explicit notes remain available if originals disappear, but affected evidence, generation, calls and review fail visibly.
67
+
68
+ Tests use synthetic JSONL, synthetic pi responses and isolated databases. Migration qualification compares a private copy of current pi data and its references/vectors; it does not add foreign transcripts to production or make provider calls. No real local Codex/Claude history was available on the qualification host, so unsupported vendor layouts must be surfaced and investigated rather than claimed compatible.
69
+
70
+ Format references consulted:
71
+
72
+ - [Codex protocol source](https://github.com/openai/codex/blob/main/codex-rs/protocol/src/protocol.rs)
73
+ - [Codex response-item models](https://github.com/openai/codex/blob/main/codex-rs/protocol/src/models.rs)
74
+ - [Claude Code session storage](https://code.claude.com/docs/en/how-claude-code-works#work-with-sessions)
75
+ - [Claude Code application data and retention](https://code.claude.com/docs/en/claude-directory#application-data)
package/TRAY.md ADDED
@@ -0,0 +1,54 @@
1
+ # Desktop tray companion (macOS / Windows)
2
+
3
+ Use `draken tray` for an optional desktop companion after [installing Draken](SETUP.md#install-and-start). Node.js 22.19+ and npm are required; this is not a standalone desktop installer. The tray remains a desktop preview.
4
+
5
+ ```sh
6
+ draken tray
7
+ ```
8
+
9
+ Run it in the **local desktop session**, as the server's user, with the intended `DRAKEN_DATA_DIR` and server environment. Once the command reports that the tray is ready, you can close the terminal. The normal `draken` command remains a foreground server.
10
+
11
+ ## What it does
12
+
13
+ - macOS: a dragon in the menu bar, using the system AppKit frameworks through JavaScript for Automation.
14
+ - Windows: a dragon in the notification area, using the system Windows PowerShell/.NET Forms components. Windows may put it in the overflow area; pin it using the Windows notification-area settings if desired.
15
+ - Green/gray/amber/red badge plus textual **running / stopped / starting / stopping / error** status. These mean server connectivity, **not pi credentials, model access, native voice readiness, or an active call**.
16
+ - **Open Draken** opens the verified server's browser URL, preferring its saved HTTPS URL. It never places credentials in the URL, logs in automatically, or opens a browser without a menu action.
17
+ - **Start Draken (current settings)** and **Stop Draken (ends active calls)** control only a child server started by this tray.
18
+ - Quit explicitly says whether it stops the owned server or leaves an existing external server running.
19
+
20
+ The tray starts a server automatically only for a fresh address with no recorded prior instance. A saved but stopped server needs an explicit Start click. Different saved LAN/TLS settings are not silently replaced with localhost defaults. Starting uses the environment supplied when launching the tray; saved address metadata does not contain credentials or a complete launch profile.
21
+
22
+ An already-running server is observed, not adopted. Stop is disabled for it, and quitting the tray leaves it running. If that server disappears, use its original launcher/configuration to restart it. A saved PID never authorizes a kill. Failed startup or unconfirmed shutdown never creates a replacement loop.
23
+
24
+ ## Boundaries
25
+
26
+ - No Electron/browser bundle, downloaded native tray binary, development compiler, global PATH change, administrator access, or paid code-signing certificate is required by this tray implementation.
27
+ - The packaged native scripts use OS frameworks. Draken does **not** change PowerShell execution policy, application-control policy, Gatekeeper, the firewall, or certificate trust. Managed/restricted desktops may refuse the helper; failure is reported rather than bypassed. Signing a future standalone installer is a separate concern.
28
+ - No Linux tray, SSH/headless tray, Windows service integration, start-at-login registration, background updater, daemon supervisor, embedded terminal, or new login implementation is included in this first version.
29
+ - Setup/login remain the existing explicit pi and native voice commands and browser guidance. The tray never installs pi, copies credentials, downloads a model, scans history, creates a sync, or captures audio itself. A server it starts retains the user's existing automatic-indexing preference and normal server behavior.
30
+ - Stop/Quit can interrupt generation and active calls. Existing server shutdown preserves completed work and retains its normal recovery behavior; unfinished generation must be retried explicitly. No review coverage is advanced.
31
+
32
+ ## How it works
33
+
34
+ `draken tray` starts a detached Node companion and waits for native UI readiness before reporting success. One heartbeat lock per data directory prevents duplicate companions. After an unclean exit, stale-lock recovery takes approximately 30 seconds; there is no unconditional lock deletion or PID-based kill.
35
+
36
+ The companion polls only the bounded `/api/auth/status` identity endpoint. The native UI receives a bounded private presentation file and heartbeat, not server credentials, provider environment variables, source text, or tokens. Menu clicks return only fixed action identifiers. If the companion stops updating, the helper closes itself after 15 seconds.
37
+
38
+ An owned server reports its actual bound addresses and instance over a private parent/child IPC channel. Stop requests and parent disconnect use that channel, including on Windows, where `kill(SIGTERM)` would be an abrupt termination. There is no new HTTP shutdown endpoint. Lost helpers cause shutdown of the tray's owned server only; existing external servers are unaffected.
39
+
40
+ Private state is under `<DRAKEN_DATA_DIR>/tray/` (default `~/.draken/tray/`):
41
+
42
+ - temporary per-run presentation files; removed on orderly exit;
43
+ - a bounded `server.log` tail (64 KiB) and `error.log` (2,000 characters);
44
+ - the adjacent `tray.lock/` directory used by pinned `proper-lockfile@4.1.2`.
45
+
46
+ These are private diagnostics, not publishable reports. Files use restrictive modes where supported and rely on the user's private data-directory permissions on Windows. No logs or private runtime files belong in git or the npm package.
47
+
48
+ ## Qualification
49
+
50
+ Platform-independent tests exercise ownership, startup/stop/quit races, stale responses, private IPC, duplicate companions, terminal disconnection, and real isolated backend processes. They make no provider requests and do not use production data.
51
+
52
+ Hosted macOS and Windows checks have passed for native helper startup, status updates and graceful exit. The tray smoke check does not start a server, open a browser, read history or access a provider. These checks do **not** establish physical icon visibility, menu usability or compatibility with every desktop policy. The tray remains a desktop preview pending hands-on acceptance; see [ACCEPTANCE.md](ACCEPTANCE.md) and [CONTRIBUTING.md](CONTRIBUTING.md) for qualification details.
53
+
54
+ Before a public release, manually verify on each supported OS/architecture: visible icon and dark/light appearance, accessible status text, Open/Start/Stop/Quit, terminal closure, duplicate launches, spaces/Unicode in install paths, existing-server non-interference, logout, and application-control restrictions. No claim of physical menu usability or all-platform compatibility follows from the synthetic tests alone.