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.
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/phases.js +7 -1
- package/dist/resources/extensions/gsd/auto.js +7 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +46 -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 +10 -10
- 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 +10 -10
- 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/package.json +1 -1
- package/src/resources/extensions/gsd/auto/phases.ts +8 -1
- package/src/resources/extensions/gsd/auto.ts +8 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +45 -1
- package/src/resources/extensions/gsd/doctor-types.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
- /package/dist/web/standalone/.next/static/{xRy4LqKSNKdT7y6ATYyEl → kkGf3_VaPFkiDNV_D7Dtl}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{xRy4LqKSNKdT7y6ATYyEl → kkGf3_VaPFkiDNV_D7Dtl}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
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,
|
|
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(
|
|
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",
|