gsd-pi 2.82.0-dev.20138ae42 → 2.82.0-dev.3709f22a5

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 (46) hide show
  1. package/dist/resources/.managed-resources-content-hash +1 -1
  2. package/dist/resources/extensions/gsd/auto/phases.js +7 -1
  3. package/dist/resources/extensions/gsd/auto.js +7 -1
  4. package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -1
  5. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  6. package/dist/web/standalone/.next/BUILD_ID +1 -1
  7. package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
  8. package/dist/web/standalone/.next/build-manifest.json +2 -2
  9. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  10. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  11. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  12. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  13. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  14. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  15. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  16. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  17. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  19. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  20. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  21. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  22. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  23. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  24. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  25. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  26. package/dist/web/standalone/.next/server/app/index.html +1 -1
  27. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  28. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  29. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  30. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  31. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  32. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  33. package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
  34. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  35. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  36. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  37. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  38. package/package.json +1 -1
  39. package/src/resources/extensions/gsd/auto/phases.ts +8 -1
  40. package/src/resources/extensions/gsd/auto.ts +8 -1
  41. package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
  42. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  43. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
  44. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  45. /package/dist/web/standalone/.next/static/{xRy4LqKSNKdT7y6ATYyEl → kkGf3_VaPFkiDNV_D7Dtl}/_buildManifest.js +0 -0
  46. /package/dist/web/standalone/.next/static/{xRy4LqKSNKdT7y6ATYyEl → kkGf3_VaPFkiDNV_D7Dtl}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- ecbb2e6b2eb47e9d
1
+ d2173e15ccf5aedf
@@ -104,6 +104,12 @@ function unitWritesSource(unitType) {
104
104
  function formatWorktreeSafetyFailure(result) {
105
105
  return `Worktree Safety failed (${result.kind}): ${result.reason} ${result.remediation}`;
106
106
  }
107
+ function formatWorktreeSafetyStopReason(result) {
108
+ if (result.kind === "empty-worktree-with-project-content") {
109
+ return `Worktree Safety failed (${result.kind}). Run /gsd doctor fix, then /gsd auto.`;
110
+ }
111
+ return `Worktree Safety failed (${result.kind}).`;
112
+ }
107
113
  function resolveEmptyWorktreeWithProjectContent(unitRoot, projectRoot) {
108
114
  if (isSamePathLocal(unitRoot, projectRoot))
109
115
  return false;
@@ -177,7 +183,7 @@ async function validateSourceWriteWorktreeSafety(ic, unitType, unitId, milestone
177
183
  projectRoot,
178
184
  });
179
185
  ctx.ui.notify(msg, "error");
180
- await deps.stopAuto(ctx, pi, msg);
186
+ await deps.stopAuto(ctx, pi, formatWorktreeSafetyStopReason(result));
181
187
  return { action: "break", reason: result.kind };
182
188
  }
183
189
  // ─── Session timeout auto-resume state ────────────────────────────────────────
@@ -127,6 +127,12 @@ import { normalizeRealPath } from "./paths.js";
127
127
  // ─────────────────────────────────────────────────────────────────────────────
128
128
  /** Throttle STATE.md rebuilds — at most once per 30 seconds */
129
129
  const STATE_REBUILD_MIN_INTERVAL_MS = 30_000;
130
+ export function formatAutoStopNotification(prefix, totals, unitCount) {
131
+ return [
132
+ `${prefix}.`,
133
+ `Session: ${formatCost(totals.cost)} · ${formatTokenCount(totals.tokens.total)} tokens · ${unitCount} units`,
134
+ ].join("\n");
135
+ }
130
136
  /**
131
137
  * Phase B — register this auto-mode process in the workers table so other
132
138
  * workers and janitors can detect liveness via heartbeat. Best-effort: if
@@ -1030,7 +1036,7 @@ export async function stopAuto(ctx, pi, reason, options = {}) {
1030
1036
  : `Auto-mode stopped${reasonSuffix}`;
1031
1037
  if (ledger && ledger.units.length > 0) {
1032
1038
  const totals = getProjectTotals(ledger.units);
1033
- ctx?.ui.notify(`${notificationPrefix}. Session: ${formatCost(totals.cost)} · ${formatTokenCount(totals.tokens.total)} tokens · ${ledger.units.length} units`, "info");
1039
+ ctx?.ui.notify(formatAutoStopNotification(notificationPrefix, totals, ledger.units.length), "info");
1034
1040
  }
1035
1041
  else {
1036
1042
  ctx?.ui.notify(`${notificationPrefix}.`, "info");
@@ -7,7 +7,7 @@ import { parseRoadmap as parseLegacyRoadmap } from "./parsers-legacy.js";
7
7
  import { isDbAvailable, getMilestone } from "./gsd-db.js";
8
8
  import { resolveMilestoneFile } from "./paths.js";
9
9
  import { deriveState, isMilestoneComplete } from "./state.js";
10
- import { listWorktrees, resolveGitDir, worktreesDir } from "./worktree-manager.js";
10
+ import { createWorktree, listWorktrees, resolveGitDir, worktreesDir } from "./worktree-manager.js";
11
11
  import { abortAndReset } from "./git-self-heal.js";
12
12
  import { RUNTIME_EXCLUSION_PATHS, resolveMilestoneIntegrationBranch, writeIntegrationBranch } from "./git-service.js";
13
13
  import { nativeIsRepo, nativeWorktreeList, nativeWorktreeRemove, nativeBranchList, nativeBranchDelete, nativeLsFiles, nativeRmCached, nativeHasChanges, nativeLastCommitEpoch, nativeGetCurrentBranch, nativeAddTracked, nativeCommit } from "./native-git-bridge.js";
@@ -50,6 +50,21 @@ function isSameOrNestedPath(candidate, container) {
50
50
  return normalizedCandidate === normalizedContainer ||
51
51
  normalizedCandidate.startsWith(`${normalizedContainer}/`);
52
52
  }
53
+ function hasProjectContentOnDisk(dirPath) {
54
+ try {
55
+ for (const entry of readdirSync(dirPath, { withFileTypes: true })) {
56
+ if (entry.name === ".git" || entry.name === ".gsd")
57
+ continue;
58
+ if (entry.name === ".DS_Store")
59
+ continue;
60
+ return true;
61
+ }
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ return false;
67
+ }
53
68
  function getSnapshotDiffCheckFailure(basePath) {
54
69
  const failures = [];
55
70
  for (const args of [["--cached"], []]) {
@@ -104,6 +119,36 @@ export async function checkGitHealth(basePath, issues, fixesApplied, shouldFix,
104
119
  const isComplete = milestoneEntry
105
120
  ? await isCompletedMilestoneTerminal(basePath, milestoneId)
106
121
  : false;
122
+ if (!isComplete && !hasProjectContentOnDisk(wt.path) && hasProjectContentOnDisk(basePath)) {
123
+ issues.push({
124
+ severity: "error",
125
+ code: "worktree_empty_with_project_content",
126
+ scope: "milestone",
127
+ unitId: milestoneId,
128
+ message: `Worktree ${wt.path} has no project content, but project root ${basePath} does. Run doctor --fix to recreate the worktree.`,
129
+ fixable: true,
130
+ });
131
+ if (shouldFix("worktree_empty_with_project_content")) {
132
+ try {
133
+ nativeWorktreeRemove(basePath, wt.path, true);
134
+ const recreated = createWorktree(basePath, milestoneId, {
135
+ branch: wt.branch,
136
+ reuseExistingBranch: true,
137
+ });
138
+ const reset = spawnSync("git", ["reset", "--hard"], {
139
+ cwd: recreated.path,
140
+ encoding: "utf-8",
141
+ });
142
+ if (reset.status !== 0) {
143
+ throw new Error(reset.stderr || reset.error?.message || "git reset --hard failed");
144
+ }
145
+ fixesApplied.push(`recreated empty worktree ${wt.path}`);
146
+ }
147
+ catch {
148
+ fixesApplied.push(`failed to recreate empty worktree ${wt.path}`);
149
+ }
150
+ }
151
+ }
107
152
  if (isComplete) {
108
153
  issues.push({
109
154
  severity: "warning",