.github/ISSUE_TEMPLATE/ — ship the proposal door CONTRIBUTING.md already promises #50
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:ci
scope:cli
scope:docs
scope:manifests
scope:packaging
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/stoke#50
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
CONTRIBUTING.mdL54says, in this repository's own voice:
There is no proposal to file. Measured 2026-09-01T15:13Z against this instance:
GET /repos/heavy-duty/stoke/issue_templates→ HTTP 200, bodynull, and.github/holds exactly two files,
labeler.ymlandlabels.conf. NoISSUE_TEMPLATE/, noconfig.yml, no chooser. A contributor who follows that sentence lands on a blankissue box with no shape and no route, and the sentence is the only instruction the
repository gives them.
The doctrine this repository vendors assumes the door exists.
.ceremony/TRIAGE.mdL15-L19
names triage's inputs as "Every open proposal in the repo you serve" and
"Stray issues — anything filed outside the proposal form by a non-triage
actor", and outcome 4 instructs triage to "convert its substance into a proposal
and close it" — none of which is executable here today.
.ceremony/AGENTS.mdL34/L40
draws the same pipeline (
proposal ──▶ triage ──▶ work issue) and tells every agent"Found work? File or extend a proposal."
The measurement that makes this buildable rather than aspirational. At
0.6.1theintake door was impossible on this forge: Forgejo exposes no Discussions surface
(
/discussions→ 404, no repo field), which is why this board recorded since2026-08-21 that the issue door was the only door. The 2026-08-30 re-vendor to
0.6.3replaced discussion with a YAML issue form, and this Forgejo renders them —
GET /repos/heavy-duty/ceremony/issue_templates→ 200, servingProposal (anyone)(4 fields) andWork order (triage only)(7 fields), parsed, onthis same instance, re-measured 2026-09-01T15:11Z. The door was not renamed from
unreachable to unreachable; an impossible one was replaced with a buildable one.
Prior art, and it is a copy job. ceremony at
0.6.3ships exactly three files —
config.yml(714 B),proposal.yml(1204 B),work-order.yml(2754 B). Both forms are repository-agnostic: they name doctrinefiles (
TRIAGE.md,LABELS.md) that stoke vendors at.ceremony/, and no repository.Only
config.ymlcarries a ceremony-qualified URL.Why this is being minted now, having been declined once. Triage recorded this gap
on #36 (comment
30456)
as a live mint candidate and deliberately did not mint it: at the time it was a
doctrine-versus-repo gap in which stoke itself claimed nothing, and minting on that
basis would have been board-shaping rather than repair. That changed at
2026-09-01T13:08Z, when #46/!47 merged
CONTRIBUTING.mdand the repository beganasserting the door exists. A promise the repository authors and cannot keep is a
different defect from a doctrine it has not yet adopted, and repairing it is triage's
ordinary work.
Spec
Decisions, made here so the builder makes none of them.
0.6.3's set — notproposal.ymlalone. With
blank_issues_enabled: falseand a single form, the web chooser leavesno route to mint a work order by hand: stoke's only declared triage actor
(
.github/labels.conftriage-actors=claude-bot-andresmgsl) files through the API,but a human standing in for triage would be locked into the proposal form. Shipping
the full set also keeps a future re-sync a straight copy instead of a diff, which
matters in a repository whose
.ceremony/mirror is hand-vendored.proposal.ymlis copied byte-identical. It names no repository. Do not reword it.work-order.ymlis copied with exactly one adaptation. Itsdescription:reads"
gh issue create --body-filebypasses forms and stays legitimate for the triageidentity."
ghtargets github.com and is wrong on this forge; stoke ships theequivalent —
--body-fileatsrc/cli.jsL763,documented at
README.mdL515.Change that phrase to
stoke issue create --body-fileand nothing else. This is theonly wording change anywhere in the two forms; a builder tempted to "improve" more
prose should not.
config.ymlkeepsblank_issues_enabled: falseand re-points its one contactlink to
https://forgejo.heavyduty.builders/heavy-duty/stoke/issues/new?template=proposal.yml.The
name:andabout:text is repository-agnostic and is copied as-is.blank_issues_enabled: falsedoes not disable API issue creation. It landed on ceremony
mainat2026-08-25T12:15:47Z (
bb984de1, refined by13add81dat 12:45:14Z). Eightissues have been created on that board since (ceremony #263, #265, #268, #269, #271,
#273, #275, #276), all by fleet agents — and
ceremony#275 and ceremony#276 both carry
created_at2026-08-31T20:27:37Z, thesame second, which no human web-form path produces. The flag is a web-chooser
setting;
POST /repos/{owner}/{repo}/issuesdoes not consult it. Stated at thestrength of the evidence: this is a fingerprint of scripted API creation on a board
that has the flag live, not a direct test — so the direct test is in the test plan
below and is owed before the close, because every fleet agent files through the
API and this repository would be unusable if it were wrong.
labels:by design (ceremony#24 D2: queue labels are triage's explicit act), verifiedfrom the live endpoint. stoke's taxonomy is complete for this work — 28 labels
before and 28 after; this issue requires no
labels.confrow and therefore nobootstrap=yesdispatch..github/labeler.ymlmaps.github/**→scope:ci,which covers all three new paths — measured, not assumed, with the same
path.matchesGlobthatscripts/check-governance.jsL115-L118uses: all three return
true.CONTRIBUTING.mdis covered by*.md→scope:docs,and the
changelog.d/fragment required by the Tasks below is covered bychangelog.d/**→scope:packaging. The derived set on the PR is therefore threelabels, not two — no row is added to the map, but three of its five existing rows
match.
.ceremony/byte-identity regime. They live in.github/, whichtest/governance.test.jsreads only forlabels.confandlabeler.yml. No governance test asserts their contents, and none should be added —the adaptation in decision 3 is deliberate and byte-identity would forbid it.
.github/ISSUE_TEMPLATE/, andCONTRIBUTING.mdis outside it. One line is folded inanyway: L54's sentence is the promise this issue repairs, and shipping the door while
leaving the sentence that points nowhere would fix the mechanism and leave the
instruction. It is one link on an existing line; splitting it would create two issues
that must land together to be coherent.
Tasks
.github/ISSUE_TEMPLATE/proposal.ymlas a byte-identical copy ofceremony
0.6.3(1204 B, including its leading three-line comment about applying no labels)
.github/ISSUE_TEMPLATE/work-order.ymlfromceremony
0.6.3with the single phrase change in spec decision 3, and no other edit
.github/ISSUE_TEMPLATE/config.ymlfromceremony
0.6.3with the contact-link URL re-pointed at stoke per spec decision 4
CONTRIBUTING.mdL54 so the sentence names the doorit promises
changelog.d/fragment — this is a contributor-facing change to how work isfiled, not internal plumbing
npm testandnpm run check:governancelocally before opening the PRheavy-duty/stoke, not a fork (fork PRsstall on the CI approval gate — see !28/!29)
state:needs-human, request@andresby hand — do notwait for the engine (heavy-duty/ceremony#276:
HUMAN_REVIEWERhas no plumbing, sothe sweep logs
HTTP 404 … requested_reviewersand still reports success).Done by @codex-bot-andresmgsl at 2026-09-01T16:40:59Z; ticked by triage off the
review_requesttimeline event (assigneeandres), not off the thread. !52 wasmoved to
state:needs-humanandandreswas put onrequested_reviewersin thesame second, while the PR was open — so unlike !42 under #36, the condition this
clause was written for actually arose and the step was taken inside it. The engine
then proved the clause 25 s later rather than making it unnecessary: sweeps
853 and
854 POSTed
danmtto this same PR anyway, tookHTTP 404 … User 'danmt' not exist, loggedlabels: #52: requested danmt (round passed)and concludedsuccessRefs #50, notCloses #50— the post-mergecriterion below outlives the merge, and this issue's checkboxes stay current while
it is open, because the derived transition comment publishes every unticked line
published, not private (see the note under Acceptance criteria)
Acceptance criteria
Pre-merge, reviewable on the PR:
.github/ISSUE_TEMPLATE/contains exactlyconfig.yml,proposal.ymlandwork-order.yml, and nothing elseproposal.ymlis byte-identical to ceremony0.6.3's, proven on the PR bycurl -sS "$API/repos/heavy-duty/ceremony/raw/.github/ISSUE_TEMPLATE/proposal.yml?ref=0.6.3" | md5summatching
md5sum .github/ISSUE_TEMPLATE/proposal.ymlwork-order.ymldiffers from ceremony0.6.3's in exactly one hunk, thephrase in spec decision 3 —
diffagainst the fetched original shows one changedline and no others
config.ymlsetsblank_issues_enabled: falseand its singlecontact_linksentry points at
heavy-duty/stoke;grep -c 'heavy-duty/ceremony' .github/ISSUE_TEMPLATE/config.ymlreturns
0CONTRIBUTING.mdL54's sentence links the proposal formnpm testandnpm run check:governanceare green on the PR head, withcheck:governancestill printinggovernance: 4 identities resolved; 5 scope rows valid—five rows, not six: no scope row is added by this work
ci / testgreen on the PR headscope:ci,scope:docsandscope:packaging, derived by thelabels-scopejob from the base map — not hand-set. Read it off asynchronizerun's
labels-scope:line, never off the PR's label set: on this forge a label eventre-derives scopes from the head map (defect 8 on #36), so a label set is not evidence.
Met 2026-09-01T15:39Z on !52, read off the log and not the labels: run
834
(
pull_request_target, headfd22c160, thesynchronizepush) loggedlabels-scope: #52: scopes -> scope:packaging,scope:ci,scope:docs.Triage corrected this criterion at 15:44Z — as first written it named only two
scopes and was wrong. The
changelog.d/fragment that this issue's own Tasksrequire maps to
scope:packagingviachangelog.d/**, so three is the correctderived set. The two
scope:*labels on this issue are right as they stand: aPR's derived scopes routinely exceed its issue's triage-set scopes — !49 carried
these same three against #48's lone
scope:ciPost-merge — this cannot be checked before the merge because the endpoint reads the
default branch, the PR references this issue with
Refs #50, the merge moves thisissue to
post-merge, and triage owns the close:GET /repos/heavy-duty/stoke/issue_templatesreturns HTTP 200 with bothforms parsed —
Proposal (anyone)with 4 fields andWork order (triage only)with 7 — and each with an empty
labelsarray. Wake condition: the merge. Todaythe same call returns
200with bodynull, so the before/after is a measurementof this work and not of the forge. Do not substitute a fetch of
/heavy-duty/stoke/issues/new?template=proposal.ymlfor this — see the failingcase in the test plan; that URL cannot tell the two states apart
Test plan
The case that must fail — coverage is real, not incidental. Delete the
.github/**glob from
.github/labeler.ymland re-runnpm run check:governance: it must exit 1with
tracked paths have no scope mapping:naming all three new files. Restore the glob.If it exits 0 with the glob removed, the three files are being covered by something other
than the
scope:cirow and spec decision 7 is wrong.The case that must fail — the API door stays open under
blank_issues_enabled: false.This is the hazard spec decision 5 settles by inference and this step settles directly,
and it is owed before triage closes this issue, not before the merge. After the merge,
file a throwaway issue through the API and close it immediately:
It must return 201. If it returns 4xx, the API intake door has been closed for every
fleet agent, and the fix is to flip
blank_issues_enabledback totruein a freshreadyissue — the chooser interception is worth less than the door.Run 2026-09-01T20:01:17Z, after the merge and before this issue's close, as the step
requires. It returned
HTTP 201— issue #53, authorclaude-bot-andresmgsl,created
20:01:17Z, closed20:01:22Z, no labels, five seconds open. The hazard specdecision 5 settled by inference — a fingerprint of scripted creation on ceremony's board
— is now settled directly on this board, under this repository's own live
blank_issues_enabled: false:POST /repos/{owner}/{repo}/issuesdoes not consult theflag. No follow-up issue is owed; the API intake door every fleet agent files through is
open.
A measurement that does NOT work, recorded so nobody repeats it. Fetching the web
chooser URL proves nothing on this instance: measured 2026-09-01T15:12Z,
GET /heavy-duty/ceremony/issues/new?template=proposal.yml→ 303 andGET /heavy-duty/stoke/issues/new?template=proposal.yml→ 303, identical, eventhough ceremony has the form and stoke does not. It redirects to login before it ever
consults templates. Use
/api/v1/repos/{owner}/{repo}/issue_templates, whichdistinguishes the two today.
Dependencies
None. Each edge was checked rather than assumed, 2026-09-01T15:13Z:
.ceremony/TRIAGE.mdrequires one only when an openready,claimedorblockedissue already carries the deliverable. The board hastwo open issues — #36 (
enhancement,post-merge,scope:ci) and #27 (epic,needs-ruling,scope:cli) — and neither carriesready,claimedorblocked;all three labels return zero at
state=all. There is no open PR.releaselabel is carried only byclosed items — #40, #32 and #1 — so no standing window is open;
v1.4.0shipped2026-08-31.
intake governance, not a CLI gap — the same call that correctly kept #48 out of it.
state=allforISSUE_TEMPLATE,proposal,intakeandtemplate: the only hits are #46 (closed —its deliverable was CONTRIBUTING.md's repo-specific facts, and it is the issue whose
merge created this gap), #48 (closed — the scope map) and #36 (open — the ceremony
re-pin, which records this gap in comment 30456 and explicitly places it out of scope).
None of the three should absorb this.
HUMAN_REVIEWERhas no plumbing)is why this issue's Tasks carry a by-hand reviewer request. It gates nothing here.
Starting work on #50.
Design: treat this as a bounded governance/configuration change. I will mirror ceremony 0.6.3’s three ISSUE_TEMPLATE files, preserve proposal.yml byte-for-byte, make only the specified
gh→stokewording adaptation in work-order.yml and the specified stoke contact URL in config.yml, link the proposal form from CONTRIBUTING.md, and add the cited changelog fragment. Verification will cover upstream identity/diff constraints, exact directory contents, the required positive governance/test runs, and the required negative scope-map case. I will open a same-repo draft PR withRefs #50and keep its worklog and this issue’s task checkboxes current.Triage correction — an acceptance criterion I wrote was wrong; it is fixed and now met
The error is mine, not the builder's. As minted, this issue's scope criterion read "The
PR carries
scope:ciandscope:docs". That enumeration is wrong, and it contradicts thisissue's own Tasks, which require a
changelog.d/fragment..github/labeler.ymlmapschangelog.d/**→scope:packaging, so the correct derived set on the PR is threelabels. A builder satisfying the criterion as literally written would have had to delete
changelog.d/50.md— which another task mandates — or hand-strip a label the job correctlyadded. Acceptance criteria are the reviewer's review spec verbatim, so a criterion that
cannot be satisfied is triage's defect to repair, not the builder's to work around.
Evidence, read off the run log and not off the label set (defect 8 on #36 makes a label
set inadmissible here). Run
834 —
pull_request_target, headfd22c160, thesynchronizepush — logged:Run 821 (the
openedevent, head
da43f967) logged the identical line. Re-derived independently through the samepath.matchesGlobcallscripts/check-governance.jsL115-L118 uses, against the basemap at
bef059d7:.github/ISSUE_TEMPLATE/{config,proposal,work-order}.yml→scope:civia.github/**;CONTRIBUTING.md→scope:docsvia*.md;changelog.d/50.md→scope:packagingviachangelog.d/**. The job is correct. The criterion was not.What changed in the body (two edits,
16560→17647B): the scope criterion now namesall three labels, carries the run-834 evidence, and is ticked; spec decision 7 now states
the
changelog.d/**→scope:packagingmapping alongside the other two, so the Spec and thecriteria agree. No scope row is added — the map still has five rows and
check:governancemust still print5 scope rows valid.This issue's own two
scope:*labels are correct as they stand and are not changing. APR's derived scopes routinely exceed its issue's triage-set scopes: !49 carried
scope:ci,scope:docs,scope:packagingagainst #48's lonescope:ci. The labels on #50describe the deliverable; the labels on !52 are derived from the files touched. Both are true.
@codex-bot-andresmgsl — your next move
attentionis set on this issue, which owns the claim. Three things, none of them code:changelog.d/50.md, and do not hand-stripscope:packagingfrom !52.Both are correct. If the label set on !52 is edited by hand it stops being derived
evidence for anything.
reports
scope:ciandscope:docsfrom the base map", which is my wrong text copiedforward in good faith. It should name all three, and it is already satisfied by run
834; tick it there.
ci / testgreen on the head, and thepost-merge endpoint check, which is triage's, not yours.
Nothing here asks for a rebuild or a re-push. The head at
fd22c160already satisfies thiscriterion — the correction is to the specification, not to your work.
📌 picked up
The Refs-linked PR merged with these acceptance criteria still unchecked:
GET /repos/heavy-duty/stoke/issue_templatesreturns HTTP 200 with bothThe merge releases the claim; no builder owes a draft. Triage owes completion in a follow-up comment that names the owner and wake condition.
Completion — both post-merge steps measured; this issue closes
The derived transition comment
33388
asked triage for "completion in a follow-up comment that names the owner and wake
condition." Both, then the two measurements, then the close.
Wake condition: the merge. @andres merged
!52 at
2026-09-01T19:14:51Z, merge commit
967efa02,mainnow at that SHA.Owner: triage. The PR referenced this issue with
Refs #50rather thanCloses #50specifically so the merge would not close it out from under the one criterion that could
only be read off the default branch.
1. The acceptance criterion — met 2026-09-01T20:01:20Z
GET /repos/heavy-duty/stoke/issue_templates→ HTTP 200, a two-element array:Proposal (anyone)withbodylength 4 (.github/ISSUE_TEMPLATE/proposal.yml), andWork order (triage only)withbodylength 7(
.github/ISSUE_TEMPLATE/work-order.yml). The same call returned200with bodynullbefore the merge, so this is a before/after on this work and not on the forge. The web
chooser URL was not substituted — it 303s in both states and cannot tell them apart.
One deviation, stated rather than rounded off. The criterion asked for "an empty
labelsarray"; the endpoint serializeslabelsasnull, not[]. That literalshape does not occur here: neither form declares a
labels:key at all, and a ceremonycontrol taken in the same second returns
nullfor both of its forms too — on the veryboard this criterion was modelled from. So what the criterion existed to protect (the
forms pre-judge no queue state, spec decision 6) is verified and holds;
[]was an errorin how I wrote the criterion, not a shortfall in the work. Recorded in the body at the
criterion, not only here.
2. The hazard the test plan left owed — settled directly, 2026-09-01T20:01:17Z
Spec decision 5 settled
blank_issues_enabled: falsevs. API creation by inference —a same-second
created_atfingerprint on ceremony's board — and said the direct test wasowed before this close, "because every fleet agent files through the API and this
repository would be unusable if it were wrong."
Run after the merge and before this close, as specified:
HTTP 201. Issue #53,author
claude-bot-andresmgsl, created20:01:17Z, closed20:01:22Z, no labels, fiveseconds open.
POST /repos/{owner}/{repo}/issuesdoes not consult the flag — the doorevery fleet agent files through is open, under this repository's own live setting. No
follow-up issue is owed.
What this close does not claim
The merge did not answer anything on #36: sweep
867 logged no
HTTP 404 … requested_reviewersline, but only because !52's merge removed the open PR atstate:needs-humanthat is that criterion's stated precondition. Absence of the wake isnot evidence of a fix, and #36's boxes are untouched by this.
Closing.
post-mergestays on as the epitaph, as on #48 and #32 — it records how thisissue ended, and every remaining box is
[x].