Repository navigation
Conversation
Groundwork for native image builds; no command builds images yet and native up still refuses build services. - provider-pins.json pins buildx 0.34.1 (darwin-arm64, Developer ID signed) by SHA-256. `runtime prepare-builder --archive <file>` checks the pin before creating any state, copies the file into private candidate state, rehashes the owned copy, verifies its code signature and records a tree digest. An existing tree is re-verified and reused; an interrupted preparation is retained and refused. `runtime probe` reports `builder_prepared` and refuses a changed tree. - provider/build_scan.rs is a pure scanner that reports the images a build of the selected target can pull (FROM, COPY --from, RUN --mount from=, ONBUILD triggers of internal stages). It follows the Dockerfile frontend embedded in the pinned engine: directives, escape token, continuations, heredoc bodies, global ARG substitution with literal build-argument overrides, stage names and indexes, target reachability. It refuses what it cannot resolve exactly (syntax directives, variable modifiers, quotes, uncertain platform arguments, non-arm64 platforms, stage/image name collisions, unknown instructions and flags, non-Docker-Hub references, size and count bounds) and never echoes Dockerfile text or values. Refs HACK-1270 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dbcefdc01b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
A global `ARG BUILDPLATFORM=...` or `ARG TARGETPLATFORM=...` default replaces the frontend's platform value, and the frontend expands `--platform` against the global arguments. The scanner accepted `--platform=$BUILDPLATFORM` by spelling alone, so such a stage could select another platform. The spelling is now accepted only while no global default overrides the argument; an overridden one must expand to linux/arm64 like any other value. A bare global ARG still keeps the frontend's value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c88d84dfa1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Global ARG defaults expand eagerly, so repeating `ARG A=$A$A` doubled the value each time and a few hundred bytes of Dockerfile could exhaust memory. Expansion now checks a 4 KiB cap before each append, and all held global values share a 256 KiB budget. A default past either cap is unresolved and refuses only when a reference uses it, so an oversized platform override still refuses. ARG names that are not plain identifiers are refused. The frontend would unquote, unescape or expand such a name, so a literal compare could miss an override of BUILDPLATFORM or TARGETPLATFORM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78a22c2b2c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
BuildKit links a later `FROM scratch` to an earlier stage of that name instead of the empty image. The scanner treated it as empty, so it missed that stage's image and skipped its platform check. A stage alias of `scratch` (in any case) is now refused; plain `FROM scratch` is still the empty image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 62f6112b37
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
BuildKit's shell lexer keeps tabs, carriage returns and spaces after an unquoted `<<` in the same word, so `RUN true << CMD` starts a heredoc. The scanner split `<<` from the delimiter, missed the heredoc, and read its body as instructions, so a body line like `FROM scratch` could hide the real stage's image. The heredoc word lexer now absorbs that whitespace the same way. `<<- CMD` is still two words and no heredoc, as in BuildKit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
The engine fetches ADD URLs and git refs from the guest's own network namespace, so they would bypass the build network's isolation. The scanner now refuses any ADD source that BuildKit could treat as remote: after dropping quotes and escapes, a source with `://`, an scp-style `user@host:` ref, or a `$` that could expand to either. This covers shell and JSON forms, every source of a multi-source ADD, ONBUILD triggers and all flags. `--checksum` and `--keep-git-dir` apply only to remote sources and are refused outright. Local sources, local archives, heredocs and COPY are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Security fix in 1973e92: The engine fetches
Test: @codex review 🤖 Addressed by Claude Code |
|
Codex Review: Didn't find any major issues. What shall we delve into next? Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
BuildKit decodes exec-form arguments with Go's json.Decoder: it reads only the first value, ignores trailing text, and maps lone surrogate escapes to U+FFFD. The scanner required strict whole-text JSON, so for `ADD ["\uD800https://x/y", "/z"]` or `RUN ["echo"] <<EOF` it fell back to shell form and could miss a remote source or skip real instructions as a heredoc body. JSON form now decodes the first value the same way, and `[`-prefixed text with a \u escape that strict JSON rejects refuses. Bracketed shell text such as `RUN [ -d /x ]` stays shell form. The scanner cannot see ONBUILD triggers stored in a pinned base image's configuration. `provider::build_policy` adds the BuildKit source policy the build step passes through EXPERIMENTAL_BUILDKIT_SOURCE_POLICY: it denies http, https, git and docker-image+blob sources at solve time, so a base image's triggers cannot fetch them either. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Security fixes in de13309: JSON form now matches the frontend. BuildKit's ONBUILD triggers in base images. The scanner never sees a pinned base image's configuration, so it cannot check the triggers stored there.
This PR runs no builds, so the build step must write this document to a private file and set the variable. Test: @codex review 🤖 Addressed by Claude Code |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Unmatched sources are allowed, so the policy let a base image's ONBUILD trigger pull any unpinned image. `build_policy::document` now takes the build's digest-pinned base references and denies every docker-image and oci-layout source except exactly those, normalized the way BuildKit's llb.Image names a `docker-image://` named context. The http, https, git and docker-image+blob denials stay last. References that are not digest-pinned public Docker Hub images refuse. The docs now say plainly that nothing applies the policy yet: ONBUILD triggers in base images are not enforced until the build step passes it to buildx. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Follow-up in f21d5a0 to the source-policy review:
@codex review 🤖 Addressed by Claude Code |
|
Codex Review: Didn't find any major issues. You're on a roll. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
, #612, #628, #629, #630) (#639) ## What this is Merge train batch 6 into `next`: the native image builds stack and its fixes, as one batch. Builds stay off by default: they run only with `HACK_NATIVE_BUILDS=1`, which native `up`, restart and doctor all check. Each component's reviewed head is merged with `git merge --no-ff`, in stack order. Integration conflicts are resolved in the batch's merge commits, described below. Hosted CI on this branch is the full-suite gate for the combined result. | PR | Title | Linear | Head included | Review | | --- | --- | --- | --- | --- | | #583 | feat(native): pin a BuildKit client and scan Dockerfile image references | HACK-1270 | `f21d5a04` | Codex code + security: no findings; 0 open threads | | #606 | feat(native): build Compose images in the guest engine (runtime build-image) | HACK-1270 | `460ddff2` | Codex code + security: no findings; 0 open threads | | #607 | feat(native): admit build storage, budget build cache and reclaim superseded build images | HACK-1270 | `9f33a1d0` | Codex code + security: no findings; 0 open threads | | #612 | feat(native): build Compose build services in native up behind HACK_NATIVE_BUILDS | HACK-1270 | `7f42e328` | Codex clean at `8ec7460e`; `7f42e328` adds #628's squash (re-review requested) | | #628 | fix(native): admit native build fields and name services in build refusals | HACK-1925 | `f07ea583` | Codex code + security clean; already squashed into #612's branch | | #629 | fix(native): keep the VM responsive during image builds and stop a silent guest | HACK-1924 | `a0e3e797` | Codex code + security: no findings; 0 open threads | | #630 | fix(native): restore a sourceless graph after its project files were touched | HACK-1914 | `a93db842` | Codex clean at `009989c7`; `a93db842` only merges #629 into it (re-review requested) | ## Security properties in the merged code - **Build arguments:** they reach the BuildKit client only through a private 0600 bake definition, never its environment. The client environment is cleared to an allowlist. Names must be plain identifiers, and BuildKit-interpreted names such as `BUILDKIT_*`, `BUILDX_*` and `SOURCE_DATE_EPOCH` are refused. A build argument equal to a managed secret value is refused without echoing the value. Build arguments are not secrets, matching Docker. - **Source policy:** a source policy from `build_policy::document`, set through `EXPERIMENTAL_BUILDKIT_SOURCE_POLICY` in a private file, applies to every build. It allows only the scanner's digest-pinned base images and denies other images, `oci-layout`, `http`, `https`, `git` and blob sources. Pinned bases whose config has `OnBuild` triggers are refused. - **Dockerfile scanner:** - remote `ADD` sources are refused, including the JSON form, multiple sources and variables; - JSON-form arguments are read as BuildKit reads them, and a lenient-decode differential fails closed; - heredocs are recognized as BuildKit's lexer does, including whitespace after `<<`; - a stage named `scratch` is refused; - `ARG` names must be plain identifiers; - platform arguments must resolve to `linux/arm64`; - expanded values are size-bounded. - **Build output:** forwarded output is sanitized and then redacted, including Go-quoted and JSON-escaped forms and values split across a line cut. It is bounded by size. ## Integration changes - **#606 with #605 / #609:** `resolve_build_base` runs on #605's guarded registry client, so the resolver and address policy, origin-bound authentication and the realm rules apply. It uses #609's native platform selection, so builds stay Docker Hub and linux/arm64 only. The older Docker Hub-only fetch helpers are dropped. - **#606 / #607 with #605 / #609 / #615:** the `build-image` and `reclaim-build-images` commands sit beside the image-policy and emulation options. The build error helpers take `impl Into<ErrorMessage>`. - **#607:** the native-build-retention TLA+ contract is registered beside the restart-policy, pool-emulation and multi-root contracts. Its model-coverage row now says an orphaned build client keeps the fence and per-key lock until it exits (`9f33a1d0`). - **#612 with batch 5:** - The builds-enabled classification flows through `classifyAdapted`, the Compose-backend refusal and doctor. - With the gate off, native `up` refuses a build with a message that names `HACK_NATIVE_BUILDS`, so doctor's basic-build advice names it too; one test expectation changed to match. - Startup and restart keep the dependency-file selection, host aliases, emulation policy and the inactive-profile skip alongside the build services. - **New (#609 x #612):** a build service whose adaptation selects amd64 emulation is refused before any effect, because native builds are linux/arm64 only. `prefer-native` passes, and a test covers it. - **#629:** the socket cleanup after a clean stop is kept inside #629's new guest stop. #629's two flaky relay tests are fixed on its branch (`a0e3e797`): each test gets its own fixture root, and EINVAL from `set_read_timeout` after the peer closes is accepted. - **`next` merge:** the last merge brings in Kit's CI shard and SIGKILL harness changes (#624, #627). The commit hook formatted `tests/native-compose-generation.test.ts` with Biome, a whitespace-only change to that Kit file. ## Validation on this branch (`6337e0ed`) - Clean CLI typecheck: pass. Biome on the 20 changed files: no errors. - `RUSTUP_TOOLCHAIN=1.97.1 bun run check:local`: pass. All-features clippy `-D warnings` (Zig 0.15.2): pass. - Cargo `--lib`: 1346 pass. `--features native-config-plan` `provider::graph`: 673 pass. Contracts: `project_contract` 66, `compose_fields_contract` 10, `interpolation_budget_contract` 1, `local_contract` 14. - `bun run test:models` (TLA+ 1.7.4): exit 0, 172 controls verified. - Focused bun tests, bounded runner, the changed test files: 242 pass, 0 fail. - `docs:prepare` + `docs:check`, `privacy:check`, gitleaks over `origin/next..HEAD`: pass. Host evidence: 11 of 11 builds passed on an M5 host with the relay (#629). Still open: the source-policy host check (a pinned build succeeds, and a base trigger that pulls an unpinned image or fetches https fails with "denied by policy") and the bake `--allow fs.read` / metadata shape on the pinned buildx 0.34.1. Both are listed in #606. After this merges, each component PR is closed with a link to the merge commit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- codesmith:footer --> --- <a href="https://backend.blacksmith.sh/track/run-proof?expires=1796625833&installation_model_id=17053&pr_number=639&ref=codesmith_pr_footer&repository=hack-dance%2Fhack&return_to=https%3A%2F%2Fgithub.com%2Fhack-dance%2Fhack%2Fpull%2F639&variant=see_it_in_action&signature=c3ba624f6f34813ba26773c5b4c3caf941bd59515e8c3016c92df8f0e2a6048f"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/proof-see-it-in-action-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/proof-see-it-in-action-light.svg"><img alt="See it in action" src="https://pr-comments-assets.blacksmith.sh/codesmith/proof-see-it-in-action-dark-3x.png" width="132" height="28"></picture></a> <sup><a href="https://app.blacksmith.sh/hack-dance/codesmith/hack/pr/639?autoLogin=true&ref=codesmith_pr_footer">Open in [code]smith</a> · Need help on this PR? Tag <code>@codesmith-bot</code> with what you need.</sup> <!-- codesmith:autofix:disabled --> <!-- /codesmith:footer --> --------- Co-authored-by: Dimitri Kennedy <344842+roodboi@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged into 🤖 Addressed by Claude Code |
Summary
Groundwork for building Compose
build:images on the native backend. Nothing builds images yet. Nativeupstill refusesbuild:services, so no user-visible behavior changes.Pinned BuildKit client (
buildx)provider-pins.jsonnow pinsbuildx0.34.1, thedarwin-arm64release file, by SHA-256. This is the client release from the same weeks as the pinned Docker 29.5.2 engine. The file is Developer ID signed. The SHA-256 matches the digest GitHub publishes for the release file.runtime prepare-builder --archive <file>works likeprepareandprepare-engine:codesign --verify --stricton it, records a tree digest, and publishes by rename.runtime probereportsbuilder_preparedand refuses if the prepared tree changed. That covers content, file mode, extra files, a symlinked executable, and an aliased root.linux-arm64file and the client runs inside the VM.Dockerfile image-reference scanner (
provider/build_scan.rs)build_scan.rsis a pure function. It reads a Dockerfile (it never runs it) and reports the images that a build of the selected target can pull:FROMlinesCOPY --from=<image>RUN --mount=...,from=<image>ONBUILDtriggers of the Dockerfile's own stagesIt follows the Dockerfile frontend that is built into the pinned engine (BuildKit 0.30):
escapetoken, line continuations (skipping comments and blank lines), and heredoc bodies ofRUN,COPYandADD(including whitespace between<<and the delimiter) the way that frontend does.FROMnames and--platformvalues expand$NAMEand${NAME}from the globalARGs. The build's literal arguments override them. For alinux/arm64build, the known values ofTARGETOS,TARGETARCH,BUILDOSandBUILDARCHare also available.--fromand mountfrom=values are literal, because the frontend itself refuses variables there. A value that names a stage, or aCOPY --fromstage index, means a stage.scratchmeans an empty source. Anything else is an image.The scanner refuses anything it cannot resolve exactly:
# syntax=,// syntax=and JSON-form frontend selection${NAME:-...}and other variable modifiers[-prefixed exec-form arguments that strict JSON rejects but the frontend's Go decoder could accept (a\uescape such as a lone surrogate). As in the frontend, only the first JSON value counts, and text after it is ignored.*PLATFORM,*VARIANT,*OSVERSION,TARGETSTAGE,SOURCE_DATE_EPOCH--platformvalues other thanlinux/arm64or the build/target platform variables. A globalARGdefault that overridesBUILDPLATFORMorTARGETPLATFORMmust itself resolve tolinux/arm64ARGnames that are not plain[A-Za-z_][A-Za-z0-9_]*identifiersscratch, unknown instructions and flags, instructions other thanARGbefore the firstFROM, and unterminated heredocsADDsources the engine would fetch remotely, which would bypass the build network's isolation: any source with://, an scp-styleuser@host:git ref, or a variable. This applies to shell and JSON forms, every source of a multi-sourceADD, andONBUILDtriggers.ADD --checksumand--keep-git-dirare refused because they apply only to remote sources. Local sources, local archives and heredocs are still allowed.BUILDKIT_*or platform argumentsError messages give line numbers only. They never repeat Dockerfile text or argument values.
Source policy (
provider/build_policy.rs): not applied yetNothing in this PR applies this policy.
ONBUILDtriggers stored in a base image's configuration are not enforced until the build step applies it, which #606 does. The scanner cannot see those triggers. They could add remote sources or name unpinned images.build_policy::document(pinned)takes the build's digest-pinned base references and returns a BuildKit source policy:docker-image://andoci-layout://source;docker-image://<reference>named context (docker-image://docker.io/<namespace>/<repository>[:tag]@sha256:<digest>, normalized likellb.Image);http,https,gitanddocker-image+blobsources.Later matching rules win, and unmatched sources (the
local://build context and Dockerfile) are allowed. A reference that is not a digest-pinned public Docker Hub image is refused.The pinned
buildx0.34.1 reads the policy file named byEXPERIMENTAL_BUILDKIT_SOURCE_POLICYforbakeandbuild. The engine's BuildKit v0.30.0 then checks every source operation against it in the solver, including operations added by base-image triggers. The tests evaluate the document with a model of BuildKit's matching rules (exact identifier,*wildcard, last match wins). Only a host build can confirm the identifiers BuildKit actually produces, so that check belongs to the build step.Validation
RUSTUP_TOOLCHAIN=1.97.1 bun run check:local(rustfmt and Clippy with-D warnings, all targets): passcargo +1.97.1 clippy --all-targets --all-features -- -D warnings(with Zig 0.15.2): passprovider::build_scan31,provider::build_policy3,provider::artifact7). All fixtures are synthetic:ARGsubstitution with overrides, stageARGscopingscratchand images inCOPY --fromfrom, mount sources, target reachability,ONBUILDtriggers,--platformrules<<-, quoted delimiters, several on one line, JSON forms)RUSTUP_TOOLCHAIN=1.97.1 bun run test:local: pass, 21 test binaries, 1282 passed, 0 failed, 109 ignored (run from a short-path checkout of the same diff, because of the Unix socket path length limit)prepare-buildersucceeds, and running it again returns the same tree digestdocker-buildx versionreportsv0.34.1runtime probereportsbuilder_prepared: true, refuses afterchmod 755on the executable, and passes again after the mode is restoredbun run --cwd packages/cli typecheck: pass.bun run docs:prepare && bun run docs:check: pass.tests/prerelease-plan.test.tsandtests/native-candidate-authored-artifact.test.ts(which read the native candidate guide): 64 pass. This PR changes no TypeScript.Remaining gaps
ONBUILDtrigger stored in a base image's own configuration can add remote sources or pull an unpinned image.build_policy::documentdenies both at solve time, but only once the build step applies it (feat(native): build Compose images in the guest engine (runtime build-image) #606). The build step should also refuse pinned bases whose configurations have triggers. That would fail closed even if the policy were not applied.Refs HACK-1270
🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.