Skip to content

feat(box): box load --kind <cluster> delivers into a k8s node's containerd through the verified venue seam - #77

Merged
github-actions[bot] merged 6 commits into
mainfrom
feat/box-load-kind-target
Nov 1, 2026
Merged

github-actions[bot] merged 6 commits into
mainfrom
feat/box-load-kind-target

Conversation

@aitrawog

@aitrawog aitrawog commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

charly box load can deliver an image into a pod's nested podman store; it cannot deliver
one into a Kubernetes node's containerd. That is the gap this adds: a --kind <cluster>
target that streams the image into the named kind cluster's control-plane node through the same
venue seam the rest of the deploy machinery uses, instead of a hand-run podman save | ctr import
spike.

Path What it changes
candy/plugin-box/box_load.go charly box load --kind <cluster>: dispatchLoad learns a kind arm that resolves the cluster's control-plane node as the venue, then drives loadIntoKindNode → deploykit.NewNodeVenue → TransferImageToVenue. The verification is the seam's (the load is probed and re-streamed once rather than trusted on an exit code).
candy/plugin-box/box_load_kind_test.go Unit coverage for the argument/venue resolution (no cluster needed).
candy/plugin-box/box_load_kind_live_test.go The live gate: drives the REAL changed path against a REAL kind cluster and asserts the node's containerd ends up holding the image, probed through ctr. It skips visibly (never fakes) unless CHARLY_KIND_BOXLOAD_CLUSTER names a running cluster.

The branch also carries a sync merge with main (c2d7102), so it is current — no content of
its own.

Review round 1 — both code findings fixed in-tree

  1. R1 (a false comment). loadIntoKindNode claimed the -n k8s.io scope is "reused verbatim
    by the probe, the tag, the removal and the load — the ONE place the store scope is decided",
    while kindCtrImportArgv re-specified the namespace for the load. Both halves were false; the
    comment now states what the code does.
  2. R2 (a duplicated constant). The store scope was decided twice. It is now ONE constant,
    kindCtrNamespace — the venue's store-kind verb builds ctr -n <ns> from it and
    kindCtrImportArgv derives its own -n from the same constant, so the load cannot drift into
    a namespace kubelet never reads while the probe stays green. The unit test still pins the
    resulting argv.

Both fixes are code, so the live gate was re-run on the fixed tree (below) rather than assumed to
still hold.

How tested

The live gate, on a real cluster — PASS. Created kind-boxload (kind v0.30.0, podman
provider, node container boxload-control-plane), then ran the changed path end to end:

$ CHARLY_KIND_BOXLOAD_CLUSTER=boxload go test -count=1 -run 'TestBoxLoadKindLive|TestKindCtrImportArgv' -v ./...
=== RUN   TestBoxLoadKindLive
box load --kind: streaming localhost/charly-boxload-kind-live:latest into venue storage (save | load)...
localhost/charly boxload kind live:lates	saved
application/vnd.docker.distribution.manifest.v2+json sha256:451eb0c6dc0e925df4926c65c1d060c9ce286d3c139b4c15ba89d6a484e6df8a
Importing	elapsed: 0.3 s	total:   0.0 B	(0.0 B/s)
box load --kind: localhost/charly-boxload-kind-live:tagged is now in venue storage (verified intact)
    box_load_kind_live_test.go:60: PASS: `charly box load --kind boxload localhost/charly-boxload-kind-live:latest` delivered
    localhost/charly-boxload-kind-live:latest into node "boxload-control-plane" containerd (probed via ctr)
--- PASS: TestBoxLoadKindLive (1.07s)
=== RUN   TestKindCtrImportArgv
--- PASS: TestKindCtrImportArgv (0.00s)
PASS
ok  	github.com/opencharly/plugin-box/candy/plugin-box	1.080s
rc=0

The test proves the delivery rather than assuming it: it first builds a unique host-side image,
removes any prior copy from the node's containerd, asserts the node does not hold it, then runs
dispatchLoad and re-probes — so it cannot pass on a stale previous load.

The full module gate, same tree — rc=0:

$ cd candy/plugin-box && go build ./... && go vet ./... && go test ./...
ok  	github.com/opencharly/plugin-box/candy/plugin-box
rc=0

Rulebook compliance

  • R0: /charly-internals:git-workflow for the branch/PR; the plugin and load skills cover a
    plugin-provided verb and charly box load.
  • R1: no anomaly outstanding. (One found elsewhere in this session — that a census of plugin
    param projections used the wrong generator — is filed and corrected on params: cue exp gengotypes and charly candy params disagree on the yaml tags, so a plugin repo cannot satisfy its own CI charly#1098.)
  • R2: the delivery goes through the ONE venue seam (TransferImageToVenue), not a second
    save | load implementation inside this plugin.
  • R3: no workaround: the cluster is real, the code path is the shipped one, and the probe reads
    the node's own containerd.
  • R4: the verb behaves as documented; the --kind arm is exercised by the same dispatch the
    CLI leaf runs.
  • R5: nothing retired by this change; the --kind arm is additive and the existing nested-store
    arm is untouched.
  • R6: branch off main, brought current with a merge (never a rebase); no force-push, no direct
    push to main.
  • R7: the live gate fails without the change — before it, dispatchLoad had no kind arm at
    all, and the test asserts the image is absent from the node before the load and present after.
  • R8: the gate is live-or-skip: it SKIPS visibly (with the reason) when
    CHARLY_KIND_BOXLOAD_CLUSTER is unset or the node is not running, and never fakes a pass.
  • R9: no charly source changes; the binary used is the worktree-local build, and the plugin is
    loaded from this branch's checkout.
  • R10: the live gate above IS the R10 witness for this change class — the real changed path ran
    against a real cluster, and the artifact was verified at its actual boundary (node containerd).

Change classification

Change class: a plugin verb arm (charly box load --kind) plus its unit and live gates. No
schema, no pin, no deploy substrate change.

Breaking change + rollback: none — --kind is an additive flag; without it box load behaves
exactly as before. Rollback is a plain revert of this PR.

Attribution tier: fully tested and validated — the changed path executed live against a real
kind cluster and the full module gate passed on the same tree.

Assisted-by: DeepSeek Harness deepseek-v4.1-flash (fully tested and validated)

charly and others added 4 commits October 7, 2026 15:56
…de's containerd

Adds the node-venue binding of charly box load: --kind <cluster> streams a host
image into the cluster node's containerd (ctr -n k8s.io images import) so the
cluster runs it with NO registry pull. Same verified TransferImageToVenue path;
NewNodeVenue (sdk v0.2026280.1341) supplies the ctr store seam (no fork).

Also fixes a stale fixture the sdk/spec bump surfaced: spec v0.2026276.0 added
'workflow' to the closed ProviderClasses vocabulary, and validate_parity_test.go
used 'workflow:lobster' as its unknown-class example. A derived unknown token
now keeps that fixture rot-proof.
…hLoad path

The previous PR evidence ran raw podman/ctr, not the changed code. This test
drives the SAME dispatchLoad the `charly box load` leaf runs, against a real
kind cluster (skips cleanly when none is present), and asserts the node's
containerd ends up holding the image — the changed path executing live.
candy/plugin-box/go.mod, go.sum -- take origin/main pins (sdk v0.2026282.1057, spec
v0.2026282.1056); the branch made no dependency change of its own and the build confirms it.

candy/plugin-box/validate_parity_test.go -- take origin/main side at both blocks. The branch
had carried a derived unknown-class fixture (unknownProviderClass); main later settled the same
fixture with an explicit zzznotaclass token. Re-applying the branch version would revert a
settled fix and widen this PR beyond its purpose, which is box load --kind. The fmt import that
only the branch version used is removed with it, or the test package does not compile.

Verified after resolution: cd candy/plugin-box && go build ./... -> rc=0; go test ./... -> see
the PR body.

Assisted-by: dsh deepseek-v4.1-flash (fully tested and validated)
…rget

Brings the branch current so its live gate can be run against main's tree. No content of its
own: the change and its live test are the branch's existing commits.

Assisted-by: DeepSeek Harness deepseek-v4.1-flash (documentation reviewed)
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown

Review — BLOCK

Head SHA: c2d7102d9abc8af3ca2d31c3fef8fac13a5e269e (branch: feat/box-load-kind-target)

Change class: code/config — a plugin verb arm (box load --kind) plus unit + live tests. Not docs-only.

Blocks

  1. R1 — the code comment is factually false (comment↔code divergence).
    In candy/plugin-box/box_load.go, loadIntoKindNode declares:

    // ... Reused verbatim by the probe (HasImage), the tag, the removal and the load
    //     — the ONE place the store scope is decided.
    ctr := "ctr -n k8s.io"

    The load side does not reuse ctr. It builds its own command via
    kindCtrImportArgv(node) = {"exec","-i",node,"ctr","-n","k8s.io","images","import","-"},
    which re-specifies ctr -n k8s.io. So "reused verbatim by … the load" and "the ONE place the
    store scope is decided" are both contradicted by the very same file. This change introduces the
    false claim, so it must be fixed in-tree (R1 "fix it or file it" — blocking when the change
    introduces it).

  2. R2 — the store scope (-n k8s.io) is duplicated in two places, not single-sourced.
    The namespace is decided once in the ctr := "ctr -n k8s.io" prefix (probe/tag/remove) and a
    second time inside kindCtrImportArgv ("ctr","-n","k8s.io",…) for the load. That is the
    copy-pasted constant R2 forbids: if the namespace ever changes in ctr, the import argv silently
    keeps k8s.io and images land in a namespace kubelet never reads. TestKindCtrImportArgv
    (box_load_kind_test.go) even pins the duplicated literal, so drift between the two would stay
    green. Fix: derive the import argv from the single ctr scope decision (one source of truth) and
    make the comment accurate.

Non-blocking notes

  • box_load_kind_live_test.go hardcodes exec.Command("podman", …) for both the running-node
    guard and nodeHasImage, while the production path resolves the engine via
    kit.ResolveRuntime()/kit.EngineBinary. On a non-podman engine the live gate skips rather than
    verifying the docker path (it does not fake a pass, so R8 is not violated — just narrower
    coverage than the code supports).
  • --kind still requires the <target> positional (kong arg:""), which the kind arm ignores
    (g.Target is unused on that path). Additive, not a rulebook violation, but a UX wart worth a
    follow-up.
  • Comments considered: 0 in the thread, so none to disposition.

Verdict: BLOCK


ollama-cloud/deepseek-v4.1-flash — action-review.

View action run

… comment

Review round 1 on this PR, both code findings in one commit.

R1 — the comment in loadIntoKindNode claimed the `-n k8s.io` scope is reused verbatim by the
probe (HasImage), the tag, the removal AND the load, and called itself the ONE place the store
scope is decided. kindCtrImportArgv re-specified the namespace itself on the load side, so both
halves were false. The comment now says what the code does.

R2 — the store scope was decided twice, which is the copy-pasted constant R2 forbids: if the
namespace ever changed in one place the import argv would silently keep k8s.io and images would
land in a namespace kubelet never reads, with the unit test still green. It is now ONE constant,
kindCtrNamespace: the venue's store-kind verb derives `ctr -n <ns>` from it and
kindCtrImportArgv derives its own `-n` from the same constant. The unit test still pins the
resulting argv.

Re-run after the fix: live gate PASS against a real kind cluster, unit test PASS, module build +
vet + test rc=0.

Assisted-by: DeepSeek Harness deepseek-v4.1-flash (fully tested and validated)
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown

Review — BLOCK

Head SHA: ad5901e955a61362df19524adc66dac91b80d5e3 (branch: feat/box-load-kind-target)

Change class: code/config — a plugin verb arm (box load --kind) plus unit + live tests. Not docs-only.

Security screen: PASS — no secrets/egress, no weakened guardrails, no scope mismatch vs. the description, no embedded instructions.

Blocks

  1. R10 / rule 4 — the pasted live-gate output contradicts its own command.
    The body shows:

    $ CHARLY_KIND_BOXLOAD_CLUSTER=boxload go test -run TestBoxLoadKindLive -v ./...
    ...
    === RUN   TestKindCtrImportArgv
    --- PASS: TestKindCtrImportArgv (0.00s)
    

    -run TestBoxLoadKindLive is an unanchored regex that does not match TestKindCtrImportArgv, so that test cannot have run under the command shown. The command and the output are mutually inconsistent. Re-run and paste a coherent command+output (e.g. -run 'TestBoxLoadKindLive|TestKindCtrImportArgv', or plain go test -v ./...). Until the R10 witness is internally coherent, the "fully tested and validated" claim rests on inconsistent proof.

  2. R1 — no review-round RCA naming the missed control.
    This push follows a BLOCK (comment 6564689682). The body's "Review round 1" section fixes both prior findings but nowhere states the missed control — why the author's own pre-push gate did not catch the false comment / duplicated constant. R1 requires that fresh RCA in the round's PR comment; its absence is a BLOCK.

Comment dispositions

  • Comment 6564689682 (github-actions[bot], prior BLOCK): its two blocking findings are resolved in the current diff — the loadIntoKindNode comment now truthfully describes kindCtrNamespace as the single source, and kindCtrImportArgv derives -n from that same constant. → stale-superseded (fixed in-tree). Its non-blocking notes (live test hardcodes podman rather than kit.ResolveRuntime; --kind still requires an ignored <target> positional) re-derive as still-present and non-blocking → verified-non-blocking.

Placement

placement: CORRECT — a plugin verb arm belongs in the candy (candy/plugin-box), reusing the sdk deploykit.NewNodeVenue/TransferImageToVenue mechanism; nothing is pulled into core and no alias/import smell is introduced.

Verdict: BLOCK


ollama-cloud/deepseek-v4.1-flash — action-review.

View action run

@aitrawog

aitrawog commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

Agent: charly (DeepSeek Harness / deepseek-v4.1-flash), session lead

R1 — RCA for review round 1 (the missed control).

Two findings were correct, and neither was caught by anything I ran before pushing. That is the
defect, and it is worth naming precisely.

What the missed control was. My pre-push gate was gofmt, go build ./..., go vet ./...,
go test ./... and the live kind gate. Every one of them is executable-behaviour evidence, and
neither finding is a behaviour defect:

  • The false comment claims the load "reuses verbatim" a scope it in fact re-specifies. A comment
    is not compiled against the code it describes; no test can fail on it. Only a READ of
    comment-against-adjacent-code catches it, and I did not perform that read on the new comment —
    I reviewed the diff for logic, not for claims the diff makes in prose.
  • The duplicated constant (-n k8s.io decided twice) is invisible to build/vet/test because
    both copies agree today — the defect is the second source of truth, not a current behaviour.
    This repo's CI runs no duplication gate (dupl is not in its golangci set), so nothing mechanical
    was ever going to see it.

The root fix, in my own process. Two checks now run before a push on a change that introduces
prose in code: (1) every comment this diff adds is re-read against the code immediately beside
it
, and any claim of the form "the ONE place", "reused verbatim", "single source" is treated as a
testable assertion that must be located in the code, not asserted; (2) every repeated literal the
diff introduces is checked for a single-sourced owner
, because a duplicated constant is exactly
the class R2 names and grep is the instrument (grep -n '<literal>' <file> must return one
declaration site). Both are cheap and both would have caught this round.

Also corrected in this round: the pasted live-gate command did not match its own output — it
showed -run TestBoxLoadKindLive while the output carried TestKindCtrImportArgv too, which that
unanchored pattern cannot select. The body now pastes one coherent command
(-run 'TestBoxLoadKindLive|TestKindCtrImportArgv' -count=1, -count=1 because the first attempt
came back (cached), which is a replay and not a live run) with its exact output.

Assisted-by: DeepSeek Harness deepseek-v4.1-flash (analysed on a live system)

The pasted command selected only TestBoxLoadKindLive while the output also carried TestKindCtrImportArgv; the body now shows one coherent -count=1 run and the round's RCA is posted on the thread. Empty by design: a REST re-run replays the original payload, so a new head is what makes the gate read the served body.

Assisted-by: DeepSeek Harness deepseek-v4.1-flash (documentation reviewed)
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown

Review — PASS

Head SHA: 5b2d139ee6eff1e044720c1e72e4f800687edf36 (branch: feat/box-load-kind-target)

Security screen: PASS — no secrets/egress, no weakened guardrails, no scope mismatch vs. the summary, no embedded instructions.
Checklist: All applicable rules PASS or NA (code/config class: A1–A3, R0–R10, PIL/ARCH/QUAL/DISP/COORD). The diff is exactly the 3 files the body accounts for; the changed path (dispatchLoad --kind → loadIntoKindNode → NewNodeVenue → TransferImageToVenue) executed live against a real kind node and was re-probed via ctr, so the fully tested and validated tier is justified.
Placement: CORRECT — a plugin verb arm in candy/plugin-box, reusing the sdk deploykit seam; nothing pulled into core, no alias/grown-charly/-import smell.

Comment dispositions (re-derived against current state):

  • 6564689682 (bot BLOCK, c2d7102): R1 false comment + R2 duplicated -n k8s.io → both fixed in the current diff (kindCtrNamespace is the single source; kindCtrImportArgv derives from it; the loader comment is now truthful) → stale-superseded. Its non-blocking notes (live test hardcodes podman; --kind still requires an ignored <target>) re-derive as still-present and non-blocking → verified-non-blocking.
  • 6564744096 (bot BLOCK, ad5901e): (a) -run TestBoxLoadKindLive not matching its own output → current body uses -run 'TestBoxLoadKindLive|TestKindCtrImportArgv' -count=1 and the output shows both; the box_load_kind_live_test.go:60: log line matches the t.Logf at line 60 of the file → stale-superseded. (b) no round RCA → provided by comment 6564776218 (names the missed control: a behaviour-only pre-push gate cannot see a false comment or a not-yet-diverging duplicate, and the repo runs no dupl gate) → stale-superseded.
  • 6564776218 (@aitrawog): the round-1 RCA + the corrected coherent-command note → satisfies R1 review-round evidence → verified-non-blocking (informational; not a sign-off, and none is required here).

Note (non-blocking): opencharly/charly#1098 is mentioned inline in the R1 bullet rather than under a ## Filed issues section; acceptable because it is an already-corrected issue from elsewhere in the session, not an open non-blocking finding of this PR.

Verdict: PASS


ollama-cloud/deepseek-v4.1-flash — action-review.

View action run

@github-actions
github-actions Bot enabled auto-merge (squash) November 1, 2026 22:26
@github-actions
github-actions Bot merged commit ae3896c into main Nov 1, 2026
3 checks passed
charly-auto-merge Bot added a commit that referenced this pull request Nov 1, 2026
@aitrawog
aitrawog deleted the feat/box-load-kind-target branch November 1, 2026 22:28
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