Problem
gcplane apply -f shtp --force did not publish a SKILL.md body-only change for shtp/skills/design-shtp.
Observed on 2026-05-29:
goclaw-config had a committed change to shtp/skills/design-shtp/SKILL.md adding reference-image preflight/post-validation rules.
gcplane validate -f shtp passed.
gcplane apply -f shtp --endpoint https://goclaw.dataplanelabs.com --force --auto-approve ran, but the remote skill stayed on v11.
- The plan showed only an overlay/metadata diff for
Skill/design-shtp (visibility: internal -> tenant), not a package/content diff.
- Live server verification still showed
/app/data/tenants/shtp/skills-store/design-shtp/11 as current and no v12 until the skill ZIP was manually uploaded to /v1/skills/upload.
Root Cause Hypothesis
KindSkill.spec.sourceDir is write-only and excluded from diffing. KindSkill is also not in SupportsWriteOnlyHash, so the reconciler cannot detect local package drift when only the body/assets change and observable fields such as name/description/visibility/status/grants do not change.
Relevant code:
internal/manifest/field_config.go: KindSkill write-only fields include sourceDir, version; KindSkill is not in kindsSupportingWriteOnlyHash.
internal/provider/goclaw/skills.go: updateSkill would re-upload if called with sourceDir, but the reconciler never schedules an update when the only drift is the local skill package.
internal/skillpkg/skillpkg.go: already computes a package ContentHash that includes bundled assets, but it is not used as an observable desired-vs-actual signal for KindSkill.
There is a related server-side caveat: GoClaw upload currently hashes only SKILL.md content for idempotency, not the full uploaded ZIP, so asset-only changes may not create a new version even if uploaded.
Expected Behavior
Any committed change under a managed skill directory should be reconciled from git to GoClaw:
SKILL.md body-only changes should create a new skill version.
- Asset-only changes should create a new skill version.
- Agent grants should be repinned to the newly uploaded current version when the manifest declares those grants.
Suggested Fix
Prefer a package-hash design:
- Have gcplane compute
skillpkg.PackDir(sourceDir).ContentHash for KindSkill and include it as a desired package hash.
- Have GoClaw persist and echo a managed skill package/content hash, or at least expose enough hash/version metadata for reconciliation.
- Add
KindSkill to SupportsWriteOnlyHash only after GoClaw persists and echoes the hash.
- On skill package drift, call the existing upload path (
POST /v1/skills/upload with source=gcplane) and then reconcile overlays/grants.
- Ensure grant reconciliation pins agents to the uploaded current version, not stale pinned versions.
Manual Workaround Used
Uploaded the skill ZIP directly to /v1/skills/upload with source=gcplane, which created design-shtp v12, then explicitly repinned lan-runner and thu-ha grants to v12.
Problem
gcplane apply -f shtp --forcedid not publish aSKILL.mdbody-only change forshtp/skills/design-shtp.Observed on 2026-05-29:
goclaw-confighad a committed change toshtp/skills/design-shtp/SKILL.mdadding reference-image preflight/post-validation rules.gcplane validate -f shtppassed.gcplane apply -f shtp --endpoint https://goclaw.dataplanelabs.com --force --auto-approveran, but the remote skill stayed on v11.Skill/design-shtp(visibility: internal -> tenant), not a package/content diff./app/data/tenants/shtp/skills-store/design-shtp/11as current and no v12 until the skill ZIP was manually uploaded to/v1/skills/upload.Root Cause Hypothesis
KindSkill.spec.sourceDiris write-only and excluded from diffing.KindSkillis also not inSupportsWriteOnlyHash, so the reconciler cannot detect local package drift when only the body/assets change and observable fields such as name/description/visibility/status/grants do not change.Relevant code:
internal/manifest/field_config.go:KindSkillwrite-only fields includesourceDir,version;KindSkillis not inkindsSupportingWriteOnlyHash.internal/provider/goclaw/skills.go:updateSkillwould re-upload if called withsourceDir, but the reconciler never schedules an update when the only drift is the local skill package.internal/skillpkg/skillpkg.go: already computes a packageContentHashthat includes bundled assets, but it is not used as an observable desired-vs-actual signal forKindSkill.There is a related server-side caveat: GoClaw upload currently hashes only
SKILL.mdcontent for idempotency, not the full uploaded ZIP, so asset-only changes may not create a new version even if uploaded.Expected Behavior
Any committed change under a managed skill directory should be reconciled from git to GoClaw:
SKILL.mdbody-only changes should create a new skill version.Suggested Fix
Prefer a package-hash design:
skillpkg.PackDir(sourceDir).ContentHashforKindSkilland include it as a desired package hash.KindSkilltoSupportsWriteOnlyHashonly after GoClaw persists and echoes the hash.POST /v1/skills/uploadwithsource=gcplane) and then reconcile overlays/grants.Manual Workaround Used
Uploaded the skill ZIP directly to
/v1/skills/uploadwithsource=gcplane, which createddesign-shtpv12, then explicitly repinnedlan-runnerandthu-hagrants to v12.