@shepai/cli 1.144.0 → 1.145.0

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 (146) hide show
  1. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts +6 -3
  2. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts.map +1 -1
  3. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.js +104 -66
  4. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.d.ts +12 -0
  5. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.d.ts.map +1 -1
  6. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.js +33 -0
  7. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts +10 -0
  8. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
  9. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +63 -0
  10. package/dist/tsconfig.build.tsbuildinfo +1 -1
  11. package/package.json +1 -1
  12. package/web/.next/BUILD_ID +1 -1
  13. package/web/.next/build-manifest.json +2 -2
  14. package/web/.next/fallback-build-manifest.json +2 -2
  15. package/web/.next/prerender-manifest.json +3 -3
  16. package/web/.next/required-server-files.js +2 -2
  17. package/web/.next/required-server-files.json +2 -2
  18. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +28 -28
  19. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  20. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  21. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +28 -28
  22. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  23. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  24. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  25. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  26. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  27. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +36 -36
  28. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  29. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  30. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  31. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  32. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  33. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +28 -28
  34. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  35. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  36. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  37. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  38. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  39. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +36 -36
  40. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  41. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  42. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +26 -26
  43. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  44. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  45. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  46. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  47. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  48. package/web/.next/server/app/_global-error.html +2 -2
  49. package/web/.next/server/app/_global-error.rsc +1 -1
  50. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  51. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  52. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  53. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  54. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  55. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
  56. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  58. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  59. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
  61. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
  63. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
  65. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  67. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  68. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  69. package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js +2 -2
  70. package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js +1 -1
  71. package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js.map +1 -1
  72. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  73. package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js +1 -1
  74. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
  75. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
  76. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
  77. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
  78. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js.map +1 -1
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js +1 -1
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js.map +1 -1
  84. package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js +1 -1
  85. package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js.map +1 -1
  86. package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js +1 -1
  87. package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js.map +1 -1
  88. package/web/.next/server/chunks/ssr/_0c5f56e3._.js +2 -2
  89. package/web/.next/server/chunks/ssr/_0c5f56e3._.js.map +1 -1
  90. package/web/.next/server/chunks/ssr/_1b719e7f._.js +1 -1
  91. package/web/.next/server/chunks/ssr/_1b719e7f._.js.map +1 -1
  92. package/web/.next/server/chunks/ssr/{_c64f06d5._.js → _1fa6f5f0._.js} +2 -2
  93. package/web/.next/server/chunks/ssr/{_c64f06d5._.js.map → _1fa6f5f0._.js.map} +1 -1
  94. package/web/.next/server/chunks/ssr/{_c67ad133._.js → _2a415784._.js} +2 -2
  95. package/web/.next/server/chunks/ssr/{_c67ad133._.js.map → _2a415784._.js.map} +1 -1
  96. package/web/.next/server/chunks/ssr/_37e8548b._.js +1 -1
  97. package/web/.next/server/chunks/ssr/_37e8548b._.js.map +1 -1
  98. package/web/.next/server/chunks/ssr/_55d763e2._.js +1 -1
  99. package/web/.next/server/chunks/ssr/_55d763e2._.js.map +1 -1
  100. package/web/.next/server/chunks/ssr/_6256a985._.js +1 -1
  101. package/web/.next/server/chunks/ssr/_6256a985._.js.map +1 -1
  102. package/web/.next/server/chunks/ssr/_64bdfc6f._.js +2 -2
  103. package/web/.next/server/chunks/ssr/_64bdfc6f._.js.map +1 -1
  104. package/web/.next/server/chunks/ssr/_7dca1882._.js +1 -1
  105. package/web/.next/server/chunks/ssr/_7dca1882._.js.map +1 -1
  106. package/web/.next/server/chunks/ssr/_a9f57758._.js +1 -1
  107. package/web/.next/server/chunks/ssr/_a9f57758._.js.map +1 -1
  108. package/web/.next/server/chunks/ssr/_b71645b4._.js +1 -1
  109. package/web/.next/server/chunks/ssr/_b71645b4._.js.map +1 -1
  110. package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
  111. package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
  112. package/web/.next/server/chunks/ssr/_f39a1adb._.js +1 -1
  113. package/web/.next/server/chunks/ssr/_f39a1adb._.js.map +1 -1
  114. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  115. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  116. package/web/.next/server/chunks/ssr/src_presentation_web_721fb773._.js +3 -0
  117. package/web/.next/server/chunks/ssr/{src_presentation_web_dd85ad88._.js.map → src_presentation_web_721fb773._.js.map} +1 -1
  118. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
  119. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
  120. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
  121. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
  122. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  123. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  124. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  125. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  126. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  127. package/web/.next/server/pages/500.html +2 -2
  128. package/web/.next/server/server-reference-manifest.js +1 -1
  129. package/web/.next/server/server-reference-manifest.json +44 -44
  130. package/web/.next/static/chunks/{1867fdb7f2c6035f.js → 149c88eadafaf835.js} +1 -1
  131. package/web/.next/static/chunks/{de0704c3e73118cf.js → 18c49ba954b15750.js} +1 -1
  132. package/web/.next/static/chunks/{683ec435a34ca112.js → 266fe61224d14058.js} +1 -1
  133. package/web/.next/static/chunks/{21502baa33ad728a.js → 37b065777853153c.js} +2 -2
  134. package/web/.next/static/chunks/{8cc1aea0d82835be.js → 41667f7f505952e6.js} +1 -1
  135. package/web/.next/static/chunks/{53478ed65db63030.js → 7559d0ac9e155de8.js} +2 -2
  136. package/web/.next/static/chunks/{0bce83a11c7a9383.js → a6f8230f1756f318.js} +1 -1
  137. package/web/.next/static/chunks/{904cdf4c47654f32.js → c0fd9ae3d7b3ebe3.js} +1 -1
  138. package/web/.next/static/chunks/d1c52a649f1c7704.js +1 -0
  139. package/web/.next/static/chunks/{ecfbc35ad11c83bb.js → e2e3d8a7d339c110.js} +1 -1
  140. package/web/.next/static/chunks/{60c6c3c30fba3b7c.js → ed43f5ec24322234.js} +1 -1
  141. package/web/.next/static/chunks/{88300dbc7c91abb2.js → f2a6406394a41d3c.js} +1 -1
  142. package/web/.next/server/chunks/ssr/src_presentation_web_dd85ad88._.js +0 -3
  143. package/web/.next/static/chunks/9e3e916a22d1121f.js +0 -1
  144. /package/web/.next/static/{rsS9eOHzCHbGCCwBS1fRh → CrBDjRQwzIQuEXTobFPfK}/_buildManifest.js +0 -0
  145. /package/web/.next/static/{rsS9eOHzCHbGCCwBS1fRh → CrBDjRQwzIQuEXTobFPfK}/_clientMiddlewareManifest.json +0 -0
  146. /package/web/.next/static/{rsS9eOHzCHbGCCwBS1fRh → CrBDjRQwzIQuEXTobFPfK}/_ssgManifest.js +0 -0
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * CI Watch/Fix Loop
3
3
  *
4
- * After a push, watches CI status and attempts automatic fixes when CI fails.
4
+ * After a push, watches CI status using an agent-based approach and attempts
5
+ * automatic fixes when CI fails. The agent follows CI/CD best practices:
6
+ * checks ALL runs, waits for ALL to complete, and reports accurate status.
7
+ *
5
8
  * Respects configurable max attempts, timeout, and log size from settings.
6
9
  */
7
10
  import type { IAgentExecutor } from '../../../../../../application/ports/output/agents/agent-executor.interface.js';
@@ -34,8 +37,8 @@ export interface CiWatchFixResult {
34
37
  ciFixStatus: CiFixStatusValue;
35
38
  }
36
39
  /**
37
- * Run the CI watch/fix loop. Watches for the initial CI result, then
38
- * iteratively attempts fixes up to the configured maximum.
40
+ * Run the CI watch/fix loop. Watches for the initial CI result using an
41
+ * agent-based approach, then iteratively attempts fixes up to the configured maximum.
39
42
  *
40
43
  * Throws on timeout or exhausted attempts (after updating feature state).
41
44
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ci-watch-fix-loop.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAClH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAC;AAKrG,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+DAA+D,CAAC;AAK3G,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,EAAE,aAAa,CAAC;IAC5B,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,qBAAqB,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAEpG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAqL3B"}
1
+ {"version":3,"file":"ci-watch-fix-loop.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAClH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAC;AACrG,OAAO,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+DAA+D,CAAC;AAO3G,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,EAAE,aAAa,CAAC;IAC5B,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,qBAAqB,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAEpG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAyED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,gBAAgB,CAAC,CA4K3B"}
@@ -1,18 +1,70 @@
1
1
  /**
2
2
  * CI Watch/Fix Loop
3
3
  *
4
- * After a push, watches CI status and attempts automatic fixes when CI fails.
4
+ * After a push, watches CI status using an agent-based approach and attempts
5
+ * automatic fixes when CI fails. The agent follows CI/CD best practices:
6
+ * checks ALL runs, waits for ALL to complete, and reports accurate status.
7
+ *
5
8
  * Respects configurable max attempts, timeout, and log size from settings.
6
9
  */
7
- import { GitPrError, GitPrErrorCode, } from '../../../../../../application/ports/output/services/git-pr-service.interface.js';
8
10
  import { CiStatus } from '../../../../../../domain/generated/output.js';
9
11
  import { retryExecute } from '../node-helpers.js';
10
- import { buildCiWatchFixPrompt } from '../prompts/merge-prompts.js';
12
+ import { buildCiWatchFixPrompt, buildCiWatchPrompt } from '../prompts/merge-prompts.js';
13
+ import { parseCiWatchResult } from './merge-output-parser.js';
11
14
  import { extractRunId, handleCiTerminalFailure, buildCiExhaustedError } from './ci-helpers.js';
12
15
  import { getSettings } from '../../../../../services/settings.service.js';
16
+ import { recordPhaseStart, recordPhaseEnd } from '../../phase-timing-context.js';
13
17
  /**
14
- * Run the CI watch/fix loop. Watches for the initial CI result, then
15
- * iteratively attempts fixes up to the configured maximum.
18
+ * Watch CI using an agent call. The agent checks ALL runs for the branch,
19
+ * waits for ALL to complete, and reports structured CI_STATUS.
20
+ *
21
+ * Records a phase timing entry for the activity timeline.
22
+ *
23
+ * @returns Parsed CI status result with usage metrics
24
+ */
25
+ async function watchCiViaAgent(executor, branch, options, timeoutMs, log) {
26
+ const watchOptions = { ...options, timeout: timeoutMs };
27
+ const watchPrompt = buildCiWatchPrompt(branch);
28
+ const watchStart = Date.now();
29
+ const timingId = await recordPhaseStart('merge:ci-watch', {
30
+ agentType: executor.agentType,
31
+ prompt: watchPrompt,
32
+ });
33
+ try {
34
+ const result = await retryExecute(executor, watchPrompt, watchOptions, {
35
+ maxAttempts: 1,
36
+ logger: log,
37
+ });
38
+ const elapsed = Date.now() - watchStart;
39
+ await recordPhaseEnd(timingId, elapsed, {
40
+ inputTokens: result.usage?.inputTokens,
41
+ outputTokens: result.usage?.outputTokens,
42
+ costUsd: result.usage?.costUsd,
43
+ numTurns: result.usage?.numTurns,
44
+ durationApiMs: result.usage?.durationApiMs,
45
+ exitCode: 'success',
46
+ });
47
+ const parsed = parseCiWatchResult(result.result);
48
+ return { ...parsed, usage: result.usage };
49
+ }
50
+ catch (err) {
51
+ const elapsed = Date.now() - watchStart;
52
+ const errMsg = err instanceof Error ? err.message : String(err);
53
+ await recordPhaseEnd(timingId, elapsed, {
54
+ exitCode: 'error',
55
+ errorMessage: errMsg.slice(0, 500),
56
+ });
57
+ // Check if this is a timeout
58
+ if (errMsg.includes('timed out') || errMsg.includes('timeout')) {
59
+ return { status: 'failure', summary: 'CI watch timed out', timedOut: true };
60
+ }
61
+ // For other errors, treat as indeterminate (failure)
62
+ return { status: 'failure', summary: `CI watch agent error: ${errMsg.slice(0, 200)}` };
63
+ }
64
+ }
65
+ /**
66
+ * Run the CI watch/fix loop. Watches for the initial CI result using an
67
+ * agent-based approach, then iteratively attempts fixes up to the configured maximum.
16
68
  *
17
69
  * Throws on timeout or exhausted attempts (after updating feature state).
18
70
  */
@@ -23,12 +75,11 @@ export async function runCiWatchFixLoop(deps, params) {
23
75
  const maxAttempts = settings.workflow?.ciMaxFixAttempts ?? 3;
24
76
  const timeoutMs = settings.workflow?.ciWatchTimeoutMs ?? 600_000;
25
77
  const logMaxChars = settings.workflow?.ciLogMaxChars ?? 50_000;
26
- const pollInterval = settings.workflow?.ciWatchPollIntervalSeconds ?? 30;
27
78
  let ciFixAttempts = params.existingAttempts;
28
79
  const ciFixHistory = [];
29
80
  let ciFixStatus;
30
81
  log.info(`Starting CI watch (maxAttempts=${maxAttempts}, timeout=${timeoutMs}ms)`);
31
- // Check if any CI run exists for this branch
82
+ // Check if any CI run exists for this branch (lightweight check before spawning agent)
32
83
  let initialCiStatus;
33
84
  try {
34
85
  initialCiStatus = await gitPrService.getCiStatus(cwd, branch);
@@ -65,30 +116,22 @@ export async function runCiWatchFixLoop(deps, params) {
65
116
  return { ciStatus: CiStatus.Success, ciFixAttempts, ciFixHistory, ciFixStatus: 'idle' };
66
117
  }
67
118
  let runUrl = initialCiStatus.runUrl;
68
- // Initial CI watch
69
- let watchResult;
70
- try {
71
- watchResult = await gitPrService.watchCi(cwd, branch, timeoutMs, pollInterval);
72
- }
73
- catch (err) {
74
- if (err instanceof GitPrError && err.code === GitPrErrorCode.CI_TIMEOUT) {
75
- log.info('Initial CI watch timed out');
76
- ciFixHistory.push({
77
- attempt: ciFixAttempts + 1,
78
- startedAt: new Date().toISOString(),
79
- failureSummary: 'CI watch timed out',
80
- outcome: 'timeout',
81
- });
82
- await handleCiTerminalFailure(feature, prUrl, prNumber, deps.featureRepository, messages);
83
- throw buildCiExhaustedError(ciFixAttempts + 1, ciFixHistory, 'timeout');
84
- }
85
- throw err;
86
- }
87
- // Use the run URL from watchCi — it reflects the actual run watched,
88
- // which may differ from the initial getCiStatus() result when multiple
89
- // workflow runs exist for the same branch.
119
+ // Initial CI watch via agent
120
+ log.info('Watching CI via agent (checks ALL runs)');
121
+ const watchResult = await watchCiViaAgent(executor, branch, options, timeoutMs, log);
90
122
  if (watchResult.runUrl)
91
123
  runUrl = watchResult.runUrl;
124
+ if (watchResult.timedOut) {
125
+ log.info('Initial CI watch timed out');
126
+ ciFixHistory.push({
127
+ attempt: ciFixAttempts + 1,
128
+ startedAt: new Date().toISOString(),
129
+ failureSummary: 'CI watch timed out',
130
+ outcome: 'timeout',
131
+ });
132
+ await handleCiTerminalFailure(feature, prUrl, prNumber, deps.featureRepository, messages);
133
+ throw buildCiExhaustedError(ciFixAttempts + 1, ciFixHistory, 'timeout');
134
+ }
92
135
  if (watchResult.status === 'success') {
93
136
  log.info('CI passed on first watch');
94
137
  return { ciStatus: CiStatus.Success, ciFixAttempts, ciFixHistory, ciFixStatus: 'success' };
@@ -101,23 +144,40 @@ export async function runCiWatchFixLoop(deps, params) {
101
144
  ciFixStatus = 'exhausted';
102
145
  break;
103
146
  }
104
- // Fetch failure logs
147
+ // Fetch failure logs for context
105
148
  const runId = extractRunId(runUrl) ?? '';
106
149
  const failureLogs = await gitPrService.getFailureLogs(cwd, runId, branch, logMaxChars);
107
150
  const startedAt = new Date().toISOString();
108
151
  log.info(`CI fix attempt ${ciFixAttempts + 1}/${maxAttempts} for run ${runId}`);
152
+ // Record fix phase timing
153
+ const fixStart = Date.now();
154
+ const fixTimingId = await recordPhaseStart('merge:ci-fix', {
155
+ agentType: executor.agentType,
156
+ });
109
157
  // Invoke fix executor — maxAttempts:1 prevents retryExecute's internal
110
158
  // retry logic from consuming CI fix attempts behind the outer loop's back.
111
- // Each CI fix is a unique attempt with distinct failure logs and prompt;
112
- // the outer loop already handles iteration.
113
159
  const fixPrompt = buildCiWatchFixPrompt(failureLogs, ciFixAttempts + 1, maxAttempts, branch);
114
160
  try {
115
- await retryExecute(executor, fixPrompt, options, { maxAttempts: 1, logger: log });
161
+ const fixResult = await retryExecute(executor, fixPrompt, options, {
162
+ maxAttempts: 1,
163
+ logger: log,
164
+ });
165
+ await recordPhaseEnd(fixTimingId, Date.now() - fixStart, {
166
+ inputTokens: fixResult.usage?.inputTokens,
167
+ outputTokens: fixResult.usage?.outputTokens,
168
+ costUsd: fixResult.usage?.costUsd,
169
+ numTurns: fixResult.usage?.numTurns,
170
+ durationApiMs: fixResult.usage?.durationApiMs,
171
+ exitCode: 'success',
172
+ });
116
173
  }
117
174
  catch (execErr) {
118
175
  // If the fix executor fails, count it as a failed attempt and continue
119
- // the loop rather than killing the entire CI fix process.
120
176
  const execMsg = execErr instanceof Error ? execErr.message : String(execErr);
177
+ await recordPhaseEnd(fixTimingId, Date.now() - fixStart, {
178
+ exitCode: 'error',
179
+ errorMessage: execMsg.slice(0, 500),
180
+ });
121
181
  log.info(`CI fix executor failed on attempt ${ciFixAttempts + 1}: ${execMsg}`);
122
182
  ciFixAttempts++;
123
183
  ciFixHistory.push({
@@ -130,44 +190,22 @@ export async function runCiWatchFixLoop(deps, params) {
130
190
  continue;
131
191
  }
132
192
  ciFixAttempts++;
133
- // Get updated run URL (new run triggered by push in fix)
134
- const updatedCiStatus = await gitPrService.getCiStatus(cwd, branch);
135
- if (updatedCiStatus.runUrl)
136
- runUrl = updatedCiStatus.runUrl;
137
- // Watch CI after fix
138
- let fixWatchResult;
139
- try {
140
- fixWatchResult = await gitPrService.watchCi(cwd, branch, timeoutMs, pollInterval);
141
- }
142
- catch (err) {
143
- if (err instanceof GitPrError && err.code === GitPrErrorCode.CI_TIMEOUT) {
144
- log.info(`CI watch timed out during fix attempt ${ciFixAttempts}`);
145
- ciFixHistory.push({
146
- attempt: ciFixAttempts,
147
- startedAt,
148
- failureSummary: failureLogs.slice(0, 500),
149
- outcome: 'timeout',
150
- });
151
- ciFixStatus = 'timeout';
152
- break;
153
- }
154
- // For non-timeout watchCi errors (e.g. GIT_ERROR), treat as a failed
155
- // attempt and continue the loop instead of killing it.
156
- const watchMsg = err instanceof Error ? err.message : String(err);
157
- log.info(`CI watch failed during fix attempt ${ciFixAttempts}: ${watchMsg}`);
193
+ // Watch CI after fix via agent (agent checks ALL runs for updated branch)
194
+ log.info('Watching CI after fix via agent');
195
+ const fixWatchResult = await watchCiViaAgent(executor, branch, options, timeoutMs, log);
196
+ if (fixWatchResult.runUrl)
197
+ runUrl = fixWatchResult.runUrl;
198
+ if (fixWatchResult.timedOut) {
199
+ log.info(`CI watch timed out during fix attempt ${ciFixAttempts}`);
158
200
  ciFixHistory.push({
159
201
  attempt: ciFixAttempts,
160
202
  startedAt,
161
203
  failureSummary: failureLogs.slice(0, 500),
162
- outcome: 'failed',
204
+ outcome: 'timeout',
163
205
  });
164
- messages.push(`[merge] CI fix attempt ${ciFixAttempts}/${maxAttempts} — watch failed`);
165
- continue;
206
+ ciFixStatus = 'timeout';
207
+ break;
166
208
  }
167
- // Update runUrl to the run that was actually watched (avoids mismatch
168
- // when multiple workflow runs exist for the same branch).
169
- if (fixWatchResult.runUrl)
170
- runUrl = fixWatchResult.runUrl;
171
209
  const outcome = fixWatchResult.status === 'success' ? 'fixed' : 'failed';
172
210
  ciFixHistory.push({
173
211
  attempt: ciFixAttempts,
@@ -8,6 +8,11 @@ export interface PrParseResult {
8
8
  url: string;
9
9
  number: number;
10
10
  }
11
+ export interface CiWatchParseResult {
12
+ status: 'success' | 'failure';
13
+ summary?: string;
14
+ runUrl?: string;
15
+ }
11
16
  /**
12
17
  * Extract the first commit SHA from agent output text.
13
18
  * Looks for git commit output format `[branch SHA]` or `commit SHA`.
@@ -19,4 +24,11 @@ export declare function parseCommitHash(output: string): string | null;
19
24
  * Returns null if no PR URL found.
20
25
  */
21
26
  export declare function parsePrUrl(output: string): PrParseResult | null;
27
+ /**
28
+ * Extract CI watch result from agent output text.
29
+ * Looks for CI_STATUS: PASSED or CI_STATUS: FAILED markers.
30
+ * When multiple CI_STATUS markers appear, uses the last one.
31
+ * Returns failure with diagnostic summary if no marker found.
32
+ */
33
+ export declare function parseCiWatchResult(output: string): CiWatchParseResult;
22
34
  //# sourceMappingURL=merge-output-parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"merge-output-parser.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI7D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAI/D"}
1
+ {"version":3,"file":"merge-output-parser.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AASD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI7D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAI/D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAuBrE"}
@@ -9,6 +9,11 @@
9
9
  const COMMIT_SHA_RE = /\[[\w/.-]+\s+([0-9a-f]{7,40})\]|(?:commit\s+)([0-9a-f]{7,40})/i;
10
10
  // Matches GitHub PR URL: https://github.com/owner/repo/pull/123
11
11
  const PR_URL_RE = /(https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/pull\/(\d+))/;
12
+ // Matches CI_STATUS: PASSED or CI_STATUS: FAILED — <summary>
13
+ const CI_STATUS_PASSED_RE = /CI_STATUS:\s*PASSED/;
14
+ const CI_STATUS_FAILED_RE = /CI_STATUS:\s*FAILED(?:\s*—\s*(.+))?/;
15
+ // Matches GitHub Actions run URL
16
+ const RUN_URL_RE = /(https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/actions\/runs\/\d+)/;
12
17
  /**
13
18
  * Extract the first commit SHA from agent output text.
14
19
  * Looks for git commit output format `[branch SHA]` or `commit SHA`.
@@ -30,3 +35,31 @@ export function parsePrUrl(output) {
30
35
  return null;
31
36
  return { url: match[1], number: parseInt(match[2], 10) };
32
37
  }
38
+ /**
39
+ * Extract CI watch result from agent output text.
40
+ * Looks for CI_STATUS: PASSED or CI_STATUS: FAILED markers.
41
+ * When multiple CI_STATUS markers appear, uses the last one.
42
+ * Returns failure with diagnostic summary if no marker found.
43
+ */
44
+ export function parseCiWatchResult(output) {
45
+ const runUrlMatch = output.match(RUN_URL_RE);
46
+ const runUrl = runUrlMatch ? runUrlMatch[1] : undefined;
47
+ // Split into lines and check from bottom up (last status wins)
48
+ const lines = output.split('\n');
49
+ for (let i = lines.length - 1; i >= 0; i--) {
50
+ const line = lines[i];
51
+ if (CI_STATUS_PASSED_RE.test(line)) {
52
+ return { status: 'success', runUrl };
53
+ }
54
+ const failedMatch = line.match(CI_STATUS_FAILED_RE);
55
+ if (failedMatch) {
56
+ const summary = failedMatch[1]?.trim() || 'CI failed (no details provided)';
57
+ return { status: 'failure', summary, runUrl };
58
+ }
59
+ }
60
+ return {
61
+ status: 'failure',
62
+ summary: 'CI status could not be determined from agent output',
63
+ runUrl,
64
+ };
65
+ }
@@ -44,4 +44,14 @@ export declare function buildCommitPushPrPrompt(state: FeatureAgentState, branch
44
44
  * @param branch - Feature branch name to push to after fixing
45
45
  */
46
46
  export declare function buildCiWatchFixPrompt(failureLogs: string, attemptNumber: number, maxAttempts: number, branch: string): string;
47
+ /**
48
+ * Build a prompt for the CI watch agent call.
49
+ *
50
+ * Instructs the agent to check ALL CI runs for a branch, wait for all
51
+ * to complete, verify every run passed, and report structured status.
52
+ * Generic — works with any git/gh repo, not tied to specific workflows.
53
+ *
54
+ * @param branch - Feature branch name to watch CI for
55
+ */
56
+ export declare function buildCiWatchPrompt(branch: string): string;
47
57
  //# sourceMappingURL=merge-prompts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"merge-prompts.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAE3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAwCxD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAU9F;AAuCD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,QAAQ,EAAE,EACpB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAUR;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAqER;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,MAAM,CA0BR"}
1
+ {"version":3,"file":"merge-prompts.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAE3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAwCxD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAU9F;AAuCD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,QAAQ,EAAE,EACpB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAUR;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAqER;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,MAAM,CA0BR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAqDzD"}
@@ -219,3 +219,66 @@ ${failureLogs}
219
219
  - Do NOT create a new branch — push directly to \`${branch}\`
220
220
  - If the failure is unclear, make your best diagnosis and explain your reasoning in the commit message`;
221
221
  }
222
+ /**
223
+ * Build a prompt for the CI watch agent call.
224
+ *
225
+ * Instructs the agent to check ALL CI runs for a branch, wait for all
226
+ * to complete, verify every run passed, and report structured status.
227
+ * Generic — works with any git/gh repo, not tied to specific workflows.
228
+ *
229
+ * @param branch - Feature branch name to watch CI for
230
+ */
231
+ export function buildCiWatchPrompt(branch) {
232
+ return `You are checking CI status for branch \`${branch}\`.
233
+
234
+ ## Instructions
235
+
236
+ Follow these steps EXACTLY:
237
+
238
+ ### Step 1: List all CI runs for the branch
239
+
240
+ \`\`\`
241
+ gh run list --branch ${branch} --json databaseId,status,conclusion,name
242
+ \`\`\`
243
+
244
+ This shows ALL workflow runs. A single push can trigger MULTIPLE runs (e.g., CI/CD + PR validation).
245
+ You MUST check every run, not just one.
246
+
247
+ ### Step 2: Watch all in-progress runs
248
+
249
+ For EACH run with \`status\` that is NOT \`completed\`, watch it:
250
+
251
+ \`\`\`
252
+ gh run watch <databaseId> --interval 20
253
+ \`\`\`
254
+
255
+ Wait for each in-progress run to finish before proceeding.
256
+
257
+ ### Step 3: Verify all runs after watching
258
+
259
+ After all runs complete, run the list command again to confirm:
260
+
261
+ \`\`\`
262
+ gh run list --branch ${branch} --json databaseId,status,conclusion,name
263
+ \`\`\`
264
+
265
+ Check that EVERY run shows \`status: completed\`. Do NOT trust \`gh run watch\` exit status alone.
266
+
267
+ ### Step 4: Report status
268
+
269
+ After verifying all runs are complete, report EXACTLY ONE of these lines:
270
+
271
+ - If every run has \`conclusion: success\`:
272
+ \`CI_STATUS: PASSED\`
273
+
274
+ - If any run has a non-success conclusion:
275
+ \`CI_STATUS: FAILED — <brief summary of which runs failed and why>\`
276
+
277
+ ## Constraints
278
+
279
+ - NEVER claim CI passed until EVERY run shows \`completed\` + \`success\`
280
+ - NEVER watch a single run and assume it is the only one
281
+ - If \`gh run list\` returns no runs, wait 10 seconds and retry up to 3 times
282
+ - If rate-limited (403 error), report: \`CI_STATUS: PASSED\` (skip check gracefully)
283
+ - Print the URL of the failing run if CI fails`;
284
+ }