Skip to content

chore(deps): integrate four non-trivial Dependabot bumps (ACP SDK, Node 26, sandbox, Starlight) - #1842

Open
simple-agent-manager[bot] wants to merge 13 commits into
mainfrom
sam/bring-four-non-trivial-d0kabv
Open

chore(deps): integrate four non-trivial Dependabot bumps (ACP SDK, Node 26, sandbox, Starlight)#1842
simple-agent-manager[bot] wants to merge 13 commits into
mainfrom
sam/bring-four-non-trivial-d0kabv

Conversation

@simple-agent-manager

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

Copy link
Copy Markdown
Contributor

Summary

Integrates the four non-trivial Dependabot PRs as one reviewable, verified unit:
#1801 (@agentclientprotocol/sdk 0.25.0 → 1.3.0), #1790 (library/node 22 → 26-bookworm-slim),
#1792 (cloudflare/sandbox 0.12.1 → 0.12.5), #1796 (@astrojs/starlight 0.40.0 → 0.41.7).

All four head commits are merged with --no-ff, so their SHAs stay reachable and GitHub will
auto-close each PR when this lands via a merge commit.

Each Dependabot commit was incomplete. This PR finishes them:

#1801 — removed the SDK rather than bumping it

An exhaustive sweep (.ts .tsx .js .mjs .cjs .json .go .py .sh .astro .vue, every config file,
tsconfig paths/types, declare module, /// <reference types>, barrel re-exports, every
non-node_modules package.json, and packages/vm-agent/go.mod) found zero importers of
@agentclientprotocol/sdk. packages/acp-client hand-rolls its ACP payload shapes in
src/hooks/useAcpMessagePayloads.ts and its VM-agent control messages in src/transport/types.ts;
src/transport/websocket.ts deliberately types the ACP payload as unknown and forwards it. The
canonical wire contract lives in the Go VM agent, which has no dependency on this npm package.

The dep was added by spec-007 (specs/007-multi-agent-acp/tasks.md T002/T019/T020) intending to use
ClientSideConnection over a custom WebSocket transport; that intent was never implemented.

Upstream, the real API break was 0.27.0 (fluent agent()/client() rewrite; legacy
ClientSideConnection/AgentSideConnection deprecated but not removed) — 1.0.0 was a stabilization
tag, and ACP v2 in 1.3.0 is opt-in behind the ./experimental/v2 subpath. So the bump is
behaviourally inert because nothing imports it, not because the API is compatible.

Decision: carrying a 1.3.0 dependency whose deprecated ClientSideConnection/ndJsonStream
surface implies an integration that does not exist is worse than carrying none (CLAUDE.md, "No dead
code"). Removed, and corrected packages/acp-client/AGENTS.md, which claimed the SDK "defines the
ACP wire protocol types" — it defines nothing in this repo.

#1790 — Node 26 taken; stale review comment fixed

No globally-installed agent CLI in apps/api/Dockerfile.vm-agent-container declares an
engines.node upper bound (claude-agent-acp >=22, claude-code >=22.0.0, codex >=16,
gemini-cli >=20; codex-acp, opencode-ai, @ampcode/cli declare none), so npm install -g
cannot fail EBADENGINE. The pinned digest resolves to NODE_VERSION=26.7.0 and bookworm is still
published for 26. container-entrypoints/patch-acp-amp.py is pure Python under uv-managed CPython
3.12, and container-entrypoints/vm-agent-bootstrap.sh is POSIX sh that never invokes node. The
only native module (@lydell/node-pty-linux-x64, via gemini-cli) is N-API, so the
NODE_MODULE_VERSION 127 → 147 jump is ABI-safe.

Dependabot rewrote only the FROM digest, leaving line 1 asserting node:22-bookworm-slim. Fixed.

⚠️ Decision point for the merge approver — Node 26 is Current, not LTS.
Node 26 reaches LTS on 2026-10-28; Node 24 is Active LTS today; Node 22 is supported until
2027-04-30, so nothing forces this bump now. Project policy says "prefer LTS". I verified 26 as far as
staging allows (see Staging Verification) rather than deciding this unilaterally, because metadata cannot rule out the one
real risk: Node 26 ships undici 8 (major), changing global fetch for seven HTTP-heavy agent
CLIs. Switching to 24-bookworm-slim is a one-line change if you prefer the LTS line.

#1792 — the image moved without its SDK

apps/api/Dockerfile.sandbox states the invariant in its own comment: the reviewed tag "MUST match
the @cloudflare/sandbox npm package version". Dependabot bumped only the digest, leaving
apps/api/package.json at ^0.12.1 and the comment at 0.12.1. The container-server binary in the
image and the npm client speak the same versioned HTTP API (getSandbox()/exec()/readFile()), so
drift is a runtime protocol mismatch no type check or unit test can observe.

Pinned @cloudflare/sandbox to exactly 0.12.5 — exact, not ^, because a range lets the client
drift from the digest-pinned image on any unrelated pnpm install.

#1796 — kept; root cause was a missing Astro major

@astrojs/starlight@0.41.7 declares peer astro@^7.0.2; apps/www pinned astro@6.4.8. The newer
peer graph resolves @astrojs/mdx@7.0.5, which imports chunkToString from
astro/runtime/server/index.js — a symbol Astro 6 does not export. Because Type Check / Test /
Workspace Quality Surfaces / Durable Object Workers all depend on @simple-agent-manager/www#build
in turbo, that one root cause produced all five red checks.

Upgraded astro 6.4.8 → 7.2.2 (pinned in exactly one place, apps/www/package.json). Astro 7's
rolldown pipeline then resolves dynamic imports inside processed <script> blocks, so the mermaid
lazy-loader in apps/www/src/layouts/BlogPost.astro needed is:inline
/scripts/blog-mermaid.js is an esbuild artifact emitted into public/ at build time, i.e. a runtime
URL rather than a resolvable module. Build is clean: 181 pages + Pagefind index + sitemap.

Lockfile

The two npm PRs' pnpm-lock.yaml text-merge produced a wrong @types/node resolution combo;
pnpm install corrected it.

Process fix

scripts/quality/dependency-governance.test.ts asserted Docker digest pinning only, so it passed
straight through both stale-comment bugs and said nothing about image↔SDK drift. Two tests added:

  1. every Dockerfile's reviewed-source-tag comment must match its FROM tag;
  2. @cloudflare/sandbox must be an exact pin equal to the Dockerfile.sandbox image tag.

Both verified discriminating — each was run red against the exact pre-fix state Dependabot
produced, then restored.

Validation

  • pnpm lint — 13/13 packages
  • pnpm typecheck — 19/19 tasks
  • pnpm test — 21/21 tasks (apps/web alone: 260 files / 3126 tests)
  • Additional validation run (if applicable) — pnpm build 9/9; pnpm format:check ratchet;
    pnpm quality:type-boundaries (0 blocking); pnpm quality:scripts:test 38 files / 473 tests;
    and quality:dependency-governance, workspace-test-surfaces, direct-dependency-evidence,
    stale-artifacts, file-sizes, source-contract-tests, agent-install-manifest,
    wrangler-bindings, repo-visibility all pass
  • If this PR changes candidate selection for a sweep/cron/alarm loop — N/A: no sweep, cron, or
    alarm candidate selection is touched. The diff is dependency versions, one Astro template
    directive, one docs correction, and two governance tests.

Staging Verification (REQUIRED for all code changes — merge-blocking)

Staging Verification Evidence

Deploy provenance (checked before trusting any result). Deploy headSha equals this
branch's HEAD 909ba28d7d0b22e8acc8482aeebfb3ed23334561. The deploy log shows the container
images were genuinely rebuilt from node:26-bookworm-slim@sha256:cd565714d4da and
cloudflare/sandbox:0.12.5 — 4 image pushes, zero EBADENGINE / npm errors. I confirmed
from deploy-reusable.yml that wrangler deploy really does rebuild the [[containers]]
images and that staging sets skip_agent: false; without that, an Instant session would have
run the OLD image and produced a false green.

#1801 — ACP agent session: VERIFIED end-to-end on staging. Real conversation on a VM
runtime profile, session 7517db17-bc4d-4bff-b11c-0d4ef57428d2:

RESULT toolCalls=2 tools=[Read] agentMsgs=3 answered=true rendered=true errors=0 elapsed=240s
[assistant] "...SAMVERIFY26=hono"

Prompt → response → real Read tool call → correct answer, and rendered=true confirms
the answer painted in the browser through packages/acp-client with the SDK removed, with
zero console errors. Tool-call evidence comes from the durable API transcript's
toolMetadata, not from page text — whole-page innerText is unusable here because the app
chrome contains a "Search…Ctrl+K" button that false-positives naive matching.

Regression sweep: PASS. /dashboard, /projects, /settings, /nodes at 1280×800 and
375×667 — all render real content with correct headings, no document-level overflow, zero
console errors
at both viewports. One 5px clipped overshoot on mobile /settings
(MAIN.sam-main-content 380>375); this PR contains zero apps/web/ source changes, so it
cannot originate here — filed as SAM idea 01M07E845VMG8A1MZZCK98G3TZ.

Cleanup done. Node 01M07EHK49165026PHT7DHEQ12 and workspace 01M07EP268FC74B9X9SGH9RVDQ
both deleted; re-queried D1 afterwards and staging is back to zero non-destroyed nodes and
zero live workspaces
. The Hetzner 10-server cap is shared with production.

What is NOT verified, and why

#1790 / #1792 — the cf-container agent turn could not run on staging. Instant sessions are
disabled there: CF_CONTAINER_ENABLED='false' on the staging GitHub Environment (set
2026-08-11). resolveWorkspaceRuntime (apps/api/src/services/workspace-runtime.ts:61) gates
on (CF_CONTAINER_ENABLED ?? SANDBOX_ENABLED) !== 'true', so chat-start
(apps/api/src/routes/chat-start.ts:150) returns 409 "Selected profile resolves to VM
runtime". SANDBOX_ENABLED='true' cannot rescue it — ?? only falls back on null/undefined.
I confirmed the Instant profile really was selected (chip aria-pressed=true; profiles API
reports runtime=cf-container), so this is the server refusing, not a mis-click. This is
pre-existing and unrelated to this PR; enabling it means reversing a deliberate decision on
shared staging, which is an infrastructure call for the merge approver, not mine. It also
contradicts the project policy that CF_CONTAINER_ENABLED should default true.

Substitute evidence, gathered locally with Docker rather than skipped:

  • Dockerfile.vm-agent-container builds on Node 26 — exit 0, zero EBADENGINE. The pinned
    digest resolves to node v26.7.0 / npm 11.19.0.

  • Every agent binary executes in that image: claude 2.1.207, claude-agent-acp 0.58.1,
    codex 0.144.6, codex-acp 1.1.2, gemini 0.50.0, opencode 1.17.18, amp,
    vibe/vibe-acp 2.19.1, acp-amp, gh 2.97.0 — names cross-checked against
    packages/shared/src/agent-install-manifest.json.

  • Dockerfile.sandbox builds; the container server self-reports "serviceVersion":"0.12.5",
    matching the exact-pinned npm client. The image↔SDK invariant is confirmed by observation,
    not only by the new test.

  • undici 8 fetch exercised directly in the pinned Node 26 image (this was the single
    residual risk metadata could not rule out — Node 26 ships undici 8, changing global fetch
    for seven HTTP-heavy agent CLIs):

    node v26.7.0
    fetch https://registry.npmjs.org/-/ping     -> 200 ok=true
    fetch https://api.github.com/               -> 200 ok=true
    fetch https://api.anthropic.com/v1/models   -> 401 ok=false
    body read ok, bytes= 2
    

    DNS, TLS, request and response parsing, and streaming body reads all work. The 401 from
    Anthropic is the informative one: it is an authentication rejection, not a transport failure,
    so the complete request/response cycle to the exact API the agents call succeeded.

What remains genuinely unproven is a live agent turn through the deployed container — i.e.
the full agent harness running under SAM's own orchestration on Node 26, rather than the image
and its runtime being exercised piece by piece as above.

#1796 — the docs site is not staging-deployable by design. apps/www is not part of
deploy-staging.yml; it has its own deploy-www.yml, triggered by push to main touching
apps/www/** and running with environment: production. Staging's www accordingly still
serves the old build (<meta generator> reports Astro v6.4.8 / Starlight v0.40.0), which is
expected rather than a defect. I did not dispatch that workflow from this branch, because
it would publish unreviewed changes straight to the live public site.

⚠️ Merge-time consequence: merging this PR will fire a production marketing-site
deploy on Astro 7
, since it touches apps/www/**.

Docs verification was therefore done against the real Astro 7 build output, at 375 and 1280:
181 pages build; /, /docs/overview/, /docs/quickstart/, /blog/,
/docs/guides/instant-sessions/, /docs/reference/configuration/ all serve 200 with correct
<title>/<h1> and 3.6k–36k chars of real text; pagefind.js serves 200 (the Starlight
feature most likely to break on a major); zero document-level overflow. The two clipped
elements on mobile / (SECTION.hero 688>375, DIV.node-grid 424>375) are identical on
origin/main under Astro 6
— I built main in a throwaway worktree to check rather than
assume. Only the scoped-CSS hash differs, as expected when Astro regenerates scopes.

UI Compliance Checklist (Required for UI changes)

  • Mobile-first layout verified — N/A for rule 17: it scopes the mandatory Playwright visual audit
    to apps/web/, packages/ui/, packages/terminal/, none of which this PR touches. The only
    template change is is:inline on a <script> in apps/www, which changes bundling, not
    layout. Docs/blog rendering verified on staging instead (see evidence above).
  • Accessibility checks completed — N/A, same reason; no markup, ARIA, or focus behaviour changed.
  • Shared UI components used or exception documented — N/A, no components added or changed.
  • Playwright visual audit run locally — N/A per rule 17 scope, as above.

End-to-End Verification (Required for multi-component changes)

  • Data flow traced from user input to final outcome with code path citations
  • Capability test exercises the complete happy path across system boundaries
  • All spec/doc assumptions about existing behavior verified against code (not just "read the code")
  • If any gap exists between automated test coverage and full E2E, manual verification steps documented below

Data Flow Trace

The load-bearing path is the Instant (cf-container) agent session, because it is the one thing that
exercises both bumped images:

  1. User sends a chat message in a project → apps/webPOST /api/projects/:id/sessions/.../messages
  2. Control plane routes an Instant session to the container runtime →
    apps/api/src/services/sandbox.ts (await import('@cloudflare/sandbox'), getSandbox) — this
    is the npm client whose version chore(deps): bump cloudflare/sandbox from 0.12.1 to 0.12.5 in /apps/api #1792 must keep aligned with the image
  3. SandboxDO / VmAgentContainer container bindings in apps/api/wrangler.toml boot the images
    built from apps/api/Dockerfile.sandbox and apps/api/Dockerfile.vm-agent-containerthe two
    images bumped by chore(deps): bump cloudflare/sandbox from 0.12.1 to 0.12.5 in /apps/api #1792 and chore(deps): bump library/node from 22-bookworm-slim to 26-bookworm-slim in /apps/api #1790
  4. container-entrypoints/vm-agent-bootstrap.sh execs the baked Go vm-agent binary
  5. vm-agent spawns the agent adapter installed by npm install -g in that image — running on the
    Node 26 runtime from chore(deps): bump library/node from 22-bookworm-slim to 26-bookworm-slim in /apps/api #1790
  6. Adapter speaks ACP over stdio to vm-agent; vm-agent relays over WebSocket to
    packages/acp-client/src/transport/websocket.ts, which types the payload as unknown and hands it
    to src/hooks/useAcpMessagePayloads.tsthe hand-rolled types that prove chore(deps): bump @agentclientprotocol/sdk from 0.25.0 to 1.3.0 #1801's SDK is dead
  7. Rendered by packages/acp-client components in the project chat

Steps 2–6 cannot be proven by any unit test. Steps 6–7 (ACP over the wire → acp-client rendering)
are verified by the staging ACP session above. Steps 3–5 through the deployed container remain
unverified because Instant is disabled on staging; see "What is NOT verified".

Untested Gaps

The Docker images are built in the deploy pipeline, not in CI or locally, so no automated test can
observe Node 26 actually executing an agent CLI. That gap is only partially closed: the ACP half is covered by the staging session above, and the
image half by the local Docker builds. The live-agent-turn-through-the-deployed-container gap is
stated openly in "What is NOT verified" rather than papered over.

Post-Mortem (Required for bug fix PRs)

What broke

Two Dependabot bumps landed a Dockerfile in a self-contradictory state: the FROM line pointed at a
new image while the "reviewed source tag" comment beside it still named the old one. In #1792 that
was worse than cosmetic — the comment asserts an invariant ("MUST match the @cloudflare/sandbox npm
package version") that the commit itself broke, leaving a digest-pinned 0.12.5 container server
paired with a ^0.12.1 npm client.

Root cause

Dependabot rewrites only the machine-readable FROM digest. It has no concept of the human-readable
comment that records what a human actually reviewed, and it opens the image bump and the npm-package
bump as two independent PRs with no link between them.

Class of bug

An invariant asserted in a comment but enforced nowhere. Prose that states "X MUST match Y" is
documentation, not a guard; it degrades silently the moment an automated tool touches one side. The
adjacent class is a paired-artifact bump where the two halves live in different files and are updated
by independent processes.

Why it wasn't caught

scripts/quality/dependency-governance.test.ts already had a Docker test, which made the area look
covered. It asserted digest pinning only — a property both bumps satisfied — so it passed green
through both defects. A test that cannot observe the failure it is adjacent to reads as coverage
while providing none.

Process fix included in this PR

scripts/quality/dependency-governance.test.ts — two new tests, both verified to fail on the exact
pre-fix state:

  • "keeps each Dockerfile reviewed-source-tag comment in sync with its FROM tag" — promotes the
    comment from prose to an enforced invariant, for every Dockerfile, not just the two here.
  • "pins @cloudflare/sandbox to exactly the cloudflare/sandbox image tag" — enforces the
    cross-file invariant the comment claimed, and additionally requires an exact pin so a semver range
    cannot reintroduce drift on an unrelated install.

Post-mortem file

tasks/active/2026-08-17-integrate-four-nontrivial-dependabot-prs.md (section "Process gap that let
two of these ship half-done").

Specialist Review Evidence (Required for agent-authored PRs)

  • All local reviewers completed and findings addressed before merge
  • If any reviewer did NOT complete: needs-human-review label added and merge deferred to human
Reviewer Status Outcome
task-completion-validator PASS Independently re-verified all five challenged claims (zero SDK importers; astro pinned in one place; both governance tests discriminating; one root cause behind all five red checks on #1796; checklist↔diff correspondence with no scope creep). No CRITICAL/HIGH. Two LOW notes, both superseded by 909ba28d7.
test-engineer ADDRESSED 1 HIGH, 1 MEDIUM, 2 LOW — all fixed in 909ba28d7. HIGH: the comment-sync helper used .exec() (first match only) plus a file-wide toContain, so on a multi-stage Dockerfile a stale stage-2 comment was invisible and masked by stage 1 matching; replaced with nearest-preceding-comment pairing. MEDIUM: two heredoc Dockerfiles in .github/workflows/devcontainer-cache-experiments.yml use the same convention but were outside the path walk; now covered. LOW: position-agnostic regex (fixed by the pairing) and a misleading prerelease error message. Also independently re-verified my three original discrimination claims.
cloudflare-specialist ADDRESSED No CRITICAL. MEDIUM: the sandbox pin check was hardcoded to apps/api/package.json, and tasks/active/2026-07-23-codex-guided-setup-terminal.md already plans a second @cloudflare/sandbox declaration in apps/web — now walks every workspace manifest (909ba28d7). MEDIUM: Node 26 is Current, not LTS — surfaced above as an explicit decision for the merge approver rather than silently resolved. MEDIUM: Dependabot groups: cannot tie the image to the npm SDK because groups are per-ecosystem; documented in CLAUDE.md that the governance test is the tripwire instead. Verified both digests against Docker Hub manifest lists, peer deps clean, and confirmed no new DO migration is needed.
doc-sync-validator ADDRESSED Confirmed the AGENTS.md rewrite is accurate line-by-line against source and that leaving specs/006-* / specs/007-* untouched is correct per rule 01. Found no stale version claim in any doc. Both recommendations taken in 909ba28d7: a CLAUDE.md Recent Changes entry, and apps/www/AGENTS.md gotchas for the Astro 7 rolldown dynamic-import trap and the Starlight↔Astro major coupling.

Not run, with reason: go-specialist (no Go source changed), ui-ux-specialist (rule 17 scopes to
apps/web/, packages/ui/, packages/terminal/ — untouched), security-auditor (no auth,
credential, or token code), env-validator (no environment variables added, removed, or renamed),
constitution-validator (no business logic, URLs, timeouts, or limits introduced).

Exceptions (If any)

  • Scope: Do not merge. Raphaël explicitly withheld merge authorization for this batch.
  • Rationale: two major version jumps on the agent protocol package and the Instant container base
    image; the blast radius is production agent sessions. He asked for this to be made "provably good
    to go, integrated, tested in staging" and will give the merge go-ahead himself. There is also an
    open decision for him on Node 26 (Current) vs Node 24 (Active LTS) — see chore(deps): bump library/node from 22-bookworm-slim to 26-bookworm-slim in /apps/api #1790 above.
  • Expiration: on explicit merge approval from Raphaël.

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

Consulted the official documentation and primary registries for every version boundary before
changing any code (Context7 was not required — these are release notes and registry metadata, read
from source):

Codebase Impact Analysis

  • apps/api/Dockerfile.vm-agent-container — Node base image 22 → 26; backs the VmAgentContainer
    container binding in apps/api/wrangler.toml.
  • apps/api/Dockerfile.sandboxcloudflare/sandbox base image 0.12.1 → 0.12.5; backs SandboxDO.
  • apps/api/package.json@cloudflare/sandbox ^0.12.1 → exact 0.12.5; consumed by
    apps/api/src/services/sandbox.ts, apps/api/src/env.ts, and re-exported as SandboxDO from
    apps/api/src/index.ts. Aliased in apps/api/vitest.workers.config.ts.
  • packages/acp-client/package.json — removed the unused @agentclientprotocol/sdk; consumed
    transitively by apps/web.
  • packages/acp-client/AGENTS.md — corrected a false claim about where ACP types are defined.
  • apps/www/package.json, apps/www/src/layouts/BlogPost.astro — Astro 6 → 7 and the is:inline
    directive required by Astro 7's rolldown pipeline.
  • scripts/quality/dependency-governance.test.ts — two new governance tests (the process fix).
  • pnpm-lock.yaml — regenerated; also repaired a bad @types/node resolution from the text-merge.
  • tasks/active/2026-08-17-integrate-four-nontrivial-dependabot-prs.md — task record.
  • Deliberately NOT touched: specs/006-multi-agent-support/ and specs/007-multi-agent-acp/ still
    reference @agentclientprotocol/sdk. Per .claude/rules/01-doc-sync.md, spec files are historical
    records and must not be edited outside their own active spec context.

Documentation & Specs

  • packages/acp-client/AGENTS.md — rewrote the "Gotchas" claim that
    @agentclientprotocol/sdk "defines the ACP wire protocol types". It defines nothing here; the
    replacement cites the real locations (src/hooks/useAcpMessagePayloads.ts,
    src/transport/types.ts, src/transport/websocket.ts) per the "cite code paths in behavioral
    docs" requirement.
  • apps/api/Dockerfile.vm-agent-container and apps/api/Dockerfile.sandbox — reviewed-source-tag
    comments brought back in sync with their FROM lines, and now enforced by test rather than trust.
  • tasks/active/2026-08-17-integrate-four-nontrivial-dependabot-prs.md — full research record,
    checklist, and acceptance criteria.
  • No apps/www/src/content/docs/docs/ change needed: no public doc states an Astro, Starlight, Node,
    or sandbox version, and no user-facing behaviour changed.

Constitution & Risk Check

  • Principle XI (No Hardcoded Values) — no URLs, timeouts, or limits introduced. The version
    literals added are dependency pins and test assertions about those pins, which is configuration
    data, not business-logic configuration.
  • No dead code (CLAUDE.md) — the primary driver for removing @agentclientprotocol/sdk instead
    of bumping an unused dependency across a major.
  • .claude/rules/01-doc-sync.md — docs corrected in the same commit as the code; spec files left
    untouched per the spec-edit-scope rule.
  • .claude/rules/02-quality-gates.md — bug-fix PRs require a process fix; two governance tests
    added and both proven discriminating against the pre-fix state.
  • .claude/rules/13-staging-verification.md / 30-never-ship-broken-features.md — the Docker
    images are built only in the deploy pipeline, so a real Instant session completing a real agent
    turn on staging is the only admissible evidence for chore(deps): bump library/node from 22-bookworm-slim to 26-bookworm-slim in /apps/api #1790 and chore(deps): bump cloudflare/sandbox from 0.12.1 to 0.12.5 in /apps/api #1792. See the staging section above.
  • Policy "prefer LTS; image tags must move together with their SDK/package versions" — the second
    half is now enforced by test. The first half is the open Node 24-vs-26 decision flagged for the
    merge approver rather than silently resolved.

Key risks/tradeoffs. The residual risk is Node 26's undici 8 major changing global fetch for
the bundled agent CLIs; package metadata cannot detect it (every constraint is a lower bound, so the
image builds green regardless), which is why verification is empirical. Removing the ACP SDK is the
lowest-risk action available for #1801 precisely because nothing imports it — the change cannot alter
runtime behaviour. The Astro 7 upgrade is the largest real code change here, but it is confined to
apps/www, a static site with no runtime coupling to the control plane.

dependabot Bot and others added 11 commits August 10, 2026 19:58
Bumps library/node from 22-bookworm-slim to 26-bookworm-slim.

---
updated-dependencies:
- dependency-name: library/node
  dependency-version: 26-bookworm-slim
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps cloudflare/sandbox from 0.12.1 to 0.12.5.

---
updated-dependencies:
- dependency-name: cloudflare/sandbox
  dependency-version: 0.12.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@agentclientprotocol/sdk](https://github.com/agentclientprotocol/typescript-sdk) from 0.25.0 to 1.3.0.
- [Release notes](https://github.com/agentclientprotocol/typescript-sdk/releases)
- [Changelog](https://github.com/agentclientprotocol/typescript-sdk/blob/main/CHANGELOG.md)
- [Commits](agentclientprotocol/typescript-sdk@v0.25.0...v1.3.0)

---
updated-dependencies:
- dependency-name: "@agentclientprotocol/sdk"
  dependency-version: 1.3.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@astrojs/starlight](https://github.com/withastro/starlight/tree/HEAD/packages/starlight) from 0.40.0 to 0.41.7.
- [Release notes](https://github.com/withastro/starlight/releases)
- [Changelog](https://github.com/withastro/starlight/blob/main/packages/starlight/CHANGELOG.md)
- [Commits](https://github.com/withastro/starlight/commits/@astrojs/starlight@0.41.7/packages/starlight)

---
updated-dependencies:
- dependency-name: "@astrojs/starlight"
  dependency-version: 0.41.7
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Brings #1801, #1790, #1792, #1796 in as one reviewable unit and fixes what
each Dependabot commit left half-done.

#1801 @agentclientprotocol/sdk 0.25.0 -> 1.3.0: REMOVED instead of bumped.
An exhaustive sweep (all file types, tsconfig paths/types, vite/vitest/eslint
configs, every workspace package.json, Go modules) found zero importers.
packages/acp-client hand-rolls its ACP payload types in
src/hooks/useAcpMessagePayloads.ts and src/transport/types.ts, and
transport/websocket.ts deliberately types the ACP payload as `unknown`. The
canonical wire contract lives in the Go VM agent. Carrying a 1.3.0 dep whose
deprecated ClientSideConnection/ndJsonStream surface implies an integration
that does not exist is worse than carrying none. AGENTS.md claimed the SDK
"defines the ACP wire protocol types" — corrected to describe reality.

#1790 node 22 -> 26-bookworm-slim: taken, comment desync fixed. None of the
seven globally-installed agent CLIs declares an engines.node upper bound, so
no EBADENGINE is possible; the digest resolves to node 26.7.0 and bookworm is
still published for 26.

#1792 cloudflare/sandbox 0.12.1 -> 0.12.5: Dependabot moved only the image.
The npm client stayed at ^0.12.1 while the Dockerfile comment still asserted
they MUST match. Pinned @cloudflare/sandbox to exactly 0.12.5 — an exact pin,
because a range lets the client drift from the digest-pinned image on any
unrelated install.

#1796 @astrojs/starlight 0.40.0 -> 0.41.7: root cause of all five red checks
was peer astro@^7.0.2 vs pinned astro@6.4.8. The newer peer graph pulls
@astrojs/mdx@7.0.5, which imports `chunkToString` from
astro/runtime/server/index.js — absent in Astro 6. Upgraded astro to 7.2.2
(pinned in exactly one place, apps/www). Astro 7's rolldown pipeline then
resolves dynamic imports inside processed <script> blocks, so the mermaid
lazy-loader in BlogPost.astro needed is:inline; /scripts/blog-mermaid.js is
an esbuild output emitted to public/ at build time, i.e. a runtime URL rather
than a resolvable module. Build is clean: 181 pages + Pagefind + sitemap.

Also corrects a bad @types/node resolution combo the lockfile text-merge
produced across the two npm PRs.

Process fix: the existing Docker governance test asserted digest pinning only,
so it passed straight through BOTH stale-comment bugs. Adds two tests to
scripts/quality/dependency-governance.test.ts — reviewed-source-tag comments
must match their FROM tag, and @cloudflare/sandbox must be an exact pin equal
to the image tag. Both verified discriminating: each goes red on the exact
pre-fix state Dependabot produced.
Addresses findings from the local test-engineer and cloudflare-specialist
reviews of the first pass.

HIGH (test-engineer): reviewedSourceTag() used .exec() so it captured only the
FIRST reviewed-source-tag comment in a file, and the assertion then did a
file-wide `fromRefs.toContain(declared)`. On a multi-stage Dockerfile a stale
comment on stage 2 was invisible, and worse, stage 1 still matching made the
whole assertion pass. Replaced with reviewedSourcePairs(), which pairs every
FROM with its NEAREST PRECEDING comment. Verified discriminating against a
synthetic two-stage file: the old file-wide check passes the drift, the new one
catches it at the exact line.

MEDIUM (test-engineer): .github/workflows/devcontainer-cache-experiments.yml
embeds two heredoc Dockerfiles using the same reviewed-source-tag convention,
but walk() only matches files literally named Dockerfile*, so they were never
checked. reviewedSourcePairs() now operates on text rather than paths and the
test feeds it workflow files too. Verified discriminating by drifting the
heredoc comment. Inside workflows only stanzas that opted into the convention
are asserted, since workflow FROM lines otherwise legitimately have no comment.

MEDIUM (cloudflare-specialist): the sandbox pin check hardcoded
apps/api/package.json as the only place to look. tasks/active/2026-07-23-codex-
guided-setup-terminal.md already plans a second @cloudflare/sandbox declaration
in apps/web for the /xterm client, which would have reintroduced exactly the
drift this guard exists to prevent. Now walks every workspace manifest and
checks dependencies/devDependencies/optionalDependencies. Verified
discriminating by adding a caret range in apps/web.

LOW (test-engineer): a prerelease image tag failed with "must FROM
cloudflare/sandbox:<tag>", misreporting a version-format rejection as a missing
FROM. Split into a defined-check and a format-check with an explanatory message.

Also added a vacuity guard: the comment-sync test asserts it actually inspected
at least five stanzas, so a future walk()/parser regression cannot make it pass
by finding nothing.

Docs (doc-sync-validator): CLAUDE.md gets a Recent Changes entry — the SDK
removal and the two new enforced invariants are the kind of institutional
knowledge that section exists to preserve. apps/www/AGENTS.md gets the Astro 7
rolldown dynamic-import trap and the Starlight/Astro major-coupling rule so the
next agent does not rediscover them through a failed build.
@codspeed-hq

codspeed-hq Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing sam/bring-four-non-trivial-d0kabv (c1784fd) with main (1b89bf5)

Open in CodSpeed

… blocker

The ACP session verified end-to-end on staging (prompt -> Read tool call ->
correct answer, rendered in-browser, zero console errors), and the regression
sweep passed at both viewports.

The cf-container/Instant turn could NOT run: staging has
CF_CONTAINER_ENABLED='false' on its GitHub Environment (set 2026-08-11), so
resolveWorkspaceRuntime forces VM and chat-start 409s. That is pre-existing and
unrelated to this branch. Rather than skip the check, both images were built and
executed locally in Docker; what remains unproven is a live agent turn through
the deployed container. Recorded as a gap instead of rationalised as a pass.

Also records that apps/www is not staging-deployable -- deploy-www.yml runs with
environment: production on push to main -- so merging this PR will deploy the
marketing site on Astro 7.
…ivial-d0kabv

# Conflicts:
#	packages/acp-client/package.json
@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