@opengsd/gsd-pi 1.4.0-dev.c18009cd → 1.5.0-dev.553dc518
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/README.md +10 -10
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/closeout.js +97 -5
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -3
- package/dist/resources/extensions/gsd/auto/pre-dispatch.js +6 -3
- package/dist/resources/extensions/gsd/auto/unit-phase.js +5 -9
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +4 -5
- package/dist/resources/extensions/gsd/auto-start.js +3 -2
- package/dist/resources/extensions/gsd/auto-worktree-branch-lifecycle.js +189 -0
- package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +133 -0
- package/dist/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.js +35 -0
- package/dist/resources/extensions/gsd/auto-worktree-creation.js +130 -0
- package/dist/resources/extensions/gsd/auto-worktree-entry.js +118 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-already-merged.js +98 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-branch-head.js +52 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-cleanup.js +87 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-code-changes.js +46 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-db-ready.js +68 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-integration-branch.js +51 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-message.js +106 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-pre-teardown.js +64 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge-stash.js +168 -0
- package/dist/resources/extensions/gsd/auto-worktree-merge.js +302 -0
- package/dist/resources/extensions/gsd/auto-worktree-milestone-shelter.js +119 -0
- package/dist/resources/extensions/gsd/auto-worktree-path-resolution.js +5 -0
- package/dist/resources/extensions/gsd/auto-worktree-path-utils.js +5 -0
- package/dist/resources/extensions/gsd/auto-worktree-resource-version.js +41 -0
- package/dist/resources/extensions/gsd/auto-worktree-runtime-cleanup.js +99 -0
- package/dist/resources/extensions/gsd/auto-worktree-session-registry.js +57 -0
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +249 -0
- package/dist/resources/extensions/gsd/auto-worktree-teardown.js +120 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +20 -2073
- package/dist/resources/extensions/gsd/auto.js +9 -3
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +19 -1
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +118 -21
- package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +3 -3
- package/dist/resources/extensions/gsd/db/queries.js +9 -9
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +93 -11
- package/dist/resources/extensions/gsd/flat-phase-migration.js +14 -3
- package/dist/resources/extensions/gsd/forensics.js +1 -1
- package/dist/resources/extensions/gsd/git-conflict-resolve.js +2 -2
- package/dist/resources/extensions/gsd/git-service.js +45 -0
- package/dist/resources/extensions/gsd/gsd-db.js +11 -0
- package/dist/resources/extensions/gsd/guided-flow.js +6 -10
- package/dist/resources/extensions/gsd/markdown-renderer.js +15 -3
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +11 -0
- package/dist/resources/extensions/gsd/milestone-settlement.js +1 -1
- package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -1
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +82 -0
- package/dist/resources/extensions/gsd/prompts/system.md +6 -6
- package/dist/resources/extensions/gsd/quick.js +12 -3
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +2 -1
- package/dist/resources/extensions/gsd/state/derive/from-db.js +88 -153
- package/dist/resources/extensions/gsd/tool-contract.js +14 -0
- package/dist/resources/extensions/gsd/unit-registry.js +12 -2
- package/dist/resources/extensions/gsd/unmerged-milestone-guard.js +1 -1
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -1
- package/dist/resources/extensions/gsd/workspace-git-preflight.js +2 -2
- package/dist/resources/extensions/gsd/worktree-command.js +1 -1
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +14 -9
- package/dist/resources/extensions/gsd/worktree-reentry.js +2 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +24 -35
- package/integrations/hermes/tests/test_gsd_client_timeout.py +4 -4
- package/package.json +6 -6
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/export-html/template.js +53 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +14 -9
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/transform-messages.js +7 -3
- package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
- package/packages/pi-ai/dist/tool-result-content.d.ts +3 -0
- package/packages/pi-ai/dist/tool-result-content.d.ts.map +1 -0
- package/packages/pi-ai/dist/tool-result-content.js +62 -0
- package/packages/pi-ai/dist/tool-result-content.js.map +1 -0
- package/packages/pi-ai/dist/types.d.ts +8 -20
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/core/export-html/template.js +53 -4
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto/closeout.ts +114 -7
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -3
- package/src/resources/extensions/gsd/auto/pre-dispatch.ts +6 -3
- package/src/resources/extensions/gsd/auto/unit-phase.ts +5 -9
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +4 -5
- package/src/resources/extensions/gsd/auto-start.ts +4 -2
- package/src/resources/extensions/gsd/auto-worktree-branch-lifecycle.ts +237 -0
- package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +166 -0
- package/src/resources/extensions/gsd/auto-worktree-conflict-auto-resolve.ts +37 -0
- package/src/resources/extensions/gsd/auto-worktree-creation.ts +171 -0
- package/src/resources/extensions/gsd/auto-worktree-entry.ts +154 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-already-merged.ts +161 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-branch-head.ts +83 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-cleanup.ts +132 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-code-changes.ts +71 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-db-ready.ts +112 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-integration-branch.ts +99 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-message.ts +166 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-pre-teardown.ts +93 -0
- package/src/resources/extensions/gsd/auto-worktree-merge-stash.ts +213 -0
- package/src/resources/extensions/gsd/auto-worktree-merge.ts +391 -0
- package/src/resources/extensions/gsd/auto-worktree-milestone-shelter.ts +159 -0
- package/src/resources/extensions/gsd/auto-worktree-path-resolution.ts +6 -0
- package/src/resources/extensions/gsd/auto-worktree-path-utils.ts +10 -0
- package/src/resources/extensions/gsd/auto-worktree-resource-version.ts +44 -0
- package/src/resources/extensions/gsd/auto-worktree-runtime-cleanup.ts +119 -0
- package/src/resources/extensions/gsd/auto-worktree-session-registry.ts +71 -0
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +370 -0
- package/src/resources/extensions/gsd/auto-worktree-teardown.ts +161 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +69 -2429
- package/src/resources/extensions/gsd/auto.ts +11 -17
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +19 -1
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +152 -21
- package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +3 -3
- package/src/resources/extensions/gsd/db/queries.ts +9 -9
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +109 -10
- package/src/resources/extensions/gsd/flat-phase-migration.ts +14 -3
- package/src/resources/extensions/gsd/forensics.ts +1 -1
- package/src/resources/extensions/gsd/git-conflict-resolve.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +53 -0
- package/src/resources/extensions/gsd/gsd-db.ts +13 -0
- package/src/resources/extensions/gsd/guided-flow.ts +7 -11
- package/src/resources/extensions/gsd/markdown-renderer.ts +15 -3
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +15 -0
- package/src/resources/extensions/gsd/milestone-settlement.ts +1 -1
- package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +3 -1
- package/src/resources/extensions/gsd/preferences-types.ts +30 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +69 -0
- package/src/resources/extensions/gsd/prompts/system.md +6 -6
- package/src/resources/extensions/gsd/quick.ts +11 -3
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -1
- package/src/resources/extensions/gsd/state/derive/from-db.ts +201 -157
- package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-already-merged.test.ts +177 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-branch-head.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-cleanup.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-code-changes.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-db-ready.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-integration-branch.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-message.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-pre-teardown.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-merge-stash.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-shelter.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/auto-worktree-resource-version.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +44 -1
- package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +4 -6
- package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +2 -5
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/merge-strategy-regular.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +2 -4
- package/src/resources/extensions/gsd/tests/merge-closeout-consistency-gate.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +439 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +1 -4
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +3 -5
- package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/system-flat-phase-layout.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/unit-registry.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +1 -3
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +1 -1
- package/src/resources/extensions/gsd/tool-contract.ts +29 -0
- package/src/resources/extensions/gsd/unit-registry.ts +16 -2
- package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +1 -1
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -1
- package/src/resources/extensions/gsd/workspace-git-preflight.ts +2 -2
- package/src/resources/extensions/gsd/worktree-command.ts +1 -1
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +19 -15
- package/src/resources/extensions/gsd/worktree-reentry.ts +2 -1
- /package/dist/web/standalone/.next/static/{L2UMqXELiDH3oz-7yguXp → ZpFDazP-38PXBPiI_LdZf}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{L2UMqXELiDH3oz-7yguXp → ZpFDazP-38PXBPiI_LdZf}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// gsd-pi — Milestone merge integration-branch preparation.
|
|
2
|
+
//
|
|
3
|
+
// Owns branch-selection safety before the merge transaction touches the project
|
|
4
|
+
// root: resolve integration branch, fail closed on self-merge metadata, clear
|
|
5
|
+
// transient milestone state, reject detached HEAD, and checkout when needed.
|
|
6
|
+
import { GSDError, GSD_GIT_ERROR } from "./errors.js";
|
|
7
|
+
import { resolveMilestoneIntegrationBranch, } from "./git-service.js";
|
|
8
|
+
import { nativeCheckoutBranch, nativeDetectMainBranch, nativeGetCurrentBranch, } from "./native-git-bridge.js";
|
|
9
|
+
import { clearProjectRootStateFiles } from "./auto-worktree-cleanup.js";
|
|
10
|
+
const defaultDeps = {
|
|
11
|
+
chdir: process.chdir.bind(process),
|
|
12
|
+
clearProjectRootStateFiles,
|
|
13
|
+
nativeCheckoutBranch,
|
|
14
|
+
nativeDetectMainBranch,
|
|
15
|
+
nativeGetCurrentBranch,
|
|
16
|
+
resolveMilestoneIntegrationBranch,
|
|
17
|
+
};
|
|
18
|
+
let deps = defaultDeps;
|
|
19
|
+
export function _setMergeIntegrationBranchDepsForTests(overrides) {
|
|
20
|
+
deps = { ...defaultDeps, ...overrides };
|
|
21
|
+
}
|
|
22
|
+
export function _resetMergeIntegrationBranchDepsForTests() {
|
|
23
|
+
deps = defaultDeps;
|
|
24
|
+
}
|
|
25
|
+
function normalizeLocalBranchRef(branch) {
|
|
26
|
+
return branch.startsWith("refs/heads/")
|
|
27
|
+
? branch.slice("refs/heads/".length)
|
|
28
|
+
: branch;
|
|
29
|
+
}
|
|
30
|
+
export function prepareIntegrationBranchForMilestoneMerge(request) {
|
|
31
|
+
const { milestoneBranch, milestoneId, prefs, previousCwd, projectRoot } = request;
|
|
32
|
+
const branchResolution = deps.resolveMilestoneIntegrationBranch(projectRoot, milestoneId, prefs);
|
|
33
|
+
const mainBranch = branchResolution.effectiveBranch ?? deps.nativeDetectMainBranch(projectRoot);
|
|
34
|
+
if (normalizeLocalBranchRef(mainBranch) === milestoneBranch) {
|
|
35
|
+
deps.chdir(previousCwd);
|
|
36
|
+
throw new GSDError(GSD_GIT_ERROR, `Resolved integration branch "${mainBranch}" is the same ref as milestone branch ` +
|
|
37
|
+
`"${milestoneBranch}" — refusing to self-merge. ${branchResolution.reason}. ` +
|
|
38
|
+
`Repair milestone integration metadata before retrying milestone completion.`);
|
|
39
|
+
}
|
|
40
|
+
deps.clearProjectRootStateFiles(projectRoot, milestoneId);
|
|
41
|
+
const currentBranchAtBase = deps.nativeGetCurrentBranch(projectRoot);
|
|
42
|
+
if (!currentBranchAtBase || currentBranchAtBase.length === 0) {
|
|
43
|
+
deps.chdir(previousCwd);
|
|
44
|
+
throw new GSDError(GSD_GIT_ERROR, `Project root is in detached HEAD state — cannot perform milestone merge. ` +
|
|
45
|
+
`Checkout an integration branch (e.g. \`git checkout ${mainBranch}\`) before resuming.`);
|
|
46
|
+
}
|
|
47
|
+
if (currentBranchAtBase !== mainBranch) {
|
|
48
|
+
deps.nativeCheckoutBranch(projectRoot, mainBranch);
|
|
49
|
+
}
|
|
50
|
+
return { mainBranch };
|
|
51
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// gsd-pi — Milestone merge commit-message construction.
|
|
2
|
+
//
|
|
3
|
+
// Owns the completed-slice/task summary and milestone title fallback policy used
|
|
4
|
+
// by auto-worktree milestone merge commits and publication summaries.
|
|
5
|
+
import { getMilestone, getMilestoneSlices, getSliceTasks, isDbAvailable, } from "./gsd-db.js";
|
|
6
|
+
const defaultDeps = {
|
|
7
|
+
isDbAvailable,
|
|
8
|
+
getMilestone,
|
|
9
|
+
getMilestoneSlices,
|
|
10
|
+
getSliceTasks,
|
|
11
|
+
};
|
|
12
|
+
let deps = defaultDeps;
|
|
13
|
+
export function _setMilestoneMergeMessageDepsForTests(overrides) {
|
|
14
|
+
deps = { ...defaultDeps, ...overrides };
|
|
15
|
+
}
|
|
16
|
+
export function _resetMilestoneMergeMessageDepsForTests() {
|
|
17
|
+
deps = defaultDeps;
|
|
18
|
+
}
|
|
19
|
+
function stripGsdDisplayPrefix(value, id) {
|
|
20
|
+
const raw = String(value ?? "").trim();
|
|
21
|
+
if (!raw)
|
|
22
|
+
return undefined;
|
|
23
|
+
const lower = raw.toLowerCase();
|
|
24
|
+
const idLower = id.toLowerCase();
|
|
25
|
+
if (lower.startsWith(`${idLower}:`)) {
|
|
26
|
+
return raw.slice(id.length + 1).trim() || undefined;
|
|
27
|
+
}
|
|
28
|
+
return raw;
|
|
29
|
+
}
|
|
30
|
+
function getDbCompletedSlices(milestoneId) {
|
|
31
|
+
if (!deps.isDbAvailable())
|
|
32
|
+
return [];
|
|
33
|
+
return deps.getMilestoneSlices(milestoneId)
|
|
34
|
+
.filter((slice) => slice.status === "complete")
|
|
35
|
+
.map((slice) => ({
|
|
36
|
+
id: slice.id,
|
|
37
|
+
title: stripGsdDisplayPrefix(slice.title, slice.id) ?? slice.id,
|
|
38
|
+
tasks: deps.getSliceTasks(milestoneId, slice.id)
|
|
39
|
+
.filter((task) => task.status === "complete")
|
|
40
|
+
.map((task) => ({
|
|
41
|
+
id: task.id,
|
|
42
|
+
title: stripGsdDisplayPrefix(task.title, task.id) ?? task.id,
|
|
43
|
+
})),
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
function getRoadmapCompletedSlices(roadmapContent) {
|
|
47
|
+
if (!roadmapContent)
|
|
48
|
+
return [];
|
|
49
|
+
const completedSlices = [];
|
|
50
|
+
const sliceRe = /- \[x\] \*\*(\w+):\s*(.+?)\*\*/gi;
|
|
51
|
+
let match;
|
|
52
|
+
while ((match = sliceRe.exec(roadmapContent)) !== null) {
|
|
53
|
+
completedSlices.push({ id: match[1], title: match[2], tasks: [] });
|
|
54
|
+
}
|
|
55
|
+
return completedSlices;
|
|
56
|
+
}
|
|
57
|
+
function getCompletedSlices(milestoneId, roadmapContent) {
|
|
58
|
+
const dbCompletedSlices = getDbCompletedSlices(milestoneId);
|
|
59
|
+
if (dbCompletedSlices.length > 0)
|
|
60
|
+
return dbCompletedSlices;
|
|
61
|
+
return getRoadmapCompletedSlices(roadmapContent);
|
|
62
|
+
}
|
|
63
|
+
function getRoadmapMilestoneTitle(milestoneId, roadmapContent) {
|
|
64
|
+
if (!roadmapContent)
|
|
65
|
+
return undefined;
|
|
66
|
+
const titleMatch = roadmapContent.match(new RegExp(`^#\\s+${milestoneId}:\\s*(.+)`, "m"));
|
|
67
|
+
return titleMatch?.[1]?.trim() || undefined;
|
|
68
|
+
}
|
|
69
|
+
function getMilestoneTitle(milestoneId, roadmapContent) {
|
|
70
|
+
const dbMilestone = deps.getMilestone(milestoneId);
|
|
71
|
+
const dbTitle = stripGsdDisplayPrefix(dbMilestone?.title, milestoneId);
|
|
72
|
+
return dbTitle ?? getRoadmapMilestoneTitle(milestoneId, roadmapContent) ?? milestoneId;
|
|
73
|
+
}
|
|
74
|
+
function buildCommitMessage(request) {
|
|
75
|
+
const { completedSlices, milestoneBranch, milestoneId, milestoneTitle } = request;
|
|
76
|
+
const subject = `feat: ${milestoneTitle}`;
|
|
77
|
+
const milestoneContext = milestoneTitle === milestoneId
|
|
78
|
+
? `Milestone: ${milestoneId}`
|
|
79
|
+
: `Milestone: ${milestoneId} - ${milestoneTitle}`;
|
|
80
|
+
if (completedSlices.length === 0) {
|
|
81
|
+
return `${subject}\n\n${milestoneContext}\nGSD-Milestone: ${milestoneId}\nBranch: ${milestoneBranch}`;
|
|
82
|
+
}
|
|
83
|
+
const sliceLines = completedSlices
|
|
84
|
+
.map((slice) => `- ${slice.id}: ${slice.title}`)
|
|
85
|
+
.join("\n");
|
|
86
|
+
const taskLines = completedSlices
|
|
87
|
+
.flatMap((slice) => slice.tasks.map((task) => `- ${slice.id}/${task.id}: ${task.title}`))
|
|
88
|
+
.join("\n");
|
|
89
|
+
const taskBlock = taskLines ? `\n\nCompleted tasks:\n${taskLines}` : "";
|
|
90
|
+
return `${subject}\n\nCompleted slices:\n${sliceLines}${taskBlock}\n\n${milestoneContext}\nGSD-Milestone: ${milestoneId}\nBranch: ${milestoneBranch}`;
|
|
91
|
+
}
|
|
92
|
+
export function buildMilestoneMergeMessage(request) {
|
|
93
|
+
const { milestoneId, milestoneBranch, roadmapContent } = request;
|
|
94
|
+
const completedSlices = getCompletedSlices(milestoneId, roadmapContent);
|
|
95
|
+
const milestoneTitle = getMilestoneTitle(milestoneId, roadmapContent);
|
|
96
|
+
return {
|
|
97
|
+
commitMessage: buildCommitMessage({
|
|
98
|
+
completedSlices,
|
|
99
|
+
milestoneBranch,
|
|
100
|
+
milestoneId,
|
|
101
|
+
milestoneTitle,
|
|
102
|
+
}),
|
|
103
|
+
milestoneTitle,
|
|
104
|
+
sliceSummaries: completedSlices.map((slice) => `### ${slice.id}\n${slice.title}`),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// gsd-pi — Milestone merge pre-teardown safety guard.
|
|
2
|
+
//
|
|
3
|
+
// Owns the final data-loss check before deleting a merged milestone worktree:
|
|
4
|
+
// if the milestone worktree still has uncommitted work, abort teardown so the
|
|
5
|
+
// milestone branch remains a recovery ref.
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { debugLog } from "./debug-logger.js";
|
|
8
|
+
import { GSDError, GSD_GIT_ERROR } from "./errors.js";
|
|
9
|
+
import { nativeGetCurrentBranch, nativeWorkingTreeStatus, } from "./native-git-bridge.js";
|
|
10
|
+
const defaultDeps = {
|
|
11
|
+
chdir: process.chdir.bind(process),
|
|
12
|
+
debugLog,
|
|
13
|
+
existsSync,
|
|
14
|
+
nativeGetCurrentBranch,
|
|
15
|
+
nativeWorkingTreeStatus,
|
|
16
|
+
};
|
|
17
|
+
let deps = defaultDeps;
|
|
18
|
+
export function _setPreTeardownSafetyDepsForTests(overrides) {
|
|
19
|
+
deps = { ...defaultDeps, ...overrides };
|
|
20
|
+
}
|
|
21
|
+
export function _resetPreTeardownSafetyDepsForTests() {
|
|
22
|
+
deps = defaultDeps;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Abort teardown when the milestone worktree still has uncommitted changes.
|
|
26
|
+
*
|
|
27
|
+
* The guard is intentionally scoped to worktree paths that are still on the
|
|
28
|
+
* milestone branch. In branch-mode or parallel merge paths, `worktreeCwd` can
|
|
29
|
+
* point at the integration branch; blocking on that dirty state would conflate
|
|
30
|
+
* unrelated milestones and preserve the wrong recovery ref.
|
|
31
|
+
*/
|
|
32
|
+
export function assertMilestoneWorktreeCleanBeforeTeardown(request) {
|
|
33
|
+
const { milestoneBranch, previousCwd, worktreeCwd } = request;
|
|
34
|
+
if (!deps.existsSync(worktreeCwd))
|
|
35
|
+
return;
|
|
36
|
+
let preTeardownBranch = null;
|
|
37
|
+
try {
|
|
38
|
+
preTeardownBranch = deps.nativeGetCurrentBranch(worktreeCwd);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
deps.debugLog("mergeMilestoneToMain", {
|
|
42
|
+
phase: "pre-teardown-branch-detect-failed",
|
|
43
|
+
error: String(err),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (preTeardownBranch !== milestoneBranch)
|
|
47
|
+
return;
|
|
48
|
+
try {
|
|
49
|
+
const dirtyCheck = deps.nativeWorkingTreeStatus(worktreeCwd);
|
|
50
|
+
if (!dirtyCheck)
|
|
51
|
+
return;
|
|
52
|
+
deps.chdir(previousCwd);
|
|
53
|
+
throw new GSDError(GSD_GIT_ERROR, `Milestone worktree still has uncommitted changes after squash merge. ` +
|
|
54
|
+
`Aborting teardown to preserve ${milestoneBranch}. Status:\n${dirtyCheck}`);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
if (err instanceof GSDError)
|
|
58
|
+
throw err;
|
|
59
|
+
deps.debugLog("mergeMilestoneToMain", {
|
|
60
|
+
phase: "pre-teardown-dirty-check-error",
|
|
61
|
+
error: String(err),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// gsd-pi — Pre-merge stash handling for auto-worktree merge closeout.
|
|
2
|
+
//
|
|
3
|
+
// Owns the local-work protection around milestone merge: stash before merge,
|
|
4
|
+
// DB handle cycling for Windows, restoring on merge failures, and post-commit
|
|
5
|
+
// stash-pop conflict recovery.
|
|
6
|
+
import { execFileSync } from "node:child_process";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { closeWorkflowDatabase, getWorkflowDatabasePath, openWorkflowDatabasePath, } from "./db-workspace.js";
|
|
9
|
+
import { nativeAddPaths, nativeConflictFiles, nativeLsFiles, nativeRmForce, } from "./native-git-bridge.js";
|
|
10
|
+
import { gsdJsonlFilesWithConflictMarkers, hasConflictMarkers, popStashByRef, stashAlreadyExistsFilesFromError, stashRefFromError, } from "./worktree-git-recovery.js";
|
|
11
|
+
import { logWarning } from "./workflow-logger.js";
|
|
12
|
+
export function createPreMergeStash(basePath, milestoneId, cycleDbHandles) {
|
|
13
|
+
let stashed = false;
|
|
14
|
+
let marker = null;
|
|
15
|
+
const dbPathToReopen = cycleDbHandles ? getWorkflowDatabasePath() : null;
|
|
16
|
+
return {
|
|
17
|
+
stash() {
|
|
18
|
+
closeDbBeforeStashIfNeeded(cycleDbHandles);
|
|
19
|
+
try {
|
|
20
|
+
const status = execFileSync("git", ["status", "--porcelain"], {
|
|
21
|
+
cwd: basePath,
|
|
22
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
23
|
+
encoding: "utf-8",
|
|
24
|
+
}).trim();
|
|
25
|
+
if (!status)
|
|
26
|
+
return;
|
|
27
|
+
marker = createStashMarker(milestoneId);
|
|
28
|
+
execFileSync("git", ["stash", "push", "--include-untracked", "-m", `gsd: pre-merge stash for ${milestoneId} [${marker}]`], { cwd: basePath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
|
|
29
|
+
stashed = true;
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
// Stash failure is non-fatal — proceed without stash and let the merge
|
|
33
|
+
// report the dirty tree if it fails.
|
|
34
|
+
logWarning("worktree", `git stash failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
reopenDbAfterMerge() {
|
|
38
|
+
if (!cycleDbHandles || !dbPathToReopen)
|
|
39
|
+
return;
|
|
40
|
+
try {
|
|
41
|
+
openWorkflowDatabasePath(dbPathToReopen);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
logWarning("worktree", `post-merge db reopen failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
restoreForMergeFailure() {
|
|
48
|
+
if (!stashed)
|
|
49
|
+
return;
|
|
50
|
+
try {
|
|
51
|
+
popStashByRef(basePath, marker);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
logWarning("worktree", `git stash pop failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
restoreAfterCommit() {
|
|
58
|
+
if (!stashed)
|
|
59
|
+
return;
|
|
60
|
+
restoreStashAfterCommit(basePath, marker);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function closeDbBeforeStashIfNeeded(cycleDbHandles) {
|
|
65
|
+
if (!cycleDbHandles)
|
|
66
|
+
return;
|
|
67
|
+
try {
|
|
68
|
+
closeWorkflowDatabase();
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
logWarning("worktree", `pre-stash db close failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function createStashMarker(milestoneId) {
|
|
75
|
+
return `gsd-pre-merge:${milestoneId}:${process.pid}:${Date.now()}:${process.hrtime.bigint().toString(36)}`;
|
|
76
|
+
}
|
|
77
|
+
function restoreStashAfterCommit(basePath, marker) {
|
|
78
|
+
let stashRefForDrop = null;
|
|
79
|
+
try {
|
|
80
|
+
stashRefForDrop = popStashByRef(basePath, marker);
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
stashRefForDrop = stashRefFromError(e);
|
|
84
|
+
logWarning("worktree", `git stash pop failed, attempting conflict resolution: ${e.message}`);
|
|
85
|
+
resolveStashPopConflict(basePath, e, stashRefForDrop);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function resolveStashPopConflict(basePath, error, stashRefForDrop) {
|
|
89
|
+
const uu = nativeConflictFiles(basePath);
|
|
90
|
+
const gsdUU = uu.filter((f) => f.startsWith(".gsd/"));
|
|
91
|
+
const nonGsdUU = uu.filter((f) => !f.startsWith(".gsd/"));
|
|
92
|
+
const stashPopMessage = error instanceof Error ? error.message : String(error);
|
|
93
|
+
const isUntrackedRestoreFailure = stashPopMessage.includes("could not restore untracked files from stash");
|
|
94
|
+
const gsdContentConflicts = [];
|
|
95
|
+
const alreadyExists = stashAlreadyExistsFilesFromError(error);
|
|
96
|
+
if (isUntrackedRestoreFailure) {
|
|
97
|
+
gsdContentConflicts.push(...gsdJsonlFilesWithConflictMarkers(basePath));
|
|
98
|
+
}
|
|
99
|
+
const gsdConflictFiles = [...new Set([...gsdUU, ...gsdContentConflicts])];
|
|
100
|
+
resolveGsdConflictFiles(basePath, gsdConflictFiles);
|
|
101
|
+
if (gsdConflictFiles.length > 0 && nonGsdUU.length === 0) {
|
|
102
|
+
dropStashIfNoNonGsdConflictsRemain(basePath, stashRefForDrop);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (gsdUU.length === 0 && nonGsdUU.length === 0 && alreadyExists.length > 0) {
|
|
106
|
+
dropRecordedStash(basePath, stashRefForDrop);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (nonGsdUU.length > 0) {
|
|
110
|
+
logWarning("reconcile", "Stash pop conflict on non-.gsd files after merge", {
|
|
111
|
+
files: nonGsdUU.join(", "),
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
logWarning("worktree", "git stash pop failed without resolvable conflict files; leaving stash for manual recovery");
|
|
116
|
+
}
|
|
117
|
+
function resolveGsdConflictFiles(basePath, conflictFiles) {
|
|
118
|
+
for (const file of conflictFiles) {
|
|
119
|
+
try {
|
|
120
|
+
// Accept the committed (HEAD) version of the state file.
|
|
121
|
+
execFileSync("git", ["checkout", "HEAD", "--", file], {
|
|
122
|
+
cwd: basePath,
|
|
123
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
124
|
+
encoding: "utf-8",
|
|
125
|
+
});
|
|
126
|
+
nativeAddPaths(basePath, [file]);
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
// Last resort: remove the conflicted state file.
|
|
130
|
+
logWarning("worktree", `checkout HEAD failed for ${file}, removing: ${err.message}`);
|
|
131
|
+
nativeRmForce(basePath, [file]);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function dropStashIfNoNonGsdConflictsRemain(basePath, stashRefForDrop) {
|
|
136
|
+
const remainingUnmerged = nativeConflictFiles(basePath);
|
|
137
|
+
const nonGsdUnmerged = remainingUnmerged.filter((f) => !f.startsWith(".gsd/"));
|
|
138
|
+
const markerCandidates = Array.from(new Set([
|
|
139
|
+
...nonGsdUnmerged,
|
|
140
|
+
...nativeLsFiles(basePath, "."),
|
|
141
|
+
])).filter((f) => !f.startsWith(".gsd/"));
|
|
142
|
+
const nonGsdMarkerConflicts = markerCandidates.filter((f) => hasConflictMarkers(join(basePath, f)));
|
|
143
|
+
const hasRemainingNonGsdConflicts = nonGsdUnmerged.length > 0 || nonGsdMarkerConflicts.length > 0;
|
|
144
|
+
if (hasRemainingNonGsdConflicts) {
|
|
145
|
+
const files = Array.from(new Set([...nonGsdUnmerged, ...nonGsdMarkerConflicts]));
|
|
146
|
+
logWarning("reconcile", "Leaving stash because non-.gsd conflicts remain after auto-resolution", {
|
|
147
|
+
files: files.join(", "),
|
|
148
|
+
});
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
dropRecordedStash(basePath, stashRefForDrop);
|
|
152
|
+
}
|
|
153
|
+
function dropRecordedStash(basePath, stashRefForDrop) {
|
|
154
|
+
if (!stashRefForDrop) {
|
|
155
|
+
logWarning("worktree", "recorded stash entry could not be resolved; skipping automatic drop");
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
execFileSync("git", ["stash", "drop", stashRefForDrop], {
|
|
160
|
+
cwd: basePath,
|
|
161
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
162
|
+
encoding: "utf-8",
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
logWarning("worktree", `git stash drop failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
167
|
+
}
|
|
168
|
+
}
|