feat(tool): govern background command job lifecycle (cap, memory floor, shutdown reaping) - #2761
Merged
Merged
Conversation
…ecl check (#2734) jsClassRe required the class name to be followed immediately by '{' or '<', so 'class Foo extends Bar {' / 'implements' forms -- the dominant class shape in real JS/TS -- were never counted. Old/new counts both 0 meant the duplicate-class check was silent dead code for those forms. Add an optional extends/implements heritage list before the terminator; 4 new tests pin match forms, non-class exclusions, duplicate detection, and the legitimate heritage-change no-warning case.
Multiple self-declared scope constraints formed an implicit AND: after two different scope declarations every edit violated one of them, burning the cvMaxWarnings quota with false positives while real violations went silent. Scope declarations now REPLACE prior scope constraints; avoid constraints stay additive. 4 regression tests in zz_issue2733_test.go. Co-Authored-By: ggcode <noreply@ggcode.dev>
…et.TCPConn assertion (#2747) Production conn is always *tls.Conn (defaultDialIRC wraps tls.Client), so the type assertion never matched and #2113 F2 anti-wedge protection was dead code. Call SetWriteDeadline directly through the interface (tls.Conn propagates to the wrapped TCP conn) and clear it after the write. Co-Authored-By: ggcode <noreply@ggcode.dev>
…cation (#2754) case "test", "pytest" flipped testsRan for any run_command whose first token was 'test' - but bare 'test' is the POSIX shell conditional builtin ('test -f x', 'test -d dist && rm -rf dist'), not a test run. This silently disarmed the git_commit/git push reversibility gate, same false-verification family as #2255 and #2552. Narrowed to bare test runners (pytest/py.test/vitest/jest); #1194 semantics preserved. Co-Authored-By: ggcode <noreply@ggcode.dev>
…2748) runStatuslineCommand now returns (text, ok); handleStatuslineMsg only replaces the cached text on success, honoring the documented contract. Failed refresh still clears running/dirty so refresh cadence is unchanged.
Phase 3 of the reproducer lifecycle tracker only checked the tool name (run_command/start_command), so any intermediate command like 'git diff' or 'ls' discharged the re-run obligation. Now the command must match the reproducer script shape (reproducerCommandRe) or share a distinctive token with the recorded reproducer snippet. Also replaces the unused reproducerFertilityWindow constant with reproducerRerunGraceIterations and fixes the stale comment in checkIncomplete. Co-Authored-By: ggcode <noreply@ggcode.dev>
…r, shutdown reaping) start_command background jobs were the only background work class that survived session exit as orphan processes: TUI shutdownAll cancelled sub-agents, swarm teammates, panes and knight tasks, but never the CommandJobManager — detach=true dev servers and long builds kept running after quit//restart, holding ports and memory. There was also no ceiling on concurrently running jobs or on process memory, the documented OOM vector on shared machines (exit-137 builds). Implements the harness-engineering "cheap caps" floor for the command loop, aligned with Hermes-style safety-gated parallel batches: - CommandJobManager.ShutdownAll(wait): cancel all running jobs, wait up to `wait`, return the reaped count. Cancelled jobs stay readable as terminal entries so late read_command_output still explains the stop. - Admission gate at spawn: refuse new jobs when running >= cap (default 8, GGCODE_MAX_RUNNING_JOBS) or when process memory (MemStats.Sys) exceeds the ceiling (GGCODE_JOB_MEM_LIMIT > GOMEMLIMIT*1.5 > 3GiB). Refusal messages are actionable (stop_command / poll / override env), sampled at spawn time with no new goroutines. - Registry.JobManager() accessor; manager wired in RegisterBuiltinTools. - Reaping wired at every exit: TUI shutdownAll (quit/ctrl+d//restart exec handoff), RunPipe, and ACP server exit. Co-Authored-By: ggcode <noreply@ggcode.dev> Co-Authored-By: ggcode <noreply@ggcode.dev>
Owner
Author
|
合并说明:reviewer 书面 approve(四点实证:准入拒绝非驱逐+运行中永不静默杀/OS 实测采样+env 可调/terminal 条目保留迟到读取无悬空/detach 豁免 timeout 不豁免 ShutdownAll 语义分层正确;捆装 7 修复探针回归 ok)。CI 全绿。执行合并。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
start_commandbackground jobs were the only background work class that survived session exit as orphan processes. TUIshutdownAll()cancelled sub-agents, swarm teammates, ext/cmd panes and knight tasks — but never theCommandJobManager. A detached dev server or a 24h-timeout build kept running after quit//restart, holding ports and memory with no way to stop it from the new session.There was also no ceiling on concurrently running background jobs and no memory-pressure awareness: every retry piled another build onto an already-swapping machine (our own CI/shared machines see exit-137 OOM kills from exactly this pattern).
Change (harness-engineering "cheap caps" floor)
Per the Harness Engineering paper (Rec 18: do ship the cheap caps; Hermes: safety-gated parallel batches), this adds bounded resources to the command loop:
ShutdownAll(wait)onCommandJobManager: cancel all running jobs, wait up towait, return reaped count. Cancelled jobs stay readable as terminal entries so lateread_command_outputstill explains the stop.GGCODE_MAX_RUNNING_JOBS);MemStats.Sys) exceeds ceiling (GGCODE_JOB_MEM_LIMIT>GOMEMLIMIT×1.5 > 3 GiB);stop_command/ poll / override env). Ownership never transfers on refusal — no phantom job entries.shutdownAll(quit / ctrl+d //restartexec handoff),RunPipe, ACP server exit.Registry.JobManager()accessor; manager wired inRegisterBuiltinTools(single line, mirrorscodeIndex).Not changed
stop_command).Tests
5 new tests in
command_jobs_lifecycle_test.go: ShutdownAll reaping + terminal-entry readability, empty-manager no-op, cap refusal + no phantom entries + slot reuse, memory-pressure refusal, env-limit resolution (valid/invalid).