Commit graph

57 commits

Author SHA1 Message Date
fc24fa4b78 docs(upstream-sync): the inventory names docs-sync, which #201 makes forge-deciding (#200)
Found by combining all five open PRs and running the suite on the result —
which is the check this PR's own runbook adds, catching a real break the first
time it was applied at scale.

!203 (#201) makes actions/docs-sync/docs-sync.sh decide the forge from
GITHUB_SERVER_URL, because it was fetching the doctrine mirror from a
hard-coded github.com. This PR's guard requires every forge-deciding file to be
named in the inventory. Both are individually green; together the tree is red:

  forge-specific but not in docs/UPSTREAM-SYNC.md:
    actions/docs-sync/docs-sync.sh

The entry belongs here rather than in !203: the inventory is this PR's artifact,
and !203 is a bug fix that should not have to know about a guard absent from
its base. Adding it early is harmless — the guard checks that deciding files
ARE listed, not that listed files decide — and correct the moment both land.

Five-way combined tree after this: 28 test files 0 failed under the runner's
jq 1.6, shellcheck 0.10.0, actionlint, self-ref, marker, vendored and
changelog-armed all clean.

Refs #200
2026-08-05 15:15:35 +00:00
f3a1336d42 fix(upstream-delta): discovery derives from the tree, not from a glob list (#200)
@codex-reviewer-andresmgsl did not argue this one, he reproduced it: an
`actions/*/action.yml` declaring CEREMONY_FORGE_CLIENT and a workflow written
`.yaml` rather than `.yml`, both invisible to the hand-picked globs, guard
still 21/21 green.

The first is not an edge case — `actions/*/action.yml` is this repository's
normal composite structure and a client declaration there IS a forge decision.
The second shows `*.yml` was never a complete workflow surface.

So discovery walks the tree and EXCLUDES by class rather than enumerating
directories, depths and extensions. Excluding is the safer default: a new file
type arrives scanned rather than invisible. Out of scope are .git/, test/
(whose harness asserts these tokens by design), changelog.d/ and *.md — prose,
including drills/, which stays in the inventory because its records are
forge-specific by CONTENT while a record mentioning a selector verb in prose is
not a decision.

Both of his reproductions are now fixtures driving the real no_unlisted, and
restricting discovery back to *.sh reds four cases.

The documentation claim is aligned with what the guard does rather than what
the table implies: it checks forge DECISIONS in executable and configuration
files; it is not a diff against upstream, so drills/ and labels.conf are listed
by judgement rather than found by scan. Saying otherwise made labels.conf and
drills/ look like evidence of completeness while action.yml was invisible.

upstream-delta 24/24; test/run.sh 29/29; shellcheck 0.10.0, actionlint and
changelog-armed clean.

Refs #200
2026-08-05 13:58:32 +00:00
634e7a3528 fix(upstream-delta): the object is mandatory, the scan covers every governed surface, and the teeth drive the real guard (#200)
@codex-reviewer-andresmgsl's five points. Three were correctness, and one of
them found that my must-fail cases could not fail.

1. THE OBJECT IS MANDATORY. UNVERIFIABLE-HERE is gone: a missing ref, an absent
   object and a non-ancestor are three distinct refusals. The ref is now the
   FULL 40-character SHA, and ci.yml fetches exactly that object before the
   suite. "Runs offline" means the TEST reads local evidence; it never meant CI
   may omit the evidence and pass.

2. THE SCAN COVERS WHAT THE INVENTORY CLAIMS. It walked shell under four globs
   and never looked at workflows, .github/labels.conf or drills/ — three
   categories the inventory governs. Widened, and it immediately found four
   real blind spots on merged main: refs-not-closing's declaration,
   labels.yml's inline forge decision, refs-guard.yml's GitHub-only scheduling
   and release-exercise.yml's pinned CEREMONY_FORGE. All four are now inventory
   entries with the issue that removes them, because a delta location with no
   exit is indistinguishable from one nobody noticed. A file that DECLARES a
   client is no longer exempt as a "consumer" — only files that merely CALL the
   shim are.

3. THE TEETH NOW DRIVE THE GUARD. They asserted the predicates separately and
   never invoked no_unlisted, so the guard could have been `return 0` and both
   must-fail rows would still have passed. SCAN_ROOT is a parameter now and the
   cases build a tree, add an unlisted decider — shell AND workflow, so
   coverage cannot regress to the old glob — and assert the real top-level
   check fails naming it. Replacing no_unlisted with `return 0` reds five.

4. PATH MATCHING, NOT PREFIX MATCHING. `drills/` accepted `drills-old/x` and
   `lib/forge.sh` accepted `lib/forge.sh.backup`. Exact for files, `dir/` for
   directories, with both negative boundaries covered.

5. THE IMMUTABLE SHA IS CAPTURED AT FETCH. The runbook now takes
   upstream_sha=$(git rev-parse gh/main) once and merges and records that
   value. This is not hypothetical: while this PR was in review upstream moved
   from 8c3a4d1 to 08e2912, and re-reading gh/main at recording time would have
   written a commit this tree does not contain. I caught that by walking into
   it.

test/run.sh 29/29; upstream-delta 21/21; shellcheck 0.10.0, actionlint,
changelog-armed clean.

Refs #200
2026-08-05 13:51:21 +00:00
f3f7538d15 docs(upstream-sync): stale in-flight branches, and auditing post-merge runs by executed steps (#200)
@codex-reviewer-andresmgsl's two additions (#5697), both measured in the #198
sync rather than anticipated.

Every branch open across a sync is stale afterwards: Forgejo never re-tests an
open PR when main moves under it, so #206 and #207's green 22-file suites were
about a tree that no longer existed once the 28-file one landed — and #206's
fragment was individually green while making the combined tree red under a rule
the sync itself introduces. The runbook now says to update each in-flight
branch from the newly synced main, or check them in a scratch merge, and that a
prior approval is evidence about the tree it was given on.

And post-merge runs are audited by executed steps, never by colour: inventory
what the sync changed about triggers and jobs, read which job actually ran, and
treat a green refusal path as evidence for that path only. Run 326 was green
and had reconciled nothing.

Both failures happened with the no-runtime-gh guard green and CI green, so the
runbook says that too.

Refs #200
2026-08-05 13:42:21 +00:00
e965b15cbf docs: the recurring upstream sync, its standing resolutions, and a guard on where the delta lives (#200)
The third child of #197, written immediately after performing the sync it
describes, while the findings are still first-hand.

docs/UPSTREAM-SYNC.md carries the procedure and the six standing resolutions,
each with the issue that decided it, so they are not re-argued every sync. The
parts that are not obvious from the outside, and that the 0.6.0 sync paid to
learn:

  * THE AUDIT STEP. `git merge` takes upstream's side wherever only upstream
    moved a region, so a function upstream ADDED to a file this tree owns
    arrives with no conflict and no question. Reviewing the hunks cannot find
    it — four reviewers read the same diff and each found a different subset.
    That was eight runtime `gh` call sites in three files and two file types.

  * THE SAME MECHANIC APPLIES TO STATE. A resolved region can remove a producer
    whose consumers auto-merged, and those consumers degrade to empty rather
    than erroring, so nothing goes red. Three such seams in one sync.

  * VERIFY WHERE IT RUNS. "Green locally" was wrong three times, for three
    different reasons: shellcheck-all lints TRACKED files so a new file's first
    lint is meaningless; CI pins shellcheck 0.10.0; and the runner's jq 1.6
    exits 0 where 1.7 exits 4 on `jq -e` with empty input — which was not a
    test problem but a guard accepting an unreadable read.

  * TEST THE MERGE RESULT. Forgejo tests heads, never what two branches produce
    together, and two green PRs did produce a red tree in this sync.

  * AFTER MERGING, CHECK THE SWEEP RECONCILED SOMETHING. The first post-merge
    run was green and had done nothing.

.upstream-ref records the carried commit in machine-readable form beside the
CHANGELOG's prose. test/upstream-delta.test.sh asserts every forge-DECIDING
file is named in the inventory — offline, comment-aware, and refusing rather
than skipping when the ref is missing. Shim CONSUMERS are allowed by name, so
a seventh consumer is silent and a seventh decider is not.

docs/CONSUMERS.md now states that two ceremonies answer to the same version
number and how a consumer says which one it pinned.

Must-fail, both from the issue's test plan: scattering a forge_detect branch
into an unlisted file reds the guard; blanking .upstream-ref reds it too.

test/run.sh 29 files 0 failed under jq 1.7 and jq 1.6; shellcheck 0.10.0,
actionlint, self-ref, marker, vendored and changelog-armed all clean.

Refs #200
2026-08-05 13:36:17 +00:00
e035130f65 merge upstream 0.6.0 onto the forge tree, and port every gh call site it brought (#198)
`git merge` of upstream `8c3a4d1` onto `dad99dd`, common ancestor `84bb1a4`.
18 hunks in 10 files; `lib/forge.sh`, `lib/forge-github.sh` and
`lib/forge-forgejo.sh` conflict in none and come out byte-identical.

The resolutions the issue decided: VERSION and both CEREMONY_SELF_REF
carriers take upstream's numbers; `.github/labels.conf` and `drills/0.4.1.md`
keep this forge's; CHANGELOG keeps both sides and names the upstream commit
this tree carries.

The part the hunks did not contain. Upstream's 0.5.0/0.6.0 work added whole
functions to files this tree already owned, so `git merge` took its side
without raising a conflict — and with them, EIGHT runtime `gh` call sites
that #188 had removed. Seven are ported onto the shim: two reads and four
comment writes in issueflow-reconcile, and labels-reconcile's HEAD_COMMIT_AT
read. The eighth is `gh workflow run` in labels.yml, which a workflow cannot
declare a client for and whose Forgejo equivalent this instance answers with
500 rather than a 4xx — named with its reason rather than ported on a guess.

test/no-runtime-gh.test.sh makes the rule mechanical, because reviewing the
diff could not: four reviewers reading it each found a different subset, and
the contract suite stubs `gh`, so a reintroduced call site passes it.

Three seams the resolution decides are silent when resolved wrongly, and each
now has a case that fails on the wrong one: the merged record's `merged_at`
third column (without it every sort key ties and the highest PR number comes
back), the open gather's one-BODY-row-per-line feed (a whole decoded body as
one record loses every declaration including the first), and the whole-board
read whose COLLISION_FLAGS/WINDOW_FLAGS consumers auto-merged.

The open gather carries CLOSING rows as well as BODY rows. `Refs` alone would
drop every `Closes #N` link on the open side and reclaim a claim the PR was
holding — the existing base64 round-trip case is red without it.

actions/refs-not-closing declares CEREMONY_FORGE_CLIENT=gh: its only gather
is GraphQL, which Forgejo does not serve at all. #199 ports it.

test/run.sh: 28 test files, 0 failed. shellcheck and actionlint clean.

Refs #198
2026-08-05 11:56:23 +00:00
cndgrr
fb8f8282a9 release: cut 0.6.0
Thirty-five fragments assembled into '## 0.6.0 — 2026-08-05'; VERSION to
bare 0.6.0; the three CEREMONY_SELF_REF carriers stamped "0.6.0" in this
one commit; the three docs/CONSUMERS.md availability markers cleared to
name 0.6.0 — refs-not-closing (#218), the RELEASES.md mirror entry (#248)
and the vendored-manifest completeness guarantee (#251).

drills/0.6.0.md opens with the measurement that decides its shape: the
doors-unchanged conditions do NOT all hold at this candidate, because
lib/changelog.sh moved on the release path since the last rehearsed tag
0.4.0. A full disposable-repo rehearsal is owed and is in progress; the
record is committed early and filled from the runs as they happen.

Refs #249.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 00:01:03 +00:00
ca99182e80 fix(forge): percent-encode asset names, and stop the docs naming a client
Both findings are @codex's on !193 (#1583), and both are real.

The asset name travels as a QUERY VALUE, and the artifact-hook contract
permits any file the consumer drops in RELEASE_ASSETS_DIR. Raw
interpolation meant `release asset.tgz` made curl reject the URL outright
(exit 3), and '&', '#', '+', '%' silently changed the name or the query's
shape. `gh release create` handled all of those, so a 1:1 port had to.

Encoded through one boundary — jq's @uri, since jq is already a hard
dependency of this backend and a hand-rolled sed class is how the next
unescaped character gets through. Six backend cases cover it: the encoder
on a space and on the delimiters, uploads under both names, the created
release id in the path, and the multipart attachment. Mutation-checked:
dropping the encoder fails exactly the two name assertions.

docs/CONSUMERS.md's artifact-hook recovery still told operators to "run
`gh release create` by hand" and described the hook as running "before
`gh release create`" — on a Forgejo runner that is precisely the failure
this PR fixes. It now names the forge-neutral tag-door recovery first and
shows both clients for the manual path, without regressing the GitHub
guidance.

1035 assertions, 22 suites, shellcheck-all and actionlint clean.

Refs #191

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 12:11:06 +00:00
cndgrr
42b8fb6850 fix(consumers): the manifest is readable at 0.1.0, not 0.5.0
docs/VENDORED.txt and actions/docs-sync/docs-sync.sh entered the tree in
the same commit and are byte-identical at every tag — blobs 10c20a3c and
ba426479 at 0.1.0 through 0.5.0 — and 0.1.0's copy of the tool is already
manifest-driven (MANIFEST="docs/VENDORED.txt", L75). Citing 0.5.0 told the
0.1.0-0.4.1 tail, which is exactly the population this section is written
for, that the manifest was unavailable at its pin, so it would keep the
hardcoded list: #251's failure mode reproduced by the document that exists
to abolish it. The same file already said 0.1.0 at L131-L133.

Also make the guard's tracked-ness skip announce itself. It degrades to
"not asserted" wherever the tree is not a git work tree root, and doing
that in silence is the shape this script's own header argues against, so
the skip now prints on both output paths, green and red, with a test row
each way.

Round 1: claude blocking point, and claude nit 3.
2026-08-04 10:29:44 +00:00
cndgrr
b9eedd8973 docs(consumers): cite the manifest availability to the tag that shipped it
0.5.0 availability is actions/docs-sync own arrival (#19); #251 is the
guidance and the guarantee, not the file date.

Refs #251
2026-08-04 10:18:17 +00:00
cndgrr
7909383ca0 docs(consumers): read the pin manifest, never a copy of it
Re-vendor tooling and docs-sync equivalents read the pin docs/VENDORED.txt
(available at 0.5.0 and later) instead of naming the doc set themselves, so
a new doctrine file reaches every consumer at its next ordinary pin bump
with zero list edits. A hardcoded list propagates nothing and its
staleness is silent: docs-sync --check asserts byte-identity for the files
the list names and says nothing about one it omits.

What makes reading the manifest sufficient rather than merely better is
the self-guard this PR adds, tagged unreleased until the first tag carries
it, per the RELEASES.md paragraph above it.

Refs #251
2026-08-04 10:18:17 +00:00
Andriujose
2a1f8a012b test: pin inline marker mention boundary 2026-08-03 23:05:05 +00:00
Andriujose
d87d76d64b fix: align marker guard with release oracle 2026-08-03 22:56:02 +00:00
Andriujose
7200c8da49 docs: define traceable availability markers 2026-08-03 22:51:17 +00:00
Andriujose
66b136efc0 docs: wire refs guard into ceremony flow 2026-08-03 20:31:34 +00:00
Andriujose
8c29424519 docs: correct release gate mechanics 2026-08-03 18:26:58 +00:00
Andriujose
ab60709f49 docs: add release-management doctrine 2026-08-03 17:29:15 +00:00
dan-claude-bot
e5e7555184 release: cut 0.5.0
Five fragments assembled into '## 0.5.0 — 2026-08-03' (#205 #216 #221
#224 #226); VERSION to bare 0.5.0; the three CEREMONY_SELF_REF carriers
stamped "0.5.0" in this one commit; the panel-rows unreleased marker in
docs/CONSUMERS.md cleared to name 0.5.0; drills/0.5.0.md records the
doors-unchanged ruling with the measurements as they are at 0ac3a6f.

Refs #233.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 12:01:05 +00:00
f2d5fcd565 feat(forge): derive outstanding review requests from the head, not the field
Term 4. GitHub clears requested_reviewers when a verdict lands, so the field
answers "who still owes a verdict" by itself. Forgejo never clears it —
measured: rig!140 listed all three panelists with all three verdicts in, and
rig!146 still lists three while MERGED, so the field is stale even on a
closed PR.

Read raw on Forgejo that is not a cosmetic over-count. `requested` drives
three decisions, and a permanently-true field pins a PR at
state:bots-reviewing for life and stops blocker:unrequested from ever being
true: the sweep believes a round is live forever and no staleness can
correct it.

So the requested set is intersected with who has NOT submitted a verdict for
the current head, derived from /pulls/{n}/reviews — the read that is true on
both forges. On GitHub the filter removes nothing, because the field is
already accurate; term 5 holds by construction rather than by care.

A STALE approval — an approval of an older head — still owes a verdict. That
is the case that matters: treating it as answered would let a stale round
read as complete, which is the shape #136 exists to prevent.

Mutation-verified both ways: reading the field raw again reds three cases,
and treating STALE as answered reds two.

Also documents @grok-reviewer-andresmgsl's ask (#4763): every panel= account
must be able to read the repo, or the forge refuses the review request —
422 naming the account on Forgejo. A real failure mode for private
consumers, and it fails loudly rather than sweeping blind.

Refs #188
2026-08-02 19:48:09 +00:00
dan-claude-bot
44b1a3d23c fix: a draft never reads state:needs-human — round 1, claude
The reorder let a draft with a live human request plus a standing block
or comment fall through to round_state, whose human-request precedence
sits above BLOCK/FEEDBACK — 224 of claude's 1500 fixture cases read
needs-human on a PR GitHub cannot merge. decide_state now disqualifies
needs-human unconditionally under DRAFT=true, landing on
state:addressing like the blocker/needs-ruling/blocked clauses. The two
new rows assert the criterion where it can actually fail: human
requested x {CHANGES_REQUESTED, COMMENTED}. Also grok's nit: the
bootstrap row for state:building now matches LABELS.md (draft is
evidence, not the definition), and the CONSUMERS.md reflow nits are in.

Refs #205

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 14:13:25 +00:00
dan-claude-bot
ecb0371cad docs: clear five stale unreleased markers; the release PR owns clearing
Each marker now says available-at-tag in the guide's existing L420
phrasing, verified by tag containment in #221; every never-mix-refs
sentence survives verbatim. The convention paragraph gains its missing
half: the release PR that ships machinery clears, in that same PR,
every marker its assembled section makes false.

Refs #221

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 13:32:31 +00:00
dan-claude-bot
8db6c3ae29 feat: per-author review panels — labels.conf gains panel[<login>]= rows
One resolution point (panel_for_author) feeds set_required_bots; the
author's row when the conf defines one, the base panel= otherwise, minus
the author in either case. Bracket prefixes are matched quoted so the
case patterns cannot glob (D7, panela= tripwire). configured_label_rows
skips the rows so a dispatch bootstrap cannot mint a label named after
one. BUILDER.md/REVIEWER.md carry the one D9 wording; CONSUMERS.md
publishes the row as unreleased with the parse-failure warning.

Refs #224

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 13:29:15 +00:00
dan-claude-bot
be660358f2 docs: spell out crew's four-edit migration; fold in crew#250 field facts (#209)
crew#250 verified two facts the design prose now carries: a queue-
displaced run is not independently rerunnable (gh run rerun / --failed /
--job all refuse), so a victim PR had no manual escape hatch; and the
displacing burst is deterministic — one review_requested event per
panelist per request — so displacement is the steady state of a working
fleet, scaling with panel size, not a traffic spike.

CONSUMERS.md now walks the adoption as one atomic four-edit PR with crew
as the worked example: the pin bump in every ceremony uses: reference,
the new labels-sweep.yml caller, the cron RELOCATED (bold warning: a
copied-not-moved schedule double-fires sweeps into the one shared group
and reads as the bug getting worse after the fix), and actions: write
replacing the labels caller's actions: read.

Refs #209

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 17:25:26 +00:00
dan-claude-bot
45aa806207 labels: detach the reconcile sweep from PR-triggered runs (#209)
The sweep rode the same workflow run as the PR event that woke it, so
every displacement in the shared labels-reconcile queue recorded a
CANCELLED reconcile check on some PR — fake red CI that held review
requests. The reconcile + issueflow jobs move, unchanged, to a new
reusable labels-sweep.yml behind their own caller; labels.yml gains a
trigger job that dispatches the consumer's sweep caller with the plain
GITHUB_TOKEN (workflow_dispatch is a documented no-retrigger exemption)
on every event that used to run reconcile. A displaced sweep now cancels
on the Actions tab, attached to no PR; PR checks show scope + trigger.

Because every trigger-driven wake arrives as workflow_dispatch, the event
name alone no longer separates the operator's manual bootstrap from an
event-woken sweep: the sweep caller's bootstrap dispatch input does — the
trigger passes no, a bare manual dispatch defaults to yes. The sweep
reusable also takes pr_workflow_name, exported as SELF_WORKFLOW for the
#208 reconciler (harmless to earlier ones; zero file overlap with #208).

The trigger is deliberately loud: a pin bumped without the sweep caller,
its bootstrap input, or actions: write on the labels caller goes red at
the trigger job instead of silently never sweeping again — documented in
docs/CONSUMERS.md with the split stubs and the atomic-adoption note.

Refs #209

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 16:20:00 +00:00
codex-bot-andresmgsl
4198597834 docs: correct labels maintenance cadence 2026-07-29 10:37:03 +00:00
codex-bot-andresmgsl
3eff28e624 docs: explain sweep cadence and manual dispatch 2026-07-29 09:27:29 +00:00
claude-bot-andresmgsl
8cf3c335df labels: name what the hourly cron uniquely covers (#199 round)
The trigger comments, CONSUMERS stub, changelog, and reusable labels.yml
comment said "events carry every real state change in seconds; the cron
only backstops a forgotten handoff." That is backwards: no subscribed
event wakes this sweep for a review verdict landing (no pull_request_review
trigger), blocker:ci-red set/cleared, blocker:conflict when another PR
merges, or the time-based stale/48h-reclaim. The hourly cron is the sole
discovery path for those four classes, not a forgotten-handoff net —
so the comments now name them and warn against deleting the cron (AC5).

codex-2 / kimi-2 (both blocking, round 2 @0a812c4b).
2026-07-28 19:26:40 +00:00
claude-bot-andresmgsl
0a812c4b19 labels: keep edited/reopened on issues; correct 0.3.0 adoption prose (#199 round)
Round fixes on #200.

codex-1 (blocking): the issues narrowing dropped `edited`/`reopened`, but both
carry a queue-state change an event uniquely carries — `edited` a body rewrite
of the `Blocked by #N` declaration the sweep parses
(issueflow-reconcile.sh:179), `reopened` a closed issue re-entering the queue.
Dropping them tripped #199's must-fail. Narrow to
`[opened, closed, edited, reopened]`, dropping only the churn/validation
actions labeled/unlabeled/assigned/unassigned. Trigger tests now pin
edited/reopened present and the four dropped; labels.test.sh exact-list updated.

kimi (blocking): the "supersedes unreleased #144" prose was false — #144's
edited/reopened shipped in 0.3.0. Dissolved: we now keep them. CONSUMERS prose
rewritten to the real version history (0.2.0 #32 / 0.3.0 #144 / #199 narrows),
and the #137 review-request line corrected from "unreleased" to shipped-in-0.3.0.

kimi (non-blocking): reusable labels.yml comment no longer cites */15.

codex-2 (AC1 after-measurement / closing) escalated to triage on #199 — held,
not guessed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 19:04:27 +00:00
claude-bot-andresmgsl
12887cc9de docs: narrow CONSUMERS stub issues triggers, relax cron to hourly (#199)
Bring the published caller stub to the #199 shape in lockstep with
self-labels.yml (preserving the stub<->caller parity #144 established):
hourly cron, issues: [opened, closed], per-trigger why-comments. Rewrite
the adoption prose — 0.2.0 shipped the broad set; #199 narrows it at its
pin bump and supersedes the unreleased edited/reopened additions (#144).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 18:13:15 +00:00
claude-bot-andresmgsl
be666ebed6 feat: ceremony flips to grouped — changelog.d/shape = grouped, five fragments converted, docs per D6
167/175 gain '### Added', 173/178 '### Changed', 180 '### Fixed' — every
bullet byte-identical, headings only (the #158 bar, inverted). CONSUMERS.md
names the sentinel and the flip procedure; changelog.d/README.md names the
sentinel. 182.md is this PR's own fragment, grouped atop the sentinel it
ships.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 13:14:05 +00:00
codex-bot-andresmgsl
eae000bd62 docs: add actions read to private caller guidance 2026-07-24 22:57:22 +00:00
claude-bot-andresmgsl
0b77d4b860 fix: the CONSUMERS.md stub's issues: types match the caller's, parity-tested
The stub published [opened, labeled, unlabeled, assigned, unassigned,
closed] while ceremony's own caller listens on eight types — PR #32's
70db91f widened the caller by edited and reopened and the stub never
followed. Both are load-bearing: an edited body rewrites the Blocked-by
declaration the reconcile sweep parses, and a reopened issue re-enters
the queue wearing labels derived at close (#144).

The stub's list is now byte-identical to the caller's, a parity row in
test/labels.test.sh keeps it that way (red on a dropped type, a drift,
or a reorder in one file only), and one adoption note names the tag the
widened list rides in on. The caller does not narrow.

Closes #144

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 13:43:35 +00:00
Daniel Marin
6a16a30bab
Merge pull request #143 from claude-bot-andresmgsl/build/137-review-request-wake
fix: review_requested wakes the labels sweep — blocker:unrequested clears when the ask lands
2026-07-24 14:33:11 +01:00
Daniel Marin
ad5c175d0c
Merge pull request #133 from claude-bot-andresmgsl/build/130-labels-scope-clobber
fix: labels/scope writes additively — a label applied mid-job survives
2026-07-24 14:14:03 +01:00
claude-bot-andresmgsl
48a3052934 docs: CONSUMERS release-state notes say 0.2.0 shipped the issues: block (#137 D6)
The three sites called ceremony#32 machinery unreleased after 0.2.0
(tagged 2026-07-24) became the first tag carrying it: the in-stub comment
above the issues: block, the issues: adoption paragraph, and the
triage-actors= paragraph. All three now state availability at 0.2.0 and
later; the 0.1.0-omission guidance and the parse-failure sentence stay —
still true. No type list moves (the caller/stub issues: subset drift is
#144, not this PR).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 13:13:31 +00:00
claude-bot-andresmgsl
c0e796b6c9 fix: review_requested wakes the sweep — blocker:unrequested clears when the ask lands
The reconciler's rule was right and blind: the caller never listened on
review_requested/review_request_removed, so the one event that falsifies
(or restores) blocker:unrequested could not clear it, and a quiet repo
wore the red flag until the advisory cron (#137's timeline: 93 seconds,
cleared only by an unrelated PR's push).

- self-labels.yml + the CONSUMERS.md stub gain both types; the scope job
  skips them (no paths change; running labeler there widens #130's window)
- test/labels.test.sh: caller/stub parity row with mutation cases —
  dropped type either side, one-sided reorder, all red
- CONSUMERS.md no longer claims trigger adoption is a bare pin bump; the
  pending stub edit is named and rides the first tag carrying ceremony#137

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 12:50:09 +00:00
codex-bot-andresmgsl
3792d52b82 docs: exempt release PRs from changelog fragments 2026-07-24 12:41:46 +00:00
claude-bot-andresmgsl
d0b857eb10 docs: the additive-scope contract in CONSUMERS/LABELS; changelog fragment
Part of #130.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 11:57:10 +00:00
claude-bot-andresmgsl
566712c690 docs: CONSUMERS and drills describe fragment-mode adoption
Bootstrap arms with a preamble plus changelog.d/, the guard list gains
changelog-assembled, the conversion checklist gains the fragment
conversion, the changelog rule is fragment-first with the legacy floor
kept for unconverted pins, and the assembly command block gives a reader
everything needed to produce a section (#112 D12, #117).
2026-07-24 11:11:23 +00:00
codex-bot-andresmgsl
22f1a0246f docs: explain core taxonomy bootstrap maintenance 2026-07-24 09:24:40 +00:00
codex-bot-andresmgsl
8ad68192e9 docs: seed grouped changelog re-arms 2026-07-23 23:45:04 +00:00
codex-bot-andresmgsl
2c57216a56 fix: surface wholly blind label sweeps 2026-07-23 23:12:30 +00:00
codex-bot-andresmgsl
0d74c827e7 docs: make consumer labels tag-aware 2026-07-23 16:09:42 +00:00
codex-bot-andresmgsl
162ce6b817 docs: count every consumer workflow caller 2026-07-23 15:34:01 +00:00
codex-bot-andresmgsl
3e96d80389 docs: make consumer guards tag-aware 2026-07-23 15:20:29 +00:00
claude-bot-andresmgsl
9ff049ae45 docs(labels): the ruling sweep behaviors in LABELS.md, CONSUMERS.md, CHANGELOG
LABELS.md's needs-ruling paragraph gains the bare-flag check and the
markerless 7-day nudge; CONSUMERS.md names them in the labels job and
states the caller stub is unchanged since #18 (a pin bump is the whole
upgrade); one CHANGELOG line under Unreleased (#52).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 12:25:24 +00:00
claude-bot-andresmgsl
44d0a79547 feat(guards): wire runner-isolated — self-guards step, consumer entry, changelog (#58) 2026-07-23 12:04:11 +00:00
codex-bot-andresmgsl
43092576ef fix: harden issueflow reconciliation edges 2026-07-23 10:49:36 +00:00
codex-bot-andresmgsl
8174080c9d feat: reconcile the issue work queue 2026-07-23 10:31:15 +00:00
claude-bot-andresmgsl
bd7670703a docs: CONSUMERS.md carries rig's conversion lessons — labels.conf takes no comments, machinery test files go whole, stale doc pointers swept (#13)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 00:34:26 +00:00