@shepai/cli 1.160.0-pr501.ddca420 → 1.161.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 (200) hide show
  1. package/apis/json-schema/WorkflowConfig.yaml +5 -0
  2. package/dist/packages/core/src/application/use-cases/features/auto-archive-completed.use-case.d.ts +30 -0
  3. package/dist/packages/core/src/application/use-cases/features/auto-archive-completed.use-case.d.ts.map +1 -0
  4. package/dist/packages/core/src/application/use-cases/features/auto-archive-completed.use-case.js +75 -0
  5. package/dist/packages/core/src/application/use-cases/features/auto-resolve-merged-branches.use-case.d.ts +38 -0
  6. package/dist/packages/core/src/application/use-cases/features/auto-resolve-merged-branches.use-case.d.ts.map +1 -0
  7. package/dist/packages/core/src/application/use-cases/features/auto-resolve-merged-branches.use-case.js +190 -0
  8. package/dist/packages/core/src/domain/factories/settings-defaults.factory.d.ts.map +1 -1
  9. package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +1 -0
  10. package/dist/packages/core/src/domain/generated/output.d.ts +4 -0
  11. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  12. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  13. package/dist/packages/core/src/infrastructure/di/container.js +5 -0
  14. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +1 -0
  15. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
  16. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +3 -0
  17. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/049-add-auto-archive-delay-minutes.d.ts +15 -0
  18. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/049-add-auto-archive-delay-minutes.d.ts.map +1 -0
  19. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/049-add-auto-archive-delay-minutes.js +20 -0
  20. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
  21. package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +6 -3
  22. package/dist/packages/core/src/infrastructure/services/auto-archive/auto-archive-watcher.service.d.ts +48 -0
  23. package/dist/packages/core/src/infrastructure/services/auto-archive/auto-archive-watcher.service.d.ts.map +1 -0
  24. package/dist/packages/core/src/infrastructure/services/auto-archive/auto-archive-watcher.service.js +101 -0
  25. package/dist/src/presentation/cli/commands/_serve.command.d.ts.map +1 -1
  26. package/dist/src/presentation/cli/commands/_serve.command.js +5 -0
  27. package/dist/src/presentation/cli/commands/ui.command.d.ts.map +1 -1
  28. package/dist/src/presentation/cli/commands/ui.command.js +5 -0
  29. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
  30. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +10 -0
  31. package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map +1 -1
  32. package/dist/src/presentation/web/components/features/settings/settings-page-client.js +23 -1
  33. package/dist/src/presentation/web/dev-server.js +10 -0
  34. package/dist/tsconfig.build.tsbuildinfo +1 -1
  35. package/package.json +1 -1
  36. package/web/.next/BUILD_ID +1 -1
  37. package/web/.next/build-manifest.json +2 -2
  38. package/web/.next/fallback-build-manifest.json +2 -2
  39. package/web/.next/prerender-manifest.json +3 -3
  40. package/web/.next/required-server-files.js +2 -2
  41. package/web/.next/required-server-files.json +2 -2
  42. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +28 -28
  43. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  44. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  45. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +26 -26
  46. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  47. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  48. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +29 -29
  49. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  50. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  51. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  52. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  53. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +36 -36
  55. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  56. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +26 -26
  58. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  59. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  61. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  62. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  63. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +26 -26
  64. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  65. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +29 -29
  67. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  68. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  69. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  70. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  71. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  72. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +36 -36
  73. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  74. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  75. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +26 -26
  76. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  77. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  78. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +26 -26
  79. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  80. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  81. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  82. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  83. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  84. package/web/.next/server/app/_global-error.html +2 -2
  85. package/web/.next/server/app/_global-error.rsc +1 -1
  86. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  87. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  88. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  89. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  90. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  91. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +5 -5
  92. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  93. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  94. package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  95. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  96. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  97. package/web/.next/server/app/skills/page/server-reference-manifest.json +10 -10
  98. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  99. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  100. package/web/.next/server/app/tools/page/server-reference-manifest.json +10 -10
  101. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  102. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  103. package/web/.next/server/app/version/page/server-reference-manifest.json +5 -5
  104. package/web/.next/server/app/version/page.js.nft.json +1 -1
  105. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  106. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
  107. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
  108. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  109. package/web/.next/server/chunks/[root-of-the-server]__beda892a._.js.map +1 -1
  110. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  112. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  113. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
  114. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
  115. package/web/.next/server/chunks/ssr/[root-of-the-server]__209c9597._.js +1 -1
  116. package/web/.next/server/chunks/ssr/[root-of-the-server]__209c9597._.js.map +1 -1
  117. package/web/.next/server/chunks/ssr/[root-of-the-server]__27301e38._.js +1 -1
  118. package/web/.next/server/chunks/ssr/[root-of-the-server]__27301e38._.js.map +1 -1
  119. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  120. package/web/.next/server/chunks/ssr/[root-of-the-server]__56b70465._.js +1 -1
  121. package/web/.next/server/chunks/ssr/[root-of-the-server]__56b70465._.js.map +1 -1
  122. package/web/.next/server/chunks/ssr/[root-of-the-server]__6fecf886._.js +1 -1
  123. package/web/.next/server/chunks/ssr/[root-of-the-server]__6fecf886._.js.map +1 -1
  124. package/web/.next/server/chunks/ssr/[root-of-the-server]__8b0aac03._.js +1 -1
  125. package/web/.next/server/chunks/ssr/[root-of-the-server]__8d27866c._.js +2 -2
  126. package/web/.next/server/chunks/ssr/[root-of-the-server]__8d27866c._.js.map +1 -1
  127. package/web/.next/server/chunks/ssr/[root-of-the-server]__9f3504c7._.js +1 -1
  128. package/web/.next/server/chunks/ssr/[root-of-the-server]__9f3504c7._.js.map +1 -1
  129. package/web/.next/server/chunks/ssr/[root-of-the-server]__bd6ed91a._.js +2 -2
  130. package/web/.next/server/chunks/ssr/[root-of-the-server]__bd6ed91a._.js.map +1 -1
  131. package/web/.next/server/chunks/ssr/[root-of-the-server]__c30f1f82._.js +1 -1
  132. package/web/.next/server/chunks/ssr/[root-of-the-server]__c30f1f82._.js.map +1 -1
  133. package/web/.next/server/chunks/ssr/[root-of-the-server]__ee0eaaf9._.js +1 -1
  134. package/web/.next/server/chunks/ssr/[root-of-the-server]__ee0eaaf9._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
  136. package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
  137. package/web/.next/server/chunks/ssr/_0dc06d07._.js.map +1 -1
  138. package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
  139. package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
  140. package/web/.next/server/chunks/ssr/{_c6670dc4._.js → _18a3b7f5._.js} +2 -2
  141. package/web/.next/server/chunks/ssr/{_c6670dc4._.js.map → _18a3b7f5._.js.map} +1 -1
  142. package/web/.next/server/chunks/ssr/_3a0b989f._.js +2 -2
  143. package/web/.next/server/chunks/ssr/_3a0b989f._.js.map +1 -1
  144. package/web/.next/server/chunks/ssr/_3c638d2f._.js +3 -0
  145. package/web/.next/server/chunks/ssr/{_fef309e0._.js.map → _3c638d2f._.js.map} +1 -1
  146. package/web/.next/server/chunks/ssr/{_17066a99._.js → _3f23f48f._.js} +2 -2
  147. package/web/.next/server/chunks/ssr/{_17066a99._.js.map → _3f23f48f._.js.map} +1 -1
  148. package/web/.next/server/chunks/ssr/_5119a3df._.js.map +1 -1
  149. package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
  150. package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
  151. package/web/.next/server/chunks/ssr/_5f69c13f._.js +1 -1
  152. package/web/.next/server/chunks/ssr/_5f69c13f._.js.map +1 -1
  153. package/web/.next/server/chunks/ssr/_7c5b97c6._.js +1 -1
  154. package/web/.next/server/chunks/ssr/_7c5b97c6._.js.map +1 -1
  155. package/web/.next/server/chunks/ssr/_82c57f10._.js +1 -1
  156. package/web/.next/server/chunks/ssr/_82c57f10._.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/_9495d50b._.js +1 -1
  158. package/web/.next/server/chunks/ssr/_9495d50b._.js.map +1 -1
  159. package/web/.next/server/chunks/ssr/_a0e3f7e4._.js +1 -1
  160. package/web/.next/server/chunks/ssr/_a0e3f7e4._.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/_ac4a3873._.js +1 -1
  162. package/web/.next/server/chunks/ssr/_ca0aa7f0._.js +1 -1
  163. package/web/.next/server/chunks/ssr/_ca0aa7f0._.js.map +1 -1
  164. package/web/.next/server/chunks/ssr/_cb5a021e._.js +1 -1
  165. package/web/.next/server/chunks/ssr/_cb5a021e._.js.map +1 -1
  166. package/web/.next/server/chunks/ssr/_d86175ae._.js +1 -1
  167. package/web/.next/server/chunks/ssr/_d86175ae._.js.map +1 -1
  168. package/web/.next/server/chunks/ssr/_d8bedf13._.js +1 -1
  169. package/web/.next/server/chunks/ssr/_d8bedf13._.js.map +1 -1
  170. package/web/.next/server/chunks/ssr/_fa7efce3._.js +2 -2
  171. package/web/.next/server/chunks/ssr/_fa7efce3._.js.map +1 -1
  172. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  173. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  175. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  176. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
  177. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
  178. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -1
  179. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  180. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  181. package/web/.next/server/pages/500.html +2 -2
  182. package/web/.next/server/server-reference-manifest.js +1 -1
  183. package/web/.next/server/server-reference-manifest.json +45 -45
  184. package/web/.next/static/chunks/{1bd2ba8a19d079aa.js → 076eaf8a817b5284.js} +1 -1
  185. package/web/.next/static/chunks/{303c0952da094261.js → 328e534d335ef687.js} +1 -1
  186. package/web/.next/static/chunks/3ee176daee98f78c.js +1 -0
  187. package/web/.next/static/chunks/{c6b20cc5ee4ef34d.js → 419f55272dedf3b3.js} +1 -1
  188. package/web/.next/static/chunks/{9a4178dc39dcd688.js → 496df1d4a9c9d83c.js} +3 -3
  189. package/web/.next/static/chunks/{477846404f442a7e.js → 6d60df4b3071af3b.js} +1 -1
  190. package/web/.next/static/chunks/{ef2562bc1dc46399.js → 9555d8a511c05bd5.js} +1 -1
  191. package/web/.next/static/chunks/{548c3788e8b0e92d.js → 990b5a6eb6b8dedb.js} +1 -1
  192. package/web/.next/static/chunks/{23b9eb93920d2ff9.js → b5155ee03ad70945.js} +1 -1
  193. package/web/.next/static/chunks/{2132c13f17d12462.js → c304db8f1d27505a.js} +2 -2
  194. package/web/.next/static/chunks/{a5782487c8a1ccbf.js → c7b37a688ea97611.js} +1 -1
  195. package/web/.next/static/chunks/{295fdc5e64c8733c.js → e523ab79dcc7f132.js} +1 -1
  196. package/web/.next/server/chunks/ssr/_fef309e0._.js +0 -3
  197. package/web/.next/static/chunks/e8987f3bc065cff8.js +0 -1
  198. /package/web/.next/static/{9dkRcoZpYzBI-UmJ3hw5- → kYE1v6B90r_hNugkL9Zh-}/_buildManifest.js +0 -0
  199. /package/web/.next/static/{9dkRcoZpYzBI-UmJ3hw5- → kYE1v6B90r_hNugkL9Zh-}/_clientMiddlewareManifest.json +0 -0
  200. /package/web/.next/static/{9dkRcoZpYzBI-UmJ3hw5- → kYE1v6B90r_hNugkL9Zh-}/_ssgManifest.js +0 -0
@@ -69,7 +69,8 @@ let SQLiteSettingsRepository = class SQLiteSettingsRepository {
69
69
  workflow_enable_evidence, workflow_commit_evidence,
70
70
  hide_ci_status, default_fast_mode,
71
71
  interactive_agent_enabled, interactive_agent_auto_timeout_minutes,
72
- interactive_agent_max_concurrent_sessions
72
+ interactive_agent_max_concurrent_sessions,
73
+ auto_archive_delay_minutes
73
74
  ) VALUES (
74
75
  @id, @created_at, @updated_at,
75
76
  @model_analyze, @model_requirements, @model_plan, @model_implement, @model_default,
@@ -97,7 +98,8 @@ let SQLiteSettingsRepository = class SQLiteSettingsRepository {
97
98
  @workflow_enable_evidence, @workflow_commit_evidence,
98
99
  @hide_ci_status, @default_fast_mode,
99
100
  @interactive_agent_enabled, @interactive_agent_auto_timeout_minutes,
100
- @interactive_agent_max_concurrent_sessions
101
+ @interactive_agent_max_concurrent_sessions,
102
+ @auto_archive_delay_minutes
101
103
  )
102
104
  `);
103
105
  // Execute with named parameters (safe from SQL injection)
@@ -199,7 +201,8 @@ let SQLiteSettingsRepository = class SQLiteSettingsRepository {
199
201
  default_fast_mode = @default_fast_mode,
200
202
  interactive_agent_enabled = @interactive_agent_enabled,
201
203
  interactive_agent_auto_timeout_minutes = @interactive_agent_auto_timeout_minutes,
202
- interactive_agent_max_concurrent_sessions = @interactive_agent_max_concurrent_sessions
204
+ interactive_agent_max_concurrent_sessions = @interactive_agent_max_concurrent_sessions,
205
+ auto_archive_delay_minutes = @auto_archive_delay_minutes
203
206
  WHERE id = @id
204
207
  `);
205
208
  // Execute with named parameters (safe from SQL injection)
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Auto-Archive Watcher Service
3
+ *
4
+ * Periodically polls for completed features (Maintain lifecycle) that have
5
+ * exceeded the configured auto-archive delay, and archives them automatically.
6
+ *
7
+ * Follows the same singleton + start/stop pattern as NotificationWatcherService.
8
+ *
9
+ * The poll interval is 60 seconds — auto-archiving is not time-critical and
10
+ * a minute-level granularity keeps DB load minimal.
11
+ */
12
+ import type { IFeatureRepository } from '../../../application/ports/output/repositories/feature-repository.interface.js';
13
+ export declare class AutoArchiveWatcherService {
14
+ private readonly featureRepo;
15
+ private readonly pollIntervalMs;
16
+ private intervalId;
17
+ constructor(featureRepo: IFeatureRepository, pollIntervalMs?: number);
18
+ isRunning(): boolean;
19
+ start(): void;
20
+ stop(): void;
21
+ private poll;
22
+ }
23
+ /**
24
+ * Initialize the auto-archive watcher singleton.
25
+ * Must be called once during web server startup.
26
+ *
27
+ * @throws Error if the watcher is already initialized
28
+ */
29
+ export declare function initializeAutoArchiveWatcher(featureRepo: IFeatureRepository, pollIntervalMs?: number): void;
30
+ /**
31
+ * Get the auto-archive watcher singleton.
32
+ *
33
+ * @returns The auto-archive watcher service
34
+ * @throws Error if the watcher hasn't been initialized yet
35
+ */
36
+ export declare function getAutoArchiveWatcher(): AutoArchiveWatcherService;
37
+ /**
38
+ * Check if the auto-archive watcher has been initialized.
39
+ */
40
+ export declare function hasAutoArchiveWatcher(): boolean;
41
+ /**
42
+ * Reset the auto-archive watcher singleton (for testing purposes only).
43
+ * Stops the watcher if running before resetting.
44
+ *
45
+ * @internal
46
+ */
47
+ export declare function resetAutoArchiveWatcher(): void;
48
+ //# sourceMappingURL=auto-archive-watcher.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-archive-watcher.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/auto-archive/auto-archive-watcher.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gFAAgF,CAAC;AAQzH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,UAAU,CAA+C;gBAErD,WAAW,EAAE,kBAAkB,EAAE,cAAc,GAAE,MAAiC;IAK9F,SAAS,IAAI,OAAO;IAIpB,KAAK,IAAI,IAAI;IAWb,IAAI,IAAI,IAAI;YAOE,IAAI;CAcnB;AAMD;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,kBAAkB,EAC/B,cAAc,CAAC,EAAE,MAAM,GACtB,IAAI,CAMN;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,yBAAyB,CAQjE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Auto-Archive Watcher Service
3
+ *
4
+ * Periodically polls for completed features (Maintain lifecycle) that have
5
+ * exceeded the configured auto-archive delay, and archives them automatically.
6
+ *
7
+ * Follows the same singleton + start/stop pattern as NotificationWatcherService.
8
+ *
9
+ * The poll interval is 60 seconds — auto-archiving is not time-critical and
10
+ * a minute-level granularity keeps DB load minimal.
11
+ */
12
+ import { AutoArchiveCompletedUseCase } from '../../../application/use-cases/features/auto-archive-completed.use-case.js';
13
+ import { ArchiveFeatureUseCase } from '../../../application/use-cases/features/archive-feature.use-case.js';
14
+ import { getSettings } from '../settings.service.js';
15
+ const DEFAULT_POLL_INTERVAL_MS = 60_000;
16
+ const DEFAULT_DELAY_MINUTES = 10;
17
+ export class AutoArchiveWatcherService {
18
+ featureRepo;
19
+ pollIntervalMs;
20
+ intervalId = null;
21
+ constructor(featureRepo, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS) {
22
+ this.featureRepo = featureRepo;
23
+ this.pollIntervalMs = pollIntervalMs;
24
+ }
25
+ isRunning() {
26
+ return this.intervalId !== null;
27
+ }
28
+ start() {
29
+ if (this.intervalId !== null)
30
+ return;
31
+ // Run first poll immediately
32
+ void this.poll();
33
+ this.intervalId = setInterval(() => {
34
+ void this.poll();
35
+ }, this.pollIntervalMs);
36
+ }
37
+ stop() {
38
+ if (this.intervalId !== null) {
39
+ clearInterval(this.intervalId);
40
+ this.intervalId = null;
41
+ }
42
+ }
43
+ async poll() {
44
+ try {
45
+ const settings = getSettings();
46
+ const delayMinutes = settings.workflow.autoArchiveDelayMinutes ?? DEFAULT_DELAY_MINUTES;
47
+ if (delayMinutes <= 0)
48
+ return;
49
+ const archiveFeature = new ArchiveFeatureUseCase(this.featureRepo);
50
+ const useCase = new AutoArchiveCompletedUseCase(this.featureRepo, archiveFeature);
51
+ await useCase.execute(delayMinutes);
52
+ }
53
+ catch {
54
+ // Settings not initialized or DB not ready — skip this poll cycle
55
+ }
56
+ }
57
+ }
58
+ // --- Singleton accessors (follows NotificationWatcher pattern) ---
59
+ let watcherInstance = null;
60
+ /**
61
+ * Initialize the auto-archive watcher singleton.
62
+ * Must be called once during web server startup.
63
+ *
64
+ * @throws Error if the watcher is already initialized
65
+ */
66
+ export function initializeAutoArchiveWatcher(featureRepo, pollIntervalMs) {
67
+ if (watcherInstance !== null) {
68
+ throw new Error('Auto-archive watcher already initialized. Cannot re-initialize.');
69
+ }
70
+ watcherInstance = new AutoArchiveWatcherService(featureRepo, pollIntervalMs);
71
+ }
72
+ /**
73
+ * Get the auto-archive watcher singleton.
74
+ *
75
+ * @returns The auto-archive watcher service
76
+ * @throws Error if the watcher hasn't been initialized yet
77
+ */
78
+ export function getAutoArchiveWatcher() {
79
+ if (watcherInstance === null) {
80
+ throw new Error('Auto-archive watcher not initialized. Call initializeAutoArchiveWatcher() during web server startup.');
81
+ }
82
+ return watcherInstance;
83
+ }
84
+ /**
85
+ * Check if the auto-archive watcher has been initialized.
86
+ */
87
+ export function hasAutoArchiveWatcher() {
88
+ return watcherInstance !== null;
89
+ }
90
+ /**
91
+ * Reset the auto-archive watcher singleton (for testing purposes only).
92
+ * Stops the watcher if running before resetting.
93
+ *
94
+ * @internal
95
+ */
96
+ export function resetAutoArchiveWatcher() {
97
+ if (watcherInstance !== null) {
98
+ watcherInstance.stop();
99
+ }
100
+ watcherInstance = null;
101
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"_serve.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/_serve.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAyB1D;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CA2D5C"}
1
+ {"version":3,"file":"_serve.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/_serve.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AA6B1D;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAgE5C"}
@@ -29,6 +29,7 @@ import { container } from '../../../../packages/core/src/infrastructure/di/conta
29
29
  import { setVersionEnvVars } from '../../../../packages/core/src/infrastructure/services/version.service.js';
30
30
  import { resolveWebDir } from '../../../../packages/core/src/infrastructure/services/web-server.service.js';
31
31
  import { initializeNotificationWatcher, getNotificationWatcher, } from '../../../../packages/core/src/infrastructure/services/notifications/notification-watcher.service.js';
32
+ import { initializeAutoArchiveWatcher, getAutoArchiveWatcher, } from '../../../../packages/core/src/infrastructure/services/auto-archive/auto-archive-watcher.service.js';
32
33
  import { getCliI18n } from '../i18n.js';
33
34
  function parsePort(value) {
34
35
  const port = parseInt(value, 10);
@@ -64,6 +65,9 @@ export function createServeCommand() {
64
65
  const notificationService = container.resolve('INotificationService');
65
66
  initializeNotificationWatcher(runRepo, phaseTimingRepo, featureRepo, notificationService);
66
67
  getNotificationWatcher().start();
68
+ // Start auto-archive watcher
69
+ initializeAutoArchiveWatcher(featureRepo);
70
+ getAutoArchiveWatcher().start();
67
71
  // Graceful shutdown handler — identical pattern to ui.command.ts
68
72
  let isShuttingDown = false;
69
73
  const shutdown = async () => {
@@ -74,6 +78,7 @@ export function createServeCommand() {
74
78
  const forceExit = setTimeout(() => process.exit(0), 5000);
75
79
  forceExit.unref();
76
80
  getNotificationWatcher().stop();
81
+ getAutoArchiveWatcher().stop();
77
82
  const deploymentService = container.resolve('IDeploymentService');
78
83
  deploymentService.stopAll();
79
84
  await service.stop();
@@ -1 +1 @@
1
- {"version":3,"file":"ui.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ui.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAkC1D;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CA+FzC"}
1
+ {"version":3,"file":"ui.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/ui.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAsC1D;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAoGzC"}
@@ -21,6 +21,7 @@ import { setVersionEnvVars } from '../../../../packages/core/src/infrastructure/
21
21
  import { resolveWebDir } from '../../../../packages/core/src/infrastructure/services/web-server.service.js';
22
22
  import { initializeNotificationWatcher, getNotificationWatcher, } from '../../../../packages/core/src/infrastructure/services/notifications/notification-watcher.service.js';
23
23
  import { initializePrSyncWatcher, getPrSyncWatcher, } from '../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js';
24
+ import { initializeAutoArchiveWatcher, getAutoArchiveWatcher, } from '../../../../packages/core/src/infrastructure/services/auto-archive/auto-archive-watcher.service.js';
24
25
  import { getExistingConnection } from '../../../../packages/core/src/infrastructure/persistence/sqlite/connection.js';
25
26
  import { BrowserOpenerService } from '../../../../packages/core/src/infrastructure/services/browser-opener.service.js';
26
27
  import { colors, fmt, messages } from '../ui/index.js';
@@ -73,6 +74,9 @@ Examples:
73
74
  const db = getExistingConnection();
74
75
  initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db, gitForkService);
75
76
  getPrSyncWatcher().start();
77
+ // Start auto-archive watcher for completed features
78
+ initializeAutoArchiveWatcher(featureRepo);
79
+ getAutoArchiveWatcher().start();
76
80
  const url = `http://localhost:${port}`;
77
81
  messages.success(t('cli:commands.ui.serverReady', { url: fmt.code(url) }));
78
82
  messages.info(t('cli:commands.ui.pressCtrlC'));
@@ -96,6 +100,7 @@ Examples:
96
100
  forceExit.unref();
97
101
  getPrSyncWatcher().stop();
98
102
  getNotificationWatcher().stop();
103
+ getAutoArchiveWatcher().stop();
99
104
  await service.stop();
100
105
  process.exit(0);
101
106
  };
@@ -1 +1 @@
1
- {"version":3,"file":"get-graph-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/(dashboard)/get-graph-data.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAiFD,MAAM,MAAM,aAAa,GACrB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC;AA6B7B,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CAmExF"}
1
+ {"version":3,"file":"get-graph-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/(dashboard)/get-graph-data.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAI1C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAiFD,MAAM,MAAM,aAAa,GACrB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC;AA6B7B,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CA+ExF"}
@@ -121,6 +121,16 @@ export async function getGraphData() {
121
121
  }
122
122
  // PR/CI status is kept fresh by PrSyncWatcher (30s background poll).
123
123
  // No live GitHub calls here — use cached DB values for fast response.
124
+ // Fire-and-forget: resolve features whose branches have been merged.
125
+ // This corrects stale "action needed" states without blocking page load.
126
+ // Resolved features surface on the next SSE poll cycle (~500ms).
127
+ try {
128
+ const autoResolve = resolve('AutoResolveMergedBranchesUseCase');
129
+ void autoResolve.execute(features);
130
+ }
131
+ catch {
132
+ // Use case not registered — skip silently (e.g. test environments)
133
+ }
124
134
  const featuresWithRuns = await Promise.all(features.map(async (feature) => {
125
135
  const run = feature.agentRunId ? await agentRunRepo.findById(feature.agentRunId) : null;
126
136
  return { feature, run };
@@ -1 +1 @@
1
- {"version":3,"file":"settings-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.tsx"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EACV,QAAQ,EAIT,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AA6B/E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC1C;AA+QD,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,kBAAkB,GACnB,EAAE,uBAAuB,2CA8xCzB"}
1
+ {"version":3,"file":"settings-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.tsx"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EACV,QAAQ,EAIT,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AA6B/E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC1C;AA+QD,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,kBAAkB,GACnB,EAAE,uBAAuB,2CAm1CzB"}
@@ -158,6 +158,9 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
158
158
  const [ciWatchEnabled, setCiWatchEnabled] = useState(settings.workflow.ciWatchEnabled !== false);
159
159
  const [hideCiStatus, setHideCiStatus] = useState(settings.workflow.hideCiStatus !== false);
160
160
  const [defaultFastMode, setDefaultFastMode] = useState(settings.workflow.defaultFastMode !== false);
161
+ // Auto-archive state
162
+ const [autoArchiveEnabled, setAutoArchiveEnabled] = useState((settings.workflow.autoArchiveDelayMinutes ?? 10) > 0);
163
+ const [autoArchiveDelay, setAutoArchiveDelay] = useState(String(settings.workflow.autoArchiveDelayMinutes ?? 10));
161
164
  const [ciMaxFix, setCiMaxFix] = useState(settings.workflow.ciMaxFixAttempts != null ? String(settings.workflow.ciMaxFixAttempts) : '');
162
165
  const [ciTimeout, setCiTimeout] = useState(settings.workflow.ciWatchTimeoutMs != null
163
166
  ? String(Math.round(settings.workflow.ciWatchTimeoutMs / 1000))
@@ -237,6 +240,8 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
237
240
  // Workflow helpers
238
241
  function buildWorkflowPayload(overrides = {}) {
239
242
  const timeoutSeconds = parseOptionalInt(overrides.ciTimeout ?? ciTimeout);
243
+ const archiveEnabled = overrides.autoArchiveEnabled ?? autoArchiveEnabled;
244
+ const archiveDelay = parseInt(overrides.autoArchiveDelay ?? autoArchiveDelay, 10);
240
245
  return {
241
246
  workflow: {
242
247
  openPrOnImplementationComplete: overrides.openPr ?? openPr,
@@ -251,6 +256,11 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
251
256
  ciWatchEnabled: overrides.ciWatchEnabled ?? ciWatchEnabled,
252
257
  hideCiStatus: overrides.hideCiStatus ?? hideCiStatus,
253
258
  defaultFastMode: overrides.defaultFastMode ?? defaultFastMode,
259
+ autoArchiveDelayMinutes: archiveEnabled
260
+ ? Number.isNaN(archiveDelay) || archiveDelay < 1
261
+ ? 10
262
+ : archiveDelay
263
+ : 0,
254
264
  ciMaxFixAttempts: parseOptionalInt(overrides.ciMaxFix ?? ciMaxFix),
255
265
  ciWatchTimeoutMs: timeoutSeconds != null ? timeoutSeconds * 1000 : undefined,
256
266
  ciLogMaxChars: parseOptionalInt(overrides.ciLogMax ?? ciLogMax),
@@ -399,7 +409,19 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
399
409
  } }), _jsx(SwitchRow, { label: t('settings.workflow.watchCiAfterPush'), description: t('settings.workflow.watchCiAfterPushDescription'), id: "ci-watch-enabled", testId: "switch-ci-watch-enabled", checked: ciWatchEnabled, onChange: (v) => {
400
410
  setCiWatchEnabled(v);
401
411
  save(buildWorkflowPayload({ ciWatchEnabled: v }));
402
- } })] }), _jsx(SectionHint, { links: [
412
+ } }), _jsx(SubsectionLabel, { children: "Archive" }), _jsx(SwitchRow, { label: "Auto-archive completed", description: "Automatically archive features after they reach the completed state", id: "auto-archive-enabled", testId: "switch-auto-archive-enabled", checked: autoArchiveEnabled, onChange: (v) => {
413
+ setAutoArchiveEnabled(v);
414
+ save(buildWorkflowPayload({ autoArchiveEnabled: v }));
415
+ } }), _jsx(SettingsRow, { label: "Archive delay", description: "Minutes to wait after completion before archiving (1\u20131440)", htmlFor: "auto-archive-delay", children: _jsx(NumberStepper, { id: "auto-archive-delay", testId: "input-auto-archive-delay", value: autoArchiveDelay, placeholder: "10", min: 1, max: 1440, suffix: "min", onChange: (v) => {
416
+ setAutoArchiveDelay(v);
417
+ }, onBlur: () => {
418
+ if (!autoArchiveEnabled)
419
+ return;
420
+ const n = parseInt(autoArchiveDelay, 10);
421
+ const clamped = Number.isNaN(n) ? 10 : Math.min(1440, Math.max(1, n));
422
+ setAutoArchiveDelay(String(clamped));
423
+ save(buildWorkflowPayload({ autoArchiveDelay: String(clamped) }));
424
+ } }) })] }), _jsx(SectionHint, { links: [
403
425
  {
404
426
  label: t('settings.workflow.links.approvalGates'),
405
427
  href: 'https://github.com/shep-ai/shep/blob/main/specs/016-hitl-approval-gates/spec.yaml',
@@ -20,6 +20,7 @@ import { initializeSettings } from '../../../packages/core/src/infrastructure/se
20
20
  import { initializeNotificationWatcher, getNotificationWatcher, } from '../../../packages/core/src/infrastructure/services/notifications/notification-watcher.service.js';
21
21
  import { initializePrSyncWatcher, getPrSyncWatcher, } from '../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js';
22
22
  import { getExistingConnection } from '../../../packages/core/src/infrastructure/persistence/sqlite/connection.js';
23
+ import { initializeAutoArchiveWatcher, getAutoArchiveWatcher, } from '../../../packages/core/src/infrastructure/services/auto-archive/auto-archive-watcher.service.js';
23
24
  const DEFAULT_PORT = 3000;
24
25
  async function isPortAvailable(port) {
25
26
  return new Promise((resolve) => {
@@ -69,6 +70,9 @@ async function main() {
69
70
  const db = getExistingConnection();
70
71
  initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db, gitForkService);
71
72
  getPrSyncWatcher().start();
73
+ // Start auto-archive watcher for completed features
74
+ initializeAutoArchiveWatcher(featureRepo);
75
+ getAutoArchiveWatcher().start();
72
76
  }
73
77
  catch (error) {
74
78
  console.warn('[dev-server] DI initialization failed — features will be empty:', error);
@@ -127,6 +131,12 @@ async function main() {
127
131
  catch {
128
132
  /* not initialized */
129
133
  }
134
+ try {
135
+ getAutoArchiveWatcher().stop();
136
+ }
137
+ catch {
138
+ /* not initialized */
139
+ }
130
140
  server.closeAllConnections();
131
141
  await Promise.all([
132
142
  new Promise((resolve) => server.close(() => resolve())),