fix(#3503): derive the code-review diff base from GSD's own commit scopes, not prose mentions (#3526)
* fix(#3503): derive the code-review diff base from GSD's own commit scopes, not prose mentions The #2989/#3191 anchor ('[Pp]hase N' + POSIX boundary) still resolved the phase diff base ~4 phases early on real repos: git log --grep searches full commit bodies and tail -1 keeps the OLDEST match, so a single prose mention anywhere in history (a planning commit forward-referencing the phase per D-09, a doc commit using '### Phase N' as a format example) silently captured the base — while GSD's own commits, which use conventional-commit scopes (docs(phase-6):, feat(6-01):, docs(06):) and never contain the literal 'Phase N', were matched by nothing. The wrong base inflated the Tier-3 file-list fallback, the #2666 SUMMARY/diff union, the reviewer agent's diff_base, and fallow's --changed-since scope, with no warning. All three derivation sites (Tier-3 fallback, spawn_reviewer, fallow structural pre-pass) now grep for the subject-line conventional-commit phase scope under --extended-regexp, in lockstep per the #3191 contract: ^[[:alpha:]]+!?\((phase-)?(N|0N)(-[0-9]+)?\)!?: PHASE_SCOPE_NUM accepts both padded and unpadded phase spellings because workflows emit the unpadded roadmap number (docs(phase-6):) while code-review greps the zero-padded PADDED_PHASE. The ^ anchor makes it a subject-line match, so commit-body prose can never capture the base. The POSIX-ERE portability rule (#3191, no \b), the fail-closed empty-result warning, and the --files escape hatch are preserved: histories with no scope-style commits yield no base instead of an arbitrary one. Tests (tests/code-review-pipeline-regression.test.cjs): new Bug 6 (#3503) block executes the SHIPPED bash from all three sites against a real git fixture whose history carries every prose false-positive class from the issue — red pre-fix (the prose-body commits captured the base at every site), green post-fix. The Bug 5 (#3191) block is updated to the scope anchor contract (its fixtures bound to the shipped text), and its T6 docs-parity guard now enforces the identical scope-anchored grep plus the PHASE_SCOPE_NUM prep at every git-log site. Emitted drift: 3503-diff-base-scope-anchor.json acks the deliberate workflow growth; the spent 3191-unanchored-grep-sites.json fragment (its code-review.md entry was consumed when #3191 merged) is pruned. * chore(#3503): add changeset fragment for PR #3526 * fix(#3503): rebase onto next and correct the emitted-drift ack Rebase onto origin/next@6badb839 (PR freshness: #3514/#3516 landed after this branch was cut). Post-rebase the attribution gate classifies the two source-path ack entries (gsd-core/workflows/code-review.md, structural- pre-pass.md) as stale — source files present in the diff are identity- attributed by the table, so only the emitted code-review.md basename growth needs an acknowledgment. The fragment now names exactly that one consumed entry. --------- Co-authored-by: sim <sim@local>
This commit is contained in:
@@ -26,14 +26,20 @@ FALLOW_STDERR_TMP=$(mktemp)
|
||||
|
||||
# Phase scope uses fallow's native changed-files scoping (--changed-since <base>).
|
||||
# Derive the phase base commit; if none is found, fall back to repo scope (fallow
|
||||
# auto-detects the base branch). #3191: the grep is the SAME anchored,
|
||||
# POSIX-portable phase-mention derivation the workflow's Tier-3 scope step uses
|
||||
# ("Phase N" followed by a non-alphanumeric or end-of-line) — a bare digit
|
||||
# substring matches version strings, dates, and other phases, and the oldest
|
||||
# auto-detects the base branch). #3191/#3503: the grep is the SAME anchored,
|
||||
# POSIX-portable conventional-commit-scope derivation the workflow's Tier-3
|
||||
# scope step uses (subject-line `type((phase-)?N(-plan)?):`, padded or unpadded
|
||||
# phase spelling). Free prose in commit bodies — "deferred to Phase N per
|
||||
# D-09", "### Phase N" format examples — never captures the base, and a bare
|
||||
# digit substring matches version strings, dates, and other phases; the oldest
|
||||
# such false match would silently widen --changed-since far past the phase.
|
||||
FALLOW_SCOPE_ARGS=()
|
||||
if [ \"$FALLOW_SCOPE\" = \"phase\" ]; then
|
||||
FALLOW_PHASE_COMMITS=$(git log --oneline --all --grep=\"[Pp]hase ${PADDED_PHASE}([^[:alnum:]_]|$)\" --extended-regexp --format=\"%H\" 2>/dev/null)
|
||||
PHASE_SCOPE_NUM=\"${PADDED_PHASE}\"
|
||||
case \"$PADDED_PHASE\" in
|
||||
0[0-9]*) PHASE_SCOPE_NUM=\"${PADDED_PHASE#0}|${PADDED_PHASE}\" ;;
|
||||
esac
|
||||
FALLOW_PHASE_COMMITS=$(git log --oneline --all --extended-regexp --grep=\"^[[:alpha:]]+!?\((phase-)?(${PHASE_SCOPE_NUM})(-[0-9]+)?\)!?:\" --format=\"%H\" 2>/dev/null)
|
||||
if [ -n \"$FALLOW_PHASE_COMMITS\" ]; then
|
||||
FALLOW_BASE=$(echo \"$FALLOW_PHASE_COMMITS\" | tail -1)^
|
||||
FALLOW_SCOPE_ARGS=(--changed-since \"$FALLOW_BASE\")
|
||||
|
||||
Reference in New Issue
Block a user