gsd-pi 2.31.2 → 2.32.0-dev.3d7932c
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 +27 -20
- package/dist/cli.js +5 -5
- package/dist/resource-loader.js +13 -3
- package/dist/resources/extensions/gsd/auto-constants.ts +6 -0
- package/dist/resources/extensions/gsd/auto-dashboard.ts +23 -27
- package/dist/resources/extensions/gsd/auto-direct-dispatch.ts +1 -6
- package/dist/resources/extensions/gsd/auto-dispatch.ts +4 -8
- package/dist/resources/extensions/gsd/auto-idempotency.ts +3 -2
- package/dist/resources/extensions/gsd/auto-observability.ts +2 -4
- package/dist/resources/extensions/gsd/auto-post-unit.ts +32 -37
- package/dist/resources/extensions/gsd/auto-prompts.ts +84 -78
- package/dist/resources/extensions/gsd/auto-recovery.ts +8 -22
- package/dist/resources/extensions/gsd/auto-start.ts +16 -12
- package/dist/resources/extensions/gsd/auto-stuck-detection.ts +3 -2
- package/dist/resources/extensions/gsd/auto-timeout-recovery.ts +2 -1
- package/dist/resources/extensions/gsd/auto-timers.ts +3 -2
- package/dist/resources/extensions/gsd/auto-verification.ts +6 -6
- package/dist/resources/extensions/gsd/auto-worktree.ts +5 -4
- package/dist/resources/extensions/gsd/auto.ts +82 -60
- package/dist/resources/extensions/gsd/commands-inspect.ts +2 -1
- package/dist/resources/extensions/gsd/commands-workflow-templates.ts +5 -6
- package/dist/resources/extensions/gsd/commands.ts +19 -0
- package/dist/resources/extensions/gsd/complexity-classifier.ts +5 -7
- package/dist/resources/extensions/gsd/crash-recovery.ts +15 -2
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +28 -0
- package/dist/resources/extensions/gsd/dispatch-guard.ts +2 -1
- package/dist/resources/extensions/gsd/doctor-environment.ts +497 -0
- package/dist/resources/extensions/gsd/doctor-providers.ts +343 -0
- package/dist/resources/extensions/gsd/doctor-types.ts +14 -1
- package/dist/resources/extensions/gsd/doctor.ts +6 -0
- package/dist/resources/extensions/gsd/error-utils.ts +6 -0
- package/dist/resources/extensions/gsd/export.ts +2 -1
- package/dist/resources/extensions/gsd/git-service.ts +12 -2
- package/dist/resources/extensions/gsd/guided-flow-queue.ts +1 -8
- package/dist/resources/extensions/gsd/guided-flow.ts +3 -2
- package/dist/resources/extensions/gsd/health-widget.ts +167 -0
- package/dist/resources/extensions/gsd/index.ts +18 -5
- package/dist/resources/extensions/gsd/key-manager.ts +2 -1
- package/dist/resources/extensions/gsd/marketplace-discovery.ts +4 -3
- package/dist/resources/extensions/gsd/metrics.ts +3 -3
- package/dist/resources/extensions/gsd/migrate-external.ts +21 -4
- package/dist/resources/extensions/gsd/milestone-ids.ts +2 -1
- package/dist/resources/extensions/gsd/native-git-bridge.ts +2 -1
- package/dist/resources/extensions/gsd/parallel-merge.ts +2 -1
- package/dist/resources/extensions/gsd/parallel-orchestrator.ts +2 -1
- package/dist/resources/extensions/gsd/post-unit-hooks.ts +8 -9
- package/dist/resources/extensions/gsd/preferences-types.ts +8 -0
- package/dist/resources/extensions/gsd/preferences-validation.ts +3 -10
- package/dist/resources/extensions/gsd/progress-score.ts +273 -0
- package/dist/resources/extensions/gsd/prompts/run-uat.md +1 -42
- package/dist/resources/extensions/gsd/quick.ts +61 -8
- package/dist/resources/extensions/gsd/repo-identity.ts +22 -1
- package/dist/resources/extensions/gsd/session-lock.ts +12 -1
- package/dist/resources/extensions/gsd/tests/auto-reentrancy-guard.test.ts +127 -0
- package/dist/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/doctor-environment.test.ts +314 -0
- package/dist/resources/extensions/gsd/tests/doctor-providers.test.ts +298 -0
- package/dist/resources/extensions/gsd/tests/export-html-enhancements.test.ts +3 -0
- package/dist/resources/extensions/gsd/tests/memory-leak-guards.test.ts +7 -3
- package/dist/resources/extensions/gsd/tests/progress-score.test.ts +206 -0
- package/dist/resources/extensions/gsd/tests/run-uat.test.ts +56 -7
- package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +12 -0
- package/dist/resources/extensions/gsd/undo.ts +5 -7
- package/dist/resources/extensions/gsd/unit-id.ts +14 -0
- package/dist/resources/extensions/gsd/unit-runtime.ts +2 -1
- package/dist/resources/extensions/gsd/visualizer-data.ts +60 -2
- package/dist/resources/extensions/gsd/visualizer-views.ts +54 -0
- package/dist/resources/extensions/gsd/worktree-command.ts +8 -7
- package/dist/worktree-cli.d.ts +42 -6
- package/dist/worktree-cli.js +88 -48
- package/package.json +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto-constants.ts +6 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +23 -27
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +1 -6
- package/src/resources/extensions/gsd/auto-dispatch.ts +4 -8
- package/src/resources/extensions/gsd/auto-idempotency.ts +3 -2
- package/src/resources/extensions/gsd/auto-observability.ts +2 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +32 -37
- package/src/resources/extensions/gsd/auto-prompts.ts +84 -78
- package/src/resources/extensions/gsd/auto-recovery.ts +8 -22
- package/src/resources/extensions/gsd/auto-start.ts +16 -12
- package/src/resources/extensions/gsd/auto-stuck-detection.ts +3 -2
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/auto-timers.ts +3 -2
- package/src/resources/extensions/gsd/auto-verification.ts +6 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +5 -4
- package/src/resources/extensions/gsd/auto.ts +82 -60
- package/src/resources/extensions/gsd/commands-inspect.ts +2 -1
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +5 -6
- package/src/resources/extensions/gsd/commands.ts +19 -0
- package/src/resources/extensions/gsd/complexity-classifier.ts +5 -7
- package/src/resources/extensions/gsd/crash-recovery.ts +15 -2
- package/src/resources/extensions/gsd/dashboard-overlay.ts +28 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
- package/src/resources/extensions/gsd/doctor-environment.ts +497 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +343 -0
- package/src/resources/extensions/gsd/doctor-types.ts +14 -1
- package/src/resources/extensions/gsd/doctor.ts +6 -0
- package/src/resources/extensions/gsd/error-utils.ts +6 -0
- package/src/resources/extensions/gsd/export.ts +2 -1
- package/src/resources/extensions/gsd/git-service.ts +12 -2
- package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -8
- package/src/resources/extensions/gsd/guided-flow.ts +3 -2
- package/src/resources/extensions/gsd/health-widget.ts +167 -0
- package/src/resources/extensions/gsd/index.ts +18 -5
- package/src/resources/extensions/gsd/key-manager.ts +2 -1
- package/src/resources/extensions/gsd/marketplace-discovery.ts +4 -3
- package/src/resources/extensions/gsd/metrics.ts +3 -3
- package/src/resources/extensions/gsd/migrate-external.ts +21 -4
- package/src/resources/extensions/gsd/milestone-ids.ts +2 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +2 -1
- package/src/resources/extensions/gsd/parallel-merge.ts +2 -1
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +2 -1
- package/src/resources/extensions/gsd/post-unit-hooks.ts +8 -9
- package/src/resources/extensions/gsd/preferences-types.ts +8 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +3 -10
- package/src/resources/extensions/gsd/progress-score.ts +273 -0
- package/src/resources/extensions/gsd/prompts/run-uat.md +1 -42
- package/src/resources/extensions/gsd/quick.ts +61 -8
- package/src/resources/extensions/gsd/repo-identity.ts +22 -1
- package/src/resources/extensions/gsd/session-lock.ts +12 -1
- package/src/resources/extensions/gsd/tests/auto-reentrancy-guard.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +314 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +298 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/memory-leak-guards.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/progress-score.test.ts +206 -0
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +56 -7
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +12 -0
- package/src/resources/extensions/gsd/undo.ts +5 -7
- package/src/resources/extensions/gsd/unit-id.ts +14 -0
- package/src/resources/extensions/gsd/unit-runtime.ts +2 -1
- package/src/resources/extensions/gsd/visualizer-data.ts +60 -2
- package/src/resources/extensions/gsd/visualizer-views.ts +54 -0
- package/src/resources/extensions/gsd/worktree-command.ts +8 -7
|
@@ -9,6 +9,7 @@ import { deriveState } from "./state.js";
|
|
|
9
9
|
import { invalidateAllCaches } from "./cache.js";
|
|
10
10
|
import { gsdRoot, resolveTasksDir, resolveSlicePath, buildTaskFileName } from "./paths.js";
|
|
11
11
|
import { sendDesktopNotification } from "./notifications.js";
|
|
12
|
+
import { parseUnitId } from "./unit-id.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Undo the last completed unit: revert git commits, remove from completed-units,
|
|
@@ -62,11 +63,10 @@ export async function handleUndo(args: string, ctx: ExtensionCommandContext, _pi
|
|
|
62
63
|
writeFileSync(completedKeysFile, JSON.stringify(keys), "utf-8");
|
|
63
64
|
|
|
64
65
|
// 3. Delete summary artifact
|
|
65
|
-
const
|
|
66
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
66
67
|
let summaryRemoved = false;
|
|
67
|
-
if (
|
|
68
|
+
if (mid && sid && tid) {
|
|
68
69
|
// Task-level: M001/S01/T01
|
|
69
|
-
const [mid, sid, tid] = parts;
|
|
70
70
|
const tasksDir = resolveTasksDir(basePath, mid, sid);
|
|
71
71
|
if (tasksDir) {
|
|
72
72
|
const summaryFile = join(tasksDir, buildTaskFileName(tid, "SUMMARY"));
|
|
@@ -75,9 +75,8 @@ export async function handleUndo(args: string, ctx: ExtensionCommandContext, _pi
|
|
|
75
75
|
summaryRemoved = true;
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
} else if (
|
|
78
|
+
} else if (mid && sid) {
|
|
79
79
|
// Slice-level: M001/S01
|
|
80
|
-
const [mid, sid] = parts;
|
|
81
80
|
const slicePath = resolveSlicePath(basePath, mid, sid);
|
|
82
81
|
if (slicePath) {
|
|
83
82
|
// Try common summary filenames
|
|
@@ -93,8 +92,7 @@ export async function handleUndo(args: string, ctx: ExtensionCommandContext, _pi
|
|
|
93
92
|
|
|
94
93
|
// 4. Uncheck task in PLAN if execute-task
|
|
95
94
|
let planUpdated = false;
|
|
96
|
-
if (unitType === "execute-task" &&
|
|
97
|
-
const [mid, sid, tid] = parts;
|
|
95
|
+
if (unitType === "execute-task" && mid && sid && tid) {
|
|
98
96
|
planUpdated = uncheckTaskInPlan(basePath, mid, sid, tid);
|
|
99
97
|
}
|
|
100
98
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// GSD Extension — Unit ID Parsing
|
|
2
|
+
// Centralizes the milestone/slice/task decomposition of unit ID strings.
|
|
3
|
+
|
|
4
|
+
export interface ParsedUnitId {
|
|
5
|
+
milestone: string;
|
|
6
|
+
slice?: string;
|
|
7
|
+
task?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Parse a unit ID string (e.g. "M1/S1/T1") into its milestone, slice, and task components. */
|
|
11
|
+
export function parseUnitId(unitId: string): ParsedUnitId {
|
|
12
|
+
const [milestone, slice, task] = unitId.split("/");
|
|
13
|
+
return { milestone: milestone!, slice, task };
|
|
14
|
+
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "./paths.js";
|
|
10
10
|
import { loadFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
|
|
11
11
|
import { loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
|
|
12
|
+
import { parseUnitId } from "./unit-id.js";
|
|
12
13
|
|
|
13
14
|
export type UnitRuntimePhase =
|
|
14
15
|
| "dispatched"
|
|
@@ -131,7 +132,7 @@ export async function inspectExecuteTaskDurability(
|
|
|
131
132
|
basePath: string,
|
|
132
133
|
unitId: string,
|
|
133
134
|
): Promise<ExecuteTaskRecoveryStatus | null> {
|
|
134
|
-
const
|
|
135
|
+
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
135
136
|
if (!mid || !sid || !tid) return null;
|
|
136
137
|
|
|
137
138
|
const planAbs = resolveSliceFile(basePath, mid, sid, "PLAN");
|
|
@@ -18,6 +18,9 @@ import {
|
|
|
18
18
|
} from './metrics.js';
|
|
19
19
|
import { loadAllCaptures, countPendingCaptures } from './captures.js';
|
|
20
20
|
import { loadEffectiveGSDPreferences } from './preferences.js';
|
|
21
|
+
import { runProviderChecks, type ProviderCheckResult } from './doctor-providers.js';
|
|
22
|
+
import { generateSkillHealthReport } from './skill-health.js';
|
|
23
|
+
import { runEnvironmentChecks, type EnvironmentCheckResult } from './doctor-environment.js';
|
|
21
24
|
|
|
22
25
|
import type { Phase } from './types.js';
|
|
23
26
|
import type { CaptureEntry } from './captures.js';
|
|
@@ -142,6 +145,22 @@ export interface CapturesInfo {
|
|
|
142
145
|
totalCount: number;
|
|
143
146
|
}
|
|
144
147
|
|
|
148
|
+
export interface ProviderStatusSummary {
|
|
149
|
+
name: string;
|
|
150
|
+
label: string;
|
|
151
|
+
category: string;
|
|
152
|
+
ok: boolean;
|
|
153
|
+
required: boolean;
|
|
154
|
+
message: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface SkillSummaryInfo {
|
|
158
|
+
total: number;
|
|
159
|
+
warningCount: number;
|
|
160
|
+
criticalCount: number;
|
|
161
|
+
topIssue: string | null;
|
|
162
|
+
}
|
|
163
|
+
|
|
145
164
|
export interface HealthInfo {
|
|
146
165
|
budgetCeiling: number | undefined;
|
|
147
166
|
tokenProfile: string;
|
|
@@ -152,6 +171,9 @@ export interface HealthInfo {
|
|
|
152
171
|
toolCalls: number;
|
|
153
172
|
assistantMessages: number;
|
|
154
173
|
userMessages: number;
|
|
174
|
+
providers: ProviderStatusSummary[];
|
|
175
|
+
skillSummary: SkillSummaryInfo;
|
|
176
|
+
environmentIssues: import("./doctor-environment.js").EnvironmentCheckResult[];
|
|
155
177
|
}
|
|
156
178
|
|
|
157
179
|
export interface VisualizerData {
|
|
@@ -538,7 +560,7 @@ function loadKnowledge(basePath: string): KnowledgeInfo {
|
|
|
538
560
|
|
|
539
561
|
// ─── Health Loader ────────────────────────────────────────────────────────────
|
|
540
562
|
|
|
541
|
-
function loadHealth(units: UnitMetrics[], totals: ProjectTotals | null): HealthInfo {
|
|
563
|
+
function loadHealth(units: UnitMetrics[], totals: ProjectTotals | null, basePath: string): HealthInfo {
|
|
542
564
|
const prefs = loadEffectiveGSDPreferences();
|
|
543
565
|
const budgetCeiling = prefs?.preferences?.budget_ceiling;
|
|
544
566
|
const tokenProfile = prefs?.preferences?.token_profile ?? 'standard';
|
|
@@ -553,6 +575,39 @@ function loadHealth(units: UnitMetrics[], totals: ProjectTotals | null): HealthI
|
|
|
553
575
|
const tierBreakdown = aggregateByTier(units);
|
|
554
576
|
const tierSavingsLine = formatTierSavings(units);
|
|
555
577
|
|
|
578
|
+
// Provider checks — fast (auth.json + env vars only, no network)
|
|
579
|
+
let providers: ProviderStatusSummary[] = [];
|
|
580
|
+
try {
|
|
581
|
+
providers = runProviderChecks().map((r: ProviderCheckResult) => ({
|
|
582
|
+
name: r.name,
|
|
583
|
+
label: r.label,
|
|
584
|
+
category: r.category,
|
|
585
|
+
ok: r.status === "ok" || r.status === "unconfigured",
|
|
586
|
+
required: r.required,
|
|
587
|
+
message: r.message,
|
|
588
|
+
}));
|
|
589
|
+
} catch { /* non-fatal */ }
|
|
590
|
+
|
|
591
|
+
// Skill health summary
|
|
592
|
+
let skillSummary: SkillSummaryInfo = { total: 0, warningCount: 0, criticalCount: 0, topIssue: null };
|
|
593
|
+
try {
|
|
594
|
+
const report = generateSkillHealthReport(basePath);
|
|
595
|
+
const warnings = report.suggestions.filter(s => s.severity === "warning");
|
|
596
|
+
const criticals = report.suggestions.filter(s => s.severity === "critical");
|
|
597
|
+
skillSummary = {
|
|
598
|
+
total: report.skills.length,
|
|
599
|
+
warningCount: warnings.length,
|
|
600
|
+
criticalCount: criticals.length,
|
|
601
|
+
topIssue: report.suggestions[0]?.message ?? null,
|
|
602
|
+
};
|
|
603
|
+
} catch { /* non-fatal */ }
|
|
604
|
+
|
|
605
|
+
// Environment issues (from doctor-environment.ts, #1221)
|
|
606
|
+
let environmentIssues: EnvironmentCheckResult[] = [];
|
|
607
|
+
try {
|
|
608
|
+
environmentIssues = runEnvironmentChecks(basePath).filter(r => r.status !== "ok");
|
|
609
|
+
} catch { /* non-fatal */ }
|
|
610
|
+
|
|
556
611
|
return {
|
|
557
612
|
budgetCeiling,
|
|
558
613
|
tokenProfile,
|
|
@@ -563,6 +618,9 @@ function loadHealth(units: UnitMetrics[], totals: ProjectTotals | null): HealthI
|
|
|
563
618
|
toolCalls: totals?.toolCalls ?? 0,
|
|
564
619
|
assistantMessages: totals?.assistantMessages ?? 0,
|
|
565
620
|
userMessages: totals?.userMessages ?? 0,
|
|
621
|
+
providers,
|
|
622
|
+
skillSummary,
|
|
623
|
+
environmentIssues,
|
|
566
624
|
};
|
|
567
625
|
}
|
|
568
626
|
|
|
@@ -780,7 +838,7 @@ export async function loadVisualizerData(basePath: string): Promise<VisualizerDa
|
|
|
780
838
|
totalCount: allCaptures.length,
|
|
781
839
|
};
|
|
782
840
|
|
|
783
|
-
const health = loadHealth(units, totals);
|
|
841
|
+
const health = loadHealth(units, totals, basePath);
|
|
784
842
|
const stats = buildVisualizerStats(milestones, changelog.entries);
|
|
785
843
|
const discussion = loadDiscussionState(basePath, milestones);
|
|
786
844
|
|
|
@@ -1113,5 +1113,59 @@ export function renderHealthView(
|
|
|
1113
1113
|
lines.push(` Tool calls: ${th.fg("text", String(health.toolCalls))}`);
|
|
1114
1114
|
lines.push(` Messages: ${th.fg("text", String(health.assistantMessages))} sent / ${th.fg("text", String(health.userMessages))} received`);
|
|
1115
1115
|
|
|
1116
|
+
// Environment section — issues only (from doctor-environment.ts, #1221)
|
|
1117
|
+
if (health.environmentIssues?.length > 0) {
|
|
1118
|
+
lines.push("");
|
|
1119
|
+
lines.push(th.fg("accent", th.bold("Environment")));
|
|
1120
|
+
lines.push("");
|
|
1121
|
+
for (const r of health.environmentIssues) {
|
|
1122
|
+
const icon = r.status === "error" ? th.fg("error", "✗") : th.fg("warning", "⚠");
|
|
1123
|
+
lines.push(` ${icon} ${th.fg("text", r.message)}`);
|
|
1124
|
+
if (r.detail) lines.push(` ${th.fg("dim", r.detail)}`);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
// Providers section
|
|
1129
|
+
if (health.providers?.length > 0) {
|
|
1130
|
+
lines.push("");
|
|
1131
|
+
lines.push(th.fg("accent", th.bold("Providers")));
|
|
1132
|
+
lines.push("");
|
|
1133
|
+
const categoryOrder = ["llm", "remote", "search", "tool"];
|
|
1134
|
+
const categoryLabels: Record<string, string> = { llm: "LLM", remote: "Notifications", search: "Search", tool: "Tools" };
|
|
1135
|
+
const grouped = new Map<string, typeof health.providers>();
|
|
1136
|
+
for (const p of health.providers) {
|
|
1137
|
+
const cat = p.category;
|
|
1138
|
+
if (!grouped.has(cat)) grouped.set(cat, []);
|
|
1139
|
+
grouped.get(cat)!.push(p);
|
|
1140
|
+
}
|
|
1141
|
+
for (const cat of categoryOrder) {
|
|
1142
|
+
const items = grouped.get(cat);
|
|
1143
|
+
if (!items || items.length === 0) continue;
|
|
1144
|
+
lines.push(` ${th.fg("dim", categoryLabels[cat] ?? cat)}`);
|
|
1145
|
+
for (const p of items) {
|
|
1146
|
+
const icon = p.ok ? th.fg("success", "✓") : th.fg("error", "✗");
|
|
1147
|
+
const msg = p.ok ? th.fg("dim", p.message) : th.fg("text", p.message);
|
|
1148
|
+
lines.push(` ${icon} ${msg}`);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// Skills section
|
|
1154
|
+
if (health.skillSummary?.total > 0) {
|
|
1155
|
+
lines.push("");
|
|
1156
|
+
lines.push(th.fg("accent", th.bold("Skills")));
|
|
1157
|
+
lines.push("");
|
|
1158
|
+
const { total, warningCount, criticalCount, topIssue } = health.skillSummary;
|
|
1159
|
+
const issueColor = criticalCount > 0 ? "error" : warningCount > 0 ? "warning" : "success";
|
|
1160
|
+
const issueTag = criticalCount > 0
|
|
1161
|
+
? `${criticalCount} critical`
|
|
1162
|
+
: warningCount > 0
|
|
1163
|
+
? `${warningCount} warning${warningCount > 1 ? "s" : ""}`
|
|
1164
|
+
: "all healthy";
|
|
1165
|
+
lines.push(` ${th.fg("text", String(total))} skills tracked · ${th.fg(issueColor, issueTag)}`);
|
|
1166
|
+
if (topIssue) lines.push(` ${th.fg("warning", "⚠")} ${th.fg("dim", topIssue)}`);
|
|
1167
|
+
lines.push(` ${th.fg("dim", "→ /gsd skill-health for full report")}`);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1116
1170
|
return lines;
|
|
1117
1171
|
}
|
|
@@ -34,6 +34,7 @@ import type { FileLineStat } from "./worktree-manager.js";
|
|
|
34
34
|
import { existsSync, realpathSync, readdirSync, rmSync, unlinkSync } from "node:fs";
|
|
35
35
|
import { nativeMergeAbort } from "./native-git-bridge.js";
|
|
36
36
|
import { join, sep } from "node:path";
|
|
37
|
+
import { getErrorMessage } from "./error-utils.js";
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Tracks the original project root so we can switch back.
|
|
@@ -370,7 +371,7 @@ async function handleCreate(
|
|
|
370
371
|
"info",
|
|
371
372
|
);
|
|
372
373
|
} catch (error) {
|
|
373
|
-
const msg =
|
|
374
|
+
const msg = getErrorMessage(error);
|
|
374
375
|
ctx.ui.notify(`Failed to create worktree: ${msg}`, "error");
|
|
375
376
|
}
|
|
376
377
|
}
|
|
@@ -418,7 +419,7 @@ async function handleSwitch(
|
|
|
418
419
|
"info",
|
|
419
420
|
);
|
|
420
421
|
} catch (error) {
|
|
421
|
-
const msg =
|
|
422
|
+
const msg = getErrorMessage(error);
|
|
422
423
|
ctx.ui.notify(`Failed to switch to worktree: ${msg}`, "error");
|
|
423
424
|
}
|
|
424
425
|
}
|
|
@@ -528,7 +529,7 @@ async function handleList(
|
|
|
528
529
|
|
|
529
530
|
ctx.ui.notify(lines.join("\n"), "info");
|
|
530
531
|
} catch (error) {
|
|
531
|
-
const msg =
|
|
532
|
+
const msg = getErrorMessage(error);
|
|
532
533
|
ctx.ui.notify(`Failed to list worktrees: ${msg}`, "error");
|
|
533
534
|
}
|
|
534
535
|
}
|
|
@@ -646,7 +647,7 @@ async function handleMerge(
|
|
|
646
647
|
);
|
|
647
648
|
return;
|
|
648
649
|
} catch (mergeErr) {
|
|
649
|
-
const mergeMsg =
|
|
650
|
+
const mergeMsg = getErrorMessage(mergeErr);
|
|
650
651
|
const isConflict = /conflict/i.test(mergeMsg);
|
|
651
652
|
|
|
652
653
|
if (isConflict) {
|
|
@@ -703,7 +704,7 @@ async function handleMerge(
|
|
|
703
704
|
"info",
|
|
704
705
|
);
|
|
705
706
|
} catch (error) {
|
|
706
|
-
const msg =
|
|
707
|
+
const msg = getErrorMessage(error);
|
|
707
708
|
ctx.ui.notify(`Failed to start merge: ${msg}`, "error");
|
|
708
709
|
}
|
|
709
710
|
}
|
|
@@ -746,7 +747,7 @@ async function handleRemove(
|
|
|
746
747
|
|
|
747
748
|
ctx.ui.notify(`${CLR.ok("✓")} Worktree ${CLR.name(name)} removed ${CLR.muted("(branch deleted)")}.`, "info");
|
|
748
749
|
} catch (error) {
|
|
749
|
-
const msg =
|
|
750
|
+
const msg = getErrorMessage(error);
|
|
750
751
|
ctx.ui.notify(`Failed to remove worktree: ${msg}`, "error");
|
|
751
752
|
}
|
|
752
753
|
}
|
|
@@ -800,7 +801,7 @@ async function handleRemoveAll(
|
|
|
800
801
|
if (failed.length > 0) lines.push(`${CLR.warn("✗")} Failed: ${failed.map(n => CLR.name(n)).join(", ")}`);
|
|
801
802
|
ctx.ui.notify(lines.join("\n"), failed.length > 0 ? "warning" : "info");
|
|
802
803
|
} catch (error) {
|
|
803
|
-
const msg =
|
|
804
|
+
const msg = getErrorMessage(error);
|
|
804
805
|
ctx.ui.notify(`Failed to remove worktrees: ${msg}`, "error");
|
|
805
806
|
}
|
|
806
807
|
}
|