diff --git a/Agent.md b/Agent.md index 2dcc25eb..ca621ba8 100644 --- a/Agent.md +++ b/Agent.md @@ -85,7 +85,7 @@ Usage: say "tool loop" for the whole process, "round N" for a single LLM request - Streaming chat with delta rendering (16ms batching), markdown on done (marked + DOMPurify + local highlight.js subset), tool call status cards (2000-char truncation + expand) - Session list/switch/new/delete + right-click rename (context menu, #423) synced with daemon; own-stream busy lock (G65); broadcast streams from other clients tagged "来自其他客户端" - Disconnect/reconnect: red status dot, auto daemon respawn (stale-port detection), session resume, input bar restored on disconnect (no 30s fake-timeout) - - Unit tests `npm test` (260: 45 daemon_client + 19 conn-manager + 22 app-commands + 131 renderer smoke + 16 i18n + 7 integration + 3 commands + 8 build-config + 7 gui-state + 2 tool-group); RESPONSE_TYPES mirror daemon protocol verified against `daemon.py` + - Unit tests `npm test` (254: 45 daemon_client + 19 conn-manager + 22 app-commands + 126 renderer smoke + 15 i18n + 7 integration + 3 commands + 8 build-config + 7 gui-state + 2 tool-group); RESPONSE_TYPES mirror daemon protocol verified against `daemon.py` - **Scheduled tasks** — Task generalization + CRUD (rant 2026-08-12T18:23:15, #709/#710/#711) - Task handler generalized: `TaskHandler` (renamed from `EvolutionHandler`), repo-configured self-heal for any project, template lookup builtin → `~/.emrg/task-templates/.md` → fallback - Daemon commands: `task_create/update/delete` + `task_template_create/list/update/delete` (tasks stored in `~/.emrg/tasks.yml`, custom type templates in `~/.emrg/task-templates/`) @@ -119,7 +119,7 @@ pkill -f "emrg.server"; rm -f ~/.emrg/emrgd.token; python -m emrg ``` Python: `uv run pytest tests/ -v` (985) — import check: `uv run python -c "from emrg.client.app import run_client"` -GUI: `cd emrg/gui && npm test` (260: 45 daemon_client + 19 conn-manager + 22 app-commands + 131 renderer smoke + 16 i18n + 7 integration + 3 commands + 8 build-config + 7 gui-state + 2 tool-group) — syntax: `node --check main.js preload.js daemon_client.js renderer/js/*.js` +GUI: `cd emrg/gui && npm test` (254: 45 daemon_client + 19 conn-manager + 22 app-commands + 126 renderer smoke + 15 i18n + 7 integration + 3 commands + 8 build-config + 7 gui-state + 2 tool-group) — syntax: `node --check main.js preload.js daemon_client.js renderer/js/*.js` CI: `uv run pytest` (ubuntu + **windows-2025 matrix** — Windows pytest 回归在 PR CI 即失败,v0.2.29 教训 #725) + GUI tests + **actionlint workflow lint** (`rhysd/actionlint@v1.7.12` gate, #444 — workflow 解析错误在 PR CI 即失败,如 `if:` secrets 上下文) Re-trigger: `scripts/re-trigger-ci.sh [branch]` (workflow_dispatch, #527 — 替代空 commit 重触发:Actions outage 会整段丢弃 push 事件,dispatch 走 API 路径不受影响) diff --git a/emrg/gui/test/integration.test.js b/emrg/gui/test/integration.test.js index 404990ce..8157c26c 100644 --- a/emrg/gui/test/integration.test.js +++ b/emrg/gui/test/integration.test.js @@ -21,12 +21,43 @@ const os = require("node:os"); const path = require("node:path"); const { spawn } = require("node:child_process"); -const SKIP = !!process.env.EMRG_SKIP_INTEGRATION; -if (SKIP) { - skip("EMRG_SKIP_INTEGRATION=1 — 集成测试跳过(本地运行)"); +const { DaemonClient, generateSessionId, TOKEN_FILE, EMRGD_PORT } = require("../daemon_client.js"); + +// #861 (rant 2026-08-19T08:05:21) made the daemon bind a FIXED loopback port +// (56031) as its single-instance admission; #884 (rant 2026-08-20T14:32:52) +// moved the auth credential to emrgd.token (port no longer carried in any +// file). This suite spawns its OWN isolated daemon (HOME→tmp) — on any host +// where the real daemon is already running (the normal dev machine state, +// "the server is the living core"), the isolated daemon cannot bind 56031 +// (EADDRINUSE) and exits → no token file → every test times out with +// "daemon token file timeout". CI stays green only because runners have no +// live daemon. Fix: probe the fixed port at module load and skip the whole +// suite (like EMRG_SKIP_INTEGRATION) when a live daemon already owns it — +// the isolated-daemon premise is impossible in that state. CI (daemon-free +// runners) still runs the full suite. +function liveDaemonOnFixedPort() { + try { + require("node:child_process").execSync( + `node -e "const s=require('node:net').connect(${EMRGD_PORT},'127.0.0.1');` + + `s.on('connect',()=>process.exit(0));s.on('error',()=>process.exit(1));` + + `setTimeout(()=>process.exit(1),1000)"`, + { stdio: "ignore", timeout: 2000 } + ); + return true; + } catch { + return false; + } } -const { DaemonClient, generateSessionId, TOKEN_FILE } = require("../daemon_client.js"); +const SKIP = !!process.env.EMRG_SKIP_INTEGRATION || liveDaemonOnFixedPort(); +if (SKIP) { + skip( + process.env.EMRG_SKIP_INTEGRATION + ? "EMRG_SKIP_INTEGRATION=1 — 集成测试跳过(本地运行)" + : `fixed-port admission: a live daemon owns 127.0.0.1:${EMRGD_PORT} — ` + + "integration tests need an isolated daemon (CI runs them on daemon-free runners)" + ); +} // ── 环境 ───────────────────────────────────────────────── const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "emrg-gui-integ-")); @@ -93,7 +124,9 @@ function spawnDaemon() { before(async () => { // ⚠️ EMRG_SKIP_INTEGRATION 时 skip() 只跳过测试体,before() 仍执行—— // 必须显式短路,否则 Windows CI 单测步骤会 spawn daemon 超时(daemon port file timeout) - if (process.env.EMRG_SKIP_INTEGRATION) return; + // #861/#884 后同样的短路也适用于 live-daemon 自动跳过(固定端口已被真实 daemon 占用时 + // 隔离 daemon 无法启动,waitForPortFile 必超时——见文件头注释)。 + if (SKIP) return; daemonProc = spawnDaemon(); await waitForPortFile(); client = new DaemonClient({ });