gsd-pi 2.36.0-dev.d612764 → 2.36.0-dev.f887f4e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/resources/extensions/gsd/auto-dashboard.js +104 -334
- package/dist/resources/extensions/gsd/auto-loop.js +0 -11
- package/dist/resources/extensions/gsd/auto.js +0 -16
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -1
- package/dist/resources/extensions/gsd/commands.js +1 -51
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -25
- package/dist/resources/extensions/gsd/index.js +0 -5
- package/dist/resources/extensions/gsd/notifications.js +1 -10
- package/dist/resources/extensions/gsd/preferences-types.js +0 -2
- package/dist/resources/extensions/gsd/preferences-validation.js +0 -29
- package/dist/resources/extensions/gsd/preferences.js +0 -3
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +3 -4
- package/dist/resources/extensions/gsd/prompts/research-slice.md +2 -3
- package/dist/resources/extensions/gsd/templates/preferences.md +0 -6
- package/dist/resources/extensions/search-the-web/native-search.js +4 -45
- package/dist/resources/extensions/shared/terminal.js +0 -5
- package/dist/resources/extensions/subagent/index.js +60 -180
- package/package.json +1 -1
- package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal-image.js +0 -4
- package/packages/pi-tui/dist/terminal-image.js.map +1 -1
- package/packages/pi-tui/src/terminal-image.ts +0 -5
- package/src/resources/extensions/gsd/auto-dashboard.ts +116 -363
- package/src/resources/extensions/gsd/auto-loop.ts +0 -42
- package/src/resources/extensions/gsd/auto.ts +0 -21
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -1
- package/src/resources/extensions/gsd/commands.ts +1 -54
- package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -25
- package/src/resources/extensions/gsd/index.ts +0 -8
- package/src/resources/extensions/gsd/notifications.ts +1 -10
- package/src/resources/extensions/gsd/preferences-types.ts +0 -13
- package/src/resources/extensions/gsd/preferences-validation.ts +0 -26
- package/src/resources/extensions/gsd/preferences.ts +0 -4
- package/src/resources/extensions/gsd/prompts/research-milestone.md +3 -4
- package/src/resources/extensions/gsd/prompts/research-slice.md +2 -3
- package/src/resources/extensions/gsd/templates/preferences.md +0 -6
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +0 -2
- package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -23
- package/src/resources/extensions/search-the-web/native-search.ts +4 -50
- package/src/resources/extensions/shared/terminal.ts +0 -5
- package/src/resources/extensions/subagent/index.ts +79 -236
- package/dist/resources/extensions/cmux/index.js +0 -321
- package/dist/resources/extensions/gsd/commands-cmux.js +0 -120
- package/src/resources/extensions/cmux/index.ts +0 -384
- package/src/resources/extensions/gsd/commands-cmux.ts +0 -143
- package/src/resources/extensions/gsd/tests/cmux.test.ts +0 -98
|
@@ -25,7 +25,6 @@ import type {
|
|
|
25
25
|
import type { DispatchAction } from "./auto-dispatch.js";
|
|
26
26
|
import type { WorktreeResolver } from "./worktree-resolver.js";
|
|
27
27
|
import { debugLog } from "./debug-logger.js";
|
|
28
|
-
import type { CmuxLogLevel } from "../cmux/index.js";
|
|
29
28
|
|
|
30
29
|
/**
|
|
31
30
|
* Maximum total loop iterations before forced stop. Prevents runaway loops
|
|
@@ -277,12 +276,6 @@ export interface LoopDeps {
|
|
|
277
276
|
unitId: string,
|
|
278
277
|
state: GSDState,
|
|
279
278
|
) => void;
|
|
280
|
-
syncCmuxSidebar: (preferences: GSDPreferences | undefined, state: GSDState) => void;
|
|
281
|
-
logCmuxEvent: (
|
|
282
|
-
preferences: GSDPreferences | undefined,
|
|
283
|
-
message: string,
|
|
284
|
-
level?: CmuxLogLevel,
|
|
285
|
-
) => void;
|
|
286
279
|
|
|
287
280
|
// State and cache functions
|
|
288
281
|
invalidateAllCaches: () => void;
|
|
@@ -616,7 +609,6 @@ export async function autoLoop(
|
|
|
616
609
|
|
|
617
610
|
// Derive state
|
|
618
611
|
let state = await deps.deriveState(s.basePath);
|
|
619
|
-
deps.syncCmuxSidebar(deps.loadEffectiveGSDPreferences()?.preferences, state);
|
|
620
612
|
let mid = state.activeMilestone?.id;
|
|
621
613
|
let midTitle = state.activeMilestone?.title;
|
|
622
614
|
debugLog("autoLoop", {
|
|
@@ -638,11 +630,6 @@ export async function autoLoop(
|
|
|
638
630
|
"success",
|
|
639
631
|
"milestone",
|
|
640
632
|
);
|
|
641
|
-
deps.logCmuxEvent(
|
|
642
|
-
deps.loadEffectiveGSDPreferences()?.preferences,
|
|
643
|
-
`Milestone ${s.currentMilestoneId} complete. Advancing to ${mid}.`,
|
|
644
|
-
"success",
|
|
645
|
-
);
|
|
646
633
|
|
|
647
634
|
const vizPrefs = deps.loadEffectiveGSDPreferences()?.preferences;
|
|
648
635
|
if (vizPrefs?.auto_visualize) {
|
|
@@ -780,18 +767,12 @@ export async function autoLoop(
|
|
|
780
767
|
"success",
|
|
781
768
|
"milestone",
|
|
782
769
|
);
|
|
783
|
-
deps.logCmuxEvent(
|
|
784
|
-
deps.loadEffectiveGSDPreferences()?.preferences,
|
|
785
|
-
"All milestones complete.",
|
|
786
|
-
"success",
|
|
787
|
-
);
|
|
788
770
|
await deps.stopAuto(ctx, pi, "All milestones complete");
|
|
789
771
|
} else if (state.phase === "blocked") {
|
|
790
772
|
const blockerMsg = `Blocked: ${state.blockers.join(", ")}`;
|
|
791
773
|
await deps.stopAuto(ctx, pi, blockerMsg);
|
|
792
774
|
ctx.ui.notify(`${blockerMsg}. Fix and run /gsd auto.`, "warning");
|
|
793
775
|
deps.sendDesktopNotification("GSD", blockerMsg, "error", "attention");
|
|
794
|
-
deps.logCmuxEvent(deps.loadEffectiveGSDPreferences()?.preferences, blockerMsg, "error");
|
|
795
776
|
} else {
|
|
796
777
|
const ids = incomplete.map((m: { id: string }) => m.id).join(", ");
|
|
797
778
|
const diag = `basePath=${s.basePath}, milestones=[${state.registry.map((m: { id: string; status: string }) => `${m.id}:${m.status}`).join(", ")}], phase=${state.phase}`;
|
|
@@ -869,11 +850,6 @@ export async function autoLoop(
|
|
|
869
850
|
"success",
|
|
870
851
|
"milestone",
|
|
871
852
|
);
|
|
872
|
-
deps.logCmuxEvent(
|
|
873
|
-
deps.loadEffectiveGSDPreferences()?.preferences,
|
|
874
|
-
`Milestone ${mid} complete.`,
|
|
875
|
-
"success",
|
|
876
|
-
);
|
|
877
853
|
await deps.stopAuto(ctx, pi, `Milestone ${mid} complete`);
|
|
878
854
|
debugLog("autoLoop", { phase: "exit", reason: "milestone-complete" });
|
|
879
855
|
break;
|
|
@@ -895,7 +871,6 @@ export async function autoLoop(
|
|
|
895
871
|
await deps.stopAuto(ctx, pi, blockerMsg);
|
|
896
872
|
ctx.ui.notify(`${blockerMsg}. Fix and run /gsd auto.`, "warning");
|
|
897
873
|
deps.sendDesktopNotification("GSD", blockerMsg, "error", "attention");
|
|
898
|
-
deps.logCmuxEvent(deps.loadEffectiveGSDPreferences()?.preferences, blockerMsg, "error");
|
|
899
874
|
debugLog("autoLoop", { phase: "exit", reason: "blocked" });
|
|
900
875
|
break;
|
|
901
876
|
}
|
|
@@ -939,14 +914,12 @@ export async function autoLoop(
|
|
|
939
914
|
"warning",
|
|
940
915
|
);
|
|
941
916
|
deps.sendDesktopNotification("GSD", msg, "warning", "budget");
|
|
942
|
-
deps.logCmuxEvent(prefs, msg, "warning");
|
|
943
917
|
await deps.pauseAuto(ctx, pi);
|
|
944
918
|
debugLog("autoLoop", { phase: "exit", reason: "budget-pause" });
|
|
945
919
|
break;
|
|
946
920
|
}
|
|
947
921
|
ctx.ui.notify(`${msg} Continuing (enforcement: warn).`, "warning");
|
|
948
922
|
deps.sendDesktopNotification("GSD", msg, "warning", "budget");
|
|
949
|
-
deps.logCmuxEvent(prefs, msg, "warning");
|
|
950
923
|
} else if (newBudgetAlertLevel === 90) {
|
|
951
924
|
s.lastBudgetAlertLevel =
|
|
952
925
|
newBudgetAlertLevel as AutoSession["lastBudgetAlertLevel"];
|
|
@@ -960,11 +933,6 @@ export async function autoLoop(
|
|
|
960
933
|
"warning",
|
|
961
934
|
"budget",
|
|
962
935
|
);
|
|
963
|
-
deps.logCmuxEvent(
|
|
964
|
-
prefs,
|
|
965
|
-
`Budget 90%: ${deps.formatCost(totalCost)} / ${deps.formatCost(budgetCeiling)}`,
|
|
966
|
-
"warning",
|
|
967
|
-
);
|
|
968
936
|
} else if (newBudgetAlertLevel === 80) {
|
|
969
937
|
s.lastBudgetAlertLevel =
|
|
970
938
|
newBudgetAlertLevel as AutoSession["lastBudgetAlertLevel"];
|
|
@@ -978,11 +946,6 @@ export async function autoLoop(
|
|
|
978
946
|
"warning",
|
|
979
947
|
"budget",
|
|
980
948
|
);
|
|
981
|
-
deps.logCmuxEvent(
|
|
982
|
-
prefs,
|
|
983
|
-
`Budget 80%: ${deps.formatCost(totalCost)} / ${deps.formatCost(budgetCeiling)}`,
|
|
984
|
-
"warning",
|
|
985
|
-
);
|
|
986
949
|
} else if (newBudgetAlertLevel === 75) {
|
|
987
950
|
s.lastBudgetAlertLevel =
|
|
988
951
|
newBudgetAlertLevel as AutoSession["lastBudgetAlertLevel"];
|
|
@@ -996,11 +959,6 @@ export async function autoLoop(
|
|
|
996
959
|
"info",
|
|
997
960
|
"budget",
|
|
998
961
|
);
|
|
999
|
-
deps.logCmuxEvent(
|
|
1000
|
-
prefs,
|
|
1001
|
-
`Budget 75%: ${deps.formatCost(totalCost)} / ${deps.formatCost(budgetCeiling)}`,
|
|
1002
|
-
"progress",
|
|
1003
|
-
);
|
|
1004
962
|
} else if (budgetAlertLevel === 0) {
|
|
1005
963
|
s.lastBudgetAlertLevel = 0;
|
|
1006
964
|
}
|
|
@@ -184,7 +184,6 @@ import {
|
|
|
184
184
|
} from "./auto-supervisor.js";
|
|
185
185
|
import { isDbAvailable } from "./gsd-db.js";
|
|
186
186
|
import { countPendingCaptures } from "./captures.js";
|
|
187
|
-
import { clearCmuxSidebar, logCmuxEvent, syncCmuxSidebar } from "../cmux/index.js";
|
|
188
187
|
|
|
189
188
|
// ── Extracted modules ──────────────────────────────────────────────────────
|
|
190
189
|
import { startUnitSupervision } from "./auto-timers.js";
|
|
@@ -467,7 +466,6 @@ function handleLostSessionLock(ctx?: ExtensionContext): void {
|
|
|
467
466
|
s.paused = false;
|
|
468
467
|
clearUnitTimeout();
|
|
469
468
|
deregisterSigtermHandler();
|
|
470
|
-
clearCmuxSidebar(loadEffectiveGSDPreferences()?.preferences);
|
|
471
469
|
ctx?.ui.notify(
|
|
472
470
|
"Session lock lost — another GSD process appears to have taken over. Stopping gracefully.",
|
|
473
471
|
"error",
|
|
@@ -483,7 +481,6 @@ export async function stopAuto(
|
|
|
483
481
|
reason?: string,
|
|
484
482
|
): Promise<void> {
|
|
485
483
|
if (!s.active && !s.paused) return;
|
|
486
|
-
const loadedPreferences = loadEffectiveGSDPreferences()?.preferences;
|
|
487
484
|
const reasonSuffix = reason ? ` — ${reason}` : "";
|
|
488
485
|
clearUnitTimeout();
|
|
489
486
|
if (lockBase()) clearLock(lockBase());
|
|
@@ -546,13 +543,6 @@ export async function stopAuto(
|
|
|
546
543
|
}
|
|
547
544
|
}
|
|
548
545
|
|
|
549
|
-
clearCmuxSidebar(loadedPreferences);
|
|
550
|
-
logCmuxEvent(
|
|
551
|
-
loadedPreferences,
|
|
552
|
-
`Auto-mode stopped${reasonSuffix || ""}.`,
|
|
553
|
-
reason?.startsWith("Blocked:") ? "warning" : "info",
|
|
554
|
-
);
|
|
555
|
-
|
|
556
546
|
if (isDebugEnabled()) {
|
|
557
547
|
const logPath = writeDebugSummary();
|
|
558
548
|
if (logPath) {
|
|
@@ -718,8 +708,6 @@ function buildLoopDeps(): LoopDeps {
|
|
|
718
708
|
pauseAuto,
|
|
719
709
|
clearUnitTimeout,
|
|
720
710
|
updateProgressWidget,
|
|
721
|
-
syncCmuxSidebar,
|
|
722
|
-
logCmuxEvent,
|
|
723
711
|
|
|
724
712
|
// State and cache
|
|
725
713
|
invalidateAllCaches,
|
|
@@ -902,7 +890,6 @@ export async function startAuto(
|
|
|
902
890
|
restoreHookState(s.basePath);
|
|
903
891
|
try {
|
|
904
892
|
await rebuildState(s.basePath);
|
|
905
|
-
syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
|
|
906
893
|
} catch (e) {
|
|
907
894
|
debugLog("resume-rebuild-state-failed", {
|
|
908
895
|
error: e instanceof Error ? e.message : String(e),
|
|
@@ -954,7 +941,6 @@ export async function startAuto(
|
|
|
954
941
|
s.currentMilestoneId ?? "unknown",
|
|
955
942
|
s.completedUnits.length,
|
|
956
943
|
);
|
|
957
|
-
logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
|
|
958
944
|
|
|
959
945
|
await autoLoop(ctx, pi, s, buildLoopDeps());
|
|
960
946
|
return;
|
|
@@ -979,13 +965,6 @@ export async function startAuto(
|
|
|
979
965
|
);
|
|
980
966
|
if (!ready) return;
|
|
981
967
|
|
|
982
|
-
try {
|
|
983
|
-
syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
|
|
984
|
-
} catch {
|
|
985
|
-
// Best-effort only — sidebar sync must never block auto-mode startup
|
|
986
|
-
}
|
|
987
|
-
logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
|
|
988
|
-
|
|
989
968
|
// Dispatch the first unit
|
|
990
969
|
await autoLoop(ctx, pi, s, buildLoopDeps());
|
|
991
970
|
}
|
|
@@ -740,7 +740,7 @@ export function serializePreferencesToFrontmatter(prefs: Record<string, unknown>
|
|
|
740
740
|
"skill_rules", "custom_instructions", "models", "skill_discovery",
|
|
741
741
|
"skill_staleness_days", "auto_supervisor", "uat_dispatch", "unique_milestone_ids",
|
|
742
742
|
"budget_ceiling", "budget_enforcement", "context_pause_threshold",
|
|
743
|
-
"notifications", "
|
|
743
|
+
"notifications", "remote_questions", "git",
|
|
744
744
|
"post_unit_hooks", "pre_dispatch_hooks",
|
|
745
745
|
"dynamic_routing", "token_profile", "phases", "parallel",
|
|
746
746
|
"auto_visualize", "auto_report",
|
|
@@ -49,7 +49,6 @@ import { runEnvironmentChecks } from "./doctor-environment.js";
|
|
|
49
49
|
import { handleLogs } from "./commands-logs.js";
|
|
50
50
|
import { handleStart, handleTemplates, getTemplateCompletions } from "./commands-workflow-templates.js";
|
|
51
51
|
import { readSessionLockData, isSessionLockProcessAlive } from "./session-lock.js";
|
|
52
|
-
import { handleCmux } from "./commands-cmux.js";
|
|
53
52
|
|
|
54
53
|
|
|
55
54
|
/** Resolve the effective project root, accounting for worktree paths. */
|
|
@@ -106,7 +105,7 @@ function notifyRemoteAutoActive(ctx: ExtensionCommandContext, basePath: string):
|
|
|
106
105
|
|
|
107
106
|
export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
108
107
|
pi.registerCommand("gsd", {
|
|
109
|
-
description: "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|visualize|queue|quick|capture|triage|dispatch|history|undo|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|
|
|
108
|
+
description: "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|visualize|queue|quick|capture|triage|dispatch|history|undo|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|update",
|
|
110
109
|
getArgumentCompletions: (prefix: string) => {
|
|
111
110
|
const subcommands = [
|
|
112
111
|
{ cmd: "help", desc: "Categorized command reference with descriptions" },
|
|
@@ -115,7 +114,6 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
|
115
114
|
{ cmd: "stop", desc: "Stop auto mode gracefully" },
|
|
116
115
|
{ cmd: "pause", desc: "Pause auto-mode (preserves state, /gsd auto to resume)" },
|
|
117
116
|
{ cmd: "status", desc: "Progress dashboard" },
|
|
118
|
-
{ cmd: "widget", desc: "Cycle widget: full → small → min → off" },
|
|
119
117
|
{ cmd: "visualize", desc: "Open 10-tab workflow visualizer (progress, timeline, deps, metrics, health, agent, changes, knowledge, captures, export)" },
|
|
120
118
|
{ cmd: "queue", desc: "Queue and reorder future milestones" },
|
|
121
119
|
{ cmd: "quick", desc: "Execute a quick task without full planning overhead" },
|
|
@@ -149,7 +147,6 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
|
149
147
|
{ cmd: "knowledge", desc: "Add persistent project knowledge (rule, pattern, or lesson)" },
|
|
150
148
|
{ cmd: "new-milestone", desc: "Create a milestone from a specification document (headless)" },
|
|
151
149
|
{ cmd: "parallel", desc: "Parallel milestone orchestration (start, status, stop, merge)" },
|
|
152
|
-
{ cmd: "cmux", desc: "Manage cmux integration (status, sidebar, notifications, splits)" },
|
|
153
150
|
{ cmd: "park", desc: "Park a milestone — skip without deleting" },
|
|
154
151
|
{ cmd: "unpark", desc: "Reactivate a parked milestone" },
|
|
155
152
|
{ cmd: "update", desc: "Update GSD to the latest version" },
|
|
@@ -206,38 +203,6 @@ export function registerGSDCommand(pi: ExtensionAPI): void {
|
|
|
206
203
|
.map((s) => ({ value: `parallel ${s.cmd}`, label: s.cmd, description: s.desc }));
|
|
207
204
|
}
|
|
208
205
|
|
|
209
|
-
if (parts[0] === "cmux") {
|
|
210
|
-
if (parts.length <= 2) {
|
|
211
|
-
const subPrefix = parts[1] ?? "";
|
|
212
|
-
const subs = [
|
|
213
|
-
{ cmd: "status", desc: "Show cmux detection, prefs, and capabilities" },
|
|
214
|
-
{ cmd: "on", desc: "Enable cmux integration" },
|
|
215
|
-
{ cmd: "off", desc: "Disable cmux integration" },
|
|
216
|
-
{ cmd: "notifications", desc: "Toggle cmux desktop notifications" },
|
|
217
|
-
{ cmd: "sidebar", desc: "Toggle cmux sidebar metadata" },
|
|
218
|
-
{ cmd: "splits", desc: "Toggle cmux visual subagent splits" },
|
|
219
|
-
{ cmd: "browser", desc: "Toggle future browser integration flag" },
|
|
220
|
-
];
|
|
221
|
-
return subs
|
|
222
|
-
.filter((s) => s.cmd.startsWith(subPrefix))
|
|
223
|
-
.map((s) => ({ value: `cmux ${s.cmd}`, label: s.cmd, description: s.desc }));
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
if (parts.length <= 3 && ["notifications", "sidebar", "splits", "browser"].includes(parts[1])) {
|
|
227
|
-
const togglePrefix = parts[2] ?? "";
|
|
228
|
-
return [
|
|
229
|
-
{ cmd: "on", desc: "Enable this cmux area" },
|
|
230
|
-
{ cmd: "off", desc: "Disable this cmux area" },
|
|
231
|
-
]
|
|
232
|
-
.filter((item) => item.cmd.startsWith(togglePrefix))
|
|
233
|
-
.map((item) => ({
|
|
234
|
-
value: `cmux ${parts[1]} ${item.cmd}`,
|
|
235
|
-
label: item.cmd,
|
|
236
|
-
description: item.desc,
|
|
237
|
-
}));
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
206
|
if (parts[0] === "setup" && parts.length <= 2) {
|
|
242
207
|
const subPrefix = parts[1] ?? "";
|
|
243
208
|
const subs = [
|
|
@@ -509,18 +474,6 @@ export async function handleGSDCommand(
|
|
|
509
474
|
return;
|
|
510
475
|
}
|
|
511
476
|
|
|
512
|
-
if (trimmed === "widget" || trimmed.startsWith("widget ")) {
|
|
513
|
-
const { cycleWidgetMode, setWidgetMode, getWidgetMode } = await import("./auto-dashboard.js");
|
|
514
|
-
const arg = trimmed.replace(/^widget\s*/, "").trim();
|
|
515
|
-
if (arg === "full" || arg === "small" || arg === "min" || arg === "off") {
|
|
516
|
-
setWidgetMode(arg);
|
|
517
|
-
} else {
|
|
518
|
-
cycleWidgetMode();
|
|
519
|
-
}
|
|
520
|
-
ctx.ui.notify(`Widget: ${getWidgetMode()}`, "info");
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
477
|
if (trimmed === "visualize") {
|
|
525
478
|
await handleVisualize(ctx);
|
|
526
479
|
return;
|
|
@@ -540,11 +493,6 @@ export async function handleGSDCommand(
|
|
|
540
493
|
return;
|
|
541
494
|
}
|
|
542
495
|
|
|
543
|
-
if (trimmed === "cmux" || trimmed.startsWith("cmux ")) {
|
|
544
|
-
await handleCmux(trimmed.replace(/^cmux\s*/, "").trim(), ctx);
|
|
545
|
-
return;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
496
|
if (trimmed === "init") {
|
|
549
497
|
const { detectProjectState } = await import("./detection.js");
|
|
550
498
|
const { showProjectInit, handleReinit } = await import("./init-wizard.js");
|
|
@@ -1048,7 +996,6 @@ function showHelp(ctx: ExtensionCommandContext): void {
|
|
|
1048
996
|
" /gsd setup Global setup status [llm|search|remote|keys|prefs]",
|
|
1049
997
|
" /gsd mode Set workflow mode (solo/team) [global|project]",
|
|
1050
998
|
" /gsd prefs Manage preferences [global|project|status|wizard|setup|import-claude]",
|
|
1051
|
-
" /gsd cmux Manage cmux integration [status|on|off|notifications|sidebar|splits|browser]",
|
|
1052
999
|
" /gsd config Set API keys for external tools",
|
|
1053
1000
|
" /gsd keys API key manager [list|add|remove|test|rotate|doctor]",
|
|
1054
1001
|
" /gsd hooks Show post-unit hook configuration",
|
|
@@ -173,13 +173,6 @@ Setting `prefer_skills: []` does **not** disable skill discovery — it just mea
|
|
|
173
173
|
- `on_milestone`: boolean — notify when a milestone finishes. Default: `true`.
|
|
174
174
|
- `on_attention`: boolean — notify when manual attention is needed. Default: `true`.
|
|
175
175
|
|
|
176
|
-
- `cmux`: configures cmux terminal integration when GSD is running inside a cmux workspace. Keys:
|
|
177
|
-
- `enabled`: boolean — master toggle for cmux integration. Default: `false`.
|
|
178
|
-
- `notifications`: boolean — route desktop notifications through cmux. Default: `true` when enabled.
|
|
179
|
-
- `sidebar`: boolean — publish status, progress, and log metadata to the cmux sidebar. Default: `true` when enabled.
|
|
180
|
-
- `splits`: boolean — run supported subagent work in visible cmux splits. Default: `false`.
|
|
181
|
-
- `browser`: boolean — reserve the future browser integration flag. Default: `false`.
|
|
182
|
-
|
|
183
176
|
- `dynamic_routing`: configures the dynamic model router that adjusts model selection based on task complexity. Keys:
|
|
184
177
|
- `enabled`: boolean — enable dynamic routing. Default: `false`.
|
|
185
178
|
- `tier_models`: object — model overrides per complexity tier. Keys: `light`, `standard`, `heavy`. Values are model ID strings.
|
|
@@ -484,24 +477,6 @@ Disables per-unit completion notifications (noisy in long runs) while keeping er
|
|
|
484
477
|
|
|
485
478
|
---
|
|
486
479
|
|
|
487
|
-
## cmux Example
|
|
488
|
-
|
|
489
|
-
```yaml
|
|
490
|
-
---
|
|
491
|
-
version: 1
|
|
492
|
-
cmux:
|
|
493
|
-
enabled: true
|
|
494
|
-
notifications: true
|
|
495
|
-
sidebar: true
|
|
496
|
-
splits: true
|
|
497
|
-
browser: false
|
|
498
|
-
---
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
Enables cmux-aware notifications, sidebar metadata, and visible subagent splits when GSD is running inside a cmux terminal.
|
|
502
|
-
|
|
503
|
-
---
|
|
504
|
-
|
|
505
480
|
## Post-Unit Hooks Example
|
|
506
481
|
|
|
507
482
|
```yaml
|
|
@@ -65,7 +65,6 @@ import { pauseAutoForProviderError, classifyProviderError } from "./provider-err
|
|
|
65
65
|
import { toPosixPath } from "../shared/mod.js";
|
|
66
66
|
import { isParallelActive, shutdownParallel } from "./parallel-orchestrator.js";
|
|
67
67
|
import { DEFAULT_BASH_TIMEOUT_SECS } from "./constants.js";
|
|
68
|
-
import { markCmuxPromptShown, shouldPromptToEnableCmux } from "../cmux/index.js";
|
|
69
68
|
|
|
70
69
|
// ── Agent Instructions (DEPRECATED) ──────────────────────────────────────
|
|
71
70
|
// agent-instructions.md is deprecated. Use AGENTS.md or CLAUDE.md instead.
|
|
@@ -624,13 +623,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
624
623
|
const stopContextTimer = debugTime("context-inject");
|
|
625
624
|
const systemContent = loadPrompt("system");
|
|
626
625
|
const loadedPreferences = loadEffectiveGSDPreferences();
|
|
627
|
-
if (shouldPromptToEnableCmux(loadedPreferences?.preferences)) {
|
|
628
|
-
markCmuxPromptShown();
|
|
629
|
-
ctx.ui.notify(
|
|
630
|
-
"cmux detected. Run /gsd cmux on to enable sidebar metadata, notifications, and visual subagent splits for this project.",
|
|
631
|
-
"info",
|
|
632
|
-
);
|
|
633
|
-
}
|
|
634
626
|
let preferenceBlock = "";
|
|
635
627
|
if (loadedPreferences) {
|
|
636
628
|
const cwd = process.cwd();
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import { execFileSync } from "node:child_process";
|
|
5
5
|
import type { NotificationPreferences } from "./types.js";
|
|
6
6
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
7
|
-
import { CmuxClient, emitOsc777Notification, resolveCmuxConfig } from "../cmux/index.js";
|
|
8
7
|
|
|
9
8
|
export type NotifyLevel = "info" | "success" | "warning" | "error";
|
|
10
9
|
export type NotificationKind = "complete" | "error" | "budget" | "milestone" | "attention";
|
|
@@ -24,15 +23,7 @@ export function sendDesktopNotification(
|
|
|
24
23
|
level: NotifyLevel = "info",
|
|
25
24
|
kind: NotificationKind = "complete",
|
|
26
25
|
): void {
|
|
27
|
-
|
|
28
|
-
if (!shouldSendDesktopNotification(kind, loaded?.notifications)) return;
|
|
29
|
-
|
|
30
|
-
const cmux = resolveCmuxConfig(loaded);
|
|
31
|
-
if (cmux.notifications) {
|
|
32
|
-
const delivered = CmuxClient.fromPreferences(loaded).notify(title, message);
|
|
33
|
-
if (delivered) return;
|
|
34
|
-
emitOsc777Notification(title, message);
|
|
35
|
-
}
|
|
26
|
+
if (!shouldSendDesktopNotification(kind)) return;
|
|
36
27
|
|
|
37
28
|
try {
|
|
38
29
|
const command = buildDesktopNotificationCommand(process.platform, title, message, level);
|
|
@@ -68,7 +68,6 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
68
68
|
"budget_enforcement",
|
|
69
69
|
"context_pause_threshold",
|
|
70
70
|
"notifications",
|
|
71
|
-
"cmux",
|
|
72
71
|
"remote_questions",
|
|
73
72
|
"git",
|
|
74
73
|
"post_unit_hooks",
|
|
@@ -85,7 +84,6 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
85
84
|
"search_provider",
|
|
86
85
|
"compression_strategy",
|
|
87
86
|
"context_selection",
|
|
88
|
-
"widget_mode",
|
|
89
87
|
]);
|
|
90
88
|
|
|
91
89
|
/** Canonical list of all dispatch unit types. */
|
|
@@ -166,14 +164,6 @@ export interface RemoteQuestionsConfig {
|
|
|
166
164
|
poll_interval_seconds?: number; // clamped to 2-30
|
|
167
165
|
}
|
|
168
166
|
|
|
169
|
-
export interface CmuxPreferences {
|
|
170
|
-
enabled?: boolean;
|
|
171
|
-
notifications?: boolean;
|
|
172
|
-
sidebar?: boolean;
|
|
173
|
-
splits?: boolean;
|
|
174
|
-
browser?: boolean;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
167
|
export interface GSDPreferences {
|
|
178
168
|
version?: number;
|
|
179
169
|
mode?: WorkflowMode;
|
|
@@ -192,7 +182,6 @@ export interface GSDPreferences {
|
|
|
192
182
|
budget_enforcement?: BudgetEnforcementMode;
|
|
193
183
|
context_pause_threshold?: number;
|
|
194
184
|
notifications?: NotificationPreferences;
|
|
195
|
-
cmux?: CmuxPreferences;
|
|
196
185
|
remote_questions?: RemoteQuestionsConfig;
|
|
197
186
|
git?: GitPreferences;
|
|
198
187
|
post_unit_hooks?: PostUnitHookConfig[];
|
|
@@ -213,8 +202,6 @@ export interface GSDPreferences {
|
|
|
213
202
|
compression_strategy?: CompressionStrategy;
|
|
214
203
|
/** Context selection mode for file inlining. "full" inlines entire files, "smart" uses semantic chunking. Default derived from token profile. */
|
|
215
204
|
context_selection?: ContextSelectionMode;
|
|
216
|
-
/** Default widget display mode for auto-mode dashboard. "full" | "small" | "min" | "off". Default: "full". */
|
|
217
|
-
widget_mode?: "full" | "small" | "min" | "off";
|
|
218
205
|
}
|
|
219
206
|
|
|
220
207
|
export interface LoadedGSDPreferences {
|
|
@@ -242,32 +242,6 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
// ─── Cmux ───────────────────────────────────────────────────────────────
|
|
246
|
-
if (preferences.cmux !== undefined) {
|
|
247
|
-
if (preferences.cmux && typeof preferences.cmux === "object") {
|
|
248
|
-
const cmux = preferences.cmux as Record<string, unknown>;
|
|
249
|
-
const validatedCmux: NonNullable<GSDPreferences["cmux"]> = {};
|
|
250
|
-
if (cmux.enabled !== undefined) validatedCmux.enabled = !!cmux.enabled;
|
|
251
|
-
if (cmux.notifications !== undefined) validatedCmux.notifications = !!cmux.notifications;
|
|
252
|
-
if (cmux.sidebar !== undefined) validatedCmux.sidebar = !!cmux.sidebar;
|
|
253
|
-
if (cmux.splits !== undefined) validatedCmux.splits = !!cmux.splits;
|
|
254
|
-
if (cmux.browser !== undefined) validatedCmux.browser = !!cmux.browser;
|
|
255
|
-
|
|
256
|
-
const knownCmuxKeys = new Set(["enabled", "notifications", "sidebar", "splits", "browser"]);
|
|
257
|
-
for (const key of Object.keys(cmux)) {
|
|
258
|
-
if (!knownCmuxKeys.has(key)) {
|
|
259
|
-
warnings.push(`unknown cmux key "${key}" — ignored`);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (Object.keys(validatedCmux).length > 0) {
|
|
264
|
-
validated.cmux = validatedCmux;
|
|
265
|
-
}
|
|
266
|
-
} else {
|
|
267
|
-
errors.push("cmux must be an object");
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
245
|
// ─── Remote Questions ───────────────────────────────────────────────
|
|
272
246
|
if (preferences.remote_questions !== undefined) {
|
|
273
247
|
if (preferences.remote_questions && typeof preferences.remote_questions === "object") {
|
|
@@ -45,7 +45,6 @@ export type {
|
|
|
45
45
|
SkillDiscoveryMode,
|
|
46
46
|
AutoSupervisorConfig,
|
|
47
47
|
RemoteQuestionsConfig,
|
|
48
|
-
CmuxPreferences,
|
|
49
48
|
GSDPreferences,
|
|
50
49
|
LoadedGSDPreferences,
|
|
51
50
|
SkillResolution,
|
|
@@ -242,9 +241,6 @@ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPr
|
|
|
242
241
|
notifications: (base.notifications || override.notifications)
|
|
243
242
|
? { ...(base.notifications ?? {}), ...(override.notifications ?? {}) }
|
|
244
243
|
: undefined,
|
|
245
|
-
cmux: (base.cmux || override.cmux)
|
|
246
|
-
? { ...(base.cmux ?? {}), ...(override.cmux ?? {}) }
|
|
247
|
-
: undefined,
|
|
248
244
|
remote_questions: override.remote_questions
|
|
249
245
|
? { ...(base.remote_questions ?? {}), ...override.remote_questions }
|
|
250
246
|
: base.remote_questions,
|
|
@@ -25,10 +25,9 @@ Then research the codebase and relevant technologies. Narrate key findings and s
|
|
|
25
25
|
2. **Skill Discovery ({{skillDiscoveryMode}}):**{{skillDiscoveryInstructions}}
|
|
26
26
|
3. Explore relevant code. For small/familiar codebases, use `rg`, `find`, and targeted reads. For large or unfamiliar codebases, use `scout` to build a broad map efficiently before diving in.
|
|
27
27
|
4. Use `resolve_library` / `get_library_docs` for unfamiliar libraries — skip this for libraries already used in the codebase
|
|
28
|
-
5.
|
|
29
|
-
6.
|
|
30
|
-
7.
|
|
31
|
-
8. Write `{{outputPath}}`
|
|
28
|
+
5. Use the **Research** output template from the inlined context above — include only sections that have real content
|
|
29
|
+
6. If `.gsd/REQUIREMENTS.md` exists, research against it. Identify which Active requirements are table stakes, likely omissions, overbuilt risks, or domain-standard behaviors the user may or may not want.
|
|
30
|
+
7. Write `{{outputPath}}`
|
|
32
31
|
|
|
33
32
|
## Strategic Questions to Answer
|
|
34
33
|
|
|
@@ -46,9 +46,8 @@ Research what this slice needs. Narrate key findings and surprises as you go —
|
|
|
46
46
|
2. **Skill Discovery ({{skillDiscoveryMode}}):**{{skillDiscoveryInstructions}}
|
|
47
47
|
3. Explore relevant code for this slice's scope. For targeted exploration, use `rg`, `find`, and reads. For broad or unfamiliar subsystems, use `scout` to map the relevant area first.
|
|
48
48
|
4. Use `resolve_library` / `get_library_docs` for unfamiliar libraries — skip this for libraries already used in the codebase
|
|
49
|
-
5.
|
|
50
|
-
6.
|
|
51
|
-
7. Write `{{outputPath}}`
|
|
49
|
+
5. Use the **Research** output template from the inlined context above — include only sections that have real content. The template is already inlined above; do NOT attempt to read any template file from disk (there is no `templates/SLICE-RESEARCH.md` — the correct template is already present in this prompt).
|
|
50
|
+
6. Write `{{outputPath}}`
|
|
52
51
|
|
|
53
52
|
The slice directory already exists at `{{slicePath}}/`. Do NOT mkdir — just write the file.
|
|
54
53
|
|
|
@@ -171,29 +171,6 @@ test("notification fields validate correctly", () => {
|
|
|
171
171
|
assert.equal(preferences.notifications?.on_complete, false);
|
|
172
172
|
});
|
|
173
173
|
|
|
174
|
-
test("cmux fields validate correctly", () => {
|
|
175
|
-
const { preferences, errors } = validatePreferences({
|
|
176
|
-
cmux: {
|
|
177
|
-
enabled: true,
|
|
178
|
-
notifications: true,
|
|
179
|
-
sidebar: false,
|
|
180
|
-
splits: true,
|
|
181
|
-
browser: false,
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
assert.equal(errors.length, 0);
|
|
185
|
-
assert.equal(preferences.cmux?.enabled, true);
|
|
186
|
-
assert.equal(preferences.cmux?.sidebar, false);
|
|
187
|
-
assert.equal(preferences.cmux?.splits, true);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
test("cmux unknown keys produce warnings", () => {
|
|
191
|
-
const { warnings } = validatePreferences({
|
|
192
|
-
cmux: { enabled: true, strange_mode: true } as any,
|
|
193
|
-
});
|
|
194
|
-
assert.ok(warnings.some((warning) => warning.includes('unknown cmux key "strange_mode"')));
|
|
195
|
-
});
|
|
196
|
-
|
|
197
174
|
test("git fields comprehensive validation", () => {
|
|
198
175
|
const { preferences, errors } = validatePreferences({
|
|
199
176
|
git: {
|