@opengsd/gsd-pi 1.1.1-dev.154fd443 → 1.1.1-dev.1854a79a
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/project-sessions.js +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/index.js +39 -22
- package/dist/resources/extensions/browser-tools/state.js +12 -0
- package/dist/resources/extensions/browser-tools/tools/session.js +3 -2
- package/dist/resources/extensions/browser-tools/utils.js +3 -3
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -9
- package/dist/resources/extensions/gsd/auto/contracts.js +8 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +659 -57
- package/dist/resources/extensions/gsd/auto-prompts.js +14 -1
- package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +5 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +29 -0
- package/dist/resources/extensions/gsd/auto.js +62 -464
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +2 -1
- package/dist/resources/extensions/gsd/debug-logger.js +10 -0
- package/dist/resources/extensions/gsd/doctor-proactive.js +7 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +31 -32
- package/dist/resources/extensions/gsd/mcp-filter.js +6 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +9 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/schemas/parsers.js +6 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +21 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +169 -20
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- 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/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +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 +6 -6
- package/dist/web/standalone/.next/server/chunks/5047.js +2 -0
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -0
- package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
- 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/node-pty/build/Makefile +1 -1
- package/package.json +6 -4
- 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/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +21 -23
- package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- 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 +18 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +16 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +0 -34
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +0 -34
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +11 -3
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +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/package.json +1 -1
- package/src/resources/extensions/browser-tools/index.ts +39 -22
- package/src/resources/extensions/browser-tools/state.ts +13 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +57 -0
- package/src/resources/extensions/browser-tools/tools/session.ts +4 -2
- package/src/resources/extensions/browser-tools/utils.ts +3 -3
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -8
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +2 -2
- package/src/resources/extensions/gsd/auto/contracts.ts +8 -119
- package/src/resources/extensions/gsd/auto/orchestrator.ts +794 -58
- package/src/resources/extensions/gsd/auto-prompts.ts +21 -1
- package/src/resources/extensions/gsd/auto-runtime-state.ts +4 -0
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +5 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +33 -0
- package/src/resources/extensions/gsd/auto.ts +81 -500
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +2 -0
- package/src/resources/extensions/gsd/debug-logger.ts +11 -0
- package/src/resources/extensions/gsd/doctor-proactive.ts +8 -2
- package/src/resources/extensions/gsd/markdown-renderer.ts +38 -19
- package/src/resources/extensions/gsd/mcp-filter.ts +7 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +9 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/schemas/parsers.ts +6 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +31 -10
- package/src/resources/extensions/gsd/tests/artifact-db-drift-memo.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/auto-dispatch-baseline-harness.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +590 -855
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +38 -10
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/markdown-renderer-parse-cache.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/orchestrator-legacy-parity.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/parse-project-milestone-bridge.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +19 -5
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -3
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +183 -21
- package/dist/web/standalone/.next/server/chunks/678.js +0 -2
- /package/dist/web/standalone/.next/static/{vAecbJ3K9eO213bAxU8Mi → h38jfi0dnRY0y3hbyBszg}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{vAecbJ3K9eO213bAxU8Mi → h38jfi0dnRY0y3hbyBszg}/_ssgManifest.js +0 -0
|
@@ -6,10 +6,11 @@ import { sanitizeCompleteMilestoneParams } from "../bootstrap/sanitize-complete-
|
|
|
6
6
|
import { loadWriteGateSnapshot, shouldBlockContextArtifactSaveInSnapshot, shouldBlockRootArtifactSaveInSnapshot } from "../bootstrap/write-gate.js";
|
|
7
7
|
import {
|
|
8
8
|
getActiveRequirements,
|
|
9
|
-
|
|
9
|
+
getAllMilestones,
|
|
10
10
|
getMilestone,
|
|
11
11
|
getSliceStatusSummary,
|
|
12
12
|
getSliceTaskCounts,
|
|
13
|
+
insertMilestone,
|
|
13
14
|
insertAssessment,
|
|
14
15
|
insertGateRun,
|
|
15
16
|
readTransaction,
|
|
@@ -126,6 +127,111 @@ function registerProjectMilestoneSequence(content: string): string[] {
|
|
|
126
127
|
return registered;
|
|
127
128
|
}
|
|
128
129
|
|
|
130
|
+
/** Minimal shape of a DB milestone row needed to re-render the sequence section. */
|
|
131
|
+
interface MilestoneSeqRow {
|
|
132
|
+
id: string;
|
|
133
|
+
title: string;
|
|
134
|
+
status: string;
|
|
135
|
+
vision: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Best-effort recovery of the human one-liner for each milestone id from a
|
|
140
|
+
* (possibly malformed) Milestone Sequence body. Deliberately lenient: tolerates
|
|
141
|
+
* any separator the canonical MILESTONE_LINE_RE rejects (en-dash, " : ", a
|
|
142
|
+
* missing checkbox, etc.) so a model formatting slip does not discard the prose.
|
|
143
|
+
*/
|
|
144
|
+
function recoverMilestoneTails(sequenceBody: string): Map<string, string> {
|
|
145
|
+
const out = new Map<string, string>();
|
|
146
|
+
const lenient = /^\s*(?:-\s*)?(?:\[[ xX]\]\s*)?(M\d{3})\b\s*[:.\-–—]*\s*(.*)$/;
|
|
147
|
+
for (const rawLine of sequenceBody.split("\n")) {
|
|
148
|
+
const m = rawLine.match(lenient);
|
|
149
|
+
if (m) out.set(m[1], m[2].trim());
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function firstSentence(text: string): string {
|
|
155
|
+
const trimmed = text.trim();
|
|
156
|
+
if (!trimmed) return "";
|
|
157
|
+
const idx = trimmed.search(/[.!?](\s|$)/);
|
|
158
|
+
return (idx >= 0 ? trimmed.slice(0, idx + 1) : trimmed).trim();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Render one canonical, parseable milestone line for the given DB row. */
|
|
162
|
+
function renderMilestoneLine(m: MilestoneSeqRow, recoveredTail: string): string {
|
|
163
|
+
const done = m.status === "complete";
|
|
164
|
+
let oneLiner = recoveredTail;
|
|
165
|
+
// The recovered tail often still carries the title (e.g. "Foo — bar" or
|
|
166
|
+
// "Foo : bar"). Strip a leading repetition of the title, then any separator.
|
|
167
|
+
if (oneLiner.toLowerCase().startsWith(m.title.toLowerCase())) {
|
|
168
|
+
oneLiner = oneLiner.slice(m.title.length).replace(/^\s*[:.\-–—]+\s*/, "").trim();
|
|
169
|
+
} else {
|
|
170
|
+
const sep = oneLiner.match(/\s+(?:—|–|--|-|:)\s+/);
|
|
171
|
+
if (sep && sep.index !== undefined) oneLiner = oneLiner.slice(sep.index + sep[0].length).trim();
|
|
172
|
+
}
|
|
173
|
+
// MILESTONE_LINE_RE requires non-empty prose after the separator.
|
|
174
|
+
if (!oneLiner) oneLiner = firstSentence(m.vision) || (done ? "Completed." : "Planned.");
|
|
175
|
+
return `- [${done ? "x" : " "}] ${m.id}: ${m.title} — ${oneLiner}`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Rebuild the "## Milestone Sequence" section from authoritative DB rows when a
|
|
180
|
+
* model-authored PROJECT.md projection parsed to zero milestone lines but the DB
|
|
181
|
+
* already holds milestones. The DB is the source of truth (markdown is a
|
|
182
|
+
* projection), so this repairs the projection rather than failing the save.
|
|
183
|
+
* Preserves a leading HTML comment in the section and recovers one-liners
|
|
184
|
+
* best-effort. The returned content parses cleanly under MILESTONE_LINE_RE.
|
|
185
|
+
*/
|
|
186
|
+
function rebuildMilestoneSequenceSection(content: string, milestones: MilestoneSeqRow[]): string {
|
|
187
|
+
const lines = content.split("\n");
|
|
188
|
+
const headerIdx = lines.findIndex(l => /^##\s+Milestone Sequence\s*$/.test(l));
|
|
189
|
+
|
|
190
|
+
const canonicalLines = (() => {
|
|
191
|
+
// Recover tails from the existing (malformed) body when the section exists.
|
|
192
|
+
let body = "";
|
|
193
|
+
if (headerIdx !== -1) {
|
|
194
|
+
let end = headerIdx + 1;
|
|
195
|
+
while (end < lines.length && !/^##\s+/.test(lines[end])) end++;
|
|
196
|
+
body = lines.slice(headerIdx + 1, end).join("\n");
|
|
197
|
+
}
|
|
198
|
+
const tails = recoverMilestoneTails(body);
|
|
199
|
+
return milestones.map(m => renderMilestoneLine(m, tails.get(m.id) ?? ""));
|
|
200
|
+
})();
|
|
201
|
+
|
|
202
|
+
if (headerIdx === -1) {
|
|
203
|
+
// No section at all — append a fresh, canonical one.
|
|
204
|
+
const sep = content.endsWith("\n") ? "" : "\n";
|
|
205
|
+
return `${content}${sep}\n## Milestone Sequence\n\n${canonicalLines.join("\n")}\n`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
let bodyEnd = headerIdx + 1;
|
|
209
|
+
while (bodyEnd < lines.length && !/^##\s+/.test(lines[bodyEnd])) bodyEnd++;
|
|
210
|
+
const existingBody = lines.slice(headerIdx + 1, bodyEnd);
|
|
211
|
+
|
|
212
|
+
// Preserve a contiguous leading HTML comment block (the "Check off…" hint).
|
|
213
|
+
let i = 0;
|
|
214
|
+
while (i < existingBody.length && existingBody[i].trim() === "") i++;
|
|
215
|
+
const preserved: string[] = [];
|
|
216
|
+
if (i < existingBody.length && existingBody[i].trim().startsWith("<!--")) {
|
|
217
|
+
while (i < existingBody.length) {
|
|
218
|
+
preserved.push(existingBody[i]);
|
|
219
|
+
const closed = existingBody[i].includes("-->");
|
|
220
|
+
i++;
|
|
221
|
+
if (closed) break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return [
|
|
226
|
+
...lines.slice(0, headerIdx + 1),
|
|
227
|
+
"",
|
|
228
|
+
...(preserved.length ? [...preserved, ""] : []),
|
|
229
|
+
...canonicalLines,
|
|
230
|
+
"",
|
|
231
|
+
...lines.slice(bodyEnd),
|
|
232
|
+
].join("\n");
|
|
233
|
+
}
|
|
234
|
+
|
|
129
235
|
async function mirrorArtifactToActiveWorktreeProjection(
|
|
130
236
|
basePath: string,
|
|
131
237
|
relativePath: string,
|
|
@@ -260,6 +366,7 @@ export async function executeSummarySave(
|
|
|
260
366
|
await mirrorArtifactToActiveWorktreeProjection(basePath, relativePath, contentToSave);
|
|
261
367
|
|
|
262
368
|
let registeredMilestones: string[] = [];
|
|
369
|
+
let milestoneSequenceSelfHealed = false;
|
|
263
370
|
if (params.artifact_type === "PROJECT") {
|
|
264
371
|
try {
|
|
265
372
|
registeredMilestones = registerProjectMilestoneSequence(contentToSave);
|
|
@@ -294,29 +401,83 @@ export async function executeSummarySave(
|
|
|
294
401
|
};
|
|
295
402
|
}
|
|
296
403
|
if (registeredMilestones.length === 0) {
|
|
297
|
-
|
|
404
|
+
const existingMilestones = getAllMilestones();
|
|
405
|
+
if (existingMilestones.length === 0) {
|
|
406
|
+
// Genuine first-save failure: no milestones parsed AND none in the DB.
|
|
407
|
+
// /gsd really would report "No Active Milestone" — hard-fail so the
|
|
408
|
+
// caller rewrites the sequence before proceeding.
|
|
409
|
+
logError("tool", `gsd_summary_save: PROJECT.md saved to ${relativePath} but parsed zero milestones — registration produced no DB rows`, {
|
|
410
|
+
tool: "gsd_summary_save",
|
|
411
|
+
});
|
|
412
|
+
// PROJECT.md was persisted; invalidate so subsequent reads see the new
|
|
413
|
+
// artifacts row even though no milestones registered.
|
|
414
|
+
invalidateStateCache();
|
|
415
|
+
return {
|
|
416
|
+
content: [{
|
|
417
|
+
type: "text",
|
|
418
|
+
text:
|
|
419
|
+
`Error: PROJECT.md was saved to ${relativePath} but contains zero parseable milestone lines, ` +
|
|
420
|
+
`so no milestones were registered in the DB. /gsd will report "No Active Milestone". ` +
|
|
421
|
+
`Rewrite PROJECT.md so the "Milestone Sequence" section uses canonical lines: ` +
|
|
422
|
+
`\`- [ ] M001: <Title> — <One-liner>\` (em-dash, double-dash \`--\`, or single-dash \`-\` separator), then re-call gsd_summary_save(PROJECT).`,
|
|
423
|
+
}],
|
|
424
|
+
details: {
|
|
425
|
+
operation: "save_summary",
|
|
426
|
+
path: relativePath,
|
|
427
|
+
artifact_type: params.artifact_type,
|
|
428
|
+
error: "milestone_registration_empty_parse",
|
|
429
|
+
},
|
|
430
|
+
isError: true,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Existing DB rows mean this is projection drift, not data loss. Rebuild
|
|
435
|
+
// the section from DB state and re-persist a parseable projection.
|
|
436
|
+
logWarning("tool", `gsd_summary_save: PROJECT.md parsed zero milestone lines but DB has ${existingMilestones.length} — rebuilding Milestone Sequence from DB (projection self-heal)`, {
|
|
298
437
|
tool: "gsd_summary_save",
|
|
438
|
+
path: relativePath,
|
|
299
439
|
});
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
440
|
+
try {
|
|
441
|
+
const healed = rebuildMilestoneSequenceSection(contentToSave, existingMilestones);
|
|
442
|
+
await saveArtifactToDb(
|
|
443
|
+
{ path: relativePath, artifact_type: params.artifact_type, content: healed },
|
|
444
|
+
basePath,
|
|
445
|
+
);
|
|
446
|
+
await mirrorArtifactToActiveWorktreeProjection(basePath, relativePath, healed);
|
|
447
|
+
const healedRegisteredMilestones = registerProjectMilestoneSequence(healed);
|
|
448
|
+
if (healedRegisteredMilestones.length === 0) {
|
|
449
|
+
throw new Error("self-healed PROJECT.md still parsed zero milestone lines");
|
|
450
|
+
}
|
|
451
|
+
registeredMilestones = healedRegisteredMilestones;
|
|
452
|
+
milestoneSequenceSelfHealed = true;
|
|
453
|
+
} catch (healErr) {
|
|
454
|
+
const msg = healErr instanceof Error ? healErr.message : String(healErr);
|
|
455
|
+
logError("tool", `gsd_summary_save: Milestone Sequence self-heal failed: ${msg}`, {
|
|
456
|
+
tool: "gsd_summary_save",
|
|
314
457
|
path: relativePath,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
458
|
+
error: msg,
|
|
459
|
+
});
|
|
460
|
+
invalidateStateCache();
|
|
461
|
+
return {
|
|
462
|
+
content: [{
|
|
463
|
+
type: "text",
|
|
464
|
+
text:
|
|
465
|
+
`Error: PROJECT.md was saved to ${relativePath} but contains zero parseable milestone lines, ` +
|
|
466
|
+
`and automatic DB-backed Milestone Sequence repair failed: ${msg}. ` +
|
|
467
|
+
`Rewrite PROJECT.md so the "Milestone Sequence" section uses canonical lines: ` +
|
|
468
|
+
`\`- [ ] M001: <Title> — <One-liner>\`, then re-call gsd_summary_save(PROJECT).`,
|
|
469
|
+
}],
|
|
470
|
+
details: {
|
|
471
|
+
operation: "save_summary",
|
|
472
|
+
path: relativePath,
|
|
473
|
+
artifact_type: params.artifact_type,
|
|
474
|
+
error: "milestone_sequence_self_heal_failed",
|
|
475
|
+
self_heal_error: msg,
|
|
476
|
+
},
|
|
477
|
+
isError: true,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
invalidateStateCache();
|
|
320
481
|
}
|
|
321
482
|
}
|
|
322
483
|
|
|
@@ -339,6 +500,7 @@ export async function executeSummarySave(
|
|
|
339
500
|
artifact_type: params.artifact_type,
|
|
340
501
|
content_source: contentSource,
|
|
341
502
|
...(registeredMilestones.length > 0 ? { registeredMilestones } : {}),
|
|
503
|
+
...(milestoneSequenceSelfHealed ? { milestoneSequenceSelfHealed: true } : {}),
|
|
342
504
|
},
|
|
343
505
|
};
|
|
344
506
|
} catch (err) {
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";exports.id=678,exports.ids=[678],exports.modules={10678:(a,b,c)=>{let d;c.d(b,{isOnboardingComplete:()=>r,readOnboardingRecord:()=>q});var e=c(89477),f=c(86697);c(76212),c(78335);var g=c(65521),h=c(62228);c(95398),process.env.GSD_ENABLE_NATIVE_GSD_PARSER,Symbol("native-unavailable"),new g.AsyncLocalStorage,c(97526),Object.values({Q3:{id:"Q3",scope:"slice",ownerTurn:"gate-evaluate",question:"How can this be exploited?",guidance:"Identify abuse scenarios: parameter tampering, replay attacks, privilege escalation.\nMap data exposure risks: PII, tokens, secrets accessible through this slice.\nDefine input trust boundaries: untrusted user input reaching DB, API, or filesystem.\nIf none apply, return verdict 'omitted' with rationale explaining why.",promptSection:"Abuse Surface"},Q4:{id:"Q4",scope:"slice",ownerTurn:"gate-evaluate",question:"Which existing requirements (R-IDs) does this slice touch, and which must be re-tested?",guidance:"List the R-IDs (e.g. R001, R003) touched by this slice; see the milestone requirements artifact at .gsd/milestones/<id>/REQUIREMENTS.md.\nIdentify what must be re-tested after shipping.\nFlag decisions that should be revisited given the new scope.\nIf no existing requirements are affected, return verdict 'omitted'.",promptSection:"Broken Promises"},Q5:{id:"Q5",scope:"task",ownerTurn:"execute-task",question:"What breaks when dependencies fail?",guidance:"Enumerate the task's external dependencies (APIs, filesystem, network, subprocesses).\nDescribe the failure path for each: timeout, malformed response, connection loss.\nVerify the implementation handles each failure or explicitly bubbles the error.\nReturn verdict 'omitted' only if the task has no external dependencies.",promptSection:"Failure Modes"},Q6:{id:"Q6",scope:"task",ownerTurn:"execute-task",question:"What is the 10x load breakpoint?",guidance:"Identify the resource that saturates first at 10x the expected load.\nDescribe the protection applied (pool sizing, rate limiting, pagination, caching).\nReturn verdict 'omitted' if the task has no runtime load dimension.",promptSection:"Load Profile"},Q7:{id:"Q7",scope:"task",ownerTurn:"execute-task",question:"What negative tests protect this task?",guidance:"List malformed inputs, error paths, and boundary conditions the tests cover.\nPoint to the specific test files or cases that assert each negative scenario.\nReturn verdict 'omitted' only if the task has no meaningful negative surface.",promptSection:"Negative Tests"},Q8:{id:"Q8",scope:"slice",ownerTurn:"complete-slice",question:"How will ops know this slice is healthy or broken?",guidance:"Describe the health signal (metric, log line, dashboard) that proves the slice works.\nDescribe the failure signal that triggers an alert or paging.\nDocument the recovery procedure and any monitoring gaps.\nReturn verdict 'omitted' only for slices with no runtime behavior at all.",promptSection:"Operational Readiness"},MV01:{id:"MV01",scope:"milestone",ownerTurn:"validate-milestone",question:"Is every success criterion in the milestone roadmap satisfied?",guidance:"Walk the success-criteria checklist from the milestone roadmap.\nFor each criterion, point to the slice / assessment / verification evidence that proves it.\nReturn verdict 'flag' if any criterion is unmet or unverifiable.",promptSection:"Success Criteria Checklist"},MV02:{id:"MV02",scope:"milestone",ownerTurn:"validate-milestone",question:"Does every slice have a SUMMARY.md and a passing assessment?",guidance:"Confirm every slice listed in the roadmap has a SUMMARY.md.\nConfirm each slice has an ASSESSMENT verdict of 'pass' (or justified 'omitted').\nFlag missing artifacts and slices with outstanding follow-ups or known limitations.",promptSection:"Slice Delivery Audit"},MV03:{id:"MV03",scope:"milestone",ownerTurn:"validate-milestone",question:"Do the slices integrate end-to-end?",guidance:"Trace at least one cross-slice flow proving the pieces compose.\nFlag gaps where two slices were built in isolation with no integration evidence.",promptSection:"Cross-Slice Integration"},MV04:{id:"MV04",scope:"milestone",ownerTurn:"validate-milestone",question:"Are all touched requirements covered and still coherent?",guidance:"For each requirement advanced, validated, surfaced, or invalidated across the milestone's slices, confirm the milestone-level evidence matches.\nFlag requirements that slices claim to advance but no artifact proves.",promptSection:"Requirement Coverage"}});class i{get(a){return this.entries.get(a)}set(a,b){this.entries.set(a,b)}has(a){return this.entries.has(a)}delete(a){return this.entries.delete(a)}asReadonlyMap(){return this.entries}closeNonActive(a,b){for(let[c,d]of this.entries)d.db!==a&&(this.entries.delete(c),b(d))}constructor(){this.entries=new Map}}class j{markAttempted(){this.attempted=!0}clearError(){this.lastError=null,this.lastPhase=null}recordError(a,b){this.lastPhase=a,this.lastError=b instanceof Error?b:Error(String(b))}reset(){this.attempted=!1,this.clearError()}snapshot(){return{attempted:this.attempted,lastError:this.lastError,lastPhase:this.lastPhase}}constructor(){this.attempted=!1,this.lastError=null,this.lastPhase=null}}class k{isInTransaction(){return this.depth>0}transaction(a,b){if(this.depth>0)return this.runNested(b);a.begin(),this.depth++;try{let c=b();return a.commit(),c}catch(b){throw a.rollback(),b}finally{this.depth--}}readTransaction(a,b,c){if(this.depth>0)return this.runNested(b);a.beginRead(),this.depth++;try{let c=b();return a.commit(),c}catch(b){try{a.rollback()}catch(a){c(a instanceof Error?a:Error(String(a)))}throw b}finally{this.depth--}}runNested(a){this.depth++;try{return a()}finally{this.depth--}}constructor(){this.depth=0}}class l{constructor(a){this.providerName=null,this.providerModule=null,this.loadAttempted=!1,this.deps=a}load(){if(this.loadAttempted)return;this.loadAttempted=!0;try{this.deps.suppressSqliteWarning();let a=this.deps.tryRequireNodeSqlite();if(a.DatabaseSync){this.providerModule=a,this.providerName="node:sqlite";return}}catch{}let a=this.loadBetterSqliteModule();if(a){this.providerModule=a,this.providerName="better-sqlite3";return}let b=22>parseInt(this.deps.nodeVersion.split(".")[0],10)?` GSD requires Node >= 22.0.0 (current: v${this.deps.nodeVersion}). Upgrade Node to fix this.`:"";this.deps.writeStderr(`gsd-db: No SQLite provider available (tried node:sqlite, better-sqlite3).${b}
|
|
2
|
-
`)}getProviderName(){return this.providerName}openRaw(a){if(this.load(),!this.providerModule||!this.providerName)return null;if("node:sqlite"===this.providerName){let{DatabaseSync:b}=this.providerModule;return new b(a)}return new this.providerModule(a)}tryOpenBetterSqliteFallback(a){if("node:sqlite"!==this.providerName)return null;let b=this.loadBetterSqliteModule();return b?{providerName:"better-sqlite3",providerModule:b,rawDb:new b(a)}:null}commitFallback(a){this.providerName=a.providerName,this.providerModule=a.providerModule}reset(){this.loadAttempted=!1,this.providerModule=null,this.providerName=null}loadBetterSqliteModule(){try{let a=this.deps.tryRequireBetterSqlite3();if("function"==typeof a)return a;if(a&&"function"==typeof a.default)return a.default}catch{}return null}}function m(){if(void 0!==d)return d;try{d=createRequire(import.meta.url)}catch{d=null}return d}new l({tryRequireNodeSqlite:()=>{let a=m();if(!a)throw Error("unavailable");return a("node:sqlite")},tryRequireBetterSqlite3:()=>{let a=m();if(!a)throw Error("unavailable");return a("better-sqlite3")},suppressSqliteWarning:function(){let a=process.emit;process.emit=function(b,...c){return!("warning"===b&&c[0]&&"object"==typeof c[0]&&"name"in c[0]&&"ExperimentalWarning"===c[0].name&&"message"in c[0]&&"string"==typeof c[0].message&&c[0].message.includes("SQLite"))&&a.apply(process,[b,...c])}},nodeVersion:process.versions.node,writeStderr:a=>process.stderr.write(a)}),new j,new i,new k;let n=process.env.GSD_CODING_AGENT_DIR||(0,f.join)(process.env.GSD_HOME?(0,f.resolve)(process.env.GSD_HOME):(0,f.join)((0,h.homedir)(),".gsd"),"agent"),o=(0,f.join)(n,"onboarding.json"),p={version:1,flowVersion:1,completedAt:null,completedSteps:[],skippedSteps:[],lastResumePoint:null};function q(){if(!(0,e.existsSync)(o))return{...p};try{let a=JSON.parse((0,e.readFileSync)(o,"utf-8"));return{version:"number"==typeof a.version?a.version:1,flowVersion:"number"==typeof a.flowVersion?a.flowVersion:0,completedAt:"string"==typeof a.completedAt?a.completedAt:null,completedSteps:Array.isArray(a.completedSteps)?a.completedSteps.filter(a=>"string"==typeof a):[],skippedSteps:Array.isArray(a.skippedSteps)?a.skippedSteps.filter(a=>"string"==typeof a):[],lastResumePoint:"string"==typeof a.lastResumePoint?a.lastResumePoint:null}}catch{return{...p}}}function r(){let a=q();return null!==a.completedAt&&1===a.flowVersion}},97526:(a,b,c)=>{c.d(b,{DZ:()=>e,rs:()=>d});let d="GSD_GIT_ERROR";class e extends Error{constructor(a,b,c){super(b,c),this.name="GSDError",this.code=a}}}};
|
|
File without changes
|
|
File without changes
|