@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
|
@@ -6,7 +6,7 @@ import { cpSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync, statSyn
|
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
|
|
8
8
|
import { renderAllFromDb, renderRoadmapFromDb } from "./markdown-renderer.js";
|
|
9
|
-
import { getAllMilestones, getMilestoneSlices } from "./gsd-db.js";
|
|
9
|
+
import { deleteArtifactsByPathPrefix, getAllMilestones, getMilestoneSlices } from "./gsd-db.js";
|
|
10
10
|
import { migrateFromMarkdown } from "./md-importer.js";
|
|
11
11
|
import { countDbHierarchy } from "./migration-auto-check.js";
|
|
12
12
|
import { logWarning } from "./workflow-logger.js";
|
|
@@ -195,7 +195,8 @@ export function pruneStaleFlatPhaseBackups(basePath: string): number {
|
|
|
195
195
|
* 2. Rename .gsd/milestones/ aside so path resolvers target phases/
|
|
196
196
|
* 3. Render flat-phase from the DB (which already has the data)
|
|
197
197
|
* 4. Verify counts match
|
|
198
|
-
* 5.
|
|
198
|
+
* 5. Prune legacy milestones/ artifact rows
|
|
199
|
+
* 6. Remove the renamed legacy tree
|
|
199
200
|
*
|
|
200
201
|
* Idempotent: if .gsd/milestones/ doesn't exist, returns immediately.
|
|
201
202
|
*/
|
|
@@ -313,7 +314,17 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
313
314
|
throw new Error("flat-phase migration verification failed: no artifacts rendered");
|
|
314
315
|
}
|
|
315
316
|
|
|
316
|
-
// 6. Verified —
|
|
317
|
+
// 6. Verified — prune legacy artifact rows now that renderAllFromDb has
|
|
318
|
+
// re-inserted flat-phase rows for artifacts that still have files.
|
|
319
|
+
try {
|
|
320
|
+
deleteArtifactsByPathPrefix("milestones/");
|
|
321
|
+
} catch (err) {
|
|
322
|
+
logWarning("migration", `flat-phase migration could not prune legacy artifact rows: ${(err as Error).message}`);
|
|
323
|
+
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
324
|
+
throw err;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// 7. Remove the renamed legacy tree (backup already on disk).
|
|
317
328
|
try {
|
|
318
329
|
removePathWithRetries(migratingPath);
|
|
319
330
|
} catch (err) {
|
|
@@ -30,7 +30,7 @@ import { loadPrompt } from "./prompt-loader.js";
|
|
|
30
30
|
import { gsdRoot } from "./paths.js";
|
|
31
31
|
import { isDbAvailable, getHierarchyCompletionCounts } from "./gsd-db.js";
|
|
32
32
|
import { formatDuration } from "../shared/format-utils.js";
|
|
33
|
-
import { getAutoWorktreePath } from "./auto-worktree.js";
|
|
33
|
+
import { getAutoWorktreePath } from "./auto-worktree-path-resolution.js";
|
|
34
34
|
import { clearGSDPreferencesCache, loadEffectiveGSDPreferences, loadGlobalGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
|
|
35
35
|
import { showNextAction } from "../shared/tui.js";
|
|
36
36
|
import {
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
nativeCheckoutTheirs,
|
|
8
8
|
nativeRmForce,
|
|
9
9
|
} from "./native-git-bridge.js";
|
|
10
|
-
import { isSafeToAutoResolve } from "./auto-worktree.js";
|
|
10
|
+
import { isSafeToAutoResolve } from "./auto-worktree-conflict-auto-resolve.js";
|
|
11
11
|
|
|
12
|
-
export { isSafeToAutoResolve } from "./auto-worktree.js";
|
|
12
|
+
export { isSafeToAutoResolve } from "./auto-worktree-conflict-auto-resolve.js";
|
|
13
13
|
|
|
14
14
|
export interface AutoResolveSafePathsResult {
|
|
15
15
|
resolved: string[];
|
|
@@ -704,6 +704,59 @@ export function runGit(basePath: string, args: string[], options: { allowFailure
|
|
|
704
704
|
}
|
|
705
705
|
}
|
|
706
706
|
|
|
707
|
+
/**
|
|
708
|
+
* Arguments for creating a task/workflow branch.
|
|
709
|
+
*
|
|
710
|
+
* When the current branch is a leftover GSD task branch (workflow template,
|
|
711
|
+
* quick task, or slice), the new branch starts from `baseBranch` — the
|
|
712
|
+
* caller's resolved integration branch, normally `GitServiceImpl.getMainBranch()`
|
|
713
|
+
* so `main_branch` preference, milestone integration branch, and worktree base
|
|
714
|
+
* all take priority over repo-default detection. Branching from HEAD there
|
|
715
|
+
* silently stacks consecutive workflow branches on top of each other, so every
|
|
716
|
+
* new gsd/* branch (and its eventual PR) drags along the previous workflow's
|
|
717
|
+
* commits.
|
|
718
|
+
*
|
|
719
|
+
* On any other branch (a user's feature branch, a worktree base, the main
|
|
720
|
+
* branch itself) the legacy branch-from-HEAD behavior is kept: basing new work
|
|
721
|
+
* on the branch the user chose to stand on is intentional there.
|
|
722
|
+
*
|
|
723
|
+
* Falls back to branch-from-HEAD, with a logged warning, when the base branch
|
|
724
|
+
* has no local ref or the working tree is still dirty (a start point that
|
|
725
|
+
* changes the tree would abort the checkout or strand in-flight changes).
|
|
726
|
+
* The base is the local ref — deliberately no fetch, so branch creation stays
|
|
727
|
+
* offline-safe even if the local base is behind its remote.
|
|
728
|
+
*/
|
|
729
|
+
export function taskBranchArgs(basePath: string, branchName: string, currentBranch: string, baseBranch: string): string[] {
|
|
730
|
+
const args = ["checkout", "-b", branchName];
|
|
731
|
+
const onTaskBranch =
|
|
732
|
+
WORKFLOW_BRANCH_RE.test(currentBranch) ||
|
|
733
|
+
QUICK_BRANCH_RE.test(currentBranch) ||
|
|
734
|
+
SLICE_BRANCH_RE.test(currentBranch);
|
|
735
|
+
if (!onTaskBranch || !baseBranch || baseBranch === currentBranch) return args;
|
|
736
|
+
try {
|
|
737
|
+
if (!nativeBranchExists(basePath, baseBranch)) {
|
|
738
|
+
logWarning(
|
|
739
|
+
"engine",
|
|
740
|
+
`taskBranchArgs: base branch "${baseBranch}" has no local ref — branching ${branchName} from HEAD (${currentBranch})`,
|
|
741
|
+
{ file: "git-service.ts" },
|
|
742
|
+
);
|
|
743
|
+
return args;
|
|
744
|
+
}
|
|
745
|
+
if (nativeHasChanges(basePath)) {
|
|
746
|
+
logWarning(
|
|
747
|
+
"engine",
|
|
748
|
+
`taskBranchArgs: working tree still dirty after auto-commit — branching ${branchName} from HEAD (${currentBranch}) to preserve in-flight changes`,
|
|
749
|
+
{ file: "git-service.ts" },
|
|
750
|
+
);
|
|
751
|
+
return args;
|
|
752
|
+
}
|
|
753
|
+
} catch {
|
|
754
|
+
return args;
|
|
755
|
+
}
|
|
756
|
+
args.push(baseBranch);
|
|
757
|
+
return args;
|
|
758
|
+
}
|
|
759
|
+
|
|
707
760
|
// ─── Commit Type Inference ─────────────────────────────────────────────────
|
|
708
761
|
|
|
709
762
|
/**
|
|
@@ -1397,6 +1397,19 @@ export function deleteArtifactByPath(path: string): void {
|
|
|
1397
1397
|
getDbOrNull()!.prepare("DELETE FROM artifacts WHERE path = :path").run({ ":path": path });
|
|
1398
1398
|
}
|
|
1399
1399
|
|
|
1400
|
+
/** Delete artifact rows whose paths share a DB-relative prefix. */
|
|
1401
|
+
export function deleteArtifactsByPathPrefix(prefix: string): number {
|
|
1402
|
+
if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1403
|
+
return transaction(() => {
|
|
1404
|
+
const likePrefix = `${prefix}%`;
|
|
1405
|
+
const countRow = getDbOrNull()!.prepare(
|
|
1406
|
+
"SELECT COUNT(*) AS count FROM artifacts WHERE path LIKE :prefix",
|
|
1407
|
+
).get({ ":prefix": likePrefix });
|
|
1408
|
+
getDbOrNull()!.prepare("DELETE FROM artifacts WHERE path LIKE :prefix").run({ ":prefix": likePrefix });
|
|
1409
|
+
return Number(countRow?.["count"] ?? 0);
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1400
1413
|
/**
|
|
1401
1414
|
* Drop hierarchy rows in dependency order inside a transaction. Used by
|
|
1402
1415
|
* `gsd recover --confirm` to rebuild engine state from markdown.
|
|
@@ -51,7 +51,7 @@ import { nativeAddAll, nativeCommit, nativeHasCommittedHead, nativeIsRepo, nativ
|
|
|
51
51
|
import { isInheritedRepo } from "./repo-identity.js";
|
|
52
52
|
import { ensureGitignore, ensurePreferences, untrackRuntimeFiles } from "./gitignore.js";
|
|
53
53
|
import { getIsolationMode, loadEffectiveGSDPreferences } from "./preferences.js";
|
|
54
|
-
import { getAutoWorktreePath } from "./auto-worktree.js";
|
|
54
|
+
import { getAutoWorktreePath } from "./auto-worktree-path-resolution.js";
|
|
55
55
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
56
56
|
import { ensurePlanV2Graph, isMissingFinalizedContextResult } from "./uok/plan-v2.js";
|
|
57
57
|
import { detectProjectState, hasGsdBootstrapArtifacts } from "./detection.js";
|
|
@@ -94,7 +94,7 @@ import {
|
|
|
94
94
|
import { probeCoversRequiredWorkflowTools } from "./tool-surface-readiness.js";
|
|
95
95
|
import { getRequiredWorkflowToolsForUnit } from "./unit-tool-contracts.js";
|
|
96
96
|
import { isWorkflowToolSurfaceName } from "./workflow-tool-surface.js";
|
|
97
|
-
import {
|
|
97
|
+
import { getUnitWorkflowDispatchReadinessErrorForModel } from "./tool-contract.js";
|
|
98
98
|
import {
|
|
99
99
|
runPreparation,
|
|
100
100
|
formatCodebaseBrief,
|
|
@@ -613,7 +613,7 @@ interface DispatchWorkflowOptions {
|
|
|
613
613
|
deps?: {
|
|
614
614
|
loadPreferences?: typeof loadEffectiveGSDPreferences;
|
|
615
615
|
selectModel?: typeof selectAndApplyModel;
|
|
616
|
-
getDispatchReadinessError?: typeof
|
|
616
|
+
getDispatchReadinessError?: typeof getUnitWorkflowDispatchReadinessErrorForModel;
|
|
617
617
|
};
|
|
618
618
|
}
|
|
619
619
|
|
|
@@ -730,7 +730,7 @@ async function dispatchWorkflow(
|
|
|
730
730
|
const loadPreferences = resolvedOptions.deps?.loadPreferences ?? loadEffectiveGSDPreferences;
|
|
731
731
|
const selectModel = resolvedOptions.deps?.selectModel ?? selectAndApplyModel;
|
|
732
732
|
const getDispatchReadinessError = resolvedOptions.deps?.getDispatchReadinessError
|
|
733
|
-
??
|
|
733
|
+
?? getUnitWorkflowDispatchReadinessErrorForModel;
|
|
734
734
|
|
|
735
735
|
// Route through the dynamic routing pipeline (complexity classification,
|
|
736
736
|
// tier downgrade, fallback chains) — same path as auto-mode dispatches (#2958).
|
|
@@ -750,16 +750,12 @@ async function dispatchWorkflow(
|
|
|
750
750
|
}
|
|
751
751
|
|
|
752
752
|
const compatibilityError = getDispatchReadinessError({
|
|
753
|
-
|
|
753
|
+
model: result.appliedModel,
|
|
754
|
+
fallbackModel: ctx.model,
|
|
755
|
+
getProviderAuthMode: (provider) => ctx.modelRegistry.getProviderAuthMode(provider),
|
|
754
756
|
projectRoot,
|
|
755
757
|
surface: "guided flow",
|
|
756
758
|
unitType,
|
|
757
|
-
authMode: result.appliedModel?.provider
|
|
758
|
-
? ctx.modelRegistry.getProviderAuthMode(result.appliedModel.provider)
|
|
759
|
-
: ctx.model?.provider
|
|
760
|
-
? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider)
|
|
761
|
-
: undefined,
|
|
762
|
-
baseUrl: result.appliedModel?.baseUrl ?? ctx.model?.baseUrl,
|
|
763
759
|
// Guided flow starts the MCP workflow server as part of dispatch, so the
|
|
764
760
|
// parent session's activeTools doesn't include MCP tools yet. The MCP
|
|
765
761
|
// launch config check (detectWorkflowMcpLaunchConfig) is the right gate
|
|
@@ -1299,9 +1299,21 @@ export async function renderAssessmentFromDb(
|
|
|
1299
1299
|
sliceId: string,
|
|
1300
1300
|
assessmentData: AssessmentData,
|
|
1301
1301
|
): Promise<{ assessmentPath: string; content: string }> {
|
|
1302
|
-
// Flat-phase: assessment file lives in the phase dir
|
|
1303
|
-
|
|
1304
|
-
|
|
1302
|
+
// Flat-phase: the assessment file lives in the phase dir, NOT in a slices/SID/
|
|
1303
|
+
// subdir. resolveSlicePath() detects a slices/SID/ dir unconditionally, so a
|
|
1304
|
+
// stray slices/SID/ created by an earlier planning step would send this write
|
|
1305
|
+
// to a hybrid path (wrong dir, flat filename) that verification cannot find.
|
|
1306
|
+
// Guard with the same legacy-base check relSlicePath() uses so flat-phase
|
|
1307
|
+
// milestones always target the phase dir.
|
|
1308
|
+
const mDir = resolveMilestonePath(basePath, milestoneId);
|
|
1309
|
+
const legacyBase = legacyMilestonesDir(basePath);
|
|
1310
|
+
const isLegacyLayout = mDir
|
|
1311
|
+
? mDir.startsWith(legacyBase + "/") || mDir.startsWith(legacyBase + "\\")
|
|
1312
|
+
: false;
|
|
1313
|
+
const fallbackDir = join(milestonesDir(basePath), canonicalPhaseDirName(milestoneId, getMilestone(milestoneId)?.title));
|
|
1314
|
+
const slicePath = isLegacyLayout
|
|
1315
|
+
? (resolveSlicePath(basePath, milestoneId, sliceId) ?? fallbackDir)
|
|
1316
|
+
: (mDir ?? fallbackDir);
|
|
1305
1317
|
const phaseNum = milestoneIdToPhaseNum(milestoneId);
|
|
1306
1318
|
const planNum = sliceIdToPlanNum(sliceId);
|
|
1307
1319
|
const absPath = join(slicePath, planFileName(phaseNum, planNum, "ASSESSMENT"));
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Process-level transaction wrapper for milestone merge closeout.
|
|
3
3
|
|
|
4
|
+
import { mergeMilestoneToMain } from "./auto-worktree-merge.js";
|
|
5
|
+
|
|
4
6
|
export interface MilestoneMergeTransactionResult {
|
|
5
7
|
pushed: boolean;
|
|
6
8
|
codeFilesChanged: boolean;
|
|
@@ -45,3 +47,16 @@ export function createMilestoneMergeTransaction(
|
|
|
45
47
|
);
|
|
46
48
|
};
|
|
47
49
|
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Production merge transaction adapter.
|
|
53
|
+
*
|
|
54
|
+
* This is the only production construction point that knows the legacy
|
|
55
|
+
* `auto-worktree.ts` merge primitive. Lifecycle callers depend on the
|
|
56
|
+
* transaction runner interface, not the legacy implementation module.
|
|
57
|
+
*/
|
|
58
|
+
export function createDefaultMilestoneMergeTransaction(
|
|
59
|
+
mergeMilestone: MilestoneMergeTransactionRunner = mergeMilestoneToMain,
|
|
60
|
+
): MilestoneMergeTransactionRunner {
|
|
61
|
+
return createMilestoneMergeTransaction(mergeMilestone);
|
|
62
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Milestone closeout settlement state across DB proof, artifacts, merge, and cleanup.
|
|
3
3
|
|
|
4
|
-
import { isInAutoWorktree } from "./auto-worktree.js";
|
|
4
|
+
import { isInAutoWorktree } from "./auto-worktree-entry.js";
|
|
5
5
|
import {
|
|
6
6
|
formatCloseoutProofBlock,
|
|
7
7
|
proveMilestoneCloseout,
|
|
@@ -10,7 +10,7 @@ import { join } from "node:path";
|
|
|
10
10
|
import { spawnSync } from "node:child_process";
|
|
11
11
|
import { resolveGsdPathContract } from "./paths.js";
|
|
12
12
|
import { worktreePathFor, worktreesDirs } from "./worktree-placement.js";
|
|
13
|
-
import { getAutoWorktreePath } from "./auto-worktree.js";
|
|
13
|
+
import { getAutoWorktreePath } from "./auto-worktree-path-resolution.js";
|
|
14
14
|
import { buildWorktreeLifecycleDeps } from "./auto.js";
|
|
15
15
|
import {
|
|
16
16
|
mergeMilestoneStandalone,
|
|
@@ -21,7 +21,9 @@ import { join, dirname } from "node:path";
|
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
22
|
import { gsdRoot } from "./paths.js";
|
|
23
23
|
import { createWorktree, worktreePath } from "./worktree-manager.js";
|
|
24
|
-
import { autoWorktreeBranch, fastForwardReusedMilestoneBranchIfSafe
|
|
24
|
+
import { autoWorktreeBranch, fastForwardReusedMilestoneBranchIfSafe } from "./auto-worktree-branch-lifecycle.js";
|
|
25
|
+
import { syncGsdStateToWorktreeByScope } from "./auto-worktree-sync.js";
|
|
26
|
+
import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
|
|
25
27
|
import { nativeBranchExists } from "./native-git-bridge.js";
|
|
26
28
|
import { readIntegrationBranch } from "./git-service.js";
|
|
27
29
|
import { createWorkspace, scopeMilestone } from "./workspace.js";
|
|
@@ -29,6 +29,33 @@ export interface ContextManagementConfig {
|
|
|
29
29
|
tool_result_max_chars?: number; // default: 800, range: 200-10000
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* User-tunable thresholds for the tool-call loop guard (#1198). Keeps the two
|
|
34
|
+
* guards separately configurable: the identical-args guard (catches real
|
|
35
|
+
* infinite loops) and the repeated-tool-name cap (catches improvisation loops,
|
|
36
|
+
* more likely to false-positive on legitimate automation). All fields are
|
|
37
|
+
* optional; omitted fields fall back to the built-in defaults so existing
|
|
38
|
+
* installs keep their current behavior. Also overridable via GSD_TOOL_LOOP_*
|
|
39
|
+
* environment variables.
|
|
40
|
+
*/
|
|
41
|
+
export interface ToolCallLoopGuardConfig {
|
|
42
|
+
/** Master switch for both guards. Default: true. */
|
|
43
|
+
enabled?: boolean;
|
|
44
|
+
/** Identical-args sliding-window guard. */
|
|
45
|
+
identical_args?: {
|
|
46
|
+
enabled?: boolean; // default: true
|
|
47
|
+
max_consecutive_calls?: number; // default: 4, min: 1
|
|
48
|
+
};
|
|
49
|
+
/** Per-tool-name cap, independent of args. */
|
|
50
|
+
repeated_tool?: {
|
|
51
|
+
enabled?: boolean; // default: true
|
|
52
|
+
default_cap?: number; // default: 6, min: 1
|
|
53
|
+
repeatable_cap?: number; // default: 15, min: 1
|
|
54
|
+
/** Additional tool names exempt from the per-tool cap (merged with built-in defaults). */
|
|
55
|
+
exempt_tools?: string[];
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
32
59
|
/**
|
|
33
60
|
* Opt-in tool-output sandboxing for sub-sessions. When enabled, the gsd_exec
|
|
34
61
|
* MCP tool runs scripts in an isolated subprocess and returns only a short
|
|
@@ -139,6 +166,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
139
166
|
"min_request_interval_ms",
|
|
140
167
|
"stale_commit_threshold_minutes",
|
|
141
168
|
"context_management",
|
|
169
|
+
"tool_call_loop_guard",
|
|
142
170
|
"experimental",
|
|
143
171
|
"codebase",
|
|
144
172
|
"slice_parallel",
|
|
@@ -440,6 +468,8 @@ export interface GSDPreferences {
|
|
|
440
468
|
*/
|
|
441
469
|
context_window_override?: number;
|
|
442
470
|
context_management?: ContextManagementConfig;
|
|
471
|
+
/** User-tunable tool-call loop guard thresholds (#1198). */
|
|
472
|
+
tool_call_loop_guard?: ToolCallLoopGuardConfig;
|
|
443
473
|
/**
|
|
444
474
|
* Tool-output sandboxing via gsd_exec. Keeps sub-session context windows
|
|
445
475
|
* clean by running scripts in a subprocess and only surfacing a short
|
|
@@ -794,6 +794,75 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
794
794
|
}
|
|
795
795
|
}
|
|
796
796
|
|
|
797
|
+
// ─── Tool-call loop guard (#1198) ────────────────────────────────────────
|
|
798
|
+
if (preferences.tool_call_loop_guard !== undefined) {
|
|
799
|
+
if (typeof preferences.tool_call_loop_guard === "object" && preferences.tool_call_loop_guard !== null) {
|
|
800
|
+
const g = preferences.tool_call_loop_guard as unknown as Record<string, unknown>;
|
|
801
|
+
const validGuard: Record<string, unknown> = {};
|
|
802
|
+
|
|
803
|
+
if (g.enabled !== undefined) {
|
|
804
|
+
if (typeof g.enabled === "boolean") validGuard.enabled = g.enabled;
|
|
805
|
+
else errors.push("tool_call_loop_guard.enabled must be a boolean");
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (g.identical_args !== undefined) {
|
|
809
|
+
if (typeof g.identical_args === "object" && g.identical_args !== null) {
|
|
810
|
+
const ia = g.identical_args as Record<string, unknown>;
|
|
811
|
+
const validIa: Record<string, unknown> = {};
|
|
812
|
+
if (ia.enabled !== undefined) {
|
|
813
|
+
if (typeof ia.enabled === "boolean") validIa.enabled = ia.enabled;
|
|
814
|
+
else errors.push("tool_call_loop_guard.identical_args.enabled must be a boolean");
|
|
815
|
+
}
|
|
816
|
+
if (ia.max_consecutive_calls !== undefined) {
|
|
817
|
+
const n = ia.max_consecutive_calls;
|
|
818
|
+
if (typeof n === "number" && Number.isInteger(n) && n >= 1) validIa.max_consecutive_calls = n;
|
|
819
|
+
else errors.push("tool_call_loop_guard.identical_args.max_consecutive_calls must be an integer >= 1");
|
|
820
|
+
}
|
|
821
|
+
if (Object.keys(validIa).length > 0) validGuard.identical_args = validIa;
|
|
822
|
+
} else {
|
|
823
|
+
errors.push("tool_call_loop_guard.identical_args must be an object");
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
if (g.repeated_tool !== undefined) {
|
|
828
|
+
if (typeof g.repeated_tool === "object" && g.repeated_tool !== null) {
|
|
829
|
+
const rt = g.repeated_tool as Record<string, unknown>;
|
|
830
|
+
const validRt: Record<string, unknown> = {};
|
|
831
|
+
if (rt.enabled !== undefined) {
|
|
832
|
+
if (typeof rt.enabled === "boolean") validRt.enabled = rt.enabled;
|
|
833
|
+
else errors.push("tool_call_loop_guard.repeated_tool.enabled must be a boolean");
|
|
834
|
+
}
|
|
835
|
+
if (rt.default_cap !== undefined) {
|
|
836
|
+
const n = rt.default_cap;
|
|
837
|
+
if (typeof n === "number" && Number.isInteger(n) && n >= 1) validRt.default_cap = n;
|
|
838
|
+
else errors.push("tool_call_loop_guard.repeated_tool.default_cap must be an integer >= 1");
|
|
839
|
+
}
|
|
840
|
+
if (rt.repeatable_cap !== undefined) {
|
|
841
|
+
const n = rt.repeatable_cap;
|
|
842
|
+
if (typeof n === "number" && Number.isInteger(n) && n >= 1) validRt.repeatable_cap = n;
|
|
843
|
+
else errors.push("tool_call_loop_guard.repeated_tool.repeatable_cap must be an integer >= 1");
|
|
844
|
+
}
|
|
845
|
+
if (rt.exempt_tools !== undefined) {
|
|
846
|
+
if (Array.isArray(rt.exempt_tools) && rt.exempt_tools.every((t) => typeof t === "string")) {
|
|
847
|
+
validRt.exempt_tools = rt.exempt_tools;
|
|
848
|
+
} else {
|
|
849
|
+
errors.push("tool_call_loop_guard.repeated_tool.exempt_tools must be an array of strings");
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
if (Object.keys(validRt).length > 0) validGuard.repeated_tool = validRt;
|
|
853
|
+
} else {
|
|
854
|
+
errors.push("tool_call_loop_guard.repeated_tool must be an object");
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
if (Object.keys(validGuard).length > 0) {
|
|
859
|
+
validated.tool_call_loop_guard = validGuard as any;
|
|
860
|
+
}
|
|
861
|
+
} else {
|
|
862
|
+
errors.push("tool_call_loop_guard must be an object");
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
797
866
|
// ─── Context Mode (gsd_exec sandbox) ────────────────────────────────────
|
|
798
867
|
if (preferences.context_mode !== undefined) {
|
|
799
868
|
if (typeof preferences.context_mode === "object" && preferences.context_mode !== null) {
|
|
@@ -38,7 +38,7 @@ If a `GSD Skill Preferences` block appears below, treat it as durable guidance f
|
|
|
38
38
|
|
|
39
39
|
### Naming Convention
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
GSD projects use a flat-phase layout. Phase directories are `{MM}-{slug}` where `{MM}` is the zero-padded phase number and `{slug}` is derived from the phase title (e.g. `47-real-time-runtime-hardening`). Phase-level files are `{MM}-SUFFIX.md` (e.g. `47-CONTEXT.md`, `47-RESEARCH.md`, `47-ROADMAP.md`, `47-VALIDATION.md`, `47-SUMMARY.md`). Slice/plan files live directly in the phase directory as `{MM}-{SS}-SUFFIX.md` (e.g. `47-01-PLAN.md`, `47-01-SUMMARY.md`, `47-01-UAT.md`). Task plan content lives inside the slice plan file (`{MM}-{SS}-PLAN.md`) as checkboxes; there is no `tasks/` subdirectory and no `tasks/T##-PLAN.md`. Titles live inside content, not names. Prefer GSD-provided layout-aware paths/resolvers over hardcoding artifact paths, since phase slugs are title-derived.
|
|
42
42
|
|
|
43
43
|
### Directory Structure
|
|
44
44
|
|
|
@@ -46,13 +46,13 @@ Directories use bare IDs. Files use ID-SUFFIX format. Milestones: `M001/` or `M{
|
|
|
46
46
|
.gsd/
|
|
47
47
|
PROJECT.md, REQUIREMENTS.md, DECISIONS.md, KNOWLEDGE.md, CODEBASE.md, OVERRIDES.md, QUEUE.md, STATE.md
|
|
48
48
|
runtime/, activity/, worktrees/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
S01-CONTEXT.md, S01-RESEARCH.md, S01-PLAN.md, S01-SUMMARY.md, S01-UAT.md
|
|
53
|
-
tasks/T01-PLAN.md, tasks/T01-SUMMARY.md
|
|
49
|
+
phases/{MM}-{slug}/
|
|
50
|
+
{MM}-CONTEXT.md, {MM}-RESEARCH.md, {MM}-ROADMAP.md, {MM}-VALIDATION.md, {MM}-SUMMARY.md
|
|
51
|
+
{MM}-{SS}-PLAN.md, {MM}-{SS}-SUMMARY.md, {MM}-{SS}-UAT.md
|
|
54
52
|
```
|
|
55
53
|
|
|
54
|
+
Task plan content is embedded in `{MM}-{SS}-PLAN.md`; do not expect `tasks/T##-PLAN.md`.
|
|
55
|
+
|
|
56
56
|
`runtime/`, `activity/`, `worktrees/`, and `STATE.md` are system-managed. `PROJECT.md` is current state; `REQUIREMENTS.md` is the active capability contract; `DECISIONS.md` and `KNOWLEDGE.md` are append-only; `CODEBASE.md` is an auto-refreshed codebase map.
|
|
57
57
|
|
|
58
58
|
### Isolation Model
|
|
@@ -15,7 +15,7 @@ import { isAbsolute, join, relative, resolve } from "node:path";
|
|
|
15
15
|
import { QUICK_BRANCH_RE } from "./branch-patterns.js";
|
|
16
16
|
import { loadPrompt } from "./prompt-loader.js";
|
|
17
17
|
import { gsdRoot } from "./paths.js";
|
|
18
|
-
import { GitServiceImpl, runGit } from "./git-service.js";
|
|
18
|
+
import { GitServiceImpl, runGit, taskBranchArgs } from "./git-service.js";
|
|
19
19
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
20
20
|
import { nativeBranchExists, nativeDetectMainBranch, nativeDiffNumstat } from "./native-git-bridge.js";
|
|
21
21
|
import { nativeHasStagedChanges } from "./native-git-bridge.js";
|
|
@@ -365,6 +365,7 @@ export async function handleQuick(
|
|
|
365
365
|
const git = new GitServiceImpl(basePath, gitPrefs);
|
|
366
366
|
const branchName = `gsd/quick/${taskNum}-${slug}`;
|
|
367
367
|
let originalBranch = git.getCurrentBranch();
|
|
368
|
+
let returnBranch = originalBranch;
|
|
368
369
|
|
|
369
370
|
const { getIsolationMode } = await import("./preferences.js");
|
|
370
371
|
const usesBranch = getIsolationMode() !== "none" && isGitOpsEnabled();
|
|
@@ -381,7 +382,14 @@ export async function handleQuick(
|
|
|
381
382
|
}
|
|
382
383
|
} catch { /* nothing to commit — fine */ }
|
|
383
384
|
|
|
384
|
-
|
|
385
|
+
const branchArgs = taskBranchArgs(basePath, branchName, current, git.getMainBranch());
|
|
386
|
+
const startPoint = branchArgs[3];
|
|
387
|
+
// When the quick branch is redirected off a stale task branch, the
|
|
388
|
+
// squash-merge on closeout must return to the same base — merging a
|
|
389
|
+
// base-branch-rooted quick branch back into the stale task branch
|
|
390
|
+
// would drag the base's newer history into it.
|
|
391
|
+
if (startPoint) returnBranch = startPoint;
|
|
392
|
+
runGit(basePath, branchArgs);
|
|
385
393
|
branchCreated = true;
|
|
386
394
|
}
|
|
387
395
|
} catch (err) {
|
|
@@ -395,7 +403,7 @@ export async function handleQuick(
|
|
|
395
403
|
if (actualBranch === branchName && originalBranch !== branchName) {
|
|
396
404
|
persistPendingReturn({
|
|
397
405
|
basePath,
|
|
398
|
-
originalBranch,
|
|
406
|
+
originalBranch: returnBranch,
|
|
399
407
|
quickBranch: branchName,
|
|
400
408
|
taskNum,
|
|
401
409
|
slug,
|
|
@@ -30,7 +30,9 @@ import { isAbsolute, join, dirname, resolve } from "node:path";
|
|
|
30
30
|
import { fileURLToPath } from "node:url";
|
|
31
31
|
import { gsdRoot } from "./paths.js";
|
|
32
32
|
import { createWorktree, worktreePath, removeWorktree } from "./worktree-manager.js";
|
|
33
|
-
import { autoWorktreeBranch
|
|
33
|
+
import { autoWorktreeBranch } from "./auto-worktree-branch-lifecycle.js";
|
|
34
|
+
import { syncGsdStateToWorktreeByScope } from "./auto-worktree-sync.js";
|
|
35
|
+
import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
|
|
34
36
|
import { createWorkspace, scopeMilestone } from "./workspace.js";
|
|
35
37
|
import {
|
|
36
38
|
writeSessionStatus,
|