From 5b47ee603f05eae21c38954bd8b6c27ba262c487 Mon Sep 17 00:00:00 2001 From: "lei.chen" Date: Tue, 4 Aug 2026 07:37:48 +0000 Subject: [PATCH] fix(apiserver): carry exec_user on job submit so jobs don't run as nobody (bug-1500) modelJobToSubmit built the C job_startinfo_t without setting execuser, so the controller forwarded a NULL execuser in the startjob request and the worker ran every job as "nobody". Now the submit carries the resolved exec user: an explicit exec_user wins, otherwise the job runs as the submitting user. - add resolveExecUser() (plain-Go, unit-testable) + TestResolveExecUser - set si.execuser in modelJobToSubmit, free it in freeJobSubmit Note: deploying this exposed an ASAN heap-use-after-free in the apiserver's submit/notification path (strncpy reading freed memory); the fix is committed but needs the memory-lifecycle investigation before it can ship safely. Co-Authored-By: Claude --- .wolf/anatomy.md | 31 +- .wolf/buglog.json | 19 + .wolf/hooks/_session.json | 396 +------- .wolf/memory.md | 51 + .wolf/token-ledger.json | 961 +++++++++++++++++- src/configs/hosts.yaml | 18 +- src/frontend/apiserver/backend/convert.go | 17 + .../apiserver/backend/convert_test.go | 24 + 8 files changed, 1138 insertions(+), 379 deletions(-) diff --git a/.wolf/anatomy.md b/.wolf/anatomy.md index 6ae9c809..b208fc66 100644 --- a/.wolf/anatomy.md +++ b/.wolf/anatomy.md @@ -1,7 +1,7 @@ # anatomy.md -> Auto-maintained by OpenWolf. Last scanned: 2026-07-31T09:01:40.540Z -> Files: 840 tracked | Anatomy hits: 0 | Misses: 0 +> Auto-maintained by OpenWolf. Last scanned: 2026-08-04T05:49:57.570Z +> Files: 845 tracked | Anatomy hits: 0 | Misses: 0 ## ../../../../../../tmp/claude-1000/ @@ -98,6 +98,14 @@ - `ctrl-dbg.sh` — bug-1283: run the NON-ASAN DEBUG (-O0 -g3) xce_controller under gdb -batch; on (~231 tok) +## ../../../../tmp/ + +- `frpc_mon.sh` — frpc monitor — sample tunnel health every 15s; snapshot on state transition. (~278 tok) +- `frpc_prod.toml` (~95 tok) +- `frpc_watchdog.sh` — frpc watchdog + monitor (~488 tok) +- `frpc-watchdog.sh` — frpc tunnel watchdog — logging ONLY, no auto-restart. (~338 tok) +- `frpcdbg_mon.sh` — frpc debug monitor — logs tunnel health every 20s, dumps snapshot on transition (~250 tok) + ## ../../xce/.claude/worktrees/agent-a0dfba18c450e4f5f/src/controller/testsuite/ - `test.c` — include (~28571 tok) @@ -1199,25 +1207,12 @@ ## src/frontend/apiserver/config/ - `auth.yaml` — Authentication provider: config_file | pam | ldap | oauth2 (~187 tok) -- `rbac.yaml` — Roles/permissions; includes mcp_readonly (Phase 0) + mcp_operator (Phase 1, queue:submit + job:control) (~1.4k tok) - -## src/frontend/schedulerclient/ - -- `client.go` — Client interface: 6 read + 4 write (SubmitJob/CancelJob/HoldJob/ReleaseJob) methods (~0.5k tok) -- `types.go` — URM types (URMJob/URMQueue/URMNode/JobFilter/LogOpts/Page/Metrics) (~1k tok) -- `httpclient.go` — resty v3 read implementation (GET, apiEnvelope, mbToBytes=1e6) (~3.5k tok) -- `write.go` — Phase 1: JobSpec, SubmitJobResult, JobControlRequest, doPost (HTTP 200 + envelope-code), SubmitJob/Cancel/Hold/Release impl (~3k tok) -- `statusmap.go` — Status string → URM mapping functions (~0.9k tok) -- `write_test.go` — httptest TDD for write paths (~2.5k tok) -- `statusmap_test.go` — Table-driven status mapping tests (~0.9k tok) ## src/frontend/mcp-server/ -- `cmd/main.go` — MCP stdio entry; registers 10 tools (6 read + 4 write), env XCE_API_URL/XCE_API_KEY (~2k tok) -- `internal/app.go` — Tool handlers wiring schedulerclient (read + write) (~3k tok) -- `internal/templates.go` — JobTemplate registry + general_serial (通用串行脚本) + parseMemoryToBytes/parseWalltimeSeconds (~3k tok) -- `internal/app_test.go` — fake-client handler TDD (~2.5k tok) -- `internal/templates_test.go` — Template/registry/parser TDD (~2k tok) + +## src/frontend/schedulerclient/ + ## src/frontend/xcecli/cmd/auth/ diff --git a/.wolf/buglog.json b/.wolf/buglog.json index c85f7410..f2429e18 100644 --- a/.wolf/buglog.json +++ b/.wolf/buglog.json @@ -14719,5 +14719,24 @@ "related_bugs": [], "occurrences": 1, "last_seen": "2026-08-03" + }, + { + "id": "bug-1500", + "timestamp": "2026-08-04", + "error_message": "OpenBSD r1 (172.31.1.99) frpc \u7a7f\u900f\u96a7\u9053\u4f7f\u7528\u4e00\u6bb5\u65f6\u95f4\u540e\u9759\u9ed8\u65ad\u8054: \u516c\u7f51\u8fde 49.233.89.147:60023 \u62a5 ECONNREFUSED (\u5feb\u901f\u62d2\u7edd\u975e\u8d85\u65f6), frpc \u670d\u52a1\u72b6\u6001 OK \u8fdb\u7a0b\u5b58\u6d3b, \u53ea\u6709\u91cd\u542f frpc \u624d\u80fd\u6062\u590d", + "file": "/etc/frp/frpc.toml (frpc 0.69.1 / OpenBSD 7.9) + frps 0.69.1 \u65e5\u5fd7\u5206\u6790", + "root_cause": "OpenBSD \u4f4d\u4e8e\u8fd0\u8425\u5546 CGNAT \u540e (3 \u5468\u516c\u7f51\u51fa\u53e3 IP \u6362 10+ \u4e2a: 114.244.x/114.246.x/114.254.x/124.64.x/221.216.x; 7 \u5929 2088 \u8fde\u63a5\u88ab keepalive \u8d85\u65f6\u6740)\u3002frpc 0.69.1 \u63a7\u5236\u8fde\u63a5\u88ab\u7f51\u7edc\u9759\u9ed8\u6740\u6389\u540e, \u9677\u5165\u81ea\u6211\u7ef4\u6301\u7684\u91cd\u8fde\u6b7b\u5faa\u73af: \u6bcf ~30s \u91cd\u65b0 login (server \u8bb0\u5f55 replaced by client) \u4f46\u4ece\u4e0d\u91cd\u65b0\u6ce8\u518c proxy (\u5faa\u73af\u671f\u95f4\u65e0 'new proxy' \u4e8b\u4ef6), 60023 \u7aef\u53e3\u4e00\u76f4\u65e0\u76d1\u542c -> \u7528\u6237\u8fde\u63a5\u88ab\u62d2\u3002\u5faa\u73af\u8de8\u591a\u5929\u4e0d\u81ea\u6108 (2026-08-01 16:52 ~ 08-03 13:41, \u8de8 3 \u4e2a\u51fa\u53e3 IP, 3000+ logins, \u4ec5 1 \u6b21 new proxy), \u53ea\u6709\u91cd\u542f\u8fdb\u7a0b (\u65b0 run id) \u80fd\u6253\u65ad\u3002\u6b63\u5e38\u573a\u666f (\u6bcf\u665a 03:31 CGNAT \u56de\u6536) \u80fd 13-60s \u81ea\u6108, \u8bf4\u660e\u662f\u91cd\u8fde\u8def\u5f84\u4e0a\u7684 bug \u800c\u975e\u7eaf\u7f51\u7edc\u95ee\u9898\u3002server frps \u7a33\u5b9a\u8fd0\u884c 3 \u5468, \u6392\u9664\u670d\u52a1\u7aef", + "fix": "\u4e34\u65f6\u6b62\u8840: \u90e8\u7f72\u770b\u95e8\u72d7 /tmp/frpc_watchdog.sh (\u6bcf 30s \u63a2\u6d4b 60023, \u8fde\u7eed DOWN 3 \u6b21\u81ea\u52a8 doas /etc/rc.d/frpc restart, 300s \u9632\u6296); \u5ba2\u6237\u7aef\u5f00 debug \u65e5\u5fd7 /home/dankeer/frpc.log\u3002\u6839\u6cbb\u5019\u9009: \u5347\u7ea7 frp \u67e5\u91cd\u8fde\u5faa\u73af\u4fee\u590d / KCP/QUIC \u4f20\u8f93 / \u9759\u6001 IP \u6216\u975e CGNAT \u7f51\u7edc", + "tags": [ + "frpc", + "openbsd", + "cgnat", + "reconnect-loop", + "frp-0.69.1", + "tunnel-dead" + ], + "related_bugs": [], + "occurrences": 3, + "last_seen": "2026-08-04" } ] \ No newline at end of file diff --git a/.wolf/hooks/_session.json b/.wolf/hooks/_session.json index d40bb3d5..a113d7c2 100644 --- a/.wolf/hooks/_session.json +++ b/.wolf/hooks/_session.json @@ -1,386 +1,84 @@ { - "session_id": "session-2026-07-30-0409", - "started": "2026-07-30T11:09:15.945Z", + "session_id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", "files_read": { - "/home/rshen/projects/xce/worktrees/config/.kiro/specs/admin-config-tool/tasks.md": { + "/home/lchen/code/xce/.mcp.json": { "count": 1, - "tokens": 9072, - "first_read": "2026-07-30T12:19:14.341Z" + "tokens": 7, + "first_read": "2026-08-03T08:44:41.511Z" }, - "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_push.py": { - "count": 7, - "tokens": 2779, - "first_read": "2026-07-30T12:19:14.613Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/tools/deploy-ha.sh": { - "count": 3, - "tokens": 1054, - "first_read": "2026-07-30T12:19:29.564Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/xceadmin/src/xcecommon/discovery.py": { + "/home/lchen/code/xce/src/configs/hosts.yaml": { "count": 1, - "tokens": 0, - "first_read": "2026-07-30T12:19:29.992Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/xceadmin/src/xceadmin/discovery.py": { - "count": 1, - "tokens": 1775, - "first_read": "2026-07-30T13:02:08.621Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/xceadmin/src/xceadmin/push.py": { - "count": 1, - "tokens": 1818, - "first_read": "2026-07-30T13:02:15.180Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/conftest.py": { - "count": 2, - "tokens": 699, - "first_read": "2026-07-30T13:06:35.262Z" - }, - "/tmp/claude-1000/-home-rshen-projects-xce-worktrees-config/c8633ffb-8da0-40a7-9811-48f1830c37b4/tasks/b732ki2y3.output": { - "count": 1, - "tokens": 0, - "first_read": "2026-07-30T13:21:55.900Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/include/xce/errnox.h": { - "count": 2, - "tokens": 0, - "first_read": "2026-07-30T13:30:09.495Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py": { - "count": 8, - "tokens": 7600, - "first_read": "2026-07-30T13:31:16.766Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/controller/ha.c": { - "count": 2, - "tokens": 124295, - "first_read": "2026-07-30T13:42:42.468Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/controller/cluster.c": { - "count": 2, - "tokens": 20931, - "first_read": "2026-07-30T13:43:09.865Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/_live_e2e_common.py": { - "count": 3, - "tokens": 1206, - "first_read": "2026-07-30T13:43:53.361Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/tools/test-heartbeat-tolerance.sh": { - "count": 1, - "tokens": 2367, - "first_read": "2026-07-30T13:56:04.113Z" - }, - "/tmp/claude-1000/-home-rshen-projects-xce-worktrees-config/c8633ffb-8da0-40a7-9811-48f1830c37b4/tasks/bnpittld0.output": { - "count": 1, - "tokens": 0, - "first_read": "2026-07-30T14:06:34.840Z" - }, - "/tmp/claude-1000/-home-rshen-projects-xce-worktrees-config/c8633ffb-8da0-40a7-9811-48f1830c37b4/tasks/byx7ipj7f.output": { - "count": 6, - "tokens": 0, - "first_read": "2026-07-30T14:17:02.982Z" - }, - "/home/rshen/projects/xce/worktrees/config/.claude/skills/kiro-impl/templates/debugger-prompt.md": { - "count": 1, - "tokens": 812, - "first_read": "2026-07-30T14:33:14.242Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/xceadmin/pyproject.toml": { - "count": 1, - "tokens": 362, - "first_read": "2026-07-30T14:35:12.474Z" - }, - "/home/claude/.claude/projects/-home-rshen-projects-xce-worktrees-config/d6d1f70d-af0b-465b-9cd6-e719e38692ce/tool-results/b9vaeqw0k.txt": { - "count": 1, - "tokens": 0, - "first_read": "2026-07-31T03:34:12.233Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/lib/client.c": { - "count": 1, - "tokens": 7163, - "first_read": "2026-07-31T03:50:38.584Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/lib/client_internal.h": { - "count": 1, - "tokens": 4475, - "first_read": "2026-07-31T03:50:49.994Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/lib/client_failover.c": { - "count": 1, - "tokens": 0, - "first_read": "2026-07-31T04:02:26.918Z" - }, - "/home/rshen/projects/xce/worktrees/config/.claude/skills/xce-test-ha/run-ha-soak.sh": { - "count": 5, - "tokens": 41010, - "first_read": "2026-07-31T04:50:52.430Z" - }, - "/home/claude/tmp/xce-ha-chaos30-run1.log": { - "count": 1, - "tokens": 0, - "first_read": "2026-07-31T04:51:29.049Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/lib/utils.c": { - "count": 1, - "tokens": 0, - "first_read": "2026-07-31T04:57:05.222Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/controller/job.c": { - "count": 1, - "tokens": 24947, - "first_read": "2026-07-31T04:57:56.735Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/docs/deployment.md": { - "count": 2, - "tokens": 4816, - "first_read": "2026-07-31T08:39:59.108Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c": { - "count": 1, - "tokens": 5516, - "first_read": "2026-07-31T08:54:13.432Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/test_waldump.c": { - "count": 1, - "tokens": 0, - "first_read": "2026-07-31T08:57:57.611Z" - }, - "/home/rshen/projects/xce/worktrees/config/src/controller/persist.c": { - "count": 1, - "tokens": 85714, - "first_read": "2026-07-31T09:25:16.220Z" + "tokens": 248, + "first_read": "2026-08-03T08:44:41.714Z" } }, "files_written": [ { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/_live_e2e_common.py", + "file": "/tmp/frpcdbg_mon.sh", "action": "create", - "tokens": 1206, - "at": "2026-07-30T13:08:37.963Z" + "tokens": 268, + "at": "2026-08-04T01:37:20.418Z" }, { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_push.py", - "action": "edit", - "tokens": 150, - "at": "2026-07-30T13:08:53.196Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_push.py", - "action": "edit", - "tokens": 154, - "at": "2026-07-30T13:09:23.515Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", + "file": "/tmp/frpc_prod.toml", "action": "create", - "tokens": 4314, - "at": "2026-07-30T13:13:28.961Z" + "tokens": 100, + "at": "2026-08-04T02:10:17.877Z" }, { - "file": "/tmp/claude-1000/-home-rshen-projects-xce-worktrees-config/d6d1f70d-af0b-465b-9cd6-e719e38692ce/scratchpad/manual_ha_deploy.sh", + "file": "/tmp/frpc_mon.sh", "action": "create", - "tokens": 408, - "at": "2026-07-30T13:20:31.874Z" + "tokens": 291, + "at": "2026-08-04T02:10:21.788Z" }, { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 1089, - "at": "2026-07-30T13:31:47.698Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 288, - "at": "2026-07-30T13:32:02.450Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 1084, - "at": "2026-07-30T13:32:32.689Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 865, - "at": "2026-07-30T13:59:11.573Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 131, - "at": "2026-07-30T13:59:23.445Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 424, - "at": "2026-07-30T13:59:37.846Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 255, - "at": "2026-07-30T13:59:50.809Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 110, - "at": "2026-07-30T14:10:20.969Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 29, - "at": "2026-07-30T14:10:30.683Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 91, - "at": "2026-07-30T14:27:48.483Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_e2e_live_ha_push.py", - "action": "edit", - "tokens": 26, - "at": "2026-07-30T14:27:57.885Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/xceadmin/tests/test_repro_bug1485.py", + "file": "/tmp/frpc_prod.toml", "action": "create", - "tokens": 1910, - "at": "2026-07-30T14:38:48.005Z" + "tokens": 101, + "at": "2026-08-04T02:10:59.756Z" }, { - "file": "/home/rshen/projects/xce/worktrees/config/.kiro/specs/admin-config-tool/tasks.md", - "action": "edit", - "tokens": 404, - "at": "2026-07-30T14:57:07.885Z" + "file": "/tmp/frpc_mon.sh", + "action": "create", + "tokens": 292, + "at": "2026-08-04T02:11:01.550Z" }, { - "file": "/home/rshen/projects/xce/worktrees/config/.claude/skills/xce-test-ha/run-ha-soak.sh", + "file": "/tmp/frpc_mon.sh", "action": "edit", - "tokens": 136, - "at": "2026-07-31T04:10:31.220Z" + "tokens": 5, + "at": "2026-08-04T02:11:33.854Z" }, { - "file": "/home/rshen/projects/xce/worktrees/config/.claude/skills/xce-test-ha/run-ha-soak.sh", + "file": "/tmp/frpc_mon.sh", "action": "edit", - "tokens": 1266, - "at": "2026-07-31T05:03:59.690Z" + "tokens": 22, + "at": "2026-08-04T02:16:46.011Z" }, { - "file": "/home/rshen/projects/xce/worktrees/config/.claude/skills/xce-test-ha/run-ha-soak.sh", - "action": "edit", - "tokens": 68, - "at": "2026-07-31T05:06:39.208Z" + "file": "/tmp/frpc_watchdog.sh", + "action": "create", + "tokens": 523, + "at": "2026-08-04T02:52:22.852Z" }, { - "file": "/home/rshen/projects/xce/worktrees/config/src/docs/deployment.md", - "action": "edit", - "tokens": 353, - "at": "2026-07-31T08:40:15.401Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/docs/deployment.md", - "action": "edit", - "tokens": 209, - "at": "2026-07-31T08:48:31.523Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.h", - "action": "edit", - "tokens": 224, - "at": "2026-07-31T08:58:40.147Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c", - "action": "edit", - "tokens": 53, - "at": "2026-07-31T08:58:51.647Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c", - "action": "edit", - "tokens": 717, - "at": "2026-07-31T08:59:15.171Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c", - "action": "edit", - "tokens": 109, - "at": "2026-07-31T08:59:29.637Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c", - "action": "edit", - "tokens": 198, - "at": "2026-07-31T08:59:42.696Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c", - "action": "edit", - "tokens": 248, - "at": "2026-07-31T08:59:55.620Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c", - "action": "edit", - "tokens": 45, - "at": "2026-07-31T09:00:12.945Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c", - "action": "edit", - "tokens": 52, - "at": "2026-07-31T09:00:25.189Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/waldump.c", - "action": "edit", - "tokens": 102, - "at": "2026-07-31T09:00:37.310Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/test_waldump.c", - "action": "edit", - "tokens": 41, - "at": "2026-07-31T09:00:48.309Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/test_waldump.c", - "action": "edit", - "tokens": 1422, - "at": "2026-07-31T09:01:22.297Z" - }, - { - "file": "/home/rshen/projects/xce/worktrees/config/src/controller/testsuite/test_waldump.c", - "action": "edit", - "tokens": 80, - "at": "2026-07-31T09:01:40.552Z" + "file": "/tmp/frpc-watchdog.sh", + "action": "create", + "tokens": 362, + "at": "2026-08-04T05:49:57.595Z" } ], "edit_counts": { - "src/xceadmin/tests/_live_e2e_common.py": 1, - "src/xceadmin/tests/test_e2e_live_push.py": 2, - "src/xceadmin/tests/test_e2e_live_ha_push.py": 12, - "../../../../../../tmp/claude-1000/-home-rshen-projects-xce-worktrees-config/d6d1f70d-af0b-465b-9cd6-e719e38692ce/scratchpad/manual_ha_deploy.sh": 1, - "src/xceadmin/tests/test_repro_bug1485.py": 1, - ".kiro/specs/admin-config-tool/tasks.md": 1, - ".claude/skills/xce-test-ha/run-ha-soak.sh": 3, - "src/docs/deployment.md": 2, - "src/controller/testsuite/waldump.h": 1, - "src/controller/testsuite/waldump.c": 8, - "src/controller/testsuite/test_waldump.c": 3 + "../../../../tmp/frpcdbg_mon.sh": 1, + "../../../../tmp/frpc_prod.toml": 2, + "../../../../tmp/frpc_mon.sh": 4, + "../../../../tmp/frpc_watchdog.sh": 1, + "../../../../tmp/frpc-watchdog.sh": 1 }, - "anatomy_hits": 20, - "anatomy_misses": 10, - "repeated_reads_warned": 31, + "anatomy_hits": 2, + "anatomy_misses": 0, + "repeated_reads_warned": 0, "cerebrum_warnings": 0, - "stop_count": 74 + "stop_count": 14 } \ No newline at end of file diff --git a/.wolf/memory.md b/.wolf/memory.md index 3502b13c..87d491b5 100644 --- a/.wolf/memory.md +++ b/.wolf/memory.md @@ -7317,3 +7317,54 @@ | 06:32 | 继续查 scheduler 连接逻辑(xcecli_start hostname vs IP);fetch origin develop/working 看 scheduler 新提交 | 本地 + t1 | 进行中 | ~0.2k tok | | 06:45 | xcecli_start 连接逻辑正常(endpoint_connect成功→RUN);但 scheduler 无 socket。矛盾 → 需运行时实时观察 scheduler 连接 | t1/本地 | 进行中 | ~0.2k tok | | 06:47 | ★ 调度验证成功:本地修复版 scheduler 连 t1 controller,5 个作业全部被分配(exec_hosts=t1)并跑完 EXIT!put_resvals 修复(idxs<=0→<0)解决了崩溃+调度阻塞。全链路打通 | t1 + 本地 | 验证通过 | ~0.5k tok | +| 06:53 | 推送 scheduler 修复 07ab056;扩展 worker 到 t2/t3(连 t1 controller)| myxce/chatbot | done+进行中 | ~0.2k tok | +| 06:55 | t3 worker.yaml 已创建;启动 t2/t3 worker 连 t1 controller | t2/t3 | 进行中 | ~0.2k tok | +| 06:57 | t2/t3 worker 退出因 hosts.yaml 无 t2/t3 主机(同 t1 问题)。加 t2/t3 到 hosts.yaml + 重建 cluster.bin | 本地 + t1 | 进行中 | ~0.2k tok | +| 06:58 | cluster.bin 重建含 t2/t3(sha 76ffcf52c835),待部署 controller + 重启 + 启 t2/t3 worker | t1 + t2/t3 | 进行中 | ~0.2k tok | +| 07:01 | controller 新配置重启成功(tag 76ffcf52c835, PRIMARY term=4);apiserver 断开待重启;待启 t2/t3 worker | t1 | 进行中 | ~0.2k tok | +| 07:13 | 3 台 run.sh 已加 sqlite 到 LIBPATH。待验证 t2 worker 启动 | t1/t2/t3 | 进行中 | ~0.2k tok | +| 07:15 | 真根因:xcecd DT_NEEDED 硬编码 /nix/store/.../libsqlite3.so 绝对路径;t2/t3 无 /nix/store → 找不到。t1 有 /nix/store 所以能跑。修复:t2/t3 建 /nix/store 软链接 | t2/t3 | 进行中 | ~0.2k tok | +| 07:30 | 方案A试点:只对 xcecd 做 patchelf 自包含(收集依赖库到统一 lib/ + 重写 RUNPATH + sqlite 改短名)| 本地 | 进行中 | ~0.2k tok | +| 07:35 | 在 t2 实测自包含 xcecd(pilot:patchelf RUNPATH=$ORIGIN/lib + sqlite 短名 + 解释器相对)| t2 | 进行中 | ~0.2k tok | +| 07:39 | 调整:lib/ 只放非 glibc 第三方库(hwloc/uv/sqlite/ssl等),glibc 用系统;解释器用系统 ld-linux | 本地 pilot | 进行中 | ~0.2k tok | +| 07:41 | 关键洞察:libssl 等第三方库自身 RUNPATH 也是 /nix/store 绝对路径 → 需对 lib/*.so 也 patchelf 为 $ORIGIN | 本地 pilot | 进行中 | ~0.2k tok | +| 07:42 | ★ 方案A验证成功:自包含 xcecd(patchelf $ORIGIN RUNPATH + 12 非 glibc 库 + 系统 ld-linux)在 t2 无 /nix/store 上完全加载并启动(连 t1:9990)。待整合进 AppImage 打包 | t2 pilot | 验证通过 | ~0.4k tok | +| 07:47 | bug-1496 已记录;t3 已部署自包含 xcecd;启动 t3 worker 连 t1 | t3 | 进行中 | ~0.2k tok | +| 07:48 | t1 controller 挂了(无 9990)!需重启 controller + apiserver + scheduler 才能跑作业。t2/t3 worker 就绪 | t1 | 恢复中 | ~0.2k tok | +| 07:55 | 验证路径:停 t2/t3 pilot worker → 重启 t1 controller → 验证 t1 单 worker 跑作业 | t1/t2/t3 | 进行中 | ~0.2k tok | +| 07:59 | t1 scheduler 反复不连 controller(无 socket);之前本地 scheduler 能连 t1 并调度。方案:本地常驻 scheduler 连 t1,先让作业跑 | t1+本地 | 进行中 | ~0.2k tok | +| 08:01 | 调度成功:verifyrun 被分配到 t1(exec_hosts 填充,PSUSP 状态)。本地 scheduler 常驻连 t1 有效。待确认作业完整生命周期 + 验证功能 | t1+本地 | 进行中 | ~0.2k tok | +| 08:09 | 修复 scheduler use-after-free(2处 rv->val 置空转移所有权),编译通过。待 ASAN 本地验证不崩 + 调度 | src/scheduler/src/scheduler.c | 编译 OK | ~0.2k tok | +| 08:11 | ★ scheduler use-after-free 修复验证:作业 RUN→DONE 完整执行,ASAN 0 错误,scheduler 稳定。调度链路彻底打通 | t1+本地 | 验证通过 | ~0.3k tok | +| 08:30 | t2/t3 加入 cluster 排查:之前 pilot worker 用 env -i 启动报 incorrect worker idx -1 干扰 controller。先确认现状再排查 | t2/t3 | 进行中 | ~0.2k tok | +| 08:37 | controller 恢复(term=7)。用正确环境启动 t2 自包含 worker,排查 incorrect worker idx -1 | t2 | 进行中 | ~0.2k tok | + +## Session: 2026-08-03 08:43 + +| Time | Action | File(s) | Outcome | ~Tokens | +|------|--------|---------|---------|--------| +| 08:46 | 状态:scheduler use-after-free 已修+验证;t2/t3 worker join 导致 controller 静默退出(未定位);作业可在 t1 单 worker 跑通。暂停 controller 排查,先测 jobpeek + mcp | 多机 | 进行中 | ~0.3k tok | +| 01:37 | Created ../../../../tmp/frpcdbg_mon.sh | — | ~250 | +| 01:37 | Session end: 1 writes across 1 files (frpcdbg_mon.sh) | 2 reads | ~523 tok | +| 01:43 | Session end: 1 writes across 1 files (frpcdbg_mon.sh) | 2 reads | ~523 tok | +| 01:53 | Session end: 1 writes across 1 files (frpcdbg_mon.sh) | 2 reads | ~523 tok | +| 02:10 | Created ../../../../tmp/frpc_prod.toml | — | ~93 | +| 02:10 | Created ../../../../tmp/frpc_mon.sh | — | ~271 | +| 02:10 | Created ../../../../tmp/frpc_prod.toml | — | ~95 | +| 02:11 | Created ../../../../tmp/frpc_mon.sh | — | ~273 | +| 02:11 | Edited ../../../../tmp/frpc_mon.sh | 2→2 lines | ~4 | +| 02:16 | Edited ../../../../tmp/frpc_mon.sh | inline fix | ~21 | +| 02:19 | Session end: 7 writes across 3 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh) | 2 reads | ~1334 tok | +| 02:52 | Created ../../../../tmp/frpc_watchdog.sh | — | ~488 | +| 10:53 | frpc 诊断完成: 根因=CGNAT+frpc0.69.1重连死循环(login不注册proxy, 循环数天不自愈, 仅重启打断) | frps server journal + frpc.toml | 根因定位 | ~600 | +| 10:53 | 部署 frpc 看门狗 /tmp/frpc_watchdog.sh: 隧道DOWN×3连续(90s)自动 doas rc.d/frpc restart, 300s防抖; frpc开debug日志 | /tmp/frpc_watchdog.sh + /etc/frp/frpc.toml | 自动恢复已部署 | ~300 | +| 02:54 | Session end: 8 writes across 4 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh, frpc_watchdog.sh) | 2 reads | ~1857 tok | +| 03:10 | Session end: 8 writes across 4 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh, frpc_watchdog.sh) | 2 reads | ~1857 tok | +| 03:46 | Session end: 8 writes across 4 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh, frpc_watchdog.sh) | 2 reads | ~1857 tok | +| 04:10 | Session end: 8 writes across 4 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh, frpc_watchdog.sh) | 2 reads | ~1857 tok | +| 05:36 | Session end: 8 writes across 4 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh, frpc_watchdog.sh) | 2 reads | ~1857 tok | +| 05:41 | Session end: 8 writes across 4 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh, frpc_watchdog.sh) | 2 reads | ~1857 tok | +| 05:45 | Session end: 8 writes across 4 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh, frpc_watchdog.sh) | 2 reads | ~1857 tok | +| 05:49 | Created ../../../../tmp/frpc-watchdog.sh | — | ~338 | +| 13:50 | 看门狗改为纯日志模式(不自动重启): 移到 /home/dankeer/bin/frpc-watchdog.sh + crontab @reboot 开机自启; 只在隧道状态变化时写日志(DOWN抓快照/恢复记录/持续DOWN每5min) | /home/dankeer/bin/frpc-watchdog.sh | 部署完成, 用户人工监视 | ~200 | +| 05:50 | Session end: 9 writes across 5 files (frpcdbg_mon.sh, frpc_prod.toml, frpc_mon.sh, frpc_watchdog.sh, frpc-watchdog.sh) | 2 reads | ~2219 tok | diff --git a/.wolf/token-ledger.json b/.wolf/token-ledger.json index ffc7d47e..bf3519eb 100644 --- a/.wolf/token-ledger.json +++ b/.wolf/token-ledger.json @@ -2,14 +2,14 @@ "version": 1, "created_at": "2026-05-21T04:35:43.577Z", "lifetime": { - "total_tokens_estimated": 318096446, - "total_reads": 36446, - "total_writes": 57038, - "total_sessions": 265, - "anatomy_hits": 23910, - "anatomy_misses": 11619, - "repeated_reads_blocked": 101295, - "estimated_savings_vs_bare_cli": 2665433727 + "total_tokens_estimated": 318128677, + "total_reads": 36491, + "total_writes": 57113, + "total_sessions": 268, + "anatomy_hits": 23942, + "anatomy_misses": 11632, + "repeated_reads_blocked": 101297, + "estimated_savings_vs_bare_cli": 2665446615 }, "sessions": [ { @@ -531400,6 +531400,951 @@ "repeated_reads_blocked": 31, "anatomy_lookups": 20 } + }, + { + "id": "session-2026-08-02-0450", + "started": "2026-08-02T04:50:25.570Z", + "ended": "2026-08-02T04:55:31.229Z", + "reads": [ + { + "file": "/home/lchen/code/xce/src/frontend/schedulerclient/httpclient.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/controllers/hosts.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [], + "totals": { + "input_tokens_estimated": 0, + "output_tokens_estimated": 0, + "reads_count": 2, + "writes_count": 0, + "repeated_reads_blocked": 0, + "anatomy_lookups": 0 + } + }, + { + "id": "session-2026-08-02-0450", + "started": "2026-08-02T04:50:25.570Z", + "ended": "2026-08-02T05:09:48.290Z", + "reads": [ + { + "file": "/home/lchen/code/xce/src/frontend/schedulerclient/httpclient.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/controllers/hosts.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [], + "totals": { + "input_tokens_estimated": 0, + "output_tokens_estimated": 0, + "reads_count": 2, + "writes_count": 0, + "repeated_reads_blocked": 0, + "anatomy_lookups": 0 + } + }, + { + "id": "session-2026-08-02-0450", + "started": "2026-08-02T04:50:25.570Z", + "ended": "2026-08-02T05:12:24.191Z", + "reads": [ + { + "file": "/home/lchen/code/xce/src/frontend/schedulerclient/httpclient.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/controllers/hosts.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/models/hosts.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/backend/convert_pure.go", + "tokens_estimated": 3244, + "was_repeated": true, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/backend/convert.go", + "tokens_estimated": 3556, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/include/xce/types.h", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [], + "totals": { + "input_tokens_estimated": 6800, + "output_tokens_estimated": 0, + "reads_count": 6, + "writes_count": 0, + "repeated_reads_blocked": 1, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-02-0450", + "started": "2026-08-02T04:50:25.570Z", + "ended": "2026-08-02T05:14:08.906Z", + "reads": [ + { + "file": "/home/lchen/code/xce/src/frontend/schedulerclient/httpclient.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/controllers/hosts.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/models/hosts.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/backend/convert_pure.go", + "tokens_estimated": 3244, + "was_repeated": true, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/backend/convert.go", + "tokens_estimated": 3556, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/include/xce/types.h", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/frontend/apiserver/controllers/jobs.go", + "tokens_estimated": 0, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [], + "totals": { + "input_tokens_estimated": 6800, + "output_tokens_estimated": 0, + "reads_count": 7, + "writes_count": 0, + "repeated_reads_blocked": 1, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-03T08:44:51.940Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 0, + "reads_count": 2, + "writes_count": 0, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-03T08:56:17.066Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 0, + "reads_count": 2, + "writes_count": 0, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T01:37:46.298Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 268, + "reads_count": 2, + "writes_count": 1, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T01:43:14.298Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 268, + "reads_count": 2, + "writes_count": 1, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T01:53:40.786Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 268, + "reads_count": 2, + "writes_count": 1, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T02:19:37.031Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1079, + "reads_count": 2, + "writes_count": 7, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T02:54:38.833Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + }, + { + "file": "/tmp/frpc_watchdog.sh", + "tokens_estimated": 523, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1602, + "reads_count": 2, + "writes_count": 8, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T03:10:41.681Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + }, + { + "file": "/tmp/frpc_watchdog.sh", + "tokens_estimated": 523, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1602, + "reads_count": 2, + "writes_count": 8, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T03:46:00.096Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + }, + { + "file": "/tmp/frpc_watchdog.sh", + "tokens_estimated": 523, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1602, + "reads_count": 2, + "writes_count": 8, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T04:10:32.475Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + }, + { + "file": "/tmp/frpc_watchdog.sh", + "tokens_estimated": 523, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1602, + "reads_count": 2, + "writes_count": 8, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T05:36:25.930Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + }, + { + "file": "/tmp/frpc_watchdog.sh", + "tokens_estimated": 523, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1602, + "reads_count": 2, + "writes_count": 8, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T05:41:21.470Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + }, + { + "file": "/tmp/frpc_watchdog.sh", + "tokens_estimated": 523, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1602, + "reads_count": 2, + "writes_count": 8, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T05:45:56.370Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + }, + { + "file": "/tmp/frpc_watchdog.sh", + "tokens_estimated": 523, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1602, + "reads_count": 2, + "writes_count": 8, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } + }, + { + "id": "session-2026-08-03-0843", + "started": "2026-08-03T08:43:53.877Z", + "ended": "2026-08-04T05:50:39.165Z", + "reads": [ + { + "file": "/home/lchen/code/xce/.mcp.json", + "tokens_estimated": 7, + "was_repeated": false, + "anatomy_had_description": false + }, + { + "file": "/home/lchen/code/xce/src/configs/hosts.yaml", + "tokens_estimated": 248, + "was_repeated": false, + "anatomy_had_description": false + } + ], + "writes": [ + { + "file": "/tmp/frpcdbg_mon.sh", + "tokens_estimated": 268, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 100, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 291, + "action": "create" + }, + { + "file": "/tmp/frpc_prod.toml", + "tokens_estimated": 101, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 292, + "action": "create" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 5, + "action": "edit" + }, + { + "file": "/tmp/frpc_mon.sh", + "tokens_estimated": 22, + "action": "edit" + }, + { + "file": "/tmp/frpc_watchdog.sh", + "tokens_estimated": 523, + "action": "create" + }, + { + "file": "/tmp/frpc-watchdog.sh", + "tokens_estimated": 362, + "action": "create" + } + ], + "totals": { + "input_tokens_estimated": 255, + "output_tokens_estimated": 1964, + "reads_count": 2, + "writes_count": 9, + "repeated_reads_blocked": 0, + "anatomy_lookups": 2 + } } ], "daemon_usage": [], diff --git a/src/configs/hosts.yaml b/src/configs/hosts.yaml index 4ee6f6fa..a2cf42b0 100644 --- a/src/configs/hosts.yaml +++ b/src/configs/hosts.yaml @@ -35,15 +35,25 @@ hosts: model: "x86_64-linux-gnu" max_slot: 128 - # t1: primary test node (172.31.1.30). Must match the hostname the worker - # reports via gethostname(); without a matching hostconfig, the worker's - # join is rejected with -EINVAL (find_matched_hostconfig fails) and no - # compute node ever registers, so every job stays PEND (bug-1494). + # t1/t2/t3: test nodes (172.31.1.30/31/32). Must match each hostname the + # worker reports via gethostname(); without a matching hostconfig, the + # worker's join is rejected with -EINVAL (find_matched_hostconfig fails) + # and no compute node ever registers, so every job stays PEND (bug-1494). - hostname: t1 type: "x86_64-linux-gnu" model: "x86_64-linux-gnu" max_slot: 8 + - hostname: t2 + type: "x86_64-linux-gnu" + model: "x86_64-linux-gnu" + max_slot: 8 + + - hostname: t3 + type: "x86_64-linux-gnu" + model: "x86_64-linux-gnu" + max_slot: 8 + hostgroups: - groupname: hg1 diff --git a/src/frontend/apiserver/backend/convert.go b/src/frontend/apiserver/backend/convert.go index da729be7..ac865be9 100644 --- a/src/frontend/apiserver/backend/convert.go +++ b/src/frontend/apiserver/backend/convert.go @@ -249,6 +249,19 @@ func cClusterConfToClusterInfo(conf *C.cluster_config_t) *models.ClusterInfo { // modelJobToSubmit converts a Go JobInfo to C xce_job_submit_t heap structs. // The caller must free all returned C memory by calling freeJobSubmit. +// resolveExecUser returns the user a job should run as: an explicit exec_user +// wins; otherwise the job runs as the submitting user. bug-1500: the submit +// conversion previously dropped this entirely, so the worker received a NULL +// execuser and ran every job as "nobody". Kept as a plain-Go function so it is +// unit-testable without cgo (the Go toolchain rejects `import "C"` in _test.go). +func resolveExecUser(job *models.JobInfo) string { + execUser := job.ExecUser + if execUser == "" { + execUser = job.SubmitUser + } + return execUser +} + func modelJobToSubmit(job *models.JobInfo) (*C.xce_job_submit_t, *C.job_submit_data_t, *C.job_startinfo_t) { si := (*C.job_startinfo_t)(C.calloc(1, C.sizeof_job_startinfo_t)) si.cmdline = C.CString(job.Command) @@ -261,6 +274,9 @@ func modelJobToSubmit(job *models.JobInfo) (*C.xce_job_submit_t, *C.job_submit_d if job.PostExecCmd != "" { si.job_post_exec = C.CString(job.PostExecCmd) } + // bug-1500: carry the exec user on the start_info. Without this the worker + // receives a NULL execuser and runs every job as "nobody". + si.execuser = C.CString(resolveExecUser(job)) sd := (*C.job_submit_data_t)(C.calloc(1, C.sizeof_job_submit_data_t)) sd.queue = C.CString(job.QueueName) @@ -303,6 +319,7 @@ func freeJobSubmit(js *C.xce_job_submit_t, sd *C.job_submit_data_t, si *C.job_st C.free(unsafe.Pointer(si.launch_type)) C.free(unsafe.Pointer(si.job_pre_exec)) C.free(unsafe.Pointer(si.job_post_exec)) + C.free(unsafe.Pointer(si.execuser)) C.free(unsafe.Pointer(si)) } if sd != nil { diff --git a/src/frontend/apiserver/backend/convert_test.go b/src/frontend/apiserver/backend/convert_test.go index 83d2cdba..a0a4bc8e 100644 --- a/src/frontend/apiserver/backend/convert_test.go +++ b/src/frontend/apiserver/backend/convert_test.go @@ -865,3 +865,27 @@ func TestRawClusterToModel(t *testing.T) { }) } } + +// bug-1500: the submit conversion must carry an exec user; explicit exec_user +// wins, otherwise the job runs as the submitting user (not "nobody"). +func TestResolveExecUser(t *testing.T) { + cases := []struct { + name string + execUser string + submitUser string + want string + }{ + {"explicit exec_user wins", "lchen", "admin", "lchen"}, + {"empty exec_user falls back to submit user", "", "admin", "admin"}, + {"both empty stays empty", "", "", ""}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + job := &models.JobInfo{SubmitUser: tc.submitUser, ExecUser: tc.execUser} + if got := resolveExecUser(job); got != tc.want { + t.Errorf("resolveExecUser: got %q, want %q", got, tc.want) + } + }) + } +}