Files
kandev/docs/plans/noninteractive-git-execution/task-02-owned-cleanup.md
T
2026-09-13 21:57:54 +01:00

4.7 KiB

id, title, status, wave, depends_on, plan, requirements, acceptance_criteria, system_design
id title status wave depends_on plan requirements acceptance_criteria system_design
02-owned-cleanup Bound Git helpers and streaming cleanup done 2
01-prompt-policy
plan.md
REQ-PLATFORM-GIT-SUBPROCESS-ADMISSION-002
AC-PLATFORM-GIT-SUBPROCESS-ADMISSION-002.3
AC-PLATFORM-GIT-SUBPROCESS-ADMISSION-002.4
../../specs/platform/system-design/git-subprocess-execution.md

Task 02: Bound Git helpers and streaming cleanup

Summary

Helper hangs and inherited pipes return within execution plus cleanup bounds; slots and owned resources are released on every terminal path.

In scope

Add command-owned lifecycle support below agentctl. Preserve existing agents through compatibility wrappers if generic Windows job code moves. The execution design defines Unix session isolation, Windows suspended-start job attachment, 500 ms pipe waiting, and two-second cleanup limits. Reject incompatible process attributes before start and preserve stronger compatible cleanup.

Write TestGitHelperCancellationReleasesSlot and TestGitDescendantPipeCleanup before changing lifecycle execution. Use helpers which hang, spawn pipe-holding descendants, and exit while descendants retain pipes. Add a marker proving owned descendants stop and an unrelated control process remains alive. Cover start failure, cancellation races, normal exit, cleanup failure, and repeated preparation. Use TestWindowsManagedGitJobCleanup on Windows to prove attachment precedes descendant execution.

Migrate all manual AcquireGit/Run paths in manager_git.go and streaming capDiffOutput. Write TestCapDiffOutputCancellationClosesReader with a pipe-holding descendant before fixing the pre-Wait read/drain. Keep the full Start-to-Wait lifetime inside one slot. Extend raw_git_audit_test.go to detect bypasses and test its rejection fixtures. Retain the narrow descriptor-based gitinit exception; test its existing ownership contract unchanged.

Out of scope

Credential-authority changes, transport fallback, live-instance changes, and unrelated refactors.

Acceptance

  • Helper hangs and inherited pipes return within execution plus cleanup bounds; slots and owned resources are released on every terminal path.
  • Run new behavioral tests before implementation and record the expected failure, then the passing result.
  • Preserve the contracts and exclusions in the linked design.

Verification

(cd apps/backend && go test ./internal/common/... ./internal/agentctl/server/winproc ./internal/agentctl/server/process ./internal/worktree ./internal/task/gitinit -count=1 -timeout=5m)
(cd apps/backend && go test -race ./internal/common/subproc -count=1 -timeout=5m)

Run the same applicable package tests on native Windows. Skip only Unix PTY assertions; record platform evidence separately.

Files likely touched

  • apps/backend/internal/common/subproc/shared.go
  • apps/backend/internal/common/subproc/git_lifecycle*.go (new)
  • apps/backend/internal/common/subproc/raw_git_audit_test.go
  • apps/backend/internal/common/winproc/ (generic lifecycle code, if extracted)
  • apps/backend/internal/agentctl/server/winproc/lifecycle_windows.go
  • apps/backend/internal/agentctl/server/winproc/lifecycle_other.go
  • apps/backend/internal/agentctl/server/process/workspace_git_diff.go
  • apps/backend/internal/agentctl/server/process/workspace_git_diff_test.go
  • apps/backend/internal/worktree/manager_git.go
  • apps/backend/internal/task/gitinit/command_descriptor.go

Dependencies

01-prompt-policy.

Risks

Credential helper and process-lifecycle compatibility require real subprocess evidence. Do not infer success from environment assertions alone.

Parallelism

sequential

Inputs

Results

Implemented after Task 01 on the verified PR #3635 descendant 9cc146ee21c296d553ae684531219a5c711a4213.

Results: shared lifecycle code now owns Git Start-to-Wait, Unix session/process-group cleanup, Windows suspended Job Object attachment, pipe closure, and admission release. Manual worktree and streaming diff paths use the shared lifecycle; incompatible terminal and process-group attributes fail before start. The narrow task/gitinit descriptor exception remains unchanged.

Checks passed:

  • (cd apps/backend && go test ./internal/common/... ./internal/agentctl/server/winproc ./internal/agentctl/server/process ./internal/worktree ./internal/task/gitinit -count=1 -timeout=10m)
  • (cd apps/backend && go test -race ./internal/common/subproc -count=1 -timeout=10m)
  • Windows cross-compilation of the shared subprocess, agentctl process, and common Windows lifecycle test binaries.