@@ -770,15 +770,19 @@ get_ci_failure_details() {
770770}
771771
772772# Fetch all non-resolved, non-outdated PR comments for review context
773+ # Optional 3rd arg: cutoff date (ISO 8601). When provided, comments are split into
774+ # "new" (after cutoff — actionable) and "previous" (before cutoff — context only).
773775get_pr_review_comments () {
774776 local work_dir=" $1 "
775777 local pr_number=" $2 "
778+ local cutoff_date=" ${3:- } "
776779 local tmpdir
777780 tmpdir=$( mktemp -d)
778781
779782 cd " $work_dir "
780783
781784 log_err " [comments] Fetching review comments for PR #$pr_number ..."
785+ [ -n " $cutoff_date " ] && log_err " [comments] Cutoff date: $cutoff_date "
782786
783787 # Get review comments via GraphQL - only unresolved, non-outdated threads
784788 local repo_nwo
@@ -865,17 +869,44 @@ get_pr_review_comments() {
865869 log_err " [comments] Review bodies with text: $rv_count "
866870 log_err " [comments] Total comments collected: $(( rc_count + ic_count + rv_count)) "
867871
868- # Combine into a single JSON object
872+ # Combine and split by cutoff date if provided
869873 python3 -c "
870- import json
874+ import json, sys
875+
871876rc = json.load(open('$tmpdir /review_comments.json'))
872877ic = json.load(open('$tmpdir /issue_comments.json'))
873878rv = json.load(open('$tmpdir /reviews.json'))
874- print(json.dumps({
875- 'review_comments': rc,
876- 'issue_comments': ic,
877- 'reviews': rv
878- }, indent=2))
879+
880+ cutoff = '$cutoff_date '
881+
882+ if cutoff:
883+ def split_by_cutoff(items):
884+ new = [c for c in items if (c.get('created_at') or '') > cutoff]
885+ previous = [c for c in items if (c.get('created_at') or '') <= cutoff]
886+ return new, previous
887+
888+ rc_new, rc_prev = split_by_cutoff(rc)
889+ ic_new, ic_prev = split_by_cutoff(ic)
890+ rv_new, rv_prev = split_by_cutoff(rv)
891+
892+ print(json.dumps({
893+ 'new_comments': {
894+ 'review_comments': rc_new,
895+ 'issue_comments': ic_new,
896+ 'reviews': rv_new
897+ },
898+ 'previous_comments': {
899+ 'review_comments': rc_prev,
900+ 'issue_comments': ic_prev,
901+ 'reviews': rv_prev
902+ }
903+ }, indent=2))
904+ else:
905+ print(json.dumps({
906+ 'review_comments': rc,
907+ 'issue_comments': ic,
908+ 'reviews': rv
909+ }, indent=2))
879910"
880911
881912 rm -rf " $tmpdir "
@@ -1004,13 +1035,7 @@ start_review_task() {
10041035
10051036 mkdir -p " $ralph_dir "
10061037
1007- # Collect all non-outdated PR comments
1008- log_err " [start-review] Collecting PR comments..."
1009- local comments
1010- comments=$( get_pr_review_comments " $work_dir " " $pr_number " )
1011- log_err " [start-review] PR comments collected."
1012-
1013- # Clean working tree and check out the branch
1038+ # Clean working tree and check out the branch first (need commit date for cutoff)
10141039 clean_working_tree " $work_dir "
10151040 log_err " [start-review] Checking out branch $branch_name ..."
10161041 if ! git checkout " $branch_name " 2> /dev/null; then
@@ -1022,6 +1047,18 @@ start_review_task() {
10221047 fi
10231048 git pull origin " $branch_name " --ff-only 2> /dev/null || true
10241049 log_err " [start-review] On branch: $( git branch --show-current) , latest commit: $( git log -1 --format=' %h %s' ) "
1050+
1051+ # Get the latest commit date as cutoff for splitting comments
1052+ local latest_commit_date
1053+ latest_commit_date=$( TZ=UTC git log -1 --format=" %ad" --date=format-local:' %Y-%m-%dT%H:%M:%SZ' 2> /dev/null) || true
1054+ log_err " [start-review] Latest commit date (cutoff): $latest_commit_date "
1055+
1056+ # Collect PR comments, split by cutoff date
1057+ log_err " [start-review] Collecting PR comments..."
1058+ local comments
1059+ comments=$( get_pr_review_comments " $work_dir " " $pr_number " " $latest_commit_date " )
1060+ log_err " [start-review] PR comments collected."
1061+
10251062 log_err " [start-review] Invoking Claude to generate review prd.json..."
10261063
10271064 claude --dangerously-skip-permissions --print -p " $( read_prompt create-review-prd.md)
@@ -1035,9 +1072,16 @@ project: \"$issue_id: $issue_title (review feedback)\"
10351072- Title: $issue_title
10361073- URL: $issue_url
10371074
1038- ## PR #$pr_number Review Comments
1075+ ## PR #$pr_number — NEW Review Comments (after latest commit $latest_commit_date )
1076+ These are the comments that need to be addressed. Create user stories for these.
1077+
1078+ $( echo " $comments " | python3 -c " import json,sys; d=json.load(sys.stdin); print(json.dumps(d.get('new_comments', d), indent=2))" )
1079+
1080+ ## PR #$pr_number — Previous Comments (before latest commit, for context only)
1081+ These comments were posted before the latest commit. They may have already been addressed.
1082+ Do NOT create user stories for these — they are provided only as background context.
10391083
1040- $comments
1084+ $( echo " $ comments" | python3 -c " import json,sys; d=json.load(sys.stdin); print(json.dumps(d.get('previous_comments', {}), indent=2)) " )
10411085
10421086$RALPH_SKILL_GUIDELINES " 2>&1 | tee /dev/stderr || true
10431087
0 commit comments