issueflow-reconcile — the board discriminator is .pull_request == null, not has(), or this forge has no issues (#210)
#211
Merged
andres
merged 4 commits from 2026-08-05 15:49:31 +00:00
build/210-discriminator into main
4 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 5b78d29201 |
test(issueflow): isolate the scalar guard — the list row admits, the payload stands down (#210)
All checks were successful
CI / test (pull_request) Successful in 3m10s
CI / release-exercise (pull_request) Successful in 11s
CI / self-guards (pull_request) Successful in 6s
CI / action-exercise (pull_request) Successful in 6s
CI / docs-sync-exercise (pull_request) Successful in 6s
Refs guard / refs-not-closing (pull_request) Has been skipped
labels / labels (pull_request) Successful in 8s
@codex-reviewer-andresmgsl found the subtlety my board fixture could not reach: BOARD_RECORDS filters an object-valued row out of the LIST before the per-issue guard ever sees it, so no board fixture alone can prove the scalar stand-down. My #64 case proved the gather excluded it, not that reconcile_issue_pass did. The fixture that isolates the site is a deliberate mismatch: the LIST row is null-valued, so the board gather admits #65 — and the INDIVIDUAL payload the sweep then fetches is object-valued. Only reconcile_issue_pass's own guard can stand that down. Three rows over the same number, so the guard cannot pass by standing everything down or by admitting everything: payload object-valued -> NOT reconciled payload null-valued -> reconciled payload key absent -> reconciled (the GitHub shape) Mutating ONLY the scalar predicate now reds three BEHAVIOURAL rows plus the pin, where before it red only the pin and a neighbour. pass_disc is gone: it repeated the predicate inside the test helper and never called production — which is the same isolated-expression trap, one layer down, in the fix for it. issueflow 512/512; test/run.sh 28/28; shellcheck 0.10.0 clean. Refs #210 |
|||
| 087ea4a24b |
test(issueflow): each site observable through the real path, not through the expression it contains (#210)
All checks were successful
CI / test (pull_request) Successful in 3m9s
CI / release-exercise (pull_request) Successful in 10s
CI / self-guards (pull_request) Successful in 7s
CI / action-exercise (pull_request) Successful in 6s
CI / docs-sync-exercise (pull_request) Successful in 6s
Refs guard / refs-not-closing (pull_request) Has been skipped
labels / labels (pull_request) Successful in 8s
@codex-reviewer-andresmgsl's three, and items 1 and 2 were still open after
|
|||
| bada4ffff5 |
test(issueflow): each of the three sites is caught by behaviour, not only by the pin (#210)
All checks were successful
CI / test (pull_request) Successful in 3m9s
CI / release-exercise (pull_request) Successful in 11s
CI / self-guards (pull_request) Successful in 7s
CI / action-exercise (pull_request) Successful in 6s
CI / docs-sync-exercise (pull_request) Successful in 6s
Refs guard / refs-not-closing (pull_request) Has been skipped
labels / labels (pull_request) Successful in 8s
@codex-reviewer-andresmgsl's two scope items, applied before the first review round rather than after. 1. THE GUARD IS COMMENT-AWARE, WITH CONTROLS. It already stripped comments — it has to, because the #188 warning that explains why has("pull_request") is wrong contains the string. Without controls that was an untested property, and the pressure it creates is real: a raw grep would push a builder into deleting the very warning that prevents recurrence. Two fixtures now prove it: the explanatory comment is allowed, an executable jq filter is rejected. 2. ALL THREE SITES ARE DRIVEN BY BEHAVIOUR. The pin makes any revert red, but a pin proves a string is absent, not that each replacement means the intended thing: BOARD_RECORDS the forgejo-shaped board is not read as empty release_bodies an open `release` issue whose gate holds an open member makes a claimable NON-member draw a window flag — empty carriers, no flag, so the row discriminates the site instead of merely reaching it reconcile_issue_pass the scalar payload: key-present-null is an issue, object-valued is a PR, key-absent is still an issue The release_bodies row did NOT discriminate on its first write — it asserted an issue number that BOARD_RECORDS also produces, so reverting the site left it green. Caught by mutating each site separately rather than trusting the suite total. Mutation, per site: BOARD_RECORDS 3 red, release_bodies 2 red, reconcile_issue_pass 2 red. test/run.sh 28/28; issueflow 510/510; shellcheck 0.10.0 clean. Refs #210 |
|||
| 877e09e015 |
fix(issueflow): the board discriminator is .pull_request == null, not has() (#210)
All checks were successful
CI / test (pull_request) Successful in 3m8s
CI / release-exercise (pull_request) Successful in 11s
CI / self-guards (pull_request) Successful in 7s
CI / action-exercise (pull_request) Successful in 6s
CI / docs-sync-exercise (pull_request) Successful in 6s
Refs guard / refs-not-closing (pull_request) Has been skipped
labels / labels (pull_request) Successful in 8s
issueflow-reconcile has been blind on this forge since the 0.6.0 merge landed. Run 368 — #198's own post-merge acceptance probe — printed: issueflow: no open issues. issueflow: reconciled. over a board of nine. Every Forgejo entry CARRIES the `pull_request` key, valued null on an issue, so `select(has("pull_request") | not)` selects zero rows. Measured again today: #209 (an issue) has the key valued null; #208 and #207 (PRs) have it valued as objects. This is mine. #188 fixed exactly this and the file's own comment at :1113 states the rule, with :1121 already using it correctly. Resolving hunk 4 of the merge I took upstream's board block wholesale and carried the wrong discriminator into three sites — the gather, the release-body gather, and reconcile_issue_pass — in the PR whose stated purpose was to stop blind sweeps reporting success. Cost while it stood: no issue transitions, no claim reclaims, no nudges, no board flags — and no `post-merge` transitions, which is why #192 and #198 both still read `claimed` after their PRs merged, and why #198's own closure criterion could not complete. Two guards, because a comment did not hold: * A GATHER-LEVEL CASE against a Forgejo-shaped fixture — every entry carrying the key. The existing discriminator cases assert jq expressions in isolation and passed throughout this regression; they never ran the gather that uses them, which is precisely how it survived review. * A SOURCE PIN forbidding has("pull_request") on this surface, so a future sync cannot reintroduce it 40 lines below the comment forbidding it. Reverting the board gather reds both. Reverting reconcile_issue_pass reds the pin. test/run.sh 28/28 under jq 1.7 and jq 1.6; issueflow 503/503; shellcheck 0.10.0 and actionlint clean. Refs #210 |