You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue was raised during review of PR #1207, triggered by a question about why collections/hve-core-all.collection.md was missing the newly added skill, and a secondary observation that the .collection.md files are not auto-generated despite the plugin README files being auto-generated.
plugins/{id}/README.md is fully auto-generated: it takes the ymlname/description/notice fields for the header, inserts the entire collection.md content as an ## Overview section, then appends auto-built artifact tables (Agents, Commands, Instructions, Skills) from the yml items list.
extension/README.{id}.md follows the same pattern using README.template.md tokens: {{BODY}} = full collection.md, {{ARTIFACTS}} = auto-built artifact tables from yml items.
The hve-core-all.collection.ymlis auto-populated by Update-HveCoreAllCollection (scanning all other collections), but hve-core-all.collection.md is not auto-updated.
Root cause of the PR confusion: When a contributor adds a new artifact to collection.yml, the artifact tables in both generated READMEs update automatically. However, the named bullet lists inside collection.md (e.g., - **OWASP MCP Top 10** — ...) are hand-authored and silently fall out of sync. There is no linting or validation step that detects this gap.
Problem Areas
1. collection.md prose body is not auto-generated
The bullet list sections in collection.md (listing agents, subagents, skills with short descriptions) largely duplicate data already present as YAML frontmatter description: fields on each artifact. When a contributor adds a new artifact to collection.yml and does not update collection.md, the prose body becomes stale.
The ambiguity is worsened because Generate-Plugins.ps1does auto-update hve-core-all.collection.yml with newly discovered artifacts, creating a justified expectation that the companion .md would also update. It does not.
2. Extension README artifact tables do not filter by maturity channel
New-CollectionReadme in Prepare-Extension.ps1 iterates all items from the collection manifest without applying the Channel maturity filter. The function call site (around line 320) also does not pass the active channel. This means the stable extension's marketplace README (extension/README.{id}.md) lists artifact names from experimental and preview items alongside stable ones.
The package.json artifact registration does filter by maturity (via Get-CollectionArtifacts with AllowedMaturities), so the agent picker in stable VS Code correctly omits experimental agents — but the README visible to users on the marketplace says otherwise.
3. collection.md body prose may name experimental artifacts
Because collection.md is hand-authored prose that is inserted verbatim into both the plugin README and extension README, any artifact names mentioned in the prose (e.g., - **Security Planner** — ...) appear in the stable extension's marketplace page. There is no mechanism to conditionally exclude those names from the stable surface.
4. No custom header/intro slot separate from the notice
The ymlnotice: field serves callout blocks (CAUTION, WARNING, etc.), but there is no supported way to add per-collection introductory text (e.g., a one-paragraph why/when of the collection) that appears before the prose body and is distinct from the warning-style notice.
Options to Evaluate
Option A — Auto-generate collection.md entirely from yml + artifact frontmatter
Generate the entire collection.md prose from data already in collection.yml (item paths, kinds) plus description: fields read from each artifact's YAML frontmatter. The script writes collection.md as a generated file.
Pro: Single source of truth; always in sync; removes contributor burden.
Con: Loses ability to write custom non-tabular prose (e.g., narrative context). All prose must come from artifact description: fields, which are intentionally terse one-liners. The generated bullet sections would closely mirror the artifact tables already present below them, adding little value.
Con:hve-core-all.collection.md has deliberate curated prose introducing the mega-collection that cannot be derived from yml alone.
Verdict: Suitable only if the body is intentionally reduced to structured data; doesn't map well to the current narrative style.
Option B — Add header: YAML field to collection.yml; keep collection.md for body prose
Add a multiline header: field to collection.yml (analogous to notice:). Scripts inject it before the collection.md body. The body prose sections (feature lists, agent descriptions) remain hand-authored in collection.md, but are validated.
Pro: Explicit, structured header with version control; easy to see in yml review.
Con: Introduces a second prose field in yml alongside the existing notice:. For collections that don't need a header, the field is just omitted. The core sync problem (body prose vs. yml items) is not addressed.
Option C — Template sections within collection.md (recommended for discussion)
Give collection.md an optional YAML frontmatter block that carries a header: string. Below the frontmatter, the body is partitioned into:
A hand-authored <!-- hve:intro --> block (intro paragraph, preserved as-is).
Auto-generated <!-- hve:agents -->, <!-- hve:skills --> etc. blocks that Generate-Plugins.ps1 regenerates from yml items + each artifact's description: frontmatter.
The script would regenerate only the tagged blocks, leaving the intro unchanged. The plugin and extension READMEs pull the full collection.md as before.
Pro: Keeps customizable intro prose; auto-syncs the artifact bullet lists; container tags make it machine-readable.
Con: More complex script logic. Contributors must not edit inside auto-generated blocks. Tag convention needs documentation.
Option D — Move collection.md body to yml (body: multiline field); auto-generate the artifact lists appended into it
All prose lives in collection.yml as body: multiline text. Artifact bullet sections are appended automatically by the script at generation time. collection.md becomes a generated file and is removed from contributor ownership.
Pro: One file to edit (yml). The generator always produces a complete, correct collection.md.
Con: Multiline YAML prose is harder to write/review than a markdown file. Loss of markdown preview ergonomics.
Immediate Bug to Fix (independent of design choice)
Regardless of which option is chosen for the auto-generation design, New-CollectionReadme in Prepare-Extension.ps1 should receive and apply the active Channel maturity filter when building artifact tables. The $Channel parameter is already available in the calling context and Get-CollectionArtifacts already implements the correct filtering logic. Passing the filtered collection (or filtered artifact lists) into New-CollectionReadme would close the stable-extension-lists-experimental-agents gap.
Questions for Team Discussion
Is auto-generation of collection.md body desirable, or is the hand-authored narrative a deliberate quality bar we want to maintain?
If auto-generation is adopted (Option C or D), should -Refresh on Generate-Plugins.ps1 also regenerate collection.md blocks, or should there be a separate npm run collections:sync command?
For the header: slot: should it live in yml (Option B) or in collection.md frontmatter (Option C)? The yml location is simpler and follows the precedent of notice:.
Should the stable extension README for security/experimental collections explicitly state which items require the Pre-Release channel, rather than just omitting them from the listing?
Context
This issue was raised during review of PR #1207, triggered by a question about why
collections/hve-core-all.collection.mdwas missing the newly added skill, and a secondary observation that the.collection.mdfiles are not auto-generated despite the plugin README files being auto-generated.Cited discussion comments: #1207 (comment)
Current Behavior (by design, but worth revisiting)
The three files involved in producing each published surface (plugin README and extension marketplace README) are:
collections/{id}.collection.ymlnotice:fieldcollections/{id}.collection.mdplugins/{id}/README.mdnpm run plugin:generateextension/README.{id}.mdPrepare-Extension.ps1Generation flow:
plugins/{id}/README.mdis fully auto-generated: it takes theymlname/description/noticefields for the header, inserts the entirecollection.mdcontent as an## Overviewsection, then appends auto-built artifact tables (Agents, Commands, Instructions, Skills) from theymlitems list.extension/README.{id}.mdfollows the same pattern usingREADME.template.mdtokens:{{BODY}}= fullcollection.md,{{ARTIFACTS}}= auto-built artifact tables fromymlitems.hve-core-all.collection.ymlis auto-populated byUpdate-HveCoreAllCollection(scanning all other collections), buthve-core-all.collection.mdis not auto-updated.Root cause of the PR confusion: When a contributor adds a new artifact to
collection.yml, the artifact tables in both generated READMEs update automatically. However, the named bullet lists insidecollection.md(e.g.,- **OWASP MCP Top 10** — ...) are hand-authored and silently fall out of sync. There is no linting or validation step that detects this gap.Problem Areas
1. collection.md prose body is not auto-generated
The bullet list sections in
collection.md(listing agents, subagents, skills with short descriptions) largely duplicate data already present as YAML frontmatterdescription:fields on each artifact. When a contributor adds a new artifact tocollection.ymland does not updatecollection.md, the prose body becomes stale.The ambiguity is worsened because
Generate-Plugins.ps1does auto-updatehve-core-all.collection.ymlwith newly discovered artifacts, creating a justified expectation that the companion.mdwould also update. It does not.2. Extension README artifact tables do not filter by maturity channel
New-CollectionReadmeinPrepare-Extension.ps1iterates all items from the collection manifest without applying theChannelmaturity filter. The function call site (around line 320) also does not pass the active channel. This means the stable extension's marketplace README (extension/README.{id}.md) lists artifact names fromexperimentalandpreviewitems alongside stable ones.The
package.jsonartifact registration does filter by maturity (viaGet-CollectionArtifactswithAllowedMaturities), so the agent picker in stable VS Code correctly omits experimental agents — but the README visible to users on the marketplace says otherwise.3. collection.md body prose may name experimental artifacts
Because
collection.mdis hand-authored prose that is inserted verbatim into both the plugin README and extension README, any artifact names mentioned in the prose (e.g.,- **Security Planner** — ...) appear in the stable extension's marketplace page. There is no mechanism to conditionally exclude those names from the stable surface.4. No custom header/intro slot separate from the notice
The
ymlnotice:field serves callout blocks (CAUTION, WARNING, etc.), but there is no supported way to add per-collection introductory text (e.g., a one-paragraph why/when of the collection) that appears before the prose body and is distinct from the warning-stylenotice.Options to Evaluate
Option A — Auto-generate collection.md entirely from yml + artifact frontmatter
Generate the entire
collection.mdprose from data already incollection.yml(item paths, kinds) plusdescription:fields read from each artifact's YAML frontmatter. The script writescollection.mdas a generated file.description:fields, which are intentionally terse one-liners. The generated bullet sections would closely mirror the artifact tables already present below them, adding little value.hve-core-all.collection.mdhas deliberate curated prose introducing the mega-collection that cannot be derived from yml alone.Option B — Add
header:YAML field to collection.yml; keep collection.md for body proseAdd a multiline
header:field tocollection.yml(analogous tonotice:). Scripts inject it before thecollection.mdbody. The body prose sections (feature lists, agent descriptions) remain hand-authored incollection.md, but are validated.notice:. For collections that don't need a header, the field is just omitted. The core sync problem (body prose vs. yml items) is not addressed.Option C — Template sections within collection.md (recommended for discussion)
Give
collection.mdan optional YAML frontmatter block that carries aheader:string. Below the frontmatter, the body is partitioned into:<!-- hve:intro -->block (intro paragraph, preserved as-is).<!-- hve:agents -->,<!-- hve:skills -->etc. blocks thatGenerate-Plugins.ps1regenerates from yml items + each artifact'sdescription:frontmatter.The script would regenerate only the tagged blocks, leaving the intro unchanged. The plugin and extension READMEs pull the full
collection.mdas before.Option D — Move collection.md body to yml (
body:multiline field); auto-generate the artifact lists appended into itAll prose lives in
collection.ymlasbody:multiline text. Artifact bullet sections are appended automatically by the script at generation time.collection.mdbecomes a generated file and is removed from contributor ownership.collection.md.Immediate Bug to Fix (independent of design choice)
Regardless of which option is chosen for the auto-generation design,
New-CollectionReadmeinPrepare-Extension.ps1should receive and apply the activeChannelmaturity filter when building artifact tables. The$Channelparameter is already available in the calling context andGet-CollectionArtifactsalready implements the correct filtering logic. Passing the filtered collection (or filtered artifact lists) intoNew-CollectionReadmewould close the stable-extension-lists-experimental-agents gap.Questions for Team Discussion
collection.mdbody desirable, or is the hand-authored narrative a deliberate quality bar we want to maintain?-RefreshonGenerate-Plugins.ps1also regeneratecollection.mdblocks, or should there be a separatenpm run collections:synccommand?header:slot: should it live inyml(Option B) or incollection.mdfrontmatter (Option C)? Theymllocation is simpler and follows the precedent ofnotice:.Related
owasp-mcp#1207 — context for this issuescripts/plugins/Modules/PluginHelpers.psm1—New-PluginReadmeContent, plugin README generationscripts/extension/Prepare-Extension.ps1—New-CollectionReadme, extension README generation +Get-CollectionArtifacts(maturity filtering already implemented for package.json but not README)