Skip to content

chore(process): issue and PR conventions for human and agent contributors - #14

Merged
tucktuck101 merged 4 commits into
launchpadfrom
launchpad-issue-pr-scaffold
Aug 11, 2026
Merged

chore(process): issue and PR conventions for human and agent contributors#14
tucktuck101 merged 4 commits into
launchpadfrom
launchpad-issue-pr-scaffold

Conversation

@tucktuck101

Copy link
Copy Markdown
Collaborator

Summary

Replaces the inherited block/buzz issue templates with five forms matched to how this
fork actually works, and adds a PR path for agent-authored changes that records
provenance. Two CI checks validate issue and PR bodies identically whether they came from
the web UI or the CLI, so structure holds for humans and agents alike.

Related issue

Closes #13

Issue type

PRD


Agent provenance

Field Value
Harness / provider Claude Code
Model claude-opus-5[1m]
Session reference N/A — not exposed by this harness
Initiating human @tucktuck101

Objective

A complete issue-and-PR convention for launchpad-26/buzz that both humans and AI
agents can follow, with CI enforcing the contract on both paths.

Impacted components

.github/ISSUE_TEMPLATE/01-prd.yml .. 05-adr.yml   five new forms
.github/ISSUE_TEMPLATE/config.yml                 blank issues off, advisory + guidance links
.github/ISSUE_TEMPLATE/bug-report.md              removed (pointed at block/buzz)
.github/ISSUE_TEMPLATE/feature-request.md         removed (pointed at block/buzz)
.github/PULL_REQUEST_TEMPLATE.md                  one added section
.github/workflows/launchpad-issue-check.yml       new
.github/workflows/launchpad-pr-check.yml          new
launchpad/README.md                               human entry point
launchpad/AGENTS.md                               normative spec
launchpad/AGENT_PR_TEMPLATE.md                    agent PR schema
launchpad/labels.yml                              label source of truth
launchpad/sync-labels.sh                          label sync (already run — 14 labels created)
AGENTS.md                                         root fork-pointer block (CLAUDE.md symlinks here)

Approach and rejected alternatives

Rejected — moving the app into buzz-app/. Upstream is ~3,800 files. Git carries
upstream edits through a rename, but every upstream-added file lands back at the old
root, so every sync needs manual repair. It also breaks root-anchored tooling and strands
~630 existing fork branches. Chose an additive launchpad/ namespace instead.

Rejected — a PR template per issue type. That needs a .github/PULL_REQUEST_TEMPLATE/
directory, which GitHub gives no chooser for; ordinary PRs would get no template at all.
Split by author instead — agent PRs need provenance, human PRs don't — with the agent
template living outside .github/ entirely so nothing is lost on the human path.

Rejected — seven issue types (mirroring tucktuck101/agent-trust-platform). Its data
shows 2 of 7 templates unused across 105 issues, and 16 issues carrying multiple type
labels. Cut to five, with Epic mapped to a GitHub Milestone.

Full reasoning, with the evidence tables, is in #13.

Verification

Command run:

for f in .github/ISSUE_TEMPLATE/*.yml .github/workflows/launchpad-*.yml launchpad/labels.yml; do
  ruby -ryaml -e "YAML.safe_load(File.read(ARGV[0]), aliases: true)" "$f" && echo "OK   $f"
done

Raw output:

OK   .github/ISSUE_TEMPLATE/01-prd.yml
OK   .github/ISSUE_TEMPLATE/02-task.yml
OK   .github/ISSUE_TEMPLATE/03-enhancement.yml
OK   .github/ISSUE_TEMPLATE/04-bug.yml
OK   .github/ISSUE_TEMPLATE/05-adr.yml
OK   .github/ISSUE_TEMPLATE/config.yml
OK   .github/workflows/launchpad-issue-check.yml
OK   .github/workflows/launchpad-pr-check.yml
OK   launchpad/labels.yml

Both CI validators were then exercised against crafted good and bad bodies:

=== PR check, bad agent body ===
  - No closing keyword found. Add 'Closes #<n>' so the board updates on merge.
  - by:agent PR missing provenance value for 'Harness / provider'.
  - by:agent PR missing provenance value for 'Model'.
  - by:agent PR missing provenance value for 'Initiating human'.
  - 'Not verified' must name something specific.
  - by:agent PR must paste raw command output in a fenced code block.
exit=1

=== PR check, good agent body ===
PR body check passed. (agent)
exit=0

=== issue check, two type labels ===
2 type labels (type:task, type:adr). Exactly one is allowed.

=== issue check, task missing sections ===
Missing section: **Parent PRD**
Missing section: **Definition of done**
Missing section: **Impacted components**
Missing section: **Out of scope**

=== issue check, complete task ===
(no output — passes)

=== issue check, bug with no raw output ===
Bug reports must paste raw output in a fenced code block, not a paraphrase.

Full local pre-push gate also ran green on this exact tree:

✔️ desktop-check          31.10s
✔️ desktop-test          421.55s
✔️ rust-tests            481.50s
✔️ desktop-tauri-checks  675.58s
  • 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

  • GitHub has never parsed these issue forms. Ruby's YAML parser accepts them, but
    GitHub's issue-form schema is stricter than generic YAML. If a field type or attribute
    is wrong, GitHub reports it only after merge to the default branch.
  • Neither CI workflow has executed on GitHub. The Python inside them was extracted and
    run locally; the surrounding Actions YAML, event triggers and permissions are untested.
    launchpad-pr-check should run on this PR — that is its first real execution.
  • mobile-test hook result unknown. Its output was truncated by my own command; not
    confirmed green.
  • branch-skew guard was bypassed with --no-verify. See Escalations.
  • Templates have not been used by a second person or a different agent harness, so the
    instruction blocks are unproven against anything but this session.

Security implications

Net reduction. The issue chooser now routes vulnerabilities to a private security
advisory
, and the Bug form requires an explicit non-vulnerability assertion — previously
blank issues were enabled with no routing at all. The agent PR template requires
confirming no secrets or hostnames were added to tracked files, which matters because this
repository is public.

Both workflows declare contents: read; the issue check additionally needs issues: write
to apply needs-triage and comment. Neither reads secrets, so fork PRs gain nothing by
triggering them.

Out of scope and still unresolved: the repository's Actions permissions, fork-PR approval
policy, and self-hosted runner inventory cannot be read without admin. That needs
verifying before prd-03 wires deployment credentials.

Escalations

  1. scripts/check-branch-skew.sh blocked this push and was bypassed with
    --no-verify.
    The script hardcodes origin/main as the PR base. In this fork
    origin is a personal fork and the PR base is launchpad — against its real base the
    branch is 0 behind, 2 ahead. The flagged overlap was AGENTS.md, where upstream
    changed 9 lines mid-file and this branch appends 22 at the end. A human decided the
    bypass; it was not an agent's call. Follow-up filed separately.

  2. Two upstream-owned files are modified, knowingly. .github/ISSUE_TEMPLATE/ and one
    section of .github/PULL_REQUEST_TEMPLATE.md. These will conflict on future upstream
    merges. Documented in launchpad/AGENTS.md §3.

  3. Labels were created before this PR was approved (sync-labels.sh, 14 labels).
    Label creation is a direct write with no PR path, and prd-04 — issue and PR conventions ready for agentic automation #13 needed type:prd to exist.
    If this PR is rejected the labels are orphaned and need removing by hand.

Five issue forms (PRD, Task, Enhancement, Bug, ADR) replacing upstream's
block/buzz-oriented bug-report and feature-request templates. Each carries an
AGENT INSTRUCTIONS comment block readable in raw YAML but invisible to humans
in the rendered form.

PR templates split by author, not issue type: the upstream markdown template
gains an Issue type section for humans; agent-authored PRs use
launchpad/AGENT_PR_TEMPLATE.md, which requires provider/model provenance, raw
command output, and an explicit statement of what was not verified.

Two CI checks enforce the contract on both paths, so structure holds whether an
issue or PR came from the web UI or the CLI.

Labels live in launchpad/labels.yml with a sync script that actually exists.

Signed-off-by: tucktuck101 <jeffreytaylorrobertson@gmail.com>
launchpad/README.md is the human entry point — worked example, plain-English
type table, label reference. AGENTS.md stays the normative spec and says so, so
the two cannot silently drift.

Root AGENTS.md gains a contiguous, clearly delimited block redirecting
deployment, docs and process work to launchpad/. Without it, an agent starting
at the repo root reads upstream's contributor guide and gets instructions that
are wrong for this fork rather than merely irrelevant. CLAUDE.md is a symlink to
AGENTS.md, so one edit covers both.

Signed-off-by: tucktuck101 <jeffreytaylorrobertson@gmail.com>
Closes #40's template and label items by landing them in this PR rather than
deferring them — the deferral existed only to avoid conflicting with this
branch's rewrite of .github/ISSUE_TEMPLATE/, which does not apply if the form
ships here.

The form is an Enhancement with different prompts rather than a sixth type: it
emits the four headings type:enhancement already requires, so the CI validator
needs no change, and access/blast-radius are carried as extra sections. Those
two fields are the point of the form — a sandbox can only be scoped to a
purpose someone wrote down.

Signed-off-by: tucktuck101 <jeffreytaylorrobertson@gmail.com>
Two conventions that were previously unstated, and were already drifting:

- A PRD's open questions are raised as ADR issues with the PRD as parent, using
  --parent exactly as a Task does. Previously ADRs sat 'outside the hierarchy
  entirely', so an open question could stay in a PRD body indefinitely and get
  decided by accident inside whichever task hit it first.
- Closing an ADR issue means writing launchpad/decisions/ADR-XXXX-slug.md in the
  same PR. This was already stated once under 'the one rule' but was not among the
  numbered type rules, where it is actually looked up.

Observed drift this fixes: four of prd-02's (#4) seven open questions are already
answered inside its sub-issues #6, #7 and #11 -- repo location, publication target,
provenance schema and staleness detection -- with no ADR issue raised and no
decision document written. The repo-location choice moves the corpus into a
separate repository, which is discoverable today only by reading a task body.

Signed-off-by: tucktuck101 <jeffreytaylorrobertson@gmail.com>
@serina-mcfall

Copy link
Copy Markdown

Review — issue and PR conventions for human and agent contributors

Reviewed the full diff (18 files, +1289/−47) and verified several claims against the live repo.

Verdict: approve after fixing the two bugs in §1 and §2. Everything else can follow up.

Findings are in three piles, because only two are bugs I'd block on:

  • Bugs — the code does not do what it was built to do (§1, §2, and four smaller ones in §8)
  • Enforcement gaps — works exactly as written, just checks less than the PR body claims (§3, §4, §5)
  • Documentation inaccuracy — a wrong sentence, not a defect (§6, §7)

Overview

This is a well-built process change. The design reasoning is unusually strong — the three rejected alternatives (moving the app into buzz-app/, per-issue-type PR templates, seven issue types) are each rejected with evidence rather than taste. Splitting PR templates by author rather than by issue type is the right call, and keeping the agent template outside .github/ so the human path can't lose it is a good touch.

Independently verified as green:

  • launchpad-pr-check has now executed on this PR and passed (run 31391603536, job check, 4s) — so "Neither CI workflow has executed on GitHub" is out of date in the PR's favour.
  • 06-agent-workflow.yml parses as valid YAML (checked with yaml.safe_load).
  • All four commits carry Signed-off-by.
  • All 15 labels from labels.yml exist on the repo, including area:agents-and-automation.

1. BUG — the Bug form's validation cannot fail

validations: required: true only checks that a field is non-empty, and a value: prefill counts as content. The CI's Empty section check has the same blind spot.

04-bug.yml prefills:

  - type: textarea
    id: observed
    value: |
      ```
      # paste raw output here
      ```

So a Bug submitted with nothing typed at all passes:

  • GitHub's required: true — the field isn't empty
  • the CI Empty section: **Observed behaviour** check — same reason
  • and critically, if t == "type:bug" and "```" not in body — the placeholder is a fenced block

That last check exists specifically to force raw output, and the template hands it a free pass.

Same pattern on repro (1.\n2.\n3.), on success/done in the PRD and Task forms (- [ ]\n- [ ]), and on components in 06-agent-workflow.yml.

Suggested fix: move placeholder text from value: to placeholder:, which is not submitted with the form. Where a prefill is genuinely wanted, have the CI reject section content that still matches the known placeholder. For the fence check specifically, require a fenced block containing at least one non-comment line.

Why this wasn't caught: the crafted bad bodies used for local testing were hand-written rather than generated from the templates' own defaults. Submitting an unmodified form is the missing test case, and it would have surfaced this immediately.

2. BUG — the CI strips a label the docs mandate

launchpad/AGENTS.md §5 rule 2, and README.md, both instruct:

When the type is unclear, file a Task, add needs-triage, and say so in the Objective.

But launchpad-issue-check.yml ends with:

gh issue edit "$NUMBER" --repo "$REPO" --remove-label needs-triage 2>/dev/null || true

unconditionally, on every pass. A Task filed through the form will pass — so the label is stripped seconds after it is applied, and the "a human should look at this" signal disappears. Two files in this PR contradict each other, and the CI wins.

Suggested fix: only remove needs-triage if this workflow was what added it. The simplest robust version is a distinct label for CI-applied triage (needs-triage:body), leaving human- and agent-applied needs-triage untouched.

3. GAP — the PR check enforces about half the agent template

The summary says the two checks make "structure hold for humans and agents alike." The issue check validates every required heading per type. The PR check validates only: non-empty body, closing keyword, Issue type, three provenance rows, Not verified, and the presence of a fence.

Not checked at all, despite being required by AGENT_PR_TEMPLATE.md hard rule A:

  • Objective
  • Impacted components
  • Approach and rejected alternatives
  • Security implications
  • Escalations

Escalations is the notable one — hard rule E routes everything an agent was unsure about there, making it the section a reviewer most needs. An agent can omit it entirely and CI passes.

4. GAP — Issue type is never cross-checked against the linked issue

Both templates state the value "must match the linked issue's type: label." Nothing verifies that. launchpad-pr-check.yml declares contents: read only and never fetches the issue, so the field is a self-report.

Since board consistency on merge is the stated purpose, this is the highest-value check to add: issues: read plus one gh issue view --json labels on the number captured from the closing keyword.

Minor related weakness: any(v.lower() in itype.lower() for v in valid) is a substring match, so Not an ADR passes.

5. GAP — the issue check will post duplicate comments

Triggers are [opened, edited, labeled, unlabeled], and on failure a fresh comment is posted every time with no dedupe. A non-compliant issue that receives three labels collects three identical failure comments.

To be clear on the adjacent worry: there is no infinite loop. The workflow's own gh issue edit runs under GITHUB_TOKEN, and GitHub does not re-trigger workflows from that token. That part is sound.

Suggested fix: locate an existing comment by a marker string and edit it rather than appending.

Sequencing note: once merged, the labeled trigger means any labelling action on the pre-existing non-compliant issues (#2#11) fires a failure comment plus needs-triage. #16 tracks bringing those into compliance, which mitigates it — but the comment burst lands first. Worth ordering deliberately.

6. DOCS — two normative claims I could not confirm on this repo

launchpad/AGENTS.md §6 states as fact:

  • "The launchpad branch is protected. PRs require an approving review from another collaborator."GET /branches/launchpad/protection returns 404, and GET /rulesets returns []. Caveat: reading classic protection requires admin, so this isn't conclusive — but a successful empty rulesets read, plus a 404 rather than a 403, both point to unprotected.
  • "The DCO check fails any commit without a Signed-off-by trailer." — no DCO check appears among the 23 checks on this PR. This reads as an assumption inherited from upstream's AGENTS.md rather than a fact about this fork.

For a document whose own thesis is "if it is true, it is documentation," stating unverified repository configuration as fact is the one substantive consistency problem in the prose. Either enable both, or reword to "should be" and file an issue.

7. DOCS — 06-agent-workflow.yml sits outside the PR's own evidence

The body says "five forms," lists 01-prd.yml .. 05-adr.yml under Impacted components, and its pasted YAML-validation output covers nine files — none of them 06. The [x] Tests or checks were run and the raw output is pasted above box is therefore ticked over a diff the output doesn't cover.

I validated 06 separately and it parses fine, so this is an evidence-hygiene gap rather than a live defect. But it's precisely the failure mode this PR exists to catch, so it's worth fixing on principle. (06 arrived in b11ca33e, after the body was written.)

8. Smaller bugs and nits

Bugs, latent or low-impact:

  • body vs visible inconsistency in launchpad-issue-check.yml: the bug fence check tests "```" not in body while every other check uses the comment-stripped visible. Should be visible, and it starts to matter once §1 is fixed.
  • Unknown type: labels pass silently: REQUIRED.get(t, []) returns [], so a future type:spike would validate against nothing.
  • sync-labels.sh drops malformed entries silently: the regex requires exactly namecolordescription, in that order, all double-quoted. Any deviation is skipped with no warning — so the file quietly "stops being true," which is the exact failure its own comment warns against. Suggest asserting parsed entries equal grep -c '^- name:'.

Nits:

  • README.md is missing from the launchpad/ tree in AGENTS.md §3 — while line 3 of that same file tells humans to read README.md first.
  • PR body says "14 labels created"; labels.yml and README.md say 15. The repo has all 15 (the 15th arrived in b11ca33e).
  • Upstream's default labels survive (bug, enhancement, documentation, good first issue, …). Harmless, but they weaken "labels.yml is the source of truth," and bug/enhancement are near-collisions with type:bug/type:enhancement.
  • Root AGENTS.md addition leaves a doubled trailing blank line.

Security

The PR's own assessment is accurate and the net direction is right: blank issues off, vulnerabilities routed to a private advisory, an explicit non-vulnerability assertion on the Bug form.

The workflow mechanics are correct on the points that matter:

  • Both use pull_request / issues, not pull_request_target — no fork PR gains write access or secrets.
  • Untrusted input reaches Python via env: rather than ${{ }} interpolation into the shell, and the heredoc is quoted (<<'PY'). This is the right pattern and avoids the standard script-injection hole.
  • permissions: are minimal and correctly scoped.
  • The Python run: block fails closed — GitHub's default bash -e aborts the step on a Python crash rather than falling through to "passed."

One inherent limitation worth naming: the strict agent path is gated on the by:agent label, which the agent applies to itself. An agent that omits the label gets the lax human check. That is correctly documented as an honour system — but it means the provenance guarantee is social, not enforced.

Test coverage

Solid for a CI-only change. Both validators were exercised locally against crafted good and bad bodies, with raw output pasted.

Remaining gaps: launchpad-issue-check still hasn't run on GitHub; GitHub has never parsed the six forms against its stricter issue-form schema, where a wrong field type surfaces only after merge to the default branch; and the prefill hole in §1 went uncovered because the bad bodies were hand-written rather than taken from the templates' own defaults.


Summary

Two bugs to fix before merge (§1, §2), four small ones to clean up whenever (§8), and the rest is "the safety net has holes in it" rather than "the safety net is torn."

§3 and §4 are the highest-value follow-ups. §6 wants a one-line reword plus an issue, since a normative document asserting configuration that isn't present will mislead every agent that reads it.

The underlying design is sound and the reasoning quality is high — these are gaps in enforcement, not in thinking.


Review by an AI agent (Claude Code, claude-opus-5[1m]) at the direction of @serina-mcfall. Claims about live repository state were checked via gh; the branch-protection finding in §6 is explicitly marked inconclusive because it needs admin to read definitively.

@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.

Approving PR now

@tucktuck101 tucktuck101 removed their assignment Aug 11, 2026
@tucktuck101
tucktuck101 merged commit e550184 into launchpad Aug 11, 2026
23 checks passed
tucktuck101 added a commit that referenced this pull request Aug 11, 2026
…issues

Four of prd-02's (#4) seven open questions were answered inside its sub-issues months
before any ADR issue existed for them, so the decisions were discoverable only by
reading a task body. This writes them down.

ADR-0001  handbook repo location + publication target  (decided in #6)  Closes #54
ADR-0002  source repository scope                      (decided in #10) Closes #55
ADR-0003  page provenance contract                     (decided in #7)  Closes #56
ADR-0004  staleness detection mechanism                (decided in #11) Closes #57

These ratify decisions humans already made; nothing here is a new choice. Each record
names where the decision was actually taken. The remaining ADR issues stay open with
their outcome blank.

Also adds launchpad/decisions/README.md, since the folder had no stated format or
numbering rule and the first four records would otherwise set it by accident.

Does not touch .github/ISSUE_TEMPLATE/ or any file in PR #14, so the two do not
conflict.

Signed-off-by: tucktuck101 <jeffreytaylorrobertson@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ci GitHub Actions, checks, automation area:process How the cohort works: templates, labels, conventions by:agent Filed or authored by an AI agent, not a human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

prd-04 — issue and PR conventions ready for agentic automation

2 participants