gsd-pi 2.33.1-dev.9bafd68 → 2.33.1-dev.b1c6556

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.
Files changed (26) hide show
  1. package/dist/resource-loader.js +3 -1
  2. package/dist/resources/extensions/gsd/auto-start.js +300 -288
  3. package/dist/resources/extensions/gsd/auto-worktree.js +71 -0
  4. package/dist/resources/extensions/gsd/auto.js +11 -1
  5. package/dist/resources/extensions/gsd/session-lock.js +13 -0
  6. package/package.json +1 -1
  7. package/packages/pi-ai/dist/models.generated.d.ts +5498 -3645
  8. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  9. package/packages/pi-ai/dist/models.generated.js +2595 -742
  10. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  11. package/packages/pi-ai/src/models.generated.ts +2852 -999
  12. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  13. package/packages/pi-coding-agent/dist/core/agent-session.js +9 -0
  14. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  15. package/packages/pi-coding-agent/src/core/agent-session.ts +9 -0
  16. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  17. package/packages/pi-tui/dist/utils.js +32 -2
  18. package/packages/pi-tui/dist/utils.js.map +1 -1
  19. package/packages/pi-tui/src/utils.ts +28 -2
  20. package/src/resources/extensions/gsd/auto-start.ts +22 -10
  21. package/src/resources/extensions/gsd/auto-worktree.ts +71 -0
  22. package/src/resources/extensions/gsd/auto.ts +11 -0
  23. package/src/resources/extensions/gsd/session-lock.ts +11 -0
  24. package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +37 -0
  25. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +4 -4
  26. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +64 -0
@@ -140,6 +140,77 @@ export function syncGsdStateToWorktree(mainBasePath, worktreePath_) {
140
140
  }
141
141
  return { synced };
142
142
  }
143
+ /**
144
+ * Sync milestone artifacts from worktree back to the main external state directory.
145
+ * Called before milestone merge to ensure completion artifacts (SUMMARY, VALIDATION,
146
+ * updated ROADMAP) are visible from the project root (#1412).
147
+ *
148
+ * Only syncs .gsd/milestones/ content — root-level files (DECISIONS, REQUIREMENTS, etc.)
149
+ * are handled by the merge itself.
150
+ */
151
+ export function syncWorktreeStateBack(mainBasePath, worktreePath, milestoneId) {
152
+ const mainGsd = gsdRoot(mainBasePath);
153
+ const wtGsd = gsdRoot(worktreePath);
154
+ const synced = [];
155
+ // If both resolve to the same directory (symlink), no sync needed
156
+ try {
157
+ const mainResolved = realpathSync(mainGsd);
158
+ const wtResolved = realpathSync(wtGsd);
159
+ if (mainResolved === wtResolved)
160
+ return { synced };
161
+ }
162
+ catch {
163
+ // Can't resolve — proceed with sync
164
+ }
165
+ const wtMilestoneDir = join(wtGsd, "milestones", milestoneId);
166
+ const mainMilestoneDir = join(mainGsd, "milestones", milestoneId);
167
+ if (!existsSync(wtMilestoneDir))
168
+ return { synced };
169
+ mkdirSync(mainMilestoneDir, { recursive: true });
170
+ // Sync milestone-level files (SUMMARY, VALIDATION, ROADMAP, CONTEXT)
171
+ try {
172
+ for (const entry of readdirSync(wtMilestoneDir, { withFileTypes: true })) {
173
+ if (entry.isFile() && entry.name.endsWith(".md")) {
174
+ const src = join(wtMilestoneDir, entry.name);
175
+ const dst = join(mainMilestoneDir, entry.name);
176
+ try {
177
+ cpSync(src, dst, { force: true });
178
+ synced.push(`milestones/${milestoneId}/${entry.name}`);
179
+ }
180
+ catch { /* non-fatal */ }
181
+ }
182
+ }
183
+ }
184
+ catch { /* non-fatal */ }
185
+ // Sync slice-level files (summaries, UATs)
186
+ const wtSlicesDir = join(wtMilestoneDir, "slices");
187
+ const mainSlicesDir = join(mainMilestoneDir, "slices");
188
+ if (existsSync(wtSlicesDir)) {
189
+ try {
190
+ for (const sliceEntry of readdirSync(wtSlicesDir, { withFileTypes: true })) {
191
+ if (!sliceEntry.isDirectory())
192
+ continue;
193
+ const sid = sliceEntry.name;
194
+ const wtSliceDir = join(wtSlicesDir, sid);
195
+ const mainSliceDir = join(mainSlicesDir, sid);
196
+ mkdirSync(mainSliceDir, { recursive: true });
197
+ for (const fileEntry of readdirSync(wtSliceDir, { withFileTypes: true })) {
198
+ if (fileEntry.isFile() && fileEntry.name.endsWith(".md")) {
199
+ const src = join(wtSliceDir, fileEntry.name);
200
+ const dst = join(mainSliceDir, fileEntry.name);
201
+ try {
202
+ cpSync(src, dst, { force: true });
203
+ synced.push(`milestones/${milestoneId}/slices/${sid}/${fileEntry.name}`);
204
+ }
205
+ catch { /* non-fatal */ }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ catch { /* non-fatal */ }
211
+ }
212
+ return { synced };
213
+ }
143
214
  // ─── Worktree Post-Create Hook (#597) ────────────────────────────────────────
144
215
  /**
145
216
  * Run the user-configured post-create hook script after worktree creation.
@@ -41,7 +41,7 @@ import { atomicWriteSync } from "./atomic-write.js";
41
41
  import { autoCommitCurrentBranch, captureIntegrationBranch, detectWorktreeName, getCurrentBranch, getMainBranch, setActiveMilestoneId, } from "./worktree.js";
42
42
  import { createGitService } from "./git-service.js";
43
43
  import { getPriorSliceCompletionBlocker } from "./dispatch-guard.js";
44
- import { createAutoWorktree, enterAutoWorktree, teardownAutoWorktree, isInAutoWorktree, getAutoWorktreePath, mergeMilestoneToMain, autoWorktreeBranch, } from "./auto-worktree.js";
44
+ import { createAutoWorktree, enterAutoWorktree, teardownAutoWorktree, isInAutoWorktree, getAutoWorktreePath, mergeMilestoneToMain, autoWorktreeBranch, syncWorktreeStateBack, } from "./auto-worktree.js";
45
45
  import { pruneQueueOrder } from "./queue-order.js";
46
46
  import { showNextAction } from "../shared/mod.js";
47
47
  import { debugLog, debugTime, isDebugEnabled, writeDebugSummary } from "./debug-logger.js";
@@ -228,6 +228,16 @@ function tryMergeMilestone(ctx, milestoneId, mode) {
228
228
  // Worktree merge path
229
229
  if (isInAutoWorktree(s.basePath) && s.originalBasePath) {
230
230
  try {
231
+ // Sync completion artifacts from worktree → external state before merge (#1412)
232
+ try {
233
+ const { synced } = syncWorktreeStateBack(s.originalBasePath, s.basePath, milestoneId);
234
+ if (synced.length > 0) {
235
+ debugLog("worktree-reverse-sync", { milestoneId, synced: synced.length });
236
+ }
237
+ }
238
+ catch (syncErr) {
239
+ debugLog("worktree-reverse-sync-failed", { milestoneId, error: getErrorMessage(syncErr) });
240
+ }
231
241
  const roadmapPath = resolveMilestoneFile(s.originalBasePath, milestoneId, "ROADMAP");
232
242
  if (!roadmapPath) {
233
243
  teardownAutoWorktree(s.originalBasePath, milestoneId);
@@ -129,6 +129,18 @@ function ensureExitHandler(gsdDir) {
129
129
  */
130
130
  export function acquireSessionLock(basePath) {
131
131
  const lp = lockPath(basePath);
132
+ // Re-entrant acquire on the same path: release our current OS lock first so
133
+ // proper-lockfile clears its update timer before we acquire a fresh lock.
134
+ if (_releaseFunction && _lockedPath === basePath) {
135
+ try {
136
+ _releaseFunction();
137
+ }
138
+ catch { /* may already be released */ }
139
+ _releaseFunction = null;
140
+ _lockedPath = null;
141
+ _lockPid = 0;
142
+ _lockCompromised = false;
143
+ }
132
144
  // Ensure the directory exists
133
145
  mkdirSync(dirname(lp), { recursive: true });
134
146
  // Clean up numbered lock file variants from cloud sync conflicts (#1315)
@@ -206,6 +218,7 @@ export function acquireSessionLock(basePath) {
206
218
  _releaseFunction = release;
207
219
  _lockedPath = basePath;
208
220
  _lockPid = process.pid;
221
+ _lockCompromised = false;
209
222
  // Safety net — uses centralized handler to avoid double-registration
210
223
  ensureExitHandler(gsdDir);
211
224
  atomicWriteSync(lp, JSON.stringify(lockData, null, 2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gsd-pi",
3
- "version": "2.33.1-dev.9bafd68",
3
+ "version": "2.33.1-dev.b1c6556",
4
4
  "description": "GSD — Get Shit Done coding agent",
5
5
  "license": "MIT",
6
6
  "repository": {