Template validator CLI: tier computation + section check, with shared tracker lib (#186) #253

Closed
opened 2026-08-04 11:44:35 +00:00 by jared · 2 comments
Owner

Spec: #250
Blocked by #251

Slice

Template validator in os-backlog's Ruby CLI surface: given an issue number, compute the structural tier (capture/ticket/map per ADR-0092) and report missing/malformed sections against the canonical templates. Build the shared lib this and decision-sweep need (tracker fetch, body/section parsing, label ops) — this lib implements #186's surface.

Acceptance criteria

  • Given an issue with the wayfinder:map label, when validated, then tier is map.
  • Given a body whose ## headings exactly match the ticket template's (case-sensitive, any order, non-empty after stripping HTML comments/placeholders), when validated, then tier is ticket and validation passes.
  • Given duplicate headings, wrong heading depth, or an empty required section, when validated, then the specific malformation is reported and validation fails.
  • Given anything else, when validated, then tier is capture.
  • Given a Blocked by #NNN reference that cannot be fetched, when validated, then validation fails naming the reference.
  • Minitest suite at the CLI/lib boundary: fixture bodies + stubbed tracker fetch, no live tracker; fixtures are the authority for accepted/rejected forms.
  • Ruby, Sandi Metz OOP style; exit code 0 pass / non-zero fail with section report on stdout.

Non-goals

No sweep logic (its own ticket), no label mutations, never runs at capture time.

Spec: #250 Blocked by #251 ## Slice Template validator in os-backlog's Ruby CLI surface: given an issue number, compute the structural tier (capture/ticket/map per ADR-0092) and report missing/malformed sections against the canonical templates. Build the shared lib this and `decision-sweep` need (tracker fetch, body/section parsing, label ops) — this lib implements #186's surface. ## Acceptance criteria - Given an issue with the `wayfinder:map` label, when validated, then tier is `map`. - Given a body whose `##` headings exactly match the ticket template's (case-sensitive, any order, non-empty after stripping HTML comments/placeholders), when validated, then tier is `ticket` and validation passes. - Given duplicate headings, wrong heading depth, or an empty required section, when validated, then the specific malformation is reported and validation fails. - Given anything else, when validated, then tier is `capture`. - Given a `Blocked by #NNN` reference that cannot be fetched, when validated, then validation fails naming the reference. - Minitest suite at the CLI/lib boundary: fixture bodies + stubbed tracker fetch, no live tracker; fixtures are the authority for accepted/rejected forms. - Ruby, Sandi Metz OOP style; exit code 0 pass / non-zero fail with section report on stdout. ## Non-goals No sweep logic (its own ticket), no label mutations, never runs at capture time.
Author
Owner

Scope amendment from the 2026-08-04 review of #251/#257/#258:

Templates blocker (from #251): plugins/os-backlog/references/templates/ticket.md and spec.md were promoted as annotated section listings — headings carry inline annotations (e.g. ## Slice — one sentence: ...) with no bodies. capture.md has the correct fill-in shape (bare canonical headings + placeholder body). Since the validator built here matches headings case-sensitively against the canonical templates, no real ticket — including #251–#258, which use bare ## Slice — would validate against the current files.

First slice of this ticket: reshape ticket.md and spec.md to the fill-in shape (bare canonical headings, placeholder bodies) consistent with capture.md, then build the validator and its fixtures against the reshaped files.

Scope amendment from the 2026-08-04 review of #251/#257/#258: **Templates blocker (from #251):** `plugins/os-backlog/references/templates/ticket.md` and `spec.md` were promoted as annotated section listings — headings carry inline annotations (e.g. `## Slice — one sentence: ...`) with no bodies. `capture.md` has the correct fill-in shape (bare canonical headings + placeholder body). Since the validator built here matches headings case-sensitively against the canonical templates, no real ticket — including #251–#258, which use bare `## Slice` — would validate against the current files. **First slice of this ticket:** reshape `ticket.md` and `spec.md` to the fill-in shape (bare canonical headings, placeholder bodies) consistent with `capture.md`, then build the validator and its fixtures against the reshaped files.
Author
Owner

Resolution

Done: Shipped Backlog::TemplateValidator + validate-template CLI + backend fetch surface

Evidence: 120-run minitest suite green, rubocop zero offenses, opus reviewer APPROVE, merged as 643da05

Follow-ups: none

## Resolution **Done:** Shipped Backlog::TemplateValidator + validate-template CLI + backend fetch surface **Evidence:** 120-run minitest suite green, rubocop zero offenses, opus reviewer APPROVE, merged as 643da05 **Follow-ups:** none
jared closed this issue 2026-08-04 15:46:49 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jared/cc-os#253
No description provided.