Commit graph

112 commits

Author SHA1 Message Date
cndgrr
5356702817 docs(changelog): fragment for #267 2026-08-04 15:34:17 +00:00
Daniel Marin
5fd1c1b014
Merge pull request #295 from cndgrr/build/281-builder-slim
docs(builder): BUILDER.md slims to the rules — narratives become bare local cites
2026-08-04 16:27:06 +01:00
cndgrr
b44f7ed6ee Merge branch 'main' into build/281-builder-slim 2026-08-04 14:47:38 +00:00
Andriujose
90961cad51 docs: declare collision-edge chains 2026-08-04 14:27:49 +00:00
cndgrr
64e3af682f Merge branch 'main' into build/281-builder-slim 2026-08-04 14:13:38 +00:00
Andriujose
08b817b814 docs: name the epic task-list heading 2026-08-04 13:42:24 +00:00
Andriujose
5ea59780b6 docs(triage): scope no-assignee bug to flagging 2026-08-04 13:16:58 +00:00
cndgrr
6ebdd2efd9 docs(builder): WIP — slim BUILDER.md to the rules, bare local cites 2026-08-04 13:11:32 +00:00
Daniel Marin
acf4125fd6
Merge branch 'main' into build/291-terminal-fragment-cites 2026-08-04 14:11:20 +01:00
Andriujose
7af13eae73 docs: add terminal citations to release fragments 2026-08-04 12:53:38 +00:00
cndgrr
9f1f88de72 fix(changelog): #285's fragment carries a terminal cite
changelog.d/253.md landed on main after this branch's point with the
cite trailing the period — the crew#309 shape, the fifth fragment to
arrive with it since #262 measured two. The criterion is that
changelog.d/ is clean at the head, and the head CI reviews is the merge
with main, which is where this one surfaced.

Refs #262.
2026-08-04 12:40:55 +00:00
cndgrr
d13f61b6c5 merge: origin/main — #285's fragment lands under the rule
The self-guards job checks out the merge of this branch with main, so
changelog.d/253.md from #285 reaches changelog_fragment_problem there and
nowhere else; the branch alone is green. Merged rather than rebased
because the round's reviewers track head SHAs.

Refs #262.
2026-08-04 12:39:55 +00:00
cndgrr
75a5b68c8a fix(changelog): one fragment, one diagnosis, wherever the long entry sits
awk runs END on the way out of an exit from a main rule, so the length
row printed mid-file was followed by the citation row it outranks — the
internal protocol line landing inside the human-facing excerpt. Found by
claude-bot and kimi-bot in #262's first round, independently and with the
same reproduction.

The guard is the reported flag the empty-heading walk in this same
predicate already uses. The fixtures are the axis 57.md could not reach:
its over-bound entry is last, so only END's flush can print. 58.md puts
one before another bullet, 59.md before a heading and after a misplaced
cite. With lib/changelog.sh alone reverted they red, which is what the
green suite was hiding.

Refs #262.
2026-08-04 12:38:13 +00:00
Daniel Marin
d30b091872
Merge pull request #285 from andriujoseba/build/253-release-init-announce
feat: announce release initialization
2026-08-04 13:22:21 +01:00
cndgrr
8aeea67d8d docs(changelog): the citation is guard-enforced, not house style
Closes #262
2026-08-04 12:12:52 +00:00
cndgrr
46b80fb6b2 fix(changelog): the four drifted fragments carry a terminal cite
Refs #262
2026-08-04 12:01:45 +00:00
cndgrr
b2313beae8 docs(builder): a displaced predecessor is not the check's verdict
Step 1 ruled what a rollup entry means and never said which entry to
read. A job in a cancel-in-progress group displaces itself, so a head
routinely carries a CANCELLED node beside the SUCCESS that replaced it,
and read by class alone that head is not green while checks_state calls
it SUCCESS.

State the collapse ahead of the classes it feeds: newest entry by start
time, and a CANCELLED entry is not the check's word while a non-cancelled
sibling stands at the same head. All-cancelled and pending are untouched.

Refs #276
2026-08-04 10:58:59 +00:00
Daniel Marin
017c571438
Merge pull request #277 from cndgrr/build/251-vendored-manifest
feat(guards): the tag declares its vendorable set
2026-08-04 11:52:15 +01:00
Andriujose
e3b4b2cdfd feat: announce release initialization 2026-08-04 10:48:55 +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
6949f8cbdc docs: define doctrine conventions 2026-08-04 10:17:30 +00:00
Daniel Marin
05738ff0dd
Merge pull request #273 from andriujoseba/build/238-marker-check
feat: guard unreleased documentation markers
2026-08-04 11:14:01 +01:00
Daniel Marin
4a9f113ef3
Merge pull request #274 from cndgrr/build/254-postmerge-nudge
feat(issueflow): the post-merge evidence nudge
2026-08-04 01:35:08 +01:00
dan-claude-bot
806e99e1cb docs(builder): green is read from conclusion, and the checkless head is the third ruled case
The ruled-term paragraph now names its field — a check carrying a
terminal conclusion is green or not-green by that conclusion whatever
its status reports — and rules the head with no checks configured:
nothing to wait for, request straight away, no argued exception owed.
The draft-round restatement comes out so the file states the rule once.

Closes #260, closes #272 via the PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 23:44:43 +00:00
cndgrr
fd9da98abf docs(labels): the evidence clock names what the sweep actually reads
"a comment, a review or a commit" is the ruling nudge's house phrasing and
false on the issue surface twice over: there is no review or commit fact in
what the sweep reads, and an assignment is no longer counted here. Say
what is read, and say what does not buy another 7 days of silence.

Refs #254
2026-08-03 23:40:48 +00:00
cndgrr
b18168b4f3 docs(labels): quiet post-merge is visible, still never reclaimed
LABELS.md said the sweep never reclaims post-merge and stopped there, which
now reads as 'the machine says nothing' — after this change it says one
thing, once per 7 quiet days. Plus the fragment.

Refs #254
2026-08-03 23:08:11 +00:00
Daniel Marin
c7f40bb818
Merge pull request #270 from cndgrr/build/258-fix-round-draft
docs(builder): a fix round may ride a draft
2026-08-03 23:55:44 +01:00
Andriujose
dca8e7220c test: exercise documentation marker guard 2026-08-03 22:49:22 +00:00
Daniel Marin
1b84d27691
Merge pull request #269 from andriujoseba/build/237-doors-unchanged
docs: define doors-unchanged drill evidence
2026-08-03 23:40:32 +01:00
cndgrr
6634a517bc docs(builder): a fix round may ride a draft
BUILDER.md's review round assumed ready-throughout, so a builder or
reviewer meeting a mid-round draft found behaviour the doctrine never
described. Three points, doctrine not mechanism: the draft phase stays
the builder's through a fix round, ready-for-review is the builder's own
act and no engine's, and where the draft suppressed CI green is proven
at the flip with the request following it — step 1's rule at a stated
moment, not a second rule.

REVIEWER.md gains the reading that keeps a reviewer from misfiling it:
a draft carrying state:addressing is a fix round in progress.

Refs #258
2026-08-03 21:49:11 +00:00
Daniel Marin
3c96406081
Merge pull request #261 from cndgrr/build/252-blocker-echo
feat(issueflow): echo the parsed blocker set when it changes
2026-08-03 22:43:29 +01:00
Andriujose
75d85df20c docs: define doors-unchanged drill records 2026-08-03 21:41:34 +00:00
cndgrr
fb89c92434 Merge remote-tracking branch 'origin/main' into build/252-blocker-echo 2026-08-03 20:42:09 +00:00
Andriujose
66b136efc0 docs: wire refs guard into ceremony flow 2026-08-03 20:31:34 +00:00
Andriujose
a9b3f4d766 test: cover attention target diagnostics 2026-08-03 19:53:25 +00:00
Daniel Marin
5626a4ef1e
Merge pull request #259 from andriujoseba/build/230-attention-target
docs: clarify the attention target at triage write time
2026-08-03 20:40:48 +01:00
cndgrr
5cfb69e104 test(issueflow): the parse echo, mutation-proven in both directions
The idempotency contract is the marker's scope, so both directions are
pinned: an unchanged set must reuse its marker (or a 15-minute cron
repeats itself forever) and a changed one must not (or a misparse hides
under a marker the thread already carries). crew#308's negated clause is
replayed through the sweep, and the empty parse is echoed beside the
untouched `blocked-unparseable` flag.

Refs #252
2026-08-03 19:28:31 +00:00
Daniel Marin
f73facea6e
Merge pull request #256 from cndgrr/build/247-read-guards
fix(issueflow): a failed read must never reach a decision function
2026-08-03 20:19:35 +01:00
Andriujose
dbb0554288 docs: clarify attention target 2026-08-03 19:07:08 +00:00
Daniel Marin
2e5aa52e29
Merge pull request #255 from andriujoseba/build/248-release-doctrine
docs: add release-management doctrine
2026-08-03 20:00:30 +01:00
cndgrr
6217798e14 fix(issueflow): a per-issue pass commits its whole effect, or none of it
The per-read guards closed the reported class — a failed read never reaches
a decision function — and left one layer standing. A pass could mutate and
only THEN reach a guarded read, fail it, and report the issue as skipped:
`stale` removed, or `needs-triage` minted, under a log line saying the
sweep had touched nothing. That is the same false report #247 exists to
close, told from the other end, and the panel reproduced it on four
separate compositions.

Fixed as the ordering invariant rather than per site. Inside
reconcile_issue_pass's subshell, run() and log() stage their effects, and
commit_staged_effects replays them in order once the pass has completed.
skip_issue emits its own line directly and exits, so the buffer dies with
the subshell. A skip therefore implies zero `gh issue edit`, zero
`gh issue comment`, and no log line about a mutation that never landed —
for compositions nobody has written yet, because reconcile_issue has no way
to mutate directly. Reads stay where they are: they may happen anywhere,
since nothing lands until the end.

Stated per site it would hold until the next composition. Two consequences
worth naming: reconcile_ruling is covered without touching lib/ruling.sh,
because it posts through the sourcing script's run()/log() — the PR surface
keeps its own and is unaffected; and a genuine crash mid-pass now also
lands nothing, where before it left the earlier mutations applied. D4's
handler string, D6's tail and D7's exit 0 are all unchanged, and the
healthy path is byte-identical: every staged write commits under the same
`>/dev/null` its call site already applied.

Refs #247
2026-08-03 18:55:52 +00:00
Andriujose
8c29424519 docs: correct release gate mechanics 2026-08-03 18:26:58 +00:00
cndgrr
13e8f54d60 fix(issueflow): a failed read never reaches a decision function
`gh api` prints a 5xx response body to stdout AND exits non-zero, and
GitHub's 5xx body is a JSON object. Inside the per-issue subshell that
payload passed `has("pull_request") | not`, emptied `.labels[]`, and
`queue_decision` — correct on the input it was handed — wrote
`needs-triage` onto a healthy epic. The run then logged `reconciled.`
and exited 0 (crew#329, #247).

errexit could not have caught it: a command whose status is tested by
`||` runs with errexit suppressed, and the suppression extends through
the whole subshell body, so the `|| log` handler is what disables the
errexit that would have aborted at the failed read. Removing the handler
revives errexit and loses #91's resilience, and an inline `set -e` does
not re-arm it. Explicit per-read checks are the mechanism.

Every read inside that subshell is now checked — the issue read on its
status AND on its payload shape (an HTTP 200 whose body is `null` exits
0 and empties the label set just the same), both reads in
`last_issue_activity`, and the comments read in
`issue_comment_has_marker`. On failure the issue is left exactly as it
is, the reason rides its own `#$n:` line, and the subshell exits with a
distinguished status the sweep counts, so a deliberate skip is not
reported as a crash and a genuine crash is still named byte-identically.

`read_failure_reason` moves to lib/read.sh beside a new `guarded_read`,
sourced by both reconcilers: labels-reconcile's copy was the only one,
and the issue surface needs the identical rule.

Refs #247
2026-08-03 18:01:58 +00:00
Daniel Marin
d8a70657eb
Merge pull request #250 from cndgrr/build/236-unrequested-green-gate
fix(labels): blocker:unrequested waits for green, and for the round to settle
2026-08-03 18:48:22 +01:00
Andriujose
ab60709f49 docs: add release-management doctrine 2026-08-03 17:29:15 +00:00
cndgrr
8459a9255b test(labels): drive the green gate and the grace, and mutate both to prove them
The six cases the issue names, plus the boundary (the grace is inclusive), a
verdict inside the window against an old head, both unreadable timestamps, and
the configured-grace override.

Two proofs run rather than asserted in prose: a copy of the script with the
gate removed must flag the PENDING fixture, and a copy with the grace removed
must flag the inside-the-window one. The harness checks itself against the
unmutated copy first, or a flip would prove nothing.

The pre-#236 stall fixtures gain real timestamps. Their symbolic stamps are
not unreadable — GNU date reads `t1` as 01:00 in military timezone T, a time on
whatever day the suite runs — so a grace measured against a fixed NOW would
flip with the calendar. Every assertion is byte-identical.

Refs #236
2026-08-03 17:18:46 +00:00
Andriujose
e133924887 fix: preserve claims linked by open Refs PRs 2026-08-03 17:07:40 +00:00
cndgrr
9c690f02b7 test(issueflow): drive the merge-order selection, and the spent-marker shape end to end
issue_probe's merged-PR argument becomes a spec list — `PR` or `PR@<iso>`
— so a probe can state merge order; the bare form keeps every existing call
site literal.

The direct-drive cases cover crew#176's shape (the lower number merged
later), agreeing orders, interleaved issues, the mergedAt tie broken by
highest PR number under both input orders, and the empty answer. The
end-to-end probe is crew#321's: a marker already standing for the
later-merged, lower-numbered PR must suppress the transition, which
selecting by number could never do.

Two static pins keep the request count honest — the sweep issues exactly two
GraphQL queries, with mergedAt selected on the merged-PR node it already
fetched.

Refs #242
2026-08-03 16:27:43 +00:00
cndgrr
bded7d0b54 docs(labels): the attention absolute stops denying the shipped reconciler
LABELS.md asserted 'nothing in actions/ sets, clears, reads, or validates
it' and then documented two exceptions to itself four sentences later. The
sentence is false on two of the four verbs: issueflow-reconcile.sh clears a
carried attention on the derived claimed -> post-merge transition and reads
it to gate the post-merge-assigned diagnostic. Keep the hand-set intent,
drop the absolute (#231).
2026-08-03 15:48:05 +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