Skip to content

DRY up artifact frontmatter repetition across skills and subagents #588

Description

@williamthorsen

Problem

After #537 introduced a canonical YAML frontmatter schema across artifact-writing surfaces, the ## Output format YAML examples and the ## Frontmatter resolution prose sections are now repeated across ~18 sites in packages/agents/content/skills/ and packages/agents/content/subagents/. The repetition is structural: universal field placeholders (timestamp, baseSha, sometimes branch/commit/pr) appear byte-identically in every YAML example, and resolution prose follows a near-identical shape with per-site variation only in a handful of fields (provenance.skill value, provenance.isInteractive value, presence/absence of provenance.model).

This will drift from day one. When the placeholder format or resolution narrative changes, 18 sites must be hand-edited in lockstep.

Context

PR #571 (commit 3a980f9d) added a partials feature for skills and subagent definitions. Partials are inlined at install time, so the installed .md output stays byte-identical while authors maintain one source. The current grammar supports:

  • <!-- include: path / --> — self-close, no slot.
  • <!-- include: path --> ... <!-- /include --> — pass children content into a partial's <!-- children --> placeholder.

Reserved-for-future tokens include <!-- slot: name --> (named slots) but parameters are not yet supported. Partials currently live in _partials/ directories at any depth under packages/agents/content/.

A separate companion PR will extract the PR-resolution dispatch snippet (~25-site duplication) into a partial as a clear-cut first application. This ticket covers the harder remaining question of the frontmatter sections themselves.

Considerations

The duplication breaks down into two distinct shapes with different cost/benefit profiles:

  1. YAML frontmatter examples in ## Output format sections (~18 sites). Universal placeholder lines (timestamp: '{ISO 8601 UTC timestamp}', baseSha: '{short SHA of origin/main, omit if unresolvable}', possibly branch:/commit:/pr: placeholders) are byte-identical. Per-site values: skill, isInteractive, and conditionally model. Readers skim YAML examples — they look for distinctive fields and gloss over boilerplate, so partial extraction here has low cognitive cost.

  2. Prose ## Frontmatter resolution sections (~18 sites). A ~10-line resolution list per site. Common spine: timestamp, baseSha, branch, commit, pr resolution lines. Per-site variation: skill value, isInteractive value, model handling (included vs omitted), field-resolution mode (interactive skills resolve themselves via Bash; orchestrated subagents may receive values via dispatch prompt; savings-analyzer only receives via dispatch because it has no Bash). Readers want this contract visible inline — the resolution section is the artifact's contract.

Options

Option A — universal-fields YAML partial only (children-only, ships today).
Extract just timestamp and baseSha placeholder lines into _partials/provenance-universal-fields.md. Each Output format YAML keeps skill, isInteractive, and model inline. Low cognitive cost; high drift prevention on placeholder format.

Option B — universal-spine partial for prose sections (children-only, ships today).
Extract the truly identical resolution lines (timestamp, baseSha, branch, commit, pr-include) into _partials/frontmatter-resolution-spine.md. Each site contributes per-site fields via the children slot. Reduces drift but reduces inline readability of the resolution contract.

Option C — parameter extension to the partials grammar.
Add scalar parameter support (e.g., <!-- include: path skill=foo interactive=false / -->) so a single partial can substitute provenance.skill and provenance.isInteractive values. Reusing the reserved <!-- slot: name --> token is a natural fit. Enables denser DRY but requires conditional rendering (<!-- if model -->) for fields like provenance.model that vary in presence — that's a meaningful grammar extension, not just adding params.

Option D — accept the duplication.
Acknowledge that the universal schema documentation in _data/artifact-conventions.md is the single source of truth and the per-site repetition is enforced by code review rather than mechanism.

Recommendation

Undecided. Option A is the lowest-risk shipment and addresses the YAML placeholder drift cheaply. Option B addresses more duplication but has a real readability cost — worth discussing whether readers actually prefer inline contracts over chasing includes. Option C is the most powerful but is a meaningful grammar change that should be scoped on its own merits rather than as a prerequisite for this ticket.

Likely path: ship A, discuss B explicitly, defer C to a separate ticket if there's appetite for grammar extension.

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactoringImprovement to code without change in functionalityscope:agents

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions