@shepai/cli 1.176.0 → 1.177.0-pr538.aa9ace4
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/dist/eslint.config.mjs +2 -0
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +15 -0
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/i-browser-opener.d.ts +28 -0
- package/dist/packages/core/src/application/ports/output/services/i-browser-opener.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/i-browser-opener.js +13 -0
- package/dist/packages/core/src/application/ports/output/services/i-desktop-notifier.d.ts +29 -0
- package/dist/packages/core/src/application/ports/output/services/i-desktop-notifier.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/i-desktop-notifier.js +13 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts +2 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.d.ts +46 -3
- package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/check-and-unblock-features.use-case.js +153 -5
- package/dist/packages/core/src/application/use-cases/features/reparent-feature.use-case.d.ts +31 -0
- package/dist/packages/core/src/application/use-cases/features/reparent-feature.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/features/reparent-feature.use-case.js +127 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +10 -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-graph.js +20 -6
- 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 +27 -4
- package/dist/packages/core/src/infrastructure/services/browser-opener.service.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/browser-opener.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +53 -0
- package/dist/packages/core/src/infrastructure/services/notifications/desktop-notifier.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/notifications/desktop-notifier.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/daemon/start-daemon.d.ts +1 -1
- package/dist/src/presentation/cli/commands/daemon/start-daemon.js +2 -3
- package/dist/src/presentation/cli/commands/ui.command.js +1 -2
- package/dist/src/presentation/web/app/actions/reparent-feature.d.ts +5 -0
- package/dist/src/presentation/web/app/actions/reparent-feature.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/reparent-feature.js +16 -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 +2 -2
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +2 -2
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +1 -0
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +47 -4
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.d.ts +1 -0
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.js +18 -6
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.stories.d.ts +3 -0
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.stories.js +27 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts +2 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +14 -3
- package/dist/src/presentation/web/hooks/use-graph-state.d.ts +7 -0
- package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-graph-state.js +74 -0
- package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -1
- package/dist/src/presentation/web/lib/derive-graph.js +5 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +10 -2
- 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 +73 -58
- 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/chat/page/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +75 -60
- 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 +91 -76
- 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 +91 -76
- 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]/[tab]/page/server-reference-manifest.json +71 -56
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +71 -56
- 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)/chat/page/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/chat/page.js +1 -1
- package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +75 -60
- 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 +91 -76
- 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 +91 -76
- 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 +69 -54
- 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]/[tab]/page/server-reference-manifest.json +71 -56
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +71 -56
- 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 +6 -6
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
- package/web/.next/server/app/features/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/features/page.js.nft.json +1 -1
- package/web/.next/server/app/features/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +9 -9
- 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 +13 -13
- 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 +11 -11
- 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 +6 -6
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__332c8d91._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__332c8d91._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_4869a7bb.js +3 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_4869a7bb.js.map +1 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_d92cb436.js +3 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_d92cb436.js.map +1 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_16dd74be.js +3 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_16dd74be.js.map +1 -0
- 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/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__a932cd3a._.js → [root-of-the-server]__000567d1._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__51ec77a8._.js.map → [root-of-the-server]__000567d1._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__23b5ca2c._.js +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]__51ec77a8._.js → [root-of-the-server]__466d5d10._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__a932cd3a._.js.map → [root-of-the-server]__466d5d10._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__540c615f._.js +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__66047a1b._.js → [root-of-the-server]__60b640ad._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__aa72e794._.js.map → [root-of-the-server]__60b640ad._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7528eb6f._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__aa72e794._.js → [root-of-the-server]__e68e2b52._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__66047a1b._.js.map → [root-of-the-server]__e68e2b52._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_8f0d3f07._.js → _09bef7ab._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_8f0d3f07._.js.map → _09bef7ab._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_2b6293f3._.js +4 -0
- package/web/.next/server/chunks/ssr/{_388d1127._.js.map → _2b6293f3._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_4cbb7f95._.js +1 -1
- package/web/.next/server/chunks/ssr/_4cbb7f95._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_6abfa39e._.js +1 -1
- package/web/.next/server/chunks/ssr/_6abfa39e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_ebb12cc5._.js +3 -0
- package/web/.next/server/chunks/ssr/{_98d94927._.js.map → _ebb12cc5._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_f8c55130._.js +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/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
- package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_807cba76._.js → src_presentation_web_06387c54._.js} +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_06387c54._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_e3a30e30._.js → src_presentation_web_1ccf607e._.js} +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_1ccf607e._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_7b7b9e3b._.js → src_presentation_web_2c992e9f._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_7b7b9e3b._.js.map → src_presentation_web_2c992e9f._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_54b02639._.js → src_presentation_web_476ed91c._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_54b02639._.js.map → src_presentation_web_476ed91c._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_17d39233._.js → src_presentation_web_5b78146e._.js} +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_5b78146e._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_e1cd1869._.js → src_presentation_web_796d2fd5._.js} +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_796d2fd5._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_3a934437.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_3a934437.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.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_app_actions_open-ide_ts_baaca5d5._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.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_components_features_skills_8a174cac._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.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 +590 -484
- package/web/.next/static/chunks/{a20f2d6f76f469b7.css → 0cf210e5b787a08b.css} +1 -1
- package/web/.next/static/chunks/{0ffb3738269e15c3.js → 129ec6d253f86319.js} +1 -1
- package/web/.next/static/chunks/{afa7e5d2a48cabc7.js → 2fe9740f9397711d.js} +1 -1
- package/web/.next/static/chunks/{4ff21d16947ec853.js → 37035f72d4f041f4.js} +1 -1
- package/web/.next/static/chunks/{eda9ee3c22b71a69.js → 4a5e1ebbe4a3fd87.js} +1 -1
- package/web/.next/static/chunks/{476873a9bac35ec8.js → 7a0b03e168a882e6.js} +1 -1
- package/web/.next/static/chunks/8692d79a48d07b5c.js +3 -0
- package/web/.next/static/chunks/8c60a1781664e9f3.js +2 -0
- package/web/.next/static/chunks/96b30c2bf69bb538.js +1 -0
- package/web/.next/static/chunks/{2cfc6022d74e2716.js → a3c5ab40fc61b2c2.js} +3 -3
- package/web/.next/static/chunks/{f17d2d0279b8db35.js → abdbfb54cbb73702.js} +1 -1
- package/web/.next/static/chunks/{236744ff71b1aadf.js → bbb9fcc0697d77b8.js} +1 -1
- package/web/.next/static/chunks/{eab3d361f7a24510.js → eb612d2c2229399e.js} +1 -1
- package/web/.next/static/chunks/{885bb8fc631bf477.js → eccf3cd99bc580a4.js} +1 -1
- package/web/.next/static/chunks/{6304540c7cf2b46a.js → fa3bbfc6b0934358.js} +1 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js.map +0 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js.map +0 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js.map +0 -1
- package/web/.next/server/chunks/ssr/_388d1127._.js +0 -4
- package/web/.next/server/chunks/ssr/_98d94927._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js.map +0 -1
- package/web/.next/static/chunks/302f474e4978cc80.js +0 -3
- package/web/.next/static/chunks/626277ca9a4cc477.js +0 -1
- package/web/.next/static/chunks/71a07df9dcb42227.js +0 -2
- /package/web/.next/static/{36ONyC02R4wfFe7iWMQLU → pZ9nz6LLItDQ4YUlAE7tc}/_buildManifest.js +0 -0
- /package/web/.next/static/{36ONyC02R4wfFe7iWMQLU → pZ9nz6LLItDQ4YUlAE7tc}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{36ONyC02R4wfFe7iWMQLU → pZ9nz6LLItDQ4YUlAE7tc}/_ssgManifest.js +0 -0
|
@@ -30,6 +30,7 @@ import { DaemonPidService } from '../services/daemon/daemon-pid.service.js';
|
|
|
30
30
|
import { DeploymentService } from '../services/deployment/deployment.service.js';
|
|
31
31
|
import { AttachmentStorageService } from '../services/attachment-storage.service.js';
|
|
32
32
|
import { GitHubRepositoryService } from '../services/external/github-repository.service.js';
|
|
33
|
+
import { BrowserOpenerService } from '../services/browser-opener.service.js';
|
|
33
34
|
import { AgentExecutorFactory } from '../services/agents/common/agent-executor-factory.service.js';
|
|
34
35
|
import { AgentExecutorProvider } from '../services/agents/common/agent-executor-provider.service.js';
|
|
35
36
|
import { StructuredAgentCallerService } from '../services/agents/common/structured-agent-caller.service.js';
|
|
@@ -97,6 +98,7 @@ import { RebaseFeatureOnMainUseCase } from '../../application/use-cases/features
|
|
|
97
98
|
import { GetBranchSyncStatusUseCase } from '../../application/use-cases/features/get-branch-sync-status.use-case.js';
|
|
98
99
|
import { ConflictResolutionService } from '../services/agents/conflict-resolution/conflict-resolution.service.js';
|
|
99
100
|
import { AutoResolveMergedBranchesUseCase } from '../../application/use-cases/features/auto-resolve-merged-branches.use-case.js';
|
|
101
|
+
import { ReparentFeatureUseCase } from '../../application/use-cases/features/reparent-feature.use-case.js';
|
|
100
102
|
// Interactive session use cases
|
|
101
103
|
import { StartInteractiveSessionUseCase } from '../../application/use-cases/interactive/start-interactive-session.use-case.js';
|
|
102
104
|
import { SendInteractiveMessageUseCase } from '../../application/use-cases/interactive/send-interactive-message.use-case.js';
|
|
@@ -287,6 +289,10 @@ export async function initializeContainer() {
|
|
|
287
289
|
return new NotificationService(bus, desktopNotif);
|
|
288
290
|
},
|
|
289
291
|
});
|
|
292
|
+
// Register browser opener service
|
|
293
|
+
container.register('IBrowserOpener', {
|
|
294
|
+
useFactory: () => new BrowserOpenerService(),
|
|
295
|
+
});
|
|
290
296
|
// Register use cases (singletons for performance)
|
|
291
297
|
container.registerSingleton(InitializeSettingsUseCase);
|
|
292
298
|
container.registerSingleton(LoadSettingsUseCase);
|
|
@@ -345,6 +351,7 @@ export async function initializeContainer() {
|
|
|
345
351
|
container.registerSingleton(RebaseFeatureOnMainUseCase);
|
|
346
352
|
container.registerSingleton(GetBranchSyncStatusUseCase);
|
|
347
353
|
container.registerSingleton(AutoResolveMergedBranchesUseCase);
|
|
354
|
+
container.registerSingleton(ReparentFeatureUseCase);
|
|
348
355
|
// Session repositories (per-AgentType string tokens)
|
|
349
356
|
container.register(`IAgentSessionRepository:${AgentType.ClaudeCode}`, {
|
|
350
357
|
useFactory: () => new ClaudeCodeSessionRepository(),
|
|
@@ -483,6 +490,9 @@ export async function initializeContainer() {
|
|
|
483
490
|
container.register('AutoResolveMergedBranchesUseCase', {
|
|
484
491
|
useFactory: (c) => c.resolve(AutoResolveMergedBranchesUseCase),
|
|
485
492
|
});
|
|
493
|
+
container.register('ReparentFeatureUseCase', {
|
|
494
|
+
useFactory: (c) => c.resolve(ReparentFeatureUseCase),
|
|
495
|
+
});
|
|
486
496
|
// Register interactive session infrastructure
|
|
487
497
|
container.register('IInteractiveSessionRepository', {
|
|
488
498
|
useFactory: (c) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-agent-graph.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAOpG,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-agent-graph.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAOpG,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAelF,OAAO,EAAE,sBAAsB,EAAE,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,cAAc,CAAC;IACzB,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;CACjD;AAwJD;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,qBAAqB,GAAG,cAAc,EACtD,YAAY,CAAC,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAsFnC"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.js
CHANGED
|
@@ -11,7 +11,7 @@ import { createRepairNode } from './nodes/repair.node.js';
|
|
|
11
11
|
import { validateSpecAnalyze, validateSpecRequirements } from './nodes/schemas/spec.schema.js';
|
|
12
12
|
import { validateResearch } from './nodes/schemas/research.schema.js';
|
|
13
13
|
import { validatePlan, validateTasks } from './nodes/schemas/plan.schema.js';
|
|
14
|
-
import { readSpecFile, safeYamlLoad, createNodeLogger, getCompletedPhases, } from './nodes/node-helpers.js';
|
|
14
|
+
import { readSpecFile, safeYamlLoad, createNodeLogger, getCompletedPhases, clearCompletedPhase, } from './nodes/node-helpers.js';
|
|
15
15
|
// Re-export state types for consumers
|
|
16
16
|
export { FeatureAgentAnnotation } from './state.js';
|
|
17
17
|
/**
|
|
@@ -33,12 +33,26 @@ function routeReexecution(selfNode, nextNode) {
|
|
|
33
33
|
* Factory that creates a conditional edge function for validation routing.
|
|
34
34
|
*
|
|
35
35
|
* Routes to successNode on pass, repairNode on fail, throws after maxRetries.
|
|
36
|
+
*
|
|
37
|
+
* When retries are exhausted, clears the producer node's completedPhases entry
|
|
38
|
+
* before throwing. This ensures that on resume, the producer node re-executes
|
|
39
|
+
* the full agent instead of skipping (because `executeNode` checks
|
|
40
|
+
* completedPhases). Without this, a phase that produced empty/unfilled output
|
|
41
|
+
* would be permanently stuck: the repair node can only fix formatting, not
|
|
42
|
+
* generate content from scratch, and the producer would skip on every retry.
|
|
36
43
|
*/
|
|
37
|
-
function routeValidation(successNode, repairNode, maxRetries = 3) {
|
|
44
|
+
function routeValidation(successNode, repairNode, producerNode, maxRetries = 3) {
|
|
45
|
+
const log = createNodeLogger('routeValidation');
|
|
38
46
|
return (state) => {
|
|
39
47
|
if (state.lastValidationErrors.length === 0)
|
|
40
48
|
return successNode;
|
|
41
49
|
if (state.validationRetries >= maxRetries) {
|
|
50
|
+
// Clear the producer's completed phase so that on resume the producer
|
|
51
|
+
// node re-executes the full agent instead of skipping.
|
|
52
|
+
if (producerNode) {
|
|
53
|
+
log.info(`Clearing completed phase '${producerNode}' so retry re-runs the agent`);
|
|
54
|
+
clearCompletedPhase(state.specDir, producerNode, log);
|
|
55
|
+
}
|
|
42
56
|
throw new Error(`Validation failed after ${maxRetries} repair attempts for '${state.lastValidationTarget}': ${state.lastValidationErrors.join('; ')}`);
|
|
43
57
|
}
|
|
44
58
|
return repairNode;
|
|
@@ -174,16 +188,16 @@ export function createFeatureAgentGraph(depsOrExecutor, checkpointer) {
|
|
|
174
188
|
// --- Edges: linear flow with validation gates ---
|
|
175
189
|
.addEdge(START, 'analyze')
|
|
176
190
|
.addEdge('analyze', 'validate_spec_analyze')
|
|
177
|
-
.addConditionalEdges('validate_spec_analyze', routeValidation('requirements', 'repair_spec_analyze'))
|
|
191
|
+
.addConditionalEdges('validate_spec_analyze', routeValidation('requirements', 'repair_spec_analyze', 'analyze'))
|
|
178
192
|
.addEdge('repair_spec_analyze', 'validate_spec_analyze')
|
|
179
193
|
.addConditionalEdges('requirements', routeReexecution('requirements', 'validate_spec_requirements'))
|
|
180
|
-
.addConditionalEdges('validate_spec_requirements', routeValidation('research', 'repair_spec_requirements'))
|
|
194
|
+
.addConditionalEdges('validate_spec_requirements', routeValidation('research', 'repair_spec_requirements', 'requirements'))
|
|
181
195
|
.addEdge('repair_spec_requirements', 'validate_spec_requirements')
|
|
182
196
|
.addEdge('research', 'validate_research')
|
|
183
|
-
.addConditionalEdges('validate_research', routeValidation('plan', 'repair_research'))
|
|
197
|
+
.addConditionalEdges('validate_research', routeValidation('plan', 'repair_research', 'research'))
|
|
184
198
|
.addEdge('repair_research', 'validate_research')
|
|
185
199
|
.addConditionalEdges('plan', routeReexecution('plan', 'validate_plan_tasks'))
|
|
186
|
-
.addConditionalEdges('validate_plan_tasks', routeValidation('implement', 'repair_plan_tasks'))
|
|
200
|
+
.addConditionalEdges('validate_plan_tasks', routeValidation('implement', 'repair_plan_tasks', 'plan'))
|
|
187
201
|
.addEdge('repair_plan_tasks', 'validate_plan_tasks');
|
|
188
202
|
// --- Merge node: wired when deps are provided ---
|
|
189
203
|
if (deps.mergeNodeDeps) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-agent-worker.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AAEH,OAAO,kBAAkB,CAAC;AAiB1B,OAAO,EAAiC,KAAK,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAW7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAkF1D;AAgCD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAiU/D"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import 'reflect-metadata';
|
|
12
12
|
import { join } from 'node:path';
|
|
13
13
|
import { homedir } from 'node:os';
|
|
14
|
+
import { unlinkSync } from 'node:fs';
|
|
14
15
|
import { Command } from '@langchain/langgraph';
|
|
15
16
|
import { initializeContainer, container } from '../../../di/container.js';
|
|
16
17
|
import { createFeatureAgentGraph } from './feature-agent-graph.js';
|
|
@@ -273,10 +274,32 @@ export async function runWorker(args) {
|
|
|
273
274
|
result = await graph.invoke(new Command({ resume: resumeValue, update: stateUpdate }), graphConfig);
|
|
274
275
|
}
|
|
275
276
|
else if (args.resume) {
|
|
276
|
-
// Resume from error —
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
// Resume from error — delete the stale checkpoint and re-invoke from
|
|
278
|
+
// scratch. Each producer node checks its completedPhases entry and skips
|
|
279
|
+
// if already done, so completed phases replay instantly. The phase that
|
|
280
|
+
// failed has its completedPhases entry cleared by routeValidation (or was
|
|
281
|
+
// never marked complete if the executor threw), so it re-executes fully.
|
|
282
|
+
//
|
|
283
|
+
// Why delete the checkpoint instead of resuming from it:
|
|
284
|
+
// When a validate/repair loop exhausts retries and throws, the checkpoint
|
|
285
|
+
// captures the validation node with maxed-out retries. Resuming from that
|
|
286
|
+
// checkpoint would re-evaluate the same conditional edge and throw again
|
|
287
|
+
// immediately — the user's retry would be stuck in an infinite loop.
|
|
288
|
+
log('Deleting stale checkpoint for fresh resume...');
|
|
289
|
+
try {
|
|
290
|
+
unlinkSync(checkpointPath);
|
|
291
|
+
log('Checkpoint deleted successfully');
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
log('No checkpoint to delete (first run or already cleaned)');
|
|
295
|
+
}
|
|
296
|
+
// Re-create checkpointer after deleting the old DB
|
|
297
|
+
const freshCheckpointer = createCheckpointer(checkpointPath);
|
|
298
|
+
const freshGraph = args.fast
|
|
299
|
+
? createFastFeatureAgentGraph(graphDeps, freshCheckpointer)
|
|
300
|
+
: createFeatureAgentGraph(graphDeps, freshCheckpointer);
|
|
301
|
+
log('Resuming graph with fresh checkpoint...');
|
|
302
|
+
result = await freshGraph.invoke({
|
|
280
303
|
featureId: args.featureId,
|
|
281
304
|
repositoryPath: args.repo,
|
|
282
305
|
worktreePath: args.worktreePath ?? args.repo,
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { type ChildProcess } from 'node:child_process';
|
|
2
|
+
import type { IBrowserOpener } from '../../application/ports/output/services/i-browser-opener.js';
|
|
2
3
|
export interface BrowserOpenerDeps {
|
|
3
4
|
platform: NodeJS.Platform;
|
|
4
5
|
execFile: (cmd: string, args: readonly string[], callback: (error: Error | null) => void) => ChildProcess;
|
|
5
6
|
warn: (msg: string) => void;
|
|
6
7
|
isTTY: boolean;
|
|
7
8
|
}
|
|
8
|
-
export declare class BrowserOpenerService {
|
|
9
|
+
export declare class BrowserOpenerService implements IBrowserOpener {
|
|
9
10
|
private deps;
|
|
10
11
|
constructor(deps?: Partial<BrowserOpenerDeps>);
|
|
11
12
|
open(url: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-opener.service.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/services/browser-opener.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"browser-opener.service.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/services/browser-opener.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6DAA6D,CAAC;AAElG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,QAAQ,EAAE,CACR,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,KACpC,YAAY,CAAC;IAClB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB;AAgBD,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,IAAI,CAAoB;gBAEpB,IAAI,GAAE,OAAO,CAAC,iBAAiB,CAAM;IAIjD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAcxB"}
|
|
@@ -62,6 +62,7 @@ export declare class GitPrService implements IGitPrService {
|
|
|
62
62
|
private parseDiffStat;
|
|
63
63
|
syncMain(cwd: string, baseBranch: string): Promise<void>;
|
|
64
64
|
rebaseOnMain(cwd: string, featureBranch: string, baseBranch: string): Promise<void>;
|
|
65
|
+
rebaseOnBranch(cwd: string, featureBranch: string, targetBranch: string): Promise<void>;
|
|
65
66
|
getConflictedFiles(cwd: string): Promise<string[]>;
|
|
66
67
|
stageFiles(cwd: string, files: string[]): Promise<void>;
|
|
67
68
|
rebaseContinue(cwd: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-pr.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/git-pr.service.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"git-pr.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/git-pr.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -807,6 +807,59 @@ let GitPrService = class GitPrService {
|
|
|
807
807
|
throw new GitPrError(`Rebase of '${featureBranch}' onto '${baseBranch}' failed: ${message}`, GitPrErrorCode.GIT_ERROR, cause);
|
|
808
808
|
}
|
|
809
809
|
}
|
|
810
|
+
async rebaseOnBranch(cwd, featureBranch, targetBranch) {
|
|
811
|
+
// Check for dirty worktree before starting
|
|
812
|
+
const dirty = await this.hasUncommittedChanges(cwd);
|
|
813
|
+
if (dirty) {
|
|
814
|
+
throw new GitPrError(`Cannot rebase: working directory has uncommitted changes. ` +
|
|
815
|
+
`Please commit or stash your changes before rebasing.`, GitPrErrorCode.GIT_ERROR);
|
|
816
|
+
}
|
|
817
|
+
// Fetch the target branch from remote — it may not be locally available
|
|
818
|
+
try {
|
|
819
|
+
await this.execFile('git', ['fetch', 'origin', targetBranch], { cwd });
|
|
820
|
+
}
|
|
821
|
+
catch (error) {
|
|
822
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
823
|
+
const cause = error instanceof Error ? error : undefined;
|
|
824
|
+
throw new GitPrError(`Failed to fetch target branch '${targetBranch}': ${message}`, GitPrErrorCode.GIT_ERROR, cause);
|
|
825
|
+
}
|
|
826
|
+
// Checkout the feature branch
|
|
827
|
+
try {
|
|
828
|
+
await this.execFile('git', ['checkout', featureBranch], { cwd });
|
|
829
|
+
}
|
|
830
|
+
catch (error) {
|
|
831
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
832
|
+
const cause = error instanceof Error ? error : undefined;
|
|
833
|
+
if (message.includes('did not match') ||
|
|
834
|
+
message.includes('not a commit') ||
|
|
835
|
+
message.includes('pathspec')) {
|
|
836
|
+
throw new GitPrError(`Branch '${featureBranch}' not found.`, GitPrErrorCode.BRANCH_NOT_FOUND, cause);
|
|
837
|
+
}
|
|
838
|
+
throw new GitPrError(`Failed to checkout '${featureBranch}': ${message}`, GitPrErrorCode.GIT_ERROR, cause);
|
|
839
|
+
}
|
|
840
|
+
// Rebase onto origin/<targetBranch>
|
|
841
|
+
const rebaseTarget = `origin/${targetBranch}`;
|
|
842
|
+
try {
|
|
843
|
+
await this.execFile('git', ['rebase', rebaseTarget], { cwd });
|
|
844
|
+
}
|
|
845
|
+
catch (error) {
|
|
846
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
847
|
+
const cause = error instanceof Error ? error : undefined;
|
|
848
|
+
// Detect rebase conflict from git stderr/exit code
|
|
849
|
+
if (message.includes('CONFLICT') || message.includes('could not apply')) {
|
|
850
|
+
let conflictedFiles = [];
|
|
851
|
+
try {
|
|
852
|
+
conflictedFiles = await this.getConflictedFiles(cwd);
|
|
853
|
+
}
|
|
854
|
+
catch {
|
|
855
|
+
// Failed to get conflicted files — still report the conflict
|
|
856
|
+
}
|
|
857
|
+
const fileList = conflictedFiles.length > 0 ? ` Conflicted files: ${conflictedFiles.join(', ')}` : '';
|
|
858
|
+
throw new GitPrError(`Rebase of '${featureBranch}' onto '${targetBranch}' encountered conflicts.${fileList}`, GitPrErrorCode.REBASE_CONFLICT, cause);
|
|
859
|
+
}
|
|
860
|
+
throw new GitPrError(`Rebase of '${featureBranch}' onto '${targetBranch}' failed: ${message}`, GitPrErrorCode.GIT_ERROR, cause);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
810
863
|
async getConflictedFiles(cwd) {
|
|
811
864
|
try {
|
|
812
865
|
const { stdout } = await this.execFile('git', ['diff', '--name-only', '--diff-filter=U'], {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* - Title truncated to 100 chars, body to 500 chars
|
|
10
10
|
* - Errors are caught and logged (never thrown)
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
import type { IDesktopNotifier } from '../../../application/ports/output/services/i-desktop-notifier.js';
|
|
13
|
+
export declare class DesktopNotifier implements IDesktopNotifier {
|
|
13
14
|
/**
|
|
14
15
|
* Send a native OS desktop notification.
|
|
15
16
|
*
|
package/dist/packages/core/src/infrastructure/services/notifications/desktop-notifier.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"desktop-notifier.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/notifications/desktop-notifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"desktop-notifier.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/notifications/desktop-notifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kEAAkE,CAAC;AAMzG,qBAAa,eAAgB,YAAW,gBAAgB;IACtD;;;;;OAKG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAYvC,OAAO,CAAC,QAAQ;CAIjB"}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* 4. Wait briefly to confirm the child is alive; surface stderr on crash
|
|
15
15
|
* 5. Write daemon.json atomically via IDaemonService
|
|
16
16
|
* 6. Print formatted URL to stdout
|
|
17
|
-
* 7. Open browser via
|
|
17
|
+
* 7. Open browser via IBrowserOpener (resolved from DI container)
|
|
18
18
|
*/
|
|
19
19
|
export interface StartDaemonOptions {
|
|
20
20
|
port?: number;
|
|
@@ -14,14 +14,13 @@
|
|
|
14
14
|
* 4. Wait briefly to confirm the child is alive; surface stderr on crash
|
|
15
15
|
* 5. Write daemon.json atomically via IDaemonService
|
|
16
16
|
* 6. Print formatted URL to stdout
|
|
17
|
-
* 7. Open browser via
|
|
17
|
+
* 7. Open browser via IBrowserOpener (resolved from DI container)
|
|
18
18
|
*/
|
|
19
19
|
import { spawn } from 'node:child_process';
|
|
20
20
|
import { closeSync, openSync, renameSync, existsSync } from 'node:fs';
|
|
21
21
|
import http from 'node:http';
|
|
22
22
|
import { container } from '../../../../../packages/core/src/infrastructure/di/container.js';
|
|
23
23
|
import { findAvailablePort, DEFAULT_PORT } from '../../../../../packages/core/src/infrastructure/services/port.service.js';
|
|
24
|
-
import { BrowserOpenerService } from '../../../../../packages/core/src/infrastructure/services/browser-opener.service.js';
|
|
25
24
|
import { getDaemonLogPath } from '../../../../../packages/core/src/infrastructure/services/filesystem/shep-directory.service.js';
|
|
26
25
|
import { fmt, messages, spinner } from '../../ui/index.js';
|
|
27
26
|
import { getCliI18n } from '../../i18n.js';
|
|
@@ -116,7 +115,7 @@ export async function startDaemon(opts = {}) {
|
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
messages.newline();
|
|
119
|
-
const opener =
|
|
118
|
+
const opener = container.resolve('IBrowserOpener');
|
|
120
119
|
opener.open(url);
|
|
121
120
|
}
|
|
122
121
|
/**
|
|
@@ -23,7 +23,6 @@ import { initializeNotificationWatcher, getNotificationWatcher, } from '../../..
|
|
|
23
23
|
import { initializePrSyncWatcher, getPrSyncWatcher, } from '../../../../packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js';
|
|
24
24
|
import { initializeAutoArchiveWatcher, getAutoArchiveWatcher, } from '../../../../packages/core/src/infrastructure/services/auto-archive/auto-archive-watcher.service.js';
|
|
25
25
|
import { getExistingConnection } from '../../../../packages/core/src/infrastructure/persistence/sqlite/connection.js';
|
|
26
|
-
import { BrowserOpenerService } from '../../../../packages/core/src/infrastructure/services/browser-opener.service.js';
|
|
27
26
|
import { colors, fmt, messages } from '../ui/index.js';
|
|
28
27
|
import { getCliI18n } from '../i18n.js';
|
|
29
28
|
function parsePort(value) {
|
|
@@ -83,7 +82,7 @@ Examples:
|
|
|
83
82
|
messages.newline();
|
|
84
83
|
// Auto-open browser (unless --no-open)
|
|
85
84
|
if (options.open !== false) {
|
|
86
|
-
const opener =
|
|
85
|
+
const opener = container.resolve('IBrowserOpener');
|
|
87
86
|
opener.open(url);
|
|
88
87
|
}
|
|
89
88
|
// Handle graceful shutdown via SIGINT/SIGTERM
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reparent-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/reparent-feature.ts"],"names":[],"mappings":"AAKA,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAa/C"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
import { resolve } from '../../lib/server-container.js';
|
|
3
|
+
export async function reparentFeature(featureId, parentId) {
|
|
4
|
+
if (!featureId.trim()) {
|
|
5
|
+
return { success: false, error: 'Feature id is required' };
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
const useCase = resolve('ReparentFeatureUseCase');
|
|
9
|
+
await useCase.execute({ featureId, parentId });
|
|
10
|
+
return { success: true };
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
const message = error instanceof Error ? error.message : 'Failed to reparent feature';
|
|
14
|
+
return { success: false, error: message };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAmDnE,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,
|
|
1
|
+
{"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAmDnE,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CAunBA"}
|
|
@@ -85,7 +85,7 @@ export function FeatureNode({ data, selected, }) {
|
|
|
85
85
|
const deployAction = useDeployAction(deployTarget);
|
|
86
86
|
const isDeployActive = deployAction.status === 'Booting' || deployAction.status === 'Ready';
|
|
87
87
|
const isDeployReady = deployAction.status === 'Ready';
|
|
88
|
-
return (_jsxs("div", { className: "animate-in fade-in group relative duration-300", style: { direction: isRtl ? 'rtl' : 'ltr' }, children: [
|
|
88
|
+
return (_jsxs("div", { className: "animate-in fade-in group relative duration-300", style: { direction: isRtl ? 'rtl' : 'ltr' }, children: [_jsx(Handle, { type: "target", position: targetHandlePos, isConnectable: true, className: "opacity-0!", style: { top: 70 } }), _jsx("div", { className: "absolute -start-14 top-0 bottom-0 flex items-center justify-center ps-4 pe-3 opacity-0 transition-opacity group-hover:opacity-100", onPointerDown: (e) => e.stopPropagation(), children: _jsxs("div", { className: "flex flex-col items-center gap-2", children: [data.onArchive &&
|
|
89
89
|
data.featureId &&
|
|
90
90
|
data.state !== 'deleting' &&
|
|
91
91
|
data.state !== 'archived' ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": t('featureNode.archiveFeature'), "data-testid": "feature-node-archive-button", onClick: (e) => {
|
|
@@ -165,5 +165,5 @@ export function FeatureNode({ data, selected, }) {
|
|
|
165
165
|
}, className: "nodrag cursor-pointer text-[11px] font-medium", children: [_jsx(Play, { className: "h-3 w-3" }), t('featureNode.start')] })) : null] })] })] }), data.onAction && data.state !== 'deleting' ? (_jsx(Handle, { type: "source", position: sourceHandlePos, className: "h-0! w-0! border-0! bg-transparent!", style: { top: 70 }, children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t('featureNode.addFeature'), "data-testid": "feature-node-action-button", onClick: (e) => {
|
|
166
166
|
e.stopPropagation();
|
|
167
167
|
data.onAction?.();
|
|
168
|
-
}, className: "nodrag absolute start-1/2 top-1/2 flex h-6 w-6 -translate-x-1/2 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-blue-500 text-white opacity-0 shadow-md transition-opacity group-hover:opacity-100 hover:bg-blue-600", children: _jsx(Plus, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { side: "right", children: t('featureNode.addFeature') })] }) }) })) :
|
|
168
|
+
}, className: "nodrag absolute start-1/2 top-1/2 flex h-6 w-6 -translate-x-1/2 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-blue-500 text-white opacity-0 shadow-md transition-opacity group-hover:opacity-100 hover:bg-blue-600", children: _jsx(Plus, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { side: "right", children: t('featureNode.addFeature') })] }) }) })) : (_jsx(Handle, { type: "source", position: sourceHandlePos, isConnectable: true, className: "opacity-0!", style: { top: 70 } }))] }));
|
|
169
169
|
}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAgC5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAgC5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CAmezF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -36,7 +36,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
36
36
|
const { fitView } = useReactFlow();
|
|
37
37
|
const drawerTimerRef = useRef(null);
|
|
38
38
|
const { defaultViewport, onMoveEnd: handleViewportChange, resetViewport, } = useViewportPersistence();
|
|
39
|
-
const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleArchiveFeature, handleDeleteFeature, handleRetryFeature, handleStartFeature, handleStopFeature, handleUnarchiveFeature, handleDeleteRepository, createFeatureNode, showArchived, setShowArchived, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
|
|
39
|
+
const { nodes, edges, onNodesChange, handleConnect, handleEdgesDelete, handleAddRepository, handleArchiveFeature, handleDeleteFeature, handleRetryFeature, handleStartFeature, handleStopFeature, handleUnarchiveFeature, handleDeleteRepository, createFeatureNode, showArchived, setShowArchived, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
|
|
40
40
|
// Publish sidebar features + repo state to context
|
|
41
41
|
const { setFeatures: setSidebarFeatures, setHasRepositories: setSidebarHasRepos } = useSidebarFeaturesContext();
|
|
42
42
|
const featureNodes = useMemo(() => nodes.filter((n) => n.type === 'featureNode'), [nodes]);
|
|
@@ -367,7 +367,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
367
367
|
featureFlags.githubImport,
|
|
368
368
|
]);
|
|
369
369
|
const canvasToolbar = (_jsx(CanvasToolbar, { showArchived: showArchived, onToggleArchived: () => setShowArchived(!showArchived), onResetViewport: resetViewport }));
|
|
370
|
-
return (_jsxs(_Fragment, { children: [_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? edges : [], selectedFeatureId: selectedFeatureId, selectedRepository: selectedRepository, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, toolbar: canvasToolbar, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }) }), showCanvas ? _jsx(CreateFab, { actions: fabActions }) : null] }));
|
|
370
|
+
return (_jsxs(_Fragment, { children: [_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? edges : [], selectedFeatureId: selectedFeatureId, selectedRepository: selectedRepository, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onEdgesDelete: handleEdgesDelete, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, toolbar: canvasToolbar, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }) }), showCanvas ? _jsx(CreateFab, { actions: fabActions }) : null] }));
|
|
371
371
|
}
|
|
372
372
|
/** (+) FAB that tracks sidebar width via CSS var + transition.
|
|
373
373
|
* When fabLayout.swapPosition is true, moves to the end side (right in LTR). */
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface ControlCenterState {
|
|
|
9
9
|
edges: Edge[];
|
|
10
10
|
onNodesChange: (changes: NodeChange<CanvasNodeType>[]) => void;
|
|
11
11
|
handleConnect: (connection: Connection) => void;
|
|
12
|
+
handleEdgesDelete: (edges: Edge[]) => void;
|
|
12
13
|
handleAddRepository: (path: string) => {
|
|
13
14
|
wasEmpty: boolean;
|
|
14
15
|
repoPath: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAkBjC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QACrC,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,OAAO,KACd,IAAI,CAAC;IACV,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,yDAAyD;IACzD,YAAY,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;
|
|
1
|
+
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAkBjC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAC3C,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QACrC,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,OAAO,KACd,IAAI,CAAC;IACV,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,yDAAyD;IACzD,YAAY,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAWD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAwoBpB"}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js
CHANGED
|
@@ -21,6 +21,8 @@ const log = createLogger('[Polling]');
|
|
|
21
21
|
const POLL_INTERVAL_MS = 15_000;
|
|
22
22
|
/** Must match the message string emitted by the SSE route in agent-events/route.ts */
|
|
23
23
|
const METADATA_UPDATED_MESSAGE = 'Feature metadata updated';
|
|
24
|
+
/** Lifecycle states that are terminal and cannot be reparented. */
|
|
25
|
+
const TERMINAL_STATES = new Set(['done', 'archived', 'deleting']);
|
|
24
26
|
let nextFeatureId = 0;
|
|
25
27
|
let nextRepoTempId = 0;
|
|
26
28
|
export function useControlCenterState(initialNodes, initialEdges) {
|
|
@@ -29,7 +31,7 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
29
31
|
const createSound = useSoundAction('create');
|
|
30
32
|
// Archive toggle: persists during session, resets on page reload (FR-10)
|
|
31
33
|
const [showArchived, setShowArchived] = useState(false);
|
|
32
|
-
const { nodes, edges, reconcile, updateFeature, addPendingFeature, removeFeature, restoreFeature, addRepository: addRepositoryToMap, removeRepository, replaceRepository, getFeatureRepositoryPath, getRepositoryData, getRepoMapSize, setCallbacks, beginMutation, endMutation, isMutating, } = useGraphState(initialNodes, initialEdges, showArchived);
|
|
34
|
+
const { nodes, edges, reconcile, updateFeature, addPendingFeature, removeFeature, restoreFeature, addRepository: addRepositoryToMap, removeRepository, replaceRepository, getFeatureRepositoryPath, getFeatureEntry, getRepositoryData, getRepoMapSize, setCallbacks, reparentFeature, beginMutation, endMutation, isMutating, } = useGraphState(initialNodes, initialEdges, showArchived);
|
|
33
35
|
// Refs for stable access to latest nodes/edges without callback recreation
|
|
34
36
|
const nodesRef = useRef(nodes);
|
|
35
37
|
const edgesRef = useRef(edges);
|
|
@@ -206,9 +208,49 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
206
208
|
const onNodesChange = useCallback((_changes) => {
|
|
207
209
|
// Intentional no-op: domain Maps are the source of truth.
|
|
208
210
|
}, []);
|
|
209
|
-
const handleConnect = useCallback((
|
|
210
|
-
|
|
211
|
-
|
|
211
|
+
const handleConnect = useCallback((connection) => {
|
|
212
|
+
const { source, target } = connection;
|
|
213
|
+
if (!source || !target)
|
|
214
|
+
return;
|
|
215
|
+
// Reject non-feature-to-feature connections (repo group nodes don't have 'feat-' prefix)
|
|
216
|
+
if (!source.startsWith('feat-') || !target.startsWith('feat-')) {
|
|
217
|
+
toast.error('Only feature-to-feature connections are allowed');
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// Reject self-connections
|
|
221
|
+
if (source === target) {
|
|
222
|
+
toast.error('A feature cannot depend on itself');
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
// Look up child (target) and parent (source) entries for validation
|
|
226
|
+
const childEntry = getFeatureEntry(target);
|
|
227
|
+
const parentEntry = getFeatureEntry(source);
|
|
228
|
+
if (!childEntry || !parentEntry) {
|
|
229
|
+
toast.error('Feature not found');
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// Reject cross-repo connections
|
|
233
|
+
if (childEntry.data.repositoryPath !== parentEntry.data.repositoryPath) {
|
|
234
|
+
toast.error('Features must be in the same repository to form a dependency');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
// Reject if child is in a terminal lifecycle state
|
|
238
|
+
if (TERMINAL_STATES.has(childEntry.data.state)) {
|
|
239
|
+
toast.error('Completed features cannot be reparented');
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
// All client-side checks passed — delegate to reparentFeature for optimistic update + server call
|
|
243
|
+
reparentFeature(target, source);
|
|
244
|
+
}, [getFeatureEntry, reparentFeature]);
|
|
245
|
+
const handleEdgesDelete = useCallback((deletedEdges) => {
|
|
246
|
+
for (const edge of deletedEdges) {
|
|
247
|
+
// Only process dependency edges — ignore repo-to-feature edges
|
|
248
|
+
if (edge.type !== 'dependencyEdge')
|
|
249
|
+
continue;
|
|
250
|
+
// target is the child feature node ID
|
|
251
|
+
reparentFeature(edge.target, null);
|
|
252
|
+
}
|
|
253
|
+
}, [reparentFeature]);
|
|
212
254
|
const createFeatureNode = useCallback((sourceNodeId, dataOverride, edgeType) => {
|
|
213
255
|
// Use real feature ID when available (from server), otherwise temp ID
|
|
214
256
|
const id = dataOverride?.featureId
|
|
@@ -501,6 +543,7 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
501
543
|
edges,
|
|
502
544
|
onNodesChange,
|
|
503
545
|
handleConnect,
|
|
546
|
+
handleEdgesDelete,
|
|
504
547
|
handleAddRepository,
|
|
505
548
|
handleArchiveFeature,
|
|
506
549
|
handleLayout,
|
|
@@ -2,6 +2,7 @@ import type { EdgeProps } from '@xyflow/react';
|
|
|
2
2
|
/**
|
|
3
3
|
* Custom React Flow edge for parent→child feature dependencies.
|
|
4
4
|
* Uses bezier curves and dashed style matching repo→feature edges.
|
|
5
|
+
* Shows a delete button on hover for unparenting.
|
|
5
6
|
*/
|
|
6
7
|
export declare function DependencyEdge(props: EdgeProps): import("react/jsx-runtime").JSX.Element;
|
|
7
8
|
//# sourceMappingURL=dependency-edge.d.ts.map
|
package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-edge.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/dependency-edge.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dependency-edge.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/dependency-edge.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAG/C;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,2CAwD9C"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { BaseEdge, EdgeLabelRenderer, getBezierPath, useReactFlow } from '@xyflow/react';
|
|
5
|
+
import { X } from 'lucide-react';
|
|
4
6
|
/**
|
|
5
7
|
* Custom React Flow edge for parent→child feature dependencies.
|
|
6
8
|
* Uses bezier curves and dashed style matching repo→feature edges.
|
|
9
|
+
* Shows a delete button on hover for unparenting.
|
|
7
10
|
*/
|
|
8
11
|
export function DependencyEdge(props) {
|
|
9
|
-
const [
|
|
12
|
+
const [hovered, setHovered] = useState(false);
|
|
13
|
+
const { deleteElements } = useReactFlow();
|
|
14
|
+
const [edgePath, labelX, labelY] = getBezierPath({
|
|
10
15
|
sourceX: props.sourceX,
|
|
11
16
|
sourceY: props.sourceY,
|
|
12
17
|
targetX: props.targetX,
|
|
@@ -14,7 +19,14 @@ export function DependencyEdge(props) {
|
|
|
14
19
|
sourcePosition: props.sourcePosition,
|
|
15
20
|
targetPosition: props.targetPosition,
|
|
16
21
|
});
|
|
17
|
-
return (_jsx(BaseEdge, { id: props.id, path: edgePath, style: {
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
return (_jsxs(_Fragment, { children: [_jsx("path", { d: edgePath, fill: "none", stroke: "transparent", strokeWidth: 20, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false) }), _jsx(BaseEdge, { id: props.id, path: edgePath, style: {
|
|
23
|
+
strokeDasharray: '5 5',
|
|
24
|
+
...(props.selected && { stroke: '#3b82f6', strokeWidth: 2 }),
|
|
25
|
+
} }), hovered || props.selected ? (_jsx(EdgeLabelRenderer, { children: _jsx("button", { type: "button", "aria-label": "Remove dependency", "data-testid": "dependency-edge-delete-button", className: "nodrag nopan pointer-events-auto flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border bg-white text-gray-500 shadow-sm transition-colors hover:border-red-300 hover:bg-red-50 hover:text-red-500 dark:bg-neutral-800 dark:text-gray-400 dark:hover:border-red-500 dark:hover:bg-red-900/30 dark:hover:text-red-400", style: {
|
|
26
|
+
position: 'absolute',
|
|
27
|
+
transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
|
|
28
|
+
}, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), onClick: (e) => {
|
|
29
|
+
e.stopPropagation();
|
|
30
|
+
deleteElements({ edges: [{ id: props.id }] });
|
|
31
|
+
}, children: _jsx(X, { className: "h-3 w-3" }) }) })) : null] }));
|
|
20
32
|
}
|
package/dist/src/presentation/web/components/features/features-canvas/dependency-edge.stories.d.ts
CHANGED
|
@@ -2,5 +2,8 @@ import type { Meta, StoryObj } from '@storybook/react';
|
|
|
2
2
|
import '@xyflow/react/dist/style.css';
|
|
3
3
|
declare const meta: Meta;
|
|
4
4
|
export default meta;
|
|
5
|
+
/** Default dependency edge — hover to reveal delete button. */
|
|
5
6
|
export declare const Default: StoryObj;
|
|
7
|
+
/** Edge in selected state — shows delete button and blue highlight stroke. */
|
|
8
|
+
export declare const Selected: StoryObj;
|
|
6
9
|
//# sourceMappingURL=dependency-edge.stories.d.ts.map
|