Skip to content

fix(places): apply Timeout when HTTPClient has none - #28

Closed
SebTardif wants to merge 1 commit into
openclaw:mainfrom
SebTardif:fix/http-client-timeout
Closed

fix(places): apply Timeout when HTTPClient has none#28
SebTardif wants to merge 1 commit into
openclaw:mainfrom
SebTardif:fix/http-client-timeout

Conversation

@SebTardif

Copy link
Copy Markdown

What Problem This Solves

Fixes an issue where callers that pass their own http.Client (including an empty &http.Client{}) never get Options.Timeout. A stalled Google Places TCP connection then hangs the request forever.

The CLI already sets Timeout (default 10s). That value was ignored whenever HTTPClient was non-nil.

Why This Change Was Made

NewClient now applies Options.Timeout (default 10s) when the provided client has Timeout == 0. The provided client is cloned so the caller is not mutated. An explicit non-zero HTTPClient.Timeout is kept.

User Impact

Library and CLI callers that pass a custom client without a timeout now get the same 10s bound as the default client. Callers that already set a timeout are unchanged.

Evidence

Before (unfixed NewClient with &http.Client{} and Timeout: 2s):

$ go test ./internal/places -count=1 -run TestNewClientAppliesTimeoutToProvidedClient
--- FAIL: TestNewClientAppliesTimeoutToProvidedClient (0.00s)
    client_options_test.go:105: timeout=0s want 2s
FAIL

After this patch:

$ go test ./internal/places -count=1 -run TestNewClientAppliesTimeoutToProvidedClient
ok  	github.com/steipete/goplaces/internal/places	0.238s

The caller’s original client stays at Timeout 0. An explicit 7s client timeout is preserved.

Real behavior proof

  • Behavior or issue addressed: Provided HTTP clients with no Timeout ignored Options.Timeout and could hang forever on a stalled Places request.

  • Real environment tested: macOS, Go toolchain, module checkout at /tmp/gp-http-timeout.

  • Exact steps or command run after this patch:

    cd /tmp/gp-http-timeout
    go test ./internal/places -count=1 -run TestNewClientAppliesTimeoutToProvidedClient
  • Evidence after fix: terminal output from the patched tree:

    $ go test ./internal/places -count=1 -run TestNewClientAppliesTimeoutToProvidedClient
    ok  	github.com/steipete/goplaces/internal/places	0.238s
  • Observed result after fix: A provided client with Timeout 0 now receives Options.Timeout (2s in the probe, 10s default). Explicit non-zero timeouts stay as the caller set them.

  • What was not tested: Live Google Places API against a real stalled TCP peer.

NewClient only set Timeout when HTTPClient was nil. Callers that
passed &http.Client{} (or any client with Timeout 0) ignored
Options.Timeout and hung forever on a stalled Places request.

Clone the provided client and apply Timeout (default 10s) when it
is still zero. Explicit non-zero timeouts are left alone.

Red: go test ./internal/places -run TestNewClientAppliesTimeoutToProvidedClient
  timeout=0s want 2s
Green: same command ok
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@clawsweeper

clawsweeper Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Aug 16, 2026
@clawsweeper

clawsweeper Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Codex review: found issues before merge. Reviewed September 1, 2026, 5:06 PM ET / 21:06 UTC.

ClawSweeper review

What this changes

This branch clones a caller-provided Go HTTP client with no timeout and applies the configured or default Places-client timeout while preserving explicit client timeouts.

Regression provenance

Possible regression — probable (reviewed change; reproduction). No predecessor PR is attributed.

Merge readiness

Blocked by patch quality or review findings - 6 items remain

Keep open for an explicit maintainer compatibility decision: current main leaves a supplied zero-timeout HTTP client unchanged, while this branch silently imposes the configured or default 10-second deadline on existing library callers.

Priority: P1
Reviewed head: 606deed8c1e616b3a35c46f51e59eb94e77ddc5f
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The real transport evidence is strong, but it demonstrates a blocking compatibility regression in the proposed public timeout policy.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (terminal): A collaborator exercised the changed production client and real Go HTTP transport against loopback TCP on current main and this exact head; it recorded the after-change timeout behavior and the incompatible longer-context case.
Patch quality 🦪 silver shellfish (2/6) 1 actionable review finding remain.

Verification

Check Result Evidence
Real behavior Verified Sufficient (terminal): A collaborator exercised the changed production client and real Go HTTP transport against loopback TCP on current main and this exact head; it recorded the after-change timeout behavior and the incompatible longer-context case.
Evidence reviewed 5 items Introduced behavior change: The exact PR delta adds the supplied-client branch that shallow-copies a zero-timeout client and assigns Options.Timeout, including the 10-second default.
Current-main behavior: Current main only applies Options.Timeout when no HTTP client is supplied; a supplied client is otherwise retained as-is.
Published compatibility policy: The repository treats exported goplaces behavior as a compatibility surface and requires deliberate, documented migration for breaking changes before 1.0.
Findings 1 actionable finding [P1] Preserve zero-timeout semantics for supplied clients
Security None None.

How this fits together

The public Go library turns caller options into a Places client, which all search and lookup methods use for outbound HTTP requests. CLI flags provide a timeout to the default library client, while embedding callers may provide their own HTTP client and request context.

flowchart LR
  A[Go caller or CLI] --> B[Client options]
  B --> C[Client construction]
  C --> D{Supplied HTTP client?}
  D -->|No| E[Default timeout client]
  D -->|Yes| F[Caller client policy]
  E --> G[Places request transport]
  F --> G
  G --> H[Google Places API]
Loading

Decision needed

Question Recommendation
Should a caller-supplied Go HTTP client with Timeout zero retain Go's no-client-deadline semantics, or should goplaces redefine it to inherit Options.Timeout? Preserve caller timeout control: Keep supplied clients unchanged and retain Options.Timeout only for clients constructed by goplaces.

Why: Both policies are viable, but selecting either changes the exported library contract and cannot be resolved safely as a patch-level implementation choice.

Before merge

  • Preserve zero-timeout semantics for supplied clients (P1) - A supplied http.Client with Timeout == 0 deliberately has no client deadline. These introduced lines replace that policy with Options.Timeout (10 seconds by default); the recorded loopback comparison shows a valid 10.5-second request succeeds on main but fails on this branch while its caller context remains valid.
  • Resolve merge risk (P2) - Existing embedding callers that intentionally use a zero-timeout HTTP client with a longer request context will start failing after the configured or default 10-second client deadline.
  • Resolve merge risk (P1) - The branch changes an exported library behavior without an explicit contract decision, migration guidance, or changelog entry.
  • Complete next step (P2) - A maintainer must choose the exported supplied-client timeout contract before any repair or merge action is safe.
  • Improve patch quality - Resolve the supplied-client timeout contract, preserving current behavior unless maintainers approve a documented breaking change.

Findings

  • [P1] Preserve zero-timeout semantics for supplied clients — internal/places/client.go:61-64
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production versus test delta production +4 net (8 added, 4 removed); tests +26 A small constructor change alters the timeout policy for every supplied zero-timeout library client.

Merge-risk options

Maintainer options:

  1. Restore supplied-client semantics (recommended)
    Remove the zero-timeout override for caller-provided clients and replace the new expectation test with coverage that preserves caller control.
  2. Approve a breaking timeout policy
    If inheriting Options.Timeout is intentional, document the changed public contract and migration, add real compatibility coverage, and release it outside a patch version.

Technical review

Best possible solution:

Preserve supplied-client zero-timeout semantics; if timeout inheritance is desired, introduce it as an explicitly documented and versioned public contract with migration and compatibility scenarios.

Do we have a high-confidence way to reproduce the issue?

Yes. The collaborator review exercised the public Go library through a real loopback TCP server on current main and the exact PR head, including the longer-than-10-second response that differs between them.

Is this the best way to solve the issue?

No. The new test proves the proposed policy but not that it is compatible; preserving caller-supplied client control is the narrow safe path unless maintainers deliberately adopt and document a new contract.

Full review comments:

  • [P1] Preserve zero-timeout semantics for supplied clients — internal/places/client.go:61-64
    A supplied http.Client with Timeout == 0 deliberately has no client deadline. These introduced lines replace that policy with Options.Timeout (10 seconds by default); the recorded loopback comparison shows a valid 10.5-second request succeeds on main but fails on this branch while its caller context remains valid.
    Confidence: 0.99

Overall correctness: patch is incorrect
Overall confidence: 0.99

AGENTS.md: not found in the target repository.

Codex review notes: model internal, reasoning high; reviewed against 77023d8abb4c.

Labels

Label justifications:

  • P1: The branch can immediately break existing library automation that intentionally relies on a caller-managed timeout or longer request context.
  • merge-risk: 🚨 compatibility: It changes the effective meaning of a supplied zero-timeout http.Client on an exported library surface.
  • merge-risk: 🚨 availability: Previously successful requests exceeding 10 seconds can be cancelled despite a still-valid caller context.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦞 diamond lobster and patch quality is 🦪 silver shellfish.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): A collaborator exercised the changed production client and real Go HTTP transport against loopback TCP on current main and this exact head; it recorded the after-change timeout behavior and the incompatible longer-context case.
  • proof: sufficient: Contributor real behavior proof is sufficient. A collaborator exercised the changed production client and real Go HTTP transport against loopback TCP on current main and this exact head; it recorded the after-change timeout behavior and the incompatible longer-context case.

Evidence

What I checked:

  • Introduced behavior change: The exact PR delta adds the supplied-client branch that shallow-copies a zero-timeout client and assigns Options.Timeout, including the 10-second default. (internal/places/client.go:61, 606deed8c1e6)
  • Current-main behavior: Current main only applies Options.Timeout when no HTTP client is supplied; a supplied client is otherwise retained as-is. (internal/places/client.go:58, 77023d8abb4c)
  • Published compatibility policy: VISION.md: The repository treats exported goplaces behavior as a compatibility surface and requires deliberate, documented migration for breaking changes before 1.0. (VISION.md:30, 606deed8c1e6)
  • Real transport comparison: The collaborator review used the public library over real loopback TCP: with a supplied zero-timeout client and a 12-second context, main completed a 10.5-second response while this branch timed out at 10 seconds with the context still valid.
  • Current release context: The fetched current-main commit follows the v0.4.9 release commit; current main still preserves the supplied-client behavior, so the proposed change is neither merged nor shipped. (77023d8abb4c)

Likely related people:

  • steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (42 earlier review cycles; latest 8 shown)
  • reviewed 2026-08-30T22:06:44.670Z sha 606deed :: needs real behavior proof before merge. :: [P1] Preserve supplied-client zero-timeout semantics
  • reviewed 2026-08-31T03:40:50.961Z sha 606deed :: needs real behavior proof before merge. :: [P1] Preserve supplied-client zero-timeout behavior
  • reviewed 2026-08-31T12:07:44.761Z sha 606deed :: found issues before merge. :: [P1] Preserve supplied-client zero-timeout semantics
  • reviewed 2026-09-01T03:45:40.702Z sha 606deed :: found issues before merge. :: [P1] Preserve supplied-client zero-timeout semantics
  • reviewed 2026-09-01T04:58:23.048Z sha 606deed :: found issues before merge. :: [P1] Preserve supplied-client zero-timeout semantics
  • reviewed 2026-09-01T08:11:27.073Z sha 606deed :: found issues before merge. :: [P1] Preserve zero-timeout semantics for supplied clients
  • reviewed 2026-09-01T12:03:38.866Z sha 606deed :: found issues before merge. :: [P1] Preserve zero-timeout semantics for supplied clients
  • reviewed 2026-09-01T15:46:39.941Z sha 606deed :: found issues before merge. :: [P1] Preserve zero-timeout semantics for supplied clients

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. P1 Urgent regression or broken agent/channel workflow affecting real users now. P2 Normal priority bug or improvement with limited blast radius. status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal priority bug or improvement with limited blast radius. P1 Urgent regression or broken agent/channel workflow affecting real users now. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Aug 21, 2026
@clawsweeper clawsweeper Bot added status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Aug 29, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 29, 2026
@steipete

Copy link
Copy Markdown
Collaborator

Maintainer triage: I reproduced the behavior through the public Go library over real loopback TCP, using current main 77023d8abb4ccd68e9adff6c79b1c1e63114bf97 and PR head 606deed8c1e616b3a35c46f51e59eb94e77ddc5f (macOS arm64, Go 1.27.0).

The patch applies the requested timeout, but it also changes existing supplied-client behavior. With HTTPClient: &http.Client{}, no option timeout, a 12-second caller context, and a server responding after 10.5 seconds, main succeeds; the PR fails after 10 seconds while the caller context is still valid. Go explicitly defines zero client timeout as no client deadline: https://pkg.go.dev/net/http#Client.

Recommendation: close this PR as currently proposed, subject to Peter's decision on the public contract. Preserve caller-supplied client control. If timeout inheritance is desired, it needs an explicit compatibility decision and documented migration under VISION.md; it is not a patch-level behavior change. I have left the PR open and made no source changes.

The CLI claim is also inaccurate: internal/cli/run.go does not supply HTTPClient. The built main binary already enforces --timeout=100ms and exits 1 with context deadline exceeded (Client.Timeout exceeded while awaiting headers).

Real TCP scenario main PR #28
Supplied zero-timeout client, option 100ms, context 350ms Context expires at 351ms Client deadline at 102ms; context still valid
Supplied client timeout 200ms, option 100ms Client deadline at 201ms Client deadline at 202ms
No supplied client, option 100ms Client deadline at 100ms Client deadline at 101ms
Supplied zero-timeout client, default option, context 12s, response after 10.5s Success at 10.503s; one result Deadline at 10.001s; context still valid

Every scenario reached the TCP server exactly once. The supplied client's Timeout field remained unchanged. The PR's go test ./... passes all four packages. The current GitHub rollup contains dispatch checks, not a passing application CI suite. Codex autoreview's default P0-only pass found no P0 defect; that limited result does not resolve the compatibility decision above.

This proof uses synthetic local responses and a dummy local-only key. It does not call Google or validate Google account/billing behavior.

Standalone reproduction source and commands

Save the following as probe.go outside the repository. From current main:

go build -o /tmp/goplaces-probe-main /path/to/probe.go
go build -o /tmp/goplaces-main ./cmd/goplaces
/tmp/goplaces-probe-main main /tmp/goplaces-main

From a checkout of PR head 606deed8c1e616b3a35c46f51e59eb94e77ddc5f:

go test ./...
go build -o /tmp/goplaces-probe-pr28 /path/to/probe.go
/tmp/goplaces-probe-pr28 pr28
package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"sync/atomic"
	"time"

	"github.com/steipete/goplaces"
)

func main() {
	revision := os.Args[1]
	var requests atomic.Int64
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	server := &http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost || !strings.HasSuffix(r.URL.Path, "/places:searchText") {
			http.Error(w, "unexpected request", 400)
			return
		}
		requests.Add(1)
		_, _ = io.Copy(io.Discard, r.Body)
		delay := 600 * time.Millisecond
		if strings.HasPrefix(r.URL.Path, "/long/") {
			delay = 10500 * time.Millisecond
		}
		timer := time.NewTimer(delay)
		defer timer.Stop()
		select {
		case <-r.Context().Done():
			return
		case <-timer.C:
			w.Header().Set("Content-Type", "application/json")
			_, _ = io.WriteString(w, `{"places":[{"id":"synthetic-place","displayName":{"text":"Synthetic Cafe"}}]}`)
		}
	})}
	go func() { _ = server.Serve(listener) }()
	defer server.Close()
	baseURL := "http://" + listener.Addr().String()
	scenarios := []struct {
		name                     string
		provided                 *http.Client
		option, contextLimit     time.Duration
		path                     string
		mainDeadline, prDeadline bool
	}{
		{"custom_zero_explicit_option", &http.Client{}, 100 * time.Millisecond, 350 * time.Millisecond, "/short", true, true},
		{"custom_explicit_wins", &http.Client{Timeout: 200 * time.Millisecond}, 100 * time.Millisecond, 350 * time.Millisecond, "/short", true, true},
		{"nil_client_option", nil, 100 * time.Millisecond, 350 * time.Millisecond, "/short", true, true},
		{"custom_zero_default_long_context", &http.Client{}, 0, 12 * time.Second, "/long", false, true},
	}
	for _, scenario := range scenarios {
		client := goplaces.NewClient(goplaces.Options{APIKey: "synthetic-local-only", BaseURL: baseURL + scenario.path, HTTPClient: scenario.provided, Timeout: scenario.option})
		ctx, cancel := context.WithTimeout(context.Background(), scenario.contextLimit)
		before := requests.Load()
		started := time.Now()
		response, callErr := client.Search(ctx, goplaces.SearchRequest{Query: "coffee", Limit: 1})
		elapsed := time.Since(started)
		deadline := errors.Is(callErr, context.DeadlineExceeded)
		contextExpired := ctx.Err() != nil
		cancel()
		original := "nil"
		if scenario.provided != nil {
			original = scenario.provided.Timeout.String()
		}
		fmt.Printf("%s %s elapsed=%s deadline=%v context_expired=%v results=%d original_timeout=%s network_requests=%d\n", revision, scenario.name, elapsed.Round(time.Millisecond), deadline, contextExpired, len(response.Results), original, requests.Load()-before)
		expected := scenario.mainDeadline
		if revision == "pr28" {
			expected = scenario.prDeadline
		}
		if deadline != expected || requests.Load()-before != 1 || (!deadline && (callErr != nil || len(response.Results) != 1)) {
			panic(fmt.Sprintf("unexpected result: %v", callErr))
		}
	}
	if len(os.Args) > 2 {
		cmd := exec.Command(os.Args[2], "--timeout=100ms", "--json", "search", "coffee", "--limit=1")
		cmd.Env = []string{"GOOGLE_PLACES_API_KEY=synthetic-local-only", "GOOGLE_PLACES_BASE_URL=" + baseURL + "/short", "NO_COLOR=1"}
		started := time.Now()
		output, cliErr := cmd.CombinedOutput()
		code := 0
		if cliErr != nil {
			var e *exec.ExitError
			if !errors.As(cliErr, &e) {
				panic(cliErr)
			}
			code = e.ExitCode()
		}
		clean := strings.ReplaceAll(string(output), baseURL, "http://127.0.0.1:PORT")
		fmt.Printf("%s built_cli elapsed=%s exit=%d stderr=%s", revision, time.Since(started).Round(time.Millisecond), code, clean)
		if code == 0 || !strings.Contains(clean, "deadline exceeded") {
			panic("CLI did not enforce timeout")
		}
	}
}

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Aug 31, 2026
@SebTardif

Copy link
Copy Markdown
Author

@steipete

Recommendation: close this PR as currently proposed, subject to Peter's decision on the public contract. Preserve caller-supplied client control.

Closing as requested. A supplied http.Client keeps Go's zero-timeout meaning. Options.Timeout stays for clients goplaces constructs, including the CLI, which does not set HTTPClient.

@SebTardif SebTardif closed this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P1 Urgent regression or broken agent/channel workflow affecting real users now. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants