T-3K8K-templates-html-comment-after-frontmatter
Status: closed/done · Impact: medium · Complexity: small
Auto-generated from a /sdlc:task-work post-mortem; reframed via PR review.
Review and promote to ready before picking up.
plugin/entities/*/template.md files currently start with an HTML comment
block, followed by the YAML frontmatter, followed by the body. This ordering
breaks standard markdown frontmatter parsers (Hugo, Jekyll, Astro, MDX,
Pandoc with --yaml-frontmatter, etc.) — all of them require the ---
fence at line 1 to treat the block as frontmatter. The original post-mortem
proposed relaxing validate_frontmatter.py to skip the leading comment; on
PR review (#18) we flipped the framing: fix the templates instead, since
non-standard ordering bites every downstream tool, not just our validator.
Cited by T-J2CW-add-epic-entity-task-depends-on-dependencies.
From the originating post-mortem:
Template files (
plugin/entities/*/template.md) failvalidate_frontmatter.pydirectly because the HTML comment block precedes the frontmatter and the parser’s regex is anchored to\A---.
Validator: plugin/validators/validate_frontmatter.py — front-matter regex
is anchored to \A---. Correct as-is: standard markdown frontmatter
must be the first thing in the file.
Strip-comment regex in the new_*.py scripts:
HTML_COMMENT_AT_TOP_RE = re.compile(r"\A<!--.*?-->\s*\n", re.DOTALL) —
also anchored to \A. When templates are reordered, this regex must move
its target from “before frontmatter” to “after the closing --- fence.”
Affected templates:
plugin/entities/task/template.mdplugin/entities/milestone/template.mdplugin/entities/backlog/template.mdplugin/entities/epic/template.md
Affected scripts (strip-comment logic):
plugin/scripts/new_task.pyplugin/scripts/new_milestone.pyplugin/scripts/new_epic.pyplugin/scripts/new_backlog.py(verify; may or may not have one)
Proposed
Section titled “Proposed”Each template starts with its YAML frontmatter at line 1. The HTML comment
block lives between the closing --- fence and the body’s # Title line:
---type: task# ... frontmatter ...---
<!-- Task template guidance. Delete this comment block once the file is in use. (Same content as today, just relocated.)-->
# <Title>
## Goal...Each new_*.py script’s strip-comment regex is updated to find and remove
the comment from its new location (after the closing --- fence, before
the title). Templates pass validate_frontmatter.py in place without any
validator changes.
Approach
Section titled “Approach”- Move the HTML comment block in all four templates from line 1 to
between the closing
---and the# <Title>line. Preserve the comment’s content verbatim. - Update each
new_*.pyscript’sHTML_COMMENT_AT_TOP_RE(and any strip-comment logic) to locate the comment after the frontmatter. Suggested rename toTEMPLATE_HEADER_COMMENT_REfor clarity; the regex needs to allow optional whitespace between---and<!--. - Verify by running each
new_*.pyscript against its updated template in a/tmpproject root and confirming the generated file has the comment fully stripped. - Add a regression test:
validate_frontmatter.pyagainst every shippedplugin/entities/*/template.mdexits 0.
Files to touch
Section titled “Files to touch”plugin/entities/task/template.md— move HTML comment block after frontmatter.plugin/entities/milestone/template.md— same.plugin/entities/backlog/template.md— same.plugin/entities/epic/template.md— same.plugin/scripts/new_task.py— update strip-comment regex location.plugin/scripts/new_milestone.py— same.plugin/scripts/new_epic.py— same.plugin/scripts/new_backlog.py— same if it has comment-stripping logic.- (Maybe)
plugin/validators/tests/— regression test that every template validates in place. Path uncertain; the validator may not have a tests dir yet.
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Each
plugin/entities/*/template.mdfile starts with---at line 1 and contains its HTML comment block AFTER the closing frontmatter---fence, BEFORE the# Titleline. - AC-2: Running
validate_frontmatter.pyagainst every shippedplugin/entities/*/template.mdexits 0. - AC-3: Running each
new_*.pyscript produces an output file with no leading or post-frontmatter<!-- ... -->comment block (the script still strips the relocated comment correctly). - AC-4: A common third-party frontmatter parser (e.g. Python’s
python-frontmatterpackage oryaml.safe_loadafter a manual----split) successfully parses the frontmatter from each template with no preprocessing.
Out of scope
Section titled “Out of scope”- Validator changes (the validator’s
\A---anchor is correct; we’re making the templates standards-compliant, not the validator more lenient). - Substantive rewrites of the comment contents (move only — content preservation is required).
- Re-architecting the templates to a different format entirely (e.g.
moving guidance to a sibling
template.guide.mdfile).
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of T-J2CW-add-epic-entity-task-depends-on-dependencies on 2026-05-19. Originally framed as “relax the validator.” Reframed on the same day via PR #18 review: the templates are non-standard markdown; the validator isn’t wrong. Standards-compliance fix is cleaner and removes the documentation-vs-code-tolerance tension entirely.
Post-mortem
Section titled “Post-mortem”Captured by /sdlc:task-work on 2026-05-20. PR: pending.
Acceptance criteria coverage
Section titled “Acceptance criteria coverage”- AC-1: agent-manual — ran a Python script in-worktree confirming each
template starts with
---, has its<!--...-->block after the closing frontmatter fence, and the next non-whitespace content after the comment is# Title. - AC-2: auto —
plugin/validators/validate_frontmatter.pyagainst all four templates returns4/4 file(s) passed. - AC-3: agent-manual — ran each
new_*.py(task, milestone, epic, backlog) against a fresh/tmpproject root; generated files contain zero<!--substrings and validate clean. - AC-4: agent-manual —
yaml.safe_loadafter a----split (the same shape downstream tools like python-frontmatter use) returns the expectedtype:field for all four templates.
What worked
Section titled “What worked”- The validator’s own
\A---anchor immediately surfaced the second issue (placeholdercreated: YYYY-MM-DDwas no longer hidden behind the leading HTML comment). One run of the validator made the gap obvious. - Moving the strip-comment step to operate on the post-frontmatter
body(rather than the full text) kept the regex simple — no need to walk past the frontmatter manually.
Friction and automation gaps
Section titled “Friction and automation gaps”- Task spec didn’t anticipate that templates becoming validator-visible
would expose
created: YYYY-MM-DDas a schema violation — had to invent the'1970-01-01'sentinel mid-implementation. Task authoring guidance for “make this file validate” tasks should require a check for placeholder values that the schema would reject, before listing the change as small/medium complexity. → T-SJBT-task-spec-flags-schema-rejecting-placeholders - AC-2 implicitly required templates to satisfy ALL of their schema
(status enum, date pattern, etc.), not just the leading-
---structural requirement. The AC could be tighter: either “validates structurally (frontmatter detected)” vs “validates fully against schema” — different bars. - Approach step 4 (“Add a regression test”) had
Files to touchflag the path as “uncertain” — skipped here as out of scope for a small task, but a follow-up task to wirecheck_entities.py(or a sibling) to also assert “all shipped templates validate clean” would close the AC-2 gap with a CI signal rather than relying on the agent to remember. → T-S99C-project-check-asserts-shipped-templates-validate - Worktree init (
mise trust && just setup-worktree) is a step the task-work skill prescribes universally, but this docs/plugin-only repo has nojustfile, nopackage.json, no lefthook config — the step is a no-op here. The skill could detect “no justfile present” and skip with a one-liner instead of asking the agent to figure out it’s a no-op. → T-FC8W-task-work-graceful-no-justfile-fallback
Spawned follow-up tasks
Section titled “Spawned follow-up tasks”- T-SJBT-task-spec-flags-schema-rejecting-placeholders — created; ensure-ready does a dry-run of files an AC says must validate.
- T-S99C-project-check-asserts-shipped-templates-validate — created; project-check guards templates against future schema drift.
- T-FC8W-task-work-graceful-no-justfile-fallback — linked existing; covers the worktree-init no-op gap.