@chanlerdev/scorel 0.0.3 → 0.0.5

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/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,100 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.0.5 - 2026-06-19
6
+
7
+ ### Highlights
8
+
9
+ - New CLI commands `scorel version`, `scorel update`, and `scorel upgrade` for software lifecycle management.
10
+ - Oversized Bash tool output is now archived to session artifacts, returning compact head/tail projections to the model.
11
+ - GUI auto-update support with macOS DMG/ZIP packaging and incremental updates.
12
+
13
+ ### Changes
14
+
15
+ - GUI and daemon now honor the selected chat model when sending messages.
16
+ - GUI settings are more resilient: ignore stale device responses, error boundaries on settings sections, and fixed state reset when switching devices.
17
+ - `scorel host serve` and `scorel host start` no longer idle-timeout by default; only convenience daemons (GUI auto-start, `scorel up`) enforce a 15-minute idle timeout.
18
+ - GUI auto-start uses an ephemeral port to avoid conflicts with user-started daemons.
19
+
20
+ ### Fixes
21
+
22
+ - GUI provider model selection now persists correctly across profile refreshes and session creation.
23
+ - Daemon lifecycle hardened: foreground daemon stays alive until Ctrl+C/SIGTERM.
24
+
25
+ ### Verification
26
+
27
+ - Unit tests for update helpers (semver comparison, npm check/install, auto-update gate).
28
+ - Unit tests for GUI main process (electron-updater import, manual update item, tray setup).
29
+ - Integration test for release asset collection and version lockstep.
30
+ - Tests for oversized Bash archive and projection logic.
31
+ - Tests for daemon idle timeout behavior.
32
+ - Tests for GUI settings resilience (stale data, error boundary, state reset).
33
+ - Tests for model selection fallback and normalization.
34
+
35
+ ### Internal
36
+
37
+ - Update SHIP.md to clarify that small bug fixes may skip spec requirement; only changes affecting stable contracts or user-visible direction need a spec.
38
+ - Oversized Bash results are written to session-scoped artifacts, excluded from diagnostics and Relay.
39
+
40
+ - Add `scorel version`, `scorel update`, and `scorel upgrade`.
41
+ - Add hourly Host auto-update checks gated by active work state.
42
+ - Add GUI macOS release packaging and Electron updater metadata to the release path.
43
+ - Add GUI application menu and macOS status bar menu entries for manual update checks and common app actions.
44
+ - Document unsigned macOS GUI quarantine bypass command.
45
+
46
+ ## 0.0.4 - 2026-06-14
47
+
48
+ ### Highlights
49
+
50
+ - Config is now device-scoped only; project-level config is no longer read or written.
51
+ - GUI settings are device-scoped with relay device rename and project scope selector.
52
+ - Local daemon is a singleton background process with idle shutdown and shared state root.
53
+ - RTK token saving settings available in GUI for Bash execution.
54
+
55
+ ### Changes
56
+
57
+ - GUI connection settings default to official Relay URL; editing requires explicit click.
58
+ - Pairing button label changed to 'Get Pair Code'.
59
+ - Paired Relay devices can be renamed locally; name persists across refresh.
60
+ - Provider delete button moved to a danger zone at bottom of settings panel.
61
+ - Token-saving statistics labels changed to Chinese (Bash 输出 Token / 已节省 Token).
62
+ - RTK token saving can be enabled/disabled in GUI settings, persisted in project config.
63
+ - Cumulative RTK savings stats are maintained across sessions and projects.
64
+ - RTK is detected from default shell; can be installed via Homebrew if missing.
65
+
66
+ ### Fixes
67
+
68
+ - Glob results are now sorted by workspace-relative path for deterministic ordering across platforms.
69
+
70
+ ### Breaking Changes
71
+
72
+ - Runtime no longer reads project `.scorel/config.toml`; existing project configs are ignored.
73
+ - GUI local projects and sessions are now stored under `~/.scorel/` instead of `~/.scorel/gui/`; old state is not migrated automatically.
74
+
75
+ ### Verification
76
+
77
+ - Core config tests prove project config is ignored and device config is used.
78
+ - Daemon embedded tests prove settings writes with projectId write device config only.
79
+ - GUI rendering tests confirm device-scoped selector, provider delete placement, and Chinese token labels.
80
+ - New local-host test verifies device config writes to ~/.scorel/config.toml.
81
+ - E2E CDP script validates shared state paths and daemon lifecycle.
82
+ - Unit tests cover RTK detection, Bash execution with RTK, and runtime stats recording.
83
+
84
+ ### Internal
85
+
86
+ - `scorel host start` launches a singleton background daemon; `scorel host serve` gains `--idle-timeout-ms` flag.
87
+ - `scorel up` ensures daemon is running but no longer owns its lifecycle.
88
+ - GUI attaches to singleton daemon instead of running embedded Host.
89
+ - gui-store.json lives at `~/.scorel/gui-store.json`.
90
+
91
+ - Add `scorel host start` for background singleton Host startup; `scorel up` now leaves the singleton Host running when WebUI exits.
92
+ - GUI local Host state now uses the shared `~/.scorel` root for Projects and Sessions, with `gui-store.json` stored at `~/.scorel/gui-store.json`.
93
+ - GUI starts and attaches to the singleton local daemon instead of starting a second local Host writer.
94
+ - Local daemon now idle-shuts down when there are no clients, no active work, and no active IM extensions; active IM keeps it alive until explicit stop.
95
+ - GUI connection settings now default to the official Relay, hide Relay URL editing behind an edit action, show `Get Pair Code`, support paired-device rename/details, and use a device-scoped settings selector.
96
+ - GUI Provider settings now place `删除提供商` in the Provider configuration block, token-saving stats use clear Chinese labels, and Relay device rows expose expand/edit affordances.
97
+ - Config loading now uses the device config only; Project `.scorel/config.toml` is no longer a runtime or Settings config source.
98
+
5
99
  ## 0.0.3 - 2026-06-12
6
100
 
7
101
  ### Highlights
package/docs/ROADMAP.md CHANGED
@@ -303,7 +303,7 @@ M5 WebUI 的正式产品方向记录在 [`S0030`](spec/ship/S0030-webui-product-
303
303
  - `scorel daemon serve` 全部 flag 有合理默认;token 在 `~/.scorel/daemon.json` 持久化,跨重启复用。
304
304
  - `~/.scorel/daemon.json` 不再每次启动删除;通过 pid liveness + `stoppedAt` 判存活。
305
305
  - WebUI Settings 页面通过 `/api/local-daemon` server route 自动发现本地 daemon,一键添加 device。
306
- - `scorel up` 同时拉起 daemon serve + webui,Ctrl+C 一并退出。
306
+ - `scorel up` 确保 singleton daemon 可用并启动 WebUI;退出 `scorel up` 不关闭后台 daemon;无 client/无 active work/无 active IM 后 idle 自动退出。
307
307
  - 全部改动通过自动测试,真实 LLM 手工烟雾通过。
308
308
 
309
309
  **Steps**:
@@ -315,7 +315,7 @@ M5 WebUI 的正式产品方向记录在 [`S0030`](spec/ship/S0030-webui-product-
315
315
  **Not in M5.6**:
316
316
 
317
317
  - WebUI 多 daemon 切换 UI;每用户单 daemon 假设。
318
- - 自动 supervisor / restart;仍需手工 `scorel daemon stop && serve`。
318
+ - restart-on-crash supervisor;仍需手工 `scorel host stop && start`。
319
319
  - Windows 专属 PID 语义。
320
320
  - TLS / OAuth / 公网隧道。
321
321
 
@@ -592,6 +592,14 @@ M5 WebUI 的正式产品方向记录在 [`S0030`](spec/ship/S0030-webui-product-
592
592
  | M9.F1.16 | [`S0087`](spec/ship/S0087-gui-ui-polish-sweep.md) | Codex-inspired GUI visual pass:学习 Codex 的比例、层级和克制风格,并把 GUI tool blocks 收敛为低噪声执行证据流 | Done |
593
593
  | M9.F1.17 | [`S0088`](spec/ship/S0088-gui-streaming-thinking-contract.md) | Streaming thinking contract:补 thinking/content delta,使 thinking 在 turn 运行中按序显示,而不是最终 assistant_message 后才插入 | Done |
594
594
  | M9.F1.18 | [`S0089`](spec/ship/S0089-memory-reliability-and-dream-trigger.md) | Memory reliability:修复 AppendDaily 调用质量、dreaming 触发与可观测性,让 M9 后半段聚焦真实使用中的质量优化 | Done |
595
+ | M9.F1.19 | [`S0097`](spec/ship/S0097-rtk-token-saving-settings.md) | GUI Token 节省设置 + RTK Bash output proxy + runtime config | Done |
596
+ | M9.F1.20 | [`S0098`](spec/ship/S0098-local-daemon-singleton-unified-state.md) | 统一本机 Host state root、后台 singleton start、GUI/CLI auto-start + attach、idle shutdown、active IM 保活 | Done |
597
+ | M9.F1.21 | [`S0099`](spec/ship/S0099-gui-connection-device-settings.md) | GUI 连接设置默认官方 Relay、配对设备命名/详情、Settings scope 初版 | Done |
598
+ | M9.F1.22 | [`S0100`](spec/ship/S0100-gui-provider-danger-zone.md) | GUI Provider 删除按钮位置初版 | Done |
599
+ | M9.F1.23 | [`S0101`](spec/ship/S0101-gui-device-settings-polish.md) | GUI Settings 改为设备级配置,修正 Provider 删除位置、Token 文案、设备展开/重命名交互 | Done |
600
+ | M9.F1.24 | [`S0102`](spec/ship/S0102-device-only-config.md) | Config 彻底收敛为设备级唯一配置,移除 Project config 运行时语义 | Done |
601
+ | M9.F1.25 | [`S0103`](spec/ship/S0103-daemon-lifecycle-and-settings-resilience.md) | Daemon 生命周期按入口区分,并修复 GUI Settings remote 切换黑屏风险 | Done |
602
+ | M9.F1.26 | [`S0105`](spec/ship/S0105-cli-update-and-gui-release.md) | CLI 命令面统一补齐、NPM 手动/自动更新、GUI release 打包和增量更新框架 | Done |
595
603
 
596
604
  **Not in M9 Follow-up**:
597
605
 
@@ -761,6 +769,16 @@ HTTP adapter 必须映射已有 Host use cases,不复制领域逻辑。
761
769
  | [`S0093`](spec/ship/S0093-gui-im-settings-platform-layout.md) | GUI IM Settings platform layout | Done |
762
770
  | [`S0094`](spec/ship/S0094-im-inbound-runtime.md) | IM inbound runtime receive paths | Done |
763
771
  | [`S0095`](spec/ship/S0095-gui-im-session-list-refresh.md) | GUI IM session list refresh | Done |
772
+ | [`S0096`](spec/ship/S0096-glob-stable-order.md) | Glob stable cross-platform ordering | Done |
773
+ | [`S0097`](spec/ship/S0097-rtk-token-saving-settings.md) | RTK token saving settings and Bash output proxy | Done |
774
+ | [`S0098`](spec/ship/S0098-local-daemon-singleton-unified-state.md) | Local daemon singleton and unified state | Done |
775
+ | [`S0099`](spec/ship/S0099-gui-connection-device-settings.md) | GUI connection device settings | Done |
776
+ | [`S0100`](spec/ship/S0100-gui-provider-danger-zone.md) | GUI Provider danger-zone placement | Done |
777
+ | [`S0101`](spec/ship/S0101-gui-device-settings-polish.md) | GUI device-scoped Settings polish | Done |
778
+ | [`S0102`](spec/ship/S0102-device-only-config.md) | Device-only config | Done |
779
+ | [`S0103`](spec/ship/S0103-daemon-lifecycle-and-settings-resilience.md) | Daemon lifecycle and Settings resilience | Done |
780
+ | [`S0104`](spec/ship/S0104-tool-result-artifacts.md) | Tool result artifacts for oversized Bash output | Done |
781
+ | [`S0105`](spec/ship/S0105-cli-update-and-gui-release.md) | CLI update and GUI release | Done |
764
782
 
765
783
  ---
766
784
 
package/docs/SHIP.md CHANGED
@@ -25,6 +25,8 @@
25
25
  ```bash
26
26
  pnpm install
27
27
  pnpm scorel # 在当前目录进入交互式项目会话
28
+ pnpm scorel --version
29
+ pnpm scorel update
28
30
  ```
29
31
 
30
32
  Hosted WebUI 路径:
@@ -35,7 +37,7 @@ open https://scorel.chanler.dev
35
37
  pnpm scorel pair <pair-code>
36
38
  ```
37
39
 
38
- `scorel host serve` 会启动本机 Host、注册当前目录为初始 Project,并默认连接官方 Relay。`scorel up` / `pnpm dev` 只作为本地开发便利入口:本地 Host + 本地 WebUI。
40
+ `scorel host serve` 会以前台调试模式启动本机 Host、注册当前目录为初始 Project,并默认连接官方 Relay;前台 Host 默认一直存活,直到 Ctrl+C / SIGTERM,除非显式传入 `--idle-timeout-ms`。`scorel host start` 会启动或复用后台 singleton Host,并返回到 shell;直接后台启动的 CLI Host 默认一直存活,直到 `scorel host stop` 或进程退出。`scorel up` / `pnpm dev` 只作为本地开发便利入口:确保后台 Host 可用,然后启动本地 WebUI,但不拥有 Host 生命周期。GUI / CUI 自动拉起的后台 Host 无 client、无 active work、无 active IM 时会按 15 分钟 idle timeout 自动退出;active IM 会保持 Host 存活。
39
41
 
40
42
  ---
41
43
 
@@ -102,7 +104,7 @@ docs/spec/ship/S####-slug.md
102
104
  - 影响文件 / 包
103
105
  - 风险与边界
104
106
 
105
- 没有 S spec,不开始实现。Bug fix 也需要 S spec,可以很短。
107
+ 没有 S spec,不开始实现。局部 bug fix 可以不创建 S spec;如果修复会改变稳定契约、配置/协议/数据边界或用户可见产品方向,就先补 S spec。
106
108
 
107
109
  ### 3. Ship
108
110
 
@@ -140,7 +142,7 @@ S####: <type>: <description>
140
142
 
141
143
  规则:
142
144
 
143
- - 一个 PR 对应一个 S spec。
145
+ - 一个 PR 对应一个 S spec;局部 bug fix 可以不对应 S spec
144
146
  - Commit message 使用 title-only semantic commit:只写标题,不写正文。
145
147
  - 按业务含义拆 commit,不把无关实现混在一起。
146
148
  - 文档、实现、测试可以拆 commit,但 PR title 必须带 S 编号。
@@ -205,9 +207,11 @@ pnpm release patch --no-generate-notes
205
207
  - 检查 working tree
206
208
  - 执行 check
207
209
  - 执行 WebUI production build
210
+ - 执行 GUI production build
208
211
  - 构建 public `scorel` npm package
209
212
  - 执行 `npm pack` 安装烟雾测试
210
213
  - bump 所有 package version
214
+ - 构建 GUI macOS dmg / zip release assets,并生成 `latest-mac.yml` 与 blockmap 增量更新 metadata
211
215
  - 默认用 DeepSeek V4 Flash 从上一个 `v*` tag 之后的 commits 生成 changelog notes
212
216
  - 更新 changelog;只有显式 `--no-generate-notes` 时才写入最小版本标题
213
217
  - commit `release: vX.Y.Z`
@@ -215,11 +219,11 @@ pnpm release patch --no-generate-notes
215
219
  - publish root `scorel` package to npm
216
220
  - push branch + tag
217
221
  - create GitHub Release from the same generated changelog notes
218
- - upload the same-version `npm pack` tarball as the only GitHub Release asset
222
+ - upload the same-version `npm pack` tarball and GUI macOS release assets to the GitHub Release
219
223
 
220
224
  Release notes 使用 `DEEPSEEK_API_KEY` 调用 DeepSeek 官方 API,默认 endpoint 为 `https://api.deepseek.com/v1`,默认模型为 `deepseek-v4-flash`。Dry-run 在缺少 key 或 API 失败时可打印 deterministic fallback preview;正式 release 默认要求 AI notes 成功,除非显式传入 `--no-generate-notes`。
221
225
 
222
- GitHub Actions 提供手动触发入口,默认执行 `patch` dry-run。正式 release 使用 `GITHUB_TOKEN` 创建 GitHub Release;正式 publish 需要仓库 secret `NPM_TOKEN`,对应 npm 账号当前为 `chanlerdev`。AI release notes 需要仓库 secret `DEEPSEEK_API_KEY`。
226
+ GitHub Actions 提供手动触发入口,默认执行 `patch` dry-run。正式 release 使用 `GITHUB_TOKEN` 创建 GitHub Release;正式 publish 需要仓库 secret `NPM_TOKEN`,对应 npm 账号当前为 `chanlerdev`。AI release notes 需要仓库 secret `DEEPSEEK_API_KEY`。GUI macOS 产物当前以 unsigned build 发布,workflow 设置 `CSC_IDENTITY_AUTO_DISCOVERY=false`;有 Apple Developer 账号后再补 signing/notarization。
223
227
 
224
228
  ---
225
229
 
@@ -152,11 +152,12 @@ class PromptBuilder {
152
152
 
153
153
  **格式**:TOML
154
154
 
155
- **读取顺序**(高 → 低):
156
- 1. `.scorel/config.toml`(项目级)
157
- 2. `~/.scorel/config.toml`(用户级)
155
+ **读取路径**:
156
+ 1. `~/.scorel/config.toml`(用户级 / 设备级唯一 config)
158
157
 
159
- `~/.scorel` 是固定用户级根目录;`~/.scorel/config.toml` 是固定用户级配置文件;JSONL session 默认固定写入 `~/.scorel/sessions`。这些路径是产品约定,不作为可配置字段暴露。测试和内部嵌入场景可以通过代码注入临时 session 目录,但这不是用户配置面。
158
+ 一个设备只有一份 config。Project workspace/session 对象,不拥有 Provider、Model、Memory、Runtime 或 Extension 配置;运行时不会读取项目目录下的 `.scorel/config.toml`。
159
+
160
+ `~/.scorel` 是固定用户级根目录;`~/.scorel/config.toml` 是固定用户级配置文件;JSONL session 默认固定写入 `~/.scorel/sessions`。这些路径是产品约定,不作为可配置字段暴露。测试和内部嵌入场景可以通过代码注入临时 `scorelHomeDir` / session 目录,但这不是用户配置面。
160
161
 
161
162
  环境变量不参与通用配置覆盖,只通过 `apiKeyEnv` 指向具体密钥。CLI 参数也不复制完整 config schema;只有明确属于交互控制的参数才进入 CLI。
162
163
 
@@ -244,7 +245,7 @@ auxiliary = "aux"
244
245
 
245
246
  `available_models.*` 是 Scorel 的 available model / use pool。它们从 `provider_models.*` 里引用少量真正允许 Scorel 使用的模型;Runtime、GUI composer 和未来 subagent selection 只能选择 pool 内模型,不能直接选择 provider catalog 或 provider model 里的任意条目。
246
247
 
247
- GUI 的 provider/model 写入必须 merge 到现有 `.scorel/config.toml`:同一 provider 下追加第二个 provider model,或把 provider model 加入 available models 时,不能删除已存在 provider、provider model、available model 或 role assignment,除非用户明确覆盖对应字段。
248
+ GUI 的 provider/model 写入必须 merge 到现有设备级 `config.toml`:同一 provider 下追加第二个 provider model,或把 provider model 加入 available models 时,不能删除已存在 provider、provider model、available model 或 role assignment,除非用户明确覆盖对应字段。
248
249
 
249
250
  Scorel 仍处在开发阶段,没有存量配置兼容要求。旧 `[models.*]` section 不再支持;遇到旧 section 必须按未知 section 报错。
250
251
 
@@ -38,7 +38,7 @@ The verifier starts:
38
38
  - a real local Relay process with durable file store
39
39
  - a real local Host daemon process connected outbound to Relay
40
40
  - a real WebUI Next dev server
41
- - a temporary real Project with project-level `.scorel/config.toml`
41
+ - a temporary real Project using the device-level `~/.scorel/config.toml`
42
42
  - a Relay Entry using `RelayTransport` and `DaemonClient`
43
43
 
44
44
  The verifier then:
@@ -29,7 +29,7 @@ Lock M9 GUI as a Project-first desktop app before implementation. The GUI should
29
29
 
30
30
  - Do not scaffold Electron in S0064.
31
31
  - Do not implement GUI screens.
32
- - Do not add SSH, direct WS + token, OAuth, account systems, or GUI auto-update.
32
+ - Do not add SSH, direct WS + token, OAuth, account systems, or GUI auto-update in S0064. GUI auto-update is introduced later by S0105 as release infrastructure.
33
33
  - Do not publish or package desktop installers.
34
34
  - Do not change the public npm CLI package surface.
35
35
 
@@ -76,10 +76,17 @@ Host runtime must use the selected model for each session/turn:
76
76
  available model or role;
77
77
  - CLI can continue using the default role without exposing a new command flag in this
78
78
  spec;
79
- - GUI composer can choose an available model for new prompts/sessions;
79
+ - GUI composer can choose an available model for the next main chat prompt, including
80
+ prompts sent into an existing session;
81
+ - background model tasks such as session title generation, session memory, foreground
82
+ compact, and memory dream use the configured `auxiliary` role unless a later spec
83
+ defines a more specific routing contract;
80
84
  - session metadata records the selected model id and role when known;
81
85
  - session header persists enough selected-model metadata to keep resume auditable if
82
86
  config later changes;
87
+ - if a restored session references a selected model that no longer exists in the
88
+ current device config, Host falls back through the persisted role or current
89
+ `standard` role instead of failing attach/resume;
83
90
  - assistant events keep recording actual provider/model metadata from pi-ai.
84
91
 
85
92
  Tool creation must use the actual selected model's context window, not a global model
@@ -103,12 +110,12 @@ The response must be display-safe:
103
110
  - if the target Project has no model profile config yet, `list_models` returns an empty
104
111
  model list instead of surfacing config-not-found as a user-facing error.
105
112
 
106
- Expose a Host API for adding/updating a Project's provider/model profile. GUI must use
107
- this Host-owned path for both local and Relay Projects; renderer code must not write
108
- `.scorel/config.toml` directly.
113
+ Expose a Host API for adding/updating the device provider/model profile. GUI must use
114
+ this Host-owned path for both local and Relay devices; renderer code must not write
115
+ `~/.scorel/config.toml` directly.
109
116
 
110
117
  Saving a provider/model profile is a config edit, not a provider call. It must validate
111
- shape and merge into the existing Project config, but it must not require the target
118
+ shape and merge into the existing device config, but it must not require the target
112
119
  Host process to already have the provider API key env var set. Missing credentials
113
120
  should block runtime use, not saving.
114
121
 
@@ -186,8 +193,8 @@ This spec does not implement a new subagent execution engine.
186
193
  - using the selected model's context window.
187
194
  - Daemon/client tests cover:
188
195
  - model profile summary is exposed without API keys;
189
- - a Project with no model config returns an empty model profile summary;
190
- - adding/updating a provider/model profile writes a valid `.scorel/config.toml`
196
+ - a device with no model config returns an empty model profile summary;
197
+ - adding/updating a provider/model profile writes a valid `~/.scorel/config.toml`
191
198
  without requiring API key env vars;
192
199
  - adding a second model under the same provider preserves the existing provider and
193
200
  model entries;
@@ -56,7 +56,7 @@ page hierarchy.
56
56
  ### 4. Existing Host contract
57
57
 
58
58
  Continue using the Host-owned `list_models` and `upsert_model_profile` path. Renderer
59
- code must not write `.scorel/config.toml` directly.
59
+ code must not write `~/.scorel/config.toml` directly.
60
60
 
61
61
  This spec can reuse the S0073 data model and does not need a new protocol message unless
62
62
  the UI needs one for clean implementation.
@@ -37,7 +37,7 @@ selecting a draft provider.
37
37
  Provider config supports either:
38
38
 
39
39
  - `apiKeyEnv`, resolved from environment variables; or
40
- - `apiKey`, stored directly in `.scorel/config.toml`.
40
+ - `apiKey`, stored directly in the device `~/.scorel/config.toml`.
41
41
 
42
42
  GUI never receives direct API key values when listing providers. Editing an existing
43
43
  direct-key provider shows only that a direct key is configured. Saving a provider with
@@ -69,7 +69,7 @@ GUI Settings Memory section exposes:
69
69
  - session memory toggle;
70
70
  - auto compact threshold select.
71
71
 
72
- These controls use the existing project-scoped memory config path.
72
+ These controls use the device-scoped memory config path; memory status and persisted memory artifacts remain project-aware activity data.
73
73
 
74
74
  ## Not In Scope
75
75
 
@@ -0,0 +1,32 @@
1
+ # S0096: Glob Stable Order
2
+
3
+ ## Goal
4
+
5
+ Make the `Glob` tool return deterministic results across local macOS and Linux CI.
6
+
7
+ ## Scope
8
+
9
+ - Sort `Glob` file results by workspace-relative path before applying `head_limit` / `offset`.
10
+ - Preserve existing `Grep` behavior and pagination shape.
11
+
12
+ ## Not In Scope
13
+
14
+ - Changing ripgrep invocation.
15
+ - Changing Grep content/count ordering.
16
+
17
+ ## Acceptance Criteria
18
+
19
+ - `Glob` result limiting does not depend on filesystem or ripgrep output order.
20
+ - Existing coding tool tests pass on Linux and macOS.
21
+
22
+ ## Test Requirements
23
+
24
+ ```bash
25
+ pnpm --filter @scorel/core test -- src/tools/coding-tools.test.ts
26
+ pnpm typecheck
27
+ pnpm test
28
+ ```
29
+
30
+ ## Status
31
+
32
+ Done.
@@ -0,0 +1,61 @@
1
+ # S0097: RTK Token Saving Settings
2
+
3
+ ## Goal
4
+
5
+ Add an opt-in GUI setting that enables RTK-backed token saving for Scorel Bash tool execution without changing session replay, model prompts, or existing tool input contracts.
6
+
7
+ RTK here means Rust Token Killer: a CLI command rewriter/filter that compresses shell command output before it reaches the LLM context.
8
+
9
+ ## Scope
10
+
11
+ - Add device-scoped `[runtime] tokenSavingRtk = boolean` config.
12
+ - Add GUI Settings page `Token 节省` with an RTK enable toggle and status.
13
+ - When the user enables the setting, Host ensures the `rtk` binary is available:
14
+ - first detect `rtk` on PATH;
15
+ - if missing on macOS/Linux with Homebrew available, attempt `brew install rtk`;
16
+ - if install fails, keep the setting but report RTK as unavailable.
17
+ - Bash tool execution and RTK discovery use the user's default shell path (`options.defaultShell` where provided, then `SHELL`, then OS user shell, then `/bin/sh` fallback), not a hard-coded `/bin/bash`.
18
+ - Shell invocation preserves the command string and uses shell-compatible command flags (`-lc` for sh/bash/zsh-like shells, `-c` for csh/tcsh/fish-like shells).
19
+ - When enabled and available, the Bash tool asks RTK to rewrite the original command and executes the rewritten command, while preserving the original tool input contract and cwd semantics.
20
+ - Bash tool result details expose RTK application state plus estimated output/saved tokens for Scorel-owned UI/diagnostics.
21
+ - Runtime Settings summarizes RTK token savings from a maintained Scorel runtime stats file across projects on the current host.
22
+ - Chat transcript rendering continues to display the original Bash tool-call command, not the RTK rewritten execution command.
23
+ - Session JSONL and persistent events keep the same tool result shape; no prompt or input assembly contract changes.
24
+
25
+ ## Not In Scope
26
+
27
+ - Changing model message assembly.
28
+ - Compressing Read / Grep / Glob built-in tool results.
29
+ - Provider-specific token accounting.
30
+ - A per-session savings breakdown view.
31
+ - Global shell hook installation through `rtk init`.
32
+ - Silent install at app startup.
33
+
34
+ ## Acceptance Criteria
35
+
36
+ - `tokenSavingRtk = false` keeps Bash behavior equivalent to the current path.
37
+ - `tokenSavingRtk = true` uses RTK rewrite for Bash command execution when RTK is available, without changing the tool-call input command string.
38
+ - Tool results sent back into model context include only the user-visible content, not RTK execution metadata or rewritten command details.
39
+ - GUI Bash tool blocks display the original tool-call command even when RTK rewrites the command at execution time.
40
+ - RTK detection and first-enable install checks run in the same default shell environment as command execution, so zsh-configured PATH entries are visible.
41
+ - Runtime creation resolves the RTK executable whenever `tokenSavingRtk` is enabled, so saved settings affect actual Bash tool execution, not only the Settings UI.
42
+ - Runtime Settings token totals come from Scorel-maintained RTK stats updated when Scorel persists tool results, so other agents' RTK usage in the same project is not counted.
43
+ - GUI Settings can enable/disable RTK token saving and shows available/unavailable status.
44
+ - Config parsing rejects unknown `[runtime]` keys.
45
+ - RTK install is only attempted after the user enables the setting.
46
+ - Existing tests, typecheck, and full test suite pass.
47
+
48
+ ## Test Requirements
49
+
50
+ ```bash
51
+ pnpm --filter @scorel/core test -- src/config/config.test.ts src/tools/coding-tools.test.ts
52
+ pnpm --filter @scorel/daemon test -- src/embedded/embedded.test.ts
53
+ pnpm --filter @scorel/app-gui test -- src/renderer/gui-shell.test.tsx
54
+ pnpm verify:m9-gui # service-level local/relay plus Electron CDP settings + prompt smoke
55
+ pnpm typecheck
56
+ pnpm test
57
+ ```
58
+
59
+ ## Status
60
+
61
+ Done.
@@ -0,0 +1,96 @@
1
+ # S0098: Local Daemon Singleton And Unified State
2
+
3
+ ## Goal
4
+
5
+ Make the local Scorel Host a single user-level daemon with one local state root, so CLI, GUI, WebUI, IM, and Relay clients attach to the same Project registry, Session JSONL, runtime stats, and config.
6
+
7
+ ## Scope
8
+
9
+ - Use `~/.scorel` as the only local Host state root:
10
+ - `daemon.json`
11
+ - `projects.json`
12
+ - `sessions/*.jsonl`
13
+ - `runtime-stats.json`
14
+ - `config.toml`
15
+ - `gui-store.json`
16
+ - Remove GUI-local Host state ownership:
17
+ - no new `~/.scorel/gui/projects.json`;
18
+ - no new `~/.scorel/gui/sessions`;
19
+ - GUI still has GUI UI state, but it lives at `~/.scorel/gui-store.json`.
20
+ - Add `scorel host start`, a background daemon start path that starts the singleton local daemon without tying daemon lifetime to the CLI process that launched it.
21
+ - Make local GUI attach to the singleton daemon when available.
22
+ - Make local GUI start the singleton daemon in the background when no live daemon exists, then attach to it.
23
+ - Make `scorel up` ensure the singleton daemon is running, register the current cwd as a Project, and launch/serve UI without owning daemon lifetime.
24
+ - Keep foreground `scorel host serve` for debugging; Ctrl-C on foreground serve still stops that foreground process.
25
+ - Daemon lifecycle:
26
+ - daemon is not killed when one client exits;
27
+ - explicit `scorel host stop` stops it;
28
+ - if no IM extensions are active, daemon idle-shuts down after no connected clients and no active work for the configured timeout;
29
+ - if any IM extension is active, daemon remains alive until explicit stop.
30
+
31
+ ## Not In Scope
32
+
33
+ - Migrating old `~/.scorel/gui/projects.json` or `~/.scorel/gui/sessions` into the unified state. Scorel is pre-1.0; users may remove old GUI-local files manually if needed.
34
+ - System LaunchAgent/login-item installation.
35
+ - Multi-user or system-wide daemon.
36
+ - Remote daemon lifecycle changes.
37
+ - Per-session RTK stats breakdown UI.
38
+ - Restart-on-crash supervisor.
39
+
40
+ ## Acceptance Criteria
41
+
42
+ - GUI local Projects and Sessions are created under `~/.scorel/projects.json` and `~/.scorel/sessions`, not under `~/.scorel/gui`.
43
+ - `gui-store.json` is stored at `~/.scorel/gui-store.json`.
44
+ - `scorel host start` starts or reuses a background singleton daemon and returns without waiting for daemon shutdown.
45
+ - `scorel up` reuses an existing running daemon instead of spawning a child daemon that dies with `scorel up`.
46
+ - Starting GUI when a daemon is alive attaches to it and does not start a second Host writer.
47
+ - Starting GUI when no daemon is alive starts the background singleton daemon, then attaches to it.
48
+ - If no clients remain, no work is active, and no IM extension is active, daemon exits after its idle timeout.
49
+ - If an IM extension is active, daemon does not idle-exit solely because there are no GUI/CLI clients.
50
+ - Model/tool messages remain unchanged: daemon lifecycle and state unification do not alter tool call args or provider tool result context.
51
+
52
+ ## Test Requirements
53
+
54
+ ```bash
55
+ pnpm --filter @scorel/app-cli test -- src/daemon-cli.test.ts src/up-cli.test.ts
56
+ pnpm --filter @scorel/app-gui test -- src/main/local-host.test.ts
57
+ pnpm --filter @scorel/daemon test -- src/embedded/embedded.test.ts
58
+ pnpm verify:m9-gui
59
+ pnpm typecheck
60
+ pnpm test
61
+ ```
62
+
63
+ Manual/E2E:
64
+
65
+ - Start GUI from a clean temp HOME through Electron CDP.
66
+ - Verify local Project registration creates `~/.scorel/projects.json`.
67
+ - Verify local Session creation creates `~/.scorel/sessions/*.jsonl`.
68
+ - Verify no `~/.scorel/gui/projects.json` or `~/.scorel/gui/sessions` is created.
69
+ - Verify GUI start from a clean HOME creates `~/.scorel/daemon.json` and attaches to that daemon.
70
+ - Verify `scorel host start` returns while `scorel host status` still reports a running daemon.
71
+ - Verify `scorel up` exit does not stop the singleton daemon it started.
72
+ - Verify short idle timeout stops a daemon with no clients and no active IM.
73
+ - Verify active IM prevents idle shutdown.
74
+
75
+ ## Impacted Files
76
+
77
+ - `apps/cli/src/daemon-cli.ts`
78
+ - `apps/cli/src/up-cli.ts`
79
+ - `apps/cli/src/index.ts`
80
+ - `apps/gui/src/main.ts`
81
+ - `apps/gui/src/main/local-host.ts`
82
+ - `packages/daemon/src/index.ts`
83
+ - `scripts/verify-m9-gui-cdp-e2e.ts`
84
+ - `docs/SHIP.md`
85
+ - `docs/ROADMAP.md`
86
+
87
+ ## Risks And Boundaries
88
+
89
+ - Background daemon process management must not leave stale `daemon.json` as a false-positive running daemon.
90
+ - The singleton daemon must remain the only local writer for Project and Session files.
91
+ - Electron GUI starts the daemon through the CLI entrypoint; packaged builds must provide `SCOREL_CLI_ENTRYPOINT` when the source tree is unavailable.
92
+ - Old GUI-local state under `~/.scorel/gui` is intentionally not migrated in this spec.
93
+
94
+ ## Status
95
+
96
+ Done.
@@ -0,0 +1,85 @@
1
+ # S0099: GUI Connection And Device Settings
2
+
3
+ ## Goal
4
+
5
+ Make GUI connection setup match the hosted Relay product path, so users can pair devices, rename paired devices, and inspect connection details.
6
+
7
+ S0101 supersedes the original settings-scope part of this spec: settings configuration is device-scoped, not Project-scoped.
8
+
9
+ ## Scope
10
+
11
+ - GUI Relay pairing:
12
+ - default to the official Relay without showing an editable URL field;
13
+ - expose Relay URL editing only behind an explicit edit affordance;
14
+ - rename the pairing action from `Pair` to `Get Pair Code`.
15
+ - GUI paired devices:
16
+ - allow users to rename a paired Relay Device locally in GUI state;
17
+ - preserve the Relay-reported label as fallback when no local name exists;
18
+ - show device details from the generic device view: status, Device ID, IP when available, and Relay URL.
19
+ - GUI Settings scope:
20
+ - superseded by S0101;
21
+ - the correct product model is device-scoped configuration.
22
+ - Tests and docs:
23
+ - cover local device rename persistence;
24
+ - cover the connection section rendering contract;
25
+ - keep ROADMAP in sync.
26
+
27
+ ## Not In Scope
28
+
29
+ - Relay protocol changes or IP discovery in Relay V1. The UI may expose an optional IP field, but Relay currently does not guarantee one.
30
+ - SSH Remote Device, remote installation, or SSH stdio proxy.
31
+ - Direct WS + token GUI setup.
32
+ - Account/OAuth identity.
33
+ - Importing every remote Host Project automatically into the GUI Project list.
34
+ - Moving IM extension settings to remote scope; IM settings remain local GUI/Host extension settings in this spec.
35
+
36
+ ## Acceptance Criteria
37
+
38
+ - Opening GUI Settings -> Connections shows the official Relay as the default endpoint and does not show a Relay URL input until the user chooses edit.
39
+ - The pair action reads `Get Pair Code`.
40
+ - A pair code is still created with the default official Relay when the URL field has not been edited.
41
+ - Paired devices can be renamed from the Connections page, and the local name persists in `~/.scorel/gui-store.json`.
42
+ - Paired device details expose status, Device ID, Relay URL, and an IP row that is populated only when the device view has IP information.
43
+ - Settings nav behavior is governed by S0101: it shows devices, not Projects.
44
+
45
+ ## Test Requirements
46
+
47
+ ```bash
48
+ pnpm --filter @scorel/app-gui test -- src/main/gui-store.test.ts src/renderer/gui-shell.test.tsx
49
+ pnpm typecheck
50
+ pnpm test
51
+ ```
52
+
53
+ Manual:
54
+
55
+ - Open GUI Settings -> Connections.
56
+ - Confirm the Relay URL input is hidden by default and `Get Pair Code` returns a pair code against the official Relay.
57
+ - Click edit, change Relay URL, and confirm pair/refresh use the edited URL.
58
+ - Pair or seed a Relay Device, rename it, refresh, and confirm the local name remains.
59
+ - Open Settings and confirm the settings selector follows S0101 device-scoped behavior.
60
+
61
+ ## Impacted Files
62
+
63
+ - `apps/gui/src/main/gui-store.ts`
64
+ - `apps/gui/src/main.ts`
65
+ - `apps/gui/src/preload.ts`
66
+ - `apps/gui/src/shared/ipc.ts`
67
+ - `apps/gui/src/renderer/App.tsx`
68
+ - `apps/gui/src/renderer/settings/SettingsShell.tsx`
69
+ - `apps/gui/src/renderer/settings/SettingsNav.tsx`
70
+ - `apps/gui/src/renderer/settings/sections/ConfigSection.tsx`
71
+ - `apps/gui/src/renderer/styles.css`
72
+ - `apps/gui/src/main/gui-store.test.ts`
73
+ - `apps/gui/src/renderer/gui-shell.test.tsx`
74
+ - `docs/CHANGELOG.md`
75
+ - `docs/ROADMAP.md`
76
+
77
+ ## Risks And Boundaries
78
+
79
+ - Device rename is GUI-local metadata, not a Relay identity mutation. Refresh must not overwrite a user's local name with a Relay label.
80
+ - Settings scope is device-based as of S0101. Projects are workspace/session objects, not configuration owners.
81
+ - IP is optional because the current Relay protocol does not report it; the UI contract must tolerate absence without inventing a fake value.
82
+
83
+ ## Status
84
+
85
+ Done.