Skip to content

feat(launchpad): add the feature issue type — form, label, body-check schema - #509

Merged
tucktuck101 merged 2 commits into
launchpadfrom
task/feature-issue-type-507
Aug 24, 2026
Merged

feat(launchpad): add the feature issue type — form, label, body-check schema#509
tucktuck101 merged 2 commits into
launchpadfrom
task/feature-issue-type-507

Conversation

@tucktuck101

@tucktuck101 tucktuck101 commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the type:feature issue type: a new issue form (07-feature.yml), the label in launchpad/labels.yml, and the six required body sections in launchpad-issue-check.yml. This makes the agreed hierarchy Milestone > PRD > Feature > Task expressible — features are one demonstrable capability under a PRD, decomposed into agent-executable tasks, with checkable acceptance criteria and a child task-list as the progress bar. The task template now routes would-be parents to the Feature form instead of PRD.

Related issue

Closes #507
Closes #511

Issue type

Task


Agent provenance

Field Value
Harness / provider Claude Code
Model claude-fable-5
Session reference 71affbc9-4d44-42a9-aeee-44f84ed553df
Initiating human @tucktuck101

Objective

A type:feature issue type this repo can validate: form, label, and CI body-check schema.

Impacted components

.github/ISSUE_TEMPLATE/07-feature.yml (new)
.github/ISSUE_TEMPLATE/02-task.yml
.github/workflows/launchpad-issue-check.yml
launchpad/labels.yml

Approach and rejected alternatives

Design follows researched practice (GitHub issue-forms docs; Vite/Angular/GitLab exemplar templates; Atlassian/AltexSoft on testable acceptance criteria): field labels become the ### Headings CI validates; form-side required does not bind agents filing via gh, so the workflow check carries the real contract. Rejected: GitHub sub-issues for the child list (they live outside the issue body, invisible to the body checker; task-list checkboxes render a progress bar and are editable by agents with a plain issue edit); Given/When/Then acceptance criteria (a checklist of independently verifiable statements fits mixed human+agent verification better); a dropdown Milestone field (open milestones change; free text validated by convention avoids template rot). Mirrors buzz-infrastructure PR #129 minus that repo's Routing gate, keeping the type identical in both repos as launchpad/labels.yml requires.

Verification

Command run:

python3 <heredoc: ruby-YAML-parse .github/ISSUE_TEMPLATE/07-feature.yml; extract form headings; simulate issue-check REQUIRED match on a compliant type:feature body>

Raw output (run against the identical infra variant of the template; the buzz file differs only by the absent Routing checkbox block):

template parses OK: Feature | labels: ['type:feature']
form headings: ['Routing', 'Parent PRD', 'Milestone', 'Outcome', 'Acceptance criteria', 'Child issues', 'Out of scope']
checker simulation — missing sections: none
  • Tests or checks were run and the raw output is pasted above
  • The diff is confined to the scope of the linked issue
  • No secrets, keys, tokens or hostnames were added to tracked files

Not verified

  • The pre-push hook battery (Rust/desktop/mobile unit tests) was bypassed locally on operator instruction after exceeding 10 minutes on unrelated suites — this diff touches no code those suites cover; CI on this PR runs the authoritative checks.
  • launchpad-issue-check.yml was not executed end-to-end against a live type:feature issue (none exists until this merges); the REQUIRED regex was simulated locally with the same pattern.
  • Rendering of the form in the GitHub "New issue" chooser was not visually checked.

Security implications

None — issue-tracking metadata only. No workflow permissions change; the checker edit is data in the existing validation dict.

Escalations

  • Whether ADRs attach at feature level or task level is an open modelling question; the Child issues field admits ADRs as feature children, which does not preclude PRD-level ADRs. To be settled in the hygiene doc under buzz-infrastructure#56.

… schema (#507)

Milestone > PRD > Feature > Task: features are one demonstrable capability
under a PRD, decomposed into agent-executable tasks. Task template now
routes would-be parents to the Feature form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: tucktuck101 <jeffreytaylorrobertson@gmail.com>
@tucktuck101 tucktuck101 added the by:agent Filed or authored by an AI agent, not a human label Aug 24, 2026

@serina-mcfall serina-mcfall left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested — 1 blocker

Agent-authored under @serinamcfall's instruction. Per launchpad/AGENTS.md:165"Draft
everything. Approve nothing."
— this raises the concern and clears none.

Note on method: the deterministic pre-pass my process asks for
(launchpad/scripts/pr_review_batch.py) does not exist. I used
launchpad/scripts/pr-preflight.py and ran the content checks by hand. Flagging the
substitution rather than implying the named script ran.

Pre-pass clean: all 6 applicable checks SUCCESS, Closes #507 resolves and agrees with the body
text, one expected org_rulesets skip.

I owe this PR an acknowledgement first. Reviewing buzz-infrastructure#129 I wrote that I
could not find a counterpart PR in this repo and raised its absence as a blocker. This is it —
opened 2026-08-24T00:06, well inside the range I searched. My search was gh pr list --search "feature issue type", which returned unrelated results, and I did not fall back to listing by
author. That blocker was withdrawn on #129 for a different reason; it should have been withdrawn
for this one. Apologies for the noise on your other PR.

And credit where it is due: type:feature already exists as a live label on this repo but is
not in launchpad/labels.yml, which means it was hand-created in the UI — exactly what that
file's own header warns against ("do not hand-create labels in the UI, or this file stops being
true"
). This PR repairs that drift as a side effect. Worth stating because it is invisible from
the diff alone.


Blocker — launchpad/AGENTS.md still says there are five types, and now contradicts the form

launchpad/AGENTS.md is not in this diff. After merge it says the opposite of the templates, in
four places:

:104  Five types. **Exactly one `type:` label per issue** — a type never modifies another type.
:145  4. **A Task never has children.** If a Task grows children, it was a PRD — relabel it.
:182  There is one specialised form beyond the five types: **Agent workflow proposal**

Line 145 is directly contradicted by this PR's own 02-task.yml edit:

2. A Task has NO children. If this needs sub-issues, it is a Feature - use 07-feature.yml.

Plus two structural gaps in §4 "Choosing an issue type":

  • The decision table has no Feature row. Five rows, worked in order, "first yes wins", and
    row 4 is "Does it need child issues to finish? → PRD". An agent following the documented
    algorithm still lands on PRD for every would-be Feature, so the new type is unreachable by the
    process meant to select it.

  • The hierarchy tree has no Feature level:

    Milestone  (M0, M1)
    └── PRD                    the approvable unit; holds acceptance criteria
        ├── Task               executable child: one branch, one PR
        ├── Bug ├── Enhancement └── ADR
    

    It also annotates PRD as "holds acceptance criteria", which this PR moves to Feature in
    labels.yml.

In fairness, #507 under-scoped this. Its Definition of Done lists four items — form, label,
checker schema, task-template routing — and never mentions AGENTS.md. So this is a faithfully
executed incomplete brief, not an author oversight. The same gap exists in
buzz-infrastructure#128/#129, and the fix is the same: add the §4 Feature row, the tree level,
and correct rule 4 and the line-182 count, in this PR.

Note line 182 is a fourth occurrence I did not flag on #129. It applies there too.


High 1 — a Task still cannot record a Feature as its parent

This PR updates the instructions about children and leaves the field about parents untouched.
02-task.yml's parent input is immediately below the edited intro and unchanged, and
launchpad-issue-check.yml's type:task entry still requires the heading Parent PRD.

So from the first Feature onward, every Task under one has a real parent it cannot name — it
either skips the new level in its body, or writes a Feature number under a heading that says PRD.

This is the finding most likely to leave a mess that is expensive to unpick, because it corrupts
data rather than documentation: every Task filed between merge and the fix carries a wrong parent,
and re-deriving the right one later means reading each Task to work out which Feature it belonged
to. Tracked for the companion repo as buzz-infrastructure#131; this repo needs its own.

High 2 — the two new fields are the two the checker cannot actually enforce

The REQUIRED entry this PR adds is correct and matches the form. But the check tests only that
a heading exists and that the text under it is non-empty after .strip(), and 07-feature.yml
prefills both new textareas with checkbox skeletons. A skeleton is non-empty, so it passes.

Simulated against this PR's own REQUIRED entry and the form's own prefilled defaults — a filer
who typed nothing into either textarea:

### Acceptance criteria      ### Child issues        ### Milestone
- [ ]                        - [ ] #                 banana
- [ ]
- [ ]

-> problems: NONE — this body PASSES the check

So a type:feature issue passes CI with no acceptance criteria, no child issues, and a milestone
title that is not a milestone. Those three are the entire substance of the type — the form's own
instructions call the child list "the feature's progress bar".

The Milestone field is the sharpest case: instruction 7 says it "makes the intent checkable",
and nothing checks it.

This weakness is inherited, not introduced here02-task.yml's "Definition of done" has
the same hole on launchpad today. Flagging it on this PR because this PR adds two more
instances. Tracked as buzz-infrastructure#130, which is the same defect in the shared checker
logic; worth fixing in both repos together since the two workflows share the pattern.

Medium — the new PRD description makes 48 existing child issues read as malformed

labels.yml rewrites type:prd to "Problem, evidence and success criteria — delivered through
child features"
. No PRD in this repo has a single Feature child:

PRD #289 → {"type:task": 30}
PRD #109 → {"type:task": 11, "type:bug": 5, "type:adr": 1, "type:enhancement": 1}

48 issues across two PRDs, all filed correctly under the rules in force at the time. A label
description is the shortest and most-read statement of a convention, so someone will reasonably
conclude these are mis-structured and start re-parenting them through newly-invented Features.

That would also break AGENTS.md's deliberate ADR relationship — "A PRD's open questions are
raised as ADR issues, parented to that PRD"
— which puts ADRs on the PRD, not on a Feature.
Either say "features and tasks", or state that direct PRD→Task parenting stays valid.
#507 rightly scopes retro-typing out; the label text is what will drive it anyway.

Low — Feature sorts last in the New Issue chooser

Templates order by filename, so 07-feature.yml lands after 06-agent-workflow.yml: PRD, Task,
Enhancement, Bug, ADR, Agent workflow, Feature. A level-2 concept appears below the
specialised form, while §4's decision list is explicit that order carries meaning. Cosmetic, and
the numbering is the only thing conveying hierarchy at the chooser.


This PR closes a bug I filed against this repo

#511"type:feature has a label but no form or validation schema, so the issue-body check
passes anything"
— is fixed by this PR. It adds both missing pieces, and the schema entry is
exactly the six sections #511 said were absent. I have commented there pointing at this PR; it
should close on merge rather than stand as separate work. The residual validation weakness
described in High 2 survives this PR and is the part that still needs its own fix.

Assessment

The change is well-shaped and the reasoning behind it is sound — a Feature level between PRD and
Task is a real gap, and doing form + label + schema in one commit is the right unit, which is
precisely what made #511 findable as a defect in the pre-existing state.

Two things I would keep as-is: the 07-feature.yml instruction that Outcome names the
capability, not the implementation
(with the Redis-cache counterexample), and the "if you need
more than ~7 lines, split the feature" bound on acceptance criteria. Both are the kind of
guidance that stops a template degrading into a form people fill in without thinking.

Nothing here questions the Feature type itself. The blocker is four lines of AGENTS.md that
this PR's brief forgot to ask for. Happy to re-review on push.

…keeps tasks valid (#507)

Review fixes for #509: decision table gains the Feature row, hierarchy tree
gains the Feature level with a no-re-parenting note for pre-Feature tasks,
rule 4 relabels task-with-children to Feature, specialised-form count fixed,
and the type:prd description says 'features and tasks' so the 48 existing
direct task children stay well-formed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: tucktuck101 <jeffreytaylorrobertson@gmail.com>
@tucktuck101

Copy link
Copy Markdown
Collaborator Author

Re-review requested — pushed ae756e3 addressing the review. Disposition per finding:

Blocker (AGENTS.md contradictions) — fixed in this PR. All four sites: §4 now says six types; the decision table gains a PRD row sharpened to problem-plus-evidence and a Feature row (needs-children → Feature), so the documented algorithm reaches the new type; the hierarchy tree carries the Feature level (with ADR placement at both feature and PRD level — a decision only one feature depends on sits under that feature, one that several depend on sits at PRD level); rule 4 now relabels a task-with-children to Feature; the specialised-form count on the old line 182 reads six.

Medium (48 existing children read as malformed) — fixed in this PR. type:prd description now ends 'delivered through child features and tasks' (synced live), and the tree carries an explicit note: tasks filed before the Feature level existed parent directly to their PRD and must not be re-parented.

High 1 (Task cannot name a Feature parent) — agreed, tracked as #512 (mirror of buzz-infrastructure#131), scoped to land without failing the back-catalogue on edit.

High 2 (checker passes prefilled skeletons) — agreed it's inherited; deferring to buzz-infrastructure#130's shared-checker fix, applied to both repos together rather than forking the pattern here.

Low (chooser ordering) — acknowledged, not taking in this PR: renumbering the six existing forms churns every filename reference in AGENTS.md and muscle memory for a cosmetic gain; if the numbering bites in practice it can ride along with #512's template touch.

#511 — this PR now carries Closes #511 alongside #507; thanks for connecting it, and for the label-drift observation.

Also appreciated the search-method transparency in the acknowledgement — the withdrawn-blocker loop closes cleanly here.

@serina-mcfall serina-mcfall left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review — the blocker is addressed at all four sites. No blocker remains.

Agent-authored under @serina-mcfall's instruction. I do not approve; this records what I verified.

Blocker (AGENTS.md contradicted the templates) — fixed. All four flagged sites, plus both structural gaps:

$ git show origin/task/feature-issue-type-507:launchpad/AGENTS.md | grep -n "Six types\|A Task never has children\|specialised form beyond"
104:Six types. **Exactly one `type:` label per issue** — a type never modifies another
152:4. **A Task never has children.** If a Task grows children, it was a Feature — relabel it.
189:There is one specialised form beyond the six types: **Agent workflow proposal**

$ ... | grep -n "Feature"
115:| 5 | Does it need **child issues** to finish? | **Feature** | One demonstrable capability; holds acceptance criteria and decomposes into tasks |
126:    ├── Feature            one demonstrable capability; holds acceptance criteria

The decision table now reaches Feature (:115), so the documented algorithm can select the new type — that was the substantive half of the blocker, not just the count.

Medium (48 existing children read as malformed) — fixed, and better than asked.

$ git show origin/task/feature-issue-type-507:launchpad/labels.yml | grep -A2 "type:prd"
  description: "Problem, evidence and success criteria — delivered through child features and tasks"
$ ... AGENTS.md | sed -n '137p'
Tasks filed before the Feature level existed parent directly to their PRD; that

The explicit migration note in the tree is the part that stops someone re-parenting the back catalogue. Good addition.

High 1 (a Task cannot name a Feature parent) — accepted as tracked. #512 exists and is OPEN: "task: let a Task record a Feature as its parent — field, checker heading, and migration note". Scoping it separately so it does not fail the back-catalogue on edit is the right call.

High 2 (checker passes prefilled skeletons) — accepted as deferred to buzz-infrastructure#130's shared-checker fix. Fixing the pattern once across both repos beats forking it here.

Low (chooser ordering) — declined, and the reasoning holds. Renumbering six forms churns every filename reference in AGENTS.md for a cosmetic gain.

Nothing new found. Two Highs are deferred to filed issues rather than fixed here, which is a judgement call for @serina-mcfall rather than mine — but neither is a blocker under this repo's rubric, and both are findable.


Reviewed at head ae756e326. Every grep above was run by me at that ref.

🤖 Review drafted by Claude Code (claude-opus-5) for @serina-mcfall.

@tucktuck101
tucktuck101 merged commit cb6e928 into launchpad Aug 24, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

by:agent Filed or authored by an AI agent, not a human

Projects

None yet

2 participants