Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/decisions/0291-the-provider-the-socket-waits-on.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Date: 2026-09-04

Status: accepted. Supersedes nothing. Superseded by nothing.

Narrowed-by: 0351, on the fourth reversal condition, which is read as a price this board has already paid rather than as a state it can reach

Issue: #291

## The decision
Expand Down
154 changes: 154 additions & 0 deletions docs/decisions/0351-the-condition-that-counts-this-board.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# 0351. The reversal condition 0291 counts this board with

Date: 2026-09-18

Status: accepted. Supersedes nothing. Superseded by nothing.

Narrows: 0291, on the fourth reversal condition, which is read as a price this board has already paid rather than as a state it can reach

Issue: #351

## The decision

0291's fourth reversal condition - the count of open issues on this board that
can be worked without a request reaching zero - is read as a price already paid
and not as a trigger that can fire: the count has a floor of one, the member
holding that floor is #98, and neither of that member's two exits is open, so no
state of this board takes the count to zero. What the condition names is
therefore the throughput the wait has been costing since 0291 landed, which is a
price the record already weighed, and the three conditions beside it stand as
the ways the choice is retaken.

## Why the count has a floor of one

The command is 0291's own, and what it answers moves every hour:

gh issue list --repo Flowfin/core --state open --limit 500 --json number,labels \
--jq '[.[] | select([.labels[].name] | map(startswith("blocked-on-")) | any | not)] | length'

The number is not what this rests on. What it rests on is that #98 is in the set
it counts and cannot leave it, and that holds at any number.

**Its first exit is closing, and closing is downstream of the wait.** #98's
done-condition is the first release and an operator running the probe against
their own server, and the chain from there arrives at the issue 0291 was written
for:

for n in 92 39 27 291; do printf '%s\t' "$n"; \
gh api "repos/Flowfin/core/issues/$n/comments?per_page=100" --paginate \
--jq '[.[] | .body | split("\n")[0] | select(startswith("Waiting for:"))] | last'; done
92 Waiting for: Flowfin/core#39
39 Waiting for: Flowfin/core#27
27 Waiting for: Flowfin/core#291
291 Waiting for: act - a pure-Rust crypto provider for `rustls` reaching a release the target leg compiles on every triple in 0113's set (upstream).

So that member drains after the wait this condition exists to retake, never
before it. A condition whose firing is downstream of the thing it would end is
not a way out of it.

**Its second exit is a `blocked-on-` label, and that move is argued shut on #98
itself.** The label subtracts an issue from the count without closing it, it has
been applied and removed twice, and the removal of 2026-08-22 gives its reason
in the issue's own words:

> Nothing holds it. It is the index, and an index that waits on the things it
> indexes cannot be read first, which is the one job it has.

gh api repos/Flowfin/core/issues/98/timeline --paginate \
--jq '.[] | select(.event=="unlabeled" or .event=="labeled") | "\(.created_at) \(.event) \(.label.name)"'

That reason is about what the index is for rather than about the state of the
board on any day, so it does not expire with a milestone.

Both exits shut, the floor is one, and zero is a state no arrangement of this
board's open issues produces.

## What moved between the reading and this record

#351 derived the count as one with #98 as its only member, and the decision of
2026-09-18 restates that figure. Read on 2026-09-18 the same command answers
eight, and #98 is one of the eight. The difference changes nothing this record
decides, because the argument above needs the floor and not the number: the two
exits are shut at any count, and a count of eight is no closer to zero than a
count of one.

It is written here rather than left out because the count is the one figure in
the argument that moves, and a reader who runs the command and gets a number
neither the issue nor the decision names should find that difference already
accounted for instead of concluding that one of the three is wrong.

## What this does not decide

- **Whether waiting is still right.** The choice 0291 holds is untouched. This
reads one of its four reversal conditions and takes no position on the other
three or on the decision they would reverse.
- **Whether the condition should be dropped or rewritten.** Rewording what would
reverse a landed record is not one of the edits 0001 allows, so the condition
stands in 0291 exactly as written and this record says how it is read.
- **Whether #98 should ever be closed or labelled.** Both of its exits are read
here as they stand today. Neither is argued for or against.
- **The other three conditions.** A provider reaching a release the target leg
compiles everywhere, a runner image measured with a working C cross-toolchain,
and a triple leaving 0113's set are each a state of the world outside this
tracker, and each one still fires.
- **Anything about the count's definition.** What subtracts an issue is a
`blocked-on-` label and nothing else, which is the rule the command encodes,
and this record neither widens nor narrows it.

## Why this is written down

Without it the reading lives in a comment on #291 and in the body of #351, and
the next reader of 0291 meets a reversal condition that reads as live. Two
things follow from that, and the second is the expensive one. A reader who takes
it for a trigger waits for a state this board does not produce, which is the
failure the condition was written against, arriving through the condition itself.
And a reader who notices that it cannot fire re-derives this argument from the
tracker - the chain behind #98, the label history, the reason of 2026-08-22 -
which is an hour of reading that ends where this record already is.

A comment is not a home for it either way. #291's done-condition is about a
socket, a record and a green target leg, so the question cannot close with it,
and what lives only in a comment is re-derived by whoever reads the record next.

## Alternatives, and what each cost

**Leave the condition unread.** It is the state that produced this issue: the
reading existed on #291, was correctly declined there as a rule question, and
had no home. It costs nothing today and costs the whole argument again at every
reader, and the failure it leaves in place is somebody waiting for zero.

**Rewrite the condition inside 0291 so it names a reachable state.** The cheapest
thing to type and the one 0001 refuses: rewording is not among the edits the
register allows, and a rule about what a reversal condition may say would be
settled by landing a diff rather than by deciding it. It would also lose the
price the original sentence records, which is the part that turned out to be
true.

**Supersede 0291.** It would carry the condition forward corrected, and it
discards the decision, the costs it weighed, and the three conditions that do
fire, in order to repair the one that does not. That is the price 0269 and 0313
were both written to avoid paying for a single line.

**Subtract #98 by labelling it.** This makes the count reachable at once and
makes it dishonest: the label means an issue waits on another open issue on this
board, #98 waits on nothing, and the board's index would be hidden from the
count that decides whether the board has work. The reason was written on #98 on
2026-08-22 and is quoted above rather than re-argued here.

## What would reverse this

#98 gains an exit this board reaches. Either its done-condition stops being
downstream of the wait, or the reason of 2026-08-22 is overturned and the index
is subtracted from the count some other way. Either one puts a reachable zero
back and makes the condition a trigger again, and this record is then wrong in
the direction that is safe to discover.

The population the count is taken over changes - a second issue takes up
permanent residence in it for a reason of its own, or what subtracts an issue
stops being the `blocked-on-` prefix. The floor then has to be re-derived, and
the reading above is about #98 alone rather than about whatever else is standing
there.

One of 0291's other three conditions fires. The wait ends on its own terms, the
record naming the provider supersedes 0291, and this narrowing goes with it
rather than outliving the sentence it reads.
1 change: 1 addition & 0 deletions docs/decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,4 @@ their wording, is under `## Decisions` in [CONTRIBUTING.md](../../CONTRIBUTING.m
- [0292. The means the core speaks HTTP with, and what it costs](0292-the-means-the-core-speaks-http-with.md)
- [0303. The licence the core is offered under, and the dependency set that follows from it](0303-the-licence-the-core-is-offered-under.md)
- [0313. A dated re-reading of a landed record](0313-a-dated-re-reading-of-a-landed-record.md)
- [0351. The reversal condition 0291 counts this board with](0351-the-condition-that-counts-this-board.md)
Loading