From 5b78d292015256ae2c19810914cf170c38ed9b6c Mon Sep 17 00:00:00 2001 From: cluade-reviewer-andresmgsl Date: Wed, 5 Aug 2026 14:49:01 +0000 Subject: [PATCH] =?UTF-8?q?test(issueflow):=20isolate=20the=20scalar=20gua?= =?UTF-8?q?rd=20=E2=80=94=20the=20list=20row=20admits,=20the=20payload=20s?= =?UTF-8?q?tands=20down=20(#210)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @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 --- test/issueflow-reconcile.test.sh | 45 +++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/test/issueflow-reconcile.test.sh b/test/issueflow-reconcile.test.sh index f31b58d..918b635 100644 --- a/test/issueflow-reconcile.test.sh +++ b/test/issueflow-reconcile.test.sh @@ -1852,23 +1852,44 @@ 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. -# 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. +# THE SCALAR SITE, ISOLATED. `BOARD_RECORDS` filters an object-valued row out +# of the LIST before the per-issue guard ever sees it, so a board fixture alone +# cannot prove the scalar stand-down (@codex-reviewer-andresmgsl, #210 review). +# +# The fixture that isolates it: the LIST row is null-valued, so the board +# gather admits it — and the INDIVIDUAL payload the sweep then fetches is +# object-valued. Only reconcile_issue_pass's own guard can stand that down. printf '%s\n' \ - '[{"number":64,"pull_request":{"merged":false},"labels":[],"title":"a PR wearing an issue row"}]' \ + '[{"number":65,"pull_request":null,"labels":[],"title":"list says issue, payload says PR"}]' \ >"$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:"", + '{number:65,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" + >"$FORGEJO_BOARD/repos_owner_repo_issues_65.json" +printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_issues_65_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" +check "the per-issue guard stands down an object-valued payload" 1 "" \ + grep -qE '^issueflow: #65: needs-triage' <<<"$fjb3_out" +check "...and the sweep still completes" 0 "" \ + grep -qF 'issueflow: reconciled.' <<<"$fjb3_out" + +# The same fixture with a null-valued payload MUST reconcile — otherwise the row +# above would pass on a guard that stands everything down. +jq -n --arg at "$(iso_at "$INOW")" \ + '{number:65,user:{login:"triage-one"},created_at:$at,body:"", + pull_request:null,labels:[],assignees:[]}' \ + >"$FORGEJO_BOARD/repos_owner_repo_issues_65.json" +fjb4_out="$(forgejo_board_run)" +check "...while a null-valued payload at the same site reconciles" 0 "" \ + grep -qE '^issueflow: #65: needs-triage' <<<"$fjb4_out" + +# And the GitHub shape — key absent entirely — is still an issue. +jq -n --arg at "$(iso_at "$INOW")" \ + '{number:65,user:{login:"triage-one"},created_at:$at,body:"",labels:[],assignees:[]}' \ + >"$FORGEJO_BOARD/repos_owner_repo_issues_65.json" +fjb5_out="$(forgejo_board_run)" +check "...and a github-shaped payload (key absent) reconciles too" 0 "" \ + grep -qE '^issueflow: #65: needs-triage' <<<"$fjb5_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