Skip to content

WP-107: Preserve caller cancellation through provider requests - #1773

Open
simple-agent-manager[bot] wants to merge 17 commits into
mainfrom
sam/wp-107-preserve-caller-6jjttt
Open

WP-107: Preserve caller cancellation through provider requests#1773
simple-agent-manager[bot] wants to merge 17 commits into
mainfrom
sam/wp-107-preserve-caller-6jjttt

Conversation

@simple-agent-manager

@simple-agent-manager simple-agent-manager Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Release contract

DO NOT MERGE THIS PR. Do not deploy it to shared staging. WP-107 is a foundation packet; the final integration task owns staging and merge authorization. This PR must remain open and unmerged even after every check is green.

Summary

  • add an optional, source-compatible ProviderRequestContext to every VM and volume provider operation
  • compose caller cancellation with configured internal timeouts through headers and response-body delivery, preserving the exact first-winner reason and cleaning listeners/timers
  • propagate cancellation through all seven providers, delegated volume clients, retries, polling, pagination, GCP STS/IAM/token caching, provider credential paths, and provisionNode
  • prevent follow-up HTTP, polling, retry, KV-success, DNS logging, terminal D1 success, and observability work after cancellation
  • add scenario-driven regression/capability coverage and synchronized provider implementation guidance

No WP-100–103 or WP-109 lifecycle/inventory behavior is included.

Root cause

providerFetch() assigned its own timeout controller after spreading RequestInit, overwriting any caller signal. The provider contract also had no context parameter, so cancellation could not cross retry, polling, helper, authentication, or API orchestration boundaries.

RED evidence

On refreshed origin/main (8eed3b740), an immediate caller abort used a different fetch signal and settled only after the 75 ms internal timeout as ProviderError. Focused RED commit 5e56b8ad9 produced:

  • providers: 21 failures / 172 passes
  • API provisionNode: 1 failure / 9 passes

The old behavior necessarily fails the pre-cancelled signal and exact in-flight identity regressions.

Final local evidence

  • providers: lint 0 errors / 26 existing warnings; typecheck/build pass; 32 files / 582 tests pass
  • provider coverage: 86.52% statements / 78.41% branches / 90.85% functions / 87.70% lines
  • API: lint 0 errors / 1,647 existing warnings; typecheck/build pass; 500 files / 6,769 tests pass
  • API coverage: 68.11% statements / 60.22% branches / 67.40% functions / 69.08% lines
  • focused cancellation boundary: providers 43/43; GCP/API 37/37; corrected terminal-D1 file 13/13
  • git diff --check: pass
  • final current-main refresh/rebase: no-op; branch 0 behind / 15 commits ahead of origin/main

The repository currently emits an existing Vitest/coverage-v8 patch-version warning; both complete coverage runs exited 0 with the totals above.

Independent local reviews

Review Result
Test engineering / scenario quality PASS
Constitution / hardcoded values / size / DRY PASS
Cloudflare Workers boundary PASS
Defensive security / side-effect bypass PASS
Documentation synchronization PASS
Task completion validation PASS — implementation complete; PR/check gates pending

Reviewer findings drove additional regressions for production GCP credential closures, WIF STS/IAM, delegated volume mutations, delay cleanup, pending KV/DNS/D1 boundaries, response bodies after headers, and zero-body 204 races.

Staging

Intentionally skipped by explicit user instruction. No shared staging state was deployed or mutated. Local full suites, coverage, static gates, and independent reviews are the non-staging evidence.

Post-mortem

The internal timeout was implemented as an exclusive signal rather than a composed lifecycle boundary, and tests covered timeout expiry without a caller signal. The durable process fix updates provider quality guidance so timeout wrappers must compose cancellation and retry/poll/multi-step tests must assert prompt exact rejection, cleanup, and post-cancel quiescence.

Agent Preflight (Required)

  • Preflight completed before code changes

Classification

  • external-api-change
  • cross-component-change
  • business-logic-change
  • public-surface-change
  • docs-sync-change
  • security-sensitive-change
  • ui-change
  • infra-change

External References

N/A: the change hardens an internal private provider contract using standard platform AbortSignal behavior; no external API contract or provider semantics changed.

Codebase Impact Analysis

The change spans packages/providers public provider operations and HTTP/retry/poll helpers plus the direct apps/api GCP credential/token and node-provisioning call paths. CLI, data schema, UI, deployment, and unrelated lifecycle/inventory paths are unchanged.

Documentation & Specs

Updated packages/providers/src/provider-fetch.ts JSDoc, .claude/rules/02-quality-gates.md, .claude/rules/06-technical-patterns.md, packages/providers/AGENTS.md, and the WP-107 task record to document cancellation propagation, exact reasons, cleanup, and post-cancel quiescence.

Constitution & Risk Check

Checked Principle IV size/DRY constraints and Principle XI no-hardcoded-values requirements. The primary risks were cancellation identity loss, listener/timer leaks, and resource side effects after cancellation; scenario tests and independent constitution, Workers, security, test-quality, doc-sync, and completion reviews all pass.

@codspeed-hq

codspeed-hq Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing sam/wp-107-preserve-caller-6jjttt (bbc73bf) with main (8c689a6)

Open in CodSpeed

@simple-agent-manager

Copy link
Copy Markdown
Contributor Author

Integration in progress — owned by task 01KZMFQJ4VKXEFB9K9Q64QKDDF. PR Shepherd: hands off until this completes.

@simple-agent-manager
simple-agent-manager Bot force-pushed the sam/wp-107-preserve-caller-6jjttt branch from b81ae6d to bbc73bf Compare August 10, 2026 00:14
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant