diff --git a/emrg/server/evolution_prompt.md b/emrg/server/evolution_prompt.md index 0f207337..fa6539a4 100644 --- a/emrg/server/evolution_prompt.md +++ b/emrg/server/evolution_prompt.md @@ -368,6 +368,7 @@ When reading rants, follow these rules: > - 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 计数同步) ✅ #### 2.2 Latest GitHub code changes