Skip to content

feat(skills): publish SKILL.md under its frontmatter identity - #4044

Open
twishabansal wants to merge 6 commits into
feat/skills-snapshotfrom
feat/skills-doc-metadata
Open

twishabansal wants to merge 6 commits into
feat/skills-snapshotfrom
feat/skills-doc-metadata

Conversation

@twishabansal

@twishabansal twishabansal commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Description

SEP-2640 fixes a SKILL.md as text/markdown, and takes its name and description from the frontmatter, not from the resource that backs it. Otherwise a client sees a resource called SKILL.md, which does not say which skill it belongs to.

Discovery already parses and validates the frontmatter, so this wraps the SKILL.md resource with the identity it declares. A wrapper keeps SKILL.md's shape out of file, text, and later directory, and applies on every protocol version.

The metadata is fixed until the next reload. Validation ties frontmatter.name to the final URI segment, so only description can drift.

Depends on #4014

SEP-2640 fixes a SKILL.md as text/markdown and takes its name and
description from frontmatter rather than the file backing it. A file
resource would otherwise be listed as "SKILL.md", which tells a client
nothing about which skill it belongs to.

Discovery already parses and validates the frontmatter, so this wraps the
SKILL.md resource with the identity it declares instead of re-reading it.
Wrapping rather than setting the fields in each resource type keeps
SKILL.md's shape out of file, text, and later directory, and applies on
every protocol version -- a client that has not negotiated the skills
extension still sees the files as ordinary resources, and should see a
sensibly named one.

Frozen until the next reload, which is sound here: validation ties
frontmatter.name to the final URI segment, so a name can only change by
renaming the directory, which changes URIs and needs a reload regardless.
Only description can drift, and nothing verifies it.

The wire name still comes from the resources map key, so the name reaches
a client once #4014 wires it to GetName(). Verified by simulating that
change locally: resources/list then reports analytics-guide rather than
the configured key. mimeType and description take effect already.
@twishabansal
twishabansal requested a review from a team as a code owner September 15, 2026 15:36
@twishabansal
twishabansal added this pull request to stack #4016 September 15, 2026 15:37
@twishabansal
twishabansal marked this pull request as draft September 15, 2026 15:37

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces functionality to publish SKILL.md resources under the identity (name and description) declared in their frontmatter, rather than using their backing resource configuration names. It implements a skillDoc wrapper in internal/skills/metadata.go and integrates it into the server's configuration initialization. Tests are also added to verify this behavior. The review feedback suggests making the description field optional in the frontmatter so that a skill is still wrapped and published under its frontmatter name even if a description is not provided.

Comment thread internal/skills/metadata.go
Every existing case builds a map holding a single skill, so nothing pins
that each SKILL.md takes its own frontmatter identity rather than another
skill's. Two skills plus a supporting file close that gap.
WithDocMetadata skipped an entry whose frontmatter name or description
was missing or not a string. Discover cannot produce one, since
Entry.Validate rejects it first, so the branch was unreachable from the
only caller. It was still the wrong behaviour to fall back on: a skip
drops the SKILL.md from the result, and with it the mimeType fix, saying
nothing about why.

It now returns an error. Reusing requiredString keeps the message
identical to the one Entry.Validate would have produced for the same
frontmatter, so a caller assembling entries by hand reads the same
diagnostic wherever the check fires.
@twishabansal

Copy link
Copy Markdown
Contributor Author

TODO (rebase onto #4014): collapse the apply loop in InitializeConfigs.

#4014 keys the runtime resource map by URI (resourcesMap[r.GetURI()] = r).
Once this rebases onto it, key and r.GetURI() are the same string, so the
loop translates a key into itself:

for key, r := range resourcesMap {
    if doc, ok := docs[r.GetURI()]; ok {
        resourcesMap[key] = doc
    }
}

It reduces to maps.Copy(resourcesMap, docs).

Flagging it because
#4014 edits server.go:250 and this edits 260-274the rebase will likely
merge clean and leave the redundant loop in place.

@twishabansal
twishabansal marked this pull request as ready for review September 15, 2026 18:26
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.

3 participants