gsd-pi 2.37.1 → 2.38.0-dev.29edcdc
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/README.md +1 -1
- package/dist/app-paths.js +1 -1
- package/dist/cli.js +9 -0
- package/dist/extension-discovery.d.ts +5 -3
- package/dist/extension-discovery.js +14 -9
- package/dist/extension-registry.js +2 -2
- package/dist/onboarding.js +1 -0
- package/dist/remote-questions-config.js +2 -2
- package/dist/resource-loader.js +34 -1
- package/dist/resources/extensions/browser-tools/package.json +3 -1
- package/dist/resources/extensions/cmux/index.js +55 -1
- package/dist/resources/extensions/context7/package.json +1 -1
- package/dist/resources/extensions/env-utils.js +29 -0
- package/dist/resources/extensions/get-secrets-from-user.js +5 -24
- package/dist/resources/extensions/github-sync/cli.js +284 -0
- package/dist/resources/extensions/github-sync/index.js +73 -0
- package/dist/resources/extensions/github-sync/mapping.js +67 -0
- package/dist/resources/extensions/github-sync/sync.js +424 -0
- package/dist/resources/extensions/github-sync/templates.js +118 -0
- package/dist/resources/extensions/github-sync/types.js +7 -0
- package/dist/resources/extensions/google-search/package.json +3 -1
- package/dist/resources/extensions/gsd/auto/session.js +6 -23
- package/dist/resources/extensions/gsd/auto-dispatch.js +75 -10
- package/dist/resources/extensions/gsd/auto-loop.js +597 -588
- package/dist/resources/extensions/gsd/auto-post-unit.js +111 -68
- package/dist/resources/extensions/gsd/auto-prompts.js +114 -45
- package/dist/resources/extensions/gsd/auto-recovery.js +37 -1
- package/dist/resources/extensions/gsd/auto-start.js +13 -2
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +13 -5
- package/dist/resources/extensions/gsd/auto-worktree.js +3 -3
- package/dist/resources/extensions/gsd/auto.js +143 -96
- package/dist/resources/extensions/gsd/captures.js +9 -1
- package/dist/resources/extensions/gsd/commands-extensions.js +3 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +16 -3
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/commands.js +24 -3
- package/dist/resources/extensions/gsd/context-budget.js +2 -10
- package/dist/resources/extensions/gsd/detection.js +1 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -2
- package/dist/resources/extensions/gsd/doctor-checks.js +82 -0
- package/dist/resources/extensions/gsd/doctor-environment.js +78 -0
- package/dist/resources/extensions/gsd/doctor-format.js +15 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +62 -12
- package/dist/resources/extensions/gsd/doctor.js +204 -12
- package/dist/resources/extensions/gsd/exit-command.js +2 -1
- package/dist/resources/extensions/gsd/export.js +1 -1
- package/dist/resources/extensions/gsd/files.js +47 -2
- package/dist/resources/extensions/gsd/forensics.js +1 -1
- package/dist/resources/extensions/gsd/git-service.js +15 -12
- package/dist/resources/extensions/gsd/guided-flow.js +82 -32
- package/dist/resources/extensions/gsd/index.js +24 -20
- package/dist/resources/extensions/gsd/migrate/parsers.js +1 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +37 -0
- package/dist/resources/extensions/gsd/observability-validator.js +24 -0
- package/dist/resources/extensions/gsd/package.json +1 -1
- package/dist/resources/extensions/gsd/preferences-models.js +0 -12
- package/dist/resources/extensions/gsd/preferences-types.js +3 -2
- package/dist/resources/extensions/gsd/preferences-validation.js +101 -11
- package/dist/resources/extensions/gsd/preferences.js +8 -5
- package/dist/resources/extensions/gsd/prompts/discuss.md +11 -14
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
- package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +4 -8
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +44 -0
- package/dist/resources/extensions/gsd/prompts/run-uat.md +27 -10
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -2
- package/dist/resources/extensions/gsd/reactive-graph.js +227 -0
- package/dist/resources/extensions/gsd/repo-identity.js +21 -4
- package/dist/resources/extensions/gsd/resource-version.js +2 -1
- package/dist/resources/extensions/gsd/roadmap-mutations.js +24 -0
- package/dist/resources/extensions/gsd/state.js +1 -1
- package/dist/resources/extensions/gsd/templates/task-plan.md +11 -3
- package/dist/resources/extensions/gsd/visualizer-data.js +1 -1
- package/dist/resources/extensions/gsd/worktree.js +35 -16
- package/dist/resources/extensions/mcp-client/index.js +14 -1
- package/dist/resources/extensions/remote-questions/status.js +2 -1
- package/dist/resources/extensions/remote-questions/store.js +2 -1
- package/dist/resources/extensions/search-the-web/provider.js +2 -1
- package/dist/resources/extensions/subagent/index.js +12 -3
- package/dist/resources/extensions/subagent/isolation.js +2 -1
- package/dist/resources/extensions/ttsr/rule-loader.js +2 -1
- package/dist/resources/extensions/universal-config/package.json +1 -1
- package/dist/welcome-screen.d.ts +12 -0
- package/dist/welcome-screen.js +53 -0
- package/package.json +2 -1
- package/packages/pi-ai/dist/env-api-keys.js +13 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +172 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +172 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +64 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.js +668 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-vertex.d.ts +5 -0
- package/packages/pi-ai/dist/providers/anthropic-vertex.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-vertex.js +85 -0
- package/packages/pi-ai/dist/providers/anthropic-vertex.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts +4 -30
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +47 -764
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/register-builtins.js +6 -0
- package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -2
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/anthropic.js +2 -2
- package/packages/pi-ai/dist/utils/oauth/anthropic.js.map +1 -1
- package/packages/pi-ai/package.json +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +14 -0
- package/packages/pi-ai/src/models.generated.ts +172 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +761 -0
- package/packages/pi-ai/src/providers/anthropic-vertex.ts +130 -0
- package/packages/pi-ai/src/providers/anthropic.ts +76 -868
- package/packages/pi-ai/src/providers/register-builtins.ts +7 -0
- package/packages/pi-ai/src/types.ts +2 -0
- package/packages/pi-ai/src/utils/oauth/anthropic.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +205 -7
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-manager.js +8 -4
- package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +223 -7
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/package-manager.ts +8 -4
- package/pkg/package.json +1 -1
- package/src/resources/extensions/cmux/index.ts +57 -1
- package/src/resources/extensions/env-utils.ts +31 -0
- package/src/resources/extensions/get-secrets-from-user.ts +5 -24
- package/src/resources/extensions/github-sync/cli.ts +364 -0
- package/src/resources/extensions/github-sync/index.ts +93 -0
- package/src/resources/extensions/github-sync/mapping.ts +81 -0
- package/src/resources/extensions/github-sync/sync.ts +556 -0
- package/src/resources/extensions/github-sync/templates.ts +183 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +20 -0
- package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +39 -0
- package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
- package/src/resources/extensions/github-sync/tests/templates.test.ts +110 -0
- package/src/resources/extensions/github-sync/types.ts +47 -0
- package/src/resources/extensions/gsd/auto/session.ts +7 -25
- package/src/resources/extensions/gsd/auto-dispatch.ts +100 -9
- package/src/resources/extensions/gsd/auto-loop.ts +484 -546
- package/src/resources/extensions/gsd/auto-post-unit.ts +92 -42
- package/src/resources/extensions/gsd/auto-prompts.ts +150 -48
- package/src/resources/extensions/gsd/auto-recovery.ts +42 -0
- package/src/resources/extensions/gsd/auto-start.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +15 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +3 -3
- package/src/resources/extensions/gsd/auto.ts +139 -101
- package/src/resources/extensions/gsd/captures.ts +10 -1
- package/src/resources/extensions/gsd/commands-extensions.ts +4 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +17 -2
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/commands.ts +26 -4
- package/src/resources/extensions/gsd/context-budget.ts +2 -12
- package/src/resources/extensions/gsd/detection.ts +2 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -2
- package/src/resources/extensions/gsd/doctor-checks.ts +75 -0
- package/src/resources/extensions/gsd/doctor-environment.ts +82 -1
- package/src/resources/extensions/gsd/doctor-format.ts +20 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +64 -10
- package/src/resources/extensions/gsd/doctor-types.ts +16 -1
- package/src/resources/extensions/gsd/doctor.ts +199 -14
- package/src/resources/extensions/gsd/exit-command.ts +2 -2
- package/src/resources/extensions/gsd/export.ts +1 -1
- package/src/resources/extensions/gsd/files.ts +50 -3
- package/src/resources/extensions/gsd/forensics.ts +1 -1
- package/src/resources/extensions/gsd/git-service.ts +20 -10
- package/src/resources/extensions/gsd/guided-flow.ts +110 -38
- package/src/resources/extensions/gsd/index.ts +24 -17
- package/src/resources/extensions/gsd/migrate/parsers.ts +1 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +37 -0
- package/src/resources/extensions/gsd/observability-validator.ts +27 -0
- package/src/resources/extensions/gsd/preferences-models.ts +0 -12
- package/src/resources/extensions/gsd/preferences-types.ts +9 -5
- package/src/resources/extensions/gsd/preferences-validation.ts +92 -11
- package/src/resources/extensions/gsd/preferences.ts +8 -5
- package/src/resources/extensions/gsd/prompts/discuss.md +11 -14
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +11 -12
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -10
- package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -1
- package/src/resources/extensions/gsd/prompts/queue.md +4 -8
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +44 -0
- package/src/resources/extensions/gsd/prompts/run-uat.md +27 -10
- package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -2
- package/src/resources/extensions/gsd/reactive-graph.ts +289 -0
- package/src/resources/extensions/gsd/repo-identity.ts +23 -4
- package/src/resources/extensions/gsd/resource-version.ts +3 -1
- package/src/resources/extensions/gsd/roadmap-mutations.ts +29 -0
- package/src/resources/extensions/gsd/state.ts +1 -1
- package/src/resources/extensions/gsd/templates/task-plan.md +11 -3
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +21 -18
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +122 -68
- package/src/resources/extensions/gsd/tests/cmux.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +266 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +191 -3
- package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +2 -7
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +511 -0
- package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +299 -0
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +11 -3
- package/src/resources/extensions/gsd/tests/worktree.test.ts +47 -0
- package/src/resources/extensions/gsd/types.ts +43 -1
- package/src/resources/extensions/gsd/visualizer-data.ts +1 -1
- package/src/resources/extensions/gsd/worktree.ts +35 -15
- package/src/resources/extensions/mcp-client/index.ts +17 -1
- package/src/resources/extensions/remote-questions/status.ts +3 -1
- package/src/resources/extensions/remote-questions/store.ts +3 -1
- package/src/resources/extensions/search-the-web/provider.ts +2 -1
- package/src/resources/extensions/subagent/index.ts +12 -3
- package/src/resources/extensions/subagent/isolation.ts +3 -1
- package/src/resources/extensions/ttsr/rule-loader.ts +3 -1
- package/dist/resources/extensions/gsd/prompt-compressor.js +0 -393
- package/dist/resources/extensions/gsd/semantic-chunker.js +0 -254
- package/dist/resources/extensions/gsd/summary-distiller.js +0 -212
- package/src/resources/extensions/gsd/prompt-compressor.ts +0 -508
- package/src/resources/extensions/gsd/semantic-chunker.ts +0 -336
- package/src/resources/extensions/gsd/summary-distiller.ts +0 -258
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +0 -193
- package/src/resources/extensions/gsd/tests/prompt-compressor.test.ts +0 -529
- package/src/resources/extensions/gsd/tests/semantic-chunker.test.ts +0 -426
- package/src/resources/extensions/gsd/tests/summary-distiller.test.ts +0 -323
- package/src/resources/extensions/gsd/tests/token-optimization-benchmark.test.ts +0 -1272
- package/src/resources/extensions/gsd/tests/token-optimization-prefs.test.ts +0 -164
|
@@ -34,6 +34,7 @@ import { showConfirm } from "../shared/mod.js";
|
|
|
34
34
|
import { debugLog } from "./debug-logger.js";
|
|
35
35
|
import { findMilestoneIds, nextMilestoneId } from "./milestone-ids.js";
|
|
36
36
|
import { parkMilestone, discardMilestone } from "./milestone-actions.js";
|
|
37
|
+
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
37
38
|
|
|
38
39
|
// ─── Re-exports (preserve public API for existing importers) ────────────────
|
|
39
40
|
export {
|
|
@@ -190,8 +191,40 @@ type UIContext = ExtensionContext;
|
|
|
190
191
|
/**
|
|
191
192
|
* Read GSD-WORKFLOW.md and dispatch it to the LLM with a contextual note.
|
|
192
193
|
* This is the only way the wizard triggers work — everything else is the LLM's job.
|
|
194
|
+
*
|
|
195
|
+
* When a unitType is provided, resolves the user's model preference for that
|
|
196
|
+
* phase (e.g., models.planning → "plan-milestone") and applies it before
|
|
197
|
+
* dispatching. This ensures guided-flow dispatches respect the same
|
|
198
|
+
* per-phase model preferences that auto-mode uses.
|
|
193
199
|
*/
|
|
194
|
-
function dispatchWorkflow(
|
|
200
|
+
async function dispatchWorkflow(
|
|
201
|
+
pi: ExtensionAPI,
|
|
202
|
+
note: string,
|
|
203
|
+
customType = "gsd-run",
|
|
204
|
+
ctx?: ExtensionContext,
|
|
205
|
+
unitType?: string,
|
|
206
|
+
): Promise<void> {
|
|
207
|
+
// Apply model preference for this unit type (if configured)
|
|
208
|
+
if (ctx && unitType) {
|
|
209
|
+
const modelConfig = resolveModelWithFallbacksForUnit(unitType);
|
|
210
|
+
if (modelConfig) {
|
|
211
|
+
const availableModels = ctx.modelRegistry.getAvailable();
|
|
212
|
+
const modelsToTry = [modelConfig.primary, ...modelConfig.fallbacks];
|
|
213
|
+
|
|
214
|
+
for (const modelId of modelsToTry) {
|
|
215
|
+
// Resolve model from available models (same logic as auto-model-selection)
|
|
216
|
+
const model = resolveAvailableModel(modelId, availableModels, ctx.model?.provider);
|
|
217
|
+
if (!model) continue;
|
|
218
|
+
|
|
219
|
+
const ok = await pi.setModel(model, { persist: false });
|
|
220
|
+
if (ok) {
|
|
221
|
+
debugLog("guided-flow-model-applied", { unitType, model: `${model.provider}/${model.id}` });
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
195
228
|
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".gsd", "agent", "GSD-WORKFLOW.md");
|
|
196
229
|
const workflow = readFileSync(workflowPath, "utf-8");
|
|
197
230
|
|
|
@@ -205,6 +238,45 @@ function dispatchWorkflow(pi: ExtensionAPI, note: string, customType = "gsd-run"
|
|
|
205
238
|
);
|
|
206
239
|
}
|
|
207
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Resolve a model ID string to a model object from available models.
|
|
243
|
+
* Handles "provider/model" and bare ID formats.
|
|
244
|
+
*/
|
|
245
|
+
function resolveAvailableModel<T extends { id: string; provider: string }>(
|
|
246
|
+
modelId: string,
|
|
247
|
+
availableModels: T[],
|
|
248
|
+
currentProvider: string | undefined,
|
|
249
|
+
): T | undefined {
|
|
250
|
+
const slashIdx = modelId.indexOf("/");
|
|
251
|
+
|
|
252
|
+
if (slashIdx !== -1) {
|
|
253
|
+
const maybeProvider = modelId.substring(0, slashIdx);
|
|
254
|
+
const id = modelId.substring(slashIdx + 1);
|
|
255
|
+
|
|
256
|
+
const knownProviders = new Set(availableModels.map(m => m.provider.toLowerCase()));
|
|
257
|
+
if (knownProviders.has(maybeProvider.toLowerCase())) {
|
|
258
|
+
const match = availableModels.find(
|
|
259
|
+
m => m.provider.toLowerCase() === maybeProvider.toLowerCase()
|
|
260
|
+
&& m.id.toLowerCase() === id.toLowerCase(),
|
|
261
|
+
);
|
|
262
|
+
if (match) return match;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Try matching the full string as a model ID (OpenRouter-style)
|
|
266
|
+
const lower = modelId.toLowerCase();
|
|
267
|
+
return availableModels.find(
|
|
268
|
+
m => m.id.toLowerCase() === lower
|
|
269
|
+
|| `${m.provider}/${m.id}`.toLowerCase() === lower,
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Bare ID — prefer current provider, then first available
|
|
274
|
+
const exactProviderMatch = availableModels.find(
|
|
275
|
+
m => m.id === modelId && m.provider === currentProvider,
|
|
276
|
+
);
|
|
277
|
+
return exactProviderMatch ?? availableModels.find(m => m.id === modelId);
|
|
278
|
+
}
|
|
279
|
+
|
|
208
280
|
/**
|
|
209
281
|
* Build the discuss-and-plan prompt for a new milestone.
|
|
210
282
|
* Used by all three "new milestone" paths (first ever, no active, all complete).
|
|
@@ -301,8 +373,8 @@ export async function showHeadlessMilestoneCreation(
|
|
|
301
373
|
// Set pending auto start (auto-mode triggers on "Milestone X ready." via checkAutoStartAfterDiscuss)
|
|
302
374
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId };
|
|
303
375
|
|
|
304
|
-
// Dispatch
|
|
305
|
-
dispatchWorkflow(pi, prompt);
|
|
376
|
+
// Dispatch — headless milestone creation is a planning activity
|
|
377
|
+
await dispatchWorkflow(pi, prompt, "gsd-run", ctx, "plan-milestone");
|
|
306
378
|
}
|
|
307
379
|
|
|
308
380
|
|
|
@@ -467,21 +539,21 @@ export async function showDiscuss(
|
|
|
467
539
|
? `${basePrompt}\n\n## Prior Discussion (Draft Seed)\n\n${draftContent}`
|
|
468
540
|
: basePrompt;
|
|
469
541
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: mid, step: false };
|
|
470
|
-
dispatchWorkflow(pi, seed, "gsd-discuss");
|
|
542
|
+
await dispatchWorkflow(pi, seed, "gsd-discuss", ctx, "plan-milestone");
|
|
471
543
|
} else if (choice === "discuss_fresh") {
|
|
472
544
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
473
545
|
const structuredQuestionsAvailable = pi.getActiveTools().includes("ask_user_questions") ? "true" : "false";
|
|
474
546
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: mid, step: false };
|
|
475
|
-
dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
547
|
+
await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
476
548
|
milestoneId: mid, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
477
549
|
commitInstruction: buildDocsCommitInstruction(`docs(${mid}): milestone context from discuss`),
|
|
478
|
-
}), "gsd-discuss");
|
|
550
|
+
}), "gsd-discuss", ctx, "plan-milestone");
|
|
479
551
|
} else if (choice === "skip_milestone") {
|
|
480
552
|
const milestoneIds = findMilestoneIds(basePath);
|
|
481
553
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
482
554
|
const nextId = nextMilestoneId(milestoneIds, uniqueMilestoneIds);
|
|
483
555
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: false };
|
|
484
|
-
dispatchWorkflow(pi, buildDiscussPrompt(nextId, `New milestone ${nextId}.`, basePath));
|
|
556
|
+
await dispatchWorkflow(pi, buildDiscussPrompt(nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "plan-milestone");
|
|
485
557
|
}
|
|
486
558
|
return;
|
|
487
559
|
}
|
|
@@ -580,7 +652,7 @@ export async function showDiscuss(
|
|
|
580
652
|
}
|
|
581
653
|
|
|
582
654
|
const prompt = await buildDiscussSlicePrompt(mid, chosen.id, chosen.title, basePath, { rediscuss: isRediscuss });
|
|
583
|
-
dispatchWorkflow(pi, prompt, "gsd-discuss");
|
|
655
|
+
await dispatchWorkflow(pi, prompt, "gsd-discuss", ctx, "plan-slice");
|
|
584
656
|
|
|
585
657
|
// Wait for the discuss session to finish, then loop back to the picker
|
|
586
658
|
await ctx.waitForIdle();
|
|
@@ -722,10 +794,10 @@ async function handleMilestoneActions(
|
|
|
722
794
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
723
795
|
const nextId = nextMilestoneId(milestoneIds, uniqueMilestoneIds);
|
|
724
796
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
725
|
-
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
797
|
+
await dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
726
798
|
`New milestone ${nextId}.`,
|
|
727
799
|
basePath
|
|
728
|
-
));
|
|
800
|
+
), "gsd-run", ctx, "plan-milestone");
|
|
729
801
|
return true;
|
|
730
802
|
}
|
|
731
803
|
|
|
@@ -866,10 +938,10 @@ export async function showSmartEntry(
|
|
|
866
938
|
if (isFirst) {
|
|
867
939
|
// First ever — skip wizard, just ask directly
|
|
868
940
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
869
|
-
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
941
|
+
await dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
870
942
|
`New project, milestone ${nextId}. Do NOT read or explore .gsd/ — it's empty scaffolding.`,
|
|
871
943
|
basePath
|
|
872
|
-
));
|
|
944
|
+
), "gsd-run", ctx, "plan-milestone");
|
|
873
945
|
} else {
|
|
874
946
|
const choice = await showNextAction(ctx, {
|
|
875
947
|
title: "GSD — Get Shit Done",
|
|
@@ -887,10 +959,10 @@ export async function showSmartEntry(
|
|
|
887
959
|
|
|
888
960
|
if (choice === "new_milestone") {
|
|
889
961
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
890
|
-
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
962
|
+
await dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
891
963
|
`New milestone ${nextId}.`,
|
|
892
964
|
basePath
|
|
893
|
-
));
|
|
965
|
+
), "gsd-run", ctx, "plan-milestone");
|
|
894
966
|
}
|
|
895
967
|
}
|
|
896
968
|
return;
|
|
@@ -926,10 +998,10 @@ export async function showSmartEntry(
|
|
|
926
998
|
const nextId = nextMilestoneId(milestoneIds, uniqueMilestoneIds);
|
|
927
999
|
|
|
928
1000
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
929
|
-
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
1001
|
+
await dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
930
1002
|
`New milestone ${nextId}.`,
|
|
931
1003
|
basePath
|
|
932
|
-
));
|
|
1004
|
+
), "gsd-run", ctx, "plan-milestone");
|
|
933
1005
|
} else if (choice === "status") {
|
|
934
1006
|
const { fireStatusViaCommand } = await import("./commands.js");
|
|
935
1007
|
await fireStatusViaCommand(ctx);
|
|
@@ -977,24 +1049,24 @@ export async function showSmartEntry(
|
|
|
977
1049
|
? `${basePrompt}\n\n## Prior Discussion (Draft Seed)\n\n${draftContent}`
|
|
978
1050
|
: basePrompt;
|
|
979
1051
|
pendingAutoStart = { ctx, pi, basePath, milestoneId, step: stepMode };
|
|
980
|
-
dispatchWorkflow(pi, seed, "gsd-discuss");
|
|
1052
|
+
await dispatchWorkflow(pi, seed, "gsd-discuss", ctx, "plan-milestone");
|
|
981
1053
|
} else if (choice === "discuss_fresh") {
|
|
982
1054
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
983
1055
|
const structuredQuestionsAvailable = pi.getActiveTools().includes("ask_user_questions") ? "true" : "false";
|
|
984
1056
|
pendingAutoStart = { ctx, pi, basePath, milestoneId, step: stepMode };
|
|
985
|
-
dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
1057
|
+
await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
986
1058
|
milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
987
1059
|
commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
|
|
988
|
-
}), "gsd-discuss");
|
|
1060
|
+
}), "gsd-discuss", ctx, "plan-milestone");
|
|
989
1061
|
} else if (choice === "skip_milestone") {
|
|
990
1062
|
const milestoneIds = findMilestoneIds(basePath);
|
|
991
1063
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
992
1064
|
const nextId = nextMilestoneId(milestoneIds, uniqueMilestoneIds);
|
|
993
1065
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
994
|
-
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
1066
|
+
await dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
995
1067
|
`New milestone ${nextId}.`,
|
|
996
1068
|
basePath
|
|
997
|
-
));
|
|
1069
|
+
), "gsd-run", ctx, "plan-milestone");
|
|
998
1070
|
}
|
|
999
1071
|
return;
|
|
1000
1072
|
}
|
|
@@ -1051,25 +1123,25 @@ export async function showSmartEntry(
|
|
|
1051
1123
|
inlineTemplate("secrets-manifest", "Secrets Manifest"),
|
|
1052
1124
|
].join("\n\n---\n\n");
|
|
1053
1125
|
const secretsOutputPath = relMilestoneFile(basePath, milestoneId, "SECRETS");
|
|
1054
|
-
dispatchWorkflow(pi, loadPrompt("guided-plan-milestone", {
|
|
1126
|
+
await dispatchWorkflow(pi, loadPrompt("guided-plan-milestone", {
|
|
1055
1127
|
milestoneId, milestoneTitle, secretsOutputPath, inlinedTemplates: planMilestoneTemplates,
|
|
1056
|
-
}));
|
|
1128
|
+
}), "gsd-run", ctx, "plan-milestone");
|
|
1057
1129
|
} else if (choice === "discuss") {
|
|
1058
1130
|
const discussMilestoneTemplates = inlineTemplate("context", "Context");
|
|
1059
1131
|
const structuredQuestionsAvailable = pi.getActiveTools().includes("ask_user_questions") ? "true" : "false";
|
|
1060
|
-
dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
1132
|
+
await dispatchWorkflow(pi, loadPrompt("guided-discuss-milestone", {
|
|
1061
1133
|
milestoneId, milestoneTitle, inlinedTemplates: discussMilestoneTemplates, structuredQuestionsAvailable,
|
|
1062
1134
|
commitInstruction: buildDocsCommitInstruction(`docs(${milestoneId}): milestone context from discuss`),
|
|
1063
|
-
}));
|
|
1135
|
+
}), "gsd-run", ctx, "plan-milestone");
|
|
1064
1136
|
} else if (choice === "skip_milestone") {
|
|
1065
1137
|
const milestoneIds = findMilestoneIds(basePath);
|
|
1066
1138
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1067
1139
|
const nextId = nextMilestoneId(milestoneIds, uniqueMilestoneIds);
|
|
1068
1140
|
pendingAutoStart = { ctx, pi, basePath, milestoneId: nextId, step: stepMode };
|
|
1069
|
-
dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
1141
|
+
await dispatchWorkflow(pi, buildDiscussPrompt(nextId,
|
|
1070
1142
|
`New milestone ${nextId}.`,
|
|
1071
1143
|
basePath
|
|
1072
|
-
));
|
|
1144
|
+
), "gsd-run", ctx, "plan-milestone");
|
|
1073
1145
|
} else if (choice === "discard_milestone") {
|
|
1074
1146
|
const confirmed = await showConfirm(ctx, {
|
|
1075
1147
|
title: "Discard milestone?",
|
|
@@ -1181,16 +1253,16 @@ export async function showSmartEntry(
|
|
|
1181
1253
|
inlineTemplate("plan", "Slice Plan"),
|
|
1182
1254
|
inlineTemplate("task-plan", "Task Plan"),
|
|
1183
1255
|
].join("\n\n---\n\n");
|
|
1184
|
-
dispatchWorkflow(pi, loadPrompt("guided-plan-slice", {
|
|
1256
|
+
await dispatchWorkflow(pi, loadPrompt("guided-plan-slice", {
|
|
1185
1257
|
milestoneId, sliceId, sliceTitle, inlinedTemplates: planSliceTemplates,
|
|
1186
|
-
}));
|
|
1258
|
+
}), "gsd-run", ctx, "plan-slice");
|
|
1187
1259
|
} else if (choice === "discuss") {
|
|
1188
|
-
dispatchWorkflow(pi, await buildDiscussSlicePrompt(milestoneId, sliceId, sliceTitle, basePath, { rediscuss: hasContext }));
|
|
1260
|
+
await dispatchWorkflow(pi, await buildDiscussSlicePrompt(milestoneId, sliceId, sliceTitle, basePath, { rediscuss: hasContext }), "gsd-run", ctx, "plan-slice");
|
|
1189
1261
|
} else if (choice === "research") {
|
|
1190
1262
|
const researchTemplates = inlineTemplate("research", "Research");
|
|
1191
|
-
dispatchWorkflow(pi, loadPrompt("guided-research-slice", {
|
|
1263
|
+
await dispatchWorkflow(pi, loadPrompt("guided-research-slice", {
|
|
1192
1264
|
milestoneId, sliceId, sliceTitle, inlinedTemplates: researchTemplates,
|
|
1193
|
-
}));
|
|
1265
|
+
}), "gsd-run", ctx, "research-slice");
|
|
1194
1266
|
} else if (choice === "status") {
|
|
1195
1267
|
const { fireStatusViaCommand } = await import("./commands.js");
|
|
1196
1268
|
await fireStatusViaCommand(ctx);
|
|
@@ -1232,9 +1304,9 @@ export async function showSmartEntry(
|
|
|
1232
1304
|
inlineTemplate("slice-summary", "Slice Summary"),
|
|
1233
1305
|
inlineTemplate("uat", "UAT"),
|
|
1234
1306
|
].join("\n\n---\n\n");
|
|
1235
|
-
dispatchWorkflow(pi, loadPrompt("guided-complete-slice", {
|
|
1307
|
+
await dispatchWorkflow(pi, loadPrompt("guided-complete-slice", {
|
|
1236
1308
|
workingDirectory: basePath, milestoneId, sliceId, sliceTitle, inlinedTemplates: completeSliceTemplates,
|
|
1237
|
-
}));
|
|
1309
|
+
}), "gsd-run", ctx, "complete-slice");
|
|
1238
1310
|
} else if (choice === "status") {
|
|
1239
1311
|
const { fireStatusViaCommand } = await import("./commands.js");
|
|
1240
1312
|
await fireStatusViaCommand(ctx);
|
|
@@ -1297,14 +1369,14 @@ export async function showSmartEntry(
|
|
|
1297
1369
|
|
|
1298
1370
|
if (choice === "execute") {
|
|
1299
1371
|
if (hasInterrupted) {
|
|
1300
|
-
dispatchWorkflow(pi, loadPrompt("guided-resume-task", {
|
|
1372
|
+
await dispatchWorkflow(pi, loadPrompt("guided-resume-task", {
|
|
1301
1373
|
milestoneId, sliceId,
|
|
1302
|
-
}));
|
|
1374
|
+
}), "gsd-run", ctx, "execute-task");
|
|
1303
1375
|
} else {
|
|
1304
1376
|
const executeTaskTemplates = inlineTemplate("task-summary", "Task Summary");
|
|
1305
|
-
dispatchWorkflow(pi, loadPrompt("guided-execute-task", {
|
|
1377
|
+
await dispatchWorkflow(pi, loadPrompt("guided-execute-task", {
|
|
1306
1378
|
milestoneId, sliceId, taskId, taskTitle, inlinedTemplates: executeTaskTemplates,
|
|
1307
|
-
}));
|
|
1379
|
+
}), "gsd-run", ctx, "execute-task");
|
|
1308
1380
|
}
|
|
1309
1381
|
} else if (choice === "status") {
|
|
1310
1382
|
const { fireStatusViaCommand } = await import("./commands.js");
|
|
@@ -60,6 +60,8 @@ import { join } from "node:path";
|
|
|
60
60
|
import { existsSync, readFileSync } from "node:fs";
|
|
61
61
|
import { homedir } from "node:os";
|
|
62
62
|
import { shortcutDesc } from "../shared/mod.js";
|
|
63
|
+
|
|
64
|
+
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
63
65
|
import { Text } from "@gsd/pi-tui";
|
|
64
66
|
import { pauseAutoForProviderError, classifyProviderError } from "./provider-error-pause.js";
|
|
65
67
|
import { toPosixPath } from "../shared/mod.js";
|
|
@@ -73,7 +75,7 @@ import { markCmuxPromptShown, shouldPromptToEnableCmux } from "../cmux/index.js"
|
|
|
73
75
|
|
|
74
76
|
function warnDeprecatedAgentInstructions(): void {
|
|
75
77
|
const paths = [
|
|
76
|
-
join(
|
|
78
|
+
join(gsdHome, "agent-instructions.md"),
|
|
77
79
|
join(process.cwd(), ".gsd", "agent-instructions.md"),
|
|
78
80
|
];
|
|
79
81
|
for (const p of paths) {
|
|
@@ -90,6 +92,23 @@ function warnDeprecatedAgentInstructions(): void {
|
|
|
90
92
|
// ── Depth verification state ──────────────────────────────────────────────
|
|
91
93
|
let depthVerificationDone = false;
|
|
92
94
|
|
|
95
|
+
// ── DB lazy-open helper ───────────────────────────────────────────────────
|
|
96
|
+
// In manual sessions (no auto-mode), the DB is never opened by bootstrapAutoSession.
|
|
97
|
+
// This helper ensures the DB is lazily opened on first tool call that needs it.
|
|
98
|
+
async function ensureDbOpen(): Promise<boolean> {
|
|
99
|
+
try {
|
|
100
|
+
const db = await import("./gsd-db.js");
|
|
101
|
+
if (db.isDbAvailable()) return true;
|
|
102
|
+
const dbPath = join(process.cwd(), ".gsd", "gsd.db");
|
|
103
|
+
if (existsSync(dbPath)) {
|
|
104
|
+
return db.openDatabase(dbPath);
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
} catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
93
112
|
// ── Queue phase tracking ──────────────────────────────────────────────────
|
|
94
113
|
// When true, the LLM is in a queue flow writing CONTEXT.md files.
|
|
95
114
|
// The write-gate applies during queue flows just like discussion flows.
|
|
@@ -298,12 +317,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
298
317
|
when_context: Type.Optional(Type.String({ description: "When/context for the decision (e.g. milestone ID)" })),
|
|
299
318
|
}),
|
|
300
319
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
try {
|
|
304
|
-
const db = await import("./gsd-db.js");
|
|
305
|
-
dbAvailable = db.isDbAvailable();
|
|
306
|
-
} catch { /* dynamic import failed */ }
|
|
320
|
+
// Ensure DB is open (lazy-open on first tool call in manual sessions)
|
|
321
|
+
const dbAvailable = await ensureDbOpen();
|
|
307
322
|
|
|
308
323
|
if (!dbAvailable) {
|
|
309
324
|
return {
|
|
@@ -365,11 +380,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
365
380
|
supporting_slices: Type.Optional(Type.String({ description: "Supporting slices" })),
|
|
366
381
|
}),
|
|
367
382
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
368
|
-
|
|
369
|
-
try {
|
|
370
|
-
const db = await import("./gsd-db.js");
|
|
371
|
-
dbAvailable = db.isDbAvailable();
|
|
372
|
-
} catch { /* dynamic import failed */ }
|
|
383
|
+
const dbAvailable = await ensureDbOpen();
|
|
373
384
|
|
|
374
385
|
if (!dbAvailable) {
|
|
375
386
|
return {
|
|
@@ -439,11 +450,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
439
450
|
content: Type.String({ description: "The full markdown content of the artifact" }),
|
|
440
451
|
}),
|
|
441
452
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
442
|
-
|
|
443
|
-
try {
|
|
444
|
-
const db = await import("./gsd-db.js");
|
|
445
|
-
dbAvailable = db.isDbAvailable();
|
|
446
|
-
} catch { /* dynamic import failed */ }
|
|
453
|
+
const dbAvailable = await ensureDbOpen();
|
|
447
454
|
|
|
448
455
|
if (!dbAvailable) {
|
|
449
456
|
return {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Zero Pi dependencies — uses only exported helpers from files.ts.
|
|
4
4
|
|
|
5
5
|
import { splitFrontmatter, parseFrontmatterMap, extractBoldField } from '../files.js';
|
|
6
|
-
import { normalizeStringArray } from '../../shared/
|
|
6
|
+
import { normalizeStringArray } from '../../shared/format-utils.js';
|
|
7
7
|
|
|
8
8
|
import type {
|
|
9
9
|
PlanningRoadmap,
|
|
@@ -671,6 +671,43 @@ export function nativeAddAll(basePath: string): void {
|
|
|
671
671
|
gitFileExec(basePath, ["add", "-A"]);
|
|
672
672
|
}
|
|
673
673
|
|
|
674
|
+
/**
|
|
675
|
+
* Stage all files with pathspec exclusions (git add -A -- ':!pattern' ...).
|
|
676
|
+
* Excluded paths are never hashed by git, preventing hangs on large
|
|
677
|
+
* untracked artifact trees (57GB+, 11K+ files). See #1605.
|
|
678
|
+
*
|
|
679
|
+
* Falls back to plain `git add -A` when no exclusions are provided.
|
|
680
|
+
* Always uses the CLI path (not libgit2) because libgit2's add_all
|
|
681
|
+
* does not support pathspec exclusion syntax.
|
|
682
|
+
*
|
|
683
|
+
* When excluded paths are already covered by .gitignore, git may exit
|
|
684
|
+
* with code 1 and an "ignored by .gitignore" warning. This is harmless
|
|
685
|
+
* (the staging succeeds for all non-ignored files) and is suppressed.
|
|
686
|
+
*/
|
|
687
|
+
export function nativeAddAllWithExclusions(basePath: string, exclusions: readonly string[]): void {
|
|
688
|
+
if (exclusions.length === 0) {
|
|
689
|
+
nativeAddAll(basePath);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
const pathspecs = exclusions.map(e => `:!${e}`);
|
|
693
|
+
try {
|
|
694
|
+
execFileSync("git", ["add", "-A", "--", ...pathspecs], {
|
|
695
|
+
cwd: basePath,
|
|
696
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
697
|
+
encoding: "utf-8",
|
|
698
|
+
env: GIT_NO_PROMPT_ENV,
|
|
699
|
+
});
|
|
700
|
+
} catch (err: unknown) {
|
|
701
|
+
// git exits 1 when pathspec exclusions reference paths already covered
|
|
702
|
+
// by .gitignore. The staging itself succeeds — only suppress that case.
|
|
703
|
+
const stderr = (err as { stderr?: string })?.stderr ?? "";
|
|
704
|
+
if (stderr.includes("ignored by one of your .gitignore files")) {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
throw new GSDError(GSD_GIT_ERROR, `git add -A with exclusions failed in ${basePath}: ${getErrorMessage(err)}`);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
674
711
|
/**
|
|
675
712
|
* Stage specific files.
|
|
676
713
|
* Native: libgit2 index add.
|
|
@@ -235,6 +235,33 @@ export function validateTaskPlanContent(file: string, content: string): Validati
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
+
// Rule: Inputs and Expected Output should contain backtick-wrapped file paths
|
|
239
|
+
const inputsSection = getSection(content, "Inputs", 2);
|
|
240
|
+
const outputSection = getSection(content, "Expected Output", 2);
|
|
241
|
+
const backtickPathPattern = /`[^`]*[./][^`]*`/;
|
|
242
|
+
|
|
243
|
+
if (outputSection === null || !backtickPathPattern.test(outputSection)) {
|
|
244
|
+
issues.push({
|
|
245
|
+
severity: "warning",
|
|
246
|
+
scope: "task-plan",
|
|
247
|
+
file,
|
|
248
|
+
ruleId: "missing_output_file_paths",
|
|
249
|
+
message: "Task plan `## Expected Output` is missing or has no backtick-wrapped file paths.",
|
|
250
|
+
suggestion: "List concrete output file paths in backticks (e.g. `src/types.ts`). These are machine-parsed to derive task dependencies.",
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (inputsSection !== null && inputsSection.trim().length > 0 && !backtickPathPattern.test(inputsSection)) {
|
|
255
|
+
issues.push({
|
|
256
|
+
severity: "info",
|
|
257
|
+
scope: "task-plan",
|
|
258
|
+
file,
|
|
259
|
+
ruleId: "missing_input_file_paths",
|
|
260
|
+
message: "Task plan `## Inputs` has content but no backtick-wrapped file paths.",
|
|
261
|
+
suggestion: "List input file paths in backticks (e.g. `src/config.json`). These are machine-parsed to derive task dependencies.",
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
238
265
|
// ── Observability rules (gated by runtime relevance) ──
|
|
239
266
|
|
|
240
267
|
const relevant = textSuggestsObservabilityRelevant(content);
|
|
@@ -295,18 +295,6 @@ export function resolveInlineLevel(): InlineLevel {
|
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
/**
|
|
299
|
-
* Resolve the compression strategy from the active token profile.
|
|
300
|
-
* budget/balanced -> "compress", quality -> "truncate".
|
|
301
|
-
* Explicit preference always wins.
|
|
302
|
-
*/
|
|
303
|
-
export function resolveCompressionStrategy(): import("./types.js").CompressionStrategy {
|
|
304
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
305
|
-
if (prefs?.preferences.compression_strategy) return prefs.preferences.compression_strategy;
|
|
306
|
-
const profile = resolveEffectiveProfile();
|
|
307
|
-
return profile === "quality" ? "truncate" : "compress";
|
|
308
|
-
}
|
|
309
|
-
|
|
310
298
|
/**
|
|
311
299
|
* Resolve the context selection mode from the active token profile.
|
|
312
300
|
* budget -> "smart", balanced/quality -> "full".
|
|
@@ -16,10 +16,11 @@ import type {
|
|
|
16
16
|
InlineLevel,
|
|
17
17
|
PhaseSkipPreferences,
|
|
18
18
|
ParallelConfig,
|
|
19
|
-
CompressionStrategy,
|
|
20
19
|
ContextSelectionMode,
|
|
20
|
+
ReactiveExecutionConfig,
|
|
21
21
|
} from "./types.js";
|
|
22
22
|
import type { DynamicRoutingConfig } from "./model-router.js";
|
|
23
|
+
import type { GitHubSyncConfig } from "../github-sync/types.js";
|
|
23
24
|
|
|
24
25
|
// ─── Workflow Modes ──────────────────────────────────────────────────────────
|
|
25
26
|
|
|
@@ -83,15 +84,16 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
83
84
|
"verification_auto_fix",
|
|
84
85
|
"verification_max_retries",
|
|
85
86
|
"search_provider",
|
|
86
|
-
"compression_strategy",
|
|
87
87
|
"context_selection",
|
|
88
88
|
"widget_mode",
|
|
89
|
+
"reactive_execution",
|
|
90
|
+
"github",
|
|
89
91
|
]);
|
|
90
92
|
|
|
91
93
|
/** Canonical list of all dispatch unit types. */
|
|
92
94
|
export const KNOWN_UNIT_TYPES = [
|
|
93
95
|
"research-milestone", "plan-milestone", "research-slice", "plan-slice",
|
|
94
|
-
"execute-task", "complete-slice", "replan-slice", "reassess-roadmap",
|
|
96
|
+
"execute-task", "reactive-execute", "complete-slice", "replan-slice", "reassess-roadmap",
|
|
95
97
|
"run-uat", "complete-milestone",
|
|
96
98
|
] as const;
|
|
97
99
|
export type UnitType = (typeof KNOWN_UNIT_TYPES)[number];
|
|
@@ -209,12 +211,14 @@ export interface GSDPreferences {
|
|
|
209
211
|
verification_max_retries?: number;
|
|
210
212
|
/** Search provider preference. "brave"/"tavily"/"ollama" force that backend and disable native Anthropic search. "native" forces native only. "auto" = current default behavior. */
|
|
211
213
|
search_provider?: "brave" | "tavily" | "ollama" | "native" | "auto";
|
|
212
|
-
/** Compression strategy for context that exceeds budget. "truncate" (default) drops sections, "compress" applies heuristic compression first. */
|
|
213
|
-
compression_strategy?: CompressionStrategy;
|
|
214
214
|
/** Context selection mode for file inlining. "full" inlines entire files, "smart" uses semantic chunking. Default derived from token profile. */
|
|
215
215
|
context_selection?: ContextSelectionMode;
|
|
216
216
|
/** Default widget display mode for auto-mode dashboard. "full" | "small" | "min" | "off". Default: "full". */
|
|
217
217
|
widget_mode?: "full" | "small" | "min" | "off";
|
|
218
|
+
/** Reactive (graph-derived parallel) task execution within slices. Disabled by default. */
|
|
219
|
+
reactive_execution?: ReactiveExecutionConfig;
|
|
220
|
+
/** GitHub sync configuration. Opt-in: syncs GSD events to GitHub Issues, Milestones, and PRs. */
|
|
221
|
+
github?: GitHubSyncConfig;
|
|
218
222
|
}
|
|
219
223
|
|
|
220
224
|
export interface LoadedGSDPreferences {
|