Skip to content

refactor(cli)!: the build concurrency flag is --stage-parallelism, and a control holds every skill body to the grammar - #66

Merged
github-actions[bot] merged 1 commit into
mainfrom
feat/build-skill-flag-spelling-65
Oct 28, 2026
Merged

github-actions[bot] merged 1 commit into
mainfrom
feat/build-skill-flag-spelling-65

Conversation

@aitrawog

Copy link
Copy Markdown
Contributor

Summary

Head cdc2a9577f2a86ef698dc6400eb0d4c17d2886a9 — the commit this PR pushes: 5 files changed,
345 insertions(+), 27 deletions(-)
.

The inner-concurrency flag of charly box build is renamed to the contract's spelling —
--stage-parallelism / CHARLY_STAGE_PARALLELISM. --podman-jobs / CHARLY_PODMAN_JOBS are
removed: no alias, no shim, no deprecation window.
This is a breaking change to the CLI
surface, which is why the title carries the ! marker.

The BuildKit cutover (opencharly/opencharly#481) renamed the knob podman_jobs →
stage_parallelism in the CONTRACT — the schema key (spec/schema/box.cue:120-121), the sdk
symbol (sdk/buildkit.ResolveStageParallelism), the config key in every defaults: block, and
the prose (opencharly/layer-charly-build#29, merged 2026-10-19, validator PASS). The Kong
grammar in THIS repo was the one surface that did not follow it, and it was false about its own
mechanism: the flag's help read "Stages per podman build" for a driver that is deleted — the
value drives the BuildKit daemon's [worker.oci] max-parallelism
(sdk/buildkit/build_helpers.go:44-47).

That left two live defects, and this PR fixes both:

  1. The published build skill documented a spelling the grammar rejected.
    .agents/skills/build/SKILL.md is published VERBATIM into the opencharly/marketplace corpus,
    so every harness that loads the corpus was handed a command that fails AT THE FLAG:
    charly box build --stage-parallelism N → charly: error: command "build": unknown flag --stage-parallelism (rc=80, measured against the shipping binary — the live proof is pasted
    under How tested).
  2. The pull skill documented --platform, a flag deleted from the pull grammar by bug: charly box pull --platform is a documented no-op — the flag is parsed, never threaded, and any value silently pulls the host platform #40 while
    the body kept its alias-table row and its flag bullet.

Both are the same class, so both get the same control:
candy/plugin-box/skill_doc_flags_test.go reads each of this repo's ten skill bodies from the
path the corpus reads it from, and asserts that every flag and every environment binding each
body presents for its OWN command is one that command's Kong grammar actually defines.
The flag
names and env bindings come from Kong's own parser model, so the surface cannot drift; it is a Go
test and not a prose review because a prose review cannot fail (R7). It reads three claim
surfaces — usage claims (a fenced line or inline span that invokes the command), alias rows (a
table row whose first cell is a --flag), and flag-section bullets — and it deliberately does NOT
read prose that merely mentions the command, because that prose names the HOST's surface (-C,
--dir, CHARLY_PROJECT_DIR), not this plugin's. Both exclusions are stated RULES about which
SURFACE is read, not an allowlist of names, so a later prose rewrite cannot smuggle a false flag
in through a sentence.

The files, and what each one does:

file what it does
candy/plugin-box/box.go the grammar: the flag is --stage-parallelism (CHARLY_STAGE_PARALLELISM), and its help now states the mechanism it actually drives. The comment above the struct records WHY the spelling changed, since a rename without a reason is a mystery to the next reader.
candy/plugin-box/box_test.go the grammar's own parse test carries the new flag, and the env-binding test now binds CHARLY_STAGE_PARALLELISM — the flag's env alias is covered by the same test that covered the old one.
candy/plugin-box/skill_doc_flags_test.go new — the control described above.
.agents/skills/pull/SKILL.md the --platform alias row and its flag bullet are deleted, with no replacement prose: the flag does not exist, so the body says nothing about it.
charly.yml the check-box-local bed's skill-owner fixture is corrected: the control's skill body now lives at the OWNING CANDY'S REPO ROOT, which is the layout every real skill owner uses (the candy under candy/, its .agents/skills/ at the project root) and the layout the sdk's body lookup actually resolves (sdk/deploykit/skills_collect.go → candyRepoRoot). The fixture had written the body BESIDE the candy, so it proved a shape that no real owner uses.

The corpus's build family is re-keyed and regenerated in opencharly/marketplace#587 (already
claimed by this session) — this PR is its PRODUCER leg, and that leg is blocked on this PR's
landing and tag. The flag rename's remaining consumer legs — opencharly/charly's compiled-in pin
(charly/charly/go.mod:15), opencharly/layer-charly-check's prose (charly.yml:709), the
umbrella's parallel-bed-testing.md, and the sdk's stale phrase — are tracked, with their order,
in opencharly/opencharly#785.

How tested

Everything below ran on the committed tree this PR pushes.

# head cdc2a9577f2a86ef698dc6400eb0d4c17d2886a9 (git rev-parse HEAD)
# base b9ed1216c8703ddd800bacc8f189ae06717382bd (git rev-parse origin/main)
# git diff --stat origin/main...HEAD
 .agents/skills/pull/SKILL.md             |   3 -
 candy/plugin-box/box.go                  |  22 ++-
 candy/plugin-box/box_test.go             |  12 +-
 candy/plugin-box/skill_doc_flags_test.go | 303 +++++++++++++++++++++++++++++++
 charly.yml                               |  32 ++--
 5 files changed, 345 insertions(+), 27 deletions(-)

1. The repo's own gate — go build / go vet / go test -count=1 in candy/plugin-box/, plus
gofmt -l.

# cd candy/plugin-box
$ gofmt -l .
GOFMT_RC=0 (empty list above = clean)
$ go build ./...
BUILD_RC=0
$ go vet ./...
VET_RC=0
$ go test -count=1 ./...
ok  	github.com/opencharly/plugin-box/candy/plugin-box	0.026s
?   	github.com/opencharly/plugin-box/candy/plugin-box/cmd/serve	[no test files]
TEST_RC=0

2. The R10 bed — check-box-local, this repo's live witness (a disposable: true kind:local
deploy driven by charly check run: build → artifact checks → realize → deployment checks →
rebuild fresh with charly update → checks again → remove).

# charly check run check-box-local
charly check run check-box-local: [deploy-add] START (charly deploy add; log: .check/check-box-local/2026.301.1531/deploy-add.log)
charly check run check-box-local: [deploy-add] PASS after 1.241s
charly check run check-box-local: [bring-up-members] START
charly check run check-box-local: [bring-up-members] PASS after 0s
charly check run check-box-local: [check-live] START (charly check live; log: .check/check-box-local/2026.301.1531/check-live.log)
charly check run check-box-local: [check-live] PASS after 14.575s
charly check run check-box-local: [update] START (charly update; log: .check/check-box-local/2026.301.1531/update.log)
charly check run check-box-local: [update] PASS after 1.26s
charly check run check-box-local: [cleanup] START (charly deploy del; log: .check/check-box-local/2026.301.1531/cleanup.log)
charly check run check-box-local: [cleanup] PASS after 1.268s
charly check run check-box-local: [cleanup-members] START
charly check run check-box-local: [cleanup-members] PASS after 0s
charly check run check-box-local: PASS (steps=6)
BED_RC=0

3. The structural check at the repo root.

$ charly box validate
charly box validate: OK — checked 1 candy, 1 deploy, 7 distros, 7 builders; 0 warnings, 0 errors

4. The changed path, executed LIVE against the sanctioned worktree-local DEV build
(bash scripts/bootstrap-charly.sh --dev-plugin plugin-box=<this checkout> → built ./bin/charly (2026.301.1224) — DEV BUILD, local plugin source; a DEV build is never installed and never
replaces the released binary). The discriminator is the exit code: rc=80 is Kong rejecting the
flag before anything else runs; rc=1 is the command running on past the parse and failing on the
box name
— so the new flag was accepted and the retired one was not.

# cd <this checkout>
$ charly box build no-such-box-xyz --stage-parallelism 4
charly: error: command "build": scoping generation to requested boxes: unknown box "no-such-box-xyz"
NEW_RC=1

$ charly box build no-such-box-xyz --podman-jobs 4
charly: error: command "build": unknown flag --podman-jobs
OLD_RC=80

The same DEV binary's help renders the renamed flag with its corrected mechanism:

$ charly box build --help
      --stage-parallelism=INT    Stages per build (0=auto: min(NCPU,
                                 defaults.stage_parallelism_cap))
                                 ($CHARLY_STAGE_PARALLELISM)

5. The control fails without the change (R7 — a coverage that cannot fail is invalid). Two red
arms, each produced by restoring the pre-change content, running the control, and restoring the
tree with the file's SHA-256 verified identical before and after the restore.

Arm M1 — the pre-rename tree (the control against the grammar as it was):

--- FAIL: TestSkillBodiesDocumentOnlyRealFlags (0.00s)
    --- FAIL: TestSkillBodiesDocumentOnlyRealFlags/build (0.00s)
        skill_doc_flags_test.go:259: ../../.agents/skills/build/SKILL.md:44: the body documents --stage-parallelism, but charly box build does not define that flag
        skill_doc_flags_test.go:259: ../../.agents/skills/build/SKILL.md:195: the body documents --stage-parallelism, but charly box build does not define that flag
        skill_doc_flags_test.go:259: ../../.agents/skills/build/SKILL.md:197: the body documents --stage-parallelism, but charly box build does not define that flag
        skill_doc_flags_test.go:270: ../../.agents/skills/build/SKILL.md:177: the body pairs --stage-parallelism with an environment variable, but charly box build does not define that flag
        skill_doc_flags_test.go:276: ../../.agents/skills/build/SKILL.md:177: the body pairs a flag with CHARLY_STAGE_PARALLELISM, but charly box build does not bind that environment variable
FAIL	github.com/opencharly/plugin-box/candy/plugin-box	0.004s

Arm M2 — the pull body before the --platform rows were deleted:

--- FAIL: TestSkillBodiesDocumentOnlyRealFlags (0.00s)
    --- FAIL: TestSkillBodiesDocumentOnlyRealFlags/pull (0.00s)
        skill_doc_flags_test.go:259: ../../.agents/skills/pull/SKILL.md:31: the body documents --platform, but charly box pull does not define that flag
        skill_doc_flags_test.go:287: ../../.agents/skills/pull/SKILL.md:132: the body lists --platform among the command's flags, but charly box pull does not define that flag
FAIL	github.com/opencharly/plugin-box/candy/plugin-box	0.004s

Both arms are the control's own findings, not an assertion about the diff: the arm restores the
file, the control reads the restored body against the grammar, and it names the exact line and
the exact flag.

6. R5's claim-keyed sweep — the retired spelling. The claim: the retired flag name and the
retired env name are not a flag, not an env binding, and not a published flag table anywhere in
this repo.

$ grep -rn "podman-jobs\|PODMAN_JOBS\|podman_jobs" . --exclude-dir=.git --exclude-dir=CHANGELOG
charly.yml:349:      # `defaults: podman_jobs must be >= 0, got -1` before the rename, and
charly.yml:355:          the MIGRATED build tunables, NEGATIVE arm: the retired key `podman_jobs` no longer
charly.yml:360:          operator whose charly.yml still says `podman_jobs` loses the setting without a word.
charly.yml:381:                podman_jobs: -1
charly.yml:387:              echo "invocation: box validate  (defaults.podman_jobs = -1, the RETIRED key)"
charly.yml:398:            grep -q 'podman_jobs must be >= 0' "$EV" && { echo 'FAIL: the RETIRED diagnostic still fires - the rule still reads the retired key'; cat "$EV"; exit 1; }
candy/plugin-box/box.go:234:// `CHARLY_STAGE_PARALLELISM`, not `--podman-jobs` / `CHARLY_PODMAN_JOBS`. The CONTRACT renamed that
candy/plugin-box/box.go:235:// knob `podman_jobs` → `stage_parallelism` (spec/schema/buildwire.cue, sdk/buildkit.

Every surviving hit is classified, and none of them is a surface:

  • charly.yml:349-398 — pre-existing, unchanged by this PR (the diff touches charly.yml
    only at 454+). This is the bed's NEGATIVE arm for the retired CONFIG key: it asserts that
    defaults.podman_jobs no longer fires, so the retired key must be named there.
  • candy/plugin-box/box.go:234-235 — the comment that records WHY the flag was renamed. It is
    prose about the retired name, not a flag, an env binding or a published row.

The pull body's --platform is gone, and the build body now matches the grammar:

$ grep -n "platform" .agents/skills/pull/SKILL.md
PLATFORM_RC=1        # no match

$ grep -n "stage-parallelism\|STAGE_PARALLELISM" .agents/skills/build/SKILL.md | head -3
.agents/skills/build/SKILL.md:44:charly box build --stage-parallelism N [image...]    # Max concurrent stages within a single build (0=auto: min(NCPU, defaults.stage_parallelism_cap))
.agents/skills/build/SKILL.md:170:## Parallelism: `--jobs` vs `--stage-parallelism`
.agents/skills/build/SKILL.md:177:| `--stage-parallelism N` | `CHARLY_STAGE_PARALLELISM` | `stage_parallelism` (+ `stage_parallelism_cap`) | **Inner** concurrency: how many stages of a *single* multi-stage build run concurrently. It becomes the BuildKit daemon's `[worker.oci] max-parallelism`, applied when the daemon starts. |

Rulebook compliance

  • R0 — skills first. /charly-build:build, /charly-build:validate, /charly-image:image,
    /charly-internals:plugin and /charly-internals:git-workflow (the five this repo's own
    AGENTS.md names) were loaded before the first source read and before the first git action.
  • R1 — RCA every anomaly. The anomaly is the divergence between the contract's spelling and
    the grammar's; its RCA (mechanism, missed control, blast radius, root fix) is in
    the build skill documents --stage-parallelism / CHARLY_STAGE_PARALLELISM — spellings this plugin's grammar does not accept #65 and, for the cross-repo fan-out, in stage_parallelism consumer legs: the retired --podman-jobs flag name remains in consumer repos after the BuildKit cutover opencharly#785. The
    findings that are not this repo's file are filed, not fixed from here (see Filed issues).
    The red arms in How tested are the proof that the new coverage fails without the change.
    Zero warnings in every gate above: 0 warnings, 0 errors from charly box validate, no
    gofmt output, no go vet output, go test rc=0, the bed's PASS (steps=6).
  • R2 — no duplication. The control is ONE implementation of "a body must not offer a flag the
    grammar lacks", and it reads the grammar through Kong's own model rather than a hand-written
    list of names. The corpus's build family is re-keyed to this repo's owners under
    the build family is published from a DRAINED candy's INLINE manifest: the six repos that now own the fifteen build-family skills are not pinned DIRECTLY, so the corpus keeps the retired engine.build prose marketplace#587 rather than gaining a second copy of a body.
  • R3 — no workaround. No alias, no deprecation shim, no fallback branch, no sleep, no retry.
    The retired flag is removed, not tolerated.
  • R4 — the product first, then the prose. The product is the grammar, and the grammar is what
    changed; the prose change is the deletion of rows for a flag that does not exist. Every command
    this body documents works with the charly binary alone.
  • R5 — legacy deleted completely. The claim-keyed sweep is pasted in How tested, and every
    surviving hit is classified there.
  • R6 — Git safety. git status was clean before every action; this PR is one commit on
    feat/build-skill-flag-spelling-65 off origin/main (b9ed121); no force-push, no amend
    after the push, no direct push to main, no hook bypass.
  • R7 — prove behavior. The control is a Go test that fails on the pre-change tree in two
    independent arms; the changed path was executed live against the DEV build (§4 of How
    tested
    ), and the emitted artifact — the skill bodies the corpus publishes — was verified above
    (at its boundary: the control reads each body from the corpus's own path, and the corpus
    regeneration publishes that same path's content).
  • R8 — live or skip. The bed's steps ran live against a disposable: true local target; no
    service was mocked.
  • R9 — binary equals source. Every live probe ran against the worktree-local DEV build made
    from THIS checkout (bootstrap-charly.sh --dev-plugin plugin-box=<this checkout>, DEV BUILD
    2026.301.1224), never against a shared install.
  • R10 — fresh disposable proof. The change-class gate for a plugin-library change is this
    repo's full assembled bed: charly check run check-box-local PASS (steps=6) on the committed
    tree, including the fresh rebuild through charly update and the removal afterwards. The bed's
    charly.yml fixture change is in the same tree that was gated.

Cutover. One cutover, one PR: the flag, its env binding, its help text, its test, the pull
body's dead rows, the control that holds the bodies, and the bed fixture that the control's
correctness depends on. No deferred phase and no TODO is left inside the scope. The cross-repo
legs are separate PRs in their own repos, tracked by number in opencharly/opencharly#785.

Landing. PR-only; the org's charly/pr-validator is the merge gate and arms native
auto-merge on PASS. No agent merges this PR.

Change classification

Filed issues

  • stage_parallelism consumer legs: the retired --podman-jobs flag name remains in consumer repos after the BuildKit cutover opencharly#785 — "stage_parallelism consumer legs: the retired --podman-jobs flag
    name remains in consumer repos after the BuildKit cutover". Carries the RCA for the whole
    fan-out and the measured referrers: opencharly/charly's compiled-in pin
    (charly/charly/go.mod:15, charly/charly.yml:2530), the marketplace's build-family owner pin
    (candy/charly-marketplace/charly.yml:125), opencharly/layer-charly-check's prose
    (charly.yml:709), the umbrella's .agents/skills/agents/references/parallel-bed-testing.md:596,601,
    and the sdk's stale phrase (sdk/buildkit/build_helpers.go:18). Non-blocking for this PR
    (each site is another repo's file); the order is producer-first, and this PR is the producer.
  • the retired CHARLY_BUILD_ENGINE builder selector is still set and still published layer-container-nesting#16 — "the retired CHARLY_BUILD_ENGINE builder selector is
    still set and still published". Found in the same pass over the corpus's published bodies: the
    contract retired engine.build / CHARLY_BUILD_ENGINE (the removal is pinned in
    opencharly/spec's hostenv/retired_build_selector_test.go and in opencharly/plugin-settings'
    candy/plugin-settings/retired_settings_test.go), yet that repo still ASSIGNS the retired
    variable (charly.yml:143) and still publishes its name in two prose surfaces that reach the
    corpus and the generated docs. Non-blocking for this PR — it is that repo's file, and the
    finding is filed there with the RCA.

Agent: charly · session ses_8efb271d-f2c0-47d3-85e3-2a1e00b11ae0

Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)

…d a control holds every skill body to the grammar

The CONTRACT renamed the inner-concurrency knob `podman_jobs` -> `stage_parallelism`
(spec/schema/buildwire.cue, sdk/buildkit.ResolveStageParallelism) and the builder is
BuildKit — the value drives the daemon's `[worker.oci] max-parallelism`, not
`podman build --jobs N`. The Kong grammar kept the retired driver's spelling, so the
flag's own help read "Stages per podman build" for a driver that is deleted, and the
published build skill documented a spelling the grammar rejected — a command that
fails AT THE FLAG (#65).

This renames the flag and its env binding to `--stage-parallelism` /
`CHARLY_STAGE_PARALLELISM`, deletes the pull skill's `--platform` rows (the flag was
deleted from the grammar by #40 while the body still documented it), and adds the
control that reads each body from the path the corpus reads it from and asserts that
the flags and env bindings it presents for its own command are ones the grammar
defines.

Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)
@aitrawog

Copy link
Copy Markdown
Contributor Author

STATUS

Agent: charly · session ses_8efb271d-f2c0-47d3-85e3-2a1e00b11ae0

PR open: #66 — head cdc2a9577f2a86ef698dc6400eb0d4c17d2886a9, branch
feat/build-skill-flag-spelling-65, base main (b9ed1216c8703ddd800bacc8f189ae06717382bd).
5 files changed, 345 insertions(+), 27 deletions(-).

What is done. The flag rename (--stage-parallelism / CHARLY_STAGE_PARALLELISM), the
retired spelling's deletion, the pull body's dead --platform rows, the control that holds every
skill body in this repo to its own Kong grammar, and the bed fixture correction the control's
correctness depends on. Gated on the committed tree: gofmt clean, go build / go vet /
go test -count=1 rc=0, charly box validate → "0 warnings, 0 errors", and the R10 bed
check-box-local → "PASS (steps=6)". The changed path was executed live against the
worktree-local DEV build: the new flag is accepted, the retired one is rejected with rc=80
"unknown flag --podman-jobs".

What is next. The org's charly/pr-validator verdict; every finding it raises is fixed in ONE
commit per round, and each round's RCA names the missed control.

When the next update is due. As soon as the validator's first verdict lands — and again at
the end of each review round.

Assisted-by: Claude Code minimax/minimax-m3.1-flash:cloud (fully tested and validated)

@github-actions

Copy link
Copy Markdown

Review — PASS

I re-derived every claim against the current body, diffs, and comment. The change is coherent, the arithmetic checks out, and the new control's logic matches the red arms it reports. Details below, file by file.

.agents/skills/pull/SKILL.md (+0/−3)

Deletes the --platform alias-table row and the --platform flag bullet. No replacement prose — correct, since the flag does not exist. The body's sweep (grep -n platform → no match) is consistent with the two removed rows; the removed table row's second cell (charly box pull jupyter --platform linux/arm64) is exactly the inline-span usage claim that Arm M2 reports at line 31, and the removed bullet is the flag-section bullet reported at line 132. Internal consistency holds.

candy/plugin-box/box.go (+15/−7)

StageParallelism is re-tagged name:"stage-parallelism" / env:"CHARLY_STAGE_PARALLELISM", and the help now reads "Stages per build" instead of the false "Stages per podman build." The struct still has exactly nine flags (Push, Tag, Platform, Cache, NoCache, Jobs, StageParallelism, IncludeDisabled, DevLocalPkg) with three env-backed tunables — matching the comment's "same nine flags (including the three env-var-backed tunables)." The explanatory comment accurately cites the contract rename and the BuildKit [worker.oci] max-parallelism mechanism. Note: build retains a --platform flag (see the parse test), which is why build's body may still document it while pull's may not — consistent.

candy/plugin-box/box_test.go (+6/−6)

Parse test now passes --stage-parallelism 2; the env-binding test sets CHARLY_STAGE_PARALLELISM=9 and asserts StageParallelism == 9. This is the same test that previously guarded the retired binding, so the alias coverage is preserved rather than dropped. The parse test still exercises --platform (valid for build), so no false coupling to the pull change.

candy/plugin-box/skill_doc_flags_test.go (+303)

The control's three read surfaces (usage claims, alias rows, flag bullets) and two exclusions (host-surface prose, direct-read diagnostics) are implemented as stated. Tracing the logic against the reported red arms:

  • Build line 44 (fenced charly box build --stage-parallelism …) → usageClaims → flagToken → fails against the pre-rename grammar. ✓
  • Build line 177 (table row, first cell a flag) → aliasRows → both the flag error and the env error. ✓
  • Pull line 31 (inline span starting with the command) → usage claim; pull line 132 (bullet under a flags heading) → flagSectionBullets. ✓
    kongSurface reads names/envs from Kong's model rather than a hand list, and the host-surface exclusion works because --dir / -C / CHARLY_PROJECT_DIR appear in spans that do not begin with the command, so they are never treated as claims. The list case with grammar: nil correctly encodes "no flag surface." The control can fail (proven by the two arms) and reads each body from ../../.agents/skills/<skill>/SKILL.md.

Non-blocking fragility worth noting for a future change: the skill set is a hand-maintained slice, so a newly added skill body is not auto-covered; and the list case assumes that body documents no flag. Neither affects this PR's stated defect (build/pull), and the gate reportedly passes.

charly.yml (+21/−11)

Negative arm: the beside-candy body write is removed and the inline-content: shape still triggers rejection — correct, the negative arm must fail on shape, not on a missing file. Control arm: the body is moved to the project root ($D2/.agents/skills/psk1/SKILL.md), which is the layout the body says candyRepoRoot resolves. The claimed R10 PASS on this same tree is the evidence that the new location resolves; I cannot execute it, but nothing in the diff contradicts it.

One documentation nuance (not a functional defect): the pre-change fixture wrote the body beside the candy and was asserted to validate clean, which implies the lookup found it there; the new comment says the lookup "did NOT look beside the candy." If the R10 PASS is accurate, the lookup must resolve the project root (whether exclusively or in addition), so the fixture change is functionally safe; the "did NOT look beside" wording is at most over-stated. This does not change the pass/fail behavior of the bed.

Honesty / consistency

  • Head SHA, base, branch, and state match the body.
  • Counts reconcile exactly: insertions 0+15+6+303+21 = 345; deletions 3+7+6+0+11 = 27. Five files. ✓
  • The "nine flags / three env-backed tunables" claim matches the struct.
  • The R5 sweep hits (charly.yml:349-398, box.go:234-235) are each classified as non-surfaces, and none is a flag table or binding — consistent with the diff (which touches charly.yml only at 454+).

Security

No secrets, no injection, no privilege change, no new dependency (Kong already used). The new test only reads repository files relative to the package.

Comments

The single comment is a STATUS post by the PR author (@aitrawog) restating the body; it matches the current head/counts and is not a maintainer sign-off. With no designated maintainer comment, the change stands on its own evidence, which it does (repo Go gate + charly box validate + check-box-local R10 + the two red arms).

No blocking defect is derivable from the provided state.

Verdict: PASS


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

View action run

@github-actions
github-actions Bot enabled auto-merge (squash) October 28, 2026 15:41
@github-actions
github-actions Bot merged commit 7a8c8b2 into main Oct 28, 2026
3 checks passed
charly-auto-merge Bot added a commit that referenced this pull request Oct 28, 2026
github-actions Bot pushed a commit to opencharly/opencharly that referenced this pull request Oct 28, 2026
…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)
github-actions Bot pushed a commit to opencharly/docs that referenced this pull request Oct 29, 2026
…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)
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