Repository navigation
fix(skills)!: the two skill bodies move to the repo root, the one canonical base - #8
Conversation
…onical base The two bodies move from candy/openclaw/.agents/skills/<name>/SKILL.md to .agents/skills/<name>/SKILL.md at this repo's root — the base the marketplace corpus reader resolves for a whole-repo ref. A pure git mv: every blob SHA is identical before and after, so the bodies MOVED rather than changed. Assisted-by: DeepSeek Harness deepseek-v4.1-flash (fully tested and validated)
Review — PASSHead SHA: Security screen: PASS — pure file relocation, no secrets/egress/guardrail weakening. The A3 "validator allowlist" sentence is runtime-identity disclosure backed by pasted config + filed opencharly#538, not an instruction to skip validation. Checklist: All applicable rules PASS or NA. Placement: CORRECT — the reader base is one derivation in sdk ( Tool-limited notes (non-blocking): I cannot re-run Verdict: PASS ollama-cloud/deepseek-v4.1-flash — action-review. |
Summary
The two skill bodies move from
candy/openclaw/.agents/skills/<name>/SKILL.mdto.agents/skills/<name>/SKILL.md— the one canonical base at this repo's root — and the candy-dir treeis deleted in the same commit. This is leg A2 of the ordered wave in opencharly/opencharly#557, and it
copies the shape opencharly/distro-arch#68 landed (leg A9): a pure
git mv, proven by blob-SHA objectidentity, with no dual source and no symlink bridge.
The base both readers resolve is unified in opencharly/sdk —
deploykit.candyRepoRoot, leg A1, mergedbdbfd8cand taggedv0.2026294.1520.Why this PR waited, and why it no longer does. The branch has been pushed and move-proven since the
previous round; the PR was withheld because the corpus leg disagreed with the label on this repo's node:
charly marketplace generateemitted anopenclaw-layerbody matching neither the branch nor itsnewest tag (opencharly/plugin-marketplace#39). opencharly/plugin-marketplace#40 — merged
d0b05ba,tagged
v2026.294.1612— made the project's own pin the authority, and the same three-way comparisonnow holds byte-identically on this node (measured under How tested below). #39 is closed, and this PR is
evidence it asked for.
Why the move is the fix, not a tidy-up. Two readers, two bases, one layout:
plugin-marketplace(skillfile.go)<entity SourceRoot>/<tree>/<name>/SKILL.md— the ref root, i.e. this repo's rootdeploykit.CollectSkills(the label andcharly box validate)<owner candy SourceDir>/<tree>/<name>/SKILL.mdbefore A1;<repo root>after itAt this repo's newest tag before this branch (
v2026.293.1422) the corpus reader could reach neitherof the two bodies, because both sat beside the candy instead of at the root.
The landing window, stated rather than hidden. A reader still on the pre-leg base now refuses this
tree:
charly box validatereports the bodies missing, loudly, naming the tree it looked in (pastedbelow). That is the wave landing in order, not a silent regression, and the same window #68 disclosed.
How tested
The bodies MOVED rather than changed. Byte-identity is proven by git OBJECT IDENTITY — each file's
blob SHA is the same object before and after the move — which does not depend on rename detection:
The count moved, it did not change — 0 to 2 at the root, 2 to 0 in the candy dir:
The diff, both ways it can be read, because the gate reads only one. This worktree carries
diff.renames=falseso the pre-push checker can see the rename SOURCES (opencharly/opencharly#558: its--name-onlyview omits them, so a pure rename's only honest body is refused). The gate thereforesees 149 insertions and 149 deletions across 4 files:
With rename detection on, the same commit is 2 files, two 0/0 renames — no content changed. The
line count is not the evidence; the blob SHAs above are.
A control that can fail, in BOTH directions, plus a third tree where both fail.
generateis thelabel-emitting verb, so it is the control here. NEW is a worktree-local build of
opencharly/charlyat75de486bcarryinggithub.com/opencharly/sdk v0.2026294.1520(the merged, tagged reader leg); OLD ischarly/bin/charly, whosego version -mshowssdk v0.2026293.417:Both diagonals fail, so neither verdict is vacuous: the old reader refuses the root layout, the new
reader refuses the candy-dir layout, and the third tree — bodies deleted from both bases — fails in
both readers, which is what makes the two green cells mean something. The messages name the base
each reader looked under:
The label and the corpus name the same file — the agreement this leg exists to establish. One box
(
openclaw), the emittedai.opencharly.skilllabel, and the corpus generator over a two-ref scratchproject pinned at this branch (the generator module pinned at
plugin-marketplace v0.2026294.1612, thepost-#40 tag;
pod-charly-hooks:v2026.290.1114+@github.com/opencharly/layer-openclaw:feat/skill-bodies-to-repo-root):The corpus file differs from the source only by the generator's 2-line
DO NOT EDITbanner and the oneblank line after the frontmatter; the comparison strips exactly those. Zero warnings means zero
generator warnings — the remaining
WARNING:line is the dev build's own provenance notice that it isnot loading installed plugins, and it is excluded by name in the command above rather than by eye.
Before #40 the same command emitted
1778Bforopenclaw-layerfrom a source neither reader couldname; it now emits
1975B, the branch's bytes.Changed paths executed live, on the final tree:
charly box generate openclawrc=0 (label carriesboth entries),
charly box validaterc=0 with the new reader,charly marketplace generaterc=0.Rulebook compliance
/charly-internals:git-workflow,/charly-internals:cutover-policyand/charly-internals:marketplaceloaded before any git action; this repo's ownAGENTS.mdread first(Part II fix(bed)!: add the openclaw plugin candy via add_candy, so its verb is served over go-plugin #4) — it carries no candy-dir base rule, so nothing in it states the superseded layout and
the sweep is a measured no-op rather than an omission.
deploykit.CollectSkillBodies— the collector sdk#445 added so that "whether a body EXISTS is not a label question" — has no call
site, so
charly box validatewith the new reader returnsrc=0on a tree whose bodies exist atneither base. It is separable from this move (this move's proof uses
generate, the label-emittingverb, and it is fail-closed in every cell above), so it is filed as CollectSkillBodies has no call site: charly box validate returns rc=0 on a tree whose skill bodies exist nowhere sdk#446 and this
body names
generateas the control instead of claimingvalidate. Every gate above reported zerowarnings.
deploykit(
candyRepoRoot), shared by the label collector andheader_copy_remote.go, landed in the sdk leg.git mv, and thebase is computed from the loader's identity without probing the filesystem (
candy_repo_root.go).AGENTS.mdstated no base rule to correct, which is why the same-commit sweep is empty.git ls-filesreports 0 bodies undercandy/*/.agents/(pasted above), and no path is preserved beside the root tree.git status --shortempty before and after the commit; the branch was pushed once, is notforce-pushed, and
mainis untouched.emitted artifacts (the Containerfile label and the corpus file) were read back and compared, not
assumed.
nothing is mocked and nothing is faked.
charly version2026.294.1603,go version -mreportinggithub.com/opencharly/sdk v0.2026294.1520), and the OLD one ischarly/bin/charlyatsdk v0.2026293.417— the exact pair whose bases differ.disposable: truebed exercises skill-body location — this repo's one bed,check-openclaw-pod,builds and deploys a container and probes the gateway, which this move does not touch — so no runtime
bed is claimed here.
separate ordered legs of Restore the repo-root .agents/skills tree as the one canonical base, and move the distro layer candies into layer-* repos opencharly#557, not work this PR leaves half-done.
Change classification
Breaking (
fix(skills)!): the accepted body location changes for this repo, and a reader left onthe candy-dir base now refuses this tree — which is the point, and why the sdk leg is producer-first.
No consumer reads this path programmatically, so there is no migration step; the visible consequence is
charly box validategoing red until the reader leg is adopted, then green.Filed issues
deploykit.CollectSkillBodies(added by sdk#445 to make body existencecomposition-independent) has no call site;
charly box validatewith the merged reader returnsrc=0on a tree whose skill bodies exist at neither base. Found while proving this leg; separable from it,
so filed and disclosed, with
generateused as this PR's control.prepush_body_check's--name-onlyview lacks rename sources, so itis unsatisfiable for a pure rename. This worktree runs
diff.renames=falseand the body pastes bothviews; that is a workaround at the tool's edge and it is filed rather than reported as a clean pass.
leg; A12 is the marketplace re-pin and
generaterc=0).source. This PR pastes the post-fix three-way agreement for the same node.
copy: .agents/skillsinstall step renders no Containerfile directive while its ADE check does sdk#444 — a carrier candy'scopy: .agents/skillsinstall step renders no Containerfiledirective while its dependent ADE
check:does; measured identical before and after this move.Runtime identity (A3)
The delivered system message in this session reads, verbatim:
The runtime's own config agrees — harness
DeepSeek Harness(thedshCLI,@deepseek-ai/dsh),provider
ollama-cloud, model iddeepseek-v4.1-flash:That is the finding opencharly/opencharly#538 records: the footer uses the runtime's exact names, and a
validator allowlist that does not know
deepseek-v4.1-flashis the gap, not this line.Agent: charly
Assisted-by: DeepSeek Harness deepseek-v4.1-flash (fully tested and validated)