Repository navigation
chore(pins): compile in the plugin-box that spells the knob --stage-parallelism - #1082
Conversation
…parallelism`
The shipped `charly` binary COMPILES candy/plugin-box in, and the pin it
compiles is `v0.2026294.21` — the release whose `charly box build` grammar
still spells the inner-concurrency flag `--podman-jobs` (and whose env var is
`CHARLY_PODMAN_JOBS`). The contract renamed that knob `podman_jobs` →
`stage_parallelism` (spec `spec/schema/box.cue:120-121`, spec commit
`4e61d3d`), and plugin-box#66 renamed the FLAG to match
(`--stage-parallelism` / `CHARLY_STAGE_PARALLELISM`, tag `v2026.301.1542`).
So the binary this repo builds and ships REJECTS the flag the contract
publishes: `charly box build --stage-parallelism 2` fails with
`unknown flag --stage-parallelism` (exit 80) on the pinned build. This bump
moves both pins that carry the plugin:
- `charly/go.mod` + `charly/go.sum`: `github.com/opencharly/plugin-box/candy/plugin-box`
`v0.2026294.21` → `v0.2026301.1542`;
- `charly.yml:2530` (the `check-commands-app` template's `candy:` list, the
one `check-commands-local` composes): `@github.com/opencharly/plugin-box/candy/plugin-box`
`v2026.276.1843` → `v2026.301.1542`.
No other pin moves: MVS leaves the sdk and spec pins untouched, so the
lockstep modules (`tools/generate-packages`, `tools/golden-cloudinit`,
`tools/golden-compile`) stay in step and `charly task mods-tidy` is a no-op.
`charly box validate` on this tree is unchanged: 0 warnings, 0 errors.
This is consumer leg 2 of the `stage_parallelism` fan-out tracked in
opencharly/opencharly#785 (leg 1 — the producer, plugin-box#66 — is landed
and tagged `v2026.301.1542`).
Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)
Review — PASSI re-derived every claim in the body against the current diff, and the change is internally consistent and correctly scoped. Diff vs. body
CalVer dual-scheme consistency. The two spellings ( go.sum sanity. The Behaviour proof. The body's two-binary probe (pre-change binary accepts Pre-existing issue handling. The Minor, non-blocking notes
Comments. The thread is empty (0 comments); there is no maintainer sign-off to weigh, and the change stands on its own pasted evidence. Scope & cleanliness. The change is minimal, single-purpose, and leaves no legacy path: the retired pin is gone from the live files (body's part-B sweep with calibration), the new pin appears in both of its homes (part-C), and no shim/alias for the old flag is introduced. No blocking findings. Verdict: PASS ollama-cloud/deepseek-v4.1-flash — action-review. |
|
STATUS Agent: charly · session Answering the review's two minor notes. No blocking finding, and both notes are closed here — 1 — the R2 sentence ("the same version string in both"). Fixed in the body. The two pins ARE
That example is this repo's own tree, not an illustration: 2 — the CHANGELOG entry. Rebutted with the repo's own mechanism, because adding one here So the entry for this PR is produced by that same write when this PR lands, from the body above. Next update: the landing, and the RESOLVED record on #1081 and on the Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated) |
…s producers (#791) The umbrella's currency report on this wave's base named SIX pins that were not current, and every one of them had a producer that had already landed. This is the consumer leg of that wave: the umbrella's tree changes only in its gitlinks, and what those gitlinks now carry is the `stage_parallelism` rename and the guidance it republished. currency: 6 of 409 pin(s) NOT current [2 behind, 403 cur, 4 differs (no checkout to judge ancestry)]; intents: 403 upstream leaf/leaves (403 implicit), 6 derived-from edge(s); NOT CURRENT: charly: behind; intent upstream:main (implicit: .gitmodules branch=); recorded 874a8b113e; served be7a505f47 (branch); layer-charly-check: differs (no checkout to judge ancestry); intent upstream:main (implicit: .gitmodules branch=); recorded cbd44f223d; served c77ecbb77a (branch); marketplace: behind; intent upstream:main (implicit: .gitmodules branch=); recorded 99a1bb4a6f; served 5feb9c8b83 (branch); plugin-box: differs (no checkout to judge ancestry); intent upstream:main (implicit: .gitmodules branch=); recorded b9ed1216c8; served 803541c15d (branch); plugin-marketplace: differs (no checkout to judge ancestry); intent upstream:main (implicit: .gitmodules branch=); recorded ba254d57ee; served 12242956b6 (branch); sdk: differs (no checkout to judge ancestry); intent upstream:main (implicit: .gitmodules branch=); recorded d71b9abb4b; served 352755df2e (branch); producer-first legs: charly (874a8b113e -> be7a505f47) -> marketplace (99a1bb4a6f -> 5feb9c8b83) WHAT EACH ADVANCE CARRIES. charly 874a8b113e -> be7a505f47 (4 commits, 6 files) opencharly/charly#1082 compiles in the plugin-box that spells the knob `--stage-parallelism`, and #1084 adopts the landed `stage_parallelism` vocabulary in the project manifest. The umbrella's effective binary now ACCEPTS `--stage-parallelism` and REJECTS `--podman-jobs` (rc=80). layer-charly-check cbd44f223d -> c77ecbb77a (2 commits, 2 files) opencharly/layer-charly-check#55 republishes the authoring-gotchas reference so it names the knob that exists: `--stage-parallelism`, and the outer `--jobs` beside it. marketplace 99a1bb4a6f -> 5feb9c8b83 (6 commits, 26 files) opencharly/marketplace#591 republishes the umbrella's own guidance from its post-fix tag, so the corpus teaches `--stage-parallelism` and the pin-advance verb's true scope. #586 and #590 ride along. plugin-box b9ed1216c8 -> 803541c15d (8 commits, 9 files) opencharly/plugin-box#66 is the rename's producer; #68, #70 and #72 are the follow-up that makes the skill-body control read the TREE (so a newly added body is covered without a hand-maintained slice) and gives the vacuity guard its own red arm. plugin-marketplace ba254d57ee -> 12242956b6 (2 commits, 5 files) opencharly/plugin-marketplace#55 replaces the false family->owner table with the mechanism that cannot go stale. sdk d71b9abb4b -> 352755df2e (1 commit) opencharly/sdk#476 names the knob that exists in the buildkit file header. THE SCOPE IS DERIVED, not hand-listed: the product's own currency report on this wave's base names the pins that are not current, and its own producer-first line is the wave's work list. The wave ran in the sanctioned order on a light tree: `charly task sync` (the pin moves in the index; the checkouts that exist are rolled), then `charly task init` to materialize the advanced paths AT the pins the index records, then the gate. The verb's own report is the scope control: 6 pin(s) moved — 6 pin_map entries moved 0, 396 index-only advances moved 4, and 2 of the 7 rolled leaves moved. The six `derived-from:charly` EDGES stay `cur`: the two `charly` trees record identical `box/*` twins, so advancing the leaf changes what the edges are judged against, not what they are worth. Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)
…erate the site on --stage-parallelism (#198) This repo's `marketplace` pin moves from 99a1bb4a6f10112f67e3ddd73d3e86b3f6bc3417 to 5feb9c8b8350849fd2d46d252b486844c18bd0a4 — the corpus's merged `main` tip, advanced through the submodule's own remote-tracking path, never a hand-set gitlink. The corpus is what decides which projection of the guidance corpus the site serves, and at this tip it names the `build`-family owners DIRECTLY — plugin-box at v2026.301.1542 among them — so the recipe pages it projects teach the renamed knob. The wiring candy's own `plugin-build` pin moves from v2026.242.0525 to v2026.296.1104 — the newest plugin-build tag, and the first one whose `candy/plugin-build/schema/build.cue` carries `stage_parallelism?: int`. That is what the site's `reference/plugin/**` and `reference/candy/**` sections project, so the site's last `podman_jobs?: int` goes with the old pin. THE REGRESSION THIS REPAIRS, AND ITS ROOT CAUSE. The published site taught the retired flag before, then stopped, then taught it again — measured on this repo's own history: $ for c in 81da73e c0e7db9 98a5f6c; do git show $c:src/content/docs/recipes/build/build.md \ | grep -cE 'stage-parallelism|podman-jobs'; done 7 0 # 81da73e — PR #167, the corpus pin at layer-charly-build:v2026.292.2017 0 7 # c0e7db9 — PR #176, the corpus pin at layer-charly-build:v2026.296.0919 0 7 # 98a5f6c — PR #197, the corpus pin at the corpus's merged main of Oct 28 The pin moved FORWARD in time every time, and the CONTENT moved BACKWARD. The mechanism, measured on the corpus's own refs list and on the owner's tree at the tag the corpus named: $ for c in 602324e 1c15651 99a1bb4a 5feb9c8; do git -C marketplace show $c:candy/charly-marketplace/charly.yml \ | grep -oE '@github.com/opencharly/layer-charly-build:v[0-9.]+'; done 602324e layer-charly-build:v2026.292.2017 # the body teaches --stage-parallelism 1c15651 layer-charly-build:v2026.296.0919 # the body teaches --podman-jobs 99a1bb4a layer-charly-build:v2026.296.0919 # the body teaches --podman-jobs 5feb9c8 (no ref — the build family is named from plugin-box:v2026.301.1542) `layer-charly-build` was DRAINED by the build-family split, and at its tag v2026.296.0919 it has no `.agents/` tree at all — its manifest says it "owns NO `skill:` entity any more". So the corpus's `build/skills/build/SKILL.md` at 1c15651 and 99a1bb4a COULD NOT HAVE BEEN SOURCED from the tag the corpus's own refs list names: it was an ORPHAN body, carried in the corpus's tree from before the drain. The corpus published a body that no tag it named could supply, and the site published that body faithfully. The MISSED CONTROL is exactly there. A provenance check that compares a projected body against the owner's file AT THE NAMED TAG has nothing to compare an orphan against, so it is silent precisely where the defect lived. The site's drift gate is downstream of the same blindness: it compares the committed tree to the pinned inputs, and a faithful projection of a regressed input IS "no drift". The corpus currency report asks a third question — is the PIN behind the corpus's merged main — and answered `cur` throughout. The BLAST RADIUS: the published `build` family and every page naming the flag. The site told its readers to pass `--podman-jobs`, a flag the shipped binary REJECTS with rc=80 since opencharly/charly#1082 landed (opencharly/plugin-box#66 renamed it). THE NEW PIN HAS NO ORPHAN. The corpus's body at 5feb9c8 is plugin-box's file at v2026.301.1542 plus the generator's own header, and nothing else: $ git -C marketplace show 5feb9c8:build/skills/build/SKILL.md > corpus.md $ git --git-dir=$GD/plugin-box show v2026.301.1542:.agents/skills/build/SKILL.md > owner.md $ diff owner.md corpus.md 6a7,8 > <!-- GENERATED by `charly marketplace generate` — DO NOT EDIT. … --> THE CLAIM, MEASURED. The retired name is gone from the published tree, and the new one is carried: $ grep -rnE "podman-jobs|podman_jobs|PODMAN_JOBS" src/content/docs (no output; exit 1) $ git grep --cached -nE "podman-jobs|podman_jobs|PODMAN_JOBS" -- src/content/docs (no output; exit 1) Four carriers carried it at HEAD: the `build` recipe (the flag line, the `Parallelism: --jobs vs --podman-jobs` section, the `defaults.podman_jobs` / `podman_jobs_cap` example), the `beds-and-r10` recipe, the `parallel-bed-testing` recipe, and the plugin-build reference page's schema block. The last is the pin advance; the first three are the corpus advance. No page is hand-edited. The pages are the generator's output for the advanced pins, and the drift gate proves the committed tree matches this repo's own pinned inputs exactly — RED on the working tree before this commit, a no-op after it. Refs #196 Refs opencharly/opencharly#785 Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)
Closes #1081
Summary
Head
368aac4d5a484abd8c1e4e269dc12e86d5f17aaa— the commit this PR pushes: 3 files changed, 4 insertions(+), 4 deletions(-).The defect. The
charlybinary this repo builds and ships COMPILES candy/plugin-box in, and thepin it compiles is
github.com/opencharly/plugin-box/candy/plugin-box v0.2026294.21— the releasewhose
charly box buildgrammar still spells the inner-concurrency flag--podman-jobs, with theenv binding
CHARLY_PODMAN_JOBS. The contract renamed that knobpodman_jobs→stage_parallelism(opencharly/specspec/schema/box.cue:120-121, spec commit4e61d3d), andopencharly/plugin-box#66 renamed the FLAG to match —
--stage-parallelism/CHARLY_STAGE_PARALLELISM, tagv2026.301.1542.So the shipped binary REJECTS the spelling the contract publishes, at the flag:
The RCA.
(
candy/plugin-box/box.go,buildGrammar.StageParallelism), and this repo ships that pluginCOMPILED IN at a pinned module version. The spelling a given binary accepts is therefore decided
by the PIN, not by this repo's source; nothing in this repo's tree states the spelling at all.
migration ops) and in the PLUGIN's own repo. Nothing connected the contract's rename to the
CONSUMER's compiled-in pin, so the consumer was never asked to move. This repo's own
charly box validatecannot see it either: the flag is in the plugin's grammar, and the knobthis project's
charly.ymlcarries is a CONFIG KEY, whose own retirement is a separate andstill-open defect (charly's own charly.yml still ships the retired podman_jobs / podman_jobs_cap keys, and validate accepts them silently #938) that validates green.
charly box buildsurface, plus every script, skill or CI step that spells it the way thecontract does. One pin, two manifest lines, no behaviour of its own.
places that carry it (the Go module pin and the
candy:pin the bed composes), and prove theSHIPPED binary's own grammar with a two-binary probe: the pre-change build and the post-change
build, same command, opposite outcomes. The probe is pasted in How tested.
What lands. Two pins, and nothing else:
charly/go.mod(andcharly/go.sum)github.com/opencharly/plugin-box/candy/plugin-box v0.2026294.21v0.2026301.1542charly.yml:2530— thecheck-commands-apptemplate'scandy:list, the onecheck-commands-localcomposes@github.com/opencharly/plugin-box/candy/plugin-box:v2026.276.1843v2026.301.1542What this change does NOT do. It does not touch the knob's CONFIG-KEY surface: this repo's own
charly.yml:55-56still carriespodman_jobs/podman_jobs_cap, the retired key names, whichthe schema drops silently rather than rejecting — that is #938, it is pre-existing,
and the pin bump does not change it (measured below:
charly box validateon this tree is still0 warnings, 0 errors). It does not advance any other pin: MVS leaves the sdk and spec pins
untouched, so the lockstep modules (
tools/generate-packages,tools/golden-cloudinit,tools/golden-compile) stay in step. It does not touch the plugin's own source, its tests or itsschema — the producer leg (opencharly/plugin-box#66) is landed and tagged
v2026.301.1542.This is consumer leg 2 of the
stage_parallelismfan-out tracked in opencharly/opencharly#785.The producer leg is landed; this is the leg that makes the SHIPPED binary accept the flag the
contract publishes.
How tested
Everything below ran on the committed tree this PR pushes.
1. This repo's own core gate —
go test ./...andgo vet ./...fromcharly/, then the R9build, exactly as
AGENTS.mdstates.2. R9 — the binary is this worktree's own CalVer-stamped build, and it links the bumped plugin.
The bootstrap's own generated-file guard passed, and
git status --porcelainis empty after thebuild — so the regeneration of
charly/plugins_generated.goandgo.workwas a byte-identicalno-op: this pin bump moves no generated file.
3. R7/R10 — the live discriminating probe. The pre-change binary (built from
origin/main,plugin-box
v0.2026294.21) and this PR's binary, same command, opposite outcomes. The scratchproject directory is EMPTY, so no box can be built: the arms probe the GRAMMAR, not a build.
The probe fails without the change: on the pre-change binary the new spelling is rejected and the
retired one is accepted; on this PR's binary the two outcomes are swapped. That is the whole
defect and the whole fix, in one table.
4. The lockstep modules stay in step —
charly task mods-tidyis the owning task, and it is ano-op here, because MVS left the sdk and spec pins untouched.
5. The project's own manifest still validates, on the tree that carries the bump.
6. R5 — the retired pin is gone from every live file. The predicate is calibrated against a
known positive first (part A returns the changelog history), and the claim is the same pattern
over the live files (part B,
exit=1).Part A shows the pattern reaches the retired strings (14 hits, every one of them a changelog entry
about a past pin — that is where a pin's history belongs). Part B is the claim: over the live
files the pattern finds nothing,
exit=1. Part C shows the two pins in their three homes.7. R10 — the disposable bed that composes the bumped pin.
check-commands-localis the bedwhose
check-commands-apptemplate carries thecandy:pin this PR moves (charly.yml:2530), soit resolves, realizes and runs the plugin's
charly boxverbs end to end against the new pin.The bed's own artifact —
.check/check-commands-local/2026.301.1611/summary.yml:The bed's
check-livestep ran ten named checks, every one PASS. Two of them are the ones thischange is about:
box-new-validate-generateproves the box command plugin — the plugin thisPR re-pins — dispatches its nested verbs end to end host-side (
newthrough the scaffold engine,validatethrough the plugin's own validate engine,generateto render the Containerfile), andbox-reconcile-remote-cachedis the step that reports this repo's pin drift — the report whoseplugin-box line this PR moves. The bed's driver is this worktree's own binary,
2026.301.1605,the same build the probe above used. Zero errors, zero warnings, zero advisories, zero skipped
checks, and
git status --porcelainis empty afterwards (.check/is gitignored).Rulebook compliance
/charly-internals:git-workflow,/charly-internals:strict-policy,/charly-internals:go,/charly-internals:cutover-policy,/charly-internals:plugin,/charly-build:reconcileand/charly-check:checkwere loaded before the first source read andbefore the first git action, and this repo's own
AGENTS.mdwas read before acting in it.missed control, blast radius, root fix) is in the Summary above and in the commit message.
Two other anomalies were met on the way and each got its own RCA: the
charly box reconcile --remote --dry-runplan for this repo rewrites 48 pins across ~30 repos, which this change doesNOT do (the tool's granularity is per repo, so the single-repo advance was applied by hand, and
the tool's own plan line for plugin-box is byte-identical to the line this PR carries); and this
repo's
charly.ymlnames plugin-kube at two versions, which is filed under Filed issues.Zero warnings in every gate above:
go vetrc=0,go testrc=0 across both packages,box validate0 warnings 0 errors, the bootstrap's generated-file guard rc=0, and the R10 bed(evidence block 7) with 0 errors, 0 warnings, 0 advisories, 0 skipped checks.
own scheme (
v0.<calver>in the Go module pin,v<calver>in the manifest pin), which is thedual scheme this repo already uses for every other pinned plugin (
plugin-authoringv0.2026271.2244↔v2026.271.2244). No shim, no alias, no second copy of the flag anywherein this repo.
and not tolerated: the new binary REJECTS it (rc=80), which is the probe in How tested.
the product is fixed by the pin, and the prose in other repos (the corpus, the skills) is a
separate leg of the same cutover, named in Filed issues and in the umbrella's fan-out issue.
proven by the claim-keyed sweep in How tested with its calibration, and the new pin is in
both of its homes (part C).
git statuswas stated before every action; this PR is one commit onfeat/plugin-box-stage-parallelism-pinofforigin/main(874a8b11); no force-push, no amendafter the push, no direct push to
main, no hook bypass, and no file outside this repo touched.tested, and it is shown FAILING without the change: on the pre-change build the new spelling
is rejected and the retired one is accepted; on this PR's build the two outcomes are swapped.
The changed path executes live — it is the shipped binary's own command line.
plugin, and the R10 bed above builds, realizes and runs the disposable deployment for real.
(
scripts/bootstrap-charly.sh→./bin/charly), never a shared install;charly versionis2026.301.1605, the stamp of THIS commit, andgo version -mrecords the bumped pluginv0.2026301.1542. No new runtime OS dependency is introduced — a Go module pin is asource-build dependency, not a shipped package dependency — so
packaging/is untouched.change-class bed: the disposable
check-commands-localdeployment, which composes the very pinthis PR moves (
charly.yml:2530) and exercises the plugin'scharly boxverbs end to end. Itsresult is pasted above (evidence block 7):
PASS (steps=6), 448 s, 0 errors, 0 warnings,0 advisories, 0 skipped checks.
Cutover. One cutover, one PR: the compiled-in pin that decides which spelling of the knob the
shipped binary accepts. The config-key surface (this repo's own
charly.yml:55-56) is a differentsurface with a different owner and its own issue, and it is named rather than folded in; the reason
is measured, not asserted:
box validateon this tree is green with the retired keys still in it.Landing. PR-only; the org's
charly/pr-validatoris the merge gate and arms nativeauto-merge on PASS. No agent merges this PR.
Change classification
accepts. Not documentation: the flag's acceptance is behaviour, and the probe above is what
proves it.
fully tested and validated— the change-class gate passed on the finaltree (the repo's own
go vet/go test, the R9 build, and the disposable R10 bed above), andthe changed path was executed live, with the output retained above.
stage_parallelismfan-out tracked instage_parallelism consumer legs: the retired --podman-jobs flag name remains in consumer repos after the BuildKit cutover opencharly#785; it depends on the landed producer (refactor(cli)!: the build concurrency flag is --stage-parallelism, and a control holds every skill body to the grammar plugin-box#66, tag
v2026.301.1542), not on the other consumer legs.Filed issues
podman_jobs_cap keys, and validate accepts them silently". This repo's own
charly.yml:55-56still carries the retired CONFIG-KEY names; the schema drops them silently instead of
rejecting them, so the intent they encode (the inner-concurrency auto cap) is not applied. It is
pre-existing, it is a different surface from this PR's (the config key, not the CLI flag), and
the pin bump does not change it — measured:
charly box validateon this tree is still 0warnings, 0 errors. Non-blocking for this PR, and tracked there.
--remote worsens skew; bare vs pinned refs of one repo can never converge". This repo's
charly.ymlnames plugin-kube at TWO versions —v2026.276.1350on six lines andv2026.295.1506on one — which is the "a candy referenced at two different tags in the resolvedclosure" shape that issue names as one of its two durable asks. Pre-existing and separable from
this PR's plugin-box pin, and tracked there.
name remains in consumer repos after the BuildKit cutover". The fan-out's record and its ordered
leg list; this PR is its leg 2, the leg that moves the SHIPPED binary's compiled-in pin.
Agent: charly · session
ses_8efb271d-f2c0-47d3-85e3-2a1e00b11ae0Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)