fix: parse live issue dependency shapes

This commit is contained in:
codex-bot-andresmgsl 2026-07-23 00:42:24 +00:00
parent a811da8b4f
commit 1532f22eb7
2 changed files with 24 additions and 4 deletions

View file

@ -85,7 +85,8 @@ claim_decision() { # $1 assignee count, $2 linked open PR, $3 age seconds
}
blocked_references() { # body on stdin -> issue numbers, one per line
sed -nE 's/^[[:space:]]*Blocked by[[:space:]]+//Ip' \
sed -nE 's/.*Blocked by[[:space:]]+//Ip' \
| sed -E 's/[.;][[:space:]].*$//' \
| { grep -Eo '#[0-9]+' || true; } | tr -d '#' | sort -nu
}
@ -99,7 +100,11 @@ blocked_decision() { # $1 refs, $2 OPEN/CLOSED states
}
epic_references() { # markdown task-list issue references from body on stdin
sed -nE '/^[[:space:]]*[-*][[:space:]]+\[[ xX]\]/p' \
awk '
tolower($0) ~ /^##[[:space:]]+task list[[:space:]]*$/ { in_list = 1; next }
in_list && /^#/ { exit }
in_list && /^[[:space:]]*[-*][[:space:]]+\[[ xX]\]/ { print }
' \
| { grep -Eo '#[0-9]+' || true; } | tr -d '#' | sort -nu
}

View file

@ -37,8 +37,20 @@ check "quiet claim without PR is reclaimed" 0 "RECLAIM" claim_decision 1 false $
check "quiet unassigned claim is also reclaimed" 0 "RECLAIM" claim_decision 0 false $((STALE_AFTER + 1))
# Invariant 3: blocked declarations parse and release only when all close.
refs="$(blocked_references <<< $'Context #99\nBlocked by #12 and #7')"
refs="$(blocked_references <<< $'Context #99. Blocked by #12 (first), #7 (second). Blocks #44.')"
check "blocked declaration extracts only declared refs" 0 $'7\n12' printf '%s\n' "$refs"
body="Part of #1. Blocked by #11 (needs a ceremony tag to pin), #12 (must be executed from the guide), #19 (the conversion vendors the doctrine). Blocks #14, #15 (they inherit the pilot's lessons)."
check "real issue 13 inline blockers parse" 0 "" test \
"$(blocked_references <<<"$body")" = $'11\n12\n19'
body="Part of #1. Blocked by #13 (inherits the pilot's lessons). Can run in parallel with #15."
check "real issue 14 inline blocker parses" 0 "" test \
"$(blocked_references <<<"$body")" = "13"
body="Part of #1. Blocked by #13 (pilot lessons). Can run in parallel with #14."
check "real issue 15 inline blocker parses" 0 "" test \
"$(blocked_references <<<"$body")" = "13"
body="Part of #1. Blocked by #11, #12 (needs a released ceremony + the bootstrap guide); benefits from #13's lessons but does not need #14/#15."
check "real issue 16 inline blockers parse" 0 "" test \
"$(blocked_references <<<"$body")" = $'11\n12'
check "open blocker keeps issue blocked" 0 "KEEP" blocked_decision "$refs" $'CLOSED\nOPEN'
check "all closed blockers release issue" 0 "READY" blocked_decision "$refs" $'CLOSED\nCLOSED'
check "missing blocked declaration is flagged" 0 "FLAG_UNPARSEABLE" blocked_decision "" ""
@ -51,8 +63,11 @@ check "outside author already marked needs-triage is stable" 0 "KEEP" author_dec
check "later sweep accepts a normalized outside-authored issue" 0 "KEEP" queue_decision <<<"ready"
# Invariant 5: completed epics get one nudge; incomplete/unparseable do not.
epic_refs="$(epic_references <<< $'- [ ] #3 first\n- [x] #2 done\nplain #8')"
epic_refs="$(epic_references <<< $'## Definition of done\n- [ ] outside #8\n\n## Task list\n- [ ] #3 first\n- [x] #2 done\nplain #9')"
check "epic parser reads task-list refs only" 0 $'2\n3' printf '%s\n' "$epic_refs"
body=$'## Task list\n- [x] #2 done\n- [x] #3 done\n\n## Definition of done\n- [ ] open issue #99 must not suppress the nudge'
check "epic parser stops before later checkbox sections" 0 "" test \
"$(epic_references <<<"$body")" = $'2\n3'
check "completed epic is nudged" 0 "NUDGE" epic_decision "$epic_refs" $'CLOSED\nCLOSED'
check "open epic child suppresses nudge" 0 "KEEP" epic_decision "$epic_refs" $'CLOSED\nOPEN'
check "epic without parseable children is stable" 0 "KEEP" epic_decision "" ""