Skip to content

examples/agent-sandbox-rl: create the namespace in setup (kubernetes-… - #5

Merged
ngeorger merged 77 commits into
mainfrom
upstream
Sep 24, 2026
Merged

ngeorger merged 77 commits into
mainfrom
upstream

Conversation

@ngeorger

Copy link
Copy Markdown
Member

Updated the paths in the workflow to include the sandbox-router directory and modified the build context for Docker.

Signed-off-by: Nicolás Georger info@sredevops.org#### What this PR does / why we need it:

Which issue(s) this PR is related to:

Release Note

…sigs#1549)
  • examples/agent-sandbox-rl: create the namespace in setup

  • examples/agent-sandbox-rl: use the same namespace throughout

  • examples/agent-sandbox-rl: reword the namespace step, update reaper docstring

  • examples/agent-sandbox-rl: update remaining namespace references

vincent0426 and others added 30 commits September 8, 2026 16:18
…sigs#1549)

* examples/agent-sandbox-rl: create the namespace in setup

* examples/agent-sandbox-rl: use the same namespace throughout

* examples/agent-sandbox-rl: reword the namespace step, update reaper docstring

* examples/agent-sandbox-rl: update remaining namespace references
…ubernetes-sigs#1589)

olm/Makefile pinned an older version of golangci-lint (v2.1.0) and used
its own go install flow, causing presubmit-agent-sandbox-lint-olm to fail
under recent CI Go toolchain updates. Point olm/Makefile's GOLANGCI_LINT
to repo-wide dev/tools/go.mod via go tool so linting uses a single source
of truth across the repository.

In addition, regenerate packages/sandboxd/spec/process/v1/process.pb.go
to drop redundant blank comment lines formatted away by newer go/format,
resolving presubmit-test-autogen-up-to-date failures.
Add an Ed25519 scoped-token format that signs the key ID and canonical
sandbox target fields. Multiple verification keys allow overlap while
legacy HMAC readers require an exclusive cutoff when both formats run.

Normalize the target after routing so authorization binds the Sandbox
UID, port, method, and exact upstream escaped path. Keep v1-only
configuration compatible and require cache mode when v2 is enabled.

Same-name replacement fencing remains separate because cache resolution
must first return and enforce its canonical Sandbox UID.
…netes-sigs#1488) (kubernetes-sigs#1503)

* feat(rl): OpenHands fleet adapter — workspaces on fleet-acquired pods

adapters/openhands.py inverts pod ownership for AgentSandboxWorkspace the
same way adapters/r2egym.py does for R2E-Gym: FleetWorkspaceClient is a
duck-typed sandbox_client whose create_sandbox() is fleet.acquire(task)
and whose handle view's terminate() is fleet.release(handle) — the
workspace never deletes, the fleet owns pools/placement/TTLs. Fleet-owned
kwargs (warmpool, ttl_s, sandbox_client) are rejected at the seam.

Module-level imports stay OpenHands-free (lazy import with a clear hint),
matching the r2egym adapter's optional-dependency pattern; 8 tests run
against fakes plus a sys.modules stub of the integration.

* feat: advisory server-version skew check on attach

After RemoteWorkspace init, compare the agent-server's /server_info
version with the installed openhands-sdk and warn loudly on mismatch
(the SDK and server image are released together; skew means protocol
drift). Advisory only — never fails the attach; check_server_version
field disables it for offline tests. Closes the remaining item from the
seam spec.

* feat(rl): handle-bound OpenHands workspaces + fleet fan-out example

make_handle_workspace(handle) is the fleet.run-native form of the adapter:
fleet.run acquires the handle before process_fn(task, handle) and releases
it after, so the workspace binds without acquiring and its terminate() is
a no-op on the pod (BoundHandleClient). namespace defaults from the
handle's cluster for router-mode headers; fleet-owned kwargs still raise.
The view-building is shared with FleetWorkspaceClient (_handle_view).

examples/run_openhands_fleet.py is the OpenHands twin of
run_swebench_fleet.py: one warm pool of agent-server pods (TemplateSpec
keepalive_command restates the image entrypoint since it renders as the
container command; extra_pod_spec merges the load-bearing /health
readinessProbe and the pool session key), N concurrent conversations via
fleet.run, and a no-LLM smoke mode so the fan-out is testable with
cluster access alone.

* fix: address self-review — pool depth follows concurrency, realistic probe budget, helper ordering

max_warmpool_size (default 8) would silently cap the example's pool below
MAX_CONCURRENT and throttle claims — size it to the concurrency with an
env override. Probe budget raised to 5 min (agent-server cold boots were
measured at ~4 min on runc; pool-fill time, off the claim path). Move
_handle_view above its first user.

* docs(rl): document the OpenHands adapter across README, architecture, and rl_integration

* fix: address kubernetes-sigs#1503 review round 1

- example: LLM_API_KEY without openhands-tools now warns once and falls
  back to smoke mode instead of failing every rollout identically
- workspace cleanup: keep the claim reference until termination succeeds
  so later cleanup() calls can retry (a no-ttl claim would otherwise leak
  warm-pool capacity); owned client stays open while retry is possible;
  regression test added (fail once -> retry succeeds -> idempotent)
- template: gvisor commented out with guidance (repo precedent: template
  must admit on clusters without the RuntimeClass; strongly recommended
  note kept) and resource limits added (cpu/memory/ephemeral-storage) —
  limits are part of the documented isolation posture
- pyproject: floor raised to openhands-sdk>=1.44.1 (the release the
  template pins); exact pin rejected deliberately — it would block every
  SDK patch release, and the attach-time version-skew check flags drift

* docs: address kubernetes-sigs#1503 review round 2 — conversation guard in snippet, Python 3.12 floor noted

The rl_integration.md rollout snippet closed the conversation in a flat
finally, so a Conversation(...) constructor failure would raise
UnboundLocalError and mask the original error — restructured to nested
try/finally, matching the runnable example (which never had the bug).
Python >= 3.12 (the openhands-sdk floor) is now called out at all three
places that say pip install openhands-k8s-agent-sandbox.

* fix: address kubernetes-sigs#1503 review round 3 — narrow version-check errors, honest detach log, pool-cap override notice

- workspace._log_version_skew: only transport/HTTP errors (httpx.HTTPError),
  a non-JSON body, or a missing openhands-sdk distribution are swallowed at
  debug level; a non-dict /server_info payload and any unexpected exception
  now log at WARNING (the latter with traceback) instead of silently
  disabling the advisory on every attach. The check still never fails the
  attach. httpx is declared as a direct dependency since it is now imported.
- Injected sandbox views may set releases_on_terminate=False; cleanup then
  logs "Detached from sandbox ..." instead of "Released sandbox claim ...".
  BoundHandleClient (handle-bound mode, fleet.run) sets it, so the workspace
  no longer claims a release the fleet performs later.
- run_openhands_fleet: when MAX_WARMPOOL_SIZE is below MAX_CONCURRENT the
  raise is logged (WARNING if set explicitly, INFO for the default) with the
  resulting replica count, instead of happening silently.
- Tests: expected-quiet failures parametrized (transport, not-json), missing
  SDK dist quiet, non-dict payload warns, check bug is loud but not fatal,
  release vs detach log lines, adapter views carry the flag.

* fix: address kubernetes-sigs#1503 review round 4 — always derive host from the claimed sandbox; drop redundant test import

- workspace: a caller-supplied host no longer survives the claim (it would
  have sent commands and the pool session key to an unrelated server while
  the claimed pod sat idle). host is always set from _endpoint_url(sandbox);
  a supplied value is logged as ignored, with a pointer to router_url /
  endpoint_template for gateway paths. Regression test with host set.
- tests: drop the redundant in-test import of logging (module-level import
  already present).
…ernetes-sigs#1556)

* rl-sdk: allow adopting warm pools provisioned by the fleet layer

* addressed comments

* addressed more cr comments
…olicy (kubernetes-sigs#1539)

* fix(router): add app: sandbox-router label to router deployment

Add the app: sandbox-router label to the Go sandbox-router deployment
metadata and pod template. This allows the controller's default NetworkPolicy
(which permits ingress from pods labeled app: sandbox-router in the
agent-sandbox-system namespace) to accept traffic from the Go sandbox-router.

* olm: regenerate bundle

* spec: regenerate process protobuf definitions
…l shaping flags (kubernetes-sigs#1593)

* docs: document high-throughput tuning, connection sharding, and refill shaping flags

Under high sustained claim rates (e.g. 10-20+ claims/sec) or large warm
pools (>1,000 replicas), default controller deployments can experience
API server write spikes and warm pool replenishment stalls caused by
HTTP/2 stream saturation and watch frame queueing behind write bursts
(the expectations gate fallback).

Document the recently added flags in docs/configuration.md and
site/content/docs/performance-assessment/_index.md:
- API transport settings (--separate-watch-connection, --api-connections)
- Warm pool replenishment shaping (--sandbox-warm-pool-max-refill-rate,
  --sandbox-warm-pool-replenish-delay)
- API write optimizations (--disable-claim-events,
  --disable-claim-observability-annotations, --cache-label-selectors,
  --sandbox-write-behind-window)

Include a dedicated High-Throughput & Scale Tuning guide and sample
Deployment manifest with recommended flag combinations.

* docs: address review comments on Deployment manifest, warm pool workers, and burst flag

- Make high-throughput Deployment manifest valid by adding spec.selector,
  matching pod template labels, serviceAccountName, and image.
- Clarify that warm-pool workers provide concurrency across distinct pools
  rather than within a single pool due to workqueue key serialization.
- Remove ineffective kube-api-burst from high-throughput args and explain
  that burst only applies when kube-api-qps is set to a positive value.
- Add adoption caveat for --cache-label-selectors in performance assessment table.

* docs: clarify required tracking label value for pre-provisioned adoption
…tes-sigs#1463)

* ci(helm): require a chart version bump for generated content

Fails presubmit when the generated chart content changes without an
increase to the helm/Chart.yaml version.

Co-authored-by: pandaji <a0094028@u.nus.edu>

* test(helm): disable commit signing in scratch git repos

The chart version tests make real commits, which inherited a global
commit.gpgsign=true and failed for every test. Also pin the CI env vars
inside patch.dict rather than popping them after start.

* ci(helm): address review comments

* ci(helm): fall back to local base branch tip

* ci(helm): scope the chart version check to its own workflow

* ci(helm): drop GHA workflow, quoted versions, PULL_BASE_SHA

* ci(helm): Clear PULL_BASE_SHA in chart-version tests

* ci(helm): fix PULL_BASE_SHA handling per review, add tests

---------

Co-authored-by: pandaji <a0094028@u.nus.edu>
…s-sigs#1574)

* fix(python-sdk): keep the connection open on 4xx responses

The connector caught every RequestException, including a 404, and reset the
resolved Pod IP and closed the port-forward tunnel. A 4xx is a successful
round trip, so a normal missing-file read tore the tunnel down and forced
the next call to rebuild it.

Only reset the Pod IP and close the connection for genuine transport
failures (no response, or a 5xx). SandboxRequestError is still raised with
status_code so callers can branch on it.

Add tests asserting a 404 keeps the connection and a transport failure
still closes it.

Signed-off-by: Vincent <0426vincent@gmail.com>

* fix(python-sdk): also keep the connection open on 5xx responses

Tear down cached routing state only when there is no response (a transport
failure). Any HTTP response, 4xx or 5xx, means the sandbox or router
answered and the connection is still usable, matching the Go SDK and the
async connector.

Signed-off-by: Vincent <0426vincent@gmail.com>

* fix(python-sdk): clear pod IP on 5xx, keep it on 4xx

* test(python-sdk): stub retry backoff in 5xx cache test

* fix(python-sdk): preserve 5xx status when retries are exhausted

* fix(python-sdk): invalidate in-cluster pod IP cache on 5xx

---------

Signed-off-by: Vincent <0426vincent@gmail.com>
…bernetes-sigs#1576)

* feat: implement PodIP dialing

* feat: implement incluster service name dialing

* doc(go-sdk): add inClusterStrategy.Connect docstring

* fix(go-sdk): clear serviceFQDN

* fix(go-sdk): tracing label and comment typo

* fix: address comments

* fix: regenerate make all

* docs(go-sdk): revert docstring deletion

* Revert "docs(go-sdk): revert docstring deletion"

This reverts commit 95a34ef.

* doc(go-sdk): TTL caveat and specify in-cluster requirements

---------

Co-authored-by: Kai <nankeen@users.noreply.github.com>
…1339)

* feat(mcp): add /healthz and /readyz probe endpoints

The server ships a Dockerfile that serves streamable HTTP on
0.0.0.0:8000, so it is deployed as a long-running network service, but
it exposed no probe endpoints. A Deployment therefore had no way to
tell a wedged replica from a healthy one, or to keep traffic away from
one that cannot reach the Kubernetes API.

Add the two-endpoint split sandbox-router already uses
(sandbox-router/server/server.go):

- /healthz -- liveness. Returns 200 as soon as the ASGI app routes the
  request, and never contacts the Kubernetes API. Wiring liveness to an
  external dependency would turn a transient control-plane blip into a
  rolling restart of every replica, which is worse than briefly serving
  no traffic. A test asserts it makes no Kubernetes call.
- /readyz -- readiness. Lists SandboxClaims in a configurable
  probe_namespace, which exercises everything a tool call needs:
  credential loading, client construction and one real apiserver
  request. Returns 503 while starting and when the API is unreachable,
  with a generic reason so the underlying exception is not exposed to an
  unauthenticated caller.

Two implementation notes. The readiness check deliberately calls the
public list_sandbox_claims rather than the private _ensure_initialized:
the latter only loads credentials without reaching the apiserver, and
nothing else in the repo depends on SDK internals. And the lifespan's
yielded mapping reaches tools through ctx.lifespan_context but is not
published on the ASGI app, so the client is stashed on the FastMCP
server object, which routes reach as request.app.state.fastmcp_server.

httpx is now declared in the test extra. The probe tests drive the ASGI
app with it, and it was only available transitively through fastmcp.

* docs(mcp): document the /readyz response body accurately

The README said /readyz returns 503 with {"ready": false}, but the
handler also returns a "reason" field. Document the real shape,
including both reason values, and note that the reason is generic on
purpose because the endpoint is unauthenticated.

Also assert the full body in the failure test rather than just the
"ready" key, so the documented contract cannot drift again silently --
it already had.
…ubernetes-sigs#1587)

* docs: clarify restartPolicy interaction with claim lifecycle cleanup

When restartPolicy is omitted, Kubernetes defaults to Always, which
prevents TTL-based cleanup from ever firing because the container
restarts indefinitely and the sandbox never reaches a terminal state.

Add a "Restart Policy and Cleanup Interaction" section to the lifecycle
docs explaining the restartPolicy x TTL/shutdownTime matrix and the
two failure modes (zombie sandboxes, unbounded CrashLoopBackOff).

Set explicit restartPolicy on 13 critical examples where the implicit
Always default could cause resource leaks:
- Never for one-shot kata demos (kata-gke, kata-aks)
- OnFailure for interactive/gateway workloads (warmpool-quickstart,
  hermes, aider, gemini-cu, sandboxd, latebind-storage, kata-aks
  template)

Signed-off-by: vvoronko <vvoronko@redhat.com>

* docs: fix ttlSecondsAfterFinished casing in lifecycle page

Use lower camelCase to match the actual API field name.

Signed-off-by: vvoronko <vvoronko@redhat.com>

* docs: fix inaccurate API field references in lifecycle page

Review caught two issues: maxLifetimeSeconds does not exist in the
current API (planned for kubernetes-sigs#1420), and ttlSecondsAfterFinished was not
attributed to its actual location in the extensions API.

Signed-off-by: vvoronko <vvoronko@redhat.com>

---------

Signed-off-by: vvoronko <vvoronko@redhat.com>
…orphan leaks (kubernetes-sigs#1379)

exec.CommandContext only sends SIGKILL to the child PID on context
cancellation, not its process group. Since Start/Execute use Setpgid:
true, grandchildren survive as orphans when the parent is killed
(e.g. client disconnect).

Fix: Replace exec.CommandContext with exec.Command, add
killProcessGroupOnContextDone helper that signals -PGID (whole process
group) on context cancellation. Also check context before forking to
avoid starting commands we'd immediately kill.

Layered kill strategy works across container runtimes:
  1. syscall.Kill(-PGID, SIGKILL) — whole group, one syscall
  2. /proc/<pid>/task/<tid>/children scan — gVisor fallback that
     iterates all threads (multithreaded parents fork from any TID)
  3. Direct PID kill — last resort

WaitDelay bounds cmd.Wait on I/O drain after the child exits, so a
grandchild holding stdout/stderr write ends cannot block the RPC
indefinitely.

Non-blocking done check in killProcessGroupOnContextDone narrows the
PID-reuse race window between Wait reaping and done closing.

Release note:
```release-note
Fixed orphan process leak in sandboxd when clients disconnect from
long-running commands with grandchildren.
```
…ubernetes-sigs#1359)

Adds docs/performance-tuning.md with the benchmark evidence and sizing
rationale behind the high-throughput flag recommendations: worker-count
and flag A/B results from GKE live testing, kops warm-adoption latency
data, write-behind trade-offs, and burst-vs-sustained profile guidance
including the replenish-delay pool-drain fragility finding.

docs/configuration.md (kubernetes-sigs#1593) remains the canonical flag reference; this
guide cross-links it instead of duplicating flag documentation, and the
two docs now agree on sizing rules (refill rate >= per-pool arrival rate,
warm-pool workers sized to pool count, batch size default under the
expectations gate).

Co-authored-by: Aditya Shantanu <aditya-shantanu@users.noreply.github.com>
…repo rename (kubernetes-sigs#1620)

* examples/envd-sandbox: repin envd after upstream repo rename broke e2e

The e2b-dev/infra repository was renamed to e2b-dev/runtime and its history
restructured (Sep 2026). The commit previously pinned in ENVD_VERSION is no
longer reachable from any branch or tag, so the 'git checkout' in the image
build fails with 'fatal: unable to read tree', which breaks the required
presubmit-agent-sandbox-test-e2e job for every PR (the e2e harness builds all
example images during setup).

Repin to the upstream release tag envd-v0.6.13 (commit 2acf2d51bd1e) — a tag
survives upstream rebases, unlike a bare SHA — and point the clone URL and
doc links at the renamed repository.

Verified: fresh clone + checkout of envd-v0.6.13 succeeds, and envd compiles
at that tag with the Dockerfile's exact build flags.

* examples/envd-sandbox: verify the pinned tag resolves to the expected commit

Address review: a tag is mutable, so checking it out alone cannot prove
future builds compile the documented source. Keep the tag as the pin (it
survives upstream rebases, which is what broke the bare-SHA pin) and fail
the build loudly if it ever resolves to a different commit.

---------

Co-authored-by: Aditya Shantanu <aditya-shantanu@users.noreply.github.com>
…up (kubernetes-sigs#1623)

When setting up the test cluster, dev/ci/presubmits/test-e2e previously
invoked push-images without specifying --images, defaulting to building
and loading all Dockerfiles across the repository (including all 21
example images). This caused presubmit failures when unrelated example
images encountered build or upstream network issues (such as git tree
checkout errors during example Dockerfile builds).

Scope E2ETestRunner.setup_cluster to only build and push the images
actually required by the E2E suites:
- agent-sandbox-controller
- sandbox-router
- sandboxd
- python-runtime-sandbox
- chrome-sandbox
…ubernetes-sigs#1516)

Bumps the pip group with 1 update in the /examples/mcp-server-sandbox directory: [mcp](https://github.com/modelcontextprotocol/python-sdk).
Bumps the pip group with 2 updates in the /examples/gemini-cu-sandbox directory: [idna](https://github.com/kjd/idna) and [python-multipart](https://github.com/Kludex/python-multipart).
Bumps the pip group with 4 updates in the /examples/analytics-tool/analytics-tool directory: [idna](https://github.com/kjd/idna), [python-multipart](https://github.com/Kludex/python-multipart), [fonttools](https://github.com/fonttools/fonttools) and [pillow](https://github.com/python-pillow/Pillow).
Bumps the pip group with 2 updates in the /clients/python/agentic-sandbox-client/sandbox-router directory: [idna](https://github.com/kjd/idna) and [starlette](https://github.com/Kludex/starlette).


Updates `mcp` from 1.27.2 to 1.28.1
- [Release notes](https://github.com/modelcontextprotocol/python-sdk/releases)
- [Changelog](https://github.com/modelcontextprotocol/python-sdk/blob/main/RELEASE.md)
- [Commits](modelcontextprotocol/python-sdk@v1.27.2...v1.28.1)

Updates `idna` from 3.10 to 3.15
- [Release notes](https://github.com/kjd/idna/releases)
- [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md)
- [Commits](kjd/idna@v3.10...v3.15)

Updates `python-multipart` from 0.0.20 to 0.0.31
- [Release notes](https://github.com/Kludex/python-multipart/releases)
- [Changelog](https://github.com/Kludex/python-multipart/blob/main/CHANGELOG.md)
- [Commits](Kludex/python-multipart@0.0.20...0.0.31)

Updates `idna` from 3.10 to 3.15
- [Release notes](https://github.com/kjd/idna/releases)
- [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md)
- [Commits](kjd/idna@v3.10...v3.15)

Updates `python-multipart` from 0.0.20 to 0.0.31
- [Release notes](https://github.com/Kludex/python-multipart/releases)
- [Changelog](https://github.com/Kludex/python-multipart/blob/main/CHANGELOG.md)
- [Commits](Kludex/python-multipart@0.0.20...0.0.31)

Updates `fonttools` from 4.60.1 to 4.60.2
- [Release notes](https://github.com/fonttools/fonttools/releases)
- [Changelog](https://github.com/fonttools/fonttools/blob/main/NEWS.rst)
- [Commits](fonttools/fonttools@4.60.1...4.60.2)

Updates `pillow` from 12.0.0 to 12.3.0
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](python-pillow/Pillow@12.0.0...12.3.0)

Updates `idna` from 3.13 to 3.15
- [Release notes](https://github.com/kjd/idna/releases)
- [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md)
- [Commits](kjd/idna@v3.10...v3.15)

Updates `starlette` from 1.1.0 to 1.3.1
- [Release notes](https://github.com/Kludex/starlette/releases)
- [Changelog](https://github.com/Kludex/starlette/blob/main/docs/release-notes.md)
- [Commits](Kludex/starlette@1.1.0...1.3.1)

---
updated-dependencies:
- dependency-name: mcp
  dependency-version: 1.28.1
  dependency-type: direct:production
  dependency-group: pip
- dependency-name: idna
  dependency-version: '3.15'
  dependency-type: indirect
  dependency-group: pip
- dependency-name: python-multipart
  dependency-version: 0.0.31
  dependency-type: direct:production
  dependency-group: pip
- dependency-name: idna
  dependency-version: '3.15'
  dependency-type: indirect
  dependency-group: pip
- dependency-name: python-multipart
  dependency-version: 0.0.31
  dependency-type: direct:production
  dependency-group: pip
- dependency-name: fonttools
  dependency-version: 4.60.2
  dependency-type: indirect
  dependency-group: pip
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: indirect
  dependency-group: pip
- dependency-name: idna
  dependency-version: '3.15'
  dependency-type: indirect
  dependency-group: pip
- dependency-name: starlette
  dependency-version: 1.3.1
  dependency-type: indirect
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…netes-sigs#1590)

Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.83.1 to 1.83.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](grpc/grpc-go@v1.83.1...v1.83.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.83.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…dates (kubernetes-sigs#1591)

Bumps the npm_and_yarn group with 1 update in the /test/e2e/clients/typescript directory: [postcss](https://github.com/postcss/postcss).


Updates `@vitest/mocker` from 4.1.8 to 5.0.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.0/packages/mocker)

Updates `postcss` from 8.5.15 to 8.5.28
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](postcss/postcss@8.5.15...8.5.28)

---
updated-dependencies:
- dependency-name: "@vitest/mocker"
  dependency-version: 5.0.0
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: postcss
  dependency-version: 8.5.28
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…3 updates (kubernetes-sigs#1578)

Bumps the npm-dependencies group with 3 updates in the /site directory: [autoprefixer](https://github.com/postcss/autoprefixer), [postcss](https://github.com/postcss/postcss) and [postcss-cli](https://github.com/postcss/postcss-cli).


Updates `autoprefixer` from 10.5.4 to 10.5.5
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](postcss/autoprefixer@10.5.4...10.5.5)

Updates `postcss` from 8.5.26 to 8.5.28
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](postcss/postcss@8.5.26...8.5.28)

Updates `postcss-cli` from 11.0.1 to 12.0.0
- [Release notes](https://github.com/postcss/postcss-cli/releases)
- [Changelog](https://github.com/postcss/postcss-cli/blob/master/CHANGELOG.md)
- [Commits](postcss/postcss-cli@11.0.1...12.0.0)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-version: 10.5.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: postcss
  dependency-version: 8.5.28
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm-dependencies
- dependency-name: postcss-cli
  dependency-version: 12.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: npm-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…broken runs as infra (kubernetes-sigs#1626)

* fix(flake-report): stop counting aborted, clone-failed, and pre-test-broken runs as infra

The infra heuristic in analyze_tab counted every red Overall column with no
failing junit testcase as an infrastructure failure. Three benign run shapes
match that exact TestGrid signature:

- aborted runs (a newer push to the PR supersedes the running job),
- stale-PR clone failures (the PR no longer merges onto main), and
- PRs that break a pre-test gate (compile/vet/mypy) while junit stays clean.

On presubmit-test-unit this inflated "infra failures" to 49 red runs — 35
aborted + 7 clone conflicts + 7 PR-caused pre-test failures, zero real infra —
and filed a false-alarm infra tracker; the kwok scalability lane tracker was
mostly clone conflicts for the same reason.

Resolve each red column against the run's GCS artifacts (fetched over HTTPS,
only for red columns): finished.json identifies ABORTED runs, and
clone-records.json identifies failed clones (falling back to the missing
"revision" field in finished.json). Junit-present-but-nothing-failed columns
are reported as pre-test PR breakage in a new report section; only "pod
started, no junit, not aborted or clone-failed" remains infra. Aborted runs
are also excluded from per-test flake tallies and the consistent-failure
check, closing the known limitation where junit errors from cancelled runs
counted as flakes.

The --json payload keeps the existing flaky/consistent/infra keys and adds
aborted_runs, clone_failures, and pretest_failures per tab.

* flake-report: verify merge conflicts before blaming stale PRs; drop aborted cells everywhere

Address review: clone-records.json sets failed=true for network and
ref-fetch errors too, so only records whose git output shows a merge
conflict may be reported as stale-PR failures — everything else stays
in the infra count, as does a junit-less red run with no clone-records
at all. Aborted columns are now also excluded from pass and flaky cells,
so an aborted rerun can no longer manufacture a retest flip or a flake
finding.

* flake-report: take the last column-ID segment and treat flaky cells as test failures

Address review: extract the build ID as the last U+E000-separated
segment so a name-prefixed column ID cannot misdirect artifact fetches
(live dashboards emit the leading-separator form; verified), and count
FLAKY_STATUS cells as failing testcases when classifying red runs so a
run whose only failure flaked-then-passed is a test story rather than
pre-test PR breakage.

---------

Co-authored-by: Aditya Shantanu <aditya-shantanu@users.noreply.github.com>
…Go (kubernetes-sigs#1586)

The sandboxed-tools example hardcoded a small ad-hoc tool surface
(run_command/ls/read/write) and its system prompt, so trying a different
agent profile meant editing the agent loop. This makes the tools and
prompt pluggable and adds a second profile that reproduces gemini-cli.

A toolset (pkg/toolsets) bundles a system prompt, the LLM-callable
tools, and the sandbox image they expect, selected with the new
-toolset flag. The existing tools become the 'basic' toolset.

The new 'geminicli' toolset (pkg/toolsets/geminicli) reproduces the
tool surface and system prompt of gemini-cli (Apache-2.0): same tool
names, parameter schemas, descriptions, and result formats
(list_directory, read_file, write_file, replace, glob, grep_search,
read_many_files, run_shell_command), so model behavior tuned for
gemini-cli transfers directly. The tools are reimplemented in Go: the
filesystem tools are compiled into a geminicli-toolbox binary that runs
inside the sandbox (JSON args on stdin, result on stdout).

images/geminicli-toolbox provides the sandbox image
(debian-slim + bash/git + the toolbox binary).

Gaps relative to gemini-cli's full tool manifest (web_fetch,
google_web_search, write_todos, ask_user, plan mode, skills, memory,
and per-tool parity items) are documented as TODOs in
pkg/toolsets/geminicli so the missing functionality is inventoried
even where we may choose not to implement it.
…ith 13 updates (kubernetes-sigs#1627)

Bumps the gomod-dependencies group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [github.com/prometheus/client_model](https://github.com/prometheus/client_model) | `0.6.2` | `0.6.3` |
| [github.com/prometheus/common](https://github.com/prometheus/common) | `0.70.1` | `0.71.0` |
| [go.opentelemetry.io/contrib/bridges/prometheus](https://github.com/open-telemetry/opentelemetry-go-contrib) | `0.70.0` | `0.71.0` |
| [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.45.0` | `1.46.0` |
| [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.45.0` | `1.46.0` |
| [golang.org/x/net](https://github.com/golang/net) | `0.58.0` | `0.59.0` |

Bumps the gomod-dependencies group with 1 update in the /olm directory: [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo).


Updates `github.com/prometheus/client_model` from 0.6.2 to 0.6.3
- [Release notes](https://github.com/prometheus/client_model/releases)
- [Commits](prometheus/client_model@v0.6.2...v0.6.3)

Updates `github.com/prometheus/common` from 0.70.1 to 0.71.0
- [Release notes](https://github.com/prometheus/common/releases)
- [Changelog](https://github.com/prometheus/common/blob/main/CHANGELOG.md)
- [Commits](prometheus/common@v0.70.1...v0.71.0)

Updates `go.opentelemetry.io/contrib/bridges/prometheus` from 0.70.0 to 0.71.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go-contrib@zpages/v0.70.0...zpages/v0.71.0)

Updates `go.opentelemetry.io/otel` from 1.45.0 to 1.46.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go@v1.45.0...v1.46.0)

Updates `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` from 1.45.0 to 1.46.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go@v1.45.0...v1.46.0)

Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` from 1.45.0 to 1.46.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go@v1.45.0...v1.46.0)

Updates `go.opentelemetry.io/otel/sdk` from 1.45.0 to 1.46.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go@v1.45.0...v1.46.0)

Updates `go.opentelemetry.io/otel/sdk/metric` from 1.45.0 to 1.46.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go@v1.45.0...v1.46.0)

Updates `go.opentelemetry.io/otel/trace` from 1.45.0 to 1.46.0
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go@v1.45.0...v1.46.0)

Updates `golang.org/x/net` from 0.58.0 to 0.59.0
- [Commits](golang/net@v0.58.0...v0.59.0)

Updates `golang.org/x/sync` from 0.22.0 to 0.23.0
- [Commits](golang/sync@v0.22.0...v0.23.0)

Updates `github.com/onsi/ginkgo/v2` from 2.22.0 to 2.32.1
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](onsi/ginkgo@v2.22.0...v2.32.1)

Updates `github.com/onsi/gomega` from 1.36.1 to 1.40.0
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](onsi/gomega@v1.36.1...v1.40.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_model
  dependency-version: 0.6.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gomod-dependencies
- dependency-name: github.com/prometheus/common
  dependency-version: 0.71.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: go.opentelemetry.io/contrib/bridges/prometheus
  dependency-version: 0.71.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: go.opentelemetry.io/otel
  dependency-version: 1.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc
  dependency-version: 1.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
  dependency-version: 1.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-version: 1.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: go.opentelemetry.io/otel/sdk/metric
  dependency-version: 1.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: go.opentelemetry.io/otel/trace
  dependency-version: 1.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: golang.org/x/net
  dependency-version: 0.59.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: golang.org/x/sync
  dependency-version: 0.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-version: 2.32.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
- dependency-name: github.com/onsi/gomega
  dependency-version: 1.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gomod-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ernetes-sigs#1592)

* ci: unify olm golangci-lint config with dev/tools/.golangci.yaml

Now that olm/Makefile uses repo-wide dev/tools/go.mod to run golangci-lint,
it still maintained its own boilerplate olm/.golangci.yml from operator-sdk.
This allowed linter rules and binary versions to drift apart over time.

Remove olm/.golangci.yml and configure olm/Makefile lint targets to pass
--config $(REPO_ROOT)/dev/tools/.golangci.yaml. Also fix minor lint issues
flagged in olm by the shared config:
- Add doc comment trailing periods (godot) in olm/test/utils
- Replace interface{} with any and strings.Split with SplitSeq (modernize)
- Add inline nolint:revive annotations on Ginkgo/Gomega dot-imports in e2e tests

* ci: enable ginkgolinter in shared golangci-lint config

Keep matcher-misuse checks for the Ginkgo/Gomega test suite in
olm/test/e2e following the migration to the shared linter configuration.
… and transient infra errors (kubernetes-sigs#1624)

* Harden the kwok scalability presubmit against invisible gate failures and transient infra errors

Of the 25 real failures on presubmit-agent-sandbox-test-e2e-scalability-kwok
since Aug 3, 8 were perf-gate violations that were invisible in junit:
ClusterLoader2 succeeds, junit reports failures=0, and then
scrape_controller_metrics.py fails the job with the violation printed only to
stdout, so Spyglass/TestGrid render the run as "failed before tests ran". Two
more were transient infra errors (a GitHub 503 while kwokctl create cluster
downloaded etcd on a cold cache, and a proxy.golang.org stream error during
the ClusterLoader2 go build), and the sleep 3 after launching the controller
with go run is not a readiness wait: a cold-pod compile can exceed it, and
ClusterLoader2 starting before the controller serves inflates the very latency
samples the gate measures.

- scrape_controller_metrics.py now writes ${ARTIFACTS}/junit_controller-metrics.xml
  with one testcase per validated percentile; failures carry the measured
  value vs target. Job exit behavior is unchanged.
- kwokctl create cluster is retried up to 3 times, deleting the partial
  cluster between attempts, mirroring the curl --retry already used for the
  kwokctl binary download.
- GOPROXY gains a |direct fallback so proxy incidents do not fail the build
  (the Prow job env pins proxy-only).
- The sleep 3 is replaced with a bounded poll of the controller's
  :8082/readyz endpoint that dumps controller.log and fails loudly on timeout.

* kwok presubmit: gate on worker startup, bound readiness probes, test the gate CLI

Address review: /readyz is a healthz.Ping check that only proves the
probe server responds, so the readiness wait now also requires
controller-runtime's "Starting workers" log line (post leader election
and cache sync) before ClusterLoader2 starts. Each curl probe carries
connect/max timeouts so a wedged connection cannot outlive the loop's
120s budget. The metrics gate now has end-to-end CLI tests covering the
violating, unreachable, and passing paths (exit code + junit contents).

---------

Co-authored-by: Aditya Shantanu <aditya-shantanu@users.noreply.github.com>
etcd's default quota is 2GiB.  When we exceed it, etcd raises the
NOSPACE alarm and rejects every write with
'mvcc: database space exceeded' until the alarm is cleared.

8GiB puts the limit far from any benchmark workload;
etcd only uses the space it actually writes.

Overridable via STRESS_ETCD_QUOTA_BYTES.
…ter (kubernetes-sigs#1595)

The controller and sandbox-router previously offered no way to tune
TLS parameters, requiring consumers to accept the compiled defaults.

Controller: add --metrics-secure-serving, --metrics-cert-dir,
--tls-min-version, and --tls-cipher-suites flags to configure the
metrics server's TLS settings. The metrics endpoint remains plain HTTP
by default; enabling secure serving is opt-in.

Sandbox-router: add --tls-min-version and --tls-cipher-suites flags
(also settable via TLS_MIN_VERSION / TLS_CIPHER_SUITES env vars and
the config file). The existing TLS 1.2 minimum default is preserved
when the flags are unset.

A downstream operator or platform integrator can inject
profile-derived values via Deployment args or environment variables
without changes to this project.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
…ments (kubernetes-sigs#1628)

Dependabot's python:3.14-bookworm bump (kubernetes-sigs#1506) has failed the e2e
presubmit on five consecutive heads because requirements.txt pins
pydantic-core 2.33.2, which ships no cp314 wheels (PyO3 caps at 3.13),
so pip falls back to a maturin source build that aborts during the
image build. Dependabot only edits the Dockerfile and cannot recompile
the lockfile, so this supersedes kubernetes-sigs#1506.

- bump pydantic to 2.12.0 in requirements.in, matching the pin in
  google-gemini/computer-use-preview so both pip installs in the
  Dockerfile agree; pydantic 2.12.0 resolves to pydantic-core 2.41.1,
  which ships cp314 wheels
- recompile requirements.txt with pip-compile --generate-hashes under
  Python 3.14 (also picks up typing-inspection 0.4.4)
- bump the base image to python:3.14-bookworm

Verified locally: every pin has a linux cp314-compatible wheel and all
hashes match PyPI; the image builds; uvicorn serves / with status ok;
test_main.py passes (4/4) both in a local 3.14 venv and inside the
built container (Python 3.14.7, pydantic-core 2.41.1).

Co-authored-by: Aditya Shantanu <aditya-shantanu@users.noreply.github.com>
dongjiang1989 and others added 26 commits September 18, 2026 19:05
…sigs#1698)

Address review nit from PR kubernetes-sigs#1661. Since t.Fatalf terminates execution,
the else branch after errors.AsType is unreachable; declare httpErr up
front so the subsequent assertions stay unnested.

Signed-off-by: dongjiang1989 <dongjiang1989@126.com>
…gs#1645)

* docs: publish and align sandboxd runtime API reference

* docs: correct sandboxd runtime API guarantees

* docs: fix sandboxd SDK examples and comments

* docs: align sandboxd protocol examples

* docs: document policy requirements for direct sandboxd access

* docs: clarify sandboxd example connectivity

* docs: correct sandboxd transport and error semantics

* docs: separate router protocol and reachability constraints
…rgets (kubernetes-sigs#1710)

Several components, SDKs, and tooling targets added since AGENTS.md was last updated were missing or outdated, which can cause AI agents to miss repository conventions or run incomplete checks.

Update AGENTS.md to reflect current HEAD:
- Add sandbox-router, packages/sandboxd, helm, olm, clients/typescript, and clients/integrations to the repository layout table.
- List the available skills in .agents/skills/ and note CLAUDE.md import.
- Update make all, make build, make test-unit, make fix-api-docs, and make verify-chart-version / bump-chart-version descriptions, plus helm/ CRD/RBAC generation in codegen.go.
- Update Hugo docs mounts in site/hugo.yaml (generated reference docs, sandboxd user guide, nemo-gym integration README).
- Update Python SDK dependencies/extras (grpc, prometheus-client) and document mypy typecheck enforcement in make test-unit.
- Add TypeScript SDK conventions section.
kubernetes-sigs#1653)

* docs(configuration): cover every controller flag in the flag reference

configuration.md is the canonical flag reference, and performance-tuning.md
points readers at it for the pprof flags in particular, but eleven of the
flags the controller registers were absent from it: the four profiling
flags, --enable-tracing, --extensions, --leader-elect,
--leader-election-namespace, --metrics-bind-address,
--health-probe-bind-address and --version.

The standard controller-manager flags join Cluster Settings. Tracing and
profiling get their own section that states which endpoints each flag
enables — --enable-pprof exposes only the CPU profile, --enable-pprof-debug
adds the sensitive ones and /debug/fgprof — along with the sampling
semantics of the two rate flags, the fact that negative values are clamped
at startup, and the warning about exposing process internals.

The reference now covers all 34 flags the controller accepts.

* docs(configuration): state the leader-election-namespace default explicitly

The flag is registered with an empty default, and the controller auto-detects
the namespace it is running in when the value is unset — that is the case the
binary logs about when leader election is enabled. Documenting the default as
"the controller's own namespace" conflated the default with the behaviour it
triggers.

Addresses the review comment on kubernetes-sigs#1653.

* docs(configuration): point at the zap logging flags the manager binds

The manager binds controller-runtime's standard zap flags through
opts.BindFlags, which made them the one group still missing from the
reference, and the claim in the previous commit that every accepted flag is
now covered was therefore not accurate.

List the flags and point at controller-runtime for their semantics rather
than duplicating documentation that lives upstream.

Addresses the review note on kubernetes-sigs#1653.

* docs(configuration): split manager flags and tighten profiling notes

Cluster Settings mixed manager process behavior — the endpoints it serves, leader election, and controller registration — with --cluster-domain, the only cluster-wide flag, so the manager flags get their own section.

The tracing and pprof entries also left out details readers need: the OTLP exporter is configured through standard OpenTelemetry environment variables and the controller exits at startup when it cannot initialize, and only the duration-based profilers reject concurrent requests. The zap flags link now points at the released controller-runtime version rather than main.
…gs#1605)

* feat(clients/ts): support automatic sandbox expiration

TypeScript clients need a controller-enforced cleanup fallback when they exit before deleting their sandboxes. Add optional shutdownAfterSeconds to set an absolute claim deadline with the Delete policy, matching the Python SDK. Validate the duration before provisioning and preserve behavior when the option is omitted.

* review: spell out the full lifecycle field paths for shutdownAfterSeconds

The option's doc comment and README named shutdownPolicy without its
spec.lifecycle prefix, so a reader could not tell which SandboxClaim
fields the option writes. Give both field paths in full.
…ubernetes-sigs#1700)

Bumps the pip group with 1 update in the /clients/python/agentic-sandbox-client/sandbox-router directory: [anyio](https://github.com/agronholm/anyio).
Bumps the pip group with 1 update in the /examples/analytics-tool/analytics-tool directory: [anyio](https://github.com/agronholm/anyio).
Bumps the pip group with 1 update in the /examples/gemini-cu-sandbox directory: [anyio](https://github.com/agronholm/anyio).
Bumps the pip group with 1 update in the /examples/python-runtime-sandbox directory: [anyio](https://github.com/agronholm/anyio).


Updates `anyio` from 4.13.0 to 4.14.2
- [Release notes](https://github.com/agronholm/anyio/releases)
- [Commits](agronholm/anyio@4.13.0...4.14.2)

Updates `anyio` from 4.10.0 to 4.14.2
- [Release notes](https://github.com/agronholm/anyio/releases)
- [Commits](agronholm/anyio@4.13.0...4.14.2)

Updates `anyio` from 4.10.0 to 4.14.2
- [Release notes](https://github.com/agronholm/anyio/releases)
- [Commits](agronholm/anyio@4.13.0...4.14.2)

Updates `anyio` from 4.14.0 to 4.14.2
- [Release notes](https://github.com/agronholm/anyio/releases)
- [Commits](agronholm/anyio@4.13.0...4.14.2)

---
updated-dependencies:
- dependency-name: anyio
  dependency-version: 4.14.2
  dependency-type: indirect
  dependency-group: pip
- dependency-name: anyio
  dependency-version: 4.14.2
  dependency-type: indirect
  dependency-group: pip
- dependency-name: anyio
  dependency-version: 4.14.2
  dependency-type: indirect
  dependency-group: pip
- dependency-name: anyio
  dependency-version: 4.14.2
  dependency-type: indirect
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…es-sigs#976 (kubernetes-sigs#1535)

* fix(clients/ts): address non-blocking review follow-ups from kubernetes-sigs#976

The initial TypeScript SDK PR (kubernetes-sigs#976) landed with five non-blocking review
notes deferred to a follow-up. This clears them:

- `SandboxClient.getSandboxClaimWarmpoolName()` declared `Promise<string>`
  but returned `warmPoolRef.name` unchecked, which is `undefined` at
  runtime for a claim that is not warm-pool-backed (a cold-pool or
  direct-template claim). Widen the return type to `string | undefined` —
  matching the Python SDK, which reads the same field as optional — so
  callers are forced to handle the absent case instead of hitting it as an
  untyped `undefined`. No consumers yet (`private: true`), so this is not a
  break in practice.
- The e2e `TestContext` resolves its Kubernetes client from an explicit
  kubeconfig (`$KUBECONFIG`, else `bin/KUBECONFIG`), but its `kubectl`
  subprocesses — `apply` and the watch-timeout `describe` / `get pods`
  diagnostics — used the ambient current-context, so a developer whose
  context drifted after `make deploy-kind` would apply manifests to and
  dump state from a different cluster than the test client talks to. Pass
  `--kubeconfig` explicitly.
- `dev/tools/test-e2e`'s `ensure_extensions_enabled()` has the same split:
  it patches the controller Deployment via `kubectl` against the ambient
  context. Thread the repo root in and target the same kubeconfig the SDK
  frameworks use.
- Drop the unused `shutil` and `time` imports from `dev/tools/test-e2e`.
- Drop the `allowScripts` block from the e2e `package.json`: its key had a
  five-segment `../` path where the dependency spec has four, and nothing
  in the repo reads `allowScripts` (there is no lavamoat), so it was dead
  config either way.

* fix(dev): propagate the resolved kubeconfig to e2e SDK test processes

The previous change pointed only ensure_extensions_enabled()'s controller
kubectl calls at the resolved kubeconfig ($KUBECONFIG, else bin/KUBECONFIG).
The SDK e2e frameworks that run afterwards never saw it: the Python framework's
apply_manifest_text() shells out to `kubectl apply` with no --kubeconfig, so
manifests could land on kubectl's ambient current-context instead of the
cluster the test client talks to.

Resolve the kubeconfig once in main() and pin it in the environment every test
subprocess inherits (Go, Python, TypeScript), so the API clients and their
kubectl invocations all target the same cluster. ensure_extensions_enabled()
now takes that env instead of re-resolving the path itself.

Signed-off-by: Hirotaka Kawashima <24205015+khirotaka@users.noreply.github.com>

* fix(dev): preserve multi-file KUBECONFIG in test-e2e's kubectl calls

ensure_extensions_enabled passed KUBECONFIG to kubectl via --kubeconfig,
but that flag treats its value as a single filename and does not merge
paths. When KUBECONFIG held multiple colon-separated paths, kubectl
would fail to find that literal filename and abort the E2E suite.

Drop --kubeconfig and pass env=env to each subprocess.run call instead,
so kubectl resolves KUBECONFIG natively (merging multi-file values) while
still honoring the bin/KUBECONFIG fallback pinned by main().

Signed-off-by: Hirotaka Kawashima <24205015+khirotaka@users.noreply.github.com>

* fix(clients/ts): align kubeconfig merging with kubectl in TestContext

Signed-off-by: Hirotaka Kawashima <24205015+khirotaka@users.noreply.github.com>

* fix(clients/ts): skip missing KUBECONFIG entries like kubectl in TestContext

Signed-off-by: Hirotaka Kawashima <24205015+khirotaka@users.noreply.github.com>

---------

Signed-off-by: Hirotaka Kawashima <24205015+khirotaka@users.noreply.github.com>
…name is too long (kubernetes-sigs#1630)

A Sandbox name may be up to 253 characters (like any Pod/CR name), but the
controller derives the headless Service name directly from the Sandbox name,
and a Service name is a DNS-1035 label capped at 63 characters. A Sandbox with
spec.service and a name of 64+ characters therefore backs a Pod that runs fine
but a Service the apiserver permanently rejects. The reconciler returned that
Invalid error from Reconcile, so controller-runtime requeued it with rate
limiting and re-logged an error-level stacktrace on every pass -- a permanent
user misconfiguration treated as a transient failure, hot-looping forever while
the Sandbox stayed stuck at Ready=False/ReconcilerError.

Classify permanent apiserver Invalid errors from child-resource reconciliation
as terminal: surface them through a new, specific Ready=False reason
(InvalidConfiguration) with the apiserver message, and keep them out of the
error returned from Reconcile so the request is not requeued. Non-Invalid
(transient) errors are unchanged and still returned for retry. Also log the
Service create rejection at info rather than error level, since retrying cannot
help.

Adds a computeConditions case for the new reason and an interceptor-based
Reconcile regression test asserting the permanent error is not returned and the
Sandbox reports Ready=False/InvalidConfiguration.
…ns (kubernetes-sigs#1532)

* feat(sandbox): emit Kubernetes Events for Sandbox lifecycle transitions

SandboxReconciler emits no Kubernetes Events today, so kubectl describe
sandbox stays silent on lifecycle transitions -- unlike the extensions'
SandboxClaimReconciler, which already emits SandboxProvisioned,
SandboxAdopted, and ClaimExpired via events.EventRecorder. The Recorder
field, its main.go wiring, and the RBAC markers were already added in
lifecycle coverage: SandboxPodCreated, SandboxPodCreateFailed (Pod creation
failing), SandboxReady, SandboxExpired, SandboxSuspended, and the Pod
reaching a terminal phase on its own (PodSucceeded/PodFailed).

SandboxReady, SandboxExpired, SandboxSuspended, and the pod-completion
events are emitted from updateStatus, after the status patch has
actually persisted, gated on the Ready condition's Reason having just
transitioned. This piggybacks on updateStatus's existing DeepEqual
short-circuit: a reconcile that doesn't change the Ready reason never
reaches the patch or the event, so nothing re-fires on retries or
steady-state reconciles, and a failed patch never produces a misleading
event. It also means SandboxExpired naturally only fires for
ShutdownPolicy=Retain: ShutdownPolicy=Delete deletes the Sandbox before
updateStatus would ever be called on that path.

SandboxPodCreated and SandboxPodCreateFailed (create failure) are emitted
directly at the r.Create call site in reconcilePod, matching the
existing recordMultiplePodsEvent convention -- pod creation is itself
the durable fact being reported, and a later reconcile finds the pod
via Get rather than re-entering this code path.

* feat(sandbox): add --disable-sandbox-events flag

main.go wired the Sandbox controller's recorder unconditionally, so the
new per-sandbox lifecycle events (SandboxPodCreated and SandboxReady at
minimum) had no way to be switched off during large warm-pool fills.
Mirror --disable-claim-events, which exists for exactly that reason on
the SandboxClaim controller: a nil recorder cleanly no-ops every Eventf
call in the Sandbox controller too, since they're all already
nil-guarded.
* feat(sdks): avoid buffering large file downloads

* fix(sdks): harden streaming download failures

* docs(go-sdk): regenerate reference for streaming downloads

* fix(sdks): handle streaming download edge cases

* fix(sdks): address streaming review feedback

* fix(sdks): preserve auth across streaming retries

* fix(sdks): preserve streaming error responses

* fix(sdks): close cancelled streaming responses

* fix(sdks): preserve main connector error handling
…rnetes-sigs#1696)

update_issues dedups findings against open kind/flake issues only, so
closing a flake issue whose stale failing columns are still inside the
100-run TestGrid window causes the next nightly run to file a duplicate.
Maintainers have had to leave verified false positives open purely to
suppress re-filing.

When no open issue matches a finding's marker, also look for the most
recently closed issue with the same marker. If the finding's newest
failure is not newer than that issue's closedAt, skip filing: the closer
already judged those failures. A failure strictly newer than the close
still files a fresh issue (genuine recurrences must surface) and links
the prior issue in the body for lineage. Applies to both per-test flaky
issues and infra-tab issues. An unparsable or missing close time files
rather than suppresses.

Co-authored-by: Aditya Shantanu <aditya-shantanu@users.noreply.github.com>
* fix(python): harden async sandboxd cleanup

* fix(python): make sandboxd cleanup retryable

* fix(python): make sync port-forward cleanup retryable

* fix(python): keep failed sandbox cleanup retryable

* fix(python): reap sync port-forward after kill
…ion, and wrapper bypasses (kubernetes-sigs#1690)

is_denied() from kubernetes-sigs#1456 only checked a command's first parsed token, a gap
its own README documented (chaining/substitution reach
sandbox.commands.run() unchecked). Extracts the classifier into
governed_run.py, adds raw-text + segment-split layers covering shell
chaining (;, &&, ||, |, &), command substitution ($(...)/backticks,
nested), and sudo/env/xargs/command wrapper stripping, with a
test_governed_run.py regression suite and a dev/tools/test-unit
registration.

Also makes the segment-level rm/wrapper exe and long-flag matching
case-insensitive, and strips bare `VAR=val` env-assignment prefixes
(not just `env VAR=val`), closing a bypass where `RM --recursive
--force /`, `SUDO rm --recursive --force /`, or `FOO=bar rm
--recursive --force /` slipped through uncaught since the raw-text
safety net only recognizes short -rf-style flags.

Per CodeRabbit review: tracks each wrapper's own arg-taking flags by
both short and long form (`sudo -u`/`--user`, `env -u`/`--unset`,
`xargs -n`/`--max-args`, ...) instead of a single shared set, since an
unrecognized arg-taking flag left its argument (e.g. "root", "FOO",
"1") sitting where the wrapped executable should be, so it was never
classified. Also strips the bash `command` builtin launcher, which
previously passed straight through unrecognized.

Also per CodeRabbit review: replaces the fixed, non-recursive
$(...) / backtick regex with a depth-tracking extractor, since a
regex can't match an outer $(...) whose own body contains another
$(...) (`echo $(rm --recursive --force $(printf /))` left the outer
rm unclassified); the new extractor also fails closed (denies) on an
unterminated $( or backtick instead of silently skipping it. And
`env -S`/`--split-string` is now denied outright rather than having
its argument (itself a shell command string subject to further word
splitting) silently discarded as an opaque flag value.

Also per CodeRabbit review: accepts unambiguous GNU-style abbreviated
long options for rm (`rm --rec --for /` really is `--recursive
--force` under GNU getopt_long), since `_has_flag()` previously
required an exact full-name match and let abbreviated invocations
through unclassified. Matches any prefix of the full option name
rather than only rm's actual unambiguous abbreviations - deliberately
over-inclusive, since a denylist should err toward denying too much
rather than missing a real invocation.

Per reviewer feedback (aditya-shantanu) and CodeRabbit: recognizes
`nohup`/`nice`/`stdbuf` as passthrough launchers in _strip_wrapper
(previously left as argv[0], so `nohup rm --recursive --force /`
skipped the token-aware rm check entirely), and denies outright any
command whose executable-position token contains a shell-expansion or
glob character ($, `, *, ?, [) rather than trying to evaluate it -
closing `$(printf rm) --recursive --force /` (substitution generates
the exe name), `/bin/r[m] -rf /` (glob-expanded path), and
`rm$IFS-rf$IFS/` (IFS word-splitting glues the whole invocation into
one token that never matches "rm") in one check, since correctly
resolving any of these would mean being a shell. README's scope
section updated to describe this fail-closed behavior explicitly
rather than overclaiming blanket coverage of "direct invocations".

Per CodeRabbit review: `xargs` is no longer treated as a transparent
wrapper for `rm`/`mkfs`/`dd`. Unlike sudo/env/nice/etc., xargs appends
argv tokens read from its own stdin - typically the previous stage of
a pipeline, a segment this checker can't see - to the command it
wraps, so a visible absence of `-rf`/`of=` on the xargs line (`find /
| xargs rm`) doesn't mean the executed command lacks them.
_strip_wrapper now tracks whether an xargs layer was stripped
anywhere in the chain, and any such invocation targeting rm/mkfs/dd is
denied unconditionally regardless of visible flags.

Per GitHub Copilot review: adds sudo's `-D`/`--chdir` and `-R`/`--chroot`
(both consume a separate following token) to `_SUDO_FLAGS_WITH_ARG`,
which previously let their argument leak through as the apparent
wrapped executable (`sudo -D /tmp rm --recursive --force /` reduced to
checking `/tmp` instead of `rm`). Also fixes the reverse mistake found
while auditing xargs's table for the same class of bug: `-i`/`-l`
(lowercase) are deprecated forms whose replacement string/line-count
argument is optional and must be attached to the flag itself, never a
separate token - treating them as separate-token-consuming (as before)
let `xargs -i rm -rf /` swallow "rm" as if it were `-i`'s own value.
Only `-I`/`-L`/`--replace`/`--max-lines` (which do require a separate
token) remain in that set.

Also fixes a POSIX line-continuation bypass: `command.splitlines()`
treated `rm \` followed by `-rf /` on the next physical line as two
separately benign commands, but a shell removes an unquoted
backslash-newline entirely and joins the following line onto the
current one with no inserted whitespace - so that really is one
command, `rm -rf /`. `is_denied()` now strips `\\\n` continuations
before both the raw-text check and line-splitting see the command.

Per PR review feedback (upramod, Santoshkumarpuppala): closes an
`env -S` attached-form bypass - `env -S'rm --recursive --force /'`
(no space) is a single shlex token that never equals the bare "-S"
or "--split-string" the fail-closed check compared against, so it
slipped through as an unrecognized flag. `_is_env_split_string_flag()`
now also matches the attached short (`-S...`) and long (`--split-string=...`)
forms. Also recognizes `timeout` and `exec` as wrapper launchers -
`timeout 5 rm --recursive --force /` and `exec rm --recursive --force /`
previously reached the same class of gap CodeRabbit's nohup/nice/stdbuf
finding closed, just for two launchers that weren't in that set yet;
`timeout` additionally strips its mandatory `DURATION` positional
before reaching the wrapped command. Adds regression tests pinning
_DESTRUCTIVE_SYNTAX_PATTERNS directly (fork bomb, curl|sh, wget|bash),
since nothing in the existing suite exercised that layer on its own.

Per reviewer feedback (aditya-shantanu): adds `{`/`}` to
_EXPANSION_CHARS, closing a brace-expansion bypass where `{rm,-rf,/}`
is one literal token to this checker but three words - `rm -rf /` -
once bash expands it. Also extends the expansion fail-closed check
from just the executable token to every argument token of an
rm/mkfs/dd segment, since `FLAGS=-rf; rm $FLAGS /` and
`X=ve; rm --recursi$X --force /` both pass the literal flag check
(neither token is a literal `-rf`/`--recursive`) yet execute
`rm -rf /` once the shell expands the variable.

Signed-off-by: Karim Mehalebi <kmehaleb@gmail.com>
… isolation for concurrent runs (kubernetes-sigs#1737)

* fix(rl-sdk): run-scoped teardown, fail-fast on deleted pools, run isolation

Two agent-sandbox-rl runs sharing a namespace can destroy each other.
SandboxFleet._teardown() listed claims, pools and templates by the
namespace-wide managed label (app=agent-sandbox-rl), so the first run to
finish deleted every other run's warm fleet; in one incident a single
teardown removed 159 pools in 0.4 s, 31 of them a concurrent run's. The
victim's wait_for_pool_ready() then read the DELETED watch event as
"0/N ready" and idled for the full ready_timeout (900 s). Names are
image-derived, so runs on the same image also share, resize and delete
one pool by accident.

- teardown selects by this run's id label (run_selector()), as the
  reaper and the breaker already did; the namespace-wide sweep remains
  only as the explicit reap(all_managed=True).
- wait_for_pool_ready() returns False immediately on a DELETED watch
  event or a 404 on the dropped-watch re-check.
- unwarm_image() / set_pool_replicas() refuse to delete or resize a pool
  labelled with another run's id and log which run owns it.
- FleetConfig.run_isolation: "names" bakes the run id into template and
  pool names for runs sharing a namespace; "namespace" gives each run
  <namespace>-<run id>, created on first use and deleted at teardown if
  the fleet created it (run_namespace_labels, run_namespace_setup hook);
  "none" (default) keeps today's naming. A {run_id} placeholder is
  accepted in template_name_prefix / pool_name_format in any mode.

Issue: kubernetes-sigs#1736

* rl-sdk: address review on run isolation (kubernetes-sigs#1737)

- Validate name formats with a run-id stand-in distinct from the image
  hash stand-in, so pool-{run_id} no longer passes the per-image
  uniqueness check.
- In "names" mode scope the template prefix and the pool format
  independently: each gets the run id unless it already carries the
  placeholder (or, for pools, {template}).
- _owns_pool fails closed when the pool cannot be read.
- _warm_entry checks ownership before writing; a colliding pool owned by
  another run is used read-only with adopt semantics instead of being
  resized (409 reconcile) and relabelled (ensure_template).
- wait_for_pool_ready returns False on a 404 in the fast path too; a
  watch opened without a resourceVersion would not replay that deletion.
- _ensure_run_namespaces is all-or-nothing per attempt: a create or setup
  hook failure rolls back the namespaces created in that attempt, so a
  failure before run() enters its teardown scope leaves nothing behind
  and a retry re-runs the hook. ensure_namespace treats a Terminating
  namespace as an error rather than "existing".
- Tests for each; README and CHANGELOG wording.

Issue: kubernetes-sigs#1736

* rl-sdk: self-review follow-ups on run isolation (kubernetes-sigs#1737)

A mutation pass over the new tests found one that did not test what it
claimed: the fast-path 404 test raised from the fake watch, the
dropped-watch handler swallowed that, and the re-check returned False
anyway. It now records whether the watch was opened and asserts it was
not. The rest are hardening and accuracy:

- unit test for namespace mode through the default registry (the path
  real callers take), and for the ApiException branch of the re-check
- _ensure_run_namespaces takes a dedicated lock: plan() is reachable
  from concurrent warm threads and create/rollback must not interleave
- adopt_existing with run_isolation="namespace" is rejected at config
  time (a per-run namespace holds nothing to adopt)
- ensure_namespace reads the phase with getattr instead of relying on
  an AttributeError being swallowed
- _owns_pool takes the caller's action for its log line, so a warm-path
  collision logs once instead of twice with different wording
- docstrings for _owns_pool (fail closed), wait_for_pool_ready (initial
  404) and ensure_namespace (Terminating); CHANGELOG clause for
  all-or-nothing namespace creation

Issue: kubernetes-sigs#1736

* rl-sdk: make cross-run pool writes conditional, revalidate names after run-id injection

Review round 2 on run isolation. The ownership guard was a snapshot: two
fleets in "none" mode could still race between the check and the write
(one creates the pool after the other saw none; the 409 reconcile then
resized it, ensure_template relabelled its template, and a same-named
pool created after an unwarm's 404 check could be deleted). Make each
write conditional on what was inspected instead of trusting the check:

- delete_warmpool takes the inspected pool's uid as a delete precondition
  (409 = replaced meanwhile, tolerated, pool left standing)
- create_warmpool(reconcile=True, owner_run_id=...) re-reads the pool at
  the 409, refuses to resize one labelled with another run's id, and
  patches with that object's resourceVersion (409 = changed concurrently,
  back off); returns False in both cases so _warm_entry falls back to
  read-only adopt semantics and set_pool_replicas skips
- ensure_template(owner_run_id=...) does not relabel a template that
  carries another live run's id
- _check_resolved_names re-validates the rendered template and pool
  names after the run id is injected; "names" mode adds 13 characters
  and a prefix valid at the 253-char limit no longer is
- rollback keeps the ownership record for a namespace it failed to
  delete, so a retry reuses it and ordinary teardown still removes it

Tests for each; README and CHANGELOG describe the conditional writes.

Issue: kubernetes-sigs#1736

* rl-sdk: fail on pool-name collisions, tri-state unwarm ownership, keep namespace state (kubernetes-sigs#1737)

Review round 3 found that the round-2 guards could still stall or leak:

- Warming a pool name held by another run used that pool read-only, but
  recorded it at this run's replica count. A later re-warm hit the reuse
  short-circuit and waited for the full count on a pool sized by someone
  else, which is the ready_timeout stall this PR exists to remove. Warming now
  raises a FleetError naming the owning run and pointing at
  run_isolation="names", adopt_existing=True, or the reaper. Deliberate
  sharing already has adopt_existing; a collision is not a second way in.
- The ownership pre-checks in the warm and set_pool_replicas paths were
  redundant with create_warmpool's 409-time owner check, cost an extra read on
  the reuse path, and turned a transient read error into a silently dropped
  scale change. They are gone. create_warmpool now re-inspects on a
  resourceVersion conflict (the controller writes status continuously, so a
  conflict on our own pool is normal) and on losing a re-create race, instead
  of reporting a collision or raising a raw 409.
- An unwarm that could not read the pool retired the image without releasing
  its reserved replicas. It now keeps the image and raises, like a failed
  delete, so a retry releases exactly once. A pool already gone gets no delete
  by name, which could hit a pool re-created under that name.
- Teardown dropped namespace ownership even when the delete failed, and a
  namespace kept after a failed rollback skipped run_namespace_setup on the
  next attempt. Ownership is now dropped only on a successful delete, and
  setup completion is tracked separately, so the hook re-runs until it
  succeeds once.

Issue: kubernetes-sigs#1736

* rl-sdk: guard the template side of run collisions (kubernetes-sigs#1737)

The pool guards left templates exposed. ensure_template returned False both
for "already existed" and for "another run's, not relabelled", and the warm
path discarded it. When another run's pool was gone but its template was
still there, create_warmpool succeeded with no 409, so this run built its
pool on the other run's template. Unwarm then deleted that template by name
with no ownership check or uid precondition, the same cross-run write the
pool guards stop.

- ensure_template(owner_run_id=...) raises OwnedByAnotherRunError for a
  template labelled with another run's id, including one created
  concurrently and found at the 409. The warm path turns that into the
  collision FleetError and writes nothing.
- Template deletes on unwarm and on an on-demand claim's rollback read the
  template first. Another run's template is left standing, a missing one gets
  no delete by name, and our own is deleted with its uid as a precondition.
  The on-demand rollback's pool delete gets the same ownership and uid guard.

Issue: kubernetes-sigs#1736
…bernetes-sigs#1741)

The kops-GCP benchmark presubmits intermittently die before tests run:
cluster bring-up on shared boskos projects sometimes hits a GCE
resourceNotReady stall on the API ForwardingRule, leaving control-plane
static pods still starting when the 15m validation wait expires. About a
tenth of recent runs on both CNI lanes failed this way, each wasting a
full benchmark job and a retest.

Raise the initial validation default to 25m. Successful runs are
unaffected (validation returns as soon as the cluster is ready); only the
slow-bring-up path waits longer, which is still far cheaper than a rerun.
The post-cilium-restart re-validation keeps its 5m default.

Co-authored-by: Aditya Shantanu <aditya-shantanu@users.noreply.github.com>
…ernetes-sigs#1286)

* docs: runtime-aware CI proposal for timing regression visibility

Propose adding gVisor and kata CI jobs to exercise the controller under
non-runc timing profiles. The controller is runtime-agnostic by design,
so the value is not catching runtime-specific bugs — it is regression
visibility on timing-sensitive changes (reconciler refactors, timeout
tuning, slowStartBatch adjustments) that look harmless at runc's 0.3s
cold starts but may disproportionately affect 8-12s kata cold starts.

Three steps:
- Step 1: gVisor on KIND (no infra changes, mild timing diversity)
- Step 2: kata on kOps with GCE nested virt (extreme timing diversity,
  plus the full VMM family — QEMU, Cloud Hypervisor, Firecracker —
  for free once KVM is available)
- Optional: bare-metal kata for production-grade baselines

Depends on PR kubernetes-sigs#1262 (RuntimeClass-aware test harness).

Signed-off-by: vvoronko <vvoronko@redhat.com>

* docs: address CodeRabbit and Copilot review comments

- Remove n2d from nested virt footnote (AMD does not support it)
- Clarify gVisor KIND prerequisites (runsc binaries + RuntimeClass)
- Change gVisor presubmit to always_run (controller changes are the
  primary regression signal, not just test/example changes)
- Fix broken reference link to non-existent README, point to PR kubernetes-sigs#1262

Signed-off-by: vvoronko <vvoronko@redhat.com>

* docs(kata-ci-proposal): address aditya review comments

- Add optional: true to gVisor presubmit so it doesn't block merge,
  matching the "no new requirements on contributors" promise in the doc
- Update isVMRuntime() description to reflect 300% CPU overprovisioning
  in TestRuntimeClassBurstRecovery (strict cap only in Benchmark*)
- Remove SANDBOX_SETTLE_SEC reference (removed in test implementation)

Signed-off-by: vvoronko <vvoronko@redhat.com>

---------

Signed-off-by: vvoronko <vvoronko@redhat.com>
…es-sigs#1685)

The include-file shortcode ran the Markdown through RenderString and
returned HTML, but almost every page invokes it with {{% %}}, which tells
Hugo the output is Markdown and renders it again. The second pass wrapped
blank lines inside fenced blocks in <p> tags and turned --> into an
en-dash, so every mermaid diagram that contained a blank line failed to
parse on the published site (network-policy-api-sandbox, demo-cilium-egress,
openclaw-fleet-gke), and a few other code blocks picked up stray tags.

Return the transformed Markdown instead and let Hugo render it once. The
result is marked safeHTML because the included files contain raw HTML
(the root README header) and <#anchor> link destinations (gomarkdoc
output) that html/template would otherwise escape. Switch the single
{{< >}} caller to {{% %}} so all pages take the same path.
* Document port changes required when enabling secure metrics serving

The TLS args were commented out with instructions to uncomment, but
the corresponding Service port, containerPort, and helm chart port
had no indication they also need to change from 8080 to 8443. Add
inline comments and expand the TLS args comment block to list all
required port changes.

Also add ALPN NextProtos (h2, http/1.1) to buildMetricsTLSOpts —
required for HTTP/2 negotiation and expected by compliant TLS clients.
The cluster TLS profile does not set NextProtos.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>

* docs: add end-to-end checklist for enabling secure metrics serving

The TLS flags, Service port, containerPort, NetworkPolicy, helm chart,
and certificate provisioning all need to change together when enabling
--metrics-secure-serving, but the instructions were scattered across
individual file comments with no single overview. Add a numbered
checklist to docs/configuration.md listing every manifest that must
be updated.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>

* olm: add commented-out prometheus resource to default kustomization

The ServiceMonitor in config/prometheus/ was not reachable from the
default kustomization, so downstream distributions enabling metrics
scraping had to discover and wire it up manually. Add it as a
commented-out resource with a pointer to the secure-metrics checklist
in docs/configuration.md.

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>

* router: add tls args and volumes commented out

Add comments to easily guide the user on how to enable tls

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>

* apply coderabbit comments

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>

---------

Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
…s#1721)

* fix(python-runtime): preserve literal percent escapes

Signed-off-by: 1fanwang <1fannnw@gmail.com>

* test(python-runtime): run path regressions in CI

Signed-off-by: 1fanwang <1fannnw@gmail.com>

---------

Signed-off-by: 1fanwang <1fannnw@gmail.com>
…1616)

* test-unit: include cluster-free e2e framework tests

The unit test runner excludes all packages under test/e2e, including
the framework's fake-client tests that do not require a cluster.

Include the framework package and its subpackages so these tests run
with the unit suite's race detector. Keep other e2e packages excluded.

Add a regression test for package selection, per-module execution,
and JUnit output.

Part of kubernetes-sigs#1200

* test-unit: document package selection regression test

The module docstring does not cover the test function in function-level
docstring checks. Describe the behavior verified by the regression test.
* build: enforce LF line endings via .gitattributes

On a clean Windows clone with the default core.autocrlf=true, git checks
text files out with CRLF line endings. mdtoc, which dev/tools/verify-toc
runs to validate the KEP tables of contents, does not handle CRLF: fenced
code blocks are not recognized, so comment lines inside fenced shell
examples are collected as headings, `make toc-verify` fails on a pristine
checkout, and `make toc-update` would rewrite READMEs that are correct.

Add a .gitattributes that normalizes text files to LF on checkout and
checkin (`* text=auto eol=lf`), the same setting kubernetes/kubernetes
uses, so the TOC tooling sees identical input on every platform. PNG and
WebP assets are marked binary explicitly. The tracked tree is already
entirely LF, so this introduces no renormalization churn.

Existing CRLF working trees need a re-checkout for the attribute to take
effect, for example `git rm -r --cached . && git reset --hard`.

* build: mark common image and document formats as binary

Only PNG and WebP assets exist in the tree today, so the initial
.gitattributes listed just those two. Also list GIF, JPEG, ICO and PDF
so that any such file added later is exempt from line-ending
normalization from the start, rather than relying on git's text/binary
heuristic to get it right.
try:
daemon_bind(pod, employee, action="unbind", retries=3)
except Exception as e: # noqa: BLE001 - already-unmounted is fine
print(f"unbind {employee}: {e}", flush=True)
except ValueError:
return JSONResponse(status_code=403, content={"message": "Access denied"})

if os.path.isfile(full_path):
return FileResponse(path=full_path, media_type='application/octet-stream', filename=decoded_path)
return FileResponse(path=full_path, media_type='application/octet-stream', filename=encoded_file_path)
# a supplied [], false or "" must 400, not silently become {}.
config = validate_config(body["config"]) if "config" in body else {}
except ValueError as e:
return jsonify(error=str(e)), 400
@ngeorger
ngeorger merged commit 2aef12e into main Sep 24, 2026
4 of 5 checks passed
@ngeorger
ngeorger deleted the upstream branch September 24, 2026 12:38
@ngeorger
ngeorger restored the upstream branch September 24, 2026 12:38
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.