Compare commits

...

1814 commits

Author SHA1 Message Date
1f61ce033a attempt 3 at the model settings fix
Some checks failed
CI master / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Has been cancelled
CI master / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Has been cancelled
CI master / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Has been cancelled
CI master / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Has been cancelled
CI master / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Has been cancelled
CI master / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Has been cancelled
CI master / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Has been cancelled
CI master / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Has been cancelled
CI master / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Has been cancelled
CI master / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Has been cancelled
CI master / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Has been cancelled
CI master / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Has been cancelled
CI master / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Has been cancelled
CI master / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Has been cancelled
CI master / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Has been cancelled
CI master / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Has been cancelled
CI master / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Has been cancelled
CI master / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Has been cancelled
CI master / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Has been cancelled
CI master / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Has been cancelled
CI master / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Has been cancelled
CI master / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Has been cancelled
E2E (real DeepSeek API) / e2e (push) Has been cancelled
Release (vendor) / Pack npm tarballs (push) Has been cancelled
Release (dsh) / Dependency layout (push) Has been cancelled
Release (dsh) / Pack npm tarballs (push) Has been cancelled
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Has been cancelled
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Has been cancelled
maybe i should fix a different file
2026-09-04 18:25:28 +00:00
2bfb9ba1af 2nd attempt for model fixing
Some checks are pending
CI master / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Waiting to run
E2E (real DeepSeek API) / e2e (push) Waiting to run
Release (vendor) / Pack npm tarballs (push) Waiting to run
Release (dsh) / Dependency layout (push) Waiting to run
Release (dsh) / Pack npm tarballs (push) Waiting to run
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Waiting to run
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Waiting to run
original attempt idk
2026-09-04 17:49:04 +00:00
3279eca9e9 fix attempt for the models settings ui
Some checks are pending
CI master / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Waiting to run
E2E (real DeepSeek API) / e2e (push) Waiting to run
Release (vendor) / Pack npm tarballs (push) Waiting to run
Release (dsh) / Dependency layout (push) Waiting to run
Release (dsh) / Pack npm tarballs (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Waiting to run
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Waiting to run
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Waiting to run
deepseek coul'nt find the model directory
2026-09-04 17:02:18 +00:00
f60c2bf51b Update Dockerfile
Some checks are pending
CI master / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Waiting to run
E2E (real DeepSeek API) / e2e (push) Waiting to run
Release (vendor) / Pack npm tarballs (push) Waiting to run
Release (dsh) / Dependency layout (push) Waiting to run
Release (dsh) / Pack npm tarballs (push) Waiting to run
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Waiting to run
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Waiting to run
2026-09-03 21:01:31 +00:00
c245952ae2 Fix for broken directory
Some checks are pending
CI master / larger-runner-benchmark (16, windows, dsh-windows-2025-16core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Waiting to run
E2E (real DeepSeek API) / e2e (push) Waiting to run
Release (vendor) / Pack npm tarballs (push) Waiting to run
Release (dsh) / Dependency layout (push) Waiting to run
Release (dsh) / Pack npm tarballs (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Waiting to run
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Waiting to run
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Waiting to run
Fix for error: client api: directoryPicker/list failed: transport failure for /api/directoryPicker/list: HTTP 403
2026-09-03 20:29:49 +00:00
333af4c0ea fix blocked connection
Some checks are pending
CI master / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Waiting to run
E2E (real DeepSeek API) / e2e (push) Waiting to run
Release (vendor) / Pack npm tarballs (push) Waiting to run
Release (dsh) / Dependency layout (push) Waiting to run
Release (dsh) / Pack npm tarballs (push) Waiting to run
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Waiting to run
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Waiting to run
Inside a Docker container, 127.0.0.1 refuses connections coming from Dokploy's internal proxy. We can bypass this easily by installing socat—a lightweight network relay—inside the container. It acts as a safe bridge: Dokploy talks to socat on 0.0.0.0:3080, and socat passes the traffic internally to the app on 127.0.0.1:3081.
2026-09-03 15:17:10 +00:00
adf5259868 fix 502 bad gateway
Some checks are pending
CI master / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Waiting to run
E2E (real DeepSeek API) / e2e (push) Waiting to run
Release (vendor) / Pack npm tarballs (push) Waiting to run
Release (dsh) / Dependency layout (push) Waiting to run
Release (dsh) / Pack npm tarballs (push) Waiting to run
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Waiting to run
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Waiting to run
ost Binding: dsh web is binding strictly to 127.0.0.1:3080 inside the container. Dokploy's proxy routes traffic using the container's internal network IP, which gets rejected because the app is only listening to local loopback inside its isolated shell.

Browser Crashes: It is attempting to spawn a desktop browser inside a headless Docker Linux container, which causes the command to crash with [ELIFECYCLE] Command failed (as seen in Containers 2 and 3).
2026-09-03 06:33:55 +00:00
d5e6da5286 Add Dockerfile
Some checks are pending
CI master / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Waiting to run
CI master / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Waiting to run
CI master / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Waiting to run
CI master / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Waiting to run
CI master / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Waiting to run
CI master / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Waiting to run
CI master / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Waiting to run
E2E (real DeepSeek API) / e2e (push) Waiting to run
Release (vendor) / Pack npm tarballs (push) Waiting to run
Release (dsh) / Dependency layout (push) Waiting to run
Release (dsh) / Pack npm tarballs (push) Waiting to run
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Waiting to run
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Waiting to run
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Waiting to run
2026-09-03 06:09:59 +00:00
imccyu
49a606bc5b Merge pull request #3456 from deepseek-harness/release/dsh-0.1.2-alpha.5-version-to-master
sync: merge 0.1.2-alpha.5 to master
2026-09-02 17:47:12 +08:00
Dudu-0223
f7cee2c888 Merge pull request #3333 from deepseek-harness/feat/3330-team-send-message-steer
feat(agent-team): unify messages on steer
2026-09-02 17:27:55 +08:00
imccyu
cf126d8699 Merge remote-tracking branch 'origin/merge/projcache-v6-compat-into-master' into release/dsh-0.1.2-alpha.5-version-to-master 2026-09-02 17:25:23 +08:00
imccyu
0a1efddd40 Merge pull request #3455 from deepseek-harness/merge/projcache-v6-compat-into-master
sync: merge projection cache fix from 0.1.2-alpha.5 to master
2026-09-02 17:18:44 +08:00
Dudu-0223
eeddd457cd fix(agent-team): preserve mailbox order on cold resume 2026-09-02 17:14:44 +08:00
Dudu-0223
1180707084 Merge remote-tracking branch 'origin/master' into feat/3330-team-send-message-steer
# Conflicts:
#	packages/experimental/agent-team/tests/team.spec.ts
2026-09-02 16:58:09 +08:00
imccyu
c917fe6d46 Merge remote-tracking branch 'origin/master' into merge/projcache-v6-compat-into-master
# Conflicts:
#	packages/session/session-projection-cache/src/spec.ts
#	packages/storage/storage-json/src/per-record-unit.ts
#	packages/storage/storage-json/tests/json-backend.spec.ts
2026-09-02 16:55:00 +08:00
imccyu
5a69ba1cdd Merge pull request #3445 from deepseek-harness/release/dsh-0.1.2-alpha.5
release: dsh@0.1.2-alpha.5
2026-09-02 15:57:43 +08:00
imccyu
db6bdc3576 release(dsh): 0.1.2-alpha.5 2026-09-02 15:48:33 +08:00
imccyu
1915665e1e Merge pull request #3438 from deepseek-harness/fix/projcache-cross-version-read-compat
fix(session-projection-cache): survive upgrades across projcache domain versions
2026-09-02 15:47:14 +08:00
imccyu
db2dd2f840 docs(session-projection-cache): land the read-compat note as implemented and state fixture provenance in place
Review follow-ups: the Agent Note triplet moves to implemented/ rewritten as
shipped state (Decision/Consequences/Testing, present tense), cross-linked
both ways with the 2026-07-28 storage recovery proposal whose projcache
reset/destroy path it supersedes (that proposal stays live for authoritative
and whole-medium damage). The fixtures spec header and the note state the
fixture provenance as recorded facts of the released builds instead of
citing local tooling, and the spec JSDoc points at the note's final home.
2026-09-02 15:25:07 +08:00
imccyu
bef26396e5 docs(session-projection-cache): cross-version read-compat note and schema-change fixture rule
The proposed Agent Note records the three shipped on-disk generations of
session_projcache, the read-compat and backup-and-skip decisions, the
upgrade matrix, and the rejected alternatives. The package README documents
the upgrade guarantees and requires every future schema or domain-version
change to land with archived fixtures and tests proving its upgrade story.
The storage subsystem page and the generated cordis catalog pick up the new
DomainSpec fields.
2026-09-02 15:25:07 +08:00
imccyu
49df707c86 fix(session-projection-cache): keep upgraded caches readable and boots safe across domain versions
The session_projcache domain declares compatibleVersions: [3, 4] and
invalidRecords: 'backup-and-skip'. The two lineage identity fields become
optional — records admitted from older versions predate them, and the single
reader (identityMatches) interprets absence as the unseeded lineage: exact
for unseeded sessions, while a seeded caller fails the match and refolds
cold, so the lineage binding keeps its protection. Upgraded homes therefore
boot and serve their cached listing titles immediately, including homes
whose new tree already holds current-stamped documents without lineage
fields, and a record failing validation anyway is backed up and skipped
instead of refusing the plugin tree.

tests/fixtures/ archives the real on-disk media of every shipped generation
(v3 whole-unit file, v4 and v5 per-record documents, and the lineage-less
current-stamped shape); fixtures.spec.ts proves each recovers through the
real storage stack, rewrites to the current format on the next live write,
and that a hopeless record is salvaged without costing the boot.
2026-09-02 15:25:07 +08:00
imccyu
fcd109d29a feat(storage): version read compatibility and backup-and-skip salvage for per-record units
A DomainSpec may declare compatibleVersions: older domain versions whose
stored records the current record schemas still accept. The json backend's
per-record reads admit documents stamped with a declared version (writes
always stamp the current one), and the legacy whole-unit bootstrap migrates
only a file whose stored version is in the accepted set — previously it
migrated any version and stamped the records current, turning a discardable
stale cache into invalid-record failures that refused the whole domain at
open and permanently poisoned the new tree on first boot.

A DomainSpec may also declare invalidRecords: 'backup-and-skip' for domains
whose records are disposable derived data: a stored record failing its zod
schema is moved aside through the new optional KvUnit.backupRecord
(<key>.json.bak.<YYYYMMDDHHmm> under the json backend), logged with its
cause, and skipped, instead of rejecting the open. The default stays
fail-loud, and so do backends without backupRecord.
2026-09-02 15:25:07 +08:00
Turtle
66ca93c3dc Merge pull request #3441 from deepseek-harness/turtle/fix-project-date-fields
fix(issue-management): restore Project date fields
2026-09-02 15:20:46 +08:00
Turtle
070b46e1ef fix(issue-management): restore Project date fields 2026-09-02 15:06:25 +08:00
Turtle
be70505f9e Merge pull request #3417 from deepseek-harness/turtle/fix-issue-field-start-date
fix(issue-management): write Start date through Issue fields
2026-09-02 13:41:29 +08:00
Yichen Jiang
bbae7318f0 Merge pull request #3424 from deepseek-harness/worktree/github-issue-725-verification-7e80bd
fix(llm): keep streamed tool-call identity across empty deltas
2026-09-02 13:35:55 +08:00
Chinesezjc
a631115597 Merge pull request #2828 from deepseek-harness/feat/toolcard-image-result
feat(ui-tool): render read_image results as the image
2026-09-02 12:45:39 +08:00
Magolor
d921d4b357 fix(storage-json): reject cross-version legacy bootstrap (#3431)
* fix(storage-json): reject cross-version legacy bootstrap

* test(webworker): sync projection cache fixture version

* docs(storage): record legacy bootstrap version ownership
2026-09-02 04:37:15 +00:00
Chinesezjc
3648331b11 Merge remote-tracking branch 'origin/master' into feat/toolcard-image-result
# Conflicts:
#	packages/client/ui-chat/src/client/chat/ChatNodeSeat.tsx
#	packages/client/ui-chat/src/client/chat/ChatView.tsx
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
2026-09-02 12:02:25 +08:00
Xu Hanxiang
d3ab4ce53d Merge pull request #3401 from deepseek-harness/issue-1424-goal-pause-stop-turn
fix(goal): abort the live turn on host-initiated pause
2026-09-02 11:32:12 +08:00
Turtle
d76c974fbb Merge branch 'master' into turtle/fix-issue-field-start-date 2026-09-02 11:13:10 +08:00
Yichen Jiang
b03261caad fix(llm): narrow the fix to identity acceptance
Refusing a response whose tool call never receives an identity needed a new
failure code, a change to the default retryable set, and a `[DONE]` gate that
overrode the finish reason a provider had already sent — turning a safe
`max-tokens` truncation into up to five retries. The lenient wire it guarded
against is hypothetical: no report describes a stream that omits identity
entirely, and the pre-existing test for it is labelled as such.

Only `acceptIdentity` and the widened wire types remain. They close the
reported erasure and cannot reach a worse outcome than the previous
assignment, because the set of inputs that assign only narrows.
2026-09-02 10:34:09 +08:00
Yichen Jiang
83931a5f3e fix(llm): correct the refusal's recorded rationale
`LlmRuntime.adapterStream` normalizes a thrown `LlmError` into the same error
`finish` the loop routes to `agent/request-error`, so throwing would reach
retry too. The Note claimed otherwise. Yielding is chosen because it reports
the attempt's billed usage first and matches the neighbouring `EMPTY_RESPONSE`
refusal.

The rejection comment repeats the corrected durability wording, and the
assembler's delta-only fallback carries a TODO for the empty name it still
invents for adapters that never close a tool-call block.
2026-09-02 10:08:42 +08:00
Yichen Jiang
e91c28d3fd fix(llm): cover the malformed tool-call path and correct its records
The `MALFORMED_TOOL_CALL` JSDoc claimed nothing durable is written, but the
loop appends an `assistant/chunk` for every yielded chunk; only the assistant
message and tool result are withheld. The bounded-recovery Note still listed
a five-code transient set, and neither Note linked the other.

A keyless `malformed-tool-call-retry` scenario now records the refusal, the
retry, and the absence of a `tool/call` for the failed attempt. A translator
case pins that an already closable block also withholds its `block-end`.
2026-09-02 10:01:56 +08:00
Yichen Jiang
96cbd8d9e6 fix(llm): refresh web and packed-fixture expectations for the new retry code
Adding `MALFORMED_TOOL_CALL` to the default retryable set changes two
expected outputs the session snapshot lane does not own: the shipped Web
composition's inline snapshot, and the canonical packed layout of the
refreshed `empty-response-retry` fixture.
2026-09-02 09:36:54 +08:00
Turtle
8b799cd7ac Merge pull request #3266 from deepseek-harness/refactor/session-persistence-handle-seam
refactor(session-persistence)!: handle-based seam with a lifecycle-owned write path
2026-09-02 00:50:53 +08:00
imccyu
4e84901e64 Merge pull request #3427 from deepseek-harness/release/dsh-0.1.2-alpha.4
release: dsh@0.1.2-alpha.4
2026-09-01 23:37:26 +08:00
imccyu
a9e185f205 release(dsh): 0.1.2-alpha.4 2026-09-01 23:19:57 +08:00
Turtle
bec6805d6a refactor(session-persistence)!: handle-based seam with a lifecycle-owned write path
The persistence seam is now create/open/stat/list returning per-session
SessionHandles (read/append/flush/close); every log read and write flows
through the owning handle. The seam package exports only the service and
handle contracts, consumer-visible errors, and pure durable-data
validation helpers; each backend owns its complete storage runtime, and
the shared contract suites pin equivalent observable behavior. The
backend routes published sessions' live events by id into the active
write handle; agent-loop only acquires, seeds, and closes the handle.
Resume appends interruptedTurnClosers through its write handle;
session-query owns the revision-keyed cold cache. Legacy-only surfaces
are removed in the same swap: locate/readRaw/supportsRawArtifacts, the
legacy event-shape read migration, zstd torn-frame salvage,
DSH_SESSION_JSONL, and hook transcript_path population; a torn final
zstd frame is discarded whole; the session-list cold blank probe returns
on stat metadata (eventCount derived from the last physical row,
sizeBytes). The WebUI ZIP export serializes the logical log from a read
handle, so both backends export identically.

Refs #3245
2026-09-01 23:19:02 +08:00
Tianyi Cui
3c5b7097ae Merge pull request #3425 from deepseek-harness/feat/ptc-disable-workflow-plugin
feat(presets): omit workflow from Web PTC mode
2026-09-01 23:18:39 +08:00
imccyu
1f694c88ab Merge pull request #3391 from deepseek-harness/worktree-chatperf
perf(web): reduce conversation rendering and layout overhead
2026-09-01 23:16:50 +08:00
imccyu
e32437d18b perf(chat): throttle scroll geometry sampling 2026-09-01 23:06:52 +08:00
imccyu
4e4733c50b test(web): await turn-tail stream publication 2026-09-01 22:55:17 +08:00
fz
0cdcc9c3c5 feat(presets): omit workflow from PTC mode 2026-09-01 22:45:09 +08:00
imccyu
e427d5746e fix: ci 2026-09-01 22:41:42 +08:00
Tianyi Cui
c3e5bd7dae Merge pull request #3418 from deepseek-harness/fix/ptc-note-cloudflare-link
docs: restore Cloudflare's Code Mode name and blog link in PTC Agent Note
2026-09-01 22:36:56 +08:00
imccyu
9ef0e28000 test(web): await streamed text before snapshot 2026-09-01 22:36:05 +08:00
imccyu
0e90d47d19 perf(chat): skip stable node list mapping 2026-09-01 22:29:46 +08:00
Yichen Jiang
a1271a4903 fix(llm): keep streamed tool-call identity across empty deltas
A continuation SSE delta that repeats a tool call's `id` or `name` as an
empty string — or as `null`, which some OpenAI-compatible gateways send —
erased the identity established by the call's first delta. The assembled
block reached the loop with an empty name and failed as `unknown tool ""`,
and the empty `callId` persisted into `tool/result`, which the session
reader refuses on reopen.

`acceptIdentity` accepts only a non-empty string, so a repeated empty or
null field means "no update". A tool call still missing `id` or `name` at
`[DONE]` ends the response with the new retryable `MALFORMED_TOOL_CALL`
code instead of closing an unusable block.
2026-09-01 22:22:51 +08:00
imccyu
577f0cf7d9 refactor(client): bind keyed chat sources in renderer 2026-09-01 22:22:25 +08:00
imccyu
b8a19413e9 fix(client): satisfy strict observable contracts 2026-09-01 22:01:18 +08:00
imccyu
de07b4c05b chore(ui-chat): document local keyed sources 2026-09-01 21:46:08 +08:00
imccyu
a718d1f0a1 docs(client): record conversation performance boundaries 2026-09-01 21:31:04 +08:00
Tianyi Cui
b74486ab29 docs: restore Cloudflare's Code Mode name and blog link in PTC note
The code-mode → ptc rename rewrote Cloudflare's product name in the
link text and the external URL path, leaving "PTC mode" pointing at
https://blog.cloudflare.com/ptc/ (404). Restore Cloudflare's own name
and the working https://blog.cloudflare.com/code-mode/ link in both
the English and Chinese notes.
2026-09-01 21:27:44 +08:00
imccyu
2e21d210a5 fix(trajectory): reanchor replaced history windows 2026-09-01 21:17:47 +08:00
imccyu
7db2bab853 test(conversation): brand fixture sequences 2026-09-01 21:14:19 +08:00
imccyu
443efeeba3 chore(client): refresh slot catalog 2026-09-01 21:09:48 +08:00
imccyu
5934201109 perf(conversation): publish streaming updates every three frames 2026-09-01 21:09:48 +08:00
imccyu
ebe9f50b44 perf(ui-chat): contain collapsed reasoning layout 2026-09-01 21:09:48 +08:00
imccyu
aad1ce0c68 perf(ui-chat): retain the stats resize observer 2026-09-01 21:09:48 +08:00
imccyu
f808112ec8 perf(ui-chat): derive user action reveal in CSS 2026-09-01 21:09:48 +08:00
imccyu
56684331c2 test(ui-chat): compare keyed snapshot values 2026-09-01 21:09:48 +08:00
imccyu
56a4d51d2c perf(ui-chat): scope turn process updates 2026-09-01 21:09:47 +08:00
imccyu
5f1eca58ea perf: InputBar use immutable props 2026-09-01 21:09:47 +08:00
imccyu
a731536ecc perf: ChatNodeSeat use seperated source 2026-09-01 21:09:47 +08:00
imccyu
6401a64e20 test(web): cover optimized streaming paths 2026-09-01 21:09:47 +08:00
imccyu
2ab37e9558 perf(trajectory): page resident history before rendering 2026-09-01 21:09:47 +08:00
imccyu
c809098b06 perf(conversation): publish streaming updates every two frames 2026-09-01 21:09:47 +08:00
imccyu
81431381d6 perf(conversation): reuse unchanged location projections 2026-09-01 21:09:47 +08:00
imccyu
203e2440ac perf(ui-chat): move reasoning tail alignment to CSS 2026-09-01 21:09:47 +08:00
imccyu
e5bbee893b perf(ui-deliverables): move overflow sizing to CSS 2026-09-01 21:09:47 +08:00
imccyu
c11c3f98ad docs(ui-deliverables): record CSS overflow policy 2026-09-01 21:09:46 +08:00
Yichen Jiang
3efd4b51e0 Merge pull request #3415 from deepseek-harness/worktree/3414-turn-rail-preview-layer
fix(web): keep turn previews above code banners
2026-09-01 21:05:36 +08:00
Turtle
6ce0b6cce8 fix(issue-management): write Start date through Issue fields 2026-09-01 21:01:36 +08:00
Tianyi Cui
876a3e0414 Merge pull request #3346 from deepseek-harness/worktree/session-format-02-seq-brands
refactor(session)!: distinguish event seqs from log offsets
2026-09-01 20:56:20 +08:00
Tianyi Cui
27bf1039db refactor(session)!: distinguish event seqs from log offsets 2026-09-01 20:36:00 +08:00
Yichen Jiang
515eca7dc7 fix(web): keep turn previews above code banners 2026-09-01 20:21:11 +08:00
ihsiang
4bc0b000f5 Merge pull request #3411 from deepseek-harness/feat/3287-smooth-corners
feat(web): superellipse corners and hairline elevation strokes
2026-09-01 20:17:16 +08:00
mektpoy
b57cc33421 docs(goal): re-record README bilingual pairing 2026-09-01 20:04:06 +08:00
yx.zhang
8a97e817b5 docs(agents): describe the corner and elevation prior art generically
The two styling notes name the surveyed product; the mechanism facts
(superellipse token, guard, full-round opt-out, stroke-in-shadow
elevation, 0.5px hairline) stand alone, so the notes now state them
without the product reference. Pairing records re-recorded.
2026-09-01 20:01:23 +08:00
mektpoy
33fa98b3c2 fix(goal): fence pause to the dropped attempt ref 2026-09-01 19:58:52 +08:00
yx.zhang
3ce5604a71 feat(web): deepen composer stroke to l2, widen menu radii to 20px
The composer hairline moves one step up from the menus' l1; the seven
menu-fill dropdown cards grow from 16px to 20px corners. Notes and the
token comment record the new layering.
2026-09-01 19:25:59 +08:00
yx.zhang
b873b9321e fix(web): per-element elevation tokens and review sync
Re-declare the derived elevation tokens on body * so per-surface
--dsw-elevation-stroke-color rebinds reach the consuming shadow (custom
properties inherit with var() already substituted); pin that mechanism
and add synthetic rejection cases to the stylesheet scans; take the
ring-track basenames through node:path so the exemption matches on
Windows; update the ModelsSection row-card spec to the hairline recipe;
align the elevation note with the shipped l1 menu rebind, refresh the
feedback-popover note's surface recipe, and document the soft tier.
2026-09-01 19:15:56 +08:00
yx.zhang
7020c7e122 feat(web): superellipse corners and hairline elevation strokes
Apply global visual polish across the web client: corner-shape:
superellipse(1.5) with corner-shape: round pairing for full circles,
elevation tokens that draw 0.5px stroke outlines inside box-shadow for
floating surfaces, 0.5px hairline borders and divider lines for
neutral-token strokes, and tuned stroke contrast plus larger radii for
menus, settings panels, and cards. Stylesheet-scan specs in ui-theme
reject unpaired circles, border+shadow mixes, and 1px neutral hairlines
repo-wide.

Closes #3287
2026-09-01 18:25:20 +08:00
fz
dead2b2324 Merge pull request #3382 from deepseek-harness/feat/sdk-default-web-fetch
feat(base): expose web fetch by default
2026-09-01 15:59:35 +08:00
Yichen Jiang
68488c552a Merge pull request #3403 from deepseek-harness/fix/model-discovery-profile-headers
fix(llm): reuse profile headers for model discovery
2026-09-01 15:46:34 +08:00
Yichen Jiang
8fa464890c Merge remote-tracking branch 'origin/master' into fix/model-discovery-profile-headers 2026-09-01 15:26:09 +08:00
Chinesezjc
d2954806de fix(snapshots): project read-image-attachment-path fixture into canonical packed layout 2026-09-01 15:19:37 +08:00
fz
0a0f9e59ff feat(base): expose web fetch by default 2026-09-01 15:18:18 +08:00
Yichen Jiang
25e4527f5e fix(llm): validate configured provider headers 2026-09-01 15:09:40 +08:00
Chinesezjc
a23c3dd64e Merge branch 'origin/master' into feat/toolcard-image-result 2026-09-01 14:45:24 +08:00
Yichen Jiang
5257c75092 fix(llm): reuse profile headers for model discovery 2026-09-01 14:37:16 +08:00
Dudu-0223
1149d47e9a test(tools): update team catalog expectation 2026-09-01 14:22:50 +08:00
Dudu-0223
040d73871b feat(agent-team): unify messages on steer 2026-09-01 14:22:50 +08:00
fz
aefbee95e2 test(acp): refresh adjacent messaging schema 2026-09-01 14:22:49 +08:00
fz
ab9dcd5a2a Merge remote-tracking branch 'origin/master' into feat/sdk-default-web-fetch 2026-09-01 14:17:15 +08:00
Dudu-0223
52af48f808 Merge pull request #3250 from deepseek-harness/feat/3220-steer-service
Unify adjacent Agent delivery on Steer
2026-09-01 14:14:38 +08:00
Dudu-0223
11719fd83c test(web): await goal composer settlement 2026-09-01 14:00:07 +08:00
mektpoy
29ce849738 fix(goal): abort the live turn on host-initiated pause 2026-09-01 13:56:36 +08:00
Dudu-0223
d960d90a98 test(snapshot): refresh Python PTC prompt 2026-09-01 13:46:36 +08:00
Dudu-0223
bfdede9d9e test(subagent): adapt session reads after rebase 2026-09-01 13:46:36 +08:00
Dudu-0223
22b08a9b9b test(subagent): update parent id expectation 2026-09-01 13:46:36 +08:00
Dudu-0223
4093ce465b Merge remote-tracking branch 'origin/master' into feat/3220-steer-service 2026-09-01 13:46:35 +08:00
fz
1bd880c587 Merge remote-tracking branch 'origin/master' into feat/sdk-default-web-fetch
# Conflicts:
#	packages/bundle/headless/README.i18n.yaml
#	packages/bundle/headless/README.md
#	packages/bundle/headless/README.zh.md
2026-09-01 13:45:44 +08:00
Turtle
714bec1316 Merge pull request #3367 from deepseek-harness/omit-unneeded-invariants
cleanup: omit unneeded invariant companions
2026-09-01 12:59:03 +08:00
fz
036abf8c6c test(snapshots): refresh remaining headless web headers 2026-09-01 12:02:29 +08:00
Turtle
d7811225dc Merge remote-tracking branch 'origin/master' into turtle/omit-unneeded-invariants
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/code-runtime/code-runtime-python/README.md
#	packages/code-runtime/code-runtime-python/README.zh.md
#	packages/experimental/code-runtime-python/README.i18n.yaml
#	packages/experimental/code-runtime-python/package.json
#	packages/experimental/code-runtime-python/src/invariant.ts
#	packages/experimental/code-runtime-python/tsconfig.json
#	pnpm-lock.yaml
#	tsconfig.base.json
2026-09-01 11:54:10 +08:00
Chinesezjc
d13d0a4b86 ci: re-trigger workflow after dropped push event 2026-09-01 11:53:19 +08:00
fz
aaf10753a1 test(snapshots): separate ACP web headers 2026-09-01 11:49:55 +08:00
Chinesezjc
9d15938073 Merge pull request #1148 from deepseek-harness/feat/code-runtime-python-backend
feat(code-runtime-python): add the CPython subprocess backend
2026-09-01 11:44:16 +08:00
Chinesezjc
6e5ed52aed fix(ui-tool): address review wording and JSDoc accuracy on the image card 2026-09-01 11:43:26 +08:00
Chinesezjc
666bd48eae fix(ui-tool): scope the image-card path fallback to nested calls; repair merge-broken docs and snapshot fixtures 2026-09-01 11:40:21 +08:00
fz
cf7b0bd5a4 feat(headless): expose web fetch by default 2026-09-01 11:40:10 +08:00
Chinesezjc
a0c0b55c8a Merge remote-tracking branch 'origin/master' into feat/code-runtime-python-backend
# Conflicts:
#	packages/experimental/code-runtime-python/package.json
2026-09-01 11:29:10 +08:00
Turtle
d68ff7e66f Merge remote-tracking branch 'origin/master' into turtle/omit-unneeded-invariants
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/session/session-projection/src/invariant.ts
#	tsconfig.base.json
2026-09-01 11:18:11 +08:00
fz
b5c61b613a Merge remote-tracking branch 'origin/master' into feat/sdk-default-web-fetch 2026-09-01 11:13:00 +08:00
_Kerman
5dd876025d Merge pull request #2907 from deepseek-harness/xtr/session-log-read-api
perf(session): separate indexed and snapshot log reads
2026-09-01 10:49:54 +08:00
imccyu
dd6322d604 Merge pull request #3387 from deepseek-harness/release/dsh-0.1.2-alpha.3
release: dsh@0.1.2-alpha.3
2026-08-31 23:53:17 +08:00
imccyu
14bab4422b release(dsh): 0.1.2-alpha.3 2026-08-31 23:39:37 +08:00
imccyu
8b4b815e7e Merge pull request #3384 from deepseek-harness/worktree-connerr
fix(connection): avoid disconnecting during host stalls
2026-08-31 22:43:12 +08:00
imccyu
8372c3e188 Merge pull request #3383 from deepseek-harness/worktree-shikiperf
perf(ui-primitives): defer offscreen syntax highlighting
2026-08-31 22:41:45 +08:00
imccyu
ddecdf6b33 test(web): wait for settled background job 2026-08-31 22:30:51 +08:00
imccyu
49bf26a794 fix(connection): tolerate stalled hosts 2026-08-31 22:17:39 +08:00
imccyu
07be260245 test(ui-primitives): cover lazy viewport highlighting 2026-08-31 22:11:39 +08:00
imccyu
faa61ada74 perf(ui-primitives): defer offscreen syntax highlighting 2026-08-31 21:58:22 +08:00
Chinesezjc
6ce131c4f4 Merge remote-tracking branch 'origin/master' into feat/code-runtime-python-backend 2026-08-31 21:41:18 +08:00
imccyu
94bbfb95e8 Merge pull request #3379 from deepseek-harness/schedule-catalog-left-alignment
fix(web): align Schedule catalog within viewport
2026-08-31 20:53:40 +08:00
_Kerman
ad02fa37b4 Merge remote-tracking branch 'github/master' into xtr/session-log-read-api 2026-08-31 20:50:19 +08:00
imccyu
76557f4899 Merge pull request #3328 from deepseek-harness/worktree/navbar-pagination-interaction-24d006
feat(web): navigate every session turn from the chat rail
2026-08-31 20:45:45 +08:00
imccyu
9ba9a35c72 test(session-projection): cover view transition matrix 2026-08-31 20:30:43 +08:00
fz
ca723d9273 feat(sdk): expose web fetch by default 2026-08-31 20:18:50 +08:00
imccyu
6f0daff1dd fix(session-projection): compare observed live views 2026-08-31 19:59:54 +08:00
Yichen Jiang
12bef3b577 perf(session-projection): memoize raw views by state identity
Review follow-up: the per-step gate recomputed view(previous) on every
changed apply — a property read for identity-stable views, but a fresh
throwaway object per change for computing views. The registry now keeps a
WeakMap from state object to raw view: the previous state's view was
cached when that state was current, so each distinct state's view computes
exactly once (gate and snapshot share the memo) and the quiet path
allocates nothing. Unlike the earlier lastView record, an entry is keyed
by the state itself — the view of that exact state by the pure-view
contract — so no stamping discipline exists to get wrong. Primitive
states bypass the WeakMap and compute directly.
2026-08-31 19:46:56 +08:00
Yichen Jiang
a2437db180 revert(session-projection): drop the viewKey token, keep the per-step raw-view gate
Review consensus: for the only declaring unit the token function was
literally the view function, so the extra wire member bought nothing —
default raw-view comparison produces the identical Object.is on
state.turns at the identical cost (one property read per side). The
per-step gate stays: it holds the no-stored-baseline property, and its
measured overhead (~ns per changed state) is four orders of magnitude
below the push path it guards.
2026-08-31 19:46:56 +08:00
Yichen Jiang
f2e4078d8c docs(session-projection): carry viewKey through the subsystem type fences 2026-08-31 19:46:56 +08:00
Yichen Jiang
9836fdbbd7 docs(session-projection): describe the change feed by its viewKey token 2026-08-31 19:46:56 +08:00
Yichen Jiang
acc23f6d9c feat(session-projection): unit-declared viewKey change token
Review follow-up (imccyu): comparing view(previous) recomputes the view on
every quiet change. The wire block now takes an optional viewKey(state)
declaring the cheap comparison token; the drive compares tokens across the
previous and next states and calls view only for an actual push. Default
stays the raw view output. turnOutline declares viewKey: state => state.turns,
making the identity-stable-turns convention an explicit contract; the
registration erasure forwards viewKey (dropping it silently reverted the
gate to the fallback, caught by the new view-call-counting test).
2026-08-31 19:46:55 +08:00
Yichen Jiang
9069a8b6f8 refactor(session-projection): compare per-step views instead of storing a dedup baseline
Review suggestion (imccyu): the drive holds both the previous and next
state, so the identity gate can compute view(previous) and view(next) in
the driving step and compare them directly. The stored lastView cell field
and its stamp-on-every-change rule are deleted; with no dedup memory,
nothing can go stale across listener generations by construction, and a
rebuilt cell no longer pushes an unchanged view on its first live event.
Costs one extra pure view() call per changed state.
2026-08-31 19:46:55 +08:00
Yichen Jiang
e71db15d1a chore(release): align session-turn-outline with root 0.1.2-alpha.2, mark mirrored preview clone
The dsh 0.1.2-alpha.2 release bumped every workspace after this branch
forked, so the new package failed the workspace version constraint in the
merge tree. The bounded preview() also grew identical enough to its
deliberate host/client mirror to trip clone detection; the client copy now
carries a jscpd ignore region naming the wire-boundary rationale.
2026-08-31 19:46:55 +08:00
Yichen Jiang
b7053eba79 refactor(session-turn-outline): bound oversized preview blocks, degrade malformed previews
preview() now slices a single text block to limit * 2 before joining and
normalizing, so one multi-megabyte block no longer pays a full-string pass;
the host projection and the client turn-navigation helper stay mirrored.
outlineEntry keeps dropping entries with damaged turn/seq (marks cannot
exist or jump without them) but degrades malformed prompt/response
previews to empty strings so the turn stays navigable.
2026-08-31 19:46:55 +08:00
Yichen Jiang
8322f804cb fix(session-projection): advance the view dedup baseline on every change
The change feed stamped lastView only when a listener was subscribed, so a
value change during a listener-free window (HMR swap) froze the baseline
and a later transition back to the old value was silently deduplicated.
The baseline now advances on every changed state, heard or not; broadcast
still only happens with listeners. Docs, catalog, and the feature note
follow the corrected semantics.
2026-08-31 19:46:55 +08:00
Yichen Jiang
39b90961c7 fix(ui-chat): hold jumps while a plain pull owns the pager
A jump clicked while the Load-earlier pull was in flight fell through the
settle effect's nearest-turn fallback and landed on the wrong row. The
effect now keeps the pending jump (busy pulse stays) while loadingOlder is
true and a retry tick re-issues loadThrough when the pull settles.

Also repins the long-interactions e2e rail block to the outline-rail
semantics (fixed mark pitch, load-and-jump labels) and covers the
loadThrough forwarding paths in apply-inject and the client-runtime stub.
2026-08-31 19:46:55 +08:00
Yichen Jiang
db5417ff6f fix(session-controller): keep refused jumps from parking a stale target
loadThrough now assigns its low-water target only when it owns the loop
(retargeting stays inside the running-jump branch): a call refused while
a plain load-earlier pull holds the pager no longer leaves jumpTargetSeq
behind to drag a later jump all the way to the head. The loop also
carries the doOpen stale-pass guard so a mid-flight resync stops it
instead of paging the new stream generation toward the old target.
2026-08-31 19:46:55 +08:00
Yichen Jiang
7c58a95ebb test(session-turn-outline): cover fold edges and deflake settle assertion
Edge-branch coverage for the preview reading bound, repeated and empty
drafts, draftless turn ends, orphan-draft clearing, and same-response
recommits (the CI per-file gate exercises them); the jump-settle spec
now asserts only the busy lifecycle after settlement — jsdom's zero
geometry made the rAF active-turn resync timing-dependent under
coverage instrumentation, and the landing position contract lives in
the browser e2e.
2026-08-31 19:46:55 +08:00
Yichen Jiang
0e63841189 feat(session-turn-outline): settled-response previews at card budgets
Outline entries gain the turn's final text-bearing assistant preview:
each assistant message overwrites a state draft and turn/end commits
the survivor, matching the loaded rail's findLast semantic; the bare-
array wire keeps its identity across draft changes, so pushes stay at
three per turn. Preview budgets shrink to the rail card's clamps — one
50-character prompt line, up to three 120-character response lines,
ellipsis on clip — on loaded and unloaded turns alike (stateVersion 2
discards v1 cache rows).
2026-08-31 19:46:55 +08:00
Yichen Jiang
ceadd90e71 feat(session-projection): identity-gated change feed
The feed previously fired on every changed state reference of a
client-visible unit; it now also compares the raw view output against
the last delivered one and stays quiet when Object.is-identical, so a
unit can buffer working fields in state behind an identity-stable
projection. Units whose views build fresh objects per call are
unaffected.
2026-08-31 19:46:54 +08:00
Yichen Jiang
62f707bb1d fix(ui-chat): release bottom ownership when a jump starts
Clicking an unloaded rail mark from the pinned tail raced the pinned
scroll snap: the first prepend's compensation fires a non-reader scroll
delivery, the snap called toBottom, and toBottom cancels a pending jump
— so the jump silently stayed at the tail while history loaded. The
click now drops atBottom itself (jumping into history is leaving the
live tail), pinned by a jsdom regression and re-verified live: a
118-turn session lands on turn 1 in ~250ms from click.
2026-08-31 19:46:54 +08:00
Yichen Jiang
422b603874 docs: turn outline rail contracts and agent note
READMEs record the rail's outline merge and the loadThrough paging
verb in both languages; the feature Agent Note owns the decision,
alternatives (sparse windows, minSeq wire bound, outline RPC, height
estimation), and coverage map. Regenerates the client/API catalogs the
widened faces feed.
2026-08-31 19:46:54 +08:00
Yichen Jiang
3a834fe6c9 feat(ui-chat): settle jump landings after paging completes
A mid-paging landing keeps the jump armed with the target row as its
paging anchor, so later chunks and the load-earlier button's unmount
cannot drift the landing; the loader's completion runs one final
correction unless the reader already scrolled off the target. Adds the
browser contract: full outline ladder, keyboard jump on an unloaded
mark, landing geometry, and rail fades.
2026-08-31 19:46:53 +08:00
Yichen Jiang
6af1ee49b1 feat(ui-chat): scrollable fixed-pitch turn rail
Marks keep a fixed 10px pitch instead of compressing into the frame:
overflow scrolls inside a hidden-scrollbar scroller with gradient fades
over each still-scrollable end, the preview compensates the rail scroll,
and the active mark keeps itself centred while the pointer is off the
rail. Pointer-to-mark mapping now works in ladder coordinates.
2026-08-31 19:46:53 +08:00
Yichen Jiang
b3064cca77 feat(ui-chat): full-session turn rail with load-and-jump
The rail now merges the turnOutline projection with loaded-window items
(view-layer only; loaded wins, outline fills mid-turn prompt previews),
renders unloaded turns as dimmer marks, and clicking one holds the
reader's place, pages history through the turn's seq, and lands on its
row after the commit — no height estimation. Settlement repages once
per head movement, then falls back to the nearest rendered turn.
2026-08-31 19:46:53 +08:00
Yichen Jiang
218bb7f645 feat(session-controller): loadThrough deep history paging
Session.loadThrough(seq) loops the existing prepend pager (200-message
pages) until the window covers the target seq, with a shared low-water
retarget for repeated calls, a no-progress guard against empty pages
still claiming history, and loadOlder's fail-soft error posture. Busy
state rides the existing loadingOlder snapshot bit.
2026-08-31 19:46:53 +08:00
Yichen Jiang
7e2eacb1fe feat(session-turn-outline): whole-log turn outline projection
New turnOutline projection unit serving every started turn's number,
turn/start seq, and bounded first-prompt preview through the
session-projection seam, mounted in the web-app bundle for the chat
turn rail. Entries stay strictly increasing; previews mirror the rail's
loaded-turn preview budget.
2026-08-31 19:46:53 +08:00
pku-xht
faa977fb29 fix(web): align Schedule catalog within viewport 2026-08-31 18:59:28 +08:00
Chinesezjc
a8d8b8cddd docs(code-runtime-python): sync hostFrameParseCeiling example numbers to the 16x multiple
The hostFrameParseCeiling JSDoc and one load-gate test comment still quoted
the pre-16x derivation (~29 MiB for a ~300 MiB heap, ~14 MiB for a 128 MiB
old space). With HOST_PARSE_WORST_CASE_MULTIPLE = 16 the same hosts derive
~14 MiB and ~7 MiB (floor((176-64)/16)); protocol.spec.ts pins the 304 MiB
case at 15 MiB. Comment-only correction, no behavior change.
2026-08-31 18:57:34 +08:00
imccyu
eca3bda903 Merge pull request #3374 from deepseek-harness/hl-perf
fix(web): make streaming code fences incremental
2026-08-31 18:49:03 +08:00
Chinesezjc
56ca8af0ee feat(ui-tool): render the image card for nested read_image calls 2026-08-31 18:14:08 +08:00
07akioni
d8e2ac5052 fix(web): retain completed streaming fence lines 2026-08-31 18:11:32 +08:00
Chinesezjc
974fca9f5a fix(code-runtime-python): restore oxlint suppressions lost in the #3289 merge-forward and re-pack the ptc-python fixture
The #3289 merge-forward dropped four typescript/no-unnecessary-condition
suppressions from index.ts (boot-write-failure fake child stdin, the
admit()-closure logsTruncated recheck, and both settled rechecks whose
guards flip mid-wait), turning the lint:contracts-ready gate red. Re-add
them with their reasons. The merge also carried a ptc-python-turn session
fixture that was not in canonical packed layout; migrate-packed-session-fixtures
re-writes it so session-fixture-layout passes.
2026-08-31 17:52:25 +08:00
Turtle
79e388547c Merge remote-tracking branch 'origin/master' into turtle/omit-unneeded-invariants 2026-08-31 17:45:29 +08:00
_Kerman
febafc7ee0 fix(test): cover indexed session reads 2026-08-31 17:43:17 +08:00
Ziya
2480bdf27a feat(web): clarify Workspace Write Chinese label (#3345)
Co-authored-by: ZiyaZhang <199893125+ZiyaZhang@users.noreply.github.com>
2026-08-31 09:42:16 +00:00
Tianyi Cui
50b6be997d Merge pull request #3289 from deepseek-harness/worktree/pr1148-runtime-contract-fixes
fix(code-runtime): settle Python provider contracts
2026-08-31 17:30:15 +08:00
07akioni
1dd3e60f50 fix(web): make streaming code fences incremental 2026-08-31 17:26:04 +08:00
_Kerman
687ae5c9c0 Merge remote-tracking branch 'github/master' into xtr/session-log-read-api
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.md
#	.agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.zh.md
#	.agents/notes/implemented/feature/2026-08-05-context-form-vocabulary.i18n.yaml
#	.agents/notes/implemented/feature/2026-08-05-context-form-vocabulary.md
#	.agents/notes/implemented/feature/2026-08-05-context-form-vocabulary.zh.md
#	packages/examples/agent-spine-demo/tests/agent-core.spec.ts
#	packages/skill/tool-skill/tests/tool-skill.spec.ts
2026-08-31 17:19:59 +08:00
Turtle
c6e6f4f460 fix: retain invariant host lint suppression 2026-08-31 17:16:58 +08:00
Tianyi Cui
01141e619a Merge latest #1148 into #3289 2026-08-31 17:11:37 +08:00
Chinesezjc
5bb2c46453 Merge branch 'master' into feat/toolcard-image-result 2026-08-31 17:11:15 +08:00
Tianyi Cui
d87b755e37 Merge origin/master into feat/code-runtime-python-backend 2026-08-31 17:11:11 +08:00
Turtle
01a8882601 fix: complete invariant omission cleanup 2026-08-31 17:10:53 +08:00
Turtle
a7f5b6e638 Merge remote-tracking branch 'origin/master' into turtle/omit-unneeded-invariants 2026-08-31 17:01:06 +08:00
Tianyi Cui
d15610a66b test(snapshot): refresh Python PTC fixture for latest master 2026-08-31 17:00:18 +08:00
Turtle
713ae6c29b Merge pull request #3360 from deepseek-harness/turtle/pr-open-start-date
feat(issue-management): initialize Issue start dates on PR open
2026-08-31 16:48:47 +08:00
Tianyi Cui
dc5cc0d575 test(code-runtime-python): align PATH rejection diagnostic 2026-08-31 16:47:26 +08:00
imccyu
60a46b9f5d Merge pull request #3331 from deepseek-harness/worktree-chatctxmemory
perf(web): reduce retained conversation state
2026-08-31 16:41:11 +08:00
Tianyi Cui
ba0609571f Merge #1148 validation corrections into #3289
# Conflicts:
#	packages/experimental/code-runtime-python/tests/runtime.spec.ts
2026-08-31 16:29:52 +08:00
Chinesezjc
8fb9bc29e9 Merge branch 'master' into turtle/pr-open-start-date 2026-08-31 16:27:41 +08:00
Tianyi Cui
f14189cf8c chore(deps): refresh Python runtime lock importer 2026-08-31 16:27:40 +08:00
Tianyi Cui
04aee12cc2 test(code-runtime-python): align macOS runtime expectations 2026-08-31 16:26:39 +08:00
Chinesezjc
c5a94f11df Merge pull request #3354 from deepseek-harness/fix/windows-coverage-flaky-test-budgets
test: stabilize the Windows coverage lane against timing flakes
2026-08-31 16:11:55 +08:00
Chinesezjc
8ace43a8b1 Merge pull request #3364 from deepseek-harness/fix/notices-serial-windows-timeout
fix(ci): serial-windows notices timeout and generator store-scan cost
2026-08-31 16:10:47 +08:00
Tianyi Cui
4e2c568efe Merge corrected #1148 checkpoint into #3289
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.zh.md
#	packages/experimental/code-runtime-python/README.i18n.yaml
#	packages/experimental/code-runtime-python/README.md
#	packages/experimental/code-runtime-python/README.zh.md
#	packages/experimental/code-runtime-python/src/index.ts
#	packages/experimental/code-runtime-python/tests/runtime.spec.ts
2026-08-31 16:10:13 +08:00
Tianyi Cui
61b3e06e97 fix(code-runtime-python): preserve post-merge hardening 2026-08-31 16:03:32 +08:00
Chinesezjc
4f877cdab1 Merge branch 'master' into fix/notices-serial-windows-timeout 2026-08-31 15:55:59 +08:00
Tianyi Cui
d6bd5eb973 fix(code-runtime): bound interpreter version probe 2026-08-31 15:55:05 +08:00
Tianyi Cui
711ec7ffac test(snapshot): canonicalize Python PTC fixture 2026-08-31 15:50:45 +08:00
Tianyi Cui
7f84a825c9 fix(code-runtime): settle Python provider contracts 2026-08-31 15:50:45 +08:00
imccyu
d7abd0a01e fix(web): activate selected view for blank sessions
fix(web): activate selected views before blank gating
2026-08-31 15:45:26 +08:00
Chinesezjc
a00c9a062c Merge branch 'master' into fix/windows-coverage-flaky-test-budgets 2026-08-31 15:45:19 +08:00
imccyu
4b21065dbe refactor(client): share conversation context initialization 2026-08-31 15:44:23 +08:00
imccyu
4203317e18 perf(client): materialize conversation targets on demand 2026-08-31 15:44:23 +08:00
imccyu
354bf44923 fix: ci 2026-08-31 15:44:23 +08:00
imccyu
b4527bedc7 fix(client): pin inbox claim semantics 2026-08-31 15:44:22 +08:00
imccyu
61da6fbbe5 perf(web): defer tool body formatting until expansion 2026-08-31 15:44:22 +08:00
imccyu
8478de9b0e perf(client): linearize inbox projection state 2026-08-31 15:44:22 +08:00
Chinesezjc
a074e6131f fix(ci): serial-windows notices timeout and generator store-scan cost
render() loaded the workspace manifests once per external dependency
name through workspaceLinkedManifest, an O(names x manifests) file
read on the cold path; on the loaded self-hosted Windows host with
coverage instrumentation the freshness spec crossed Vitest's default
5000ms budget and failed the serial-windows standby gate four times in
a week. Load the manifests once in render() and thread the map through
the collectors instead.

The serial-windows lane also ran the coverage inventory at the strictest
budget of any lane: add DSH_COVERAGE_TEST_TIMEOUT_MS=90000 to match the
pull-request windows-coverage lane, pinned by ci-workflow.spec.ts.
2026-08-31 15:33:16 +08:00
Chinesezjc
8e9d5467b0 fix(code-runtime-python): bound reply and call backlogs, snapshot binding metadata, and compact the reply queue
Review findings on the CPython backend: a child that never reads fd 3 leaves
the reply pipe full forever, so the drain loop waits on 'drain' while every
call frame it keeps sending resolves a binding and queues another reply —
the backlog (and the binding results it pins) would grow until the wall
clock. sendReply now caps the pending backlog at MAX_PENDING_REPLIES and
settles the run as worker-exit past it, mirroring the frame cap; a child
flooding calls against a binding that never settles would otherwise bypass
that cap (pendingReplies grows only after the await), so the dispatcher
counts in-flight binding calls before dispatch and releases the slot in the
async body's finally, capping outstanding closures at the same bound. The
drain also compacts its consumed prefix (replyQueue.splice(0, head)) once
head reaches the bound, so a drain that stays alive without emptying cannot
grow the backing store linearly with cumulative throughput.

The completion-value meter counted lone surrogates with
_SURROGATE.findall(folded), materializing one single-character string per
surrogate: a surrogate-dense value near the budget (millions of surrogates,
each serializing to six bytes) allocated millions of objects before the meter
returned, defeating the meter's counting-without-building contract. The count
is now the length difference between folded and the without string the meter
already computes; a standalone equivalence check confirms it matches findall
across lone-high, lone-low, paired, astral, and mixed cases.

validateBindings read namespace.global/errorClass.name/memberNameProperty
several times and retained the original errorClass object for the boot
frame, whose JSON.stringify re-read it after validation: a stateful getter
could throw or change between the two stages, turning the seam-misuse
rejection into a worker-exit or injecting an unvalidated name. Each field is
now read once into a plain value and the bindings map stores a plain
{ name, memberNameProperty } copy, so validation and the boot frame see
identical values.

Regression tests: a hostile child floods 5000 sequential valid calls without
reading fd 3 and the run settles worker-exit with the reply-queue message
before maxWallMs; a 3,000,000-surrogate completion succeeds at an
18,000,002-byte budget and reports output-limit one byte under; a 5000-call
flood against a never-settling binding settles worker-exit with the
call-backlog message; getter-backed namespace metadata that throws or
changes on a second read boots and runs with each field read exactly once; a
two-wave flood whose replies exceed the writable high-water mark drives the
drain past the compaction bound mid-delivery and verifies all 1524 replies
arrive. README Known Limitations gains the reply-backlog and call-backlog
bounds (en/zh, pairing re-recorded); a new Agent Note registers the findings.
2026-08-31 15:25:26 +08:00
Chinesezjc
b75eec0967 docs(doc-graphs): list the experimental Python backend as a codeRuntime implementation
The capability-seams graph derives its implementation lists from
SERVICE_ROLES in scripts/gen-doc-graphs.ts, which still listed only the
worker-thread backend. Add experimental-code-runtime-python so the
generated graph and table match the registered ctx.codeRuntime
implementations; regenerate docs/capability-seams.md, sync the zh pair,
and re-record the i18n pairing.
2026-08-31 15:25:26 +08:00
Chinesezjc
2df28fd249 fix(code-runtime-python): validate explicit pythonBin at load, snapshot bindings, and settle the reply drain
Review findings on the CPython backend: an explicit pythonBin path bypassed
the load-time checks (missing/non-executable/directory paths surfaced only
as a run-time worker-exit); a throwing binding member accessor escaped the
fd-3 data callback and terminated the host; the reply drain waited on
'drain' alone, so a pipe destroyed under the wait hung forever; and two
staging-leak assertions diffed a global tmpdir that parallel workers can
perturb.

resolvePythonBin now applies the same accessSync(X_OK) + isFile check to
explicit paths (resolved against the host CWD), and the load error message
distinguishes 'is not an executable regular file' from 'does not resolve on
PATH'. validateBindings snapshots callables into a plain record during run()'s
synchronous validation, turning an accessor throw into the seam-misuse
rejection and fixing the key set the boot frame and dispatch share. The reply
drain waits on drain/close/error together and short-circuits on
proto.destroyed. The staging-leak assertions check the exact paths this test
file staged (recorded by the mocked mkdtempSync) instead of a tmpdir diff.

docs(code-runtime-python): add the alternatives section to the hardening note

docs(config-catalog): refresh the code-runtime-python Config source line

test(code-runtime-python): cover the async spawn-error worker-exit path
2026-08-31 15:25:26 +08:00
Chinesezjc
2c8d545524 docs(experimental): list code-runtime-python in the group README; state the portable note as current fact
The review's items: the experimental group README's Packages table and Summary
now list code-runtime-python (CPython subprocess backend, ctx.codeRuntime),
paired; the portable-identifier note's Scope drops the 'has since shipped …
now lists' change narration in favor of the current state, removing the
apparent contradiction with 'the worker is the only shipped backend'.
2026-08-31 15:20:50 +08:00
Chinesezjc
c435170a93 docs(code-runtime): drop the remaining shipped claims for the private experimental backend
The review's final wording items: the portable-identifier note's Scope said the
backend 'has since shipped' without noting it is experimental/private; the
RESERVED_WORDS JSDoc said backends 'ship for both languages'. Both now name the
TypeScript backend as released and the CPython backend as experimental and
private. The package README also records that the truncation-marker text and
tempdir prefix keep the pre-rename short names (byte-anchored by tests,
independent of the npm name).
2026-08-31 15:19:22 +08:00
Chinesezjc
12d0bdb274 docs(code-runtime): stop calling the private experimental Python backend published
The review's carry-over: 'each has a published backend' in the CodeRuntime
JSDoc and its projections (tool-cordis api-catalog, subsystems page) plus
'both shipped'/'backends ship' in the code-runtime README all claimed the
Python backend is released; it is private and experimental, excluded from the
release family. The wording now states the TypeScript backend is released and
the Python backend is experimental and private (not published), in the JSDoc
(api-catalog regenerated to match), the READMEs (paired), and the subsystems
page (paired).
2026-08-31 15:17:56 +08:00
Chinesezjc
732a54f85b docs(code-runtime-python): fix note status grammar and paragraph wrap
The fd-3 note's Status line moved off line 3 when the experimental-location
fact was added; it is back as the sole line-3 status. The zh portable-identifier
note's merged Scope paragraph lost its blank-line separator, which the
md-wrap gate read as one hard-wrapped paragraph — the blank line is restored.
2026-08-31 15:16:24 +08:00
Chinesezjc
2504d0a501 fix(code-runtime-python): complete the experimental move across configs and docs
The review's move-follow-ups: the Windows test exclude now points at
packages/experimental/code-runtime-python (the constructor throws by design on
Windows, so the suite must stay excluded); the invariant companion and
@module annotations use the new npm name; the truncation marker text and
tmpdir prefix stay as-is (tests anchor them); the package JSDoc and READMEs no
longer call the private experimental backend 'published'/'shipped'; the
code-runtime README row describes the package as protocol AND runtime; the
fd-3 note records the package's experimental location.
2026-08-31 15:15:08 +08:00
Chinesezjc
d7eb7f4418 fix(code-runtime-python): finish the experimental move — invariant name and tsconfig aliases
The move broke two generated/derived surfaces: (1) the package invariant
companion still registered the old name
@deepseek-ai/dsh-code-runtime-python, so the exhaustive-topology test found
the new name unreserved — it now registers
@deepseek-ai/dsh-experimental-code-runtime-python; (2) the tsconfig.base.json
alias for the renamed package sat inside the generated region, so
gen-tsconfig-paths dropped it (a package named after something other than its
directory needs a hand-written alias before the BEGIN marker) — the alias is
moved out and the config is current again.
2026-08-31 15:13:55 +08:00
Chinesezjc
053d17f6a1 refactor(code-runtime-python): move the package into packages/experimental
The CPython code runtime's complete public contract is experimental, so it
moves to packages/experimental per the experimental-packages rules: npm name
@deepseek-ai/dsh-experimental-code-runtime-python, private: true, no
publishConfig. All references updated (code-runtime READMEs, config-catalog
and module-graph regenerated with zh alignment, tsconfig paths, doc-standard
and workspace-constraints scripts, the fd-3 and settlement Agent Notes, and
the package README links); md-links and translation pairing pass, and the
suite still runs green.
2026-08-31 15:13:55 +08:00
Turtle
49f1d1bd9a Merge remote-tracking branch 'origin/master' into turtle/pr-864-master-port 2026-08-31 15:12:15 +08:00
Xu Hanxiang
dc3984204d Merge pull request #3288 from deepseek-harness/issue-3135-tab-completion
fix(client): complete highlighted commands with Tab
2026-08-31 15:11:36 +08:00
Chinesezjc
45cfc9cfaf docs(code-runtime-python): sync the Consequences enumeration to eleven no-fail-before fixes
The review's item: the Problem section counts eleven no-fail-before fixes, but
the Consequences section still said 'the ten called out in the Problem section'
(zh: '那十处') and omitted the new unknown-binding preview cap. Both sides now
say eleven and name the cap, paired and re-recorded.
2026-08-31 15:09:28 +08:00
Chinesezjc
200703a20d docs(code-runtime-python): list the unknown-binding preview cap as the eleventh no-fail-before fix
The review's warning: the settlement note's Problem paragraph says ten fixes
have no fail-before test, but the unknown-binding preview cap (a transient
whole-target JSON.stringify peak, unmeasurable through the seam) is the
eleventh. The count and the item are now recorded, paired.
2026-08-31 15:09:28 +08:00
Chinesezjc
391e29ec8a docs(code-runtime-python): register the unknown-binding preview cap in the settlement note
The review's suggestion: the settlement note enumerates each review fix in this
PR, so the unknown-binding preview cap (escaped from a 1 KiB prefix,
capMessage still enforces the reply budget) gets its own short section, paired
and re-recorded.
2026-08-31 15:07:40 +08:00
Chinesezjc
a6678610b8 fix(code-runtime-python): cap the unknown-binding preview before JSON.stringify
The reviewer's standing item: the unknown-binding reply ran JSON.stringify on
the WHOLE capped target (global + '.' + name, each up to maxValueBytes code
units), allocating the escaped form — up to ~6x under control-heavy input, a
multi-hundred-MB spike near the maxValueBytes ceiling that no hostile-peer
bound would have admitted. The escaped preview is now built from a 1 KiB
prefix of the target (enough to identify the binding); capMessage still
enforces the reply budget. A forged huge-name case drives the path.
2026-08-31 15:06:50 +08:00
Chinesezjc
6719e287de docs(code-runtime-python): state the layer-5 deferral as current fact, not PR history
The review's wording item: the layer-5 bullet ended with 'not by this PR'
(zh: 'not borne by this PR'), which references PR context in durable prose.
The sentence now ends with the current-state fact ('not by this package's
suite'), paired and re-recorded.
2026-08-31 15:06:50 +08:00
Chinesezjc
80ceb4ec5f docs(code-runtime-python): register the layer-5 assembly snapshot deferral
The review's open suggestion: the Known Limitations now records that the
real-Loader assembly snapshot is deferred to issue #1182 layer 5 (this package
is exercised through ctx.plugin and real-subprocess tests; the full application
composition is covered by a tracked assembly test in that layer), paired.
2026-08-31 15:06:50 +08:00
Chinesezjc
771872a73d test(code-runtime-python): cover the finish-residual sealed side; use a block array for the open seal
The review's two remaining non-blocking items: (1) a case where the run ends
with a SEALED open hold (past MAX_PENDING_CHUNKS) — finish() must commit the
sealed prefix, verified to fail if finish drops openSealed. (2) openSealed is
now a block ARRAY (one joined block per seal) matching the fd-3 reader's
blocks and the stray capture's seal, instead of one repeated string concat
that leaned on V8 ConsString amortization.
2026-08-31 15:06:50 +08:00
Chinesezjc
74e9d97e37 docs(code-runtime-python): register the host-side open seal; note the empty-first-frame billing
The review's follow-ups on the open-seal fix: (1) the settlement note's seal
section now records the HOST-side open hold seal (openParts -> openSealed,
mirroring the child _LogStream and stray-capture seals), paired. (2) the
first-fragment guard comment notes the empty-first-frame case (bills cost + 1 =
3, establishes no hold, bounded over-charge in the safe direction). (3) a
regression case commits a SEALED open hold before the truncation marker —
verified to fail if truncateLogs drops openSealed.
2026-08-31 15:06:50 +08:00
Chinesezjc
bca392e6d1 fix(code-runtime-python): seal the open hold past MAX_PENDING_CHUNKS
The review's warning: each held open fragment is a distinct array slot plus
string object header (~30x overhead the byte cap cannot see), and a
budget-sized single-character open flood is honest-child reachable
(print('x', end='', flush=True) in a loop). With maxLogBytes near its ~67 MB
load ceiling that was up to ~2 GB of host auxiliary heap. The hold now seals
into one block past MAX_PENDING_CHUNKS, mirroring the fd-3 reader's blocks and
the stray capture's seal; the merge, truncateLogs, and the finish residual all
read sealed + current fragments, and a within-budget flood regression asserts
the merged entry is byte-identical.
2026-08-31 15:06:05 +08:00
Chinesezjc
953dd2d9b8 docs(code-runtime-python): align three stale comments with the shipped code
The review's wording items: the load-check comment still referenced the
resolvePythonBin JSDoc's old ENOENT promise; the spawn-site comment called the
type assertion a non-null assertion; and two comments claimed the
'logs serialize to maxLogBytes + marker + envelope' bound is recorded in the
README's Known Limitations, which has no such entry — the cross-references are
dropped, the bound stays stated inline.
2026-08-31 15:06:05 +08:00
Chinesezjc
fcf4e5463a docs(code-runtime-python): declare detachResidual in the public surface
The review's carry-over: detachResidual (a test seam for the settled run's
resource cleanup) is re-exported from the '.' entry but was not in the README's
declared public surface; the list now names it alongside resolvePythonBin and
readProcessStart, paired.
2026-08-31 15:06:05 +08:00
Chinesezjc
ca0e3e573e docs(code-runtime-python): drop the fixed empty-open limitation; declare the test helpers
The empty-open continuation skip (5b61a8fe6) made the Known Limitations entry
stale — the held fragment array no longer grows per empty frame — so the entry
is removed on both sides. The public-surface list now declares
resolvePythonBin and readProcessStart, which the '.' entry re-exports for the
test suite.
2026-08-31 15:06:05 +08:00
Chinesezjc
716060a04a test(code-runtime-python): cover the zero-content open-continuation skip
The skip branch (an empty open continuation is not pushed into the hold) needs
coverage; a case drives an empty continuation between a first fragment and the
closing frame and asserts the merged entry is unchanged.
2026-08-31 15:06:05 +08:00
Chinesezjc
d9ed44d62c fix(code-runtime-python): skip zero-content open continuations in the hold; correct the spawn comment
The review's items: a zero-content open continuation bills 0 but still pushed
'' into the held fragment array, so a forged empty-open flood grew host memory
without touching the ledger — the push is now skipped (an empty fragment
contributes nothing to the merged entry). The spawn-site comment said a PATH
change between load and run would fail with ENOENT; it actually makes spawn
throw synchronously, which the surrounding try settles as worker-exit.
2026-08-31 15:06:05 +08:00
Chinesezjc
3151ecb848 docs(code-runtime-python): state the pythonBin load rejection in the README and the load-check comment
The review's warning: the pythonBin load-rejection is a product-visible change
(unresolvable basename now fails at load instead of a run-time worker-exit),
but the READMEs (en + zh) only said the basename is resolved against PATH, and
the load-check comment still described the old fallback. The README pythonBin
entries and the load-check comment now state the rejection; pairing
re-recorded.
2026-08-31 15:06:05 +08:00
Chinesezjc
f931c2128a docs(code-runtime-python): register the pythonBin load-rejection change; harden PYABS
The review's follow-ups: (1) the product-visible change (an unresolvable
basename pythonBin now fails at load instead of a run-time ENOENT worker-exit)
is registered in the settlement note, paired. (2) PYABS falls back to the bare
name when python3 is not resolvable, instead of interpolating the literal
'undefined' into the wrappers.
2026-08-31 15:06:05 +08:00
Chinesezjc
80e13b3446 fix(code-runtime-python): align the resolvePythonBin docs and the exception-group guard
The review's follow-ups on the pythonBin change: (1) the JSDoc and the two
call-site comments still described the old fallback-to-bare-name contract;
they now state the load-rejection behavior. (2) the ExceptionGroup case's
version guard raised a skip message on Python < 3.11 but the assertion still
required the truncation marker unconditionally — the assertion now matches
either the truncation marker (3.11+) or the skip message (3.10). (3) the shell
wrappers quote the resolved interpreter path.
2026-08-31 15:05:23 +08:00
Chinesezjc
0b980bdfd1 fix(code-runtime-python): reject an unresolvable pythonBin at load; guard the ExceptionGroup case
The review's two non-blocking items: (1) resolvePythonBin returned the bare
basename when PATH had no hit, and spawn (env:{}) would silently fall to
execvp's platform default PATH and could start a system interpreter the caller
never asked for. It now returns undefined for an unresolvable basename and the
load check rejects it (absolute paths pass through), so the failure is loud at
configuration time instead of silent at spawn; the case that expected a
run-time worker-exit now asserts the load rejection, consistent with the
empty/NUL pythonBin cases. (2) the over-cap exception-group case skipped on
Python < 3.11 (ExceptionGroup is a 3.11+ builtin), matching the TaskGroup
case's version guard.
2026-08-31 15:05:23 +08:00
Chinesezjc
60b8fc00c4 test(code-runtime-python): resolve the interpreter path in the shell wrappers
The review's portability warning: the six shell wrappers exec'd a bare
'python3', which /bin/sh resolves against its compiled-in default PATH while
the runtime spawns with env:{} — in environments where python3 is reachable
only through the caller's PATH (Nix, pyenv) every wrapper run would fail as
worker-exit. The wrappers now bake the resolved absolute interpreter path
(module-level resolvePythonBin, which the product spawn already uses), and
resolvePythonBin is exported for the tests.
2026-08-31 15:05:23 +08:00
Chinesezjc
27b8f97150 fix(code-runtime-python): normalize the inherited SIGXCPU state before any CPU-consuming setup
The reviewer's residual timing item: the inherited-SIGXCPU reset ran AFTER
setrlimit(RLIMIT_CPU) and the boot-namespace construction, so a huge namespace
under an inherited ignore/block could burn past the soft limit inside that
window and be misclassified as worker-exit. The reset now happens at the very
top of _run, before the resource-limit setup and namespace construction.
2026-08-31 15:05:23 +08:00
Chinesezjc
c4fe0320fb test(code-runtime-python): drive the inherited SIGXCPU path with a wrapper; fix the zh outer wire sentence
The review's two follow-ups on the inherited-SIGXCPU fix: (1) a discriminating
case — pythonBin points at a wrapper that ignores SIGXCPU before exec'ing
python3, so the child genuinely inherits the ignore; with cpuSeconds: 1 the
busy loop must end as timeout (the bootstrap reset restored SIG_DFL), and
reverting the reset leaves it running to the wall — verified red. (2) The zh
README's OUTER wire section now carries the truncation-exception sentence
(the previous commit had duplicated it in the inner section instead); the
duplicate is removed, and the settlement note registers the inherited-SIGXCPU
reset.
2026-08-31 15:05:23 +08:00
Chinesezjc
7b9db83f86 fix(code-runtime-python): reset the inherited SIGXCPU disposition and mask at startup
The reviewer's standing issue: the child inherits the host's SIGXCPU
disposition and signal mask — if the host ignores or blocks SIGXCPU, the soft
RLIMIT_CPU fires but cannot stop the child, and the hard limit's SIGKILL then
classifies a definite CPU overrun as worker-exit instead of a timeout. The
bootstrap now resets SIGXCPU to SIG_DFL and unblocks it before any model code
runs (the settle-time enforcer already restores SIG_DFL for a program that
traps or masks the signal mid-run; this closes the inherited-state gap). The
zh README's outer wire section also gains the truncation-exception sentence to
match the en side.
2026-08-31 15:04:43 +08:00
Chinesezjc
fa0565032f docs(code-runtime-python): register the truncation exception to open merging; clean a case comment
The review's warning: the READMEs (outer and inner wire sections, en + zh) and
the fd-3 protocol note still claimed the next log frame always merges into an
open entry, while truncateLogs commits the already-billed prefix as its own
entry before the marker. The one exception (truncation) is now stated in both
READMEs and the owning note, paired and re-recorded. The prefix-commit case's
parenthetical describing the pre-fix implementation is removed per the
comment-does-not-record-review-history rule.
2026-08-31 15:04:43 +08:00
Chinesezjc
6bdbe71092 fix(code-runtime-python): drop fd-3 frames with illegal UTF-8 instead of mangling them
The reviewer's standing issue: line.toString('utf8') silently replaces illegal
bytes with U+FFFD, so a forged frame could land a corrupted completion value
(the honest child's lossless encoder never emits non-UTF-8, so such a frame is
hostile traffic). The fd-3 frame decode now uses a fatal UTF-8 decoder: an
illegal byte throws and the frame is dropped, same treatment as the
unsafe-integer check. A forged illegal-UTF-8 done frame is verified to be
dropped (the run settles on the program's real return), and reverting to
toString makes the case fail.
2026-08-31 15:04:43 +08:00
Chinesezjc
89fbe54cb1 fix(code-runtime-python): commit a flushed open prefix before the truncation marker
The review's warning: a flushed unterminated line is billed and committed
(README wire contract says so), but every truncation arm — the child truncated
frame, an over-budget open frame, an over-budget closing frame, and admit's two
budget arms — pushed only the marker, dropping the held prefix: the ledger
charged for output that vanished. All arms now funnel through truncateLogs(),
which pushes the (already billed) held prefix before the marker and clears
openParts, so the prefix survives and only the marker stays last; the finish()
guard drops the now-dead !logsTruncated check (a truncated run has an empty
hold). A regression case asserts [prefix, marker]; the forged-flood and
closing-overflow cases now expect the committed prefix plus the marker.
2026-08-31 15:04:43 +08:00
Chinesezjc
e7ac747e2d docs(code-runtime-python): register the zero-billed empty open-frame hold as a known limitation
The review's suggestion: an empty open continuation frame bills zero and holds
one host slot, so a forged empty-open flood grows the held fragment array
without touching logBudget. Accepted as a residual (per-frame host cost far
below its ~30-byte fd-3 wire cost, bounded by pipe throughput, model-code trust
level equal to bash) and now registered in the README's Known Limitations on
both sides, paired and re-recorded.
2026-08-31 15:04:43 +08:00
Chinesezjc
909d5c334b docs(code-runtime-python): restate the buffered-chunks pre-check comment as invariant-preserving
The review's revision: the buffered-chunks pre-check's open-aware overhead is
observationally inert — when the +3 form trips and the open-aware form does not
(pending + newline in [remaining - 2, remaining]), _push_bounded_prefix
re-slices the same newline-free line text and _push_locked admits it under the
same open-aware billing, byte for byte. The comment now states that the
open-aware form keeps _push_bounded_prefix's 'certain to reject' precondition
true, contrasting with the scan pre-check whose slice carries the newline and
therefore genuinely truncates.
2026-08-31 15:04:43 +08:00
Chinesezjc
fdcfec4977 docs(code-runtime-python): align the en wire-contract section with the open flag; fix the case comment
The review's warning: the en README's inner 'Wire contract' section still
described only the truncated flag while the zh counterpart (and the outer 'The
wire' section) described open. The inner en section now matches. The exact-fit
closing-line case comment described the buffered-chunks pre-check recipe while
the program actually drives the scan pre-check; the comment now states the
actual arithmetic and path (and the buffered variant was dropped — its writes
coalesce into one call in the test environment, so it did not discriminate).
2026-08-31 15:04:43 +08:00
Chinesezjc
9194dfebc8 fix(code-runtime-python): make the write-path pre-checks open-aware; document the open flag in zh
The review's warning: while an open entry accumulates, the newline pre-checks in
the write path still charged a NEW entry's +3 cheap-bound overhead (quotes +
separator), so an exact-fit merged TAIL was truncated (or the pre-check
over-rejected it and flushed a truncated prefix). Both pre-checks now charge
the overhead only when no open entry is in progress, matching _push_locked's
open-aware bound. A regression case (the review's recipe: flush an open
fragment, then write one exact-fit newline-terminated line) is verified to
truncate when the +3 is restored.

The zh README's wire-contract section now describes the open flag like the en
side (the fd-3 Agent Note holds the split-billing arithmetic; a cross-doc link
was omitted to keep the bilingual link sequence aligned).
2026-08-31 15:04:43 +08:00
Chinesezjc
371303822f test(code-runtime-python): give the first-fragment cap a discriminating case; dedupe the note
The review's warning: the one-byte overflow case ran through the CHILD ledger
(print path), so the host's first-fragment cap (logBudget - 1) never executed,
and the sub-2-byte guard test does not discriminate logBudget from
logBudget - 1 (a reverted cap still trips the guard). The frame is now forged
on fd 3, so a reverted cap of logBudget admits it and flushes it at settlement
— verified to turn the test red.

The review's dedupe suggestion: the split-billing arithmetic was stated in both
notes; the settlement note's Decision paragraph now links to the fd-3 protocol
note's wire-contract section (one home per fact), paired and re-recorded.
2026-08-31 15:04:43 +08:00
Chinesezjc
c7d2d4b8b5 docs(code-runtime-python): register the open-merge split billing in the settlement note
The review's suggestion: the settlement note's Decision section now states the
shipped split-billing fact (first fragment pays quotes+separator, continuations
and the closing frame pay content only; host caps logBudget-1 / logBudget+2;
child keys off _open_started), paired and re-recorded.
2026-08-31 15:04:03 +08:00
Chinesezjc
1097bd3c3c docs(code-runtime-python): register the open-merge split billing in the fd-3 note
The review's suggestion: the open-merge mechanism (incremental split billing on
both sides, host caps logBudget-1/logBudget+2, the sub-2-byte walk guard, the
child's _open_started-keyed billing) lived only in code comments. The wire
contract section of the note now states it, paired and re-recorded.
2026-08-31 15:03:21 +08:00
Chinesezjc
22e2dc454d test(code-runtime-python): cover the sub-2-byte guard of the exact-cost walk
The new jsonStringCostUpTo guard (returns undefined below a 2-byte cap) was
uncovered: forged open frames drive the host ledger down to one byte, and a new
open entry's first-fragment cap (logBudget - 1 = 0) trips the guard and
truncates to the marker, asserted as the merged entry plus the marker.
2026-08-31 15:03:21 +08:00
Chinesezjc
3001cc23be fix(code-runtime-python): correct the open-merge cap arithmetic on both sides
The review's arithmetic checks: the closing-frame walk used cap
logBudget - openCost, so a compliant merged entry (58-byte wire cost under a
64-byte budget) could see a negative cap and truncate; the first-fragment cap
used logBudget instead of the ledger's logBudget - 1, so an open frame costing
63 was admitted with a bill of 64, pushing the ledger negative and letting a
subsequent empty frame ride in one byte past the configured cap; and the child
billed a closing frame as a fresh entry (quotes+separator again) instead of the
merged tail, truncating an exact-fit 30+30 entry.

Fixes: first-fragment cap logBudget - 1 (matching admit), continuation and
closing-frame cap logBudget + 2 (billed without quotes), jsonStringCostUpTo
returns undefined below 2 bytes, and the child's split billing keys off
_open_started alone (a closing frame pays content only) with the cheaper bound
len(text) while a merge is open. Regression cases cover all three arithmetic
paths.
2026-08-31 15:03:21 +08:00
Chinesezjc
4fd0068fb7 fix(code-runtime-python): bill a merged open entry incrementally on both sides
The review's critical: the open-merge branch re-joined and re-walked the whole
held text per frame, so k tiny open frames cost O(k * budget) (thousands of
1-byte frames against a near-64 MiB budget would re-traverse hundreds of GB and
block the host event loop). The host now holds a fragment ARRAY with an
incrementally billed cost — each fragment's jsonStringCostUpTo walks only its
own text — and the closing frame bills only its own content, so the merged
entry's wire cost is charged exactly once, split across the fragments. The
child bills symmetrically: the first open fragment pays quotes+separator, each
continuation pays only its content, matching the host ledger (the review's
warning: per-fragment full billing truncated a 16-char merged entry under
maxLogBytes: 64 that costs only 19 bytes as one entry).

Regression cases: 16 single-character flushes merge to one whole entry; a
closing frame that overflows the remaining budget truncates to the marker; a
closing frame after an open flood already truncated the ledger is a no-op; and
a forged open-frame flood stays bounded by the ledger. The closing-frame
post-truncation guard is an invariant-false branch (an open frame that would
trip the ledger resets openParts, so a non-empty hold implies no truncation)
and carries a v8 ignore with that reason.
2026-08-31 15:03:20 +08:00
Chinesezjc
ea1d28a068 fix(code-runtime-python): bound the open-merge hold by the ledger budget
The review's critical: the open-merge branch accumulated the held fragment
before any ledger check, so a forged open flood could grow host memory without
touching logBudget. The held fragment is now bounded by the exact-cost walk
(jsonStringCostUpTo against the remaining budget; the closing frame's admit()
still bills the merged entry once), and the open field is registered in the
README wire-contract section and the fd-3 protocol note (en + zh). A forged
open-flood case asserts truncation to the marker under a 64-byte budget.
2026-08-31 15:03:20 +08:00
Chinesezjc
72691455e9 fix(code-runtime-python): merge a flushed unterminated line into the next log entry
The review's remaining warning: an explicit flush of an unterminated line
(print(..., end='', flush=True)) pushed a full log frame, so the following
print() landed in a second entry and logs.join('\n') rendered 'a\nb' for what
the program printed as one line — a model-visible output defect. The flush
frame now carries an  flag (LogMessage gains the optional field on both
sides and in the mirror test), the host holds it and appends the next log frame
to the same entry, and finish() admits the residual if the run ends with it
still open. The settlement note registers the decimal-context fix from the
previous commit.
2026-08-31 15:03:20 +08:00
Chinesezjc
35de0682c7 fix(code-runtime-python): make the float encoder context-independent; correct the binding-reply README entry
The review's critical: Decimal(repr(value)).normalize() read the process-global
decimal context, so a legitimate program setting getcontext().prec = 2 silently
rounded the completion value's digits and traps[Inexact] = True made the encode
raise, misclassifying a successful run as an exception. A fixed module-level
Context(prec=28) makes the spelling decision context-independent; a regression
case mutates both context knobs and asserts the float round-trips exactly.

The binding-reply README entry now states the fact (no seam-level cap;
maxValueBytes meters only the done frame; a wide reply is rebuilt and encoded
whole, bounded by process memory), matching the earlier reviewer wording.
2026-08-31 15:02:38 +08:00
Chinesezjc
666ff2855e docs(code-runtime-python): drop the placebo dispose test and finish the remaining doc drift
The review showed the added dispose case was a placebo (dispose in the same
tick as run means SIGTERM hits the group before the program body runs; the
group-emptied arm is already deterministically covered by the same-group
survivor case, which this removes the v8 ignore for). The test is deleted; the
stale silently-discards comment in the boundary test now says rejects; the
README Known Limitations gains the late-log-frame-drop and host-side
binding-value-memory entries. Pairing re-recorded.
2026-08-31 15:02:38 +08:00
Chinesezjc
bc08f405cc test(code-runtime-python): pin the reap-poll group-emptied arm with a dispose-timing case
The review's premise that the group-emptied arm could not be pinned was
incorrect; the same-group reap case already exercises it. This adds the missing
seam-observable case: dispose() while a setsid orphan holds the pipes and the
run is unresolved — settle kills the child, the group empties (the orphan is in
its own session), and the poll finalizes promptly instead of waiting out the
60 s grace. The v8 ignore on that arm is removed.
2026-08-31 15:02:38 +08:00
Chinesezjc
9b7b5489be fix(code-runtime-python): cover the poll-group arm and align the last frame-cap comments
The review's remaining coverage gap: the group-emptied arm of pollGroup depends
on the close-driven settle winning the race against the grace SIGKILL, a timing
interleaving no seam-observable test pins deterministically (the same-group
cases assert the settle and the reap, not this exact interleaving) — the arm
now carries a v8 ignore with that reason. The load-check comment and the
FRAME_ENVELOPE_BYTES JSDoc say rejects-as-worker-exit instead of drops.
2026-08-31 15:02:38 +08:00
Chinesezjc
d98965fbcc docs(code-runtime-python): remove the ack-gate v8 ignore and align the remaining doc drift
The forged-second-boot-ack regression makes the re-entry guard covered, so its
v8 ignore is removed. Doc drift: the python README and run() JSDoc state the
resolve-with-value/resolve-with-error contract without inversion; the README
Known Limitations gains the setsid-escaped-orphan entry (the settlement note
referenced it); the settlement note drops the stale drops/discard phrasing and
the two 256 MiB references; the fd-3 protocol zh note no longer claims the
codec is undelivered; the code-runtime seam README (en + zh) says both
backends ship. Pairings re-recorded.
2026-08-31 15:02:38 +08:00
Chinesezjc
3e0055edaf test(code-runtime-python): cover the boot-ack gate's re-entry guard and run-write failure
The review rejected the v8-ignore defense for the ack gate: a forged second
boot-ack is deterministically constructible (one os.write on fd 3) and the
run-write failure is deterministically constructible with the boot-write-failure
mock pattern. A program that forges an extra boot-ack asserts the run still
completes once (the gate does not re-send the run frame); a mocked child whose
fd-3 pipe accepts the boot frame but rejects the run write resolves a
worker-exit.
2026-08-31 15:00:33 +08:00
Chinesezjc
cb26dd3804 test(code-runtime-python): pin the directory-skip in pythonBin resolution; cover the ack gate defenses
The resolvePythonBin directory branch now has a regression: a PATH whose first
entry is an executable DIRECTORY named python3 is skipped for a later real
interpreter (fail-before: without the isFile guard the directory would be
chosen and spawn would fail). The boot-ack gate's forged-second-ack re-entry
guard and its write-failure branch are covered by v8 ignore comments (the
honest child sends exactly one ack; the write failure needs the child to exit
between ack and write).
2026-08-31 15:00:32 +08:00
Chinesezjc
2b3b7f87dc fix(code-runtime-python): send the run frame after boot-ack; reject directories in pythonBin resolution
The review's two behavior items: the run frame was written back-to-back with
the boot frame (the seam contract puts run after boot-ack, which confirms the
namespaces were accepted); it now goes out from the boot-ack handler, so a
boot failure cannot race the run frame. resolvePythonBin now requires the
candidate to be a regular file — a directory passes X_OK and would otherwise
shadow a later real interpreter. Doc spots: the load-time overflow message
says worker-exit (not stranding to the wall clock), the run JSDoc spells out
the resolve-with-error contract, the PATH-stub test removes the stale v8
ignore, and the README's binding-value bullet names serialization cost.
2026-08-31 14:59:01 +08:00
Chinesezjc
4943524278 chore: commit the master third-party notices (SDK 0.3.241)
The local machine's node_modules still links claude-agent-sdk 0.3.220, so a
local gen-third-party-notices run rewrites the file to that version; CI's
fresh install resolves the lockfile's 0.3.241 and gen expects it. The branch
adds no third-party dependencies (the schemastery workspace link is already
covered), so the notices file adopts master's 0.3.241 content.
2026-08-31 14:59:01 +08:00
Chinesezjc
981ade7611 fix(code-runtime-python): restore the runtime's cross-package dependency declarations
The earlier merge had adopted master's protocol-only package.json (peer/dev
limited to invariants and cordis, no dependencies), but src/index.ts imports
@deepseek-ai/dsh-code-runtime, dsh-session, dsh-timeout, and schemastery at
runtime — a published lib/index.js could not resolve those bare specifiers.
The manifest now mirrors code-runtime-worker-thread (the five peers, the
schemastery dependency, and the matching dev set); the lockfile, module graph,
and third-party notices are regenerated, and the module-graph zh pair is
re-synced.
2026-08-31 14:59:01 +08:00
Chinesezjc
aa123becf1 chore: regenerate the module graph after the sdk-runtime manifest change
Dropping the code-runtime-python peer from sdk-runtime changed the dependency
graph; gen-module-graph refreshes docs/module-graph.md.
2026-08-31 14:57:12 +08:00
Chinesezjc
1eacccc6e4 chore(sdk-runtime): adopt master's manifest (drop the code-runtime-python peer)
The branch's sdk-runtime manifest had carried a code-runtime-python workspace
peer that master's lockfile does not record, so a frozen install failed on the
mismatched specifier. The branch changes no sdk-runtime code, so it adopts
master's manifest verbatim.
2026-08-31 14:56:11 +08:00
Chinesezjc
65a4d64786 chore(code-runtime-python): adopt master's package.json peer dependencies
The earlier merge had kept the branch's older package.json while taking
master's lockfile, so a frozen install failed on mismatched specifiers for the
code-runtime-python package (master added dsh-code-runtime, dsh-session, and
dsh-timeout peers). The branch changes no dependencies, so it adopts master's
manifest verbatim.
2026-08-31 14:56:11 +08:00
Chinesezjc
5b90f4e2ac chore: adopt master's lockfile and third-party notices after the merge
The merge conflict on pnpm-lock.yaml had kept the branch's older dependency
resolutions; the coverage gate's notices check then failed because CI's frozen
install resolved the master lockfile's versions while the committed notices
still named the branch's older ones. The branch adds no dependencies, so it
adopts master's lockfile and notices verbatim.
2026-08-31 14:56:11 +08:00
Chinesezjc
6e8cc96351 docs(code-runtime-python): fix the doc-standard registry and README kind
The audited library registry still listed dsh-code-runtime-python as a plain
protocol library, but the shipped package's src/index.ts has a plugin default
export; the entry is removed from PACKAGE_LIBRARIES and both READMEs declare
kind: package-reference. The zh README heading is 概述 per the standard.
2026-08-31 14:56:11 +08:00
Chinesezjc
af72ad4409 docs(code-runtime-python): rewrite the README to the repo documentation standard
The merge pulled master's README rewrite (front-matter, Summary, TOC, section
anchors, details-folding); its content described the pre-delivery protocol-only
package, contradicting the shipped backend. The README (en + zh) now follows
that structure with the delivered facts: PythonCodeRuntime, the fd-3 wire, the
load-validated caps, the 64 MiB frame parse cap (worker-exit settlement), and
the known limitations. Pairing re-recorded.
2026-08-31 14:56:11 +08:00
Chinesezjc
7fbf370d87 docs(code-runtime-python): drop the orphan receive-cap JSDoc and correct the frame comments
The review's three stale-comment items in index.ts: the orphan JSDoc above
FRAME_PARSE_CAP_BYTES (left over from the deleted receive ceiling), the
pre-join comment's change narration and its reference to a no-longer-existing
higher ceiling, and the first-frame comment's mention of a per-line cap check
that no longer exists. Test comments for the pythonBin and sealing-threshold
cases are weakened to their observable claims (both orders reject an over-cap
frame; the pythonBin case pins the contract, not a worker-exit distinction).
2026-08-31 14:55:02 +08:00
Chinesezjc
ff87d9a00f docs(code-runtime-python): finish aligning the notes with the delivered runtime
The fd-3 protocol note (en + zh) drops the 'future provider/runtime' staging
language (the runtime is delivered and its real-subprocess suite owns the
field-type gap), and the settlement note's Testing paragraph records the
frame-cap, multi-frame, sealing-threshold, and pythonBin resolution cases now
in the suite. Pairings re-recorded.
2026-08-31 14:55:02 +08:00
Chinesezjc
65da4cfb28 Merge pull request #3352 from deepseek-harness/fix/windows-coverage-align-linux
fix(ci): windows coverage runs zero-build like the linux lane
2026-08-31 14:54:27 +08:00
Chinesezjc
4903f7da1f docs(code-runtime-python): align stale frame-ceiling prose with the 64 MiB parse cap; pin pythonBin resolution
The review's doc drift items: the orphan receive-ceiling JSDoc, the frame-ceiling
references in index.ts/bootstrap.py/tests, and the README's 'dropped, stranding
to the wall clock' phrasing (the run now settles as a worker-exit) are all
updated to the 64 MiB FRAME_PARSE_CAP_BYTES semantics; the README notes the
>64 MiB binding-argument residual as a worker-exit trip of the same cap. A
regression case resolves a basename pythonBin against a PATH whose first entry
is relative ('.') and asserts the absolute entry is used.
2026-08-31 14:54:18 +08:00
Chinesezjc
d62b63d529 fix(code-runtime-python): skip relative PATH entries in pythonBin resolution; pin the sealing-threshold rejection
The review's remaining code items:
- resolvePythonBin now skips RELATIVE PATH segments (a bare 'bin' or '.'): the
  returned candidate must be absolute, because spawn() resolves a relative
  pythonBin against the host CWD, outside the seam contract.
- A deterministic-ish regression pins the sealing-threshold corner: 64 MiB of
  4 KiB (<= PIPE_BUF, atomic) newline-free writes plus 12289 more A's before
  the first newline make the first frame exceed FRAME_PARSE_CAP_BYTES; the
  newline-bearing chunk reaches the first-frame check (sealing is the ELSE
  half of the newline branch), so the run reports worker-exit with the
  protocol-frame-exceeded message.
2026-08-31 14:53:33 +08:00
Chinesezjc
a715bfd111 fix(code-runtime-python): seal only newline-free runs so the first-frame check cannot be skipped
The review's sealing corner: the fragment-count seal ran before the newline
branch and did not exclude a newline-bearing chunk, so the 1024th chunk (the
first to carry a newline) was concatenated into a sealed block, pendingChunks
was emptied, sawNewline stayed false, and the first-frame check was skipped for
a join that then contained the newline. Sealing now runs as the ELSE half of
the newline branch, so a newline-bearing chunk always reaches the join and its
first-frame check, and the invariant 'sealed blocks hold newline-free prefixes
only' is true — which is what makes the removed per-line check genuinely dead.
2026-08-31 14:53:33 +08:00
Chinesezjc
4c3e453080 fix(code-runtime-python): drop the now-dead per-line cap check again
The pre-join counter (single unframed line) and the first-frame check
(newline-bearing chunk) reject any frame past FRAME_PARSE_CAP_BYTES before the
join, so every line reaching this loop is within the cap by construction — the
per-line check was dead code and its continue branch could never fire, failing
the per-file 100% coverage gate.
2026-08-31 14:53:33 +08:00
Chinesezjc
295e020ea4 fix(code-runtime-python): reject only an oversized FIRST frame before the join, not a multi-frame buffer
The pre-join check charged the whole unframed buffer, which legitimately holds
several frames each within FRAME_PARSE_CAP_BYTES: a first frame of exactly the
cap followed by a second frame crossed the counter and was misreported as a
worker-exit. The pre-join rejection now fires only while the held bytes are a
single unframed line (this chunk carries no newline); once a newline arrives,
a FIRST-FRAME check measures the bytes up to the first newline across the held
chunks (including sealed blocks) and rejects only that frame before the join —
keeping the peak at one copy of its wire bytes — while later frames in the
same buffer are handled by the restored per-line check. Regression cases: a
72 MiB newline-free buffer is rejected pre-join (fail-before: joining would
have doubled it); two within-cap frames whose combined buffer crosses the cap
both survive (fail-before: the unconditional counter check turns it red).
2026-08-31 14:53:33 +08:00
Chinesezjc
abf81a0905 fix(code-runtime-python): drop the now-dead per-line parse cap check
The unframed-buffer counter guard runs before every join and guarantees each
line is within FRAME_PARSE_CAP_BYTES, so the line-loop cap check was dead code
(its continue branch could never fire, failing the per-file 100% coverage gate
on index.ts). Removed with a comment explaining the invariant.
2026-08-31 14:53:33 +08:00
Chinesezjc
219d216c54 test(code-runtime-python): move the frame-overflow cases to the 64 MiB parse cap
The pendingBytes guard now trips at FRAME_PARSE_CAP_BYTES (64 MiB) instead of
the 256 MiB wire ceiling, so the three tests that flood/pin frames against the
guard assert the 67108864 message and write a 64 MiB-based workload.
2026-08-31 14:53:33 +08:00
Chinesezjc
c8139589d2 fix(code-runtime-python): reject an oversized unframed frame before the join; cap the rejection diagnostic
The review's remaining critical: the fd-3 data handler checked the unframed
counter against the 256 MiB wire ceiling, so a single 64-256 MiB frame was
fully Buffer.concat-joined (a second copy) and only then dropped in the line
loop — the peak-memory doubling the pre-join check exists to prevent, for a
frame the parser is guaranteed to discard. The counter is now checked against
FRAME_PARSE_CAP_BYTES before the join; the regression case asserts a worker-exit
with 'protocol frame exceeded' (fail-before: reverting to the ceiling turns it
green, proving the join path). FRAME_CEILING_BYTES is removed.

The rejection-cap fix now has its regression: a completion value whose class
name is 70 MiB of Ns asserts invalid-output, not worker-exit (fail-before:
uncapping the diagnostic turns it red).

The settlement note (en + zh) updates the remaining stale bound text, and the
fd-3 protocol note (en + zh) no longer claims protocol-only exports or a
missing Python codec. Pairings re-recorded.
2026-08-31 14:53:33 +08:00
Chinesezjc
3f8b45f9bb fix(code-runtime-python): cap the done-frame rejection diagnostic and sync stale docs
The review's remaining items:
- _done_with_value's rejection branch now caps the _check_done_value diagnostic
  through _cap_message (a reason embedding a hostile class name could otherwise
  push the done frame past the host's 64 MiB parse cap, misreporting an
  invalid-output run as a worker-exit).
- The settlement note (en + zh) updates three stale facts (load bound is now
  parse-cap minus envelope at 67108800; the sink goes directly through the
  bound primitives); the fd-3 protocol note (en + zh) no longer claims the
  package ships protocol without the runtime; FRAME_ENVELOPE_BYTES' JSDoc and
  _cap_message's docstring follow the new bound.
Pairings re-recorded.
2026-08-31 14:52:57 +08:00
Chinesezjc
d90155714b docs(code-runtime-python): correct the sink comment and register the frame parse cap
The review's remaining warning: the _run binding comment claimed the log sink
went 'through the bound send', contradicting the sink's actual direct use of the
bound encode+write primitives. The comment now states that; the settlement note
(en + zh) registers FRAME_PARSE_CAP_BYTES and the 65 MiB-frame regression case.
Pairing re-recorded.
2026-08-31 14:52:01 +08:00
Chinesezjc
fca41b78ea fix(code-runtime-python): bound the load-time budget to the frame parser cap
The review found the 64 MiB parse cap contradicted the load-time budget bound:
maxLogBytes/maxValueBytes could be configured up to ceiling - envelope (~256 MiB),
but the receive path silently dropped any frame past the 64 MiB parser cap, so an
honest child's budget-internal done frame under such a config would be discarded
and the run stranded to the wall clock. The load bound is now parse-cap -
envelope, so a configured budget always fits through the parser; the boundary
test moves to 64 MiB - 64. The >64 MiB model-constructed binding-argument drop
is registered as an accepted residual in the README (en + zh).
2026-08-31 14:51:20 +08:00
Chinesezjc
ab40136b02 fix(code-runtime-python): cap the raw frame length before JSON.parse and bound the log sink
Addresses the review's remaining two items:
- FRAME_PARSE_CAP_BYTES (64 MiB) drops an fd-3 frame whose raw length exceeds
  it BEFORE toString/JSON.parse: the 256 MiB wire ceiling bounds the bytes, not
  the decoded structure, and a compact wide frame near that ceiling could decode
  to far more host memory. A regression test writes a 65 MiB log frame plus a
  normal one and asserts the oversized frame is dropped while the trailing frame
  still lands in logs (fail-before: without the cap the oversized text is parsed
  and admitted, truncating the ledger so the trailing frame is dropped). The
  forged-oversized lower-bound test's frame is reduced to stay under the cap
  while still exercising the truncation path.
- The log sink writes through the def-time bound encode+write primitives (not
  send_sync, whose body resolves _encode_json_plain and self.write_encoded at
  call time), so a rebind cannot break a log frame.
2026-08-31 14:50:40 +08:00
Chinesezjc
125306324f fix(code-runtime-python): write dispatch frames through def-time bound primitives
The review's remaining functional item: send_sync's body resolves
_encode_json_plain (module global) and self.write_encoded (class attribute) at
call time, so a program rebinding either before the first binding call could
turn a legitimate call into an exception. dispatch now writes the call frame
through def-time bound write_encoded+_encode_json_plain, and the log sink goes
through the bound send; the dispatch rebind test also rebinds those two names
(verified fail-before by reverting to send_sync). The annotation test title
matches its assertion direction, and the note (en + zh) registers the
error-class constructor, dispatch primitives, and dont_inherit mechanisms.
Pairing re-recorded.
2026-08-31 14:50:39 +08:00
Chinesezjc
c4c79f094d test(code-runtime-python): pin the error-class constructor and dispatch primitives with rebind cases
The review required regression cases for the two cfb35bef6 fixes:
- Rebinding __main__.Exception/__main__.setattr must not break the minted
  error class: a host rejection still surfaces as ToolCallError with the member
  property readable.
- Rebinding __main__._lossless_json_violation/__main__.asyncio/
  __main__.ProtocolChannel.send_sync must not break dispatch: a legitimate
  binding call still round-trips.
2026-08-31 14:49:54 +08:00
Chinesezjc
44205c4949 fix(code-runtime-python): stop the program's compile from inheriting the module's future annotations
bootstrap.py imports from __future__ import annotations; compile(wrapped) was
inheriting that PEP 563 flag, stringifying the program's type annotations and
changing the semantics of a legal program that reads f.__annotations__ at
runtime. compile(..., dont_inherit=True) stops the leak; a regression test
defines an annotated function and asserts the annotation is the live int class,
verified fail-before by removing dont_inherit (the test turns red).
2026-08-31 14:49:54 +08:00
Chinesezjc
6a659df999 fix(code-runtime-python): capture the error-class constructor and dispatch primitives
The review's remaining items:
- _make_error_class captures Exception and setattr as def-time defaults, so a
  rebind of __main__.Exception/__main__.setattr cannot break the rejection
  constructor.
- dispatch binds _lossless_json_violation, asyncio.get_event_loop, and the
  channel's send method into _run locals before the program runs, so a rebind
  cannot turn a legitimate binding call into an exception or a wall-clock
  timeout.
- The note (en + zh) corrects the stdin coverage phrasing: d3f9f57f5's direct
  EOF-observing case is the in-tree pin, not an approximation.
- Collapse two stray double blank lines in the test file.
Pairing re-recorded.
2026-08-31 14:49:54 +08:00
mektpoy
ff21366916 fix(client): complete highlighted commands with Tab 2026-08-31 14:49:35 +08:00
Chinesezjc
c4d6c25ffc test(code-runtime-python): pin the pump reader against a class-attribute rebind; correct the staging comment
The review's three remaining items:
- A regression test rebinds __main__.ProtocolChannel.read_frame_async and asserts
  a binding reply still round-trips (the pump's reader is a bound method
  captured by _run before the program runs).
- The settlement note (en + zh) records that send_done's frame-shape check uses
  _run's bound _str/_isinstance.
- The staging-removal comment no longer claims teardown retries tracked state:
  teardown deliberately does not sweep staging, so a removal failure is the one
  case the gone-by-settlement contract degrades on.
Pairing re-recorded.
2026-08-31 14:49:15 +08:00
Chinesezjc
8ed96b1560 docs(code-runtime-python): register the frame-reader capture extensions in the note
The review flagged that the implemented note's capture-family enumeration had
not followed c0ca236b5: read_frame/read_frame_async now also capture len (and
asyncio.get_event_loop on the async reader), _decode_json_plain captures
isinstance/str/list, and the reply pump's frame reader is injected as a bound
method captured by _run before the program runs. Note (en + zh) updated;
pairing re-recorded.
2026-08-31 14:48:36 +08:00
Chinesezjc
aa685028a7 test(code-runtime-python): pin the stdin-close behavior with an EOF-observing case
The stdin destroy (child.stdin?.destroy() right after spawn) previously had no
in-tree coverage. A program that reads fd 0 now sees EOF immediately; without
the destroy it blocks and the run would hang to maxWallMs as a timeout —
verified fail-before by disabling the destroy (the test turns red at the wall
ceiling) and restoring it (green). The _str rebind regression was attempted but
is not viable: the success path's done-frame serialization reaches str
transitively through _encode_json_plain, which the README Known Limitations
already records as the accepted success-to-exception residual, so any rebind
test trips that documented residual before send_done's bound _str.
2026-08-31 14:47:57 +08:00
Chinesezjc
302bbb0f8f fix(code-runtime-python): close the remaining call-time lookup gaps in the reply and settlement paths
The review's completeness check found the def-time capture pattern was not yet
applied to every name the reply/settlement paths resolve at call time:
- _decode_json_plain now also captures isinstance/str/list.
- read_frame/read_frame_async capture len; read_frame_async captures
  asyncio.get_event_loop.
- send_done uses _run's bound _str/_isinstance for its frame-shape check.
- The reply pump's frame reader is a bound method captured by _run BEFORE the
  program runs and passed into _pump_replies, so a rebind of the class
  attribute cannot redirect it.
The decode-rebind regression test still pins the _decode_json_plain rebind;
rebinding builtins (len/isinstance/list/str) in a test is not viable because
the Python runtime itself resolves them implicitly.
2026-08-31 14:47:57 +08:00
Chinesezjc
aa5e8fc345 fix(code-runtime-python): suppress the unnecessary-optional-chain lint for the stdin destroy
The boot-write-failure fake child carries no stdin at runtime, so the optional
call is the documented guard; the static type (ChildProcessWithoutNullStreams)
says stdin is non-null, which trips the no-unnecessary-condition lint.
2026-08-31 14:47:57 +08:00
Chinesezjc
aecdec3f80 fix(code-runtime-python): guard the stdin destroy against a spawn-failure child
The boot-write-failure path's fake child carries no stdin handle, so the
unconditional destroy threw inside the spawn error handler and mislabeled the
worker-exit. Use the optional-call form; the no-stdin branch is exercised by
that same test.
2026-08-31 14:47:57 +08:00
Chinesezjc
40fbf92290 fix(code-runtime-python): close the child stdin handle and def-time capture the frame decode primitives
Addresses the review's two remaining items:
- The host closes the child's stdin write handle immediately after spawn. The
  program is an async body that reads nothing from fd 0; a live pipe would hold
  a host-side handle open past the run, so a setsid-escaped descendant
  inheriting fd 0 could keep the host process from exiting even after the
  closeDeadline forced settlement. The child (and any descendant) reads EOF on
  fd 0 and no host handle survives.
- read_frame/read_frame_async bind their decode primitives (_decode_json_plain,
  os.read, _READ_CHUNK_BYTES, bytes) as def-time default arguments, and
  _decode_json_plain itself captures json.loads, its two regexes, and len the
  same way, so a __main__ rebind cannot kill the reply pump and strand every
  pending Future to the wall clock. _decode_json_plain and its regexes moved
  before the ProtocolChannel class so the defaults resolve at class-definition
  time. A regression test rebinds _decode_json_plain and asserts a binding reply
  still round-trips.
Note (en + zh) registers both mechanisms; pairings re-recorded.
2026-08-31 14:47:57 +08:00
Chinesezjc
ac64039843 fix(code-runtime-python): bind str for dispatch's rejection message conversion
The review's remaining non-blocking suggestion: dispatch's call_failure(str(exc))
resolved the builtin str at call time, so a program rebinding __main__.str could
run a hostile callable when the binding-rejection message is formatted. Bind
_str into _run locals and use it in dispatch.
2026-08-31 14:47:18 +08:00
Chinesezjc
937ada4837 fix(code-runtime-python): bind RuntimeError and _BindingRejection for dispatch's rejection path
dispatch's call_failure and its except clause resolved the module globals at
call time, so a program rebinding __main__._BindingRejection = ValueError let
the internal marker type leak into model code. Bind _RuntimeError_cls and
_BindingRejection_cls into _run locals before the program runs (names distinct
from the module globals so the assignment RHS resolves the global, not an
unbound local); dispatch now uses the locals. A regression test rebinds
_BindingRejection and asserts a host rejection still surfaces as RuntimeError.

The sys.__stdout__ flush test now reconfigures the streams back to block
buffering (write_through=False) so the settlement drain path is what the case
pins — verified fail-before: binding the stream objects instead of their flush
methods turns the test red.
2026-08-31 14:47:18 +08:00
Chinesezjc
1efb0094c8 fix(code-runtime-python): bind the original std streams' flush methods, not the stream objects
The settlement drain iterated the bound stream OBJECTS, which are not
callable — every _flush() raised TypeError and was swallowed by the loop's
except, so the drain never ran and only the -u flag carried the behavior.
Bind sys.__stdout__.flush/sys.__stderr__.flush (bound methods, capturing the
stream at binding time, immune to a later sys.__stdout__ rebind; None-guarded).
Verified by removing -u temporarily: the sys.__stdout__ regression test still
passes, so the drain is a genuine backstop, not a documented-but-dead layer.
2026-08-31 14:47:18 +08:00
Chinesezjc
43a0879ad1 fix(code-runtime-python): clear stray buffers on truncation and drain the original std streams
Addresses the review's two carried warnings and the comment suggestion:
- Once the ledger truncates, every arm that marks it (admit()'s two ceilings and
  the child-marker frame arm) now clears both stray pipes' buffered output
  wholesale, so the end-path flushStray sees empty buffers instead of
  concat+decoding doomed data near a 256 MiB maxLogBytes; captureStray's newline
  loop re-checks the flag before re-retaining the residual.
- The child runs with -u (unbuffered), so sys.__stdout__/sys.__stderr__ writes
  are visible to stray capture immediately; the settlement flush still drains
  the original std streams before the done frame as a guard. A regression test
  writes through sys.__stdout__/sys.__stderr__ without an explicit flush and
  asserts both bytes land in logs. C-ext stdio remains an accepted residual,
  recorded in the README Known Limitations (en + zh).
- The ledger-comment arithmetic now states the exact boundary (serializes to
  exactly maxLogBytes; without the reserved byte it would be maxLogBytes + 1)
  in both host and child.
Note (en + zh) registers the stray-clear and -u/settlement-drain mechanisms and
the new test; pairings re-recorded; corpus passes 1029.
2026-08-31 14:47:18 +08:00
Chinesezjc
4c7811812d docs(code-runtime-python): state the macOS killGroup behavior directly and complete the residual sentence
The review flagged the change-narrative wording 'degrades to the pre-existing
behavior' (prohibited by docs/AGENTS.md) in four spots — README en/zh, the
readProcessStart JSDoc, and the test comment — and the incomplete :77 residual
sentence ('can still' with no verb complement). Reword the four to a direct
statement of current behavior (killGroup signals the pgid without the identity
re-check on macOS), complete the residual sentence with the actual consequence,
and re-record both pairings. Corpus-wide verify-translation-pairing passes 1029.
2026-08-31 14:46:31 +08:00
Chinesezjc
e0d552fa86 docs: regenerate config-catalog with the python backend config and align the zh side
The master merge brought a stale generated config-catalog that omitted the
dsh-code-runtime-python config section and mislisted the package. Regenerate
docs/config-catalog.md (verify-config-catalog passes), translate the python
config section into zh, keep the ts config-catalog code blocks verbatim
(untranslated, per the pairing rule), and drop the stray zh Library-packages
line. Corpus-wide verify-translation-pairing passes 1029.
2026-08-31 14:45:57 +08:00
Turtle
4df85c85ff feat(issue-management): initialize Issue start dates on PR open 2026-08-31 14:44:20 +08:00
Chinesezjc
203110a90c chore: re-trigger pull_request synchronize for CI 2026-08-31 14:44:19 +08:00
Chinesezjc
9af1e5e9f0 fix(code-runtime-python): correct the log-budget floor to 64 and record the marker envelope bound
The review found the 62 floor off by two (the marker's fixed prefix is 51
characters counting both square brackets, so marker(62) serializes to 63) and
the constructor error over-claiming a bound the marker-as-envelope design does
not deliver. Fixes:
- MIN_LOG_BYTES is 64 (marker-only serialization fits with one byte of room);
  the JSDoc arithmetic counts the brackets; the rejection test pins 63; the
  forged-frame test uses 11 NULs (69 escaped) at 64.
- The constructor error now states the marker-only guarantee, and the README
  Known Limitations (en + zh) records the real bound: a truncated run with
  admitted entries serializes its logs to maxLogBytes + marker + envelope.
- The SIGXCPU-mask tests burn with time.process_time() instead of wall-clock
  perf_counter, so a contended CI runner cannot under-burn the budget.
- The settlement note (en + zh) records the 64 floor and the marker envelope
  bound, including the zh pre-encode section that the earlier pass missed.
- The README constructor-rejection list names the maxLogBytes floor.
Pairings re-recorded; corpus-wide verify-translation-pairing passes 1004.
2026-08-31 14:44:19 +08:00
Chinesezjc
51d57cca03 docs(code-runtime-python): register the log-envelope reservation, SIGXCPU unblock, budget floor, and syntax label
The review flagged four mechanism changes shipped without note registration:
- Log ledgers start one byte below the budget (outer-array envelope reservation)
  and the constructor floors maxLogBytes at 62 (the smallest budget that can
  serialize its own truncation marker plus the envelope).
- die_if_cpu_exhausted restores SIG_DFL before unblocking a program-masked
  SIGXCPU, so a trap+mask program cannot run a re-masking handler at the unblock.
- ast.parse passes filename="<model>" so parse-time syntax diagnostics share the
  compile/runtime source label.
Decision and Testing (en + zh) now record all four with their fail-before cases
(exact-limit, budget rejection, syntax label, SIGXCPU-mask, trap+mask); pairing
re-recorded and consistent.
2026-08-31 14:42:28 +08:00
Chinesezjc
4a8c49f78c fix(code-runtime-python): restore SIGXCPU disposition before unblocking and floor the budgets
Addresses the review's two code warnings and one suggestion:
- die_if_cpu_exhausted now restores SIG_DFL BEFORE unblocking SIGXCPU: a program
  that installed a custom handler AND masked the signal would otherwise have
  that pending handler run at the unblock (in model code, re-masking or raising)
  and escape the re-raise; with SIG_DFL first the pending signal kills inside
  the kernel with no bytecode window. A trap+mask combined regression test pins
  it (the mask-only case was already covered).
- The constructor rejects budgets too small to honor: maxLogBytes must fit the
  truncation marker plus the serialized outer-array envelope (floor 64), and
  maxValueBytes must at least represent the smallest JSON completion (floor 4,
  matching the worker backend). The exact-limit test moves to the 64 floor and
  a rejection test pins the floors.
- The pthread_sigmask None-guard comment cites the real rationale (defensive
  against stripped CPython builds; win32 is refused at construction), not the
  unreachable Windows path.
2026-08-31 14:41:49 +08:00
Chinesezjc
a2eda792e3 docs(code-runtime-python): align the accepted-residual dep list across README and note
The residual bullets listed the encoder's transitive deps as an exhaustive set
but disagreed with each other and omitted io. Mark the list as a non-exhaustive
example (e.g. _dump_scalar/_dump_string/json/io) in the README (en + zh) and the
settlement note (en + zh); pairings re-recorded and consistent.
2026-08-31 14:41:49 +08:00
Chinesezjc
4e0d77c1d6 fix(code-runtime-python): reserve the log array envelope byte, unblock SIGXCPU before re-raise
Addresses the review's two remaining code warnings and the three suggestions:
- Log ledgers (host and child) start one byte below the budget, reserving the
  serialized outer-array envelope (two brackets and n-1 commas over n entries'
  separators); the exact-zero test moves to maxLogBytes 104 and a new exact-limit
  case pins that maxLogBytes 5 admits ['a'] (5 bytes) while 4 truncates to the
  marker alone.
- die_if_cpu_exhausted unblocks SIGXCPU (pthread_sigmask SIG_UNBLOCK, captured at
  import, None-guarded for Windows) before re-delivering it, so a program that
  masks SIGXCPU, burns past the soft limit, and returns is still classified as a
  timeout; a regression test pins the masked path.
- ast.parse passes filename="<model>" so parse-time syntax diagnostics carry the
  same source label as compile and runtime tracebacks; the syntax-error test
  asserts the label.
- The NUL-escape test comments use the true six-byte JSON escape \u0000 instead
  of the caret notation; the README Known Limitations (en + zh) records that
  PID-reuse protection is inert on macOS; a combined-rebind regression test pins
  BaseException plus the traceback reporter rebinding together.
2026-08-31 14:41:08 +08:00
Chinesezjc
96597c5ed8 fix(code-runtime-python): bind the _done_with_value entry name and correct the residual documentation
Addresses the review's registration-text accuracy findings:
- _run binds _done_with_value into a local (done_with_value_bound) before the
  program runs, closing the __main__._done_with_value = boom success-rewrite
  vector; a regression test rebinds it and returns a legitimate value, asserting
  the success survives.
- README (en + zh): the CPU-recheck bullet now states the recheck runs
  unconditionally after the program returns (a pre-return overrun dies there as
  a timeout) and the false-success window is only a trap-SIGXCPU program that
  passes the recheck and overruns during the settlement flush/encode; the
  encoder-deps residual rationale is replaced with the actual one (bash-equivalent
  trust, verdict still delivered via the send_done fallback frame) and names the
  now-bound entry; the t.join() deadlock bullet fixes the subject/object (the
  main coroutine joins the worker, blocking the pump's main event loop).
- The portable-identifier-seam architecture note no longer claims the Python
  backend does not exist.
- Settlement note (en + zh) registers the entry-name binding and the new test.
- All pairings re-recorded; corpus-wide verify-translation-pairing passes 1004.
2026-08-31 14:40:35 +08:00
Chinesezjc
8c540fd9fd Merge origin/master (revert of PR 2573)
Master reverted PR 2573, deleting the case-insensitive-path-round-trips
note that carried the dead link, so take the deletion and drop the note
repair from this branch; the jsonl.spec.ts change merges cleanly.
2026-08-31 14:39:37 +08:00
Turtle
0e7c769540 Merge remote-tracking branch 'origin/master' into turtle/pr-864-master-port 2026-08-31 14:39:13 +08:00
Chinesezjc
e6b23e829b docs(code-runtime-python): split the deadlock into its own bullet and qualify the done_value claim
Addresses the review's two registration-text accuracy findings:
- The cross-thread t.join() deadlock is a process-isolation-backend property (the
  pump runs on the child's main event loop), so it is split out of the wide-binding
  REPLY bullet into its own Known Limitations entry with the correct attribution
  (fix belongs in this backend, not packages/core/session); the zh half-width
  space is removed.
- The settlement note's _done_with_value def-time default-arg sentence is
  qualified: it guards a rebind of _check_done_value/_encode_json_plain, while a
  transitive encoder dep (_dump_scalar/io) rebind can still downgrade, which is
  registered as an accepted residual in the package README.
Pairing re-recorded; corpus-wide verify-translation-pairing passes 1004.
2026-08-31 14:39:07 +08:00
Turtle
b8e3b32fcf Merge master into codex/omit-unneeded-invariants 2026-08-31 14:38:55 +08:00
Chinesezjc
c8bc96007b docs(code-runtime-python): register the CPU-recheck and encoder-deps accepted residuals
Document the two remaining keep-current residuals in the python package README
Known Limitations (en + zh), per the review's accepted-resolution path:
- A trap-SIGXCPU program can exceed the soft CPU limit during settlement encoding
  and still report success (containment holds via hard +1s and wall clock; only
  the classification is degraded, because the recheck cannot meter mid-encode).
- The encoder's direct deps (_dump_scalar/_dump_string/json) resolve at call
  time, so a __main__ rebind after a legit return can downgrade success to
  exception; the value path's top-level deps are def-time bound, the transitive
  ones are an accepted residual.
Pairing re-recorded and consistent.
2026-08-31 14:37:52 +08:00
Chinesezjc
f79e53e74c docs(code-runtime-python): align the note consequences, register the deadlock and default-arg mechanisms
Addresses the bot's keep-current findings:
- The settlement note distinguishes the BaseException (lost done frame) and
  RuntimeError (pump killed -> replies stranded to the wall clock) consequences;
  registers the _done_with_value def-time default-arg capture and the new
  RuntimeError-rebind closed-loop test; zh:95 half-width space fixed.
- The python package README Known Limitations records the cross-thread binding +
  sync t.join() deadlock (en + zh).
- The code-runtime Service Definition README no longer claims only the
  worker-thread backend ships: the Python (process) backend is acknowledged,
  with 'container' as future work (en + zh).
- All pairings re-recorded; corpus-wide verify-translation-pairing passes 1002.
2026-08-31 14:36:31 +08:00
Chinesezjc
923fb56128 fix(code-runtime-python): bind the reply-pump exception names as def-time default arguments
A body-local X = X binding in _pump_replies is too late: _run reaches the
model's top-level statements (which run first, since there is no suspension
point between create_task and await __dsh_main__) before the pump's first step,
so a __main__.RuntimeError rebind there would be captured by the body local and
a closed-loop failure would escape the except, killing the pump. Bind
_RuntimeError, _BindingRejection, str, and bool as DEF-TIME default arguments of
_pump_replies (evaluated at import, before any model code runs). Add a regression
test that rebinds __main__.RuntimeError as the first program statement and drives
the closed-loop worker pattern, asserting the pump survives and delivers the
later binding. Update the settlement note (en + zh) to describe the default-arg
capture; pairing re-recorded and consistent.
2026-08-31 14:34:09 +08:00
Chinesezjc
b018abf405 fix(code-runtime-python): bind the pump RuntimeError after its docstring and _done_with_value deps as defaults
- The reply pump's _RuntimeError binding is placed after the function docstring
  (so the docstring remains the __doc__) and the dead _run-side binding is
  removed. _done_with_value binds _check_done_value/_encode_json_plain as
  default arguments so a __main__ rebind after model execution cannot rewrite a
  success into an exception.

The _str/_bool/_BindingRejection pump bindings were attempted but break the
closed-loop pump test (the self-referential _BindingRejection local interferes
with the closure), so they are left unbound; rebinding those names (builtins and
one internal class) is outside the practical threat model.
2026-08-31 14:34:09 +08:00
Chinesezjc
2d82b658ba fix(code-runtime-python): bind RuntimeError inside the module-level _pump_replies
The previous commit bound _RuntimeError in _run, but _pump_replies is a separate
module-level function, so its except _RuntimeError referenced an out-of-scope
local and raised NameError instead of catching the closed-loop failure — killing
the pump and timing out the run. Bind _RuntimeError at the top of _pump_replies
too. The closed-loop pump test now passes.
2026-08-31 14:34:09 +08:00
Chinesezjc
bcc11f1235 fix(code-runtime-python): bind RuntimeError for the reply pump catch and note the exception-class locals
The reply pump's except RuntimeError resolved the module global at runtime, so a
__main__.RuntimeError rebind could make a closed-loop scheduling failure escape
the catch, killing the pump and stranding every later reply. Bind RuntimeError
into a _run local alongside BaseException and catch the local. The settlement
note Decision now records that the exception classes the settlement-path except
clauses catch are bound into locals / a closure cell before model code runs
(en + zh); pairing re-recorded and consistent.
2026-08-31 14:34:09 +08:00
Chinesezjc
69dc17c906 fix(code-runtime-python): bind BaseException into every settlement-path except clause
The rebindable-BaseException vector the bot flagged existed in every except
clause of the settlement path, not just the _run outer catch: safe_model_traceback
(three guards) and the post-done flush swallow resolved the module-global
BaseException at runtime, so a __main__.BaseException rebind plus a throwing
__str__ could let a render-time exception escape and lose the done frame. Bind
BaseException into a _run local (at the top) and a closure cell in
_make_failure_reporter, and change every such except clause to catch the local
— immune to a one-line rebind.
2026-08-31 14:34:09 +08:00
Chinesezjc
d5945546c7 docs(code-runtime-python): complete the zh no-fail-before enumeration and unify the seal naming
The zh Consequences section counted ten but enumerated only nine; add the
log-fragment seal as the 10th no-fail-before item. Also unify the term to
'封存' (matching the Decision/Testing sections) instead of '封口'. Pairing
re-recorded and consistent.
2026-08-31 14:34:09 +08:00
Chinesezjc
0102cd95bf fix(code-runtime-python): catch the model exception with a pre-program local exception class
The _run outer try/except used the module-global BaseException, which the
program (running as __main__) can rebind: __main__.BaseException = RuntimeError
made the except resolve to RuntimeError, so a subsequent ValueError escaped _run
with no done frame and misreported the run as worker-exit. Bind BaseException
into a _run local before the program runs so the catch is immune; a regression
test rebinds BaseException and raises, asserting an exception, not a worker-exit.

Also correct the NUL-escape comment text: the JSON escape-result side is \^@ (6
bytes, the valid JSON NUL escape), not \x00, so the 6x-budget arithmetic in the
comments is self-consistent. Register the BaseException-rebind case in the
settlement note Testing (en + zh) and re-record the pairing.
2026-08-31 14:34:09 +08:00
Chinesezjc
202c428137 docs(code-runtime-python): correct the fallback-mechanism wording and the no-fail-before count
Addresses the bot's keep-current review findings:
- The module-level fallback comment now states the mechanism truthfully: the
  module globals are RAW primitives bound into _run LOCALS before the program
  runs (the immunity lives in the frame-local binding, not the module global);
  and the fallback literal <unrenderable> is distinguished from the failure
  reporter's _UNRENDERABLE_DIAGNOSTIC text.
- The settlement note's fallback mechanism wording, the transitive-name rebind
  case (now listing the three fallback primitives), and the no-fail-before count
  are aligned en/zh; the zh Problem paste damage is fixed and the Consequences
  count is ten with the 10th item.
- Pairing re-recorded and consistent.
2026-08-31 14:34:09 +08:00
Chinesezjc
d3e34d5612 test(code-runtime-python): replace literal NUL bytes in comments with the escape text
The comments describing NUL serialization contained literal NUL bytes, which
interfere with source tooling. Use the \x00 escape text instead.
2026-08-31 14:34:09 +08:00
Chinesezjc
fe3ba24057 docs(code-runtime-python): update the no-fail-before count to ten and document the hard==1 CPU blind spot
Addresses the keep-current review findings:
- The settlement note's Problem/Consequences count is nine -> ten, adding the
  log-fragment seal to the no-fail-before enumeration (its 25 M-scale OOM is not
  deterministically constructible in CI); the new Decision section title now
  names all four mechanisms and the double blank line is removed.
- README Known Limitations (en + zh) documents the 1-second dual-limit
  ulimit -t 1 CPU overrun being reported as worker-exit (the hard >= 2 guard
  cannot lower a 1-second soft to 0); pairings re-recorded and consistent.
2026-08-31 14:34:09 +08:00
Chinesezjc
4ff050de71 fix(code-runtime-python): bind the send_done fallback primitives into locals and use a bare except
The done-frame fallback read _os_write/_memoryview/_FALLBACK_DONE_FRAME as module
globals at call time, so a single-line rebind of any of them reopened the
rebind hole the fallback exists to close. Bind them into _run locals before the
program runs, and use a bare except (which catches everything without naming
BaseException, so a rebind of that name cannot defeat the handler). The
transitive-name rebind test now also rebinds _os_write/_memoryview/
_FALLBACK_DONE_FRAME to pin the fallback's immunity.
2026-08-31 14:33:31 +08:00
Chinesezjc
31c3b425bf docs(code-runtime-python): register the fragment-seal, CPU soft-lowering, and done-send fallback fixes
Keep the settlement note current with the latest code-review fixes:
- New Decision section for the _LogStream fragment seal, the _clamped
  RLIMIT_CPU soft-lowering (and its hard==1 blind spot), the send_done
  fallback frame, and the reply-queue slot release.
- Testing registers the fragment-cap drip (no-fail-before), the dual-limit CPU
  overrun, and the transitive-name rebind cases.
- zh mirrored; settlement-fixes.i18n.yaml re-recorded and consistent.
2026-08-31 14:33:31 +08:00
Chinesezjc
9b29d0226e fix(code-runtime-python): make the log seal incremental, scope the soft-lowering to RLIMIT_CPU, and capture memoryview
Addresses the bot's follow-up review findings on the settlement-path fixes:
- The _LogStream seal joined the WHOLE accumulated buffer past the fragment cap,
  re-copying the growing block O(B^2/cap) times for a large drip. It now seals
  only the current fragments into a _pending_blocks entry (character count
  unchanged), so a 25 M single-character drip stays O(B); the newline/flush/
  _push_bounded_prefix consumers join blocks + fragments once.
- The _clamped soft==hard lowering is scoped to RLIMIT_CPU: for RLIMIT_AS a
  one-byte soft differential would only misalign the child's applied limit with
  the host-side budget gate, with no signal to preserve. The hard == 1 blind
  spot is documented.
- send_done's fallback captures memoryview at import (_memoryview) alongside
  os.write, so a one-line rebind of the name cannot change the fallback write;
  the comment now states the module-level-captured mechanism.
2026-08-31 14:33:31 +08:00
Chinesezjc
72241b9f06 test(code-runtime-python): correct the dual-limit CPU overrun assertion and use a hard limit >= 2
The dual-limit CPU test used ulimit -t 1 (hard == 1), which the _clamped
soft-lowering guard (hard >= 2) intentionally does not lower, and trapped
SIGXCPU (which defeats the fix). Use ulimit -t 2 (hard == 2, so the soft is
lowered to 1) and leave SIGXCPU unhandled; the run then classifies as a timeout.
The message is the CPU-time-exhausted diagnostic, not the literal 'SIGXCPU'.
2026-08-31 14:33:31 +08:00
Chinesezjc
dcbce50ec2 fix(code-runtime-python): close the log-fragment OOM, CPU classification, and done-send transitive-dependency findings
Addresses the bot's v16 review on the settlement-path code:
- critical: _LogStream._pending now seals the fragment list past a chunk cap
  (like the host captureStray seal), so a newline-free single-character drip no
  longer accumulates one list slot per write and OOMs on its own accounting.
- _clamped lowers a soft==hard result by one unit (when hard >= 2) so a
  dual-limit ulimit -t leaves SIGXCPU a window to fire and a definite CPU
  overrun is reported as a timeout, not a worker-exit.
- send_done wraps its encode+write in a try and, on any throw from a rebound
  transitive name (_dump_scalar/os), writes a fixed pre-encoded done frame via
  the import-time captured os.write, so a settled exception verdict is never
  downgraded to worker-exit.
- drainReplies clears the consumed replyQueue slot so a wide written payload is
  released immediately, bounding host memory to the current backlog under
  sustained fd-3 backpressure.
Tests added for each (fragment cap drip, dual-limit CPU overrun, transitive-name
rebind done frame).
2026-08-31 14:33:31 +08:00
Chinesezjc
add4a2fb6f docs(code-runtime-python): clarify that the binding-all-names case is the fixture that rebinds the send names
The Testing sentence's subject attached the three rebinds to 'the fix' rather than
to the fixture that performs them; reword to 'pinned by a case that rebinds' and
mirror zh ('由一个…用例钉住'), re-recording the pairing.
2026-08-31 14:33:31 +08:00
Chinesezjc
7198234a82 test(code-runtime-python): pin send_done against rebinding write_encoded and _encode_json_plain
The rebinds-every-name fixture previously only rebound ProtocolChannel.send_sync,
which a bound method object ignores and the shipped send_done no longer calls —
so it did not actually guard the call-time-lookup shape. Rebind write_encoded
and _encode_json_plain too (the names send_done would resolve late if it looked
them up at call time) and state that in the settlement note's Testing section
(en + zh), re-recording the pairing.
2026-08-31 14:33:31 +08:00
Chinesezjc
093a6217ff docs(code-runtime-python): register the pre-encode, stray-flush, and late-rejection fixes in the settlement note
Keep the agent note current with the recently landed code-review fixes:
- six -> nine no-fail-before cases, adding the done-value TOCTOU pre-encoding,
  the stray-UTF-8 budget-flush retention, and the late-rejection settled guard,
  each with its reason for not carrying a fail-before test.
- New Decision sections for the pre-encode + send_done binding and the stray
  flush retention; Testing lists the binding-all-names case as a tested fix.
- zh mirrored; settlement-fixes.i18n.yaml re-recorded and consistent.
2026-08-31 14:33:31 +08:00
Chinesezjc
da38c16912 fix(code-runtime-python): drain the reply queue by head cursor, not shift()
Each shift() re-slices the remaining array, so draining a large gather of
wide bindings awaiting fd 3's drain was O(n^2). Reading by a head index into
the array keeps the drain linear; the finally still discards everything.
2026-08-31 14:33:31 +08:00
Chinesezjc
e0e1aa307d fix(code-runtime-python): bind encode/write for send_done and correct stray-flush retention
Addresses the follow-up review findings on the settlement-path fixes:
- send_done now routes both the pre-encoded VALUE frame and the dict ERROR
  frame through a bound _encode_json_plain + bound write_encoded, never through
  channel.send_sync (whose body re-resolves self.write_encoded and the module
  _encode_json_plain at call time) — a program rebinding ProtocolChannel.
  write_encoded or __main__._encode_json_plain no longer skips the done frame.
- flushStray retention re-accrues the withheld multibyte tail from a FRESH
  utf8 state (previously metering the carried lead against the post-flush
  expected>0 state charged it as an illegal continuation), and skips admitting
  when the whole residual drained into the retained tail so no bogus empty
  entry is pushed.
2026-08-31 14:33:31 +08:00
Chinesezjc
be0551f52f fix(code-runtime-python): suppress no-unnecessary-condition on the late-rejection settled guard 2026-08-31 14:33:31 +08:00
Chinesezjc
9e6f279040 fix(code-runtime-python): drop the sealed-blocks ternary in the stray flush to hold 100% branch coverage 2026-08-31 14:33:31 +08:00
Chinesezjc
6634d4800c fix(code-runtime-python): bind done-send callables and cover the stray-flush retention
Corrections to the settlement-path review fixes:
- send_done was invoking channel.send_sync / channel.write_encoded via a late
  method look-up, which a program running as __main__ could rebind through
  __main__.ProtocolChannel.send_sync before the failure path ran — a rebound
  send that raises then skipped the done frame and downgraded a settled
  exception to worker-exit. Bind both channel methods into locals before the
  program runs, mirroring the pre-existing binding of flush_out/flush_err/
  safe_model_traceback.
- Restructure flushStray so the mid-sequence budget-flush retention arm is a
  self-contained v8-ignored branch and the covered default path decodes the
  full residual (not schedulable-through-the-seam boundary).
2026-08-31 14:33:31 +08:00
Chinesezjc
f71914ceea fix(code-runtime-python): close four settlement-path review findings
Pace-free completion framing, stray UTF-8 flush, and late-rejection guards:
- Pre-encode the completion value at its validation point so send_done never
  re-walks a live value a mutating daemon thread could change (TOCTOU); a
  mutation-induced encode throw is then classified as 'exception', not a
  host-side worker-exit.
- Budget-triggered stray flush retains an incomplete multibyte UTF-8 tail
  (<=3 bytes) as residual instead of decoding a legal, split character to
  U+FFFD in an admitted entry; the end/closeDeadline paths still full-decode.
- Check 'settled' before formatting a late binding rejection's message, so a
  hostile message getter cannot stall or exhaust a run that already settled.
- Document _check_done_value's first-to-trip ruling in its docstring.
- Rewrite ProtocolChannel.send_sync around a shared write_encoded that the
  done frame's pre-encoded string path uses.
2026-08-31 14:33:31 +08:00
Chinesezjc
06e47b299e docs(code-runtime-python): drop the dangling list-conjunction in the six-item note enumeration 2026-08-31 14:33:31 +08:00
Chinesezjc
117ca8cb67 docs(code-runtime-python): register paced-replies and late-drop in the settlement note 2026-08-31 14:33:31 +08:00
Chinesezjc
441ebd0433 test(code-runtime-python): exempt the mid-drain settle branch from coverage
The drain loop's `if (settled) break` needs the run to settle in the window
between two queued frames. A file probe on the concurrent-replies case shows the
queue does reach depth 11, but the wall clock never lands inside that window, so
the branch is not schedulable from a test; a case written to force it passed
without ever executing the line, so it is removed rather than left as coverage it
does not provide. The branch carries a v8 ignore naming what is unreachable.
2026-08-31 14:33:31 +08:00
Chinesezjc
6f58f9c336 fix(code-runtime-python): pace concurrent binding replies against fd 3
`sendReply` ignored `proto.write`'s `false` return, so a program resolving
several large values in one `asyncio.gather` round encoded every reply in the
same turn and queued all of them in fd 3's writable buffer. Binding resolution
carries no seam-level byte cap to bound that, and the failure kills the host
process rather than failing the run: measured on a 64 KiB-highWaterMark pipe,
eight 4 MiB replies buffered 32.0 MiB at once against 0.0 MiB once paced.

Replies now go through a queue that encodes and writes one frame at a time,
awaiting `drain` when the pipe is full. The encode happens inside the loop, so a
queued reply the run no longer needs is dropped by the `settled` check without
ever being serialized.

This was previously deferred on the grounds that serializing would narrow the
seam's concurrency contract. That reasoning was wrong: the child matches each
reply to its `call` by id from a pump that reads fd 3 continuously, so arrival
order was never observable, and the bindings still run concurrently. Only the
host's peak memory and the flush timing change. The README entry recording the
deferral is removed and the Agent Note records the mechanism instead.
2026-08-31 14:33:31 +08:00
Tianyi Cui
cf2d0986cf Merge pull request #3361 from deepseek-harness/revert-2573-fix/windows-path-case-test-fragility
Revert "test(session): resolve one relative root on both sides of the jsonl round-trip"
2026-08-31 14:33:01 +08:00
Tianyi Cui
1f3101982b Revert "test(session): resolve one relative root on both sides of the jsonl round-trip" 2026-08-31 14:32:48 +08:00
Chinesezjc
2a9a917853 fix(code-runtime-python): drop a late binding resolution before snapshotting it
`sendReply` already refuses to write after the run settled, but only after
`snapshotJsonValue` walked and copied the resolution. Binding resolution carries
no seam-level byte cap, so a binding resolving a wide value after `maxWallMs`,
an abort, or dispose settled the run spent host heap building a frame that was
then discarded. The check moves ahead of the snapshot.

Also in this change:

- `readProcessStart` moved after `messageOf`. Inserting it between `messageOf`'s
  JSDoc and its body left that function undocumented and the orphaned block
  reading as a second doc for the reader; `verify-export-jsdoc` does not catch it
  because `messageOf` is not exported.
- The README pair adds the disposed-runtime rejection to `run()`'s public
  contract, which `src/index.ts` has enforced all along.
- Known Limitations records three deferred constraints that until now existed
  only in review discussion: the combined log-and-value peak the load gate does
  not model, the host-side per-member expansion of a wide binding reply (owned by
  `packages/core/session`, and shared with the worker-thread backend), and the
  absence of fd-3 backpressure for concurrent replies.
- The Agent Note's same-group section records the teardown identity guard and its
  two rulings, including why an ABSENT start-time reading proceeds rather than
  withholding the signal, and that reading it as a mismatch is what turned the
  three same-group heartbeat cases red on Linux.
2026-08-31 14:31:48 +08:00
Chinesezjc
0a46bb3414 style(code-runtime-python): keep the teardown v8-ignore under the line limit
The directive carried its whole justification inline at 203 characters, past the
140 the @stylistic/max-len rule allows (imports and template-literal messages
are exempt; a line comment is not). The reasoning moves to the lines above and
the directive keeps a short pointer, since a v8 ignore must stay on one line.
2026-08-31 14:30:02 +08:00
Chinesezjc
68f61b2e2f test(code-runtime-python): exempt the two single-platform teardown arms from coverage
The PID-reuse guard has two arms no single OS can execute: the non-Linux early
return in readProcessStart (the Linux coverage lane always takes the read path)
and the refusal arm, which needs a real pid recycled into a new group leader
between spawn and teardown -- no test can schedule that. The coverage lane
reported 99.53% statements / 99.14% branches on src/index.ts for exactly these
two.

Both carry a v8 ignore naming what cannot be reached and why, the convention
this file and subprocess-local already use for platform defenses. The reader
itself stays covered by the process-identity test rather than being exempted
wholesale.
2026-08-31 14:30:02 +08:00
Chinesezjc
2ad93da755 fix(code-runtime-python): treat an absent start-time reading as reaped, not recycled
The PID-reuse guard refused to signal whenever the current reading differed
from the one taken at spawn, including when it was ABSENT. On Linux a reaped
leader has no /proc/<pid>/stat, so every teardown after the leader exited
skipped SIGTERM/SIGKILL while the group it led still held survivors -- the
exact case the process-group teardown exists to reap. Three same-group survivor
tests went red on the coverage lane; they pass on Darwin because the reader
always returns undefined there, leaving the guard inert.

Only a present-and-different reading now blocks the signal. Verified on the
self-hosted Linux box: a reaped leader with live survivors allows the signal, a
pid whose start time differs still blocks it, and a live matching process is
signalled.
2026-08-31 14:30:02 +08:00
Chinesezjc
33318a5767 docs(code-runtime-python): state the real load-time rejections and finish the zh README
The README pair described `run()` as rejecting "a malformed binding namespace or
non-positive config", which understated and misplaced the configuration
failures: a non-Unix platform, a non-integer budget, a timer value setTimeout
would clamp, a budget larger than one fd-3 frame, and an incompatible
addressSpaceMb/output-budget pair all throw from the CONSTRUCTOR, so they fail
when the plugin loads rather than on a later run. Both sides now separate the
load-time platform/configuration errors from the run-result contract.

The Chinese README's Model Experience and KV Cache effect sections were still
untranslated English; the pairing record only tracks hashes, so it could not
show that. Both are now translated.
2026-08-31 14:30:02 +08:00
Chinesezjc
2e3cf144d5 docs(code-runtime-python): correct the claims the new backend invalidated
Adding a published Python backend and reordering `flush_line` left several
owning documents stating things that are no longer true.

`src/invariant.ts` justified its empty installer with "ships only the fd-3
wire-protocol codec", which the subprocess execution path contradicts. The
reason now states the actual one: every relation this backend maintains lives
in the CPython child or on the fd-3 wire, so no same-process event sequence is
observable from a listener -- the same shape the sibling worker-thread backend
uses.

The seam's `PORTABLE_RESERVED_WORDS` and `language` JSDoc, the code-runtime
README pair, and docs/subsystems/code-runtime both said only TypeScript has a
published backend. Corrected in all four, with the generated cordis catalog
regenerated for the `language` change.

The note attributed the 12x multiple to the settlement flush holding three
copies. That stopped being true when `flush_line` was reordered to drop the
pending chunks before its push: the binding worst case is the newline path's
single near-budget write. Corrected in the note (both sides) and in the test
comment that repeated it.

The note's Testing section now registers the cases this stack added, and the
Chinese side receives the O(depth) entry it never got plus the new ones -- it
had drifted from the English.

`INTERPRETER_BASELINE_BYTES` argued 64 MiB from a RESIDENT set while RLIMIT_AS
bounds address space. It now cites the bootstrap's own measurement (30.23 MiB
of mappings for `python3 -I`), making 64 MiB roughly twice the measured
baseline.

Also: a hardcoded `(:232-235)` comment reference becomes a reference by name,
a "which now walks in O(depth) too" change narrative becomes a current-state
statement, and a stray double blank line is removed.
2026-08-31 14:28:26 +08:00
Chinesezjc
e6b547bef4 fix(code-runtime-python): guard teardown, log prefix, and settlement flush
Four independent corrections in the run lifecycle.

`killGroup` signalled `-child.pid` with a raw `process.kill`. Node keeps the
numeric `child.pid` after the leader is reaped and only clears its internal
handle, so `child.kill()` refuses while the raw call does not; `close` can
trail `exit` by seconds when a pipe-holding descendant keeps the streams open.
A recycled pgid could therefore receive this run's SIGTERM and armed SIGKILL.
`groupEmpty()` does not cover it: it reports whether the group has members, not
whether they are ours, and it first runs after the signal. The leader's start
time is now read at spawn and re-checked before each signal, matching the
position packages/subprocess/subprocess-local already states
("ProcessIdentity ... preventing teardown escalation after PID reuse"). Kept
local rather than depending on that package, which would add an architectural
edge. Linux reads /proc; Darwin has no /proc, so the reader reports undefined
and the guard degrades to the previous behavior instead of forking `ps` on a
teardown path.

`_push_bounded_prefix` built `(*self._pending, extra)`, copying every pending
reference into a same-size tuple before the bounded loop. For a
single-character drip that is a second pointer array as large as the list:
measured +80 MiB of tuple over a 40 MiB list for 5.2M chunks, the allocation
the bounded prefix exists to avoid. It now iterates the list in place and
handles `extra` in the loop's `else`; 4000 randomized inputs produce byte-identical
prefixes.

The settlement `flush_out()`/`flush_err()` ran outside any guard while `done`
was already decided, so a flush raising under memory pressure skipped
`send_done` and downgraded a child-classified `exception` into a host-side
`worker-exit`. Both are now wrapped, swallowing only the log tail.

The boot re-check's `if effective_soft != RLIM_INFINITY` was dead: `_clamped`
is asked for a finite `addr_bytes` on both sides and each branch returns that
value or a `min` with an inherited bound, so RLIM_INFINITY is unreachable. The
guard could only ever have skipped the re-check it claimed to protect.
2026-08-31 14:26:23 +08:00
Chinesezjc
8f7d9121d1 fix(code-runtime-python): bound three child-side walks by depth, not width
Three separate paths in the CPython child allocated state proportional to a
value's width or a string's length, so a legitimate input the byte budgets
admit could die as the program's own MemoryError.

`_lossless_json_violation` enqueued one traversal tuple per member while
running, in `dispatch`, over MODEL-CONSTRUCTED binding arguments that no
child-side byte budget bounds first. It now uses the same (kind, container,
iterator) cursor the other two walks already had, checking dict keys as the
cursor pulls each entry. Measured over `[0] * 6_000_000` (~17 MB of JSON):
459.1 MiB of traversal tuples before, 0.0 MiB after.

`_decode_json_plain` matched JSON strings with a `(?:[^"\\]|\\.)*` repetition,
which makes CPython's engine retain backtracking state proportional to the
string's width: 146 MiB for a 1 MiB string, 557.8 MiB for 4 MiB. A legitimate
multi-megabyte binding reply raised MemoryError inside `_pump_replies`, and
because that pump is the only settler of the call's future, the run stranded
until the wall clock reported `timeout`. Strings now scan chunk-to-chunk over a
character class, which the engine matches without backtracking state; the same
4 MiB decode peaks at the 4.0 MiB result.

`_check_done_value` charged strings and dict keys what
`_dump_string(...).encode()` returned, building the escaped copy plus its
encode to MEASURE it -- ~6x the original each for control-heavy text, so
metering a value the budget then rejects could itself breach RLIMIT_AS and
report `exception` where the seam promises `output-limit`. The new
`_json_str_cost` counts instead, reusing `_json_string_cost`'s C-level passes
and reproducing `_dump_string`'s exact surrogate rules (fold spelled-out pairs,
charge six ASCII bytes per lone surrogate). Identical values, 228.9 MiB -> 19.1
MiB of peak on a 20M-NUL string.

Each fix ships a regression test. The two RLIMIT_AS repros are Linux-only:
Darwin does not apply the limit, so the peaks above are measured directly and
recorded in the test comments.
2026-08-31 14:24:59 +08:00
Chinesezjc
86674ed21e test(code-runtime-python): budget the wide-value walk for an instrumented lane
The O(depth) wide-value regression test ran under `maxWallMs: 20_000`, but the
cursor pulls 6M elements one at a time through Python-level frames: ~11s on an
idle machine, and more under the coverage lane's V8 instrumentation with several
workers sharing a runner. CI reported `timeout` instead of the round-trip.

Raise the run's ceiling to 60s inside a 90s vitest timeout, so the runtime's own
wall clock still fires first on a genuine hang. The assertion is unchanged and
still discriminates: restoring the O(width) `stack.extend` enqueue fails the test
with a child-side MemoryError in ~2.6s.
2026-08-31 14:24:59 +08:00
Chinesezjc
bca73068f6 fix(code-runtime-python): walk the completion value in O(depth), not O(width)
`_check_done_value` and `_encode_json_plain` pushed one stack entry per child
(plus a separator marker, and `dict.items()` materialized as a list), so the
bookkeeping scaled with the value's WIDTH rather than its depth. A value the
byte meter admits could then die on the walk's own frames: a flat
`[0] * 2_000_000` serializes to 4.0 MB, but measured peaks were 145.2 MB in the
meter and 114.7 MB in the encoder — 28.7x the serialized size, far past the 12x
the load-time address-space gate reserves.

Each container now pushes ONE cursor frame that pulls its children one at a
time and writes into a shared `io.StringIO`, so the output string is the only
width-proportional allocation and the caller already metered its size. Measured
on the same value: 0.0 MB in the meter and 9.0 MB in the encoder (2.3x), with
identical verdicts.
2026-08-31 14:24:59 +08:00
Chinesezjc
9a8663cc4c fix(code-runtime-python): flush logs before framing the completion value
The load gate bounds maxLogBytes and maxValueBytes independently against the
address space, but the child framed the completion value (materializing its
escaped form to meter it, then encoding the frame) while a newline-free log tail
still sat unflushed in _pending. Those two peaks added, so two budgets each
admitted alone could together breach RLIMIT_AS and die as worker-exit instead of
settling. The success path now flushes both log streams before _done_with_value
runs; the trailing flush stays for the exception path and is an idempotent no-op
after a successful settle. A combined-peak regression test (32 MiB each against
512 MiB) asserts the over-budget value reports output-limit rather than OOMing.

Also corrects the worst-case-multiple JSDoc and Agent Note: after 1088d6f03d
made flush_line drop pending before its push, the settlement-flush path holds
two copies, not three, so the newline path is the sole 12x worst case. The
reorder is recorded as a called-out untested fix (the 12x gate already admits
only configs safe under both flush orders).
2026-08-31 14:24:59 +08:00
Chinesezjc
aa54467476 Merge origin/master and repair the dead note link from PR 2573
Bring in master through cf6750b10 (including the gate-runner fail-fast
change) and drop the stale fixture reference in the
case-insensitive-path-round-trips note: PR 2573 linked a fixture that PR
3128 had already removed, so every pull request's markdown-links gate
failed on master's own note. The claim stands without naming the deleted
file; verify-md-links now resolves all 2199 files locally.
2026-08-31 14:24:51 +08:00
Chinesezjc
faeb4e2218 Merge remote-tracking branch 'origin/master' into fix/windows-coverage-align-linux 2026-08-31 14:23:32 +08:00
Chinesezjc
9d9525549d fix(code-runtime-python): raise the output-budget worst-case multiple to 12 and reject the boundary
The load-time output-budget/addressSpaceMb gate used a worst-case multiple of 8,
assuming two simultaneous ~4x astral copies (the built string and its encode).
Three are live at the peak: on the newline path a single write holds the caller's
text argument, the line slice handed to push, and push's encode copy; the
settlement flush_line path held the pending chunks, their join, and that encode
copy. A budget admitted at 8x (e.g. maxLogBytes 48 MiB against addressSpaceMb 512)
could still OOM the child. The multiple is now 12, the strict `>` is `>=` so a
budget whose peak exactly equals the room left after the interpreter baseline is
rejected (that peak plus the baseline is the whole address space), and flush_line
drops the pending chunks before its push to match the newline path's
join-clear-push order. The child re-check mirror and both note sides move in step;
config-catalog is regenerated from the updated field JSDoc.
2026-08-31 14:22:37 +08:00
Chinesezjc
ce91c70f9a test(code-runtime-python): assert the inherited-RLIMIT_AS boot re-check reports exception
The boot re-check raises inside bootstrap's setrlimit-phase handler, which
classifies every resource-limit-application failure as kind 'exception'. The
test asserted 'worker-exit'; align it to the actual class and keep the message
assertion so the case still discriminates a config rejection from a generic
setrlimit error. The Agent Note's two references to the reported kind are
corrected on both language sides and the pair re-recorded.
2026-08-31 14:22:37 +08:00
Chinesezjc
436a97a12d fix(code-runtime-python): reserve the interpreter baseline in the budget gate and re-check against the clamped RLIMIT_AS
The output-budget/address-space gate's 8x multiple had no room for the
interpreter's own footprint, so a budget sized right at addressSpaceMb/8 was
admitted while its worst-case peak plus the interpreter overran RLIMIT_AS
(e.g. 15 MiB maxLogBytes against 128 MiB). Reserve a fixed
INTERPRETER_BASELINE_BYTES (64 MiB) before the multiple claims the rest, so each
budget times 8 must fit the room LEFT after the baseline.

The host gate validates against the CONFIGURED addressSpaceMb, but a launch
environment can inherit a stricter RLIMIT_AS (a ulimit -v wrapper below
addressSpaceMb) that _clamped lowers the effective limit to, leaving the budgets
sized for a ceiling the child never gets. bootstrap.py now re-checks both budgets
against the effective clamped soft limit after applying it, mirroring the host
gate's multiple and baseline, and raises at boot rather than letting a
near-budget output OOM mid-run.

Add regression tests for both (the load gate against a 256 MiB address space
covering both budgets, and a ulimit -v wrapper for the inherited-limit re-check);
register the tail-copy test in the note Testing section; sync the zh pair. Merges
origin/feat/code-runtime-python-protocol to resolve the DIRTY base.
2026-08-31 14:22:37 +08:00
Chinesezjc
86c6d9345e test(code-runtime-python): size the tail-copy repro so the model can build its own string
The tail-copy regression built `"first\n" + "A" * 200 MiB`, whose construction
alone peaks near 400 MiB (the string plus the concat temporary) and OOMs under
the 384 MiB addressSpaceMb before the log path under test runs — a MemoryError in
the model, not the defect. Build the tail in a variable and concatenate only the
newline (peak ~2x150 MiB = 300 MiB, under the address space), so the model's own
allocation fits; the pre-fix code then buffered the whole 150 MiB tail again,
pushing past 384 MiB, while the sliced prefix does not.
2026-08-31 14:22:37 +08:00
Chinesezjc
d9307ae2a4 fix(code-runtime-python): size the output-budget/address-space gate by worst-case Unicode and gate both budgets
The load-time addressSpaceMb gate used a 1/8 fraction derived for ASCII, but the
child ledgers trigger on character count against a serialized-byte budget: an
astral character is one character yet ~4 bytes stored and ~4 encoded, live at
once, so the true worst-case peak is ~8x the budget, not ~2x. Replace the
fraction with an explicit OUTPUT_BUDGET_WORST_CASE_ADDRESS_SPACE_MULTIPLE (8)
and a strict `>`, and gate maxValueBytes the same way as maxLogBytes — the value
path builds and encodes a near-budget completion under the same RLIMIT_AS, so
the incompatible pair was previously admitted there too.

Slice the newline branch's unterminated tail to a budget-sized prefix: it
buffered the whole text[pos:] before the flush trigger could bound it, so an
early newline plus a huge tail made a second full copy of the model's string —
an RLIMIT_AS death the config gate cannot cover since the tail can far exceed
maxLogBytes.

Disclose the cross-field constraint in the maxLogBytes/maxValueBytes/addressSpaceMb
JSDoc (regenerating config-catalog); refresh the note's stale
Buffer.byteLength(JSON.stringify) reference; reconcile the arrival-order rebuttal
with the seam's "in order" logs JSDoc (within-stream, cross-stream best-effort).
Extend the load-rejection test to both budgets and add a tail-copy regression;
sync the zh pair.
2026-08-31 14:22:37 +08:00
Chinesezjc
2df88b5bbe fix(code-runtime-python): reject an oversized maxLogBytes at load instead of metering log capture at runtime
The child log ledger encodes an admitted entry to UTF-8 once to charge its
serialized cost, so a maxLogBytes approaching addressSpaceMb lets a legitimate
near-budget log entry breach RLIMIT_AS and die as worker-exit instead of
truncating. Two runtime fixes were tried and both traded one resource bound for
another: an exact serialized-cost check is either a full encode (the allocation
being avoided) or a per-character Python loop that burns the CPU budget (a 10 MB
write hits SIGXCPU under cpuSeconds:1). The breach is a property of the
maxLogBytes/addressSpaceMb pair, not any write, so reject the incompatible pair
at load — maxLogBytes must stay within one eighth of the addressSpaceMb byte
count — and revert _LogStream to its original character-count buffering, which
is memory-safe once the budget fits the address space. The check runs on every
platform since the incompatibility is a config-value property, not a runtime one.

Replace the child-flood regression tests (which asserted the reverted runtime
behavior) with a load-rejection test. The host-side accrueStrayCost UTF-8
per-lead validation and its tests are unaffected. Update the note and zh pair.
2026-08-31 14:22:37 +08:00
Chinesezjc
c24e1e991b fix(code-runtime-python): charge structurally-valid-but-illegal UTF-8 and newline-path logs by decoded cost
accrueStrayCost accepted any 0x80-0xBF continuation, so a CESU-8 surrogate
(ED A0 80) or overlong (E0 80 80) — structurally well-formed but illegal, and
as cheap to flood as 0xFF — was charged its structural width 3 while
toString('utf8') renders each byte as its own U+FFFD (cost 9). Validate each
lead's first-continuation range (WHATWG E0/ED/F0/F4 bounds) and charge 3 per
byte of any sequence outside it, folding a broken prefix to one U+FFFD.

The child _LogStream newline path had the same char-vs-serialized gap the
newline-free trigger had: its per-line fit checks (first reconstructed line and
each subsequent line) compared character count against the serialized-byte
budget, so a control-char line passed and _logs.push encoded it whole, breaching
RLIMIT_AS. Route every check through _fragment_cost_upto, which sums per-char
costs from _json_char_cost over a start/end sub-range without slicing or
encoding and stops at the budget.

Decline arrival-order stray flushing: the two pipes' data events interleave
nondeterministically and logs carries no cross-pipe ordering guarantee, so a
fixed drain order is as valid as any and an arrival-tick branch could not be
covered without a flaky test.

Add CESU-8/overlong, newline-path-flood, and all-lead-class reassembly
regression tests; fix the note's now-inaccurate CESU/illegal-byte claims and a
fixture byte-count comment; sync the zh pair.
2026-08-31 14:22:37 +08:00
Chinesezjc
5c43621ed2 fix(code-runtime-python): weigh the child log flush by per-fragment serialized cost, allocation-free
The prior child-flush fix measured each fragment with chunk.encode('utf-8'),
which copies the whole write — under a tight addressSpaceMb a single 340 MiB
write died on that encode (the exact allocation _push_bounded_prefix exists to
avoid), and re-scanning the whole pending list per write was quadratic under a
daemon-thread flood (the concurrent-write test timed out at 28s). Compute each
fragment's serialized cost with _fragment_cost_upto, which walks the str via a
new _json_char_cost (code point to escaped width, no encode) and stops once the
running total passes the budget, and accumulate it into _pending_cost once per
write. The early-flush trigger reads that accumulator: still charges control
chars their full serialized width (a NUL is 6 bytes), but never encodes a whole
write and never re-scans the buffer, so the 340 MiB single-write and
daemon-thread tests pass alongside the NUL-flood one.

Rework the child NUL-flood regression to write in 1 MiB chunks under a 512 MiB
address space so its own argument construction is not the allocation under test.
2026-08-31 14:22:37 +08:00
Chinesezjc
d9f2fa1b04 test(code-runtime-python): drive the child NUL-flood test without a single huge argument
The child-log-flood regression built one 30M-char argument string, which under
the 64 MB addressSpaceMb died on RLIMIT_AS during construction (exit 120) before
the flush trigger under test could run, so it failed on Linux CI. Write the
flood in 1 MiB chunks under a 512 MiB address space instead: the argument str is
never itself the allocation under test, the fixed serialized-cost trigger keeps
the pending tail bounded to a few MiB, and the run completes at the marker; the
pre-fix char-count trigger accumulates the whole ~200 MiB and its ~1.2 GiB
settlement encode breaches RLIMIT_AS. Mirrors the addressSpaceMb budget the
existing oversized-completion tests use.
2026-08-31 14:22:37 +08:00
Chinesezjc
dbff8ffba3 fix(code-runtime-python): charge illegal UTF-8 by its U+FFFD width on both log paths
The host stray-capture cost function charged illegal UTF-8 bytes (0x80-0xC1,
0xF5-0xFF, and orphaned multibyte leads) the raw 1, but toString('utf8')
renders each as U+FFFD (3 serialized bytes). A b"\xff" flood was undercounted
threefold, so the residual grew to a full budget's worth of raw bytes before
flushing and, near a large maxLogBytes, expanded toward a ~1 GiB peak in the
flush's concat plus toString. Replace serializedBufferCost with accrueStrayCost,
a cross-chunk UTF-8 walker that charges each byte its decoded serialized width;
carry its sequence state on each StrayBuffer.

The child _LogStream had the same-family bug: its early-flush trigger compared
_pending_chars (character count) against remaining (a serialized-byte budget),
so a 30M-NUL newline-free flood stayed under a 50 MB char trigger yet encoded to
~180 MB at settlement, breaching RLIMIT_AS as worker-exit. Track _pending_cost
via the _JSON_BYTE_COST table and trigger on it; keep _pending_chars for the
char-based slice bounds.

Correct the note's surrogate claim (only the string-walking jsonStringCostUpTo
charges a lone surrogate six bytes; the byte walker never sees one). Shrink the
post-truncation fixture below PIPE_BUF for a deterministic single callback. List
the shared stdout/stderr budget as a third honest fail-before exception
(cross-pipe arrival timing is nondeterministic). Add illegal-UTF-8,
broken-multibyte, and child-log-flood regression tests; sync the zh pair.
2026-08-31 14:22:37 +08:00
Chinesezjc
45814baf26 test(code-runtime-python): make the stray-seal copy-volume bound discriminate
The stray-sealing regression test asserted copied < 2 MiB — about 4x the
defended sealed shape, so reverting the seal to a re-merge (or removing it)
left the test green. Measured both shapes as the fd-3 sibling does: the sealed
shape copies ~120 KB, the re-merge shape ~538 KB. Tighten the bound to 256 KiB,
which sits between them, and record the measurements in the comment and the
Agent Note so the fail-before claim holds.
2026-08-31 14:22:37 +08:00
Chinesezjc
e76b3baf9e fix(code-runtime-python): meter stdout and stderr stray residual against one shared budget
stdout and stderr each checked their pending serialized cost against the full
logBudget independently, so both could retain nearly a budget's worth of
newline-free residual at once — double the intended peak, up to ~512 MiB near
the ceiling. The flush threshold now reads the COMBINED cost of both pipes and
flushes both when it crosses, since they share one ledger.

Remove the post-truncation admit() v8-ignore: captureStray's per-line loop
makes that branch deterministically reachable within one data callback (a chunk
whose first newline-terminated line exhausts the budget hits it on the second),
so it is measured by a new regression test rather than ignored.

Refresh two stray-output test comments that still named the removed
StringDecoder; the raw-chunk buffer reassembles a split multibyte sequence by
concatenating before it decodes, and the end flush renders a stranded partial
as U+FFFD via toString('utf8').
2026-08-31 14:22:37 +08:00
Chinesezjc
f29b4b1cb9 fix(code-runtime-python): seal stray fragments, flush by serialized cost, charge lone surrogates fully
Three follow-ups the review caught in the stray-capture rewrite, plus a cost
undercount shared with the log ledger.

Seal the stray fragment list into blocks past MAX_PENDING_CHUNKS, mirroring the
fd-3 reader: a program pacing single-byte os.write(1, ...) calls otherwise
accumulates one live Buffer per write, and the per-object overhead no byte
count sees exhausts the host heap far below the budget.

Flush the residual by its running SERIALIZED cost (serializedBufferCost, a
per-byte lower bound) rather than raw byte count: a control-char-dense
newline-free flood serializes several-fold, so a raw-byte threshold let it grow
to a full budget's worth of raw bytes — up to ~6x what the ledger admits —
before flushStray concat/decoded the whole ~256 MiB residual at once.

Charge a lone surrogate its full six escaped bytes (\uXXXX under ES2019
well-formed JSON.stringify) in both jsonStringCostUpTo and serializedBufferCost,
not the three bytes Buffer.byteLength reports for U+FFFD: a forged log frame
flooding \ud800 escapes was undercharged by half and admitted ~2x maxLogBytes.

Key the sync-spawn leak assertion off the exact bootstrap path from the mocked
spawn's argv, immune to a sibling worker's concurrent staging. Refresh the
stale load-check comment that named the replaced JSON.stringify mechanism.

Add lone-surrogate, stray-sealing, and companion regression tests (per-file
100% coverage); update the Agent Note and zh pair.
2026-08-31 14:22:37 +08:00
Chinesezjc
a9c480bf39 docs(config-catalog): refresh the code-runtime-python Config source line
Removing the now-unused StringDecoder import shifted the Config interface
down by one line; regenerate the embedded source reference.
2026-08-31 14:22:36 +08:00
Chinesezjc
8093d22164 fix(code-runtime-python): bound stray capture by serialized cost, chunk-scan, and flush on destroy
The line-aggregating stray capture from the previous round regressed three
ways the review caught. Rewrite it on the fd-3 reader's raw-Buffer-chunk
shape: accumulate chunks with a byte counter and split on the raw 0x0a byte,
so a large newline-free write no longer re-copies the residual and re-scans
from index 0 per chunk (both O(N^2)). Meter each admitted entry by serialized
cost through a new jsonStringCostUpTo that walks to the cap and stops, so a
near-budget control-char-dense line never allocates the sixfold-inflated
JSON.stringify result the old ledger did (the critical: ~1.6 GiB transient
under a large maxLogBytes). Flush the residual explicitly in the closeDeadline
handler before it destroys the streams, so a setsid escapee's path (which
fires no end) does not drop a leader's final newline-free diagnostic.

Harden the sync-spawn leak assertion to a set difference against a pre-run
snapshot, immune to a parallel worker's concurrent tmpdir create/delete.

Decline the round-2 request to enforce the fd-3 ceiling per-frame: the counter
check must precede Buffer.concat to prevent ~2x memory doubling (two
regression tests assert this), and the batch-edge false reject it would fix is
reachable only at a maxLogBytes/maxValueBytes configured within one pipe read
of the 256 MiB ceiling, far past the defaults. Documented at the check and in
the note Alternatives.

Add flood, NUL-flood, short-escape, and closeDeadline-flush regression tests
(restoring per-file 100% coverage); update the Agent Note and zh pair.
2026-08-31 14:21:57 +08:00
Chinesezjc
c8bf75cbe4 test(code-runtime-python): cover the newline-free stray-flood ledger bound
The line-aggregating stray capture added two branches — the post-truncation
early return and the residual-overflow admit — that the aggregation and
split tests did not exercise, so per-file coverage dropped below 100%. A
2 MB newline-free native write under a 4 KiB maxLogBytes drives the residual
across the budget (admit-and-truncate) and then short-circuits later chunks,
asserting the captured output ends at the truncation marker and stays under
budget rather than buffering the whole flood.
2026-08-31 14:21:57 +08:00
Chinesezjc
44203f3fa7 fix(code-runtime-python): resolve worker-exit on sync spawn failure; aggregate stray output by line
Wrap spawn and the fd-3 narrowing so a synchronous throw (ENAMETOOLONG on
an over-PATH_MAX pythonBin, EMFILE) removes the run's staging directory and
resolves the same worker-exit class as the async error event, instead of
rejecting run() and leaking the directory.

Aggregate native stdout/stderr by real newline rather than by Node data
chunk: logs entries are joined with "\n" downstream, so a newline-free
write larger than one pipe read no longer reads back with spurious breaks.
The ledger still bounds a newline-free flood.

Track a running scan offset in both frame readers so a large frame
accumulated across chunks is scanned once, not re-scanned from 0 per chunk.

Reword the deadline hard-bound v8-ignore to state its real environment
dependence (PID-1-doesn't-reap container, zombie survivor) and cross-ref
the note's rejected signal-0 alternative; fix settle comments that quoted
the pre-qualification teardown contract; document the capMessage vs
_cap_message billing split on both sides; guard the dispose-after-resolve
heartbeat assertion against a vacuous 0===0 pass; reuse
_TRUNCATION_MARKER_BYTES; note the abandoned-call pending-entry bound.

Update the Agent Note Decision/Testing/Alternatives/Consequences for the
above and record the confirmed-empty finalize as a second honest
fail-before exception; sync the zh pair.
2026-08-31 14:21:57 +08:00
Chinesezjc
1103e36c22 fix(code-runtime-python): confirm group death at the deadline; chunk the frame read
The reap-poll deadline arm sent SIGKILL then finalized immediately, declaring
quiescence on mere signal delivery while the group was still dying. It now keeps
polling for the group to actually empty (bounded by one more reap margin) after
its self-sent SIGKILL, so `finished` resolves only on a confirmed-empty group.

ProtocolChannel.read_frame read the boot/run handshake frames through
FileIO.readline() on the unbuffered fd — one os.read(1) per byte, so a
multi-megabyte program burned CPU (RLIMIT_CPU already in force for the run frame)
in millions of syscalls before ast.parse. It now reads in chunks into the same
_pending buffer the async reader uses; the wrapping os.fdopen is gone. read_frame
is this PR's own code (e7f22ed3), not the protocol layer. The chunked read is a
syscall-count improvement with no cross-platform-deterministic failure to assert,
noted as such in the Agent Note.
2026-08-31 14:21:57 +08:00
Chinesezjc
28f747d775 test(code-runtime-python): cover the reply-pump closed-loop guard; align setsid docs
The closed-loop reply-pump guard now ships with a deterministic regression test:
a worker thread abandons a binding so its loop closes, the host answers that call
before a later binding, and the pump must survive the closed-loop
call_soon_threadsafe to deliver the later reply (host-gated ordering makes it
deterministic; unguarding the pump hangs the later binding to the wall clock).

Align the quiescence self-description with the shipped setsid limitation:
teardown()'s JSDoc and the Agent Note's Problem line now qualify "no subprocess
outlives the fiber" to subprocesses that stay in the child's process group, with
a setsid()-escape exception pointing at the README. Tighten the setsid-orphan
fixture's self-timeout to 5s and its upper-bound assertion to <4000ms so a failed
deadline backstop is a sharper red. Register the new regression tests in the note.
2026-08-31 14:21:57 +08:00
Chinesezjc
bea8708b5d fix(code-runtime-python): reject a non-integer maxLogBytes/maxValueBytes at load
The child reads these byte budgets through int(...), which silently floors a
float, so maxLogBytes: 3.5 would truncate at 3 bytes child-side while the host
meters and marks at 3.5 — the two sides enforcing different public config. Gate
them to integers at load, as the worker backend does; correct the stale comment
that claimed the int()-truncated caps needed no gate. Adds a regression test.
2026-08-31 14:21:57 +08:00
Chinesezjc
db5f890c7f test(code-runtime-python): update CPU-timeout assertions to the reworded message
The SIGXCPU timeout message changed from "CPU budget (Ns) exhausted" to name the
configured value as a ceiling; two existing timeout tests asserted the old text.
Assert "CPU time exhausted" to match.
2026-08-31 14:21:57 +08:00
Chinesezjc
63c49c8a90 fix(code-runtime-python): meter the exception diagnostic by serialized cost
Raising maxValueBytes' load bound to ceiling-envelope assumed both budgets are
metered in serialized (JSON-escaped) bytes, which held for completion values and
logs but not the diagnostic: _cap_message capped by raw UTF-8, so a control-heavy
message near maxValueBytes could serialize sixfold and breach the fd-3 frame
ceiling — the silent worker-exit inversion the load check prevents. _cap_message
now accumulates per-byte serialized cost (new _JSON_BYTE_COST table) and cuts the
prefix that fits. Also reword the host SIGXCPU timeout message to name cpuSeconds
as the configured ceiling rather than a budget a stricter inherited RLIMIT_CPU
soft may undercut. Adds a control-heavy-diagnostic regression test.
2026-08-31 14:21:57 +08:00
Chinesezjc
e0d5d8d097 fix(code-runtime-python): send SIGKILL at the reap-poll deadline, not cancel it
The group-reap poll folded its deadline arm into the empty-group arm, so a host
event loop blocked past graceMs + CLOSE_REAP_MARGIN_MS would run the overdue
poll before the grace SIGKILL timer: the group is still non-empty, the deadline
has passed, and the shared arm cancelled the never-fired SIGKILL and finalized —
releasing a SIGTERM-ignoring same-group survivor for good. Split the arms: empty
group cancels the moot timer and finalizes; deadline-with-non-empty-group sends
SIGKILL itself (idempotent if the timer already ran) before finalizing. Adds a
regression test that busy-blocks the loop past both timers and asserts the
survivor's heartbeat freezes.
2026-08-31 14:21:57 +08:00
Chinesezjc
b1ce014035 fix(code-runtime-python): restore per-file branch coverage on the reap poll
The group-reap poll's deadline arm (Date.now() >= deadline) is a backstop that
SIGKILL emptying the reachable group never reaches, leaving one uncovered branch
under the per-file 100% gate. Mark it v8-ignore with the reason and drop the
always-true graceTimer-defined guard inside pollGroup (it runs only when killing
is set, so kill() has armed the timer).
2026-08-31 14:21:57 +08:00
Chinesezjc
ecdb79824b fix(code-runtime-python): keep a completed run in live until its group is reaped
settle() dropped the run from `live` eagerly, before the grace-window SIGKILL
reaped a same-group survivor. A dispose() racing a just-resolved run() then
snapshotted an empty `live` and returned while the descendant was still alive,
so teardown's "no subprocess outlives the fiber" (and its JSDoc) was false for
that window. The run now stays in `live` until the process-group poll confirms
the group empty, at which point it is both dropped from `live` and its finished
promise resolved. Adds a regression test asserting dispose() of a completed run
with a same-group survivor returns only after the survivor stops executing.
2026-08-31 14:21:57 +08:00
Chinesezjc
9f449a79a6 docs(code-runtime-python): correct the ProtocolChannel serialization docstring
The class docstring still credited the GIL plus per-frame PIPE_BUF atomicity for
serializing writes, which _write_lock's full-write loop already superseded. State
the current contract (writers serialized by _write_lock around a full-write loop)
and drop the double blank line under the binding-replies note heading.
2026-08-31 14:21:57 +08:00
Chinesezjc
a8e47dae37 docs(code-runtime-python): note the settlement CPU recheck uses the clamped soft
Record that die_if_cpu_exhausted compares against the effective clamped cpu_soft
in the rlimit section, and add the recheck-timeout test to Testing; re-record pair.
2026-08-31 14:21:57 +08:00
Chinesezjc
6141f0062d fix(code-runtime-python): recheck CPU against the effective clamped soft limit
The settlement-time CPU recheck compared spent CPU against the configured
cpuSeconds, but _clamped may have lowered the effective soft limit to a stricter
inherited value. A program that traps SIGXCPU, burns past the inherited soft,
and returns inside the soft-to-hard gap was checked against the configured value
and falsely reported successful, bypassing the inherited limit. The recheck now
uses the clamped cpu_soft. Adds a regression test that inherits a 1s soft CPU
limit and asserts a SIGXCPU-trapping over-burn is a timeout, not a success.
2026-08-31 14:21:57 +08:00
Chinesezjc
d432603b81 docs(code-runtime-python): note the closed-loop reply-pump guard
Record the call_soon_threadsafe-onto-a-closed-loop guard in the binding-reply
section of the settlement-fixes Agent Note; re-record the bilingual pair.
2026-08-31 14:21:57 +08:00
Chinesezjc
a30b460b37 fix(code-runtime-python): keep the reply pump alive past a closed thread loop
A binding called from a worker thread records that thread's loop for its reply.
If the thread finished and closed its loop before the host reply arrived,
_pump_replies' call_soon_threadsafe onto the closed loop raises RuntimeError;
unguarded, that ends the pump task and strands every later reply. Wrap the
schedule in a try/except that drops the moot reply (nothing awaits it) and keeps
the pump serving.
2026-08-31 14:21:57 +08:00
Chinesezjc
3a560d37a6 docs(code-runtime-python): document the setsid-escape teardown limitation
A descendant that calls setsid()/start_new_session leaves the child's process
group, so kill(-pid) teardown cannot reach it; if it also releases the inherited
pipes the run still settles and the fiber goes quiescent while the orphan runs.
This is the containment boundary (model code has bash-equivalent trust), not a
guarantee; reaching such an orphan needs descendant-pid tracking and is deferred.
2026-08-31 14:21:57 +08:00
Chinesezjc
ff604dc876 fix(code-runtime-python): clear stale SIGKILL timer and clamp inherited soft rlimit
Two further review findings on the CPython backend:
- The grace-window SIGKILL timer was left armed after settlement, so on a
  normal completion a kill(-pid) could fire up to graceMs later and strike a
  recycled pgid once the kernel reused the leader's pid. settle() now clears
  the timer the moment the process group is confirmed empty (the normal path
  and when the poll sees the survivor gone), bounding the reuse window to the
  genuine-survivor case where the group cannot be empty to reuse.
- _clamped bounded rlimits by the inherited hard limit only, silently raising
  an inherited soft limit stricter than the request (loosening RLIMIT_AS or
  deferring RLIMIT_CPU SIGXCPU). It now clamps each side against its own
  inherited counterpart and pins soft under hard, keeping the strictest of
  configured and inherited. Adds an inherited-soft-limit regression test.

Agent Note expanded to seven fixes with the two new rejected alternatives;
zh pair re-recorded.
2026-08-31 14:21:19 +08:00
Chinesezjc
6cb70e6e69 fix(code-runtime-python): reap same-group survivors and fix cross-loop bindings
Two review findings on the CPython backend:
- Disposal could return while a same-group descendant that ignores SIGTERM
  but releases the inherited pipes was still alive: the leader's close fired
  and the previous fix relied on an unref'd SIGKILL timer that a short-lived
  host never fires, reparenting the survivor to init. settle() now withholds
  the run's finished promise on a ref'd process-group poll until the SIGKILL
  has emptied the group (bounded by graceMs + margin, zero-cost when already
  empty), so teardown's "await each child's exit" holds.
- A binding called from a model worker thread via asyncio.run created its
  reply Future on that thread's loop, but _pump_replies completed it directly
  from the main loop; asyncio.Future is not thread-safe across loops, so the
  call hung to the wall clock. Replies now complete via the owning loop's
  call_soon_threadsafe, and a lock serializes the id claim/write/advance.

Tests: the same-group reap case now asserts a heartbeat file stops (robust
whether the killed descendant is reaped or a zombie, so it holds where PID 1
does not wait() orphans); a cross-loop case runs a binding from a worker
thread and asserts the reply round-trips instead of timing out. Agent Note
expanded to all six fixes with rejected alternatives; zh pair re-recorded.
2026-08-31 14:21:19 +08:00
Chinesezjc
46db9e2ad4 test(code-runtime-python): update output-cap bound to ceiling-envelope
The frame-ceiling cap test asserted the old (ceiling-envelope)/6 bound and
its 44739232 message. The load bound is now ceiling-envelope because both
budgets are metered in already-escaped bytes; assert 268435392.
2026-08-31 14:21:19 +08:00
Chinesezjc
9a05c0075f fix(code-runtime-python): reap same-group children and correct log-budget bound
Address review findings on the CPython backend:
- CRITICAL: a model program could leave a descendant in the child's own
  process group that ignores SIGTERM but releases the inherited pipes, so
  the leader's `close` fired and settle() cancelled the pending SIGKILL
  before it escalated — run()/dispose() returned while that child lived.
  kill() now unrefs the grace timer and settle() no longer clears it, so
  the SIGKILL reaches the whole group; killGroup swallows ESRCH when the
  group is already gone (the normal case). Adds a real-subprocess
  regression test.
- WARNING: the maxLogBytes/maxValueBytes load bound divided the frame
  ceiling by 6 for escape expansion, but both budgets are metered in
  already-escaped serialized bytes, so a payload occupies at most
  cap+envelope on the wire. Bound is now ceiling-envelope; drop the unused
  escape constant.
- Narrow the runtime.spec.ts header to "no subprocess mocks" (it mocks
  node:fs.copyFileSync for staging-failure cases).
- Use full-width punctuation in the README.zh.md prose per translation
  rules; re-record the pair.
2026-08-31 14:21:19 +08:00
Chinesezjc
538ad4d3dc docs(code-runtime-python): sync README with the shipped backend
The package README (both languages) still described this layer as
protocol-only with the PythonCodeRuntime implementation deferred to a
later PR, contradicting the shipped code. Rewrite the intro to describe
the registered runtime, add a Configuration section for every Config cap,
and drop the "implementation not in this layer" limitation. Also pin the
residual-detach fixture's size invariant: the byteLength assertion only
holds above Node's Buffer pool threshold.
2026-08-31 14:20:00 +08:00
Chinesezjc
e576ceb913 docs: regenerate module graph for the code-runtime-python dependency
Adding @deepseek-ai/dsh-code-runtime to the backend manifest introduces a
new edge the generated graph must reflect.
2026-08-31 14:16:47 +08:00
Chinesezjc
27901c547f fix(code-runtime-python): declare the dsh-code-runtime dependency
The manifest omitted @deepseek-ai/dsh-code-runtime although src/index.ts
imports CodeRuntime and the portable-identifier constants from it and the
tsconfig references ../code-runtime. A three-way package.json merge over
the protocol-layer stub dropped the entry; restore it in peer and dev
dependencies so the declaration matches the import.
2026-08-31 14:16:02 +08:00
Chinesezjc
7b4b8df2dd docs(code-runtime-python): fix settlement-fixes note wrap and cross-link
Unwrap the English note to one physical line per paragraph (verify-md-wrap)
and retarget the backend link to the fd-3 protocol architecture note that
this stack actually ships (verify-md-links); re-record the bilingual pair.
2026-08-31 14:14:33 +08:00
Chinesezjc
c388169cff feat(code-runtime-python): add the CPython subprocess backend
Land the PythonCodeRuntime implementation on top of the fd-3 protocol
seam: python3 -I per run, binding namespace over fd 3, RLIMIT_CPU/AS,
wall-clock timer, and SIGTERM->grace->SIGKILL process-group teardown,
with the real-subprocess integration suite.

Fixes three defects surfaced on the source PR's review before they ship:
- boot-write failure resolved a worker-exit through finish()/settle()
  that read wallTimer/onAbort/live in their TDZ, rejecting run() instead;
  the boot write now runs after those bindings and the v8-ignore that hid
  the branch is removed.
- log capture serialized against settlement with no lock while model
  daemon threads keep writing; LogBuffer now owns one shared re-entrant
  lock taken by write/flush_line/push.
- the fd-3 line residual was a subarray view pinning the whole joined
  frame; it is copied into a right-sized Buffer via detachResidual so
  pendingBytes measures what is retained.
2026-08-31 14:14:32 +08:00
Chinesezjc
456dcdd8fb Merge pull request #3211 from deepseek-harness/ci/gate-fail-fast
ci: fail fast at the first blocking gate failure
2026-08-31 14:14:22 +08:00
Chinesezjc
43cfe6a26e Merge origin/master into fix/windows-coverage-align-linux
Resolve the 08-08 note conflict (keep the zero-build rewrite, drop the
SQLite busy-journal sentence removed with the SQLite backend) and drop the
now-removed session-persistence-sqlite built-package suite from the
lib-consuming self-skip inventory in the ci.yml comment, the
ci-workflow.spec.ts comment, and the partitioned-coverage note; the
inventory is now image-loadable, transform-corpus, and client-bundle.
2026-08-31 14:13:51 +08:00
Tianyi Cui
2491a9d1d9 Merge pull request #2573 from deepseek-harness/fix/windows-path-case-test-fragility
test(session): resolve one relative root on both sides of the jsonl round-trip
2026-08-31 14:13:23 +08:00
Tianyi Cui
817c67d799 Merge pull request #3339 from deepseek-harness/worktree/session-format-01-jsonl-only
refactor(session)!: remove SQLite persistence backend
2026-08-31 13:58:04 +08:00
Tianyi Cui
4553c9d957 refactor(session)!: remove SQLite persistence backend 2026-08-31 13:23:07 +08:00
Turtle
c68676d3c9 Merge pull request #3128 from deepseek-harness/turtle/remove-agent-spine-demo
refactor(bundle): remove the agent spine demo
2026-08-31 13:17:45 +08:00
Chinesezjc
0868e5d128 test: make windows coverage timing assertions deterministic
cache.spec.ts polled fire-and-forget fail-soft writes with a fixed 40ms
settle(); contended runners drain the write after the window, so the
warn/row assertions flaked. Poll the observable outcome with vi.waitFor
(5s) instead, matching the file's existing cold-read write-back pattern.

The sdk-client and subagent-dsh-sdk dispose-ladder tests passed tight
confirmation budgets (disposeGraceMs 100-300ms) to real children; on a
contended runner the SIGKILL exit edge can arrive after the budget and
close() misreports a slow reap as failure. Use the product-default
budgets (disposeGraceMs 3000ms) for the real-child cases; the fake-child
negative cases in dispose.spec.ts keep the 10ms bound.
2026-08-31 12:42:01 +08:00
Chinesezjc
a9bc7b7056 fix(ci): add client-bundle to the zero-build self-skip inventory
client-bundle.client.spec.ts reads packages/client/ui-trajectory/lib/client.js
and skips all three cases when the bundle is absent, so it is a fourth
lib-consuming suite in the instrumented corpus. List it beside built-package
in the ci.yml comment, the ci-workflow.spec.ts comment, and the
partitioned-coverage note (both languages).
2026-08-31 12:13:43 +08:00
Chinesezjc
16853e1f77 fix(webworker-packer): update image-loadable JSDoc for zero-build coverage
Both coverage lanes now run before any build, so the post-build
uninstrumented gate wording applies only to the serial-windows complete
reference; preview builds still exercise the suite against real
artifacts.
2026-08-31 12:03:47 +08:00
Chinesezjc
2dd8b3eac3 fix(ci): harden the zero-build coverage assertion and list all skip suites
Strengthen the ci-workflow.spec.ts guard to match any 'pnpm run build'
spelling (corepack prefix, multi-line run blocks) instead of one exact
string, and complete the lib-consuming self-skip inventory with the
webworker-runtime transform-corpus import sweep alongside the packer
image assertions and the built-package check. Update the ci.yml comment
and the partitioned-coverage note (both languages) to match, and drop the
stale 'post-build' phase wording and the native-Windows build-wait
rationale from the coverage-exempt comment.
2026-08-31 12:00:05 +08:00
Chinesezjc
ec6a98452d Merge branch 'master' into ci/gate-fail-fast 2026-08-31 11:56:44 +08:00
Chinesezjc
e2ef25b06e fix(ci): windows coverage runs zero-build like the linux lane
The windows-coverage job built the workspace before running the same
ci-coverage gates as Linux, but the instrumented corpus resolves
workspace imports to src through the tsconfig paths map and never
consumes lib/; the two lib-consuming suites (webworker-packer
image-loadable, session-persistence-sqlite built-package) self-skip on
unbuilt checkouts, exactly how the Linux lane already runs them. Remove
the build step so both lanes behave identically, and pin the zero-build
invariant in ci-workflow.spec.ts (red before this change, green after).

Agent Notes updated in place: corrected the build-wait rationale and the
wrong attribution of the packer assertions to the instrumented suite.
2026-08-31 11:40:33 +08:00
Turtle
4c69dc3fed test(loader): budget production profile startup 2026-08-31 11:23:46 +08:00
Turtle
16c8cf30ed test(goal): cover projection teardown access 2026-08-31 11:23:46 +08:00
Turtle
fddad3a236 test(sdk): mount session projections in loop fixtures 2026-08-31 11:23:46 +08:00
Turtle
8528e4039d chore(cli): trim test-only profile dependencies 2026-08-31 11:23:46 +08:00
Turtle
287651fd89 test(cli): replay the session title separately 2026-08-31 11:23:30 +08:00
Turtle
244de7c18a refactor(bundle): remove the agent spine demo 2026-08-31 11:23:30 +08:00
Dudu-0223
43840d6ece fix(subagent): harden adjacent message guidance 2026-08-31 11:16:00 +08:00
CreatixChu
c3672eb1e3 Merge pull request #3277 from deepseek-harness/worktree/fix-3269-read-image
fix(tool-fs): accept extension-less attachment paths in read_image
2026-08-31 11:12:47 +08:00
CreatixChu
65b8e51042 Merge pull request #3208 from deepseek-harness/worktree/steer-followup-images
fix: deliver images reliably with steer and follow-up messages
2026-08-31 10:57:44 +08:00
_Kerman
6c63e708b8 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2907
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/persistence-catalog.i18n.yaml
#	docs/subsystems/session.i18n.yaml
#	packages/api/session-controller/tests/transport.host.spec.ts
#	packages/bundle/headless/src/index.ts
#	packages/core/session/README.i18n.yaml
#	packages/schedule/schedule/README.i18n.yaml
#	packages/schedule/schedule/README.md
#	packages/schedule/schedule/README.zh.md
#	packages/session-query/tool-session-query/src/workspace-access.ts
#	packages/session/session-log-deepseek/src/index.ts
2026-08-31 10:56:53 +08:00
creatixchu
6516fbcde8 Merge origin/master into worktree/steer-followup-images 2026-08-31 10:37:39 +08:00
creatixchu
90a8467213 Merge remote-tracking branch 'origin/master' into worktree/fix-3269-read-image 2026-08-31 10:00:53 +08:00
Chinesezjc
4032a0a428 ci(windows): use ReFS block-clone installs on the self-hosted VM (#3342)
pnpm hardlinks node_modules files to the store on the same volume, and
TypeScript's native realpath resolves those links back to store paths
(F:/.pnpm-store/v11/files/...), producing TS6231 during tsc -b and vite
resolution. ReFS block cloning (package-import-method=clone) gives each
file an independent path while sharing physical blocks, avoiding the
leak without the copy cost. Clone mode needs the @reflink/reflink native
module, which the system corepack pnpm carries but pnpm/action-setup's
dest build omits, so installs run through corepack pnpm.

The install steps branch on the workspace filesystem: clone only on
ReFS, plain install on hosted NTFS (which rejects copy-on-write). The
serial-windows store points at F:\.pnpm-store to share the ReFS volume.
Agent Note 2026-08-30-windows-refs-store-block-clone-install records the
rationale; ci-workflow.spec asserts the branch.
2026-08-31 04:13:15 +08:00
Chinesezjc
161c6591be ci: fail fast at the first blocking gate failure 2026-08-31 01:54:14 +08:00
imccyu
0a53fb55be Merge pull request #3334 from deepseek-harness/release/dsh-0.1.2-alpha.2
release: dsh@0.1.2-alpha.2
2026-08-30 21:37:53 +08:00
imccyu
3f1b46a5db release(dsh): 0.1.2-alpha.2 2026-08-30 21:19:29 +08:00
imccyu
5761890711 Merge pull request #2988 from deepseek-harness/worktree-npmalpha
feat(release): add DSH alpha and canary channels
2026-08-30 20:26:17 +08:00
imccyu
45455aae77 feat(release): route dsh prerelease dist-tags 2026-08-30 19:50:51 +08:00
imccyu
f46e4a8ada docs(release): define dsh prerelease channels 2026-08-30 19:50:51 +08:00
Dudu-0223
ff34b6c28e test(web): pin expanded snapshots to bottom 2026-08-30 16:12:43 +08:00
Dudu-0223
5b91cdbf8b Merge remote-tracking branch 'origin/master' into feat/3220-steer-service 2026-08-30 16:08:31 +08:00
Dudu-0223
3091bdc257 fix(subagent): address steer review findings 2026-08-30 16:08:20 +08:00
Tianyi Cui
ed9fb840d6 Merge pull request #3325 from deepseek-harness/worktree/revert-pr-3087
revert(session): restore ignorable event compatibility
2026-08-30 15:34:41 +08:00
imccyu
9e1bdefc72 Merge pull request #3326 from deepseek-harness/worktree-rerevert2608
fix(web): restore localized permission labels
2026-08-30 14:55:28 +08:00
Dudu-0223
9f86f31411 test: align catalogs and packed session fixtures 2026-08-30 14:44:12 +08:00
Dudu-0223
b957733bce docs: confirm config catalog pairing 2026-08-30 14:36:02 +08:00
Dudu-0223
487d61bd14 docs: refresh subagent config source link 2026-08-30 14:31:32 +08:00
Dudu-0223
4fce895468 test(subagent): cover unified messaging setup 2026-08-30 14:27:37 +08:00
imccyu
8769d57c98 fix(web): localize permission preset labels 2026-08-30 14:24:23 +08:00
imccyu
5fae1d02f5 docs(web): describe localized permission labels 2026-08-30 14:24:23 +08:00
Tianyi Cui
b7a77f4f08 Merge origin/master into worktree/revert-pr-3087 2026-08-30 14:18:37 +08:00
Tianyi Cui
089e044e5b docs(session): clarify external event compatibility 2026-08-30 14:17:44 +08:00
Dudu-0223
575dc58a07 Merge remote-tracking branch 'origin/master' into feat/3220-steer-service 2026-08-30 14:16:37 +08:00
Dudu-0223
b91e7ce366 Unify adjacent Agent messaging 2026-08-30 14:14:46 +08:00
Yichen Jiang
8448c05277 Merge pull request #3316 from deepseek-harness/worktree/plugin-list-display-cbe885
feat(plugin-inventory): scope-grouped plugin list carrying agent preset compositions
2026-08-30 14:00:23 +08:00
Yichen Jiang
cf50cfa8ac Merge pull request #3315 from deepseek-harness/worktree/issue-3310-verification-a39d1a
fix(web): publish the drill claim before the descent edit
2026-08-30 12:46:30 +08:00
Tianyi Cui
b7bccd5897 fix(docs): repair reverted session note references 2026-08-30 12:35:11 +08:00
Tianyi Cui
29b65af60b docs(session): retain ignorable events for external plugins 2026-08-30 12:29:24 +08:00
Tianyi Cui
2c6ff296af Revert "Merge pull request #3087 from deepseek-harness/worktree/remove-ignorable-session-events"
This reverts commit 2123b2f418b1c8fbb86dc327b598fb11423da226, reversing
changes made to 3c0b5c68ce697537a21084f9135663017474a2e1.
2026-08-30 12:26:20 +08:00
Yichen Jiang
19c3a270fa test(agent-presets): key mounted-row assertions by entry id
The loader's entry store is a plain object, so an auto-generated all-digit
id is reordered ahead of its siblings by integer-key semantics and the
previous ordered assertion flipped on roughly one in fifteen runs. Row
ordering belongs to loader.entries(), not to this projection; the spec now
asserts each row by its id.
2026-08-30 12:08:52 +08:00
Yichen Jiang
6ff02e8a96 Merge remote-tracking branch 'origin/master' into worktree/plugin-list-display-cbe885
# Conflicts:
#	packages/client/tsdown.client.ts
2026-08-30 12:00:06 +08:00
imccyu
a69941bf51 Merge pull request #3319 from deepseek-harness/worktree-runtime-dependency-decoupling
refactor: reduce internal peer dependency fan-out
2026-08-30 11:54:45 +08:00
Yichen Jiang
c37a402dfb Merge remote-tracking branch 'origin/master' into worktree/plugin-list-display-cbe885
# Conflicts:
#	packages/client/tsdown.client.ts
2026-08-30 11:32:22 +08:00
Yichen Jiang
2f673e5aba fix(agent-presets): register the display subpath in tsconfig paths
CI's coverage lane runs on a clean tree where workspace imports resolve
through tsconfig paths to src; the value import of
@deepseek-ai/dsh-agent-presets/display therefore needs its own paths row
beside ./types. Locally the built lib masked the gap; reproduced by moving
lib aside, fixed, and re-run green under the same condition.
2026-08-30 11:32:07 +08:00
imccyu
739d9d594e Merge pull request #3318 from deepseek-harness/release/vendor-4.0.2
release(vendor): cordis 4.0.2, cosmokit 1.8.3, group 1.0.2, hmr 1.0.1…
2026-08-30 11:24:37 +08:00
imccyu
6af96785b5 release(vendor): cordis 4.0.2, cosmokit 1.8.3, group 1.0.2, hmr 1.0.17, include 1.0.7, loader 1.0.3, logger-console 1.0.2, schemastery 3.18.2, timer 1.1.4 2026-08-30 11:04:50 +08:00
imccyu
b27c8fbc02 chore(deps): refresh package manifests 2026-08-30 02:29:53 +08:00
imccyu
795d8ec985 docs: describe runtime dependency ownership 2026-08-30 02:29:53 +08:00
imccyu
34bdc81b47 test(deps): enforce runtime dependency ownership 2026-08-30 02:29:52 +08:00
imccyu
9135a13a8b refactor(consumers): remove cross-package runtime relays 2026-08-30 02:29:52 +08:00
imccyu
f4e49ccf8f refactor(services): move shared values behind service APIs 2026-08-30 02:29:51 +08:00
imccyu
6c53fe6e2a refactor(values): make shared primitives duplicate-install safe 2026-08-30 02:29:51 +08:00
Dudu-0223
0f2134d0d8 Merge pull request #3292 from deepseek-harness/perf/3270-linear-stream-queues
perf(api): make stream queue draining linear
2026-08-29 21:47:00 +08:00
Yichen Jiang
8349cc6c73 fix(agent-presets): live-mount-first inventory, per-runtime mounts, localized shipped preset names
Review round on #3316: the composition inventory answers from a standing
mount before the broken verdict (a file corrupted after mounting no longer
hides the running composition), livePresetMounts filters by the caller's
root fiber so a second Cordis runtime in one process never answers for it,
compositions carry trust and the plugin list resolves shipped preset names
through the shared dsh-agent-presets/display fold over ui-agent-preset's
dictionaries (INLINE_SAFE inline import; no cross-plugin runtime import),
the condition detail label reads Disabled when/禁用条件, and the stale
four-surfaces comment says three.
2026-08-29 20:41:01 +08:00
Dudu-0223
1e3ca1a4b3 test(ci): tolerate reaped timeout descendants 2026-08-29 20:19:38 +08:00
Yichen Jiang
235489f5a7 Merge remote-tracking branch 'origin/master' into worktree/plugin-list-display-cbe885 2026-08-29 19:41:46 +08:00
Yichen Jiang
09e4fa562f Merge branch 'master' into worktree/issue-3310-verification-a39d1a 2026-08-29 19:40:31 +08:00
Dudu-0223
112daedd54 Merge origin/master into perf/3270-linear-stream-queues 2026-08-29 18:59:23 +08:00
imccyu
910e178b08 Merge pull request #3311 from deepseek-harness/worktree-node24resolve
fix(loader): detect internal loader shape by API presence, not Node major
2026-08-29 18:19:39 +08:00
Chinesezjc
a4d4404708 feat(ui-tool): render read_image results as the image
A settled top-level `read_image` call printed its raw attachment object as
literal text in the tool card — `{"type":"image","attachment":{…}}` —
instead of the image, because no presentation metadata told a client card
how to present the reference and the tool-card layer had no image concept.

Host: `read_image` declares an `output.presentationMeta` persisting
`{ path }` only. The attachment reference deliberately lives in the
settled result content — the single record a `tools/post-execute`
replacement rewrites — not in `meta`; the id is opaque and
provider-owned, checked for existence only.

Client: `imageCardModel` derives the card from the call head, the meta
path, the result's own image block, and a shape-matched envelope. ToolRow
gains an `image` card slot; the `read_image` toolview declares the
Tool-owned `tool.call.images` slot as its child and dispatches the
gallery through it. ui-chat down-threads the session-authorized loader
(`ChatNodeOwnerProps.loadImage`), so the tool layer supplies only derived
references plus the loader and never imports an attachment
implementation; ui-attachment fills the slot with its message gallery
renderer. The card keeps the envelope text below the gallery for the
no-attachment-plugin deployment. An image-bearing tool registers a keyed
toolview; the generic fallback keeps its flattened text. `read_image`
joins the read variant with its own locale title key; both rows share
`read-family-row.tsx`.

Verification: `read-image.spec.ts` (metadata projection, envelope by
shape, reference narrowing, real-execution round trip, rejection
branches incl. non-digest ids), `image-card.client.spec.tsx` (derivation,
row render site dispatching the slot, keyed registration with the
child-slot declaration, empty-slot fallbacks, media-type enum), keyless
snapshots (`read-image-gif` added; read-image/-dimension/-reencode
updated to the `{path}` meta), five injected-defect negative controls,
and a demo GIF recorded from this PR's head through the official
image-capable model.
2026-08-29 17:41:05 +08:00
imccyu
675efe73f2 fix: node 24.9 internal issue 2026-08-29 17:37:50 +08:00
imccyu
d5e2f22b08 Merge pull request #3313 from deepseek-harness/worktree-llme2e
test(e2e): use Flash for all live model coverage
2026-08-29 17:36:05 +08:00
Yichen Jiang
cebd0a2031 refactor(plugin-inventory): match group title and switcher pill to the General-settings row idiom 2026-08-29 17:26:05 +08:00
Yichen Jiang
3b73a415c2 Merge origin/master: RemoteError wire vocabulary and ctx-based preset stores
Reconciled with the scope-grouped plugin list: compositionInventory keeps
its additive block over master's RemoteError refactor; the slimmed
settings-store keeps ctx-based signatures while staying a display-only
roster store (no describeFace, no select); dead transport-rejection tests
dropped with the wire that no longer rejects; module graph, catalogs, and
harnesses regenerated against the merged tree.
2026-08-29 17:13:45 +08:00
Yichen Jiang
0f06f973c4 refactor(plugin-inventory): settings-row style group headers
Both scope groups drop their boxed chrome for the General-settings row
idiom: a title row (session-plugins title with the right-aligned preset
selector pill; global-plugins title), a grey subtitle line carrying the
count, a hairline divider between groups, and the cards grid below.
Counts ride the subtitle as text while the data attributes keep the raw
numbers for tests.
2026-08-29 17:13:45 +08:00
Yichen Jiang
5eb7195f9d refactor(plugin-inventory): menu-pill preset switcher, collapsible groups, inline preset-provided rows
Review-driven refinements to the scope-grouped plugin list:

- The preset switcher becomes the General-settings selector pill over the
  shared Menu primitive instead of a native select, and the preset group
  is collapsible like the global one (search still forces both open).
- The session-plugins drawer is removed: rows the presets took over sit
  inline in the global list with the preset-provided tag and per-preset
  details, since the preset group above already shows those compositions.
- The status dot renders only for a live root fiber, so file-state rows
  of an unmounted preset carry their enablement tag alone instead of a
  column of grey dots.
- PresetTree reclaims the owning entry's subtree slot: EntryTree's
  constructor filed the standing mount under the roster's own Loader row,
  so after the first session composed a preset the whole composition
  leaked into root loader.entries() as host rows (each preset overwriting
  the last). A regression test holds the root entry list identical across
  a mount.
2026-08-29 17:13:45 +08:00
Yichen Jiang
e5f36cc70f feat(plugin-inventory): carry every agent preset's composition and group the settings plugin list by scope
The settings plugin list projected ctx.loader.entries() alone, hiding the
plugins sessions actually run and rendering the web overlay's deliberate
disabled tombstones (tool-bash, tool-fs, ...) as two dozen plainly disabled
rows while the same modules ran in every standard-preset session.

- dsh-agent-presets: compositionInventory() answers flattened rows per
  preset — newest live standing generation when mounted, composition file
  otherwise with !!js disabled gates evaluated against the Loader context;
  reading never mounts (regression-tested), refusal stays 'conditional',
  raced files report broken with the reason.
- dsh-host-plugin-inventory: list() gains an optional agentPresets block,
  resolving the roster as an optional peer and mapping fiber states to the
  public phase vocabulary.
- ui-settings-plugin-inventory: preset group first behind a display-only
  switcher opening on the default preset; global group collapsed with
  failures floated; host-disabled modules enabled by >=1 preset fold into a
  session-plugins drawer naming providers; search spans scopes and points
  at matches in unselected presets.
- ui-agent-preset: the General-settings default-preset row is deleted — the
  roster section's make-default and the new-session chip keep the field —
  and the settings store slims to the display roster the header label reads.

Docs, catalogs, module graph, settings-chrome goldens, and the bilingual
Agent Note ride along.
2026-08-29 17:13:45 +08:00
imccyu
08bfeda7e8 test(e2e): use Flash for live adapter coverage 2026-08-29 17:08:44 +08:00
imccyu
4d92a61e00 test(e2e): reserve pro for adapter coverage 2026-08-29 17:08:44 +08:00
Yichen Jiang
1404ded8b1 Merge pull request #3303 from deepseek-harness/worktree/dsh-ci-test-reliability
docs(testing): add CI test reliability skill
2026-08-29 16:54:54 +08:00
Yichen Jiang
d5a9e5b274 fix(web): publish the drill claim before the descent edit
A pointer drill in the @ menu left no breadcrumb and a crumb click dropped
the header, while the keyboard drill worked. InputTriggerController.settle
assigned `drilled` after execute() returned, but a pointer mousedown runs
outside any Lexical update, so the descent edit commits discretely and
re-enters track() during execute() — where refreshHeaders and
fetchCandidates both read the claim while it was still clear.

settle now claims the drill before dispatching the edit and withdraws it
only when the edit is refused, which mutates nothing and so drives no
re-entrant track().
2026-08-29 16:52:39 +08:00
Yichen Jiang
cc5173f4cf docs(testing): state the concurrent execution model where tests are written
The skill carries the reliability rules, but nothing an agent loads by default
said that specs run concurrently at all. The testing policy described tiers and
evidence without ever stating how a spec is executed, and neither subtree
AGENTS.md mentioned it — including scripts/, where the two suites that recently
failed on unrelated branches live.

docs/testing.md gains the execution model as the one home for the fact: forked
workers, concurrent coverage partitions beside other gates, and self-hosted
runners sharing a host and volume, with the rule that a spec passing only when
run alone is a defect in the spec. It links the skill for the detailed rules.

packages/AGENTS.md and scripts/AGENTS.md carry the short actionable form and
link that section, so the rule is present in the context loaded while a test in
either subtree is being written.

Both ceilings are raised for the added words and the targets in docs/AGENTS.md
move with them: docs/testing.md 1150 to 1300 (now 1237) and packages/AGENTS.md
675 to 750 (now 712), each keeping the 5% headroom the standard requires.
2026-08-29 15:31:12 +08:00
imccyu
29f0017f51 Merge pull request #3165 from deepseek-harness/worktree-npmdepresolve
fix(npm): bound published peer dependency relays
2026-08-29 15:20:25 +08:00
Yichen Jiang
1d81fc7540 docs(testing): give the review checklist its own test-reliability entry
The 'Test strength' bullet carried assertion strength, external-state
verification, the reliability reference, and the coverage caveat at once.
Splitting the reference into an adjacent entry matches how the orientation
list above names the same skill, and restores 'Test strength' to one subject.

The new entry also names the platform and timeout-budget rules the skill now
carries, so the checklist covers what a reviewer is being pointed at.
2026-08-29 14:33:33 +08:00
imccyu
a3207a758b chore: package.json update 2026-08-29 14:26:43 +08:00
imccyu
9162bc69bd fix(release): harden dependency verification 2026-08-29 14:26:42 +08:00
imccyu
b46d36d3bf test(release): verify dual-version npm layout 2026-08-29 14:26:42 +08:00
imccyu
91b5a01980 fix: complete dependency policy generation 2026-08-29 14:26:42 +08:00
imccyu
943a544899 feat: classify Host dependency exports 2026-08-29 14:26:42 +08:00
imccyu
c55beac34a feat: verify Host dependency export identity 2026-08-29 14:26:42 +08:00
imccyu
e440634456 docs: define published dependency faces 2026-08-29 14:26:42 +08:00
imccyu
de256e8bc1 feat: enforce published dependency policy 2026-08-29 14:26:42 +08:00
Yichen Jiang
596a13d1cb docs(testing): add platform-semantics and lane-budget rules to the skill
Two failure classes the repository paid for are not covered by the isolation,
synchronization, and teardown rules already in the skill.

A value the operating system owns is not guaranteed to return as written. A
test may write one back only where the assertion tolerates that write-back
failing; where the assertion depends on it, the expected value comes from a
fresh read. NTFS truncating a fractional-millisecond mtime and Windows folding
environment variable name case are the two instances seen so far.

A describe or case timeout overrides the runner's --testTimeout rather than
yielding to it, so a value below the lane budget lowers what CI granted, while
the same literal reads as a widening where the host default is smaller. The
hook budget travels with the test budget, and a case asserting a timeout keeps
its outer wait far larger than the timeout under test. Restoring a granted
budget, or sizing a bounded retry to measured contention, is named as distinct
from the masking fixes the skill rejects.

The diagnosis reference gains the platform differences under its platform
class, a classification path for self-hosted pools that expose no host metrics,
and the stopping rule for a signature no available host can reproduce.
2026-08-29 13:54:59 +08:00
Yichen Jiang
ee309c0794 Merge pull request #3299 from deepseek-harness/worktree/fix-subagent-settings-label-color
fix(snapshot): bind fixture servers to OS-assigned ports
2026-08-29 13:17:27 +08:00
Yichen Jiang
3e56eaaa0f fix(atomic-write): retry transient Windows replacement 2026-08-29 13:04:06 +08:00
Yichen Jiang
1dd5476232 Merge pull request #3308 from deepseek-harness/worktree-windows-lane-hook-budget
test(ci): carry the hook budget and align the Lefthook suite with the lane
2026-08-29 12:06:59 +08:00
imccyu
b56d4f4472 Merge pull request #3305 from deepseek-harness/worktree-connerr
feat(web): surface and recover connection failures
2026-08-29 12:03:33 +08:00
Yichen Jiang
7fbd33de00 fix(snapshot): keep fixture lifecycle tests source-clean 2026-08-29 11:50:13 +08:00
Yichen Jiang
1f8d7b73af fix(snapshot): own fixture listener lifecycle 2026-08-29 11:29:46 +08:00
imccyu
84c7ae3398 fix(web): align connection indicator labels 2026-08-29 11:18:58 +08:00
imccyu
18480ff902 test(connection): verify and document recovery behavior 2026-08-29 11:18:58 +08:00
imccyu
19b4d7f26c feat(web): add connection recovery indicator 2026-08-29 11:18:58 +08:00
imccyu
ccfbbb443a refactor(connection): centralize websocket recovery 2026-08-29 11:18:58 +08:00
Yichen Jiang
90505636cd test(ci): carry the hook budget and raise the Lefthook suite to the lane value
The Windows coverage lane grants DSH_COVERAGE_TEST_TIMEOUT_MS=90000, but two
paths declined it.

scripts/install-lefthook.spec.ts took a describe-level 30_000, restated as a
per-case constant on five cases. Every case drives spawned Git and Node
subprocesses; the slowest costs 7.5 s on an idle host, so the ceiling carried
roughly fourfold headroom and fired on branches that did not touch the file.
The suite takes 90_000 and the redundant constant is removed.

coverageTestTimeoutArgs raised --testTimeout and --expect.poll.timeout but left
--hookTimeout at Vitest's separate 10 s default, which removeFixtureSafely's
documented 10-second Windows retry window meets exactly. Raising only the test
budget would move a contended suite's failure into its teardown.
2026-08-29 11:15:32 +08:00
imccyu
f27021c9b6 Merge pull request #3293 from deepseek-harness/worktree-apiremote
refactor(api): converge the ctx.remote programming surface
2026-08-29 11:09:58 +08:00
Yichen Jiang
837cc95245 Merge pull request #3254 from deepseek-harness/test/translation-pairing-merge-budget
test(scripts): align the translation-pairing-merge budget with the coverage lane
2026-08-29 10:44:01 +08:00
imccyu
73a723f37f docs(api): correct the api-gateway reference codes and the failure-vocabulary note
- api-gateway reference (en/zh): gateway/lookup-unavailable and
  gateway/internal replace the pre-convergence codes, and the resolver
  paragraph states the RemoteError pass-through semantics.
- failure-vocabulary note (en/zh): the package is dsh-util-time, the
  marker is isDSHRemoteError, and discrimination requires no
  instanceof at all.
2026-08-29 03:12:46 +08:00
imccyu
674a1e95a3 fix(api): rename the failure marker, harden cross-realm discrimination, and mark the packed-record violation
- protocol: isDSHRemoteGatewayError -> isDSHRemoteError (the class is
  protocol-wide, not Gateway-specific); remoteErrorOf drops its
  instanceof Error precondition and tests the marker plus a string code
  structurally, so a marked failure from another realm no longer reads
  as a local defect.
- session-controller: the live-follow packed-record protocol violation
  now throws a marked RemoteError('gateway/internal'), landing the
  session in openState=error instead of an unhandled rejection;
  pinned at the transport and session levels.
- util-time: correct the invariant companion's @module name.
- regenerate the tool-cordis catalog for the marker rename.
2026-08-29 03:12:43 +08:00
imccyu
02a542f49f chore(docs): regenerate the slot catalog for the hostInfo hook rename 2026-08-28 23:37:26 +08:00
imccyu
f9e8fc8f8a fix(api): identity-stable $host facts and a whole-record host info hook
- api/gateway: $host caches its RemoteHostFacts record and mints a new
  one only when home changes, so snapshot readers compare by reference;
  identity pinned in the client spec.
- client/ui-tool, client/ui-workspace: the hooks channel exposes the
  host facts record as hostInfo and components select the field they
  need (useHostInfo(info => info.home)); row-component contracts are
  unchanged.
2026-08-28 23:28:51 +08:00
imccyu
a4f7193d24 docs: drop the Remote-failure bullet from packages/AGENTS.md
The rule text lives in the cookbook and the failure-vocabulary Agent
Note; the AGENTS.md roster and its 675-word budget stay as they were.
2026-08-28 23:01:54 +08:00
imccyu
39a5a1d7e4 chore(docs): regenerate catalogs, graphs, and the message-feedback golden
- gen-cordis-catalog / gen-cordis-inspect-catalog / gen-client-catalog /
  gen-config-catalog / gen-doc-graphs / gen-module-graph outputs pick up
  the converged Remote vocabulary (gateway/* codes, RemoteError JSDoc)
  and the dsh-util-time package; the zh sides of the three
  English-generated pages follow the same line-number shifts.
- the message-feedback protocol golden records the accepted wire
  change: a boundary-validation failure now reports
  gateway/input-invalid with structured details instead of a bare
  internal code.
2026-08-28 22:37:42 +08:00
imccyu
2b750cfb51 docs(api): document the converged ctx.remote programming surface
- new cookbook page adding-a-remote-api (en/zh): the five-step HOW-TO
  for declaring, failing, registering, consuming, and testing a Remote
  endpoint.
- new Agent Note ctx-remote-failure-vocabulary records this round's
  decisions and alternatives; the 2026-08-02 and 2026-08-10 notes are
  rewritten to the shipped facts (RemoteError vocabulary, $host, the
  retired ApiProxy statements).
- package READMEs pick up the new failure-face contracts
  (typert/protocol, api/gateway, api/remotes,
  test-support/client-runtime), dsh-util-time gains its README and
  registry entries, and stale connection/WorkspaceError/legacy-code
  statements are corrected (ui-settings, ui-settings-models,
  workspace-controller, docs/subsystems/typert incl. the
  TypertGatewayErrorCode type-equiv block).
- packages/AGENTS.md gains the Remote-failure rule bullet; its doc
  budget rises 675 -> 714: the bullet is the compressed remainder
  after relocating detail to the cookbook and the Agent Note.
2026-08-28 22:37:36 +08:00
imccyu
41cd24f3f6 test(api): cover the non-Error terminal escape in RemoteStream
The terminal fold's String(error) arm had no coverage; a generation
that rejects with a bare string now pins the marked gateway/internal
outcome.
2026-08-28 22:37:36 +08:00
imccyu
2f2e6d627b fix(api): resolve review findings on stream boundary, inject staleness, and ctx discipline
- api/gateway: mark terminal Remote-stream escapes (carrier retry
  exhaustion and pre-acceptance end classification) as
  RemoteError('gateway/internal') at the two escape points; marked
  failures pass through verbatim. The carrier class stays the
  retry-internal signal for carrierFailed and the ended(true) retry
  trigger. Regression coverage lands on the session and workspace
  stream consumers.
- client/ui-tool, client/ui-workspace: read $host.home through a hooks
  observable subscribed to connection/reset; the slot renderer memoizes
  inject results per entry, so the previous plain-value injection froze
  home at the first render.
- client/ui-settings-models: components no longer receive ctx; apply
  binds the credential and settings Remote operations into callbacks,
  and the settings/conflict code judgment stays in the apply world.
2026-08-28 22:37:36 +08:00
imccyu
5af9eec51c fix(api): address review findings on the gateway client failure face
- classify a carrier throw under a caller-aborted signal as
  gateway/cancelled instead of gateway/internal, matching the code the
  Host produces when the abort wins the wire round-trip.
- read $host facts from the construction-time Connection handle,
  matching $stream; the service cannot be replaced without restarting
  this plugin, so the live re-lookup was dead complexity.
- state rebuiltFailure's actual contract in its comment: codes pass
  through verbatim without runtime validation.
- correct the @module name in dsh-util-time.
2026-08-28 22:37:36 +08:00
imccyu
d40d678b93 fix(api): repair runtime closure, gateway client bundle, and $host coverage
- python/sdk-runtime: add @deepseek-ai/dsh-util-time so the runtime
  dependency closure stays closed (dsh-subagent now depends on it).
- api/gateway: drop the dsh.client.external request for
  dsh-typert-protocol and admit the protocol package into INLINE_SAFE
  instead. The loader module table has no supplier for the protocol
  package, so the built client factory threw at require time; the
  protocol layer is duplication-safe by design (string marker,
  code-based discrimination), which is the inline-safe admission
  criterion.
- api/gateway tests: cover the $host getter (live service read,
  pre-ready home, and the construction-time fallback after the
  Connection service is withdrawn).
2026-08-28 22:37:36 +08:00
imccyu
804b1ffbfc refactor(api): converge the Remote failure vocabulary and client surface
Single RemoteError with a merge-extensible, domain-prefixed code map;
owners throw at the failure point; streams surface marked failures;
clients consume ctx.remote directly with isRemoteFailure as the only
discrimination point and construct no failure instances.
2026-08-28 22:37:36 +08:00
Yichen Jiang
94c714d813 docs(testing): add CI test reliability skill 2026-08-28 22:01:40 +08:00
Yichen Jiang
9055a8af3a fix(snapshot): bind fixture servers to OS-assigned ports 2026-08-28 21:37:38 +08:00
Yifffan
12d7b4ed0c Merge pull request #3262 from deepseek-harness/feat/session-turn-stats-display
feat(web): turn-tail usage and time stat pills with anchored dialogs
2026-08-28 13:52:02 +02:00
Yifffan
031bec12eb Merge pull request #3263 from deepseek-harness/hero-fish-hover-swim
feat(web): hero fish hover swim morph
2026-08-28 13:51:49 +02:00
Yif
d07108f9a0 Merge remote-tracking branch 'origin/master' into hero-fish-hover-swim
# Conflicts:
#	packages/client/ui-conversation/src/client/skeleton/EmptyHero.tsx
2026-08-28 19:35:56 +08:00
Yif
ececf8c170 fix(web): address hero fish hover review feedback
Move hover enter/leave from the svg element to the stationary fishHitbox
span so the CSS sway and SMIL morph share the same trigger surface and the
animation cannot flicker when sway displaces the svg from the pointer.
Gate the morph with (hover: hover) to match the CSS and prevent tap-sticky
loops on touch devices.

Remove residual headline changes unrelated to this PR: white-space: pre on
.headlineText, data-testid="hero-headline", and corresponding getByTestId
test assertions — these belong to #2397.

Fix Agent Note coverage claim (was "asserting render states", now accurately
"slot contract") and compress blowhole paragraph to current-state fact.
2026-08-28 19:29:31 +08:00
Yifffan
15f66b9c3c Merge pull request #3265 from deepseek-harness/fix/web-ui-polish
fix(client): Web 会话与输入 UI 细节修复
2026-08-28 13:20:23 +02:00
Yichen Jiang
a0aff5fe53 Merge pull request #3296 from deepseek-harness/worktree/fix-subagent-settings-label-color
fix(web): use primary color for Subagent setting label
2026-08-28 19:02:12 +08:00
Dudu-0223
143748bae9 test(deque): pin storage release behavior 2026-08-28 18:02:11 +08:00
Yichen Jiang
84df0f11ae fix(web): use primary color for subagent setting label 2026-08-28 17:53:18 +08:00
Yifffan
5e610e1a74 Merge branch 'master' into hero-fish-hover-swim 2026-08-28 11:51:06 +02:00
Yifffan
8f4fcdd792 Merge branch 'master' into feat/session-turn-stats-display 2026-08-28 11:50:42 +02:00
Yifffan
8a8db06d06 Merge branch 'master' into fix/web-ui-polish 2026-08-28 11:50:38 +02:00
Dudu-0223
51a6eabb27 perf(api): replace shift-backed stream queues 2026-08-28 17:37:03 +08:00
Yichen Jiang
375af94454 Merge pull request #1756 from deepseek-harness/worktree/fix-settings-focus
fix(web): restore focus after closing settings
2026-08-28 17:25:40 +08:00
Yichen Jiang
9cd2cb8f03 Merge pull request #3279 from deepseek-harness/perf/session-lookup-windows-only-stat
perf(session): stat the probe parent only on Windows
2026-08-28 17:21:49 +08:00
Yichen Jiang
f2b9875c47 test(session): await projection cache write-back 2026-08-28 17:07:33 +08:00
Yif
a0a350f640 Merge remote-tracking branch 'origin/master' into fix/web-ui-polish 2026-08-28 16:25:42 +08:00
Yif
6daed7c5aa fix(client): make trigger-menu Enter an explicit no-op while refinement pends
Retained rows made arbitrate('enter') claim 'pick-highlighted' while
pick() silently declined the pending group, so the key vanished by
coincidence. Check the highlighted group's readiness like Tab does and
return 'consumed' deliberately; record the stale-while-revalidate menu
decision in an Agent Note.
2026-08-28 16:24:07 +08:00
creatixchu
f3c69c2c3f refactor(tool-fs): keep image sniffing tool-local 2026-08-28 16:10:19 +08:00
Yif
a666f86129 Merge remote-tracking branch 'origin/master' into hero-fish-hover-swim 2026-08-28 16:07:28 +08:00
Yif
3a0dd5d38b Merge remote-tracking branch 'origin/master' into feat/session-turn-stats-display
# Conflicts:
#	packages/client/ui-primitives/tests/icons.client.spec.tsx
2026-08-28 16:04:13 +08:00
Yichen Jiang
c2a582057c Merge remote-tracking branch 'origin/master' into worktree/fix-settings-focus 2026-08-28 15:58:35 +08:00
Yichen Jiang
a12e9de5f7 perf(session): stat the probe parent only on Windows
`JsonlSessionPersistence.exists` treats ENOENT as absence and stats the
path's parent first, so a session directory blocked by a regular file
stays a storage fault. Only Windows needs that: it reports ENOENT rather
than ENOTDIR for `regular-file/child`, while POSIX open reports ENOTDIR
before the branch is reached.

The stat ran on every platform and every absent probe. findLog issues
four probes per project directory and the coordinator resolves an id
twice per inspect, so nearly every probe paid it. Counting fs calls
against a five-project store, loading an existing session drops from
40 open + 41 stat to 40 open + 3 stat.
2026-08-28 15:40:34 +08:00
creatixchu
8d337b2b32 Merge remote-tracking branch 'origin/master' into worktree/fix-3269-read-image 2026-08-28 15:37:32 +08:00
creatixchu
6f08798981 docs(tool-fs): sharpen extension notes and pin dotfile edge cases 2026-08-28 15:37:27 +08:00
creatixchu
adfd7074f3 Merge remote-tracking branch 'origin/master' into worktree/steer-followup-images 2026-08-28 15:23:15 +08:00
pku-xht
28e8e86bc3 Merge pull request #3065 from deepseek-harness/schedule-web-catalog
feat(web): surface active schedules in session views
2026-08-28 15:20:36 +08:00
creatixchu
3b2e5105e6 Merge remote-tracking branch 'origin/master' into worktree/steer-followup-images 2026-08-28 15:19:28 +08:00
creatixchu
aaa692033b test(snapshots): project new attachment-path fixtures into packed layout 2026-08-28 15:16:20 +08:00
CreatixChu
0fba5d1406 Merge pull request #3238 from deepseek-harness/fix/web-search-config-guidance
fix(web-search): guide endpoint recovery after failures
2026-08-28 15:09:46 +08:00
Yif
21d039be1b fix(web): label the Turn-time TTFT row as first-token latency, not an average
The Turn fold publishes the first step's TTFT (contract/turn-metrics.ts
firstStepTtftMs), never an average; only the Session StatsLine averages
across steps. Rename the dialog row in both locales and align the Agent
Note with what actually ships.
2026-08-28 15:03:47 +08:00
_Kerman
4096b0b408 refactor(time-context): scan turn messages in reverse 2026-08-28 15:02:12 +08:00
creatixchu
7222e17dc0 fix(tool-fs): accept extension-less attachment paths in read_image 2026-08-28 15:02:04 +08:00
_Kerman
1b6f9a1b51 refactor(session-telemetry): simplify capture replay 2026-08-28 14:58:11 +08:00
_Kerman
32d681f023 fix(subagent): preserve empty restored model selection
Detect explicit empty seeds through the existing end-seed marker and remove the redundant Session.seeded API.
2026-08-28 14:55:46 +08:00
pku-xht
6c5bb90b48 Merge remote-tracking branch 'origin/master' into schedule-web-catalog 2026-08-28 14:45:30 +08:00
_Kerman
47e6448e23 perf(session): avoid unnecessary event snapshots 2026-08-28 14:17:21 +08:00
Yif
5156226cb9 docs(notes): record the hero glow removal, consolidating the one-axis-scroll note
The 2026-08-04 bug-fix note owned the overflow-x clip that existed only
for the glow's bleed; with the glow, the clip, and its test all gone the
note is fully superseded. The new note preserves its rationale and the
reintroduction condition for future bleeding chrome.
2026-08-28 14:12:33 +08:00
Yif
08f770275c Merge remote-tracking branch 'origin/master' into hero-fish-hover-swim
# Conflicts:
#	packages/client/ui-brand-official/package.json
2026-08-28 14:08:24 +08:00
_Kerman
bcfec8d1c3 perf(session): reuse immutable event snapshots 2026-08-28 13:43:16 +08:00
_Kerman
5660f44d29 perf(session): separate indexed and snapshot log reads 2026-08-28 13:25:58 +08:00
Turtle
15f2997bcb cleanup: omit unneeded invariant companions 2026-08-28 13:12:52 +08:00
_Kerman
6d38ba8656 Merge pull request #2774 from deepseek-harness/xtr/session-projection-required-form
refactor(projections): use the required registry directly
2026-08-28 13:11:11 +08:00
Chinesezjc
8a25a876fc Merge pull request #3150 from deepseek-harness/feat/weighted-coverage-shard
perf(ci): assign coverage partitions by recorded file duration
2026-08-28 13:00:47 +08:00
_Kerman
d25ace0f22 refactor(api): require the session projection registry 2026-08-28 12:50:51 +08:00
Yif
d461922627 Merge remote-tracking branch 'origin/master' into fix/web-ui-polish 2026-08-28 12:50:49 +08:00
Yif
66d0bbd5b5 test(web): align e2e suite with the hero-glow removal and menu retention
conversation-column-overflow existed solely to verify the glow bleed was
clipped; delete it with its golden. The geometry golden picks up the
scroll body losing overflow-x: hidden. reference-composer now waits for
the stale '@' rows to settle before clicking: the menu keeps the
previous query's rows while the next loads, and index-keyed rows swap
content in place.
2026-08-28 12:50:25 +08:00
Yif
1278877d91 fix(client): dismiss stat dialogs through the shared outside-pointer hook
The turn-stat dialogs copied ContextMeter's document-listener effect, which
the duplication gate flags; useDismissOnOutsidePointer gains an optional
portal ref so the portaled dialog counts as inside, and TurnUsagePanel keeps
only the Escape listener. The icon-count test also learns the two pill
glyphs the branch added.
2026-08-28 12:47:15 +08:00
Turtle
626f21dabd Merge pull request #2735 from deepseek-harness/codex/remove-knip
Remove Knip from repository tooling
2026-08-28 12:38:41 +08:00
Chinesezjc
46a8e83094 ci: refresh checks before merge 2026-08-28 12:37:24 +08:00
_Kerman
8645053ca0 refactor(goal, permission, plan): require the projection registry 2026-08-28 12:37:17 +08:00
_Kerman
a40a776c95 Merge pull request #2742 from deepseek-harness/xtr/session-projection-migrations
refactor(session): migrate host state reads to projections
2026-08-28 12:37:14 +08:00
Chinesezjc
ab0f942dd7 Merge remote-tracking branch 'origin/master' into feat/weighted-coverage-shard 2026-08-28 12:18:14 +08:00
Turtle
7e92ed8213 Merge origin/master into codex/remove-knip 2026-08-28 12:07:36 +08:00
_Kerman
f6d4f2149d fix(webworker-runtime): restore v1 title cache fixture 2026-08-28 11:53:17 +08:00
creatixchu
aa70a737ae fix(web-search): guide users to endpoint settings 2026-08-28 11:45:27 +08:00
_Kerman
5c9ca1f25b fix(session-title): preserve v1 title cache schema 2026-08-28 11:22:52 +08:00
Yif
d6b30db252 Merge remote-tracking branch 'origin/master' into feat/session-turn-stats-display 2026-08-28 11:19:23 +08:00
Yif
d576865f76 fix(client): remove the hero glow under the new-session input
The blurred blue ellipse (HeroGlow) below the homepage input card reads as
stray tint rather than intentional chrome; drop the component and its
positioning/overflow scaffolding.
2026-08-28 11:16:01 +08:00
Yif
452013effa fix(client): web session and input UI polish
Batch of visually verified Web UI fixes: trigger-menu z-index over the
resize handle (#3228, #3229), input scrollbar offset, tool-row file
links and diff stats (#3230), @ menu crumb alignment, light-mode
divider, and @ menu flicker while typing (#3234) via
stale-while-revalidate — a refinement hit keeps the previous items and
highlight on screen until the new generation settles, so neither the
skeleton nor the first-row focus blinks per keystroke.
2026-08-28 11:16:00 +08:00
creatixchu
f55c676485 fix(web-search): clarify endpoint recovery guidance 2026-08-28 11:00:50 +08:00
_Kerman
25b0c943ce Merge remote-tracking branch 'github/master' into xtr/session-projection-migrations
# Conflicts:
#	.agents/notes/implemented/architecture/2026-08-04-draft-provider-endpoint-interrogation.i18n.yaml
#	.agents/notes/implemented/architecture/2026-08-04-draft-provider-endpoint-interrogation.md
#	.agents/notes/implemented/architecture/2026-08-04-draft-provider-endpoint-interrogation.zh.md
#	.agents/notes/implemented/feature/2026-08-06-continuable-subagent-interrupt.i18n.yaml
#	.agents/notes/implemented/feature/2026-08-06-continuable-subagent-interrupt.md
#	.agents/notes/implemented/feature/2026-08-06-continuable-subagent-interrupt.zh.md
#	.agents/notes/implemented/process/2026-07-20-gui-testing-system.i18n.yaml
#	.agents/notes/implemented/process/2026-07-20-gui-testing-system.md
#	.agents/notes/implemented/process/2026-07-20-gui-testing-system.zh.md
2026-08-28 10:59:30 +08:00
creatixchu
c904169915 Merge remote-tracking branch 'origin/master' into fix/web-search-config-guidance 2026-08-28 10:55:59 +08:00
creatixchu
878857a5f2 Merge remote-tracking branch 'origin/master' into worktree/steer-followup-images 2026-08-28 10:35:50 +08:00
Chinesezjc
00f2a701bd test(scripts): align the translation-pairing-merge budget with the coverage lane
Every case in the suite drives real git invocations against a scratch
repository, so it is bound by process creation rather than by its assertions.
The describe-level 15 s capped all 23 cases below the 90 s the Windows coverage
lane passes as --testTimeout, and the suite has been observed timing out at
15000ms on a branch that did not touch the file.

Refs #2677.
2026-08-28 10:21:45 +08:00
Chinesezjc
206fb8b53c test(session): resolve one relative root on both sides of the jsonl round-trip 2026-08-28 10:21:26 +08:00
pku-xht
5a8ef5f3f5 fix(web): tighten schedule catalog evidence 2026-08-28 09:28:33 +08:00
pku-xht
19b215f426 fix(ui-schedule): scope Escape dismissal to catalog 2026-08-28 08:39:31 +08:00
pku-xht
1a5d004524 Merge commit 'bc954280ae67e349291e51e5787c6987e767fa40' into schedule-web-catalog
# Conflicts:
#	packages/client/ui-workspace/src/client/rows/Rows.tsx
#	tsconfig.base.json
2026-08-28 07:24:24 +08:00
Yif
f14f50416e docs(notes): record the turn-tail stat pill decision 2026-08-28 02:22:47 +08:00
Yif
6f16d5868c refactor(ui-chat): drop the flat usage-variant debug switch and square narrow pills
The A/B test settled on the twin-pill layout, so the TEMPORARY
?usage-variant=flat trigger, its locale keys, and its tests leave with it.
Below 480px the stat pills now take the sibling action-button geometry so
their bare icons keep the row's rhythm instead of drifting on the wider
label padding and the -6px pair rebate.
2026-08-28 02:14:37 +08:00
Yif
9effa0c6b3 feat(ui-chat): split turn stats into usage and time pills with dialogs
The turn tail's exposed meta line collapses into two icon pills — Usage
(database glyph, turn total) and Ran-for (clock glyph, wall time) — each
click-opening a details dialog; the calendar clock trails as plain text.
Cache hit, TPS, and TTFT move dialog-only, and narrow viewports collapse
the pills to bare icons. The TEMPORARY flat variant keeps the whole-line
trigger for the A/B test.
2026-08-28 01:34:18 +08:00
Dudu-0223
ec493c2db8 feat(subagent): unify adjacent agent delivery on steer 2026-08-28 01:04:46 +08:00
imccyu
cd5ef81481 Merge pull request #3248 from deepseek-harness/release/dsh-0.1.2-alpha.1
release: dsh@0.1.2-alpha.1
2026-08-28 00:57:43 +08:00
imccyu
6c705be1ce release(dsh): 0.1.2-alpha.1 2026-08-28 00:50:12 +08:00
Tianyi Cui
8437bfb9e4 Merge pull request #3074 from deepseek-harness/worktree/ptc-rename-base
Rename code-mode to ptc (PTC mode), except session-persistent vocabulary
2026-08-28 00:49:44 +08:00
Yif
5ba375fd88 feat(client): hover swim morph for the hero fish 2026-08-28 00:37:46 +08:00
Tianyi Cui
188d77ed4b docs: sync remaining code mode-value prose to ptc in notes and spill README
Review bot findings: DSH_TOOLS_MODE values, the wire-replacement
wording, 'code-only' mode references, and the spill README's
dispatch-log waterfall name all still named the removed 'code' value.
2026-08-28 00:24:05 +08:00
Tianyi Cui
b7c71d805a docs(zh): sync remaining code mode-value prose to ptc
The review bot found stale 'code' configuration values in the zh tools
and agent-tool-presentation READMEs and the zh tool catalog, which the
runtime schema already rejects in favor of 'ptc'.
2026-08-28 00:16:29 +08:00
creatixchu
b9060b4f9b Merge remote-tracking branch 'origin/master' into worktree/steer-followup-images
# Conflicts:
#	packages/context/file-reference-local/tests/search.spec.ts
2026-08-27 23:29:17 +08:00
creatixchu
61f65ffd48 test: allow Windows title diagnostic latency 2026-08-27 23:27:14 +08:00
Tianyi Cui
84dd2447f3 docs: point note references at the surviving RPC test homes
Master removed the ApiProxy package; its former test paths now live in
the client connection, API gateway, and settings controller test
directories. Update the three notes' references so verify-package-paths
resolves.
2026-08-27 23:22:02 +08:00
_Kerman
13c1541c63 Merge remote-tracking branch 'github/master' into xtr/session-projection-migrations
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	pnpm-lock.yaml
2026-08-27 23:18:55 +08:00
Tianyi Cui
558b6d9193 fix(notices): restore the SDK 0.3.241 platform payload rows
The rename commit regenerated the notices file against a stale local
install (0.3.220); the lockfile and CI install resolve 0.3.241.
2026-08-27 23:14:33 +08:00
Tianyi Cui
cf12723ba8 docs: re-record pairing hashes after the master rebase merge
The rebase merged master's SDK-example and telemetry prose with the
ptc renames in the tools and CLI reference READMEs and the executor
collapse note; re-record their pair hashes.
2026-08-27 23:14:33 +08:00
Tianyi Cui
c3904faee0 test(snapshot): restore canonical packed fixture layout
The DSH_SNAPSHOT refresh recorded the internal seq-range form; the
canonical fixture layout expands those ranges. Apply the mechanical
migration instead.
2026-08-27 23:14:33 +08:00
Tianyi Cui
ee42efbccd test(snapshot): re-record cordis-inspect-jsdoc after the seq-range projection
Master's session persistence projection now writes sourceEventSeqs as
compressed ranges; the recorded replay fixture must match the new output.
2026-08-27 23:14:33 +08:00
Tianyi Cui
70af4edf3e fix: point the rename note at the fail-closed session-event vocabulary note
Master replaced the session-log-version-mechanism note with the
fail-closed-session-event-vocabulary note; update the rename note's links
(en/zh) so cross-links resolve.
2026-08-27 23:14:33 +08:00
Tianyi Cui
215e90dfb2 fix: rename the remaining code mode-value prose found in review
The subagent review found stale code mode-value prose the mechanical pass
missed: tools and agent-tool-presentation READMEs (en/zh), the CLI reference
page (DSH_TOOLS_MODE and the preset roster), the zh tool catalog, the
execute JSDoc and collapse comments in dsh-tools, the codeModeHarness
helper in agent-loop tests, and stale code-mode titles in ptc.spec.
2026-08-27 23:14:33 +08:00
Tianyi Cui
409f9ee304 fix: repair merged README remnants and note links after the master rebase
Apply the rename pass to READMEs and docs the master sweep rewrote, fix
PTC mode anchors and the renamed-note links in the spill READMEs, and
regenerate the doc graphs.
2026-08-27 23:14:33 +08:00
Tianyi Cui
45c514a42b fix: align mode-value prose and stale persistent mentions with the split
The split kept the session-persistent vocabulary (tool/code-dispatch*,
tools-code-mode, :code:) on this PR, but several prose surfaces still named
the new values: the zh persistence/tool catalogs, the renamed Agent Notes'
event mentions, spill-policy comments, and a garbled 're-enPTC mode'
replacement. Also rename the mode value to ptc in the places the rename
missed (tools and agent-tool-presentation READMEs, the Config JSDoc, note
mode unions) and the codeModeHarness* e2e helpers.
2026-08-27 23:14:32 +08:00
Tianyi Cui
3ca9c7d489 rename code-mode to ptc (PTC mode), except session-persistent vocabulary
Rename the tool-presentation transport from code-mode to ptc everywhere
that is not written into session logs: the mode config value becomes 'ptc',
the preset directory/id becomes ptc, the demo becomes demo:ptc, the
dispatch waterfall becomes tools/ptc-dispatch-log (types PtcDispatch*), the
prompt rule becomes tools:ptc-only, source/test files become ptc.ts etc.,
and prose says PTC mode / PTC 模式. The session-persistent vocabulary
(durable events tool/code-dispatch*, logged plugin name tools-code-mode,
sub-call id segment :code:) intentionally stays and moves in the stacked
persistence PR, which is blocked until the SESSION_FORMAT_VERSION v0→v1
migration lands with it. run_code, its code parameter, CodeSdkLanguage,
CodeRunFailedError, the dsh-code-runtime family, third-party codex names,
and frozen archived notes keep their names.
2026-08-27 23:14:31 +08:00
Yif
f15078532f feat(ui-chat): reshape the usage trigger as an icon-row pill
The whole-line meta trigger read as plain text and hid what was clickable.
The Turn-usage trigger is now a data-icon pill (Usage {total} · Cache hit
{percent}%) seated right of the branch action with the action buttons'
hover chrome, so the one interactive element in the tail is visibly a
button; the timing facts (clock, run time, speed, TTFT) return to plain
non-clickable text behind a dot separator. The details dialog keeps the
Turn-usage title and full token buckets, gains a permanent cache-hit row,
and breathes with wider vertical padding. Narrow columns trim the pill
label to an ellipsis instead of widening the chat column. User rows and
turn tails share the recency gate: only the latest row of each kind keeps
its actions visible without hover.
2026-08-27 23:14:08 +08:00
_Kerman
2bcd4cc552 fix(agent-presets): treat absent turn boundary as blank 2026-08-27 23:12:22 +08:00
imccyu
57aba7695b Merge pull request #3235 from deepseek-harness/worktree-apire-f
refactor(api): remove ApiProxy transport
2026-08-27 23:10:56 +08:00
imccyu
9fa87800a2 fix(api): keep file-reference output in its project 2026-08-27 22:58:43 +08:00
Chinesezjc
bb7a640237 Merge pull request #3236 from deepseek-harness/fix/file-search-unreadable-subtree-test
test(file-reference-local): pin the unreadable-subtree test to POSIX non-root
2026-08-27 22:48:31 +08:00
imccyu
b0c44e54ba fix: build 2026-08-27 22:48:16 +08:00
creatixchu
0158adc926 Merge remote-tracking branch 'origin/master' into worktree/steer-followup-images
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
2026-08-27 22:33:20 +08:00
imccyu
26f1eda42a test(connection): allow non-Error rejection fixture 2026-08-27 22:29:47 +08:00
creatixchu
6f446e196b ci: retrigger pull request workflows 2026-08-27 22:29:06 +08:00
imccyu
e57e7c3f25 docs(api): describe Connection-owned transport 2026-08-27 22:26:30 +08:00
imccyu
4f00a8b82a refactor(api): remove ApiProxy package 2026-08-27 22:26:29 +08:00
imccyu
e14d354e83 refactor(connection): own RPC transport contracts 2026-08-27 22:26:29 +08:00
imccyu
3b40a14555 test(session-export): assign Host compiler face 2026-08-27 22:26:29 +08:00
imccyu
40929d6e1a refactor(client): replace host description consumers 2026-08-27 22:26:28 +08:00
imccyu
e036aae7c0 refactor(connection): carry Host facts with generations 2026-08-27 22:26:28 +08:00
imccyu
17c03bbbcc feat(session-export): own the download route 2026-08-27 22:26:28 +08:00
imccyu
e5e4b02742 feat(connection): register exact Fetch routes 2026-08-27 22:26:27 +08:00
creatixchu
267bdd60aa test: allow loaded Windows coverage timing 2026-08-27 22:26:06 +08:00
imccyu
5ba36aa350 Merge pull request #3217 from deepseek-harness/worktree-apire-remaining
refactor(api): migrate remaining API proxy endpoints
2026-08-27 22:22:33 +08:00
imccyu
ea07f465ac docs: refresh module graph 2026-08-27 22:00:58 +08:00
imccyu
2ff3a0c09f fix(file-reference): remove unused zod dependency 2026-08-27 21:57:58 +08:00
imccyu
18ae39a665 fix(api): preserve native path opening behavior 2026-08-27 21:57:58 +08:00
imccyu
72cf4fae83 fix(settings): preserve config catalog source anchor 2026-08-27 21:57:57 +08:00
imccyu
89ee54ebb7 test(api): align migrated client contracts 2026-08-27 21:57:57 +08:00
imccyu
5f6293e67a test(client): update remote session fixtures 2026-08-27 21:57:57 +08:00
imccyu
812556040d fix(api): restore migrated remote coverage 2026-08-27 21:57:57 +08:00
imccyu
88f2f0aaec test(api): complete migrated Remote coverage 2026-08-27 21:57:57 +08:00
imccyu
674301721c fix(build): correct workspace dependency declarations 2026-08-27 21:57:57 +08:00
imccyu
160706be60 test(api): refresh Remote migration artifacts 2026-08-27 21:57:56 +08:00
imccyu
ce3391e280 refactor(apiproxy): retire migrated unary routes 2026-08-27 21:57:56 +08:00
imccyu
5b2f679e4a refactor(client): consume migrated Remote namespaces 2026-08-27 21:57:56 +08:00
imccyu
2d4393d842 refactor(api): expose remaining domain remotes 2026-08-27 21:57:55 +08:00
creatixchu
266440c5a7 test: allow Windows merge-driver latency 2026-08-27 21:25:46 +08:00
creatixchu
56f1a3bde6 test: gate unreadable directory case to POSIX 2026-08-27 21:23:49 +08:00
creatixchu
e719eee47f fix(web): guide search endpoint recovery 2026-08-27 21:21:10 +08:00
Chinesezjc
6ac1b82939 test(file-reference-local): pin the unreadable-subtree test to POSIX non-root
chmod 0 can only deny directory reads on POSIX to a non-root owner:
Windows exposes no directory permission bits for readdir, and root
bypasses them. Where the fixture stays readable the sealed candidate is
indexed, so the unreadable-branch behavior is pinned on POSIX non-root.
An injected readdir failure keeps that branch covered on every platform.
2026-08-27 21:12:14 +08:00
Chinesezjc
10b31043ab feat(ci): assign coverage partitions by recorded file duration
Replace Vitest's hash-based --shard with a coordinator-side
longest-processing-time assignment. The coordinator collects the
instrumented inventory from a vitest list run (dropping the exempt
heavy suites that list does not exclude), reads per-file durations from
the Vitest results cache, and seeds heavy subprocess-bound suites into
different partitions. A weight-aware test fails when assignment ignores
recorded weights, verified by injecting a file-count-only rule.

Windows coverage measured partition spread of 442s (275-717s) under
hash sharding; a simulation with the same file durations and the new
assignment balances partitions to within 21s, cutting the critical
partition to roughly half.
2026-08-27 21:04:15 +08:00
creatixchu
318bf7d2c1 test: account for Windows chmod coverage 2026-08-27 20:44:35 +08:00
creatixchu
eb349d56e6 Merge remote-tracking branch 'origin/master' into worktree/steer-followup-images 2026-08-27 20:44:04 +08:00
Chinesezjc
12efd638d4 Merge pull request #3202 from deepseek-harness/fix/windows-directory-picker-loader-composition
test(host): drain Include write queue in directory-picker composition spec
2026-08-27 20:37:23 +08:00
imccyu
07cb5934af Merge pull request #3227 from deepseek-harness/fix/inspector-client-bootstrap
fix(inspector): stabilize client bootstrap identity
2026-08-27 20:33:08 +08:00
creatixchu
145f936946 test: stabilize queued image browser snapshot 2026-08-27 20:29:25 +08:00
Yichen Jiang
b2442d00f9 Merge pull request #3219 from deepseek-harness/perf/tsconfig-paths-flatten
perf(infra): map each workspace package to an explicit path alias
2026-08-27 20:16:56 +08:00
imccyu
b46953f3cc test(client-modules): type loader resolver stubs 2026-08-27 20:16:51 +08:00
creatixchu
21d2d9395d refactor: align prompt admission and echo ownership 2026-08-27 20:14:18 +08:00
imccyu
827acd07b1 docs(client-modules): align resolver contract 2026-08-27 20:10:20 +08:00
imccyu
dc1be1334f fix(inspector): address bootstrap review findings 2026-08-27 20:03:17 +08:00
Yichen Jiang
71b3c50261 refactor(infra): share one workspace walk between the alias collectors
collectPackageNames repeated collectPackageAliases' directory walk
verbatim, which jscpd reported as a 7-line clone and which failed the
lint-and-duplication gate on both the Linux and Windows lanes. Both now
read one workspacePackages() iterator: the alias collector keeps only
packages named after their directory, and the coverage collector keeps
every one of them.
2026-08-27 20:02:10 +08:00
creatixchu
b71d0a35ef Merge remote-tracking branch 'origin/master' into worktree/steer-followup-images 2026-08-27 19:46:54 +08:00
Yichen Jiang
c4c3c32931 fix(infra): assert alias coverage and harden the generator entry guard
Review found the CLI entry guard compared import.meta.url against a
concatenated file:// URL. That fails whenever import.meta.url encodes
something process.argv[1] does not — a repository path containing a
space, or any Windows drive path — and it fails silently: the script
exits 0 having done nothing, so verify-tsconfig-paths would pass
without checking exactly where it is needed. Running a copy from a
directory whose name contains a space reproduces it. The guard now uses
the comparison the repository's seven other generators already use.

Deleting the group wildcards also removed the fallback that resolved a
package nobody had aliased, so the generator now asserts coverage:
every workspace package with a src directory must be mapped, and
--check names any that is not. That assertion immediately found four
packages named dsh-<group>-<directory> whose siblings carry hand-written
aliases while they did not, so they reached built lib/ output through
the workspace symlink. They now carry aliases too, which takes the
resolution differences in this branch from seven to eleven.

Two comments in tsconfig.base.json still pointed at the deleted
wildcards; they now state why those aliases stay hand-written. The
package-inventory proposal recorded the wildcard collapse as current,
so both notes are cross-linked as partial supersession.
2026-08-27 19:39:21 +08:00
creatixchu
2c1cc3e778 refactor: narrow closing-turn wake tracking 2026-08-27 19:37:25 +08:00
imccyu
ac13b16c0c fix(inspector): stabilize client bootstrap identity 2026-08-27 19:35:34 +08:00
Yif
bc88e152c5 test(ui-chat): restore turn-tail assertions lost in the rebase merge
The rebase onto master's turn-process folding kept master's makeHarness
rework, which dropped the turnUsages passthrough and the single-trigger
footer assertions; re-merge both sides.
2026-08-27 18:35:09 +08:00
Yif
bb1df10c69 feat(ui-chat): collapse the turn tail into one clickable meta line
Replace the two-row footer (TurnUsageDisclosure + icon-row clock chrome)
with a single whole-line trigger (clock · run time · turn usage · cache
hit · speed · TTFT) that opens a per-Turn usage dialog. The latest turn
keeps its tail always visible; older turns reveal the whole row on
hover/focus. Turns without usage data keep the plain clock line with
identical spacing.
2026-08-27 18:27:02 +08:00
lsdsjy
8b09a0be52 feat(ui-conversation): fold turn process before final answer (#2547)
* feat(ui-conversation): fold turn process before final answer

* fix(ui-chat): polish turn-process control row from review

* test(web): drive preset slash catalog with gestures

* fix(ui-chat): keep turn process order stable

* fix(ui-chat): preserve prompt order after pagination

Co-authored-by: Yif <877193178@qq.com>
2026-08-27 10:12:39 +00:00
07akioni
2c9c871eff Merge pull request #3213 from deepseek-harness/docs/cordis-paper-arxiv
docs: link Cordis paper on arXiv
2026-08-27 18:07:01 +08:00
07akioni
35ac64c209 docs: link Cordis paper on arXiv 2026-08-27 17:45:31 +08:00
Wenlu Wang
6720bff936 Merge pull request #1372 from deepseek-harness/style/cjk-latin-autospace
Add global CJK/Latin auto-spacing via text-autospace
2026-08-27 17:37:08 +08:00
_Kerman
3a34b7870e test(agent-team): cover failed projection reads 2026-08-27 17:27:31 +08:00
Yichen Jiang
12c161e1a7 perf(infra): map each workspace package to an explicit path alias
tsconfig.base.json resolved @deepseek-ai/dsh-* through 49 candidate
globs and @deepseek-ai/dsh-*/invariant through 45, one per package
group. Resolution tries candidates in order, so a package late in the
list paid for every earlier miss — and under the dsh source launch each
miss is an ERR_MODULE_NOT_FOUND that Node decorates with a full
CommonJS resolution walk. A boot profile attributed 934.6 ms, 35% of
startup, to that decoration path across 60,942 failed resolutions. The
cost landed hardest on packages/util/*, which sits at position 44 of 49
and holds the leaf utilities nearly every plugin imports.

gen-tsconfig-paths writes one explicit alias per package into a marked
region and both group wildcards are gone; verify-tsconfig-paths reports
drift and runs in the ci-static lane. Booting the headless profile from
source drops from ~2,157 ms to ~1,055 ms with --help output unchanged.

All 1,022 dsh specifiers in repository sources resolve to the same
target as before, except seven /invariant specifiers in the lsp,
terminal, and runtime-diagnostics groups that the deleted wildcard
never listed: those reached built lib/types instead of src, against the
rule that static gates resolve through paths to src on a clean tree.
2026-08-27 17:26:52 +08:00
creatixchu
53f5418a72 fix: 稳定 steer 提交回显位置 2026-08-27 17:25:36 +08:00
fz
1c808341ec Add global CJK/Latin auto-spacing via text-autospace
Progressive enhancement on body in the shell base sheet so mixed
Chinese/English copy gets consistent spacing without content edits;
engines without support ignore the property.
2026-08-27 17:21:40 +08:00
_Kerman
4b48b2b439 Merge remote-tracking branch 'github/master' into xtr/session-projection-migrations 2026-08-27 17:18:58 +08:00
_Kerman
6717cb8d19 refactor(session): trim projection migration diff 2026-08-27 17:18:51 +08:00
imccyu
631135cc06 Merge pull request #3012 from deepseek-harness/worktree-inspectorcordis
feat(inspector): add cross-realm CDP inspection
2026-08-27 17:10:55 +08:00
creatixchu
5bb24c03f1 test: avoid untyped catalog matcher 2026-08-27 16:57:12 +08:00
imccyu
90cae21deb fix: ci 2026-08-27 16:52:40 +08:00
creatixchu
abe185205b fix: scope prompt catalog type to client 2026-08-27 16:49:15 +08:00
creatixchu
b67663c583 fix: retain prompt parts in client catalog 2026-08-27 16:42:11 +08:00
_Kerman
d9c0aa1cd0 Merge remote-tracking branch 'github/master' into xtr/session-projection-migrations
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	packages/context/session-reference/package.json
#	packages/context/session-reference/tests/session-reference.spec.ts
#	packages/subagent/tool-subagent/src/index.ts
#	packages/subagent/tool-subagent/src/invariant.ts
#	packages/subagent/tool-subagent/src/model-selection-state.ts
#	packages/subagent/tool-subagent/tests/harness.ts
#	packages/subagent/tool-subagent/tests/list-models.spec.ts
#	packages/subagent/tool-subagent/tests/model-selection-settings.spec.ts
#	packages/subagent/tool-subagent/tests/tool-subagent.spec.ts
#	pnpm-lock.yaml
2026-08-27 16:38:06 +08:00
creatixchu
bf85410fbb Merge remote-tracking branch 'origin/master' into worktree/steer-followup-images 2026-08-27 16:35:03 +08:00
creatixchu
ba810b3539 fix: harden subagent image follow-up admission 2026-08-27 16:31:04 +08:00
imccyu
3f4a6a2698 docs: align the module graph translation pair 2026-08-27 16:28:26 +08:00
_Kerman
1c2acd9157 refactor(permission): project the seed boundary 2026-08-27 16:25:43 +08:00
_Kerman
42e0781cda refactor(agent-team): name the Team projection explicitly 2026-08-27 16:25:33 +08:00
_Kerman
722d9f016b perf(goal): avoid copying open-turn event suffix 2026-08-27 16:25:29 +08:00
_Kerman
ba4bd08bc3 perf(llm-retry): reset state without scanning keys 2026-08-27 16:25:25 +08:00
_Kerman
85bf796a95 refactor(subagent): retain identity projection state 2026-08-27 16:25:20 +08:00
_Kerman
9e184cde37 test(python): restore strict live response smoke 2026-08-27 16:25:12 +08:00
imccyu
1c1c0adf6e fix(inspector): classify the demo launcher and refresh the module graph 2026-08-27 16:23:21 +08:00
imccyu
15572ddb22 feat(inspector): add the development mount overlay and demo script 2026-08-27 16:16:28 +08:00
imccyu
ef712e3006 fix(inspector): serve Cordis DOM levels on demand 2026-08-27 16:16:28 +08:00
imccyu
a031b95fdb fix(inspector): preserve responses after caller abort 2026-08-27 16:16:28 +08:00
imccyu
777489dfc5 fix(inspector): print the startup URL 2026-08-27 16:16:28 +08:00
imccyu
d6245fc254 fix(inspector): update Cordis DOM incrementally 2026-08-27 16:16:28 +08:00
imccyu
c5f34e8ada fix(inspector): preserve event stream replay order 2026-08-27 16:16:27 +08:00
imccyu
5a5d5de948 fix(inspector): address protocol review findings 2026-08-27 16:16:27 +08:00
imccyu
0954bad2bb fix(inspector): render captured event streams 2026-08-27 16:16:27 +08:00
imccyu
b1748f0c55 fix(inspector): satisfy CI checks 2026-08-27 16:16:27 +08:00
imccyu
daf3858759 fix(inspector): restore client console and response bodies 2026-08-27 16:16:27 +08:00
imccyu
008ae0c01e docs(inspector): record cross-realm architecture 2026-08-27 16:16:24 +08:00
imccyu
6822ad3afc test(inspector): enforce execution-plane boundaries 2026-08-27 16:15:18 +08:00
imccyu
28cc3e930b feat(inspector): expose Cordis trees through CDP DOM 2026-08-27 16:15:18 +08:00
imccyu
7ecd7004eb feat(inspector): project Host fetches through CDP Network 2026-08-27 16:15:18 +08:00
imccyu
bcee99e39d feat(inspector): serve Runtime through a CDP Worker 2026-08-27 16:15:18 +08:00
imccyu
19f0076668 feat(inspector): connect Host and Client producers 2026-08-27 16:15:18 +08:00
imccyu
189fb34797 feat(inspector): define shared protocol foundation 2026-08-27 16:15:17 +08:00
CreatixChu
c6e1914f2d Merge pull request #3207 from deepseek-harness/fix-3204-ptc-run-code-prompt
fix(tools): keep PTC SDK calls inside run_code
2026-08-27 16:13:22 +08:00
Yichen Jiang
efd816c0dd Merge pull request #3182 from deepseek-harness/worktree/web-mention-ux-polish-1bf698
feat(web): trim @ mention rows and cut their discovery cost
2026-08-27 16:12:02 +08:00
creatixchu
2951512e18 docs: refresh module graph for subagent attachments 2026-08-27 15:59:03 +08:00
creatixchu
520bc3ce75 fix(tools): scope bash SDK example to its schema 2026-08-27 15:54:20 +08:00
creatixchu
381ea9fc5d Merge branch 'master' into worktree/steer-followup-images
# Conflicts:
#	packages/api/session-controller/src/client/contract/session.ts
2026-08-27 15:53:14 +08:00
Yichen Jiang
317ab06b24 Merge pull request #3176 from deepseek-harness/worktree/web-readable-ask-question-cards
fix(web): render readable ask-user transcripts
2026-08-27 15:45:58 +08:00
Yichen Jiang
adca6a8cc3 Merge pull request #3193 from deepseek-harness/perf/process-table-snapshot
fix(subprocess): read the process table once per terminal poll
2026-08-27 15:36:17 +08:00
Yichen Jiang
093048d256 Merge remote-tracking branch 'origin/master' into worktree/web-mention-ux-polish-1bf698 2026-08-27 15:35:28 +08:00
CreatixChu
c10be57913 Merge pull request #3111 from deepseek-harness/worktree/3003-instant-pending-submit
feat(web): 图片询问点击发送即回显,压缩与传输转入后台
2026-08-27 15:31:01 +08:00
creatixchu
7c38fd8102 fix: deliver images reliably with steer and follow-up messages
A steer or follow-up accepted while a turn is closing is now claimed by a
fresh turn at the driver's clean exit instead of stranding in the inbox;
cancellation and pre-step rejection still park accepted work. Continuable
subagent follow-ups accept image parts: the wire is upload-shaped, the Host
admits and persists each batch before inbox acceptance, and delivery is
refused when the child model declines image input. The queue dock renders
durable image thumbnails instead of an [image] text marker.

Fixes #3186
2026-08-27 15:30:35 +08:00
Yichen Jiang
8e9da9debf refactor(session-reference): label discovery from projections alone
A title now comes from an attached session's live projection cut or a cold
one's durable checkpoint, and from nothing else. Attachment is decided by the
session store at read time, so a session that attached after the listing is no
longer answered from a checkpoint its log has moved past — the stale-title case
`api-session.list` already handles this way.

The log fold and its per-log memo are gone. Folding one title costs a whole
log, and this call sits under every keystroke; a session no projection answers
for is labeled by its id and regains its title the first time it is opened.

`lib` leaves the default exclusions: Ruby gems and many npm packages keep
sources there, and the miss would be silent and total. A traversal whose root
is unreadable now rejects instead of publishing an empty index over entries
that are still good, which is what the stale-while-revalidate path claimed but
could not do while every readdir error was swallowed. A drill marks the menu
drilled only when its edit actually reached the draft.

Refs #3154
Refs #3180
2026-08-27 15:21:08 +08:00
creatixchu
f9770e34af fix(tools): keep PTC SDK calls inside run_code 2026-08-27 15:20:03 +08:00
Yichen Jiang
9757224349 fix(subprocess): fence each signal against current process state
Review found the shared observation defeated the very fence it fed:
it carries the original PID-to-start-time pairing forward, so a
recycled PID still matches it and takes a signal meant for the process
that exited. Capturing it outside the per-member try also let one
failed read abort a whole teardown round, breaking the synchronous
host-exit contract, and an empty round paid a read for no members.

signalProcess now reads ProcessInspector.isAlive immediately before
delivering, from the narrowest per-identity source each platform
offers; signalMembers and waitForMembers return before capturing when
a round has no members. snapshot() keeps serving the readiness poll,
whose per-poll table read stays at one.

Windows enumerates Toolhelp32 lazily on the first tree question, so a
snapshot asked only for liveness — the 25 ms teardown poll — performs
no table walk at all.
2026-08-27 15:19:43 +08:00
Yichen Jiang
94d06e23d2 fix(web): preserve mixed ask-user results 2026-08-27 15:11:55 +08:00
Chinesezjc
397fb929de test(host): drain Include write queue in picker composition spec
Replace the debounce-timer polling with Include.stop(), which flushes the
file-backed write queue deterministically. This avoids Windows coverage
flakes where the self-dispose write could land after the expect.poll
timeout.
2026-08-27 15:10:06 +08:00
lsdsjy
ed6ac33a88 Merge pull request #3148 from deepseek-harness/fix/websocket-heartbeat
fix(api-gateway): keep idle websocket alive
2026-08-27 15:07:11 +08:00
lsdsjy
af562d3649 fix(api-gateway): keep idle websocket alive 2026-08-27 14:48:13 +08:00
Chinesezjc
fb07d6db54 Merge pull request #2887 from deepseek-harness/fix/windows-pnpm-setup-isolation
ci: isolate pnpm setup destination per GitHub run
2026-08-27 14:30:00 +08:00
Dudu-0223
0615d17a82 Merge pull request #3020 from deepseek-harness/fix/subagent-model-switch-plugins
feat(subagent): authorize selectable child models
2026-08-27 14:12:24 +08:00
pku-xht
b36f3d323a docs(session): align projection hint ordering 2026-08-27 13:40:09 +08:00
Yichen Jiang
72f1e19184 Merge pull request #3194 from deepseek-harness/perf/turn-navigator-memo
fix(client): stop rebuilding the turn rail on every chat render
2026-08-27 13:29:22 +08:00
Dudu-0223
2722c202ad fix(subagent): tolerate policy-only preset states 2026-08-27 13:25:51 +08:00
Yichen Jiang
49753b33fa fix(web): keep question card props data-only 2026-08-27 13:21:22 +08:00
Dudu-0223
a7b054b8f6 docs: refresh module dependency graph 2026-08-27 13:09:08 +08:00
Yichen Jiang
c873fc9d2e fix(client): stop rebuilding the turn rail on every chat render
TurnNavigator was an unmemoized component rendering one div and one
button per loaded Turn, so every ChatView render rebuilt the whole rail:
143 button rebuilds per commit in a 300-Turn session against 8.4 in a
4-Turn one, while a streaming answer commits dozens of times.

memo alone would not have helped, because navigateToTurn was rebuilt on
every render and broke prop identity, so it moves into useCallback.
2026-08-27 13:08:17 +08:00
Yichen Jiang
32ddfcd89c fix(subprocess): read the process table once per terminal poll
MacProcessInspector answered the descendant tree and every member's
liveness with its own `/bin/ps` fork, so one readiness poll cost N+1
full table reads for N tracked descendants. With execFileSync on that
path and a 50 ms poll interval, any command spawning two or more
children saturated the host event loop until it exited.

ProcessInspector.snapshot() now returns one ProcessSnapshot that
answers tree, session, and alive from a single observation, and
signalProcess takes the caller's observation so its PID-reuse fence
does not re-read the table per member.
2026-08-27 13:06:12 +08:00
Dudu-0223
e49e7202c1 fix: align model selection with current settings remotes 2026-08-27 12:18:05 +08:00
Yichen Jiang
db14361372 test(web): scope the aria age normalizer to the region that needs it
Collapsing every relative-time bucket to `{{age}}` reached the session-tree
goldens, where a literal age is the assertion: a fresh row reads `now` and an
older one does not. Six e2e files failed, two of them by aborting mid-scenario
and leaving their replay fixtures half-consumed.

`captureStableAria` now takes the rule as an opt-in, and only the reference
menu — whose rows are dated from the live Host list — asks for it.

Refs #3154
2026-08-27 12:10:52 +08:00
_Kerman
eeb4ca2b87 Merge remote-tracking branch 'origin/master' into xtr/session-projection-migrations 2026-08-27 12:03:10 +08:00
Dudu-0223
aad90d5cf3 fix(ui-settings-plugins): preserve model selection drafts 2026-08-27 12:00:02 +08:00
Dudu-0223
cbacceca4b fix(ui-settings-plugins): place Subagent after Agent loop 2026-08-27 12:00:02 +08:00
Dudu-0223
d5787b1847 test(web): expect plugin cards to collapse after save 2026-08-27 12:00:02 +08:00
Dudu-0223
4cc1f5e0ff fix(ui-settings-plugins): relax Subagent card layout 2026-08-27 12:00:02 +08:00
Dudu-0223
a7614f971e fix(subagent): omit undefined scoped fixture options 2026-08-27 12:00:02 +08:00
Dudu-0223
1c0e46870c test(subagent): keep scoped fixture config explicit 2026-08-27 12:00:02 +08:00
Dudu-0223
bf7020ade2 test(subagent): migrate model selection fixtures 2026-08-27 12:00:02 +08:00
Dudu-0223
a5cc8a2186 fix(notices): resolve current installed dependency versions 2026-08-27 12:00:02 +08:00
Dudu-0223
5a5e1b7373 test(ui-settings-plugins): cover provider model grouping 2026-08-27 12:00:02 +08:00
Dudu-0223
0b2f476071 fix(ui-settings-plugins): align Subagent configuration card 2026-08-27 12:00:02 +08:00
Dudu-0223
a130273434 test(subagent): type provider route defaults fixture 2026-08-27 12:00:02 +08:00
Dudu-0223
3a146064a4 fix: address subagent model selection review 2026-08-27 12:00:02 +08:00
Dudu-0223
9fae988691 test(sdk): expect model discovery off by default 2026-08-27 12:00:02 +08:00
Dudu-0223
f2bb5cef05 fix(snapshot): stabilize workflow prompt order 2026-08-27 12:00:02 +08:00
Dudu-0223
1ea72339fd fix(web): close model switch review gaps 2026-08-27 12:00:02 +08:00
Dudu-0223
7c626fb5d2 fix(subagent): gate model selection with explicit allowlist 2026-08-27 12:00:02 +08:00
Dudu-0223
ebe8d4db1c test(web): configure subagent model allowlist 2026-08-27 12:00:01 +08:00
Dudu-0223
aefc083be7 feat(subagent): authorize selectable child models 2026-08-27 12:00:01 +08:00
Dudu-0223
f887a8f907 fix(web): move subagent model switch to Plugins 2026-08-27 12:00:01 +08:00
Yichen Jiang
c8e8f8249f fix(web): date @ session rows by last activity, not creation
The Host session list already carries each session's `updatedAt`, which is
the number its own rows show; reading it there keeps the two surfaces from
disagreeing and avoids making a context capability depend on the BFF
assembly that owns the `sessionListMetadata` projection. A session the list
does not carry falls back to the candidate's creation time.

Refs #3154
2026-08-27 11:50:52 +08:00
CreatixChu
f1344a4077 Merge pull request #3045 from deepseek-harness/worktree/feedback-otel-enable
feat(bundle): default session telemetry to feedback-gated sharing
2026-08-27 11:47:02 +08:00
Yichen Jiang
97e0299f74 feat(web): trim @ mention rows and cut their discovery cost
Session candidates labelled from projection checkpoints instead of a full
log fold per keystroke, with the uncheckpointed remainder folded once and
memoized while its log stays cold. The file index keeps answering while an
invalidated traversal rebuilds behind the caret, and its default exclusions
now cover build outputs so deep sources stay reachable.

Rows carry only what distinguishes them: a file names its parent directory,
a session names its workspace only when that workspace is not the current
one, and a drilled listing names none because its new breadcrumb does.

Resolves #3180
Related to #3154
2026-08-27 11:42:06 +08:00
pku-xht
b2071a50b9 test(api): complete session manager coverage 2026-08-27 11:34:01 +08:00
Chinesezjc
2413eab847 ci: isolate non-Windows pnpm setup per run attempt
Stacked on #3115: keep its windows-* setup-pnpm-js-<run_id>-<run_attempt>-<job>
destination, and extend the same isolation to non-Windows jobs in ci.yml
and ci-master.yml with setup-pnpm-<run_id>-<run_attempt>. This prevents
sequential self-hosted Windows jobs from tripping over a stale locked
pnpm.exe/reflink native module.
2026-08-27 11:33:27 +08:00
creatixchu
6107e10c25 test(web): refresh feedback release golden 2026-08-27 11:32:23 +08:00
Yichen Jiang
94db8e881b fix(web): render readable ask-user transcripts 2026-08-27 11:28:59 +08:00
creatixchu
25ae5ae6e0 Merge remote-tracking branch 'origin/master' into worktree/feedback-otel-enable 2026-08-27 11:19:57 +08:00
Chinesezjc
4ed5303f41 Merge pull request #3115 from deepseek-harness/fix/remove-transform-corpus
fix(ci): Windows pnpm setup isolation and spawn budget alignment
2026-08-27 11:14:03 +08:00
pku-xht
8c67d49ca5 fix(api): simplify projection reconciliation 2026-08-27 11:02:06 +08:00
creatixchu
16a7ead9ab Merge remote-tracking branch 'origin/master' into codex/pr-3111-review
# Conflicts:
#	scripts/ci-workflow.spec.ts
2026-08-27 10:57:27 +08:00
pku-xht
c3b694312f fix(web): harden schedule catalog state handling 2026-08-27 10:24:36 +08:00
Yichen Jiang
a24c71127f Merge pull request #3155 from deepseek-harness/feat/web-input-trigger-menu-polish
feat(web): 输入触发菜单(/ 与 @)呈现打磨
2026-08-27 10:12:39 +08:00
pku-xht
beaa5638b4 fix(session): centralize projection baseline precedence 2026-08-27 08:55:32 +08:00
pku-xht
dfb9b9475f test(web): close schedule catalog review gaps 2026-08-27 06:46:00 +08:00
pku-xht
86fa9f512b Merge origin/master into schedule-web-catalog 2026-08-27 05:26:09 +08:00
pku-xht
57d8a79bfe fix(session): validate seeded projection boundary 2026-08-27 05:21:41 +08:00
imccyu
e290fb1dc7 Merge pull request #3085 from deepseek-harness/worktree-apire-c
refactor(apiproxy): credentials and settings to Remote
2026-08-27 04:16:33 +08:00
imccyu
f3e16c9bcc docs(api): refresh configuration type records 2026-08-27 03:28:30 +08:00
pku-xht
a5330ecf99 Merge commit 'e25ae41263f1ce4066aa8352f76d3d6d077b7959' into schedule-web-catalog
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/client/ui-workspace/package.json
2026-08-27 03:13:03 +08:00
imccyu
08176e6626 test(api): type heterogeneous provider calls 2026-08-27 03:12:36 +08:00
imccyu
f19c25123d style(apiproxy): remove stale spacing 2026-08-27 03:08:53 +08:00
imccyu
9fdbec00ee fix(web): reuse the preview Remote helper 2026-08-27 03:06:59 +08:00
imccyu
fcba3bbacb test(api): avoid mixed Remote result inference 2026-08-27 03:06:58 +08:00
imccyu
fd7f2065b2 refactor(apiproxy)!: remove settings and credentials RPCs 2026-08-27 03:01:29 +08:00
imccyu
5918dd205e refactor(client): use settings Remote namespaces 2026-08-27 03:01:02 +08:00
imccyu
dd70c0c88d feat(api): serve settings through Remote controllers 2026-08-27 03:00:49 +08:00
imccyu
0a9a9ee686 docs(api): record settings Remote migration 2026-08-27 03:00:25 +08:00
pku-xht
68c48109e3 docs(session): align projection replay criteria 2026-08-27 02:51:36 +08:00
imccyu
fc5224b389 Merge pull request #3086 from deepseek-harness/worktree-apire-d2
refactor(apiproxy): directory-picker to Remote
2026-08-27 02:42:12 +08:00
imccyu
54d77eff00 docs(directory-picker): record the Remote transport 2026-08-27 02:20:40 +08:00
imccyu
6e4087626d refactor(apiproxy)!: remove directory-picker RPCs 2026-08-27 02:20:39 +08:00
imccyu
011d53862d refactor(client): use directory-picker Remote 2026-08-27 02:20:38 +08:00
imccyu
76dedd4862 feat(workspace-controller): expose directory picking through Remote 2026-08-27 02:20:38 +08:00
pku-xht
11a5bc5083 fix(api): preserve projection baseline precedence 2026-08-27 02:18:51 +08:00
imccyu
3007864cfe refactor(directory-picker): expose client-safe listing types 2026-08-27 01:44:15 +08:00
pku-xht
8042ac94a3 test(web): make schedule locale assertion deterministic 2026-08-27 00:56:48 +08:00
pku-xht
650e96cb4d docs(session-projection): correct initialization contract 2026-08-27 00:03:57 +08:00
pku-xht
dd3e1c8490 fix(session): replay projection baselines in order 2026-08-26 23:11:22 +08:00
Chinesezjc
d77b64e7cf test: derive the plugin add/remove budget and note the exe build
The anchors-a-relative-add-spec case serializes two subprocesses (plugin
add + remove) under a hardcoded 90s budget, which the 2x60s worst case
exhausts; derive it from SPAWN_TIMEOUT_MS * 2 + 30s like the other
dual-call cases. The pnpm setup isolation note now also records the python
SDK exe build's suffixed destination and its regression-test coverage.
2026-08-26 22:42:55 +08:00
Yif
36dd657c7e test(ui-input-trigger): cover the onHover slot wiring; restore master's notices
The merge resolution had reverted THIRD_PARTY_NOTICES.md to the SDK 0.3.220
rows; the lockfile pins 0.3.241, so CI regenerated a mismatch. The apply spec
now drives the injected onHover face, closing the per-file coverage gap on
src/client/index.ts.
2026-08-26 22:10:58 +08:00
Chinesezjc
075cfc3b4d test: give the dual-call built-bin cases a 150s outer budget
The plugin add and dump-default-config cases serialize two runBuiltBin
calls, each with a 60s execa cap; the 90s outer budget could be exhausted
before the second call. Raise them to SPAWN_TIMEOUT_MS * 2 + 30s, matching
the multi-call treatment.
2026-08-26 21:52:44 +08:00
Yif
9ec543c943 Merge remote-tracking branch 'origin/master' into feat/web-input-trigger-menu-polish
# Conflicts:
#	apps/web/tests/agent-preset-selection.e2e.ts
2026-08-26 21:35:21 +08:00
pku-xht
9e17966e05 Merge commit '9acb9c5ac5de67a511afedbb30e74edbdbc4d57e' into schedule-web-catalog
# Conflicts:
#	apps/web/tests/schedule-after.e2e.ts
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/api/session-controller/tests/manager.client.spec.ts
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
2026-08-26 21:27:19 +08:00
Yif
0114dc1f81 feat(web): polish the input trigger menu presentation
Candidate rows lead with domain icons instead of localized text
prefixes; pointer and keyboard share one reducer-owned highlight (last
input wins); drillable folder rows reveal a localized Browse-folder +
Tab keycap hint with the library chevron; pending sources render
skeleton bars; the menu spans the composer card. The editable @dir/
text decorates color-only — the domain icon now belongs exclusively to
the settled reference chip. Composer placeholders advertise / and @,
and the zh copy for commands is unified to 指令.
2026-08-26 21:17:46 +08:00
ihsiang
bc1f515b04 Merge pull request #3145 from deepseek-harness/ihsiangzhang/secondary-font-tier
feat(ui): unify the flow-row secondary font tier and scale tables
2026-08-26 20:50:23 +08:00
pku-xht
48f79a52d8 test(session-query): model non-error rejection 2026-08-26 20:08:54 +08:00
pku-xht
5fe390dc8b chore: keep generated notices current 2026-08-26 20:08:06 +08:00
_Kerman
14bdba0924 fix(notices): refresh Claude SDK payload versions 2026-08-26 20:07:07 +08:00
pku-xht
e841fb6049 feat(web): surface active schedules in session views 2026-08-26 20:03:19 +08:00
_Kerman
bd6f72cbbb Merge remote-tracking branch 'origin/master' into xtr/session-projection-migrations 2026-08-26 19:59:02 +08:00
yx.zhang
9e33469913 fix(review): correct the secondary-tier floor claim and pin engine-resolved sizes
The Agent Note (both languages), the PR prose, and the commit message
claimed a 13px floor for the table variants; the formula has none —
max(13px, setting − 2px) selects the −1 branch at low settings rather
than clamping the result, so the tier bottoms out at 11px at the 12px
setting, matching think text. Rewrite the claim, say so in the axis
comment, and split the README sentence that lumped body-pair and
secondary-pair consumers together.

Assert the engine-resolved secondary size in the settings-chrome e2e
(13px at the default, 13px at the 15px boundary, 14px at 16px,
unchanged across reload), sync the StatsLine and workflow-panel spec
headers with the tier they now pin, and note why memberLabel stays at
the body size.
2026-08-26 19:28:04 +08:00
yx.zhang
a77e23a975 feat(ui): unify the flow-row secondary font tier and scale tables
Derive --dsh-content-font-size-secondary (setting -1 at <=14, setting -2
above; 13px at the default) with --dsh-content-font-delta-secondary in
gradient-shadow-text.css, and move every one-step-under-the-body text
onto it: think text and reasoning summaries, the shared DisclosureRow
title, ToolRow and bash-row summaries and file links, compaction/
context/command/retry/error rows, StatsLine, the workflow-run panel
tiers, reference summaries, the turn-status clock, and the feedback
note trigger. The markdown table variants join the same tier instead of
staying fixed; its 13px floor keeps them legible at the 12px setting.

At the default setting the flow-row titles and summaries render at 13px
(previously 14px) so they match think text at every setting instead of
sitting 2px above it.
2026-08-26 19:28:04 +08:00
Chinesezjc
6cbd3dda21 test: give the multi-call built-bin cases a 210s outer budget
The requires-profile and routes-help cases serialize 4-6 runBuiltBin calls,
each with a 60s execa cap; under the loaded pool the 90s outer budget was
exhausted before the last call and vitest truncated the run without the
execa diagnostics. Raise both to SPAWN_TIMEOUT_MS * 3 + 30s.
2026-08-26 18:20:43 +08:00
Yichen Jiang
b7ac86a4e0 Merge branch 'master' into worktree/fix-settings-focus 2026-08-26 18:02:00 +08:00
Chinesezjc
91379e8de6 ci(build-exe): drop pull_request label trigger to avoid skipped checks (#3049)
* ci(build-exe): drop pull_request label trigger to avoid skipped checks

* docs(build-exe): sync agent note and pin event set in workflow spec

* test(ci): type-safe event key assertion for build-exe workflow

* ci(build-exe): use present-tense trigger comment and drop label-run note
2026-08-26 17:52:34 +08:00
Chinesezjc
b648ed75c9 test: unify the last Windows spawn budgets to the 90s pattern
The built-bin help/usage case still used a win32-conditional 60/30s outer
budget while serializing six runBuiltBin calls, and startProfileLifecycle
lacked the execa timeout/killSignal the sibling helper has; the tool-ralph
cases pinned 20-30s explicit timeouts that the 90s lane default cannot
override. Align all of them to the SPAWN_TIMEOUT_MS + 30s (or 90s) pattern.
2026-08-26 17:43:57 +08:00
Yichen Jiang
4ecebeb54f Merge pull request #3138 from deepseek-harness/feat/models-provider-card-slots
feat(ui-settings-models): open provider-card and footer extension slots
2026-08-26 17:25:48 +08:00
Chinesezjc
84692044af test: raise the contended Windows spawn budgets to 90s
The per-case 15-30s budgets on the Windows native and coverage lanes fire
before oxlint, workflow-worker-thread, and other subprocess-spawning cases
finish under the loaded self-hosted pool; the failures rotate across cases
as load shifts, so per-case widening only moved the flake. Raise the lane
defaults (DSH_COVERAGE_TEST_TIMEOUT_MS and the native --testTimeout) to 90s,
align the oxlint and workflow-worker-thread case budgets, and keep the
built-bin SPAWN_TIMEOUT_MS at 60s under a 90s outer budget.
2026-08-26 17:17:47 +08:00
Yichen Jiang
bf0db65bb0 fix(ui-settings-models): address review — derived key fact, required render seat, spec sync
The provider-card seat's keyConfigured now derives from the reference the
page would use — the profile's apiKeyEnv, or the page's derived
<ROUTE>_API_KEY while the profile names none — so the add-provider draft
agrees with its own editor about an existing conventional credential (the
store joins the derived describe in the same batched call, as
ProviderRow.derivedCredential). ModelsSectionProps makes the renderSlot seat
required so a direct render that forgets it fails to compile; the one such
render in provider-form.client.spec regained a real mount and the test
boilerplate collapsed to renderSlot={() => null}. The extension-slots Agent
Note now states the keyed cell's real override rule (same priority throws,
a different priority shadows), and docs/subsystems/slots.md carries the two
new seats in its hierarchy, both languages.
2026-08-26 17:12:58 +08:00
Yichen Jiang
21a2a38a2f Merge pull request #3125 from deepseek-harness/worktree/composer-editable-gate
test(web): gate composer gestures on the editable attribute
2026-08-26 16:54:37 +08:00
_Kerman
96c1c762d5 fix(session-projection): preserve optional registrations 2026-08-26 16:51:36 +08:00
Chinesezjc
43b5b473bf ci: drop the stale pnpm setup cleanup steps
The windows-* jobs now install pnpm under a run/attempt/job-suffixed
destination, so the pre-install step that cleared the old fixed
setup-pnpm-js path no longer touches the actual destination and its
comment claims stale state. The suffix already gives every job a fresh
directory, so remove the four cleanup steps.
2026-08-26 16:39:30 +08:00
Chinesezjc
c20cfe77c6 test: align built-bin spawn budget with its outer case budgets
The execa timeout was widened to 60s but the outer vitest case budgets stayed
at 30s, so a cold-starting built bin would trip the vitest budget first and
the execa SIGKILL cleanup could not run inside it. Extract SPAWN_TIMEOUT_MS,
share it across the execa deadline, its error text, waitForFile, and the
outer case budgets (60s spawn + 30s headroom), so the widening is coherent.
2026-08-26 16:39:30 +08:00
Chinesezjc
e9cb003e9e test: widen oxlint contract and built-bin spawn budgets
Both suites spawn real subprocesses (oxlint probes; the dsh built bin) that
cold-start slowly on the contended self-hosted Windows pool, so their 20-25s
timeouts fire before the child finishes. Raise the oxlint contract case
timeouts to 60s and the built-bin execa timeouts to 60s, matching the
tool-ralph budget treatment.
2026-08-26 16:39:30 +08:00
Chinesezjc
e87a47692d ci: isolate the Windows pnpm setup destination per job
The windows-* jobs keep a separate standalone pnpm executable under
runner.temp/setup-pnpm-js. A previous job on the same self-hosted runner
can leave a locked @reflink native module there, so the next job's
pnpm/action-setup fails with EPERM during unlink before any test runs.
Suffix the destination with run_id, run_attempt, and job so every job
gets a fresh directory even when sequential jobs land on the same
runner; apply the same to the python SDK exe build. Update the pnpm
setup isolation note to record the Windows-specific destination.
2026-08-26 16:39:30 +08:00
Yichen Jiang
b5c3cc897c fix(llm-pi-ai): store the JSON image of a grant payload
pi-ai credentials carry optional members as explicit undefined (a github.com
Copilot grant holds enterpriseUrl: undefined), and the store bridge committed
the object verbatim, so the credential store's strict validator refused the
write and sign-in failed after the provider had already authorized it.
toRecord now drops explicitly-undefined members and renders undefined array
entries null, exactly as JSON.stringify would; everything else passes through
untouched so genuinely unstorable values still fail loud at the store.
2026-08-26 16:37:49 +08:00
Yichen Jiang
21e5ee9071 test(web): derive the editable gate from the gesture target
Review follow-ups: wait on the caller's own locator instead of assuming
it is the page's first composer, describe the actual read-only window
(submit adjudication and locked states — a running turn stays editable
for queueing), drop the pre-Lexical narration from the JSDoc, and record
the gesture-semantics trap as an Agent Note.
2026-08-26 16:35:49 +08:00
Yichen Jiang
10d1c603be Merge remote-tracking branch 'origin/master' into worktree/composer-editable-gate
# Conflicts:
#	apps/web/tests/permission-policy-context.e2e.ts
2026-08-26 16:11:32 +08:00
Yichen Jiang
5661b7a972 Merge pull request #3110 from deepseek-harness/worktree/fix-question-drafts-session-switch
fix(web): preserve ask_user_question drafts across Sessions
2026-08-26 16:10:37 +08:00
Magolor
df76bc695b feat(session): reduce persistence storage size (#3048) 2026-08-26 08:01:07 +00:00
Yichen Jiang
e5d39b6076 Merge origin/master into worktree/fix-question-drafts-session-switch 2026-08-26 15:51:15 +08:00
creatixchu
3031cb0e33 Merge remote-tracking branch 'origin/master' into codex/pr-3111-review
# Conflicts:
#	packages/api/session-controller/src/client/contract/snapshot.ts
#	packages/test-support/client-runtime/src/sessions.ts
2026-08-26 15:34:18 +08:00
imccyu
1e2d2b7b47 Merge pull request #3107 from deepseek-harness/worktree-workerfix3
fix(webworker): retain createRequire dependencies in preview images
2026-08-26 15:28:44 +08:00
_Kerman
f3d6433d9d test(agent-presets): mount projection seam in baseless harness 2026-08-26 15:22:21 +08:00
_Kerman
81e07e3935 Merge remote-tracking branch 'origin/master' into xtr/session-projection-migrations 2026-08-26 15:15:04 +08:00
_Kerman
c3468623ea test(python-sdk): accept explanatory live responses 2026-08-26 15:14:49 +08:00
_Kerman
4d34d59733 test(webworker-runtime): refresh title projection fixture 2026-08-26 15:14:34 +08:00
_Kerman
cd18de61d8 fix(session-projection): close migration coverage gaps 2026-08-26 15:14:14 +08:00
_Kerman
e296e79b18 fix(session-projection): complete mandatory compositions 2026-08-26 15:13:51 +08:00
Chinesezjc
ac36c6b975 test(web): drain trajectory scroll timer before teardown
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
2026-08-26 15:09:49 +08:00
imccyu
b72f5879c8 fix(webworker): scope createRequire dependency discovery 2026-08-26 15:09:49 +08:00
imccyu
437ab3cefe docs(webworker): define createRequire reachability limits 2026-08-26 15:09:48 +08:00
imccyu
f2cc573eb3 test(webworker): keep dependency coverage generic 2026-08-26 15:09:48 +08:00
imccyu
1429737a52 perf(hmr): poll client bundles only 2026-08-26 15:09:48 +08:00
imccyu
8f88a6f207 fix(webworker): expose Node process identity 2026-08-26 15:09:48 +08:00
imccyu
ba54d722a1 docs(web): clarify worker globals and HMR polling 2026-08-26 15:09:48 +08:00
imccyu
d54c2795cc fix(webworker): retain createRequire dependencies 2026-08-26 15:09:48 +08:00
imccyu
b588cdc478 docs(webworker): define createRequire reachability 2026-08-26 15:09:48 +08:00
Yichen Jiang
855461c2e8 feat(ui-settings-models): open provider-card and footer extension slots
The Models section now declares two SlotMap seats for out-of-tree plugins:
settings.models.provider-card (keyed by the row's settingsNs, dispatched on
saved cards, the first-run setup posture, and the add-provider draft, with
the row view, configured join, and confirmed api-key state as owner props)
and settings.models.footer (ordered list after the rows and add controls).
Without registrants both seats render nothing. First consumer: the
llm-pi-ai-oauth companion plugin's sign-in surface.
2026-08-26 15:09:30 +08:00
imccyu
5dba32bb48 Merge pull request #3083 from deepseek-harness/worktree-apire-b
refactor(apiproxy): subagent control to Remote
2026-08-26 15:08:59 +08:00
Chinesezjc
41591aa57f Merge branch 'master' into worktree/composer-editable-gate 2026-08-26 15:00:57 +08:00
Yichen Jiang
74fa4a00d7 Merge pull request #3123 from deepseek-harness/worktree/wizardly-maxwell-194a2a
fix(agent-presets): report unresolvable rows and refused switches
2026-08-26 14:57:09 +08:00
Yichen Jiang
605e33a2f5 fix(web): address question draft review feedback 2026-08-26 14:53:37 +08:00
imccyu
00c37f4ead test(web): drive preset slash catalog with gestures 2026-08-26 14:52:54 +08:00
imccyu
459919d21d test(session-projection-cache): drive interval deterministically 2026-08-26 14:52:54 +08:00
imccyu
b8360cac53 test(web): wait for editable permission composer 2026-08-26 14:52:53 +08:00
imccyu
64575de655 docs(subagent): regenerate Remote references 2026-08-26 14:52:53 +08:00
imccyu
91fea67745 test(subagent): cover Remote control migration 2026-08-26 14:52:53 +08:00
imccyu
cbe5d76e5c refactor(api-session-controller): route subagent calls through Remote 2026-08-26 14:52:53 +08:00
imccyu
377f3b4f1d feat(subagent): migrate browser control to Remote 2026-08-26 14:52:53 +08:00
creatixchu
dc82511497 ci(windows): restore complete coverage sharding 2026-08-26 14:49:29 +08:00
Yichen Jiang
1d00f5b4c0 Merge pull request #3117 from deepseek-harness/worktree/3116-docs-mpa-idempotence
fix(docs): make site builds idempotent
2026-08-26 14:49:11 +08:00
Yichen Jiang
23044ea774 Merge remote-tracking branch 'origin/worktree/wizardly-maxwell-194a2a' into worktree/wizardly-maxwell-194a2a 2026-08-26 14:43:22 +08:00
Yichen Jiang
56d3e8f82a fix(agent-presets): answer health from the walk alone, and keep the reason reachable
`import.meta.resolve`'s `parentURL` argument takes effect only under
`--experimental-import-meta-resolve`, which no launch passes, so the
fallback resolved from this module rather than from the harness — the one
question it existed to answer. The disk walk is the whole answer now, and
the refusal memo it needed goes with it. A `file:` URL joins the file
branch rather than the package one, where a resolver would only normalize
it and report a missing target as present, and a row is skipped on the
Loader's own `Boolean(disabled)` so `disabled: 0` is checked like the
Loader checks it.

A broken card says so through `aria-disabled` rather than `disabled`, and
refuses the pick in its own handler. `disabled` took it out of the tab
order, which with the reason moved onto the badge left it unreachable
without a pointer — reachable before this change, so hiding it was a
regression rather than a path that never existed.

Both notes this decision partly supersedes are updated in place and
cross-linked, one README pair loses an editing residue that repeated a
sentence, and the single-row diagnostic no longer reads "row row 1".
2026-08-26 14:42:39 +08:00
pku-xht
9cd9c7f634 test(web): complete schedule catalog validation 2026-08-26 14:40:12 +08:00
Yichen Jiang
f95cbca9ce test(web): target the editable command composer 2026-08-26 14:39:58 +08:00
creatixchu
116cd2332e Merge remote-tracking branch 'origin/master' into worktree/feedback-otel-enable 2026-08-26 14:35:49 +08:00
Yichen Jiang
308d1b21cb Merge remote-tracking branch 'origin/master' into worktree/3116-docs-mpa-idempotence 2026-08-26 14:33:23 +08:00
Yichen Jiang
1d09a4c877 fix(docs): harden build output cleanup 2026-08-26 14:33:17 +08:00
Yichen Jiang
2831054b97 test(web): await editable composer between turns 2026-08-26 14:30:56 +08:00
Yichen Jiang
4e1c87b1a2 fix(ci): bound Windows process contention 2026-08-26 14:24:24 +08:00
creatixchu
fab41be07e Merge remote-tracking branch 'origin/master' into codex/pr-3111-review 2026-08-26 14:21:56 +08:00
_Kerman
a6c7c70d4f fix(session-projection): close review findings from the fold migration
- permission-presets: register the permissions unit synchronously before the
  existing-session sweep, so a remount reads folded knob state instead of
  treating every session as fresh; add a regression test for that path
- sandbox-policy/terminal-bash: mount the projection registry in the 5 pwsh
  terminal tests, the sdk-minimal bundle, and the e2b fixture composition;
  declare the new package dependency in both manifests
- plan-mode: restore .strict() on the plan unit state schema and drop the
  deleted foldPlanMode from the bilingual READMEs
- session-title/session-projection: sync bilingual READMEs to the mandatory
  projection seam and re-record translation pairing
- docs: turnBoundary reader contract, subagent schema comment, token-meter
  import comment, sandbox-policy module docstring
2026-08-26 14:13:42 +08:00
creatixchu
7817ed3d82 docs: refresh Claude SDK notices 2026-08-26 14:09:31 +08:00
_Kerman
df0e0960c2 Merge remote-tracking branch 'origin/master' into xtr/session-projection-migrations 2026-08-26 13:51:57 +08:00
_Kerman
ef4dde9fe2 docs: reconcile projection catalogs after master merge 2026-08-26 13:51:32 +08:00
_Kerman
e6bf040dc3 fix(session-query): use renamed tool call id 2026-08-26 13:51:24 +08:00
creatixchu
2dd59b2ca1 test(client): cover instant image echo branches 2026-08-26 13:49:20 +08:00
Yichen Jiang
2cb1a323b7 Merge remote-tracking branch 'origin/master' into worktree/fix-question-drafts-session-switch 2026-08-26 13:44:45 +08:00
Yichen Jiang
94e3bfd5d1 test(web): gate composer gestures on the editable attribute
A running turn disables the composer by flipping contenteditable to
false on the same element. fill() throws there immediately — a disabled
textarea used to hold it back through actionability — and isEnabled()
reports true for a div regardless, so the permission-policy scenario's
post-settle wait never waited and its next gesture raced the re-enable
render. The window is a few frames wide; #3083's Remote-routed subagent
control stretches settle enough to hit it on CI.

writeComposerDraft now waits for contenteditable="true" before acting,
and the permission-policy scenario drives all four sends through it with
the settle wait pinned to the attribute.
2026-08-26 13:44:32 +08:00
Yichen Jiang
f87b6c35df Merge branch 'master' into worktree/wizardly-maxwell-194a2a 2026-08-26 13:42:28 +08:00
Yichen Jiang
002af9f20b fix(ui-agent-preset): read a refusal's cause by its detail, not its code 2026-08-26 13:41:20 +08:00
imccyu
6770f76fda Merge pull request #3063 from deepseek-harness/fix/window0825
perf(ci): optimize coverage / snapshot parameter
2026-08-26 13:40:33 +08:00
Yichen Jiang
cd3401a39a Merge remote-tracking branch 'origin/master' into worktree/wizardly-maxwell-194a2a
# Conflicts:
#	packages/client/ui-agent-preset/src/client/seat-store.ts
2026-08-26 13:37:53 +08:00
_Kerman
737691054a Merge remote-tracking branch 'origin/master' into xtr/session-projection-migrations
# Conflicts:
#	packages/core/agent-loop/tests/agent-initiator.spec.ts
#	packages/core/tools/tests/tools.spec.ts
#	packages/fs/tool-fs/tests/tools.spec.ts
#	packages/schedule/schedule/tests/plugin.spec.ts
#	packages/session/session-checkpoint-policy/tests/fixtures/crash-child.ts
2026-08-26 13:36:05 +08:00
Yichen Jiang
f7890f591a fix(agent-presets): make a preset's failures legible where they happen
Discovery proved only that a composition parsed, so a preset naming a
package a later rename took away kept a healthy card and its place in
every picker until a person switched to it. It now resolves each row it
can prove will start, reading the package off disk and falling back to
the resolver only for names that look absent — the resolver costs a
synchronous hooks-thread round-trip under the source launch's tsx hook,
which the walk avoids for every row it clears.

The mount diagnostic followed `AggregateError.errors` but never a cause,
so a group that failed on two rows named neither. It now follows a cause
that carries more than its own message.

A refused switch left the chip's label snapping back with no account of
why, which is the only account there can be for a preset that resolves
and then refuses. It announces through the shared Toast, which gained a
caller-set hold for a cause that names packages and rows.
2026-08-26 13:31:08 +08:00
creatixchu
5f3112d6ce Merge remote-tracking branch 'origin/master' into worktree/feedback-otel-enable
# Conflicts:
#	apps/web/tsconfig.json
2026-08-26 13:30:52 +08:00
imccyu
2a1a2605dc test(workflow-worker-thread): budget startup waits for the contended Windows pool 2026-08-26 13:28:44 +08:00
imccyu
b342b09401 chore(release): drop the unused synchronous runner 2026-08-26 13:23:41 +08:00
_Kerman
212df86cf8 refactor(session): migrate simple folds to projections 2026-08-26 13:23:01 +08:00
creatixchu
b22cc3e95b Merge master and address submission echo review 2026-08-26 13:20:24 +08:00
Yichen Jiang
d6a1031cfa Merge remote-tracking branch 'origin/master' into worktree/3116-docs-mpa-idempotence 2026-08-26 13:10:09 +08:00
Yichen Jiang
3275365489 fix(docs): make site builds idempotent 2026-08-26 13:09:53 +08:00
imccyu
f18ab429e4 ci(release): pack rehearsal tarballs concurrently 2026-08-26 12:46:17 +08:00
imccyu
e1c49dab59 ci(windows): clear stale pnpm setup state before install 2026-08-26 12:35:05 +08:00
imccyu
2d89a76b94 test(webworker-runtime): restore the transform semantic spec 2026-08-26 12:35:05 +08:00
imccyu
8793cd477b test(webworker-runtime): keep the corpus gate as a Node import sweep 2026-08-26 12:35:05 +08:00
imccyu
6d9cc6ab96 test(webworker-runtime): drop coverage requirement and compile transform suites 2026-08-26 12:35:04 +08:00
imccyu
54ef0f315a perf(typert): skip re-verified diagnostics and share analyzer caches in the tsdown plugin 2026-08-26 12:35:04 +08:00
imccyu
75428c7f47 perf(ci) 2026-08-26 12:35:04 +08:00
_Kerman
2efaacd807 Merge pull request #2731 from deepseek-harness/xtr/message-tool-call-id
refactor(llm): rename CallId to ToolCallId
2026-08-26 12:32:08 +08:00
creatixchu
c01cf6e549 test: exactOptionalPropertyTypes 下的 onRetire 捕获类型 2026-08-26 12:12:59 +08:00
creatixchu
f1606e31d2 test(web): 提交回显的组装路径 e2e 与不可见标记
PendingSubmissionBubble 携带 data-submission-echo 标记(渲染不变,仅供检测),
新增 keyless 组装 e2e:发送按键当下回显即在流中、composer 已清空可编辑,
durable 节点到达后原位替换且只剩一条气泡。
2026-08-26 12:12:08 +08:00
creatixchu
1da466a0a6 test+docs: 回显生命周期、去重与预览移交的覆盖,README 与 Agent Note
新增 sendSession 回显编排、ChatView 回显渲染与 rpcId 去重、control 队列 rpcId
投影、HistoricalImageCache.seed、MessageImage 预览 arm 的测试;四个包 README
双语更新;Agent Note 记录 rpcId 关联与延帧退休决策。
2026-08-26 12:01:27 +08:00
_Kerman
3759ea5dfe fix(agent-team): keep projection through runtime disposal 2026-08-26 12:00:02 +08:00
_Kerman
c7abeb23bf refactor(session): keep approval outside projection migration 2026-08-26 11:59:28 +08:00
creatixchu
5657066b1d test: 修复回显契约扩散到的类型化 fake 与断言 2026-08-26 11:51:35 +08:00
creatixchu
cf47b7e059 feat(web): 提交回显在 Chat 流尾即时渲染
ChatView 渲染 pendingSubmissions 为用户气泡,按 rpcId 对正式节点与队列行做
渲染期去重,替换原子无闪烁;新增回显跟随滚动;MessageImage/ImageGallery 增加
本地预览 arm,回显图片直接显示 object URL。
2026-08-26 11:49:56 +08:00
creatixchu
390dad6138 feat(ui-conversation): 默认发送改为乐观提交并接入提交回显
enter 即清空草稿并解冻输入框,默认发送作为 detached attempt 并发运行;
sink-settled 失败时仅还原未被覆盖的空草稿与图片;sendSession 在序列化前注册
提交回显并在绘制让步后再编码(FileReader 原生 base64);观察退休时把预览 URL
移交 HistoricalImageCache,正式消息节点零往返显示。
2026-08-26 11:49:16 +08:00
_Kerman
4325672ad6 Merge origin/master into xtr/session-projection-migrations 2026-08-26 11:48:52 +08:00
creatixchu
98da332260 feat(session-controller): 客户端本地提交回显与 rpcId 关联
beginSubmission 在 prompt 之前同步把本地提交回显写入 SessionSnapshot.pendingSubmissions;
durable user/message(source.rpcId)或队列投影(SessionQueuedItem.rpcId)到达后延迟一帧退休,
prompt 失败与放弃立即退休并回调 onRetire。fixture 的 prompt 同步回显 requestId。
2026-08-26 11:48:33 +08:00
Yichen Jiang
2c90710383 fix(web): preserve question drafts across Session switches 2026-08-26 11:42:52 +08:00
_Kerman
bf83f0889b Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2731 2026-08-26 11:40:56 +08:00
imccyu
a3c852b497 Merge pull request #3082 from deepseek-harness/worktree-apire-a2
refactor(apiproxy): move the agent-preset to Remote
2026-08-26 11:37:08 +08:00
_Kerman
3d05fdfbfb refactor(session): keep instruction and skill scans on event log 2026-08-26 11:32:38 +08:00
_Kerman
cf06f10229 test(session-controller): cover cold host-only projection cache 2026-08-26 11:32:19 +08:00
Yichen Jiang
d2a4a95a85 Merge pull request #2852 from deepseek-harness/worktree/web-textarea-refactor-991614
refactor(web): rebuild the composer on Lexical with atomic reference chips
2026-08-26 11:24:22 +08:00
imccyu
5752b1dc3c docs(agent-presets): refresh @Remote migration references 2026-08-26 11:18:36 +08:00
imccyu
c5be99838c test(agent-presets): cover the Remote migration 2026-08-26 11:18:28 +08:00
imccyu
ef1c812d93 refactor(ui-agent-preset): consume the preset Remote 2026-08-26 11:18:28 +08:00
imccyu
306419cc84 refactor(agent-presets): expose browser operations through Remote 2026-08-26 11:18:28 +08:00
_Kerman
6a311f0638 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2731 2026-08-26 11:17:50 +08:00
Dudu-0223
5e52e7eaef Merge pull request #2555 from deepseek-harness/codex/agentteams-web
feat(team): add experimental Agent Teams Web profile
2026-08-26 11:15:48 +08:00
_Kerman
e8c2423f5b chore: regenerate third-party notices for claude-agent-sdk 0.3.241 2026-08-26 11:12:37 +08:00
fengsy
d0eb02c206 docs(team): adopt package README standard 2026-08-26 10:56:57 +08:00
fengsy
194facabdb fix(team): authenticate browser panel snapshot 2026-08-26 10:56:57 +08:00
fengsy
eadd5df82b fix(team): preserve current Client architecture after rebase 2026-08-26 10:56:57 +08:00
Dudu-0223
8852161662 docs(team): link deferred Web preset work 2026-08-26 10:56:57 +08:00
Dudu-0223
80e033efe5 fix(team): address Agent Teams Web review 2026-08-26 10:56:57 +08:00
Dudu-0223
c6cab2aada fix(agent-team): isolate generated Remote browser entry 2026-08-26 10:56:57 +08:00
Dudu-0223
61dea35bd2 refactor: let Team own browser remotes 2026-08-26 10:56:57 +08:00
Dudu-0223
36588ade22 fix(team): isolate browser remote adapter 2026-08-26 10:56:57 +08:00
Dudu-0223
806642b064 feat(team): add experimental Agent Teams Web profile 2026-08-26 10:56:57 +08:00
_Kerman
5521b98143 fix(session-projection): isolate host state from wire snapshots 2026-08-26 10:52:27 +08:00
creatixchu
307bd73cc9 Merge remote-tracking branch 'origin/master' into worktree/feedback-otel-enable 2026-08-26 10:43:48 +08:00
imccyu
8a4fc10f36 Merge pull request #3050 from deepseek-harness/worktree/session-turn-nav-styling-7715ae
feat(web): navigate loaded Chat Turns from a compact rail
2026-08-26 10:40:34 +08:00
_Kerman
d3dd816d67 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2731
# Conflicts:
#	packages/util/brand/README.i18n.yaml
#	packages/util/brand/README.md
#	packages/util/brand/README.zh.md
2026-08-26 10:35:38 +08:00
Yichen Jiang
f20f0161ab fix(notices): restore the SDK 0.3.241 platform payload rows
The tenth master merge staged the correct 0.3.241 notices, but the
pre-commit regenerator ran against a local pnpm store that still held a
stale 0.3.220 SDK directory alphabetically ahead of it and silently
committed the old payload table. Regenerated after removing the stale
store entries; the lexical rows this branch adds stay.
2026-08-26 10:27:58 +08:00
Yichen Jiang
87ac9f5bea fix(notices): restore the SDK version the lockfile installs
The generator names the first matching virtual-store directory, so a local
store still holding an older SDK payload alongside the locked one renders
that older version into the notices.
2026-08-26 10:21:49 +08:00
creatixchu
66f2938b63 fix(web): adopt authenticated scaffold URL and post-merge golden in feedback-release lane 2026-08-26 10:14:20 +08:00
Yichen Jiang
2f157dbd76 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	packages/client/ui-chat/src/client/chat/MessageItem.module.css
#	packages/client/ui-conversation/package.json
#	packages/client/ui-input-trigger/README.i18n.yaml
#	packages/client/ui-input-trigger/README.md
#	packages/client/ui-input-trigger/README.zh.md
#	packages/client/ui-reference/README.i18n.yaml
#	packages/client/ui-reference/README.md
#	packages/client/ui-reference/README.zh.md
#	pnpm-lock.yaml
2026-08-26 10:10:09 +08:00
creatixchu
9c37f7a553 Merge remote-tracking branch 'origin/master' into worktree/feedback-otel-enable
# Conflicts:
#	apps/cli/reference/README.i18n.yaml
#	apps/cli/reference/README.md
#	apps/cli/reference/README.zh.md
#	packages/bundle/base/cordis.patch.yml
2026-08-26 10:06:55 +08:00
Yichen Jiang
f47b18d2f6 Merge remote-tracking branch 'origin/master' into worktree/session-turn-nav-styling-7715ae
# Conflicts:
#	packages/client/ui-chat/README.i18n.yaml
#	packages/client/ui-chat/README.md
#	packages/client/ui-chat/README.zh.md
2026-08-26 10:05:44 +08:00
creatixchu
ac4a2f9792 fix(feedback): address review — accurate release wording, current-state notes, default-mode snapshot lane 2026-08-26 10:05:31 +08:00
Tianyi Cui
d233300d55 Merge pull request #3087 from deepseek-harness/worktree/remove-ignorable-session-events
refactor(session): require known event types on read
2026-08-26 02:57:19 +08:00
Tianyi Cui
035ac85f42 Merge branch 'master' into worktree/remove-ignorable-session-events 2026-08-26 02:44:26 +08:00
Dudu-0223
0eccabd5c3 Merge pull request #2556 from deepseek-harness/codex/agentteams-cli
feat(team): add experimental Agent Teams CLI profile
2026-08-26 02:34:32 +08:00
Tianyi Cui
0d551b9f5c docs(session): align SQLite schema evidence 2026-08-26 01:39:53 +08:00
fengsy
a28f543ae4 docs(agent-team-profile): adopt package README standard 2026-08-26 00:53:57 +08:00
pku-xht
673aeb65af Merge commit 'a75a281deadcd90a3841bdd2efebbbbfd68696fc' into schedule-web-catalog
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/subsystems/session-projection.i18n.yaml
#	docs/subsystems/session-projection.md
#	docs/subsystems/session-projection.zh.md
#	packages/client/README.i18n.yaml
#	packages/client/README.md
#	packages/client/README.zh.md
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/schedule/README.i18n.yaml
#	packages/schedule/README.md
#	packages/schedule/README.zh.md
#	packages/schedule/schedule/README.i18n.yaml
#	packages/schedule/schedule/README.md
#	packages/schedule/schedule/README.zh.md
#	packages/session/session-projection-cache/README.i18n.yaml
#	packages/session/session-projection-cache/README.md
#	packages/session/session-projection-cache/README.zh.md
#	packages/session/session-projection-cache/src/index.ts
#	packages/session/session-projection-cache/src/spec.ts
#	packages/session/session-projection-cache/tests/cache.spec.ts
#	packages/session/session-projection/README.i18n.yaml
#	packages/session/session-projection/README.md
#	packages/session/session-projection/README.zh.md
2026-08-26 00:51:57 +08:00
Tianyi Cui
e7522ad39b test(persistence): retain primitive log-only coverage 2026-08-26 00:44:31 +08:00
Tianyi Cui
42dc2a46c2 refactor(session): require known event types on read 2026-08-26 00:22:31 +08:00
fengsy
d97868b943 test(subagent-acp): exempt Windows-inaccessible branches 2026-08-26 00:15:18 +08:00
fengsy
42378a987e fix(profile): deduplicate fallback manifest traversal 2026-08-26 00:15:18 +08:00
fengsy
1477d5b9ef fix(profile): preserve current fallback architecture after rebase 2026-08-26 00:15:18 +08:00
Dudu-0223
2c16c20d2a fix(profile): address Agent Teams CLI review 2026-08-26 00:13:36 +08:00
Dudu-0223
6e4fabdc1f fix(boot): stabilize profile module fallbacks 2026-08-26 00:13:36 +08:00
Dudu-0223
fd53e479b4 fix(profile): isolate bundle module fallbacks 2026-08-26 00:13:35 +08:00
Dudu-0223
a6c274e250 feat(team): add experimental Agent Teams CLI profile 2026-08-26 00:13:35 +08:00
imccyu
f18f2215b6 Merge pull request #3073 from deepseek-harness/worktree-apire-a
refactor(apiproxy): delete the goal unary domain
2026-08-25 23:54:01 +08:00
Magolor
0b5eba0c8d docs: rebuild the documentation skill and standards (#2983) 2026-08-25 23:47:20 +08:00
pku-xht
cdba045dfc fix(session): trust authoritative projection frames 2026-08-25 23:18:46 +08:00
Tianyi Cui
f4d1d3fb25 Merge pull request #3058 from deepseek-harness/fix/pwsh-local-dispose-status
fix(ci): consolidate windows/snapshot/e2e CI blocker fixes
2026-08-25 22:36:54 +08:00
pku-xht
5fe7dc333f fix(session): reconcile cached projection hints 2026-08-25 22:17:55 +08:00
Chinesezjc
9bf6f4b43c perf(ci): move the transform corpus out of coverage partitions
The full-corpus transform gate spawns one child that transforms and imports
every built bundle, so it runs for 8-25 minutes as a single case and
dominates one native Windows coverage partition, blowing its 900s budget
under load. Move it to the coverage-exempt heavy gate, which runs it with
its own worker budget instead of competing with the instrumented
partitions. The package's src is threshold-excluded in vitest.config.ts, so
the exemption carries no coverage; the exempt-heavy roster note records the
entry.
2026-08-25 22:11:11 +08:00
Chinesezjc
a404edf3b1 test: widen windows-hosted subprocess budgets in two web-stack specs
The self-hosted Windows coverage pool (16 shards x 12 workers on 192
threads) pushes real subprocess boots past their vitest deadlines: the
tool-pwsh Loader smoke reaches ~40s against a 30s process cap, and the
tool-ralph worker-thread cases exceed the 5s default. Give the pwsh
smoke a 90s process deadline (the subprocess keeps the assembled boot,
the vitest deadline stays at 120s), and give the two un-budgeted ralph
cases 30s each, matching the existing 20s quiescence case.
2026-08-25 22:11:11 +08:00
Chinesezjc
553b8c35da test(pwsh-local): accept graceful SIGTERM exit as service-disposal death
On Linux, pwsh may trap SIGTERM and exit cleanly when the subprocess service
is disposed, so the handle status is 'completed' rather than 'killed'. The
test already proved the process tree is gone via kill(pid,0); both statuses
satisfy the contract.
2026-08-25 22:10:31 +08:00
Yichen Jiang
e601f813a4 Merge pull request #3079 from deepseek-harness/worktree/3077-model-selector-names-only
fix(web): hide model selector descriptions
2026-08-25 22:02:18 +08:00
07akioni
79fd46b98e Merge pull request #3025 from deepseek-harness/ihsiangzhang/content-width-font-size
feat(ui): adaptive content width and settings font-size control
2026-08-25 21:54:15 +08:00
_Kerman
248d22f2c6 Merge remote-tracking branch 'origin/master' into xtr/message-tool-call-id 2026-08-25 21:44:26 +08:00
_Kerman
4e6a1f8d21 Merge origin/xtr/projection-per-session-cache into xtr/session-projection-migrations 2026-08-25 21:42:06 +08:00
_Kerman
53c8f64eed Merge pull request #2781 from deepseek-harness/xtr/projection-per-session-cache
feat(session-projection-cache): per-session checkpoint documents on a per-record storage layout
2026-08-25 21:37:09 +08:00
ihsiang
be994a9270 Merge branch 'master' into ihsiangzhang/content-width-font-size 2026-08-25 21:27:28 +08:00
_Kerman
cef391487a Merge remote-tracking branch 'origin/master' into xtr/projection-per-session-cache 2026-08-25 21:23:28 +08:00
imccyu
97405878c0 chore(tool-cordis): regenerate the Cordis catalog after the goal unary deletion 2026-08-25 21:23:24 +08:00
Yichen Jiang
7cc5a053fb Merge pull request #3071 from deepseek-harness/worktree/3070-minimal-bash-card-expand
fix(web): expand persistent Bash result cards
2026-08-25 21:22:18 +08:00
Yichen Jiang
b6c5aa7516 fix(web): hide model selector descriptions
Refs #3077
2026-08-25 21:19:21 +08:00
pku-xht
a47535ceab Merge pull request #2871 from deepseek-harness/codex/dsh-sdk-minimal-diagnostics
fix(subagent): preserve actionable DSH SDK failure facts
2026-08-25 21:16:02 +08:00
Yichen Jiang
a91fa3ddbc test(web): stabilize minimal Bash card snapshot 2026-08-25 21:05:01 +08:00
Yichen Jiang
9b6729d505 fix(web): expand persistent Bash result cards 2026-08-25 21:05:01 +08:00
_Kerman
380334436e fix(storage-json): preserve legacy cache after bootstrap 2026-08-25 21:02:39 +08:00
imccyu
09e2440b80 Merge pull request #2966 from deepseek-harness/worktree-locale2
feat(locale): allow external language registration
2026-08-25 21:01:36 +08:00
pku-xht
446a632c58 Merge commit '882fb242ad930f15617e95cfb04e5c2225d70772' into codex/dsh-sdk-minimal-diagnostics 2026-08-25 20:57:46 +08:00
imccyu
f04e2fe44a build(apiproxy): drop the now-unused goal dependency
Nothing under packages/host/apiproxy imports @deepseek-ai/dsh-goal after the
unary domain deletion, so the dependency and its project reference go too.
2026-08-25 20:55:03 +08:00
_Kerman
741083f03b Merge remote-tracking branch 'origin/master' into xtr/projection-per-session-cache 2026-08-25 20:54:08 +08:00
pku-xht
abebdb1eaa Merge origin/master into schedule-web-catalog 2026-08-25 20:52:51 +08:00
imccyu
243f6629ef refactor(apiproxy): delete the goal unary domain
The goal domain has been served by GoalService's @Remote namespace since it
shipped; the API Proxy copy was a second implementation of the same six
mutations. Remove the goals contract, schemas, route rows, IApiClient stub,
host implementation, and the fixture's compatibility face, leaving
ctx.remote.goals as the only path.

The fixture's goal fold keeps its coverage through the Goal Remotes: its
lifecycle case moves out of the unary-dispatch test, which no longer has
goal rows to cover.
2026-08-25 20:52:46 +08:00
_Kerman
83459fa476 perf(storage-json): load record files concurrently 2026-08-25 20:50:54 +08:00
pku-xht
36a047d436 Merge commit '788bc260f98e31801feccde77efdc985c780065a' into codex/dsh-sdk-minimal-diagnostics
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	packages/sdk/client/README.i18n.yaml
#	packages/sdk/client/README.md
#	packages/sdk/client/README.zh.md
#	packages/sdk/client/tests/sdk-client.spec.ts
#	packages/subagent/subagent-dsh-sdk/README.i18n.yaml
#	packages/subagent/subagent-dsh-sdk/README.md
#	packages/subagent/subagent-dsh-sdk/README.zh.md
#	packages/subagent/subagent-dsh-sdk/src/index.ts
#	packages/subagent/subagent-dsh-sdk/src/run.ts
#	packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/child-mock-llm.ts
#	packages/subagent/subagent-dsh-sdk/tests/loader-composition.e2e.ts
#	packages/subagent/subagent-dsh-sdk/tests/subagent-dsh-sdk.spec.ts
#	snapshots/sdk/sdk.snapshot.ts
2026-08-25 20:50:41 +08:00
pku-xht
907457580f Merge origin/master into schedule-web-catalog 2026-08-25 20:46:07 +08:00
yx.zhang
5720917ea7 polish(ui): trim the width handle and describe the font-size scope
Drop the width handle's double-click reset and tooltip — the handle is now
drag-only and a stored preference is only replaced by another drag — and
add a tertiary description line under the Settings font-size title stating
the size only affects conversation content. Update both Agent Notes and
the settings dialog goldens.
2026-08-25 20:44:07 +08:00
yx.zhang
9ecd18e986 feat(ui): extend the content font-size axis to flow chrome
Adopt --dsh-content-font-size / --dsh-content-font-delta across the flow
rows around the transcript body: DisclosureRow header (row height, title,
leading box, and registered glyphs, with StateDot exempt), ToolRow and
bash-row summaries and file links, think text, compaction/context/retry/
error rows, message clock and icon actions, the workflow-run panel, and
the workspace browser. Update the font-size Agent Note and add CSS-text
specs for the new adoptions.
2026-08-25 20:44:07 +08:00
pku-xht
be7e746bb7 Merge pull request #2873 from deepseek-harness/codex/product-subagent-runtime-refresh-codex
feat(subagent): configure Codex provider models
2026-08-25 20:43:31 +08:00
ihsiang
6d6f8f044c feat(ui): adaptive content width and font-size control
Add conversation adaptive content width and a Settings font-size control,
with theme presenter, font-size row, snapshots, tests, and agent notes.
2026-08-25 20:42:03 +08:00
imccyu
45b9f2db44 fix(locale): validate contributed language tags 2026-08-25 20:40:26 +08:00
imccyu
bbe00b0db2 feat(locale): allow external language registration 2026-08-25 20:40:26 +08:00
imccyu
9d61ab6756 docs(locale): define extensible language fallbacks 2026-08-25 20:40:25 +08:00
imccyu
c4e0b3b1e7 Merge pull request #2587 from deepseek-harness/codex/history-packed-transport
perf(history): carry packed assistant chunks
2026-08-25 20:39:45 +08:00
imccyu
27b8d6fe97 fix(chat): exclude packed deltas from token fold 2026-08-25 20:25:23 +08:00
_Kerman
f436c888aa Merge remote-tracking branch 'origin/master' into xtr/message-tool-call-id 2026-08-25 20:24:54 +08:00
_Kerman
d79ff0b589 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2781 2026-08-25 20:15:26 +08:00
imccyu
d3efd9c35d fix(conversation): restore merge-map lint scope 2026-08-25 20:15:07 +08:00
imccyu
adddc4dea6 test(history): cover packed record branches 2026-08-25 20:15:07 +08:00
imccyu
f37bb35a97 perf(conversation): fold packed assistant history 2026-08-25 20:15:06 +08:00
imccyu
1ec75c9082 perf(history): retain packed records in client 2026-08-25 20:13:54 +08:00
pku-xht
ea3284b1af Merge commit '0c177e17a23692d018a79bae59ac9a2db6eba59c' into codex/product-subagent-runtime-refresh-codex 2026-08-25 20:11:56 +08:00
imccyu
20d55b2c41 feat(gateway): support ranged journal entries 2026-08-25 20:10:50 +08:00
kingwl
4f02717ebc fix(e2e): decode packed history records 2026-08-25 20:10:50 +08:00
kingwl
04c0758fe9 fix(history): adapt packed pages to session journal 2026-08-25 20:10:43 +08:00
kingwl
055c505c6d test(history): measure complete response parsing 2026-08-25 20:10:43 +08:00
kingwl
86e79b5886 test(history): label synthetic timing totals 2026-08-25 20:10:43 +08:00
kingwl
5171e107e0 test(history): measure end-to-end timing stages 2026-08-25 20:10:43 +08:00
kingwl
a47e80678e fix(history): preserve per-delta replay 2026-08-25 20:10:43 +08:00
kingwl
3511796fa6 test(web): await completed turn footers 2026-08-25 20:10:43 +08:00
kingwl
ea282f5710 test(history): measure packed heap usage 2026-08-25 20:10:43 +08:00
kingwl
dec9732d1f test(history): add packed transport benchmark 2026-08-25 20:10:43 +08:00
kingwl
f2ca913756 perf(history): carry packed assistant chunks 2026-08-25 20:10:42 +08:00
CreatixChu
e2a10b141e Merge pull request #3014 from deepseek-harness/worktree/2848-image-token-pressure
feat(llm): 在 compaction 中按路由为图片请求压力计价
2026-08-25 20:10:28 +08:00
_Kerman
3f34c026e3 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2781 2026-08-25 20:04:32 +08:00
creatixchu
e497ea69b1 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 19:56:17 +08:00
Yichen Jiang
effbffbff1 test(web): drive the streaming-fence prompt through the composer surface
The scenario landed on master with a textarea locator; the composer is a
Lexical contenteditable surface here, so the fill waited 30s for a node
that never exists. Use the shared per-key draft helper against
[data-composer-input] like the other composer scenarios.
2026-08-25 19:55:45 +08:00
pku-xht
b4b18715ad Merge pull request #2868 from deepseek-harness/codex/dsh-sdk-dynamic-subagent-routing
feat(subagent): carry model routing through DSH SDK
2026-08-25 19:54:24 +08:00
pku-xht
ddbe5abac8 Merge commit '80d68a54120fc87e6b354e41562a9fbfd6874e48' into codex/dsh-sdk-minimal-diagnostics 2026-08-25 19:52:38 +08:00
pku-xht
d149e6f222 Merge commit '80d68a54120fc87e6b354e41562a9fbfd6874e48' into codex/product-subagent-runtime-refresh-codex
# Conflicts:
#	examples/acp-agent/tests/snapshots/product-subagent-result-diagnostic/stdout.expected.jsonl
#	snapshots/session/product-subagent-result-diagnostic/session.jsonl
2026-08-25 19:42:47 +08:00
pku-xht
170c640bdf Merge commit '80d68a54120fc87e6b354e41562a9fbfd6874e48' into codex/dsh-sdk-dynamic-subagent-routing 2026-08-25 19:38:11 +08:00
pku-xht
4d54bfdff3 test(snapshot): refresh DSH SDK route schemas 2026-08-25 19:36:55 +08:00
Yichen Jiang
e177571236 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	.agents/notes/archived/manifest.json
#	apps/web/tests/reference-composer.e2e.ts
#	pnpm-lock.yaml
2026-08-25 19:35:55 +08:00
pku-xht
b57d378e7d Merge commit '74a6e1e5cf520cdde8bf461d9051c81142fd6afe' into codex/dsh-sdk-minimal-diagnostics 2026-08-25 19:33:48 +08:00
pku-xht
24e7d55ec6 Merge pull request #2869 from deepseek-harness/codex/product-subagent-runtime-refresh-claude-code
feat(subagent): configure Claude Code provider models
2026-08-25 19:33:08 +08:00
Yichen Jiang
47067a8ad2 Merge remote-tracking branch 'origin/master' into worktree/session-turn-nav-styling-7715ae
# Conflicts:
#	packages/client/ui-chat/README.i18n.yaml
#	packages/client/ui-chat/README.md
#	packages/client/ui-chat/README.zh.md
#	snapshots/web/cordis-tool-round/ui.expected.md
#	snapshots/web/message-actions/ui.expected.md
#	snapshots/web/seeded-history/command-row.expected.md
#	snapshots/web/seeded-history/feedback-row.expected.md
#	snapshots/web/seeded-history/ui.expected.md
#	snapshots/web/subagent-conversation/ui.expected.md
2026-08-25 19:32:16 +08:00
pku-xht
08aed20139 test(ci): stabilize cross-platform consumer gates 2026-08-25 19:27:34 +08:00
pku-xht
d372dceee1 Merge commit '74a6e1e5cf520cdde8bf461d9051c81142fd6afe' into codex/dsh-sdk-dynamic-subagent-routing 2026-08-25 19:25:22 +08:00
pku-xht
88f518097b Merge commit '74a6e1e5cf520cdde8bf461d9051c81142fd6afe' into codex/product-subagent-runtime-refresh-claude-code 2026-08-25 19:15:55 +08:00
pku-xht
f217795644 Merge commit 'a0e4561b88e76172dd779bef4b5e8c454550c3e9' into codex/dsh-sdk-minimal-diagnostics 2026-08-25 19:10:14 +08:00
lsdsjy
ad1156eb0b Merge pull request #2904 from deepseek-harness/feat/headless-reasoning-progress
feat(headless): stream reasoning progress to stderr
2026-08-25 19:09:47 +08:00
Ziya
b565df3442 feat(web): show exact per-turn token usage (#3005)
* feat(web): show exact per-turn token usage

* test(runtime): refresh exact token usage snapshots

* refactor(token-meter): own per-turn usage folding

* perf(ui-chat): bound paging anchor layout reads

* test(web): align usage golden with system prompt row

* fix(test): resolve token-meter client from source

* test(token-meter): cover retry without usage

---------

Co-authored-by: ZiyaZhang <199893125+ZiyaZhang@users.noreply.github.com>
2026-08-25 19:05:52 +08:00
lsdsjy
7c7e4aada8 fix(snapshot): project headless reasoning stderr 2026-08-25 18:51:37 +08:00
lsdsjy
3a9820c8cb fix(headless): make stream chunk handling exhaustive 2026-08-25 18:51:37 +08:00
lsdsjy
2813ef2a95 fix(headless): preserve reasoning block continuity 2026-08-25 18:51:37 +08:00
lsdsjy
937d2b3513 feat(headless): stream reasoning progress to stderr 2026-08-25 18:51:37 +08:00
pku-xht
2a9b940ef5 feat(web): list active reminders in the session header 2026-08-25 18:50:50 +08:00
lsdsjy
4f3f716de7 Merge pull request #2765 from deepseek-harness/fix/str-replace-null-insert-line
fix(fs): tolerate null editor placeholders
2026-08-25 18:47:34 +08:00
pku-xht
847c13a117 test(cli): allow Windows help smoke startup budget 2026-08-25 18:46:42 +08:00
pku-xht
b274f5e606 test: refresh dynamic route prompts after master 2026-08-25 18:39:26 +08:00
pku-xht
09fcf48ad8 test(snapshot): refresh DSH diagnostic prompt 2026-08-25 18:32:13 +08:00
pku-xht
311d565ace Merge commit '8385aeecf95a4b842e8c317ab75ce26cafe8ba90' into codex/dsh-sdk-dynamic-subagent-routing 2026-08-25 18:31:27 +08:00
pku-xht
b9cd0d0c93 test: declare loader fixture skill dependency 2026-08-25 18:29:13 +08:00
pku-xht
e52b940781 Merge master into codex/dsh-sdk-minimal-diagnostics 2026-08-25 18:28:47 +08:00
lsdsjy
5c98d5ece8 fix(fs): tolerate null editor placeholders 2026-08-25 18:28:09 +08:00
pku-xht
7e234bb5b9 test(ci): stabilize required snapshot and Windows lanes 2026-08-25 18:27:06 +08:00
Dudu-0223
ee57508c26 Merge pull request #2985 from deepseek-harness/fix/web-fetch-ssrf
feat(web): enable public WebFetch by default
2026-08-25 18:25:58 +08:00
pku-xht
c97f985caa test: stabilize post-merge integration fixtures 2026-08-25 18:22:42 +08:00
Dudu-0223
560729be76 ci(windows): serialize native test files 2026-08-25 18:12:03 +08:00
pku-xht
c2fb21d13a Merge commit 'ead58a4a476200de2a2f2549ef6a02e73752b618' into codex/dsh-sdk-dynamic-subagent-routing
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.md
#	.agents/notes/implemented/feature/2026-07-27-typescript-sdk-and-sdk-subagent-backend.zh.md
#	examples/python-sdk-agent/tests/sdk.snapshot.ts
#	packages/sdk/client/README.i18n.yaml
#	packages/sdk/client/README.md
#	packages/sdk/client/README.zh.md
#	packages/sdk/client/src/types.ts
#	packages/sdk/protocol/README.i18n.yaml
#	packages/sdk/protocol/README.md
#	packages/sdk/protocol/README.zh.md
#	packages/sdk/server/src/server.ts
#	packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/snapshot.cordis.yml
#	packages/subagent/subagent-dsh-sdk/tests/fixtures/loader/snapshot.replay.cordis.yml
2026-08-25 18:01:08 +08:00
pku-xht
19fe4ffb1b Merge commit 'ead58a4a476200de2a2f2549ef6a02e73752b618' into codex/product-subagent-runtime-refresh-claude-code
# Conflicts:
#	examples/acp-agent/tests/snapshots/product-subagent-result-diagnostic/stdout.expected.jsonl
#	snapshots/session/product-subagent-result-diagnostic/session.jsonl
2026-08-25 17:54:09 +08:00
creatixchu
a6f2149472 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure
# Conflicts:
#	packages/subagent/subagent-acp/tests/subagent-acp.spec.ts
2026-08-25 17:51:27 +08:00
pku-xht
c386957475 Merge commit 'ead58a4a476200de2a2f2549ef6a02e73752b618' into codex/dsh-sdk-minimal-diagnostics 2026-08-25 17:22:27 +08:00
Dudu-0223
aeb83639c4 Merge remote-tracking branch 'origin/master' into fix/web-fetch-ssrf
# Conflicts:
#	packages/subagent/subagent-acp/tests/subagent-acp.spec.ts
2026-08-25 17:20:48 +08:00
Dudu-0223
b68f36a1ca test(web): authenticate folding snapshot 2026-08-25 17:20:06 +08:00
Chinesezjc
9bb3a5e262 Merge pull request #3059 from deepseek-harness/fix/subagent-acp-skip-ts
fix(subagent-acp): correct it.skipIf call arity
2026-08-25 17:19:53 +08:00
Chinesezjc
c26a3351c4 fix(subagent-acp): correct it.skipIf call arity
it.skipIf takes only the condition; passing a reason string as a second
argument breaks tsc and fails every build. Move the explanation to a comment.
2026-08-25 17:19:32 +08:00
creatixchu
1ca08183a6 test(web): authenticate folding snapshot page 2026-08-25 17:14:23 +08:00
Dudu-0223
637e029365 fix(subagent-acp): use supported skipIf signature 2026-08-25 17:10:03 +08:00
Dudu-0223
2abd486f8f Merge remote-tracking branch 'origin/master' into fix/web-fetch-ssrf 2026-08-25 17:07:57 +08:00
Dudu-0223
f858caa9c2 test(subagent-acp): skip half-close cases on Windows 2026-08-25 17:07:31 +08:00
creatixchu
89b50d3f1c test(subagent): exercise proxy EOF on Windows 2026-08-25 17:04:35 +08:00
creatixchu
771311eb6f Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 17:03:42 +08:00
creatixchu
903d9732aa test(subagent): close ACP protocol portably 2026-08-25 17:02:50 +08:00
Chinesezjc
af4e529149 Merge pull request #3055 from deepseek-harness/fix/windows-coverage-timeout-60s
test(subagent-acp): skip stdout half-close tests on Windows
2026-08-25 17:02:43 +08:00
Chinesezjc
ac2f00070e ci(windows): make windows-coverage temporarily non-blocking
Other PRs are blocked by Windows ACP half-close tests timing out. Keep the
coverage job running for signal, but remove it from all-checks-passed.needs
until the Windows skip fix is validated.
2026-08-25 17:02:16 +08:00
lsdsjy
fd0ed9fed4 Merge pull request #2845 from deepseek-harness/fix/workspace-new-session-fold-quota
fix(ui-workspace): keep blank new sessions outside the fold quota
2026-08-25 16:57:41 +08:00
Chinesezjc
eea3c132ff test(subagent-acp): skip stdout half-close tests on Windows
Windows anonymous pipes do not surface a child stdout EOF while the child
process stays alive. The three tests that simulate 'child closes protocol but
stays alive' therefore cannot be reproduced on Windows and hang until the
test timeout. Skip them on win32.
2026-08-25 16:36:28 +08:00
pku-xht
12dadc1f24 Merge commit '562d15dbb637e5eb15ddafd9167a21ee75b14d91' into codex/dsh-sdk-minimal-diagnostics
# Conflicts:
#	.github/workflows/ci.yml
#	scripts/ci-workflow.spec.ts
2026-08-25 16:33:17 +08:00
creatixchu
4dca5359a2 test(subagent): make ACP coverage platform-independent 2026-08-25 16:29:36 +08:00
pku-xht
0e632c82d0 Merge master into codex/dsh-sdk-minimal-diagnostics 2026-08-25 16:18:27 +08:00
Chinesezjc
5e7c567dc8 test(subagent-acp): double the per-test timeout relative to default
These tests spawn real ACP child subprocesses. On contended self-hosted
Windows runners the default 30s budget times out. Instead of raising the
global coverage timeout, give this file 2x the configured default
(DSH_COVERAGE_TEST_TIMEOUT_MS) so it follows future default changes.
2026-08-25 16:07:38 +08:00
Dudu-0223
6199f477de test(snapshot): sync web search trust prompt 2026-08-25 16:04:38 +08:00
creatixchu
1f288ede79 test(snapshot): refresh image request header 2026-08-25 15:59:44 +08:00
Chinesezjc
3073107ec4 ci(windows): raise coverage test timeout to 60s
After the 4-partition split, other PRs' windows coverage now fails on
process-bound subagent-acp tests timing out at 30s under self-hosted
concurrency. Give the coverage lane the same 60s per-test budget that the
earlier failover profile used.
2026-08-25 15:56:32 +08:00
Dudu-0223
44468d4583 Merge remote-tracking branch 'origin/master' into fix/web-fetch-ssrf 2026-08-25 15:53:46 +08:00
creatixchu
eea65e5275 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 15:52:17 +08:00
creatixchu
68be3e2270 test(subagent): stabilize ACP process coverage 2026-08-25 15:51:54 +08:00
imccyu
a1781cc4a8 Merge pull request #3054 from deepseek-harness/worktree-revert2698
revert(session): remove streaming format migration pipeline
2026-08-25 15:47:19 +08:00
07akioni
e5dbb368cd Merge pull request #2631 from deepseek-harness/worktree/fix-web-chat-system-prompt
fix(web): show system prompts in chat
2026-08-25 15:41:43 +08:00
imccyu
211e6939e3 Revert "Merge pull request #2698 from deepseek-harness/xtr/session-format-migration"
This reverts commit 4b592eb90df20dc53dd12215921d5a9137214777, reversing
changes made to d15d3275d905e4d21229cd70a074388a428189d1.
2026-08-25 15:30:10 +08:00
creatixchu
bb03d8e305 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 15:24:43 +08:00
Dudu-0223
6625c94449 Merge branch 'master' into fix/web-fetch-ssrf 2026-08-25 15:24:04 +08:00
Chinesezjc
5e3c04276e Merge pull request #3042 from deepseek-harness/test/windows-coverage-4-partitions
test(windows): lower coverage partitions 8->4 to reduce worker startup pressure
2026-08-25 15:22:39 +08:00
creatixchu
b2701b4ef9 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 15:20:59 +08:00
Dudu-0223
8da063441b Merge remote-tracking branch 'origin/master' into fix/web-fetch-ssrf 2026-08-25 15:17:09 +08:00
pku-xht
79fcf8481b Merge pull request #2870 from deepseek-harness/codex/acp-minimal-diagnostics
fix(subagent): preserve actionable ACP failure facts
2026-08-25 15:16:26 +08:00
_Kerman
96db1c8c81 fix(snapshot): canonicalize cache-split chunk runs 2026-08-25 15:10:26 +08:00
creatixchu
d978d6f90c Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 15:04:56 +08:00
pku-xht
13f373f0ce Merge master into codex/acp-minimal-diagnostics 2026-08-25 14:49:59 +08:00
Yichen Jiang
1272c7d0df perf(web): accumulate the Turn rail instead of scanning the loaded window
The rail's items now ride the Chat snapshot: a structural upsert re-derives
the loaded Turn set, a content-only upsert re-derives only the Turns whose
nodes changed, and each preview is capped so navigation state never holds a
copy of the transcript. The published array keeps its identity until an item
changes, so ChatView selects it as both data and change signal — and a
streaming reply's preview follows the in-place node update instead of the
last structural publication.

A scroll frame resolves the active mark with one hit test at the reading
line, falling back to a single row scan, rather than a DOM query per mark.
Flow-height changes resync through the existing column observer, navigating
during a pending page keeps the paging anchor, and the rail height no longer
holds a floor taller than the band it centers in.
2026-08-25 14:46:38 +08:00
Dudu-0223
8e681a66b9 Merge origin/master into fix/web-fetch-ssrf 2026-08-25 14:46:26 +08:00
_Kerman
38355623a2 Merge remote-tracking branch 'origin/master' into xtr/projection-per-session-cache
# Conflicts:
#	packages/bundle/web-app/README.i18n.yaml
#	packages/bundle/web-app/README.md
#	packages/bundle/web-app/README.zh.md
2026-08-25 14:45:03 +08:00
07akioni
61b65d3147 fix(web): show system prompts in chat
Render reconstructable system prompts at each request-series boundary, preserve series declarations through pre-step wrappers, and keep the presentation and replay snapshots aligned across clients.
2026-08-25 14:44:08 +08:00
_Kerman
804db36546 Merge remote-tracking branch 'origin/master' into xtr/message-tool-call-id 2026-08-25 14:42:35 +08:00
Tianyi Cui
5e868ef2c6 Merge pull request #3033 from deepseek-harness/worktree/fix-2090-web-auth
fix(web): authenticate the browser Host API
2026-08-25 14:40:58 +08:00
Dudu-0223
aaf0924b48 Merge origin/master into fix/web-fetch-ssrf 2026-08-25 14:40:51 +08:00
_Kerman
b588675ccf Merge remote-tracking branch 'origin/master' into xtr/projection-per-session-cache
# Conflicts:
#	pnpm-lock.yaml
2026-08-25 14:40:22 +08:00
_Kerman
f34c5f9838 Merge remote-tracking branch 'origin/master' into xtr/message-tool-call-id 2026-08-25 14:38:20 +08:00
creatixchu
a235f48c69 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 14:37:52 +08:00
_Kerman
9365ef496d Merge remote-tracking branch 'origin/master' into xtr/message-tool-call-id
# Conflicts:
#	packages/acp/acp/tests/approval.spec.ts
#	packages/acp/acp/tests/edges.spec.ts
#	packages/api/session-controller/tests/event-script.client.ts
#	packages/client/connection/src/client/fixture.ts
#	packages/client/ui-conversation/src/client/contract/slots.ts
#	packages/client/ui-conversation/src/client/contract/views.ts
#	packages/client/ui-conversation/src/client/index.ts
#	packages/client/ui-conversation/src/client/stores.ts
#	packages/core/agent-loop/tests/loop.spec.ts
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/events.ts
#	packages/host/apiproxy/tests/api-proxy-view.spec.ts
#	packages/interaction/user-approval/src/index.ts
#	packages/llm/llm-deepseek/tests/adapter.e2e.ts
#	packages/llm/llm-pi-ai/src/context.ts
#	packages/llm/llm-pi-ai/tests/context.spec.ts
#	packages/llm/llm/tests/content.spec.ts
#	packages/subagent/subagent/tests/continuation.spec.ts
#	packages/subagent/tool-subagent/tests/tool-subagent.spec.ts
#	packages/test-support/llm-replay/tests/llm-replay.spec.ts
#	packages/todo/tool-todo/tests/tool-todo.spec.ts
#	scripts/gen-persistence-catalog.ts
2026-08-25 14:37:44 +08:00
lsdsjy
9d25fbf218 fix(ui-workspace): keep blank new sessions outside the fold quota
Keep five non-blank rows stable while the selected blank New Session is provisional, and derive the overflow count from the rows still hidden.

Fixes #2841
2026-08-25 14:36:56 +08:00
Yichen Jiang
c612f2071d Merge pull request #3046 from deepseek-harness/worktree/fix-persistent-bash-pipeline-readiness
fix(pty): distinguish pipeline reads from terminal input
2026-08-25 14:33:37 +08:00
_Kerman
2c17b3048e fix(bundle): enable projection cache in base-backed profiles 2026-08-25 14:33:05 +08:00
pku-xht
8bab9d1731 Merge commit '7ef7175ff0c16623ab4e43187d1ecc29820b3909' into codex/acp-minimal-diagnostics 2026-08-25 14:31:14 +08:00
pku-xht
f7a885a522 Merge commit '4b592eb90df20dc53dd12215921d5a9137214777' into codex/acp-minimal-diagnostics
# Conflicts:
#	apps/cli/tests/profiles/acp/tests/snapshots/subagent-acp-diagnostic/input.json
#	apps/cli/tests/profiles/acp/tests/snapshots/subagent-acp-diagnostic/replay.override.json
#	apps/cli/tests/profiles/acp/tests/snapshots/subagent-acp-diagnostic/session.jsonl
#	apps/cli/tests/profiles/acp/tests/snapshots/subagent-acp-diagnostic/stdout.expected.jsonl
#	apps/cli/tests/profiles/acp/tests/snapshots/subagent-acp-diagnostic/tool-schemas.expected.json
#	examples/acp-agent/tests/acp.snapshot.ts
#	packages/subagent/subagent-acp/src/run.ts
#	packages/subagent/subagent-acp/tests/mock-acp-server.ts
2026-08-25 14:28:36 +08:00
Yichen Jiang
ba84299c98 test(web): record the Turn rail in every affected aria golden
The rail is a landmark on every Chat wide enough to show it, so each
recorded conversation with at least two loaded Turns now carries the
navigation node and its marks.
2026-08-25 14:26:10 +08:00
Dudu-0223
797c711e11 refactor(web): remove fetch approval policy 2026-08-25 14:25:12 +08:00
Tianyi Cui
4de11c0229 test(web): authenticate streaming fence scaffold 2026-08-25 14:23:47 +08:00
Tianyi Cui
b43d0934f7 test(web): keep credential fixtures package-local 2026-08-25 14:23:47 +08:00
Tianyi Cui
9c964848cd fix(web): keep browser authentication synchronous 2026-08-25 14:23:47 +08:00
Tianyi Cui
5595d593d1 docs(web): state authentication contracts directly 2026-08-25 14:23:47 +08:00
Tianyi Cui
3b3b493a96 fix(web): retain launch token across reloads 2026-08-25 14:23:46 +08:00
Tianyi Cui
ce031ddd16 fix(web): cover authenticated host runtimes 2026-08-25 14:23:46 +08:00
Tianyi Cui
3e24087bfa fix(web): authenticate the browser Host API 2026-08-25 14:23:45 +08:00
Yichen Jiang
a3f67137bc test(pty): cover restricted proc syscall access 2026-08-25 14:19:56 +08:00
creatixchu
718dd4d1b4 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 14:19:37 +08:00
Yichen Jiang
19c772f46c Merge pull request #3036 from deepseek-harness/worktree/system-prompt-order-bands
fix(system-prompt): centralize sparse section orders
2026-08-25 14:16:26 +08:00
_Kerman
ee2ee398ce test(credentials-local): seed fixtures atomically to close a boot-read race
The concurrent-migrator test wrote the winner document with a plain
writeFile, whose truncate-then-write window lets the boot's unlocked
initial read observe an empty file and boot an empty store under load.
Seed fixtures through writeFileAtomic instead, matching how the provider
itself persists, so a reader sees either the old or the new complete
document.
2026-08-25 14:13:06 +08:00
Yichen Jiang
133ed2d0f0 test(pty): report proc state on readiness failure 2026-08-25 14:08:30 +08:00
creatixchu
0d9bdccb7b Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 14:03:24 +08:00
Yichen Jiang
d38ff54150 feat(web): navigate loaded Chat Turns from a compact rail
ChatView derives one navigation mark per currently loaded Turn, keyed by
Turn number and anchored on that Turn's first loaded user node. The rail
sits against the scrollport's right edge, centered in the band the sticky
composer leaves visible; hover and keyboard focus preview the Turn's
prompt and response, and activating a mark moves the shared scrollport
and records the resulting restoration anchor.

ConversationRoot publishes --dsh-conversation-viewport-height beside the
composer height it already measures on the scrollport, so floating View
chrome can center in that band without assuming a Session header height.
2026-08-25 14:02:57 +08:00
creatixchu
4309dab24b fix(snapshot): honor ACP-local sidecar sources 2026-08-25 14:02:12 +08:00
Yichen Jiang
2338f4ad14 fix(pty): detect emulated kernel syscall ABI 2026-08-25 14:01:04 +08:00
07akioni
1ddee605dc Merge pull request #2857 from deepseek-harness/fix/streaming-fence-highlight
feat(web): keep code-fence syntax highlighting while streaming
2026-08-25 14:00:45 +08:00
Yichen Jiang
152d949f3e Merge remote-tracking branch 'origin/master' into worktree/system-prompt-order-bands 2026-08-25 13:53:44 +08:00
_Kerman
3fefcdbe3f Merge pull request #2698 from deepseek-harness/xtr/session-format-migration
feat(session): add streaming format migration pipeline
2026-08-25 13:47:43 +08:00
creatixchu
bcdbd85d15 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure 2026-08-25 13:43:45 +08:00
Yichen Jiang
5467685bc1 fix(pty): identify waiting thread terminals 2026-08-25 13:35:53 +08:00
Chinesezjc
bea14f9fcd docs(i18n): re-record translation pairing sidecars after partition update 2026-08-25 13:32:23 +08:00
Chinesezjc
16dbf73348 docs(windows): sync native CI note to 4 coverage partitions 2026-08-25 13:23:22 +08:00
Chinesezjc
a813b487ab docs(coverage): update Agent Note for Windows 4-partition alignment
The PR changes native Windows coverage partitions from 8 to 4 to reduce
vitest worker startup pressure under high self-hosted concurrency. Sync the
implemented Agent Note (EN/ZH) so the decision record no longer says Windows
is fixed at 8, and revise the same-partition-count alternative accordingly.
2026-08-25 13:17:22 +08:00
_Kerman
2664200844 Merge remote-tracking branch 'github/master' into xtr/session-format-migration 2026-08-25 13:04:23 +08:00
_Kerman
e5a41d164b Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2781 2026-08-25 13:04:04 +08:00
07akioni
1825cb4657 feat(client): highlight streaming fences incrementally
Keep recognized code fences syntax-highlighted while assistant text streams. Preserve completed Shiki token lines across chunks, mirror token styles and CRLF handling, and retain plain rendering for unsupported or math-like fences.

Add unit, DOM-parity, and keyless assembled-Web coverage for the streaming-to-settled transition.

Closes #1499
2026-08-25 12:59:21 +08:00
Yichen Jiang
9a12505f86 fix(pty): distinguish pipeline reads from terminal input 2026-08-25 12:54:55 +08:00
Tianyi Cui
78b9b9d499 Merge pull request #3032 from deepseek-harness/worktree/post-2958-simplifications-20260824
refactor: remove post-#2958 redundancy
2026-08-25 12:51:51 +08:00
_Kerman
e62d6d3d15 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2781 2026-08-25 12:49:32 +08:00
Chinesezjc
58cc29b4f1 test(windows): split native job into build/coverage/native-tests/observational
Keep the 4-partition coverage profile, split the monolithic windows-native
job into smaller required jobs (build, coverage, native-tests) plus a
non-blocking observational job. Update ci-workflow.spec for the new topology.
2026-08-25 12:45:47 +08:00
_Kerman
d385dfb3e3 Merge remote-tracking branch 'github/master' into xtr/session-format-migration
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	packages/session/session-persistence-jsonl/src/index.ts
#	packages/session/session-persistence/src/coordinator.ts
#	packages/session/session-persistence/src/index.ts
2026-08-25 12:41:23 +08:00
Tianyi Cui
7e6193acca refactor(cli): keep config dumps out of runtime healing 2026-08-25 12:21:51 +08:00
Tianyi Cui
8146557ef5 refactor(python): keep launch override on client 2026-08-25 12:21:51 +08:00
Tianyi Cui
aa801a418a test(python): share advanced runtime profile patch 2026-08-25 12:21:51 +08:00
Tianyi Cui
d0e8f5f9c4 test(sdk): leave model surface to packaged snapshot 2026-08-25 12:21:50 +08:00
Tianyi Cui
43f0f07f9b refactor(prompt): remove unused complete-persona config 2026-08-25 12:21:50 +08:00
Tianyi Cui
d35459e3c1 refactor(sdk): remove unused root tool filter 2026-08-25 12:21:50 +08:00
Yichen Jiang
145e060992 Merge remote-tracking branch 'origin/master' into worktree/system-prompt-order-bands 2026-08-25 12:07:56 +08:00
Yichen Jiang
8020f6386d docs(system-prompt): sync first-party order references 2026-08-25 12:05:38 +08:00
Chinesezjc
55ef5aad06 test(windows): try 4 coverage partitions instead of 8
Under high self-hosted concurrency, 8 partitions per Windows native job
triggered vitest fork worker startup timeouts. This branch lowers Windows
coverage to the same 4 partitions Linux uses, trading some single-job
coverage wall time for lower process-creation pressure.
2026-08-25 12:02:21 +08:00
creatixchu
106e5ce0bc feat(bundle): default session telemetry to feedback-gated sharing 2026-08-25 12:00:24 +08:00
CreatixChu
09eda93884 Merge pull request #3009 from deepseek-harness/worktree/2986-trajectory-image-attachments
feat(web): 在 Trajectory 中展示图片附件
2026-08-25 12:00:24 +08:00
Yichen Jiang
07319c011d test(web): share the per-key composer draft helper
CI hit the same dropped-fill race in lifecycle-chrome's slash-menu
sequence that the folder scenario hit: fill()'s single-task select-all +
edit lands on a Lexical selection that has not absorbed the DOM
selection after a trigger-menu interaction, so the previous draft
survives and poisons the next test. Promote the per-key gesture to
support.ts and use it at both proven-fragile sites.
2026-08-25 11:52:10 +08:00
_Kerman
ce65310183 fix(ci): keep the base projection cache out of listing-less profiles
The base-mounted projection cache's write-behind forces session-log flushes
at cache-chosen times, splitting packed chunk rows and changing the durable
JSONL batching the keyless headless and sdk replay fixtures pin. Neither
profile exposes a session-listing surface — the one-shot runner and the SDK
protocol — so both bundles disable the base row, restoring the pre-base
behavior the fixtures were recorded against (the same pattern acp-app uses).
2026-08-25 11:48:12 +08:00
Dudu-0223
04e946ed8b test(web): refresh fetch and trust snapshots 2026-08-25 11:37:22 +08:00
Yichen Jiang
0f7b28ad31 test(snapshot): refresh web prompt pins 2026-08-25 11:33:21 +08:00
Yichen Jiang
4d859cc062 test(web): align system-prompt pins with the reference guidance
The pinned prompts were recorded on master before this branch's
file-reference guidance rewrite; refresh them so the pin carries the
directory-aware wording the assembly now produces.
2026-08-25 11:27:30 +08:00
Yichen Jiang
5b3bfbed42 test(snapshot): refresh prompt order pins 2026-08-25 11:24:25 +08:00
Dudu-0223
433aab2724 test(web): refresh fetch tool schema snapshots 2026-08-25 11:22:42 +08:00
Dudu-0223
1af98028fa test(web): refresh external content prompt snapshots 2026-08-25 11:17:25 +08:00
creatixchu
1c065f3cd4 Merge remote-tracking branch 'origin/master' into worktree/2848-image-token-pressure
# Conflicts:
#	apps/cli/tests/profiles/acp/image-compaction.cordis.snapshot.yml
#	apps/cli/tests/profiles/acp/image-compaction.cordis.yml
#	apps/cli/tests/profiles/acp/tests/snapshots/image-compaction/input.json
#	apps/cli/tests/profiles/acp/tests/snapshots/image-compaction/session.jsonl
#	apps/cli/tests/profiles/acp/tests/snapshots/image-compaction/stdout.expected.jsonl
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	examples/acp-agent/tests/acp.snapshot.ts
#	packages/llm/token-meter/README.i18n.yaml
#	packages/llm/token-meter/README.md
#	packages/llm/token-meter/README.zh.md
#	packages/llm/token-meter/src/index.ts
#	packages/llm/token-meter/src/surface-fold.ts
2026-08-25 11:15:35 +08:00
Yichen Jiang
55eeaf6565 docs: refresh module graph 2026-08-25 11:12:21 +08:00
creatixchu
9c931ef5a8 fix: 修正轨迹图片测试归属 2026-08-25 11:06:17 +08:00
Yichen Jiang
43ac97b554 fix(system-prompt): centralize sparse section orders 2026-08-25 11:06:01 +08:00
_Kerman
3c8b5a26a4 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2781
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/subsystems/session-projection.i18n.yaml
#	docs/subsystems/session-projection.md
#	docs/subsystems/session-projection.zh.md
#	packages/api/session-controller/src/history.ts
#	packages/api/session-controller/tests/session-cold.host.spec.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/session/session-projection-cache/src/index.ts
#	packages/session/session-projection-cache/tests/cache.spec.ts
#	packages/session/session-projection/src/index.ts
#	scripts/run-gates.ts
2026-08-25 10:52:45 +08:00
creatixchu
dde6c8d7fc Merge remote-tracking branch 'origin/master' into worktree/2986-trajectory-image-attachments 2026-08-25 10:50:06 +08:00
Yichen Jiang
e71688c1fe test(web): write folder queries with per-key gestures
Directly after a chip deletion, fill()'s single-task select-all +
insertText lands on a Lexical selection that has not absorbed the DOM
selection yet and is dropped, leaving the previous draft in place. Real
keystrokes leave room for selectionchange between keys, matching what a
user's typing does.
2026-08-25 10:42:40 +08:00
Yichen Jiang
0a247137f0 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	apps/web/tests/composer-draft-scroll.e2e.ts
#	apps/web/tests/expected/reference-composer/caret-edits.expected.md
#	apps/web/tests/startup-auto-selection.e2e.ts
#	pnpm-lock.yaml
2026-08-25 10:42:32 +08:00
hypatiamay
0c5aa8110f Merge pull request #2999 from deepseek-harness/perf/token-meter-surface-fold-plan-commit
perf(token-meter): commit the surface fold in place through a plan/commit pair
2026-08-25 10:28:11 +08:00
Dudu-0223
8bf8e42b63 Merge remote-tracking branch 'origin/master' into fix/web-fetch-ssrf 2026-08-25 09:38:28 +08:00
Dudu-0223
070a180a10 Merge remote-tracking branch 'origin/master' into fix/web-fetch-ssrf
# Conflicts:
#	examples/acp-agent/tests/acp.snapshot.ts
#	examples/acp-agent/tests/snapshots/web-fetch/input.json
#	examples/acp-agent/tests/snapshots/web-fetch/stdout.expected.jsonl
#	knip.json
#	packages/test-support/session-snapshot/tests/fixtures/web-fetch-network.ts
#	snapshots/sdk/subagent-mixed/session.1.jsonl
#	snapshots/sdk/subagent-mixed/session.2.jsonl
#	snapshots/session/advanced-toolchain-runtime/session.1.jsonl
#	snapshots/session/advanced-toolchain-runtime/session.2.jsonl
#	snapshots/session/subagent-depth-two-rejection/session.1.jsonl
#	snapshots/session/subagent-depth-two-rejection/session.2.jsonl
#	snapshots/session/subagent-multi/session.1.jsonl
#	snapshots/session/subagent-multi/session.2.jsonl
#	snapshots/session/subagent-parallel/session.1.jsonl
#	snapshots/session/subagent-parallel/session.2.jsonl
#	snapshots/session/web-fetch/session.jsonl
#	snapshots/session/web-fetch/web-fetch-fixture-server.mjs
2026-08-25 09:14:36 +08:00
imccyu
8bb358d935 Merge pull request #2674 from deepseek-harness/feat/http-gzip
为 Web 静态资源与 API 响应增加 gzip 协商压缩
2026-08-25 06:58:58 +08:00
imccyu
78184a6ee1 fix(webworker): inline combo source maps 2026-08-25 06:43:25 +08:00
imccyu
60089680f9 test(webworker): keep bundle transport on host face 2026-08-25 06:43:25 +08:00
imccyu
075a46cdec fix(client): preserve combo source identities 2026-08-25 06:43:25 +08:00
imccyu
b3081bb4be fix(webworker): retain third-party runtime sources 2026-08-25 06:43:25 +08:00
imccyu
83463aa896 feat(client): use bounded plugin combo URLs 2026-08-25 06:43:24 +08:00
imccyu
08ed5a54a8 refactor(webserver): minimize HTTP gzip integration 2026-08-25 06:43:24 +08:00
imccyu
fc4c0a02eb Merge pull request #3029 from deepseek-harness/worktree-perfproj
perf(session): centralize cold observation and snapshot-first opening
2026-08-25 06:42:56 +08:00
imccyu
2b60227d08 docs(session): record observation and projection ownership 2026-08-25 06:23:10 +08:00
imccyu
059598de59 fix: c i 2026-08-25 06:19:23 +08:00
imccyu
1229292497 docs(session): refresh architecture and generated contracts 2026-08-25 06:10:25 +08:00
imccyu
d2904a6c06 fixup! refactor(session): open journal streams from snapshots 2026-08-25 06:09:25 +08:00
imccyu
f5f0448bee refactor(subagent): consume shared session observations 2026-08-25 06:09:25 +08:00
imccyu
b8dfa8b892 fix(agent-presets): project selection and refresh client catalogs 2026-08-25 06:07:58 +08:00
imccyu
822d735356 feat(session): persist model selection and share its catalog 2026-08-25 06:07:42 +08:00
imccyu
69fad4b8db perf(session-controller): serve cache-first session state 2026-08-25 06:07:26 +08:00
imccyu
e7952d82ed refactor(session): open journal streams from snapshots 2026-08-25 06:07:11 +08:00
imccyu
7fb2ca07e4 feat(session-query): add shared projected observations 2026-08-25 06:06:03 +08:00
imccyu
7f4cdc809c refactor(session-persistence): add borrowable prepared sessions 2026-08-25 06:05:50 +08:00
Dudu-0223
77e0b121df test(web): exercise fetch snapshot across build faces 2026-08-25 03:35:09 +08:00
Tianyi Cui
f8b0ca046f Merge pull request #3028 from deepseek-harness/worktree/fix-windows-coverage-worker-exit
fix(ci): order native Windows coverage after build
2026-08-24 23:35:24 +08:00
Tianyi Cui
aec6e4371a docs(ci): align Windows coverage capacity model 2026-08-24 23:33:18 +08:00
Tianyi Cui
10ba26dcf7 test(sqlite): decouple retry pacing from setup time 2026-08-24 23:06:05 +08:00
Tianyi Cui
97f9e2e402 fix(ci): serialize native Windows coverage after build 2026-08-24 22:36:02 +08:00
Tianyi Cui
084a1ac5f6 Merge pull request #2977 from deepseek-harness/worktree/remove-examples
refactor(repo): retire top-level examples
2026-08-24 14:17:05 +00:00
Tianyi Cui
e73c8a9fce fix(repo): close examples migration review gaps 2026-08-24 22:02:44 +08:00
Tianyi Cui
3b090c3c1b fix(test): declare Loader fixture dependencies 2026-08-24 22:02:44 +08:00
Tianyi Cui
4125514a08 refactor(repo): retire top-level examples 2026-08-24 22:02:44 +08:00
Tianyi Cui
e25463bc0a test(snapshot): cover Windows workspace symlinks 2026-08-24 22:02:38 +08:00
Tianyi Cui
59b156cb6c fix(test): refresh inherited session pins 2026-08-24 21:48:06 +08:00
Dudu-0223
2ac9072996 test(web): register snapshot network fixture 2026-08-24 21:47:19 +08:00
Dudu-0223
3b6cb9e83d Merge remote-tracking branch 'origin/master' into fix/web-fetch-ssrf
# Conflicts:
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-parallel/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-parallel/session.2.jsonl
2026-08-24 21:42:27 +08:00
Dudu-0223
709e5edaba fix(web): enforce approval before DNS resolution 2026-08-24 21:39:24 +08:00
pku-xht
0aafe0f8f8 test(subagent): align DSH SDK route evidence with profiles 2026-08-24 21:38:28 +08:00
pku-xht
9a6c94cb2f fix(sdk): gate prompts on route initialization 2026-08-24 21:38:28 +08:00
pku-xht
57eba4341c fix(subagent): narrow provider route defaults 2026-08-24 21:38:28 +08:00
pku-xht
096ae14db2 fix(subagent): bind preflight to provider route defaults 2026-08-24 21:38:28 +08:00
pku-xht
3c79979d1d fix(subagent): resolve DSH defaults before preflight 2026-08-24 21:38:28 +08:00
pku-xht
54e908df52 test: simplify DSH SDK route evidence 2026-08-24 21:38:28 +08:00
pku-xht
40f6205cdf test(snapshot): stabilize DSH SDK route usage 2026-08-24 21:38:28 +08:00
pku-xht
1044db218d feat(subagent): carry model routing through DSH SDK 2026-08-24 21:38:28 +08:00
Tianyi Cui
1232e61138 fix(test): align snapshots with merged tool routing 2026-08-24 21:37:58 +08:00
Tianyi Cui
6a74eec7a3 fix(test): reconcile snapshot corpus with merged parent 2026-08-24 21:37:58 +08:00
Tianyi Cui
920fe95be7 fix(test): refresh Goal UI from complete build 2026-08-24 21:37:58 +08:00
Tianyi Cui
8e23adcd28 fix(test): align snapshots with latest base 2026-08-24 21:37:58 +08:00
Tianyi Cui
84d172de3d fix(test): make Goal replay host-independent 2026-08-24 21:37:58 +08:00
Tianyi Cui
61cfe86f6e fix(test): stabilize rebased web fixtures 2026-08-24 21:37:58 +08:00
Tianyi Cui
6ea8a52e22 fix(test): harden snapshot corpus invariants 2026-08-24 21:37:57 +08:00
Tianyi Cui
d1e8f4672e fix(test): make session replay portable in CI 2026-08-24 21:37:14 +08:00
Tianyi Cui
e4a3918e87 docs: refresh module dependency graph 2026-08-24 21:37:14 +08:00
Tianyi Cui
caf386f59c fix(test): use expected-output naming 2026-08-24 21:37:14 +08:00
Tianyi Cui
1cfe0f9942 refactor(test): reserve snapshots for session recordings 2026-08-24 21:37:14 +08:00
Tianyi Cui
d4e81b6af7 test(snapshot): verify final workspace state 2026-08-24 21:37:14 +08:00
Tianyi Cui
6ca682733f refactor(test): drive sessions through owning profiles 2026-08-24 21:37:13 +08:00
Tianyi Cui
4790f23fea test(snapshot): drive ordinary turns through headless dsh 2026-08-24 21:36:32 +08:00
Tianyi Cui
6189e4a374 test(web): separate session snapshots from goldens 2026-08-24 21:36:31 +08:00
Tianyi Cui
33faf7f35f test(snapshot): separate headless sessions from goldens 2026-08-24 21:36:31 +08:00
Tianyi Cui
da1cb2c06e test(snapshot): centralize SDK session corpus 2026-08-24 21:36:31 +08:00
Tianyi Cui
84d6482a95 test(snapshot): declare recorded session ownership 2026-08-24 21:36:31 +08:00
Tianyi Cui
5c67cf898c test(snapshot): centralize ACP session corpus 2026-08-24 21:36:31 +08:00
Tianyi Cui
30762b63c9 refactor(test): make session snapshots transport neutral 2026-08-24 21:36:31 +08:00
Dudu-0223
b44a139ab7 Merge pull request #365 from deepseek-harness/pr-186
feat(spill-local): one-shot startup cleanup for local spill files
2026-08-24 21:31:37 +08:00
Yichen Jiang
91aa211d0d Merge pull request #2997 from deepseek-harness/worktree/fix-system-prompt-order
fix(system-prompt): stabilize workflow section order
2026-08-24 21:21:08 +08:00
Dudu-0223
d6f9931c4b test(spill-local): exclude POSIX identity branches on Windows 2026-08-24 21:20:23 +08:00
Dudu-0223
357d9749d1 Merge remote-tracking branch 'origin/master' into fix/web-fetch-ssrf
# Conflicts:
#	apps/web/tests/preview-boot.e2e.ts
2026-08-24 21:13:00 +08:00
Yichen Jiang
7e95ac012e Merge branch 'master' into worktree/fix-system-prompt-order 2026-08-24 21:08:27 +08:00
Dudu-0223
ca0e6f9707 Merge remote-tracking branch 'origin/master' into codex/pr-365-fixes 2026-08-24 21:07:22 +08:00
Dudu-0223
97693bbc85 test(spill-local): cover platform-specific cleanup paths 2026-08-24 21:07:12 +08:00
imccyu
2db3f8d4b0 Merge pull request #2710 from deepseek-harness/perf/client-plugin-batches
perf(client-modules): batch startup plugin scripts
2026-08-24 21:06:22 +08:00
Yichen Jiang
c697f260a4 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
2026-08-24 20:56:17 +08:00
Dudu-0223
202a2fe60f Merge remote-tracking branch 'origin/master' into codex/pr-365-fixes 2026-08-24 20:53:45 +08:00
Dudu-0223
9f9cc130e2 test(spill-local): normalize Windows realpaths consistently 2026-08-24 20:53:40 +08:00
Yichen Jiang
76a03e104e Merge remote-tracking branch 'origin/master' into worktree/fix-system-prompt-order 2026-08-24 20:53:09 +08:00
Yichen Jiang
adb133e303 Merge remote-tracking branch 'origin/master' into worktree/fix-system-prompt-order
# Conflicts:
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl
#	examples/acp-agent/tests/snapshots/subagent-parallel/session.1.jsonl
#	examples/acp-agent/tests/snapshots/subagent-parallel/session.2.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl
#	examples/headless-agent/tests/snapshots/compaction-recovery/session.jsonl
#	examples/headless-agent/tests/snapshots/pty-tools/session.jsonl
2026-08-24 20:52:52 +08:00
lsdsjy
838006d960 docs(client-modules,client-hmr): align bootstrap and rebuild semantics 2026-08-24 20:49:13 +08:00
imccyu
9c3a0893f6 perf(client-modules): defer per-plugin revision hashing
Preserve sourcemaps through the production Client build and verify batched loading across Host, HMR, and Web Worker paths.
2026-08-24 20:49:13 +08:00
lsdsjy
47bf44a5bb fix(client-modules,webserver,webworker-runtime): preserve batched boot across transports 2026-08-24 20:49:12 +08:00
lsdsjy
445de0ab3e fix(client-modules): tolerate incomplete source maps 2026-08-24 20:48:13 +08:00
lsdsjy
9ee9a3270c test(web): hold application batch during boot theme check 2026-08-24 20:48:12 +08:00
lsdsjy
5bbaf168d9 perf(client-modules): batch startup plugin scripts 2026-08-24 20:48:12 +08:00
imccyu
82aa8906e5 Merge pull request #2905 from deepseek-harness/turtle/local-build-banner-version
Show build version in local Web banner
2026-08-24 20:46:43 +08:00
Tianyi Cui
eeae6ba96a Merge pull request #2961 from deepseek-harness/worktree/python-sdk-windows-x64
feat(python): publish the Windows x64 dsh runtime
2026-08-24 20:43:37 +08:00
creatixchu
c2ce4a1405 Merge remote-tracking branch 'origin/master' into worktree/2986-trajectory-image-attachments 2026-08-24 20:32:07 +08:00
Dudu-0223
a0c1f7a6a7 Merge remote-tracking branch 'origin/master' into codex/pr-365-fixes 2026-08-24 20:31:27 +08:00
creatixchu
9f2ba9f5aa Merge origin/master (regenerate config catalog) 2026-08-24 19:51:16 +08:00
creatixchu
5183bc2b65 fix(compaction): 摘要收缩改按路由价并补齐定价访问路径
ds-review-bot 首轮意见修复:

- 摘要收缩比较改用所选节点的路由价 shadowedRouteTokenCount,修复图片消息启发式价低于带框摘要时压缩被误拒;日志影子价仍为启发式
- DeepSeek 定价经序列化器同一套 access 解析构建句柄与占位文本,消除逐图数十 token 的低估;uncatalogued 分支 JSDoc 指明复现 projectImagesForTextModel 替换
- llm-replay 在加载时拒绝纯文本模型上的 imageRequestTokens 声明
- contextBreakdown 的 README 与 JSDoc 改为等于 heuristicTokens 之和,不再声称等于路由价 surfaceTokens
2026-08-24 19:48:52 +08:00
lsdsjy
bf432bd0c8 Merge pull request #2854 from deepseek-harness/fix/web-running-draft-send-button
fix(web): switch running drafts to Send
2026-08-24 19:29:15 +08:00
creatixchu
42164508c8 feat(llm): 在 compaction 中按路由为图片请求压力计价
Closes #2848.

- dsh-llm 新增 LlmAdapter.imageRequestPricing 同步钩子与 LlmImageRequestPricing/LlmImageRequestPrice 词汇,ctx.llm 按路由解析
- llm-deepseek 用官方公布的 v4 视觉计算器逐句移植(14px patch、3:1 降采样、384 上限、最坏对齐 pad)实现该钩子,复现请求投影的最旧优先 offload 与像素预算缩放;纯几何 requestImageDimensions 上移到 dsh-attachment
- token-meter 表层 fold 存储与路由无关的节点事实,measure() 按生效 envelope 的路由为图片出现处定价;锚点存快照并按同一路由重定价;TokenSurfaceNode 同时携带路由价 tokens 与固定启发式 heuristicTokens
- compaction 触发、保留与选段读取同一套路由价,记录的 shadowedTokenCount 保持启发式以维持 O(1) 投影 fold 一致
- llm-replay 支持按模型的 imageRequestTokens 声明;新增 keyless 的 image-compaction ACP 快照场景端到端验证装配应用
2026-08-24 19:15:30 +08:00
creatixchu
00d3c82563 Merge remote-tracking branch 'origin/master' into worktree/2986-trajectory-image-attachments 2026-08-24 19:12:37 +08:00
creatixchu
15d53e228a docs: 同步模块依赖关系图 2026-08-24 19:10:18 +08:00
Tianyi Cui
dff3e18afd fix(python): budget cold profile initialization
The Windows x64 installed-wheel job timed out while waiting for initialize even though the same head passed on rerun. Exact packaged-runtime VM evidence showed a 6.47-second first cold handshake and 2.69-2.94-second warm fresh-home handshakes, leaving too little variance below the public 10-second default.\n\nRaise the independent initialize default to 30 seconds in both Python SDK configuration layers. Ordinary turn and shutdown timeouts remain unchanged, callers retain an explicit override, and tests plus paired documentation pin the public behavior.
2026-08-24 19:09:40 +08:00
Tianyi Cui
8101a0d097 fix(python): make Windows release paths native
Run the GitHub Windows runtime leg under the runner’s native PowerShell instead of inheriting the POSIX Bash body. POSIX and Windows now own explicit output resolution, virtual-environment setup, environment scrubbing, and keyless/live black-box commands, while portable build commands continue to use each runner’s default shell.

Put the pinned uv installation on the GitLab Windows job PATH before either the smoke or release builder invokes it. Reject a runtime executable whose basename does not match the selected platform manifest, and reject Intel macOS at platform selection instead of reporting a misleading missing artifact.

Add a complete PowerShell path to the published Python tutorial and record the three-phase shutdown-time bound in the Windows runtime decision. Workflow, Python, and bilingual documentation tests pin the resulting behavior.
2026-08-24 19:09:40 +08:00
Tianyi Cui
d4a63abe85 docs(python): define the Windows x64 runtime contract
Record win-x64 as the sole Windows Python carrier: node24-win-x64 builds a py3-none-win_amd64 wheel with dsh.exe, rg.exe, and both ConPTY addons; Windows arm64 remains explicitly unsupported. The note also pins native build ownership, shell-free pnpm launch, installed-wheel keyless/live gates, and the PowerShell-specific minimal snapshot.

Update the active SEA, sole-launcher, profile-runtime, installed-wheel, and publication decisions from three runtime wheels to four, preserving their existing rationale while linking the Windows extension. Contributor and runtime references now state the exact target, filenames, sidecars, snapshot ownership, and five-wheel release set in both languages.
2026-08-24 19:09:40 +08:00
Tianyi Cui
28442337cf feat(python-example): select the persistent shell by platform
Make the checked-in minimal SDK overlay disable both one-shot shell rows and mount exactly one persistent PTY stack: Bash on Linux/macOS and PowerShell on Windows. The SDK server, explicit dsh home, persistence, editor, timeout, and reduced tool catalog remain unchanged.

Update the runnable example and tutorial to list Windows x64 as supported, describe the platform-selected shell, and remove the obsolete POSIX-only restriction. This keeps the documented first Python task executable through the packaged Windows dsh profile instead of advertising a Linux-only overlay on a Windows-capable SDK.
2026-08-24 19:09:40 +08:00
Tianyi Cui
026a37fc07 ci(python): gate the Windows x64 installed wheel
Add node24-win-x64 to the required pull-request and public-release matrices on a native windows-2025 runner, and publish the same win_amd64 artifact from the GitLab tag pipeline. GitHub uses Git Bash for the shared release script while selecting the Windows venv's Scripts/python.exe explicitly; the Linux and macOS legs retain their existing commands and native checks.

Run the complete installed-wheel keyless suite and the trusted two-turn DeepSeek smoke on Windows exactly as on the existing targets. Make the minimal blackbox choose persistent PowerShell on Windows, keep advanced and restart snapshots platform-stable by disabling both one-shot shell variants, locate the generated dsh.exe console command, and validate text lines without assuming POSIX newlines.

Workflow tests pin the four-target matrix, Windows runner and wheel tag, cross-platform venv selection, GitLab publication dependency, and full blackbox invocation. The existing POSIX minimal snapshot changes only its platform-neutral prompt wording; Windows owns a separate model-visible snapshot.
2026-08-24 19:09:40 +08:00
Tianyi Cui
ca0b21661e feat(python-runtime): package the Windows x64 dsh executable
Add node24-win-x64 as the only supported Windows runtime target and publish it as a py3-none-win_amd64 wheel containing the conventional dsh and ripgrep .exe payload names. Keep Windows ARM64 rejected explicitly so Python cannot claim a carrier that CI and release automation do not build.

Teach the pkg builder to require a native x64 Windows host, validate both node-pty ConPTY addons, copy @vscode's win32 ripgrep executable, and recognize pkg's .exe output. Extend runtime resolution, wheel staging, payload validation, and the preset closure check so the Windows-specific PowerShell plugins and sidecars fail loud when omitted.

The sidecar resolver now maps a packaged main.exe to main-rg.exe; focused TypeScript and Python tests cover that name, the win_amd64 manifest, x64-only host selection, complete wheel payload, ConPTY inventory, and platform-conditioned plugin closure.
2026-08-24 19:09:40 +08:00
creatixchu
d420292400 fix(web): 处理评审发现的图片记录边界情况
- 图片错误结果在 Result 页签保留错误名称与代码
- 空文本块加图片的记录按纯图片标注,不再空行
- sourceBlock 的持久化图片守卫检查 attachmentId 字段
- 移除 ui-chat 对 util/crypto 的过期 tsconfig 引用
- 同步 slots.md 层级图与 2026-08-20 所有权 Note
2026-08-24 18:58:25 +08:00
pku-xht
55a8c2e9f2 chore(subagent): refresh Codex runtime 2026-08-24 18:31:03 +08:00
pku-xht
97e3a175ff docs(subagent): include product policy diagnostics 2026-08-24 18:31:02 +08:00
pku-xht
d495089ff7 review fix: align Codex policy evidence 2026-08-24 18:31:02 +08:00
pku-xht
bd6577072f docs(subagent): align Codex permission evidence 2026-08-24 18:31:02 +08:00
pku-xht
7c62fa127b docs(subagent): describe Host-only stderr flow 2026-08-24 18:31:02 +08:00
pku-xht
e2315e3b14 review fix: tighten Codex failure ownership 2026-08-24 18:31:02 +08:00
pku-xht
fe8a961348 feat(subagent): configure Codex provider models 2026-08-24 18:31:02 +08:00
pku-xht
56067f9972 docs(subagent): refresh Claude runtime notices 2026-08-24 18:30:50 +08:00
pku-xht
6a02e2c4a9 chore(subagent): refresh Claude Code runtime 2026-08-24 18:30:50 +08:00
pku-xht
f76cce2fc2 test(subagent): cover Claude limit subtypes 2026-08-24 18:30:49 +08:00
pku-xht
7d30a39619 review fix: simplify Claude diagnostic evidence 2026-08-24 18:30:49 +08:00
pku-xht
a043395c2d feat(subagent): configure Claude Code provider models 2026-08-24 18:30:49 +08:00
Dudu-0223
f76a225a7d Merge pull request #2663 from deepseek-harness/feat/subagent-provider
让 subagent 按需发现并选择子 Agent 模型
2026-08-24 18:23:42 +08:00
creatixchu
c27de594fd feat(web): 在 Trajectory 中展示图片附件
Trajectory 现在通过共享的 ui-attachment 画廊渲染会话日志中的持久化图片引用:ui-conversation 拥有按会话的图片 URL 缓存(ctx.uiConversation.imageUrl),ui-trajectory 声明 conversation.trajectory.images 子槽位,纯图片记录行以图片数量标注,内联 imageSrc 嗅探作为死代码删除。

Closes #2986
2026-08-24 17:59:02 +08:00
Tianyi Cui
de6d83a0fa Merge pull request #2958 from deepseek-harness/worktree/python-sdk-dsh-cli
feat(python): launch the SDK through packaged dsh profiles
2026-08-24 17:48:24 +08:00
Tianyi Cui
4719bef932 test(python): exercise the shipped SDK profile directly
The keyless max-token smoke carried a disable overlay that reproduced the removed private carrier's reduced tool roster. That legacy roster is now owned by the standalone sdk-minimal profile, so mutating the full sdk profile hides the application the SDK actually ships.\n\nLaunch sdk without a patch for both the successful and invalid-config paths. The separate sdk-minimal process test continues to pin its exact platform-selected two-tool request.
2026-08-24 17:28:29 +08:00
Tianyi Cui
104fe9b9e7 test(sdk-app): cover default profile configuration
The startup test helper always constructed an explicit sdk profile, so coverage never exercised apply's supported default-config path even though runtime behavior depended on it.\n\nPass Config objects through the helper and default them to an empty config. The existing startup and help tests now prove sdk defaulting, while the explicit sdk-minimal case remains covered.
2026-08-24 17:28:29 +08:00
Tianyi Cui
e2920f0109 fix(sdk-minimal): make the SDK model argument authoritative
Stop narrowing the standalone DeepSeek adapter to a DSH_MODEL-derived one-entry catalog. The direct adapter already accepts model ids outside its advisory catalog, so retain only the DSH_CONTEXT_WINDOW fallback and let the JSON-RPC initialize model be the single runtime selection.

Remove model mirroring from minimal.py and the packaged smoke. The keyless process now initializes deepseek-v4-pro without DSH_MODEL, while the packaged scenario continues to use its unlisted smoke-model; together they prove both cataloged and arbitrary SDK model arguments reach the adapter directly.

Update the bundle, tutorial, SDK/example references, and owning Agent Notes to keep DSH_MODEL only as minimal.py's optional default input, never as a second value callers must synchronize.
2026-08-24 17:28:29 +08:00
Tianyi Cui
7a11f5fde3 docs(python): define the standalone minimal profile
Record sdk-minimal as the narrow repository-owned exception to base-first profile composition: callers still launch only dsh and cannot provide an arbitrary Cordis tree, while the shipped bundle may own a complete explicit roster. Cross-link the launcher, profile-bundle, Python-runtime, minimal-agent, snapshot, and telemetry decisions; the supersession audit keeps each older note active because its remaining rationale is independent.

Update the CLI, architecture, Python tutorial/reference, example, runtime-wheel reference, and bundle documentation. The docs distinguish the full sdk profile from sdk-minimal, explain explicit-home/plugin/patch customization, state the minimal permission and persistence choices, and retain the separately packaged web profile and frontend assets for direct dsh use.

Correct dsh-base descriptions to cover base-backed profiles, make SDK startup configuration visible in the generated config catalog, add sdk-minimal to the module graph, and regenerate the base-composition graph. English and Chinese pairs are re-recorded at the exact reviewed contents.
2026-08-24 17:28:29 +08:00
Tianyi Cui
79a8f667f7 refactor(python): launch the minimal example through sdk-minimal
Make minimal.py select the shipped sdk-minimal profile directly and pass its selected model into the profile-owned adapter catalog. The Python SDK still starts only the bundled dsh CLI with an explicit Harness home; it no longer supplies an invocation overlay for this mode.

Drive both the source keyless process test and installed-wheel smoke through the same named profile. The keyless test pins the generated profile manifest and exact two-tool model request, while the packaged smoke keeps the persistent-shell, editor, session-log, and model-visible snapshot evidence.

Delete minimal.patch.yml and the unused complete-config/replay fixtures. Their composition now has one owner in @deepseek-ai/dsh-sdk-minimal, so the example and tests cannot drift into separate launch trees.
2026-08-24 17:28:28 +08:00
Tianyi Cui
8dc3b0380e feat(bundle): ship the standalone sdk-minimal profile
Add a startup-only sdk-minimal template whose sole bundle inserts the complete JSON-RPC agent tree over the empty profile root. The roster is an explicit composition allowlist: it contains one DeepSeek adapter, the minimal agent spine, persistent Bash, the string-replace editor, local execution, and JSONL persistence, while dsh-base and Web remain absent.

Reuse the SDK app startup provider so the new profile retains help, stdin EOF, and bounded launcher shutdown semantics. Make that provider render its configured profile name, which keeps both sdk and sdk-minimal help truthful without duplicating process lifecycle code.

Register the package in the CLI closure, TypeScript graph, lockfile, Knip policy, and bilingual bundle references. Exact manifest, row-roster, profile-template, config-dump, and HMR tests make later additions visible instead of relying on a blacklist.
2026-08-24 17:28:28 +08:00
Tianyi Cui
ab4e65ba82 perf(app-boot): avoid fallback locks for complete profiles
Resolve the installation fallback generation before locking and return immediately when every required symlink or packaged proxy is complete. Parallel SDK rollouts sharing an initialized DSH_HOME therefore do not queue on profiles/node_modules.lock.

Missing or stale entries still acquire the cross-process writer lock, recheck the generation, and repair under exclusive ownership. Tests hold the lock to prove the steady-state bypass and verify that a partial repair retains already-correct siblings.
2026-08-24 17:28:28 +08:00
Tianyi Cui
c2ad69344f fix(python-sdk): make the minimal profile an explicit allowlist
Give the SDK JSON-RPC server a per-root tool filter and let deployments mark the configured persona as the complete system prompt. The checked-in minimal overlay now names only bash and str_replace_editor, so later global tools and unrelated guidance from dsh-base cannot appear implicitly.

Keep the shared SDK host services and packaged Web capability intact. Only workspace instructions, compaction, and the conflicting one-shot Bash row remain disabled. Unit coverage pins the configuration paths, and a real dsh profile smoke proves the assembled prompt and exact two-tool request.
2026-08-24 17:28:28 +08:00
Tianyi Cui
d801f262d8 fix(python-sdk): resolve packaged proxies from real module entries
The packaged dsh launcher must expose installation modules to profile-local plugins without writing symlinks into pkg's virtual filesystem. The first review fix selected ESM exports correctly in ordinary Node, but real carrier execution exposed package metadata and VFS behavior that a synthetic tree did not cover: executable and declaration packages have no import entry, legacy main fields rely on Node probing, and pkg's Windows VFS prevents filesystem package-scope resolution from seeing exports such as zod/mini and @google/genai/web.

Resolve explicit exports directly from each installed manifest with the maintained resolve.exports package under Node import conditions. Publish only package-local candidate files that exist, reject escaping or malformed targets, preserve the package installation URL without realpath, and keep Node's legacy resolver only for exports-less packages. This avoids pkg filesystem package lookup entirely while retaining fail-loud behavior for broken runtime entries.

Add regression coverage for import-only, nested, symlinked, zod-style, and genai-style condition maps; unavailable and types-only entries; invalid and escaping targets; executable/declaration packages; extensionless main; and legacy index fallback. profile.ts remains at 100% statements, branches, functions, and lines. Update the bilingual package and Agent Note contracts, replace the runtime dependency and generated notice, and regenerate the lockfile through pnpm.
2026-08-24 17:28:27 +08:00
Tianyi Cui
9edf1b9f10 fix(python-sdk): harden profile runtime startup
Resolve packaged profile proxies with Node ESM import conditions from each package installation, and fail loud when an explicit runtime export or legacy main entry is missing. Serialize the shared profile fallback under the existing cross-process writer lock so concurrent dsh processes cannot observe partial proxies; either carrier now replaces the other carrier’s managed entry without manual cleanup.

Give Python initialize its own 10-second default bound and name the selected profile in timeout diagnostics, while leaving ordinary agent turns unbounded by default. Package the dynamically resolved web frontend and skill-badge assets so the runtime wheel’s normal dsh profiles do not depend on pkg static-discovery accidents.

Rewrite the root launch rule and every active stale SDK-runtime note to the shipped dsh profile architecture in both languages. Focused tests prove import-only and transitive package exports, lock contention, cross-carrier transitions, missing-entry failures, asset inventory, and bounded initialization.
2026-08-24 17:28:27 +08:00
Tianyi Cui
f0f9b294dd docs(python): make the dsh profile runtime current
Document dsh as the only application launcher across architecture, CLI, SDK, app-boot, Python package, contributor, tutorial, and example references. Explain explicit home selection, profile and patch precedence, persistent external plugin installation, the Node-free runtime path, and the absence of complete-config or ~/.dsh fallbacks.

Record the Python profile-runtime decision and update the active naming, installed-wheel, and SEA packaging notes with precise supersession. Regenerate the configuration catalog and module graph after deleting the carrier, update both reviewed languages and pairing records, and classify the retained standalone Cordis files as lower-level test fixtures rather than launch interfaces.
2026-08-24 17:28:27 +08:00
Tianyi Cui
01da043737 test(python): prove installed dsh profile customization
Migrate the packaged-runtime smoke inventory from complete Cordis trees to the sdk profile plus ordered patches. Preserve the focused minimal and advanced behaviors, update the generated durable snapshots for explicit permission events and the smaller RunResult, and keep worker, MCP, ripgrep, PTY/editor, direct JSON-RPC, and real-provider coverage.

Add an installed-only external bundle scenario that invokes the wheel's dsh plugin command with a local file package, verifies profile manifest reconciliation, imports @deepseek-ai/cordis as a peer, asserts the packaged proxy returns the exact host Context instance, and proves its system-prompt contribution reaches the model. Migrate the repository source e2e and runnable minimal example to the same profile grammar.
2026-08-24 17:28:26 +08:00
Tianyi Cui
56e038b2e3 feat(python-sdk): launch dsh profiles from explicit homes
Replace complete-config, session_root, runtime-bin, bridge-bin, and public argv override options with dsh_bin, profile, ordered patches, and dsh_home. Resolve executable/home/patch/cwd paths before spawn, select the sdk profile by default, and fail before launch unless dsh_home or non-empty DSH_HOME is explicit; Python never inherits ~/.dsh silently.

Remove Python-owned DSH_CORDIS_CONFIG, DSH_SESSION_ROOT, and DSH_CWD injection and drop session_root from RunResult. Keep arbitrary argv only as an underscore-prefixed fake-runtime adapter, retain provider/model/token and process controls, and append subprocess stderr to initialization JSON-RPC errors so profile boot failures name their actual plugin cause. Unit and carrier tests cover both exe and Node modes.
2026-08-24 17:28:26 +08:00
Tianyi Cui
be7b064504 feat(python-runtime): package the dsh CLI and profile assets
Make the zero-code dsh-python-runtime-closure depend on the real @deepseek-ai/dsh application and every required profile peer, then package apps/cli's built bin instead of the deleted Python carrier. Rename executables to deepseek-harness-sdk-runtime-<platform>-<arch>, update wheel/platform/build workflow discovery, and install a Python dsh console command that requires explicit DSH_HOME before exec.

Include profile, bundle, preset, native addon, and shared-library assets needed by the full CLI. Remove the checked-in default cordis.yml and preserve the existing wheel distribution names, Python module names, sidecar validation, and wire identity. Runtime resolution and release tests pin the new artifacts and dev Node carrier.
2026-08-24 17:28:26 +08:00
Tianyi Cui
809a4c5bad fix(app-boot): preserve profile modules inside pkg executables
Teach the profile installation fallback to use normal symlinks under Node and real ESM proxy packages under pkg. Each proxy records the source package version, mirrors its explicit runtime subpath exports, and re-exports the virtual /snapshot URLs, so built-in Loader rows and external plugin peers resolve one shared Cordis/module instance from an on-disk profile.

Keep proxy healing idempotent, reject foreign real directories, cover root and subpath imports in packaged mode, and expand AggregateError startup diagnostics so concurrent Loader failures retain their individual import causes. This is the reusable packaged-profile mechanism; Python-specific artifact wiring remains in the next commit.
2026-08-24 17:28:26 +08:00
Tianyi Cui
1d4dcf3b57 refactor(python): remove the private direct-config carrier
Delete @deepseek-ai/dsh-sdk-python-runtime and its packaged-bin entry now that Python uses the repository's dsh application launcher. Remove the package's project reference, Knip entry, workspace-policy exception, executable allowlist entry, and README-model classification together so no tooling preserves the old exception.

This commit is deliberately mechanical: it removes the obsolete package and gate accommodations without introducing the replacement launch behavior. The following commits add the packaged dsh runtime and Python profile API, keeping the architecture change separate from deletion noise.
2026-08-24 17:28:26 +08:00
CreatixChu
8122bec7cc Merge pull request #2989 from deepseek-harness/worktree/2885-image-compression
修正图片 master 压缩的编码路由并降低压缩耗时
2026-08-24 17:26:34 +08:00
creatixchu
cfacca1b07 test(attachment): pin the assembled image re-encoding path in a keyless snapshot
The read-image-reencode lane feeds a 16-bit gradient PNG through the
shipped app: pass-through is impossible, the master converts down the
opaque JPEG ladder, and the 640,000-pixel request budget re-encodes a
downscaled request version — the projection the byte-identical tiny
fixtures never exercised.
2026-08-24 17:15:59 +08:00
creatixchu
30704dc1df fix(attachment): budget master pixels and share the encoding ladder
Master dimensions move from a 2048 long-edge rule to a total-pixel
budget (normalizedImageMaxPixels, default 2048x2048) with an 8192
long-edge cap, so extreme aspect ratios keep short-edge resolution.
The shared quality ladder and lazy execution move to encoding.ts,
review-round doc fixes land across attachment and llm packages, and
the superseded facts in the unified-image-pipeline note now describe
the shipped routing.
2026-08-24 17:10:59 +08:00
Yichen Jiang
70d6e7abd6 fix(file-reference): teach the @-mention guidance directories and the workspace root
Field test: the model received a bare '@niulai/' and guessed a user
mention — the guidance section was present but said only that @-prefixed
paths are files, never covering the trailing-slash directory form, the
workspace-relative root, or the quoted spelling. Rewrite the section to
name all three; the section's presence conditions and every consumer
pin the constant, so nothing else moves.
2026-08-24 17:05:34 +08:00
Yichen Jiang
4036db4450 test(web): create reference fixtures before the workspace connects
CI's snapshots lane timed out waiting for the folderx candidate: the
fixture directory was created after connectFreshWorkspace, racing the
Host's file index on a loaded runner. Land every fixture (and the
workspace directory itself) before the connect, and give the first
folder query a cold-start allowance.
2026-08-24 16:57:38 +08:00
Yichen Jiang
dad39c8c18 feat(web): settle folder references on pick and move descent to a drill verb
A directory row in the @ menu had one verb doing two jobs: picking it
inserted literal @dir/ text and kept the menu open, so a user wanting
the folder itself never got a settled entity — the token kept its
trigger character and stayed editable, nothing like a file's atomic
chip.

Split the intents on the same row, mapped to shell-completion instincts:
row click / Enter settles the directory as an atomic folder chip (the
file chip's exact language; canonical @dir/ mention as its serialized
form — the { insert } arm the folder path never took), while Tab or the
row's trailing chevron drills: literal editable text, menu open on the
children. One new dimension carries it: candidate.drill advertises the
verb, InputTriggerPick.action reports it, ArbitrateKey gains 'tab', and
the keymap intercepts Tab only while a drill row is highlighted.

Covered by controller arbitration, MenuView chevron routing, the
ui-reference verb split, a keymap Tab-passthrough spec, and a real-
browser e2e driving all three gestures; menu golden refreshed for the
chevron and the fixture directory.
2026-08-24 16:45:34 +08:00
Dudu-0223
32d7092c84 Merge remote-tracking branch 'origin/master' into codex/pr-365-fixes 2026-08-24 16:33:31 +08:00
Dudu-0223
a268aada8c fix(spill-local): harden startup cleanup 2026-08-24 16:33:15 +08:00
Hypatia May
4db19c352e docs(token-meter): distinguish projection and measurement folds 2026-08-24 16:24:13 +08:00
Hypatia May
58a0e450b3 perf(token-meter): commit the surface fold in place through a plan/commit pair
foldSurfaceTokens rebuilt the priced surface on every surface event: an
append allocated [...nodes, node] and a replacement copied the whole
array before splicing, charging every well-formed event O(surface) for
an atomicity property only malformed events need. Benchmarks put the
copy at ~99.9% of an append's cost (100µs at a 50k-node surface vs
0.1µs for pricing) with O(S²) accumulation over a session, inside the
synchronous session/event publication path.

Split the fold into the session core's planSurfaceEvent/applySurfacePlan
shape: planSurfaceTokens performs every fallible step against the
read-only surface, commitSurfaceTokens applies the plan in place and is
infallible by construction. _foldEvent plans first, runs the remaining
fallible anchor validation, and only then commits, so retry identity is
preserved by ordering instead of by allocation. Appends drop to
amortized O(1) (100.3µs -> 1.9µs at 50k nodes); replacements keep their
O(surface) findIndex but stop paying the extra full copy (21µs -> 4.2µs).

A new regression test pins the one hazard this introduces: an event
whose surface plan is valid but whose later anchor validation throws
must leave the priced surface and running total uncommitted across
repeated failures.
2026-08-24 16:24:12 +08:00
creatixchu
ebb8010b56 Merge remote-tracking branch 'origin/master' into worktree/2885-image-compression
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/README.md
#	packages/llm/llm-deepseek/README.zh.md
#	packages/llm/llm-deepseek/src/adapter.ts
2026-08-24 16:23:34 +08:00
_Kerman
5fe36b513e fix(ci): restore acp snapshot transcripts and windows coverage gate ordering
- The base-mounted projection cache's write-behind forces session-log
  flushes at cache-chosen times, splitting packed chunk rows and collapsing
  the persistence window the keyless acp transcripts pin. ACP exposes no
  session-listing surface, so the automation profile disables the base row,
  restoring the pre-base behavior the fixtures were recorded against.
- The windows coverage lane runs suites that read built lib/ output (the
  webworker-packer image tests) and raced the build gate's tsdown writes
  against a partial tree; every coverage gate now waits for the build gate.
2026-08-24 16:17:19 +08:00
CreatixChu
6ac321d990 Merge pull request #2990 from deepseek-harness/worktree/model-readable-image-paths
feat(attachment): expose model-readable image paths
2026-08-24 16:14:55 +08:00
creatixchu
4863890535 fix(attachment): route image encoding by alpha over shared quality ladders
Delete the 5-bit colour-count classifier and palette PNG branch that
misrouted high-frequency photographic JPEGs (issue #2885 images 23/24)
into an encoder 100x slower with 4x larger output. Both normalization
and request-image encoding now route by the decoded alpha fact alone:
opaque sources down a JPEG ladder and alpha sources down a WebP
effort-0 ladder, each at qualities 85/75/60. Byte budgets become ladder
targets: the downscale retry loop is gone and a ladder-exhausted encode
keeps its smallest output, while provider byte caps stay enforced at
the transmitting route. Request transforms move to request-image-v5.
2026-08-24 16:14:32 +08:00
Yichen Jiang
836be779e9 Merge pull request #3004 from deepseek-harness/worktree/3002-restore-deep-diving-copy
fix(client): restore branded running copy
2026-08-24 16:14:10 +08:00
Yichen Jiang
d61ba08685 fix(client): restore branded running copy 2026-08-24 16:04:17 +08:00
creatixchu
7bad88206b test(llm): 覆盖执行环境图片路径解析 2026-08-24 16:01:49 +08:00
creatixchu
5c799a9520 fix(attachment): 修正 Windows 只读发布顺序 2026-08-24 15:44:42 +08:00
Dudu-0223
545d177911 fix(spill-local): make startup cleanup race-safe 2026-08-24 15:36:51 +08:00
Dudu-0223
dbb3bcca8e test(spill-local): v8-ignore the two race-only sweep catch branches
The exact-shape fix added two filesystem-failure catch branches that only
fire on a race/permission fault the caller already guards against (the
session-dir readdir after an isDirectory() check, and the discovered-root
rmdir after the root was observed empty). Neither is deterministically
reproducible in-process, so tag both with the same reasoned v8 ignore the
sibling catch blocks already use, restoring per-file 100% coverage and the
symmetry between the parallel rmdir handlers.
2026-08-24 15:36:51 +08:00
Dudu-0223
c6a4de6207 fix(spill-local): exact-shape root/session matching and prune discovered roots
Tighten the startup sweep to backend-generated name shapes and fix the tests
that had drifted from the SweepRoot-based API:

- Match roots by the exact `dsh-spill-<6>` mkdtemp shape and session dirs by
  `session-<12 hex>` (DEFAULT_ROOT_RE / SESSION_DIR_RE), replacing loose
  startsWith checks so foreign or fixture-shaped directories are never swept.
- Carry `SweepRoot { path, pruneWhenEmpty }` through SweepOptions so a discovered
  prior-default root is removed once emptied while the active root is never
  pruned; lstat each session entry so a symlinked session dir is not followed.
- Fix the tests to the SweepRoot API: import SweepRoot, correct the gatherRoots
  override return shapes, build discovery fixtures with the real mkdtemp shape,
  and route the warn-wiring test through a deterministic failure path.
2026-08-24 15:36:51 +08:00
Dudu-0223
2f430f2fbd feat(spill-local): one-shot startup cleanup for local spill files
The local spill backend never reclaimed its files, so configured roots
grew without bound and default per-process dsh-spill-* temp roots piled
up across runs. Immediate deletion is unsafe because persisted, resumed,
and forked sessions may still reference an older locator.

Add a fiber-owned, best-effort sweep that runs once after activation
(never delaying availability, awaited on disposal): it deletes regular
files older than cleanupPeriodDays (default 30; 0 disables) across the
configured root and prior default temp roots, prunes emptied dirs, and
skips symlinks/unknown entries. Every filesystem failure is contained
and logged, so the sweep cannot fail activation or a concurrent write.
2026-08-24 15:36:51 +08:00
imccyu
15ddb2edc4 test(web): wait for stable preview onboarding 2026-08-24 15:28:14 +08:00
_Kerman
334dd53c92 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2781
# Conflicts:
#	.agents/notes/proposed/architecture/2026-07-28-storage-root-and-derived-medium-recovery.i18n.yaml
#	.agents/notes/proposed/architecture/2026-07-28-storage-root-and-derived-medium-recovery.md
#	.agents/notes/proposed/architecture/2026-07-28-storage-root-and-derived-medium-recovery.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/session-controller/tests/session-cold.host.spec.ts
#	packages/bundle/web-app/package.json
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/session/session-projection-cache/package.json
2026-08-24 15:13:10 +08:00
imccyu
1a36d5c6f5 style(client): stack local build metadata 2026-08-24 15:08:14 +08:00
Turtle
720c5c247c fix(client): localize local build banner 2026-08-24 15:04:01 +08:00
Turtle
17bde3f5be feat: label local build banner 2026-08-24 15:04:01 +08:00
Turtle
749c4ef93e fix: sample dev web metadata at startup 2026-08-24 15:04:01 +08:00
Turtle
b636b01092 test: update client build fixtures 2026-08-24 15:04:01 +08:00
Turtle
65a8d6be1b feat(client): show build version in local banner 2026-08-24 15:04:00 +08:00
creatixchu
b5182e2ac2 Merge remote-tracking branch 'origin/master' into worktree/model-readable-image-paths 2026-08-24 14:57:00 +08:00
Yichen Jiang
9a6845828a Merge remote-tracking branch 'origin/master' into worktree/fix-system-prompt-order 2026-08-24 14:54:55 +08:00
creatixchu
558f08780c refactor(attachment): 分离宿主位置与模型访问路径 2026-08-24 14:51:03 +08:00
Chinesezjc
e0249fba1c Merge pull request #3000 from deepseek-harness/revert-2926-worktree/optimize-windows-ci-20260822
Revert "perf(ci): shorten native Windows coverage critical path"
2026-08-24 14:40:33 +08:00
Chinesezjc
cd6941d5d7 Revert "perf(ci): shorten native Windows coverage critical path" 2026-08-24 14:39:56 +08:00
Dudu-0223
470af0a404 fix(web): preserve preview fetch composition 2026-08-24 14:18:15 +08:00
Yichen Jiang
25428f8e08 fix(system-prompt): preserve downstream section order 2026-08-24 14:12:36 +08:00
Dudu-0223
14e4d3f078 docs(web): document shipped fetch policy 2026-08-24 13:40:08 +08:00
Yichen Jiang
fdf60301f2 fix(system-prompt): stabilize workflow section order 2026-08-24 13:38:34 +08:00
Dudu-0223
9fbcea099b feat(web): require one-shot fetch approval 2026-08-24 13:38:06 +08:00
creatixchu
7f4cf99eeb 修正图片路径访问与只读存储 2026-08-24 13:11:04 +08:00
Dudu-0223
2fbe199a1c test(web): permit loopback spill fixture 2026-08-24 12:35:32 +08:00
creatixchu
bd4e4173e7 feat(attachment): expose model-readable image paths 2026-08-24 12:08:26 +08:00
Yichen Jiang
6f17d10102 test(web): finish the textarea-locator sweep after the architecture merge
preview-boot's hero wait was master's new textarea:enabled locator (the
conv refactor predates the Lexical composer); migrate it to the
data-composer-input surface like every other lane. Drop the unnecessary
DOMRect assertion oxlint flagged on the new Range stub.
2026-08-24 12:06:48 +08:00
Dudu-0223
c406560452 test(web): permit loopback integration fixture 2026-08-24 12:05:17 +08:00
creatixchu
6434b894c2 chore(attachment): start issue-2885 image codec work 2026-08-24 12:02:38 +08:00
Dudu-0223
9d5fa7a593 test(web): snapshot blocked loopback fetch 2026-08-24 11:57:27 +08:00
Dudu-0223
b2219bba63 fix(web): block non-public fetch destinations 2026-08-24 11:47:08 +08:00
Yichen Jiang
04caa1248d test(client): close the merged-architecture coverage and jsdom gaps
- user-text.tsx enters ui-primitives' per-file 100% gate: replace three
  regex-guaranteed impossible ?? fallbacks with asserted captures, make
  the precedence sort a branch-free rank comparator, and pin the nested
  recall-label ordering and the no-basename quoted-path fallback with
  tests (100% statements/branches/functions locally).
- assembled-boot stubs Range.prototype.getBoundingClientRect: jsdom has
  no Range geometry, and Lexical's selection reveal now reaches it in the
  built-graph lane after the architecture merge (the unhandled TypeError
  behind command-image-envelope and preview-boot).
2026-08-24 11:39:34 +08:00
lsdsjy
e06625d202 fix(web): switch running drafts to Send 2026-08-24 11:37:48 +08:00
Yichen Jiang
5f94875a3d Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614 2026-08-24 11:28:59 +08:00
Turtle
528815dd1e Merge pull request #2860 from deepseek-harness/turtle/warn-torn-jsonl-recovery
fix(jsonl): warn when repairing torn tails
2026-08-24 11:15:05 +08:00
Yichen Jiang
f26936d695 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	.agents/notes/archived/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.i18n.yaml
#	apps/web/tests/composer-draft-scroll.e2e.ts
#	packages/client/ui-chat/src/client/chat/MessageItem.tsx
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.md
#	packages/client/ui-conversation/README.zh.md
#	packages/client/ui-conversation/package.json
#	packages/client/ui-conversation/src/client/contract/input.ts
#	packages/client/ui-conversation/src/client/contract/slots.ts
#	packages/client/ui-conversation/src/client/input/facade.ts
#	packages/client/ui-conversation/src/client/input/machine.ts
#	packages/client/ui-conversation/src/client/skeleton/InputBar.tsx
#	packages/client/ui-conversation/src/client/skeleton/decorations.ts
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
#	packages/client/ui-conversation/tests/input-machine.client.spec.ts
#	packages/client/ui-conversation/tests/input-reference-submit.client.spec.ts
#	packages/client/ui-conversation/tests/skeleton.client.spec.tsx
#	packages/client/ui-primitives/src/user-text.module.css
#	packages/client/ui-primitives/src/user-text.tsx
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	pnpm-lock.yaml
2026-08-24 11:04:58 +08:00
Yichen Jiang
02d6af9d05 Merge pull request #2864 from deepseek-harness/fix/derive-shipped-preset-root-per-composition
fix(cli): derive the shipped agent-preset root per composition
2026-08-24 10:54:29 +08:00
imccyu
559ac1bfb7 Merge pull request #2967 from deepseek-harness/worktree-webhostfix
feat(webworker): support filesystem watches and confinement
2026-08-24 10:51:44 +08:00
imccyu
ab0f7937ca perf(webworker): index VFS hard links 2026-08-24 10:37:06 +08:00
imccyu
92cac5d291 fix(webworker): close Node compatibility gaps 2026-08-24 10:37:06 +08:00
imccyu
ce1247d953 docs(client): sync injected module graph contract 2026-08-24 10:37:06 +08:00
imccyu
5549b9add5 fix(client): preload injected module factories 2026-08-24 10:37:06 +08:00
imccyu
91b545daf5 fix(webworker): support package inventory resolution 2026-08-24 10:37:05 +08:00
imccyu
8aa222a40d test(web): await subagent history before snapshot 2026-08-24 10:37:05 +08:00
imccyu
be852d4e9b fix(webworker): scope Linux-only CI checks 2026-08-24 10:37:05 +08:00
imccyu
5ad9b128f9 fix(webworker): align filesystem semantics with Node 2026-08-24 10:37:05 +08:00
imccyu
4f80422595 fix(webworker): preserve preview loading sequence 2026-08-24 10:37:05 +08:00
imccyu
14bd300880 fix(webworker): match preview chooser styling 2026-08-24 10:37:05 +08:00
imccyu
e883dc2354 feat(webworker): add selectable preview fixtures 2026-08-24 10:37:04 +08:00
imccyu
181a0e18ef docs(webworker): define the preview example seed 2026-08-24 10:37:04 +08:00
imccyu
8fe9af8db9 feat(webworker): support fs watches and confinement 2026-08-24 10:37:04 +08:00
Yichen Jiang
925eac4b2e Merge remote-tracking branch 'origin/master' into fix/derive-shipped-preset-root-per-composition 2026-08-24 10:36:24 +08:00
imccyu
5f7150b69f Merge pull request #2968 from deepseek-harness/client-tool-view-rendering
refactor: derive Web tool presentation from raw events
2026-08-24 10:33:49 +08:00
_Kerman
04abeddd3e Merge origin/master into xtr/session-format-migration 2026-08-24 10:31:05 +08:00
Yichen Jiang
34a3097317 fix(preview): point the config-tree declaration at the plugin-bundled presets
The worker-preview pack landed on master declaring dsh.configTrees
against apps/cli/config/agent-presets, which this branch moved into
packages/preset/agent-presets/presets. The VFS mount and the worker-side
roster patch keep their paths; only the source directory follows the
move.
2026-08-24 10:29:18 +08:00
imccyu
8fbd1650a3 docs(session): record cold projection composition rule 2026-08-24 10:24:18 +08:00
imccyu
1dd6bf1973 fix(client): localize terminal send presentation 2026-08-24 10:24:18 +08:00
imccyu
bfc145cc7c docs(tools): link terminal presentation markers 2026-08-24 10:24:18 +08:00
imccyu
d9a071340f fix(client): preserve editor running diffs 2026-08-24 10:24:18 +08:00
imccyu
a99516c330 refactor(client): derive deliverables from mutation calls 2026-08-24 10:24:17 +08:00
imccyu
a4c296f9fe refactor(client): derive tool cards from raw events 2026-08-24 10:24:17 +08:00
imccyu
a42c0b523a refactor(session): stream raw tool events 2026-08-24 10:24:17 +08:00
imccyu
64c9e4a22c docs: define client-derived tool presentation 2026-08-24 10:24:16 +08:00
Yichen Jiang
05daf25e10 test(llm): pin includeShippedRoot off in the inventory roster
The spec landed on master before the roster gained the plugin-bundled
shipped root; its empty-roots harness now opts out explicitly, matching
every other exact-roster suite.
2026-08-24 10:17:11 +08:00
Yichen Jiang
91e30d6f82 Merge remote-tracking branch 'origin/master' into fix/derive-shipped-preset-root-per-composition
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md
#	.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md
#	scripts/check-workspace-constraints.ts
#	scripts/rescope-vendor.ts
2026-08-24 10:11:11 +08:00
Magolor
4b7b039129 Merge pull request #2777 from deepseek-harness/fix/minimal-disable-goal-plugin
fix: 在 Minimal preset 中禁用 /goal
2026-08-24 09:18:48 +08:00
Tianyi Cui
51f274d7a4 Merge pull request #2972 from deepseek-harness/worktree/upgrade-pi-ai-0.84.2
chore(llm): bump pi-ai to 0.84.2
2026-08-24 02:22:50 +08:00
Tianyi Cui
c4f10577b5 test(llm): cover pi-ai upgrade compatibility 2026-08-24 01:57:18 +08:00
Tianyi Cui
76c3bf5f6f Merge origin/master into worktree/upgrade-pi-ai-0.84.2 2026-08-24 01:38:25 +08:00
Tianyi Cui
114846b4ca test(web): refresh pi-ai provider catalog snapshots 2026-08-24 01:37:51 +08:00
imccyu
0b11356d05 Merge pull request #2970 from deepseek-harness/worktree-convrefactor
refactor(client): remove cross-package value dependencies
2026-08-24 01:36:01 +08:00
imccyu
3e942e5e21 docs(client): document web architecture 2026-08-24 01:27:48 +08:00
Tianyi Cui
44bd9182ff chore(llm): bump pi-ai to 0.84.2 2026-08-24 01:19:01 +08:00
imccyu
78b8cc731e docs(client): preserve opaque context fallback 2026-08-24 00:54:24 +08:00
imccyu
e5395b36af refactor(client): remove directory error re-export 2026-08-24 00:54:17 +08:00
imccyu
2a597bea80 test(pwsh): allow Windows shell restart latency 2026-08-23 23:58:42 +08:00
imccyu
d7db423d5b docs(client): restore boundary rationale 2026-08-23 23:54:06 +08:00
imccyu
b19752fda4 fix(client): validate exact external specifiers 2026-08-23 23:54:03 +08:00
imccyu
cad09dbcb7 test(ci): include inspect catalog in gate order 2026-08-23 23:37:49 +08:00
imccyu
efda53c189 test(client): update bundle purity expectation 2026-08-23 23:37:45 +08:00
imccyu
177142aa4a test(cordis): refresh inspect catalog snapshot 2026-08-23 23:29:54 +08:00
imccyu
39ebc860df docs: refresh module dependency graph 2026-08-23 23:29:50 +08:00
imccyu
3e9c5d1bc9 refactor(util): remove unreachable path fallback 2026-08-23 23:29:46 +08:00
imccyu
e791147203 test(client): cover malformed browse errors 2026-08-23 23:29:42 +08:00
imccyu
e47c897f5f refactor(session): localize token delta detection 2026-08-23 23:29:38 +08:00
imccyu
a050b3d4f1 fix(client): gate the inspect catalog 2026-08-23 23:06:39 +08:00
imccyu
d80419f4ea chore(client): enforce value dependency policy 2026-08-23 23:06:39 +08:00
imccyu
81c922c7be chore(client): remove feature module externals 2026-08-23 23:06:38 +08:00
imccyu
997ad27a60 refactor(client): remove compatibility imports 2026-08-23 23:06:38 +08:00
imccyu
3d1c0af60b refactor(client): keep feature helpers with consumers 2026-08-23 23:06:38 +08:00
imccyu
9f2f498e7c refactor(client): localize conversation projections 2026-08-23 23:05:31 +08:00
imccyu
85427aea9e refactor(client): move shared primitives to static packages 2026-08-23 23:02:33 +08:00
imccyu
64bb0427f9 feat(util): add workspace path helpers 2026-08-23 23:01:48 +08:00
Tianyi Cui
11b69490bf Merge pull request #2964 from deepseek-harness/worktree/localize-ui-strings-gate
fix(client): localize UI copy and gate regressions
2026-08-23 22:56:29 +08:00
Tianyi Cui
2a72de67d1 fix(ci): preserve cross-platform lint suppressions 2026-08-23 21:48:32 +08:00
Tianyi Cui
ac4ade3aaa fix(client): address localization review findings 2026-08-23 21:22:41 +08:00
Tianyi Cui
174c672f45 Merge remote-tracking branch 'origin/master' into worktree/localize-ui-strings-gate 2026-08-23 20:15:02 +08:00
Tianyi Cui
e1a5942c9a fix(client): satisfy UI localization CI gates 2026-08-23 20:14:53 +08:00
Tianyi Cui
c9b1c1b0b0 Merge pull request #2960 from deepseek-harness/worktree/fix-master-sandbox-ci-20260823
fix(ci): restore Sandbox master checks
2026-08-23 19:50:25 +08:00
Tianyi Cui
b6b08beb0d test(sandbox): derive packed workspace closure
The Landlock packed-install rehearsal packed a hand-maintained list of
workspace tarballs. When dsh-llm gained the dsh-util-crypto runtime
dependency, the list stayed stale and npm tried to fetch the unpublished
release candidate from the public registry, failing both Linux master jobs
with E404 before confinement ran.

Read the current pnpm workspace inventory and traverse dependencies,
optionalDependencies, and required peerDependencies from the packed test
roots. Verify package identities, fail loudly on unresolved workspace names,
sort the closure deterministically, and leave native-family packages to the
existing mode-preserving native packer.

Cover runtime traversal, optional-peer exclusion, native filtering, and
invalid workspace metadata. Remove the obsolete vendoring exact edit for the
deleted manual list so future runtime workspace additions are included by
their manifests instead of becoming post-merge CI failures.
2026-08-23 19:24:50 +08:00
Tianyi Cui
4f3a47d792 fix(terminal-bash): handle terminal protocol replies
Unix PowerShell emits cursor-position requests while PSReadLine starts and
redraws prompts. The subprocess PTY is only a transport, so those requests
went unanswered. Startup could then accept the dsh> literal echoed from its
setup source as a rendered prompt, and later sends were lost or clipped.

Feed raw PTY output into a zero-scrollback @xterm/headless state machine and
write generated replies through the provider-owned terminal handle. Drain
replies before caller input, repeat foreground inspection when terminal
activity races the sample, and retain send ownership until parser and reply
work quiesce. Coalesce raw chunks behind one active parser write so large
Windows output cannot create thousands of queued parse callbacks.

Publish pwsh only from backend stdin_read evidence and start one timeoutMs
deadline before the complete startup retry loop, so inferred-idle follow-ups
cannot reset the bound. Dispose the emulator when the
terminal or cleanup fails. Document the fail-loud ConstrainedLanguage path
and add focused coverage for split queries, reply ordering, foreground
resampling, failure containment, batching, timeout, and disposal.
2026-08-23 19:24:50 +08:00
Tianyi Cui
9ebda8755e Merge remote-tracking branch 'origin/master' into worktree/localize-ui-strings-gate
# Conflicts:
#	packages/client/ui-chat/src/client/chat/AssistantMarkdown.tsx
#	packages/client/ui-chat/src/client/chat/CompactionItem.tsx
#	packages/client/ui-conversation/src/client/locales.ts
#	packages/client/ui-renderer/src/client/app.tsx
#	packages/client/ui-renderer/src/client/index.ts
#	packages/client/ui-renderer/tests/ui-renderer.client.spec.tsx
#	packages/client/ui-tool/src/client/tool/models/tool-call-model.ts
#	packages/client/ui-trajectory/src/client/trajectory-record.ts
#	packages/client/ui-trajectory/src/client/trajectory-snapshot-builder.ts
#	packages/client/ui-trajectory/tests/views.client.spec.tsx
#	packages/client/ui-workspace/src/client/tree.ts
2026-08-23 18:34:42 +08:00
Tianyi Cui
3c10f5d2d3 fix(client): route UI copy through locale 2026-08-23 17:31:37 +08:00
Tianyi Cui
3c1c6a89b1 test(python): gate installed runtime wheels across release targets (#2953)
* test(python): exercise installed wheels as black boxes

Add an installed-wheel mode that refuses source/editable imports, repository working directories, mismatched SDK/runtime versions, unpinned runtime dependencies, and executables outside the installed runtime distribution. The mode resolves the wheel-owned executable itself, so callers cannot accidentally prove an explicit checkout artifact.

Add a real-API scenario that drives two tool-using turns through the public synchronous SDK, verifies the file bytes outside the agent, checks completed turn/tool events and persistence, and projects provider failures without retaining credential-bearing error text. The existing deterministic scenario set remains the keyless behavior oracle.

Refs #2952.

* ci(python): require installed-wheel checks on every release target

Move the complete deterministic runtime scenarios behind construction and clean installation of the SDK and matching runtime wheels. Each native leg runs outside the checkout with source-resolution environment variables removed; Linux manylinux smokes assert the same installed provenance.

Expand the required pull-request call from Linux x64 to Linux x64, Linux arm64, and macOS arm64. Trusted heads receive only DEEPSEEK_API_KEY_EXTERNAL for a fail-loud live two-turn smoke on each carrier, while fork and Dependabot heads retain the full keyless path without exposing secrets.

Pin the reusable secret declaration, matrix call, aggregate dependency, untrusted-head condition, and live/keyless commands in the workflow contract test.

Refs #2952.

* docs(testing): make installed wheels the Python CI authority

Record the clean-wheel provenance boundary, complete keyless scenario set, trusted real-API contract, secret handling, and three-target required topology in a new implemented testing decision. Update the SEA distribution and portable-CI authorities plus the Python contributor reference to describe the same current state.

Archive the fully superseded Linux-x64-only decision after consolidating its rationale and alternatives into the new owner. Preserve its bilingual triplet as a sealed historical snapshot and redirect every active current-state reference.

Refs #2952.
2026-08-23 16:53:55 +08:00
imccyu
9f9f160854 Merge pull request #2911 from deepseek-harness/client-session-conversation-chat
refactor(client): split Session Conversation and Chat ownership
2026-08-23 16:36:08 +08:00
imccyu
e4fb885f3e chore(client): mark mirrored interaction lifecycle 2026-08-23 16:28:20 +08:00
imccyu
7402ce3fc7 fix(client): settle interactions during plugin teardown 2026-08-23 16:28:20 +08:00
imccyu
61ee176973 docs(client): align split ownership contracts 2026-08-23 16:28:20 +08:00
imccyu
689644463d fix(client): keep conversation updates incremental 2026-08-23 16:28:20 +08:00
imccyu
a40f30a4a2 fix(client): preserve scoped UI lifecycles 2026-08-23 16:28:20 +08:00
imccyu
956a72ffe0 fix(client): restore injected workspace dependencies 2026-08-23 16:28:19 +08:00
imccyu
7ddccac0d4 fix(client): remove unused workspace dev dependencies 2026-08-23 16:28:19 +08:00
imccyu
0b6269b50c fixup! refactor(interaction): move Approval and Question into UI owners 2026-08-23 16:28:19 +08:00
imccyu
828cd3f7b1 fix(client): avoid cyclic UI service type imports 2026-08-23 16:28:19 +08:00
imccyu
dc92793f10 fix(client): align domain split with repository gates 2026-08-23 16:28:19 +08:00
imccyu
f5767ba15e fixup! docs(client): document split ownership 2026-08-23 16:28:18 +08:00
imccyu
55dd6320d2 fixup! refactor(interaction): move Approval and Question into UI owners 2026-08-23 16:28:18 +08:00
imccyu
f13fb4daeb docs(client): document split ownership 2026-08-23 16:28:18 +08:00
imccyu
3a23185edb chore(client): align split package graph 2026-08-23 16:28:18 +08:00
imccyu
be531688f3 refactor(client): migrate consumers and remove Runtime 2026-08-23 16:28:18 +08:00
imccyu
049170c6d0 refactor(interaction): move Approval and Question into UI owners 2026-08-23 16:28:17 +08:00
imccyu
c7d8e32aec refactor(conversation): separate Conversation, Chat, and Trajectory owners 2026-08-23 16:28:17 +08:00
imccyu
d231c8777a refactor(ui): add Session and Workspace React adapters 2026-08-23 16:28:16 +08:00
imccyu
1b535f611c refactor(client): extract Store and renderer Slot infrastructure 2026-08-23 16:28:16 +08:00
imccyu
0ea9a456c0 refactor(workspace): move Client ownership into Workspace Controller 2026-08-23 16:28:16 +08:00
imccyu
956730a5fb refactor(session): move Client ownership into Session Controller 2026-08-23 16:28:16 +08:00
imccyu
291a43819a test(web): tolerate responsive transcript reflow 2026-08-23 16:27:09 +08:00
imccyu
8f919cb9ac test: ignore defensive Remote branches 2026-08-23 16:16:06 +08:00
imccyu
c5efa5ce9c docs(typert): sync Gateway type excerpt 2026-08-23 16:16:06 +08:00
imccyu
d020f60911 docs(typert): refresh Remote output contract 2026-08-23 16:16:06 +08:00
imccyu
2d974b187e perf(api-gateway): skip Remote output decoding 2026-08-23 16:16:06 +08:00
imccyu
4326dd4bca fix(api-session): preserve presenter fast path 2026-08-23 16:16:06 +08:00
imccyu
d34be03f7b fix: skip get proxy 2026-08-23 16:16:05 +08:00
imccyu
08d6a215c9 perf(api-session): reuse live tool call arguments 2026-08-23 16:16:05 +08:00
imccyu
4ebd9fad79 test(web): avoid unstable subagent hover 2026-08-23 16:16:05 +08:00
imccyu
24a610db74 fix(api): preserve migrated transport semantics 2026-08-23 16:16:05 +08:00
imccyu
3728c0b13e test(client): cover reconnect and question scope paths 2026-08-23 16:16:05 +08:00
imccyu
18cf84d133 fix(client): materialize Agent scopes before list baseline 2026-08-23 16:16:05 +08:00
imccyu
d319a0773b docs: refresh module graph after rebase 2026-08-23 16:16:05 +08:00
imccyu
ddcab34c0e test(api): close stream transport coverage gaps 2026-08-23 16:16:05 +08:00
imccyu
6a3f35e248 docs: refresh generated client metadata 2026-08-23 16:16:04 +08:00
imccyu
f494caca45 refactor(client): move pending interactions out of Session state 2026-08-23 16:16:04 +08:00
imccyu
003fc024c2 docs: refresh module graph 2026-08-23 16:16:04 +08:00
imccyu
30f43b9870 test(api-session): bind history probes to follow cursors 2026-08-23 16:16:04 +08:00
imccyu
7d21611391 test(api-gateway): cover clientless Remote event replay 2026-08-23 16:16:04 +08:00
imccyu
a49b265f88 docs: synchronize controller transport documentation 2026-08-23 16:16:04 +08:00
imccyu
e38982adc8 fix(client): satisfy stream lifecycle contracts 2026-08-23 16:16:04 +08:00
imccyu
9eb3747ffc fix(user-questions): bridge scoped request events 2026-08-23 16:16:03 +08:00
imccyu
016be7d533 fix(interaction): type Agent-scoped request events 2026-08-23 16:16:03 +08:00
imccyu
9ff067dfbd fix(client-runtime): close journals with session scopes 2026-08-23 16:16:03 +08:00
imccyu
2b2a45f30c fix(client-connection): release stream ownership on unload 2026-08-23 16:16:03 +08:00
imccyu
5d17b6798d fix(api-gateway): retry journal pages after reconnect 2026-08-23 16:16:03 +08:00
imccyu
1e0e827425 refactor(client-runtime): remove Session interaction consumers 2026-08-23 16:16:03 +08:00
imccyu
7f908c1bb4 fix(user-questions): normalize in-flight aborts 2026-08-23 16:16:03 +08:00
imccyu
639dcef5d8 refactor(api-session): remove interaction transport 2026-08-23 16:16:03 +08:00
imccyu
e8ede58603 fix(api-session): bind history pages to follow cursor 2026-08-23 16:16:03 +08:00
imccyu
9b1069c234 docs: document controller Remote transport 2026-08-23 16:16:03 +08:00
imccyu
54d739cf53 chore(api): align controller assembly and package graph 2026-08-23 16:16:02 +08:00
imccyu
dcddaa1a6e refactor(client): replace legacy Host event carriers 2026-08-23 16:16:02 +08:00
imccyu
ae25df3ac6 refactor(workspace): move APIs into Workspace Controller 2026-08-23 16:16:02 +08:00
imccyu
d26acfa2e3 refactor(session): move APIs into Session Controller 2026-08-23 16:16:02 +08:00
imccyu
3d6d595d79 feat(api-gateway): unify Remote streams and events 2026-08-23 16:16:01 +08:00
Tianyi Cui
4ba47e665b Merge pull request #2119 from deepseek-harness/worktree/gate-package-subsystem-pages
Require package groups to declare subsystem documentation
2026-08-23 16:14:47 +08:00
Tianyi Cui
5e0fd757e1 Merge pull request #2460 from deepseek-harness/test/translation-prompt-snapshot-fixtures
test: decouple the translation prompt snapshot from live documents
2026-08-23 16:13:58 +08:00
Tianyi Cui
1d46946963 test(docs): use a block cleanup callback 2026-08-23 16:02:32 +08:00
Tianyi Cui
97938582e5 test(docs): avoid duplicate fixture cleanup 2026-08-23 15:55:46 +08:00
Tianyi Cui
4bc6f4bdf7 Merge origin/master into worktree/gate-package-subsystem-pages 2026-08-23 15:47:32 +08:00
Tianyi Cui
ce2de363dd Merge latest master into test/translation-prompt-snapshot-fixtures 2026-08-23 15:41:54 +08:00
Tianyi Cui
947205fb80 Merge pull request #2956 from deepseek-harness/worktree/win32-utf16-nul-truncation-20260823
fix(directory-picker-native): stop truncating Win32 UTF-16 paths at U+XX00
2026-08-23 14:28:53 +08:00
Tianyi Cui
56f0297321 docs(agent-notes): record the Win32 UTF-16 NUL-scan fix 2026-08-23 14:22:03 +08:00
ericcaiwx-star
9a2217b74a test(directory-picker-win32): use a synthetic path in the UTF-16 fixture
The U+5F00 case only needs that code unit in the buffer. A real-looking user desktop path does not belong in a public fixture.
2026-08-23 14:08:39 +08:00
ericcaiwx-star
51c242749a fix(directory-picker-native): stop truncating Win32 UTF-16 paths at U+XX00
readUtf16 treated any zero low byte as NUL, so BMP characters such as 开 (U+5F00) cut the folder-picker path in half.
2026-08-23 13:56:48 +08:00
Tianyi Cui
b7e16fdaeb Merge pull request #2954 from deepseek-harness/worktree/remove-openai-yml
chore: remove openai.yaml files
2026-08-23 13:22:09 +08:00
Tianyi Cui
8c420de301 chore: remove OpenAI skill metadata 2026-08-23 13:14:41 +08:00
Turtle
cc8ea70dc0 Merge pull request #2560 from deepseek-harness/codex/add-security-policy
docs: add bilingual experimental safety notice
2026-08-23 11:10:52 +08:00
Tianyi Cui
92f8fb6c4a Merge pull request #2948 from deepseek-harness/worktree/unify-dsh-launch-profiles-reviewable-20260823
feat: unify application launch under dsh profiles
2026-08-23 11:10:27 +08:00
Tianyi Cui
fd814589fb refactor(profiles): make module HMR opt-in
Move the shared module-reload policy into dsh-base by inserting its HMR row disabled, then remove the redundant disabled overrides from Web, headless, SDK, and ACP. No shipped profile enables server module reload; live profile patch watching continues through the launcher-owned config-only fallback, and browser client HMR remains a separate mechanism.

A later profile layer can opt into source-module reload explicitly with disabled: false while retaining the base root configuration. Composition tests cover every shipped mode and the explicit enable path, and the bundle references plus launcher Agent Notes document the resulting ownership and safety rationale.
2026-08-23 10:59:01 +08:00
Tianyi Cui
2eea02dae3 ci: bound profile e2e subprocess fan-out
Set DSH_E2E_MAX_WORKERS=4 for the credentialed e2e workflow and pin that environment contract in the workflow test. Profile-launched SDK and ACP scenarios each boot a complete subprocess tree, so the previous file-level fan-out could multiply process and provider pressure far beyond the runner's useful concurrency.

The bound changes scheduling only: every e2e file still runs, the Vitest configuration retains its explicit override knob, and local callers can choose a different positive worker count when their resources allow it.
2026-08-23 10:59:01 +08:00
Tianyi Cui
fdac6cffcb test: refresh profile migration catalogs and built smokes
Regenerate the configuration catalog and module graph after replacing standalone application packages with dsh profile bundles and renaming the private Python carrier. Update built-bin coverage to launch the shipped sdk and acp profiles, assert retired bins stay absent, and keep the Web golden text aligned with the same assembled runtime.

Clarify that headless is a startup profile whose patches freeze after boot. This commit is projection and verification work: it contains no application implementation, and every generated document is produced from source committed earlier in the series.
2026-08-23 10:59:01 +08:00
Tianyi Cui
32c32932f9 chore(repo): wire profile apps and the renamed runtime through builds
Update workspace manifests, the lockfile, Host project references, Knip inputs, package constraints, vendoring rewrites, and Python runtime build/smoke scripts for sdk-app, acp-app, and @deepseek-ai/dsh-sdk-python-runtime. Add the ACP hook packages to the dsh dependency closure so installed profile materialization resolves the same plugins as source workspaces.

Keep Python distribution outputs deliberately unchanged: the wheel modules, executable names, and smoke targets retain their public identities even though their private npm carrier moved. Constraint fixtures pin the new package locations and catch missing application dependencies on every platform.
2026-08-23 10:59:01 +08:00
Tianyi Cui
3b33ca058f chore(repo): enforce dsh as the only Node application launcher
Add verify-application-entrypoints to the top-level gate graph. It inventories executable sources and package bins across apps, packages, and examples; rejects unclassified launchers including root-level js/mjs/cjs/ts files; and permits only the dsh CLI plus the explicitly private Python runtime carrier exception.

Update repository, architecture, CLI, and naming records to state the same rule: Node consumers select a dsh profile instead of invoking application-package bins, and no compatibility aliases remain. Fixtures prove both allowed classifications and representative escape attempts, making the architectural rule mechanically enforceable.
2026-08-23 10:59:01 +08:00
Tianyi Cui
a6447db01c refactor(sdk): name the private Python runtime carrier explicitly
Rename the relocated npm workspace to @deepseek-ai/dsh-sdk-python-runtime and the runnable example to python-sdk-agent, then update every owning English/Chinese document, test, and packaged-runtime reference. Remove the obsolete standalone bin while retaining the carrier entrypoints used to assemble the wheel runtime.

This is intentionally a naming and ownership change, not a Python SDK migration. The public deepseek_harness_sdk and deepseek_harness_runtime module, wheel, executable, environment, and wire behavior remain unchanged. Documentation records that this private carrier is the temporary sole non-dsh application exception and will move to profile launch later.
2026-08-23 10:59:01 +08:00
Tianyi Cui
189e7b84e8 test(sdk): refresh dsh-profile SDK transcripts
Regenerate the four TypeScript SDK replay scenarios after switching their subprocess to dsh --profile sdk. The fixtures now project profile-owned runtime context, tool composition, nested-child persistence, and the opt-in DeepSeek session-log acceptance event while preserving each scenario's final response and file assertions.

This commit contains only committed snapshot outputs. Separating them from the SDK implementation keeps protocol/API review focused and makes the model-visible consequences auditable as generated evidence.
2026-08-23 10:59:00 +08:00
Tianyi Cui
3368ddc0ab feat(sdk): launch TypeScript clients through dsh profiles
Replace the TypeScript SDK's public arbitrary command/argv launch surface with the same-version dsh CLI, a named profile, ordered per-launch patches, optional process cwd, and explicit Harness home selection. Installed consumers use the built CLI; clean source checkouts use the package's src/bin.ts through an absolute tsx/esm loader and a source-only patch that omits build-generated Typert loading.

Materialize explicit or inherited environments at spawn time, keep profile-internal patches below caller patches, and resolve every caller-relative path before the child starts. The SDK subagent provider validates its optional CLI and patch files at plugin load and requires an isolated absolute child home.

Treat JSON-RPC initialize as the Loader-owned readiness point: Loader settlement joins entry imports, fiber lifecycle work, and synchronous effect registration, so the server needs no scheduler tick. A delayed profile entry registers a private adapter before initialize resolves, proving caller-supplied plugin routes are visible without fallback.

Update sdk-app ownership, server diagnostics, TypeScript SDK examples, nested-loader coverage, and session-upload replay layering together. The following commit contains only the regenerated SDK transcripts, keeping this API and lifecycle change directly reviewable.
2026-08-23 10:59:00 +08:00
Tianyi Cui
f3402eff58 refactor(sdk): relocate JSON-RPC example and runtime without edits
Move examples/jsonrpc-agent to examples/python-sdk-agent and packages/examples/jsonrpc-demo to packages/sdk/python-runtime while preserving every file byte-for-byte. The directory placement now reflects the example's Python-distribution role and the private runtime carrier's SDK ownership.

This commit deliberately keeps the old package names, commands, configuration, and snapshots inside their new directories. All 42 files are 100% renames; API/profile migration and naming changes follow separately so reviewers do not have to disentangle behavior from filesystem movement.
2026-08-23 10:59:00 +08:00
Tianyi Cui
d52f2900d6 test(acp): refresh profile-launched application transcripts
Regenerate the ACP composition graph and committed replay outputs from the assembled dsh base plus acp-app profile. The updated logs, system prompts, tool schemas, and stdout projections capture the same scenarios after shared plugins move out of the retired demo package and into profile-owned composition.

There is no runtime source in this commit. Keeping generator-owned artifacts separate lets reviewers validate the behavioral migration first, then inspect expected wire/model-visible consequences as a mechanical projection update.
2026-08-23 10:59:00 +08:00
Tianyi Cui
d8dbb8235c refactor(acp): launch automation through the dsh acp profile
Replace the standalone @deepseek-ai/dsh-acp-demo application with dsh --profile acp plus ordered example patches. The shipped acp-app bundle owns only the protocol bridge; every example overlay now targets shared dsh-base rows instead of copying a complete application tree.

Move launcher responsibilities into the ACP snapshot harness: it materializes profile patches, links required packages, reserves stdout for JSON-RPC, observes spawn and drain failures, and escalates process teardown deterministically. The relocated control-surface fixture and the ACP/subagent integration tests now exercise the real CLI/profile path.

This commit contains authored runtime, configuration, and test changes only. Generated transcript and projection churn is deliberately left for the next commit so reviewers can inspect the migration logic without hundreds of expected-output edits.
2026-08-23 10:59:00 +08:00
Tianyi Cui
713b41a946 refactor(acp): relocate control-surface fixtures without edits
Move the ACP control-surface e2e, scripted LLM, and Cordis fixture out of the application package that later commits retire and into the runnable examples/acp-agent test tree. This gives the assembled dsh profile example ownership of its integration fixture.

This commit is intentionally mechanical: all three files retain their exact blobs and appear as 100% renames. Imports and launch behavior are updated only in the subsequent ACP migration commit, keeping reviewer-visible code changes separate from file movement.
2026-08-23 10:59:00 +08:00
Tianyi Cui
47a46e4cca feat(profiles): add the ACP application bundle
Introduce @deepseek-ai/dsh-acp-app as the thin application layer for the built-in acp profile. It contributes only the ACP protocol bridge and profile metadata; dsh-base remains the single owner of shared agent composition, providers, persistence, permissions, and tools.

Wire the bundle into CLI resolution, catalogs, workspace configuration, and built-bin coverage. The focused bundle and startup tests prove that base plus acp-app exposes automation sessions while keeping stdout reserved for ACP JSON-RPC.
2026-08-23 10:59:00 +08:00
Tianyi Cui
a16822944b feat(profiles): add the SDK application bundle
Introduce @deepseek-ai/dsh-sdk-app as the thin application layer for the built-in sdk profile. The bundle contributes the JSON-RPC server and startup-only profile metadata, while dsh-base continues to own the shared agent, provider, persistence, and tool composition.

Publish ctx.appReady from the launcher only after the Loader tree and launcher-owned setup succeed. The stdio lifetime binding leaves stdin unread until the protocol transport claims it and defers EOF exit 0 until readiness commits, so early protocol frames remain buffered and a racing startup failure remains the nonzero process outcome. Fiber disposal cancels both pending lifecycle listeners.

Register the bundle in the CLI resolver closure, generated configuration catalog, workspace graph, and built-bin smoke. Startup tests prove that base plus sdk-app exposes the SDK server without taking ownership of shared runtime plugins; focused and built-bin regressions cover early input, EOF readiness, and startup-error precedence.
2026-08-23 10:59:00 +08:00
Tianyi Cui
2c9da6eb5b feat(cli): make profile patch reload policy explicit
Add a patchReload field to built-in profile metadata and carry it through CLI profile resolution into app boot. Live profiles install the existing patch watcher; startup profiles freeze every layer after boot and apply later edits only on the next launch. Missing or invalid metadata fails before the plugin tree starts.

The implementation keeps reload policy with the profile that owns it instead of inferring behavior from an entrypoint. Unit tests cover metadata validation and both lifecycle modes, while the CLI and app-boot references document which built-ins are live versus startup.
2026-08-23 10:59:00 +08:00
Tianyi Cui
3fa19b3b30 docs: define dsh as the sole Node application launcher
Record the final architecture before any runtime or file-layout changes. The decision makes named dsh profiles the only supported Node application launch path, gives TypeScript SDK callers ordered profile patches for per-launch customization, and retains the packaged Python runtime as an explicitly temporary exception with a later migration obligation.

Keeping this decision in a documentation-only commit gives every following commit one stable naming, lifecycle, and compatibility reference. The English and Chinese notes and their pairing record enter together.
2026-08-23 10:58:59 +08:00
Tianyi Cui
ca53c90a74 Merge pull request #2875 from deepseek-harness/ci/python-release-gray
ci(python): drop PR labeled trigger for python-release dry-run
2026-08-23 10:34:15 +08:00
Tianyi Cui
e73c78fc20 Merge pull request #2946 from deepseek-harness/worktree/webhook-real-e2e
test(webhook): exercise real CLI and model flow
2026-08-23 09:34:53 +08:00
Tianyi Cui
c5311d665d test(webhook): preserve real e2e environment 2026-08-23 01:56:42 +08:00
Tianyi Cui
65509a225b test(webhook): resolve the real CLI rule from examples 2026-08-23 01:48:55 +08:00
Tianyi Cui
3bf5edb5d5 test(webhook): exercise the real CLI and model flow 2026-08-23 01:48:55 +08:00
Tianyi Cui
76a450529d docs(app-boot): clarify patch path anchoring 2026-08-23 01:48:36 +08:00
Tianyi Cui
2b2a8e8240 test(webhook-github): verify chunked overflow response 2026-08-23 01:48:36 +08:00
Tianyi Cui
2f56345439 fix(webhook-github): export provider event types 2026-08-23 01:48:36 +08:00
Tianyi Cui
bf23f59979 fix(webhook): quiet expected disposal cancellation 2026-08-23 01:48:35 +08:00
Tianyi Cui
ea3d0ffcee fix(webhook): preserve the initial model selection 2026-08-23 01:48:35 +08:00
Tianyi Cui
d06f544d8c fix(ci): give Wine Host compiler sufficient heap 2026-08-23 01:48:35 +08:00
Tianyi Cui
9cd383059f fix(build): raise host compiler heap ceiling 2026-08-23 01:48:35 +08:00
Tianyi Cui
01258a6bca fix(webhook): retain checked invariant installer 2026-08-23 01:48:35 +08:00
Tianyi Cui
a1455edeb8 fix(webhook): align patch-relative fixtures and invariants 2026-08-23 01:48:35 +08:00
Tianyi Cui
5f60e50d71 feat(webhook): create workspace sessions from GitHub events 2026-08-23 01:48:35 +08:00
Tianyi Cui
c6c9426efb Merge pull request #2917 from deepseek-harness/worktree/deepseek-session-log-upload
feat(deepseek): upload incremental session logs
2026-08-23 01:23:59 +08:00
Tianyi Cui
9c7e142f79 refactor(session): send canonical events directly 2026-08-23 00:22:41 +08:00
Tianyi Cui
3c0da7bef7 refactor(session): name delivery acceptance event 2026-08-22 23:18:13 +08:00
Tianyi Cui
e0a8050aea docs(deepseek): merge todo event graph updates 2026-08-22 22:55:02 +08:00
Tianyi Cui
8ac8245d39 docs(deepseek): specify session log wire format 2026-08-22 22:55:02 +08:00
Tianyi Cui
1c7af99c80 feat(deepseek): apply session upload review feedback 2026-08-22 22:55:02 +08:00
Tianyi Cui
fe72ab42d1 feat(deepseek): upload incremental session logs 2026-08-22 22:55:02 +08:00
Tianyi Cui
df6e581f58 Merge pull request #2934 from deepseek-harness/worktree/todo-event-ownership-v2-20260822
refactor(todo): move todo event vocabulary to its producer
2026-08-22 22:37:23 +08:00
Tianyi Cui
851eab756e docs(todo): add the owning subsystem reference 2026-08-22 22:22:43 +08:00
Tianyi Cui
b7dca9eb7e fix(todo): validate announced session histories 2026-08-22 22:22:27 +08:00
_Kerman
65295d5b68 docs(session): refresh persistence pairing record 2026-08-22 21:51:49 +08:00
_Kerman
2ba721f799 Merge github/master into xtr/session-format-migration 2026-08-22 21:51:30 +08:00
Tianyi Cui
c41c5f3959 Merge origin/master into todo-event-ownership-v2 2026-08-22 21:12:36 +08:00
Tianyi Cui
59e49458e5 docs(todo): record event ownership 2026-08-22 21:10:02 +08:00
Tianyi Cui
a2b415096d refactor(todo): own todo event vocabulary 2026-08-22 21:10:02 +08:00
Tianyi Cui
d16ab1ac9a Merge pull request #2914 from deepseek-harness/worktree/trim-cot-leakage-20260821
docs: trim CoT leakage from post-purge prose
2026-08-22 20:54:12 +08:00
Tianyi Cui
f964f4078c docs: remove rebase residue and hedge parser-swap regression
- drop the commit-message suffix left at the end of the ui-workspace zh README
- state parser-swap regressions as possible, not guaranteed
2026-08-22 20:35:11 +08:00
Tianyi Cui
750c7f7535 docs: address CoT review findings
- stop attributing the 45-case helper/Node divergence to the path port spec,
  which pins only the Node-facing port to Node
- keep the divergence measurement as provenance, without a dead owner
- fix the path corpus comment so it does not claim divergence from the spec
  that asserts equality
- drop the v2 generation stamp from the cordis mount fallback test
- restate the watcher refusal rationale in current-state terms
- re-record the ui-workspace bilingual pair after rebase
2026-08-22 20:35:11 +08:00
Tianyi Cui
17f85bdbcd docs: trim CoT leakage from post-purge prose
Remove dead design-session citations, change narration, indexical
stamps, and review-adjacent justification found by the
dsh-trim-cot-leakage recall batteries in prose that landed after the
last purge. Bilingual README pairs are re-recorded.
2026-08-22 20:35:11 +08:00
Tianyi Cui
efdafb8610 Merge pull request #2926 from deepseek-harness/worktree/optimize-windows-ci-20260822
perf(ci): shorten native Windows coverage critical path
2026-08-22 20:21:00 +08:00
Tianyi Cui
f39af7bae9 feat(acp): complete standard v1 automation controls (#2928)
* feat(acp): complete standard v1 automation controls

* docs: refresh ACP module graph

* docs: synchronize module graph pair

* docs(acp): explain empty-session durability

* test(acp): align assembled automation coverage

* fix(acp): address lifecycle review findings
2026-08-22 20:19:21 +08:00
Tianyi Cui
35f26699be fix(test): publish lint probes atomically 2026-08-22 20:10:55 +08:00
Tianyi Cui
811788e57a fix(ci): harden optimized Windows gate fixtures 2026-08-22 20:10:55 +08:00
Tianyi Cui
c92c86492d ci: require native Windows aggregate verdict 2026-08-22 20:10:55 +08:00
Tianyi Cui
c8cecd6079 perf(ci): raise isolated Windows coverage fan-out 2026-08-22 20:10:55 +08:00
Tianyi Cui
d39b6c638b perf(test): widen transform corpus sharding 2026-08-22 20:10:55 +08:00
Tianyi Cui
d27a5f2967 perf(test): shard the transform corpus checker 2026-08-22 20:10:55 +08:00
Tianyi Cui
12ad38b234 perf(ci): phase native Windows coverage work 2026-08-22 20:10:55 +08:00
Tianyi Cui
4edf6400ff perf(ci): isolate the transform corpus from coverage 2026-08-22 20:10:54 +08:00
Tianyi Cui
cd6197b428 Merge origin/master into worktree/acp-v1-control 2026-08-22 20:05:11 +08:00
Tianyi Cui
ea6f61f144 feat(deepseek): upload plugin package metadata (#2916)
* feat(deepseek): upload plugin package metadata

* feat(deepseek): apply metadata review feedback

* docs(deepseek): specify request wire extensions

* docs(notes): record inventory cache benchmark

* docs(site): keep DeepSeek wire spec repository-only
2026-08-22 20:03:23 +08:00
Tianyi Cui
52bd3e1805 fix(acp): address lifecycle review findings 2026-08-22 19:44:00 +08:00
Tianyi Cui
e37985f5d5 test(acp): align assembled automation coverage 2026-08-22 19:32:27 +08:00
Tianyi Cui
e0a700baf9 docs(acp): explain empty-session durability 2026-08-22 19:17:06 +08:00
Tianyi Cui
696ec4880e docs: synchronize module graph pair 2026-08-22 19:11:28 +08:00
Tianyi Cui
28c93d8224 docs: refresh ACP module graph 2026-08-22 19:06:37 +08:00
Tianyi Cui
c1764157e7 Merge origin/master into worktree/acp-v1-control 2026-08-22 18:52:58 +08:00
Tianyi Cui
511181684c feat(acp): complete standard v1 automation controls 2026-08-22 18:52:27 +08:00
_Kerman
d375d58889 Merge remote-tracking branch 'origin/xtr/session-format-migration' into xtr/message-tool-call-id 2026-08-22 16:26:47 +08:00
_Kerman
3d660d2db2 ci: raise host TypeScript heap budget 2026-08-22 16:26:31 +08:00
_Kerman
3cd80a6f3f Merge remote-tracking branch 'origin/xtr/session-format-migration' into xtr/message-tool-call-id
# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-20-branded-ids.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-20-branded-ids.md
#	.agents/notes/implemented/architecture/2026-06-20-branded-ids.zh.md
#	packages/fs/tool-fs/tests/read-image.spec.ts
#	packages/llm/llm-deepseek/tests/adapter.e2e.ts
#	packages/llm/llm-deepseek/tests/serialize.spec.ts
#	packages/llm/llm-pi-ai/src/context.ts
#	packages/llm/llm-pi-ai/tests/context.spec.ts
#	packages/llm/llm-pi-ai/tests/convert.spec.ts
#	packages/llm/llm/src/message.ts
#	packages/llm/llm/tests/content.spec.ts
2026-08-22 16:03:48 +08:00
_Kerman
421a577b1c Merge remote-tracking branch 'origin/master' into xtr/session-format-migration
# Conflicts:
#	.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.i18n.yaml
#	.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.md
#	.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.zh.md
#	docs/subsystems/persistence.i18n.yaml
#	docs/subsystems/persistence.md
#	docs/subsystems/persistence.zh.md
#	packages/session/session-persistence-jsonl/src/format.ts
#	packages/session/session-persistence/src/coordinator.ts
2026-08-22 16:01:15 +08:00
Tianyi Cui
e184d26380 Merge pull request #2923 from deepseek-harness/worktree/archive-agent-notes-20260822
docs(notes): archive low-future-value records
2026-08-22 15:45:31 +08:00
Tianyi Cui
198c6c595c docs(notes): archive low-value records 2026-08-22 15:15:08 +08:00
Tianyi Cui
7476b0495d Merge pull request #2922 from deepseek-harness/worktree/trim-cot-skill-followup-20260822
docs: harden chain-of-thought leakage audits
2026-08-22 14:43:09 +08:00
Tianyi Cui
7f93f65ca9 docs: address leakage audit review 2026-08-22 14:34:28 +08:00
Tianyi Cui
d72ff1f49a docs: harden chain-of-thought leakage audits 2026-08-22 13:39:00 +08:00
Tianyi Cui
43c30bf063 Merge pull request #2921 from deepseek-harness/worktree/trim-cot-leakage-20260822
docs: purge residual chain-of-thought leakage
2026-08-22 13:22:50 +08:00
Tianyi Cui
934976732d docs: purge residual chain-of-thought leakage 2026-08-22 13:10:23 +08:00
Tianyi Cui
72d3a80c23 Merge pull request #2915 from deepseek-harness/worktree/deepseek-ci-stability
test(ci): stabilize cross-platform gate baselines
2026-08-22 11:00:26 +08:00
Tianyi Cui
1d6f84ff42 test(ci): apply review feedback 2026-08-22 02:31:11 +08:00
Tianyi Cui
b9869d1e97 test(ci): stabilize cross-platform gate baselines 2026-08-22 01:47:43 +08:00
Turtle
de727c4a1b Merge pull request #2773 from deepseek-harness/codex/simplify-comments-and-docs
docs: remove implementation narration from prose
2026-08-21 22:51:38 +08:00
Turtle
51684bd6be Merge pull request #2901 from deepseek-harness/turtle/add-docs-link
docs: add documentation website link
2026-08-21 22:38:37 +08:00
Turtle
6b3e971805 docs: remove implementation narration from prose 2026-08-21 22:22:23 +08:00
_Kerman
95ed302c9c fix(session): remove unreachable listing branch 2026-08-21 22:08:53 +08:00
pku-xht
d04adbc73c Merge pull request #2714 from deepseek-harness/codex/subprocess-win32-process-primitives
refactor(win32-process): share native process primitives
2026-08-21 21:53:42 +08:00
pku-xht
e6818bd697 Merge commit '4913489a6184d124900273e3a76d595e25d76099' into codex/subprocess-win32-process-primitives
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
2026-08-21 21:42:39 +08:00
imccyu
060070203f Merge pull request #2712 from deepseek-harness/worktree-webworker
Web Worker host runtime with packed VFS image and static preview
2026-08-21 21:14:24 +08:00
imccyu
311aaed2e5 fix(release): align new package versions with the 0.1.1-rc.2 root 2026-08-21 20:35:48 +08:00
imccyu
4e6937064c fix(util): mint the pinned uuid bytes without dead fallback branches 2026-08-21 20:35:35 +08:00
imccyu
f910e4f84f test: follow the uuid mint to its new entropy seam 2026-08-21 20:35:34 +08:00
imccyu
86357f5f01 fix(lint): clear contracts-ready findings in the mode-model batch 2026-08-21 20:35:34 +08:00
imccyu
6811e44308 test(webworker): narrow the stat shape in the mode round-trip spec 2026-08-21 20:35:34 +08:00
imccyu
54b05a8dcb ci: put the preview-comment marker on its own line 2026-08-21 20:35:34 +08:00
imccyu
c2a30af92d fix(webworker): store and honour VFS permission bits 2026-08-21 20:35:34 +08:00
imccyu
8081620a35 fix: loopback 2026-08-21 20:35:34 +08:00
imccyu
0bee546177 feat(util): mint UUIDs without crypto.randomUUID in every context 2026-08-21 20:35:34 +08:00
imccyu
99db143e37 feat(webworker): name packed modules and client bundles for the debugger 2026-08-21 20:35:33 +08:00
imccyu
304b4b8424 docs: localize a cross-note link in the composer edit-range note 2026-08-21 20:35:33 +08:00
imccyu
3a47674798 ci: add build-preview workflow 2026-08-21 20:35:33 +08:00
imccyu
3cc90952cc chore(gates): regenerate catalogs and keep repository gates green
Config catalog, module graph, event producer-consumer tables, and
third-party notices regenerate over the webworker surface; the oxlint
rule fingerprint and the ui-renderer NodeNext import face follow.
2026-08-21 20:35:33 +08:00
imccyu
50bfb00985 feat(web): single-build preview page and its acceptance e2e
One Vite build emits dist/index.html and dist/preview.html sharing every
chunk; the only difference is one prepended bootstrap entry whose module
connects the worker host, so the page from the stock entry onward is the
served startup chain verbatim. The dist moves to a relative base so the
preview mounts under any static directory, and the served form anchors
deep SPA-fallback paths with a rendered <base href="/">. The preview-boot
e2e serves the real built pages, packs the VFS image when absent, and
holds the boot line's lowering contract, the interactive hero, and a
clean page-error channel in headless Chromium.
2026-08-21 20:35:33 +08:00
imccyu
fd3112a23f feat(web): unify served and preview startup behind a boot-ready seam
The webserver renders a boot-readiness tail after the injection rows and
AppWebEntry.run awaits the __DSH_BOOT_READY__ deferred before reading any
injected state. Whichever bootstrap applies the injection table settles
the deferred - the served renderer resolves it inline, an asynchronous
bootstrap installs it ahead of the entry module and settles it with the
handshake - so both deployments run one startup chain and a failed
handshake surfaces on the boot page instead of proceeding on missing
globals.
2026-08-21 20:35:32 +08:00
imccyu
4779ec9af9 feat(webworker): model-executed shell over nested worker processes
Buy the grammar, own the execution: @yarnpkg/parsers parses the command
line - aliased at bundle time to its shell entry so the root barrel's
syml/js-yaml closure stays out of the worker - and a VFS-backed evaluator
with a coreutils command table runs it inside the worker host. Each shell
process is a real child WebWorker spawned from the same bundle (the first
frame decides the role), so the TERM-then-KILL ladder is real - TERM
requests, KILL terminates the worker - and the file face stays
asynchronous end to end, since the deployment target serves no COOP/COEP
headers and SharedArrayBuffer never exists there. node:child_process
reports through the ChildProcess surface the subprocess service consumes;
execSync, execFileSync and fork refuse, and node-pty stays stubbed.
2026-08-21 20:35:32 +08:00
imccyu
f47b1ecac2 feat(webworker): browser worker host runtime and the vfs image packer
Two private experimental packages run the whole harness tree inside one
dedicated Web Worker. dsh-experimental-webworker-runtime owns the in-memory
VFS (BigInt stats with per-path identity and strictly increasing mtimes),
the CommonJS wrapper loader over a lazily-evaluated builtin table whose
shims typecheck against Node's own module types, the postMessage tunnel
speaking plain HTTP, the AsyncLocalStorage runtime, and the worker
assembly. dsh-experimental-webworker-packer lowers every module body at
pack time against the shared wrapper contract, sweeps the profile closure
by static reachability, and writes a deterministically gzip-compressed tar
the worker inflates through the browser's native DecompressionStream while
it downloads.
2026-08-21 20:35:32 +08:00
imccyu
b150a551b8 Merge pull request #2908 from deepseek-harness/release/dsh-0.1.1-rc.2
release: dsh@0.1.1-rc.2
2026-08-21 20:03:37 +08:00
imccyu
aa6c361a97 release(dsh): 0.1.1-rc.2 2026-08-21 19:48:58 +08:00
CreatixChu
272ffffddd Merge pull request #2676 from deepseek-harness/worktree/image-management-strategy
feat(attachment): add normalized image and Files API pipeline
2026-08-21 19:40:51 +08:00
creatixchu
d618bfebb4 fix(deepseek): decouple files and stream timeouts 2026-08-21 18:34:16 +08:00
creatixchu
1b389798dc fix(llm-deepseek): fall back when Files resolution fails 2026-08-21 18:14:46 +08:00
_Kerman
73a1dae665 docs(session-projection): sync generated catalog translations 2026-08-21 17:53:58 +08:00
_Kerman
54d5d92c08 docs(session-projection): refresh generated catalogs 2026-08-21 17:52:31 +08:00
_Kerman
7e3d5332dc fix(session): address migration review feedback 2026-08-21 17:48:45 +08:00
creatixchu
e30d92a03e fix(attachment): accept opaque WebP alpha omission 2026-08-21 17:27:08 +08:00
_Kerman
82c34463fc fix(tests): complete ToolCallId rename 2026-08-21 17:11:33 +08:00
Yichen Jiang
e08be4df6f Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614 2026-08-21 17:10:03 +08:00
Yichen Jiang
73792a81b1 fix(ui-conversation): restore the folder glyph on composer folder references
The old backdrop overpainted a folder reference's trigger character with
IconFolderClose16; the Lexical rewrite kept the data-ref-appearance
attribute but nothing consumed it, so the composer showed a bare blue
token while the sent bubble carried the icon. A Lexical text node cannot
split out its trigger character for overpainting, so the glyph renders
as an icon prefix instead: a currentcolor mask of the same asset before
the intact literal token. The Lexical note's behavior line follows.
2026-08-21 17:09:07 +08:00
_Kerman
9ce7ef3e23 Merge remote-tracking branch 'origin/xtr/session-format-migration' into xtr/message-tool-call-id 2026-08-21 17:05:09 +08:00
_Kerman
9ab59b8001 Merge remote-tracking branch 'origin/master' into xtr/session-format-migration 2026-08-21 17:01:51 +08:00
creatixchu
d4b24b5148 Merge remote-tracking branch 'origin/master' into worktree/image-management-strategy 2026-08-21 16:55:00 +08:00
imccyu
577bb71418 Merge pull request #2903 from deepseek-harness/worktree-revert-2608
revert: undo #2608 permission labels and blank defaults
2026-08-21 16:53:49 +08:00
imccyu
32f3c09c26 test: sync reverted permission snapshot 2026-08-21 16:41:11 +08:00
_Kerman
6c4bbf7300 perf(goal): read durable state from session projection 2026-08-21 16:29:36 +08:00
imccyu
7ce85283b5 Revert "Merge pull request #2608 from deepseek-harness/fix/permission-copy-and-default"
This reverts commit d51f4106a2b0669d33e0f5dc1d5dcf21a764d313, reversing
changes made to 69ace51625b6ac665b2f2ec1e81005d5b055f152.
2026-08-21 16:21:13 +08:00
_Kerman
6def839f56 perf(team): project durable state incrementally 2026-08-21 16:12:59 +08:00
_Kerman
aa5bc532d3 docs(notes): rename CallId to ToolCallId in agent notes
Keep the active implemented and proposed Agent Notes current with the
renamed ToolCallId brand: branded-ids, content-block-vocabulary,
approval-seam, tool-output-spill-files, and task-surface, in both
languages, with re-recorded .i18n.yaml pairing records.
2026-08-21 16:10:46 +08:00
_Kerman
a789637db6 refactor(llm): rename CallId to ToolCallId 2026-08-21 16:10:24 +08:00
_Kerman
8cf2445f11 Merge remote-tracking branch 'origin/master' into xtr/session-format-migration
# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-14-session-persistence.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-14-session-persistence.zh.md
#	docs/config-catalog.i18n.yaml
#	docs/subsystems/persistence.i18n.yaml
#	docs/subsystems/persistence.md
#	docs/subsystems/persistence.zh.md
#	packages/session/session-persistence-jsonl/README.i18n.yaml
#	packages/session/session-persistence/README.i18n.yaml
#	packages/session/session-persistence/README.zh.md
2026-08-21 15:55:20 +08:00
_Kerman
2da00047f3 refactor(session-persistence): make format migrations one-to-one 2026-08-21 15:50:30 +08:00
Turtle
6ef68c3b96 docs: add documentation website link 2026-08-21 15:33:48 +08:00
creatixchu
6816cc0b04 test(snapshot): stabilize persisted-turn coverage 2026-08-21 15:25:27 +08:00
creatixchu
6a27286e44 docs(i18n): fix rebased image note links 2026-08-21 15:09:14 +08:00
creatixchu
cbc830aded test(composition): remove retired image-region tool 2026-08-21 15:06:24 +08:00
creatixchu
2491e12fd8 refactor(attachment): normalize image storage API 2026-08-21 15:06:24 +08:00
creatixchu
724783b024 refactor(image): remove region reads 2026-08-21 15:06:24 +08:00
creatixchu
0c9a664223 test(deepseek): print vision failure facts 2026-08-21 15:06:11 +08:00
creatixchu
703ce4a3d6 test(deepseek): expose Files API e2e failures 2026-08-21 15:06:11 +08:00
creatixchu
d65e2a9e8a test(images): close unified pipeline coverage gaps 2026-08-21 15:06:11 +08:00
creatixchu
72b204afa1 feat(images): expand source upload envelope 2026-08-21 15:06:11 +08:00
creatixchu
657ec56fbf test(images): cover attachment projection edges 2026-08-21 15:06:10 +08:00
creatixchu
48a58b9090 fix(images): address unified pipeline review 2026-08-21 15:06:10 +08:00
creatixchu
de8ea5d715 docs: refresh image pipeline module graph 2026-08-21 15:05:55 +08:00
creatixchu
c09a42ccb5 fix(images): parse listed missing Files ids 2026-08-21 15:05:55 +08:00
creatixchu
c0dd8ec820 chore(images): align merged runtime closure 2026-08-21 15:05:54 +08:00
creatixchu
d29855f97c feat(images): unify master and Files request pipeline 2026-08-21 15:05:54 +08:00
creatixchu
c1bdac6939 docs: propose attachment read quarantine 2026-08-21 15:02:10 +08:00
creatixchu
118f244420 fix(attachment-local): exclude metadata carriers and animation from passthrough; validate the canonical budget up front
Review-round hardening of canonical admission:
- passthrough now requires a single-frame source free of EXIF/XMP/IPTC
  metadata, so location/device metadata never enters durable storage and
  stored dimensions always describe the perceived pixels; animated WebP joins
  GIF on the always-re-encode path (first frame only)
- SourceImageInfo records orientation-applied dimensions, keeping source and
  stored raster on shared axes for coordinate mapping
- validateImage runs a canonical-encoding dry run, so a validated batch can no
  longer be refused mid-write by the byte target (no partial writes)
- read_image names per-axis multipliers when rounding splits the two ratios
  and maps IMAGE_TOO_LARGE to actionable downscale guidance
2026-08-21 15:02:10 +08:00
creatixchu
c90a944abd docs: bring the zh config catalog along; pin read_image source fields in the code-mode prompt sidecar 2026-08-21 15:02:10 +08:00
creatixchu
867dc44697 docs(notes): record the canonical image admission decision 2026-08-21 15:02:10 +08:00
creatixchu
fec8aa62df docs(attachment): document canonical admission; pin wide-image acceptance snapshot
READMEs (both languages) describe the wide source envelope, the canonical
encoding and its fixed encoder parameters, and read_image's downscale
envelope; tool/config catalogs regenerate for the new schema and Config
fields. The read-image-dimension scenario now pins the acceptance the old
2000px admission cap refused: the 2001x1 source is admitted and stored
byte-identically, so the fixture stays platform-independent.
2026-08-21 15:02:10 +08:00
creatixchu
c6fa512e15 fix(attachment-local): keep reference field order stable for logged fixtures
The canonical ref serializes mediaType, width, height, bytes in the order the
pre-canonicalization store used, so existing session-log fixtures and logged
histories keep byte-identical reference JSON.
2026-08-21 15:01:45 +08:00
creatixchu
6e17c20804 feat(tool-fs): read_image reports downscaled dimensions and coordinate scale
When the attachment store's canonical encoding shrinks the file on disk, the
read_image envelope names the original dimensions and the multiplier that
maps coordinates measured on the attached image back onto the file, and the
output schema carries sourceWidth/sourceHeight for programmatic callers.
2026-08-21 15:01:45 +08:00
creatixchu
83a526eea1 feat(attachment-local): store a deterministic canonical image encoding
Admission now validates a wide source envelope (32MiB, 100MP, 16384px per
side) and persists a canonical encoding instead of refusing large sources:
EXIF orientation baked in, metadata stripped, long edge downscaled to the
configured canonical target (default 2048px), PNG palette for alpha/PNG/GIF
sources and a fixed JPEG quality ladder (85/75/60/45) until the canonical
byte target holds (default 1MiB). In-budget PNG/JPEG/WebP passes through
byte-identically so equal sources keep deduplicating to the same content
address; GIF always re-encodes to the PNG of its first frame, pinning the
first-frame meaning providers apply. Encoder parameters are fixed by design;
only the canonical budget is deployment configuration.
2026-08-21 15:01:45 +08:00
creatixchu
8f83853b60 refactor(attachment): saveImage returns the canonical ref beside source facts
AttachmentStore.saveImage now resolves SavedImageAttachment: the durable
reference paired with the submitted raster's intrinsic facts, so a store may
persist a canonical re-encoding while callers keep the source dimensions for
coordinate mapping. saveImages keeps returning refs; every fake store and the
cordis API catalog follow the new signature.
2026-08-21 15:01:45 +08:00
creatixchu
92a9741050 docs(llm): anchor unified request-image management design PR 2026-08-21 15:01:07 +08:00
_Kerman
265f02fbf5 perf(session-projection): index contiguous restore tails 2026-08-21 14:24:28 +08:00
Yichen Jiang
339a12030d fix(web): project sent user text inline and fold wire references in queue rows
The user-bubble decorator rendered every plain run through the
block-level MessageText div, so a decorated single-line message broke
into one line per run and the space between two tokens rendered as a
blank line. The queue dock's read-only row printed row.preview verbatim,
showing the wire session form (@[label](dsh-session:...)) instead of a
readable label. Both predate the Lexical composer; the logged model text
was correct in both cases.

One shared inline projection (reference/user-text.tsx) now owns sent
user text for the bubble and the queue row: plain runs are spans with
white-space policy left to the consumer (bubble pre-wrap, queue nowrap),
and a highest-precedence rule folds the wire session form to its label
chip, shielding the URI from the bare-token scan. The queue edit field
keeps the literal sent text. user-text.client.spec pins the inline
guarantee and every fold rule; queue-actions.e2e locators move to
row-container matching (the projection adds one span layer).
2026-08-21 14:23:01 +08:00
_Kerman
89b5bc276f perf(session-projection): skip history reads for in-order events 2026-08-21 14:09:39 +08:00
_Kerman
a216756222 perf(session-projection): avoid restore tail copies 2026-08-21 14:09:33 +08:00
Turtle
d97e398383 fix(jsonl): warn when repairing torn tails 2026-08-21 13:44:35 +08:00
Yichen Jiang
c365daa53c chore(rescope): realign two manifest anchors, allowlist the preset-id spec
Exposed by this branch touching rescope-vendor.ts, which runs the full
rescope check: the knip-logger-console exact edit targeted the
packages/util/home knip section that #2758 deleted (drop the edit), the
zh vendoring-cookbook anchor predates the rescope.zh.md link
localization (follow it), and the new shipped-root.spec.ts joins the
files whose bare 'cordis' tokens are preset ids.
2026-08-21 13:42:24 +08:00
Yichen Jiang
d858832bbb chore(constraints): register the preset-root files policy
The files constraint tables gained per-package expectations on master
while this branch changed two files lists: apps/cli no longer ships
config/, and dsh-agent-presets ships presets/ (ordered where the
expected-files derivation places extras).
2026-08-21 13:42:23 +08:00
Yichen Jiang
548b9f07d4 Merge remote-tracking branch 'origin/master' into fix/derive-shipped-preset-root-per-composition 2026-08-21 13:19:58 +08:00
_Kerman
a693e0764b docs: revert spurious BRAND-GUIDELINES.md change from master merge 2026-08-21 13:09:33 +08:00
Yichen Jiang
f94495e527 refactor(preset): bundle the shipped presets inside dsh-agent-presets
Review asked why the launcher special-cases one plugin's row. It no
longer does: the four shipped compositions move into the package
(presets/, in files), dsh-agent-presets resolves its own shipped root
and prepends it before configured roots (includeShippedRoot, default
true, opt-out for bare-machinery embedders), and the per-composition
derived patch, its spec, and the dump layer are deleted — profile-boot
and dump-config return to plain layer stacking. The always-load
guarantee now rides the schema default instead of patch ordering, so a
whole-config replacement keeps the shipped set and the squash, reload
freeze, and dump divergence stop being possible.

Gate globs, the web scaffold, and both preset browser lanes drop their
hand-fed shipped roots; the roster e2e keeps asserting configured roots
beside the shipped four against the built lib.

Fixes #2863.
2026-08-21 12:37:57 +08:00
Chinesezjc
a633c19b02 ci(windows): raise native coverage test timeout to 60s
The Windows native coverage lane was hitting Vitest's 30s per-test
ceiling on slow subprocess/ACP fixtures. Doubling the per-test budget
absorbs cold-start and process-teardown jitter without changing the
assertions or the job-level 120-minute cap.
2026-08-21 11:57:42 +08:00
Chinesezjc
7214d0d958 refactor(python): drop now-always-true build.if
python-release.yml only triggers on workflow_dispatch, so build.if:
github.event_name == 'workflow_dispatch' is always true and redundant; remove it
(the exact event set is already pinned in the spec). Update the spec assertion
accordingly.
2026-08-21 11:55:57 +08:00
Chinesezjc
ae193bfc07 fix(cic): narrow workflow.on before Object.keys in python-release assertion
Guard workflow.on with isRecord before Object.keys to satisfy TS2769.
2026-08-21 11:54:36 +08:00
Chinesezjc
374f3cdb07 fix(cic): re-record development pair and tighten python-release spec assertion
Address PR #2875 review:

- Re-record python/development.i18n.yaml (corpus verify-translation-pairing was
  out of sync after editing development.md/zh.md) and the 2026-08-11
  python-publication-workflow pair after the dry-run wording tweak.
- Tighten the python-release spec assertion to the exact event set
  (['workflow_dispatch']) instead of not.toHaveProperty('pull_request').
- Fix the 'dry-run run' wording in development.md and the note.

Corpus-wide verify-translation-pairing (1001 pairs) and note-format (594) pass;
ci-workflow.spec.ts 14/14.
2026-08-21 11:53:50 +08:00
Chinesezjc
cb5b762922 fix(docs): correct zh locale link in composer-edit-range note
The static gate (translation pairing) failed on a pre-existing master note:
2026-08-20-composer-edit-range-from-selection.zh.md:17 linked the zh target with
the en .md path. Point it at the .zh.md target and re-record the i18n hash. This
unblocks the required node 24 / static gate (it is not part of the python-release
gray-check change but sits on the same PR's CI path).
2026-08-21 11:51:50 +08:00
_Kerman
bb3105d7b5 refactor(apiproxy): restore the single-line listProjectionsFor signature
An intermediate cache iteration made cachedSnapshot async, which forced
listProjectionsFor onto a multi-line async signature; the final design
kept the sync read but the formatting residue stayed. No behavior
change.
2026-08-21 11:49:52 +08:00
_Kerman
87c01d9966 test(storage-json): reach the unreadable-record branch on every platform
The per-record contract test forced readFile to fail via chmod 0o000,
which is a no-op on win32, so the readRecord catch stayed uncovered on
the windows native coverage gate. Route record documents without an
isFile pre-filter: a directory where the document should be throws
EISDIR on every platform, and readRecord's existing contract already
reads an unreadable document as absent. Drop the win32 skip.
2026-08-21 11:34:22 +08:00
Yichen Jiang
f9c4309c60 Merge remote-tracking branch 'origin/master' into fix/derive-shipped-preset-root-per-composition 2026-08-21 11:32:04 +08:00
Yichen Jiang
25058f2658 docs(cli): sync the derived preset-root layer into launcher docs
Review follow-ups: enumerate the derived shipped agent-preset root in
apps/cli README/reference dumps and the profile-boot module JSDoc
(bilingual pairs re-recorded), correct the stale AppCLIEntry/distIndex
analogy in the web scaffold and the shipped-root cross-reference in the
web preset e2e, drop the write-only ComposedProfile.rows field, and make
the Agent Note describe the dump path as sharing the derivation rather
than the builder.
2026-08-21 11:32:02 +08:00
Yichen Jiang
df0fbbb091 test(web): migrate the retry-exhaustion composer wait off the textarea locator
Master's #2844 asserted composer recovery through a textarea locator the
Lexical composer no longer renders; the merge carried it in silently and
the CI web-snapshot lane timed out waiting for it. Use the same
data-composer-input wait the file's other cases already migrated to.
2026-08-21 11:19:57 +08:00
Yichen Jiang
ae01b19bd3 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	.agents/notes/archived/bug-fix/2026-08-20-composer-edit-range-from-selection.i18n.yaml
2026-08-21 11:19:14 +08:00
_Kerman
4760c40e84 docs(session-projection): apply master's locale link fixes after merge
The master merge brought the doc-sync regenerations (locale-specific
paired document paths). Re-apply the zh-side link fixes to the agent
note and the session-projection intro, re-record translation pairing,
and keep the e2e event arrays as asserted literals like master.
2026-08-21 11:14:07 +08:00
_Kerman
ff9735cb8c Merge origin/master into xtr/projection-per-session-cache 2026-08-21 11:07:27 +08:00
_Kerman
8baa987387 test(storage): harden windows-native teardown and chmod probe
The per-record rm in the cache spec hits an EPERM flake on windows
native (directory still draining); retry the recursive rm like the
subagent spec does. The unreadable-record probe is meaningless on
windows, where chmod 0o000 is a no-op; skip it there.
2026-08-21 10:46:21 +08:00
_Kerman
1134c2a98e test(web): seed cold subagent fixtures through the per-record cache
The reworked cache moved from the awaited coldSnapshot(id) to a sync
coldSnapshot(meta, events) whose write-back is fire-and-forget, and the
e2e fixture dropped the seeding call with it. The web bundle mounts the
cache again, so list rows read projection columns from stored rows only;
the one-shot and grandchild fixtures therefore lost their projections
column and the tree golden drifted. Re-seed both through the new API and
poll for the write-back to land.
2026-08-21 10:46:17 +08:00
Chinesezjc
499c1262a2 ci(python): drop PR labeled trigger for python-release dry-run
Remove the pull_request:[labeled] trigger from python-release.yml so the
workflow no longer fires (and shows a gray skipped check) when a PR gets any
non-dry-run label. The credential-free dry-run validation is now manual-only
(workflow_dispatch with publish=false), preserving the validation capability
without a PR gray segment.

- python-release.yml: on is workflow_dispatch only; build.if is
  github.event_name == 'workflow_dispatch'.
- ci-workflow.spec.ts: assert python-release has no pull_request event and the
  simplified build.if.
- python/development.(md,zh.md) and 2026-08-11-python-publication-workflow note
  (en/zh/i18n): describe the manual dispatch-only dry-run path.

Verification: ci-workflow.spec.ts 14/14, typecheck clean, note-format 585,
verify-translation-pairing consistent.
2026-08-21 08:56:32 +08:00
pku-xht
b9cbcf8e2b docs(subagent): clarify diagnostic-bearing results 2026-08-21 08:52:19 +08:00
pku-xht
d5fe4e9307 Merge ACP direct-outcome simplification into DSH SDK layer 2026-08-21 08:06:43 +08:00
pku-xht
8dc7852881 refactor(subagent): observe ACP direct process outcome 2026-08-21 08:06:10 +08:00
pku-xht
4f196f41d4 Merge ACP quiescence wording into DSH SDK layer 2026-08-21 07:58:14 +08:00
pku-xht
aaa85cce01 docs(subagent): name SDK quiescence precisely 2026-08-21 07:57:43 +08:00
pku-xht
9a6f5cf7ff docs(subagent): name ACP quiescence precisely 2026-08-21 07:57:32 +08:00
pku-xht
f2615dc114 Merge ACP cancellation wording into DSH SDK layer 2026-08-21 07:50:41 +08:00
pku-xht
30cd11e698 docs(subagent): distinguish cancelled SDK cleanup 2026-08-21 07:50:13 +08:00
pku-xht
3900de296d docs(subagent): distinguish cancelled cleanup failure 2026-08-21 07:50:00 +08:00
pku-xht
d9ad13c5b7 Merge ACP cleanup contract into DSH SDK layer 2026-08-21 07:39:26 +08:00
pku-xht
d90003b4e0 docs(subagent): qualify ACP cleanup failure 2026-08-21 07:38:48 +08:00
pku-xht
1653143ca5 Merge ACP config catalog refresh into DSH SDK layer 2026-08-21 07:34:28 +08:00
pku-xht
075108dc08 docs(config): refresh ACP process grace catalog 2026-08-21 07:34:00 +08:00
pku-xht
75b8eb08ba docs(subagent): qualify startup cleanup outcomes 2026-08-21 07:29:12 +08:00
pku-xht
ca7ccac27f Merge ACP observation fixes into DSH SDK layer 2026-08-21 07:24:15 +08:00
pku-xht
ba0d7dfdca fix(sdk): validate closed turn cancellation facts 2026-08-21 07:23:43 +08:00
pku-xht
2a060adfa8 fix(subagent): keep ACP failure observation cancellable 2026-08-21 07:23:14 +08:00
pku-xht
fe88976b6a Merge ACP cancellation simplification into DSH SDK layer 2026-08-21 07:10:24 +08:00
pku-xht
0dcb514fc6 refactor(subagent): drop unused ACP cancel classification 2026-08-21 07:09:42 +08:00
pku-xht
1c5305ca22 test(subagent): type blocked SDK outcomes precisely 2026-08-21 06:56:31 +08:00
pku-xht
12c7e968a0 Merge ACP diagnostic lifecycle fixes into DSH SDK layer 2026-08-21 06:54:24 +08:00
pku-xht
bbf1c6e842 fix(subagent): close DSH SDK diagnostic review gaps 2026-08-21 06:53:28 +08:00
pku-xht
67e038ab3a fix(subagent): align ACP diagnostic lifecycle facts 2026-08-21 06:53:00 +08:00
pku-xht
1af22c23b4 Merge minimal ACP permission diagnostics into DSH SDK layer 2026-08-21 06:06:10 +08:00
pku-xht
659749dc09 fix(subagent): align DSH SDK diagnostics with reachable facts 2026-08-21 06:05:51 +08:00
pku-xht
5e1494ff17 refactor(subagent): keep ACP permission diagnostics minimal 2026-08-21 05:58:43 +08:00
pku-xht
ee50ee088d test(subagent): stabilize DSH SDK background snapshot 2026-08-21 05:24:13 +08:00
pku-xht
569bf3e5e0 docs: refresh DSH SDK config catalog pair 2026-08-21 04:57:44 +08:00
pku-xht
f72ef36331 Merge latest ACP review fixes into DSH SDK layer 2026-08-21 04:54:26 +08:00
pku-xht
d6de6bb0cb test(subagent): align ACP permission snapshot 2026-08-21 04:52:40 +08:00
pku-xht
34c7feef83 Merge parent ACP diagnostics into DSH SDK layer 2026-08-21 04:48:57 +08:00
pku-xht
b88a35d506 fix(subagent): preserve actionable DSH SDK failure facts 2026-08-21 04:48:40 +08:00
pku-xht
dfb36080d8 fix(subagent): close ACP diagnostic review gaps 2026-08-21 04:41:21 +08:00
pku-xht
5c27df5ed7 fix(subagent): preserve actionable ACP failure facts 2026-08-21 04:00:40 +08:00
Yichen Jiang
b010c20703 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	packages/client/ui-conversation/src/client/skeleton/InputBar.tsx
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
2026-08-20 23:27:33 +08:00
Yichen Jiang
9820b6a1e9 fix(cli): derive the shipped agent-preset root per composition
The boot-time agent-presets overlay replaced the composed roots with the
shipped root alone, so roots configured in a profile's cordis.patch.yml
vanished from the roster (externally reported in
deepseek-ai/deepseek-harness#3636). The overlay also froze the row's
boot-time config above every live reload and never reached the config
dump, which therefore showed roots the boot dropped.

Derive the roster patch from the current layers instead: prepend the
shipped root (system trust, wins duplicate ids) to configured roots,
share one builder across boot, live user-layer reloads, and
--dump-config, and fail loud on a roots value the launcher cannot
statically rewrite.

Fixes #2863.
2026-08-20 22:57:58 +08:00
Yichen Jiang
c8b4ec73a0 fix(ui-conversation): step across chips without a keyboard-selected state
isKeyboardSelectable() defaulted to true, so an arrow key at a chip edge
created a NodeSelection whose DOM projection collapses to an element
point; the plain-text binding's arrow/delete/insert handlers all bail on
non-Range selections, deadlocking arrows, typing, and Backspace at the
chip until a pointer click. False restores the placeholder semantics:
arrows cross the chip in one move and Backspace/Delete remove it whole.
Reproduced and verified with real-key Playwright probes (CDP raw
keydowns carry no engine default and cannot reproduce it); the
reference-composer e2e pins the gesture in the browser lane.
2026-08-20 22:48:56 +08:00
Yichen Jiang
315fc9b16e fix(ui-conversation): address composer review findings
- drop the space-key debug probe from the production keymap
- give pastes their own undo boundary (PASTE_TAG via $addUpdateTag on the
  nested dispatch path), with an input-bar regression test
- claim decoration outranks text-ref entities on the leading-token seat:
  the entity transform skips the active claim token, restoring the warn
  color for lexicon-listed command names (probe-confirmed regression test)
- caret-only commits no longer advance draftRev or re-publish InputState;
  content changes still do (snapshot-built CAS spans stay valid)
- retire stale JSDoc/contract wording (paste-upgrade, set-invalid; the
  invalid bit only promises the render treatment)
- rename the keydown probe spec to keymap-routing and drop test dead code
- reference-composer e2e gains the #2813 type-ahead-of-chip gesture
- archive three superseded composer notes (Safari soft-wrap, text layers,
  decoration keys), rewrite the input-machine note's superseded half in
  place, and record the new behavior decisions in the Lexical note
2026-08-20 22:20:31 +08:00
Yichen Jiang
8905b0a195 test(ui-conversation): drop an unnecessary type assertion in the chip DOM spec 2026-08-20 21:51:24 +08:00
Yichen Jiang
4fe0db5031 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.md
#	packages/client/ui-conversation/README.zh.md
#	packages/client/ui-conversation/tests/skeleton.client.spec.tsx
2026-08-20 21:39:48 +08:00
pku-xht
8a99ff7a29 Merge commit '80d7e34e6acd5babf2f1e3e91b8d4534ddc78657' into codex/subprocess-win32-process-primitives 2026-08-20 20:37:37 +08:00
pku-xht
85b8484a95 test(sandbox): remove stale export assertion 2026-08-20 20:13:01 +08:00
Yichen Jiang
f908cf434b docs: zh-locale links for the composer note after the master merge 2026-08-20 19:56:19 +08:00
pku-xht
a5368680ae docs(win32-process): keep localized header link valid 2026-08-20 19:53:56 +08:00
Yichen Jiang
0cdb569cf8 Merge remote-tracking branch 'origin/master' into worktree/web-textarea-refactor-991614
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.zh.md
2026-08-20 19:53:44 +08:00
pku-xht
6db3ed93bf Merge origin/master into codex/subprocess-win32-process-primitives 2026-08-20 19:49:34 +08:00
pku-xht
458ba49815 docs(win32-process): narrow ABI verification claims 2026-08-20 19:28:05 +08:00
pku-xht
ff7a5a042c docs(win32-process): point ABI verification to its owner 2026-08-20 19:17:03 +08:00
Yichen Jiang
9b64106e9e test(web): settle the remaining e2e drive gaps
Every consecutive composer send waits out the submit round-trip's
read-only span; the end-of-document caret gesture becomes select-all +
ArrowRight (Cmd/Ctrl+End moves no caret in mac contenteditable), which
lets Lexical's own ancestor scroll walk prove the typing reveal.
2026-08-20 19:05:26 +08:00
Yichen Jiang
504a1c6f4b test(web): null-tolerant textContent length in the perf lane 2026-08-20 18:55:26 +08:00
Yichen Jiang
4f808771ce test(web): finish the e2e migration to the composer surface
textContent/data-placeholder probes replace inputValue/placeholder reads,
evaluate-string selectors move to the composer anchor, queued fills wait
out the submit round-trip's read-only span, and the refreshed aria goldens
drop the hover tooltip the old interaction order happened to capture.
2026-08-20 18:50:59 +08:00
pku-xht
6d9bc90532 Merge origin/master into codex/subprocess-win32-process-primitives 2026-08-20 18:38:46 +08:00
Yichen Jiang
e920185700 test(web): drive the built-graph snapshot lanes through the editor surface
Paste-command text entry (awaiting its microtask commit), data-placeholder
lookup, a scrollIntoView stub for the menu the settled-caret re-track now
opens, and a trailing separator on the bare /plan paste so Enter submits
instead of picking from that menu.
2026-08-20 18:32:44 +08:00
Yichen Jiang
f6fb66a318 docs+build(ui-conversation): lexical composer collateral
The client-bundle preset pins the production/development exports condition
(lexical's node-condition file selects its flavor with a top-level await a
CJS bundle cannot carry); the composer carries an explicit aria-label (a
div's data-placeholder does not name it the way a textarea placeholder
did); READMEs, the composer.bar slot doc, and the Agent Note record the
editor architecture; web e2e drives the contenteditable surface.
2026-08-20 18:27:55 +08:00
Yichen Jiang
7222b066d5 test(ui-conversation): align suites with the editor composer
Drive keyboard gestures as real KeyboardEvents at the contenteditable
(Lexical routes them through the command layer), write drafts through the
shell, and probe decorations at their new DOM (chip decorators, styled
claim leaf, hint CSS variable, text-ref entity nodes). jsdom lacks
Selection.modify, so the Backspace-deletes-chip gesture moves to the
browser lane.
2026-08-20 18:06:58 +08:00
Yichen Jiang
b519cb87b0 feat(ui-conversation): lexical composer replaces the textarea stack
The editor (shell-owned, per-session) is the draft + chip truth; the
machine slims to the submit plane. Chips are atomic decorator nodes with
NodeKey identity; TokenSpan coordinates ride the detect projection (chip =
one U+FFFC), persistence and InputState.draft ride the clipboard
projection. The mirror/backdrop layers, Safari soft-wrap repair, manual
undo log, boundary occurrence deletion, and clipboard expansion all
retire; the producerless paste-attempt and set-invalid planes go with
them.
2026-08-20 17:58:52 +08:00
_Kerman
cdb918c4b0 chore(storage-json): exempt the shared unit lifecycle from the duplication gate
The two standalone unit classes deliberately mirror the KvUnit drain/guard
lifecycle (close + assertOpen); mark the block with a reason-carrying
jscpd ignore so the duplication gate stays green.
2026-08-20 17:34:08 +08:00
_Kerman
f6080c3753 docs(session-projection-cache): sync catalogs, type-equiv, and event consumers after master merge
Regenerate config/cordis catalogs and doc graphs (the master merge changed
configs and consumers), add the DomainSpec layout field to the storage
type-equiv block, record session-projection-cache as a session/created
consumer, and drop the leftover experimental/team ghost directories from
the master rename. All 37 static gates pass.
2026-08-20 17:26:32 +08:00
_Kerman
2c11e73c55 Merge remote-tracking branch 'origin/master' into xtr/projection-per-session-cache 2026-08-20 17:15:25 +08:00
_Kerman
eb1f167fa4 refactor(session-projection-cache): restore the base method order
Keep the base class's relative method order (write before coldSnapshot) so
the diff against the base shows the cold-read methods as a pure insertion
instead of a reorder of existing methods.
2026-08-20 17:14:05 +08:00
Yichen Jiang
477615162a feat(ui-conversation): lexical chip node, projections, span map 2026-08-20 16:57:56 +08:00
Yichen Jiang
2279fd19b0 chore(ui-conversation): add lexical dependencies and jsdom spike 2026-08-20 16:46:57 +08:00
_Kerman
b67761a8a5 fix(session-projection-cache): checkpoint at session creation
A session that never talks — a forked child seeded with its ancestor's
title, say — previously got its first cache row only at detach; a crash,
or a fork held live in the store, left the seed-derived values (the
title) unreadable on the cold list. Session creation is now a third
mandatory write point: the creation checkpoint folds the seed and
persists immediately. Write-policy docs (README + catalogs) updated.
2026-08-20 16:37:41 +08:00
_Kerman
08e546eff1 feat(storage-json): one-time migration of a legacy whole-unit file to per-record
Opening a per-record unit splits a legacy `<root>/<name>.json` (the
pre-per-record single-file layout) into per-record documents; an
already-present new record wins, and the legacy file is deleted once
every record migrated. The migration also runs when the new tree is
absent — the fresh-upgrade shape — and foreign, shapeless, or malformed
legacy files are left alone. This preserves previously cached session
titles, list metadata, stats, and subagent identity across the medium
change.
2026-08-20 16:25:39 +08:00
_Kerman
84db39cec4 feat(session-projection-cache): seed cold reads from the cache and write back
A detached history read still traverses the complete log, but each unit's
fold is now seeded from its cached checkpoint: the registry's restore
slices off the already-folded prefix (events at or below the row's seq)
and applies only the tail. The first cold read writes the refreshed
checkpoint back (fail-soft), so the cache row is created on first read
and kept current afterwards. The recipe lives on the cache
(cachedCheckpoint, coldSnapshot, writeBack); the api-proxy carrier only
supplies the stored header and the full log.
2026-08-20 16:25:39 +08:00
_Kerman
02a608271e Merge origin/master into xtr/projection-per-session-cache 2026-08-20 16:03:51 +08:00
pku-xht
7ef1c458f0 fix(win32-process): close PR1 validation gaps 2026-08-20 16:03:15 +08:00
pku-xht
19256704c7 test(win32-process): type handle-order assertions 2026-08-20 15:25:02 +08:00
pku-xht
b2d344771e Merge origin/master into codex/subprocess-win32-process-primitives 2026-08-20 15:21:28 +08:00
pku-xht
5b47da02ae refactor(win32-process): restore mechanical extraction 2026-08-20 15:21:01 +08:00
_Kerman
07cf16d57c docs(session-projection-cache): sync the per-record domain medium across docs
Cache README (EN/ZH): the medium is the session_projcache domain in
per-record layout (one version-stamped document per session under the
json backend root), reads are synchronous from the domain's in-memory
tables, and the storage stack rides in base. storage-json README
documents both layouts and their contracts; web-app README notes that
storage and the projection cache live in the shared base. Regenerated:
session-projection subsystem catalog (sync cachedSnapshot, domain
medium), config-catalog (Config.root gone), module-graph (cache now
depends on storage-domain, not session-persistence), cli composition
(storage rows in base), and the projection-cache Agent Note — which now
records the file-root revision and its revert as rejected alternatives.
2026-08-20 14:38:39 +08:00
_Kerman
9226d9bbf6 test(session-projection-cache): rewrite for the per-record domain medium
cache.spec now boots the real storage stack (storage, storage-json,
storage-domain) and asserts the per-record medium directly:
<root>/session_projcache/sessions/<id>.json carries a version-stamped
{version, record} document, cachedSnapshot is synchronous (zero-I/O from
the domain's in-memory tables), and the write-policy / fail-soft / listing
coverage is preserved at 100%. json-backend.spec gains a per-record layout
block (per-record documents, overwrite/delete/reopen, unsafe keys and
undeclared tables rejecting, foreign-document discard on open, closed
guard, close drain, unreadable-as-absent); storage-domain domain.spec
covers layout validation and descriptorOf projection. list-children.spec
mounts the storage stack for its projectionCache cases and its
cachedSnapshot mocks and reads go synchronous; the api-proxy specs' cache
mocks go synchronous too. devDeps and tsconfig references updated for the
storage stack.
2026-08-20 14:38:33 +08:00
_Kerman
50ad2aba19 fix(session-persistence): repair persistence CI gates
- document the exported SqliteStore prefix/suffix loaders (verify-export-jsdoc)
- share createStoredEventRead from session-persistence so the standalone
  SQLite store stops duplicating the service helper (duplication gate)
- route replaceStored header upserts through writeRow (duplication gate)
- move replacement/conflict test SQL into closed test resources so the
  SQLite SQL resource boundary test passes
2026-08-20 14:21:47 +08:00
_Kerman
3a4232a8fa fix(bundle): promote the storage stack and the projection cache to base
The storage hub, json backend, and domain form are general infrastructure,
and the projection cache is a session-layer service that depends on them —
both belong in the shared base, not in the web overlay. Base now provides
storage / storage-json / storage-domain / session-projection-cache; the
web-app overlay keeps its surface consumers (workspace, message-feedback),
which inherit storageDomain from base (a child layer sees parent services).
This reverts the storage stack's historical web-app-only placement and the
file-root design's base mount of the cache.
2026-08-20 13:56:23 +08:00
_Kerman
e01c1a4b41 fix(bundle): mount the projection cache in the web-app overlay
The cache now opens its domain through ctx.storageDomain, which the
web-app overlay provides (storage-json + storage-domain, backend json).
A parent layer cannot see a child layer's services, so the base-layer
mount from the file-root design is reverted: the cache mount moves back
to web-app next to its storage dependencies, and Config.root is gone.
2026-08-20 13:47:53 +08:00
_Kerman
1201ecc828 fix(session-projection-cache): store checkpoints on a per-record storage domain
Restore the storage-domain medium the file-root design replaced: the cache
opens the session_projcache domain (per-record layout — one document per
session under the json backend root) and checkpoint writes land through
the domain's write chain. Reads and writes now share ONE coherent state:
cachedSnapshot reads synchronously from the domain's in-memory tables,
and every write is durability-first-then-memory, so a read can never go
around the write chain to the medium. The hand-rolled write chains,
in-flight tracking, per-session file paths, owner-only file modes, and
the sqlite no-path special case are gone; Config.root is removed and the
domain's version stamp makes a checkpointRecord bump discard stale
sessions per record instead of rejecting the whole medium. The async
ripple of the old file read is reverted: api-proxy's listing column and
subagent's cold identity read go back to synchronous cachedSnapshot.
2026-08-20 13:47:47 +08:00
_Kerman
501f387b46 feat(storage): add the per-record layout to the json backend
The json backend now serves two layouts. single (the default) keeps the
whole unit as one document at <root>/<name>.json; per-record keeps one
version-stamped document per record at <root>/<name>/<table>/<key>.json
(plus global.json), so one write rewrites one record instead of the whole
unit. The per-record unit is stateless — the directory is the state,
loadAll re-reads the tree, and every write is a single durable file
operation — while single keeps its authoritative in-memory state and
whole-file publish. Records keys must be path-safe ([a-zA-Z0-9_-]+);
an unsafe key rejects. A record document that is malformed or stamped
with another version reads as an absent record: one bad or stale file
never bricks the unit, and a version bump discards stale records instead
of migrating them. DomainSpec and KvUnitDescriptor gain the optional
layout field (defineDomain validates it, descriptorOf projects it).
2026-08-20 13:47:39 +08:00
_Kerman
c26ca6acb6 fix(session-projection-cache): drain in-flight writes on disposal; sync stale lockfile and generated docs
- Track fire-and-forget durable writes and await them at plugin disposal so
  a late flush can never land after teardown (fixes the ENOTEMPTY cleanup
  race in the disposal test).
- Drop the now-async-less Service.init and flushSoft void operators to keep
  lint clean, and remove the redundant dsh-storage-json devDependency.
- Regenerate the stale pnpm lockfile and the config/persistence/module-graph
  catalogs (with zh mirrors and pairing records) that the per-session cache
  merge left out of sync, and fix the session-projection type-equiv doc
  blocks to match the source.
- Add coverage for the unrelated-log-identity and no-per-session-directory
  (sqlite) cold-read paths.
2026-08-20 10:49:43 +08:00
_Kerman
f62986c01a docs(session-projection): sync persist removal, cache root, and catalogs
- subsystem docs: drop the removed persist flag from the ProjectionDefinition
  type block (both languages).
- config-catalog regenerated (cache requires sessionProjections/sessions,
  config gains root) and the zh side synced by hand; doc graphs regenerated.
- Agent Notes: the per-session cache note records the owned root tree and
  no-persistence design; the storage-root proposal's link to it is corrected
  (two levels up).
2026-08-19 22:26:16 +08:00
_Kerman
32ed3e2bce test: adapt consumers to the cache's own root tree
The web e2e seeds no longer warm the deleted coldSnapshot; assertions do not
depend on the cache path. list-children mounts the cache with a scratch
root instead of a storage-domain backend, and drops the now-unused storage
devDependencies.
2026-08-19 22:26:08 +08:00
_Kerman
a9a51f8096 fix(bundle): mount the projection cache in the base overlay
The cache now owns its storage root (dshHomePath('projections')), so the
mount moves from the web-app overlay to base with that root declared, next
to the other base session layers. web-app inherits it; its overlay mount is
removed.
2026-08-19 22:26:02 +08:00
_Kerman
89321489db refactor(session-projection-cache): own the cache tree under a config root
Store each session's projection_cache.json under the cache's own root tree
(<root>/<session-id>/projection_cache.json, wired to dshHomePath('projections')
in the base bundle) instead of beside the session log via
sessionPersistence.locate(). The cache owns its directory layout, keys
directories by the code-generated session id, and never consults the
persistence layer; the service now injects only sessionProjections and
sessions.

Drop the coldSnapshot method and its readFrom-tail fold ladder: every cold
consumer refolds from the log itself, so the cache only serves the listing
read (cachedSnapshot, one async file read per session) and the write side.
Fail-soft durability, per-path write serialization, in-flight drain, and
atomic 0600 writes are unchanged; the chain cleanup now observes its own
rejection so a failed write cannot surface as an unhandled error.

dsh-session-persistence leaves peer/dev dependencies and the tsconfig
reference; dsh-atomic-write moves to peerDependencies. Config gains a
required root.
2026-08-19 22:25:54 +08:00
_Kerman
3f4c5f0563 fix(session-projection-cache): address review — atomic-write reuse, sqlite no-path, ordering and drain
- Write through @deepseek-ai/dsh-atomic-write with { mode: 0o600,
  dirMode: 0o700 } instead of exporting a second atomic-write primitive
  from dsh-storage-json; the session tree stays owner-only like the jsonl
  backend's own directories.
- Serialize atomic replacements per cache path so an older cut can never
  overwrite a newer one; track in-flight writes and drain them on
  disposal so a late flush cannot land after teardown.
- Detect the absent per-session directory before the checkpoint cut and
  durability flush: sqlite-style backends no-op the write entirely.
- Cold-read write-back path and identity both come from the stored log
  header (tail.meta), so a stale caller header cannot mint an orphan
  cache file.
- Add no-path coverage (write no-op, cachedSnapshot undefined, cold
  fallback to the full-log rung) and a concurrent-write ordering test;
  the package now holds 100% statement/branch/function/line coverage.
- Sync README.md/zh (inject list, coldSnapshot signature, per-session
  file read wording), package description, the Agent Note alternatives,
  and the superseded proposed/implemented notes (EN/ZH); add the
  concurrent-checkpoint Known Limitation.
2026-08-19 21:40:12 +08:00
_Kerman
30334322eb fix(apiproxy): crop host-only units from wire projection blocks
history and session.list baselines built through restore/snapshot without
wireOnly leaked host-only unit state onto the wire; pass { wireOnly: true }
on the detached history fold, the attached history snapshot, and the
attached listing snapshot.
2026-08-19 21:16:00 +08:00
_Kerman
aa527186d6 merge: bring in the per-session projection cache (2781) 2026-08-19 21:11:59 +08:00
_Kerman
bb6faaf87b Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2698 2026-08-19 21:08:03 +08:00
_Kerman
cdb4cc3c68 feat(session-projection-cache): store one projection_cache.json per session
Replace the single global session_projcache domain with a per-session
cache file inside the session's own persistence directory, resolved
through sessionPersistence.locate(meta) — the persistence backend owns
the session-directory layout, the cache service keeps every checkpoint
and cold-read responsibility.

- cachedSnapshot(meta) becomes async (one file read per session);
  coldSnapshot takes the session header so it can locate the file, with
  the stored log header remaining the identity witness.
- Backends without a per-session directory (sqlite) disable the durable
  cache: writes no-op and cold reads fall to the full-log rung. An
  obsolete global cache is never read — derived data refolds on first
  cold read (no migration).
- writeAtomic is exported from dsh-storage-json as the shared atomic
  whole-file replace primitive; api-proxy listing and subagent cold
  reads await the now-async cachedSnapshot.
- READMEs and a new Agent Note document the per-session medium.
2026-08-19 21:03:20 +08:00
_Kerman
270a06b38b fix(session-persistence-jsonl): drop crash-unsafe cross-process log lock
The product model has no cross-process writer exclusion (the coordinator
serializes per-session operations in-process; the README documents one
live writer per session), so the wx-created .lock sibling only guarded
byte-level races while adding two failure modes: a crash leaves a stale
lock that permanently wedges that log's appends/repairs/replacements, and
a post-commit lock cleanup failure makes a committed append look failed,
so the retained write-behind batch retries into duplicate seqs.

Remove withLogLock and keep replaceStored's revision compare-and-swap at
the commit boundary (recheck immediately before the atomic rename).
2026-08-19 20:42:56 +08:00
_Kerman
e8f4315cee fix(session): scope format registry completeness to per-session decode
buildStepIndex rejected the whole decoder at initialization whenever any
registered step could not reach the current version, so one retired old
upgrader blocked every session, including later versions whose path to
the current version is complete. planSteps already refuses a specific
stored version when a needed step is missing; initialization now checks
only step legality and duplicates.
2026-08-19 20:31:31 +08:00
pku-xht
615d910f04 Merge origin/master into codex/subprocess-win32-process-primitives 2026-08-19 20:01:10 +08:00
_Kerman
842f42d7ea Revert "fix: resolve remaining review findings — explicit turnBoundary dependency and uniform missing-key handling"
This reverts commit 3a664c73e131d073025c5c3041e3f4a3cebb3889.
2026-08-19 18:01:11 +08:00
_Kerman
5ef3f0bd94 fix: resolve remaining review findings — explicit turnBoundary dependency and uniform missing-key handling
- user-approval: name the absent agent loop when the turnBoundary
  projection is not registered (instead of the misleading 'outside an
  open turn') and declare dsh-agent-loop as a peer dependency; add a
  regression test for the missing-unit composition (v4p).
- session-title / time-context / agent-instructions: converge the
  self-registered-key-absent handling to a loud throw with the same
  v8-ignored comment style (v5 suggestion).
2026-08-19 17:58:29 +08:00
_Kerman
58ebaa63d0 docs(notes): refresh superseded projection notes for the mandatory seam
Update in place the implemented notes whose mechanisms this stack changed:
the subagent list identity note drops the deleted
SUBAGENT_CONTROL_PROJECTIONS_UNAVAILABLE error contract and hostile-unit
probe for the required-injection seam; the durable-subagent-catalog note
drops the same stale error-code reference; the sandbox pair replaces the
effectiveSandboxMode/effectiveApprovalPolicy trio with the sandboxMode
projection unit on the required registry; the plan collaboration note
replaces foldPlanMode with the plan projection unit. EN/ZH in lock-step;
i18n pairing re-recorded.
2026-08-19 17:46:11 +08:00
_Kerman
2a4f6541d6 fix: revert the projection-registration form per review
Per the imccyu review, the pre-existing goal, permissions, and plan units
go back to registering through the ctx.inject(['sessionProjections'], …)
child form instead of the required-inject direct register; goal returns to
zero diff (its service never reads projections). The mandatory-seam rework
for these three sites moves to a follow-up PR. New projection units keep
the required-inject direct-register form.

Regenerated catalog and subsystem docs follow the reverted service
signatures.
2026-08-19 17:46:02 +08:00
_Kerman
abe572e7c4 merge: bring in the base's uniform checkpointing
Reconcile the base's persist removal and later master content with the
migration branch: keep 2742's wireOnly read options, the host-inclusive
snapshot/viewCheckpoint/restore defaults, and the drive's late-event
replay (applyToCell) that bare-session reads rely on.
2026-08-19 17:27:47 +08:00
_Kerman
86831ea9a2 docs(notes): date the mandatory projection-seam note 2026-08-19
The note was committed on 2026-08-19 but filed under 2026-08-07 while
building on the 08-19 state-and-client-views note; rename the triplet to
align the filename with the actual date and update the inbound
architecture links.
2026-08-19 16:59:07 +08:00
_Kerman
5ddbc6e71f refactor(session-projection): checkpoint every projection unit (migration side)
Adapts this branch to the base's removal of the persist opt-in: the
registry folds and checkpoints every registered unit, the host-only
subagent identity drops its explicit persist: true, and the
state-and-client-views note records the uniform rule. The cordis API
catalog and session-projection subsystem signatures are regenerated.
2026-08-19 16:59:00 +08:00
_Kerman
b0c2e2bf01 refactor(session-title): keep title input as an O(1) projection
The titleInput unit no longer retains the full eligible message history
in bounded reverse-linked chunks. It folds only {first, last, count} —
the values scheduling and fallback reads need — and the full eligible
prefix for one provider generation is scanned from the session log at
execution time. The projection state is O(1) per session instead of
growing with every user message.

The README description updates accordingly and drops the inaccurate
"latest request route" claim; the projection test now asserts the
bounded aggregate and its checkpoint row.
2026-08-19 16:58:53 +08:00
_Kerman
f364d6ba37 fix: address ds-review-bot findings on the projection migration
- llm-retry: validate config before registering the projection unit;
  document the branded-retry-id zod cast; start stateVersion at 1.
- agent-loop: register turnBoundary only after every config validation,
  so a rejected constructor leaves no unit behind; the defensive-cap
  test no longer needs fiber cleanup.
- agent-instructions: keep newest-first per-scope change history so the
  latest visible change survives a surface replacement shadowing the
  newest one (restores the previous scan-visible semantics); add a
  regression test for the delete-after-shadow sequence.
- tool-skill: keep catalog-message history so a shadowed newest catalog
  message still falls back to the latest visible digest.
- session-query-sqlite: drop the unused required sessionProjections
  injection.
- plan-mode: restore the command/done error-drop regression test and the
  cold-replay command/done fold; drop the inaccurate state-reference
  comment.
- tool-todo: remove a stray blank line; document the turnBoundary
  reader contract on the projection type.
2026-08-19 16:58:47 +08:00
pku-xht
ce46af97f2 Merge commit '84d329db60462a97ff7de82d8c7bd101676a3f0e' into codex/subprocess-win32-process-primitives 2026-08-19 16:19:10 +08:00
Yichen Jiang
3f5fc12b4c fix(web): restore settings focus after commit 2026-08-19 15:40:49 +08:00
pku-xht
f4caaf9697 Merge commit '698c1ce95b23d649a3fb21da13660ba23f063537' into codex/subprocess-win32-process-primitives 2026-08-19 15:06:36 +08:00
Yichen Jiang
c2a6f67e22 Merge remote-tracking branch 'origin/master' into worktree/fix-settings-focus 2026-08-19 14:38:07 +08:00
pku-xht
051851ac60 Merge commit '806f0f1ae7af106f12237bbd56cfe6f16b79cecb' into codex/subprocess-win32-process-primitives 2026-08-19 14:35:58 +08:00
pku-xht
5f6936b4f6 Merge commit 'ccadc8a43aca7c11d7a42b75ae8115730ce57e68' into codex/subprocess-win32-process-primitives 2026-08-19 14:28:39 +08:00
pku-xht
163fef7d64 Merge commit '881f7fe696c64e7775572680a38af07be6e9d158' into codex/subprocess-win32-process-primitives 2026-08-19 14:12:26 +08:00
_Kerman
acbb2532ab Merge remote-tracking branch 'origin/xtr/projection-state-schema' into xtr/session-projection-migrations
# Conflicts:
#	packages/subagent/subagent-claude-code/tests/real-product.spec.ts
#	packages/subagent/subagent-codex/tests/real-product.spec.ts
2026-08-19 14:03:36 +08:00
_Kerman
1a72ae202a refactor(session): migrate host state reads to projections 2026-08-19 13:57:58 +08:00
Turtle
907c6334c1 Remove Knip from repository tooling 2026-08-19 13:33:24 +08:00
_Kerman
34a04ab077 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2698
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-08-19 11:59:15 +08:00
_Kerman
64c11fa055 Merge remote-tracking branch 'origin/master' into xtr/session-format-migration 2026-08-19 11:18:37 +08:00
_Kerman
44feadea05 fix(session): load legacy compact events 2026-08-19 11:15:25 +08:00
_Kerman
c4b3f48e64 fix(session): address format migration review 2026-08-19 11:07:23 +08:00
pku-xht
a163f4019b fix(sandbox): preserve all drain failures 2026-08-19 08:58:12 +08:00
pku-xht
03186fe93f fix(sandbox): cancel sibling drain after child termination 2026-08-19 08:45:54 +08:00
pku-xht
60587b4901 fix(sandbox): cancel sibling drain on termination failure 2026-08-19 08:06:38 +08:00
pku-xht
8505d61f69 test(sandbox): remove duplicate failure assertion 2026-08-19 07:24:36 +08:00
pku-xht
9241ac22af test(sandbox): preserve rejection evidence 2026-08-19 07:21:00 +08:00
pku-xht
f9a264c76e test(sandbox): keep aggregate failure assertion typed 2026-08-19 07:15:00 +08:00
pku-xht
33e90e9919 fix(sandbox): terminate on first drain failure 2026-08-19 06:58:54 +08:00
pku-xht
5375142827 fix(sandbox): contain drain failure settlement 2026-08-19 06:35:50 +08:00
pku-xht
4605124732 ci(windows): exercise ABI probes on failover standby 2026-08-19 05:49:56 +08:00
pku-xht
4f381b83c9 refactor(win32-process): remove redundant suspension 2026-08-19 05:23:43 +08:00
pku-xht
5490a5e070 ci(windows): run ABI probes with MSVC 2026-08-19 05:09:38 +08:00
pku-xht
4a722de4fa fix(win32-process): close PR1 review gaps 2026-08-19 05:03:59 +08:00
pku-xht
ab494bfdca refactor(win32-process): narrow PR1 native surface 2026-08-19 04:39:31 +08:00
pku-xht
f1fd304dff fix(sandbox): memoize inherited settlement promise 2026-08-19 04:14:07 +08:00
pku-xht
e18564de03 chore(sandbox): align inherited wait lint 2026-08-19 04:11:59 +08:00
pku-xht
668da7f507 refactor(win32-process): share native process primitives 2026-08-19 04:08:46 +08:00
_Kerman
f73f2d9b65 docs(config): refresh persistence source link 2026-08-18 18:15:17 +08:00
_Kerman
44b676af68 Merge remote-tracking branch 'origin/master' into xtr/session-format-migration 2026-08-18 18:09:23 +08:00
_Kerman
d4ff836dc2 refactor(session-persistence): share stored read machinery 2026-08-18 18:06:48 +08:00
_Kerman
cc9ab200c7 feat(session): add format migration decoder pipeline 2026-08-18 17:42:40 +08:00
Tianyi Cui
3161ef4e59 Merge latest master into test/translation-prompt-snapshot-fixtures 2026-08-13 16:26:21 +08:00
Tianyi Cui
36cca40281 test: make the product translation fixture generic 2026-08-13 13:58:03 +08:00
Tianyi Cui
9d0ef6f5bb test: make the Agent Note translation fixture generic 2026-08-13 13:48:09 +08:00
Tianyi Cui
c1f368b493 Merge latest master into test/translation-prompt-snapshot-fixtures 2026-08-13 13:44:39 +08:00
Tianyi Cui
16d86cfba7 test: decouple the translation prompt snapshot from live documents
The snapshot embedded five live bilingual document pairs as reviewed
examples, so editing any of them (README, development guide, i18n docs)
churned the snapshot. Replace them with three synthetic fixture pairs
(product, rules, agent-note shapes) under scripts/fixtures; the prompt
examples stay representative without tracking real document content.
2026-08-13 13:07:57 +08:00
Tianyi Cui
5ad051a9cf Merge remote-tracking branch 'origin/master' into worktree/gate-package-subsystem-pages 2026-08-09 23:30:36 +08:00
Tianyi Cui
4125dac22d fix(docs): harden subsystem ownership links 2026-08-09 23:30:03 +08:00
Tianyi Cui
fb4554a9be Merge remote-tracking branch 'origin/master' into worktree/gate-package-subsystem-pages 2026-08-09 22:50:17 +08:00
Tianyi Cui
9d37d7155a test(docs): require package subsystem ownership 2026-08-09 22:50:01 +08:00
Yichen Jiang
8ac1bd64e2 fix(web): document settings focus restoration
Fixes #1407
2026-08-06 21:13:36 +08:00
Yichen Jiang
58c02e0c07 Merge remote-tracking branch 'origin/master' into worktree/fix-settings-focus 2026-08-06 16:41:55 +08:00
Yichen Jiang
f45f693d80 Merge remote-tracking branch 'origin/master' into worktree/fix-settings-focus 2026-08-06 15:08:07 +08:00
Yichen Jiang
0289791d5d fix(web): restore focus after closing settings 2026-08-06 14:21:56 +08:00
7739 changed files with 396858 additions and 172251 deletions

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.md
2026-06-18-shared-persistence-write-coordinator.md: 5c324f2c0c2b951f664bcf92725a36c4975fd3a1
2026-06-18-shared-persistence-write-coordinator.zh.md: 51ef76189cb9276214bf05bbd1dbd8e3755daa35

View file

@ -0,0 +1,53 @@
# Agent Note: Shared persistence write coordinator
Status: implemented
Archived: 2026-08-31
English | [中文](2026-06-18-shared-persistence-write-coordinator.zh.md)
## Problem
The JSONL provider needs correctness-heavy write orchestration around its storage primitives: per-Session state, `session/created` adoption, prefix reads, write-behind control, per-id operation serialization, HMR seeding, and dispose drains. Keeping that lifecycle in the Service Definition prevents an out-of-tree provider from copying it. The removed first-party database provider demonstrated the duplication cost; the [JSONL-only persistence decision](../simplification/2026-08-30-jsonl-only-session-persistence.md) owns its removal.
## Decision
`dsh-session-persistence` exports a backend-agnostic `PersistenceCoordinator`. The JSONL provider composes one (`new PersistenceCoordinator(ctx, this)`), implements the small `PersistenceBackend` hook interface, and delegates its stateful public methods (`create`/`append`/`prepare`/`load`/`inspect`/`readFrom`) to it. Backend-owned metadata and revision listing bypass the coordinator.
Composition, not inheritance. The coordinator is a concrete class the backend holds, not a base class the backend extends. The risk that a coordinator makes unusual backends fight an inheritance hierarchy is avoided: a backend exposes only the hooks and cannot reach the coordinator's private orchestration state. A third-party backend MAY still implement the abstract service directly without the coordinator, including immutable logical inspection and the default preparation fallback through `load`.
The coordinator holds one lifecycle entry for each exact live `Session`: initialization plus a package-private write controller that owns pending events, a fixed batching deadline, the active write, failure retention, and the shared flush barrier. Each `session/event` enters that bounded write path, and `session/flush` bypasses the wait to observe quiescence. The [flush-controller simplification](../simplification/2026-07-23-collapse-persistence-flush-state.md) owns controller consolidation; the [bounded batching decision](2026-08-08-bounded-session-persistence-write-batching.md) owns scheduling cadence.
Creation borrows the exact `Session.events` snapshot as its persistence seed. `Session` has already detached, validated, and deeply frozen every event, and the snapshot array remains stable when later appends replace the cached view. The coordinator and its backend hooks only read this typed in-process value, so cloning the complete log again would duplicate the ownership work described by the [agent-scope runtime decision](2026-07-12-agent-scope-runtime-design.md#session-append-materialize-validate-commit-notify). Public persistence `append()` still snapshots caller-owned input at its API boundary.
Prepared-session suffixes and events admitted to the write-behind queue retain their existing copies. Those paths establish asynchronous queue ownership one suffix or event at a time and have no measured whole-log clone cost; removing their copies remains a separate ownership audit rather than part of creation-seed borrowing.
The coordinator retires a session from `session/disposed`: it waits for the controller's initialization and current flush, serializes a final drain, and removes the controller and owned per-id state only after success. A failure leaves the controller discoverable for backend teardown to retry. Settled per-id chain tails remove themselves only when they are still current, so a completion cannot erase a newer operation for the same id. Backend teardown unregisters write-path listeners, flushes every remaining controller, awaits per-id operations, and then closes the backend.
### The hook interface (`PersistenceBackend<TornMarker>`)
Five required members plus optional empty-materialization and lifecycle hooks form the only boundary between the coordinator and storage:
- `name` — backend label for the dispose-failure `AggregateError`.
- `loadStored(id)` — read one stored prefix by id across every storage scope. Preparation, logical load/inspection, physical suffix reads, live adoption, and the create-collision probe share this lookup. The coordinator asserts the returned id and rejects a stored/live cwd mismatch before repair or state publication.
- `appendBatch(meta, events, isMaterialized)` — durably append a contiguous batch, lazily materializing the session ATOMICALLY when not yet materialized. Ordinary creation therefore cannot leave an abandoned materialized-but-empty session.
- `materializeHeader?(meta)` — explicitly persist a header-only session for `SessionPersistence.ensureMaterialized(session)`. This is reserved for a lifecycle frontend that treats an empty session itself as a resumable durable resource; [standard ACP automation controls](../feature/2026-08-22-standard-acp-automation-controls.md) are the first consumer. Backends that support that lifecycle implement the hook; lazy creation remains the default.
- `commitRepair(meta, tornMarker, closers)` — make a crash repair durable: truncate the torn tail (iff `tornMarker !== undefined`) and append `closers`. **NOT required to be atomic** — JSONL legitimately truncates then appends in two fsync'd steps. Used by `prepare`/`load` (truncate + synthetic closers) and live adoption (truncate only, `closers = []`).
- `list()` — list all stored metadata.
- `close?()` — optional lifecycle teardown for a provider with owned resources; JSONL omits it. The dispose effect awaits it after the quiescence drain so a close failure never masks a drain error.
### The opaque torn marker
The single design choice that keeps the seam clean: the crash-repair "where is the torn tail" token is opaque to the coordinator. The coordinator computes the synthetic closers (it owns `interruptedTurnClosers` from `dsh-session`), but it only tests `tornMarker !== undefined` and passes the value straight back to `commitRepair`; it never inspects it. JSONL carries the byte offset to truncate to plus any complete events decoded from an incomplete final frame, while another provider may choose its own marker type. The coordinator therefore knows neither byte lengths nor frame recovery state.
## Testing
The shared `runPersistenceContract` proves that JSONL `inspect` balances an interrupted logical view without changing storage or revisions before `prepare` or `load` commits recovery. `runCoordinatorContract` (`tests/coordinator-contract.ts`) covers adoption, HMR, collision, Session and provider disposal drains, and crash-tail repair through an in-memory reference and JSONL. `persistence.spec.ts`, `preparations.spec.ts`, and `write-behind.spec.ts` cover preparation reuse and reservation, bounded prepared-state eviction, fixed-window follow-up batches, live-controller cleanup, same-id chain-tail races, failed-batch retry, and close ordering. JSONL specs retain storage mechanics and the through-coordinator torn-tail case that exercises the opaque-marker branch.
## Alternatives considered
- **A base class the backends extend** — rejected for composition: a backend exposes only the hooks, cannot reach the coordinator's private orchestration state, and a third-party backend may still implement the abstract service directly without the coordinator at all.
- **A wider hook API** — each candidate hook folds away: there is no scope-specific live lookup because `loadStored` plus the coordinator's cwd check preserves the collision boundary, no storage-locator generic because validated JSONL metadata reproduces its path, no separate `materialize` hook because the first batch must commit atomically with materialization, no separate create-collision probe because it is `loadStored(id) !== undefined`, and no coordinator pass-through for `list()` because listing needs none of the orchestration.
## Consequences
The coordinator adds one indirection, an opaque torn marker, detached Session-retirement tasks, and bounded prepared Session state, but centralizes correctness-heavy orchestration for the JSONL provider and future implementations. Session disposal remains an observe-only event, so the Session owner does not await persistence retirement; the coordinator contains failures, preserves pending events in the live controller, and makes provider teardown the quiescence boundary. Its hook surface stays narrow: identity, adoption, collision checks, preparation, and immutable inspection reuse `loadStored`; materialization stays atomic inside `appendBatch`; and listing bypasses the coordinator. Read models use `inspect` rather than `load`, so observing a persisted open turn does not commit interruption closers; the [Session preparation decision](2026-08-05-session-preparation.md) owns reuse, reservation, and publication. A new provider implements storage primitives rather than copy the bounded write lifecycle.

View file

@ -0,0 +1,53 @@
# Agent Note: 共享持久化写入协调器
Status: implemented
Archived: 2026-08-31
[English](2026-06-18-shared-persistence-write-coordinator.md) | 中文
## 问题
JSONL provider 需要在其存储原语周围执行对正确性要求很高的写入编排:逐 Session 状态、`session/created` 接管、前缀读取、write-behind 控制、按 id 串行执行、HMR 种子注入与 dispose 排空。把该生命周期放在 Service Definition 中,可以避免仓库外 provider 重复实现。已删除的 first-party 数据库 provider 证明了这种重复成本;其删除由 [JSONL-only 持久化决策](../simplification/2026-08-30-jsonl-only-session-persistence.zh.md)负责。
## 决策
`dsh-session-persistence` 导出后端无关的 `PersistenceCoordinator`。JSONL provider 组合一个协调器实例(`new PersistenceCoordinator(ctx, this)`)、实现小型 `PersistenceBackend` 钩子接口,并把有状态公开方法(`create`/`append`/`prepare`/`load`/`inspect`/`readFrom`)委托给协调器。由后端拥有的元数据与修订版本列举会绕过协调器。
组合,而非继承。协调器是后端持有的具体类,不是后端继承的基类。协调器让非常规后端与继承层级作斗争的风险由此规避:后端只暴露钩子,无法触及协调器的私有编排状态。第三方后端仍然可以完全不使用协调器、直接实现抽象服务,包括不可变逻辑检查,以及通过 `load` 实现的默认准备回退。
协调器为每个存活的 `Session` 实例持有一个生命周期条目:初始化,加上一个包私有写入控制器,后者负责待处理事件、固定批处理截止时间、活跃写入、失败保留和共享 flush 屏障。每个 `session/event` 都进入这条有界写入路径,`session/flush` 则绕过等待以观察完全停稳。控制器归并由 [flush 控制器简化](../simplification/2026-07-23-collapse-persistence-flush-state.zh.md)定义;调度节奏由[有界批处理决策](2026-08-08-bounded-session-persistence-write-batching.zh.md)定义。
创建流程将 `Session.events` 的原始快照借作持久化种子。`Session` 已经分离、验证并深度冻结每个事件,后续追加会替换缓存视图,因此该快照数组保持稳定。协调器及其后端钩子只读取这个有类型的进程内值;再次克隆完整日志会重复 [agent scope 运行时决策](2026-07-12-agent-scope-runtime-design.zh.md#session-append-materialize-validate-commit-notify)规定的所有权工作。持久化服务的公开 `append()` 仍在 API 边界为调用方拥有的输入创建快照。
已准备 Session 的后缀,以及进入 write-behind 队列的事件,仍保留现有复制。这些路径会逐个后缀或事件建立异步队列所有权,且没有已测得的完整日志克隆成本;移除这些复制属于单独的所有权审计,不属于创建种子的借用决策。
协调器通过 `session/disposed` 退役会话:它等待控制器完成初始化和当前 flush,串行执行最后一次排空,且仅在成功后才移除控制器与其拥有的每 id 状态。失败时保持控制器可被找到,以供后端 teardown(拆除)重试。每个 id 的已结算链尾仅在其仍是当前链尾时才移除自身,因此旧操作完成后不会抹除同一 id 的新操作。后端 teardown 会注销写入路径监听器、flush 每个剩余的控制器、等待所有按 id 串行化的操作,最后关闭后端。
### 钩子接口(`PersistenceBackend<TornMarker>`)
五个必需成员加可选的空会话实体化与生命周期钩子,构成协调器与存储之间唯一的边界:
- `name`——后端标签,用于 dispose 失败时的 `AggregateError`。
- `loadStored(id)`——按 id 跨所有存储范围读取一个已存储前缀。准备、逻辑加载/检查、物理后缀读取、存活会话接管与创建碰撞探测共用此查找。协调器会断言返回的 id,并在修复或发布状态之前拒绝已存储记录与存活会话的 cwd 不匹配。
- `appendBatch(meta, events, isMaterialized)`——持久追加一个连续批次,在尚未物化时原子地惰性物化会话。因此,普通创建不会留下被放弃的已物化空会话。
- `materializeHeader?(meta)`——为 `SessionPersistence.ensureMaterialized(session)` 显式持久化仅含 header 的会话。它只供把空会话本身视为可恢复持久资源的生命周期前端使用;[标准 ACP 自动化控制](../feature/2026-08-22-standard-acp-automation-controls.zh.md)是第一个 consumer。支持该生命周期的后端实现此钩子;惰性创建仍是默认行为。
- `commitRepair(meta, tornMarker, closers)`——使崩溃修复持久化:截断损坏的尾部(当且仅当 `tornMarker !== undefined`)并追加 `closers`。**不要求原子性**——JSONL 合理地分两步 fsync,先截断再追加。用于 `prepare`/`load`(截断 + 合成收尾事件)和存活会话接管(仅截断,`closers = []`)。
- `list()`——列出所有已存储的元数据。
- `close?()`——供拥有资源的 provider 使用的可选生命周期清理;JSONL 省略该钩子。dispose effect 在排空至完全停稳后 await 它,因此 close 失败不会掩盖排空错误。
### 不透明的 torn marker
保持 seam 整洁的唯一设计选择:崩溃修复中「损坏尾部在哪里」的 token 对协调器是不透明的。协调器计算合成收尾事件(它拥有来自 `dsh-session` 的 `interruptedTurnClosers`),但只测试 `tornMarker !== undefined` 并将值原样传回 `commitRepair`,从不检视其内容。JSONL 携带要截断到的字节偏移,以及从不完整最终帧中解码出的任何完整事件;其他 provider 可以选择自己的 marker 类型。协调器因此既不了解字节长度,也不了解帧恢复状态。
## 测试
共享 `runPersistenceContract` 证明 JSONL 的 `inspect` 会配平被中断的逻辑视图但不改变存储或修订版本,随后由 `prepare` 或 `load` 提交恢复。`runCoordinatorContract`(`tests/coordinator-contract.ts`)通过内存参考实现与 JSONL 覆盖接管、HMR、碰撞、Session 与 provider dispose 排空和崩溃尾部修复。`persistence.spec.ts`、`preparations.spec.ts` 与 `write-behind.spec.ts` 覆盖准备复用与预留、有界准备状态淘汰、固定窗口后续批次、存活控制器清理、同 id 链尾竞态、失败批次重试与关闭顺序。JSONL 规格保留存储机制,以及覆盖不透明 marker 分支的经由协调器崩溃尾部用例。
## 曾考虑的替代方案
- **后端继承的基类**——否决,改用组合:后端只暴露钩子,无法触及协调器的私有编排状态,且第三方后端仍可完全不使用协调器、直接实现抽象服务。
- **更宽的钩子 API**——每个候选钩子都被折叠掉:没有限定存储范围的存活会话查找,因为 `loadStored` 加上协调器的 cwd 检查即可维持碰撞边界;没有存储定位器泛型,因为经验证的 JSONL 元数据可还原其路径;没有单独的 `materialize` 钩子,因为首批事件必须与物化原子提交;没有单独的创建碰撞探测,因为它就是 `loadStored(id) !== undefined`;`list()` 也不经由协调器透传,因为列举不需要任何编排。
## 后果
协调器增加一层间接、一个不透明 torn marker、脱离 Session 生命周期的退役任务,以及有界的已准备 Session 状态,但为 JSONL provider 与未来实现集中管理对正确性要求很高的编排。Session dispose 仍是仅观察事件,因此 Session owner 不等待持久化退役;协调器收容失败、在存活控制器中保留待处理事件,并以 provider teardown 为完全停稳边界。其钩子面保持窄小:标识校验、接管、碰撞检查、准备与不可变检查共用 `loadStored`;物化保持在 `appendBatch` 内原子完成;列举绕过协调器。读模型使用 `inspect` 而非 `load`,因此观察已持久化但仍开放的轮次时不会提交中断收尾事件;复用、预留与发布由 [Session 准备阶段决策](2026-08-05-session-preparation.zh.md)定义。新 provider 只需实现存储原语,而无需复制有界写入生命周期。

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/archived/architecture/2026-07-19-gui-layering-and-rpc-protocol.md
2026-07-19-gui-layering-and-rpc-protocol.md: b27d8d024612d890819bfca9b43c0c81464dfdd3
2026-07-19-gui-layering-and-rpc-protocol.zh.md: 3cf4ba6421c7332c1f8cebb61656a1546f3ad45f

View file

@ -1,6 +1,7 @@
# Agent Note: GUI layering and the RPC protocol — host/client layering by capability provider, the four-quadrant message model, and the fetch carrier # Agent Note: GUI layering and the RPC protocol — host/client layering by capability provider, the four-quadrant message model, and the fetch carrier
Status: implemented Status: implemented
Archived: 2026-08-27
English | [中文](2026-07-19-gui-layering-and-rpc-protocol.zh.md) English | [中文](2026-07-19-gui-layering-and-rpc-protocol.zh.md)
@ -209,7 +210,7 @@ The same domain tree as `ApiProxy`, but unary methods **take the business payloa
### The instance-level envelope observation aspect ### The instance-level envelope observation aspect
All four quadrant full forms pass through `onEnvelope`; the base implementation is an **instance-owned microtask-batched buffer** (frame storms must not disturb consumers per frame; module-level state would leak across instances/tests, hence instance-owned). Observers subscribe via `subscribeEnvelopes(listener)` (receiving whole batches as `readonly RpcMessage[]`, returning an unsubscribe function); a listener throw is isolated (observation must never bite the carrier). With no subscribers the buffering costs nothing. No shipped consumer subscribes today — the aspect is the designated seat for wire diagnostics (the retired RPC debug panel was its first consumer, and a future one plugs in without touching the carrier). All four quadrant full forms pass through `onEnvelope`; the base implementation is an **instance-owned microtask-batched buffer** (frame storms must not disturb consumers per frame; module-level state would leak across instances/tests, hence instance-owned). Observers subscribe via `subscribeEnvelopes(listener)` (receiving whole batches as `readonly RpcMessage[]`, returning an unsubscribe function); a listener throw is isolated (observation must never bite the carrier). With no subscribers the buffering costs nothing. No shipped consumer subscribes — the aspect is the designated seat for wire diagnostics (the retired RPC debug panel was its first consumer, and a future one plugs in without touching the carrier).
### The subclass table (transport carriage) ### The subclass table (transport carriage)

View file

@ -1,6 +1,7 @@
# Agent Note: GUI 分层与 RPC 协议——host/client 按能力提供方分层、四象限消息模型与 fetch 载体 # Agent Note: GUI 分层与 RPC 协议——host/client 按能力提供方分层、四象限消息模型与 fetch 载体
Status: implemented Status: implemented
Archived: 2026-08-27
[English](2026-07-19-gui-layering-and-rpc-protocol.md) | 中文 [English](2026-07-19-gui-layering-and-rpc-protocol.md) | 中文
@ -207,7 +208,7 @@ export type ResponseValue<K> =
### 实例级 envelope 观测切面 ### 实例级 envelope 观测切面
四象限全形均过 `onEnvelope`;基类实现是**实例持有的微任务合批缓冲**(帧风暴不逐帧惊扰消费方;模块级状态会跨实例/测试泄漏,故实例持有)。观测者经 `subscribeEnvelopes(listener)` 订阅(收整批 `readonly RpcMessage[]`,返回退订函数);listener 抛异常被隔离(观测不得反噬载体)。无订阅者时零缓冲成本。当前没有任何现役消费方订阅——该切面是 wire 诊断的预留位(已退役的 RPC 调试面板是它的首个消费方,将来的诊断消费方接入时不动载体)。 四象限全形均过 `onEnvelope`;基类实现是**实例持有的微任务合批缓冲**(帧风暴不逐帧惊扰消费方;模块级状态会跨实例/测试泄漏,故实例持有)。观测者经 `subscribeEnvelopes(listener)` 订阅(收整批 `readonly RpcMessage[]`,返回退订函数);listener 抛异常被隔离(观测不得反噬载体)。无订阅者时零缓冲成本。没有任何已交付消费方订阅——该切面是 wire 诊断的预留位(已退役的 RPC 调试面板是它的首个消费方,将来的诊断消费方接入时不动载体)。
### 子类表(传输承载) ### 子类表(传输承载)

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/archived/architecture/2026-08-04-websocket-downlink-carrier.md
2026-08-04-websocket-downlink-carrier.md: 5edcdd95cf2845d455a61930a9fc00e7e57e72eb
2026-08-04-websocket-downlink-carrier.zh.md: 213697effb8655583e7c420e58acfd171261a8d8

View file

@ -1,6 +1,7 @@
# Agent Note: WebSocket carrier for browser downlinks # Agent Note: WebSocket carrier for browser downlinks
Status: implemented Status: implemented
Archived: 2026-08-27
English | [中文](2026-08-04-websocket-downlink-carrier.zh.md) English | [中文](2026-08-04-websocket-downlink-carrier.zh.md)
@ -16,7 +17,7 @@ WebSocket carries only the host→browser downlink. All client→host unary call
## Upgrade and lifecycle boundaries ## Upgrade and lifecycle boundaries
`dsh-host-webserver` provides an exact upgrade-route registration point alongside ordinary routes, dispatches Node upgrade sockets by pathname only, contains raw-socket errors, and waits for surviving upgraded connections to close during server teardown; it knows nothing about Harness frames or WebSocket messages. `dsh-client-connection` owns the WebSocket handshake, frame output, and stream cancellation, and reuses the `/api` Host/Origin trust fence before upgrade. An untrusted authority or cross-origin Origin is rejected before `ctx.apiProxy.events.*` starts. `dsh-host-webserver` provides an exact upgrade-route registration point alongside ordinary routes, dispatches Node upgrade sockets by pathname only, contains raw-socket errors, and waits for surviving upgraded connections to close during server teardown; it knows nothing about Harness frames or WebSocket messages. `dsh-client-connection` owns the WebSocket handshake, frame output, and stream cancellation. Before upgrade it applies the `/api` Host/Origin checks followed by the same signed browser-cookie authentication as unary HTTP. An untrusted authority or cross-origin Origin receives 403; a trusted but unauthenticated request receives 401; neither starts a Remote stream.
A browser abort or socket close cancels the corresponding host stream; plugin teardown also waits for that source iterator's cleanup. If a host stream throws midway, the carrier sends one existing `stream/error` frame and then closes the socket; the client treats that frame as connection loss rather than delivering it to a business sink. Each WebSocket reports open independently, and the existing readiness handshake still waits until mux and host are both open and the `host.describe` HTTP call has succeeded before publishing connected. A browser abort or socket close cancels the corresponding host stream; plugin teardown also waits for that source iterator's cleanup. If a host stream throws midway, the carrier sends one existing `stream/error` frame and then closes the socket; the client treats that frame as connection loss rather than delivering it to a business sink. Each WebSocket reports open independently, and the existing readiness handshake still waits until mux and host are both open and the `host.describe` HTTP call has succeeded before publishing connected.

View file

@ -1,6 +1,7 @@
# Agent Note: 浏览器下行 WebSocket 载体 # Agent Note: 浏览器下行 WebSocket 载体
Status: implemented Status: implemented
Archived: 2026-08-27
[English](2026-08-04-websocket-downlink-carrier.md) | 中文 [English](2026-08-04-websocket-downlink-carrier.md) | 中文
@ -16,7 +17,7 @@ WebSocket 只承担 host→browser 下行。所有 client→host unary 调用和
## Upgrade 与生命周期边界 ## Upgrade 与生命周期边界
`dsh-host-webserver` 提供与普通 route 并列的精确 upgrade-route 注册点,只按 pathname 分发 Node upgrade socket,隔离原始 socket 错误,并在 server teardown 期间等待仍存活的升级连接关闭;它不认识 Harness 帧或 WebSocket 消息。`dsh-client-connection` 拥有 WebSocket handshake、frame 写出和流取消,并在 upgrade 前复用 `/api` 的 Host/Origin 信任栅栏。未受信任的 authority 或跨来源 Origin 在 `ctx.apiProxy.events.*` 启动前即被拒绝。 `dsh-host-webserver` 提供与普通 route 并列的精确 upgrade-route 注册点,只按 pathname 分发 Node upgrade socket,隔离原始 socket 错误,并在 server teardown 期间等待仍存活的升级连接关闭;它不认识 Harness 帧或 WebSocket 消息。`dsh-client-connection` 拥有 WebSocket handshake、frame 写出和流取消。upgrade 前先执行 `/api` Host/Origin 校验,再执行与一元 HTTP 相同的签名浏览器 cookie 认证。未受信任的 authority 或跨来源 Origin 得到 403;Host 可信但未认证的请求得到 401;两者都不会启动 Remote stream。
浏览器 abort 或 socket close 会取消对应的 host 流;插件 teardown 还会等待该 source iterator 完成清理。host 流中途抛错时,载体发送一个现有的 `stream/error` frame 后关闭 socket;客户端把该 frame 收敛为连接丢失,不投递给业务 sink。每条 WebSocket 独立报告 open,既有 readiness handshake 仍等待 mux、host 都 open 且 `host.describe` HTTP 调用成功后才发布 connected。 浏览器 abort 或 socket close 会取消对应的 host 流;插件 teardown 还会等待该 source iterator 完成清理。host 流中途抛错时,载体发送一个现有的 `stream/error` frame 后关闭 socket;客户端把该 frame 收敛为连接丢失,不投递给业务 sink。每条 WebSocket 独立报告 open,既有 readiness handshake 仍等待 mux、host 都 open 且 `host.describe` HTTP 调用成功后才发布 connected。

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-11-plugin-settings-tabs.md: 1f1701e000b891b4fc00bc666f603ee00bae50a7
2026-08-11-plugin-settings-tabs.zh.md: f76a4a9e2317eb6603b48e1a7e451abdc55e00ff

View file

@ -1,6 +1,7 @@
# Agent Note: Feature-owned tabs in Plugins settings # Agent Note: Feature-owned tabs in Plugins settings
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-11-plugin-settings-tabs.zh.md) English | [中文](2026-08-11-plugin-settings-tabs.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: “插件”设置中的功能自有标签页 # Agent Note: “插件”设置中的功能自有标签页
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-11-plugin-settings-tabs.md) | 中文 [English](2026-08-11-plugin-settings-tabs.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-18-sqlite-physical-chunk-row-compression.md
2026-08-18-sqlite-physical-chunk-row-compression.md: 031e9a27575b9e802718dac040f9735335d39d0a
2026-08-18-sqlite-physical-chunk-row-compression.zh.md: 1bc493c690de12c5eb9805f615cc32280cc3e608

View file

@ -1,6 +1,7 @@
# Agent Note: SQLite physical chunk-row compression # Agent Note: SQLite physical chunk-row compression
Status: implemented Status: implemented
Archived: 2026-08-30
English | [中文](2026-08-18-sqlite-physical-chunk-row-compression.zh.md) English | [中文](2026-08-18-sqlite-physical-chunk-row-compression.zh.md)
@ -12,15 +13,15 @@ A physical row that represents several events affects append contiguity, crash r
## Decision ## Decision
`@deepseek-ai/dsh-session-persistence-sqlite` uses the packed schema-17 implementation. It is the only SQLite persistence package and provider; the predecessor scalar layout and the temporary versioned sibling are not retained. SQLite remains an opt-in switch, while shipped default compositions continue to use JSONL. Both backends implement the same `SessionPersistence` service through `PersistenceCoordinator`, so physical packing changes neither live event delivery nor the logical session API. `@deepseek-ai/dsh-session-persistence-sqlite` uses the packed schema-20 implementation. It is the only SQLite persistence package and provider; the predecessor scalar layout and the temporary versioned sibling are not retained. SQLite remains an opt-in switch, while shipped default compositions continue to use JSONL. Both backends implement the same `SessionPersistence` service through `PersistenceCoordinator`, so physical packing changes neither live event delivery nor the logical session API.
Schema 17 keeps ordinary ROWID tables and the composite `events(session_id, seq)` primary-key index. Scalar rows represent one logical event. Packed rows use the storage tags `text-chunks`, `reasoning-chunks`, and `tool-call-chunks`; the SQL `seq` and `time` columns hold the first logical member, and `data` holds the packed payload. Packed rows set `ignorable=0` as a physical discriminator and leave `source_event_seqs` and `surface_op` as `NULL`; scalar rows use `ignorable=1` only for logical ignorable events and `NULL` otherwise. A future ignorable logical event may therefore reuse a storage-tag name without being decoded as a packed row. The tags are storage vocabulary, not `SessionEventMap` members. Schema 20 keeps ordinary ROWID tables and the composite `events(session_id, seq)` primary-key index. Scalar rows represent one logical event. Packed rows use the storage tags `text-chunks`, `reasoning-chunks`, and `tool-call-chunks`; the SQL `seq` and `time` columns hold the first logical member, and `data` holds the packed payload. Packed rows set `ignorable=0` as a physical discriminator and leave `source_event_seqs` and `surface_op` as `NULL`; scalar rows use `ignorable=1` only for logical ignorable events and `NULL` otherwise. A future ignorable logical event may therefore reuse a storage-tag name without being decoded as a packed row. The tags are storage vocabulary, not `SessionEventMap` members.
SQLite owns chunk encoding and validation inside the schema-17 package. Exact-field whitelisting means unknown fields, surface metadata, incompatible chunk identity, sequence gaps, and unsafe timestamps remain scalar rather than losing information. One packed row represents at most 1,024 events and 1 MiB of uncompressed UTF-8 `data`; the encoder partitions longer runs, and the decoder rejects rows outside those format limits. SQLite owns chunk encoding and validation inside the schema-20 package. Exact-field whitelisting means unknown fields, surface metadata, incompatible chunk identity, sequence gaps, and unsafe timestamps remain scalar rather than losing information. One packed row represents at most 1,024 events and 1 MiB of uncompressed UTF-8 `data`; the encoder partitions longer runs, and the decoder rejects rows outside those format limits.
The `data` column accepts `TEXT` or `BLOB`. Serialized values below 4 KiB remain text. At or above the threshold, the writer uses Zstandard level 3 and retains the frame only when it is smaller than the text; the reader decompresses the blob before strict UTF-8 decoding and JSON parsing. The fixed moderate level and threshold limit frame overhead and synchronous CPU work while capturing the repeated payloads that dominate retained bytes. The `data` column accepts `TEXT` or `BLOB`. Serialized values below 4 KiB remain text. At or above the threshold, the writer uses Zstandard level 3 and retains the frame only when it is smaller than the text; the reader decompresses the blob before strict UTF-8 decoding and JSON parsing. The fixed moderate level and threshold limit frame overhead and synchronous CPU work while capturing the repeated payloads that dominate retained bytes.
`source_event_seqs` remains the complete ordered list of earlier events cited by a surface node, including every streamed chunk behind an assembled assistant message. Schema 17 stores the first sequence as an unsigned varint and every subsequent signed difference as a ZigZag varint. This preserves arbitrary order and every sequence while exploiting the overwhelmingly consecutive lists produced by streaming. An empty list is an empty non-null blob, distinct from absent provenance. `source_event_seqs` remains the complete ordered list of earlier events cited by a surface node, including every streamed chunk behind an assembled assistant message. Schema 20 stores the first sequence as an unsigned varint and every subsequent signed difference as a ZigZag varint. This preserves arbitrary order and every sequence while exploiting the overwhelmingly consecutive lists produced by streaming. An empty list is an empty non-null blob, distinct from absent provenance.
### Transactional append packing ### Transactional append packing
@ -32,11 +33,11 @@ Normal append never deletes or replaces an earlier event row. Fixed write-behind
Full reads decode each physical row as one all-or-nothing logical span and validate contiguous logical sequences. A reverse pass identifies the last valid `turn/end` without retaining a second decoded copy of the full physical scan; the forward pass decodes one row at a time into the required logical result. A malformed row or gap before that committed boundary is corruption; a malformed final physical row becomes the opaque repair marker at that row's base sequence. Recovery re-reads and validates that marker while holding the write lock, then deletes the whole physical row and any later rows before binding synthetic closers as scalar events. A stale repair cannot delete a newer writer's valid suffix. Full reads decode each physical row as one all-or-nothing logical span and validate contiguous logical sequences. A reverse pass identifies the last valid `turn/end` without retaining a second decoded copy of the full physical scan; the forward pass decodes one row at a time into the required logical result. A malformed row or gap before that committed boundary is corruption; a malformed final physical row becomes the opaque repair marker at that row's base sequence. Recovery re-reads and validates that marker while holding the write lock, then deletes the whole physical row and any later rows before binding synthetic closers as scalar events. A stale repair cannot delete a newer writer's valid suffix.
`readFrom(id, fromSeq)` examines packed predecessors only within the maximum schema-17 row span, then reads from the earliest candidate that may contain `fromSeq`. The decoder filters reconstructed members below `fromSeq`, so a suffix may begin inside a packed row without parsing an unrelated earlier scalar row. Reading from that candidate also exposes an overlapping scalar row to contiguity validation instead of letting it hide the packed member. Packed data exceeding the uncompressed format byte limit rejects before JSON parsing. `readFrom(id, fromSeq)` examines packed predecessors only within the maximum schema-20 row span, then reads from the earliest candidate that may contain `fromSeq`. The decoder filters reconstructed members below `fromSeq`, so a suffix may begin inside a packed row without parsing an unrelated earlier scalar row. Reading from that candidate also exposes an overlapping scalar row to contiguity validation instead of letting it hide the packed member. Packed data exceeding the uncompressed format byte limit rejects before JSON parsing.
### Schema ownership ### Schema ownership
A pristine database initializes at schema 17. Older physical schemas, foreign application identities, non-pristine unversioned databases, and incompatible schema objects reject; the pre-release package supplies no migration. Every connection disables trusted schemas and memory-mapped I/O before inspecting durable schema, then reads both settings back. After selecting and verifying the journal mode, the provider pins `synchronous=FULL` and verifies it so SQLite build defaults cannot weaken committed-append durability. Package code loads every statement and fixed pragma from closed-name `.sql` resources and binds runtime values as parameters. A pristine database initializes at schema 20. Older physical schemas, foreign application identities, non-pristine unversioned databases, and incompatible schema objects reject; the pre-release package supplies no migration. Every connection disables trusted schemas and memory-mapped I/O before inspecting durable schema, then reads both settings back. After selecting and verifying the journal mode, the provider pins `synchronous=FULL` and verifies it so SQLite build defaults cannot weaken committed-append durability. Package code loads every statement and fixed pragma from closed-name `.sql` resources and binds runtime values as parameters.
### Physical-write regression ### Physical-write regression
@ -58,11 +59,11 @@ The repository regression guard writes 1,000 streamed deltas in 40-event durable
**Compress every payload.** Rejected because small independent Zstandard frames add headers and synchronous CPU work while losing the cross-record dictionary opportunity of a whole-file stream. On the 105-session comparison corpus, a threshold sweep produced 75.01 MB at 4 KiB, versus 93.87 MB at 16 KiB and 60.92 MB at 1 KiB. The writer fixes level 3 rather than inheriting a library default, matching the moderate level used by [Codex cold-rollout compression](https://github.com/openai/codex/blob/main/codex-rs/rollout/src/compression.rs) while retaining independent row access. **Compress every payload.** Rejected because small independent Zstandard frames add headers and synchronous CPU work while losing the cross-record dictionary opportunity of a whole-file stream. On the 105-session comparison corpus, a threshold sweep produced 75.01 MB at 4 KiB, versus 93.87 MB at 16 KiB and 60.92 MB at 1 KiB. The writer fixes level 3 rather than inheriting a library default, matching the moderate level used by [Codex cold-rollout compression](https://github.com/openai/codex/blob/main/codex-rs/rollout/src/compression.rs) while retaining independent row access.
The final frozen comparison used 105 sessions, 2,507,860 logical events, 512-event durable batches, three independent builds per backend, and three read passes per build. SQLite used 75.01 MB, wrote in 8.58 s, read complete sessions at 3.95/21.58 ms p50/p95, read 50-event tails at 0.253/0.378 ms, and forked every session in 13.10 s. Zstandard JSONL used 30.65 MB and measured 28.21 s, 4.49/23.36 ms, 10.58/80.90 ms, and 14.48 s. The predecessor scalar SQLite layout used 709.57 MB and measured 10.64 s, 9.02/69.16 ms, 0.189/0.293 ms, and 19.30 s. The packed layout is 89.4% smaller than the predecessor, writes 19.4% faster, improves complete-read p50/p95 by 56.2%/68.8%, and reduces 2,507,860 physical event rows to 65,810. Scalar tail-50 and list micro-latency are lower, but the packed provider remains materially faster than JSONL on those paths and wins the dominant size, write, full-read, and fork costs. The 4 KiB threshold is the accepted balance rather than a strict dominance claim. The final frozen comparison used 105 sessions, 2,507,860 logical events, 512-event durable batches, three independent builds per backend, and three read passes per build. SQLite used 75.01 MB, wrote in 8.58 s, read complete sessions at 3.95/21.58 ms p50/p95, read 50-event tails at 0.253/0.378 ms, and forked every session in 13.10 s. Zstandard JSONL used 30.65 MB and measured 28.21 s, 4.49/23.36 ms, 10.58/80.90 ms, and 14.48 s. The predecessor scalar SQLite layout used 709.57 MB and measured 10.64 s, 9.02/69.16 ms, 0.189/0.293 ms, and 19.30 s. The packed layout is 89.4% smaller than the predecessor, writes 19.4% faster, improves complete-read p50/p95 by 56.2%/68.8%, and reduces 2,507,860 physical event rows to 65,810. Scalar tail-50 and list micro-latency are lower, but the packed provider remains materially faster than JSONL on those paths and wins the dominant size, write, full-read, and fork costs. The 4 KiB threshold is the accepted balance rather than a strict dominance claim. This comparison measured schema 17; its exact values are evidence for the original packed-row decision, not schema-20 measurements. The [persistence latency and page-size decision](2026-08-25-persistence-latency-and-page-size.md) owns the schema-19 benchmark and current encoding refinements.
**Store packed payloads under the logical `assistant/chunk` type.** Rejected because payload heuristics make malformed rows ambiguous and couple physical decoding to future logical payload fields. Explicit tags fail loudly. **Store packed payloads under the logical `assistant/chunk` type.** Rejected because payload heuristics make malformed rows ambiguous and couple physical decoding to future logical payload fields. Explicit tags fail loudly.
**Store `SessionHeader` fields in an extensible metadata blob.** Rejected for schema 17 because `agentPreset` is a typed core resume invariant shared by JSONL and SQLite, not provider extension metadata. Persisting validated core fields directly keeps both backends aligned; an untyped catch-all would add another compatibility mechanism without a current producer. Revisit this only with a core-owned, namespaced `SessionHeader` extension protocol implemented by every backend. **Store `SessionHeader` fields in an extensible metadata blob.** Rejected for schema 20 because `agentPreset` is a typed core resume invariant shared by JSONL and SQLite, not provider extension metadata. Persisting validated core fields directly keeps both backends aligned; an untyped catch-all would add another compatibility mechanism without a current producer. Revisit this only with a core-owned, namespaced `SessionHeader` extension protocol implemented by every backend.
**Expose compression rules through configuration or a live registry.** Rejected because same-version databases must be readable independently of runtime topology. The codec is modular source code, but the durable rule set is fixed by schema version. **Expose compression rules through configuration or a live registry.** Rejected because same-version databases must be readable independently of runtime topology. The codec is modular source code, but the durable rule set is fixed by schema version.

View file

@ -1,6 +1,7 @@
# Agent Note: SQLite 物理分片行压缩 # Agent Note: SQLite 物理分片行压缩
Status: implemented Status: implemented
Archived: 2026-08-30
[English](2026-08-18-sqlite-physical-chunk-row-compression.md) | 中文 [English](2026-08-18-sqlite-physical-chunk-row-compression.md) | 中文
@ -12,15 +13,15 @@ Status: implemented
## 决策 ## 决策
`@deepseek-ai/dsh-session-persistence-sqlite` 使用打包后的 schema 17 实现。它是唯一的 SQLite 持久化包和提供方;仓库不保留此前的标量布局与临时版本化同级包。SQLite 仍是可选开关,随产品交付的默认组合继续使用 JSONL。两个后端都通过 `PersistenceCoordinator` 实现同一 `SessionPersistence` 服务,因此物理打包既不改变实时事件投递,也不改变逻辑会话 API。 `@deepseek-ai/dsh-session-persistence-sqlite` 使用打包后的 schema 20 实现。它是唯一的 SQLite 持久化包和提供方;仓库不保留此前的标量布局与临时版本化同级包。SQLite 仍是可选开关,随产品交付的默认组合继续使用 JSONL。两个后端都通过 `PersistenceCoordinator` 实现同一 `SessionPersistence` 服务,因此物理打包既不改变实时事件投递,也不改变逻辑会话 API。
Schema 17 保留普通 ROWID 表以及复合主键索引 `events(session_id, seq)`。标量行表示一个逻辑事件。打包行使用存储标签 `text-chunks`、`reasoning-chunks` 与 `tool-call-chunks`;SQL 的 `seq` 和 `time` 列保存第一个逻辑成员,`data` 保存打包 payload。打包行把 `ignorable=0` 用作物理判别值,并让 `source_event_seqs` 与 `surface_op` 保持 `NULL`;标量行仅在逻辑事件可忽略时使用 `ignorable=1`,否则使用 `NULL`。因此,未来的可忽略逻辑事件即使复用了某个存储标签名称,也不会被解码为打包行。这些标签属于存储词汇,而不是 `SessionEventMap` 成员。 Schema 20 保留普通 ROWID 表以及复合主键索引 `events(session_id, seq)`。标量行表示一个逻辑事件。打包行使用存储标签 `text-chunks`、`reasoning-chunks` 与 `tool-call-chunks`;SQL 的 `seq` 和 `time` 列保存第一个逻辑成员,`data` 保存打包 payload。打包行把 `ignorable=0` 用作物理判别值,并让 `source_event_seqs` 与 `surface_op` 保持 `NULL`;标量行仅在逻辑事件可忽略时使用 `ignorable=1`,否则使用 `NULL`。因此,未来的可忽略逻辑事件即使复用了某个存储标签名称,也不会被解码为打包行。这些标签属于存储词汇,而不是 `SessionEventMap` 成员。
SQLite 在 schema 17 包内拥有分片编码和验证。字段完全匹配的白名单意味着未知字段、surface 元数据、不兼容的分片身份、序列缺口和不安全时间戳仍保持标量表示,不会丢失信息。一个打包行最多表示 1,024 个事件和 1 MiB 未压缩 UTF-8 `data`;编码器会分割更长的连续段,解码器则拒绝超出这些格式上限的行。 SQLite 在 schema 20 包内拥有分片编码和验证。字段完全匹配的白名单意味着未知字段、surface 元数据、不兼容的分片身份、序列缺口和不安全时间戳仍保持标量表示,不会丢失信息。一个打包行最多表示 1,024 个事件和 1 MiB 未压缩 UTF-8 `data`;编码器会分割更长的连续段,解码器则拒绝超出这些格式上限的行。
`data` 列接受 `TEXT` 或 `BLOB`。序列化值小于 4 KiB 时保持为文本。达到或超过该阈值时,写入方使用 Zstandard level 3,并且只在 frame 小于原文本时保留该 frame;读取方会先解压,再进行严格 UTF-8 解码和 JSON 解析。固定的适中级别与阈值限制 frame 开销与同步 CPU 工作,同时覆盖占据大部分保留字节的重复 payload。 `data` 列接受 `TEXT` 或 `BLOB`。序列化值小于 4 KiB 时保持为文本。达到或超过该阈值时,写入方使用 Zstandard level 3,并且只在 frame 小于原文本时保留该 frame;读取方会先解压,再进行严格 UTF-8 解码和 JSON 解析。固定的适中级别与阈值限制 frame 开销与同步 CPU 工作,同时覆盖占据大部分保留字节的重复 payload。
`source_event_seqs` 是 surface 节点引用的早期事件的完整有序列表,包括组装后的 assistant 消息背后的每个流式分片。Schema 17 把第一个序列存为无符号 varint,把后续每个有符号差值存为 ZigZag varint。这样既能保留任意顺序和每个序列,又能利用流式处理所产生的绝大多数连续列表。空列表表示为空的非 `NULL` blob,与不存在来源区分开来。 `source_event_seqs` 是 surface 节点引用的早期事件的完整有序列表,包括组装后的 assistant 消息背后的每个流式分片。Schema 20 把第一个序列存为无符号 varint,把后续每个有符号差值存为 ZigZag varint。这样既能保留任意顺序和每个序列,又能利用流式处理所产生的绝大多数连续列表。空列表表示为空的非 `NULL` blob,与不存在来源区分开来。
### 事务化追加打包 ### 事务化追加打包
@ -32,11 +33,11 @@ SQLite 在 schema 17 包内拥有分片编码和验证。字段完全匹配的
完整读取把每个物理行解码为全有或全无的逻辑范围,并验证逻辑序列连续。反向扫描会定位最后一个有效 `turn/end`,但不会保留完整物理扫描的第二份解码副本;正向扫描则逐行解码并写入必需的逻辑结果。在该已提交边界之前出现的畸形行或缺口属于损坏;畸形最终物理行则以该行的起始序列作为不透明修复标记。恢复会在持有写锁时重新读取并验证该 marker,再删除整个物理行及其后所有行,然后把合成 closers 绑定为标量事件。陈旧修复无法删除较新写入方的有效后缀。 完整读取把每个物理行解码为全有或全无的逻辑范围,并验证逻辑序列连续。反向扫描会定位最后一个有效 `turn/end`,但不会保留完整物理扫描的第二份解码副本;正向扫描则逐行解码并写入必需的逻辑结果。在该已提交边界之前出现的畸形行或缺口属于损坏;畸形最终物理行则以该行的起始序列作为不透明修复标记。恢复会在持有写锁时重新读取并验证该 marker,再删除整个物理行及其后所有行,然后把合成 closers 绑定为标量事件。陈旧修复无法删除较新写入方的有效后缀。
`readFrom(id, fromSeq)` 只检查 schema 17 最大行跨度内的打包前驱,再从可能包含 `fromSeq` 的最早候选项开始读取。解码器会过滤重建后序列小于 `fromSeq` 的成员,因此后缀可以从打包行内部开始,而无需解析无关的更早标量行。从该候选项开始读取,还会让连续性验证看到相互重叠的标量行,而不是让它隐藏打包成员。打包数据超出未压缩格式字节上限时,会在解析 JSON 前拒绝。 `readFrom(id, fromSeq)` 只检查 schema 20 最大行跨度内的打包前驱,再从可能包含 `fromSeq` 的最早候选项开始读取。解码器会过滤重建后序列小于 `fromSeq` 的成员,因此后缀可以从打包行内部开始,而无需解析无关的更早标量行。从该候选项开始读取,还会让连续性验证看到相互重叠的标量行,而不是让它隐藏打包成员。打包数据超出未压缩格式字节上限时,会在解析 JSON 前拒绝。
### Schema 所有权 ### Schema 所有权
全新数据库初始化为 schema 17。旧物理 schema、外部 application identity、非空未版本化数据库以及不兼容 schema 对象都会被拒绝;该预发布提供方不提供迁移。每个连接都会在检查持久 schema 前禁用可信 schema 和内存映射 I/O,然后读回这两项设置。选择并验证 journal mode 后,提供方会把 `synchronous` 固定为 `FULL` 并验证该设置,避免 SQLite 构建默认值削弱已提交追加的持久性。包代码通过封闭名称的 `.sql` 资源加载每条语句和固定 pragma,并把运行时值作为参数绑定。 全新数据库初始化为 schema 20。旧物理 schema、外部 application identity、非空未版本化数据库以及不兼容 schema 对象都会被拒绝;该预发布提供方不提供迁移。每个连接都会在检查持久 schema 前禁用可信 schema 和内存映射 I/O,然后读回这两项设置。选择并验证 journal mode 后,提供方会把 `synchronous` 固定为 `FULL` 并验证该设置,避免 SQLite 构建默认值削弱已提交追加的持久性。包代码通过封闭名称的 `.sql` 资源加载每条语句和固定 pragma,并把运行时值作为参数绑定。
### 物理写入回归 ### 物理写入回归
@ -58,11 +59,11 @@ SQLite 在 schema 17 包内拥有分片编码和验证。字段完全匹配的
**压缩每个 payload。** 不予采用,因为小型独立 Zstandard frame 会增加 header 和同步 CPU 工作,也无法利用整文件流的跨记录字典。在 105 个会话的对比语料上,阈值扫描结果为:4 KiB 生成 75.01 MB,16 KiB 为 93.87 MB,1 KiB 为 60.92 MB。写入方固定使用 level 3,而不是继承库默认值;这与 [Codex 冷 rollout 压缩](https://github.com/openai/codex/blob/main/codex-rs/rollout/src/compression.rs)所用的适中级别一致,同时保留独立行访问。 **压缩每个 payload。** 不予采用,因为小型独立 Zstandard frame 会增加 header 和同步 CPU 工作,也无法利用整文件流的跨记录字典。在 105 个会话的对比语料上,阈值扫描结果为:4 KiB 生成 75.01 MB,16 KiB 为 93.87 MB,1 KiB 为 60.92 MB。写入方固定使用 level 3,而不是继承库默认值;这与 [Codex 冷 rollout 压缩](https://github.com/openai/codex/blob/main/codex-rs/rollout/src/compression.rs)所用的适中级别一致,同时保留独立行访问。
最终冻结对比包含 105 个会话、2,507,860 个逻辑事件,以 512 个事件为持久批次;每个后端独立构建三次,每次构建执行三轮读取。SQLite 使用 75.01 MB,写入耗时 8.58 秒,完整读取 p50/p95 为 3.95/21.58 毫秒,读取最后 50 个事件为 0.253/0.378 毫秒,对所有会话执行 fork 为 13.10 秒。Zstandard JSONL 使用 30.65 MB,对应指标为 28.21 秒、4.49/23.36 毫秒、10.58/80.90 毫秒和 14.48 秒。此前的标量 SQLite 布局使用 709.57 MB,对应指标为 10.64 秒、9.02/69.16 毫秒、0.189/0.293 毫秒和 19.30 秒。打包布局比此前布局小 89.4%,写入快 19.4%,完整读取 p50/p95 改善 56.2%/68.8%,并把 2,507,860 个物理事件行减少到 65,810 行。标量布局的最后 50 个事件读取与 list 微延迟更低,但打包提供方在这些路径上仍明显快于 JSONL,并改善主要的空间、写入、完整读取和 fork 成本。4 KiB 阈值是接受的平衡点,而不是严格支配所有指标的结论。 最终冻结对比包含 105 个会话、2,507,860 个逻辑事件,以 512 个事件为持久批次;每个后端独立构建三次,每次构建执行三轮读取。SQLite 使用 75.01 MB,写入耗时 8.58 秒,完整读取 p50/p95 为 3.95/21.58 毫秒,读取最后 50 个事件为 0.253/0.378 毫秒,对所有会话执行 fork 为 13.10 秒。Zstandard JSONL 使用 30.65 MB,对应指标为 28.21 秒、4.49/23.36 毫秒、10.58/80.90 毫秒和 14.48 秒。此前的标量 SQLite 布局使用 709.57 MB,对应指标为 10.64 秒、9.02/69.16 毫秒、0.189/0.293 毫秒和 19.30 秒。打包布局比此前布局小 89.4%,写入快 19.4%,完整读取 p50/p95 改善 56.2%/68.8%,并把 2,507,860 个物理事件行减少到 65,810 行。标量布局的最后 50 个事件读取与 list 微延迟更低,但打包提供方在这些路径上仍明显快于 JSONL,并改善主要的空间、写入、完整读取和 fork 成本。4 KiB 阈值是接受的平衡点,而不是严格支配所有指标的结论。该对比测量的是 schema 17;其精确数值是原始打包行决策的证据,并非 schema 20 实测。[持久化延迟与 page size 决策](2026-08-25-persistence-latency-and-page-size.zh.md)记录 schema 19 基准与当前编码细节。
**把打包 payload 存在逻辑 `assistant/chunk` 类型下。** 不予采用,因为 payload 启发式判断会使畸形行产生歧义,并把物理解码耦合到未来逻辑 payload 字段。显式标签会明确失败。 **把打包 payload 存在逻辑 `assistant/chunk` 类型下。** 不予采用,因为 payload 启发式判断会使畸形行产生歧义,并把物理解码耦合到未来逻辑 payload 字段。显式标签会明确失败。
**把 `SessionHeader` 字段存入可扩展元数据 blob。** Schema 17 不采用该方案,因为 `agentPreset` 是 JSONL 与 SQLite 共同使用的强类型核心恢复不变量,而不是提供方扩展元数据。直接持久化已校验的核心字段可使两个后端保持一致;在没有当前生产方的情况下加入无类型兜底字段,只会增加另一套兼容机制。只有核心层定义由所有后端实现、带命名空间的 `SessionHeader` 扩展协议后,才应重新考虑该方案。 **把 `SessionHeader` 字段存入可扩展元数据 blob。** Schema 20 不采用该方案,因为 `agentPreset` 是 JSONL 与 SQLite 共同使用的强类型核心恢复不变量,而不是提供方扩展元数据。直接持久化已校验的核心字段可使两个后端保持一致;在没有当前生产方的情况下加入无类型兜底字段,只会增加另一套兼容机制。只有核心层定义由所有后端实现、带命名空间的 `SessionHeader` 扩展协议后,才应重新考虑该方案。
**通过配置或实时注册表暴露压缩规则。** 不予采用,因为同一版本数据库必须能独立于运行时拓扑被读取。Codec 在源码层保持模块化,但持久规则集由 schema 版本固定。 **通过配置或实时注册表暴露压缩规则。** 不予采用,因为同一版本数据库必须能独立于运行时拓扑被读取。Codec 在源码层保持模块化,但持久规则集由 schema 版本固定。

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.md
2026-07-31-composer-text-layers-share-one-scrollport.md: eb50673bb5fac50e12b0325c22c67072e130efb6
2026-07-31-composer-text-layers-share-one-scrollport.zh.md: f0af130d34682fcdfe145eb73b18187ca316c0d2

View file

@ -1,6 +1,7 @@
# Agent Note: The composer's two text layers share one scrollport # Agent Note: The composer's two text layers share one scrollport
Status: implemented Status: implemented
Archived: 2026-08-20
English | [中文](2026-07-31-composer-text-layers-share-one-scrollport.zh.md) English | [中文](2026-07-31-composer-text-layers-share-one-scrollport.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: composer 的两层文本共用同一个滚动容器 # Agent Note: composer 的两层文本共用同一个滚动容器
Status: implemented Status: implemented
Archived: 2026-08-20
[English](2026-07-31-composer-text-layers-share-one-scrollport.md) | 中文 [English](2026-07-31-composer-text-layers-share-one-scrollport.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-04-large-history-pagination-call-stack.md: 12e9bbf72c2eea2058bf83fe864e09b4a520d391
2026-08-04-large-history-pagination-call-stack.zh.md: 288687b05ecdfc2858b4d67e1be199135ea20227

View file

@ -1,6 +1,7 @@
# Agent Note: Large history provenance is scanned without argument expansion # Agent Note: Large history provenance is scanned without argument expansion
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-04-large-history-pagination-call-stack.zh.md) English | [中文](2026-08-04-large-history-pagination-call-stack.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 大规模历史记录的溯源信息通过扫描处理,不做参数展开 # Agent Note: 大规模历史记录的溯源信息通过扫描处理,不做参数展开
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-04-large-history-pagination-call-stack.md) | 中文 [English](2026-08-04-large-history-pagination-call-stack.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-06-plan-narrow-viewport-regression.md: c42a110bf487ffab8f5975e65a8eb9bff4f1b0ae
2026-08-06-plan-narrow-viewport-regression.zh.md: 3df4f8aca57a1830d7f8062cefe76ac1afa9c2ce

View file

@ -1,6 +1,7 @@
# Agent Note: narrow-viewport plan chip click-area regression test # Agent Note: narrow-viewport plan chip click-area regression test
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-06-plan-narrow-viewport-regression.zh.md) English | [中文](2026-08-06-plan-narrow-viewport-regression.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 窄视口下 Plan chip 点击区域回归测试 # Agent Note: 窄视口下 Plan chip 点击区域回归测试
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-06-plan-narrow-viewport-regression.md) | 中文 [English](2026-08-06-plan-narrow-viewport-regression.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-11-preset-card-description-clamp.md: b9088b46184cde6f000fa39afbfe2d1145137b24
2026-08-11-preset-card-description-clamp.zh.md: a7a3c4f26a55405715fe017ec3a7deb164432b0e

View file

@ -1,6 +1,7 @@
# Agent Note: Preset cards clamp their description instead of sizing the roster # Agent Note: Preset cards clamp their description instead of sizing the roster
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-11-preset-card-description-clamp.zh.md) English | [中文](2026-08-11-preset-card-description-clamp.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 预设卡片截断自身描述,而不是由描述决定整份名单的高度 # Agent Note: 预设卡片截断自身描述,而不是由描述决定整份名单的高度
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-11-preset-card-description-clamp.md) | 中文 [English](2026-08-11-preset-card-description-clamp.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md
2026-08-13-safari-textarea-soft-wrap-reflow.md: 45cb3f39c50c72b44b8ae952ce3a861210e9f00a
2026-08-13-safari-textarea-soft-wrap-reflow.zh.md: 37409b010c0009edf3c944076ba8c3db1b140de9

View file

@ -1,6 +1,7 @@
# Agent Note: Safari textarea soft-wrap shrink recovery # Agent Note: Safari textarea soft-wrap shrink recovery
Status: implemented Status: implemented
Archived: 2026-08-20
English | [中文](2026-08-13-safari-textarea-soft-wrap-reflow.zh.md) English | [中文](2026-08-13-safari-textarea-soft-wrap-reflow.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: Safari textarea 软换行收缩恢复 # Agent Note: Safari textarea 软换行收缩恢复
Status: implemented Status: implemented
Archived: 2026-08-20
[English](2026-08-13-safari-textarea-soft-wrap-reflow.md) | 中文 [English](2026-08-13-safari-textarea-soft-wrap-reflow.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-08-20-composer-edit-range-from-selection.md
2026-08-20-composer-edit-range-from-selection.md: 46eaa0add61bdab9fdcb4fcfd0ec08b44481126d
2026-08-20-composer-edit-range-from-selection.zh.md: 73a3903ad6c7c0aad55a35aacc5e1396084b6e7a

View file

@ -1,6 +1,7 @@
# Agent Note: Composer edits carry the range they applied to # Agent Note: Composer edits carry the range they applied to
Status: implemented Status: implemented
Archived: 2026-08-20
English | [中文](2026-08-20-composer-edit-range-from-selection.zh.md) English | [中文](2026-08-20-composer-edit-range-from-selection.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 输入框的编辑自带它所作用的范围 # Agent Note: 输入框的编辑自带它所作用的范围
Status: implemented Status: implemented
Archived: 2026-08-20
[English](2026-08-20-composer-edit-range-from-selection.md) | 中文 [English](2026-08-20-composer-edit-range-from-selection.md) | 中文
@ -14,7 +15,7 @@ Status: implemented
此时草稿看上去仍然正确,却已不携带任何结构化引用,提交走的是无 occurrence 的那条路,把草稿原样发出。宿主收到的是给人看的标签而不是所有者的模型形式,什么也解析不出来。专为阻止这种降级而存在的序列化守卫从不运行,因为它只在还有 occurrence 需要序列化时才触发。 此时草稿看上去仍然正确,却已不携带任何结构化引用,提交走的是无 occurrence 的那条路,把草稿原样发出。宿主收到的是给人看的标签而不是所有者的模型形式,什么也解析不出来。专为阻止这种降级而存在的序列化守卫从不运行,因为它只在还有 occurrence 需要序列化时才触发。
这条路径是在引用[变成字面内联文本](../feature/2026-07-27-web-file-and-session-references.zh.md)之后才可达的。此前一个引用占据一个 `U+FFFC`——任何按键都打不出的字符,扫描无从撞车。 这条路径是在引用[变成字面内联文本](../feature/2026-07-27-web-file-and-session-references.md)之后才可达的。此前一个引用占据一个 `U+FFFC`——任何按键都打不出的字符,扫描无从撞车。
## 决策 ## 决策

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-08-20-composer-reference-decoration-keys.md
2026-08-20-composer-reference-decoration-keys.md: 316d45841c658d3d65246fb7425526b10e2f6bf3
2026-08-20-composer-reference-decoration-keys.zh.md: 90ac7c8011bb7f7f45312c25ffccb7dbbbb70505

View file

@ -1,6 +1,7 @@
# Agent Note: Composer reference decorations key by draft-order ordinal # Agent Note: Composer reference decorations key by draft-order ordinal
Status: implemented Status: implemented
Archived: 2026-08-20
English | [中文](2026-08-20-composer-reference-decoration-keys.zh.md) English | [中文](2026-08-20-composer-reference-decoration-keys.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 输入框引用装饰按草稿顺序序号取 key # Agent Note: 输入框引用装饰按草稿顺序序号取 key
Status: implemented Status: implemented
Archived: 2026-08-20
[English](2026-08-20-composer-reference-decoration-keys.md) | 中文 [English](2026-08-20-composer-reference-decoration-keys.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-08-24-system-prompt-section-order-ties.md
2026-08-24-system-prompt-section-order-ties.md: d92756e751e893b1d03b8892ef71ff9faac9d2c6
2026-08-24-system-prompt-section-order-ties.zh.md: 4a822b7925a38feb254dbc534fc6153c76a93e19

View file

@ -0,0 +1,28 @@
# Agent Note: Equal-order system-prompt sections render in activation order
Status: implemented
Archived: 2026-08-25
English | [中文](2026-08-24-system-prompt-section-order-ties.zh.md)
## Problem
`SystemPromptRegistry` sorts sections by `order` with a stable sort, so equal orders render in plugin-activation order. `tool:cordis` and `tool:workflow` both declared `order: 115`, while their activation order varies between clean platform compositions. ACP and SDK snapshot replays could therefore assemble the same sections in a different order from their committed `system-prompt.expected.md` files.
## Decision
Give the affected sequence distinct values without changing its established relative order: `tool:cordis` stays at 115, `tool:workflow` uses 115.5, `tool:ralph` stays at 116, continuable subagent guidance stays at 116.5, and child-report guidance stays at 117. Prompt text and tool schemas remain unchanged.
## Alternatives considered
**Normalize section order in the snapshot harness.** Rejected because the runtime, request header, and model prompt would remain sensitive to activation timing while only the fixture comparison hid the difference.
**Tie-break equal orders by section name in the registry.** Rejected because it would silently reorder every existing tie. Explicit orders keep each model-visible placement local to the contributing plugin.
## Consequences
The Cordis and workflow guidance has a platform-independent order while Ralph remains before continuable subagent and child-report guidance. Prompt-section placements that require a stable relative position need distinct `order` values; other equal-order sections retain activation-order semantics and are outside this decision.
## Testing
The keyless ACP and SDK snapshot replays pin Cordis before workflow and preserve the workflow, Ralph, continuable-subagent, and child-report sequence. The full snapshot suite verifies the refreshed fixtures.

View file

@ -0,0 +1,28 @@
# Agent Note: 等序系统提示词分段按激活顺序渲染
Status: implemented
Archived: 2026-08-25
[English](2026-08-24-system-prompt-section-order-ties.md) | 中文
## Problem
`SystemPromptRegistry` 使用稳定排序按 `order` 排列分段,因此相同 order 的分段会按插件激活顺序渲染。`tool:cordis` 与 `tool:workflow` 都声明了 `order: 115`,但两者在不同平台的全新组合中激活顺序不同。因此,ACP(Agent Client Protocol)与 SDK 的快照回放可能把相同分段组装成不同于已提交 `system-prompt.expected.md` 文件的顺序。
## Decision
在不改变既有相对顺序的前提下,为受影响的分段序列指定互不相同的 order:`tool:cordis` 保持 115,`tool:workflow` 使用 115.5,`tool:ralph` 保持 116,可继续运行的子代理指引保持 116.5,子代理报告指引保持 117。提示词文本与工具 schema 保持不变。
## Alternatives considered
**在快照 harness 中规范化分段顺序。** 已否决,因为运行时、请求标头和模型提示词仍然受激活时序影响,只有 fixture 比较会隐藏差异。
**在注册表中用分段名称打破并列。** 已否决,因为这会静默重排每一组现有并列。显式 order 让每个模型可见位置都由贡献该分段的插件就地决定。
## Consequences
Cordis 与 workflow 指引具有不依赖平台的顺序,同时 Ralph 仍排在可继续运行的子代理指引和子代理报告指引之前。需要稳定相对位置的提示词分段必须使用互不相同的 `order`;其他等序分段仍采用激活顺序,不属于本决策的范围。
## Testing
无密钥 ACP 与 SDK 快照回放会固定 Cordis 排在 workflow 之前,并保留 workflow、Ralph、可继续运行的子代理和子代理报告指引的顺序。完整快照套件验证刷新的 fixture。

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-07-30-versioned-gui-welcome-onboarding.md: 370793dd4e6d744ea61fc9319a94728dbbf3e1fe
2026-07-30-versioned-gui-welcome-onboarding.zh.md: 7b99377d00127174d5bfd8d080107c2cb67e6fff

View file

@ -1,6 +1,7 @@
# Agent Note: Versioned GUI welcome onboarding # Agent Note: Versioned GUI welcome onboarding
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-07-30-versioned-gui-welcome-onboarding.zh.md) English | [中文](2026-07-30-versioned-gui-welcome-onboarding.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 版本化 GUI 欢迎引导 # Agent Note: 版本化 GUI 欢迎引导
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-07-30-versioned-gui-welcome-onboarding.md) | 中文 [English](2026-07-30-versioned-gui-welcome-onboarding.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-06-bundled-dsh-badge-skill.md: 2909736d53f8aff41ca69e705de44657bc1b4f1e
2026-08-06-bundled-dsh-badge-skill.zh.md: de85e9476d3945cd13335ef596243bc2a126ae55

View file

@ -1,6 +1,7 @@
# Agent Note: Bundled dsh badge skill # Agent Note: Bundled dsh badge skill
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-06-bundled-dsh-badge-skill.zh.md) English | [中文](2026-08-06-bundled-dsh-badge-skill.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 内置 dsh 徽章 skill # Agent Note: 内置 dsh 徽章 skill
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-06-bundled-dsh-badge-skill.md) | 中文 [English](2026-08-06-bundled-dsh-badge-skill.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-07-workspace-picker-composer-entry.md: 023cbe09dd75015a1555103642d1b66ce75aafc9
2026-08-07-workspace-picker-composer-entry.zh.md: 6b84885b11fb5372a51d620b40ea7d24fe7e45a2

View file

@ -1,6 +1,7 @@
# Agent Note: The no-Workspace composer opens the existing picker # Agent Note: The no-Workspace composer opens the existing picker
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-07-workspace-picker-composer-entry.zh.md) English | [中文](2026-08-07-workspace-picker-composer-entry.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 未选择 Workspace 时从编辑器打开现有选择器 # Agent Note: 未选择 Workspace 时从编辑器打开现有选择器
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-07-workspace-picker-composer-entry.md) | 中文 [English](2026-08-07-workspace-picker-composer-entry.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-10-creator-guidance-introduce-cue.md: 2954bb9dca6bd5359ab3ed4b7e32bd8336709a10
2026-08-10-creator-guidance-introduce-cue.zh.md: 4f818b3a444cbc7bbd4355ac8e7a883aaa4bfa51

View file

@ -1,6 +1,7 @@
# Agent Note: Creator guidance lands as an introduce cue on the preset chip # Agent Note: Creator guidance lands as an introduce cue on the preset chip
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-10-creator-guidance-introduce-cue.zh.md) English | [中文](2026-08-10-creator-guidance-introduce-cue.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 创造模式引导以介绍动效落在预设 chip 上 # Agent Note: 创造模式引导以介绍动效落在预设 chip 上
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-10-creator-guidance-introduce-cue.md) | 中文 [English](2026-08-10-creator-guidance-introduce-cue.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-11-collapsible-ask-user-question-card.md: 08e87b0d1f05f47c5bc87ef9b32cab05ef229e5c
2026-08-11-collapsible-ask-user-question-card.zh.md: fd3b838ff174dcdb3d4994fe30b193d63f5c4d15

View file

@ -1,6 +1,7 @@
# Agent Note: Collapsible Ask-User Question Card # Agent Note: Collapsible Ask-User Question Card
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-11-collapsible-ask-user-question-card.zh.md) English | [中文](2026-08-11-collapsible-ask-user-question-card.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 可收起的提问卡片 # Agent Note: 可收起的提问卡片
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-11-collapsible-ask-user-question-card.md) | 中文 [English](2026-08-11-collapsible-ask-user-question-card.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-11-web-export-command-and-dialog.md: aba9048f26237ea01e861a5ee6e31b89429629c8
2026-08-11-web-export-command-and-dialog.zh.md: be4a3a53b1ff75cfbe176e258fb6a73e5abfee22

View file

@ -1,6 +1,7 @@
# Agent Note: Web `/export` shares the streamed Session ZIP download # Agent Note: Web `/export` shares the streamed Session ZIP download
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-11-web-export-command-and-dialog.zh.md) English | [中文](2026-08-11-web-export-command-and-dialog.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: Web `/export` 共用流式 Session ZIP 下载 # Agent Note: Web `/export` 共用流式 Session ZIP 下载
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-11-web-export-command-and-dialog.md) | 中文 [English](2026-08-11-web-export-command-and-dialog.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/archived/feature/2026-08-18-product-subagent-failure-facts.md
2026-08-18-product-subagent-failure-facts.md: b1d80cf66172ac67d38dbad873fa4cbd970a775c
2026-08-18-product-subagent-failure-facts.zh.md: df4b14b4a243f7768240678b8d434c7aef7d48a7

View file

@ -0,0 +1,81 @@
# Agent Note: Product subagents expose bounded structured failure facts
Status: implemented
Archived: 2026-08-21
English | [中文](2026-08-18-product-subagent-failure-facts.zh.md)
## Problem
The [Claude Code and Codex product providers](2026-08-04-claude-code-and-codex-subagent-backends.md) receive structured product failures, but a published run historically flattened most of them to the shared `error` stop reason. Product logs retained detail that the foreground parent and a [one-shot background Job](2026-08-12-product-subagent-one-shot-background-tasks.md) could not use to distinguish a product limit, an execution failure, or an early process exit.
Copying SDK error text, app-server payloads, or stderr into the result would expose task text, paths, environment values, credentials, or product internals. Adding shared error fields would also make the provider-neutral [subagent seam](2026-06-21-subagent-capability-seam.md) own product version vocabularies that change independently.
## Decision
Each product Provider owns the mapping from its pinned official structured failures, current operation, and managed process outcome to one fixed safe diagnostic line. `SubagentResult` remains unchanged: consumers receive the existing bounded `diagnostic` string and do not parse its product-private fields. The [minimal-diagnostics decision](../simplification/2026-08-21-product-subagent-minimal-diagnostics.md) supersedes this note's complete Claude Code subtype mirror; this note continues to own the current detailed Codex categories until that provider adopts the same simplification.
### Safe diagnostic
The structured line has this fixed order:
```text
Product subagent failure (product: <product>; stage: <stage>; category: <category>; HTTP status: <status>; exit code: <code>; signal: <signal>)
```
The Provider omits unavailable optional fields. Exit code and signal are independent facts and are each retained when observed. A contributing permission decision from the [non-interactive permissions decision](2026-08-15-product-subagent-noninteractive-permissions.md) follows the structured line; the latest safe permission fact remains operation-local. The shared result boundary limits the complete text to 4096 UTF-8 bytes.
Successful results and local cancellation expose no failure fact. Raw product errors, stderr, tool input, paths, environment values, credentials, and protocol payloads never enter the diagnostic. Startup and cleanup rejections use the same safe line in their Error message. Original failures remain on internal cause chains; Provider Host logs and forwarded stderr remain product-local observation only.
### Claude Code facts
The [minimal-diagnostics decision](../simplification/2026-08-21-product-subagent-minimal-diagnostics.md) exclusively owns Claude Code categories, stages, process facts, permission ordering, and verification for Agent SDK 0.3.241 and Claude Code 2.1.241. This note carries no separate Claude category contract.
### Codex facts
Codex app-server 0.147.0 defines eleven string categories and five object variants. The Provider preserves `contextWindowExceeded`, `sessionBudgetExceeded`, `usageLimitExceeded`, `serverOverloaded`, `cyberPolicy`, `internalServerError`, `unauthorized`, `badRequest`, `threadRollbackFailed`, `sandboxError`, and `other`. It also preserves `httpConnectionFailed`, `responseStreamConnectionFailed`, `responseStreamDisconnected`, `responseTooManyFailedAttempts`, and `activeTurnNotSteerable`; the four connection/stream variants retain numeric `httpStatusCode`, while the active-turn variant does not expose `turnKind`. Unknown strings, objects with another variant set, malformed values, and unclassified exceptions use `unknown`.
| Stage | Owned operation | Observable failure |
| --- | --- | --- |
| `initialize` | App-server spawn and initialize/initialized handshake | `start()` rejects with fixed safe facts and any process outcome already observed |
| `thread-start` | Ephemeral `thread/start` request and response validation | `start()` rejects with the thread stage and any available process outcome |
| `turn-start` | Published `turn/start` request, provisional ids, and early frames | The run resolves as `error` with a safe unknown fallback when no structured category exists |
| `turn` | Terminal notification, final-answer selection, and error-info mapping | The complete category and optional HTTP status reach the non-completed result |
| `process` | Managed app-server exits before another terminal path settles | The run resolves as `error` with `process-exit` and any available code and signal |
| `teardown` | Wire close and process-tree release | `dispose()` rejects independently; startup rollback aggregation exposes both startup and teardown lines |
`contextWindowExceeded` remains `max-tokens`; every other known or unknown Codex category remains `error`, and `cyberPolicy` does not become `refusal`.
### Ownership and lifecycle
| Fact or resource | Owner | Consumer behavior |
| --- | --- | --- |
| Codex error category | Codex Provider over its pinned official app-server | The Provider preserves its current structured category and uses `unknown` outside the recognized set |
| Current failure stage | Product Provider operation | Derived at the failure site; never persisted or used as a recovery state |
| Exit code and signal | `dsh-subprocess` process handle | The Provider displays observed values without inferring missing ones |
| Diagnostic bytes and delivery | `dsh-subagent`, foreground tool, and Job runtime | The same bounded text is presented separately from assistant output in both scheduling modes |
| Raw product failure | Product runtime, internal cause chain, and Host observation | It remains internal and never becomes model-visible result text |
## Verification
Claude Code verification is owned by the [minimal-diagnostics decision](../simplification/2026-08-21-product-subagent-minimal-diagnostics.md). Codex package tests pin all sixteen current error-info variants, HTTP status presence and absence, all six stages, unknown fallback, stop-reason preservation, permission ordering, sanitization, cancellation, concurrency, and cleanup aggregation. The real app-server fixture produces an actual Codex `internalServerError` and covers process/protocol failure and whole-tree quiescence. The keyless ACP snapshot records the Codex diagnostic in foreground error output, a background completion notice, and `job_output`.
## Alternatives considered
**Return raw SDK errors, app-server payloads, or stderr.** These values can contain commands, paths, workspace content, environment values, credentials, or upstream prose. A fixed allowlisted mapping preserves actionable facts without expanding the model-visible trust boundary.
**Add a shared product-error enum or structured result fields.** Claude Code and Codex version their error unions independently. A shared enum would duplicate those authorities and force unrelated Providers and consumers to track product releases.
**Parse generic stderr and exception messages.** Free-form text is neither stable nor safe. Only pinned structured product fields and the managed process outcome qualify as diagnostic input.
**Persist stages or add a recovery controller.** The stage is derived from the current call site only when a failure is reported. Persistence, retries, resume, and remediation need separate ownership and user contracts.
**Map product limits to new shared stop reasons.** Claude Code turn and budget limits are not token-window exhaustion, and an error category does not establish refusal semantics. Existing stop reasons remain unchanged.
## Consequences
The parent can distinguish the current Codex budget, usage, service, policy, request, connection, stream, rollback, sandbox, and active-turn categories without receiving raw product text. The [minimal-diagnostics decision](../simplification/2026-08-21-product-subagent-minimal-diagnostics.md) owns the corresponding Claude result. Foreground and background scheduling preserve the same fact because both consume one `SubagentResult`.
The diagnostic is display text rather than a new public protocol. Callers may present it but must not branch on its punctuation or product-private category names. A pinned product-version upgrade revalidates the Provider mapping and evidence without requiring every official error member to remain model-visible.
This decision adds no product session persistence, retry policy, recovery state, stderr classifier, authentication or configuration taxonomy, progress stream, or human interaction path.

View file

@ -0,0 +1,81 @@
# Agent Note: 产品 subagent 公开有界结构化失败事实
Status: implemented
Archived: 2026-08-21
[English](2026-08-18-product-subagent-failure-facts.md) | 中文
## Problem
[Claude Code 与 Codex 产品提供方](2026-08-04-claude-code-and-codex-subagent-backends.zh.md)会收到结构化产品失败,但已发布运行以往会把其中大多数压成共享的 `error` 终止原因。产品日志保留了细节,前台父 agent 与[一次性后台 Job](2026-08-12-product-subagent-one-shot-background-tasks.zh.md)却无法据此区分产品限制、执行失败或进程提前退出。
若把 SDK 错误文本、app-server payload 或 stderr 复制进结果,就会暴露任务文本、路径、环境值、凭证或产品内部信息。若增加共享错误字段,又会让提供方无关的 [subagent seam](2026-06-21-subagent-capability-seam.zh.md)拥有彼此独立变化的产品版本词汇。
## Decision
每个产品提供方分别拥有从锁定版本官方结构化失败、当前操作和受管进程结果到一行固定安全诊断的映射。`SubagentResult` 保持不变:消费方仍接收现有的有界 `diagnostic` 字符串,而且不解析其中由产品私有的字段。[最小诊断决策](../simplification/2026-08-21-product-subagent-minimal-diagnostics.zh.md)已经取代本说明对 Claude Code 完整 subtype 的镜像;在 Codex 采用同一简化前,本说明继续负责其当前详细类别。
### 安全诊断
结构化行采用以下固定顺序:
```text
Product subagent failure (product: <product>; stage: <stage>; category: <category>; HTTP status: <status>; exit code: <code>; signal: <signal>)
```
提供方会省略不可用的可选字段。退出码与信号是相互独立的事实,只要已观测到就分别保留。来自[非交互权限决策](2026-08-15-product-subagent-noninteractive-permissions.zh.md)且参与失败的权限决定会跟在结构化行之后;最新的安全权限事实仍只属于当前操作。共享结果边界会把完整文本限制在 4096 个 UTF-8 字节以内。
成功结果与本地取消都不公开失败事实。原始产品错误、stderr、工具输入、路径、环境值、凭证和协议 payload 绝不会进入诊断。启动与清理拒绝会在 Error 消息中使用同一安全行。原始失败保留在内部 cause 链中;提供方 Host 日志与转发的 stderr 也只作为产品本地观测。
### Claude Code 事实
[最小诊断决策](../simplification/2026-08-21-product-subagent-minimal-diagnostics.zh.md)独占负责 Agent SDK 0.3.241 与 Claude Code 2.1.241 的 Claude Code 类别、阶段、进程事实、权限顺序与验证。本说明不再承载独立的 Claude 类别约定。
### Codex 事实
Codex app-server 0.147.0 定义十一种字符串类别与五种对象 variant。提供方会保留 `contextWindowExceeded`、`sessionBudgetExceeded`、`usageLimitExceeded`、`serverOverloaded`、`cyberPolicy`、`internalServerError`、`unauthorized`、`badRequest`、`threadRollbackFailed`、`sandboxError` 和 `other`。它还会保留 `httpConnectionFailed`、`responseStreamConnectionFailed`、`responseStreamDisconnected`、`responseTooManyFailedAttempts` 与 `activeTurnNotSteerable`;四种连接/stream variant 会保留数值 `httpStatusCode`,而 active-turn variant 不公开 `turnKind`。未知字符串、同时含其他 variant 的对象、格式错误值与未分类异常统一使用 `unknown`。
| 阶段 | 归属操作 | 可观察失败 |
| --- | --- | --- |
| `initialize` | App-server spawn 与 initialize/initialized 握手 | `start()` 以固定安全事实和已经观测到的进程结果拒绝 |
| `thread-start` | 临时 `thread/start` 请求与响应校验 | `start()` 以线程阶段和可用进程结果拒绝 |
| `turn-start` | 已发布 `turn/start` 请求、暂定 id 与早到 frame | 没有结构化类别时,运行以 `error` 和安全 unknown 回退兑现 |
| `turn` | 终态通知、最终答案选择与 error-info 映射 | 完整类别与可选 HTTP status 进入非完成结果 |
| `process` | 受管 app-server 在另一终态路径结算前退出 | 运行以 `error` 兑现,并携带 `process-exit` 以及可用的退出码与信号 |
| `teardown` | Wire 关闭与进程树释放 | `dispose()` 独立拒绝;启动回滚聚合会同时公开启动与 teardown 两行 |
`contextWindowExceeded` 仍是 `max-tokens`;其他所有已知或未知 Codex 类别仍是 `error`,`cyberPolicy` 不会变成 `refusal`。
### 所有权与生命周期
| 事实或资源 | Owner | 消费方行为 |
| --- | --- | --- |
| Codex 错误类别 | Codex 提供方及其锁定的官方 app-server | 提供方保留当前结构化类别,并在已识别集合之外使用 `unknown` |
| 当前失败阶段 | 产品提供方操作 | 只在失败点派生;绝不持久化,也不作为恢复状态 |
| 退出码与信号 | `dsh-subprocess` 进程句柄 | 提供方展示已观测值,不推测缺失值 |
| 诊断字节与送达 | `dsh-subagent`、前台工具与 Job 运行时 | 两种调度模式都把同一份有界文本与 assistant 输出分开呈现 |
| 原始产品失败 | 产品运行时、内部 cause 链与 Host 观测 | 只保留在内部,绝不成为模型可见的结果文本 |
## Verification
Claude Code 验证由[最小诊断决策](../simplification/2026-08-21-product-subagent-minimal-diagnostics.zh.md)负责。Codex 包测试固定当前全部十六种 error-info variant、HTTP status 存在与缺失、六个阶段、unknown 回退、终止原因保持不变、权限顺序、脱敏、取消、并发与清理聚合。真实 app-server fixture 会产生实际 Codex `internalServerError`,并覆盖进程/协议失败与整棵进程树完全停稳。无密钥 ACP snapshot 会在前台错误输出、后台完成通知和 `job_output` 中记录 Codex 诊断。
## Alternatives considered
**返回原始 SDK 错误、app-server payload 或 stderr。** 这些值可能包含命令、路径、工作区内容、环境值、凭证或上游文本。固定白名单映射可以保留可操作事实,同时不扩大模型可见的信任边界。
**增加共享产品错误 enum 或结构化结果字段。** Claude Code 与 Codex 各自独立版本化错误联合。共享 enum 会复制这些权威,并迫使无关提供方和消费方跟随产品版本。
**解析通用 stderr 与异常消息。** 自由文本既不稳定也不安全。只有锁定版本产品提供的结构化字段和受管进程结果可以成为诊断输入。
**持久化阶段或增加恢复控制器。** 阶段只在报告失败时从当前调用点派生。持久化、重试、resume 与修复需要独立的所有权和用户约定。
**把产品限制映射为新的共享终止原因。** Claude Code 的轮次和预算限制并不表示 token 窗口耗尽,错误类别也不能证明拒绝语义。既有终止原因保持不变。
## Consequences
父 agent 可以区分当前 Codex 的预算、用量、服务、策略、请求、连接、stream、回滚、sandbox 与 active-turn 类别,而不会收到原始产品文本。[最小诊断决策](../simplification/2026-08-21-product-subagent-minimal-diagnostics.zh.md)负责对应的 Claude 结果。前台与后台调度会保留同一事实,因为二者都消费同一个 `SubagentResult`。
诊断只是展示文本,不是新的公开协议。调用方可以呈现它,但不得根据其标点或产品私有类别名称进行分支。锁定产品版本升级时必须重新验证提供方映射与证据,但不要求每个官方错误成员都继续模型可见。
本决策不增加产品会话持久化、重试策略、恢复状态、stderr 分类器、身份验证或配置分类体系、进度流或人工交互路径。

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-18-web-home-path-tilde.md: 108674740c804a42ec3b0491505186215a9d9fcd
2026-08-18-web-home-path-tilde.zh.md: 1f742158f62b9b7fbb8eae8be35c13adc95f3a09

View file

@ -1,6 +1,7 @@
# Agent Note: Web UI abbreviates POSIX home paths as `~` # Agent Note: Web UI abbreviates POSIX home paths as `~`
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-18-web-home-path-tilde.zh.md) English | [中文](2026-08-18-web-home-path-tilde.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: Web UI abbreviates POSIX home paths as `~` # Agent Note: Web UI abbreviates POSIX home paths as `~`
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-18-web-home-path-tilde.md) | 中文 [English](2026-08-18-web-home-path-tilde.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-19-high-cache-hit-decimal-display.md: 83c031bd1049ec26029d2e9ba0dc5cd623c3f867
2026-08-19-high-cache-hit-decimal-display.zh.md: 62f27e39d37cf2445ac6796030092e892d82b581

View file

@ -1,6 +1,7 @@
# Agent Note: High cache-hit decimal display # Agent Note: High cache-hit decimal display
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-19-high-cache-hit-decimal-display.zh.md) English | [中文](2026-08-19-high-cache-hit-decimal-display.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 高缓存命中率的小数显示 # Agent Note: 高缓存命中率的小数显示
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-19-high-cache-hit-decimal-display.md) | 中文 [English](2026-08-19-high-cache-hit-decimal-display.md) | 中文

View file

@ -10,6 +10,9 @@
"architecture/2026-06-15-turn-enclosure-invariant.i18n.yaml": "sha256:7eb471a53b7bef104c57e9343b80d672763f062ecb086b01b318b65b488d3c02", "architecture/2026-06-15-turn-enclosure-invariant.i18n.yaml": "sha256:7eb471a53b7bef104c57e9343b80d672763f062ecb086b01b318b65b488d3c02",
"architecture/2026-06-15-turn-enclosure-invariant.md": "sha256:afefa3a268c84f26cf5461e08933245352a9e63cff688d3c398c8064a4ac6e85", "architecture/2026-06-15-turn-enclosure-invariant.md": "sha256:afefa3a268c84f26cf5461e08933245352a9e63cff688d3c398c8064a4ac6e85",
"architecture/2026-06-15-turn-enclosure-invariant.zh.md": "sha256:c54fdac980abc922cdc252a8fef59e4bdd7567316c7fbb6f7dbc035e470d95fa", "architecture/2026-06-15-turn-enclosure-invariant.zh.md": "sha256:c54fdac980abc922cdc252a8fef59e4bdd7567316c7fbb6f7dbc035e470d95fa",
"architecture/2026-06-18-shared-persistence-write-coordinator.i18n.yaml": "sha256:3c5c22e9e6a63598ba648cad46d783af322cf3afd6021426a2d738f4b026bf65",
"architecture/2026-06-18-shared-persistence-write-coordinator.md": "sha256:d5242c770101086b6f0a0c40eab500d405ef4a98cae07e28d9ec21e89d94f90e",
"architecture/2026-06-18-shared-persistence-write-coordinator.zh.md": "sha256:3dce52e302600a0eea29b4821a2718b6bbc1ebe4c6c2ae372cd0cbe66cb05519",
"architecture/2026-06-20-extract-example-app-packages.i18n.yaml": "sha256:d99b612cc1051c86d883d74737c72e921735e7a28e0b5e6351d3870c664bdcc4", "architecture/2026-06-20-extract-example-app-packages.i18n.yaml": "sha256:d99b612cc1051c86d883d74737c72e921735e7a28e0b5e6351d3870c664bdcc4",
"architecture/2026-06-20-extract-example-app-packages.md": "sha256:9c7aca3a1e9a1ccc3729961663bc649b90076e671cae23e3db8203305983ccce", "architecture/2026-06-20-extract-example-app-packages.md": "sha256:9c7aca3a1e9a1ccc3729961663bc649b90076e671cae23e3db8203305983ccce",
"architecture/2026-06-20-extract-example-app-packages.zh.md": "sha256:19bd50232d9f25d35aa3f9dc72d9af0df457dd0eaca8b982d5aa625e5b95bcff", "architecture/2026-06-20-extract-example-app-packages.zh.md": "sha256:19bd50232d9f25d35aa3f9dc72d9af0df457dd0eaca8b982d5aa625e5b95bcff",
@ -25,6 +28,9 @@
"architecture/2026-07-05-windows-fs-permissions.i18n.yaml": "sha256:7e61ee9bbd9de4bf3285a6f250d9625bd062e5fb90279dbffd64c820f1f7fe6b", "architecture/2026-07-05-windows-fs-permissions.i18n.yaml": "sha256:7e61ee9bbd9de4bf3285a6f250d9625bd062e5fb90279dbffd64c820f1f7fe6b",
"architecture/2026-07-05-windows-fs-permissions.md": "sha256:03734da511eae3b0736f7cad73d9da76ae2f69f9d5ed09089b0121ccb135a861", "architecture/2026-07-05-windows-fs-permissions.md": "sha256:03734da511eae3b0736f7cad73d9da76ae2f69f9d5ed09089b0121ccb135a861",
"architecture/2026-07-05-windows-fs-permissions.zh.md": "sha256:454848057ea905fe76c88d17264e71e71fb685f08f82088de6976878372865c3", "architecture/2026-07-05-windows-fs-permissions.zh.md": "sha256:454848057ea905fe76c88d17264e71e71fb685f08f82088de6976878372865c3",
"architecture/2026-07-19-gui-layering-and-rpc-protocol.i18n.yaml": "sha256:855477999c84236430dc9308e16797eb21658a67a72b8537315c6964ff0c0c0a",
"architecture/2026-07-19-gui-layering-and-rpc-protocol.md": "sha256:3517f37e98e74865dced37d5e1559d443e8fa827031c8335e99a1e910586e9ac",
"architecture/2026-07-19-gui-layering-and-rpc-protocol.zh.md": "sha256:8181386d957fa6d6b3eb9b05d29adb10804b5a926853425415d368cc7fceaefa",
"architecture/2026-07-22-tui-interactive-extension-service.i18n.yaml": "sha256:1b4822af5c8d642b73e3a0b04fb0a1dea9f50d0147046fbef53f5e49c030fb91", "architecture/2026-07-22-tui-interactive-extension-service.i18n.yaml": "sha256:1b4822af5c8d642b73e3a0b04fb0a1dea9f50d0147046fbef53f5e49c030fb91",
"architecture/2026-07-22-tui-interactive-extension-service.md": "sha256:ca6b2774f4821e66f7c8397f20fcd34926728ded853fa48cbe451db7a8d2f883", "architecture/2026-07-22-tui-interactive-extension-service.md": "sha256:ca6b2774f4821e66f7c8397f20fcd34926728ded853fa48cbe451db7a8d2f883",
"architecture/2026-07-22-tui-interactive-extension-service.zh.md": "sha256:5b060c7626ee796c27108be7467a5e4be0677d7525d383336e7ec31ddce5c303", "architecture/2026-07-22-tui-interactive-extension-service.zh.md": "sha256:5b060c7626ee796c27108be7467a5e4be0677d7525d383336e7ec31ddce5c303",
@ -43,6 +49,15 @@
"architecture/2026-07-28-dsh-native-typescript-source-launch.i18n.yaml": "sha256:af071e07bce5d9bc8f3df65fed9dcd9b3779a98c5864badbd530363bda021b55", "architecture/2026-07-28-dsh-native-typescript-source-launch.i18n.yaml": "sha256:af071e07bce5d9bc8f3df65fed9dcd9b3779a98c5864badbd530363bda021b55",
"architecture/2026-07-28-dsh-native-typescript-source-launch.md": "sha256:1b56e3454277ace713e2a01c4da538c756c45bf633fd24d7b16443d584afac5d", "architecture/2026-07-28-dsh-native-typescript-source-launch.md": "sha256:1b56e3454277ace713e2a01c4da538c756c45bf633fd24d7b16443d584afac5d",
"architecture/2026-07-28-dsh-native-typescript-source-launch.zh.md": "sha256:8c0f97472c2c89d2c19ae5cfa68c6e67f32b50960b08b60b46496f78ea6ffad1", "architecture/2026-07-28-dsh-native-typescript-source-launch.zh.md": "sha256:8c0f97472c2c89d2c19ae5cfa68c6e67f32b50960b08b60b46496f78ea6ffad1",
"architecture/2026-08-04-websocket-downlink-carrier.i18n.yaml": "sha256:b9d742d068a0e36df2f3030f6a04a3638f3461f7e10b50ed0cd6bd5e85de5019",
"architecture/2026-08-04-websocket-downlink-carrier.md": "sha256:b9be27a4cda8abd410c6e8b728c571f96b4891eb003c5200e9a0ffbbc9145b42",
"architecture/2026-08-04-websocket-downlink-carrier.zh.md": "sha256:118b71b33710a7a3d28375c48b42c1ec19993ca7e13f286dd6ea64f934456f46",
"architecture/2026-08-11-plugin-settings-tabs.i18n.yaml": "sha256:0365da2b317fc5f94dd190064198565f4c624afc91d2e62161ab9170f79d11bc",
"architecture/2026-08-11-plugin-settings-tabs.md": "sha256:fdd92cfe55b6c4cd31b3f768dd46a2ecf129a04c9818249cbdd33857cf722bbf",
"architecture/2026-08-11-plugin-settings-tabs.zh.md": "sha256:8993df1a0178aba1ea35c460ee67c522900344a4b386287bba9dfac2bfb87efa",
"architecture/2026-08-18-sqlite-physical-chunk-row-compression.i18n.yaml": "sha256:42bce930799cb511e9fb245dec5e26efd78bdab4c9b75f7393e37b40fbee4d10",
"architecture/2026-08-18-sqlite-physical-chunk-row-compression.md": "sha256:4fe241f1b272278d9f3ca1a4431971220e1fa54411df043826ef6f59225bf949",
"architecture/2026-08-18-sqlite-physical-chunk-row-compression.zh.md": "sha256:73178c9ec5abf571680d8facfb145cbadc1efbb2e67e3f039747c2f9cf4bb730",
"bug-fix/2026-07-20-code-mode-result-card-completeness.i18n.yaml": "sha256:1035dae11d049d32ab09fd7d4f950eceae44bf46ba498b3cfaf3c75102b9fb64", "bug-fix/2026-07-20-code-mode-result-card-completeness.i18n.yaml": "sha256:1035dae11d049d32ab09fd7d4f950eceae44bf46ba498b3cfaf3c75102b9fb64",
"bug-fix/2026-07-20-code-mode-result-card-completeness.md": "sha256:6ca2c9d4df98be18813ef38b7462db880900b5bcd6944fbcd1b8f2258006b93e", "bug-fix/2026-07-20-code-mode-result-card-completeness.md": "sha256:6ca2c9d4df98be18813ef38b7462db880900b5bcd6944fbcd1b8f2258006b93e",
"bug-fix/2026-07-20-code-mode-result-card-completeness.zh.md": "sha256:ed85fa7f935e5f525d566bc37a92014614983e649c75de9a9f244939097a7991", "bug-fix/2026-07-20-code-mode-result-card-completeness.zh.md": "sha256:ed85fa7f935e5f525d566bc37a92014614983e649c75de9a9f244939097a7991",
@ -85,6 +100,9 @@
"bug-fix/2026-07-30-web-details-default-closed.i18n.yaml": "sha256:2af5559d727f3e4afdd4946eaf89ac212c81db611db78dbd9bfabb1c4661db17", "bug-fix/2026-07-30-web-details-default-closed.i18n.yaml": "sha256:2af5559d727f3e4afdd4946eaf89ac212c81db611db78dbd9bfabb1c4661db17",
"bug-fix/2026-07-30-web-details-default-closed.md": "sha256:27a280a817c8048718bb22927e7d9572cf99ffd0c044631e99e0fd6ea236876f", "bug-fix/2026-07-30-web-details-default-closed.md": "sha256:27a280a817c8048718bb22927e7d9572cf99ffd0c044631e99e0fd6ea236876f",
"bug-fix/2026-07-30-web-details-default-closed.zh.md": "sha256:e047c7d02cf4b95b0c7f78f4b79af254091294b05cc75e98a8bb860ae2074189", "bug-fix/2026-07-30-web-details-default-closed.zh.md": "sha256:e047c7d02cf4b95b0c7f78f4b79af254091294b05cc75e98a8bb860ae2074189",
"bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.i18n.yaml": "sha256:36fc626dcbf1e276a36713e85860752cef0b36a5881f2493bdeb6d9654621b02",
"bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.md": "sha256:3ece47f91ee5f7354ef73ca0562aafeec19f89a19d9a64c9e0a565fe6d8c2049",
"bug-fix/2026-07-31-composer-text-layers-share-one-scrollport.zh.md": "sha256:578e772ecbc1a4a39bddbb0a9f3fdbf67c70ff8c8952cc80d2caa3d8b76e9b36",
"bug-fix/2026-07-31-hero-visible-while-blank-session-opens.i18n.yaml": "sha256:42218a762ce0141d3cb43deb6c688d3705cdc4405e03851d486c78f3d25b70ef", "bug-fix/2026-07-31-hero-visible-while-blank-session-opens.i18n.yaml": "sha256:42218a762ce0141d3cb43deb6c688d3705cdc4405e03851d486c78f3d25b70ef",
"bug-fix/2026-07-31-hero-visible-while-blank-session-opens.md": "sha256:a40992e89736131f5c487e5357848f14accd06e135dbec9ce242c968a5b11d43", "bug-fix/2026-07-31-hero-visible-while-blank-session-opens.md": "sha256:a40992e89736131f5c487e5357848f14accd06e135dbec9ce242c968a5b11d43",
"bug-fix/2026-07-31-hero-visible-while-blank-session-opens.zh.md": "sha256:e0cc576bc1c196affc9220ddabf15d735c347029c530c56454f0e585979101e1", "bug-fix/2026-07-31-hero-visible-while-blank-session-opens.zh.md": "sha256:e0cc576bc1c196affc9220ddabf15d735c347029c530c56454f0e585979101e1",
@ -94,12 +112,33 @@
"bug-fix/2026-08-03-tui-long-session-render-costs.i18n.yaml": "sha256:f65f7bf8fc84c7a1f022ee393c8d969c06d9bde8bed3a0206de86fb35b246ac6", "bug-fix/2026-08-03-tui-long-session-render-costs.i18n.yaml": "sha256:f65f7bf8fc84c7a1f022ee393c8d969c06d9bde8bed3a0206de86fb35b246ac6",
"bug-fix/2026-08-03-tui-long-session-render-costs.md": "sha256:6ecf2ef831f527f361ade18a882d79bc6eccf15cc676d05728e7753f41cde051", "bug-fix/2026-08-03-tui-long-session-render-costs.md": "sha256:6ecf2ef831f527f361ade18a882d79bc6eccf15cc676d05728e7753f41cde051",
"bug-fix/2026-08-03-tui-long-session-render-costs.zh.md": "sha256:5f44e707b332e13fa06d625212173ea055c1c3c0aee60888435a0ff099ec6037", "bug-fix/2026-08-03-tui-long-session-render-costs.zh.md": "sha256:5f44e707b332e13fa06d625212173ea055c1c3c0aee60888435a0ff099ec6037",
"bug-fix/2026-08-04-large-history-pagination-call-stack.i18n.yaml": "sha256:9bb1ceec013521116ee73eb9ec28c5708ae9520d6e53dcd4a3621fd2283b215c",
"bug-fix/2026-08-04-large-history-pagination-call-stack.md": "sha256:38c5afd347b131abd6b73634d25210d593bcb1fd72c7ba501bad0b33fb639810",
"bug-fix/2026-08-04-large-history-pagination-call-stack.zh.md": "sha256:2a2790b3b3400c747e20b998edfa96788b4035ccfa5fd4100dbc9a0e694ed30e",
"bug-fix/2026-08-06-plan-narrow-viewport-regression.i18n.yaml": "sha256:fe0539da9ce4015c6deaf585350e586e99d86e0073a36e131b6f1f62cc13382b",
"bug-fix/2026-08-06-plan-narrow-viewport-regression.md": "sha256:ccecdf52213dd1f6ab9935db31906520b83a7d9166f612376877d612230d1331",
"bug-fix/2026-08-06-plan-narrow-viewport-regression.zh.md": "sha256:be10805f0cd5a4f0812c883ab7f3e1e9396b579be455696d5cd726434a26b3e1",
"bug-fix/2026-08-10-web-favicon-dark-mode.i18n.yaml": "sha256:859c4399f9a017a68ba89552fdafa05e73c0599d94cee9551c84ea5b749a14f3", "bug-fix/2026-08-10-web-favicon-dark-mode.i18n.yaml": "sha256:859c4399f9a017a68ba89552fdafa05e73c0599d94cee9551c84ea5b749a14f3",
"bug-fix/2026-08-10-web-favicon-dark-mode.md": "sha256:4d17e247abd76ae3aed5fb4e075fd66a2838292f89f7021c82a79fe37ed905e6", "bug-fix/2026-08-10-web-favicon-dark-mode.md": "sha256:4d17e247abd76ae3aed5fb4e075fd66a2838292f89f7021c82a79fe37ed905e6",
"bug-fix/2026-08-10-web-favicon-dark-mode.zh.md": "sha256:7bbff8a3b7061c127afcc75cd2a8043b02a999b78c0180edd8f7e4807fcfe71d", "bug-fix/2026-08-10-web-favicon-dark-mode.zh.md": "sha256:7bbff8a3b7061c127afcc75cd2a8043b02a999b78c0180edd8f7e4807fcfe71d",
"bug-fix/2026-08-11-preset-card-description-clamp.i18n.yaml": "sha256:d50452503b59aa22c81617888f9391f31f12a779c4b18efb2b4b6de1bd9702a6",
"bug-fix/2026-08-11-preset-card-description-clamp.md": "sha256:7eb8db697f3ad3dea8c0a6045331c05730a010404a89e2b08348cb7b0fad26c8",
"bug-fix/2026-08-11-preset-card-description-clamp.zh.md": "sha256:6d2f7b55ce02275a45adfdd853805e7daf2d6534929b77beb86685a54fc34f85",
"bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.i18n.yaml": "sha256:3ce4f6e39e173fc304bf64deca9c95bcddc1dbb492e065ca8c267a7a40788588", "bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.i18n.yaml": "sha256:3ce4f6e39e173fc304bf64deca9c95bcddc1dbb492e065ca8c267a7a40788588",
"bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.md": "sha256:7b169aa4543edfc965de5a8b7b9e60aa9d9d5218693cd0b57908e2d482280723", "bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.md": "sha256:7b169aa4543edfc965de5a8b7b9e60aa9d9d5218693cd0b57908e2d482280723",
"bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.zh.md": "sha256:88db36c698800bf55c3c7531d6f92665576d978c29c15ff7d74215fb93376cb1", "bug-fix/2026-08-12-collapsed-sidebar-shared-entry-motion.zh.md": "sha256:88db36c698800bf55c3c7531d6f92665576d978c29c15ff7d74215fb93376cb1",
"bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.i18n.yaml": "sha256:23c26323f92a2172fd30fd724177b84d012cf4e18f1eff79ab092d4e0687ad4e",
"bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.md": "sha256:f9edea8501df36d444d84790ef9b0ae5bed4283a9cc5a5403800b80908f3db39",
"bug-fix/2026-08-13-safari-textarea-soft-wrap-reflow.zh.md": "sha256:ddcf6bb67823d19dc98964fcb9d663a10bcf663573394cfd7b235d9801d6525a",
"bug-fix/2026-08-20-composer-edit-range-from-selection.i18n.yaml": "sha256:c91ed2d9cb2a9891011fcbbe46885bc1808e36831279d56bc5cea0b9b1515b55",
"bug-fix/2026-08-20-composer-edit-range-from-selection.md": "sha256:e36920dee0318a35eaf49bff8c574698902f3be51d6115d40a3f97fa1436bd47",
"bug-fix/2026-08-20-composer-edit-range-from-selection.zh.md": "sha256:41f44adc93797cf9073f19f954b6ac87147a2e6806f1ad051c80c3423f0175ae",
"bug-fix/2026-08-20-composer-reference-decoration-keys.i18n.yaml": "sha256:cadf1de336aa2756d1bc1c20c7679449390b0a7a4217fe9602996801b6bc1958",
"bug-fix/2026-08-20-composer-reference-decoration-keys.md": "sha256:0093eabd710f10ae1faca53be01c9404a9d63cf6a2cf4dbf226e458e6315e201",
"bug-fix/2026-08-20-composer-reference-decoration-keys.zh.md": "sha256:a5fb2a748cf6ff8353d536448a5469e731157ccc2d0bb43210ea5dc44dd8ed31",
"bug-fix/2026-08-24-system-prompt-section-order-ties.i18n.yaml": "sha256:f7a20bddd4544738ec0dbbfc52ea931f42317defa1674beb9a3c0daebd52fc2d",
"bug-fix/2026-08-24-system-prompt-section-order-ties.md": "sha256:108a97346eb7a62f1ab01f48dbb9fdd965e8991f53e382b0f501b916af0e9e23",
"bug-fix/2026-08-24-system-prompt-section-order-ties.zh.md": "sha256:3deaddfcf9736b3ff8d61b51093d7e46fdcc86103705033e4aa4c9d043794b16",
"feature/2026-06-14-acp-agent-client-protocol.i18n.yaml": "sha256:006795baa43ae962a8d125cc0f1e9f134bc2ee9fb758b6e7669e3fa0126e1918", "feature/2026-06-14-acp-agent-client-protocol.i18n.yaml": "sha256:006795baa43ae962a8d125cc0f1e9f134bc2ee9fb758b6e7669e3fa0126e1918",
"feature/2026-06-14-acp-agent-client-protocol.md": "sha256:6828c0af74bb3fb96206ca6b21c0e56a000b50e4744aad4bc2c05092f3a5a31b", "feature/2026-06-14-acp-agent-client-protocol.md": "sha256:6828c0af74bb3fb96206ca6b21c0e56a000b50e4744aad4bc2c05092f3a5a31b",
"feature/2026-06-14-acp-agent-client-protocol.zh.md": "sha256:ba104e841a1fb84edbd3b6c8119d50445b7785255a7a8d13bb9ac8a2cb4d2e69", "feature/2026-06-14-acp-agent-client-protocol.zh.md": "sha256:ba104e841a1fb84edbd3b6c8119d50445b7785255a7a8d13bb9ac8a2cb4d2e69",
@ -241,6 +280,9 @@
"feature/2026-07-30-tui-details-command.i18n.yaml": "sha256:033cea6df0a16fc68cbdb435babdc6e75c1199a8e70e1a71d87c800c40f5a044", "feature/2026-07-30-tui-details-command.i18n.yaml": "sha256:033cea6df0a16fc68cbdb435babdc6e75c1199a8e70e1a71d87c800c40f5a044",
"feature/2026-07-30-tui-details-command.md": "sha256:a13478d4e55ec6d358209b51b541413ec75d0e20dfc22196ace28020f03f0c2d", "feature/2026-07-30-tui-details-command.md": "sha256:a13478d4e55ec6d358209b51b541413ec75d0e20dfc22196ace28020f03f0c2d",
"feature/2026-07-30-tui-details-command.zh.md": "sha256:de9c449b98468cef34ce4f9a9d2a854a5d8905eecd61f80e27a9a0e4495e9901", "feature/2026-07-30-tui-details-command.zh.md": "sha256:de9c449b98468cef34ce4f9a9d2a854a5d8905eecd61f80e27a9a0e4495e9901",
"feature/2026-07-30-versioned-gui-welcome-onboarding.i18n.yaml": "sha256:3d453f1a8f1a642ed569d1900009b785e582614bcabf9fede566ecbd9842e3ef",
"feature/2026-07-30-versioned-gui-welcome-onboarding.md": "sha256:cfaa38cfec722ac3792a4770f7733372805a6c0571f4f08519f367976b0d2379",
"feature/2026-07-30-versioned-gui-welcome-onboarding.zh.md": "sha256:0ce0e4616580c583725aa3d28063dc009889d7f0a260a3cdda53ff48721c1ae4",
"feature/2026-07-30-versioned-tui-first-run-welcome.i18n.yaml": "sha256:4c3fc380b0512ad7c00baacd0ac610e1a78ae45374311d9bd43bab6b5e29e630", "feature/2026-07-30-versioned-tui-first-run-welcome.i18n.yaml": "sha256:4c3fc380b0512ad7c00baacd0ac610e1a78ae45374311d9bd43bab6b5e29e630",
"feature/2026-07-30-versioned-tui-first-run-welcome.md": "sha256:296f153e6c839f3743078e4f5aab3b2befc211c934835238668c57bdeae52231", "feature/2026-07-30-versioned-tui-first-run-welcome.md": "sha256:296f153e6c839f3743078e4f5aab3b2befc211c934835238668c57bdeae52231",
"feature/2026-07-30-versioned-tui-first-run-welcome.zh.md": "sha256:82871a9cca1fec46bb08a5b39daad28a44bb2419dea367b4ae41af3cf07bfa65", "feature/2026-07-30-versioned-tui-first-run-welcome.zh.md": "sha256:82871a9cca1fec46bb08a5b39daad28a44bb2419dea367b4ae41af3cf07bfa65",
@ -259,9 +301,33 @@
"feature/2026-07-31-web-cards-toolrow.i18n.yaml": "sha256:f9a6ab72a77934cdcc02167c7313f08d7e9925362017b34bed7ad56c8c70fbaa", "feature/2026-07-31-web-cards-toolrow.i18n.yaml": "sha256:f9a6ab72a77934cdcc02167c7313f08d7e9925362017b34bed7ad56c8c70fbaa",
"feature/2026-07-31-web-cards-toolrow.md": "sha256:5058f7cec4497d1cb0a5c8e77b88fddacac6eead034f3edec88e8514919b8a3e", "feature/2026-07-31-web-cards-toolrow.md": "sha256:5058f7cec4497d1cb0a5c8e77b88fddacac6eead034f3edec88e8514919b8a3e",
"feature/2026-07-31-web-cards-toolrow.zh.md": "sha256:ba84ef2e1be61211ab5ba6950b78ede3d3a979f252bc068d3e04e2c025f7bc03", "feature/2026-07-31-web-cards-toolrow.zh.md": "sha256:ba84ef2e1be61211ab5ba6950b78ede3d3a979f252bc068d3e04e2c025f7bc03",
"feature/2026-08-06-bundled-dsh-badge-skill.i18n.yaml": "sha256:4b568d89976a71b7b3864e13b36925bf055479213739ffd4ac81614e00e93e36",
"feature/2026-08-06-bundled-dsh-badge-skill.md": "sha256:7b67f7c09b7e2b2ca756983a8951dad3a15786b8cd3adc6e819f316c67d31b2c",
"feature/2026-08-06-bundled-dsh-badge-skill.zh.md": "sha256:dcc0acb2dca596196ac034a8e86a644131c5b7fb09b184ec9d8493f93019d2b1",
"feature/2026-08-07-workspace-picker-composer-entry.i18n.yaml": "sha256:24a8bb2956371c7c840a662ac16dffbe04a6bb40a7296d01db86cb85da58d238",
"feature/2026-08-07-workspace-picker-composer-entry.md": "sha256:036212fbae6f5d7194e8c7fc9b1e7cd1c35251e9c227e895834a7d00bd5f69f8",
"feature/2026-08-07-workspace-picker-composer-entry.zh.md": "sha256:fb65c3330e8324f90d1270345e1ac941fc800e8caaf3b4bbee1bbb743f713262",
"feature/2026-08-08-dsh-run-headless-command.i18n.yaml": "sha256:1c2b4c5b61b9263b6267275d6fc69faeaad3cc887f0728a7ed4172d817af812b", "feature/2026-08-08-dsh-run-headless-command.i18n.yaml": "sha256:1c2b4c5b61b9263b6267275d6fc69faeaad3cc887f0728a7ed4172d817af812b",
"feature/2026-08-08-dsh-run-headless-command.md": "sha256:7695fe7fd322377d5986f14e35f13337f4cd376405c758218a81230f6d182d1c", "feature/2026-08-08-dsh-run-headless-command.md": "sha256:7695fe7fd322377d5986f14e35f13337f4cd376405c758218a81230f6d182d1c",
"feature/2026-08-08-dsh-run-headless-command.zh.md": "sha256:113c14a36c64d2facc8ae46f37c7aa76359d8cacb9c18fcba26a723f15d036fb", "feature/2026-08-08-dsh-run-headless-command.zh.md": "sha256:113c14a36c64d2facc8ae46f37c7aa76359d8cacb9c18fcba26a723f15d036fb",
"feature/2026-08-10-creator-guidance-introduce-cue.i18n.yaml": "sha256:74f519839f0cf82c7304bdeae41ae1cab8bb930bfb94f79ab44708acd3b72128",
"feature/2026-08-10-creator-guidance-introduce-cue.md": "sha256:3e25409dda498de150de18943ee332e1760963e377a40a365902b66f667fdc9f",
"feature/2026-08-10-creator-guidance-introduce-cue.zh.md": "sha256:203847010cab9e9d13c3969f17921d3a5aa0d69377eccfef555c7ff96572f162",
"feature/2026-08-11-collapsible-ask-user-question-card.i18n.yaml": "sha256:9c0873bbb1437bcd5025f5859e1dc447a6b936f19c2c2ad2250521a3aa773a12",
"feature/2026-08-11-collapsible-ask-user-question-card.md": "sha256:4f3b3f5d7020fefbbac8a3c36a97642721ef14a0476a7d8117bde8a128d25f42",
"feature/2026-08-11-collapsible-ask-user-question-card.zh.md": "sha256:e7186c92f77d337a875f981ae39b16331a1c5466a948415bcacfe108ad98fb63",
"feature/2026-08-11-web-export-command-and-dialog.i18n.yaml": "sha256:db7d523a2a1f82a86f532661bd2953ee8538d971d91f886e4bd4e0d88f7226b2",
"feature/2026-08-11-web-export-command-and-dialog.md": "sha256:ec44b47589ca7924018dc24f7fa73379a97b8f053d9e8ccce2aebb600230e47b",
"feature/2026-08-11-web-export-command-and-dialog.zh.md": "sha256:ad28e67d397c87300cfe1705ba3d206cc4d054e07f5647c095c718ac8cf4ec98",
"feature/2026-08-18-product-subagent-failure-facts.i18n.yaml": "sha256:0aa7a873fdd878ee7f4b0a850ecf16d7b652b4f85de979acb7efcdf90883b6c1",
"feature/2026-08-18-product-subagent-failure-facts.md": "sha256:f7e05703c44106359798e6e4b76e442a4107b62ff0363554382d4767e4806788",
"feature/2026-08-18-product-subagent-failure-facts.zh.md": "sha256:19d2619fb5b5c6e40305dd82432d837357afa433ab735504ec204a2c25582ce6",
"feature/2026-08-18-web-home-path-tilde.i18n.yaml": "sha256:f151e3e3514f59784fc646c2feb3075dc954c65110d48c2cc482ad486fc0b86f",
"feature/2026-08-18-web-home-path-tilde.md": "sha256:8c7ecf120ff8c81826160acab5fc906a2a0a14213bcd2958343cfea47328d68e",
"feature/2026-08-18-web-home-path-tilde.zh.md": "sha256:3486c5b42aed5bcadf12c62c5e1e6cf7c1b493fc1085ad7d154cdf2ec34076cc",
"feature/2026-08-19-high-cache-hit-decimal-display.i18n.yaml": "sha256:c2cb839ed676040ed62153c2aab65b677fa59739f69253af50246e79a2347620",
"feature/2026-08-19-high-cache-hit-decimal-display.md": "sha256:08cb68bfc379da47a05b816afac26126146d36d6248350d4380f7cb98607d573",
"feature/2026-08-19-high-cache-hit-decimal-display.zh.md": "sha256:9d7afe3e2fc3029fbccc643b432a01bcb3b5671750adb6945ac414ec843ca063",
"process/2026-06-11-doc-sync-enforcement.i18n.yaml": "sha256:33b6d5874427bd7a2bd82e7e2f4f482b12448b2464aef15a9c57975edb48554d", "process/2026-06-11-doc-sync-enforcement.i18n.yaml": "sha256:33b6d5874427bd7a2bd82e7e2f4f482b12448b2464aef15a9c57975edb48554d",
"process/2026-06-11-doc-sync-enforcement.md": "sha256:aa2fe83d519fc30d48dff19e596e83c8922aacc9e063e14fe2cc35b769b9100e", "process/2026-06-11-doc-sync-enforcement.md": "sha256:aa2fe83d519fc30d48dff19e596e83c8922aacc9e063e14fe2cc35b769b9100e",
"process/2026-06-11-doc-sync-enforcement.zh.md": "sha256:698017bd35f030fdea3eac51df9e43138c48140f504739d687b7251d13fced2b", "process/2026-06-11-doc-sync-enforcement.zh.md": "sha256:698017bd35f030fdea3eac51df9e43138c48140f504739d687b7251d13fced2b",
@ -322,6 +388,9 @@
"process/2026-08-08-review-driven-issue-lifecycle-triggers.i18n.yaml": "sha256:4c28c59d3fc323e7cd01eff31f1fe759834719c5bede1e82b39f868970bf856d", "process/2026-08-08-review-driven-issue-lifecycle-triggers.i18n.yaml": "sha256:4c28c59d3fc323e7cd01eff31f1fe759834719c5bede1e82b39f868970bf856d",
"process/2026-08-08-review-driven-issue-lifecycle-triggers.md": "sha256:1b0514de5d030170e91e12e4d6ba788a9247f840e82700faa385a1c0c76ab857", "process/2026-08-08-review-driven-issue-lifecycle-triggers.md": "sha256:1b0514de5d030170e91e12e4d6ba788a9247f840e82700faa385a1c0c76ab857",
"process/2026-08-08-review-driven-issue-lifecycle-triggers.zh.md": "sha256:028d78d61f603d8bac64c4cce20b393a78f8e029d3bb4976e79a47ecaefa6032", "process/2026-08-08-review-driven-issue-lifecycle-triggers.zh.md": "sha256:028d78d61f603d8bac64c4cce20b393a78f8e029d3bb4976e79a47ecaefa6032",
"process/2026-08-12-documentation-site-navigation-and-chrome.i18n.yaml": "sha256:dde0041399b253e3758045f0858488db8178ffc563ce889c8b396c87af6c3730",
"process/2026-08-12-documentation-site-navigation-and-chrome.md": "sha256:56cb836ed862378afd33eb5c1a9dc159958b35a0aed3bf4336fcf26ab0b84b8b",
"process/2026-08-12-documentation-site-navigation-and-chrome.zh.md": "sha256:f2dd4adde38a09fe312866a1e6dad0f465684d809287862f40f1a488acd4fe18",
"simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.i18n.yaml": "sha256:ad3d1263cb0051b885173bf064de62065e2c646ccaae2d7250723da3b4eab90c", "simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.i18n.yaml": "sha256:ad3d1263cb0051b885173bf064de62065e2c646ccaae2d7250723da3b4eab90c",
"simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.md": "sha256:8fb061d51c8c23b47d2367814bab3623c6d5b972f38d207a273caa9030b579bd", "simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.md": "sha256:8fb061d51c8c23b47d2367814bab3623c6d5b972f38d207a273caa9030b579bd",
"simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.zh.md": "sha256:2ffeaca91f82844a5616d6dcce6b4af514bb8a7c46f78e47f668b204ac6edc04", "simplification/2026-06-20-drop-unconsumed-llm-adapter-change-event.zh.md": "sha256:2ffeaca91f82844a5616d6dcce6b4af514bb8a7c46f78e47f668b204ac6edc04",
@ -406,6 +475,18 @@
"simplification/2026-08-03-explicit-config-dsh-entrypoint.i18n.yaml": "sha256:5466161f3fb8f2e8117fe8ff242675cc9fe9ef264d1e29b9bc586891c73c051a", "simplification/2026-08-03-explicit-config-dsh-entrypoint.i18n.yaml": "sha256:5466161f3fb8f2e8117fe8ff242675cc9fe9ef264d1e29b9bc586891c73c051a",
"simplification/2026-08-03-explicit-config-dsh-entrypoint.md": "sha256:f23accae7d05c2e75cb73ec69b492307f1ce7526ecfa9f6b12a621e02fd1a0c3", "simplification/2026-08-03-explicit-config-dsh-entrypoint.md": "sha256:f23accae7d05c2e75cb73ec69b492307f1ce7526ecfa9f6b12a621e02fd1a0c3",
"simplification/2026-08-03-explicit-config-dsh-entrypoint.zh.md": "sha256:a32d2c6ecf748a16a2c35b59cd2da2fda75769e3ab24be6a2e026d8655466db4", "simplification/2026-08-03-explicit-config-dsh-entrypoint.zh.md": "sha256:a32d2c6ecf748a16a2c35b59cd2da2fda75769e3ab24be6a2e026d8655466db4",
"simplification/2026-08-11-cmdline-program-action.i18n.yaml": "sha256:e33b6dee66e23beabf03275e4e4f15134d23a82740ae7be6afd28c11c3163fca",
"simplification/2026-08-11-cmdline-program-action.md": "sha256:e6a274bd92a35c98ea24704161b408507876de3162c0f640b4bc70a86ab4d86f",
"simplification/2026-08-11-cmdline-program-action.zh.md": "sha256:bd213ad65ea6129c5360f28b2f52e6f3e224a58d07f56da190702939e7b402ee",
"simplification/2026-08-11-quickstart-documentation-home.i18n.yaml": "sha256:548c0ff16d40fed3b3318b0b9a26e11d53a60582ff457098a212fc64e7d67eac",
"simplification/2026-08-11-quickstart-documentation-home.md": "sha256:21946a828417aca4a214a874a35e88fe5a3e5989c330421f3849937b35bb9a9b",
"simplification/2026-08-11-quickstart-documentation-home.zh.md": "sha256:cb292a428d427cf36aff0a184347f0ab653331edb874daf3c5b58a0d1f8e6964",
"simplification/2026-08-13-remove-first-run-beta-notice.i18n.yaml": "sha256:51267b74e39544991bfe606e3f749a26914162e454cf357f26223a6ed8de5fad",
"simplification/2026-08-13-remove-first-run-beta-notice.md": "sha256:7ef5c712b8dff1152becee6a3f800acd5f7589d7b000f01544f57b175660bcc1",
"simplification/2026-08-13-remove-first-run-beta-notice.zh.md": "sha256:f899c79f838b97d1eea4a118de2cf00a97bae910d86d4aabdc447b4e02fb585f",
"simplification/2026-08-19-knip-config-cleanup.i18n.yaml": "sha256:ca8f5726aed57ce376c3fbd8b70113e235f3ba37dbf290683157fb4bf143ab13",
"simplification/2026-08-19-knip-config-cleanup.md": "sha256:18c61713b3358d3019dac096afc26ce8e5189002f626b25e858dfc5e6f626c8d",
"simplification/2026-08-19-knip-config-cleanup.zh.md": "sha256:b8ff16089c1a331603bb80278544c637cb16c1fa3bcfca3c5e1187152a1a0947",
"testing/2026-06-20-remove-redundant-snapshot-log-expected-output.i18n.yaml": "sha256:4177012c0821a8c22499852ecdf096af56d7263cb91c5d9d1bcd552cc26a3e00", "testing/2026-06-20-remove-redundant-snapshot-log-expected-output.i18n.yaml": "sha256:4177012c0821a8c22499852ecdf096af56d7263cb91c5d9d1bcd552cc26a3e00",
"testing/2026-06-20-remove-redundant-snapshot-log-expected-output.md": "sha256:45234e7cc04b6010c6141f8d5924c04547300098f96262d423c50108e7c7011a", "testing/2026-06-20-remove-redundant-snapshot-log-expected-output.md": "sha256:45234e7cc04b6010c6141f8d5924c04547300098f96262d423c50108e7c7011a",
"testing/2026-06-20-remove-redundant-snapshot-log-expected-output.zh.md": "sha256:15e5a4ad3dee0bb711480cabe45cd97ec37bbdba19c2c2b47d1e9c203b07a48b", "testing/2026-06-20-remove-redundant-snapshot-log-expected-output.zh.md": "sha256:15e5a4ad3dee0bb711480cabe45cd97ec37bbdba19c2c2b47d1e9c203b07a48b",
@ -429,6 +510,9 @@
"testing/2026-07-18-tui-terminal-state-snapshots.zh.md": "sha256:26750f240f6c8a7b28746f62fe161b357e9c5dd52867cc7037399f1ed6ff37fa", "testing/2026-07-18-tui-terminal-state-snapshots.zh.md": "sha256:26750f240f6c8a7b28746f62fe161b357e9c5dd52867cc7037399f1ed6ff37fa",
"testing/2026-07-26-execa-for-test-subprocess-plumbing.i18n.yaml": "sha256:dd45cddb591b892739b75b0c180bde7f14008f4769227b863571475be295e1e0", "testing/2026-07-26-execa-for-test-subprocess-plumbing.i18n.yaml": "sha256:dd45cddb591b892739b75b0c180bde7f14008f4769227b863571475be295e1e0",
"testing/2026-07-26-execa-for-test-subprocess-plumbing.md": "sha256:1f45a69d0a7367ec5afbf112a77b355339b35270af8ff52696bee879cdf770d3", "testing/2026-07-26-execa-for-test-subprocess-plumbing.md": "sha256:1f45a69d0a7367ec5afbf112a77b355339b35270af8ff52696bee879cdf770d3",
"testing/2026-07-26-execa-for-test-subprocess-plumbing.zh.md": "sha256:8a24bdc8376373d7a97f65cefc07078824bf918d6a9934056a025ecfafe8634b" "testing/2026-07-26-execa-for-test-subprocess-plumbing.zh.md": "sha256:8a24bdc8376373d7a97f65cefc07078824bf918d6a9934056a025ecfafe8634b",
"testing/2026-08-12-required-python-runtime-pull-request-ci.i18n.yaml": "sha256:741e7e58e5e8a9c82d901c4a16a70cea9bd256eac0e94179b5a24a231bb9fe1f",
"testing/2026-08-12-required-python-runtime-pull-request-ci.md": "sha256:1f1273d7a550667533e29c76efd148aebf57581a91729c877b44a5e43a52d9ad",
"testing/2026-08-12-required-python-runtime-pull-request-ci.zh.md": "sha256:6b9bf126c6b83d9b21e135d38df677c0d5623168b4353c6ddb706f76762c2193"
} }
} }

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-12-documentation-site-navigation-and-chrome.md: f33f017d54bcbb3583f37be27dcd6c69952bc66a
2026-08-12-documentation-site-navigation-and-chrome.zh.md: 7f3ff5c829c561167d8e2475cd1c2adf050975be

View file

@ -1,6 +1,7 @@
# Agent Note: Documentation-site navigation and repository chrome # Agent Note: Documentation-site navigation and repository chrome
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-12-documentation-site-navigation-and-chrome.zh.md) English | [中文](2026-08-12-documentation-site-navigation-and-chrome.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 文档站导航与仓库 chrome # Agent Note: 文档站导航与仓库 chrome
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-12-documentation-site-navigation-and-chrome.md) | 中文 [English](2026-08-12-documentation-site-navigation-and-chrome.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-11-cmdline-program-action.md: 96cbe2342eef90e68dece3c78b12a2de1bbea7c0
2026-08-11-cmdline-program-action.zh.md: f5a9fea1447c78c9f099d3b54acd5b90a21aa503

View file

@ -1,6 +1,7 @@
# Agent Note: parseCmdline runs the program's own commander action # Agent Note: parseCmdline runs the program's own commander action
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-11-cmdline-program-action.zh.md) English | [中文](2026-08-11-cmdline-program-action.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: parseCmdline 运行 program 自己的 commander action # Agent Note: parseCmdline 运行 program 自己的 commander action
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-11-cmdline-program-action.md) | 中文 [English](2026-08-11-cmdline-program-action.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-11-quickstart-documentation-home.md: 653c702eba4c90e52ee0539959d926ae23a98e6c
2026-08-11-quickstart-documentation-home.zh.md: 3d21566f9e4a822d095a115a5e65bfbaa3f947df

View file

@ -1,6 +1,7 @@
# Agent Note: Route documentation roots to quick start # Agent Note: Route documentation roots to quick start
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-11-quickstart-documentation-home.zh.md) English | [中文](2026-08-11-quickstart-documentation-home.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 将文档根路由指向快速开始 # Agent Note: 将文档根路由指向快速开始
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-11-quickstart-documentation-home.md) | 中文 [English](2026-08-11-quickstart-documentation-home.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-13-remove-first-run-beta-notice.md: 535d0a20a5805c137551e6047f40fc5cf53153b8
2026-08-13-remove-first-run-beta-notice.zh.md: 20626bbd9d0bd13c00d4ee66f5dbc267c2e92082

View file

@ -1,6 +1,7 @@
# Agent Note: Remove the first-run beta notice # Agent Note: Remove the first-run beta notice
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-13-remove-first-run-beta-notice.zh.md) English | [中文](2026-08-13-remove-first-run-beta-notice.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 移除首次启动内测声明 # Agent Note: 移除首次启动内测声明
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-13-remove-first-run-beta-notice.md) | 中文 [English](2026-08-13-remove-first-run-beta-notice.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write
2026-08-19-knip-config-cleanup.md: 56426aeb7ff53caf7828b3f252269559e596940d
2026-08-19-knip-config-cleanup.zh.md: a74fa831f2301d9b95d5e34b003585293501c874

View file

@ -1,6 +1,7 @@
# Agent Note: Deleted stale and duplicative knip.json workspace entries # Agent Note: Deleted stale and duplicative knip.json workspace entries
Status: implemented Status: implemented
Archived: 2026-08-22
English | [中文](2026-08-19-knip-config-cleanup.zh.md) English | [中文](2026-08-19-knip-config-cleanup.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 删除 knip.json 中失效与重复的 workspace 条目 # Agent Note: 删除 knip.json 中失效与重复的 workspace 条目
Status: implemented Status: implemented
Archived: 2026-08-22
[English](2026-08-19-knip-config-cleanup.md) | 中文 [English](2026-08-19-knip-config-cleanup.md) | 中文

View file

@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/testing/2026-08-12-required-python-runtime-pull-request-ci.md
2026-08-12-required-python-runtime-pull-request-ci.md: e7da767f22634bd50bc4fd38b1de34677c4124e7
2026-08-12-required-python-runtime-pull-request-ci.zh.md: 702125b0da864eb35f1fe870748cc0e314b01a39

View file

@ -1,6 +1,7 @@
# Agent Note: Required Python runtime pull-request validation # Agent Note: Required Python runtime pull-request validation
Status: implemented Status: implemented
Archived: 2026-08-23
English | [中文](2026-08-12-required-python-runtime-pull-request-ci.zh.md) English | [中文](2026-08-12-required-python-runtime-pull-request-ci.zh.md)

View file

@ -1,6 +1,7 @@
# Agent Note: 必需的 Python 运行时拉取请求验证 # Agent Note: 必需的 Python 运行时拉取请求验证
Status: implemented Status: implemented
Archived: 2026-08-23
[English](2026-08-12-required-python-runtime-pull-request-ci.md) | 中文 [English](2026-08-12-required-python-runtime-pull-request-ci.md) | 中文

View file

@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority; # side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with: # after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.md # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.md
2026-06-11-content-block-vocabulary.md: a31df6a7d16ea7cba649702fdb474dab34533c1b 2026-06-11-content-block-vocabulary.md: d7d3f6b43a3f65d1421f026e5b6c2cc1ba1eadd2
2026-06-11-content-block-vocabulary.zh.md: da387b179816cda64791e71ca7affa1fbdfd195b 2026-06-11-content-block-vocabulary.zh.md: ed4f915dff6dcb6dbc91400f9bfa5384253aea7b

View file

@ -25,4 +25,4 @@ In-session context injection (`context/message`) and mid-turn steering originall
- Multimodal blocks return only with coordinated adapter, UI, and compaction support; see [the drop-image Agent Note](../../archived/simplification/2026-07-04-drop-image-content-block.md). - Multimodal blocks return only with coordinated adapter, UI, and compaction support; see [the drop-image Agent Note](../../archived/simplification/2026-07-04-drop-image-content-block.md).
- Cache hints and assistant prefill remain absent until a shipping adapter can honor them; see the [producer-less variants](../../archived/simplification/2026-07-04-prune-producerless-vocabulary-variants.md) and [inert request knobs](../../archived/simplification/2026-07-04-drop-inert-request-knobs.md) Agent Notes. - Cache hints and assistant prefill remain absent until a shipping adapter can honor them; see the [producer-less variants](../../archived/simplification/2026-07-04-prune-producerless-vocabulary-variants.md) and [inert request knobs](../../archived/simplification/2026-07-04-drop-inert-request-knobs.md) Agent Notes.
- Every adapter pays a translation cost; the first real adapters have since validated the streaming protocol, and new adapters should continue proving their provider-specific mapping in adapter-local tests. - Every adapter pays a translation cost; the first real adapters have since validated the streaming protocol, and new adapters should continue proving their provider-specific mapping in adapter-local tests.
- IDs that cross package boundaries are branded (`CallId`, the shared agent/session `SessionId`) — nominal typing at zero runtime cost. - IDs that cross package boundaries are branded (`ToolCallId`, the shared agent/session `SessionId`) — nominal typing at zero runtime cost.

View file

@ -25,4 +25,4 @@ harness 需要一套统一的内部消息语言,供 agent loop(智能体循
- 多模态块只有在适配器、UI 和上下文压缩(context compaction)三方协同支持后才会回归;见 [drop-image Agent Note](../../archived/simplification/2026-07-04-drop-image-content-block.md)。 - 多模态块只有在适配器、UI 和上下文压缩(context compaction)三方协同支持后才会回归;见 [drop-image Agent Note](../../archived/simplification/2026-07-04-drop-image-content-block.md)。
- 缓存提示与 assistant prefill 在有实际适配器能兑现之前保持缺席;见[无生产者的词汇变体](../../archived/simplification/2026-07-04-prune-producerless-vocabulary-variants.md)与[无端到端可用路径的请求旋钮](../../archived/simplification/2026-07-04-drop-inert-request-knobs.md) Agent Note。 - 缓存提示与 assistant prefill 在有实际适配器能兑现之前保持缺席;见[无生产者的词汇变体](../../archived/simplification/2026-07-04-prune-producerless-vocabulary-variants.md)与[无端到端可用路径的请求旋钮](../../archived/simplification/2026-07-04-drop-inert-request-knobs.md) Agent Note。
- 每个适配器都需承担翻译成本;首批真实适配器已验证了流式输出协议,新适配器应继续在适配器本地测试中验证其提供方特有的映射。 - 每个适配器都需承担翻译成本;首批真实适配器已验证了流式输出协议,新适配器应继续在适配器本地测试中验证其提供方特有的映射。
- 跨包边界的 ID 使用品牌类型(`CallId`、agent 与会话共享的 `SessionId`)——零运行时开销的名义类型。 - 跨包边界的 ID 使用品牌类型(`ToolCallId`、agent 与会话共享的 `SessionId`)——零运行时开销的名义类型。

View file

@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority; # side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with: # after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.md # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.md
2026-06-11-dev-invariants-over-deep-readonly.md: 66980f1ee09c6112f72786d6c3a147aadbc57f6c 2026-06-11-dev-invariants-over-deep-readonly.md: 7e5f55e8910797bd46674050ea5eb8abbca4aef7
2026-06-11-dev-invariants-over-deep-readonly.zh.md: 576e53e0b27e65f6fa071ff649509223a7bc30ff 2026-06-11-dev-invariants-over-deep-readonly.zh.md: c1413e9c89284312af41b6c115b7e50a99d1b5e3

View file

@ -22,7 +22,7 @@ Responsibility is split between an always-on storage boundary and optional devel
`Session` accepts an event only after one recursive pass has materialized a lossless JSON snapshot. That pass rejects unsupported values and produces the exact detached record that enters the log, so validation and storage cannot observe different values from a stateful getter or retain caller-owned nested references. `Session` accepts an event only after one recursive pass has materialized a lossless JSON snapshot. That pass rejects unsupported values and produces the exact detached record that enters the log, so validation and storage cannot observe different values from a stateful getter or retain caller-owned nested references.
The accepted event and all of its descendants are deep-frozen before publication. `append()` returns that owned frozen event, `session/event` observers receive the same record, and `session.events` returns a frozen array snapshot. A previously returned array does not grow after a later append. Seed records pass through the same validation, snapshot, and freeze boundary before construction succeeds. The accepted event and all of its descendants are deep-frozen before publication. `append()` returns that owned frozen event, and `session/event` observers and `eventAt(seq)` receive the same record. `snapshotEvents(fromSeq?, toSeqExclusive?)` returns a frozen array snapshot; a previously returned array does not grow after a later append. `seq` and `eventAt()` avoid array materialization when a caller needs only the current length or one event. Seed records pass through the same validation, snapshot, and freeze boundary before construction succeeds.
This guarantee belongs in `Session`, not in an optional listener, because every composition relies on trustworthy history. A production deployment, a focused test, or a custom embedding receives the same storage semantics whether or not development support plugins are registered. This guarantee belongs in `Session`, not in an optional listener, because every composition relies on trustworthy history. A production deployment, a focused test, or a custom embedding receives the same storage semantics whether or not development support plugins are registered.
@ -32,7 +32,7 @@ This guarantee belongs in `Session`, not in an optional listener, because every
### Package-owned invariant companions check relationships ### Package-owned invariant companions check relationships
`dsh-invariants` registers the configurable `ctx.invariants` service and contains no product checks. Every package publishes a `./invariant` ownership companion; `dsh-session`, `dsh-agent`, `dsh-scope`, and `dsh-agent-loop` currently add the rules that require trace state or observation of another seam: monotonic sequence numbers, turn and step nesting, tool-call/result pairing, legal agent-status transitions, subject-correct scoped dispatch, and equality between a loop-built request and the request reconstructed from its session-log prefix. Global enablement and package-name regex filters belong to the service ([package-owned invariant service](2026-07-19-package-owned-invariant-service.md)). `dsh-invariants` registers the configurable `ctx.invariants` service and contains no product checks. A package publishes a `./invariant` ownership companion only for an independently observable runtime relationship; packages without one omit the companion and record the reason in their README. `dsh-session`, `dsh-agent`, `dsh-scope`, and `dsh-agent-loop` provide the initial rules that require trace state or observation of another seam: monotonic sequence numbers, turn and step nesting, tool-call/result pairing, legal agent-status transitions, subject-correct scoped dispatch, and equality between a loop-built request and the request reconstructed from its session-log prefix. Global enablement and package-name regex filters belong to the service ([package-owned invariant service](2026-07-19-package-owned-invariant-service.md); [omission decision](../simplification/2026-08-28-omit-unneeded-invariant-companions.md)).
When the session companion attaches to an existing or seeded session, it replays the immutable log to rebuild trace state. The service gives each contribution a disposable child fiber, so hot reload is safe in the middle of a turn without giving diagnostics ownership of session storage. When the session companion attaches to an existing or seeded session, it replays the immutable log to rebuild trace state. The service gives each contribution a disposable child fiber, so hot reload is safe in the middle of a turn without giving diagnostics ownership of session storage.
@ -48,12 +48,12 @@ Freezing history only when an invariants plugin is installed would make the core
### Clone only when deriving messages ### Clone only when deriving messages
Detaching `deriveMessages()` would protect the most common request path but leave other readers of `session.events`, append return values, and session-event observers able to mutate durable history. The log must protect its own boundary; derived projections are an additional isolation boundary, not a substitute. Detaching `deriveMessages()` would protect the most common request path but leave other readers of `snapshotEvents()`, `eventAt()`, append return values, and session-event observers able to mutate durable history. The log must protect its own boundary; derived projections are an additional isolation boundary, not a substitute.
## Consequences ## Consequences
- Every accepted live or seeded session event is detached from caller-owned inputs and deeply immutable before any observer can receive it. - Every accepted live or seeded session event is detached from caller-owned inputs and deeply immutable before any observer can receive it.
- `session.events` exposes stable immutable snapshots instead of the private growing array. - `snapshotEvents()` exposes stable immutable snapshots instead of the private growing array; `seq` and `eventAt()` serve scalar reads without copying that array.
- Request-side mutation cannot reach stored history through derived messages. - Request-side mutation cannot reach stored history through derived messages.
- Development builds can enable relational assertions without changing storage behavior, and disposing or filtering a companion does not weaken log immutability. - Development builds can enable relational assertions without changing storage behavior, and disposing or filtering a companion does not weaken log immutability.
- `dsh-invariants` configures global enablement plus package allow/block regex lists; each check remains owned and tested by its product package. - `dsh-invariants` configures global enablement plus package allow/block regex lists; each check remains owned and tested by its product package.

View file

@ -22,7 +22,7 @@ TypeScript readonly 类型不是充分的运行时边界。它们在程序运行
`Session` 仅在一次递归遍历完成无损 JSON 快照的物化之后才接受事件。该遍历拒绝不支持的值,并产出进入日志的已分离的确切记录,因此验证与存储不会从有状态的 getter 观察到不同的值,也不会保留调用方拥有的嵌套引用。 `Session` 仅在一次递归遍历完成无损 JSON 快照的物化之后才接受事件。该遍历拒绝不支持的值,并产出进入日志的已分离的确切记录,因此验证与存储不会从有状态的 getter 观察到不同的值,也不会保留调用方拥有的嵌套引用。
被接受的事件及其所有后代在发布前被深度冻结。`append()` 返回由 Session 拥有的冻结事件,`session/event` 观察者接收同一记录,`session.events` 返回冻结的数组快照。先前返回的数组不会因后续 append 而增长。种子记录在构造成功前经过相同的验证、快照与冻结边界。 被接受的事件及其所有后代在发布前被深度冻结。`append()` 返回由 Session 拥有的冻结事件,`session/event` 观察者和 `eventAt(seq)` 接收同一记录。`snapshotEvents(fromSeq?, toSeqExclusive?)` 返回冻结的数组快照;先前返回的数组不会因后续 append 而增长。调用方只需要当前长度或单个事件时,`seq` 和 `eventAt()` 不会物化数组。种子记录在构造成功前经过相同的验证、快照与冻结边界。
此保证属于 `Session` 而非可选监听器,因为每种组合都依赖可信的历史。无论是否注册了开发支持插件,生产部署、聚焦测试或自定义嵌入都获得相同的存储语义。 此保证属于 `Session` 而非可选监听器,因为每种组合都依赖可信的历史。无论是否注册了开发支持插件,生产部署、聚焦测试或自定义嵌入都获得相同的存储语义。
@ -32,7 +32,7 @@ TypeScript readonly 类型不是充分的运行时边界。它们在程序运行
### 包拥有的不变式配套插件检查关系 ### 包拥有的不变式配套插件检查关系
`dsh-invariants` 注册可配置的 `ctx.invariants` 服务,本身不包含产品检查。每个包发布一个 `./invariant` 所有权配套插件;`dsh-session`、`dsh-agent`、`dsh-scope` 和 `dsh-agent-loop` 目前添加需要跟踪状态或观察另一个 seam 的规则:单调递增的序列号、轮次与步骤嵌套、工具调用/结果配对、合法的 agent(智能体)状态转换、主体正确的作用域分发,以及循环构建的请求与从其会话日志前缀重建的请求之间的相等性。全局启用和包名 regex 过滤器归该服务所有(见[包拥有的不变式服务](2026-07-19-package-owned-invariant-service.zh.md))。 `dsh-invariants` 注册可配置的 `ctx.invariants` 服务,本身不包含产品检查。只有拥有可独立观察的运行时关系时,包才发布 `./invariant` 所有权配套插件;没有该关系的包会省略 companion 并在 README 中记录原因。`dsh-session`、`dsh-agent`、`dsh-scope` 和 `dsh-agent-loop` 提供首批需要跟踪状态或观察另一个 seam 的规则:单调递增的序列号、轮次与步骤嵌套、工具调用/结果配对、合法的 agent(智能体)状态转换、主体正确的作用域分发,以及循环构建的请求与从其会话日志前缀重建的请求之间的相等性。全局启用和包名 regex 过滤器归该服务所有(见[包拥有的不变式服务](2026-07-19-package-owned-invariant-service.zh.md)与[省略决策](../simplification/2026-08-28-omit-unneeded-invariant-companions.zh.md))。
当会话配套插件附加到已有会话或以种子记录初始化的会话时,它回放不可变日志以重建跟踪状态。服务为每项贡献提供一个可 dispose(资源释放)的子 fiber,因此轮次中途热重载是安全的,同时不赋予诊断逻辑对会话存储的所有权。 当会话配套插件附加到已有会话或以种子记录初始化的会话时,它回放不可变日志以重建跟踪状态。服务为每项贡献提供一个可 dispose(资源释放)的子 fiber,因此轮次中途热重载是安全的,同时不赋予诊断逻辑对会话存储的所有权。
@ -48,12 +48,12 @@ TypeScript readonly 类型不是充分的运行时边界。它们在程序运行
### 仅在派生消息时克隆 ### 仅在派生消息时克隆
分离 `deriveMessages()` 能保护最常见的请求路径,但 `session.events` 的其他读取者、append 返回值和会话事件观察者仍能修改持久历史。日志必须保护自身的边界;派生投影是额外的隔离边界,而非替代品。 分离 `deriveMessages()` 能保护最常见的请求路径,但 `snapshotEvents()`、`eventAt()` 的其他读取者、append 返回值和会话事件观察者仍能修改持久历史。日志必须保护自身的边界;派生投影是额外的隔离边界,而非替代品。
## 后果 ## 后果
- 每个被接受的实时或种子会话事件在任何观察者接收之前,都已从调用方拥有的输入中分离并深度不可变。 - 每个被接受的实时或种子会话事件在任何观察者接收之前,都已从调用方拥有的输入中分离并深度不可变。
- `session.events` 暴露稳定的不可变快照,而非持续增长的私有数组。 - `snapshotEvents()` 暴露稳定的不可变快照,而非持续增长的私有数组;`seq` 和 `eventAt()` 为标量读取提供无需复制数组的路径。
- 请求侧的修改无法通过派生消息触及已存储的历史。 - 请求侧的修改无法通过派生消息触及已存储的历史。
- 开发构建可以启用关系断言而不改变存储行为;dispose 或过滤一个配套插件不会削弱日志不可变性。 - 开发构建可以启用关系断言而不改变存储行为;dispose 或过滤一个配套插件不会削弱日志不可变性。
- `dsh-invariants` 配置全局启用状态以及包名允许/阻止 regex 列表;每项检查仍由其产品包拥有并测试。 - `dsh-invariants` 配置全局启用状态以及包名允许/阻止 regex 列表;每项检查仍由其产品包拥有并测试。

View file

@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority; # side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with: # after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-13-capability-seams.md # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-13-capability-seams.md
2026-06-13-capability-seams.md: 2a166278ea454895177fa12b58f5493276f19cd1 2026-06-13-capability-seams.md: 46a2c39e927e859c7eb95956d8586f3bf04c7b1c
2026-06-13-capability-seams.zh.md: 28b45cbbc7f65a0b783db3d91a2e559132b5779f 2026-06-13-capability-seams.zh.md: f44e3e68d2153149435b0fd0aaa5fd121cf3ecad

View file

@ -6,7 +6,7 @@ English | [中文](2026-06-13-capability-seams.zh.md)
## Problem ## Problem
The harness has swappable capabilities — bash execution today, sandboxed/remote executors and alternative model providers tomorrow. A capability has three concerns that change at different rates and for different reasons: the *contract* (what the capability is), the *implementation* (how it runs), and the *consumer API* (what the model and other plugins program against). Bundling them in one package couples those rates of change — swapping a local executor for a sandboxed one would churn the tool schemas the model sees, even though the model-facing contract never changed. The harness has swappable capabilities, including shell execution and model providers. A capability has three concerns that change at different rates and for different reasons: the *contract* (what the capability is), the *implementation* (how it runs), and the *consumer API* (what the model and other plugins program against). Bundling them in one package couples those rates of change — swapping a local executor for a sandboxed one would churn the tool schemas the model sees, even though the model-facing contract never changed.
This is distinct from "who provides vs. needs a capability at runtime", which Cordis already answers with services + `inject` (a provider registers `ctx.shell`; a consumer declares `inject: ['bash']` and its fiber pends until the service exists). That mechanism is necessary but doesn't dictate package boundaries; this Agent Note does. This is distinct from "who provides vs. needs a capability at runtime", which Cordis already answers with services + `inject` (a provider registers `ctx.shell`; a consumer declares `inject: ['bash']` and its fiber pends until the service exists). That mechanism is necessary but doesn't dictate package boundaries; this Agent Note does.

View file

@ -6,7 +6,7 @@ Status: implemented
## 问题 ## 问题
harness 具有可替换的能力:当前是 bash 执行,未来会有沙箱化/远程执行器和替代模型提供方。一项能力涉及三个关注点,它们以不同速率、因不同原因变化:*约定*(这项能力是什么)、*实现*(它如何运行)、*消费方 API*(模型和其他插件面向什么编程)。将三者捆绑在一个包中会耦合这些变化速率——把本地执行器换成沙箱化执行器时,模型看到的工具 schema 也会被搅动,尽管面向模型的约定从未改变。 harness 具有可替换的能力,包括 shell 执行和模型提供方。一项能力涉及三个关注点,它们以不同速率、因不同原因变化:*约定*(这项能力是什么)、*实现*(它如何运行)、*消费方 API*(模型和其他插件面向什么编程)。将三者捆绑在一个包中会耦合这些变化速率——把本地执行器换成沙箱化执行器时,模型看到的工具 schema 也会被搅动,尽管面向模型的约定从未改变。
这与「谁在运行时提供、谁需要一项能力」是不同的问题,后者 Cordis 已通过服务 + `inject` 解决(提供方注册 `ctx.shell`;消费方声明 `inject: ['bash']`,其 fiber 挂起直到服务存在)。该机制是必要的,但不决定包的边界;本 Agent Note 决定的是包的边界。 这与「谁在运行时提供、谁需要一项能力」是不同的问题,后者 Cordis 已通过服务 + `inject` 解决(提供方注册 `ctx.shell`;消费方声明 `inject: ['bash']`,其 fiber 挂起直到服务存在)。该机制是必要的,但不决定包的边界;本 Agent Note 决定的是包的边界。

View file

@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority; # side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with: # after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-14-session-persistence.md # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-14-session-persistence.md
2026-06-14-session-persistence.md: 62228bd2f5b25b13880a563818d08f3a2d52d956 2026-06-14-session-persistence.md: a7e06af78c4a372be7a68f3e0f6dc18e38cbead1
2026-06-14-session-persistence.zh.md: ebf004333c383336cd025aa8a4aabc9d1e07f0e5 2026-06-14-session-persistence.zh.md: 6d458d4f4c31793212d674bb406204c3882a25ed

View file

@ -14,23 +14,23 @@ The [event-sourced model](2026-06-11-event-sourced-sessions.md) makes the append
Persistence is a **capability seam** with an abstract Service Definition ([capability seams](2026-06-13-capability-seams.md), the `dsh-shell` template), not loop or core logic: Persistence is a **capability seam** with an abstract Service Definition ([capability seams](2026-06-13-capability-seams.md), the `dsh-shell` template), not loop or core logic:
1. **Interface** (`dsh-session-persistence`, `ctx.sessionPersistence`) — an abstract `SessionPersistence` service: `locate`/`create`/`append`/`prepare`/`load`/`inspect`/`readFrom`/`list`/`listSnapshots`. Its persisted unit IS the existing `SessionEvent` (`{ type, seq, time, data }`), reused verbatim — no conversion type. 1. **Interface** (`dsh-session-persistence`, `ctx.sessionPersistence`) — an abstract `SessionPersistence` service: `create`/`open`/`stat`/`list`/`export`, with `create`/`open` returning per-session `SessionHandle`s that carry `read`/`append`/`flush`/`close` ([handle-based seam](2026-08-27-handle-based-session-persistence.md)). Its persisted unit IS the existing `SessionEvent` (`{ type, seq, time, data }`), reused verbatim — no conversion type.
2. **Implementation** (`dsh-session-persistence-jsonl`) — an append-only logical JSONL log per session: a `SessionHeader` line followed by storage records that losslessly represent the contiguous `SessionEvent` stream. Eligible `assistant/chunk` delta runs use packed rows by default; [checksummed Zstandard frames](2026-07-19-zstandard-jsonl-session-logs.md) are the default physical encoding, with raw lines configurable. 2. **Implementation** (`dsh-session-persistence-jsonl`) — an append-only logical JSONL log per session: a `SessionHeader` line followed by storage records that losslessly represent the contiguous `SessionEvent` stream. Eligible `assistant/chunk` delta runs use packed rows by default; [checksummed Zstandard frames](2026-07-19-zstandard-jsonl-session-logs.md) are the default physical encoding, with raw lines configurable.
Key durable, contested choices: Key durable, contested choices:
- **The canonical durable log persists every `SessionEvent` losslessly, including `assistant/chunk`.** JSONL storage may encode a consecutive delta run as one packed row, but logical readers reconstruct the exact event boundaries, sequence numbers, and timestamps. `deriveMessages()` skips chunks, and a chunk-filtered rollout (Codex's `policy.rs`) is tempting — but `seq = log.length` and validation of `events[i].seq === i` require a *contiguous* logical log; filtering chunks out would leave holes and break both the contract and resume. A chunk-filtered projection is possible later as a derived view with its own renumbering, but it is NOT the canonical log. - **The canonical durable log persists every `SessionEvent` losslessly, including `assistant/chunk`.** JSONL storage may encode a consecutive delta run as one packed row, but logical readers reconstruct the exact event boundaries, sequence numbers, and timestamps. `deriveMessages()` skips chunks, and a chunk-filtered rollout (Codex's `policy.rs`) is tempting — but `seq = log.length` and validation of `events[i].seq === i` require a *contiguous* logical log; filtering chunks out would leave holes and break both the contract and resume. A chunk-filtered projection is possible later as a derived view with its own renumbering, but it is NOT the canonical log.
- **Append-only; a crashed turn is closed, never truncated.** Flushed events are never rewritten. The [semantic checkpoint policy](../bug-fix/2026-07-21-semantic-session-checkpoints.md) drains the request before model dispatch, a recorded top-level call before tool dispatch, and the complete response/result batch after a step; the loop drains the final turn boundary. Because one interrupted turn may contain substantial valid work, cold inspection preserves its contiguous, parseable events and adds risk-classified error results for unanswered assistant calls, a missing `step/end`, and `turn/end` with `{ kind: 'interrupted' }` to the in-memory logical view. `prepare` or `load` commits those closers before returning a recoverable view; the synthetic results keep resumed provider transcripts valid. Only an incomplete final record is discarded during committed repair; a parse error or sequence gap at or before the last real `turn/end` is corruption and makes the session unloadable. - **Append-only; a crashed turn is closed, never truncated.** Flushed events are never rewritten. The [semantic checkpoint policy](../bug-fix/2026-07-21-semantic-session-checkpoints.md) drains the request before model dispatch, a recorded top-level call before tool dispatch, and the complete response/result batch after a step; the loop drains the final turn boundary. Because one interrupted turn may contain substantial valid work, persistence returns its contiguous, parseable events unmodified; the reader owns balancing — resume computes risk-classified error results for unanswered assistant calls, a missing `step/end`, and `turn/end` with `{ kind: 'interrupted' }` (`interruptedTurnClosers`) and appends them through its write handle, while read-only observers add the same closers in memory. The synthetic results keep resumed provider transcripts valid. Only the incomplete fragment of a torn final append is discarded — complete records recovered from it are durably rewritten by the write path before its first new append; a parse error or sequence gap in the committed prefix is corruption and makes the session unloadable.
- **File backend canonical, DB backend a proven drop-in.** `SessionEvent` maps 1:1 onto a row `(session_id, seq, type, time, data)` — `append` is INSERT (in a transaction asserting the contiguous-seq contract), and reads use SELECT … ORDER BY seq. `dsh-session-persistence-sqlite` is exactly this: a `SessionPersistence` subclass with no interface change (opencode runs this exact shape on SQLite/WAL), and it passes the same `runPersistenceContract` suite as the JSONL backend — so the contract holds both backends to identical semantics (lazy materialization, logical interrupted-turn closure, single committed repair, contiguous-seq), expressed once over file bytes and once over rows. Its database carries a dedicated application id and monotonic schema version. A pristine file creates all tables and stamps both header values in one transaction; an unversioned file with any user-defined schema object or application identity, a foreign current-version identity, and every non-current version reject before journal-mode mutation. - **The file backend is canonical while the service remains extensible.** `dsh-session-persistence-jsonl` is the sole first-party provider and passes `runPersistenceContract`; the abstract service remains available to out-of-tree providers. The [JSONL-only persistence decision](../simplification/2026-08-30-jsonl-only-session-persistence.md) owns removal of the first-party database provider and its deliberate compatibility cut.
- **Metadata is out-of-log.** Format version, cwd, and lineage are storage concerns, not replayable conversation state, so they live in a `SessionHeader` owned by `dsh-session` and attached to a `Session` via a new readonly `session.header` — never in `SessionEventMap`, never reaching `deriveMessages()`. `createdAt` is non-negative safe-integer Unix epoch milliseconds: live creation and persistence registration reject fractional values, JSONL validates the decoded header, and SQLite stores it in a strict `INTEGER` column. The alternative (a merge-extensible `session/meta` event as log line 0) was rejected: an in-log event would ride along with a seeded/forked session for free, but metadata is not replayable state, so the explicit out-of-log header boundary is the cleaner cost. (The header was originally split into an immutable `SessionHeader` plus a mutable `SessionSummary` whose union was `SessionMeta`; the mutable summary was later removed as dead state — see [Drop the mutable session summary](../simplification/2026-06-19-drop-mutable-session-summary.md).) - **Metadata is out-of-log.** Format version, cwd, and lineage are storage concerns, not replayable conversation state, so they live in a `SessionHeader` owned by `dsh-session` and attached to a `Session` via a new readonly `session.header` — never in `SessionEventMap`, never reaching `deriveMessages()`. `createdAt` is non-negative safe-integer Unix epoch milliseconds: live creation and persistence registration reject fractional values, and JSONL validates the decoded header. The alternative (a merge-extensible `session/meta` event as log line 0) was rejected: an in-log event would ride along with a seeded/forked session for free, but metadata is not replayable state, so the explicit out-of-log header boundary is the cleaner cost. (The header was originally split into an immutable `SessionHeader` plus a mutable `SessionSummary` whose union was `SessionMeta`; the mutable summary was later removed as dead state — see [Drop the mutable session summary](../simplification/2026-06-19-drop-mutable-session-summary.md).)
- **`ctx.agents.create()` and `ctx.agents.resume()` are async factories; resume additionally crosses the persistence boundary.** `ctx.agents.resume({ resumeSessionId })` obtains the exact unpublished Session through `ctx.sessionPersistence.prepare()`, publishes it under the persisted id, and continues its projections. The [Session preparation decision](2026-08-05-session-preparation.md) owns reuse between history inspection and resume. The agent-loop does NOT hard-inject `sessionPersistence` (that would pend non-persistent demos forever); `resume` rejects with a clear error when it is absent. - **`ctx.agents.create()` and `ctx.agents.resume()` are async factories; resume additionally crosses the persistence boundary.** `ctx.agents.resume({ resumeSessionId })` opens the session's write handle, reads the stored log, and publishes the prepared Session under the persisted id, continuing its projections. The [Session preparation decision](2026-08-05-session-preparation.md) owns the unpublished-Session ownership window. The agent-loop does NOT hard-inject `sessionPersistence` (that would pend non-persistent demos forever); `resume` rejects with a clear error when it is absent.
## Alternatives considered ## Alternatives considered
Each key choice above records its rejected alternative where the choice is stated: a **chunk-filtered canonical log** (Codex's `policy.rs` shape) — breaks the contiguous-seq contract; **truncating a crashed turn** — silently destroys a long autonomous run's real work; an **in-log `session/meta` event as line 0** — metadata is not replayable state; **finite fractional `createdAt` values** — have no producer and diverge from integer Unix-millisecond storage and query columns; **adopting a non-pristine unversioned SQLite file** — can overwrite unrelated objects or identity; **hard-injecting `sessionPersistence` into the loop** — would pend non-persistent demos forever. Each key choice above records its rejected alternative where the choice is stated: a **chunk-filtered canonical log** (Codex's `policy.rs` shape) — breaks the contiguous-seq contract; **truncating a crashed turn** — silently destroys a long autonomous run's real work; an **in-log `session/meta` event as log line 0** — metadata is not replayable state; **finite fractional `createdAt` values** — have no producer and diverge from integer Unix-millisecond storage; **hard-injecting `sessionPersistence` into the loop** — would pend non-persistent demos forever.
Format versioning: the header carries a `version`; cold reads reject any non-current version. The pre-release session format stays pinned at `SESSION_FORMAT_VERSION = 0` and carries no broad compatibility promise, while the coordinator may own an explicit narrow import upgrade when persisted user data requires it ([pre-identity message recovery](../bug-fix/2026-07-28-load-pre-identity-session-messages.md)). Append-only + flush is robust to partial trailing writes (tolerated during cold preparation) but not to fsync-less power loss mid-line; a DB/WAL backend is the stronger option there. Format versioning: the header carries a `version`; cold reads reject any non-current version. The pre-release session format stays pinned at `SESSION_FORMAT_VERSION = 0` and carries no compatibility promise: reads validate current v0 records only, and retired same-version shapes refuse fail-closed ([export and pre-release trims](../simplification/2026-08-27-persistence-export-and-pre-release-trims.md)). Append-only + flush is robust to partial trailing writes (tolerated during cold preparation) but not to fsync-less power loss mid-line; a DB/WAL backend is the stronger option there.
## Consequences ## Consequences
Two new packages and the metadata contract in `dsh-session` (`session.header`, the `create(id?, options?)` signature). Bought: durable resume/fork, a read/replay path, crash tolerance, and host-side session access over the existing event-sourced log, with the backend swappable behind one interface. The reusable `runPersistenceContract` suite holds every backend to the same append-only, contiguous-seq, lazy-materialization, logical-recovery, integer-metadata, and serializability semantics. Persisting the full logical log also settles event fidelity: every `assistant/chunk` survives exactly even when JSONL packs several into one storage row. SQLite initialization either commits its complete owned schema and header identity or leaves no partial schema to strand on the next open. The Service Definition, JSONL provider, and metadata contract in `dsh-session` (`session.header`, the `create(id?, options?)` signature) buy durable resume/fork, a read/replay path, crash tolerance, and host-side session access over the existing event-sourced log. The reusable `runPersistenceContract` suite holds the provider and future implementations to the same append-only, contiguous-seq, lazy-materialization, logical-recovery, integer-metadata, and serializability semantics. Persisting the full logical log also settles event fidelity: every `assistant/chunk` survives exactly even when JSONL packs several into one storage row.

View file

@ -14,23 +14,23 @@ Status: implemented
持久化是一个具有抽象 Service Definition 的**能力 seam**([能力 seam](2026-06-13-capability-seams.zh.md),`dsh-shell` 模板),而非循环或核心逻辑: 持久化是一个具有抽象 Service Definition 的**能力 seam**([能力 seam](2026-06-13-capability-seams.zh.md),`dsh-shell` 模板),而非循环或核心逻辑:
1. **接口**(`dsh-session-persistence`,`ctx.sessionPersistence`):一个抽象的 `SessionPersistence` 服务,提供 `locate`/`create`/`append`/`prepare`/`load`/`inspect`/`readFrom`/`list`/`listSnapshots`。其持久化单元就是现有的 `SessionEvent`(`{ type, seq, time, data }`),原样复用,无转换类型。 1. **接口**(`dsh-session-persistence`,`ctx.sessionPersistence`):一个抽象的 `SessionPersistence` 服务,提供 `create`/`open`/`stat`/`list`/`export`,其中 `create`/`open` 返回逐会话的 `SessionHandle`,句柄承载 `read`/`append`/`flush`/`close`([基于句柄的 seam](2026-08-27-handle-based-session-persistence.zh.md))。其持久化单元就是现有的 `SessionEvent`(`{ type, seq, time, data }`),原样复用,无转换类型。
2. **实现**(`dsh-session-persistence-jsonl`):每个会话一个仅追加的逻辑 JSONL 日志:先是一行 `SessionHeader`,随后是无损表示连续 `SessionEvent` 流的存储记录。符合条件的 `assistant/chunk` 增量连续段默认使用打包行;[带校验和的 Zstandard 帧](2026-07-19-zstandard-jsonl-session-logs.zh.md)是默认物理编码,也可通过配置使用原始行。 2. **实现**(`dsh-session-persistence-jsonl`):每个会话一个仅追加的逻辑 JSONL 日志:先是一行 `SessionHeader`,随后是无损表示连续 `SessionEvent` 流的存储记录。符合条件的 `assistant/chunk` 增量连续段默认使用打包行;[带校验和的 Zstandard 帧](2026-07-19-zstandard-jsonl-session-logs.zh.md)是默认物理编码,也可通过配置使用原始行。
长期有效、存在争议的关键选择: 长期有效、存在争议的关键选择:
- **规范的持久日志无损保留每个 `SessionEvent`,包括 `assistant/chunk`。** JSONL 存储可以将一段连续的增量事件编码为一条打包行,但逻辑读取方会重建精确的事件边界、序号与时间戳。`deriveMessages()` 跳过分片,而过滤分片的方案(Codex 的 `policy.rs`)很有吸引力,但 `seq = log.length` 以及 `events[i].seq === i` 验证要求*连续*的逻辑日志;过滤掉分片会留下空洞,同时破坏约定和恢复功能。基于分片过滤的投影可以作为派生视图在后续实现(带有自己的重新编号),但它不是规范日志。 - **规范的持久日志无损保留每个 `SessionEvent`,包括 `assistant/chunk`。** JSONL 存储可以将一段连续的增量事件编码为一条打包行,但逻辑读取方会重建精确的事件边界、序号与时间戳。`deriveMessages()` 跳过分片,而过滤分片的方案(Codex 的 `policy.rs`)很有吸引力,但 `seq = log.length` 以及 `events[i].seq === i` 验证要求*连续*的逻辑日志;过滤掉分片会留下空洞,同时破坏约定和恢复功能。基于分片过滤的投影可以作为派生视图在后续实现(带有自己的重新编号),但它不是规范日志。
- **仅追加;崩溃的轮次被关闭,而非截断。** 已刷写的事件永不被重写。[语义检查点策略](../bug-fix/2026-07-21-semantic-session-checkpoints.zh.md)会在调用模型前排空请求、在调用工具前排空已记录的顶层调用,并在步骤结束后排空完整的响应/结果批次;循环则排空最终轮次边界。由于一个被中断的轮次可能包含大量有效工作,冷检查会保留其连续、可解析的事件,并在内存逻辑视图中为未应答的 assistant 调用添加按风险分类的错误结果、补一个缺失的 `step/end`,以及带 `{ kind: 'interrupted' }` 的 `turn/end`。`prepare` 或 `load` 在返回可恢复视图前提交这些收尾事件;合成结果保证恢复后的提供方 transcript(文本记录)仍然有效。只有不完整的最后一条记录会在提交修复时被丢弃;在最后一个真实 `turn/end` 处或之前出现解析错误或序号间隙,属于数据损坏,会使该会话不可加载。 - **仅追加;崩溃的轮次被关闭,而非截断。** 已刷写的事件永不被重写。[语义检查点策略](../bug-fix/2026-07-21-semantic-session-checkpoints.zh.md)会在调用模型前排空请求、在调用工具前排空已记录的顶层调用,并在步骤结束后排空完整的响应/结果批次;循环则排空最终轮次边界。由于一个被中断的轮次可能包含大量有效工作,持久化会原样返回其连续、可解析的事件;配平是读方的职责——resume 会为未应答的 assistant 调用计算按风险分类的错误结果、补一个缺失的 `step/end`,以及带 `{ kind: 'interrupted' }` 的 `turn/end`(`interruptedTurnClosers`),并通过其写句柄追加它们,而只读观察方仅在内存中添加同样的收尾事件。合成结果保证恢复后的提供方 transcript(文本记录)仍然有效。只有撕裂的最终 append 中不完整的碎片会被丢弃——从中恢复的完整记录由写路径在第一次新 append 之前持久重写;已提交前缀中的解析错误或序号间隙,属于数据损坏,会使该会话不可加载。
- **文件后端为规范实现,数据库后端为经过验证的直接替换。** `SessionEvent` 1:1 映射到一行 `(session_id, seq, type, time, data)`:`append` 是 INSERT(在一个断言连续 seq 约定的事务中),读取使用 SELECT … ORDER BY seq。`dsh-session-persistence-sqlite` 正是如此:一个 `SessionPersistence` 子类,接口无变化(opencode 在 SQLite/WAL 上采用的正是这种接口形态),且通过与 JSONL 后端相同的 `runPersistenceContract` 测试套件。该约定以相同的语义约束两个后端(惰性物化、逻辑关闭中断轮次、修复只提交一次、连续 seq),一次表达在文件字节上,一次表达在数据库行上。其数据库拥有专用的 application id 与单调递增的 schema 版本。系统会在一个事务中为全新文件创建所有表并写入这两个 header 值;未版本化文件若带有任何用户定义的 schema 对象或应用标识、当前版本文件若带有外部应用标识,以及任何非当前版本文件,都会在修改日志模式之前被拒绝。 - **文件后端为规范实现,服务保持可扩展。** `dsh-session-persistence-jsonl` 是唯一 first-party provider,并通过 `runPersistenceContract`;抽象服务继续供仓库外 provider 使用。[JSONL-only 持久化决策](../simplification/2026-08-30-jsonl-only-session-persistence.zh.md)负责 first-party 数据库 provider 的删除及其明确 compatibility cut。
- **元数据在日志之外。** 格式版本、cwd 和谱系是存储关注点,不是可回放的对话状态,因此它们存放在 `dsh-session` 拥有的 `SessionHeader` 中,并通过新的只读属性 `session.header` 附加到 `Session` 上——永远不进入 `SessionEventMap`,永远不到达 `deriveMessages()`。`createdAt` 是以 Unix epoch 毫秒表示的非负安全整数:运行时创建和持久化注册会拒绝小数值,JSONL 会验证解码后的 header,SQLite 则将其存入严格的 `INTEGER` 列。替代方案(一个可合并扩展的 `session/meta` 事件作为日志第 0 行)被否决:日志内事件会自然随 seed/fork 的会话携带,但元数据不是可回放状态,因此显式的日志外 header 边界是更清晰的取舍。(header 最初被拆分为不可变的 `SessionHeader` 加可变的 `SessionSummary`,二者的联合类型为 `SessionMeta`;可变 summary 后来因属于死状态而被移除——见 [移除可变会话摘要](../simplification/2026-06-19-drop-mutable-session-summary.zh.md)。) - **元数据在日志之外。** 格式版本、cwd 和谱系是存储关注点,不是可回放的对话状态,因此它们存放在 `dsh-session` 拥有的 `SessionHeader` 中,并通过新的只读属性 `session.header` 附加到 `Session` 上——永远不进入 `SessionEventMap`,永远不到达 `deriveMessages()`。`createdAt` 是以 Unix epoch 毫秒表示的非负安全整数:运行时创建和持久化注册会拒绝小数值,JSONL 会验证解码后的 header。替代方案(一个可合并扩展的 `session/meta` 事件作为日志第 0 行)被否决:日志内事件会自然随 seed/fork 的会话携带,但元数据不是可回放状态,因此显式的日志外 header 边界是更清晰的取舍。(header 最初被拆分为不可变的 `SessionHeader` 加可变的 `SessionSummary`,二者的联合类型为 `SessionMeta`;可变 summary 后来因属于死状态而被移除——见 [移除可变会话摘要](../simplification/2026-06-19-drop-mutable-session-summary.zh.md)。)
- **`ctx.agents.create()` 和 `ctx.agents.resume()` 是异步工厂;恢复还跨越持久化边界。** `ctx.agents.resume({ resumeSessionId })` 通过 `ctx.sessionPersistence.prepare()` 取得精确的未发布 Session,以持久化 id 发布它,并继续其投影。[Session 准备阶段决策](2026-08-05-session-preparation.zh.md)定义历史检查与恢复之间的复用。agent loop(智能体循环)不会硬注入 `sessionPersistence`(那样会让非持久化的演示永远挂起);当它不存在时,`resume` 会以明确的错误拒绝。 - **`ctx.agents.create()` 和 `ctx.agents.resume()` 是异步工厂;恢复还跨越持久化边界。** `ctx.agents.resume({ resumeSessionId })` 打开该会话的写句柄,读取已存储的日志,并以持久化 id 发布准备好的 Session,继续其投影。[Session 准备阶段决策](2026-08-05-session-preparation.zh.md)定义未发布 Session 的所有权窗口。agent loop(智能体循环)不会硬注入 `sessionPersistence`(那样会让非持久化的演示永远挂起);当它不存在时,`resume` 会以明确的错误拒绝。
## 曾考虑的替代方案 ## 曾考虑的替代方案
上述每个关键选择都在陈述处记录了被否决的替代方案:**过滤分片的规范日志**(Codex 的 `policy.rs` 形式)破坏连续 seq 约定;**截断崩溃的轮次**会静默销毁长时间自主运行中的真实工作;**日志内 `session/meta` 事件作为第 0 行**——元数据不是可回放状态;**有限的非整数 `createdAt` 值**没有生产方,且与整数 Unix 毫秒存储及查询列不一致;**接受非全新的未版本化 SQLite 文件**可能覆盖无关对象或应用标识;**将 `sessionPersistence` 硬注入循环**会让非持久化的演示永远挂起。 上述每个关键选择都在陈述处记录了被否决的替代方案:**过滤分片的规范日志**(Codex 的 `policy.rs` 形式)破坏连续 seq 约定;**截断崩溃的轮次**会静默销毁长时间自主运行中的真实工作;**日志内 `session/meta` 事件作为第 0 行**——元数据不是可回放状态;**有限的非整数 `createdAt` 值**没有生产方,且与整数 Unix 毫秒存储不一致;**将 `sessionPersistence` 硬注入循环**会让非持久化的演示永远挂起。
格式版本控制:header 携带一个 `version`;冷读取拒绝任何非当前版本。预发布阶段的会话格式仍固定为 `SESSION_FORMAT_VERSION = 0`,不承诺广泛兼容;当持久化用户数据确有需要时,协调器可以负责显式且范围受限的导入升级([消息标识机制引入前的消息恢复](../bug-fix/2026-07-28-load-pre-identity-session-messages.zh.md))。仅追加 + 刷写对尾部的不完整写入具有健壮性(冷准备时可容忍),但无法抵御未使用 fsync 时在行写入中途断电;数据库/WAL 后端是该场景下更强的选项。 格式版本控制:header 携带一个 `version`;冷读取拒绝任何非当前版本。预发布阶段的会话格式仍固定为 `SESSION_FORMAT_VERSION = 0`,不作兼容承诺:读取只校验当前 v0 记录,已废弃的同版本形态会以 fail-closed 方式拒绝([导出与预发布精简](../simplification/2026-08-27-persistence-export-and-pre-release-trims.zh.md))。仅追加 + 刷写对尾部的不完整写入具有健壮性(冷准备时可容忍),但无法抵御未使用 fsync 时在行写入中途断电;数据库/WAL 后端是该场景下更强的选项。
## 后果 ## 后果
新增两个包,以及 `dsh-session` 中的元数据约定(`session.header`,`create(id?, options?)` 签名)。收益:持久恢复/fork、读取/回放路径、崩溃容忍,以及基于现有事件溯源日志的宿主侧会话访问,后端可在同一接口下替换。可复用的 `runPersistenceContract` 测试套件以相同的仅追加、连续 seq、惰性物化、逻辑恢复、整数元数据与可序列化语义约束每个后端。持久化完整的逻辑日志还确定了事件保真度:即使 JSONL 将多个 `assistant/chunk` 打包到一条存储行中,每个事件也会精确保留。SQLite 初始化要么提交完整的自有 schema 与 header 标识,要么不留下任何会使下次打开受阻的部分 schema。 Service Definition、JSONL provider 与 `dsh-session` 中的元数据约定(`session.header`,`create(id?, options?)` 签名)带来持久恢复/fork、读取/回放路径、崩溃容忍,以及基于现有事件溯源日志的宿主侧会话访问。可复用的 `runPersistenceContract` 测试套件以相同的仅追加、连续 seq、惰性物化、逻辑恢复、整数元数据与可序列化语义约束该 provider 与未来实现。持久化完整的逻辑日志还确定了事件保真度:即使 JSONL 将多个 `assistant/chunk` 打包到一条存储行中,每个事件也会精确保留。

View file

@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority; # side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with: # after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-18-session-surface.md # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-18-session-surface.md
2026-06-18-session-surface.md: 3682ae7b8b58b9e5d40695732c3a1531d0651d5e 2026-06-18-session-surface.md: 95298da0e4bd16e822cb5960718d23ecda7a1b5c
2026-06-18-session-surface.zh.md: 8cba9645dc6d0c8a4d1ee096668fc0bc38aaa725 2026-06-18-session-surface.zh.md: 7dd05d79f635b193b2c11cb3599264ebf2424d79

View file

@ -41,7 +41,7 @@ Delta processing is O(1) when no new events and O(new events) when new events ar
### Persistence ### Persistence
The new fields are serialized as top-level JSON properties. The JSONL backend requires zero changes — `JSON.stringify`/`JSON.parse` preserve everything transparently. The SQLite backend's `events` table carries two nullable TEXT columns (`source_event_seqs`, `surface_op`). The on-disk `SCHEMA_VERSION` is bumped to reflect the column set, and — per the pre-release bump-and-reject policy — a database written by any other build is REJECTED on open rather than migrated (there is no persisted user data to upgrade). The session format `version` is pinned at `SESSION_FORMAT_VERSION = 0` (the "unstable / pre-release" stance): the optional surface fields are absorbed without bumping it. The new fields are serialized as top-level JSON properties. JSONL storage requires no separate column mapping: its lossless JSON boundary preserves both values. The session format `version` is pinned at `SESSION_FORMAT_VERSION = 0`; the optional surface fields are absorbed without bumping it.
### Crash recovery ### Crash recovery
@ -64,7 +64,6 @@ Every surface-eligible event must carry `surfaceOp` or it would disappear from d
- **`packages/core/session`**: `surface.ts` (`SurfaceManager`) maintains one ordered seq array for candidate acceptance and live projection; `SessionSurface` is its readonly public view. `SurfaceOp`/`SurfaceIntent` and the top-level session-event fields record how entries join it. `append()` requires a `SurfaceIntent` for surface events, `deriveMessages()` walks the surface as the sole derivation path, and `repair.ts` emits surface-aware closers. The seed constructor rejects a surface-eligible seed event missing its `surfaceOp` marker (see § Invariants). - **`packages/core/session`**: `surface.ts` (`SurfaceManager`) maintains one ordered seq array for candidate acceptance and live projection; `SessionSurface` is its readonly public view. `SurfaceOp`/`SurfaceIntent` and the top-level session-event fields record how entries join it. `append()` requires a `SurfaceIntent` for surface events, `deriveMessages()` walks the surface as the sole derivation path, and `repair.ts` emits surface-aware closers. The seed constructor rejects a surface-eligible seed event missing its `surfaceOp` marker (see § Invariants).
- **`packages/core/agent-loop`**: All surface-capable appends pass surface opts. Each `assistant/message` cites its chunk seqs; each `tool/result` cites its `tool/call` seq. - **`packages/core/agent-loop`**: All surface-capable appends pass surface opts. Each `assistant/message` cites its chunk seqs; each `tool/result` cites its `tool/call` seq.
- **`packages/session/session-persistence-sqlite`**: Two new nullable TEXT columns (`source_event_seqs`, `surface_op`) on the `events` table; `SCHEMA_VERSION` bumped (bump-and-reject, no migration).
- **`packages/session/session-persistence-jsonl`**: No changes required. - **`packages/session/session-persistence-jsonl`**: No changes required.
- **`packages/session/session-persistence`**: Abstract interface unchanged. - **`packages/session/session-persistence`**: Abstract interface unchanged.

View file

@ -41,7 +41,7 @@ export type SurfaceOp =
### 持久化 ### 持久化
新字段作为顶层 JSON 属性序列化。JSONL 后端无需任何改动:`JSON.stringify`/`JSON.parse` 透明地保留一切。SQLite 后端的 `events` 表新增两个可空 TEXT 列(`source_event_seqs`、`surface_op`)。磁盘上的 `SCHEMA_VERSION` 递增以反映列集变化,并且按照预发布的 bump-and-reject 策略,由其他构建写入的数据库在打开时被拒绝而非迁移(没有需要升级的持久化用户数据)。会话格式 `version` 固定为 `SESSION_FORMAT_VERSION = 0`(「不稳定/预发布」立场):可选的 surface 字段被吸收而不递增版本号。 新字段作为顶层 JSON 属性序列化。JSONL 存储无需单独列映射:其无损 JSON 边界会保留两个值。会话格式 `version` 固定为 `SESSION_FORMAT_VERSION = 0`;可选 surface 字段被吸收而不递增版本号。
### 崩溃恢复 ### 崩溃恢复
@ -64,7 +64,6 @@ export type SurfaceOp =
- **`packages/core/session`**:`surface.ts`(`SurfaceManager`)维护一个用于候选接纳和实时投影的有序 seq 数组;`SessionSurface` 是其只读公共视图。`SurfaceOp`/`SurfaceIntent` 与顶层会话事件字段记录条目如何加入它。`append()` 要求 surface 事件携带 `SurfaceIntent`,`deriveMessages()` 以遍历 surface 作为唯一派生路径,`repair.ts` 则发出 surface 感知的闭合事件。种子构造函数拒绝缺少 `surfaceOp` 标记的可进入 surface 的种子事件(见「不变式」一节)。 - **`packages/core/session`**:`surface.ts`(`SurfaceManager`)维护一个用于候选接纳和实时投影的有序 seq 数组;`SessionSurface` 是其只读公共视图。`SurfaceOp`/`SurfaceIntent` 与顶层会话事件字段记录条目如何加入它。`append()` 要求 surface 事件携带 `SurfaceIntent`,`deriveMessages()` 以遍历 surface 作为唯一派生路径,`repair.ts` 则发出 surface 感知的闭合事件。种子构造函数拒绝缺少 `surfaceOp` 标记的可进入 surface 的种子事件(见「不变式」一节)。
- **`packages/core/agent-loop`**:所有涉及 surface 事件的追加操作都传入 surface 选项。每个 `assistant/message` 都引用产生它的分片 seq;每个 `tool/result` 都引用它的 `tool/call` seq。 - **`packages/core/agent-loop`**:所有涉及 surface 事件的追加操作都传入 surface 选项。每个 `assistant/message` 都引用产生它的分片 seq;每个 `tool/result` 都引用它的 `tool/call` seq。
- **`packages/session/session-persistence-sqlite`**:`events` 表新增两个可空 TEXT 列(`source_event_seqs`、`surface_op`);`SCHEMA_VERSION` 递增(bump-and-reject,无迁移)。
- **`packages/session/session-persistence-jsonl`**:无需改动。 - **`packages/session/session-persistence-jsonl`**:无需改动。
- **`packages/session/session-persistence`**:抽象接口不变。 - **`packages/session/session-persistence`**:抽象接口不变。

Some files were not shown because too many files have changed in this diff Show more