agentsys 5.3.0 → 5.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.cursor/commands/audit-project-agents.md +454 -0
  4. package/.cursor/commands/audit-project-github.md +141 -0
  5. package/.cursor/commands/audit-project.md +330 -0
  6. package/.cursor/commands/consult.md +417 -0
  7. package/.cursor/commands/debate.md +381 -0
  8. package/.cursor/commands/delivery-approval.md +334 -0
  9. package/.cursor/commands/deslop.md +142 -0
  10. package/.cursor/commands/drift-detect.md +259 -0
  11. package/.cursor/commands/enhance.md +172 -0
  12. package/.cursor/commands/learn.md +165 -0
  13. package/.cursor/commands/next-task.md +519 -0
  14. package/.cursor/commands/perf.md +464 -0
  15. package/.cursor/commands/repo-map.md +124 -0
  16. package/.cursor/commands/ship-ci-review-loop.md +468 -0
  17. package/.cursor/commands/ship-deployment.md +348 -0
  18. package/.cursor/commands/ship-error-handling.md +265 -0
  19. package/.cursor/commands/ship.md +517 -0
  20. package/.cursor/commands/sync-docs.md +171 -0
  21. package/.cursor/commands/web-ctl.md +101 -0
  22. package/.cursor/skills/consult/SKILL.md +425 -0
  23. package/.cursor/skills/debate/SKILL.md +316 -0
  24. package/.cursor/skills/deslop/SKILL.md +204 -0
  25. package/.cursor/skills/discover-tasks/SKILL.md +297 -0
  26. package/.cursor/skills/drift-analysis/SKILL.md +324 -0
  27. package/.cursor/skills/enhance-agent-prompts/SKILL.md +277 -0
  28. package/.cursor/skills/enhance-claude-memory/SKILL.md +387 -0
  29. package/.cursor/skills/enhance-cross-file/SKILL.md +110 -0
  30. package/.cursor/skills/enhance-docs/SKILL.md +298 -0
  31. package/.cursor/skills/enhance-hooks/SKILL.md +554 -0
  32. package/.cursor/skills/enhance-orchestrator/SKILL.md +255 -0
  33. package/.cursor/skills/enhance-plugins/SKILL.md +319 -0
  34. package/.cursor/skills/enhance-prompts/SKILL.md +340 -0
  35. package/.cursor/skills/enhance-skills/SKILL.md +436 -0
  36. package/.cursor/skills/learn/SKILL.md +349 -0
  37. package/.cursor/skills/orchestrate-review/SKILL.md +260 -0
  38. package/.cursor/skills/perf-analyzer/SKILL.md +37 -0
  39. package/.cursor/skills/perf-baseline-manager/SKILL.md +30 -0
  40. package/.cursor/skills/perf-benchmarker/SKILL.md +52 -0
  41. package/.cursor/skills/perf-code-paths/SKILL.md +32 -0
  42. package/.cursor/skills/perf-investigation-logger/SKILL.md +41 -0
  43. package/.cursor/skills/perf-profiler/SKILL.md +42 -0
  44. package/.cursor/skills/perf-theory-gatherer/SKILL.md +35 -0
  45. package/.cursor/skills/perf-theory-tester/SKILL.md +36 -0
  46. package/.cursor/skills/repo-mapping/SKILL.md +83 -0
  47. package/.cursor/skills/sync-docs/SKILL.md +351 -0
  48. package/.cursor/skills/validate-delivery/SKILL.md +186 -0
  49. package/.cursor/skills/web-auth/SKILL.md +177 -0
  50. package/.cursor/skills/web-browse/SKILL.md +516 -0
  51. package/.kiro/agents/agent-enhancer.json +12 -0
  52. package/.kiro/agents/ci-fixer.json +13 -0
  53. package/.kiro/agents/ci-monitor.json +12 -0
  54. package/.kiro/agents/claudemd-enhancer.json +12 -0
  55. package/.kiro/agents/consult-agent.json +13 -0
  56. package/.kiro/agents/cross-file-enhancer.json +12 -0
  57. package/.kiro/agents/debate-orchestrator.json +13 -0
  58. package/.kiro/agents/delivery-validator.json +12 -0
  59. package/.kiro/agents/deslop-agent.json +12 -0
  60. package/.kiro/agents/docs-enhancer.json +12 -0
  61. package/.kiro/agents/exploration-agent.json +12 -0
  62. package/.kiro/agents/hooks-enhancer.json +11 -0
  63. package/.kiro/agents/implementation-agent.json +13 -0
  64. package/.kiro/agents/learn-agent.json +12 -0
  65. package/.kiro/agents/map-validator.json +11 -0
  66. package/.kiro/agents/perf-analyzer.json +12 -0
  67. package/.kiro/agents/perf-code-paths.json +11 -0
  68. package/.kiro/agents/perf-investigation-logger.json +12 -0
  69. package/.kiro/agents/perf-orchestrator.json +13 -0
  70. package/.kiro/agents/perf-theory-gatherer.json +12 -0
  71. package/.kiro/agents/perf-theory-tester.json +13 -0
  72. package/.kiro/agents/plan-synthesizer.json +12 -0
  73. package/.kiro/agents/planning-agent.json +12 -0
  74. package/.kiro/agents/plugin-enhancer.json +12 -0
  75. package/.kiro/agents/prompt-enhancer.json +12 -0
  76. package/.kiro/agents/reviewer-perf-test.json +11 -0
  77. package/.kiro/agents/reviewer-quality-security.json +11 -0
  78. package/.kiro/agents/simple-fixer.json +13 -0
  79. package/.kiro/agents/skills-enhancer.json +11 -0
  80. package/.kiro/agents/sync-docs-agent.json +13 -0
  81. package/.kiro/agents/task-discoverer.json +12 -0
  82. package/.kiro/agents/test-coverage-checker.json +12 -0
  83. package/.kiro/agents/web-session.json +12 -0
  84. package/.kiro/agents/worktree-manager.json +13 -0
  85. package/.kiro/skills/consult/SKILL.md +425 -0
  86. package/.kiro/skills/debate/SKILL.md +316 -0
  87. package/.kiro/skills/deslop/SKILL.md +204 -0
  88. package/.kiro/skills/discover-tasks/SKILL.md +297 -0
  89. package/.kiro/skills/drift-analysis/SKILL.md +324 -0
  90. package/.kiro/skills/enhance-agent-prompts/SKILL.md +277 -0
  91. package/.kiro/skills/enhance-claude-memory/SKILL.md +387 -0
  92. package/.kiro/skills/enhance-cross-file/SKILL.md +110 -0
  93. package/.kiro/skills/enhance-docs/SKILL.md +298 -0
  94. package/.kiro/skills/enhance-hooks/SKILL.md +554 -0
  95. package/.kiro/skills/enhance-orchestrator/SKILL.md +255 -0
  96. package/.kiro/skills/enhance-plugins/SKILL.md +319 -0
  97. package/.kiro/skills/enhance-prompts/SKILL.md +340 -0
  98. package/.kiro/skills/enhance-skills/SKILL.md +436 -0
  99. package/.kiro/skills/learn/SKILL.md +349 -0
  100. package/.kiro/skills/orchestrate-review/SKILL.md +260 -0
  101. package/.kiro/skills/perf-analyzer/SKILL.md +37 -0
  102. package/.kiro/skills/perf-baseline-manager/SKILL.md +30 -0
  103. package/.kiro/skills/perf-benchmarker/SKILL.md +52 -0
  104. package/.kiro/skills/perf-code-paths/SKILL.md +32 -0
  105. package/.kiro/skills/perf-investigation-logger/SKILL.md +41 -0
  106. package/.kiro/skills/perf-profiler/SKILL.md +42 -0
  107. package/.kiro/skills/perf-theory-gatherer/SKILL.md +35 -0
  108. package/.kiro/skills/perf-theory-tester/SKILL.md +36 -0
  109. package/.kiro/skills/repo-mapping/SKILL.md +83 -0
  110. package/.kiro/skills/sync-docs/SKILL.md +351 -0
  111. package/.kiro/skills/validate-delivery/SKILL.md +186 -0
  112. package/.kiro/skills/web-auth/SKILL.md +177 -0
  113. package/.kiro/skills/web-browse/SKILL.md +516 -0
  114. package/.kiro/steering/audit-project-agents.md +459 -0
  115. package/.kiro/steering/audit-project-github.md +146 -0
  116. package/.kiro/steering/audit-project.md +330 -0
  117. package/.kiro/steering/consult.md +422 -0
  118. package/.kiro/steering/debate.md +386 -0
  119. package/.kiro/steering/delivery-approval.md +339 -0
  120. package/.kiro/steering/deslop.md +149 -0
  121. package/.kiro/steering/drift-detect.md +264 -0
  122. package/.kiro/steering/enhance.md +177 -0
  123. package/.kiro/steering/learn.md +166 -0
  124. package/.kiro/steering/next-task.md +481 -0
  125. package/.kiro/steering/perf.md +469 -0
  126. package/.kiro/steering/repo-map.md +126 -0
  127. package/.kiro/steering/ship-ci-review-loop.md +473 -0
  128. package/.kiro/steering/ship-deployment.md +353 -0
  129. package/.kiro/steering/ship-error-handling.md +270 -0
  130. package/.kiro/steering/ship.md +522 -0
  131. package/.kiro/steering/sync-docs.md +178 -0
  132. package/.kiro/steering/web-ctl.md +106 -0
  133. package/CHANGELOG.md +15 -0
  134. package/bin/cli.js +2 -2
  135. package/lib/adapter-transforms.js +34 -2
  136. package/package.json +1 -1
  137. package/site/content.json +1 -1
@@ -0,0 +1,468 @@
1
+
2
+ <ci-review-loop>
3
+ # Phase 4: CI & Review Monitor Loop - Reference
4
+
5
+ This file contains detailed implementation for the CI & Review Monitor Loop phase of `/ship`.
6
+
7
+ **Parent document**: `ship.md`
8
+
9
+ ---
10
+
11
+ <mandatory-requirements>
12
+ ## This Phase Is Mandatory
13
+
14
+ This is not optional. You must:
15
+ 1. Wait the full 3 minutes for auto-reviewers
16
+ 2. Run the monitor loop (not just check once)
17
+ 3. Address all comments before merge
18
+ </mandatory-requirements>
19
+
20
+ ---
21
+
22
+ <pr-auto-review>
23
+ ## PR Auto-Review Process
24
+
25
+ PRs receive automatic reviews from configured auto-reviewers (Copilot, Gemini, CodeRabbit, etc.).
26
+
27
+ **Mandatory workflow:**
28
+ 1. After PR creation, wait **at least 3 minutes** for first review round
29
+ 2. Read **all comments** from all reviewers
30
+ 3. Address **every comment** - no exceptions
31
+ 4. Iterate until **zero unresolved threads** (typically 2-4 rounds)
32
+
33
+ **Rules:**
34
+ - Always address all comments, including "minor" or "nit" suggestions
35
+ - Do not skip a comment unless factually wrong or user-approved
36
+ - Treat all feedback as **required changes**, not suggestions
37
+ </pr-auto-review>
38
+
39
+ ---
40
+
41
+ <overview>
42
+ ## Overview
43
+
44
+ The monitor loop must wait for:
45
+ 1. CI to pass
46
+ 2. All comments resolved (addressed or replied to)
47
+ 3. No "changes requested" reviews remain
48
+
49
+ ## Why All Comments Matter
50
+
51
+ **Every comment must be addressed:**
52
+ - Critical/High issues: Fix immediately
53
+ - Medium issues: Fix (don't defer)
54
+ - Minor/Nit issues: Fix (shows attention to quality)
55
+ - Style suggestions: Fix (maintains codebase consistency)
56
+ - Questions: Answer with explanation
57
+ - False positives: Reply explaining why, then resolve
58
+ - Not relevant: Reply explaining why, then resolve
59
+
60
+ Do not ignore comments. Do not leave comments unresolved. A clean PR has zero unresolved conversations.
61
+ </overview>
62
+
63
+ ## The Monitor Loop Algorithm
64
+
65
+ > **Note:** The JavaScript below is **conceptual pseudocode** showing the algorithm flow.
66
+ > Implement using bash functions defined in this file.
67
+
68
+ ```javascript
69
+ const MAX_ITERATIONS = 10; // Safety limit
70
+ const INITIAL_WAIT_MS = 180000; // 3 minutes - wait for auto-reviews
71
+ const ITERATION_WAIT_MS = 30000; // 30 seconds between iterations
72
+ let iteration = 0;
73
+
74
+ while (iteration < MAX_ITERATIONS) {
75
+ iteration++;
76
+ console.log(`\n## CI & Review Monitor - Iteration ${iteration}`);
77
+
78
+ // Step 1: Wait for CI to complete
79
+ const ciStatus = await waitForCI();
80
+ if (ciStatus === 'failed') {
81
+ await fixCIFailures();
82
+ continue; // Push fix, re-run CI
83
+ }
84
+
85
+ // Step 1.5: First iteration only - wait for auto-reviews
86
+ if (iteration === 1) {
87
+ console.log("Waiting 3 minutes for auto-reviews...");
88
+ await sleep(INITIAL_WAIT_MS);
89
+ }
90
+
91
+ // Step 2: Check for PR comments and reviews
92
+ const feedback = await checkPRFeedback();
93
+
94
+ if (feedback.unresolvedCount === 0 && !feedback.changesRequested) {
95
+ console.log("[OK] CI passed, all comments resolved");
96
+ break; // Ready to merge!
97
+ }
98
+
99
+ // Step 3: Address ALL feedback
100
+ await addressAllFeedback(PR_NUMBER);
101
+
102
+ // Step 4: Push fixes
103
+ if (feedback.hasCodeChanges) {
104
+ await commitAndPush(`fix: address review feedback (iteration ${iteration})`);
105
+ }
106
+
107
+ // Step 5: Sleep before next check
108
+ await sleep(ITERATION_WAIT_MS);
109
+ }
110
+ ```
111
+
112
+ ## Step 1: Wait for CI
113
+
114
+ ```bash
115
+ wait_for_ci() {
116
+ echo "Waiting for CI checks..."
117
+
118
+ while true; do
119
+ CHECKS=$(gh pr checks $PR_NUMBER --json name,state 2>/dev/null || echo "[]")
120
+
121
+ PENDING=$(echo "$CHECKS" | jq '[.[] | select(.state | IN("PENDING", "QUEUED", "IN_PROGRESS"))] | length')
122
+ FAILED=$(echo "$CHECKS" | jq '[.[] | select(.state | IN("FAILURE", "CANCELLED"))] | length')
123
+ PASSED=$(echo "$CHECKS" | jq '[.[] | select(.state=="SUCCESS")] | length')
124
+
125
+ if [ "$FAILED" -gt 0 ]; then
126
+ echo "[ERROR] CI failed ($FAILED checks)"
127
+ gh pr checks $PR_NUMBER
128
+ return 1
129
+ elif [ "$PENDING" -eq 0 ] && [ "$PASSED" -gt 0 ]; then
130
+ echo "[OK] CI passed ($PASSED checks)"
131
+ return 0
132
+ elif [ "$PENDING" -eq 0 ] && [ "$PASSED" -eq 0 ]; then
133
+ echo "[WARN] No CI checks found, proceeding..."
134
+ return 0
135
+ fi
136
+
137
+ echo " Waiting... ($PENDING pending, $PASSED passed)"
138
+ sleep 15
139
+ done
140
+ }
141
+ ```
142
+
143
+ ## Step 2: Check PR Feedback
144
+
145
+ ```bash
146
+ check_pr_feedback() {
147
+ local pr_number=$1
148
+
149
+ echo "Checking PR feedback..."
150
+
151
+ # Extract owner and repo from git remote
152
+ REPO_INFO=$(gh repo view --json owner,name --jq '"\(.owner.login)/\(.name)"')
153
+ OWNER=$(echo "$REPO_INFO" | cut -d'/' -f1)
154
+ REPO=$(echo "$REPO_INFO" | cut -d'/' -f2)
155
+
156
+ # Get review state
157
+ REVIEWS=$(gh pr view $pr_number --json reviews --jq '.reviews')
158
+ CHANGES_REQUESTED=$(echo "$REVIEWS" | jq '[.[] | select(.state=="CHANGES_REQUESTED")] | length')
159
+
160
+ # Get unresolved review threads
161
+ # NOTE: Fetches first 100 threads. For PRs with >100 threads, implement pagination.
162
+ UNRESOLVED_THREADS=$(gh api graphql -f query='
163
+ query($owner: String!, $repo: String!, $pr: Int!) {
164
+ repository(owner: $owner, name: $repo) {
165
+ pullRequest(number: $pr) {
166
+ reviewThreads(first: 100) {
167
+ nodes {
168
+ isResolved
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }
174
+ ' -f owner="$OWNER" -f repo="$REPO" -F pr=$pr_number \
175
+ --jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length')
176
+
177
+ echo " Unresolved threads: $UNRESOLVED_THREADS"
178
+ echo " Changes requested: $CHANGES_REQUESTED"
179
+
180
+ echo "{\"unresolvedThreads\": $UNRESOLVED_THREADS, \"changesRequested\": $CHANGES_REQUESTED}"
181
+ }
182
+ ```
183
+
184
+ ### Get Full Thread Details
185
+
186
+ ```bash
187
+ get_unresolved_threads() {
188
+ local pr_number=$1
189
+
190
+ REPO_INFO=$(gh repo view --json owner,name --jq '"\(.owner.login)/\(.name)"')
191
+ OWNER=$(echo "$REPO_INFO" | cut -d'/' -f1)
192
+ REPO=$(echo "$REPO_INFO" | cut -d'/' -f2)
193
+
194
+ # NOTE: Fetches first 100 threads. For PRs with >100, implement pagination.
195
+ gh api graphql -f query='
196
+ query($owner: String!, $repo: String!, $pr: Int!) {
197
+ repository(owner: $owner, name: $repo) {
198
+ pullRequest(number: $pr) {
199
+ reviewThreads(first: 100) {
200
+ nodes {
201
+ id
202
+ isResolved
203
+ path
204
+ line
205
+ diffHunk
206
+ comments(first: 1) {
207
+ nodes {
208
+ id
209
+ body
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ }
216
+ }
217
+ ' -f owner="$OWNER" -f repo="$REPO" -F pr=$pr_number \
218
+ --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)'
219
+ }
220
+ ```
221
+
222
+ ## Step 3: Address ALL Feedback
223
+
224
+ > **Note:** This is **conceptual pseudocode** showing the algorithm flow.
225
+ > Implement using: gh api, Read, Edit, Task (ci-fixer), etc.
226
+
227
+ ```javascript
228
+ async function addressAllFeedback(prNumber) {
229
+ const threads = await getUnresolvedThreads(prNumber);
230
+
231
+ console.log(`\nAddressing ${threads.length} unresolved threads...`);
232
+
233
+ for (const thread of threads) {
234
+ console.log(`\n--- Thread: ${thread.path}:${thread.line} ---`);
235
+ const analysis = analyzeComment(thread);
236
+
237
+ switch (analysis.type) {
238
+ case 'code_fix_required':
239
+ console.log(`Action: Fixing code issue`);
240
+ await implementFix(thread); // Use Task(ci-fixer) or Edit tool
241
+ break;
242
+
243
+ case 'style_suggestion':
244
+ console.log(`Action: Applying style fix`);
245
+ await implementFix(thread);
246
+ break;
247
+
248
+ case 'question':
249
+ console.log(`Action: Answering question`);
250
+ await replyToComment(prNumber, thread.commentId, generateAnswer(thread));
251
+ await resolveThread(thread.id);
252
+ break;
253
+
254
+ case 'false_positive':
255
+ console.log(`Action: Explaining false positive`);
256
+ await replyToComment(prNumber, thread.commentId,
257
+ `This is a false positive because: ${analysis.reason}\n\n` +
258
+ `Resolving. Please reopen if you disagree.`
259
+ );
260
+ await resolveThread(thread.id);
261
+ break;
262
+
263
+ case 'not_relevant':
264
+ console.log(`Action: Explaining out of scope`);
265
+ await replyToComment(prNumber, thread.commentId,
266
+ `Outside scope of this PR: ${analysis.reason}\n\n` +
267
+ `Resolving. Please reopen if needed.`
268
+ );
269
+ await resolveThread(thread.id);
270
+ break;
271
+
272
+ case 'already_addressed':
273
+ console.log(`Action: Confirming addressed`);
274
+ await replyToComment(prNumber, thread.commentId,
275
+ `Addressed in commit ${gitRevParseHead}.`
276
+ );
277
+ await resolveThread(thread.id);
278
+ break;
279
+ }
280
+ }
281
+
282
+ // Request re-review from those who requested changes
283
+ const changesRequestedReviews = await getChangesRequestedReviews(prNumber);
284
+ for (const review of changesRequestedReviews) {
285
+ await requestReReview(prNumber, review.author);
286
+ }
287
+ }
288
+ ```
289
+
290
+ ## Comment Analysis Heuristics
291
+
292
+ > **Note:** Classification heuristics for comment handling.
293
+
294
+ ```javascript
295
+ function analyzeComment(thread) {
296
+ const body = thread.body.toLowerCase();
297
+
298
+ // Question patterns
299
+ if (body.includes('?') || body.startsWith('why') || body.startsWith('how') ||
300
+ body.startsWith('what') || body.startsWith('could you explain')) {
301
+ return { type: 'question', reason: 'Comment is a question' };
302
+ }
303
+
304
+ // Style/nit patterns
305
+ if (body.includes('nit:') || body.includes('nitpick') || body.includes('minor:') ||
306
+ body.includes('style:') || body.includes('consider') || body.includes('optional')) {
307
+ return { type: 'style_suggestion', reason: 'Style or minor suggestion' };
308
+ }
309
+
310
+ // Out of scope patterns
311
+ if (!thread.diffHunk || commentRefersToUnchangedCode(thread)) {
312
+ return { type: 'not_relevant', reason: 'Comment refers to unchanged code' };
313
+ }
314
+
315
+ // Default: treat as code fix required
316
+ return { type: 'code_fix_required', reason: 'Valid code feedback' };
317
+ }
318
+ ```
319
+
320
+ ## Implementing Fixes
321
+
322
+ Use the ci-fixer agent for code changes:
323
+
324
+ ```javascript
325
+ Task({
326
+ subagent_type: "ci-fixer",
327
+ prompt: `Fix the following review comment:
328
+
329
+ **File**: ${thread.path}
330
+ **Line**: ${thread.line}
331
+ **Comment**: ${thread.body}
332
+ **Code Context**:
333
+ \`\`\`
334
+ ${thread.diffHunk}
335
+ \`\`\`
336
+
337
+ Requirements:
338
+ 1. Make the minimal change to address the feedback
339
+ 2. Do NOT over-engineer or add unrelated changes
340
+ 3. Ensure tests still pass after the fix`
341
+ });
342
+ ```
343
+
344
+ ## Resolving Threads
345
+
346
+ ```bash
347
+ resolve_thread() {
348
+ local thread_id=$1
349
+
350
+ gh api graphql -f query='
351
+ mutation($threadId: ID!) {
352
+ resolveReviewThread(input: {threadId: $threadId}) {
353
+ thread {
354
+ isResolved
355
+ }
356
+ }
357
+ }
358
+ ' -f threadId="$thread_id"
359
+ }
360
+
361
+ reply_to_comment() {
362
+ local pr_number=$1
363
+ local comment_id=$2
364
+ local body=$3
365
+
366
+ REPO_INFO=$(gh repo view --json owner,name --jq '"\(.owner.login)/\(.name)"')
367
+ OWNER=$(echo "$REPO_INFO" | cut -d'/' -f1)
368
+ REPO=$(echo "$REPO_INFO" | cut -d'/' -f2)
369
+
370
+ gh api -X POST "repos/$OWNER/$REPO/pulls/$pr_number/comments" \
371
+ -f body="$body" \
372
+ -F in_reply_to="$comment_id"
373
+ }
374
+ ```
375
+
376
+ ## Step 4: Commit and Push
377
+
378
+ ```bash
379
+ commit_and_push_fixes() {
380
+ local message=$1
381
+ local branch=${2:-$(git branch --show-current)}
382
+
383
+ if [ -n "$(git status --porcelain)" ]; then
384
+ git add -A
385
+ git commit -m "$message"
386
+ git push origin "$branch"
387
+ echo "[OK] Pushed fixes"
388
+ return 0
389
+ else
390
+ echo "No code changes to commit (only comment replies)"
391
+ return 1
392
+ fi
393
+ }
394
+ ```
395
+
396
+ ## Complete Loop Script
397
+
398
+ ```bash
399
+ #!/bin/bash
400
+ # Phase 4: CI & Review Monitor Loop
401
+
402
+ MAX_ITERATIONS=10
403
+ INITIAL_WAIT=${SHIP_INITIAL_WAIT:-180} # Configurable via env var
404
+ ITERATION_WAIT=30
405
+ iteration=0
406
+
407
+ while [ $iteration -lt $MAX_ITERATIONS ]; do
408
+ iteration=$((iteration + 1))
409
+ echo "[CI Monitor] Iteration $iteration"
410
+
411
+ # Step 1: Wait for CI
412
+ if ! wait_for_ci; then
413
+ echo "CI failed - launching ci-fixer agent..."
414
+ continue
415
+ fi
416
+
417
+ # Step 1.5: First iteration - wait for auto-reviews
418
+ if [ $iteration -eq 1 ] && [ "$INITIAL_WAIT" -gt 0 ]; then
419
+ echo "First iteration - waiting ${INITIAL_WAIT}s for auto-reviews..."
420
+ sleep $INITIAL_WAIT
421
+ fi
422
+
423
+ # Step 2: Check feedback
424
+ FEEDBACK=$(check_pr_feedback $PR_NUMBER)
425
+ UNRESOLVED=$(echo "$FEEDBACK" | jq -r '.unresolvedThreads')
426
+ CHANGES_REQ=$(echo "$FEEDBACK" | jq -r '.changesRequested')
427
+
428
+ if [ "$UNRESOLVED" -eq 0 ] && [ "$CHANGES_REQ" -eq 0 ]; then
429
+ echo "[OK] ALL CHECKS PASSED"
430
+ echo "[OK] ALL COMMENTS RESOLVED"
431
+ echo "Ready to merge!"
432
+ break
433
+ fi
434
+
435
+ # Step 3: Address all feedback
436
+ echo "Addressing $UNRESOLVED unresolved threads..."
437
+
438
+ # Step 4: Commit and push
439
+ commit_and_push_fixes "fix: address review feedback (iteration $iteration)"
440
+
441
+ # Step 5: Wait before next iteration
442
+ echo "Waiting ${ITERATION_WAIT}s..."
443
+ sleep $ITERATION_WAIT
444
+ done
445
+
446
+ if [ $iteration -ge $MAX_ITERATIONS ]; then
447
+ echo "[ERROR] Max iterations reached - manual intervention required"
448
+ exit 1
449
+ fi
450
+ ```
451
+
452
+ <iteration-summary>
453
+ ## Iteration Summary Output
454
+
455
+ ```markdown
456
+ ## Iteration ${iteration} Summary
457
+
458
+ **CI Status**: [OK] Passed
459
+ **Comments Addressed**: ${addressedCount}
460
+ - Code fixes: ${codeFixCount}
461
+ - Answered questions: ${questionCount}
462
+ - Resolved as not applicable: ${notApplicableCount}
463
+ **Remaining Unresolved**: ${remainingCount}
464
+
465
+ ${remainingCount > 0 ? 'Continuing...' : 'Ready to merge!'}
466
+ ```
467
+ </iteration-summary>
468
+ </ci-review-loop>