15 KiB
created, status, requirements, system_design, legacy_specs
| created | status | requirements | system_design | legacy_specs | ||||
|---|---|---|---|---|---|---|---|---|
| 2026-09-13 | completed |
|
|
Implementation Plan: Noninteractive Git execution
Overview
Enforce application Git prompt suppression after callers assemble their environments, then bound helper cleanup and uncovered network operations. Prove selected credential compatibility and task recovery before updating public guidance. The five work orders were implemented sequentially on the verified PR #3635 descendant and validated with focused backend, web, build, documentation, and desktop/mobile E2E checks.
Evidence and root cause
Source inspected at bd7974dc8, matching the supplied report's build.
NewGitCommand constructs Git without prompt controls. All shared runner variants execute caller commands without final preparation.
GitOperator.runGitCommandWithEnvironment replaces the environment after construction, making constructor-only enforcement insufficient.
Local worktree, repository-fetch, and tracker helpers apply inconsistent controls; the tracker uses GIT_ASKPASS=echo.
A temporary real-Git experiment on 2026-09-13 used a controlling PTY, isolated HOME/global/system config, and credential.helper=!false.
git credential fill for example.invalid printed a username prompt and was still waiting after 1.039 seconds.
With terminal prompting disabled, deny-only askpass, and GCM noninteractive mode, Git failed in 0.047 seconds.
The parent killed only its owned waiting process group. No network, credentials, or live instance were used.
The failure diagnostic also quotes the username prompt, so substring absence alone is not a correct regression assertion.
This confirms the terminal-fallback mechanism and missing enforcement boundary. The original task-navigation subprocess, regression commit, whole-backend outage, and provider-trigger hypothesis remain unconfirmed. The supplied GitHub incident and invalid-token observations are reported context, not independently verified facts in this package.
Merged dependency: PR #3635
PR #3635 merged on 2026-09-13 at 11:19:46 UTC as 9cc146ee21c296d553ae684531219a5c711a4213.
The merge commit was the inspected origin/main head when this package began. The working checkout includes this commit and the implementation changes.
Verify that git merge-base --is-ancestor 9cc146ee21c296d553ae684531219a5c711a4213 HEAD succeeds before compatibility tests.
Recheck upstream changes if main advances again.
The merged host bridge package is implemented, not another pending work order.
It owns REQ-INTEGRATIONS-GITHUB-AUTHENTICATION-002, criteria .1 through .7.
The merged credential design is the compatibility authority.
No change to our observable requirements or five-task dependency order is needed.
The merge adds credential routing and environment composition. It does not modify common/subproc/shared.go or git_command.go.
The shared execution defect is the target of this package. The implementation consumes the composed environment without rebuilding host eligibility or helper registration.
Preserve existing user-helper order, optional marker-owned host helpers, token precedence, and managed-mode exclusion. Environment duplicate removal applies to repeated assignments of the same environment variable, not repeated Git configuration entries at different indexes. The existing optional helper chain is allowed; the prohibition on new fallback means no new routing after authentication failure. Do not remove the host bridge because its shell function is not a direct OpenSSH command; SSH normalization applies only to SSH settings.
An installed bridge can recover on a later command when its credential store or service recovers. If bridge registration was skipped, existing launch/resume/prepared-start evaluation can install it after recovery, without restarting the backend. Do not promise that every existing instance acquires a previously absent bridge on its next arbitrary Git command.
Requirement conformance
Platform owns shared execution safety across callers.
Reuse AC-PLATFORM-WORKSPACE-GIT-STATUS-001.16 through .18 for comparison behavior.
Add REQ-PLATFORM-GIT-SUBPROCESS-ADMISSION-002 to the existing shared Git requirement because universal prompt and helper-cleanup criteria were missing.
The existing accepted transport ADR remains authoritative. Its credential scope and no-fallback policy do not change.
The assumption check found no material unanswered product choice: the prompt explicitly settles scope, recovery, exclusions, and planning handoff.
Scope
In scope
- Final prompt enforcement and selected-scope credential compatibility.
- Finite network budgets after admission, owned helper cancellation, pipe cleanup, and slot release.
- Required error completion and optional comparison recovery on desktop and phone.
- Targeted TDD, source audit, scoped engineering guidance, and public recovery guidance.
Out of scope
- Credential changes, automatic retries, transport changes, and new authentication UI.
- Launcher-wide environment changes or deliberately interactive task terminals.
- Publication, live-instance mutation, credential changes, and provider operations.
- Attribution of the original incident to an unproven subprocess or provider event.
Technical approach
The execution design defines the shared preparation and lifecycle boundary. Preserve the GitHub credential authority and existing clone isolation. Move only reusable process primitives below agentctl; keep the unrelated agent lifecycle stable through compatibility wrappers. Do not replace stdin or pass sensitive credentials through logs.
Initial caller inventory
Task 03 completed the repository-wide inventory and applied the shared execution boundary to each discovered application-owned network path.
| Caller / path under apps/backend/internal | Finding and treatment |
|---|---|
| orchestrator/executor/executor_host_gh_bridge.go (merged dependency) | Keep optional host probing and helper registration unchanged; add compatibility evidence through final Git execution |
| agent/runtime/environment/environment.go and agentctl/server/process/manager.go (merged dependency) | Consume canonical indexed configuration; preserve overlay/complete replacement and stale generated-helper removal |
| common/subproc/shared.go | All runner variants now use final preparation and bounded lifecycle handling |
| agentctl/server/process/git.go | Explicit instance environment and operation-specific AfterAcquire budgets are preserved |
| agentctl/server/process/workspace_git_cmd.go | Tracker environment, index, lock behavior, prompt/SSH controls, and the 10-second budget are preserved |
| agentctl/server/process/workspace_git_diff.go | Manual admission uses the shared stream lifecycle and closes the reader on cancellation before Wait |
| worktree/manager_git.go | Manual admitted paths use the shared lifecycle and 500 ms WaitDelay while retaining manager budgets |
| task/service/repository_fetch.go | The 30-second refresh, singleflight, cooldown, and shared prompt controls are preserved |
| task/service/fresh_branch.go | The 30-second AfterAcquire budget, best-effort fetch, and required checkout errors are preserved |
| agent/runtime/lifecycle/env_preparer_local.go | Fetch and checkout use finite post-admission budgets with the caller context |
| repoclone/clone.go | Clone, fetch, and submodule operations retain scoped helper authority with finite budgets |
| gitbootstrap/gitbootstrap.go | Network reachability is covered without changing local initialization behavior |
| office/configloader/git.go | The 30-second AfterAcquire path inherits final policy and cleanup |
| backendapp and submodule callers | Generic command construction and network verbs are covered by the completed inventory |
| task/gitinit/command_descriptor.go | Local descriptor-based ExecGit exception; preserve security and process ownership |
The completed budget inventory is summarized below. A shorter caller lifetime always wins over these post-admission budgets.
| Caller group | Network operations | Post-admission budget | Error owner |
|---|---|---|---|
agentctl/server/process Git operator |
fetch, push, remote inspection | 30 seconds for ordinary operations; five minutes for clone, push, and submodule operations | Required API result with sanitized error and released operation lock |
| Workspace tracker and comparison materialization | fetch and target refresh | Existing 10-second tracker command budget | Optional unavailable comparison state; local Changes remains usable |
| Worktree manager | fetch and pull | Existing configured fetch/pull budgets, 60 seconds by default; 30-second inspect commands | Existing lifecycle and fallback policy |
| Runtime, task, repository, and Office setup | fetch, checkout, clone, submodule | 30 seconds for ordinary fetch/checkout; five minutes for clone/submodule | Existing required setup errors or documented best-effort fetch handling |
| Backend materialization and repository state | fetch, pull, clone, push, submodule, ls-remote |
30 seconds for ordinary operations; five minutes for clone/push/submodule | Existing caller-specific required or optional result |
Uncovered ordinary fetch, pull, checkout, and ls-remote paths use the 30-second default. Uncovered clone, submodule, and push paths use the five-minute default.
Existing explicit operation budgets remain intact, and earlier parent cancellation wins.
Tests
The following table records the behavioral evidence implemented by the work orders.
| Acceptance criteria | Behavioral evidence |
|---|---|
| ADMISSION-002.1, .2 | Task 01: TestManagedGitCredentialFillPTY, TestGitFinalEnvironment, TestGitCredentialHTTPSelectedScope, TestGitSSHCommandPreservation |
| ADMISSION-002.3, .4 | Task 02: TestGitHelperCancellationReleasesSlot, TestGitDescendantPipeCleanup, TestWindowsManagedGitJobCleanup, TestCapDiffOutputCancellationClosesReader |
| ADMISSION-002.2 through .6 | Task 03: TestGitOperatorAuthenticationFailureAndRecovery, TestLocalCheckoutFetchDeadline, TestCloneDeadlineAfterAdmission, existing queue-cancellation regressions |
| WORKSPACE-GIT-STATUS-001.16 through .18 | Task 04: authentication fixture with available local status, unavailable comparison, and later recovery |
Prefixes above abbreviate AC-PLATFORM-; work orders contain full IDs and exact paths/commands.
Protect PTY/helper tests with outer timeouts and owned-process cleanup. Use local HTTP and synthetic credentials only.
Task 03 also runs the merged executor, runtime-environment, configuration, and lifecycle regressions.
Native Windows must execute environment, helper, and job-lifecycle tests. Linux cross-compilation cannot replace that evidence.
E2E tests
The implementation extends apps/web/e2e/tests/git/fork-pr-comparison-target.spec.ts in chromium and mobile-fork-pr-comparison-target.spec.ts in mobile-chrome.
Reuse fork-pr-comparison-target-helpers.ts, adding real authentication-failure fixture behavior.
Desktop opens Changes through its session tab. Phone taps Changes and uses the existing mobile panel.
Both retain the existing unavailable-target notice and can open local file changes before authentication recovers.
No rendered UI change is proposed, so no new composition or ASCII preview is required.
Task 04 owns exact installation, build, and guarded runner commands. Run the two projects sequentially.
Companion packages
The merged host bridge package above adds compatibility inputs for Tasks 01, 03, and 05. Its completed statuses and historical results remain unchanged.
Git admission, Noninteractive comparison Git, and Fork comparison targets are prior implemented packages. Their recorded checks remain historical evidence for their original scope. This package owns the broader runner enforcement and additional authentication-failure scenarios; it does not relabel their old results as new validation. Workspace scalability, dependency exclusion, and mixed-change packages have no changed task scope.
Work orders
- Task 01: Enforce final Git prompt policy
- Task 02: Bound Git helpers and streaming cleanup
- Task 03: Cover network callers and failure recovery
- Task 04: Prove desktop and phone task access
- Task 05: Document Git failure and recovery
Verification results
Package authoring: temporary PTY mechanism reproduced as recorded above.
Implementation: completed on the verified PR #3635 descendant. Focused backend packages, the shared subprocess race test, web lint, Vite build, TypeScript typecheck, and Linux build passed.
The full backend make lint command passes after updating pre-existing Office test fixtures to discard the unused QueueRun outcome.
Cross-platform evidence: Windows subprocess, agentctl, and common lifecycle test binaries cross-compiled successfully. Native Windows execution was unavailable in this workspace, so the native Windows requirement remains a platform CI responsibility.
Browser evidence: the desktop Chromium and mobile Chrome comparison-recovery specs passed against the disposable local HTTP authentication fixture.
Documentation: public-doc validation, specification catalog validation, specification lint, and git diff --check passed.
Risks
- Windows suspended-start job handling and Git shell askpass need native execution evidence.
- Caller process attributes may conflict with session isolation; fail before start rather than weakening ownership.
- Arbitrary custom helpers may ignore prompt controls or escape process ownership; never kill shared daemons to compensate.
- Constructor audit alone cannot prove direct Start coverage. Task 02 covers the lifecycle bypasses.
- Previously implicit clone/push lifetimes become finite; preserve established budgets and document uncovered defaults.
- The original incident call site remains unknown; universal execution-boundary coverage addresses the confirmed defect without assigning blame.
Package reconciliation with merged PR #3635: source and contract comparison completed; the implementation consumes the merged host bridge environment without adding a credential or transport fallback.