fix(den-api): parse YAML frontmatter in deriveProjection to prevent SKILL.md name/description mangling#2355
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@adityadeshlahre is attempting to deploy a commit to the Different AI Team on Vercel. A member of the Team first needs to authorize it. |
Reproduction (live API test)Bug reproduction — create a config object with only curl -X POST "http://localhost:8788/v1/config-objects" \
-H "Cookie: better-auth.session_token=<session>" \
-H "Content-Type: application/json" \
-d '{
"type": "skill",
"sourceMode": "cloud",
"input": {
"rawSourceText": "---\nname: laptop-refresh\ndescription: 4-step laptop refresh / ServiceNow request policy for the Sales team\n---\n\n## Steps\n\n1. Check warranty status\n2. Submit ServiceNow request\n3. Schedule technician visit\n4. Confirm receipt"
}
}'Before (broken { "title": "---", "description": "name: laptop-refresh" }After (fixed { "title": "laptop-refresh", "description": "4-step laptop refresh / ServiceNow request policy for the Sales team" }The fix also correctly handles the subsequent install flow — when |
|
Took a close read through this — the fix is at the right layer and reusing the file-local One residual edge I think is worth handling before merge: Description still gets mangled when frontmatter has const descriptionCandidate = [
// ...
typeof frontmatterDescription === "string" ? frontmatterDescription : null,
rawSourceText
? rawSourceText.split(/\r?\n/g) /* ...scans the frontmatter lines... */
: null,
]A SKILL.md with const { data: frontmatter, body } = rawSourceText
? parseMarkdownFrontmatter(rawSourceText)
: { data: {}, body: "" }
// ...use `body` instead of `rawSourceText` in the firstTextLine / raw-scan branchesTwo smaller notes:
Nothing blocking on the primary reported scenario — the title/description fix itself is solid. |
|
---------- Forwarded message ---------
Gönderen: Nikhil ***@***.***>
Date: 26 Haz 2026 Cum 16:19
Subject: Re: [different-ai/openwork] fix(den-api): parse YAML frontmatter
in deriveProjection to prevent SKILL.md name/description mangling (PR #2355)
To: different-ai/openwork ***@***.***>
Cc: Subscribed ***@***.***>
*Pablosinyores* left a comment (different-ai/openwork#2355)
<#2355 (comment)>
Took a close read through this — the fix is at the right layer and reusing
the file-local parseMarkdownFrontmatter (the same helper the GitHub-import
path already uses) keeps the two create paths consistent without pulling in
a new YAML dep. Candidate ordering looks right too: explicit metadata/
payload still win, frontmatter slots in above the raw heuristic.
One residual edge I think is worth handling before merge:
*Description still gets mangled when frontmatter has name: but no
description:.* The new frontmatterDescription is only added as a candidate
— the heuristic fallback below it still scans the un-stripped rawSourceText:
const descriptionCandidate = [
// ...
typeof frontmatterDescription === "string" ? frontmatterDescription : null,
rawSourceText
? rawSourceText.split(/\r?\n/g) /* ...scans the frontmatter lines... */
: null,]
A SKILL.md with name: but no description: (allowed) leaves
frontmatterDescription undefined, so the scan falls through to the
frontmatter block and picks up name: <value> as the description — the same
class of bug this PR fixes for the title. Suggest destructuring the body
once and feeding it to the fallback, mirroring the GitHub path which
already passes parseMarkdownFrontmatter(...).body:
const { data: frontmatter, body } = rawSourceText
? parseMarkdownFrontmatter(rawSourceText)
: { data: {}, body: "" }// ...use `body` instead of `rawSourceText`
in the firstTextLine / raw-scan branches
Two smaller notes:
- deriveProjection has no direct test coverage, and this path was wrong
in production — a unit test asserting {title, description} for a
frontmatter SKILL.md (plus the no-description case above) would lock it in
cheaply.
- Minor: the file-local parser is case-sensitive on keys and treats |/>
block scalars literally. There's a more robust exported parser in
@openwork-ee/utils (parseFrontmatter); not needed for this fix, but a
follow-up consolidating both paths onto it would be more correct.
Nothing blocking on the primary reported scenario — the title/description
fix itself is solid.
—
Reply to this email directly, view it on GitHub
<#2355?email_source=notifications&email_token=BZI5ZUNPHSHJPGUDRNQE5YL5BZZ7PA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIOBQHE4TIOBWGY4KM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#issuecomment-4809948668>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BZI5ZUK5QVGO2F7OHANH4RT5BZZ7PAVCNFSNUABGKJSXA33TNF2G64TZHMYTCMZTHEYTCMZTGU5US43TOVSTWNBXGI4TSMRVGA3DTILWAI>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/BZI5ZUMFHI2ZQWVAL24YWOD5BZZ7PA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIOBQHE4TIOBWGY4KM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSVGM33PORSXEX3JN5ZQ>
and Android
<https://github.com/notifications/mobile/android/BZI5ZULKRSTGPIN2E6AUROT5BZZ7PA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIOBQHE4TIOBWGY4KM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSXGM33PORSXEX3BNZSHE33JMQ>.
Download it today!
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Pablosinyores
left a comment
There was a problem hiding this comment.
Nice catch on parsing the frontmatter. One thing on the title path though: frontmatterName is added after metadata.name/payload.name/metadata.title/payload.title in the titleCandidate array, and since .find returns the first truthy entry, whichever of those already carries the cob_... id will still win — so the name half of #2350 looks like it stays broken. Only the description half is actually fixed here, because frontmatterDescription is placed before the raw-source fallback.
The reported output (name: "cob-01k...") is the tell: one of metadata.title/name or payload.title/name is populated with the config-object id on member install, which outranks the new frontmatterName. Moving frontmatterName ahead of the metadata/payload name candidates — similar to how materializeGithubImportedObject strips frontmatter into projectionRawSource before deriving — should make the name resolve correctly too.
Worth adding a test that asserts the installed name equals the original skill name (laptop-refresh), not just the description, so the title path is actually covered.
Problem
When a member installs a shared skill from the org Marketplace, the materialized
SKILL.mdfrontmatter is wrong:namebecomes the config-object id (cob_...) instead of the real skill namename:line is nested intodescriptionRoot Cause
deriveProjection()inee/apps/den-api/src/routes/org/plugin-system/store.tsextractstitleanddescriptionwhen creating config objects, but never parsed YAML frontmatter fromrawSourceTextfor markdown-based types (skill, agent, command).firstTextLine()→ returned"---"→ stored as title---→"name: laptop-refresh"was the first hitFix
Parse YAML frontmatter using the existing
parseMarkdownFrontmatter()helper and insertname/titleanddescription/summaryas high-priority candidates before the raw-text heuristics.Reproduction Evidence
Before (broken) — config-object create response:
{ "title": "---", "description": "name: laptop-refresh" }After (fixed) — config-object create response:
{ "title": "laptop-refresh", "description": "4-step laptop refresh / ServiceNow request policy for the Sales team" }