gsd-pi 2.33.1-dev.ee47f1b → 2.34.0-dev.bbb5216
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/bundled-resource-path.d.ts +8 -0
- package/dist/bundled-resource-path.js +14 -0
- package/dist/headless-query.js +6 -6
- package/dist/resources/extensions/gsd/auto/session.js +27 -32
- package/dist/resources/extensions/gsd/auto-dashboard.js +29 -109
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +6 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +52 -81
- package/dist/resources/extensions/gsd/auto-loop.js +956 -0
- package/dist/resources/extensions/gsd/auto-observability.js +4 -2
- package/dist/resources/extensions/gsd/auto-post-unit.js +75 -185
- package/dist/resources/extensions/gsd/auto-prompts.js +133 -101
- package/dist/resources/extensions/gsd/auto-recovery.js +59 -97
- package/dist/resources/extensions/gsd/auto-start.js +330 -309
- package/dist/resources/extensions/gsd/auto-supervisor.js +5 -11
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +7 -7
- package/dist/resources/extensions/gsd/auto-timers.js +3 -4
- package/dist/resources/extensions/gsd/auto-verification.js +35 -73
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +167 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +291 -126
- package/dist/resources/extensions/gsd/auto.js +283 -1013
- package/dist/resources/extensions/gsd/captures.js +10 -4
- package/dist/resources/extensions/gsd/dispatch-guard.js +7 -8
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +25 -18
- package/dist/resources/extensions/gsd/doctor-checks.js +3 -4
- package/dist/resources/extensions/gsd/git-service.js +1 -1
- package/dist/resources/extensions/gsd/gsd-db.js +296 -151
- package/dist/resources/extensions/gsd/index.js +92 -228
- package/dist/resources/extensions/gsd/post-unit-hooks.js +13 -13
- package/dist/resources/extensions/gsd/progress-score.js +61 -156
- package/dist/resources/extensions/gsd/quick.js +98 -122
- package/dist/resources/extensions/gsd/session-lock.js +13 -0
- package/dist/resources/extensions/gsd/templates/preferences.md +1 -0
- package/dist/resources/extensions/gsd/undo.js +43 -48
- package/dist/resources/extensions/gsd/unit-runtime.js +16 -15
- package/dist/resources/extensions/gsd/verification-evidence.js +0 -1
- package/dist/resources/extensions/gsd/verification-gate.js +6 -35
- package/dist/resources/extensions/gsd/worktree-command.js +30 -24
- package/dist/resources/extensions/gsd/worktree-manager.js +2 -3
- package/dist/resources/extensions/gsd/worktree-resolver.js +344 -0
- package/dist/resources/extensions/gsd/worktree.js +7 -44
- package/dist/tool-bootstrap.js +59 -11
- package/dist/worktree-cli.js +7 -7
- package/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +3630 -5483
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +735 -2588
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/src/models.generated.ts +1039 -2892
- package/packages/pi-coding-agent/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto/session.ts +47 -30
- package/src/resources/extensions/gsd/auto-dashboard.ts +28 -131
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +6 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +135 -91
- package/src/resources/extensions/gsd/auto-loop.ts +1665 -0
- package/src/resources/extensions/gsd/auto-observability.ts +4 -2
- package/src/resources/extensions/gsd/auto-post-unit.ts +85 -228
- package/src/resources/extensions/gsd/auto-prompts.ts +138 -109
- package/src/resources/extensions/gsd/auto-recovery.ts +124 -118
- package/src/resources/extensions/gsd/auto-start.ts +440 -354
- package/src/resources/extensions/gsd/auto-supervisor.ts +5 -12
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +8 -8
- package/src/resources/extensions/gsd/auto-timers.ts +3 -4
- package/src/resources/extensions/gsd/auto-verification.ts +76 -90
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +204 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +389 -141
- package/src/resources/extensions/gsd/auto.ts +515 -1199
- package/src/resources/extensions/gsd/captures.ts +10 -4
- package/src/resources/extensions/gsd/dispatch-guard.ts +13 -9
- package/src/resources/extensions/gsd/docs/preferences-reference.md +25 -18
- package/src/resources/extensions/gsd/doctor-checks.ts +3 -4
- package/src/resources/extensions/gsd/git-service.ts +8 -1
- package/src/resources/extensions/gsd/gitignore.ts +4 -2
- package/src/resources/extensions/gsd/gsd-db.ts +375 -180
- package/src/resources/extensions/gsd/index.ts +104 -263
- package/src/resources/extensions/gsd/post-unit-hooks.ts +13 -13
- package/src/resources/extensions/gsd/progress-score.ts +65 -200
- package/src/resources/extensions/gsd/quick.ts +121 -125
- package/src/resources/extensions/gsd/session-lock.ts +11 -0
- package/src/resources/extensions/gsd/templates/preferences.md +1 -0
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +32 -59
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +75 -27
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1458 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +8 -162
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -108
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +1 -3
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +0 -55
- package/src/resources/extensions/gsd/tests/headless-query.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-worktree.test.ts +8 -11
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +4 -6
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/undo.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +24 -26
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +7 -201
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +705 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +57 -106
- package/src/resources/extensions/gsd/tests/worktree.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +43 -132
- package/src/resources/extensions/gsd/types.ts +90 -81
- package/src/resources/extensions/gsd/undo.ts +42 -46
- package/src/resources/extensions/gsd/unit-runtime.ts +14 -18
- package/src/resources/extensions/gsd/verification-evidence.ts +1 -3
- package/src/resources/extensions/gsd/verification-gate.ts +6 -39
- package/src/resources/extensions/gsd/worktree-command.ts +36 -24
- package/src/resources/extensions/gsd/worktree-manager.ts +2 -3
- package/src/resources/extensions/gsd/worktree-resolver.ts +485 -0
- package/src/resources/extensions/gsd/worktree.ts +7 -44
- package/dist/resources/extensions/gsd/auto-constants.js +0 -5
- package/dist/resources/extensions/gsd/auto-idempotency.js +0 -106
- package/dist/resources/extensions/gsd/auto-stuck-detection.js +0 -165
- package/dist/resources/extensions/gsd/mechanical-completion.js +0 -351
- package/src/resources/extensions/gsd/auto-constants.ts +0 -6
- package/src/resources/extensions/gsd/auto-idempotency.ts +0 -151
- package/src/resources/extensions/gsd/auto-stuck-detection.ts +0 -221
- package/src/resources/extensions/gsd/mechanical-completion.ts +0 -430
- package/src/resources/extensions/gsd/tests/auto-dispatch-loop.test.ts +0 -691
- package/src/resources/extensions/gsd/tests/auto-reentrancy-guard.test.ts +0 -127
- package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +0 -123
- package/src/resources/extensions/gsd/tests/dispatch-stall-guard.test.ts +0 -126
- package/src/resources/extensions/gsd/tests/loop-regression.test.ts +0 -874
- package/src/resources/extensions/gsd/tests/mechanical-completion.test.ts +0 -356
- package/src/resources/extensions/gsd/tests/progress-score.test.ts +0 -206
- package/src/resources/extensions/gsd/tests/session-lock.test.ts +0 -434
|
@@ -55,6 +55,55 @@ function formatExecutorConstraints(): string {
|
|
|
55
55
|
].join("\n");
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
function buildSourceFilePaths(
|
|
59
|
+
base: string,
|
|
60
|
+
mid: string,
|
|
61
|
+
sid?: string,
|
|
62
|
+
): string {
|
|
63
|
+
const paths: string[] = [];
|
|
64
|
+
|
|
65
|
+
const projectPath = resolveGsdRootFile(base, "PROJECT");
|
|
66
|
+
if (existsSync(projectPath)) {
|
|
67
|
+
paths.push(`- **Project**: \`${relGsdRootFile("PROJECT")}\``);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const requirementsPath = resolveGsdRootFile(base, "REQUIREMENTS");
|
|
71
|
+
if (existsSync(requirementsPath)) {
|
|
72
|
+
paths.push(`- **Requirements**: \`${relGsdRootFile("REQUIREMENTS")}\``);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const decisionsPath = resolveGsdRootFile(base, "DECISIONS");
|
|
76
|
+
if (existsSync(decisionsPath)) {
|
|
77
|
+
paths.push(`- **Decisions**: \`${relGsdRootFile("DECISIONS")}\``);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
81
|
+
if (contextPath) {
|
|
82
|
+
paths.push(`- **Milestone Context**: \`${relMilestoneFile(base, mid, "CONTEXT")}\``);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
86
|
+
if (roadmapPath) {
|
|
87
|
+
paths.push(`- **Roadmap**: \`${relMilestoneFile(base, mid, "ROADMAP")}\``);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (sid) {
|
|
91
|
+
const researchPath = resolveSliceFile(base, mid, sid, "RESEARCH");
|
|
92
|
+
if (researchPath) {
|
|
93
|
+
paths.push(`- **Slice Research**: \`${relSliceFile(base, mid, sid, "RESEARCH")}\``);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
const researchPath = resolveMilestoneFile(base, mid, "RESEARCH");
|
|
97
|
+
if (researchPath) {
|
|
98
|
+
paths.push(`- **Milestone Research**: \`${relMilestoneFile(base, mid, "RESEARCH")}\``);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return paths.length > 0
|
|
103
|
+
? paths.join("\n")
|
|
104
|
+
: "- Use `rg --files` and targeted reads to identify the relevant source files before planning.";
|
|
105
|
+
}
|
|
106
|
+
|
|
58
107
|
// ─── Inline Helpers ───────────────────────────────────────────────────────
|
|
59
108
|
|
|
60
109
|
/**
|
|
@@ -189,52 +238,30 @@ export async function inlineGsdRootFile(
|
|
|
189
238
|
// ─── DB-Aware Inline Helpers ──────────────────────────────────────────────
|
|
190
239
|
|
|
191
240
|
/**
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* or the query yields no results.
|
|
195
|
-
*
|
|
196
|
-
* @param base Project root for filesystem fallback
|
|
197
|
-
* @param label Section heading (e.g. "Decisions")
|
|
198
|
-
* @param filename Filesystem fallback file (e.g. "decisions.md")
|
|
199
|
-
* @param queryDb Async callback receiving the dynamically-imported
|
|
200
|
-
* context-store module. Returns formatted markdown or null.
|
|
241
|
+
* Inline decisions with optional milestone scoping from the DB.
|
|
242
|
+
* Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
|
|
201
243
|
*/
|
|
202
|
-
async function
|
|
203
|
-
base: string,
|
|
204
|
-
label: string,
|
|
205
|
-
filename: string,
|
|
206
|
-
queryDb: (cs: typeof import("./context-store.js")) => string | null,
|
|
244
|
+
export async function inlineDecisionsFromDb(
|
|
245
|
+
base: string, milestoneId?: string, scope?: string, level?: InlineLevel,
|
|
207
246
|
): Promise<string | null> {
|
|
247
|
+
const inlineLevel = level ?? resolveInlineLevel();
|
|
208
248
|
try {
|
|
209
249
|
const { isDbAvailable } = await import("./gsd-db.js");
|
|
210
250
|
if (isDbAvailable()) {
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
if (
|
|
214
|
-
|
|
251
|
+
const { queryDecisions, formatDecisionsForPrompt } = await import("./context-store.js");
|
|
252
|
+
const decisions = queryDecisions({ milestoneId, scope });
|
|
253
|
+
if (decisions.length > 0) {
|
|
254
|
+
// Use compact format for non-full levels to save ~35% tokens
|
|
255
|
+
const formatted = inlineLevel !== "full"
|
|
256
|
+
? formatDecisionsCompact(decisions)
|
|
257
|
+
: formatDecisionsForPrompt(decisions);
|
|
258
|
+
return `### Decisions\nSource: \`.gsd/DECISIONS.md\`\n\n${formatted}`;
|
|
215
259
|
}
|
|
216
260
|
}
|
|
217
261
|
} catch {
|
|
218
262
|
// DB not available — fall through to filesystem
|
|
219
263
|
}
|
|
220
|
-
return inlineGsdRootFile(base,
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Inline decisions with optional milestone scoping from the DB.
|
|
225
|
-
* Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
|
|
226
|
-
*/
|
|
227
|
-
export async function inlineDecisionsFromDb(
|
|
228
|
-
base: string, milestoneId?: string, scope?: string, level?: InlineLevel,
|
|
229
|
-
): Promise<string | null> {
|
|
230
|
-
const inlineLevel = level ?? resolveInlineLevel();
|
|
231
|
-
return inlineFromDbOrFile(base, "Decisions", "decisions.md", (cs) => {
|
|
232
|
-
const decisions = cs.queryDecisions({ milestoneId, scope });
|
|
233
|
-
if (decisions.length === 0) return null;
|
|
234
|
-
return inlineLevel !== "full"
|
|
235
|
-
? formatDecisionsCompact(decisions)
|
|
236
|
-
: cs.formatDecisionsForPrompt(decisions);
|
|
237
|
-
});
|
|
264
|
+
return inlineGsdRootFile(base, "decisions.md", "Decisions");
|
|
238
265
|
}
|
|
239
266
|
|
|
240
267
|
/**
|
|
@@ -245,13 +272,23 @@ export async function inlineRequirementsFromDb(
|
|
|
245
272
|
base: string, sliceId?: string, level?: InlineLevel,
|
|
246
273
|
): Promise<string | null> {
|
|
247
274
|
const inlineLevel = level ?? resolveInlineLevel();
|
|
248
|
-
|
|
249
|
-
const
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
275
|
+
try {
|
|
276
|
+
const { isDbAvailable } = await import("./gsd-db.js");
|
|
277
|
+
if (isDbAvailable()) {
|
|
278
|
+
const { queryRequirements, formatRequirementsForPrompt } = await import("./context-store.js");
|
|
279
|
+
const requirements = queryRequirements({ sliceId });
|
|
280
|
+
if (requirements.length > 0) {
|
|
281
|
+
// Use compact format for non-full levels to save ~40% tokens
|
|
282
|
+
const formatted = inlineLevel !== "full"
|
|
283
|
+
? formatRequirementsCompact(requirements)
|
|
284
|
+
: formatRequirementsForPrompt(requirements);
|
|
285
|
+
return `### Requirements\nSource: \`.gsd/REQUIREMENTS.md\`\n\n${formatted}`;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
} catch {
|
|
289
|
+
// DB not available — fall through to filesystem
|
|
290
|
+
}
|
|
291
|
+
return inlineGsdRootFile(base, "requirements.md", "Requirements");
|
|
255
292
|
}
|
|
256
293
|
|
|
257
294
|
/**
|
|
@@ -261,9 +298,19 @@ export async function inlineRequirementsFromDb(
|
|
|
261
298
|
export async function inlineProjectFromDb(
|
|
262
299
|
base: string,
|
|
263
300
|
): Promise<string | null> {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
301
|
+
try {
|
|
302
|
+
const { isDbAvailable } = await import("./gsd-db.js");
|
|
303
|
+
if (isDbAvailable()) {
|
|
304
|
+
const { queryProject } = await import("./context-store.js");
|
|
305
|
+
const content = queryProject();
|
|
306
|
+
if (content) {
|
|
307
|
+
return `### Project\nSource: \`.gsd/PROJECT.md\`\n\n${content}`;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} catch {
|
|
311
|
+
// DB not available — fall through to filesystem
|
|
312
|
+
}
|
|
313
|
+
return inlineGsdRootFile(base, "project.md", "Project");
|
|
267
314
|
}
|
|
268
315
|
|
|
269
316
|
// ─── Skill Discovery ──────────────────────────────────────────────────────
|
|
@@ -326,27 +373,6 @@ function oneLine(text: string): string {
|
|
|
326
373
|
return text.replace(/\s+/g, " ").trim();
|
|
327
374
|
}
|
|
328
375
|
|
|
329
|
-
/** Build the standard inlined-context section used by all prompt builders. */
|
|
330
|
-
function buildInlinedContextSection(inlined: string[]): string {
|
|
331
|
-
return `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/** Build the formatted list of available GSD source files for planners to read on demand. */
|
|
335
|
-
function buildSourceFileList(base: string, opts?: { includeProject?: boolean }): string {
|
|
336
|
-
const paths: string[] = [];
|
|
337
|
-
if (opts?.includeProject && existsSync(resolveGsdRootFile(base, "PROJECT")))
|
|
338
|
-
paths.push(`- **Project**: \`${relGsdRootFile("PROJECT")}\``);
|
|
339
|
-
if (existsSync(resolveGsdRootFile(base, "REQUIREMENTS")))
|
|
340
|
-
paths.push(`- **Requirements**: \`${relGsdRootFile("REQUIREMENTS")}\``);
|
|
341
|
-
if (existsSync(resolveGsdRootFile(base, "DECISIONS")))
|
|
342
|
-
paths.push(`- **Decisions**: \`${relGsdRootFile("DECISIONS")}\``);
|
|
343
|
-
if (paths.length === 0) {
|
|
344
|
-
const types = opts?.includeProject ? "project/requirements/decisions" : "requirements/decisions";
|
|
345
|
-
return `_No ${types} files found._`;
|
|
346
|
-
}
|
|
347
|
-
return paths.join("\n");
|
|
348
|
-
}
|
|
349
|
-
|
|
350
376
|
// ─── Section Builders ──────────────────────────────────────────────────────
|
|
351
377
|
|
|
352
378
|
export function buildResumeSection(
|
|
@@ -492,17 +518,6 @@ export async function checkNeedsReassessment(
|
|
|
492
518
|
|
|
493
519
|
if (hasAssessment) return null;
|
|
494
520
|
|
|
495
|
-
// Fallback: check the expected path directly via existsSync.
|
|
496
|
-
// resolveSliceFile relies on directory listing (readdirSync) which may not
|
|
497
|
-
// reflect a freshly written file in git worktree directories on some
|
|
498
|
-
// filesystems (observed on macOS APFS). A direct existsSync on the
|
|
499
|
-
// constructed path bypasses directory listing entirely. (#1112)
|
|
500
|
-
const sliceDir = resolveSlicePath(base, mid, lastCompleted.id);
|
|
501
|
-
if (sliceDir) {
|
|
502
|
-
const directPath = join(sliceDir, `${lastCompleted.id}-ASSESSMENT.md`);
|
|
503
|
-
if (existsSync(directPath)) return null;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
521
|
// Also need a summary to reassess against
|
|
507
522
|
const summaryFile = resolveSliceFile(base, mid, lastCompleted.id, "SUMMARY");
|
|
508
523
|
const hasSummary = !!(summaryFile && await loadFile(summaryFile));
|
|
@@ -553,21 +568,15 @@ export async function checkNeedsRunUat(
|
|
|
553
568
|
const uatContent = await loadFile(uatFile);
|
|
554
569
|
if (!uatContent) return null;
|
|
555
570
|
|
|
556
|
-
// If
|
|
557
|
-
// be re-dispatched. PASS means progression can continue; any non-PASS verdict
|
|
558
|
-
// must be handled by the dispatch table's verdict gate, which stops progression
|
|
559
|
-
// with a human-action message instead of replaying the same run-uat unit.
|
|
571
|
+
// If UAT result already exists, skip (idempotent)
|
|
560
572
|
const uatResultFile = resolveSliceFile(base, mid, sid, "UAT-RESULT");
|
|
561
573
|
if (uatResultFile) {
|
|
562
|
-
const
|
|
563
|
-
if (
|
|
574
|
+
const hasResult = !!(await loadFile(uatResultFile));
|
|
575
|
+
if (hasResult) return null;
|
|
564
576
|
}
|
|
565
577
|
|
|
566
|
-
// Classify UAT type;
|
|
567
|
-
// execute mechanical checks. Non-artifact UATs are tracked in the dashboard
|
|
568
|
-
// but don't block auto-mode progression.
|
|
578
|
+
// Classify UAT type; unknown type → treat as human-experience (human review)
|
|
569
579
|
const uatType = extractUatType(uatContent) ?? "human-experience";
|
|
570
|
-
if (uatType !== "artifact-driven") return null;
|
|
571
580
|
|
|
572
581
|
return { sliceId: sid, uatType };
|
|
573
582
|
}
|
|
@@ -590,7 +599,7 @@ export async function buildResearchMilestonePrompt(mid: string, midTitle: string
|
|
|
590
599
|
if (knowledgeInlineRM) inlined.push(knowledgeInlineRM);
|
|
591
600
|
inlined.push(inlineTemplate("research", "Research"));
|
|
592
601
|
|
|
593
|
-
const inlinedContext =
|
|
602
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
594
603
|
|
|
595
604
|
const outputRelPath = relMilestoneFile(base, mid, "RESEARCH");
|
|
596
605
|
return loadPrompt("research-milestone", {
|
|
@@ -618,8 +627,14 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba
|
|
|
618
627
|
const { inlinePriorMilestoneSummary } = await import("./files.js");
|
|
619
628
|
const priorSummaryInline = await inlinePriorMilestoneSummary(mid, base);
|
|
620
629
|
if (priorSummaryInline) inlined.push(priorSummaryInline);
|
|
621
|
-
|
|
622
|
-
|
|
630
|
+
if (inlineLevel !== "minimal") {
|
|
631
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
632
|
+
if (projectInline) inlined.push(projectInline);
|
|
633
|
+
const requirementsInline = await inlineRequirementsFromDb(base, undefined, inlineLevel);
|
|
634
|
+
if (requirementsInline) inlined.push(requirementsInline);
|
|
635
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
|
|
636
|
+
if (decisionsInline) inlined.push(decisionsInline);
|
|
637
|
+
}
|
|
623
638
|
const knowledgeInlinePM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
624
639
|
if (knowledgeInlinePM) inlined.push(knowledgeInlinePM);
|
|
625
640
|
inlined.push(inlineTemplate("roadmap", "Roadmap"));
|
|
@@ -634,22 +649,22 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba
|
|
|
634
649
|
inlined.push(inlineTemplate("task-plan", "Task Plan"));
|
|
635
650
|
}
|
|
636
651
|
|
|
637
|
-
const inlinedContext =
|
|
652
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
638
653
|
|
|
639
654
|
const outputRelPath = relMilestoneFile(base, mid, "ROADMAP");
|
|
655
|
+
const researchOutputPath = join(base, relMilestoneFile(base, mid, "RESEARCH"));
|
|
640
656
|
const secretsOutputPath = join(base, relMilestoneFile(base, mid, "SECRETS"));
|
|
641
|
-
const researchOutputRelPath = relMilestoneFile(base, mid, "RESEARCH");
|
|
642
657
|
return loadPrompt("plan-milestone", {
|
|
643
658
|
workingDirectory: base,
|
|
644
659
|
milestoneId: mid, milestoneTitle: midTitle,
|
|
645
660
|
milestonePath: relMilestonePath(base, mid),
|
|
646
661
|
contextPath: contextRel,
|
|
647
662
|
researchPath: researchRel,
|
|
663
|
+
researchOutputPath,
|
|
648
664
|
outputPath: join(base, outputRelPath),
|
|
649
665
|
secretsOutputPath,
|
|
650
666
|
inlinedContext,
|
|
651
|
-
sourceFilePaths,
|
|
652
|
-
researchOutputPath: join(base, researchOutputRelPath),
|
|
667
|
+
sourceFilePaths: buildSourceFilePaths(base, mid),
|
|
653
668
|
...buildSkillDiscoveryVars(),
|
|
654
669
|
});
|
|
655
670
|
}
|
|
@@ -683,7 +698,7 @@ export async function buildResearchSlicePrompt(
|
|
|
683
698
|
const overridesInline = formatOverridesSection(activeOverrides);
|
|
684
699
|
if (overridesInline) inlined.unshift(overridesInline);
|
|
685
700
|
|
|
686
|
-
const inlinedContext =
|
|
701
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
687
702
|
|
|
688
703
|
const outputRelPath = relSliceFile(base, mid, sid, "RESEARCH");
|
|
689
704
|
return loadPrompt("research-slice", {
|
|
@@ -713,8 +728,12 @@ export async function buildPlanSlicePrompt(
|
|
|
713
728
|
inlined.push(await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap"));
|
|
714
729
|
const researchInline = await inlineFileOptional(researchPath, researchRel, "Slice Research");
|
|
715
730
|
if (researchInline) inlined.push(researchInline);
|
|
716
|
-
|
|
717
|
-
|
|
731
|
+
if (inlineLevel !== "minimal") {
|
|
732
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
|
|
733
|
+
if (decisionsInline) inlined.push(decisionsInline);
|
|
734
|
+
const requirementsInline = await inlineRequirementsFromDb(base, sid, inlineLevel);
|
|
735
|
+
if (requirementsInline) inlined.push(requirementsInline);
|
|
736
|
+
}
|
|
718
737
|
const knowledgeInlinePS = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
719
738
|
if (knowledgeInlinePS) inlined.push(knowledgeInlinePS);
|
|
720
739
|
inlined.push(inlineTemplate("plan", "Slice Plan"));
|
|
@@ -727,13 +746,17 @@ export async function buildPlanSlicePrompt(
|
|
|
727
746
|
const planOverridesInline = formatOverridesSection(planActiveOverrides);
|
|
728
747
|
if (planOverridesInline) inlined.unshift(planOverridesInline);
|
|
729
748
|
|
|
730
|
-
const inlinedContext =
|
|
749
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
731
750
|
|
|
732
751
|
// Build executor context constraints from the budget engine
|
|
733
752
|
const executorContextConstraints = formatExecutorConstraints();
|
|
734
753
|
|
|
735
754
|
const outputRelPath = relSliceFile(base, mid, sid, "PLAN");
|
|
736
|
-
const
|
|
755
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
756
|
+
const commitDocsEnabled = prefs?.preferences?.git?.commit_docs !== false;
|
|
757
|
+
const commitInstruction = commitDocsEnabled
|
|
758
|
+
? `Commit the plan files only: \`git add ${relSlicePath(base, mid, sid)}/ .gsd/DECISIONS.md .gitignore && git commit -m "docs(${sid}): add slice plan"\`. Do not stage .gsd/STATE.md or other runtime files — the system manages those.`
|
|
759
|
+
: "Do not commit — planning docs are not tracked in git for this project.";
|
|
737
760
|
return loadPrompt("plan-slice", {
|
|
738
761
|
workingDirectory: base,
|
|
739
762
|
milestoneId: mid, sliceId: sid, sliceTitle: sTitle,
|
|
@@ -743,9 +766,9 @@ export async function buildPlanSlicePrompt(
|
|
|
743
766
|
outputPath: join(base, outputRelPath),
|
|
744
767
|
inlinedContext,
|
|
745
768
|
dependencySummaries: depContent,
|
|
769
|
+
sourceFilePaths: buildSourceFilePaths(base, mid, sid),
|
|
746
770
|
executorContextConstraints,
|
|
747
771
|
commitInstruction,
|
|
748
|
-
sourceFilePaths: sliceSourceFilePaths,
|
|
749
772
|
});
|
|
750
773
|
}
|
|
751
774
|
|
|
@@ -902,7 +925,7 @@ export async function buildCompleteSlicePrompt(
|
|
|
902
925
|
const completeOverridesInline = formatOverridesSection(completeActiveOverrides);
|
|
903
926
|
if (completeOverridesInline) inlined.unshift(completeOverridesInline);
|
|
904
927
|
|
|
905
|
-
const inlinedContext =
|
|
928
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
906
929
|
|
|
907
930
|
const sliceRel = relSlicePath(base, mid, sid);
|
|
908
931
|
const sliceSummaryPath = join(base, `${sliceRel}/${sid}-SUMMARY.md`);
|
|
@@ -961,7 +984,7 @@ export async function buildCompleteMilestonePrompt(
|
|
|
961
984
|
if (contextInline) inlined.push(contextInline);
|
|
962
985
|
inlined.push(inlineTemplate("milestone-summary", "Milestone Summary"));
|
|
963
986
|
|
|
964
|
-
const inlinedContext =
|
|
987
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
965
988
|
|
|
966
989
|
const milestoneSummaryPath = join(base, `${relMilestonePath(base, mid)}/${mid}-SUMMARY.md`);
|
|
967
990
|
|
|
@@ -1032,7 +1055,7 @@ export async function buildValidateMilestonePrompt(
|
|
|
1032
1055
|
const contextInline = await inlineFileOptional(contextPath, contextRel, "Milestone Context");
|
|
1033
1056
|
if (contextInline) inlined.push(contextInline);
|
|
1034
1057
|
|
|
1035
|
-
const inlinedContext =
|
|
1058
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
1036
1059
|
|
|
1037
1060
|
const validationOutputPath = join(base, `${relMilestonePath(base, mid)}/${mid}-VALIDATION.md`);
|
|
1038
1061
|
const roadmapOutputPath = `${relMilestonePath(base, mid)}/${mid}-ROADMAP.md`;
|
|
@@ -1086,7 +1109,7 @@ export async function buildReplanSlicePrompt(
|
|
|
1086
1109
|
const replanOverridesInline = formatOverridesSection(replanActiveOverrides);
|
|
1087
1110
|
if (replanOverridesInline) inlined.unshift(replanOverridesInline);
|
|
1088
1111
|
|
|
1089
|
-
const inlinedContext =
|
|
1112
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
1090
1113
|
|
|
1091
1114
|
const replanPath = join(base, `${relSlicePath(base, mid, sid)}/${sid}-REPLAN.md`);
|
|
1092
1115
|
|
|
@@ -1119,7 +1142,7 @@ export async function buildReplanSlicePrompt(
|
|
|
1119
1142
|
}
|
|
1120
1143
|
|
|
1121
1144
|
export async function buildRunUatPrompt(
|
|
1122
|
-
mid: string, sliceId: string, uatPath: string, base: string,
|
|
1145
|
+
mid: string, sliceId: string, uatPath: string, uatContent: string, base: string,
|
|
1123
1146
|
): Promise<string> {
|
|
1124
1147
|
const inlined: string[] = [];
|
|
1125
1148
|
inlined.push(await inlineFile(resolveSliceFile(base, mid, sliceId, "UAT"), uatPath, `${sliceId} UAT`));
|
|
@@ -1134,9 +1157,10 @@ export async function buildRunUatPrompt(
|
|
|
1134
1157
|
const projectInline = await inlineProjectFromDb(base);
|
|
1135
1158
|
if (projectInline) inlined.push(projectInline);
|
|
1136
1159
|
|
|
1137
|
-
const inlinedContext =
|
|
1160
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
1138
1161
|
|
|
1139
1162
|
const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "UAT-RESULT"));
|
|
1163
|
+
const uatType = extractUatType(uatContent) ?? "human-experience";
|
|
1140
1164
|
|
|
1141
1165
|
return loadPrompt("run-uat", {
|
|
1142
1166
|
workingDirectory: base,
|
|
@@ -1144,6 +1168,7 @@ export async function buildRunUatPrompt(
|
|
|
1144
1168
|
sliceId,
|
|
1145
1169
|
uatPath,
|
|
1146
1170
|
uatResultPath,
|
|
1171
|
+
uatType,
|
|
1147
1172
|
inlinedContext,
|
|
1148
1173
|
});
|
|
1149
1174
|
}
|
|
@@ -1171,7 +1196,7 @@ export async function buildReassessRoadmapPrompt(
|
|
|
1171
1196
|
const knowledgeInlineRA = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
1172
1197
|
if (knowledgeInlineRA) inlined.push(knowledgeInlineRA);
|
|
1173
1198
|
|
|
1174
|
-
const inlinedContext =
|
|
1199
|
+
const inlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
1175
1200
|
|
|
1176
1201
|
const assessmentPath = join(base, relSliceFile(base, mid, completedSliceId, "ASSESSMENT"));
|
|
1177
1202
|
|
|
@@ -1189,7 +1214,11 @@ export async function buildReassessRoadmapPrompt(
|
|
|
1189
1214
|
// Non-fatal — captures module may not be available
|
|
1190
1215
|
}
|
|
1191
1216
|
|
|
1192
|
-
const
|
|
1217
|
+
const reassessPrefs = loadEffectiveGSDPreferences();
|
|
1218
|
+
const reassessCommitDocsEnabled = reassessPrefs?.preferences?.git?.commit_docs !== false;
|
|
1219
|
+
const reassessCommitInstruction = reassessCommitDocsEnabled
|
|
1220
|
+
? `Commit: \`docs(${mid}): reassess roadmap after ${completedSliceId}\`. Stage only the .gsd/milestones/ files you changed — do not stage .gsd/STATE.md or other runtime files.`
|
|
1221
|
+
: "Do not commit — planning docs are not tracked in git for this project.";
|
|
1193
1222
|
|
|
1194
1223
|
return loadPrompt("reassess-roadmap", {
|
|
1195
1224
|
workingDirectory: base,
|