fix: union repeated Blocked by declarations #185

Closed
codex-bot-andresmgsl wants to merge 1 commit from build/184-multi-blocked-by into main
codex-bot-andresmgsl commented 2026-07-25 13:57:31 +00:00 (Migrated from github.com)

Closes #184

Worklog

  • Scan every Blocked by occurrence and union its clause records
  • Add repeated-declaration and prose-before-declaration regressions
  • Add repeated open/closed decision coverage
  • Add the grouped changelog fragment
  • Run the full test suite and static checks
  • Mark acceptance criteria complete and request the review panel

Acceptance criteria

  • The rig#154 repeated declaration produces 148 152 153
  • Earlier prose containing “blocked by” cannot hide a later declaration
  • Existing invariant-3 parsing cases remain unchanged
  • A repeated open/closed declaration decides KEEP
  • mawk-compatible; shellcheck-clean; test/run.sh green

Verification

  • bash test/run.sh (18 test files pass; issueflow has 143 checks)
  • bash .github/scripts/shellcheck-all.sh
  • bash .github/scripts/actionlint-all.sh
  • git diff --check
Closes #184 ## Worklog - [x] Scan every `Blocked by` occurrence and union its clause records - [x] Add repeated-declaration and prose-before-declaration regressions - [x] Add repeated open/closed decision coverage - [x] Add the grouped changelog fragment - [x] Run the full test suite and static checks - [x] Mark acceptance criteria complete and request the review panel ## Acceptance criteria - [x] The rig#154 repeated declaration produces `148 152 153` - [x] Earlier prose containing “blocked by” cannot hide a later declaration - [x] Existing invariant-3 parsing cases remain unchanged - [x] A repeated open/closed declaration decides `KEEP` - [x] mawk-compatible; shellcheck-clean; `test/run.sh` green ## Verification - `bash test/run.sh` (18 test files pass; issueflow has 143 checks) - `bash .github/scripts/shellcheck-all.sh` - `bash .github/scripts/actionlint-all.sh` - `git diff --check`
danmt (Migrated from github.com) reviewed 2026-07-25 13:57:31 +00:00
grok-bot-andresmgsl commented 2026-07-25 14:00:41 +00:00 (Migrated from github.com)

🔎 reviewing head 07c8db9939

🔎 reviewing head 07c8db9939dae018d0113c00e51ef593a0ba10e6
claude-bot-andresmgsl commented 2026-07-25 14:00:47 +00:00 (Migrated from github.com)

🔎 reviewing head 07c8db9939

🔎 reviewing head 07c8db9939dae018d0113c00e51ef593a0ba10e6
grok-bot-andresmgsl (Migrated from github.com) approved these changes 2026-07-25 14:01:36 +00:00
grok-bot-andresmgsl (Migrated from github.com) left a comment

Verdict: approve

Panel membership: on-panel (author is codex-bot-andresmgsl; I am required).

Spec / acceptance criteria (#184)

Criterion Result
rig#154-shaped body → 148 152 153 Pass (manual + test)
Earlier “blocked by” prose does not hide a later declaration Pass (both clauses contribute; prose has no refs)
Existing invariant-3 cases unchanged Pass (soft-wrap, unterminated, real-issue bodies, qualified drops, adjacency forms)
Repeated open/closed → KEEP Pass
mawk-compatible; shellcheck-clean; test/run.sh green Pass

Closes #184 is present. Grouped changelog fragment changelog.d/184.md is present and proportional.

Code

blocked_reference_records now slurps the body and walks every blocked by occurrence, cutting each clause at its own first ./; (or to EOF when unterminated). That is exactly the union the issue specifies: later declarations are no longer dropped when the first clause names a closed issue, and earlier prose cannot monopolize the parse. Soft-wrap still lands inside a single clause. Cross-repo classification and blocked_decision are untouched; over-retention of historical prose is called out in the function comment with the correct bias (#184).

Blocks #N correctly never contributes. I re-ran the issue’s exact repro string under system mawk and got 148\n152\n153.

Verification (this head 07c8db9939dae018d0113c00e51ef593a0ba10e6)

  • Detached worktree at the head SHA
  • bash test/run.sh — 18 files, 0 failed (issueflow: 143 checks, including the three new ones)
  • bash .github/scripts/shellcheck-all.sh — clean
  • Manual probes of AC1/AC2, soft-wrap, unterminated, qualified drops, KEEP/READY/FLAG paths under mawk
  • actionlint is not installed in this box; relied on CI (action-exercise / workflow checks green on this head) and reading the unchanged workflow surface
  • CI on head: test, self-guards, action-exercise, release-exercise fixtures, labels reconcile — success

No blocking issues. Non-blocking none worth a round-trip.

## Verdict: approve **Panel membership:** on-panel (author is `codex-bot-andresmgsl`; I am required). ### Spec / acceptance criteria (#184) | Criterion | Result | |---|---| | rig#154-shaped body → `148 152 153` | Pass (manual + test) | | Earlier “blocked by” prose does not hide a later declaration | Pass (both clauses contribute; prose has no refs) | | Existing invariant-3 cases unchanged | Pass (soft-wrap, unterminated, real-issue bodies, qualified drops, adjacency forms) | | Repeated open/closed → `KEEP` | Pass | | mawk-compatible; shellcheck-clean; `test/run.sh` green | Pass | `Closes #184` is present. Grouped changelog fragment `changelog.d/184.md` is present and proportional. ### Code `blocked_reference_records` now slurps the body and walks every `blocked by` occurrence, cutting each clause at its own first `.`/`;` (or to EOF when unterminated). That is exactly the union the issue specifies: later declarations are no longer dropped when the first clause names a closed issue, and earlier prose cannot monopolize the parse. Soft-wrap still lands inside a single clause. Cross-repo classification and `blocked_decision` are untouched; over-retention of historical prose is called out in the function comment with the correct bias (#184). `Blocks #N` correctly never contributes. I re-ran the issue’s exact repro string under system `mawk` and got `148\n152\n153`. ### Verification (this head `07c8db9939dae018d0113c00e51ef593a0ba10e6`) - Detached worktree at the head SHA - `bash test/run.sh` — 18 files, 0 failed (issueflow: 143 checks, including the three new ones) - `bash .github/scripts/shellcheck-all.sh` — clean - Manual probes of AC1/AC2, soft-wrap, unterminated, qualified drops, KEEP/READY/FLAG paths under mawk - `actionlint` is not installed in this box; relied on CI (`action-exercise` / workflow checks green on this head) and reading the unchanged workflow surface - CI on head: `test`, `self-guards`, `action-exercise`, release-exercise fixtures, labels reconcile — success No blocking issues. Non-blocking none worth a round-trip.
claude-bot-andresmgsl (Migrated from github.com) approved these changes 2026-07-25 14:03:39 +00:00
claude-bot-andresmgsl (Migrated from github.com) left a comment

Approve — reviewed at head 07c8db9939.

The extraction rewrite is correct: the body is accumulated whole, every blocked by occurrence is scanned, each clause runs to its own first ./;, and the unterminated tail still prints to end of input. A marker embedded inside an already-printed clause contributes its refs through the printed superset, so the union is never lossy. Classification stays per-record through the unchanged issue_references, so #61's cross-repo invariant holds over the larger set.

Verified, not just read:

  • bash test/run.sh — 18 test files pass (issueflow: 143 checks). shellcheck-all.sh and actionlint-all.sh exit 0; git diff --check clean. The box's system awk is mawk 1.3.4, so mawk compatibility is exercised, not assumed.
  • AC1 — the rig#154 body verbatim → 148 152 153. AC2 — earlier prose containing "blocked by" no longer hijacks: the two-line body → 148 152 153, and the prose clause's refs would be retained too, never substituted.
  • Must-fail check ran: I reverted blocked_reference_records to the first-occurrence-only shape and re-ran the suite — exactly the two new cases go red (repeated blocker declarations retain every clause, earlier blocker prose does not hide a later declaration), everything else stays green. The tests pin precisely the promotion bug this issue is about.
  • Boundaries probed by hand: Blocks #155 never contributes; unterminated repeated clauses (Blocked by #12\nBlocked by #13) union both; a qualified ref in a second clause (Blocked by #12. Blocked by rig#7.) still routes to blocked_cross_references; the soft-wrapped and comma/paren/slash-adjacent single-clause cases parse identically to before; blocked_decision on the union with one OPEN → KEEP.
  • The retain-bias comment states the over-retention trade-off with the #184 pointer, where the next reader will look, per the spec. The changelog fragment is grouped-shape (### Fixed), under the #167 length bound, named 184.md.

One non-blocking note: the new an open blocker in a repeated declaration prevents promotion check drives blocked_decision with a literal $'12\n13' rather than piping a repeated-declaration body through extraction, so by itself it wouldn't catch an extraction regression — but the two extraction cases beside it do, and together they cover the pipeline end to end. Fine as is.

**Approve** — reviewed at head 07c8db9939dae018d0113c00e51ef593a0ba10e6. The extraction rewrite is correct: the body is accumulated whole, every `blocked by` occurrence is scanned, each clause runs to its own first `.`/`;`, and the unterminated tail still prints to end of input. A marker embedded inside an already-printed clause contributes its refs through the printed superset, so the union is never lossy. Classification stays per-record through the unchanged `issue_references`, so #61's cross-repo invariant holds over the larger set. Verified, not just read: - `bash test/run.sh` — 18 test files pass (issueflow: 143 checks). `shellcheck-all.sh` and `actionlint-all.sh` exit 0; `git diff --check` clean. The box's system awk **is mawk 1.3.4**, so mawk compatibility is exercised, not assumed. - **AC1** — the rig#154 body verbatim → `148 152 153`. **AC2** — earlier prose containing "blocked by" no longer hijacks: the two-line body → `148 152 153`, and the prose clause's refs would be retained too, never substituted. - **Must-fail check ran**: I reverted `blocked_reference_records` to the first-occurrence-only shape and re-ran the suite — exactly the two new cases go red (`repeated blocker declarations retain every clause`, `earlier blocker prose does not hide a later declaration`), everything else stays green. The tests pin precisely the promotion bug this issue is about. - **Boundaries probed by hand**: `Blocks #155` never contributes; unterminated repeated clauses (`Blocked by #12\nBlocked by #13`) union both; a qualified ref in a *second* clause (`Blocked by #12. Blocked by rig#7.`) still routes to `blocked_cross_references`; the soft-wrapped and comma/paren/slash-adjacent single-clause cases parse identically to before; `blocked_decision` on the union with one OPEN → `KEEP`. - The retain-bias comment states the over-retention trade-off with the #184 pointer, where the next reader will look, per the spec. The changelog fragment is grouped-shape (`### Fixed`), under the #167 length bound, named `184.md`. One non-blocking note: the new `an open blocker in a repeated declaration prevents promotion` check drives `blocked_decision` with a literal `$'12\n13'` rather than piping a repeated-declaration body through extraction, so by itself it wouldn't catch an extraction regression — but the two extraction cases beside it do, and together they cover the pipeline end to end. Fine as is.
kimi-bot-andresmgsl commented 2026-07-25 15:28:25 +00:00 (Migrated from github.com)

🔎 reviewing head 07c8db9939

🔎 reviewing head 07c8db9939dae018d0113c00e51ef593a0ba10e6
kimi-bot-andresmgsl (Migrated from github.com) approved these changes 2026-07-25 15:34:18 +00:00
kimi-bot-andresmgsl (Migrated from github.com) left a comment

Approve — head 07c8db9.

Verified against issue #184's acceptance criteria in a detached worktree at the head (mawk 1.3.4, the exact engine CI ships):

  • AC1: blocked_references on the verbatim rig#154 body → 148 152 153. ✓
  • AC2: earlier "blocked by" prose + later Blocked by #152, #153, #148. → all three; prose refs are retained, not substituted (blocked by #9 … + Blocked by #12.9 12). ✓
  • AC3: existing invariant-3 cases unchanged — test/issueflow-reconcile.test.sh passes 114 (baseline on origin/main in the same environment: 111; the +3 are this PR's new cases). ✓
  • AC4: repeated declaration with one open blocker → KEEP. ✓ (probe: Blocked by #152. Blocked by #153. with CLOSED/OPEN states.)
  • AC5: suite run under mawk; see environment note below.
  • Must-fail: with the extraction reverted to origin/main, both new extraction cases go red (repeated blocker declarations retain every clause, earlier blocker prose does not hide a later declaration) — they pin exactly the promotion this issue is about. Restored after.
  • Cross-repo classification intact: a qualified ref in a later clause still routes to FLAG_CROSS_REPO (probe → rig#7). Control: single clause, all closed → READY. git diff --check clean. Fragment changelog.d/184.md carries the ### Fixed heading the grouped shape sentinel requires (#182). CI green on this head.

Could not verify locally: shellcheck is not installed on this box, so .github/scripts/shellcheck-all.sh was not run here — relied on CI (test, self-guards green on this head) and on reading the awk for mawk-incompatible constructs (none found: no \x escapes, match/RSTART used portably). The 29 failures in issueflow-reconcile.test.sh on this box are pre-existing environment gaps (no jq, no npm/node); they fail identically on origin/main and none is in the invariant-3 block this PR touches.

Non-blocking nits:

  • The AC4 test feeds blocked_decision a hand-written $'12\n13' ref list rather than refs derived from a repeated declaration, so the criterion is pinned one indirection away from its letter. The behavior itself is correct (probe above).
  • No pinned case for prose-refs-retained (9 12) or for a cross-repo ref in a later clause; both behave correctly, and #186 pins them if you want the coverage for free.

Panel note (not a code defect): this and #186 both Closes #184, both are assigned on the issue, and they edit the same function, the same test block, and the same changelog.d/184.md — only one can land. I'm approving each head on its merits per the round doctrine; which of the two merges is the human's call at the merge gate, and triage may want to note the double-claim that produced it.

**Approve** — head `07c8db9`. Verified against issue #184's acceptance criteria in a detached worktree at the head (mawk 1.3.4, the exact engine CI ships): - **AC1**: `blocked_references` on the verbatim rig#154 body → `148 152 153`. ✓ - **AC2**: earlier "blocked by" prose + later `Blocked by #152, #153, #148.` → all three; prose refs are retained, not substituted (`blocked by #9 …` + `Blocked by #12.` → `9 12`). ✓ - **AC3**: existing invariant-3 cases unchanged — `test/issueflow-reconcile.test.sh` passes 114 (baseline on `origin/main` in the same environment: 111; the +3 are this PR's new cases). ✓ - **AC4**: repeated declaration with one open blocker → `KEEP`. ✓ (probe: `Blocked by #152. Blocked by #153.` with `CLOSED/OPEN` states.) - **AC5**: suite run under mawk; see environment note below. - **Must-fail**: with the extraction reverted to `origin/main`, both new extraction cases go red (`repeated blocker declarations retain every clause`, `earlier blocker prose does not hide a later declaration`) — they pin exactly the promotion this issue is about. Restored after. - Cross-repo classification intact: a qualified ref in a *later* clause still routes to `FLAG_CROSS_REPO` (probe → `rig#7`). Control: single clause, all closed → `READY`. `git diff --check` clean. Fragment `changelog.d/184.md` carries the `### Fixed` heading the grouped `shape` sentinel requires (#182). CI green on this head. **Could not verify locally**: shellcheck is not installed on this box, so `.github/scripts/shellcheck-all.sh` was not run here — relied on CI (`test`, `self-guards` green on this head) and on reading the awk for mawk-incompatible constructs (none found: no `\x` escapes, `match`/`RSTART` used portably). The 29 failures in `issueflow-reconcile.test.sh` on this box are pre-existing environment gaps (no `jq`, no `npm`/`node`); they fail identically on `origin/main` and none is in the invariant-3 block this PR touches. **Non-blocking nits:** - The AC4 test feeds `blocked_decision` a hand-written `$'12\n13'` ref list rather than refs derived from a repeated declaration, so the criterion is pinned one indirection away from its letter. The behavior itself is correct (probe above). - No pinned case for prose-refs-retained (`9 12`) or for a cross-repo ref in a later clause; both behave correctly, and #186 pins them if you want the coverage for free. **Panel note (not a code defect)**: this and #186 both `Closes #184`, both are assigned on the issue, and they edit the same function, the same test block, and the same `changelog.d/184.md` — only one can land. I'm approving each head on its merits per the round doctrine; which of the two merges is the human's call at the merge gate, and triage may want to note the double-claim that produced it.
codex-bot-andresmgsl commented 2026-07-25 15:36:58 +00:00 (Migrated from github.com)

Closing round summary

What shipped

  • blocked_reference_records now scans the whole issue body and unions every Blocked by clause instead of stopping after the first occurrence.
  • Each occurrence retains the existing clause boundary (. / ;, or EOF), ordering/dedup remains unchanged, and cross-repo classification plus the KEEP / READY / FLAG_* decision table are untouched.
  • Regression coverage pins the rig#154-shaped three-declaration body, earlier prose before a real declaration, and an open blocker in a repeated declaration.
  • Added the grouped changelog.d/184.md fragment.

Rounds

  • Round 1 (head 07c8db9939dae018d0113c00e51ef593a0ba10e6): no code changes were requested. Grok, Claude, and Kimi each approved the current head. Their boundary probes confirmed repeated and unterminated clauses, soft wraps, Blocks #N exclusion, later qualified cross-repo refs, and conservative over-retention.

Verification

  • Builder: bash test/run.sh (18 test files; issueflow 143 checks), bash .github/scripts/shellcheck-all.sh, bash .github/scripts/actionlint-all.sh, and git diff --check.
  • Reviewers independently reproduced the exact rig#154 input as 148 152 153, exercised the KEEP path with mixed open/closed blockers, and ran must-fail reversions proving the new extraction regressions fail under the old behavior.
  • CI is green on the approved head: test, self-guards, action exercise, docs-sync exercise, and release-exercise fixtures all pass. The PR is mergeable with a clean merge state and no blocker:* labels.

Post-merge residue

  • PR #186 independently implements the same issue and also carries Closes #184; if this PR merges, #186 should be closed as the superseded duplicate.
  • Consumers receive this fix on their next ceremony pin bump. rig#154 was already rewritten to a single blocker clause as the interim live-board mitigation, so no board is currently known to be mis-set.
## Closing round summary ### What shipped - `blocked_reference_records` now scans the whole issue body and unions every `Blocked by` clause instead of stopping after the first occurrence. - Each occurrence retains the existing clause boundary (`.` / `;`, or EOF), ordering/dedup remains unchanged, and cross-repo classification plus the `KEEP` / `READY` / `FLAG_*` decision table are untouched. - Regression coverage pins the rig#154-shaped three-declaration body, earlier prose before a real declaration, and an open blocker in a repeated declaration. - Added the grouped `changelog.d/184.md` fragment. ### Rounds - Round 1 (head `07c8db9939dae018d0113c00e51ef593a0ba10e6`): no code changes were requested. Grok, Claude, and Kimi each approved the current head. Their boundary probes confirmed repeated and unterminated clauses, soft wraps, `Blocks #N` exclusion, later qualified cross-repo refs, and conservative over-retention. ### Verification - Builder: `bash test/run.sh` (18 test files; issueflow 143 checks), `bash .github/scripts/shellcheck-all.sh`, `bash .github/scripts/actionlint-all.sh`, and `git diff --check`. - Reviewers independently reproduced the exact rig#154 input as `148 152 153`, exercised the `KEEP` path with mixed open/closed blockers, and ran must-fail reversions proving the new extraction regressions fail under the old behavior. - CI is green on the approved head: test, self-guards, action exercise, docs-sync exercise, and release-exercise fixtures all pass. The PR is mergeable with a clean merge state and no `blocker:*` labels. ### Post-merge residue - PR #186 independently implements the same issue and also carries `Closes #184`; if this PR merges, #186 should be closed as the superseded duplicate. - Consumers receive this fix on their next ceremony pin bump. rig#154 was already rewritten to a single blocker clause as the interim live-board mitigation, so no board is currently known to be mis-set.

Pull request closed

Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/ceremony#185
No description provided.