Repository navigation
feat(skills): move the cuda skill body to .agents/skills - #18
Conversation
The bodies lived only as inline content: blocks on the skill: nodes. They now live in the repo that owns them, at .agents/skills/<name>/SKILL.md, and each node keeps its routing metadata (name, family, owner, description) with no body of its own. The plugin-marketplace generator reads this shape (skillfile.go): it takes the body from the first declared tree that holds the file and hard-errors when an inline content: disagrees with the file, so no stale second copy can survive.
Review — PASSHead SHA: Security screen: PASS — no injected directives, secrets, new deps, or guardrail weakening; the diff is a faithful content relocation (SKILL.md body byte-matches the removed inline Checklist: All applicable rules PASS or NA. Change class = config + authored skill content (no runtime path, no candy install behavior altered), so no disposable bed is required; the generator-reader gate on the committed tree, Non-blocking note (rulebook gap, not a finding): the How-tested block does not explicitly mark the "disposable target" / "fresh-rebuild" sub-items Verdict: PASS ollama-cloud/deepseek-v4.1-flash — action-review. |
Summary
Moves the 1
cudaskill body out of the manifest and into the repo that owns them:.agents/skills/<name>/SKILL.md. Eachskill:node keeps its routing metadata —name,family,owner,description— and no longer carries a body of its own.The generator reads this shape already:
plugin-marketplace/candy/plugin-marketplace/skillfile.gotakes the body from the first declared tree that holds the file, defaults the id to the node name, and hard-errors when a node's inlinecontent:disagrees with the file — and likewise when itsdescription:disagrees with the file's frontmatter. That is what makes R5 mechanical rather than a convention.Why the gate below is the generator and not
charly box validate:box validatereports no skills at all, and measured on these repos it still returnsrc=0with a relocatedSKILL.mddeleted outright. It cannot see this change, so it is pasted for completeness and not as the proof.How tested
Run on the committed tree at head
a4186be.That last block is why the routing metadata is intact rather than merely asserted: it counts each field in the
base and at the head, so
name,family,owneranddescriptionare shown to survive unchanged while the skill bodies go.contentgoes from 1 to zero. A diff hunk's context is not evidence for this — it shows only the lines near the deletion.Skill nodes at the head that still carry a body: 0 of 1 — which is the claim that
actually matters, and it is counted rather than asserted.
The generator's own reader, from a clone of
plugin-marketplaceat its released state, pointed at this tree:ReadsFromAgentsSkillsasserts the body comes from the file and equals it byte-for-byte, and that the description comes from the file's frontmatter.RejectsStaleInlineBodyasserts the inline-content:disagreement rule fires.The description-equality rule is exercised separately, because the generic reader above passes an empty
description and therefore skips
if s.Description != "" && s.Description != sf.Description. The test passes thenode's real
description:and the log line states the comparison result, not merely byte counts — two stringsthat differ only in newline-versus-space have equal lengths, so equal lengths alone prove nothing. No claim is made
here about the YAML scalar style the node happens to use; the equality is measured, not inferred from the style:
Negative control — the same gate, red: the reader run against a copy of this tree with
.agents/skills/cuda/SKILL.mddeleted:Green on the tree being pushed, red when a relocated body goes missing.
The manifest gate, for completeness:
AGENTS.mdnames every one of these skills, so its enumeration needed no change.Runtime identity
The attribution footer uses the runtime's own names, verified rather than guessed:
The model and provider are read from the harness's own record of this session (keyed by
DSH_SESSION_ID),not from a config file:
record.rows.modelSelection.val.lastUsedis what the runtime wrote for the turns thatproduced this change.
dshis the harness (DeepSeek Harness) anddeepseek-v4.1-flashthe model it reports —the same identity that signs this repo's own validator run.
Rulebook compliance
/charly-internals:git-workflow,/charly-internals:cutover-policyand/charly-internals:skillsloaded before the first git action.nameanddescriptionon the node are the routing identity the generator matches the file against; the generator errors ifdescriptiondiverges, so the two cannot drift silently.git statusread first; worktree off freshorigin/main; no force-push, no bypass, no push tomain.rc=0, with a red control, pluscharly box validaterc=0and zero warnings.Change classification
Config + authored skill content: 1
.agents/skills/*/SKILL.mdfile added, 1 inlinecontent:block removed fromcharly.yml. No runtime, no Go, no pin.Filed issues
opencharly/charly#983—charly box validatedoes not validate skill bodies: a deleted or empty.agents/skills/<name>/SKILL.mdpasses withrc=0. Filed from this leg's evidence. The generator gate above exists in addition to that filing, not instead of it.Agent: charly
Assisted-by: DeepSeek Harness ollama-cloud deepseek-v4.1-flash (fully tested and validated)