@shepai/cli 1.140.0 → 1.141.0-pr452.1d8e904
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 +79 -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 +31 -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 +4 -0
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +4 -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 +23 -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 +84 -0
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.js +2 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +21 -0
- 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 +5 -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 +12 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-columns.d.ts +13 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-columns.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/045-add-fork-and-pr-columns.js +30 -0
- 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 +11 -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 +50 -0
- 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 +25 -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 +145 -0
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.d.ts +17 -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 +98 -15
- package/dist/src/presentation/cli/commands/ui.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/ui.command.js +2 -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/components/common/feature-create-drawer/feature-create-drawer.d.ts +4 -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 +23 -6
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +11 -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 +34 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.js +12 -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.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +1 -0
- package/dist/src/presentation/web/dev-server.js +2 -1
- 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 +3 -3
- package/web/.next/required-server-files.json +3 -3
- 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.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.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.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.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.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.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.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.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.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.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/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_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_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_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/[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]__2bdf88a0._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2bdf88a0._.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]__42faf5ae._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__42faf5ae._.js.map +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]__685ee565._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__685ee565._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6ec59045._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6ec59045._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__74756aae._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__74756aae._.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]__a5f9c6e5._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a5f9c6e5._.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]__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]__df7c1cd3._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__df7c1cd3._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_02ec1aea._.js +1 -1
- package/web/.next/server/chunks/ssr/_02ec1aea._.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/_64bdfc6f._.js +2 -2
- package/web/.next/server/chunks/ssr/_64bdfc6f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_6a83b821._.js +3 -0
- package/web/.next/server/chunks/ssr/{_bbb3a0fc._.js.map → _6a83b821._.js.map} +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/_8fcc39d4._.js +3 -0
- package/web/.next/server/chunks/ssr/_8fcc39d4._.js.map +1 -0
- 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/{_0a69ebd5._.js → _c5657bb7._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_0a69ebd5._.js.map → _c5657bb7._.js.map} +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/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_340a9d64._.js → src_presentation_web_e05921f6._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_340a9d64._.js.map → src_presentation_web_e05921f6._.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/{8ae10749f2e8db60.js → 026580606b8b7231.js} +1 -1
- package/web/.next/static/chunks/09131550e55102d1.css +1 -0
- package/web/.next/static/chunks/{2349b8618faac5df.js → 3a2cf0e09f1a0159.js} +1 -1
- package/web/.next/static/chunks/{3c5c3a51c24cf5c8.js → 3a3726fb6c94f651.js} +1 -1
- package/web/.next/static/chunks/{e65c4ae61b6f8045.js → 3a61077325daf0c3.js} +1 -1
- package/web/.next/static/chunks/{41e43675a8864a3f.js → 65268efa9fd1584d.js} +1 -1
- package/web/.next/static/chunks/{ec05de0bd9d358e4.js → 74675bf4df9bc445.js} +1 -1
- package/web/.next/static/chunks/{9eff18338e76d253.js → 8a65fc8ff0c02d79.js} +2 -2
- package/web/.next/static/chunks/a63b3e9232d9429c.js +1 -0
- package/web/.next/static/chunks/c56bedce824cd983.js +1 -0
- package/web/.next/static/chunks/{7b850f14e5ef6865.js → e005665fcc9cf8d5.js} +1 -1
- package/web/.next/static/chunks/{5bea21d249dc35f8.js → e013cc94f105db24.js} +2 -2
- package/web/.next/static/chunks/{523ad15a08ac9fe7.js → f08792db31cb4046.js} +1 -1
- package/web/.next/static/chunks/fa556c575c788679.js +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cb850066._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cb850066._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_a9f57758._.js +0 -3
- package/web/.next/server/chunks/ssr/_a9f57758._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_bbb3a0fc._.js +0 -3
- package/web/.next/static/chunks/1df0c0594135d736.css +0 -1
- package/web/.next/static/chunks/6a370f2709c81d83.js +0 -1
- package/web/.next/static/chunks/7ac8f98c0d991dda.js +0 -1
- package/web/.next/static/chunks/b705d6e7529f010b.js +0 -1
- /package/web/.next/static/{VLtWZeBgMjP_Lk91OEpmY → C5RqIopAMg1O7JgTQ3P_o}/_buildManifest.js +0 -0
- /package/web/.next/static/{VLtWZeBgMjP_Lk91OEpmY → C5RqIopAMg1O7JgTQ3P_o}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{VLtWZeBgMjP_Lk91OEpmY → C5RqIopAMg1O7JgTQ3P_o}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Fork Service Implementation
|
|
3
|
+
*
|
|
4
|
+
* Manages GitHub fork operations: forking repos, pushing to forks,
|
|
5
|
+
* creating upstream PRs, and polling upstream PR status.
|
|
6
|
+
* Uses `gh` CLI for all GitHub API interactions.
|
|
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
|
+
import { PrStatus } from '../../../domain/generated/output.js';
|
|
23
|
+
let GitForkService = class GitForkService {
|
|
24
|
+
execFile;
|
|
25
|
+
constructor(execFile) {
|
|
26
|
+
this.execFile = execFile;
|
|
27
|
+
}
|
|
28
|
+
async forkRepository(cwd) {
|
|
29
|
+
// Check if origin is already a fork — if so, just ensure upstream remote exists
|
|
30
|
+
try {
|
|
31
|
+
const { stdout } = await this.execFile('gh', ['repo', 'view', '--json', 'isFork,parent'], {
|
|
32
|
+
cwd,
|
|
33
|
+
});
|
|
34
|
+
const repoInfo = JSON.parse(stdout);
|
|
35
|
+
if (repoInfo.isFork && repoInfo.parent) {
|
|
36
|
+
// Origin is already a fork — ensure upstream remote points to parent
|
|
37
|
+
const parentUrl = `https://github.com/${repoInfo.parent.owner.login}/${repoInfo.parent.name}.git`;
|
|
38
|
+
try {
|
|
39
|
+
await this.execFile('git', ['remote', 'add', 'upstream', parentUrl], { cwd });
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Remote may already exist — update it
|
|
43
|
+
await this.execFile('git', ['remote', 'set-url', 'upstream', parentUrl], { cwd });
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// gh repo view failed — could be auth issue or not a GitHub repo
|
|
50
|
+
}
|
|
51
|
+
// Fork the repository: gh repo fork --remote remaps origin to fork, adds upstream
|
|
52
|
+
try {
|
|
53
|
+
await this.execFile('gh', ['repo', 'fork', '--remote', '--remote-name', 'origin'], { cwd });
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
57
|
+
if (message.includes('auth') || message.includes('login')) {
|
|
58
|
+
throw new GitForkError('GitHub authentication required to fork', GitForkErrorCode.AUTH_FAILURE, err instanceof Error ? err : undefined);
|
|
59
|
+
}
|
|
60
|
+
throw new GitForkError(`Failed to fork repository: ${message}`, GitForkErrorCode.FORK_FAILED, err instanceof Error ? err : undefined);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async pushToFork(cwd, branch) {
|
|
64
|
+
try {
|
|
65
|
+
await this.execFile('git', ['push', '-u', 'origin', branch], { cwd });
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
69
|
+
throw new GitForkError(`Failed to push to fork: ${message}`, GitForkErrorCode.PUSH_FAILED, err instanceof Error ? err : undefined);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async createUpstreamPr(cwd, title, body, head, base) {
|
|
73
|
+
try {
|
|
74
|
+
// Get the upstream repo identifier
|
|
75
|
+
const { stdout: upstreamUrl } = await this.execFile('git', ['remote', 'get-url', 'upstream'], { cwd });
|
|
76
|
+
const upstreamRepo = this.extractRepoFromUrl(upstreamUrl.trim());
|
|
77
|
+
// Get the fork owner for the head ref (owner:branch format)
|
|
78
|
+
const { stdout: forkUrl } = await this.execFile('git', ['remote', 'get-url', 'origin'], {
|
|
79
|
+
cwd,
|
|
80
|
+
});
|
|
81
|
+
const forkRepo = this.extractRepoFromUrl(forkUrl.trim());
|
|
82
|
+
const forkOwner = forkRepo.split('/')[0];
|
|
83
|
+
const { stdout } = await this.execFile('gh', [
|
|
84
|
+
'pr',
|
|
85
|
+
'create',
|
|
86
|
+
'--repo',
|
|
87
|
+
upstreamRepo,
|
|
88
|
+
'--title',
|
|
89
|
+
title,
|
|
90
|
+
'--body',
|
|
91
|
+
body,
|
|
92
|
+
'--head',
|
|
93
|
+
`${forkOwner}:${head}`,
|
|
94
|
+
'--base',
|
|
95
|
+
base,
|
|
96
|
+
'--json',
|
|
97
|
+
'url,number',
|
|
98
|
+
], { cwd });
|
|
99
|
+
const result = JSON.parse(stdout);
|
|
100
|
+
return { url: result.url, number: result.number };
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
104
|
+
throw new GitForkError(`Failed to create upstream PR: ${message}`, GitForkErrorCode.PR_CREATE_FAILED, err instanceof Error ? err : undefined);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async getUpstreamPrStatus(upstreamRepo, prNumber) {
|
|
108
|
+
try {
|
|
109
|
+
const { stdout } = await this.execFile('gh', ['pr', 'view', String(prNumber), '--repo', upstreamRepo, '--json', 'state'], {});
|
|
110
|
+
const result = JSON.parse(stdout);
|
|
111
|
+
const state = (result.state ?? '').toUpperCase();
|
|
112
|
+
if (state === 'MERGED')
|
|
113
|
+
return PrStatus.Merged;
|
|
114
|
+
if (state === 'CLOSED')
|
|
115
|
+
return PrStatus.Closed;
|
|
116
|
+
return PrStatus.Open;
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
120
|
+
throw new GitForkError(`Failed to get upstream PR status: ${message}`, GitForkErrorCode.PR_STATUS_FAILED, err instanceof Error ? err : undefined);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Extract owner/repo from a git remote URL.
|
|
125
|
+
* Handles both HTTPS and SSH formats.
|
|
126
|
+
*/
|
|
127
|
+
extractRepoFromUrl(url) {
|
|
128
|
+
// SSH: git@github.com:owner/repo.git
|
|
129
|
+
const sshMatch = url.match(/git@[^:]+:([^/]+\/[^/.]+)/);
|
|
130
|
+
if (sshMatch)
|
|
131
|
+
return sshMatch[1];
|
|
132
|
+
// HTTPS: https://github.com/owner/repo.git
|
|
133
|
+
const httpsMatch = url.match(/github\.com\/([^/]+\/[^/.]+)/);
|
|
134
|
+
if (httpsMatch)
|
|
135
|
+
return httpsMatch[1];
|
|
136
|
+
// Strip .git suffix and return as-is
|
|
137
|
+
return url.replace(/\.git$/, '');
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
GitForkService = __decorate([
|
|
141
|
+
injectable(),
|
|
142
|
+
__param(0, inject('ExecFunction')),
|
|
143
|
+
__metadata("design:paramtypes", [Function])
|
|
144
|
+
], GitForkService);
|
|
145
|
+
export { GitForkService };
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* PR Sync Watcher Service
|
|
3
3
|
*
|
|
4
4
|
* Polls GitHub PR status and CI status for features in the Review lifecycle
|
|
5
|
-
* stage,
|
|
5
|
+
* stage, and upstream PR status for features in the AwaitingUpstream stage,
|
|
6
|
+
* updating feature records and emitting notifications when transitions
|
|
6
7
|
* are detected. Follows the NotificationWatcherService polling pattern.
|
|
7
8
|
*
|
|
8
9
|
* Maintains in-memory tracking of last-known PR and CI status per feature
|
|
@@ -13,12 +14,14 @@ import type { IFeatureRepository } from '../../../application/ports/output/repos
|
|
|
13
14
|
import type { IAgentRunRepository } from '../../../application/ports/output/agents/agent-run-repository.interface.js';
|
|
14
15
|
import type { IGitPrService } from '../../../application/ports/output/services/git-pr-service.interface.js';
|
|
15
16
|
import type { INotificationService } from '../../../application/ports/output/services/notification-service.interface.js';
|
|
17
|
+
import type { IGitForkService } from '../../../application/ports/output/services/git-fork-service.interface.js';
|
|
16
18
|
import type Database from 'better-sqlite3';
|
|
17
19
|
export declare class PrSyncWatcherService {
|
|
18
20
|
private readonly featureRepo;
|
|
19
21
|
private readonly agentRunRepo;
|
|
20
22
|
private readonly gitPrService;
|
|
21
23
|
private readonly notificationService;
|
|
24
|
+
private readonly gitForkService;
|
|
22
25
|
private readonly pollIntervalMs;
|
|
23
26
|
private readonly trackedFeatures;
|
|
24
27
|
private readonly skippedRepos;
|
|
@@ -27,7 +30,7 @@ export declare class PrSyncWatcherService {
|
|
|
27
30
|
private readonly processId;
|
|
28
31
|
private intervalId;
|
|
29
32
|
private pollCycle;
|
|
30
|
-
constructor(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null);
|
|
33
|
+
constructor(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null, gitForkService?: IGitForkService | null);
|
|
31
34
|
isRunning(): boolean;
|
|
32
35
|
start(): void;
|
|
33
36
|
stop(): void;
|
|
@@ -40,6 +43,17 @@ export declare class PrSyncWatcherService {
|
|
|
40
43
|
private handleRateLimitError;
|
|
41
44
|
private processRepository;
|
|
42
45
|
private processFeature;
|
|
46
|
+
/**
|
|
47
|
+
* Extract upstream repo (owner/name) from an upstream PR URL.
|
|
48
|
+
* Expected format: https://github.com/owner/repo/pull/123
|
|
49
|
+
*/
|
|
50
|
+
private extractUpstreamRepo;
|
|
51
|
+
/**
|
|
52
|
+
* Poll upstream PR status for a feature in AwaitingUpstream lifecycle.
|
|
53
|
+
* If the upstream PR is merged, transition to Maintain.
|
|
54
|
+
* If the upstream PR is closed, update upstreamPrStatus to Closed.
|
|
55
|
+
*/
|
|
56
|
+
private processAwaitingUpstreamFeature;
|
|
43
57
|
/** Mark associated agent run as completed so the UI reflects "done" state. */
|
|
44
58
|
private completeAgentRun;
|
|
45
59
|
private emitNotification;
|
|
@@ -50,7 +64,7 @@ export declare class PrSyncWatcherService {
|
|
|
50
64
|
*
|
|
51
65
|
* @throws Error if the watcher is already initialized
|
|
52
66
|
*/
|
|
53
|
-
export declare function initializePrSyncWatcher(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null): void;
|
|
67
|
+
export declare function initializePrSyncWatcher(featureRepo: IFeatureRepository, agentRunRepo: IAgentRunRepository, gitPrService: IGitPrService, notificationService: INotificationService, pollIntervalMs?: number, db?: Database.Database | null, gitForkService?: IGitForkService | null): void;
|
|
54
68
|
/**
|
|
55
69
|
* Get the PR sync watcher singleton.
|
|
56
70
|
*
|
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;;;;;;;;;;;GAWG;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,EAAE,eAAe,EAAE,MAAM,0EAA0E,CAAC;AAChH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAqB3C,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,cAAc,CAAyB;IACxD,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,cAAc,GAAE,eAAe,GAAG,IAAW;IAY/C,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;IAmDlB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,oBAAoB;YAYd,iBAAiB;YA+CjB,cAAc;IAkM5B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAK3B;;;;OAIG;YACW,8BAA8B;IA0F5C,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,cAAc,CAAC,EAAE,eAAe,GAAG,IAAI,GACtC,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"}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* PR Sync Watcher Service
|
|
3
3
|
*
|
|
4
4
|
* Polls GitHub PR status and CI status for features in the Review lifecycle
|
|
5
|
-
* stage,
|
|
5
|
+
* stage, and upstream PR status for features in the AwaitingUpstream stage,
|
|
6
|
+
* updating feature records and emitting notifications when transitions
|
|
6
7
|
* are detected. Follows the NotificationWatcherService polling pattern.
|
|
7
8
|
*
|
|
8
9
|
* Maintains in-memory tracking of last-known PR and CI status per feature
|
|
@@ -24,6 +25,7 @@ export class PrSyncWatcherService {
|
|
|
24
25
|
agentRunRepo;
|
|
25
26
|
gitPrService;
|
|
26
27
|
notificationService;
|
|
28
|
+
gitForkService;
|
|
27
29
|
pollIntervalMs;
|
|
28
30
|
trackedFeatures = new Map();
|
|
29
31
|
skippedRepos = new Set();
|
|
@@ -32,11 +34,12 @@ export class PrSyncWatcherService {
|
|
|
32
34
|
processId;
|
|
33
35
|
intervalId = null;
|
|
34
36
|
pollCycle = 0;
|
|
35
|
-
constructor(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, db = null) {
|
|
37
|
+
constructor(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, db = null, gitForkService = null) {
|
|
36
38
|
this.featureRepo = featureRepo;
|
|
37
39
|
this.agentRunRepo = agentRunRepo;
|
|
38
40
|
this.gitPrService = gitPrService;
|
|
39
41
|
this.notificationService = notificationService;
|
|
42
|
+
this.gitForkService = gitForkService;
|
|
40
43
|
this.pollIntervalMs = pollIntervalMs;
|
|
41
44
|
this.db = db;
|
|
42
45
|
this.processId = `${process.pid}-${Date.now()}`;
|
|
@@ -97,26 +100,32 @@ export class PrSyncWatcherService {
|
|
|
97
100
|
return; // another process holds the lock — skip this cycle
|
|
98
101
|
}
|
|
99
102
|
this.pollCycle++;
|
|
100
|
-
const
|
|
103
|
+
const allReviewFeatures = await this.featureRepo.list({ lifecycle: SdlcLifecycle.Review });
|
|
101
104
|
// Include features with a valid repositoryPath (with or without PR data)
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
this.trackedFeatures.clear();
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
// Group features by repositoryPath for batch queries
|
|
105
|
+
const reviewFeatures = allReviewFeatures.filter((f) => f.repositoryPath);
|
|
106
|
+
// Group Review features by repositoryPath for batch queries
|
|
108
107
|
const byRepo = new Map();
|
|
109
|
-
for (const feature of
|
|
108
|
+
for (const feature of reviewFeatures) {
|
|
110
109
|
const group = byRepo.get(feature.repositoryPath) ?? [];
|
|
111
110
|
group.push(feature);
|
|
112
111
|
byRepo.set(feature.repositoryPath, group);
|
|
113
112
|
}
|
|
114
|
-
// Process each repository
|
|
113
|
+
// Process each repository (Review features)
|
|
115
114
|
for (const [repoPath, repoFeatures] of byRepo) {
|
|
116
115
|
await this.processRepository(repoPath, repoFeatures);
|
|
117
116
|
}
|
|
118
|
-
//
|
|
119
|
-
const
|
|
117
|
+
// Process AwaitingUpstream features (poll upstream PR status individually)
|
|
118
|
+
const awaitingFeatures = await this.featureRepo.list({
|
|
119
|
+
lifecycle: SdlcLifecycle.AwaitingUpstream,
|
|
120
|
+
});
|
|
121
|
+
for (const feature of awaitingFeatures) {
|
|
122
|
+
await this.processAwaitingUpstreamFeature(feature);
|
|
123
|
+
}
|
|
124
|
+
// Prune features no longer in Review or AwaitingUpstream
|
|
125
|
+
const currentFeatureIds = new Set([
|
|
126
|
+
...reviewFeatures.map((f) => f.id),
|
|
127
|
+
...awaitingFeatures.map((f) => f.id),
|
|
128
|
+
]);
|
|
120
129
|
for (const trackedId of this.trackedFeatures.keys()) {
|
|
121
130
|
if (!currentFeatureIds.has(trackedId)) {
|
|
122
131
|
this.trackedFeatures.delete(trackedId);
|
|
@@ -319,6 +328,80 @@ export class PrSyncWatcherService {
|
|
|
319
328
|
tracked.unchangedCycles++;
|
|
320
329
|
}
|
|
321
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Extract upstream repo (owner/name) from an upstream PR URL.
|
|
333
|
+
* Expected format: https://github.com/owner/repo/pull/123
|
|
334
|
+
*/
|
|
335
|
+
extractUpstreamRepo(upstreamPrUrl) {
|
|
336
|
+
const match = upstreamPrUrl.match(/github\.com\/([^/]+\/[^/]+)\/pull\//);
|
|
337
|
+
return match?.[1] ?? null;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Poll upstream PR status for a feature in AwaitingUpstream lifecycle.
|
|
341
|
+
* If the upstream PR is merged, transition to Maintain.
|
|
342
|
+
* If the upstream PR is closed, update upstreamPrStatus to Closed.
|
|
343
|
+
*/
|
|
344
|
+
async processAwaitingUpstreamFeature(feature) {
|
|
345
|
+
if (!this.gitForkService)
|
|
346
|
+
return;
|
|
347
|
+
if (!feature.pr?.upstreamPrUrl || !feature.pr?.upstreamPrNumber)
|
|
348
|
+
return;
|
|
349
|
+
// Check exponential backoff — skip features that haven't changed recently
|
|
350
|
+
if (!this.shouldPollFeature(feature.id)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const upstreamRepo = this.extractUpstreamRepo(feature.pr.upstreamPrUrl);
|
|
354
|
+
if (!upstreamRepo) {
|
|
355
|
+
// eslint-disable-next-line no-console
|
|
356
|
+
console.warn(`${TAG} Could not extract upstream repo from URL: ${feature.pr.upstreamPrUrl}`);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
let upstreamStatus;
|
|
360
|
+
try {
|
|
361
|
+
upstreamStatus = await this.gitForkService.getUpstreamPrStatus(upstreamRepo, feature.pr.upstreamPrNumber);
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
365
|
+
// eslint-disable-next-line no-console
|
|
366
|
+
console.warn(`${TAG} getUpstreamPrStatus failed for "${feature.name}" (${upstreamRepo}#${feature.pr.upstreamPrNumber}): ${msg}`);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
// Initialize tracking if needed
|
|
370
|
+
const prevState = this.trackedFeatures.get(feature.id);
|
|
371
|
+
if (!prevState) {
|
|
372
|
+
this.trackedFeatures.set(feature.id, {
|
|
373
|
+
prStatus: feature.pr.upstreamPrStatus ?? PrStatus.Open,
|
|
374
|
+
ciStatus: undefined,
|
|
375
|
+
mergeable: undefined,
|
|
376
|
+
featureName: feature.name,
|
|
377
|
+
unchangedCycles: 0,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
const tracked = this.trackedFeatures.get(feature.id);
|
|
381
|
+
const previousStatus = tracked.prStatus;
|
|
382
|
+
if (upstreamStatus === previousStatus) {
|
|
383
|
+
tracked.unchangedCycles++;
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
// eslint-disable-next-line no-console
|
|
387
|
+
console.log(`${TAG} Upstream PR #${feature.pr.upstreamPrNumber} status changed: ${previousStatus} -> ${upstreamStatus} for "${feature.name}"`);
|
|
388
|
+
tracked.prStatus = upstreamStatus;
|
|
389
|
+
tracked.unchangedCycles = 0;
|
|
390
|
+
if (upstreamStatus === PrStatus.Merged) {
|
|
391
|
+
feature.lifecycle = SdlcLifecycle.Maintain;
|
|
392
|
+
feature.pr = { ...feature.pr, upstreamPrStatus: PrStatus.Merged };
|
|
393
|
+
feature.updatedAt = new Date();
|
|
394
|
+
await this.featureRepo.update(feature);
|
|
395
|
+
await this.completeAgentRun(feature);
|
|
396
|
+
this.emitNotification(NotificationEventType.PrMerged, feature.id, feature.agentRunId ?? '', feature.name, `Upstream PR #${feature.pr.upstreamPrNumber} merged for ${feature.name}`, NotificationSeverity.Success);
|
|
397
|
+
}
|
|
398
|
+
else if (upstreamStatus === PrStatus.Closed) {
|
|
399
|
+
feature.pr = { ...feature.pr, upstreamPrStatus: PrStatus.Closed };
|
|
400
|
+
feature.updatedAt = new Date();
|
|
401
|
+
await this.featureRepo.update(feature);
|
|
402
|
+
this.emitNotification(NotificationEventType.PrClosed, feature.id, feature.agentRunId ?? '', feature.name, `Upstream PR #${feature.pr.upstreamPrNumber} closed for ${feature.name}`, NotificationSeverity.Warning);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
322
405
|
/** Mark associated agent run as completed so the UI reflects "done" state. */
|
|
323
406
|
async completeAgentRun(feature) {
|
|
324
407
|
if (!feature.agentRunId)
|
|
@@ -353,11 +436,11 @@ let watcherInstance = null;
|
|
|
353
436
|
*
|
|
354
437
|
* @throws Error if the watcher is already initialized
|
|
355
438
|
*/
|
|
356
|
-
export function initializePrSyncWatcher(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db) {
|
|
439
|
+
export function initializePrSyncWatcher(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db, gitForkService) {
|
|
357
440
|
if (watcherInstance !== null) {
|
|
358
441
|
throw new Error('PR sync watcher already initialized. Cannot re-initialize.');
|
|
359
442
|
}
|
|
360
|
-
watcherInstance = new PrSyncWatcherService(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db ?? null);
|
|
443
|
+
watcherInstance = new PrSyncWatcherService(featureRepo, agentRunRepo, gitPrService, notificationService, pollIntervalMs, db ?? null, gitForkService ?? null);
|
|
361
444
|
}
|
|
362
445
|
/**
|
|
363
446
|
* 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"}
|
|
@@ -67,8 +67,9 @@ Examples:
|
|
|
67
67
|
getNotificationWatcher().start();
|
|
68
68
|
// Start PR sync watcher to detect PR/CI status transitions on GitHub
|
|
69
69
|
const gitPrService = container.resolve('IGitPrService');
|
|
70
|
+
const gitForkService = container.resolve('IGitForkService');
|
|
70
71
|
const db = getExistingConnection();
|
|
71
|
-
initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db);
|
|
72
|
+
initializePrSyncWatcher(featureRepo, runRepo, gitPrService, notificationService, undefined, db, gitForkService);
|
|
72
73
|
getPrSyncWatcher().start();
|
|
73
74
|
const url = `http://localhost:${port}`;
|
|
74
75
|
messages.success(`Server ready at ${fmt.code(url)}`);
|
|
@@ -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"}
|
|
@@ -36,6 +36,7 @@ const LIFECYCLE_TO_NODE = {
|
|
|
36
36
|
[SdlcLifecycle.Blocked]: 'blocked',
|
|
37
37
|
[SdlcLifecycle.Pending]: 'pending',
|
|
38
38
|
[SdlcLifecycle.Deleting]: 'blocked',
|
|
39
|
+
[SdlcLifecycle.AwaitingUpstream]: 'merge',
|
|
39
40
|
[SdlcLifecycle.Archived]: 'archived',
|
|
40
41
|
};
|
|
41
42
|
const STATUS_TO_EVENT = {
|
package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts
CHANGED
|
@@ -39,6 +39,10 @@ export interface FeatureCreatePayload {
|
|
|
39
39
|
fast: boolean;
|
|
40
40
|
/** When true, create the feature in pending state (no agent spawned). */
|
|
41
41
|
pending?: boolean;
|
|
42
|
+
/** Fork repo and create PR to upstream at merge time. */
|
|
43
|
+
forkAndPr: boolean;
|
|
44
|
+
/** Commit specs/evidences into the repo (defaults false when forkAndPr is enabled). */
|
|
45
|
+
commitSpecs: boolean;
|
|
42
46
|
/** Optional agent type override for this feature run */
|
|
43
47
|
agentType?: string;
|
|
44
48
|
/** Optional model override for this feature run */
|
|
@@ -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":"
|
|
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":"AA4BA,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,yDAAyD;IACzD,SAAS,EAAE,OAAO,CAAC;IACnB,uFAAuF;IACvF,WAAW,EAAE,OAAO,CAAC;IACrB,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,2CAg5B1B;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"}
|
package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
4
|
-
import { PaperclipIcon, ChevronsUpDown, CheckIcon, Zap, Clock, FolderPlus, Loader2, } from 'lucide-react';
|
|
4
|
+
import { PaperclipIcon, ChevronsUpDown, CheckIcon, Zap, Clock, FolderPlus, Loader2, GitFork, FileText, } from 'lucide-react';
|
|
5
5
|
import { cn } from '../../../lib/utils.js';
|
|
6
6
|
import { useSoundAction } from '../../../hooks/use-sound-action.js';
|
|
7
7
|
import { BaseDrawer } from '../../common/base-drawer/index.js';
|
|
@@ -131,6 +131,8 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
131
131
|
const [parentId, setParentId] = useState(undefined);
|
|
132
132
|
const [fast, setFast] = useState(false);
|
|
133
133
|
const [pending, setPending] = useState(false);
|
|
134
|
+
const [forkAndPr, setForkAndPr] = useState(false);
|
|
135
|
+
const [commitSpecs, setCommitSpecs] = useState(true);
|
|
134
136
|
const [overrideAgent, setOverrideAgent] = useState(undefined);
|
|
135
137
|
const [overrideModel, setOverrideModel] = useState(undefined);
|
|
136
138
|
const [selectedRepoPath, setSelectedRepoPath] = useState(validRepoPath || undefined);
|
|
@@ -177,6 +179,8 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
177
179
|
setLocalRepos(repositories ?? []);
|
|
178
180
|
setFast(false);
|
|
179
181
|
setPending(false);
|
|
182
|
+
setForkAndPr(false);
|
|
183
|
+
setCommitSpecs(true);
|
|
180
184
|
setOverrideAgent(undefined);
|
|
181
185
|
setOverrideModel(undefined);
|
|
182
186
|
setUploadError(null);
|
|
@@ -320,12 +324,14 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
320
324
|
allowPlan: approvalGates.allowPlan ?? false,
|
|
321
325
|
allowMerge: approvalGates.allowMerge ?? false,
|
|
322
326
|
},
|
|
323
|
-
push: push || openPr,
|
|
324
|
-
openPr,
|
|
327
|
+
push: forkAndPr ? true : push || openPr,
|
|
328
|
+
openPr: forkAndPr ? true : openPr,
|
|
325
329
|
ciWatchEnabled,
|
|
326
330
|
enableEvidence,
|
|
327
331
|
commitEvidence,
|
|
328
332
|
fast,
|
|
333
|
+
forkAndPr,
|
|
334
|
+
commitSpecs,
|
|
329
335
|
...(pending ? { pending } : {}),
|
|
330
336
|
...(overrideAgent ? { agentType: overrideAgent } : {}),
|
|
331
337
|
...(overrideModel ? { model: overrideModel } : {}),
|
|
@@ -346,6 +352,8 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
346
352
|
ciWatchEnabled,
|
|
347
353
|
commitEvidence,
|
|
348
354
|
fast,
|
|
355
|
+
forkAndPr,
|
|
356
|
+
commitSpecs,
|
|
349
357
|
pending,
|
|
350
358
|
overrideAgent,
|
|
351
359
|
overrideModel,
|
|
@@ -453,15 +461,24 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
453
461
|
? 'Requires PR to be enabled'
|
|
454
462
|
: !enableEvidence
|
|
455
463
|
? 'Requires evidence collection to be enabled'
|
|
456
|
-
: 'Include evidence in the pull request body.' })] })] })] }), _jsxs("div", { className: "border-input flex items-center gap-4 rounded-md border px-3 py-2.5", children: [_jsx("span", { className: "text-muted-foreground w-16 shrink-0 text-xs font-semibold tracking-wider", children: "GIT" }), _jsxs("div", { className: "flex flex-1 items-center gap-4", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex cursor-pointer items-center gap-1.5", children: [_jsx(Switch, { id: "push", size: "sm", checked: push || openPr, onCheckedChange: (v) => {
|
|
464
|
+
: 'Include evidence in the pull request body.' })] })] })] }), _jsxs("div", { className: "border-input flex items-center gap-4 rounded-md border px-3 py-2.5", children: [_jsx("span", { className: "text-muted-foreground w-16 shrink-0 text-xs font-semibold tracking-wider", children: "GIT" }), _jsxs("div", { className: "flex flex-1 items-center gap-4", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex cursor-pointer items-center gap-1.5", children: [_jsx(Switch, { id: "push", size: "sm", checked: forkAndPr ? true : push || openPr, onCheckedChange: (v) => {
|
|
457
465
|
setPush(v);
|
|
458
466
|
if (!v && openPr)
|
|
459
467
|
setOpenPr(false);
|
|
460
|
-
}, disabled: isSubmitting }), _jsx(Label, { htmlFor: "push", className:
|
|
468
|
+
}, disabled: isSubmitting || forkAndPr }), _jsx(Label, { htmlFor: "push", className: cn('cursor-pointer text-xs font-medium', forkAndPr && 'opacity-50'), children: "Push" })] }) }), _jsx(TooltipContent, { side: "bottom", children: forkAndPr
|
|
469
|
+
? 'Implicitly enabled by fork-and-PR mode'
|
|
470
|
+
: 'Push branch to remote after implementation.' })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex cursor-pointer items-center gap-1.5", children: [_jsx(Switch, { id: "open-pr", size: "sm", checked: forkAndPr ? true : openPr, onCheckedChange: (v) => {
|
|
461
471
|
setOpenPr(v);
|
|
462
472
|
if (!v)
|
|
463
473
|
setCommitEvidence(false);
|
|
464
|
-
}, disabled: isSubmitting }), _jsx(Label, { htmlFor: "open-pr", className:
|
|
474
|
+
}, disabled: isSubmitting || forkAndPr }), _jsx(Label, { htmlFor: "open-pr", className: cn('cursor-pointer text-xs font-medium', forkAndPr && 'opacity-50'), children: "PR" })] }) }), _jsx(TooltipContent, { side: "bottom", children: forkAndPr
|
|
475
|
+
? 'Implicitly enabled by fork-and-PR mode'
|
|
476
|
+
: 'Open a pull request after pushing.' })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex cursor-pointer items-center gap-1.5", children: [_jsx(Switch, { id: "ci-watch", size: "sm", checked: ciWatchEnabled, onCheckedChange: setCiWatchEnabled, disabled: isSubmitting }), _jsx(Label, { htmlFor: "ci-watch", className: "cursor-pointer text-xs font-medium", children: "Watch" })] }) }), _jsx(TooltipContent, { side: "bottom", children: "Watch CI and auto-fix after push." })] })] })] }), _jsxs("div", { className: "border-input flex items-center gap-4 rounded-md border px-3 py-2.5", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "text-muted-foreground w-16 shrink-0 cursor-default text-xs font-semibold tracking-wider", children: "FORK" }) }), _jsx(TooltipContent, { side: "bottom", children: "Fork the repository and create a PR to the upstream repo." })] }), _jsxs("div", { className: "flex flex-1 items-center gap-4", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex cursor-pointer items-center gap-1.5", children: [_jsx(Switch, { id: "fork-and-pr", size: "sm", checked: forkAndPr, onCheckedChange: (v) => {
|
|
477
|
+
setForkAndPr(v);
|
|
478
|
+
// Auto-flip commitSpecs to false when enabling fork mode
|
|
479
|
+
if (v)
|
|
480
|
+
setCommitSpecs(false);
|
|
481
|
+
}, disabled: isSubmitting }), _jsxs(Label, { htmlFor: "fork-and-pr", className: "flex cursor-pointer items-center gap-1 text-xs font-medium", children: [_jsx(GitFork, { className: "h-3 w-3" }), "Fork & PR"] })] }) }), _jsx(TooltipContent, { side: "bottom", children: "Contribute via fork (PR to upstream)." })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "flex cursor-pointer items-center gap-1.5", children: [_jsx(Switch, { id: "commit-specs", size: "sm", checked: commitSpecs, onCheckedChange: setCommitSpecs, disabled: isSubmitting }), _jsxs(Label, { htmlFor: "commit-specs", className: "flex cursor-pointer items-center gap-1 text-xs font-medium", children: [_jsx(FileText, { className: "h-3 w-3" }), "Commit Specs"] })] }) }), _jsx(TooltipContent, { side: "bottom", children: "Commit specs to repository." })] })] })] })] })] }) }) }) }));
|
|
465
482
|
}
|
|
466
483
|
function ParentFeatureCombobox({ features, value, onChange, disabled, }) {
|
|
467
484
|
const [open, setOpen] = useState(false);
|
|
@@ -120,6 +120,17 @@ export declare const DiscardConfirmation: Story;
|
|
|
120
120
|
*/
|
|
121
121
|
export declare const DragDropReady: Story;
|
|
122
122
|
export declare const Interactive: Story;
|
|
123
|
+
/**
|
|
124
|
+
* Fork & PR enabled — the "Fork & PR" toggle is checked. When enabled,
|
|
125
|
+
* Push and PR toggles are implicitly locked to `true` (disabled), and
|
|
126
|
+
* `commitSpecs` auto-flips to `false`.
|
|
127
|
+
*/
|
|
128
|
+
export declare const ForkAndPrEnabled: Story;
|
|
129
|
+
/**
|
|
130
|
+
* Fork & PR with Commit Specs re-enabled — after enabling fork mode
|
|
131
|
+
* (which auto-disables commitSpecs), the user overrides commitSpecs back to `true`.
|
|
132
|
+
*/
|
|
133
|
+
export declare const ForkAndPrWithCommitSpecs: Story;
|
|
123
134
|
/**
|
|
124
135
|
* With repository selector — opened from sidebar without repo context.
|
|
125
136
|
* Shows the searchable repository combobox at the top of the form.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-create-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAU9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAgC1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAmDlD,uFAAuF;AACvF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAiBvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAMhC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAUxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,KAMzB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,KAUxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAgBjC,CAAC;AAeF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAWlC,CAAC;AAkDF,+EAA+E;AAC/E,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAwCF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAM/B,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAgBjC,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,KAY3B,CAAC;AAMF,eAAO,MAAM,WAAW,EAAE,KAwCzB,CAAC;AAuCF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAM9B,CAAC;AA6BF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAMnC,CAAC"}
|
|
1
|
+
{"version":3,"file":"feature-create-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAU9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,mBAAmB,CAgC1C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAmDlD,uFAAuF;AACvF,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAiBvB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAMhC,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,SAAS,EAAE,KAMvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAUxB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,KAUrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,KAUvB,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,KAMzB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,KAUxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAgBjC,CAAC;AAeF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,KAWlC,CAAC;AAkDF,+EAA+E;AAC/E,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAwCF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAM/B,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAgBjC,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,KAY3B,CAAC;AAMF,eAAO,MAAM,WAAW,EAAE,KAwCzB,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAU9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,EAAE,KAatC,CAAC;AAuCF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAM9B,CAAC;AA6BF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAMnC,CAAC"}
|
|
@@ -398,6 +398,40 @@ export const Interactive = {
|
|
|
398
398
|
}, repositoryPath: "/Users/dev/my-repo", currentAgentType: "claude-code", currentModel: "claude-sonnet-4-6" })] }));
|
|
399
399
|
},
|
|
400
400
|
};
|
|
401
|
+
/* ---------------------------------------------------------------------------
|
|
402
|
+
* Fork & PR stories
|
|
403
|
+
* ------------------------------------------------------------------------- */
|
|
404
|
+
/**
|
|
405
|
+
* Fork & PR enabled — the "Fork & PR" toggle is checked. When enabled,
|
|
406
|
+
* Push and PR toggles are implicitly locked to `true` (disabled), and
|
|
407
|
+
* `commitSpecs` auto-flips to `false`.
|
|
408
|
+
*/
|
|
409
|
+
export const ForkAndPrEnabled = {
|
|
410
|
+
render: () => _jsx(CreateDrawerTrigger, { label: "Open (Fork & PR)" }),
|
|
411
|
+
play: async ({ canvasElement }) => {
|
|
412
|
+
const canvas = within(canvasElement);
|
|
413
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Open (Fork & PR)' }));
|
|
414
|
+
const body = within(canvasElement.ownerDocument.body);
|
|
415
|
+
const forkToggle = await body.findByLabelText('Fork & PR');
|
|
416
|
+
await userEvent.click(forkToggle);
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* Fork & PR with Commit Specs re-enabled — after enabling fork mode
|
|
421
|
+
* (which auto-disables commitSpecs), the user overrides commitSpecs back to `true`.
|
|
422
|
+
*/
|
|
423
|
+
export const ForkAndPrWithCommitSpecs = {
|
|
424
|
+
render: () => _jsx(CreateDrawerTrigger, { label: "Open (Fork + Specs)" }),
|
|
425
|
+
play: async ({ canvasElement }) => {
|
|
426
|
+
const canvas = within(canvasElement);
|
|
427
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Open (Fork + Specs)' }));
|
|
428
|
+
const body = within(canvasElement.ownerDocument.body);
|
|
429
|
+
const forkToggle = await body.findByLabelText('Fork & PR');
|
|
430
|
+
await userEvent.click(forkToggle);
|
|
431
|
+
const specsToggle = body.getByLabelText('Commit Specs');
|
|
432
|
+
await userEvent.click(specsToggle);
|
|
433
|
+
},
|
|
434
|
+
};
|
|
401
435
|
/* ---------------------------------------------------------------------------
|
|
402
436
|
* Repository selector stories
|
|
403
437
|
* ------------------------------------------------------------------------- */
|
package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Node } from '@xyflow/react';
|
|
|
3
3
|
import type { PrStatus, CiStatus, DeploymentState } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
4
4
|
import type { AgentTypeValue } from './agent-type-icons.js';
|
|
5
5
|
export type FeatureNodeState = 'creating' | 'running' | 'action-required' | 'done' | 'blocked' | 'pending' | 'error' | 'deleting' | 'archived';
|
|
6
|
-
export type FeatureLifecyclePhase = 'pending' | 'requirements' | 'research' | 'implementation' | 'review' | 'deploy' | 'maintain';
|
|
6
|
+
export type FeatureLifecyclePhase = 'pending' | 'requirements' | 'research' | 'implementation' | 'review' | 'awaitingUpstream' | 'deploy' | 'maintain';
|
|
7
7
|
/** Human-readable display labels for lifecycle phases. */
|
|
8
8
|
export declare const lifecycleDisplayLabels: Record<FeatureLifecyclePhase, string>;
|
|
9
9
|
/** Left border color for each lifecycle phase. */
|