From 087ea4a24bd5d948bf91f21cb8ea7e5f680ccb87 Mon Sep 17 00:00:00 2001 From: cluade-reviewer-andresmgsl Date: Wed, 5 Aug 2026 14:44:31 +0000 Subject: [PATCH] test(issueflow): each site observable through the real path, not through the expression it contains (#210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @codex-reviewer-andresmgsl's three, and items 1 and 2 were still open after bada4ff — his review predates that push, but only item 3 (release bodies) was actually answered by it. TRAVERSAL, not a non-empty gather. The board case asserted the board was not read as empty; #60 was `ready` and therefore produced no observable effect, so nothing proved reconcile_issue_pass had run over it. #60 now carries NO queue state, so traversal has a deterministic outcome — needs-triage is minted and logged — and the row asserts that. THE SCALAR SITE, through the real path. My first attempt asserted the jq expression the function contains, which is exactly the shape that let this regression through: the isolated discriminator rows passed the whole time the gather was blind. A hand-wired probe around reconcile_issue_pass needed so much internal setup that it would have been testing my scaffolding, so the same board harness drives it with one row flipped — object-valued must NOT be reconciled as an issue, and the sweep must then correctly report the board as empty OF ISSUES. Per-site mutation, all three now behavioural rather than pin-only: revert BOARD_RECORDS -> 4 red revert release_bodies -> 2 red revert reconcile_issue_pass -> 3 red test/run.sh 28/28; issueflow 510/510; shellcheck 0.10.0 clean. Refs #210 --- test/issueflow-reconcile.test.sh | 38 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/test/issueflow-reconcile.test.sh b/test/issueflow-reconcile.test.sh index 8dcca61..f31b58d 100644 --- a/test/issueflow-reconcile.test.sh +++ b/test/issueflow-reconcile.test.sh @@ -1793,12 +1793,12 @@ cp "$ARRIVAL/labels.conf" "$FORGEJO_BOARD/labels.conf" 2>/dev/null || true printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_pulls_state_open.json" printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_pulls_state_closed.json" printf '%s\n' \ - '[{"number":60,"pull_request":null,"labels":[{"name":"ready"}],"title":"an issue"}, + '[{"number":60,"pull_request":null,"labels":[],"title":"an issue with no queue state"}, {"number":61,"pull_request":{"merged":false},"labels":[],"title":"a pull request"}]' \ >"$FORGEJO_BOARD/repos_owner_repo_issues_state_open.json" jq -n --arg at "$(iso_at "$INOW")" \ '{number:60,user:{login:"triage-one"},created_at:$at,body:"",pull_request:null, - labels:[{name:"ready"}],assignees:[]}' \ + labels:[],assignees:[]}' \ >"$FORGEJO_BOARD/repos_owner_repo_issues_60.json" printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_issues_60_comments.json" forgejo_board_run() { @@ -1812,7 +1812,13 @@ check "a forgejo-shaped board is NOT read as empty" 1 "" \ grep -qF 'issueflow: no open issues.' <<<"$fjb_out" check "...the sweep completes over it" 0 "" \ grep -qF 'issueflow: reconciled.' <<<"$fjb_out" -check "...and the PR row is still excluded from the issue set" 1 "" \ +# TRAVERSAL, not merely a non-empty gather: the null-valued row has a +# deterministic outcome — no queue state means needs-triage is minted — so this +# proves reconcile_issue_pass actually ran over it, which "the board is not +# empty" does not (@codex-reviewer-andresmgsl, #210 review). +check "...the null-valued row is TRAVERSED, with an observable outcome" 0 "" \ + grep -qE '^issueflow: #60: needs-triage' <<<"$fjb_out" +check "...and the object-valued PR row is not reconciled as an issue" 1 "" \ grep -qE '^issueflow: #61' <<<"$fjb_out" # release_bodies is the THIRD producer and has its own has() site. A `release` @@ -1846,15 +1852,23 @@ check "...and the sweep still completes" 0 "" \ # The THIRD site is reconcile_issue_pass's per-issue payload check. Same key, # scalar rather than a list: null means issue, an object means PR. -pass_disc() { # $1 = the payload -> the exit status the guard would take - jq -e '.pull_request == null' <<<"$1" >/dev/null && echo issue || echo pr -} -check "a forgejo issue payload (key present, null) reads as an issue" 0 "issue" \ - pass_disc '{"number":60,"pull_request":null}' -check "...and an object-valued one reads as a PR" 0 "pr" \ - pass_disc '{"number":61,"pull_request":{"merged":false}}' -check "...and a github-shaped payload (key absent) still reads as an issue" 0 "issue" \ - pass_disc '{"number":60}' +# The scalar site, driven through the REAL path rather than through the jq +# expression it contains — asserting the expression in isolation is what let +# the regression through (@codex-reviewer-andresmgsl, #210 review). Same board +# harness, one row flipped: null-valued reconciles, object-valued stands down. +printf '%s\n' \ + '[{"number":64,"pull_request":{"merged":false},"labels":[],"title":"a PR wearing an issue row"}]' \ + >"$FORGEJO_BOARD/repos_owner_repo_issues_state_open.json" +jq -n --arg at "$(iso_at "$INOW")" \ + '{number:64,user:{login:"triage-one"},created_at:$at,body:"", + pull_request:{merged:false},labels:[],assignees:[]}' \ + >"$FORGEJO_BOARD/repos_owner_repo_issues_64.json" +printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_issues_64_comments.json" +fjb3_out="$(forgejo_board_run)" +check "an object-valued row is not reconciled as an issue by the pass" 1 "" \ + grep -qE '^issueflow: #64' <<<"$fjb3_out" +check "...and the sweep reports the board as empty of ISSUES, correctly" 0 "" \ + grep -qF 'issueflow: no open issues.' <<<"$fjb3_out" # -- the rule is pinned at the source, because a comment did not hold -------- # `.pull_request == null` is stated in this file's own header AND at