fix: harden subprocess, maintenance, and output paths (#100440)

* fix(agents): contain exec output stream failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(tui): contain local shell stream failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(process): contain command output stream failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(skills): isolate remote bin refresh failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(agents): contain background subagent sweep failures

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(skills): report directory scan failures

Co-authored-by: wendy-chsy <wan.wenyan@xydigit.com>

* fix(agents): classify plugin approval gateway failures

Co-authored-by: 唐梓夷0668001293 <tang.ziyi@xydigit.com>

* fix(exec): preserve sanitized control-byte evidence

Co-authored-by: Lavya Tandel <lavya@loom.local>

* fix(shared): unwrap standalone parameter tags

Co-authored-by: nankingjing <1079826437@qq.com>

* fix(android): fail shared capture on audio read errors

Co-authored-by: NianJiuZst <3235467914@qq.com>

* docs(changelog): record small bugfix sweep

* fix(output): preserve sanitizer boundary semantics

* test: align sanitizer and sweeper regressions

* fix(terminal): preserve text after lone C1 controls

---------

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: wendy-chsy <wan.wenyan@xydigit.com>
Co-authored-by: 唐梓夷0668001293 <tang.ziyi@xydigit.com>
Co-authored-by: Lavya Tandel <lavya@loom.local>
Co-authored-by: nankingjing <1079826437@qq.com>
Co-authored-by: NianJiuZst <3235467914@qq.com>
This commit is contained in:
Peter Steinberger
2026-07-05 22:21:54 +01:00
committed by GitHub
parent 8c19dbfb62
commit a4b032e5d7
24 changed files with 555 additions and 71 deletions
+14
View File
@@ -346,6 +346,20 @@ describe("runCommandWithTimeout", () => {
},
);
it("does not crash when stdout or stderr emit an error event", async () => {
await loadExecModules({ mockSpawn: true });
const child = createKilledChild();
spawnMock.mockReturnValue(child);
const resultPromise = runCommandWithTimeout(createSilentIdleArgv(), { timeoutMs: 2_000 });
child.stdout?.emit("error", new Error("stdout read failed"));
child.stderr?.emit("error", new Error("stderr read failed"));
child.emit("exit", 0, null);
child.emit("close", 0, null);
await expect(resultPromise).resolves.toMatchObject({ code: 0, termination: "exit" });
});
it("preserves matching output lines even when the tail capture truncates them", async () => {
await loadExecModules();
const result = await runCommandWithTimeout(
+4
View File
@@ -612,6 +612,10 @@ export async function runCommandWithTimeout(
child.stdin.end();
}
// Output pipes may fail independently; child exit/close remains authoritative.
const ignoreOutputStreamError = () => {};
child.stdout?.on("error", ignoreOutputStreamError);
child.stderr?.on("error", ignoreOutputStreamError);
child.stdout?.on("data", (d) => {
appendPreservedOutputLines({
capture: stdoutCapture,