gsd-pi 2.24.0 → 2.26.0
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 +13 -3
- package/dist/headless.js +24 -4
- package/dist/models-resolver.d.ts +0 -11
- package/dist/models-resolver.js +0 -15
- package/dist/resource-loader.d.ts +0 -1
- package/dist/resource-loader.js +0 -9
- package/dist/resources/GSD-WORKFLOW.md +12 -9
- package/dist/resources/extensions/async-jobs/index.ts +9 -1
- package/dist/resources/extensions/bg-shell/index.ts +3 -2
- package/dist/resources/extensions/bg-shell/overlay.ts +18 -17
- package/dist/resources/extensions/get-secrets-from-user.ts +5 -23
- package/dist/resources/extensions/gsd/activity-log.ts +5 -3
- package/dist/resources/extensions/gsd/auto-prompts.ts +14 -0
- package/dist/resources/extensions/gsd/auto-recovery.ts +7 -4
- package/dist/resources/extensions/gsd/auto-worktree.ts +132 -3
- package/dist/resources/extensions/gsd/auto.ts +265 -48
- package/dist/resources/extensions/gsd/cache.ts +3 -1
- package/dist/resources/extensions/gsd/doctor-proactive.ts +7 -6
- package/dist/resources/extensions/gsd/doctor.ts +26 -1
- package/dist/resources/extensions/gsd/files.ts +13 -2
- package/dist/resources/extensions/gsd/git-service.ts +74 -14
- package/dist/resources/extensions/gsd/gsd-db.ts +78 -1
- package/dist/resources/extensions/gsd/guided-flow.ts +54 -22
- package/dist/resources/extensions/gsd/index.ts +62 -8
- package/dist/resources/extensions/gsd/memory-extractor.ts +352 -0
- package/dist/resources/extensions/gsd/memory-store.ts +441 -0
- package/dist/resources/extensions/gsd/migrate/command.ts +2 -2
- package/dist/resources/extensions/gsd/migrate/writer.ts +39 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.ts +122 -4
- package/dist/resources/extensions/gsd/preferences.ts +2 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +4 -4
- package/dist/resources/extensions/gsd/prompts/discuss.md +5 -5
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +3 -3
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/roadmap-slices.ts +45 -1
- package/dist/resources/extensions/gsd/state.ts +17 -6
- package/dist/resources/extensions/gsd/tests/auto-recovery.test.ts +54 -0
- package/dist/resources/extensions/gsd/tests/auto-worktree.test.ts +58 -0
- package/dist/resources/extensions/gsd/tests/derive-state.test.ts +70 -0
- package/dist/resources/extensions/gsd/tests/doctor-proactive.test.ts +23 -3
- package/dist/resources/extensions/gsd/tests/git-service.test.ts +70 -4
- package/dist/resources/extensions/gsd/tests/gsd-db.test.ts +2 -2
- package/dist/resources/extensions/gsd/tests/md-importer.test.ts +2 -3
- package/dist/resources/extensions/gsd/tests/memory-extractor.test.ts +180 -0
- package/dist/resources/extensions/gsd/tests/memory-store.test.ts +345 -0
- package/dist/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +13 -7
- package/dist/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +171 -0
- package/dist/resources/extensions/gsd/tests/smart-entry-draft.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +8 -4
- package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +147 -2
- package/dist/resources/extensions/gsd/tests/visualizer-overlay.test.ts +88 -10
- package/dist/resources/extensions/gsd/tests/visualizer-views.test.ts +314 -87
- package/dist/resources/extensions/gsd/triage-ui.ts +1 -1
- package/dist/resources/extensions/gsd/types.ts +2 -0
- package/dist/resources/extensions/gsd/visualizer-data.ts +291 -10
- package/dist/resources/extensions/gsd/visualizer-overlay.ts +237 -28
- package/dist/resources/extensions/gsd/visualizer-views.ts +462 -48
- package/dist/resources/extensions/gsd/worktree.ts +9 -2
- package/dist/resources/extensions/search-the-web/native-search.ts +19 -5
- package/dist/resources/extensions/shared/path-display.ts +19 -0
- package/package.json +1 -6
- package/packages/pi-agent-core/dist/agent-loop.js +2 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +64 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/mistral.js +3 -0
- package/packages/pi-ai/dist/providers/mistral.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +23 -1
- 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/src/providers/anthropic.ts +65 -1
- package/packages/pi-ai/src/providers/mistral.ts +3 -0
- package/packages/pi-ai/src/types.ts +19 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +32 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.js +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +12 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +7 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +8 -3
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +2 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +5 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +41 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +301 -62
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +17 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +5 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +135 -30
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/path-display.test.d.ts +8 -0
- package/packages/pi-coding-agent/dist/tests/path-display.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/path-display.test.js +60 -0
- package/packages/pi-coding-agent/dist/tests/path-display.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/utils/clipboard-image.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/utils/clipboard-image.js +32 -6
- package/packages/pi-coding-agent/dist/utils/clipboard-image.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/path-display.d.ts +34 -0
- package/packages/pi-coding-agent/dist/utils/path-display.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/utils/path-display.js +36 -0
- package/packages/pi-coding-agent/dist/utils/path-display.js.map +1 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +36 -0
- package/packages/pi-coding-agent/src/core/keybindings.ts +1 -1
- package/packages/pi-coding-agent/src/core/lsp/client.ts +11 -1
- package/packages/pi-coding-agent/src/core/lsp/index.ts +7 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +17 -1
- package/packages/pi-coding-agent/src/core/settings-manager.ts +11 -0
- package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +2 -1
- package/packages/pi-coding-agent/src/index.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +347 -62
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +18 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +124 -4
- package/packages/pi-coding-agent/src/tests/path-display.test.ts +85 -0
- package/packages/pi-coding-agent/src/utils/clipboard-image.ts +33 -6
- package/packages/pi-coding-agent/src/utils/path-display.ts +36 -0
- package/src/resources/GSD-WORKFLOW.md +12 -9
- package/src/resources/extensions/async-jobs/index.ts +9 -1
- package/src/resources/extensions/bg-shell/index.ts +3 -2
- package/src/resources/extensions/bg-shell/overlay.ts +18 -17
- package/src/resources/extensions/get-secrets-from-user.ts +5 -23
- package/src/resources/extensions/gsd/activity-log.ts +5 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +14 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +7 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +132 -3
- package/src/resources/extensions/gsd/auto.ts +265 -48
- package/src/resources/extensions/gsd/cache.ts +3 -1
- package/src/resources/extensions/gsd/doctor-proactive.ts +7 -6
- package/src/resources/extensions/gsd/doctor.ts +26 -1
- package/src/resources/extensions/gsd/files.ts +13 -2
- package/src/resources/extensions/gsd/git-service.ts +74 -14
- package/src/resources/extensions/gsd/gsd-db.ts +78 -1
- package/src/resources/extensions/gsd/guided-flow.ts +54 -22
- package/src/resources/extensions/gsd/index.ts +62 -8
- package/src/resources/extensions/gsd/memory-extractor.ts +352 -0
- package/src/resources/extensions/gsd/memory-store.ts +441 -0
- package/src/resources/extensions/gsd/migrate/command.ts +2 -2
- package/src/resources/extensions/gsd/migrate/writer.ts +39 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +122 -4
- package/src/resources/extensions/gsd/preferences.ts +2 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +4 -4
- package/src/resources/extensions/gsd/prompts/discuss.md +5 -5
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/queue.md +3 -3
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +45 -1
- package/src/resources/extensions/gsd/state.ts +17 -6
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +23 -3
- package/src/resources/extensions/gsd/tests/git-service.test.ts +70 -4
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +345 -0
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +171 -0
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +147 -2
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +88 -10
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +314 -87
- package/src/resources/extensions/gsd/triage-ui.ts +1 -1
- package/src/resources/extensions/gsd/types.ts +2 -0
- package/src/resources/extensions/gsd/visualizer-data.ts +291 -10
- package/src/resources/extensions/gsd/visualizer-overlay.ts +237 -28
- package/src/resources/extensions/gsd/visualizer-views.ts +462 -48
- package/src/resources/extensions/gsd/worktree.ts +9 -2
- package/src/resources/extensions/search-the-web/native-search.ts +19 -5
- package/src/resources/extensions/shared/path-display.ts +19 -0
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
// Data loader for workflow visualizer overlay — aggregates state + metrics.
|
|
2
2
|
|
|
3
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
3
4
|
import { deriveState } from './state.js';
|
|
4
5
|
import { parseRoadmap, parsePlan, parseSummary, loadFile } from './files.js';
|
|
5
6
|
import { findMilestoneIds } from './guided-flow.js';
|
|
6
|
-
import { resolveMilestoneFile, resolveSliceFile } from './paths.js';
|
|
7
|
+
import { resolveMilestoneFile, resolveSliceFile, resolveGsdRootFile } from './paths.js';
|
|
7
8
|
import {
|
|
8
9
|
getLedger,
|
|
9
10
|
getProjectTotals,
|
|
10
11
|
aggregateByPhase,
|
|
11
12
|
aggregateBySlice,
|
|
12
13
|
aggregateByModel,
|
|
14
|
+
aggregateByTier,
|
|
15
|
+
formatTierSavings,
|
|
13
16
|
loadLedgerFromDisk,
|
|
14
17
|
classifyUnitPhase,
|
|
15
18
|
} from './metrics.js';
|
|
19
|
+
import { loadAllCaptures, countPendingCaptures } from './captures.js';
|
|
20
|
+
import { loadEffectiveGSDPreferences } from './preferences.js';
|
|
16
21
|
|
|
17
22
|
import type { Phase } from './types.js';
|
|
23
|
+
import type { CaptureEntry } from './captures.js';
|
|
18
24
|
import type {
|
|
19
25
|
ProjectTotals,
|
|
20
26
|
PhaseAggregate,
|
|
21
27
|
SliceAggregate,
|
|
22
28
|
ModelAggregate,
|
|
29
|
+
TierAggregate,
|
|
23
30
|
UnitMetrics,
|
|
24
31
|
} from './metrics.js';
|
|
25
32
|
|
|
@@ -48,6 +55,7 @@ export interface VisualizerTask {
|
|
|
48
55
|
title: string;
|
|
49
56
|
done: boolean;
|
|
50
57
|
active: boolean;
|
|
58
|
+
estimate?: string;
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
export interface CriticalPathInfo {
|
|
@@ -81,6 +89,71 @@ export interface ChangelogInfo {
|
|
|
81
89
|
entries: ChangelogEntry[];
|
|
82
90
|
}
|
|
83
91
|
|
|
92
|
+
export interface VisualizerSliceRef {
|
|
93
|
+
milestoneId: string;
|
|
94
|
+
sliceId: string;
|
|
95
|
+
title: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface VisualizerSliceActivity extends VisualizerSliceRef {
|
|
99
|
+
completedAt: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface VisualizerStats {
|
|
103
|
+
missingCount: number;
|
|
104
|
+
missingSlices: VisualizerSliceRef[];
|
|
105
|
+
updatedCount: number;
|
|
106
|
+
updatedSlices: VisualizerSliceActivity[];
|
|
107
|
+
recentEntries: ChangelogEntry[];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export type DiscussionState = 'undiscussed' | 'draft' | 'discussed';
|
|
111
|
+
|
|
112
|
+
export interface VisualizerDiscussionState {
|
|
113
|
+
milestoneId: string;
|
|
114
|
+
title: string;
|
|
115
|
+
state: DiscussionState;
|
|
116
|
+
hasContext: boolean;
|
|
117
|
+
hasDraft: boolean;
|
|
118
|
+
lastUpdated: string | null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface SliceVerification {
|
|
122
|
+
milestoneId: string;
|
|
123
|
+
sliceId: string;
|
|
124
|
+
verificationResult: string;
|
|
125
|
+
blockerDiscovered: boolean;
|
|
126
|
+
keyDecisions: string[];
|
|
127
|
+
patternsEstablished: string[];
|
|
128
|
+
provides: string[];
|
|
129
|
+
requires: { slice: string; provides: string }[];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface KnowledgeInfo {
|
|
133
|
+
rules: { id: string; scope: string; content: string }[];
|
|
134
|
+
patterns: { id: string; content: string }[];
|
|
135
|
+
lessons: { id: string; content: string }[];
|
|
136
|
+
exists: boolean;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface CapturesInfo {
|
|
140
|
+
entries: CaptureEntry[];
|
|
141
|
+
pendingCount: number;
|
|
142
|
+
totalCount: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface HealthInfo {
|
|
146
|
+
budgetCeiling: number | undefined;
|
|
147
|
+
tokenProfile: string;
|
|
148
|
+
truncationRate: number;
|
|
149
|
+
continueHereRate: number;
|
|
150
|
+
tierBreakdown: TierAggregate[];
|
|
151
|
+
tierSavingsLine: string;
|
|
152
|
+
toolCalls: number;
|
|
153
|
+
assistantMessages: number;
|
|
154
|
+
userMessages: number;
|
|
155
|
+
}
|
|
156
|
+
|
|
84
157
|
export interface VisualizerData {
|
|
85
158
|
milestones: VisualizerMilestone[];
|
|
86
159
|
phase: Phase;
|
|
@@ -88,11 +161,19 @@ export interface VisualizerData {
|
|
|
88
161
|
byPhase: PhaseAggregate[];
|
|
89
162
|
bySlice: SliceAggregate[];
|
|
90
163
|
byModel: ModelAggregate[];
|
|
164
|
+
byTier: TierAggregate[];
|
|
165
|
+
tierSavingsLine: string;
|
|
91
166
|
units: UnitMetrics[];
|
|
92
167
|
criticalPath: CriticalPathInfo;
|
|
93
168
|
remainingSliceCount: number;
|
|
94
169
|
agentActivity: AgentActivityInfo | null;
|
|
95
170
|
changelog: ChangelogInfo;
|
|
171
|
+
sliceVerifications: SliceVerification[];
|
|
172
|
+
knowledge: KnowledgeInfo;
|
|
173
|
+
captures: CapturesInfo;
|
|
174
|
+
health: HealthInfo;
|
|
175
|
+
discussion: VisualizerDiscussionState[];
|
|
176
|
+
stats: VisualizerStats;
|
|
96
177
|
}
|
|
97
178
|
|
|
98
179
|
// ─── Critical Path ────────────────────────────────────────────────────────────
|
|
@@ -334,12 +415,18 @@ function loadAgentActivity(units: UnitMetrics[], milestones: VisualizerMilestone
|
|
|
334
415
|
};
|
|
335
416
|
}
|
|
336
417
|
|
|
337
|
-
// ─── Changelog
|
|
418
|
+
// ─── Changelog & Verifications ────────────────────────────────────────────────
|
|
338
419
|
|
|
339
|
-
const changelogCache = new Map<string, { mtime: number; entry: ChangelogEntry }>();
|
|
420
|
+
const changelogCache = new Map<string, { mtime: number; entry: ChangelogEntry; verification: SliceVerification }>();
|
|
340
421
|
|
|
341
|
-
|
|
422
|
+
interface ChangelogAndVerifications {
|
|
423
|
+
changelog: ChangelogInfo;
|
|
424
|
+
verifications: SliceVerification[];
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
async function loadChangelogAndVerifications(basePath: string, milestones: VisualizerMilestone[]): Promise<ChangelogAndVerifications> {
|
|
342
428
|
const entries: ChangelogEntry[] = [];
|
|
429
|
+
const verifications: SliceVerification[] = [];
|
|
343
430
|
|
|
344
431
|
for (const ms of milestones) {
|
|
345
432
|
for (const sl of ms.slices) {
|
|
@@ -348,11 +435,9 @@ async function loadChangelog(basePath: string, milestones: VisualizerMilestone[]
|
|
|
348
435
|
const summaryFile = resolveSliceFile(basePath, ms.id, sl.id, 'SUMMARY');
|
|
349
436
|
if (!summaryFile) continue;
|
|
350
437
|
|
|
351
|
-
// Check cache by file path
|
|
352
438
|
const cacheKey = `${ms.id}/${sl.id}`;
|
|
353
439
|
const cached = changelogCache.get(cacheKey);
|
|
354
440
|
|
|
355
|
-
// Check mtime for cache invalidation
|
|
356
441
|
let mtime = 0;
|
|
357
442
|
try {
|
|
358
443
|
const { statSync } = await import('node:fs');
|
|
@@ -363,6 +448,7 @@ async function loadChangelog(basePath: string, milestones: VisualizerMilestone[]
|
|
|
363
448
|
|
|
364
449
|
if (cached && cached.mtime === mtime) {
|
|
365
450
|
entries.push(cached.entry);
|
|
451
|
+
verifications.push(cached.verification);
|
|
366
452
|
continue;
|
|
367
453
|
}
|
|
368
454
|
|
|
@@ -382,15 +468,184 @@ async function loadChangelog(basePath: string, milestones: VisualizerMilestone[]
|
|
|
382
468
|
completedAt: String(summary.frontmatter.completed_at ?? ''),
|
|
383
469
|
};
|
|
384
470
|
|
|
385
|
-
|
|
471
|
+
const verification: SliceVerification = {
|
|
472
|
+
milestoneId: ms.id,
|
|
473
|
+
sliceId: sl.id,
|
|
474
|
+
verificationResult: summary.frontmatter.verification_result || '',
|
|
475
|
+
blockerDiscovered: summary.frontmatter.blocker_discovered,
|
|
476
|
+
keyDecisions: summary.frontmatter.key_decisions || [],
|
|
477
|
+
patternsEstablished: summary.frontmatter.patterns_established || [],
|
|
478
|
+
provides: summary.frontmatter.provides || [],
|
|
479
|
+
requires: (summary.frontmatter.requires || []).map(r => ({
|
|
480
|
+
slice: r.slice,
|
|
481
|
+
provides: r.provides,
|
|
482
|
+
})),
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
changelogCache.set(cacheKey, { mtime, entry, verification });
|
|
386
486
|
entries.push(entry);
|
|
487
|
+
verifications.push(verification);
|
|
387
488
|
}
|
|
388
489
|
}
|
|
389
490
|
|
|
390
|
-
// Sort by completedAt descending
|
|
391
491
|
entries.sort((a, b) => String(b.completedAt || '').localeCompare(String(a.completedAt || '')));
|
|
392
492
|
|
|
393
|
-
return { entries };
|
|
493
|
+
return { changelog: { entries }, verifications };
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// ─── Knowledge Loader ─────────────────────────────────────────────────────────
|
|
497
|
+
|
|
498
|
+
function loadKnowledge(basePath: string): KnowledgeInfo {
|
|
499
|
+
const knowledgePath = resolveGsdRootFile(basePath, 'KNOWLEDGE');
|
|
500
|
+
if (!existsSync(knowledgePath)) {
|
|
501
|
+
return { rules: [], patterns: [], lessons: [], exists: false };
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
let content: string;
|
|
505
|
+
try {
|
|
506
|
+
content = readFileSync(knowledgePath, 'utf-8');
|
|
507
|
+
} catch {
|
|
508
|
+
return { rules: [], patterns: [], lessons: [], exists: false };
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const rules: { id: string; scope: string; content: string }[] = [];
|
|
512
|
+
const patterns: { id: string; content: string }[] = [];
|
|
513
|
+
const lessons: { id: string; content: string }[] = [];
|
|
514
|
+
|
|
515
|
+
const lines = content.split('\n');
|
|
516
|
+
let currentSection = '';
|
|
517
|
+
|
|
518
|
+
for (const line of lines) {
|
|
519
|
+
if (line.startsWith('## Rules')) { currentSection = 'rules'; continue; }
|
|
520
|
+
if (line.startsWith('## Patterns')) { currentSection = 'patterns'; continue; }
|
|
521
|
+
if (line.startsWith('## Lessons')) { currentSection = 'lessons'; continue; }
|
|
522
|
+
if (line.startsWith('## ')) { currentSection = ''; continue; }
|
|
523
|
+
|
|
524
|
+
if (!line.startsWith('| ') || line.startsWith('| ---') || line.startsWith('| ID')) continue;
|
|
525
|
+
const cols = line.split('|').map(c => c.trim()).filter(c => c.length > 0);
|
|
526
|
+
if (cols.length < 2) continue;
|
|
527
|
+
|
|
528
|
+
if (currentSection === 'rules' && cols.length >= 3) {
|
|
529
|
+
rules.push({ id: cols[0], scope: cols[1], content: cols[2] });
|
|
530
|
+
} else if (currentSection === 'patterns' && cols.length >= 2) {
|
|
531
|
+
patterns.push({ id: cols[0], content: cols[1] });
|
|
532
|
+
} else if (currentSection === 'lessons' && cols.length >= 2) {
|
|
533
|
+
lessons.push({ id: cols[0], content: cols[1] });
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
return { rules, patterns, lessons, exists: true };
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// ─── Health Loader ────────────────────────────────────────────────────────────
|
|
541
|
+
|
|
542
|
+
function loadHealth(units: UnitMetrics[], totals: ProjectTotals | null): HealthInfo {
|
|
543
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
544
|
+
const budgetCeiling = prefs?.preferences?.budget_ceiling;
|
|
545
|
+
const tokenProfile = prefs?.preferences?.token_profile ?? 'standard';
|
|
546
|
+
|
|
547
|
+
let truncationRate = 0;
|
|
548
|
+
let continueHereRate = 0;
|
|
549
|
+
if (totals && totals.units > 0) {
|
|
550
|
+
truncationRate = (totals.totalTruncationSections / totals.units) * 100;
|
|
551
|
+
continueHereRate = (totals.continueHereFiredCount / totals.units) * 100;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const tierBreakdown = aggregateByTier(units);
|
|
555
|
+
const tierSavingsLine = formatTierSavings(units);
|
|
556
|
+
|
|
557
|
+
return {
|
|
558
|
+
budgetCeiling,
|
|
559
|
+
tokenProfile,
|
|
560
|
+
truncationRate,
|
|
561
|
+
continueHereRate,
|
|
562
|
+
tierBreakdown,
|
|
563
|
+
tierSavingsLine,
|
|
564
|
+
toolCalls: totals?.toolCalls ?? 0,
|
|
565
|
+
assistantMessages: totals?.assistantMessages ?? 0,
|
|
566
|
+
userMessages: totals?.userMessages ?? 0,
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const RECENT_ENTRY_LIMIT = 3;
|
|
571
|
+
const FEATURE_PREVIEW_LIMIT = 5;
|
|
572
|
+
const UPDATED_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
|
|
573
|
+
|
|
574
|
+
function buildVisualizerStats(
|
|
575
|
+
milestones: VisualizerMilestone[],
|
|
576
|
+
entries: ChangelogEntry[],
|
|
577
|
+
): VisualizerStats {
|
|
578
|
+
const missing: VisualizerSliceRef[] = [];
|
|
579
|
+
for (const ms of milestones) {
|
|
580
|
+
for (const sl of ms.slices) {
|
|
581
|
+
if (!sl.done) missing.push({ milestoneId: ms.id, sliceId: sl.id, title: sl.title });
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const missingCount = missing.length;
|
|
586
|
+
const missingSlices = missing.slice(0, FEATURE_PREVIEW_LIMIT);
|
|
587
|
+
|
|
588
|
+
const now = Date.now();
|
|
589
|
+
const updatedEntries = entries.filter(entry => {
|
|
590
|
+
if (!entry.completedAt) return false;
|
|
591
|
+
const parsed = Date.parse(entry.completedAt);
|
|
592
|
+
return !Number.isNaN(parsed) && now - parsed <= UPDATED_WINDOW_MS;
|
|
593
|
+
});
|
|
594
|
+
const updatedCount = updatedEntries.length;
|
|
595
|
+
const updatedSlices = updatedEntries.slice(0, FEATURE_PREVIEW_LIMIT).map(entry => ({
|
|
596
|
+
milestoneId: entry.milestoneId,
|
|
597
|
+
sliceId: entry.sliceId,
|
|
598
|
+
title: entry.title,
|
|
599
|
+
completedAt: entry.completedAt,
|
|
600
|
+
}));
|
|
601
|
+
|
|
602
|
+
const recentEntries = entries.slice(0, RECENT_ENTRY_LIMIT);
|
|
603
|
+
|
|
604
|
+
return {
|
|
605
|
+
missingCount,
|
|
606
|
+
missingSlices,
|
|
607
|
+
updatedCount,
|
|
608
|
+
updatedSlices,
|
|
609
|
+
recentEntries,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
function loadDiscussionState(
|
|
614
|
+
basePath: string,
|
|
615
|
+
milestones: VisualizerMilestone[],
|
|
616
|
+
): VisualizerDiscussionState[] {
|
|
617
|
+
const states: VisualizerDiscussionState[] = [];
|
|
618
|
+
|
|
619
|
+
for (const ms of milestones) {
|
|
620
|
+
const contextPath = resolveMilestoneFile(basePath, ms.id, "CONTEXT");
|
|
621
|
+
const draftPath = resolveMilestoneFile(basePath, ms.id, "CONTEXT-DRAFT");
|
|
622
|
+
const state: DiscussionState = contextPath
|
|
623
|
+
? "discussed"
|
|
624
|
+
: draftPath
|
|
625
|
+
? "draft"
|
|
626
|
+
: "undiscussed";
|
|
627
|
+
|
|
628
|
+
let lastUpdated: string | null = null;
|
|
629
|
+
const target = contextPath ?? draftPath;
|
|
630
|
+
if (target) {
|
|
631
|
+
try {
|
|
632
|
+
lastUpdated = new Date(statSync(target).mtimeMs).toISOString();
|
|
633
|
+
} catch {
|
|
634
|
+
lastUpdated = null;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
states.push({
|
|
639
|
+
milestoneId: ms.id,
|
|
640
|
+
title: ms.title,
|
|
641
|
+
state,
|
|
642
|
+
hasContext: !!contextPath,
|
|
643
|
+
hasDraft: !!draftPath,
|
|
644
|
+
lastUpdated,
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
return states;
|
|
394
649
|
}
|
|
395
650
|
|
|
396
651
|
// ─── Loader ───────────────────────────────────────────────────────────────────
|
|
@@ -433,6 +688,7 @@ export async function loadVisualizerData(basePath: string): Promise<VisualizerDa
|
|
|
433
688
|
title: t.title,
|
|
434
689
|
done: t.done,
|
|
435
690
|
active: state.activeTask?.id === t.id,
|
|
691
|
+
estimate: t.estimate || undefined,
|
|
436
692
|
});
|
|
437
693
|
}
|
|
438
694
|
}
|
|
@@ -464,6 +720,8 @@ export async function loadVisualizerData(basePath: string): Promise<VisualizerDa
|
|
|
464
720
|
let byPhase: PhaseAggregate[] = [];
|
|
465
721
|
let bySlice: SliceAggregate[] = [];
|
|
466
722
|
let byModel: ModelAggregate[] = [];
|
|
723
|
+
let byTier: TierAggregate[] = [];
|
|
724
|
+
let tierSavingsLine = '';
|
|
467
725
|
let units: UnitMetrics[] = [];
|
|
468
726
|
|
|
469
727
|
const ledger = getLedger() ?? loadLedgerFromDisk(basePath);
|
|
@@ -474,6 +732,8 @@ export async function loadVisualizerData(basePath: string): Promise<VisualizerDa
|
|
|
474
732
|
byPhase = aggregateByPhase(units);
|
|
475
733
|
bySlice = aggregateBySlice(units);
|
|
476
734
|
byModel = aggregateByModel(units);
|
|
735
|
+
byTier = aggregateByTier(units);
|
|
736
|
+
tierSavingsLine = formatTierSavings(units);
|
|
477
737
|
}
|
|
478
738
|
|
|
479
739
|
// Compute new fields
|
|
@@ -487,7 +747,20 @@ export async function loadVisualizerData(basePath: string): Promise<VisualizerDa
|
|
|
487
747
|
}
|
|
488
748
|
|
|
489
749
|
const agentActivity = loadAgentActivity(units, milestones);
|
|
490
|
-
const changelog = await
|
|
750
|
+
const { changelog, verifications: sliceVerifications } = await loadChangelogAndVerifications(basePath, milestones);
|
|
751
|
+
|
|
752
|
+
const knowledge = loadKnowledge(basePath);
|
|
753
|
+
const allCaptures = loadAllCaptures(basePath);
|
|
754
|
+
const pendingCount = countPendingCaptures(basePath);
|
|
755
|
+
const captures: CapturesInfo = {
|
|
756
|
+
entries: allCaptures,
|
|
757
|
+
pendingCount,
|
|
758
|
+
totalCount: allCaptures.length,
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
const health = loadHealth(units, totals);
|
|
762
|
+
const stats = buildVisualizerStats(milestones, changelog.entries);
|
|
763
|
+
const discussion = loadDiscussionState(basePath, milestones);
|
|
491
764
|
|
|
492
765
|
return {
|
|
493
766
|
milestones,
|
|
@@ -496,10 +769,18 @@ export async function loadVisualizerData(basePath: string): Promise<VisualizerDa
|
|
|
496
769
|
byPhase,
|
|
497
770
|
bySlice,
|
|
498
771
|
byModel,
|
|
772
|
+
byTier,
|
|
773
|
+
tierSavingsLine,
|
|
499
774
|
units,
|
|
500
775
|
criticalPath,
|
|
501
776
|
remainingSliceCount,
|
|
502
777
|
agentActivity,
|
|
503
778
|
changelog,
|
|
779
|
+
sliceVerifications,
|
|
780
|
+
knowledge,
|
|
781
|
+
captures,
|
|
782
|
+
health,
|
|
783
|
+
discussion,
|
|
784
|
+
stats,
|
|
504
785
|
};
|
|
505
786
|
}
|