diff --git a/emrg/server/evolution_prompt.md b/emrg/server/evolution_prompt.md index d113a058..a9c522b5 100644 --- a/emrg/server/evolution_prompt.md +++ b/emrg/server/evolution_prompt.md @@ -272,239 +272,7 @@ When reading rants, follow these rules: > **Note**: first check whether a rant was already handled, to avoid duplicate work: > 1. Check `git log --oneline -20` for commits referencing the rant (search the rant's timestamp or message keywords) — **note: a commit referencing the rant timestamp is only evidence the rant was touched, NOT sufficient proof of completion**. You must further verify: does the rant have unmet acceptance items? Are there unmerged branches? An early PR merge in a multi-stage effort does not mean the rant is done. -> 2. Cross-check against the **implemented-features quick reference** below — if the rant's problem matches a feature in the table, it's handled -> 3. Handled rants need no further attention, unless the user repeats the feedback (meaning the earlier fix was incomplete) -> -> **Implemented-features quick reference** (avoid duplicate work; meta entries like "quick-ref update" removed, feature entries only): -> - ESC interrupt ✅ | command autocomplete (/) ✅ | response countdown ✅ -> - session selector (↑↓/j/k) ✅ | input auto-wrap ✅ | cursor rendering fix ✅ -> - CJK wrapping/cursor ✅ | SIGWINCH resize ✅ | project auto-tracking ✅ -> - config.toml hot reload ✅ | CLAUDE.md removed ✅ | /project removed ✅ -> - Agent.md/CLAUDE.md reading ✅ | README bilingual (zh/en) ✅ -> - PID single-instance lock ✅ | `/rant @project` ✅ | `/clear` ✅ -> - `/resume` ✅ | `/rename` ✅ | `/rewind` ✅ | `/trigger` ✅ | `/memory` ✅ | `/sessions` ✅ | `/help` ✅ | `/skills` ✅ | `/version` ✅ -> - Ctrl+A/E/W/K/U shortcuts ✅ | bracketed paste optimization ✅ -> - render throttling (60fps) ✅ | dynamic viewport ✅ | auto-compact ✅ -> - ANSI style rendering (style_to_sgr, buffer cascade) ✅ | install/uninstall ✅ | Windows/WSL guide ✅ -> - `/rant` interactive project picker ✅ | parallel evolution coroutines (asyncio.gather) ✅ -> - CI workflow (pytest + conflict-marker check) ✅ | CI badge ✅ -> - projects.jsonl→projects.yml migration ✅ | prompt variable substitution validation ✅ -> - `emrg rant -p/--project` CLI flag ✅ | install.sh standard paths + gh check + python version validation ✅ -> - `/model` model switching ✅ | CJK/UTF-8 input fix ✅ | model name shown at startup ✅ -> - Terminal title sync (idle/busy) ✅ | llm.jsonl full logging + rotation ✅ -> - Selector state consolidation (SelectorState) ✅ | nonlocal CI check ✅ | install.sh config template ✅ -> - dynamic __version__ in User-Agent ✅ | llm.jsonl full HTTP request/response ✅ -> - stream_options per-model (None = Kimi) ✅ | README/Agent.md multi-model config examples ✅ -> - [[llm.models]] supports model field (name ≠ API model) ✅ | auto_compact_threshold consistent across files ✅ -> - length-prefixed framing protocol (4-byte header + body) ✅ | client auto-reconnect ✅ | client log rotation ✅ -> - /skills command lists loaded skills ✅ | install.sh auto-installs deps (uv, gh, python) ✅ -> - extracted _log_llm_exchange, _handle_selector_nav, atomic_write_yaml ✅ -> - encoding='utf-8' full fix (read_text, write_text, open, subprocess) ✅ -> - json.dumps ensure_ascii=False CJK-safe (__main__, client, scheduler, daemon, rename) ✅ -> - read_tool param rename (start_line/line_limit/start_line_byte_offset) ✅ -> - markdown_it DEBUG log suppression ✅ | atomic_write_yaml unit tests (420 passed) ✅ -> - ESC cancel propagates to daemon tool-loop stop ✅ | /rewind truncates session history ✅ -> - /trigger interactive task picker (↑↓/j/k, live filter, asyncio.Event) ✅ -> - widget classes extracted to widgets.py (app.py 2157→1529 lines) ✅ | Agent.md slash commands documented ✅ -> - /resume usable while busy ✅ | SIGWINCH stdin reader thread leak fix ✅ -> - ruff cleanup (F401/F841/F821/F541) ✅ | O_NONBLOCK leak fix ✅ -> - _touch_project git-root detection + home-dir filter ✅ -> - Contributor/Committer role gating (ROLE LOCK table, gatekeeping boundary) ✅ -> - paper task type #246 ✅ | open-source task type #248 ✅ -> - paper_prompt.md: date awareness + arXiv search #254 ✅ | git push #255 ✅ -> - paper_prompt.md: stage awareness + Heilmeier Catechism #258 ✅ -> - paper_prompt.md: experiment-first guard + state file + 11 best practices #261 ✅ merged -> - emrg rant CLI @project parsing #257 ✅ -> - Terminal title simplified to idle/busy #260 ✅ merged -> - Electron GUI (Phase 3 non-developer main entry, emrg/gui/) ✅ | first-run onboarding (settings dialog when config missing) ✅ -> - GUI streaming chat (16ms delta batching + marked after done) ✅ | session management (list/switch/new/delete) ✅ -> - GUI disconnect-reconnect (G43 stale port + auto-relaunch + session restore) ✅ | broadcast model (multi-client same session) ✅ -> - GUI G65 own-stream lock (busy blocks session switch) ✅ | G143 pre-generated requestId eliminates race ✅ | G144 first-run default model selected ✅ -> - GUI 15 TUI slash commands (P1-P4, #486/#487/#491/#496) ✅ | GUI /rant evolution dialog + /trigger task dialog ✅ -> - GUI WorkBuddy P1 result panel (three-column, tool-output cards, ⌘\ collapse, narrow auto-hide, #498) ✅ -> - GUI WorkBuddy P2 Ask/Auto mode (daemon empty toolset on ask, capsule switcher, #500) ✅ -> - GUI WorkBuddy P3 evolution visibility (#501 growth card + one-per-day toast + dynamic /version) ✅ -> - daemon evolution_summary command (count + recent N improvements from ~/.emrg/logs/evolution-*.json, #502) ✅ -> - result-panel.js window.ResultPanel export (ES-module migration hardening, #502) ✅ -> - GUI i18n Stage 1 (#503 i18n.js dict {zh,en} + detectLocale + Settings language switcher + data-i18n static) ✅ -> - GUI i18n Stage 2 (#504 all dynamic renderer strings localized: chat/sidebar/dialogs/result-panel/markdown/utils/app) ✅ -> - GUI i18n leak closures (#507 index.html static data-i18n 12 处 + #508 JS runtime strings + Stage 3/3b 漏网扫描回归测试) ✅ -> - Language policy #485 (outward GitHub output always English) ✅ | evolution workspace self-heal #489/#490 (clone on demand + projects/tasks bootstrap) ✅ -> - evolution_summary e2e tests (#509 empty/ordered/limit-clamp/corrupt-skip, hermetic tmp-config harness) ✅ -> - doc test-count guard (#511 tests/test_doc_counts.py: pytest --collect-only vs README/Agent.md 计数 + GUI breakdown 求和;测试增删必须同步文档,否则 CI 失败) ✅ -> - log redaction inline credentials (#513 _redact 遮蔽字符串值内联凭据:sk-/ghp_/xox/AKIA/Bearer/Authorization/JWT/base64-JSON 40+ 字符;logging-only daemon.py:1482) ✅ -> - log redaction sk- tightening (#515 sk- 16+ 纯字母数字/sk-proj-/sk-ant-apiNN-,排除 task-evolution 等路径片段误伤;测试密钥拼接构造防 push protection 拦截) ✅ -> - log previews redaction (#516 _redact_string 覆盖日志内容预览:任务 prompt/rant 消息/记忆 reflection+consolidation 工具结果;LLM prompt 内嵌 user_prompt 不在日志脱敏范围) ✅ -> - LLM error redaction (#518 llm.py _redact_text/_redact_headers:错误日志/异常脱敏 response headers(set-cookie/auth/token)+ body 内联凭据;lazy import daemon._redact_string 防循环导入) ✅ -> - LLM URL redaction (#520 logger.debug 请求/流式 URL 经 _redact_text 遮蔽 query-string 凭据;base_url 可携带 token) ✅ -> - GUI max-rounds truncation hint (#523 chat.js handleDone 检测 exceeded+max|limit|round → chat.maxRoundsHint zh/en 提示可继续;对齐 TUI client/app.py:442;正反两态测试无假阳性) ✅ -> - evolution cycle truncation flag (#525 scheduler EvolutionHandler done 帧检测 exceeded → truncated 标记,不误计空周期/不推进 idle-halt backoff;impact tag -truncated + truncated=max-tool-rounds;正反两态测试) ✅ -> - Test workflow manual dispatch (#527 test.yml 加 workflow_dispatch 触发:push 事件被丢/CI 队列故障时 `gh workflow run test.yml --ref ` 手动重触发,替代空 commit 重触发(空 commit 污染 git 历史且 push 管线若坏同样无效);actionlint gate 已验) ✅ -> - CI re-trigger one-click script (#529 scripts/re-trigger-ci.sh [branch]:宿主侧一键 dispatch 重触发(默认当前分支,set -euo pipefail),替代手记 gh workflow run 命令/空 commit;Agent.md CI 段已文档化) ✅ -> - CI-check pre-LGTM gate (#645 #644 教训:PR push 事件可被丢弃——branch 零 checks 而本地双跑绿 + 并行周期已 LGTM,`gh pr checks ` 才暴露;LGTM 前必须确认 CI checks 存在,无则 workflow_dispatch 重触发(#527/#529)等成功后再说;本地验证必要但不充分——actionlint gate #444 + doc-count guard #511 只在 CI 跑) ✅ -> - Fork-PR conflict CI unblock (#716 教训:**冲突中的 fork PR 零 CI checks**——`mergeable: CONFLICTING`/`mergeable_state: dirty` 时 GitHub 拒跑 CI,close/reopen 与 workflow_dispatch(无法 target fork ref)均无效;唯一解=maintainer push:`maintainer_can_modify:true` → fetch `refs/pull/N/head` → 本地 merge master 解冲突 → push 到 fork 分支 → `pull_request` synchronize 触发 CI;Committer 可直接代解冲突,不必等作者反复 rebase) ✅ -> - Fork-PR conflict merge push guidance (#718 续:合并冲突指引区分 fork PR——`gh pr checkout` 后 `git push origin` 必被拒(origin=上游非 fork);fork PR 须 push 到作者 fork remote(`git push git@github.com:/.git :`),`maintainer_can_modify:false` 时把解决 commit 号贴给作者拉取) ✅ -> - Parallel-cycle merge race handling (#720 教训:多周期可同时看到 2 ✅ 并同时 `gh pr merge`——败者报 "already merged"/"not mergeable" 是**成功信号非失败**:复查 `gh pr view --json mergedAt` 确认后 fetch master 验证 commit 已在;仅真实拒绝(冲突/CI 红/❌)才阻塞) ✅ -> - saturation halt auto-resume (#531 scheduler _saturation_halt_active:停机(≥30 空循环)后 scheduled run 全 skip → handler 无法自检 HEAD 变化,只有手动 /trigger 能恢复;_remote_advanced 用 git ls-remote 对比 origin/master,上游推进即自动恢复+计数清零;+4 测试正反两态/边界/无 git 仓库不崩) ✅ -> - README MANIFESTO intro anglicized (#533 README.md 行 25 MANIFESTO 中文引言→英文;MANIFESTO.md 零改动(宿主方案 C);行 16 语言切换器 + 行 71 `卸载 EMRG.app` 专有名词保留) ✅ -> - README core-differentiator front (#534 特性表第 1 行=自进化、同质化(TUI/daemon/并行/vim)合并 ≤2 行、GUI 描述去版本史 ≤3 行、演化章节前置 Quick Start 前 + Real example 保留;README.md/README.cn.md 同步) ✅ -> - scheduler projects.yml self-heal (#535 _ensure_self_evolution_task 启动即补 projects.yml emrg 条目(path 固定 ~/.emrg/evolution/emrg,已有条目保留)——tasks.yml 有启动自愈但 projects.yml 缺对等保证,唯一补写点 clone 分支需 tick+网络 → _resolve_project_path None → _source_dir 退化 "emrg" 悬空 cwd;+3 测试缺失追加/存在保留/其他条目保留) ✅ -> - LLM gzip body tolerance (#541 llm.py _parse_json_body:gateway 返回无 Content-Encoding 的 gzip body(0x1f 0x8b magic)时 httpx 不解压 → resp.json() UnicodeDecodeError 裸崩(memory reflection 12:40 生产事故);magic 检测透明解压 + chat() 解析失败(JSONDecodeError/UnicodeDecodeError/OSError/EOFError)走瞬时错误同款指数退避重试;chat_stream 已优雅降级无需改;+6 测试 plain/gzip/corrupt/解压/重试成功/重试耗尽) ✅ -> - GUI message display fixes (#543 rant 14:11 宿主实测三缺陷:欢迎屏不隐藏 + 光标残留 + 误标"来自其他客户端";Bug A updateEmptyState 只在切会话调用 → Chat.append()/clear() 同步 App.updateEmptyState?.();Bug B G122 16ms delta 缓冲 vs done 直通竞态 → 残留 delta 晚到建孤儿节点 → main.js flushDeltaBuf 终态(done/error/cancelled)前同步冲刷(webContents.send 保序)+ chat.js doneRids 集合丢弃已 done 流残留 delta(UUID 不复用,500 上限)+ cancelled/流式 error 调 clearTyping 全清在途 typing(daemon cancelled 无 request_id,mid-round 取消无 done 帧);+3 回归测试,npm test 88→91 文档同步) ✅ -> - Windows GCM silent-fail (#545 rant 10:17 Windows 干净安装演化 cycle 反复弹 Git Credential Manager:daemon 是非交互后台进程,凭据操作必须静默快速失败——git_utils.no_prompt_env() 三守卫(GIT_TERMINAL_PROMPT=0/GCM_INTERACTIVE=never/GIT_ASKPASS=)应用于 bash_tool 子进程 + scheduler 全部 8 处 git subprocess + git_cmd;新增 github_status daemon 命令(bundled gh auth status 10s 超时 prompt-free 永不抛,parse_gh_auth_user 解析 as/account 双形态);evolution/open_source prompt 平台守卫(Windows 跳过 git credential fill → 指向 GUI 设置页,未认证优雅跳过不重试);+12 测试 508→520) ✅ -> - Windows TUI input + /rant visibility (#546 rant 10:38 Windows TUI 无法输入中文 + / 菜单上下键失效:win32.py _RAW_INPUT_MODE 加 ENABLE_VIRTUAL_TERMINAL_INPUT(0x0200) 使 conhost 交付 UTF-8 + ANSI 方向键(SetConsoleMode 失败回退 window-input-only 兼容 Win10 1607 前);events.py 0xE0/0x00 老式扫描码归一化(InputParser 在 _utf8_len 之前拦截且门控在已识别扫描码 0x47-0x53——与 UTF-8 续字节 0xA0-0xBF 值域不相交精确无假拦截;parse_keypress 直映射 KeyName);rant 10:48 /rant 项目列表过滤 evolution 工作区导致 emrg 项目消失(#78 过滤设计过时,#489/#490/#535 自愈后 ~/.emrg/evolution/emrg 是打包机唯一路径)→ _handle_list_projects 去过滤(_touch_project 保留跳过);+12 测试 520→534,含判别力回归(泰文/天城文/Ctrl+@/分片读)) ✅ -> - GitHub PAT auth + setup-git (#548 GCM rant 10:17 Stage 2a:GUI 设置页 GitHub 连接区——github_connect daemon 命令(`gh auth login --with-token`,token 走 stdin 永不进 argv(防 ps 泄露);成功后 `gh auth setup-git` 让 git 用 gh 当 credential helper → push/pull/fetch 永不回退 GCM;复用 _check_github_auth 同解析器重验 user 单一事实源);github_disconnect(`gh auth logout --hostname github.com`);dispatch github_connect_result/disconnect_result 帧;GUI RESPONSE_TYPES/IPC/preload 全链路 + 15 条 zh/en i18n;+8 测试 534→542(含 stdin 送达断言固化"token 不进 argv")) ✅ -> - GitHub device-flow auth (#549 GCM rant 10:17 Stage 2b:首选授权路径不开终端不弹 GCM——github_connect_web daemon 命令 spawn `gh auth login --web`(stdin=DEVNULL prompt-free,探针实证非 TTY 仍输出 code+URL),解析一次性 code + device URL 返 GUI;后台任务保活 gh 至授权完成/300s 超时 kill(proc 存 self,cancel 竞态直 kill 防泄漏——task.cancel() 对未启动 task 不执行 body);GUI 设置页无 token 优先 device flow + 新对话框(大号 code + shell.openExternal 开浏览器 + 3s github_status 轮询直至授权);PAT 仍为受限环境兜底;+6 测试 542→548) ✅ -> - GitHub connect banner (#550 GCM rant 10:17 Stage 2c:演化计数增长(=演化刚产出需推 GitHub)且未认证时横幅提示"启用自进化需连接 GitHub → [去连接]"——挂钩 maybeShowEvolutionToast 增长检测点(每日 gate 前,每次增长都查);maybeShowGithubBanner 查 github_status 未认证则显示,[去连接] 打开设置页 GitHub 区,[关闭] 本会话不再弹;本地聊天不依赖 GitHub 启动不打扰;与 #548/#549 闭环(横幅→设置→device flow→已连接);GUI +1=92(正反两态 + seed hidden 判别 + 源码断言)) ✅ -> - Windows TUI Unicode input via ReadConsoleInputW (#553 rant 21:35:47 宿主实测 v0.2.11 中文 IME 仍乱码——#546 VT input 只解决功能键 ANSI 化,字符输入仍走 os.read 字节流按控制台输入代码页(中文系统 GBK/CP936)交付,UTF-8 假设输入链必乱;修复=win32.py 新增 ctypes INPUT_RECORD 结构(KEY_EVENT_RECORD 固定宽度 c_int/c_uint/c_ushort——wintypes.BOOL/DWORD 是 c_long/c_ulong,LP64 POSIX 8B 会把结构撑到 32/40B 而非 Win32 ABI 16/20B,须固定宽度+布局断言测试钉死)+ read_console_unicode(ReadConsoleInputW:UnicodeChar≠0→UTF-8 编码(IME 中文),==0→既有 _LEGACY_SCAN_TO_ANSI 扫描码表→ANSI CSI)+ flush_console_input(raw mode 入口清残余字节流)+ 纯函数 _key_event_to_bytes;app.py _win_stdin_loop 改宽字符路径(非阻塞+5ms 防忙轮询,POSIX 路径不动);win32 模块 POSIX 可导入(守卫 msvcrt/windll)→ 纯逻辑+模拟记录循环单测可移植(ctypes setattr 带点号路径静默 no-op 须逐段 get/set);+24 测试 548→572) ✅ -> - GUI interleaved text/tool message order (#554 rant 21:57:10 完整回合(LLM 文本+工具交替)显示顺序错乱:文本段全拼在顶部、工具行全堆下面(TUI 是顺序交错);根因=handleDelta 每 request_id 复用同一 assistant 节点而 handleToolStart 独立 append 工具行→后续文本段全落回第一个节点;修复=groupNodes 值改 {node,nodes,hasText,sealed}:handleToolStart 在组已有文本时封存当前段,handleDelta 遇 sealed 新建文本段节点(旧节点保留 DOM 原位),handleDone/clearTyping 遍历全段逐个渲染/清 typing;G104 工具先行(无文本)不封存→文本落既有节点防空泡;+1 smoke 测试(text,tool,text,tool,text 交错=5 节点独立成块,判别力实证=去 seal 逻辑即红/恢复即绿);doc GUI 91→93;npm test 93) ✅ -> - Rant UX + locale-safety (#556 外部贡献 pm25coder fork,宿主 UTC+8 Windows zh-CN 实测三缺陷:①rant 时间戳 daemon 权威化——daemon.py 改 datetime.now().astimezone().isoformat()(tz-aware 本地时间,忽略客户端 timestamp),GUI 此前发 new Date().toISOString()(UTC Z,UTC+8 宿主慢 8h)vs TUI 发 naive 本地时间 → 排序错乱;测试断言 stale UTC 被忽略+tz-aware+60s 内(三回归模式:client 泄漏/naive/UTC)②emrgd.log RotatingFileHandler encoding='utf-8'——zh-CN Windows 默认 GBK 代码页乱码 CJK 日志行 ③rant 对话框 textarea CSS(.dialog-card label > textarea min-height 120px resize 继承字体)——默认 box 太小;+测试 read_text(encoding='utf-8') locale-safe(GBK 默认 locale 会挂);package-lock 0.2.0→0.2.11 版本同步;外部贡献通道实证=宿主痛点以 fork PR 回流) ✅ - -> - Evolution count aggregation (#558 外部贡献 pm25coder fork:`/version` pong 与 evolution_summary 的 evolution count 生产恒 0——daemon.py:161 `self.evolutions=[]` 是 pre-scheduler BackgroundThread #95 遗留,从未 append;真实 per-cycle 日志归 scheduler handler(scheduler.py:131 初始化 :708 append);修复=`_evolution_count()` 聚合 `scheduler.total_evolutions()`(sum over handlers 的 evolutions),scheduler 不可用(测试 harness)时回退 legacy `len(self.evolutions)`(isinstance int 守卫 + try/except 双保险);`total_evolutions()` 挂 TaskScheduler(`_handlers` 类型 list[EvolutionHandler],全部任务类型都解析到 EvolutionHandler → 不会 AttributeError);count/recent 一致性(evolution_summary recent 读磁盘 evolution-*.json、count 读 scheduler——两源皆活无错配);+1 测试 572→573;与 #559 配套=aborted cycle 排除后 count 才真正干净) ✅ - -> - Aborted-cycle exclusion (#559 外部贡献 pm25coder fork:aborted evolution cycle(server error 如 "session busy"、或异常)被双重误分类——①空循环判定只查 truncated 不查 error → aborted+HEAD 未变被当 empty cycle 推进 idle-halt backoff(agent 被阻塞 ≠ NTE);②aborted cycle 仍写 EvolutionLog+append self.evolutions+impact 带 error= → 膨胀 evolution count(GUI growth card/toast/evolution_summary);修复=空循环条件加 `not error` + else 分支 reset empty streak(reason "aborted cycle (error[:80])")+ **error 提前 return 不写 log 不计数**(error= impact 条目随 no-log 退役);三态分类完备(complete/truncated/aborted 互斥穷尽循环全部出口);与 #558 配套:total_evolutions() 计 handler.evolutions 而 aborted 永不 append → count 按构造排除 abort;+2 测试 572→575(_get_git_head 钉死 HEAD 判别力:撤 not error 即红/撤 return 即 "log" not in captured 红)) ✅ - -> - Durable evolution count (#563 外部贡献 pm25coder fork:daemon 重启后 scheduler in-memory count 归 0 而 evolution-*.json 日志文件仍在 → GUI growth card/toast/evolution_summary 显示 0,与 recent 列表(读同一批文件)不一致;修复=`_evolution_count()` 返回 `max(in_memory, disk)`——in_memory 来自 scheduler.total_evolutions()(scheduler 不可用时回退 legacy self.evolutions,isinstance int 守卫),disk 遍历 config_dir()/logs 下 evolution-*.json 验证 `data.get("timestamp")` 存在才计数(JSONDecodeError/OSError 跳过=corrupt/partial write 不计);与 #558/#559 配套=count 真正持久化跨重启;+1 测试断言 count==2(corrupt 跳过)+ count==25(limit 截断仍计全量)) ✅ -> - HTTPS→SSH fallback (#565 宿主网络 github.com:443 被墙:git_utils `https_to_ssh_url()`/`is_git_connection_error()`(仅连接性错误判别)/`git_origin_url()`;scheduler 一次性 `_ensure_origin_reachable()` 探针 + `_clone_workspace()` SSH 重试(http.connectTimeout=10)+ `_remote_advanced()` SSH 兜底;+14 测试 575→589,mutation-verified) ✅ -> - git mid-transfer drop marker (#566 外部贡献 pm25coder:`git ls-remote`/`fetch` 中途断连报 "remote end hung up"——补入 `_CONNECTION_ERROR_MARKERS`;正反两态验证) ✅ -> - evolution prompt FETCH_HEAD (#567 Step 2.2 与合并冲突指引改用 `FETCH_HEAD` 而非 `origin/master`——fetch refspec 缺失时 origin/master 陈旧/缺失;+1 回归测试) ✅ -> - Windows TUI GBK logging crash (#568 宿主 rant 09:35:30 Windows "--- Logging error ---" 崩溃:`__main__.py` 客户端 RotatingFileHandler `encoding="utf-8", errors="backslashreplace"`;`bash_tool.py` `_decode_output()`(locale strict → UTF-8 strict → UTF-8 replace;POSIX 零改动);+6 测试,mutation-verified) ✅ -> - install-info.json 原子性 (#569 外部贡献 pm25coder:`_cache_tool_paths` 读共享 install-info.json 非原子 + daemon 实时重写 → 并发读半写 JSONDecodeError flake;修复=守卫 json.loads(损坏→{})+ .tmp/os.replace 原子写;+2 测试 597→599) ✅ -> - Installable-skills catalog (#570 宿主 rant 10:14:29 修订版覆盖 10:11:35 原方案:推荐技能列表本身就是一个技能 skill-catalog.md——复用现有 loader(Available Skills 自动渲染一行)、system.j2 零改动、无元机制;frontmatter 嵌套 `skills:` 列表承载 5 字段元信息;/skills available/install(宿主确认 CLI 安装,MANIFESTO §10)/update;24h TTL 后台自更(仅 managed=true、CLI 缺失跳过、不动宿主手工副本);版本走 api.github.com releases/latest(本机 github.com:443/raw 被墙);loader `_parse_frontmatter` 跳过缩进行(防嵌套 description 覆盖顶层)+ 废弃 recommended.md 永不加载;+35 测试 599→634) ✅ -> - Skills status-center reset (#572 外部贡献 pm25coder:#570 遗留——skills_available/install/update 三个 result handler 渲染后未恢复 status center,/skills available 后状态栏停在 "checking available skills…";修复=三处 handler 渲染前 `status.update(center=server_id or "emrg")`(与 sessions_list/compact/trigger 既有模式一致);+0 测试(3 行改动,634 全绿)) ✅ -> - Windowless daemon spawn on Windows (#576 外部贡献 pm25coder,宿主 rant 19:50:07+08:00 Windows GUI 启动弹控制台黑窗:windowsHide 只藏 cmd.exe,python.exe(console 子系统)被拉起仍分配新控制台 → emrgd.cmd 改优先 `python-dist\pythonw.exe`(GUI 子系统,回退链 pythonw→python→python3.13);daemon 日志走 RotatingFileHandler→emrgd.log(stderr=None 安全,handleError 吞 StreamHandler 失败,daemon 路径零 print);daemon_client.js/main.js 源码模式 spawn 补 `windowsHide:true`(win32 only);+0 测试(9 行改动,634 全绿)) ✅ -> - GUI spinner/typing/markdown fixes (#580 外部贡献 pm25coder,宿主 rant 21:08/21:09/21:10 Windows GUI v0.2.14 实测:①工具完成后 spinner 仍转圈 → handleToolEnd 移除 .tool-spinner + CSS `.tool-row:not(.running)` 兜底防闪烁;②文本段被工具封存后残留 typing 光标 → handleToolStart 封存时移除前段 typing class(光标只留最新段);③✦ 前缀破坏 markdown 块语法(`✦ # Title`/列表/代码围栏 marked 不解析)→ done 渲染前剥离 `^✦\s*`、渲染后以 msg-assistant-mark span 元素重插保持视觉;测试桩升级(classList 以 className 为唯一事实源 / querySelector 类选择器 DFS / remove() 真实脱离父节点);+3 GUI 测试 93→96(Agent.md/README.md 计数同步),634 Python 全绿) ✅ -> - GUI test port-file isolation + scheduler connect-failure alert (#583 外部贡献 pm25coder,G129 rant 2026-08-09T08:03:46:Windows 测试 setupTempHome 只设 HOME 不设 USERPROFILE,os.homedir() 仍读 USERPROFILE → 假 port/token 写进真实 ~/.emrg/emrgd.port → 演化周期 10h 连不上 daemon(WinError 1225);修复=①daemon_client.js PORT_FILE(projectDir=os.homedir()) 参数化,全部调用点传 this.projectDir,生产默认不变;②测试隔离守卫 assertPortFileInTmp(写 port 文件前断言路径在 tmpHome 内)+ setupTempHome 一并重定向 USERPROFILE;③integration findPython 上溯 3 级(test→gui→emrg→仓库根,此前 2 级解析到 emrg/ 包目录找不到 .venv → 回退 PATH 损坏 python.exe);④scheduler `_CONNECT_FAIL_ALERT=3` 连续连接失败计数器:达阈值 WARNING→ERROR 升级 + 可操作提示(检查 emrgd.port),成功连接归零,失败不写 log 不计空循环;⑤doc-count guard 纳入 README.cn.md(CJK 全角括号/「N 项」归一化);+2 pytest 634→636,GUI 96 全绿) ✅ -> - Saturation halt → low-frequency heartbeat full cycles (#585 宿主 rant 2026-08-09T09:35:55,覆盖 #559 完全停机:保护=降频不是停止,**永不停机**——≥30 空轮后不 skip,按 heartbeat 间隔继续跑完整六步循环;`_heartbeat_interval()` = max(interval, min(interval×8, 8h))(60s 任务→480s=8 分钟 / 10min→80min / 1h→8h / ≥8h 任务不变);run loop wait_timeout 饱和时用 heartbeat,manual trigger / 上游 ls-remote 推进立即恢复正常频率(计数清零);`_saturation_halt_active()` → `_saturation_heartbeat_active()`,日志 "never halting";新 rant 最迟一个心跳周期内处理;持久化语义不变;+3 pytest 636→639(公式 7 例 / 饱和 tick 仍跑完整 cycle / 日志无 "skipping" / 上游恢复 / 无 git 仓库不崩),639 全绿,README/Agent/README.cn 计数同步) ✅ -> - Windows integration-test tree-kill (#587 外部贡献 pm25coder,G130 同族于 G129 rant 2026-08-09T08:03:46:Windows 集成测试 `process.kill(-pid)` 进程组杀是 no-op(负 PID 不受支持,抛 ESRCH)→ 被 kill 的 daemon 变孤儿进程残留,G43 stale-port 重连测试本地必挂;修复=新增 `killProcessTree` 帮助函数(win32 分支 `taskkill /PID /T /F` 树杀+强杀,windowsHide:true + stdio:ignore + 错误吞掉;POSIX 分支保持既有 group-kill),killDaemon SIGTERM→3s→SIGKILL 回退链与 stale-port 测试两处调用点全部改走帮助函数;纯测试改动(21+/3-,GUI 96 / pytest 639 计数不变);判别力=负 PID 语义平台差异,win32 分支由本地实跑验证,POSIX 分支 CI 31289054189 SUCCESS 无回归) ✅ -> - Stale-check exception narrowing (#589 外部贡献 pm25coder,G129 同族续:`check_and_restart_if_stale()` 裸 `except Exception` 吞掉一切——AuthError(token 不匹配=配置/安装问题,用户必须看到)与编程错误(AttributeError 等真 bug)被静默隐藏,掩盖 #583 家族根因;修复=收窄为仅瞬态清单(ConnectionRefusedError/FileNotFoundError/OSError/JSONDecodeError/TimeoutError/**ConnectionClosed**——websockets 握手后 ping 中途断线场景),AuthError 与编程错误向上传播给 ensure_connected 调用者;+2 测试 639→641(AuthError 传播 / AttributeError 传播,负态 test_server_unreachable_silent 仍吞瞬态),三处文档计数同步;判别力=删 `not error` 即红/删 return 即 "log" not in captured 红) ✅ -> - Windows cmd-window storm + daemon spawn throttle (#592 宿主紧急 rant 2026-08-09T13:16:36(最高优先级,Windows v0.2.15 宿主实测 cmd 弹窗风暴被迫重启 + daemon 启动失败 GUI/scheduler 无法连接):根因①代码库零处 CREATE_NO_WINDOW——每个 subprocess(git/gh/bash 工具/scheduler/daemon spawn)在 Windows 都弹控制台;②GUI 重连循环每 ~5s 重拉 emrgd.cmd 且每次与前一 daemon 启动竞争(G43 stale-port unlink 删掉健康 daemon 的 port 文件 → scheduler 连不上 93 次);③scheduler 无连接失败退避。修复=新增 `emrg/_win.py` `win32_no_window_kwargs()`(win32 返回 {creationflags: CREATE_NO_WINDOW},其余平台 {})splat 进全部 34 处 subprocess 调用点;daemon spawn 加退避/节流;G43 不删活 daemon 的 port 文件(#593 深化);+测试覆盖) ✅ -> - Port-file self-heal + G43 PID guard (#593 外部贡献 pm25coder/#592 根因深化:daemon 侧新增 `_port_keepalive_loop` 每 60s 检查 `emrgd.port` 缺失即用当前 listener 端口重新 `_assert_port_file`(提取自 startup 的原子写逻辑,外部 G43 unlink 自愈),shutdown 干净 cancel;GUI `daemon_client.js` 新增 `_daemonProcessAlive()`(读 `~/.emrg/emrgd.pid` + `process.kill(pid,0)` 探测,EPERM=存活(Windows 权限),ESRCH/ENOENT=死亡),G43 捕获路径先查 pid——daemon 活着【绝不删 port 文件】(瞬时失败→退避重试 + 抛 "daemon unreachable (pid alive)"),只有真死才 unlink+重拉;+57 pytest(_assert_port_file 提取/keepalive 重断言/shutdown cancel)、+49 GUI 测试(_daemonProcessAlive 正反两态)641→650 / 96→101,README/Agent 计数同步) ✅ -> - TUI daemon spawn throttle (#594 #592 客户端侧总闸补完:`daemon_manager.py` 模块级 `_MAX_SPAWN_ATTEMPTS=3` + `_spawn_attempts` 计数——`start_daemon()` 超限抛 `RuntimeError("daemon failed to start after N attempts — please run 'emrg server' manually...")`(TUI app.py `_reconnect` 循环每 1s 调 ensure_connected → 无限 spawn 即 Windows 弹窗风暴源),`ensure_connected` 成功连接后计数归零(连接生命周期语义,与 GUI daemon_client.js auth_ok 归零一致);`app.py _reconnect` 捕获节流错误一次(`_throttle_warned`)→ 一次性系统消息 + status 提示 "daemon down — run 'emrg server'";+56 pytest(3 次 spawn 无第 4 次 await_count 断言 / 成功连接归零 / autouse fixture 防跨测试泄漏)→ 合并后 652 全绿) ✅ -> - GUI connect canonical-home fallback + probe-before-give-up (#597 宿主 rant 2026-08-09T18:47:37(Windows,v0.2.16 回归):GUI 报 "daemon failed to start after 3 attempts" 而真 daemon 一直活着——根因=daemon 永远写规范 `~/.emrg/emrgd.port`(config_dir()=home;connect.py 无条件读 home),GUI 只读 `gui.project_dir/.emrg`(≠home 时全落空)→ 假"daemon 不存在"→ spawn 撞 PID 锁 → 3 次超时假错误;修复=①`daemon_client.js _readPortToken()` projectDir→canonical-home 权威回退(port/token/log/pid 四处一致:`HOME_PORT_FILE/HOME_PID_FILE/HOME_EMRGD_LOG`),缺失/畸形时 warn + 记 source;②`_spawnOrProbe()` spawn 失败先 `_probeExistingDaemon()` 4 状态诊断(port_file_exists / port_file_content / daemon_alive(ping) / spawn_result),活着直接复用不再盲报;③daemon.py 启动自证日志(pid | port_file | port_file_written_ok)+ ensureConnected 结构化逐次日志 + 最终 result=connected 一行;+2 GUI 测试 101→103(projectDir 缺失→home 复用不 spawn / stale+节流→probe 复用 4 状态字段断言),652 pytest 全绿,README/Agent/README.cn 计数同步) ✅ -> - GUI streaming markdown block projection (#600 外部贡献 pm25coder/宿主 rant 2026-08-09T21:00:28(GUI 流式期间 markdown 不渲染——流式只追加纯文本、done 才整体渲染,无法在流式中查看已稳定的标题/列表/代码块结构,闪烁+丢失上下文):修复(参考 OpenCode markdown-stream.ts 块投影)——`markdown.js` 新增 `streamProject(body, raw, stream)`:`marked.lexer` 逐 token 分词,除尾部 live 块外的稳定块完整渲染并缓存 DOM(不打断选中/不闪烁),尾部 live 块只渲染已稳定部分;fenced code 围栏未闭合(`FENCE_END_RE` 行尾 ```/~~~ 判断)→ 纯文本不高亮(与 TUI fence_count%2 启发式一致),闭合后转完整渲染;done 时 `streamFinalize` 将 live 块转 full 一次性校正(与旧 done 渲染同源 renderMarkdown,requestIdleCallback 调度);`ensureConfigured()` 提取(marked.use 自定义 code renderer 只配置一次,renderMarkdown/streamProject 共用);`chat.js` 流式路径改调 `streamProject`,无 marked.lexer/投影异常 → 回退既有纯文本追加(done 整体渲染兜底);+158 行 renderer.smoke.test.js(块投影稳定/live/围栏未闭合正反两态 + 回退)→ GUI 测试 103→107(29 daemon_client + 22 app-commands + 31 renderer smoke + 15 i18n + 7 integration + 3 commands),README/Agent/README.cn 计数同步) ✅ -> - Auto update-check + prompt (#602 宿主 rant 2026-08-10T07:12:12(打包版 `emrg update` 只打印手动下载提示,从未自动检查 GitHub 新版本——宿主只能靠口碑得知发布):新增 `emrg/update_check.py`——semver 比较 prerelease-safe(`parse_version` 在首个非数字段截断:`v0.2.18-beta1`/`v0.2.18-rc.2` 永远不比已发布版本新,正反两态测试验证)、TTL 门控(`should_check`:无记录/fresh/stale/custom)、幂等 prompt 状态文件 `~/.emrg/.last_update_check.json`(同一版本只提示一次)、静默 api.github.com 检查(网络/HTTP 失败返回 None 绝不 raise,下个 TTL 重试);`[update] check=true|false`(默认 true)+ `ttl_hours=24` 配置;daemon `_update_check_loop` 后台任务(启动 + 每 TTL,禁用时立即退出,shutdown cancel)+ `update_check`/`update_check_prompted` 命令;TUI 一次性非阻塞启动横幅(`New version vX available — .../releases`);GUI settings about 区 Releases 链接行(一次性,无 modal);宿主边界严格遵循——仅检查+提示,**绝不自动下载/安装**;+18 测试 652→670(版本比较 0.2.17<0.2.18、TTL 未过期不查、prompt 幂等、静默网络失败、config 禁用),README/Agent/README.cn 计数同步) ✅ -> - Evolution status rules (#605 宿主 rant 2026-08-10T08:59:57:completed 判定不再等宿主实测——"这种等待没有任何意义,如果我发现没改好,会新起一个 rant";completed = 所有 PR merged + 演化自测通过(pytest/import/CLI green);验收项必须演化可自证(测试/CI/审查),不写"宿主实测"类验收项;宿主反馈走新 rant;分步实现=最后一个 PR merged 才 completed;correction mechanism 保留(新 rant 暴露旧修复不足→回退 in_progress);rants.jsonl 存量 7 条"等宿主"in_progress 按新规则转 completed,不再堆积) ✅ -> - Windows installer pre-stop (#606 宿主 rant 2026-08-10T08:50:44:Windows 升级安装卡在"停止已有进程"——Inno 覆盖 `~/.emrg\install` 前不停运行进程,无窗口 pythonw daemon(emrgd.cmd→pythonw.exe -m emrg.server)独占锁文件,CloseApplications 看不见它 → 宿主只能重启;修复=新 `bin/stop-emrg.cmd`(①GUI taskkill /IM EMRG.exe 优雅 WM_CLOSE→~5s→/F 兜底 ②TUI python.exe -m emrg wmic 命令行过滤(%% 转义 LIKE,PowerShell CIM 兜底 Win11 24H2+ 无 wmic,排除 daemon pythonw -m emrg.server)③daemon:旧安装 `emrg.cmd server stop` 协议关闭(#364 起存在=版本安全)→ emrgd.pid 轮询 ≤10s → taskkill /F /PID 兜底;退出码=残留进程判定,非零→安装器中止给可操作消息;干净安装全跳过)+ `bin/emrgd.cmd` stop 分支 + .iss `[Files] dontcopy` + `[Code] PrepareToInstall`(ExtractTemporaryFile→经 cmd.exe 以 /c SW_HIDE 运行,非零中止)+ build-runtime 打包;审查中修复 cmd 括号块 %DPID% 解析时展开 bug(→setlocal enabledelayedexpansion + !DPID!,判别回归断言);+4 测试 670→674 文档同步;Windows 真机行为待宿主反馈(新规则:反馈走新 rant)) ✅ -> - Installer pre-stop unconditional GUI /F (#608 宿主 01:27:07Z 实测反馈:pm25coder 在 #606 合并后于 Windows 真机验证——长活 ~15h GUI 会话 WM_CLOSE 在 5s 宽限窗内未退出,两次整跑未终止,直接 `taskkill /IM EMRG.exe` 也未终止、`/F` 才终止 → 旧 GUI 会话可拖住安装器;修复=`stop-emrg.cmd` GUI `/F` 兜底改为**无条件**(移除 tasklist/findstr survivor gate:GUI 未运行→优雅 taskkill errorlevel 1→跳过等待→/F 快速 no-op;GUI 运行但延迟→无条件 /F 强制终止);判别断言就地强化(ping→/F 之间无 findstr,去掉无条件 /F 即红);计数 674 不变;安装器 rant 08:50:44 闭环(#606+#608 均 merged + 测试绿)) ✅ -> - cmd launchers ASCII-only REM (#610 宿主 01:36:12Z note:`bin/stop-emrg.cmd`/`bin/emrgd.cmd` 等 .cmd 文件 REM 注释含中文 → zh-CN Windows CP936 代码页 mojibake(REM 行乱码);修复=全部 .cmd REM 注释改 ASCII-only;+0 测试(纯注释改动,674 全绿)) ✅ -> - GUI packaged vendor bundling (#612 宿主 rant 2026-08-10T11:03:51:打包版 GUI Markdown 不渲染——electron-builder `files` 白名单漏 `vendor/**` → marked/DOMPurify/highlight 未进安装包 → renderMarkdown 静默降级纯文本(源码模式正常、仅打包版中招);修复=package.json build.files 加 `vendor/**` + markdown.js `!window.marked` 时 console.warn 可诊断(不再静默降级)+ build-config.test.js 3 测试钉死白名单/vendor 脚本存在/warn 兜底;GUI 测试 107→110 文档计数同步;674 pytest 全绿) ✅ -> - GUI result-panel collapse deadlock (#615 宿主 rant 2026-08-10T14:11:18:GUI 右侧产物面板点折叠后无法再点开——CSS `#result-panel.collapsed` 把 width 置 0 且 header(含 toggle 按钮)display:none 一起藏掉 → 死锁只能靠 ⌘\/Ctrl+\ 快捷键;修复=方案 A:折叠改 **40px 窄条**(非 0,保留左边框)+ header 保留可见(flex 居中,仅 toggle 按钮,title 隐藏)+ 只藏 .result-list + toggle rotate(180deg)(»→« 指示可展开);localStorage 持久化/窄屏自动隐藏逻辑不变;+1 GUI 测试 110→111(CSS 源级断言:40px 非 0 / header flex / list none / rotate;DOM 存活检查——折叠后 toggle 按钮仍在;slice 到折叠规则组结束防 media query width:0 误伤负断言);README/Agent/README.cn 计数同步 111;674 pytest 全绿) ✅ -> - doc-count guard duplicate npm-test lines (#618 外部贡献 pm25coder:#617 修复的回归类——README.cn.md 曾有两条**完全相同**的 npm test 命令行(复制粘贴重复),原 breakdown 求和守卫逐行独立校验各自求和成立 → 无法发现重复;修复=test_doc_counts.py 新增 `test_no_duplicate_npm_test_command_lines`:逐文档收集含 `npm test` 的行,完全相同行出现 >1 即 AssertionError;Agent.md 两条*不同*的 npm test 行不受影响(全行去重非子串匹配);正反两态验证(干净 675 全绿 / 插重复行即红);测试增删文档计数同步的护栏体系再加固一层) ✅ -> - daemon remove_project command (#619 GUI 多会话 rant 2026-08-10T15:07:19 P1:daemon 侧改动极小=仅新增 `remove_project` 命令——删 projects.yml 中 name 匹配条目(原子写,镜像 `_touch_project` 读路径),**磁盘 `/.emrg/sessions/` 数据保留**(后续 `_touch_project` 自动重注册);响应 `{"type":"project_removed","removed":bool,"name":...}`,失败带 `error` key(文件缺失/损坏 YAML/非 list/未知 name/写失败);`_process_message` dispatch(空 name → error);+5 测试(删除匹配/未知 name 文件不动/磁盘数据保留/无文件不崩/损坏 YAML 报错)→ 合并 #618 计数冲突后 675→680 全绿;三文档计数同步;rant 分阶段 P1-P6,P2 起为 GUI 侧 connManager 多连接改造) ✅ -> - DaemonClient ensureConnected skipStart option (#623 GUI 多会话 rant 2026-08-10T15:07:19 P2 slice 1:connManager 将独占 daemon 生命周期,DaemonClient 实例只连**已运行** daemon——`ensureConnected({ skipStart = false } = {})` 默认不变;skipStart+无 port 文件 → 抛 `daemon not running (skipStart)` 不 spawn;skipStart+stale port+daemon 死(G43 路径)→ 抛 `daemon unreachable (skipStart)` **不删 port 文件不重拉**(port 文件保留供 connManager 重启恢复检测);+2 测试 daemon_client 29→31、GUI 111→113 三文档同步;680 pytest 全绿) ✅ -> - ConnManager open/close/get (#624 GUI 多会话 rant 2026-08-10T15:07:19 P2 slice 2:新模块 `emrg/gui/conn-manager.js`——connManager=daemon 生命周期唯一 owner + 每会话一条独立 DaemonClient 连接(对齐 TUI 多开:每 TUI 一条连接;会话间天然隔离无事件路由);`open(sid, projectPath)`=引导 client `ensureConnected()`(spawn 或直连后关闭)→ 新 DaemonClient `ensureConnected({skipStart})` → `resume_session(sid, cwd=projectPath)` 自动订阅 → 存储,已打开 sid 复用不重复建连;`close(sid)`/`get(sid)`/`all()`/`closeAll()`;main.js 未改线(单会话无回归目标随 rewire 片落);+5 测试 conn-manager、GUI 111→116 三文档同步;680 pytest 全绿;rant 分阶段 P1-P6,P2 剩余=main.js rewire + restart recovery,P3-P6 待续) ✅ -> - DaemonClient per-connection delta batching (#626 GUI 多会话 rant 2026-08-10T15:07:19 P2 slice 3:delta 批量从 main.js 共享态移入**每条 DaemonClient 实例**——构造参数 `deltaBatchMs`(默认 0=每帧即时发,既有行为不变);`_deltaBuf/_deltaTimer/_flushDeltaBuf()` 实例化,`message_delta` 帧入缓冲按 batch 合并成 `chunks` 形状一次发出(与 G122 16ms 同形),终态(done/error/cancelled)与断连前强制冲刷保序(rant 14:11 孤儿节点教训);多会话各自独立缓冲互不干扰;+6 测试 daemon_client 31→37、GUI 118→124 三文档同步;680 pytest 全绿) ✅ -> - ConnManager daemon restart recovery (#627 GUI 多会话 rant 2026-08-10T15:07:19 P2 slice 4:短窗口内**所有**打开会话连接同时断 → 判定 daemon 重启 → `recoverAll()` 全量恢复——close 全部 → 按 `open()` 序列(引导→skipStart→resume_session 重订阅)逐会话重开,单会话失败跳过不阻塞其余;单条断 → 不触发全量恢复(留给后续片独立退避);`_restartDetected()` 检查 `_disconnects`(sid→最近断连时间戳)全部落在 `restartWindowMs`(默认 1000ms 可配)窗口内;`_recovering` 守卫防 close→disconnect→recoverAll 递归;+3 测试 conn-manager 5→8(全断自动恢复/单断负态/recoverAll 重开重订阅含 stale 连接排除)、GUI 121→127(合并 #626 后 124→127 文档计数冲突化解)三文档同步;680 pytest 全绿;P2 剩余=main.js rewire + single-conn backoff,P3-P6 待续) ✅ -> - GUI main.js ConnManager rewire (#629 GUI 多会话 rant 2026-08-10T15:07:19 P2 收官:main.js 全量改走 ConnManager——conn-manager `ensureDaemon()` 保留 daemon 级连接(ping/list_sessions/set_model/github_* 等非会话命令),会话连接 skipStart 不 spawn;`open({resume:false})` 供新会话(daemon 隐式订阅),失败关半开连接不泄漏,断连残留 stale 关闭重开;`onOpen`/`onRecovered` 钩子(事件桥含 recoverAll 重开路径 + 恢复后 sessions/pong/status 刷新);`close()` 标 `_intentionalClose` 抑制断线横幅 + 不触发重启判定;**单连接独立退避**(N 会话单条断 → 退避重开该会话);daemon_client G65 自有流锁移入实例(own done/timeout/session-busy/own cancelled/断连释放);main.js 删全局 client/ownStream/deltaBuf,IPC 全走 activeConn/requireConn/openSession,sendMessage 自动 open,switchSession 切走关旧连接,cancel 发激活连接,事件桥附带 sid;+15 测试(dc 37→43、cm 8→17)GUI 127→142 三文档同步;680 pytest 全绿;P2 完成) ✅ -> - GUI renderer per-session chat isolation (#630 GUI 多会话 rant 2026-08-10T15:07:19 P3 slice 0:renderer 会话级聊天状态隔离——chat.js `sessionState` Map(sid→{groupNodes,toolRows,doneRids},sid=null 旧版单会话桶零回归)+ 全部 handler 可选 sid(handleDelta/handleDone/handleToolStart/handleToolEnd/clearTyping/clear/addSystemMessage/addUserMessage/createAssistantNode)+ 容器路由 API `registerContainer(sid,el)`/`unregisterContainer(sid)`/`chatContainer(sid)`(未注册回退默认 #chat-view,P4 openSessions 用)+ `groupNodesFor`/`toolRowsFor` 访问器;app.js handleEvent 透传 `evt.sid`(#629 事件桥附带),disconnected 按 sid 隔离分组清理+工具行失败标记;+4 测试 renderer.smoke 32→36(两会话同 rid 隔离/done 只清本会话/clearTyping 作用域/容器路由回退);GUI 142→146 三文档同步(#629 合并计数冲突解到 146);680 pytest 全绿;P3 剩余=chat-view 容器 + sessionsBySid + 事件按 sid 路由,P4-P6 待续) ✅ -> - GUI renderer sessionsBySid state table (#632 GUI 多会话 rant 2026-08-10T15:07:19 P3 slice 1:renderer 会话级状态表——`state.sessionsBySid: Map` + `sidState(sid)` get-or-create;`state.busy`/`ownStreamRequestId`/`mode` defineProperty getter/setter 委托**激活会话条目**(既有调用点零改动);handleEvent done/cancelled/disconnected/error 释放**事件 sid 条目**锁(后台会话广播 done/取消/断连不误清激活会话,仅激活会话事件同步输入条 UI);switchSession 不再清 marker(每会话自持 busy/rid,P4 切回继续生成符合验收);+4 测试 renderer.smoke 36→40(激活条目路由/切会话指针移动/bg done 隔离/无 sid 回退激活);GUI 146→150 三文档同步;680 pytest 全绿;P3 剩余=chat-view 容器 + 事件路由终态,P4-P6 待续) ✅ -> - GUI per-session chat-view containers (#634 GUI 多会话 rant 2026-08-10T15:07:19 P3 slice 2:每会话一个 `.session-view` 容器 + display 切换(浏览器 tab 效果)——`#chat-view` 变绝对定位包装(overflow:hidden),`.session-view` = inset:0 滚动容器(display:none 除非 `.active`);app.js `ensureSessionView(sid)`(wrapper 内按 dataset.sid 查找/建容器 + 幂等 registerContainer,不依赖 getElementById——测试沙箱对未知 id 返新 mock 且 mock .id 不入 attributes)`activateSessionView(sid)`(去旧加新 .active + scrollToBottom,导出供测试);`switchSession`/`newSession` 改为激活容器(**不再 Chat.clear()**——切走保留滚动/草稿/工具卡片/流式现场);`deleteSession` unregister+移除被删容器;`/clear`+`/rewind` 定向 `Chat.clear(state.sessionId)`(无 sid 只清激活容器,后台容器保留);`updateEmptyState` 查**激活会话**容器(wrapper 恒含 session-view 子节点不能数 wrapper);chat.js `chatContainer(sid)` 回退链=已注册容器→激活会话容器(无 sid 事件落激活会话,P4 过渡)→默认 #chat-view;CSS `#chat-view > *:not(.session-view)` 防滚动条内缩到 760px 中栏 + 媒体查询 padding 移入 .session-view;+3 测试 renderer.smoke 40→43 + mock innerHTML setter 忠实化("" 清 children,Chat.clear 依赖);GUI 150→153 三文档同步;680 pytest 全绿;P3 剩余=事件路由终态,P4-P6 待续) ✅ -> - GUI disconnected per-sid isolation (#636 GUI 多会话 rant 2026-08-10T15:07:19 P3 finalize:disconnected 事件按 sid 隔离——sidState 条目加 `disconnected` 标记 + 注册容器 `.disconnected` 类(`Chat.hasContainer(sid)` 守卫,防 chatContainer 回退链误标激活容器);**全局横幅/红点仅激活会话(或无 sid 单会话过渡期)断连显示**,后台会话断连不打扰全局 UI(rant 验收"断一条不影响其他会话");`status` connected 清全部断线标记 + 容器类;switchSession 切入断线会话提示 i18n `app.sessionDisconnected`(G89 输入条仍可用);CSS `.session-view.disconnected` 视觉(dim + hatch);+3 测试 renderer.smoke 43→46、GUI 153→156 三文档同步;680 pytest 全绿;P3 完成) ✅ -> - GUI open-sessions state + gui_state.json (#637 GUI 多会话 rant 2026-08-10T15:07:19 P4 slice 1 写路径:新 `emrg/gui/gui-state.js`(纯 Node)——`guiStatePath`(~/.emrg/gui_state.json)+ `sanitizeOpenSessions`(跳过缺 sid/projectPath 条目、lastActive 倒序、上限 20,读写共用)+ `saveGuiState`(.tmp+rename 原子写,镜像 #569);main.js `openSessions: Map` 簿记 + touchOpenSession/markSessionActive/防抖 1s 写盘 + 退出冲刷;**switchSession 不再关闭旧会话连接**(多会话保持,浏览器 tab 语义——关闭走新 `emrg:closeSession` IPC:断开+移除+持久化**保留磁盘数据**,与 delete_session 区分);`emrg:getOpenSessions` IPC(跨项目打开列表,slice 2 侧边栏数据源);sendMessage 标记激活 + 事件桥 done/delta 刷新 lastActive(conn-manager onOpen 钩子加 projectPath 参);deleteSession/newSession 同步簿记;+7 测试 gui-state.test.js;GUI 153→163(#636 并入后 renderer.smoke 46 + 7 gui-state,计数冲突解到实测 163)三文档同步;680 pytest 全绿;P4 剩余=slice 2 sidebar + 启动恢复) ✅ -> - GUI open-sessions sidebar + gui_state restore (#639 GUI 多会话 rant 2026-08-10T15:07:19 P4 slice 2 读路径/侧边栏:main.js `restoreOpenSessions`(init 读 gui_state.json → 重开有效条目 cap 20 + resume 重订阅 → 失效跳过 + 重写盘 → activeSid 恢复/回退最近有效 → 窗口标题同步)+ `broadcastOpenSessions`(打开/激活/关闭/删除/新建每次变更推 `open_sessions` 事件给 renderer)+ init 返回 `open_sessions` + `active_sid`(renderer 直接采用恢复激活会话,免 switchSession IPC 往返);sidebar.js `renderOpenSessions`(侧边栏顶部跨项目打开会话区:项目名/会话标题、lastActive 倒序、激活高亮、点击切换、右键关闭保留数据/重命名/删除)+ highlight 扩展覆盖;app.js `state.openSessions` + `open_sessions` 事件 + `closeOpenSession`(断开+释放容器+保留磁盘数据;关激活会话 → 切最近打开会话否则新建)+ showOpenSessionsMenu;index.html `#open-sessions` + i18n zh/en + CSS;+4 测试 renderer.smoke 46→50 + mock 升级(querySelectorAll DFS 类选择器 + classList.toggle 忠实 force);GUI 163→167 三文档同步;680 pytest 全绿;P4 完成,P5-P6 待续) ✅ -> - GUI open-session dialog project→session (#641 GUI 多会话 rant 2026-08-10T15:07:19 P5 slice 1:打开会话弹窗两步——`showOpenSessionDialog`(listProjects → 项目行含路径 hint + 底部"+ 新建项目…")+ `showProjectSessions`(listProjectSessions(cwd=projectPath) → created_at 倒序 → 点击 switchSession 复用连接);main.js `emrg:listProjectSessions`/`emrg:registerProject` IPC(G121 目录可写校验;list_sessions(cwd) 轻量命令 → daemon 隐式 `_touch_project` 注册,零 daemon 改动,**不调 init_auto_evolve** 防意外建演化任务);preload 暴露两 API;app.js `/open` 指令(commands 15→16)+ bindUi 初始化;i18n zh/en 10 条 + cmd.open.hint;+2 测试 renderer.smoke 50→52(项目→会话下钻 / 无项目提示);GUI 167→169 三文档同步;680 pytest 全绿;P5 剩余=slice 2 新建会话 + 删除项目) ✅ -> - GUI new-session dialog + delete-project protected guard (#642 GUI 多会话 rant 2026-08-10T15:07:19 P5 slice 2:**新建会话弹窗** `showNewSessionDialog`(listProjects 活跃序 → 点选即 `App.newSession({projectPath})`;底部"+ 新建项目…" → pickProjectDir → registerProject → 同路径新建)+ index.html `#new-session-dialog` + 打开弹窗顶部"+ 新建会话…"入口;**删除项目**:打开弹窗项目行右侧删除按钮 → 受保护守卫(内置 project `emrg` / 内置 task `emrg-task` 提示"系统项目不可删除",不调 API;`.emrg` 非内置可删)→ 确认弹窗(数据保留可恢复)→ main.js `emrg:removeProject` IPC(关闭该项目已打开会话连接 + 移出簿记 + 写盘 + 激活被关 → renderer 切相邻/新建 + 广播 open_sessions)→ daemon `remove_project`(P1 已备);**slice-1 补洞**:switchSession/sendMessage 带 per-session projectPath(跨项目 resume 用项目 cwd 非全局 projectDir);newSession 接受 projectPath(首条消息前即记簿记);i18n zh/en 11 条;+3 测试 renderer.smoke 52→55(新建会话选项目 / 新建项目→注册→新建 / 删除项目受保护+普通确认);GUI 169→172 三文档同步;680 pytest 全绿;P5 完成,P6 收尾待续) ✅ -> - GUI multi-session P6 finalize (#643 GUI 多会话 rant 2026-08-10T15:07:19 收尾边界:①**关闭在忙连接先 cancel 再 close**——ConnManager.close() 检测 `conn.ownStream && conn.ws` 先发 cancel(fire-and-forget 吞断连异常,不阻塞同步 close 语义),防流式半途断线留脏状态;②**上限 20 超限提示不自动关**——switchSession 显式打开新会话时 `openSessions.size >= DEFAULT_CAP && !openSessions.has(sid)` → 抛 "too many open sessions (20) — close some first"(已打开 sid 复用不拦;sendMessage/newSession 创建路径不拦);renderer 识别该错误 → 本地化 `app.tooManyOpenSessions` zh/en(不再漏英文原始错误);③**projectPath 校验**——switchSession/newSession IPC 收 projectPath 时校验 string 非空;+3 测试(conn-manager 17→19:忙 close 发 cancel / 空闲 close 不 cancel;renderer.smoke 55→56:超限本地化提示);GUI 172→175 三文档同步;680 pytest 全绿;P1-P6 全部完成,验收清单剩余宿主实测项) ✅ -> - GUI multi-session acceptance completion (#644 GUI 多会话 rant 2026-08-10T15:07:19 验收补完两件:①**项目按最新会话活跃倒序**——daemon `_handle_list_projects` 并行扫描各项目 `/.emrg/sessions/*/meta.json` 取最大 created_at(asyncio.gather),projects 响应带 `latest_session_at` 并倒序(此前 projects.yml 按 path 排序、list_projects 按文件序返回,打开/新建会话弹窗"按最近活跃"的验收项实际未满足);GUI 单连接无法并发 list_sessions(DaemonClient `_pending` 按 respType 键控互相覆盖)→ daemon 侧聚合的正确架构;/rant 项目列表同步受益(最近活跃置顶);②**model_set 多连接重复广播幂等测试**——renderer.smoke 新增两/三连接同值广播:state.model 不变、无新系统消息、model-switcher-label 一致(验收"model_set 多连接重复收无副作用");+2 测试(pytest 680→681、renderer.smoke 55→56)GUI 172→173、三文档同步;681 pytest 全绿;P1-P6 验收项仅剩宿主实测类) ✅ -> - GUI project-row recent-activity hints (#646 GUI 多会话 rant 2026-08-10T15:07:19 验收体验补完:打开/新建会话弹窗项目行显示"最近活跃"相对时间——utils.js 新增 `relTime(iso)`(ISO → "刚刚/N 分钟前/N 小时前/N 天前",走 i18n zh/en,缺失/非法输入返回空串);dialogs.js showOpenSessionDialog + showNewSessionDialog 项目行消费 daemon `latest_session_at`(#644 新增字段)追加 hint span(无字段不显示);i18n zh/en 4 键(relTime.*);+2 测试 renderer.smoke 57→59(relTime 六态:刚刚/分钟/小时/天/空/非法 + 弹窗行活动提示/无字段不显示);GUI 176→178 三文档同步;681 pytest 全绿;"按最近活跃排序"从隐式排序变为可见提示,宿主可感知排序依据) ✅ -> - Windows release zip asset (#649 宿主 rant 2026-08-10T20:10:41:Windows 发布资产除 exe 安装包外再提供 zip 压缩版——`build-release.yml` Windows job 在 Make installer 后新增 "Zip installer (Windows only)" 步骤(find `EMRG-*-windows-x64.exe` → PowerShell `Compress-Archive -Force` → bash `test -s` 校验非空)+ upload-artifact glob 加 `dist/artifacts/*.zip`(release job `files: artifacts/*` 自动带上);actionlint 1.7.12 全工作流验证通过;**tag-push 构建教训**:tag 触发的工作流读 tag ref 上的 workflow 文件——v0.2.21 tag 早于 #649 合并 → 该版本 release 无 zip(6 资产符合原始 release rant 验收),zip 自 v0.2.22 起随 CI 产出;验证=CI Windows job 全绿 + actionlint clean;workflow-only 改动,测试计数不变) ✅ -> - GUI packaged local-module whitelist guard (#651 宿主 rant 2026-08-10T20:37:08:v0.2.21 Windows 打包版启动崩溃 `Cannot find module './conn-manager'`——main.js:15/16 require 的 **conn-manager.js 和 gui-state.js 都不在 electron-builder `files` 白名单**(多会话 P2/P4 新增模块忘更新,与 #612 vendor 同根因类);修复=①package.json build.files 加 `conn-manager.js` + `gui-state.js`;②test/build-config.test.js 新增**通用守卫**:扫描 main.js/preload.js 每个本地 `require("./x")` 断言被 files 白名单覆盖(支持 `x.js` 与 `dir/**` 形态;正反两态验证——删白名单项即红并命名缺失模块)——**#612/#651 整个"新增模块忘加白名单"类闭合**;GUI 178→179(build-config 3→4)三文档同步;验证=GUI 179/179 ✓ pytest 681 ✓ doc guard 3/3 ✓;打包版自 v0.2.22 起修复) ✅ -> - Mid-turn queue injection P1 (#655 宿主 rant 2026-08-10T21:55:37:tool loop 进行中发新消息 → **daemon 排队注入**(对齐 codex steer_input)——busy 时新消息入 per-session FIFO 队列(`_session_pending`),当前 round(LLM 请求+全部工具执行)结束后、下一轮 LLM 请求前注入;**不打断工具执行、不丢消息**;busy 分支不再回 "session busy" error → `task_queued`(含 position);注入走 `_inject_pending_messages`(原子 pop 防并发 append 丢失 + `append_message` 持久化保 auto-compact + `steer_committed` 广播);round 预算=注入轮不消耗(stop/Case3/循环用尽均先重查 pending 再 return);wrapper finally:正常结束 → `queued_requeue`(request_ids,客户端自动重发)、cancel/异常/clear/delete → `queued_cancelled`(cancel_event 判定防误重发);Ask mode 注入轮空工具集;clear/delete_session 清队列;协议帧 4 个 daemon→client 广播(P2 GUI / P3 TUI 客户端侧后续 rant);pytest 681→687(+7 e2e)、GUI 179 不变;合并 535efd2) ✅ -> - GUI queue-injection client side (#655 P2 follow-up,自发现:GUI sendMessage 在 busy 时静默 return(app.js:136)——daemon 排队注入对 GUI 用户不可达,4 个广播帧 handleEvent 无分支;修复=①sendMessage 移除 busy 早退(wasBusy 捕获),busy 时记录 `state.queuedSends`(sid→[{requestId,text,mode}]);②handleEvent 新增 4 case——task_queued 显示 '⏳ 已排队(位置 N)'(sid 作用域)、steer_committed 从队列移除、queued_requeue 以原 requestId 经 window.emrg.sendMessage 静默重发(**不重加用户行**,后台会话只操作该 sid 条目 + setComposerDisabled 仅激活会话)、queued_cancelled 清队列+提示;③disconnected 清该 sid 队列(daemon 断连丢队列);④i18n zh/en 3 键(app.queued/queuedResent/queuedCancelled);**review ❌ 同 #695**:was_busy 循环前捕获 → 单客户端回合刚结束 was_busy=false,M2+ 重发到达时 daemon busy 被再排队但未跟踪 → 下个 queued_requeue 找不到 → 静默丢失;修复=每条重发 `if (wasBusy || i > 0)` 重新跟踪(steer_committed 移除已注入,下个 queued_requeue 重发其余,收敛);+6 GUI 测试 212→218(busy 发送记录/位置提示/steer 移除/requeue 同 id 重发+重新跟踪/2 消息 idle 回合 i>0 跟踪回归/cancel 清队列),pytest 705 不变) ✅ -> - GUI multi-session deviations B1-B3 (#656 宿主 rant 2026-08-10T21:59:11:v0.2.22 实测三偏差——①B1 侧边栏"+ 新对话"按钮 + ⌘N 直接新建不弹项目列表(无法选项目/新建项目)→ 改绑 `Dialogs.showNewSessionDialog()`(既有 P5 slice 2 弹窗:项目活跃排序点选新建 / 新建项目按钮);②B2 侧边栏无"打开会话"入口(仅 /open 命令可达两步弹窗)→ 新增 `#open-chat-btn` ghost 按钮 → `Dialogs.showOpenSessionDialog()`(项目→会话)+ i18n zh/en `sidebar.openChat`/`openChatTitle` + CSS `.open-chat-btn`;③B3 切换会话草稿丢失(容器 per-session 但输入框全局单例)→ `state.drafts: Map` + saveDraft/restoreDraft:switchSession 离开前存旧 sid、切后恢复新 sid;newSession 存旧+新会话空草稿;sendMessage 发送成功 delete 该 sid 草稿;restore 重置 auto-resize 高度;回归安全(打开弹窗内"+ 新建会话…"入口与无 projectPath 兜底路径 deleteSession/closeOpenSession→newSession 不动);GUI 179→183(+4 renderer.smoke:B1 按钮弹窗不直建 / B2 入口弹窗 / B3 草稿保存恢复 / B3 发送清除+新建空草稿)三文档同步;合并 9e907aa) ✅ -> - GUI proactive update prompt (#660 宿主 rant 2026-08-11T09:18:16:GUI 启动主动检查新版本 + 设置页手动检查按钮——boot() 成功路径调 refreshUpdateCheck(幂等 prompted_version 只提示一次,对齐 TUI 启动横幅;daemon 未就绪静默失败);设置页 #about-update 行旁新增"检查更新"按钮 → update_check 消息加 `force:true` → daemon 立即 `run_update_check_once()` 刷新缓存再返回(不再只读 TTL 缓存);i18n zh/en `settings.checkUpdate`/`settings.checkingUpdate`;测试 GUI 187→188;合并 e5edaaf) ✅ -> - GUI workspace panel P1 (#661 宿主 rant 2026-08-11T12:20:35 阶段 1 数据层:daemon `list_files`→`files_list`(目录在前按名排序对齐 ReadTool/单目录 5000 条上限 + `truncated`/绝对路径校验相对拒绝/符号链接不展开归 file/错误返回 error 不崩溃)+ `read_file`→`file_content`(UTF-8 文本/1MB 上限 error 提示用系统工具/UnicodeDecodeError→`binary:true` content 空不走 base64/start_line+line_limit 分页显式 limit 上限 2000);GUI RESPONSE_TYPES 加 `list_files:"files_list"`/`read_file:"file_content"` + `_classify` list_result 白名单加 files_list(防 pending 超时迟到帧)+ preload `listFiles`/`readFile` + main.js `emrg:listFiles`/`emrg:readFile` IPC(requireConn 10s 当前会话连接天然认证);+6 pytest e2e TestWSWorkspacePanel(混排排序/相对拒绝/符号链接不展开/5000 截断/文本+分页/二进制+1MB)+1 build-config(preload API 存在性);pytest 688→694、GUI 187→188;合并 a83638b) ✅ -> - README philosophy intro block (#662 宿主 rant 2026-08-11T12:27:00:MANIFESTO 引语后追加双语理念对偶句——EN "Everyone is a product manager — every rant is a ticket for the next release / Everyone is a host of silicon life — what you run is a digital organism that evolves with you" + ZH "人人都是产品经理——你的每一条吐槽,都是下一版的需求单 / 人人都是硅基生命的宿主——你运行的,是一个与你共生进化的数字生命";PM=需求主权民主化对应 MANIFESTO 第三条【需求即变异】、Host=共生对应第六章【宿主权利】;MANIFESTO.md 零改动、顶部标语不变、纯文档无测试变更;合并 06ca9b1) ✅ -> - GUI workspace panel P2 framework (#664 宿主 rant 2026-08-11T12:20:35 阶段 2 框架层:`#result-resizer` 绝对定位拖拽手柄(不进 #app flex 流 R6-②,防 WebContentsView bounds x 偏移)+ `.dragging` 抑制 width transition(R1-①);折叠(⌘\)保留 40px 窄条(#615)且 **panelWidth 与 collapsed 分离持久化**(两个 localStorage 键,展开恢复拖拽宽度);Tab 栏 = 静态「文件/产物」+ 打开文件 Tab 条(`#result-tabbar`)——`openFileTab/closeFileTab/activateTab`(同路径去重、上限 8 淘汰最旧、可关闭、active 高亮);per-session 容器模式(缺口 5):`openedTabsBySid/artifactsBySid` 状态表 + `switchSession(sid)` 接入 app.js switchSession/newSession + `addToolResult(data, sid)` 按事件 sid 归类;产物卡片(WorkBuddy P1)暂保留至 P3.2 改 write/edit 登记;i18n zh/en 4 键;+5 GUI 测试 188→193;合并 4c71b25) ✅ -> - GUI workspace panel P3 file browser + viewer (#665 宿主 rant 2026-08-11T12:20:35 阶段 3 slice 1:新模块 `file-tree.js`——懒加载目录树(根 = 激活会话 projectPath,app.js switchSession/newSession/bindUi 三处 `FileTree.setSession(sid, path)` 接线,openSessions 优先回退 projectDir);目录行点击 → `emrg.listFiles`(P1 daemon)**首次展开拉取 + 缓存**(折叠再展开不重复拉取);文件行点击 → `openFileTab(sid, path)`;查看器基础版 `#result-viewer` pane:`emrg.readFile` 内容转义渲染 `
`(per-tab 缓存不重拉)、二进制 → i18n 提示用系统工具、读失败 → 错误提示、头部路径 + 系统工具打开按钮;`openFileTab/closeFileTab` 空 sid 归当前会话桶(对齐 switchSession+setSession 成对接线);i18n zh/en 6 键;+5 GUI 测试 193→198;合并 7c4e953) ✅
-> - GUI result-panel per-session artifact isolation (#666 外部贡献 pm25coder:后台会话 `tool_finished` 只入 sid 桶**不渲染激活 pane**(防污染;切回时 `renderArtifacts()` 从桶恢复 DOM,镜像 renderTabbar 模式)——修掉 P2.2 桶化但无条件渲染的缺口;`switchSession`/`init` 走 `renderArtifacts`;+2 GUI 测试(后台只入桶不渲染 / switchSession 按 sid 重渲染恢复);合并 a1d8d8d) ✅
-> - GUI workspace panel P3.2 artifacts re-scope (#668 宿主 rant 2026-08-11T12:20:35 阶段 3 slice 2:产物 Tab 改 **write/edit 成功文件登记**(决策点 3——bash/read 工具卡移除,错误跳过);**同路径去重**(重写更新既有条目移顶 R6-①)+ **per-session 上限 100**(R7-⑦);记录形状 `{path,name,tool_name,elapsed}` 存 sid 桶(#666 隔离保留);**extractFilePath 改进**(R4-①:优先首个 `/` 开头绝对路径段——write `Created /path (N chars)` / edit `Made 1 replacement in /path` 均命中,去扩展名白名单依赖,Makefile/.env/Dockerfile 可提取);产物行 = 文件名+完整路径,点击 → 查看器 Tab(系统工具在查看器头部);CSS `.artifact-row`;WorkBuddy P1 卡片测试改 P3.2 语义 +2 新测试(去重+上限 / 无扩展名提取+点击开 Tab),GUI 200→202;合并 07de9be) ✅
-> - GUI workspace panel P3.3 viewer (#670 宿主 rant 2026-08-11T12:20:35 阶段 3 slice 3:查看器升级——文本 hljs 语法高亮 + markdown 渲染(marked 复用)+ 图片 file:// 直显(不走 read_file)+ 二进制系统工具提示;CSP `img-src` 加 `file:` 放行本地图片;+3 GUI 测试 202→205;合并 80ab4a0) ✅
-> - GUI workspace panel P2.3+P3.4 HTML preview (#671 宿主 rant 2026-08-11T12:20:35 收官 slice:WebContentsView 内嵌浏览器 HTML 预览——懒创建单实例复用(sandbox+contextIsolation+nodeIntegration:false 对齐主窗)、setWindowOpenHandler deny + will-frame-navigate 仅允许 file: 主框架导航(防远程 URL)、右对齐 bounds 同步(win resize + `emrg:panelResized` IPC;折叠 → offscreen)、renderer 崩溃恢复(`emrg:getPreviewState` main 为真相源)、.html/.htm 不走 read_file + `.viewer-html` DOM 占位混合模型、HTML→HTML 切换=重新加载;i18n zh/en `result.htmlPreview`;+7 GUI 测试 205→212;合并 c6b5872;rant P1-P3 全部 slice 完结) ✅
-> - Windows installer CloseApplications=no + release v0.2.25 (#675 宿主 rant 2026-08-11T17:03:00:Inno Restart Manager 默认 `CloseApplications=yes` 误报任何占用 install 目录文件的非 EMRG 进程(sh/vim/explorer/Defender)弹 "unable to automatically close all applications" 选择框且 Try again 反复失败 → `make-installer.sh` .iss 加 `CloseApplications=no`,EMRG 进程关闭由 R124 `stop-emrg.cmd`(#606/#608)精确负责;版本号 0.2.24→0.2.25 同步 8 处(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json×2、build-runtime.sh、make-installer.sh),零 stale 引用;Build Release v0.2.25 成功,7 assets) ✅
-> - README/Agent.md name definition (#676 宿主 rant 2026-08-11T17:08:48:README/README.cn/Agent.md 三处对称加入 EMRG 名称定义——EMRG 读作 Emergence (emerge),展开为 **Evolving Micro-kernel, Rant-driven Growth**(演化微内核,吐槽驱动成长);纯文档改动 3 文件 5 行;合并 0a50e6e) ✅
-> - README fact fixes + trust copy (#677 宿主 rant 2026-08-11T17:28:02:竞品表 Codex 开源列 ❌→✅ *Apache-2.0*(此前误标 ❌——Codex 是开源但无自进化,差异化注:开源本身不是差异点,闭环进化才是);FAQ 新增安全边界条目 EN/CN(自进化只改 `~/.emrg/evolution/emrg`,绝不碰宿主项目文件;宿主项目上的工具调用仅宿主指令触发;每处改动都过 pytest + PR 评审);Quick Start 新增 BYOK 句 EN/CN(自带 API Key、额度/账单归宿主、软件 MIT 免费);README.md/README.cn.md 同步,MANIFESTO.md 零改动;合并 a499732) ✅
-> - README contribution philosophy (#678 宿主 rant 2026-08-11T17:30:31:Rant-Driven Evolution 段(Real example 之后)EN/CN 对称新增"如何贡献?使用它。"——连接 GitHub + 吐槽 → 吐槽变成真实 PR(演化周期负责编码/测试/上线),无需 fork/clone/写代码,"使用 EMRG 就是在为 EMRG 做贡献";完成三段式叙事(产品经理 / 硅基生命宿主 / 使用即贡献);合并 35ca1c3) ✅
-> - GUI packaged icon fix (#680 宿主 rant 2026-08-11T17:37:03:打包版曾用 Electron 默认蓝色原子球图标——package.json build.mac/win/linux.icon 从目录形 `../packaging/assets/` 改显式单文件(mac .icns / win .ico / linux .png,全部存在于 packaging/assets);运行时 `BrowserWindow icon` 经 `windowIconPath()`(打包版 extraResources 落 `resources/icon.png`,源码回退 `packaging/assets/icon.png`);fs/path 已导入零新增依赖;node --check 通过;合并 b400267) ✅
-> - Windows installer kill bundled-git orphans (#683 宿主 rant 2026-08-11T17:56:25,**18:56:58 修正方向**:Windows 升级安装卡 Inno "DeleteFile failed; code 5"——daemon 演化周期 git 操作中途被杀 → 孤儿 git/ssh/bash 进程锁 `install\git\usr\bin\msys-2.0.dll`;初版修复=stop-emrg.cmd step 4 按**可执行文件路径前缀**杀 bundled git 孤儿(`ExecutablePath -like "$env:USERPROFILE\.emrg\install\git\*"`),:verify 无差别存活判定 → exit 1 中止;**宿主实测 18:56:58 发现方向错误**:路径前缀会误杀宿主自己的 Git Bash sh/vim(也从 install\git 启动),vim 未存盘内容丢失 + verify 抓存活 → 安装中止(R125 同族:Inno 不该干涉宿主工具);**修正**=step 4 只杀 **EMRG 自己的 git 子进程树**(`Get-CimInstance` + `ParentProcessId` 祖先回溯 ≤5 层,祖先含 daemon `pythonw -m emrg.server` / TUI `python -m emrg` 才杀;宿主 sh/vim 祖先链是 explorer/终端 → 不杀),:verify 存活判定同步改为"仅 EMRG 子树残留 → exit 1",宿主工具存活不再是失败;测试锚定判别信号(ParentProcessId + -m emrg + verify 无旧无差别检查);合并 c9131c6(#683)→ 修正 #689 已合并 888efb0) ✅
-> - README emoji restraint (#684 宿主 rant 2026-08-11T17:58:11:README 标题/特性表/流程图 emoji 泛滥——装饰性 emoji 从标题(# 🧱→#、## ✨→##、## 🔄→##、## 🚀→##、### 📦→###)与特性表行移除,EN/CN 对称;演化流程图改纯文本(Inputs / 演化循环 / 编号步骤);doc-count 新增标题无 emoji 守卫(`^#{1,3} ` 标题行禁 emoji,对比表 ✅/❌、底部 ❤️、语言切换 🇬🇧/🇨🇳 保留在正文非标题);MANIFESTO.md 零改动;合并 80a338a) ✅
-> - Release v0.2.26 (#686 宿主 rant 2026-08-11T18:16:52:master 自 v0.2.25 (c8eb77a) 以来 11 commits / 11 PRs(#676-#686),宿主确认发布下一版本;版本号 0.2.25→0.2.26 同步 7 files / 8 refs(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json、gui/package-lock.json、build-runtime.sh、make-installer.sh),grep 0.2.25 仅历史;pytest 694 + GUI 212 绿;Build Release v0.2.26 成功,7 assets(含 Windows zip #649),latest=v0.2.26;合并 f2ba4be) ✅
-> - App icon finalization (#688 宿主 rant 2026-08-11T18:28:09:rant 内嵌 SVG 源码是字面 `%s` 占位符——穷尽搜索(sessions/logs/Downloads/git 历史)无原始 Gemini SVG → 按 rant 详细设计规格**重建** `packaging/assets/icon.svg`(Branch Emergence 分支涌现:绿渐变 #00FF87→#047857、顶部青色 #60EFFF 节点、深绿底 #111c16→#070b08、主干→枢纽→5 支扇形→3 层发光节点);新增 `packaging/gen-assets.sh` 渲染 SVG→PNG(rsvg-convert → Chrome headless → sips 面积平均 box-filter 缩放回退链)+ CI "Generate icon assets" 步骤(Build GUI 前)+ 5 个二进制产物 gitignore(仅 SVG 设计源提交);两轮审查修复:cygpath file-URL(Windows Chrome `file:///$(cygpath -m "$SVG")`,be39d4c)+ iconutil macOS 守卫(非 macOS 跳过 icns + CI 断言仅 macOS,7224890);合并 afbfaea;若宿主产出原始 Gemini SVG 可经新 rant 替换) ✅
-> - stop-emrg EMRG-tree-only kill (#689 宿主 rant 2026-08-11T18:56:58 修正 #683:step 4 按路径前缀杀 bundled git 误杀宿主 Git Bash sh/vim——vim 未存盘 + 安装器中止;初版修正=ParentProcessId 祖先回溯,**review ❌**:祖先回溯无法解析**已死父进程**(#683 主场景正是 daemon 已死后的孤儿,查父返回 $null → 不杀 → DeleteFile code 5 回归);终版=step 0 杀任何进程前**向下 BFS 快照** EMRG 树(根=emrgd.pid daemon PID + EMRG.exe + python.exe -m emrg TUI 排除 emrg.server)→ %TEMP%\emrg-stop-pids.txt;step 4 只杀快照集内仍在 install\git\ 下的 PID;:verify 只查快照集存活 → 宿主 sh/vim 永不被碰(不在快照集),已死 daemon 的孤儿因生前已记录仍被抓;测试重锚定快照语义(Set-Content/$ids -contains/清理);合并 888efb0) ✅
-> - Packaging gen-assets doc (#690 并行周期 doc-only:Agent.md + DEVELOPMENT.md 新增 Packaging 段——图标产物 gitignore(仅 icon.svg 提交,#688),本地安装包构建需先 `bash packaging/gen-assets.sh`(幂等;渲染优先级 rsvg-convert → Chrome headless → sips;.icns 需 macOS iconutil 否则跳过带提示);#467/#468 宿主对称原则(CI 构建时生成 + 宿主本地自检文档化);合并 6b8fff3) ✅
-> - stop-git.ps1 EMRG-tree snapshot kill (#692 宿主 rant 2026-08-11T19:47:44 修正 #689:`Get-CimInstance Win32_Process` 祖先回溯对**已死 daemon 的孤儿 git 进程**解析失败(查父返回 $null → 不杀 → Inno DeleteFile code 5 回归)——改**向下 BFS 快照**:step 0 杀任何进程前从 EMRG 根(emrgd.pid daemon + EMRG.exe + `python.exe -m emrg` TUI 排除 emrg.server)BFS 整棵树写 `%TEMP%\emrg-stop-pids.txt`;step 4 只杀快照集内仍占 `install\git\` 的 PID;:verify 只查快照集存活;宿主 Git Bash sh/vim 永不被碰(不在快照集)且孤儿进程生前已入快照仍被抓;R125 同族(Inno 不干涉宿主工具);另 README 吸引力文案(rant 19:50:37);合并 5d57d60) ✅
-> - TUI cursor-left CLEAR_TO_EOL fix + status bar reorg (#693 宿主 rants 2026-08-11T19:59:09/20:02:43:①光标左移右侧字符消失——write_frame 尾部 `row_dirty_end`+`CLEAR_TO_EOL`(\x1b[0K) 行尾清理把光标右侧未变字符整行清掉(diff 只含光标附近 2 格);修复=**整块删除** row_dirty_end 声明/dirty_end 计算/尾部 CUP+EL;SPACER_TAIL 残影由 WIDE 字 2 列天然覆盖 + 行内收缩(prev 字符→curr 空)走正常分支写空格;review ❌ 纠偏=显式 spacer 空格写入有 off-by-one(WIDE 后光标在 x+2 非 x+1,空格落偏右移字符)→ 彻底删除 elif 块(7296269);②状态栏重组=左段 bold magenta `title (sid[:8]) [model] [1:23] · 3 msgs · ~/proj`(模型独立 `current_model` 跟踪、耗时纯文本 [m:ss] 去 ⏱、消息数+目录走 `left_extra`)、中段 dim 仅 `id @ host`(服务端 ID + 主机名)、右段移除(`_update_right()`→`_update_left_extra()`);/model 切换刷新左段;+8 测试 695→703(test_output +3 / test_buffer +1 / 新 test_status_line +4),GUI 212;合并 2d12ad8) ✅
-> - TUI queue-injection client side (#655 P3 follow-up,自发现:daemon P1 排队注入已 e2e 验证但 TUI 不可达——busy 时 ENTER 被静默吞掉(app.py:1837),4 个广播帧无人处理;修复=①`send_task` 增可选 `id` 参数并返回最终请求 id(重发复用原 id);②ENTER busy 不再拦截(was_busy 捕获),发送后若当时 busy 记入 `_queued_sends`;③read_server 新增 4 帧处理——task_queued 显示 '⏳ Queued (position N)'、steer_committed 从队列移除、queued_requeue 以原 id 静默重发(**不重加 user 行/不重复 msg_count**,busy 置 True + need_new_assistant 保证响应进新 md 行 + 重启耗时计时)、queued_cancelled 清队列+提示;④断线重连清 `_queued_sends`(daemon 断连即 drop 队列);**review ❌ 同 #696**:queued_requeue 重发循环 was_busy 循环前捕获 → 单客户端回合刚结束 was_busy=false,M2+ 重发到达时 daemon busy 被再排队但未跟踪 → 下个 queued_requeue 找不到 → 静默丢失;修复=每条重发 `if (was_busy or i > 0)` 重新跟踪(9cb4194,steer_committed 移除已注入,下个 queued_requeue 重发其余,收敛);+2 测试 703→705(send_task 显式 id 透传 / 返回生成 id),GUI 212 不变) ✅
-> - Release v0.2.27 (#698 宿主 rant 2026-08-12T09:50:56:master 自 v0.2.26 (f2ba4be) 以来 12 commits / 11 PRs(#687-#697),宿主确认发布下一版本;版本号 0.2.26→0.2.27 同步 7 files / 8 refs(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json、gui/package-lock.json×2、build-runtime.sh、make-installer.sh),grep 0.2.26 仅历史;pytest 705 + GUI 218 绿;Build Release v0.2.27 成功(31556996537),7 assets(含 Windows zip #649),latest=v0.2.27;合并 45d0cd7(并行周期 3 LGTM);What's new=stop-git.ps1 连坐强杀 #692 + TUI 光标/状态栏 #693 + README 吸引力 #692 + 图标定稿 #688 + queue-injection 客户端 #695/#696 + quick-ref ×4) ✅
-> - Release v0.2.28 (#703 宿主 rant 2026-08-12T15:49:45:master 自 v0.2.27 (45d0cd7) 以来 4 commits / 4 PRs(#699-#702),宿主指示发布 v0.2.28;版本号 0.2.27→0.2.28 同步 7 files / 8 refs(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json、gui/package-lock.json×2、build-runtime.sh、make-installer.sh),grep 0.2.27 仅历史;pytest 730 + GUI 221 绿;Build Release v0.2.28 成功(31577111800),7 assets(含 Windows zip),latest=v0.2.28;合并 32d2947(3 周期 LGTM);What's new=自动下载更新 + GUI 一键安装 #700 + 单文件 stop-emrg.cmd(CRLF 修复三弹窗根因)#701/#702 + quick-ref #699) ✅
-> - Release v0.2.29 (#721 宿主 rant 2026-08-12:master 自 v0.2.28 (32d2947) 以来 18 commits / 18 PRs(#704-#721),宿主指示发布 v0.2.29;版本号 0.2.28→0.2.29 同步 7 files / 8 refs(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json、gui/package-lock.json×2、build-runtime.sh、make-installer.sh),grep 0.2.28 仅历史;pytest 748(#723 后 +10 pngutil → 758)+ GUI 229 绿;Build Release v0.2.29 成功(31608141280,3 次尝试——#722 renderer 回退 + #723 filter-aware PNG 解码(pngutil.py)/Windows git.EXE 大小写根因修复后 4 平台全过 + release job),7 assets(含 Windows zip),latest=v0.2.29,发布 14:48:05Z;合并 b3a668d(3 周期 LGTM),tag 最终 re-point 6907b14;What's new=任务泛化 + GUI 任务管理 #709/#710/#711 + GUI 文件树 VS Code 对齐 #707 + Windows 图标透明修复 #705/#722/#723 + 演化记录入 memory #708 + git 解析/打包修复 #712/#714/#716/#717/#719/#720 + README 文档 #715 + quick-ref #704) ✅
-> - Task handler generalization P1 (#709 宿主 rant 2026-08-12T18:14:46,被 18:23:15 全面设计取代:EvolutionHandler→TaskHandler 类改名(40 refs)+ workspace 自愈特判泛化(`_repo_configured` = 有 repo 配置即自愈 clone/对齐,不再特判 emrg 项目)+ `_resolve_task_template` 模板查找 helper(内置 TASK_TEMPLATES → ~/.emrg/task-templates/.md → evolution_prompt.md 兜底 + 告警);纯重构行为不变,pytest 730→736;合并 f7e8671) ✅
-> - Task/template CRUD + hot reload P2 (#710 宿主 rant 2026-08-12T18:23:15:daemon 任务管理能力——`task_create/update/delete` + `task_template_create/list/update/delete` 命令(task_result/templates_list/template_result 帧);存储 `~/.emrg/tasks.yml`(扩展 description/config.repo)+ `~/.emrg/task-templates/.md`(原子 tmp+replace 写);校验=name `^[a-z0-9][a-z0-9-]*$` ≤32、type 内置或已存在自定义、project 必须在 projects.yml、interval ≥60、内置类型/模板只读拒绝、删除被任务引用的自定义类型拒绝(错误带任务数);`TaskScheduler.apply_tasks()` 热重载(原子写 → 与运行 handler 签名 diff → 增删重启,幂等);未知/自定义类型不再静默跳过——以用户模板 → evolution_prompt.md 兜底启动为 TaskHandler;+8 测试 736→744;合并 be574d5) ✅
-> - GUI task/template management P3 (#711 宿主 rant 2026-08-12T18:23:15 收官:设置对话框「定时任务」区——任务列表(名称/类型/项目/间隔/启用 + 触发/编辑/删除)、行内新建/编辑表单(类型下拉含自定义、项目下拉仅注册项目、间隔 ≥60 客户端+daemon 双校验、名称编辑只读)、自定义类型管理(内置只读无操作按钮、自定义编辑/删除/新增带提示词模板 textarea);IPC 7 个 handler(main.js+preload.js)+ RESPONSE_TYPES +7(task_result/templates_list/template_result——缺失则 sendCommandAndWait 回退命令名 → 8s 超时假失败);i18n 26 键 zh/en;6 个宿主拍板点全部落地;renderer.smoke +3 + daemon_client +1 → GUI 225→229;合并 b8d4817) ✅
-> - Windows pytest matrix in CI (#725 v0.2.29 CI 缺口:Windows pytest 此前只在 tag 触发的 Build Release 跑(test.yml 仅 ubuntu)——FakeGitRun git.EXE 大小写 bug(#723)等 Windows-only 测试回归要到发版构建才暴露;修复=test.yml 新增 test-windows job(windows-2025 + astral-sh/setup-uv python 3.13 + uv sync + uv run pytest tests/ -v),每个 PR 都在 Windows 上跑 pytest 门禁;合并 1be1e34) ✅
-> - Installer stop-emrg output on failure (#727 宿主 rant 2026-08-13T09:24:37:安装器失败时宿主只看到 exit 1 无任何原因(R125 家族);修复=make-installer.sh .iss [Code] 捕获 stop-emrg.cmd 输出并在失败时显示给宿主(FileExists 守卫 + 2000 字符截断),不再静默失败;合并 9599852) ✅
-> - Packaged *.cmd pure CRLF (#728 宿主 rant 2026-08-13T09:44:32:打包版 .cmd 因 LF 行尾在 cmd.exe 下行为异常(三弹窗根因家族);修复=build-runtime.sh + build-release.yml 对打包运行时全部 *.cmd 强制纯 CRLF 转换 + 测试断言;合并 2b2e857) ✅
-> - stop-emrg.cmd v2 host-verified (#729 宿主 rants 2026-08-13T09:56:47/10:00:33:安装器 exit 1 最终修复——stop-emrg.cmd 重写(124 行,83+/72-),Windows 真机验证通过(EMRG 树 BFS 快照杀 + 宿主工具不碰 + :verify 只查快照集);合并 eb38234) ✅
-> - Release v0.2.30 (#730 宿主 rant 2026-08-13T10:28:24:master 自 v0.2.29 (b3a668d) 以来 8 commits / 8 PRs(#722-#729),宿主确认发布 v0.2.30(Windows 安装器 exit-1 最终修复版);版本号 0.2.29→0.2.30 同步 7 files / 8 refs(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json、gui/package-lock.json×2、build-runtime.sh、make-installer.sh);Build Release v0.2.30 成功(31663482261,#731 iscc gate 修复后 4 平台全过 + release job),7 assets(含 Windows zip),latest=v0.2.30,发布 03:25:18Z;合并 f5d7f47;What's new=Windows 安装器 exit-1 修复链 #727/#728/#729 + CRLF 根因 #728 + iscc gate #731 + Windows pytest 门禁 #725) ✅
-> - iscc compile gate (#731 v0.2.30 Build Release 31661378619 在 windows 'Make installer' 步骤失败——iscc 拒绝 emrg.iss [Code]:'Invalid number of parameters' on LoadStringFromFile(LogFile);根因=Inno Pascal Script API 是 2 参 out-arg 形式(LoadStringFromFile(FileName; var S: AnsiString)),#727 的日志浮出代码调了不存在的 1 参 string-return 形式;Test 工作流从不编译 .iss → 只在 tag-push Build Release 暴露(v0.2.7 教训重现);修复=①make-installer.sh 改 2 参 out-param 形式 + 测试断言 2 参正态/1 参负态;②test.yml Windows job 新增 iscc compile gate(Test 阶段即编译 .iss,heredoc 反引号/shellcheck/icon.ico 占位/AnsiString var 参全修);合并 ca367ed) ✅
-> - GUI file-browser scroll + root collapse fix (#733 宿主 rants 2026-08-13T12:46/12:47:①`.result-files` 只有 overflow-y:auto 没有 flex:1/min-height:0 → flex 子项高度随内容增长永不压缩进 #result-panel 容器,overflow 永不触发,内容被 overflow:hidden 裁掉(有滚动条槽但滚不动);修复=`.result-files` 加 flex:1 + min-height:0(与 .result-list 对齐);②file-tree.js render() 手写根目录行漏绑 click 事件(renderEntry 的普通目录行有 toggleDir,根目录永远展开收不起);修复=rootRow 补 addEventListener click → toggleDir(root, kids, ensure(root), 1)(展开态持久 + 图标切换与普通目录一致);renderer.smoke 测试 +28 行;合并 34942e1) ✅
-> - workspace-path repair per cycle (#734 宿主 rant 2026-08-13T13:13:20 跟进 #716:scheduler 只在启动时修复 stale emrg 条目(被删的 pytest-temp 目录泄漏进 projects.yml),长活 daemon 中途污染不自愈;修复=TaskHandler 每 cycle `if self._project_name == "emrg": self._ensure_project_entry()` 幂等重写正确路径(list_projects/GUI pickers 保持正确,无需重启);+3 测试;合并 1ea959c) ✅
-> - system prompt time + OS (#735 宿主 rant 2026-08-13T14:01:46:agent system prompt 增加当前时间 + 操作系统,避免使用错误的命令/路径分隔符——system.j2 在 Working directory 前渲染 **Current time**(tz-aware 本地 ISO 秒)+ **Operating system**(platform.system + platform.platform),Jinja2 条件门控;合并 4e8607a) ✅
-> - TUI status bar version (#736 宿主 rant 2026-08-13T14:11:03:TUI 状态栏左段显示 v<__version__>,无需 /version 也能看到运行版本——_format_status_left 提取 +5 测试;合并 e419875) ✅
-> - daemon list_history pagination (#737 宿主 rant 2026-08-13T14:15:12 后端:GUI 会话历史分页加载 limit/offset/has_more——user_messages 最旧在前,end=total-offset; start=max(0,end-limit) 正确返回最新在前分页 + has_more 标志;+4 测试;合并 d855ef6) ✅
-> - tests hermeticity guard (#738 外部贡献 pm25coder:pytest 全量跑会偶发写真实 `~/.emrg/projects.yml`/`tasks.yml`(e2e `_boot_server` 漏 patch scheduler config_dir → serve() 建真 TaskScheduler → `_ensure_self_evolution_task` 写真实 projects.yml;CI fresh runner 必触发)→ conftest autouse 守卫包装 scheduler+daemon 的 atomic_write_yaml 拒绝真实配置文件写入(失败测试点名肇事者)+ `_make_server` tmp `_projects_log` + `_tasks_file` 惰性解析(config_dir 补丁生效)+ 4 测试;Agent.md 773→777;合并 1378eb7) ✅
-> - GUI session history on-demand loading (#739 宿主 rant 2026-08-13T14:15:12 前端:chat.js + app.js 消费 #737 分页接口按需加载会话历史(加载更多按钮/滚动触发),i18n + CSS;+3 renderer.smoke(107→110)GUI 229→232;合并 0cc5b8f) ✅
-> - GUI sidebar navigation framework (#743 宿主 rant 2026-08-13T14:10:14 P1:侧边栏 activity-bar 式 5 入口导航(会话/项目/任务/Rant/设置)——.side-nav + .side-panel 占位框架(不遮聊天区,纯增量:默认全部隐藏、会话列表常驻);app.js SIDE_PANELS + switchPanel(点同项关闭/点其他切换/高亮 active);i18n zh/en 12 键;+1 renderer.smoke(GUI 232→233);P2-P5 逐面板填充,P6 移除老弹窗;合并 05c2053) ✅
-> - GUI settings panel 6 tabs + tasks panel (#746 宿主 rant 2026-08-13T14:10:14 P2+P3:#743 续——`#settings-dialog` 删除改 `#panel-settings` 内 6 tab(模型服务/工作目录/GitHub/外观/语言/关于,`switchSettingsTab` SETTINGS_TABS 白名单 + .hidden/.active 切换,非法 tab 名忽略;`settings-cancel`=关面板);任务管理从设置对话框迁出 + `#tasks-dialog` 删除 → `#panel-tasks`(`/trigger` 无参数改开任务面板,`Dialogs.loadTaskMeta/renderTaskList` 共享复用,错误改 Chat.addSystemMessage);nav 点击 settings/tasks 打开时按需加载(loadEvolutionSummary+showSettings / openTasksPanel,同项点击关闭不重复加载);i18n 键全部复用无新键;+1 renderer.smoke(P2 tab 切换正反两态)GUI 233→234;合并 09b31dc) ✅
-> - GUI projects panel (#747 宿主 rant 2026-08-13T14:10:14 P5:#746 续——侧边栏项目面板 `#panel-projects`:项目列表(auto_evolve 徽标 + 最近活跃提示 + 查看会话/删除按钮);`showProjectSessionsInPanel` 内嵌项目会话列表(点击切换会话,复用既有 switchSession IPC);删除项目=受保护守卫(emrg/emrg-task 系统项目不可删)+ 确认弹窗 + removeProject 刷新列表;i18n zh/en 新增 projects.* 12 键(hint/add/empty/added/addFailed/sessions/autoEvolve/viewSessions/noSessions/sessionsOf/back/current);+1 renderer.smoke(renderer 112→113)GUI 234→235;合并 f5eeadd) ✅
-> - GUI rant panel + list_rants daemon 命令 (#750 宿主 rant 2026-08-13T14:10:14 P4:#747 续——侧边栏 Rant 面板占位→功能面板;daemon 新增 `list_rants` 命令(读 ~/.emrg/rants.jsonl,可选 status 筛选 pending/in_progress/completed/空=全部,时间倒序,损坏行跳过,文件缺失→空列表不崩,响应帧 rants_list);GUI 4 状态筛选 tab(全部/待处理/进行中/已完成)+ 列表行(时间戳+状态徽标+项目+进度摘要)+ 点击展开详情(完整内容+进度)+ 新建 Rant 表单(项目下拉 + 内容 textarea → sendRant,成功 toast+刷新);IPC 链 main.js emrg:listRants + preload listRants + RESPONSE_TYPES list_rants→rants_list;i18n zh/en rants.* 19 键(含 data-i18n-placeholder 过 Stage-3 中文串守卫);+2 pytest(777→779 筛选/倒序/损坏跳过/缺文件空)+1 renderer.smoke(renderer 113→114)GUI 235→236;合并 1f4fa57) ✅
-> - TUI status bar full session id (#752 宿主 rant 2026-08-13T16:14:12:会话有标题时状态栏左段显示完整 sid(此前截断 8 字符,与无标题形态显示完整 id 不一致)——_format_status_left 一行改动 `sid[:8]`→`sid`,测试重命名 test_sid_full_in_title_form 断言完整 id;合并 03181fc) ✅
-> - GUI redesign P6 — remove legacy dialogs (#753 宿主 rant 2026-08-13T14:10:14 P6 收官:#743 续——移除 `#sessions-dialog` 与 `#rant-dialog` 两个遗留对话框;`/sessions`/`/resume` 无参数改开 `Dialogs.showOpenSessionDialog()`(两步现代弹窗),`/rant` 无参数改开 Rant 面板 + `Dialogs.openRantForm()`(#750 新建表单复用);删除 showSessionsDialog/showRantDialog 及 bindUi close/submit 处理器;测试原位更新(app-commands 2 测试改新语义 + mock 补 setAttribute/removeAttribute,renderer.smoke ELEMENT_IDS 删 8 个废弃 id);GUI 236 计数不变;合并 dca0cc5) ✅
-> - i18n orphan-key cleanup (#755 外部贡献 pm25coder,#753 遗留收尾——#753 删除遗留对话框后 8 组 legacy i18n 键成为孤儿(sessions.title/desc、rant.title/desc/project/message/placeholder/submit,zh+en 各 8 = i18n.js -16 行;rant 面板 #750 用 rants.* 命名空间独占,grep 实证 0 命中);评审连环(R1398 ❌ 实证 rant.project/rant.submit 仍孤儿 → R1399 纠正并行周期错误 ✅ → R1401 nudge → R1402 作者 60edb96 修复 → 3 ✅ 合并);合并 d89811b) ✅
-> - Global cross-project session index (#756 宿主 rant 2026-08-13T16:42:22:`~/.emrg/sessions_index.json` 全局会话索引——session_id → session 目录映射(meta.json/history.jsonl/memory 按需读),任意会话可定位并读取其他项目的对话;sessions_index.py 新模块(upsert/remove/rebuild + 原子写 tmp+os.replace + 损坏容忍 + 启动扫描回填注册项目与 ~/.emrg 未注册项目,剪枝 install/.git/node_modules 加速遍历);Session._save_meta_with_title upsert + Session.delete remove(create/append/compact/rename/clear 全漏斗)+ 幂等(路径不变跳过重写);daemon _build_system_prompt 注入 config_dir + serve() 启动重建 + system.j2 文档化;7 files +443/-1,+20 测试 779→799;合并 6da1592) ✅
-> - sessions_index stale-dead-path prune (#757 外部贡献 pm25coder,#756 非阻塞评审注记跟进——sessions_index 重建时剪除指向已删除目录的陈旧条目,防索引膨胀指向死路径;+48/-3(sessions_index.py prune 循环 + 测试),Agent.md 799→800;合并 702dea2) ✅
-> - Release v0.2.31 (#758 宿主 rant 2026-08-13T17:17:09:master 自 v0.2.30 (f5d7f47) 以来 26 commits / 26 PRs(#731-#758,#732/#740 未合并),宿主指示发布 v0.2.31;版本号 0.2.30→0.2.31 同步 7 files / 8 refs(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json、gui/package-lock.json×2、build-runtime.sh、make-installer.sh);pytest 800 全绿;Build Release v0.2.31 成功(31686486841,**首次尝试即全过**——#722/#723/#731/#725 教训落地后 4 平台 + release job 一次通过,含 macOS 签名/公证),7 assets(含 Windows zip),latest=v0.2.31,发布 09:31:49Z;合并 11b4a6e(3 周期 LGTM);What's new=GUI 侧边栏重构 P1-P6 #743/#746/#747/#750/#753 + 文件树滚动/根折叠修复 #733 + 会话历史按需加载 #739 + list_history 分页 #737 + 测试隔离守卫 #738 + 系统提示时间/OS #735 + TUI 状态栏版本 #736 + 完整 sid #752 + workspace 路径逐周期修复 #734 + i18n 清理 #755 + 跨项目会话索引 #756/#757 + quick-ref ×8) ✅
-> - open-source task rant-driven development (#760 宿主 rant 2026-08-13T18:35:09:open-source 类型任务(open_source_prompt.md)此前完全不读 ~/.emrg/rants.jsonl,aitokenpool 等仓库无法用 rant 驱动开发;改造=新增 0.5 Rant scan 节(读 rants.jsonl → 筛选 project == config.project 且 pending/in_progress → git log 去重——commit 引用只算"触及"不算完成)、State Assessment 决策 rant 优先(未处理 rant → Phase Contribution 最高优先级)、Phase B 新增 B.1b Rant-driven mode(rant 是宿主开发指令优先于 issue;处理前标 in_progress 写 progress;一个验收项一个 PR;完成 = 全部 PR merged + 自验证通过;宿主新 rant 指出不充分 → 恢复 in_progress)、状态管理表/语言政策/Reflection Q3 记录 PR↔rant 关联;+1 模板渲染测试 800→801;合并 6584cba) ✅
-> - GUI layout v0.2 — panels become workspace views (#762 宿主 rant 2026-08-13T18:55:09 否决 v0.1"侧边栏内展开窄面板"(264px 侧边栏只剩 ~220px 可用,设置 6 tab/任务 CRUD/项目列表挤成窄条):v0.2 导航点击 → 右侧工作区整块切换视图,与会话切换完全同机制(DOM 显隐 .active 互斥 + 状态保留);#chat-view → #workspace(会话视图 + 面板视图公共父容器),4 面板(projects/tasks/rants/settings)从 #sidebar 移入 #workspace(.side-panel → .workspace-view、data-panel-body → data-view),#panel-sessions 删除(💬 = 激活当前会话视图);switchPanel → switchView(VIEWS)、state.activePanel → state.activeView;面板视图激活 → 隐藏 composer/empty-state/result-panel/resizer(+ closePreview),会话视图恢复;activateSessionView 互斥清全部面板视图 + 导航高亮;点当前激活导航 → 关闭回会话视图;术语统一(App Shell/Sidebar/Nav/Workspace/Workspace View/Session View,docs/gui-redesign.md v0.2);GUI 236 测试 + pytest 801 绿;合并 d664ada) ✅
-> - GUI scroll capture fix (#764 #634 回归:滚动容器下移到 .session-view 后 #workspace(overflow:hidden)自身不滚动,原生 scroll 事件**不冒泡** → 挂在 #workspace 上的两个 bubble-phase 监听从不触发:back-to-bottom 按钮真实 GUI 永不出现(测试直接 dispatch wrapper 掩盖)、滚动到顶加载更早历史失效;修复=两个监听改 `capture:true`(捕获相可达子元素)+ `activeScrollEl()`/`updateBackToBottomState()` 从激活 .session-view 读滚动指标 + back-to-bottom 点击滚动该容器;activateSessionView 仅**新建**容器滚底(既有容器保留滚动位置——浏览器 tab 语义,面板往返/会话切换不跳底,rant 18:55:09 验收"滚动位置保留");setWorkspaceChrome 面板视图隐藏 back-to-bottom 返回按位置恢复;+1 renderer.smoke 回归(GUI 236→237);合并 f46b141) ✅
-> - Release v0.2.32 (#766 宿主 rant 2026-08-13T19:44:40:master 自 v0.2.31 (11b4a6e) 以来 7 commits / 7 PRs(#759-#765,#760/#761/#762/#763/#764/#765 功能 + #759 quick-ref),宿主指示发布 v0.2.32;版本号 0.2.31→0.2.32 同步 7 files / 8 refs(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json、gui/package-lock.json×2、build-runtime.sh、make-installer.sh),grep 0.2.31 仅历史;pytest 801 全绿;Build Release v0.2.32 成功(31697356494,**连续第 2 次首次尝试全过**——#722/#723/#731/#725 教训持续生效),7 assets(含 Windows zip),latest=v0.2.32,发布 12:01:16Z;合并 2750768(3 周期 LGTM);What's new=GUI 布局 v0.2 工作区视图 #762 + 滚动捕获修复 #764 + 清理 #763 + open-source rant 驱动 #760 + quick-ref ×2) ✅
-> - Release v0.2.33 (#770 宿主 rant 2026-08-13T21:25:05:master 自 v0.2.32 (2750768) 以来 4 commits / 4 PRs(#767 quick-ref v0.2.32 + #768 GUI 会话头 + #769 文件浏览器 chevron + #770 bump),宿主指示发布 v0.2.33;版本号 0.2.32→0.2.33 同步 7 files / 8 refs(emrg/__init__.py、pyproject.toml、uv.lock、gui/package.json、gui/package-lock.json×2、build-runtime.sh、make-installer.sh),grep 0.2.32 仅历史;pytest 801 全绿;Build Release v0.2.33 成功(31705462590,**连续第 3 次首次尝试全过**——#722/#723/#731/#725 教训持续生效),7 assets(含 Windows zip),latest=v0.2.33,发布 13:40:34Z;合并 44b09d8(3 周期 LGTM);What's new=GUI 会话头 + 会话列表名刷新 + 结果列表窗修复 #768 + 文件浏览器 chevron 指示 + 树滚动修复 #769 + quick-ref #767) ✅
-> - GUI chat visual optimization (#771 宿主 rant 2026-08-13T21:28:49:对齐/滚动/工具耗时/紧凑行/连续工具分组——.msg.user margin-left:auto 对齐修复(flex auto-margin 胜 align-self)、.session-view 去 scroll-behavior:smooth(JS scrollTop=scrollHeight 即时)、.tool-time 成功耗时(row.dataset.elapsed 供组求和)、行间距 24→12/内边距 4→2/字号 13→12/spinner 14→12、Plan-A 连续工具合并组(last-child 吸收已完成 .tool-row 成 .tool-group + ⌄ N 个工具执行 · Ts 摘要 + 点击展开 user-expanded 持久 + 运行行保持展开 + 文本穿插独立行)+ 独立 tool-group.test.js +2(GUI 239→241);评审过程=❌ 检出 7 个孤儿 i18n keys(rants.title/col* + projects.title)+ 12 个未用 CSS 类(.workspace-view-title/.rant-*/.task-badge.badge-*——并行 rant/projects 面板重构误带死代码,renderRantList 用 .task-row 从未引用)→ 作者修 d84de1e 纯删除(−99 行零新增)→ post-fix 3 周期 ✅(14:03:44Z 起重启链)→ 合并 f60eec0(14:10:25Z);post-merge Test CI PASS(31708754550)) ✅
-> - TUI status bar authoritative context message count (#772 宿主 rant 2026-08-13T21:52:18:状态栏 `· N msgs ·` 此前客户端本地 `msg_count += 1` 近似,auto-compact 重建消息后计数漂移;修复=daemon.py 两个最终 done 帧(Case 1 loop-exit + Case 3 max-tokens)均携带 `context_messages: len(messages)`(当前 LLM 上下文权威大小:system+history+user+tool results+assistant replies,auto-compact 重建后正确重导出);app.py done handler `int(context_messages)` 优先、缺失时回退 +1(向后兼容旧 daemon);e2e 单轮工具流断言 == 5(system+user+assistant-tool_calls+tool-result+final assistant);合并 66ab9a0;post-merge Test CI PASS(31709343733)) ✅
-> - GUI settings panel title + dead settings-btn removal (#773 宿主 rant 2026-08-13T21:49:51:设置面板缺标题(Rant/项目/任务面板样式对齐)+ 侧边栏底部 settings-btn 与导航 ⚙ 重复入口;修复=index.html panel-settings 加 `

`(layout.css 补 .workspace-view-title 定义——此前并行面板标题引用但全库无此 CSS)、sidebar-footer 删 settings-btn(保留 status-dot)、app.js settings-btn 绑定删除(导航 switchView("settings") 路径已含 loadEvolutionSummary+showSettings,功能保留)、i18n.js 删 sidebar.settings 孤儿键(zh+en,settings.title 两语言已存在);+1 renderer.smoke 判别测试(title 存在/footer 无 btn 有 dot/app.js 无绑定/i18n 无孤儿键,GUI 241→242);合并 2d9d7d6;post-merge Test CI PASS(31709827480)) ✅ -> - GUI i18n orphan/missing-key guard (#776 自发现:#771 review ❌ 检出 7 个孤儿 i18n keys——#755 清理类无防回归护栏;修复=i18n.test.js 双向守卫——(A) 无孤儿字典键(字典每个 key 被 JS 代码/index.html data-i18n 引用)、(B) 无缺失引用键(代码引用的 key 在字典中);处理形态=字面 t 调用(_t/I18N.t/EMRG_I18N.t/t)、三元 span(_t(cond ? "A" : "B"))、模板 glob(按 base 段归一 tool.*.doing 匹配)、registry 属性值(hint/title/key/label/placeholder/text/msg)、camelCase 段(projects.autoEvolve);同时删 15 个死键(result.title/settings.groupTasks/settings.githubTokenEmpty/tasks.title/tasks.desc/panel.openFailed/panel.copied/app.helpNoSessions/app.historyLoading/app.globalAll/app.noTasks/sidebar.noOpenSessions/projects.sessions/composer.modeAsk/composer.modeAuto,zh+en 各 15 = i18n.js −30 行);+1 测试 GUI 242→243、Agent.md 同步;合并 c54280e) ✅ -> - GUI workspace panel titles + Rant 5-column list + i18n.apply control-preserving fix (#778 宿主 rants 2026-08-13T21:36:01/21:38:25/21:46:53:①Rant 面板=`.workspace-view-title` 标题 + `.rant-head` 5 列头(时间/项目/状态/进度/内容)+ 行同宽类对齐 + 状态徽标三态配色(badge-done 绿/badge-warn 琥珀/badge-muted 灰)+ 点击展开详情(meta 行 + 完整 message 经 window.emrgMarkdown.renderMarkdown 渲染 md,DOMPurify 同源,fallback textContent)+ 内容列摘要去 md 标题/列表标记;②项目面板=标题 + 删顶部 hint;③任务面板=标题 + **i18n.apply 根因修复**——旧实现整体 `node.textContent = t(key)` 清空含控件 label(``)子元素 → 「添加任务/自定义类型」点击无响应;改为只替换首个文本节点(`first.nodeValue = text`,无文本节点时回退 textContent);④孤儿键 rants.detail/projects.hint 删除、tasks.title 复用(#776 删后本 PR 重新引用);i18n 新增 rants.title/colTime/colProject/colStatus/colProgress/colContent + projects.title(zh/en);+1 renderer.smoke(GUI 243→244,含真实 marked 注入断言 h2/strong/code + 源码级 i18n.apply 断言);合并 b970031;post-merge Test CI PASS(31735360625)) ✅ - -> - TUI clear terminal residue on width shrink (#781 宿主 rant 2026-08-14T11:47:11:终端宽度缩小后残留字符未清——TUI 渲染在宽度收缩时清理行尾残留(clear to EOL on width shrink);合并 8af06ba) ✅ -> - GUI open-sessions sidebar cross-project session title (#782 宿主 rant 2026-08-14T12:01:44:打开会话侧边栏跨项目会话显示标题——openSessions 列表用会话标题而非占位;合并 f39763d) ✅ -> - README Running the TUI section (#783/#785/#786 宿主 rants 2026-08-14T12:04/12:34/12:50:README 新增 Running the TUI 启动段(one-line Run instruction),随后去 From source 提及、重写为单行 Run 指令;合并 9a2e5c5/2e9cdc2/2a23dae) ✅ -> - open-source task allow_self_merge (#787 宿主 rant 2026-08-14T12:47:25:open-source 任务新增 allow_self_merge 配置项——允许任务自行合并自己的 PR(此前必须等外部 LGTM);合并 aca973e) ✅ -> - GUI task form empty dropdown fix (#789 宿主 rant 2026-08-14T15:41:52:快速添加任务时表单下拉为空——类型/项目下拉未填充(quick add empty dropdowns);修复数据加载时序;合并 4f0d69f) ✅ -> - open_source_prompt full-code study (#790 宿主 rant 2026-08-14T15:53:39:open-source 任务贡献前必须完整阅读项目代码(full-code study before contributing)——open_source_prompt.md 增加全量代码研读要求;合并 b2c2db9) ✅ -> - loopback daemon proxy=None (#792 自发现:daemon 回环连接被代理拦截——loopback WebSocket 连接强制 proxy=None(httpx 环境代理误配时回环连接走代理失败);合并 1c1d66a) ✅ -> - GUI task save type-field collision fix (#793 宿主反馈:保存任务无响应——GUI 任务表单 type 字段与表单对象属性冲突(wire type field collision)导致保存数据丢失;合并 70d2209) ✅ -> - promote task learn latest state (#795 promote 任务升级前必须先学习项目最新状态——promote 前读取项目最新 README/代码避免基于过期认知推广;合并 36e72d4) ✅ -> - bash heredoc stdin redirect on Windows (#797 bash 工具 Windows heredoc 支持——translate bash heredocs to stdin redirects(Windows cmd 无 heredoc,自动转 stdin 重定向);合并 f978290) ✅ -> - promote task de-hardening (#798 宿主 rant 2026-08-15T08:40:25:promote 任务去硬化——homework-first 参与、披露默认 OFF(disclosure default OFF,不强制公开);合并 41b775f) ✅ -> - promote task host-authorized registration + blog publishing (#799 宿主 rants 2026-08-15T09:04/09:06:promote 任务宿主授权账号注册 + 博客发布(host-authorized account registration + blog publishing);合并 73a6d9d) ✅ -> - promote task mention-density window (#800 promote 任务定义 mention-density 统计窗口——明确计数的会话窗口范围;合并 e8d0912) ✅ -> - GUI task template prompt editor Monaco (#801 GUI 任务模板提示词编辑器——Monaco editor(vendor、markdown、只读内置模板视图);合并 2fa8261) ✅ -> - GUI panel action toast + Trigger semantics (#802 宿主 rants 2026-08-15T09:20/09:23:GUI 面板操作反馈全局 toast + Trigger 运行态语义(running-state 时 Trigger 显示执行中状态);合并 b370909) ✅ -> - GUI task status + next-run countdown (#804 宿主 rant 2026-08-15T10:36:39:GUI 任务列表显示任务状态 + 下次运行倒计时;合并 bb0fe0a) ✅ -> - Monaco AMD define hijacking fix (#805 宿主 rant 2026-08-15T10:48:58:Monaco AMD define 劫持 UMD marked——markdown 降级纯文本;修复 AMD define 拦截 UMD 模块加载;合并 a65a2a8) ✅ -> - GUI rant detail markdown preprocessing + click-to-collapse (#806 宿主 rant 2026-08-15T10:41:43:Rant 详情 markdown 预处理 + 点击折叠(click-to-collapse);合并 1a5be40) ✅ -> - server prompts Chinese-to-English translation (#807 宿主 rant 2026-08-15T10:44:58:服务端提示词剩余中文翻译为英文——server prompts 全英文化;合并 146adec) ✅ -> - emrg stop command (#808 emrg stop 命令——kill 全部 emrg 进程(daemon/TUI/GUI,统一停止入口);合并 820e033) ✅ -> - Release v0.2.34 (#780 宿主 rant 2026-08-14T09:18:37:master 自 v0.2.33 (44b09d8) 以来 5 commits / 5 PRs(#778 面板标题 + #779 quick-ref + #780 bump + #781 TUI 残留清理 + #782 跨项目会话标题),宿主指示发布 v0.2.34;版本号 0.2.33→0.2.34 同步 7 files / 8 refs;pytest 801 全绿;Build Release v0.2.34 成功(31760629911),7 assets(含 Windows zip),latest=v0.2.34;合并 dc85829(3 周期 LGTM);What's new=TUI 宽度收缩残留清理 #781 + GUI 跨项目会话标题 #782 + quick-ref #779) ✅ -> - Release v0.2.35 (#784 宿主 rant 2026-08-14T12:33:02:master 自 v0.2.34 (dc85829) 以来 4 commits / 4 PRs(#783 README Running TUI + #784 bump + #785 README 去 From source + #786 README 重写单行),宿主指示发布 v0.2.35;版本号 0.2.34→0.2.35 同步;pytest 801 全绿;Build Release v0.2.35 成功(31770607623),7 assets,latest=v0.2.35;合并 53feee6(3 周期 LGTM);What's new=README Running the TUI 三段式 #783/#785/#786 + allow_self_merge #787) ✅ -> - Release v0.2.36 (#788 宿主 rant 2026-08-14T13:02:40:master 自 v0.2.35 (53feee6) 以来 4 commits / 4 PRs(#787 allow_self_merge + #788 bump + #789 GUI 任务表单下拉 + #790 open_source 全码研读),宿主指示发布 v0.2.36;版本号 0.2.35→0.2.36 同步;pytest 801 全绿;Build Release v0.2.36 成功(31772177571),7 assets,latest=v0.2.36;合并 6f15c5a(3 周期 LGTM);What's new=allow_self_merge #787 + GUI 表单下拉修复 #789 + open_source 全码研读 #790) ✅ -> - Release v0.2.37 (#791 宿主 rant 2026-08-14T16:17:48:master 自 v0.2.36 (6f15c5a) 以来 3 commits / 3 PRs(#791 bump + #792 回环 proxy=None + #793 GUI 任务保存修复),宿主指示发布 v0.2.37;版本号 0.2.36→0.2.37 同步;pytest 801 全绿;Build Release v0.2.37 成功(31783977596),7 assets,latest=v0.2.37;合并 1e7d022(3 周期 LGTM);What's new=回环 proxy 修复 #792 + GUI 任务保存修复 #793) ✅ -> - Release v0.2.38 (#794 宿主 rant 2026-08-14T22:11:26:master 自 v0.2.37 (1e7d022) 以来 2 commits / 2 PRs(#794 bump + #795 promote 学习最新状态),宿主指示发布 v0.2.38;版本号 0.2.37→0.2.38 同步;pytest 801 全绿;Build Release v0.2.38 成功(31809036770),7 assets,latest=v0.2.38;合并 ae3e39b(3 周期 LGTM);What's new=promote 最新状态学习 #795) ✅ -> - Release v0.2.39 (#796 宿主 rant 2026-08-14T23:08:39:master 自 v0.2.38 (ae3e39b) 以来 7 commits / 7 PRs(#797 Windows heredoc + #798 promote 去硬化 + #799 promote 注册/发布 + #800 mention 窗口 + #801 GUI Monaco 模板编辑 + #802 toast + #796 bump),宿主指示发布 v0.2.39;版本号 0.2.38→0.2.39 同步;pytest 801 全绿;Build Release v0.2.39 成功(31813675001),7 assets,latest=v0.2.39;合并 e33b604(3 周期 LGTM);What's new=Windows heredoc #797 + promote 系列 #798/#799/#800 + GUI Monaco 模板编辑 #801 + toast #802) ✅ -> - Release v0.2.40 (#803 宿主 rant 2026-08-15T10:07:18:master 自 v0.2.39 (e33b604) 以来 6 commits / 6 PRs(#803 bump + #804 GUI 任务状态/倒计时 + #805 Monaco AMD 修复 + #806 Rant 详情预处理 + #807 提示词英文化 + #808 emrg stop),宿主指示发布 v0.2.40;版本号 0.2.39→0.2.40 同步;pytest 801 全绿;Build Release v0.2.40 成功(31858856079),7 assets,latest=v0.2.40;合并 c550a54(3 周期 LGTM);What's new=GUI 任务状态 #804 + Monaco 修复 #805 + Rant 详情 #806 + 提示词英文 #807 + emrg stop #808) ✅ -> - Release v0.2.41 (#809 宿主 rant 2026-08-15T11:53:55:master 自 v0.2.40 (c550a54) 以来 8 commits / 8 PRs(#809 bump + #810 Linux .run 离线安装器 + #811 Windows stop 收敛 + #812 日志日期 + #813 vibe check + #814 submit_rant + #816 双兼容 rant 匹配 + #817 PS 花括号修复),宿主指示发布 v0.2.41;版本号 0.2.40→0.2.41 同步;pytest 869 全绿;Build Release v0.2.41 成功(31917625994),7 assets,latest=v0.2.41;合并 293fba6(3 周期 LGTM);What's new=Linux .run 安装器 #810 + Windows stop 收敛 #811 + 日志日期 #812 + vibe check #813 + submit_rant #814 + 双兼容 rant 匹配 #816 + PS 修复 #817) ✅ -> - Release v0.2.42 (#818 宿主 rant 2026-08-17T10:57:58:master 自 v0.2.41 (293fba6) 以来 7 commits / 7 PRs(#810-#817 全为 v0.2.41 后新特性 + #818 bump),宿主指示发布 v0.2.42(首发含 Linux .run 离线安装器 + Windows stop 收敛);版本号 0.2.41→0.2.42 同步 8 files / 9 refs(含新 make-run-installer.sh 第 9 处,test_version_sync 抓出);pytest 869 收集(868 过 + 1 跳);Build Release v0.2.42 成功(31997742618),9 assets(exe/zip/pkg/.run 双架构/AppImage 双架构/tar.gz 双架构),latest=v0.2.42;合并 adeaa46(3 周期 LGTM:560/561/562);What's new=Linux .run 自解压离线安装器 #810 + Windows stop 收敛 #811 + 日志日期 #812 + agent vibe check #813 + submit_rant 工具 #814 + 双兼容 rant 匹配 #816 + PS 花括号修复 #817) ✅ +> 2. Handled rants need no further attention, unless the user repeats the feedback (meaning the earlier fix was incomplete) #### 2.2 Latest GitHub code changes ```bash @@ -628,4 +396,5 @@ Create a **cycle memory entry** (rant 2026-08-12T18:03:26 — no more standalone - Do not modify `~/.emrg/config.toml` - Do not modify `max_tool_rounds` - Do not modify files under `{{ evolution_cwd }}` outside `{{ source_dir }}/` +- **Do not modify this file (`evolution_prompt.md`) during normal evolution** — it is a **stable template** (host rant 2026-08-17T14:22:21). Routine evolution must not edit it, and must not append changelog/quick-reference history to it. The ONLY exception is when the evolution target itself is improving `evolution_prompt.md` (a prompt-specific rant like this one). "Was this feature already done?" is answered by the **memory system** (`.emrg/memory/` + MEMORY.md + `cycle-*.md` records) and `git log` — not by a static in-prompt history table. - Must push