Skip to content

KubectlTransport has no default deadline while GrpcRelayTransport always applies 120s, and the battery cannot see it #182

Description

@pdettori

Problem

The two per-call transports disagree on what happens to a command with no explicit timeout, and the disagreement is invisible to the conformance battery.

  • packages/k8s-sandbox/src/exec.ts arms a timer only when the caller passes opts.timeout > 0. With no timeout, the kubectl exec child runs until it finishes.
  • packages/k8s-sandbox/src/grpc-relay-transport.ts applies DEFAULT_DEADLINE_MS = 120_000 unconditionally, so any exec without an explicit timeout is cancelled at 120 s with timeout:120.

Pi's bash tool documents no default timeout (pi-fork/packages/coding-agent/src/core/tools/bash.ts), so a model-issued bash with none runs unbounded on the in-cluster pod path and dies after two minutes on the remote-worker path. A pnpm install, a full test run, or a long build crosses that line routinely.

The shared conformance battery cannot catch this: its timeout case always passes an explicit timeout (packages/k8s-sandbox/test/conformance.ts), so neither transport's default is ever exercised. The battery's green status therefore does not speak to this divergence at all — which is worth noting, because that battery is the evidence behind the epic's transport-swappability claim (#89, driver #2).

Recorded in spec §8's "Accepted divergences" pending this decision. Found by the whole-branch review of the epic-closing work.

The decision

  1. Give KubectlTransport the same 120 s default. Makes the transports agree. Cost: commands that work today on the pod path start dying at two minutes — a real regression for legitimate long-running work, and the kind that surfaces as a confusing mid-build failure.
  2. Raise or remove the gRPC default. Removing it means the harness can hang on a silent or malicious worker, which is the specific thing §8's dual-ended timeout exists to prevent — so this is really "raise it", and then to what?
  3. Keep them different, deliberately, and add a battery case asserting each transport's documented default. The divergence stops being accidental and starts being tested; the docs already state it.

Whatever is chosen, option 3's test belongs in it — right now nothing pins either default, so both could drift silently.

Refs

Epic #89 · spec §8 "Accepted divergences" and its dual-ended timeout bullet · related #180, #181.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions