@shepai/cli 1.142.0 → 1.142.1-pr454.60f0445
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.
- package/apis/json-schema/Feature.yaml +10 -0
- package/apis/json-schema/PullRequest.yaml +11 -0
- package/apis/json-schema/SdlcLifecycle.yaml +1 -0
- package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts +2 -0
- package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/git-fork-service.interface.d.ts +33 -0
- package/dist/packages/core/src/application/ports/output/services/git-fork-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/git-fork-service.interface.js +24 -0
- package/dist/packages/core/src/application/use-cases/features/adopt-branch.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/adopt-branch.use-case.js +2 -0
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +16 -1
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +2 -0
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/poll-upstream-pr.use-case.d.ts +29 -0
- package/dist/packages/core/src/application/use-cases/features/poll-upstream-pr.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/features/poll-upstream-pr.use-case.js +105 -0
- package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.js +2 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +22 -1
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/domain/generated/output.js +1 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +2 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.js +4 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-fields.d.ts +11 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-fields.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-fields.js +28 -0
- package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +6 -2
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts +10 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +34 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +6 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +12 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +89 -49
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.js +8 -0
- package/dist/packages/core/src/infrastructure/services/git/git-fork.service.d.ts +29 -0
- package/dist/packages/core/src/infrastructure/services/git/git-fork.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/git/git-fork.service.js +204 -0
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts +13 -3
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js +39 -10
- package/dist/src/presentation/cli/commands/ui.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/ui.command.js +3 -1
- package/dist/src/presentation/web/app/actions/create-feature.d.ts +2 -0
- package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/create-feature.js +5 -1
- package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/agent-events/route.js +1 -0
- package/dist/src/presentation/web/app/api/sessions/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/sessions/route.js +45 -13
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts +2 -0
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +22 -5
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +18 -0
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.js +52 -0
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +1 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.js +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +7 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +29 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-sessions-dropdown.d.ts +3 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-sessions-dropdown.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-sessions-dropdown.js +13 -5
- package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/repository-node.js +1 -1
- package/dist/src/presentation/web/dev-server.js +3 -1
- package/dist/src/presentation/web/next.config.d.ts.map +1 -1
- package/dist/src/presentation/web/next.config.js +4 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +6 -4
- package/web/.next/required-server-files.json +6 -4
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/create/page.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/page.js +1 -1
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/sessions/route.js +3 -2
- package/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/skills/page.js +1 -1
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/tools/page.js +1 -1
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_ff60e4a5.js +3 -0
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_ff60e4a5.js.map +1 -0
- package/web/.next/server/chunks/[externals]__448264a3._.js +3 -0
- package/web/.next/server/chunks/[externals]__448264a3._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0b150ddf._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0b150ddf._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__a5f9c6e5._.js → [root-of-the-server]__2138fa7e._.js} +3 -3
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__a5f9c6e5._.js.map → [root-of-the-server]__2138fa7e._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_0c5f56e3._.js +2 -2
- package/web/.next/server/chunks/ssr/_0c5f56e3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_1b719e7f._.js +1 -1
- package/web/.next/server/chunks/ssr/_1b719e7f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_37e8548b._.js +1 -1
- package/web/.next/server/chunks/ssr/_37e8548b._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_55d763e2._.js +1 -1
- package/web/.next/server/chunks/ssr/_55d763e2._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_6256a985._.js +1 -1
- package/web/.next/server/chunks/ssr/_6256a985._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_64bdfc6f._.js +2 -2
- package/web/.next/server/chunks/ssr/_64bdfc6f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_67104d9e._.js +1 -1
- package/web/.next/server/chunks/ssr/_7dca1882._.js +1 -1
- package/web/.next/server/chunks/ssr/_7dca1882._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_7e5c4d9c._.js → _a8a2233a._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_7e5c4d9c._.js.map → _a8a2233a._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_a9f57758._.js +1 -1
- package/web/.next/server/chunks/ssr/_b71645b4._.js +1 -1
- package/web/.next/server/chunks/ssr/_b71645b4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_cfbd1d7e._.js +1 -1
- package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
- package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_f39a1adb._.js +1 -1
- package/web/.next/server/chunks/ssr/_f39a1adb._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_1c6fbecf._.js → _f4d19ff3._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_1c6fbecf._.js.map → _f4d19ff3._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_7bda2f00._.js → src_presentation_web_d50bc654._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_7bda2f00._.js.map → src_presentation_web_d50bc654._.js.map} +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +44 -44
- package/web/.next/static/chunks/{4d7e25ef4b8e2f62.js → 00fd65dc10f3da0a.js} +1 -1
- package/web/.next/static/chunks/{ea9969f79b2162ec.js → 024575217799dac8.js} +1 -1
- package/web/.next/static/chunks/101d4334f60ec83f.js +1 -0
- package/web/.next/static/chunks/{73889aad2b3356b1.js → 4c543e4daf8755a3.js} +2 -2
- package/web/.next/static/chunks/{e599050b1f6466fe.js → 72e48a32d1f244b9.js} +1 -1
- package/web/.next/static/chunks/{13978ecd00a81172.js → 8a42aa668b401526.js} +1 -1
- package/web/.next/static/chunks/94bb64cb067c785e.js +1 -0
- package/web/.next/static/chunks/{74eef53714ab461d.js → 9e93ecdd1b445607.js} +1 -1
- package/web/.next/static/chunks/a230d5954cc322fd.js +1 -0
- package/web/.next/static/chunks/{2eec9756f5220e22.js → a4c2c8c731b0875f.js} +1 -1
- package/web/.next/static/chunks/{21ddf1d59c98adf0.js → d5bb1d4f97abcdd7.js} +1 -1
- package/web/.next/static/chunks/{4adda8dd11458a46.js → d7425a1e8e823fb1.js} +2 -2
- package/web/.next/server/chunks/[root-of-the-server]__a62bd945._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__a62bd945._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6ec59045._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6ec59045._.js.map +0 -1
- package/web/.next/static/chunks/3f18dfdd07d48ecd.js +0 -1
- package/web/.next/static/chunks/6ad8d8682f4836c9.js +0 -1
- package/web/.next/static/chunks/a6a6a8387bae31f0.js +0 -1
- /package/web/.next/static/{G2BdtwIuunZEcXQ0FjJJF → zv3n0xrL5vsVhyfYT8O1w}/_buildManifest.js +0 -0
- /package/web/.next/static/{G2BdtwIuunZEcXQ0FjJJF → zv3n0xrL5vsVhyfYT8O1w}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{G2BdtwIuunZEcXQ0FjJJF → zv3n0xrL5vsVhyfYT8O1w}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Fork Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Manages GitHub fork operations: forking repos, pushing to forks,
|
|
5
|
+
* and creating/querying upstream PRs.
|
|
6
|
+
* Uses constructor dependency injection for the command executor.
|
|
7
|
+
*/
|
|
8
|
+
import type { IGitForkService, UpstreamPrStatus } from '../../../application/ports/output/services/git-fork-service.interface.js';
|
|
9
|
+
import type { ExecFunction } from './worktree.service.js';
|
|
10
|
+
export declare class GitForkService implements IGitForkService {
|
|
11
|
+
private readonly execFile;
|
|
12
|
+
constructor(execFile: ExecFunction);
|
|
13
|
+
forkRepository(cwd: string): Promise<void>;
|
|
14
|
+
/** Ensure that an `upstream` remote exists pointing to `nameWithOwner`. */
|
|
15
|
+
private _ensureUpstreamRemote;
|
|
16
|
+
pushToFork(cwd: string, branch: string): Promise<void>;
|
|
17
|
+
createUpstreamPr(cwd: string, title: string, body: string, head: string, base: string): Promise<{
|
|
18
|
+
url: string;
|
|
19
|
+
number: number;
|
|
20
|
+
}>;
|
|
21
|
+
getUpstreamPrStatus(upstreamRepo: string, prNumber: number): Promise<UpstreamPrStatus>;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the upstream repo as "owner/repo".
|
|
24
|
+
* 1. Try `git remote get-url upstream` and parse it.
|
|
25
|
+
* 2. Fall back to `gh repo view --json parent`.
|
|
26
|
+
*/
|
|
27
|
+
private _getUpstreamRepo;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=git-fork.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-fork.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/git-fork.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EACjB,MAAM,0EAA0E,CAAC;AAKlF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AA2C1D,qBACa,cAAe,YAAW,eAAe;IAChB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAMrE,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2ChD,2EAA2E;YAC7D,qBAAqB;IAmB7B,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBtD,gBAAgB,CACpB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IA6CrC,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAyC5F;;;;OAIG;YACW,gBAAgB;CAiB/B"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Fork Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Manages GitHub fork operations: forking repos, pushing to forks,
|
|
5
|
+
* and creating/querying upstream PRs.
|
|
6
|
+
* Uses constructor dependency injection for the command executor.
|
|
7
|
+
*/
|
|
8
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
9
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
10
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
11
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
12
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
13
|
+
};
|
|
14
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
15
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
16
|
+
};
|
|
17
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
18
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
19
|
+
};
|
|
20
|
+
import { injectable, inject } from 'tsyringe';
|
|
21
|
+
import { GitForkError, GitForkErrorCode, } from '../../../application/ports/output/services/git-fork-service.interface.js';
|
|
22
|
+
/** Keywords indicating an authentication failure in error messages. */
|
|
23
|
+
const AUTH_KEYWORDS = ['auth', 'credential', 'forbidden', '401', '403'];
|
|
24
|
+
/** Returns true when the error message suggests an authentication problem. */
|
|
25
|
+
function isAuthError(err) {
|
|
26
|
+
const msg = err instanceof Error ? err.message.toLowerCase() : String(err).toLowerCase();
|
|
27
|
+
return AUTH_KEYWORDS.some((kw) => msg.includes(kw));
|
|
28
|
+
}
|
|
29
|
+
/** Parse owner/repo from a GitHub URL or nameWithOwner string. */
|
|
30
|
+
function parseOwnerRepo(raw) {
|
|
31
|
+
// Handle https://github.com/owner/repo[.git]
|
|
32
|
+
const httpsMatch = raw.match(/github\.com[/:]([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
33
|
+
if (httpsMatch)
|
|
34
|
+
return httpsMatch[1];
|
|
35
|
+
// Handle git@github.com:owner/repo[.git]
|
|
36
|
+
const sshMatch = raw.match(/git@github\.com:([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
37
|
+
if (sshMatch)
|
|
38
|
+
return sshMatch[1];
|
|
39
|
+
// Assume it's already "owner/repo"
|
|
40
|
+
return raw.replace(/\.git$/, '');
|
|
41
|
+
}
|
|
42
|
+
/** Extract the PR number from a GitHub PR URL. */
|
|
43
|
+
function extractPrNumber(url) {
|
|
44
|
+
const match = url.match(/\/pull\/(\d+)/);
|
|
45
|
+
if (!match)
|
|
46
|
+
throw new Error(`Cannot parse PR number from URL: ${url}`);
|
|
47
|
+
return parseInt(match[1], 10);
|
|
48
|
+
}
|
|
49
|
+
/** Normalise GitHub GraphQL state strings (OPEN/MERGED/CLOSED) to lowercase union. */
|
|
50
|
+
function normaliseState(state) {
|
|
51
|
+
switch (state.toUpperCase()) {
|
|
52
|
+
case 'OPEN':
|
|
53
|
+
return 'open';
|
|
54
|
+
case 'MERGED':
|
|
55
|
+
return 'merged';
|
|
56
|
+
case 'CLOSED':
|
|
57
|
+
default:
|
|
58
|
+
return 'closed';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
let GitForkService = class GitForkService {
|
|
62
|
+
execFile;
|
|
63
|
+
constructor(execFile) {
|
|
64
|
+
this.execFile = execFile;
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// forkRepository
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
async forkRepository(cwd) {
|
|
70
|
+
// Check if the current origin is already a fork.
|
|
71
|
+
const viewResult = await this.execFile('gh', ['repo', 'view', '--json', 'isFork,parent'], {
|
|
72
|
+
cwd,
|
|
73
|
+
});
|
|
74
|
+
const repoInfo = JSON.parse(viewResult.stdout);
|
|
75
|
+
if (repoInfo.isFork && repoInfo.parent) {
|
|
76
|
+
// Origin is already a fork — just make sure `upstream` remote points to the parent.
|
|
77
|
+
await this._ensureUpstreamRemote(cwd, repoInfo.parent.nameWithOwner);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Not yet a fork — create one and remap remotes.
|
|
81
|
+
try {
|
|
82
|
+
const { stderr } = await this.execFile('gh', ['repo', 'fork', '--remote', '--remote-name', 'origin'], { cwd });
|
|
83
|
+
// gh exits 0 even for "already exists" — treat it as success.
|
|
84
|
+
if (stderr?.toLowerCase().includes('already exists')) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
if (isAuthError(err)) {
|
|
90
|
+
throw new GitForkError(`Authentication failed while forking repository: ${err.message}`, GitForkErrorCode.AUTH_FAILURE, err instanceof Error ? err : undefined);
|
|
91
|
+
}
|
|
92
|
+
throw new GitForkError(`Failed to fork repository: ${err.message}`, GitForkErrorCode.FORK_FAILED, err instanceof Error ? err : undefined);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Ensure that an `upstream` remote exists pointing to `nameWithOwner`. */
|
|
96
|
+
async _ensureUpstreamRemote(cwd, nameWithOwner) {
|
|
97
|
+
const { stdout } = await this.execFile('git', ['remote'], { cwd });
|
|
98
|
+
const remotes = stdout
|
|
99
|
+
.split('\n')
|
|
100
|
+
.map((r) => r.trim())
|
|
101
|
+
.filter(Boolean);
|
|
102
|
+
if (!remotes.includes('upstream')) {
|
|
103
|
+
await this.execFile('git', ['remote', 'add', 'upstream', `https://github.com/${nameWithOwner}.git`], { cwd });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// pushToFork
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
async pushToFork(cwd, branch) {
|
|
110
|
+
try {
|
|
111
|
+
await this.execFile('git', ['push', '-u', 'origin', branch], { cwd });
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
if (isAuthError(err)) {
|
|
115
|
+
throw new GitForkError(`Authentication failed while pushing to fork: ${err.message}`, GitForkErrorCode.AUTH_FAILURE, err instanceof Error ? err : undefined);
|
|
116
|
+
}
|
|
117
|
+
throw new GitForkError(`Failed to push branch "${branch}" to fork: ${err.message}`, GitForkErrorCode.PUSH_FAILED, err instanceof Error ? err : undefined);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// createUpstreamPr
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
async createUpstreamPr(cwd, title, body, head, base) {
|
|
124
|
+
const upstreamRepo = await this._getUpstreamRepo(cwd);
|
|
125
|
+
try {
|
|
126
|
+
const { stdout } = await this.execFile('gh', [
|
|
127
|
+
'pr',
|
|
128
|
+
'create',
|
|
129
|
+
'--repo',
|
|
130
|
+
upstreamRepo,
|
|
131
|
+
'--title',
|
|
132
|
+
title,
|
|
133
|
+
'--body',
|
|
134
|
+
body,
|
|
135
|
+
'--head',
|
|
136
|
+
head,
|
|
137
|
+
'--base',
|
|
138
|
+
base,
|
|
139
|
+
], { cwd });
|
|
140
|
+
const url = stdout.trim();
|
|
141
|
+
const number = extractPrNumber(url);
|
|
142
|
+
return { url, number };
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (isAuthError(err)) {
|
|
146
|
+
throw new GitForkError(`Authentication failed while creating upstream PR: ${err.message}`, GitForkErrorCode.AUTH_FAILURE, err instanceof Error ? err : undefined);
|
|
147
|
+
}
|
|
148
|
+
throw new GitForkError(`Failed to create upstream PR: ${err.message}`, GitForkErrorCode.UPSTREAM_PR_FAILED, err instanceof Error ? err : undefined);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
// getUpstreamPrStatus
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
async getUpstreamPrStatus(upstreamRepo, prNumber) {
|
|
155
|
+
try {
|
|
156
|
+
const { stdout } = await this.execFile('gh', ['pr', 'view', String(prNumber), '--repo', upstreamRepo, '--json', 'state,url,number'], {});
|
|
157
|
+
const data = JSON.parse(stdout);
|
|
158
|
+
return {
|
|
159
|
+
state: normaliseState(data.state),
|
|
160
|
+
url: data.url,
|
|
161
|
+
number: data.number,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
const msg = err instanceof Error ? err.message.toLowerCase() : String(err).toLowerCase();
|
|
166
|
+
if (isAuthError(err)) {
|
|
167
|
+
throw new GitForkError(`Authentication failed while fetching upstream PR status: ${err.message}`, GitForkErrorCode.AUTH_FAILURE, err instanceof Error ? err : undefined);
|
|
168
|
+
}
|
|
169
|
+
if (msg.includes('not found') || msg.includes('no pull requests found')) {
|
|
170
|
+
throw new GitForkError(`Upstream PR #${prNumber} not found in ${upstreamRepo}`, GitForkErrorCode.UPSTREAM_PR_NOT_FOUND, err instanceof Error ? err : undefined);
|
|
171
|
+
}
|
|
172
|
+
throw new GitForkError(`Failed to fetch upstream PR status: ${err.message}`, GitForkErrorCode.UPSTREAM_PR_NOT_FOUND, err instanceof Error ? err : undefined);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Private helpers
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
/**
|
|
179
|
+
* Resolve the upstream repo as "owner/repo".
|
|
180
|
+
* 1. Try `git remote get-url upstream` and parse it.
|
|
181
|
+
* 2. Fall back to `gh repo view --json parent`.
|
|
182
|
+
*/
|
|
183
|
+
async _getUpstreamRepo(cwd) {
|
|
184
|
+
try {
|
|
185
|
+
const { stdout } = await this.execFile('git', ['remote', 'get-url', 'upstream'], { cwd });
|
|
186
|
+
return parseOwnerRepo(stdout.trim());
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// No upstream remote — try to infer from gh repo view parent.
|
|
190
|
+
const { stdout } = await this.execFile('gh', ['repo', 'view', '--json', 'parent'], { cwd });
|
|
191
|
+
const data = JSON.parse(stdout);
|
|
192
|
+
if (data.parent?.nameWithOwner) {
|
|
193
|
+
return data.parent.nameWithOwner;
|
|
194
|
+
}
|
|
195
|
+
throw new GitForkError('Cannot determine upstream repository. No upstream remote configured and repo has no parent.', GitForkErrorCode.UPSTREAM_PR_FAILED);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
GitForkService = __decorate([
|
|
200
|
+
injectable(),
|
|
201
|
+
__param(0, inject('ExecFunction')),
|
|
202
|
+
__metadata("design:paramtypes", [Function])
|
|
203
|
+
], GitForkService);
|
|
204
|
+
export { GitForkService };
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Polls GitHub PR status and CI status for features in the Review lifecycle
|
|
5
5
|
* stage, updating feature records and emitting notifications when transitions
|
|
6
|
-
* are detected.
|
|
6
|
+
* are detected. Also polls features in the AwaitingUpstream lifecycle stage,
|
|
7
|
+
* delegating to PollUpstreamPrUseCase to check upstream fork PR status.
|
|
8
|
+
* Follows the NotificationWatcherService polling pattern.
|
|
7
9
|
*
|
|
8
10
|
* Maintains in-memory tracking of last-known PR and CI status per feature
|
|
9
11
|
* to avoid duplicate updates and notifications. Features are grouped by
|
|
@@ -13,12 +15,18 @@ import type { IFeatureRepository } from '../../../application/ports/output/repos
|
|
|
13
15
|
import type { IAgentRunRepository } from '../../../application/ports/output/agents/agent-run-repository.interface.js';
|
|
14
16
|
import type { IGitPrService } from '../../../application/ports/output/services/git-pr-service.interface.js';
|
|
15
17
|
import type { INotificationService } from '../../../application/ports/output/services/notification-service.interface.js';
|
|
18
|
+
import type { PollUpstreamPrInput, PollUpstreamPrOutput } from '../../../application/use-cases/features/poll-upstream-pr.use-case.js';
|
|
16
19
|
import type Database from 'better-sqlite3';
|
|
20
|
+
/** Minimal interface satisfied by PollUpstreamPrUseCase */
|
|
21
|
+
interface IPollUpstreamPrUseCase {
|
|
22
|
+
execute(input: PollUpstreamPrInput): Promise<PollUpstreamPrOutput>;
|
|
23
|
+
}
|
|
17
24
|
export declare class PrSyncWatcherService {
|
|
18
25
|
private readonly featureRepo;
|
|
19
26
|
private readonly agentRunRepo;
|
|
20
27
|
private readonly gitPrService;
|
|
21
28
|
private readonly notificationService;
|
|
29
|
+
private readonly pollUpstreamPrUseCase;
|
|
22
30
|
private readonly pollIntervalMs;
|
|
23
31
|
private readonly trackedFeatures;
|
|
24
32
|
private readonly skippedRepos;
|
|
@@ -27,7 +35,7 @@ export declare class PrSyncWatcherService {
|
|
|
27
35
|
private readonly processId;
|
|
28
36
|
private intervalId;
|
|
29
37
|
private pollCycle;
|
|
30
|
-
constructor(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null);
|
|
38
|
+
constructor(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null, pollUpstreamPrUseCase?: IPollUpstreamPrUseCase | null);
|
|
31
39
|
isRunning(): boolean;
|
|
32
40
|
start(): void;
|
|
33
41
|
stop(): void;
|
|
@@ -38,6 +46,7 @@ export declare class PrSyncWatcherService {
|
|
|
38
46
|
private poll;
|
|
39
47
|
private isRateLimited;
|
|
40
48
|
private handleRateLimitError;
|
|
49
|
+
private processAwaitingUpstreamFeature;
|
|
41
50
|
private processRepository;
|
|
42
51
|
private processFeature;
|
|
43
52
|
/** Mark associated agent run as completed so the UI reflects "done" state. */
|
|
@@ -50,7 +59,7 @@ export declare class PrSyncWatcherService {
|
|
|
50
59
|
*
|
|
51
60
|
* @throws Error if the watcher is already initialized
|
|
52
61
|
*/
|
|
53
|
-
export declare function initializePrSyncWatcher(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null): void;
|
|
62
|
+
export declare function initializePrSyncWatcher(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null, pollUpstreamPrUseCase?: IPollUpstreamPrUseCase | null): void;
|
|
54
63
|
/**
|
|
55
64
|
* Get the PR sync watcher singleton.
|
|
56
65
|
*
|
|
@@ -69,4 +78,5 @@ export declare function hasPrSyncWatcher(): boolean;
|
|
|
69
78
|
* @internal
|
|
70
79
|
*/
|
|
71
80
|
export declare function resetPrSyncWatcher(): void;
|
|
81
|
+
export {};
|
|
72
82
|
//# sourceMappingURL=pr-sync-watcher.service.d.ts.map
|
package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-sync-watcher.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pr-sync-watcher.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAWH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gFAAgF,CAAC;AACzH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4EAA4E,CAAC;AACtH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wEAAwE,CAAC;AAK5G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8EAA8E,CAAC;AACzH,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,sEAAsE,CAAC;AAC9E,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,2DAA2D;AAC3D,UAAU,sBAAsB;IAC9B,OAAO,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACpE;AAqBD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAuB;IAC3D,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAgC;IACtE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;IACrE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;IAC9D,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA2B;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,SAAS,CAAK;gBAGpB,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,mBAAmB,EACjC,YAAY,EAAE,aAAa,EAC3B,mBAAmB,EAAE,oBAAoB,EACzC,cAAc,GAAE,MAAiC,EACjD,EAAE,GAAE,QAAQ,CAAC,QAAQ,GAAG,IAAW,EACnC,qBAAqB,GAAE,sBAAsB,GAAG,IAAW;IAY7D,SAAS,IAAI,OAAO;IAIpB,KAAK,IAAI,IAAI;IAcb,IAAI,IAAI,IAAI;IASZ,gFAAgF;IAChF,OAAO,CAAC,cAAc;IAiBtB,0FAA0F;IAC1F,OAAO,CAAC,iBAAiB;YAUX,IAAI;IAyDlB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,oBAAoB;YAYd,8BAA8B;YAgB9B,iBAAiB;YA+CjB,cAAc;IAkM5B,8EAA8E;YAChE,gBAAgB;IAW9B,OAAO,CAAC,gBAAgB;CAoBzB;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,mBAAmB,EACjC,YAAY,EAAE,aAAa,EAC3B,mBAAmB,EAAE,oBAAoB,EACzC,cAAc,CAAC,EAAE,MAAM,EACvB,EAAE,CAAC,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,EAC7B,qBAAqB,CAAC,EAAE,sBAAsB,GAAG,IAAI,GACpD,IAAI,CAcN;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,oBAAoB,CAQvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAKzC"}
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Polls GitHub PR status and CI status for features in the Review lifecycle
|
|
5
5
|
* stage, updating feature records and emitting notifications when transitions
|
|
6
|
-
* are detected.
|
|
6
|
+
* are detected. Also polls features in the AwaitingUpstream lifecycle stage,
|
|
7
|
+
* delegating to PollUpstreamPrUseCase to check upstream fork PR status.
|
|
8
|
+
* Follows the NotificationWatcherService polling pattern.
|
|
7
9
|
*
|
|
8
10
|
* Maintains in-memory tracking of last-known PR and CI status per feature
|
|
9
11
|
* to avoid duplicate updates and notifications. Features are grouped by
|
|
@@ -24,6 +26,7 @@ export class PrSyncWatcherService {
|
|
|
24
26
|
agentRunRepo;
|
|
25
27
|
gitPrService;
|
|
26
28
|
notificationService;
|
|
29
|
+
pollUpstreamPrUseCase;
|
|
27
30
|
pollIntervalMs;
|
|
28
31
|
trackedFeatures = new Map();
|
|
29
32
|
skippedRepos = new Set();
|
|
@@ -32,11 +35,12 @@ export class PrSyncWatcherService {
|
|
|
32
35
|
processId;
|
|
33
36
|
intervalId = null;
|
|
34
37
|
pollCycle = 0;
|
|
35
|
-
constructor(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, db = null) {
|
|
38
|
+
constructor(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, db = null, pollUpstreamPrUseCase = null) {
|
|
36
39
|
this.featureRepo = featureRepo;
|
|
37
40
|
this.agentRunRepo = agentRunRepo;
|
|
38
41
|
this.gitPrService = gitPrService;
|
|
39
42
|
this.notificationService = notificationService;
|
|
43
|
+
this.pollUpstreamPrUseCase = pollUpstreamPrUseCase;
|
|
40
44
|
this.pollIntervalMs = pollIntervalMs;
|
|
41
45
|
this.db = db;
|
|
42
46
|
this.processId = `${process.pid}-${Date.now()}`;
|
|
@@ -97,25 +101,36 @@ export class PrSyncWatcherService {
|
|
|
97
101
|
return; // another process holds the lock — skip this cycle
|
|
98
102
|
}
|
|
99
103
|
this.pollCycle++;
|
|
100
|
-
const
|
|
104
|
+
const [reviewFeaturesFull, awaitingFeaturesFull] = await Promise.all([
|
|
105
|
+
this.featureRepo.list({ lifecycle: SdlcLifecycle.Review }),
|
|
106
|
+
this.featureRepo.list({ lifecycle: SdlcLifecycle.AwaitingUpstream }),
|
|
107
|
+
]);
|
|
101
108
|
// Include features with a valid repositoryPath (with or without PR data)
|
|
102
|
-
const
|
|
109
|
+
const reviewFeatures = reviewFeaturesFull.filter((f) => f.repositoryPath);
|
|
110
|
+
const awaitingFeatures = awaitingFeaturesFull.filter((f) => f.repositoryPath);
|
|
111
|
+
const features = [...reviewFeatures, ...awaitingFeatures];
|
|
103
112
|
if (features.length === 0) {
|
|
104
113
|
this.trackedFeatures.clear();
|
|
105
114
|
return;
|
|
106
115
|
}
|
|
107
|
-
//
|
|
116
|
+
// Process AwaitingUpstream features via PollUpstreamPrUseCase
|
|
117
|
+
if (this.pollUpstreamPrUseCase) {
|
|
118
|
+
for (const feature of awaitingFeatures) {
|
|
119
|
+
await this.processAwaitingUpstreamFeature(feature);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Group Review features by repositoryPath for batch queries
|
|
108
123
|
const byRepo = new Map();
|
|
109
|
-
for (const feature of
|
|
124
|
+
for (const feature of reviewFeatures) {
|
|
110
125
|
const group = byRepo.get(feature.repositoryPath) ?? [];
|
|
111
126
|
group.push(feature);
|
|
112
127
|
byRepo.set(feature.repositoryPath, group);
|
|
113
128
|
}
|
|
114
|
-
// Process each repository
|
|
129
|
+
// Process each repository (Review lifecycle)
|
|
115
130
|
for (const [repoPath, repoFeatures] of byRepo) {
|
|
116
131
|
await this.processRepository(repoPath, repoFeatures);
|
|
117
132
|
}
|
|
118
|
-
// Prune features no longer in Review
|
|
133
|
+
// Prune features no longer in Review or AwaitingUpstream
|
|
119
134
|
const currentFeatureIds = new Set(features.map((f) => f.id));
|
|
120
135
|
for (const trackedId of this.trackedFeatures.keys()) {
|
|
121
136
|
if (!currentFeatureIds.has(trackedId)) {
|
|
@@ -150,6 +165,20 @@ export class PrSyncWatcherService {
|
|
|
150
165
|
console.warn(`${TAG} Rate limited for ${repoPath}, backing off until ${new Date(backoffUntil).toISOString()}`);
|
|
151
166
|
}
|
|
152
167
|
}
|
|
168
|
+
async processAwaitingUpstreamFeature(feature) {
|
|
169
|
+
if (!this.pollUpstreamPrUseCase)
|
|
170
|
+
return;
|
|
171
|
+
try {
|
|
172
|
+
const result = await this.pollUpstreamPrUseCase.execute({ featureId: feature.id });
|
|
173
|
+
// eslint-disable-next-line no-console
|
|
174
|
+
console.log(`${TAG} AwaitingUpstream poll for "${feature.name}": status=${result.status} transitioned=${result.transitioned}`);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
178
|
+
// eslint-disable-next-line no-console
|
|
179
|
+
console.warn(`${TAG} PollUpstreamPrUseCase failed for "${feature.name}": ${msg}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
153
182
|
async processRepository(repoPath, features) {
|
|
154
183
|
if (this.skippedRepos.has(repoPath))
|
|
155
184
|
return;
|
|
@@ -353,11 +382,11 @@ let watcherInstance = null;
|
|
|
353
382
|
*
|
|
354
383
|
* @throws Error if the watcher is already initialized
|
|
355
384
|
*/
|
|
356
|
-
export function initializePrSyncWatcher(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db) {
|
|
385
|
+
export function initializePrSyncWatcher(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db, pollUpstreamPrUseCase) {
|
|
357
386
|
if (watcherInstance !== null) {
|
|
358
387
|
throw new Error('PR sync watcher already initialized. Cannot re-initialize.');
|
|
359
388
|
}
|
|
360
|
-
watcherInstance = new PrSyncWatcherService(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db ?? null);
|
|
389
|
+
watcherInstance = new PrSyncWatcherService(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db ?? null, pollUpstreamPrUseCase ?? null);
|
|
361
390
|
}
|
|
362
391
|
/**
|
|
363
392
|
* Get the PR sync watcher singleton.
|
|
@@ -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;
|
|
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;AAiC1D;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CA4FzC"}
|
|
@@ -22,6 +22,7 @@ import { resolveWebDir } from '../../../../packages/core/src/infrastructure/serv
|
|
|
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
24
|
import { getExistingConnection } from '../../../../packages/core/src/infrastructure/persistence/sqlite/connection.js';
|
|
25
|
+
import { PollUpstreamPrUseCase } from '../../../../packages/core/src/application/use-cases/features/poll-upstream-pr.use-case.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';
|
|
27
28
|
function parsePort(value) {
|
|
@@ -68,7 +69,8 @@ Examples:
|
|
|
68
69
|
// Start PR sync watcher to detect PR/CI status transitions on GitHub
|
|
69
70
|
const gitPrService = container.resolve('IGitPrService');
|
|
70
71
|
const db = getExistingConnection();
|
|
71
|
-
|
|
72
|
+
const pollUpstreamPrUseCase = container.resolve(PollUpstreamPrUseCase);
|
|
73
|
+
initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db, pollUpstreamPrUseCase);
|
|
72
74
|
getPrSyncWatcher().start();
|
|
73
75
|
const url = `http://localhost:${port}`;
|
|
74
76
|
messages.success(`Server ready at ${fmt.code(url)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/create-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAGpE,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAQD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"create-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/create-feature.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAGpE,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAQD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAqFhD"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { resolve } from '../../lib/server-container.js';
|
|
3
3
|
import { composeUserInput } from './compose-user-input.js';
|
|
4
4
|
export async function createFeature(input) {
|
|
5
|
-
const { description, repositoryPath, attachments, sessionId, approvalGates, push, openPr, parentId, fast, pending, agentType, model, } = input;
|
|
5
|
+
const { description, repositoryPath, attachments, sessionId, approvalGates, push, openPr, forkAndPr, commitSpecs, parentId, fast, pending, agentType, model, } = input;
|
|
6
6
|
if (!description?.trim()) {
|
|
7
7
|
return { error: 'description is required' };
|
|
8
8
|
}
|
|
@@ -24,6 +24,8 @@ export async function createFeature(input) {
|
|
|
24
24
|
approvalGates: gates,
|
|
25
25
|
push: push ?? false,
|
|
26
26
|
openPr: openPr ?? false,
|
|
27
|
+
...(forkAndPr ? { forkAndPr } : {}),
|
|
28
|
+
...(commitSpecs !== undefined ? { commitSpecs } : {}),
|
|
27
29
|
...(parentId ? { parentId } : {}),
|
|
28
30
|
description,
|
|
29
31
|
...(fast ? { fast } : {}),
|
|
@@ -40,6 +42,8 @@ export async function createFeature(input) {
|
|
|
40
42
|
approvalGates: gates,
|
|
41
43
|
push: push ?? false,
|
|
42
44
|
openPr: openPr ?? false,
|
|
45
|
+
...(forkAndPr ? { forkAndPr } : {}),
|
|
46
|
+
...(commitSpecs !== undefined ? { commitSpecs } : {}),
|
|
43
47
|
...(parentId ? { parentId } : {}),
|
|
44
48
|
...(fast ? { fast } : {}),
|
|
45
49
|
...(pending ? { pending } : {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/agent-events/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAwEvC,wBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CA4R9C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/sessions/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/sessions/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,eAAO,MAAM,OAAO,kBAAkB,CAAC;AA2VvC;;;;;GAKG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,OAAO;;;;YA9VpC,MAAM;mBACC,MAAM;iBACR,MAAM,GAAG,IAAI;sBACR,MAAM;wBACJ,MAAM,GAAG,IAAI;uBACd,MAAM,GAAG,IAAI;mBACjB,MAAM,GAAG,IAAI;qBACX,MAAM;kBACT,MAAM;;IAoXjB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
2
3
|
import { homedir } from 'node:os';
|
|
3
4
|
import { join } from 'node:path';
|
|
4
5
|
import { readdir, stat } from 'node:fs/promises';
|
|
@@ -20,28 +21,58 @@ function cursorEncodePath(p) {
|
|
|
20
21
|
return p.replace(/^\//, '').replace(/\./g, '').replace(/[/\\]/g, '-');
|
|
21
22
|
}
|
|
22
23
|
// ── Claude Code session scanner ───────────────────────────────────────
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Collect .jsonl session files from a single Claude project directory.
|
|
26
|
+
*/
|
|
27
|
+
async function collectJsonlFiles(projectDir) {
|
|
28
|
+
let entries;
|
|
27
29
|
try {
|
|
28
|
-
|
|
29
|
-
files = entries.filter((e) => e.endsWith('.jsonl'));
|
|
30
|
+
entries = await readdir(projectDir);
|
|
30
31
|
}
|
|
31
32
|
catch {
|
|
32
33
|
return [];
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
-
const fileInfos = await Promise.allSettled(
|
|
35
|
+
const jsonlFiles = entries.filter((e) => e.endsWith('.jsonl'));
|
|
36
|
+
const fileInfos = await Promise.allSettled(jsonlFiles.map(async (name) => {
|
|
36
37
|
const filePath = join(projectDir, name);
|
|
37
38
|
const s = await stat(filePath);
|
|
38
39
|
return { name, filePath, mtime: s.mtime.getTime() };
|
|
39
40
|
}));
|
|
40
|
-
|
|
41
|
+
return fileInfos
|
|
41
42
|
.filter((r) => r.status === 'fulfilled')
|
|
42
|
-
.map((r) => r.value)
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
.map((r) => r.value);
|
|
44
|
+
}
|
|
45
|
+
async function scanClaudeSessions(repositoryPath, limit, includeWorktrees = false) {
|
|
46
|
+
const dirName = claudeEncodePath(repositoryPath);
|
|
47
|
+
const projectsRoot = join(homedir(), '.claude', 'projects');
|
|
48
|
+
// Collect files from the exact directory
|
|
49
|
+
const primaryDir = join(projectsRoot, dirName);
|
|
50
|
+
let allFiles = await collectJsonlFiles(primaryDir);
|
|
51
|
+
// When includeWorktrees is set, also scan:
|
|
52
|
+
// 1. Directories whose name starts with the encoded repo path (git worktrees, .worktrees)
|
|
53
|
+
// 2. Shep worktree directories (~/.shep/repos/<hash>/wt/*) which use a hash of the repo path
|
|
54
|
+
if (includeWorktrees) {
|
|
55
|
+
try {
|
|
56
|
+
const allDirs = await readdir(projectsRoot);
|
|
57
|
+
// Match git-style worktrees (same prefix as repo path)
|
|
58
|
+
const prefixMatches = allDirs.filter((d) => d !== dirName && d.startsWith(dirName));
|
|
59
|
+
// Match shep worktrees: compute repo hash → find dirs starting with encoded shep path
|
|
60
|
+
const normalizedRepoPath = repositoryPath.replace(/\\/g, '/');
|
|
61
|
+
const repoHash = createHash('sha256').update(normalizedRepoPath).digest('hex').slice(0, 16);
|
|
62
|
+
const shepHome = join(homedir(), '.shep').replace(/\\/g, '/');
|
|
63
|
+
const shepWorktreePrefix = claudeEncodePath(join(shepHome, 'repos', repoHash));
|
|
64
|
+
const shepMatches = allDirs.filter((d) => d.startsWith(shepWorktreePrefix) && !prefixMatches.includes(d) && d !== dirName);
|
|
65
|
+
const worktreeDirs = [...prefixMatches, ...shepMatches];
|
|
66
|
+
const worktreeResults = await Promise.all(worktreeDirs.map((d) => collectJsonlFiles(join(projectsRoot, d))));
|
|
67
|
+
for (const files of worktreeResults) {
|
|
68
|
+
allFiles = allFiles.concat(files);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// projectsRoot doesn't exist — no sessions at all
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const valid = allFiles.sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
45
76
|
// Parse each file
|
|
46
77
|
const results = await Promise.allSettled(valid.map(async (fi) => parseClaudeSession(fi.filePath, fi.name, fi.mtime, repositoryPath)));
|
|
47
78
|
return results
|
|
@@ -238,13 +269,14 @@ export async function GET(request) {
|
|
|
238
269
|
const url = new URL(request.url);
|
|
239
270
|
const repositoryPath = url.searchParams.get('repositoryPath');
|
|
240
271
|
const limit = parseInt(url.searchParams.get('limit') ?? '10', 10);
|
|
272
|
+
const includeWorktrees = url.searchParams.get('includeWorktrees') === 'true';
|
|
241
273
|
if (!repositoryPath?.trim()) {
|
|
242
274
|
return NextResponse.json({ error: 'repositoryPath is required' }, { status: 400 });
|
|
243
275
|
}
|
|
244
276
|
try {
|
|
245
277
|
// Scan all providers in parallel
|
|
246
278
|
const [claudeSessions, cursorSessions] = await Promise.all([
|
|
247
|
-
scanClaudeSessions(repositoryPath, limit),
|
|
279
|
+
scanClaudeSessions(repositoryPath, limit, includeWorktrees),
|
|
248
280
|
scanCursorSessions(repositoryPath, limit),
|
|
249
281
|
]);
|
|
250
282
|
// Merge and sort by mtime descending, apply limit
|
package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ export interface FeatureCreatePayload {
|
|
|
34
34
|
ciWatchEnabled: boolean;
|
|
35
35
|
enableEvidence: boolean;
|
|
36
36
|
commitEvidence: boolean;
|
|
37
|
+
forkAndPr: boolean;
|
|
38
|
+
commitSpecs: boolean;
|
|
37
39
|
parentId?: string;
|
|
38
40
|
/** When true, skip SDLC phases and implement directly from the prompt. */
|
|
39
41
|
fast: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAS5E,YAAY,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAE/F,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,IAAI,EAAE,OAAO,CAAC;IACd,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+ED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,+EAA+E;IAC/E,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAClC,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,GACnB,EAAE,wBAAwB,
|
|
1
|
+
{"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAS5E,YAAY,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAE/F,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,IAAI,EAAE,OAAO,CAAC;IACd,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+ED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,+EAA+E;IAC/E,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAClC,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,GACnB,EAAE,wBAAwB,2CA83B1B;AAmJD,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,eAAe,EACf,QAAQ,GACT,EAAE,uBAAuB,2CAiNzB"}
|