@shepai/cli 1.144.0 → 1.145.0-pr452.ae7b9df

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 (267) hide show
  1. package/apis/json-schema/Feature.yaml +25 -0
  2. package/apis/json-schema/PullRequest.yaml +11 -0
  3. package/apis/json-schema/SdlcLifecycle.yaml +1 -0
  4. package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts +5 -0
  5. package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
  6. package/dist/packages/core/src/application/ports/output/services/git-fork-service.interface.d.ts +79 -0
  7. package/dist/packages/core/src/application/ports/output/services/git-fork-service.interface.d.ts.map +1 -0
  8. package/dist/packages/core/src/application/ports/output/services/git-fork-service.interface.js +31 -0
  9. package/dist/packages/core/src/application/use-cases/features/adopt-branch.use-case.d.ts.map +1 -1
  10. package/dist/packages/core/src/application/use-cases/features/adopt-branch.use-case.js +5 -0
  11. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
  12. package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +10 -0
  13. package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +10 -0
  14. package/dist/packages/core/src/application/use-cases/features/create/types.d.ts.map +1 -1
  15. package/dist/packages/core/src/application/use-cases/features/poll-upstream-pr.use-case.d.ts +23 -0
  16. package/dist/packages/core/src/application/use-cases/features/poll-upstream-pr.use-case.d.ts.map +1 -0
  17. package/dist/packages/core/src/application/use-cases/features/poll-upstream-pr.use-case.js +84 -0
  18. package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.d.ts.map +1 -1
  19. package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.js +2 -0
  20. package/dist/packages/core/src/domain/generated/output.d.ts +33 -0
  21. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  22. package/dist/packages/core/src/domain/generated/output.js +1 -0
  23. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  24. package/dist/packages/core/src/infrastructure/di/container.js +2 -0
  25. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts +8 -0
  26. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts.map +1 -1
  27. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.js +18 -0
  28. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-columns.d.ts +13 -0
  29. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-columns.d.ts.map +1 -0
  30. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-columns.js +30 -0
  31. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/046-add-per-feature-workflow-columns.d.ts +12 -0
  32. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/046-add-per-feature-workflow-columns.d.ts.map +1 -0
  33. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/046-add-per-feature-workflow-columns.js +23 -0
  34. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts.map +1 -1
  35. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +23 -4
  36. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts +25 -0
  37. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts.map +1 -1
  38. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +85 -0
  39. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
  40. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +5 -0
  41. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
  42. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +15 -0
  43. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +5 -0
  44. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
  45. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +23 -0
  46. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts +6 -3
  47. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts.map +1 -1
  48. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.js +104 -66
  49. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.d.ts +12 -0
  50. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.d.ts.map +1 -1
  51. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge-output-parser.js +33 -0
  52. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts +2 -0
  53. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
  54. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +50 -0
  55. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +8 -0
  56. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
  57. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +40 -1
  58. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/analyze.prompt.d.ts.map +1 -1
  59. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/analyze.prompt.js +11 -9
  60. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts +10 -0
  61. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.d.ts.map +1 -1
  62. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/merge-prompts.js +68 -1
  63. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/plan.prompt.d.ts.map +1 -1
  64. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/plan.prompt.js +8 -6
  65. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.d.ts.map +1 -1
  66. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/requirements.prompt.js +11 -9
  67. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/research.prompt.d.ts.map +1 -1
  68. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/research.prompt.js +8 -6
  69. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/schemas/spec.schema.d.ts.map +1 -1
  70. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/schemas/spec.schema.js +3 -1
  71. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/schemas/validation.d.ts +1 -0
  72. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/schemas/validation.d.ts.map +1 -1
  73. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/schemas/validation.js +9 -0
  74. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts +5 -0
  75. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts.map +1 -1
  76. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.js +20 -0
  77. package/dist/packages/core/src/infrastructure/services/git/git-fork.service.d.ts +25 -0
  78. package/dist/packages/core/src/infrastructure/services/git/git-fork.service.d.ts.map +1 -0
  79. package/dist/packages/core/src/infrastructure/services/git/git-fork.service.js +145 -0
  80. package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts +17 -3
  81. package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts.map +1 -1
  82. package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js +98 -15
  83. package/dist/src/presentation/cli/commands/ui.command.d.ts.map +1 -1
  84. package/dist/src/presentation/cli/commands/ui.command.js +2 -1
  85. package/dist/src/presentation/web/app/actions/create-feature.d.ts +10 -0
  86. package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
  87. package/dist/src/presentation/web/app/actions/create-feature.js +8 -1
  88. package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
  89. package/dist/src/presentation/web/app/api/agent-events/route.js +1 -0
  90. package/dist/src/presentation/web/app/build-feature-node-data.d.ts.map +1 -1
  91. package/dist/src/presentation/web/app/build-feature-node-data.js +5 -3
  92. package/dist/src/presentation/web/app/build-graph-nodes.js +5 -3
  93. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +1 -1
  94. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts +4 -0
  95. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
  96. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +24 -7
  97. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +12 -0
  98. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts.map +1 -1
  99. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.js +35 -0
  100. package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.js +7 -1
  101. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +5 -1
  102. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  103. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.js +12 -0
  104. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
  105. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +1 -0
  106. package/dist/src/presentation/web/dev-server.js +2 -1
  107. package/dist/tsconfig.build.tsbuildinfo +1 -1
  108. package/package.json +1 -1
  109. package/web/.next/BUILD_ID +1 -1
  110. package/web/.next/build-manifest.json +2 -2
  111. package/web/.next/fallback-build-manifest.json +2 -2
  112. package/web/.next/prerender-manifest.json +3 -3
  113. package/web/.next/required-server-files.js +3 -3
  114. package/web/.next/required-server-files.json +3 -3
  115. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +28 -28
  116. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  117. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  118. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +28 -28
  119. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  120. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  121. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  122. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  123. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  124. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +36 -36
  125. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  126. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  127. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  128. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  129. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  130. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +28 -28
  131. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  132. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  133. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  134. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  135. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  136. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +36 -36
  137. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  138. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  139. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +26 -26
  140. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  141. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  142. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  143. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  144. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  145. package/web/.next/server/app/_global-error.html +2 -2
  146. package/web/.next/server/app/_global-error.rsc +1 -1
  147. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  148. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  149. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  150. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  151. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  152. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
  153. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  154. package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  155. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  156. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  157. package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
  158. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  159. package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
  160. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  161. package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
  162. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  163. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
  164. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
  165. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
  166. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
  167. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  168. package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js +1 -1
  169. package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js.map +1 -1
  170. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
  171. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  172. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  173. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/[root-of-the-server]__0b150ddf._.js +1 -1
  175. package/web/.next/server/chunks/ssr/[root-of-the-server]__0b150ddf._.js.map +1 -1
  176. package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js +2 -2
  177. package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js.map +1 -1
  178. package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js +1 -1
  179. package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js.map +1 -1
  180. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  181. package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js +1 -1
  182. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
  183. package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
  184. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
  185. package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
  186. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
  187. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  188. package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js +1 -1
  189. package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js.map +1 -1
  190. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js +1 -1
  191. package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js.map +1 -1
  192. package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js +1 -1
  193. package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js.map +1 -1
  194. package/web/.next/server/chunks/ssr/[root-of-the-server]__df7c1cd3._.js +3 -0
  195. package/web/.next/server/chunks/ssr/[root-of-the-server]__df7c1cd3._.js.map +1 -0
  196. package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js +1 -1
  197. package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js.map +1 -1
  198. package/web/.next/server/chunks/ssr/_0c5f56e3._.js +2 -2
  199. package/web/.next/server/chunks/ssr/_0c5f56e3._.js.map +1 -1
  200. package/web/.next/server/chunks/ssr/_1b719e7f._.js +1 -1
  201. package/web/.next/server/chunks/ssr/_1b719e7f._.js.map +1 -1
  202. package/web/.next/server/chunks/ssr/_37e8548b._.js +1 -1
  203. package/web/.next/server/chunks/ssr/_37e8548b._.js.map +1 -1
  204. package/web/.next/server/chunks/ssr/_55d763e2._.js +1 -1
  205. package/web/.next/server/chunks/ssr/_55d763e2._.js.map +1 -1
  206. package/web/.next/server/chunks/ssr/{_c67ad133._.js → _5b89327c._.js} +2 -2
  207. package/web/.next/server/chunks/ssr/{_c67ad133._.js.map → _5b89327c._.js.map} +1 -1
  208. package/web/.next/server/chunks/ssr/_6256a985._.js +1 -1
  209. package/web/.next/server/chunks/ssr/_6256a985._.js.map +1 -1
  210. package/web/.next/server/chunks/ssr/_64bdfc6f._.js +2 -2
  211. package/web/.next/server/chunks/ssr/_64bdfc6f._.js.map +1 -1
  212. package/web/.next/server/chunks/ssr/_7dca1882._.js +1 -1
  213. package/web/.next/server/chunks/ssr/_7dca1882._.js.map +1 -1
  214. package/web/.next/server/chunks/ssr/_8fcc39d4._.js +3 -0
  215. package/web/.next/server/chunks/ssr/_8fcc39d4._.js.map +1 -0
  216. package/web/.next/server/chunks/ssr/_b71645b4._.js +1 -1
  217. package/web/.next/server/chunks/ssr/_b71645b4._.js.map +1 -1
  218. package/web/.next/server/chunks/ssr/{_c64f06d5._.js → _c480d290._.js} +2 -2
  219. package/web/.next/server/chunks/ssr/{_c64f06d5._.js.map → _c480d290._.js.map} +1 -1
  220. package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -1
  221. package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
  222. package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
  223. package/web/.next/server/chunks/ssr/_f39a1adb._.js +1 -1
  224. package/web/.next/server/chunks/ssr/_f39a1adb._.js.map +1 -1
  225. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  226. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  227. package/web/.next/server/chunks/ssr/src_presentation_web_36d135cd._.js +3 -0
  228. package/web/.next/server/chunks/ssr/{src_presentation_web_dd85ad88._.js.map → src_presentation_web_36d135cd._.js.map} +1 -1
  229. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
  230. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
  231. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
  232. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
  233. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  234. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  235. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
  236. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  237. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  238. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  239. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  240. package/web/.next/server/pages/500.html +2 -2
  241. package/web/.next/server/server-reference-manifest.js +1 -1
  242. package/web/.next/server/server-reference-manifest.json +44 -44
  243. package/web/.next/static/chunks/{74ee98538b63a4b2.css → 0b18c50740356276.css} +1 -1
  244. package/web/.next/static/chunks/2f69a2c8803b4d03.js +1 -0
  245. package/web/.next/static/chunks/{53478ed65db63030.js → 412d6a39406dcc01.js} +2 -2
  246. package/web/.next/static/chunks/{21502baa33ad728a.js → 4887b859bc457552.js} +2 -2
  247. package/web/.next/static/chunks/4f0adb1f7fe668dc.js +1 -0
  248. package/web/.next/static/chunks/{1867fdb7f2c6035f.js → 62b396454129b531.js} +1 -1
  249. package/web/.next/static/chunks/{8cc1aea0d82835be.js → 66dbc5a3e4f9a938.js} +1 -1
  250. package/web/.next/static/chunks/{60c6c3c30fba3b7c.js → 9940f68284ee180e.js} +1 -1
  251. package/web/.next/static/chunks/{683ec435a34ca112.js → 9f1367bf0f603996.js} +1 -1
  252. package/web/.next/static/chunks/{ecfbc35ad11c83bb.js → af3b565e34bea1e8.js} +1 -1
  253. package/web/.next/static/chunks/{88300dbc7c91abb2.js → b190938cb5fd9b35.js} +1 -1
  254. package/web/.next/static/chunks/{904cdf4c47654f32.js → e7744ffb13a4a677.js} +1 -1
  255. package/web/.next/static/chunks/{de0704c3e73118cf.js → f0d47ebee8ca8bc3.js} +1 -1
  256. package/web/.next/static/chunks/fa556c575c788679.js +1 -0
  257. package/web/.next/server/chunks/ssr/[root-of-the-server]__cb850066._.js +0 -3
  258. package/web/.next/server/chunks/ssr/[root-of-the-server]__cb850066._.js.map +0 -1
  259. package/web/.next/server/chunks/ssr/_a9f57758._.js +0 -3
  260. package/web/.next/server/chunks/ssr/_a9f57758._.js.map +0 -1
  261. package/web/.next/server/chunks/ssr/src_presentation_web_dd85ad88._.js +0 -3
  262. package/web/.next/static/chunks/0bce83a11c7a9383.js +0 -1
  263. package/web/.next/static/chunks/6a370f2709c81d83.js +0 -1
  264. package/web/.next/static/chunks/9e3e916a22d1121f.js +0 -1
  265. /package/web/.next/static/{rsS9eOHzCHbGCCwBS1fRh → myvK7Q1DabrQLkyfNQtH1}/_buildManifest.js +0 -0
  266. /package/web/.next/static/{rsS9eOHzCHbGCCwBS1fRh → myvK7Q1DabrQLkyfNQtH1}/_clientMiddlewareManifest.json +0 -0
  267. /package/web/.next/static/{rsS9eOHzCHbGCCwBS1fRh → myvK7Q1DabrQLkyfNQtH1}/_ssgManifest.js +0 -0
@@ -54,6 +54,11 @@ export function parseWorkerArgs(args) {
54
54
  const resumeFromInterrupt = args.includes('--resume-from-interrupt');
55
55
  const push = args.includes('--push');
56
56
  const openPr = args.includes('--open-pr');
57
+ const forkAndPr = args.includes('--fork-and-pr');
58
+ const commitSpecs = !args.includes('--no-commit-specs');
59
+ const ciWatchEnabled = !args.includes('--no-ci-watch');
60
+ const enableEvidence = args.includes('--enable-evidence');
61
+ const commitEvidence = args.includes('--commit-evidence');
57
62
  const fast = args.includes('--fast');
58
63
  const threadIdx = args.indexOf('--thread-id');
59
64
  const threadId = threadIdx !== -1 && threadIdx + 1 < args.length ? args[threadIdx + 1] : undefined;
@@ -83,6 +88,11 @@ export function parseWorkerArgs(args) {
83
88
  resumeFromInterrupt,
84
89
  push,
85
90
  openPr,
91
+ forkAndPr,
92
+ commitSpecs,
93
+ ciWatchEnabled,
94
+ enableEvidence,
95
+ commitEvidence,
86
96
  resumePayload,
87
97
  agentType,
88
98
  fast,
@@ -143,6 +153,8 @@ export async function runWorker(args) {
143
153
  ...(args.resumeFromInterrupt ? ['--resume-from-interrupt'] : []),
144
154
  ...(args.push ? ['--push'] : []),
145
155
  ...(args.openPr ? ['--open-pr'] : []),
156
+ ...(args.forkAndPr ? ['--fork-and-pr'] : []),
157
+ ...(args.commitSpecs === false ? ['--no-commit-specs'] : []),
146
158
  ...(args.resumePayload ? ['--resume-payload', args.resumePayload] : []),
147
159
  ...(args.agentType ? ['--agent-type', args.agentType] : []),
148
160
  ...(args.fast ? ['--fast'] : []),
@@ -185,6 +197,7 @@ export async function runWorker(args) {
185
197
  localMergeSquash: (cwd, featureBranch, baseBranch, commitMessage, hasRemote) => gitPrService.localMergeSquash(cwd, featureBranch, baseBranch, commitMessage, hasRemote),
186
198
  featureRepository,
187
199
  gitPrService,
200
+ gitForkService: container.resolve('IGitForkService'),
188
201
  cleanupFeatureWorktreeUseCase,
189
202
  },
190
203
  };
@@ -274,6 +287,11 @@ export async function runWorker(args) {
274
287
  ...(args.resumeReason ? { resumeReason: args.resumeReason } : {}),
275
288
  push: args.push ?? false,
276
289
  openPr: args.openPr ?? false,
290
+ forkAndPr: args.forkAndPr ?? false,
291
+ commitSpecs: args.commitSpecs ?? true,
292
+ ciWatchEnabled: args.ciWatchEnabled ?? true,
293
+ enableEvidence: args.enableEvidence ?? false,
294
+ commitEvidence: args.commitEvidence ?? false,
277
295
  }, graphConfig);
278
296
  }
279
297
  else {
@@ -287,6 +305,11 @@ export async function runWorker(args) {
287
305
  ...(args.model ? { model: args.model } : {}),
288
306
  push: args.push ?? false,
289
307
  openPr: args.openPr ?? false,
308
+ forkAndPr: args.forkAndPr ?? false,
309
+ commitSpecs: args.commitSpecs ?? true,
310
+ ciWatchEnabled: args.ciWatchEnabled ?? true,
311
+ enableEvidence: args.enableEvidence ?? false,
312
+ commitEvidence: args.commitEvidence ?? false,
290
313
  }, graphConfig);
291
314
  }
292
315
  log(`Graph invocation completed. Error: ${result.error ?? 'none'}`);
@@ -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
+ }
@@ -17,6 +17,7 @@ import type { FeatureAgentState } from '../../state.js';
17
17
  import type { IFeatureRepository } from '../../../../../../application/ports/output/repositories/feature-repository.interface.js';
18
18
  import type { DiffSummary, IGitPrService } from '../../../../../../application/ports/output/services/git-pr-service.interface.js';
19
19
  import type { CleanupFeatureWorktreeUseCase } from '../../../../../../application/use-cases/features/cleanup-feature-worktree.use-case.js';
20
+ import type { IGitForkService } from '../../../../../../application/ports/output/services/git-fork-service.interface.js';
20
21
  export interface MergeNodeDeps {
21
22
  executor: IAgentExecutor;
22
23
  getDiffSummary: (cwd: string, baseBranch: string) => Promise<DiffSummary>;
@@ -37,6 +38,7 @@ export interface MergeNodeDeps {
37
38
  */
38
39
  revParse: (cwd: string, ref: string) => Promise<string>;
39
40
  gitPrService: IGitPrService;
41
+ gitForkService?: IGitForkService;
40
42
  cleanupFeatureWorktreeUseCase: Pick<CleanupFeatureWorktreeUseCase, 'execute'>;
41
43
  }
42
44
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAClH,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACd,MAAM,iEAAiE,CAAC;AAoBzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uEAAuE,CAAC;AAE3H,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;IACnE;;OAEG;IACH,gBAAgB,EAAE,CAChB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,SAAS,CAAC,EAAE,OAAO,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB;;;OAGG;IACH,WAAW,EAAE,CACX,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB;;OAEG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,YAAY,EAAE,aAAa,CAAC;IAC5B,6BAA6B,EAAE,IAAI,CAAC,6BAA6B,EAAE,SAAS,CAAC,CAAC;CAC/E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAiU7E"}
1
+ {"version":3,"file":"merge.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yEAAyE,CAAC;AAClH,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACd,MAAM,iEAAiE,CAAC;AAoBzE,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uEAAuE,CAAC;AAC3H,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mEAAmE,CAAC;AAEzG,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1E,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,QAAQ,CAAC,CAAC;IACnE;;OAEG;IACH,gBAAgB,EAAE,CAChB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,SAAS,CAAC,EAAE,OAAO,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB;;;OAGG;IACH,WAAW,EAAE,CACX,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB;;OAEG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,YAAY,EAAE,aAAa,CAAC;IAC5B,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,6BAA6B,EAAE,IAAI,CAAC,6BAA6B,EAAE,SAAS,CAAC,CAAC;CAC/E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,IAGnC,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAgY7E"}
@@ -220,6 +220,56 @@ export function createMergeNode(deps) {
220
220
  ciStatus = feature.pr.ciStatus ?? ciStatus;
221
221
  }
222
222
  }
223
+ // --- Fork-and-PR flow ---
224
+ // When forkAndPr=true, fork the repo, push to the fork, create upstream PR,
225
+ // then transition to AwaitingUpstream instead of merging.
226
+ if (state.forkAndPr && deps.gitForkService) {
227
+ log.info('Fork-and-PR flow: forking repo and creating upstream PR');
228
+ await deps.gitForkService.forkRepository(cwd);
229
+ log.info('Repository forked, remotes remapped');
230
+ await deps.gitForkService.pushToFork(cwd, branch);
231
+ log.info(`Branch ${branch} pushed to fork`);
232
+ const upstreamPr = await deps.gitForkService.createUpstreamPr(cwd, feature?.name ?? branch, feature?.description ?? '', branch, baseBranch);
233
+ log.info(`Upstream PR created: ${upstreamPr.url}`);
234
+ messages.push(`[merge] Upstream PR created: ${upstreamPr.url}`);
235
+ if (feature) {
236
+ await deps.featureRepository.update({
237
+ ...feature,
238
+ lifecycle: SdlcLifecycle.AwaitingUpstream,
239
+ pr: {
240
+ ...(feature.pr ?? { url: '', number: 0, status: PrStatus.Open }),
241
+ ...(commitHash ? { commitHash } : {}),
242
+ upstreamPrUrl: upstreamPr.url,
243
+ upstreamPrNumber: upstreamPr.number,
244
+ upstreamPrStatus: PrStatus.Open,
245
+ },
246
+ updatedAt: new Date(),
247
+ });
248
+ messages.push(`[merge] Feature lifecycle → AwaitingUpstream`);
249
+ }
250
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
251
+ await recordPhaseEnd(mergeTimingId, Date.now() - startTime, {
252
+ inputTokens: totalInputTokens || undefined,
253
+ outputTokens: totalOutputTokens || undefined,
254
+ exitCode: 'success',
255
+ });
256
+ messages.push(`[merge] Complete (${elapsed}s)`);
257
+ log.info(`Fork-and-PR merge flow complete (${elapsed}s)`);
258
+ return {
259
+ currentNode: 'merge',
260
+ messages,
261
+ commitHash,
262
+ prUrl,
263
+ prNumber,
264
+ ciStatus,
265
+ ciFixAttempts,
266
+ ciFixHistory,
267
+ ciFixStatus,
268
+ _approvalAction: null,
269
+ _rejectionFeedback: null,
270
+ _needsReexecution: false,
271
+ };
272
+ }
223
273
  // --- Merge ---
224
274
  // Merge when: allowMerge is true (auto-merge), OR user explicitly
225
275
  // approved at the merge gate (isResumeAfterInterrupt means they
@@ -159,6 +159,14 @@ export declare function buildCommitPushBlock(opts: {
159
159
  * context so the agent knows to check existing work before proceeding.
160
160
  */
161
161
  export declare function buildResumeContext(resumeReason: string | undefined): string;
162
+ /**
163
+ * Safety net: remove spec-file commits the agent made despite being told not to.
164
+ *
165
+ * When commitSpecs=false and the agent ignored the "do NOT commit" instruction,
166
+ * this function finds the most recent commit that touches the spec directory and
167
+ * soft-resets it so the files remain on disk (for local use) but are not committed.
168
+ */
169
+ export declare function removeSpecCommitsIfNeeded(state: FeatureAgentState, nodeName: string, log: NodeLogger): void;
162
170
  /**
163
171
  * Execute a node with consistent logging and error handling.
164
172
  *
@@ -1 +1 @@
1
- {"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,8 @@
6
6
  */
7
7
  import yaml from 'js-yaml';
8
8
  import { mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync } from 'node:fs';
9
- import { join, dirname } from 'node:path';
9
+ import { execSync } from 'node:child_process';
10
+ import { join, dirname, relative } from 'node:path';
10
11
  import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
11
12
  import { hasSettings, getSettings } from '../../../../services/settings.service.js';
12
13
  import { reportNodeStart } from '../heartbeat.js';
@@ -394,6 +395,42 @@ Before proceeding with this phase:
394
395
 
395
396
  `;
396
397
  }
398
+ /** Spec-only phases whose commits should be removed when commitSpecs=false. */
399
+ const SPEC_PHASE_NODES = new Set(['analyze', 'requirements', 'research', 'plan']);
400
+ /**
401
+ * Safety net: remove spec-file commits the agent made despite being told not to.
402
+ *
403
+ * When commitSpecs=false and the agent ignored the "do NOT commit" instruction,
404
+ * this function finds the most recent commit that touches the spec directory and
405
+ * soft-resets it so the files remain on disk (for local use) but are not committed.
406
+ */
407
+ export function removeSpecCommitsIfNeeded(state, nodeName, log) {
408
+ if (state.commitSpecs)
409
+ return;
410
+ if (!SPEC_PHASE_NODES.has(nodeName))
411
+ return;
412
+ const cwd = state.worktreePath || state.repositoryPath;
413
+ const specRelDir = relative(cwd, state.specDir).replaceAll('\\', '/');
414
+ try {
415
+ // Check if HEAD commit touches spec files
416
+ const filesInHead = execSync(`git diff --name-only HEAD~1 HEAD -- "${specRelDir}"`, {
417
+ cwd,
418
+ encoding: 'utf-8',
419
+ windowsHide: true,
420
+ }).trim();
421
+ if (!filesInHead)
422
+ return;
423
+ log.info(`commitSpecs=false but agent committed spec files: ${filesInHead.split('\n').join(', ')}. Soft-resetting to undo.`);
424
+ // Soft-reset the last commit so spec files are unstaged but kept on disk
425
+ execSync('git reset --soft HEAD~1', { cwd, windowsHide: true });
426
+ // Unstage the spec files (keep them as untracked/modified on disk)
427
+ execSync(`git reset HEAD -- "${specRelDir}"`, { cwd, windowsHide: true });
428
+ }
429
+ catch {
430
+ // If git commands fail (e.g., no prior commit, detached HEAD), log and continue
431
+ log.info('Failed to check/remove spec commits — continuing');
432
+ }
433
+ }
397
434
  /**
398
435
  * Execute a node with consistent logging and error handling.
399
436
  *
@@ -480,6 +517,8 @@ export function executeNode(nodeName, executor, buildPrompt) {
480
517
  durationApiMs: result.usage?.durationApiMs,
481
518
  exitCode: 'success',
482
519
  });
520
+ // Safety net: undo spec commits if commitSpecs=false
521
+ removeSpecCommitsIfNeeded(state, nodeName, log);
483
522
  // Mark phase complete BEFORE interrupting so that on resume the
484
523
  // node detects the work is already done and returns early.
485
524
  markPhaseComplete(state.specDir, nodeName, log);
@@ -1 +1 @@
1
- {"version":3,"file":"analyze.prompt.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/analyze.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA6GnE"}
1
+ {"version":3,"file":"analyze.prompt.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/analyze.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAiHnE"}
@@ -36,9 +36,9 @@ Write your analysis to: ${state.specDir}/spec.yaml
36
36
 
37
37
  You MUST write the COMPLETE file (not a partial update). Preserve the existing name/number/branch fields and update everything else. Use this YAML structure:
38
38
 
39
- name: (keep existing)
40
- number: (keep existing)
41
- branch: (keep existing)
39
+ name: (keep existing — string)
40
+ number: (keep existing — MUST be a bare integer, e.g. 2, NOT "002" or "2")
41
+ branch: (keep existing — string)
42
42
  oneLiner: (concise one-line description of the feature)
43
43
  summary: >
44
44
  (2-3 sentence summary of what this feature involves based on your analysis)
@@ -107,10 +107,12 @@ You MUST write the COMPLETE file (not a partial update). Preserve the existing n
107
107
  - Do NOT start implementing the feature
108
108
  - Keep your analysis thorough but concise
109
109
 
110
- ${buildCommitPushBlock({
111
- push: state.push,
112
- files: [`${state.specDir}/spec.yaml`],
113
- commitHint: 'docs(specs): analyze repository and define spec',
114
- skipVerification: true,
115
- })}`;
110
+ ${state.commitSpecs
111
+ ? buildCommitPushBlock({
112
+ push: state.push,
113
+ files: [`${state.specDir}/spec.yaml`],
114
+ commitHint: 'docs(specs): analyze repository and define spec',
115
+ skipVerification: true,
116
+ })
117
+ : `## Git Operations\n\nDo NOT commit or push any spec files. Spec files are managed locally only.`}`;
116
118
  }
@@ -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