Skip to content

Add long-lived duplex Git protocol sessions #10

Description

@flyingrobots

Problem

@git-stunts/plumbing currently models every Git invocation as a one-shot command: stdin is closed immediately and consumers receive stdout plus process completion. That contract forces callers performing repeated object reads, tree writes, or bulk imports to spawn one Git process per operation.

The git-warp access spike in git-stunts/git-warp#763 found that stock Git's long-lived protocols (cat-file --batch-command, mktree --batch, and fast-import) preserve the required Git semantics while removing the dominant process/setup overhead. The plumbing package should expose the process/session primitive needed to use those protocols without replacing its existing one-shot runner API.

Proposed contract

Add an optional, additive duplex session port:

CommandSessionRunner.open(options) -> CommandSession

CommandSession
  stdout: AsyncIterable<Uint8Array>
  finished: Promise<exit result>
  write(bytes): Promise<void>
  closeInput(): void
  terminate(): void

The built-in Node, Bun, and Deno adapters should implement the port. Existing custom one-shot runners must remain source- and behavior-compatible; requesting a session from a runner that does not support sessions must fail with a structured unsupported-capability error.

Expose low-level protocol session constructors for stock Git. Protocol framing/parsing may be factored into focused wrappers for:

  • git cat-file --batch-command
  • git mktree --batch
  • git fast-import

Ownership boundary

Plumbing owns:

  • child-process lifecycle;
  • stdin backpressure and early-termination errors;
  • bounded stderr and process completion;
  • timeout and abort behavior;
  • raw Git protocol mechanics.

Plumbing does not own:

  • session reuse policy;
  • object retention or anchoring;
  • cache admission, eviction, or materialization policy;
  • git-cas workspace/checkpoint semantics.

Those policies belong to @git-stunts/git-cas and its callers.

Acceptance criteria

  • Existing execute and executeStream behavior remains compatible.
  • Node, Bun, and Deno built-in runners can open duplex sessions.
  • write() honors stream backpressure and rejects after closure/failure.
  • finished settles exactly once for success, spawn failure, timeout, abort, and early exit.
  • stderr remains bounded.
  • closing and terminating are idempotent.
  • unsupported custom runners receive a structured capability error.
  • protocol integration tests cover repeated requests in one process, malformed/missing objects, mid-session failure, and orderly shutdown.
  • multi-runtime CI remains green.
  • public documentation states the lifecycle and ownership boundary.

Evidence

The benchmark design and results are in git-stunts/git-warp#763 and docs/topics/git-perf.md in that PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions