From c757046e77f2a7f8449a9c2a4b535b92da7b3488 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Thu, 8 Oct 2026 20:18:04 +1100 Subject: [PATCH 1/3] fix(registry): preserve root Skill snapshots --- COPY.md | 2 + .../registry/app/components/SkillDetail.vue | 12 +-- .../registry/app/components/SkillFileTree.vue | 2 +- .../app/components/SkillFileTreeNode.vue | 3 +- .../app/components/_SkillBehaviors.vue | 8 +- .../server/api/skill-asset/[...slug].get.ts | 88 ++++--------------- .../server/api/skills-raw/[...slug].get.ts | 4 + .../server/api/skills/[...slug].get.ts | 47 +++++++--- .../server/presenters/skill-detail-v1.ts | 5 +- layers/registry/server/utils/github-client.ts | 3 +- .../registry/server/utils/skill-behaviors.ts | 6 +- layers/registry/server/utils/skill-license.ts | 30 +++++++ .../server/utils/skill-md-render.spec.ts | 12 +++ .../registry/server/utils/skill-md-render.ts | 4 +- .../server/utils/skill-stored-source.ts | 20 +++-- layers/registry/server/utils/sync-repo.ts | 48 +++++----- migrations/0148_skill_snapshot_commit.sql | 15 ++++ test/unit/skill-asset-tree-outage.test.ts | 36 +++++--- test/unit/skill-behaviors-panel.nuxt.test.ts | 7 ++ test/unit/skill-detail-behaviors.test.ts | 22 +++++ test/unit/skill-detail-d1-cost.test.ts | 3 +- test/unit/skill-detail-swr.test.ts | 2 +- test/unit/skill-detail-v1.test.ts | 3 + test/unit/skill-file-tree-root.nuxt.test.ts | 21 +++++ test/unit/skill-license.test.ts | 20 +++++ test/unit/skill-page-behaviors.test.ts | 10 +-- test/unit/skill-stored-source.test.ts | 18 ++-- test/unit/skills-raw-stored.test.ts | 5 +- test/unit/sync-repo-correctness.test.ts | 23 +---- test/unit/sync-repo-streaming.test.ts | 70 ++++++++++++++- test/unit/sync-repo-unreadable-blob.test.ts | 2 +- 31 files changed, 367 insertions(+), 184 deletions(-) create mode 100644 layers/registry/server/utils/skill-license.ts create mode 100644 migrations/0148_skill_snapshot_commit.sql create mode 100644 test/unit/skill-file-tree-root.nuxt.test.ts create mode 100644 test/unit/skill-license.test.ts diff --git a/COPY.md b/COPY.md index 6029172c..ca0c0348 100644 --- a/COPY.md +++ b/COPY.md @@ -157,6 +157,8 @@ The Skill behaviors panel shows a behavior reading under each SKILL.md match tha Name the model plainly, as a language model. Never call a reading a review, a scan, a safety call, or a false positive. The strings live in `layers/registry/app/components/_SkillBehaviors.vue`. +- If the rules fail: `Skill behaviors are unavailable. Run skilld run to check every file.` + - Each match: `SKILL.md:42 · Quoted example. {reason}`. `behaviorVerdictLabel` in `shared/behavior-readings.ts` owns the five labels: `Instruction`, `Quoted example`, `Prohibition`, `Documentation`, `Unclear`. - Panel note, shown when a match has a reading: `A language model read each match that needs approval in its context. Its reading is no guarantee and changes no approval.` - The skilld CLI approval message adds `(model reading: quoted example. {reason})` to each match, and ends its list with `A language model on skilld.dev wrote each model reading. A reading is no guarantee and changes no approval.` The CLI owns that string, so change it there first. diff --git a/layers/registry/app/components/SkillDetail.vue b/layers/registry/app/components/SkillDetail.vue index 3eb102d3..88b29434 100644 --- a/layers/registry/app/components/SkillDetail.vue +++ b/layers/registry/app/components/SkillDetail.vue @@ -122,7 +122,7 @@ interface SourceFacts { capabilityScopes: ('read' | 'write' | 'exec' | 'net')[] mcpServers: string[] } - behaviors: SkillBehavior[] + behaviors: SkillBehavior[] | null } interface NeighborSkill { @@ -191,6 +191,7 @@ const skillFetch = useFetch( githubUrl: string description: string | null license: string | null + licenseSource: 'skill' | 'repository' | null stars: number forks: number pushedAt: string | null @@ -446,8 +447,7 @@ const { data: skillFiles } = useFetch( total: number } | null>> -// Prefer the live ungh-walked file list when available (catches markdown -// siblings the sync job hasn't registered yet); fall back to data.assets. +// Prefer the stored file inventory endpoint; fall back to detail metadata. const treeAssets = computed(() => { if (data.value?.sourceGone) return [] @@ -1655,7 +1655,7 @@ useHead(computed(() => ({ v-if="licenseFile" type="button" class="skill-chip skill-chip-link" - :title="`License: ${data.license}. Opens ${licenseFile}.`" + :title="`${data.licenseSource === 'repository' ? 'Repository license' : 'License'}: ${data.license}. Opens ${licenseFile}.`" @click="() => { void resolveAndOpen(licenseFile!) }" >