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
|
@@ -9,6 +9,9 @@ import {
|
|
|
9
9
|
renderAgentView,
|
|
10
10
|
renderChangelogView,
|
|
11
11
|
renderExportView,
|
|
12
|
+
renderKnowledgeView,
|
|
13
|
+
renderCapturesView,
|
|
14
|
+
renderHealthView,
|
|
12
15
|
} from "../visualizer-views.js";
|
|
13
16
|
import type { VisualizerData } from "../visualizer-data.js";
|
|
14
17
|
import { createTestContext } from "./test-helpers.ts";
|
|
@@ -32,6 +35,8 @@ function makeVisualizerData(overrides: Partial<VisualizerData> = {}): Visualizer
|
|
|
32
35
|
byPhase: [],
|
|
33
36
|
bySlice: [],
|
|
34
37
|
byModel: [],
|
|
38
|
+
byTier: [],
|
|
39
|
+
tierSavingsLine: "",
|
|
35
40
|
units: [],
|
|
36
41
|
criticalPath: {
|
|
37
42
|
milestonePath: [],
|
|
@@ -42,6 +47,28 @@ function makeVisualizerData(overrides: Partial<VisualizerData> = {}): Visualizer
|
|
|
42
47
|
remainingSliceCount: 0,
|
|
43
48
|
agentActivity: null,
|
|
44
49
|
changelog: { entries: [] },
|
|
50
|
+
sliceVerifications: [],
|
|
51
|
+
knowledge: { rules: [], patterns: [], lessons: [], exists: false },
|
|
52
|
+
captures: { entries: [], pendingCount: 0, totalCount: 0 },
|
|
53
|
+
health: {
|
|
54
|
+
budgetCeiling: undefined,
|
|
55
|
+
tokenProfile: "standard",
|
|
56
|
+
truncationRate: 0,
|
|
57
|
+
continueHereRate: 0,
|
|
58
|
+
tierBreakdown: [],
|
|
59
|
+
tierSavingsLine: "",
|
|
60
|
+
toolCalls: 0,
|
|
61
|
+
assistantMessages: 0,
|
|
62
|
+
userMessages: 0,
|
|
63
|
+
},
|
|
64
|
+
discussion: [],
|
|
65
|
+
stats: {
|
|
66
|
+
missingCount: 0,
|
|
67
|
+
missingSlices: [],
|
|
68
|
+
updatedCount: 0,
|
|
69
|
+
updatedSlices: [],
|
|
70
|
+
recentEntries: [],
|
|
71
|
+
},
|
|
45
72
|
...overrides,
|
|
46
73
|
};
|
|
47
74
|
}
|
|
@@ -76,29 +103,62 @@ console.log("\n=== renderProgressView ===");
|
|
|
76
103
|
risk: "high",
|
|
77
104
|
depends: ["S01"],
|
|
78
105
|
tasks: [
|
|
79
|
-
{ id: "T01", title: "Dispatch Loop", done: false, active: true },
|
|
106
|
+
{ id: "T01", title: "Dispatch Loop", done: false, active: true, estimate: "30m" },
|
|
80
107
|
{ id: "T02", title: "Session Mgmt", done: true, active: false },
|
|
81
108
|
],
|
|
82
109
|
},
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
{
|
|
111
|
+
id: "S03",
|
|
112
|
+
title: "Dashboard",
|
|
113
|
+
done: false,
|
|
114
|
+
active: false,
|
|
115
|
+
risk: "medium",
|
|
116
|
+
depends: ["S02"],
|
|
117
|
+
tasks: [],
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: "M002",
|
|
123
|
+
title: "Plugin Arch",
|
|
124
|
+
status: "pending",
|
|
125
|
+
dependsOn: ["M001"],
|
|
126
|
+
slices: [],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
sliceVerifications: [
|
|
94
130
|
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
131
|
+
milestoneId: "M001",
|
|
132
|
+
sliceId: "S01",
|
|
133
|
+
verificationResult: "passed",
|
|
134
|
+
blockerDiscovered: false,
|
|
135
|
+
keyDecisions: [],
|
|
136
|
+
patternsEstablished: [],
|
|
137
|
+
provides: ["core-types"],
|
|
138
|
+
requires: [],
|
|
100
139
|
},
|
|
101
140
|
],
|
|
141
|
+
stats: {
|
|
142
|
+
missingCount: 2,
|
|
143
|
+
missingSlices: [
|
|
144
|
+
{ milestoneId: "M001", sliceId: "S02", title: "State Engine" },
|
|
145
|
+
{ milestoneId: "M001", sliceId: "S03", title: "Dashboard" },
|
|
146
|
+
],
|
|
147
|
+
updatedCount: 1,
|
|
148
|
+
updatedSlices: [
|
|
149
|
+
{ milestoneId: "M001", sliceId: "S01", title: "Core Types", completedAt: "2026-03-15T14:30:00Z" },
|
|
150
|
+
],
|
|
151
|
+
recentEntries: [
|
|
152
|
+
{
|
|
153
|
+
milestoneId: "M001",
|
|
154
|
+
sliceId: "S01",
|
|
155
|
+
title: "Core Types Infrastructure",
|
|
156
|
+
oneLiner: "Core structures assembled",
|
|
157
|
+
filesModified: [],
|
|
158
|
+
completedAt: "2026-03-15T14:30:00Z",
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
102
162
|
});
|
|
103
163
|
|
|
104
164
|
const lines = renderProgressView(data, mockTheme, 80);
|
|
@@ -108,12 +168,82 @@ console.log("\n=== renderProgressView ===");
|
|
|
108
168
|
assertTrue(lines.some(l => l.includes("T01")), "shows task T01 for active slice");
|
|
109
169
|
assertTrue(lines.some(l => l.includes("M002")), "shows milestone M002");
|
|
110
170
|
assertTrue(lines.some(l => l.includes("depends on M001")), "shows dependency note");
|
|
171
|
+
assertTrue(lines.some(l => l.includes("30m")), "shows task estimate");
|
|
172
|
+
assertTrue(lines.some(l => l.includes("Feature Snapshot")), "shows stats header");
|
|
173
|
+
assertTrue(lines.some(l => l.includes("Missing slices")), "shows missing slices count");
|
|
174
|
+
assertTrue(lines.some(l => l.includes("State Engine")), "shows missing slice preview");
|
|
175
|
+
assertTrue(lines.some(l => l.includes("Updated (last 7 days)")), "shows updated count");
|
|
176
|
+
assertTrue(lines.some(l => l.includes("Recent completions")), "shows recent completions section");
|
|
177
|
+
assertTrue(lines.some(l => l.includes("Core structures assembled")), "shows recent one-liner entry");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
{
|
|
181
|
+
const data = makeVisualizerData({
|
|
182
|
+
discussion: [
|
|
183
|
+
{
|
|
184
|
+
milestoneId: "M001",
|
|
185
|
+
title: "First Milestone",
|
|
186
|
+
state: "discussed",
|
|
187
|
+
hasContext: true,
|
|
188
|
+
hasDraft: false,
|
|
189
|
+
lastUpdated: "2026-03-15T14:30:00Z",
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
milestoneId: "M002",
|
|
193
|
+
title: "Plugin Arch",
|
|
194
|
+
state: "draft",
|
|
195
|
+
hasContext: false,
|
|
196
|
+
hasDraft: true,
|
|
197
|
+
lastUpdated: "2026-03-16T09:00:00Z",
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
milestoneId: "M003",
|
|
201
|
+
title: "Next Batch",
|
|
202
|
+
state: "undiscussed",
|
|
203
|
+
hasContext: false,
|
|
204
|
+
hasDraft: false,
|
|
205
|
+
lastUpdated: null,
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
const lines = renderProgressView(data, mockTheme, 80);
|
|
211
|
+
assertTrue(lines.some(l => l.includes("Discussion Status")), "shows discussion section");
|
|
212
|
+
assertTrue(lines.some(l => l.includes("Discussed: 1")), "counts discussed milestones");
|
|
213
|
+
assertTrue(lines.some(l => l.includes("Draft")), "shows draft badge");
|
|
214
|
+
assertTrue(lines.some(l => l.includes("Pending")), "shows pending badge");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Verification badges
|
|
218
|
+
{
|
|
219
|
+
const data = makeVisualizerData({
|
|
220
|
+
milestones: [
|
|
221
|
+
{
|
|
222
|
+
id: "M001", title: "Test", status: "active", dependsOn: [],
|
|
223
|
+
slices: [
|
|
224
|
+
{ id: "S01", title: "Done Slice", done: true, active: false, risk: "low", depends: [], tasks: [] },
|
|
225
|
+
],
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
sliceVerifications: [
|
|
229
|
+
{
|
|
230
|
+
milestoneId: "M001", sliceId: "S01",
|
|
231
|
+
verificationResult: "passed", blockerDiscovered: true,
|
|
232
|
+
keyDecisions: [], patternsEstablished: [], provides: [], requires: [],
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const lines = renderProgressView(data, mockTheme, 80);
|
|
238
|
+
// The verification badge should show check mark and warning
|
|
239
|
+
assertTrue(lines.some(l => l.includes("S01")), "shows slice with verification");
|
|
111
240
|
}
|
|
112
241
|
|
|
113
242
|
{
|
|
114
243
|
const data = makeVisualizerData({ milestones: [] });
|
|
115
244
|
const lines = renderProgressView(data, mockTheme, 80);
|
|
116
|
-
|
|
245
|
+
assertTrue(lines.some(l => l.includes("Feature Snapshot")), "shows stats snapshot even when no milestones");
|
|
246
|
+
assertTrue(lines.some(l => l.includes("Missing slices")), "reports missing slices count");
|
|
117
247
|
}
|
|
118
248
|
|
|
119
249
|
// ─── Risk Heatmap ───────────────────────────────────────────────────────────
|
|
@@ -140,8 +270,6 @@ console.log("\n=== Risk Heatmap ===");
|
|
|
140
270
|
|
|
141
271
|
const lines = renderProgressView(data, mockTheme, 80);
|
|
142
272
|
assertTrue(lines.some(l => l.includes("Risk Heatmap")), "heatmap header present");
|
|
143
|
-
assertTrue(lines.some(l => l.includes("██")), "heatmap has colored blocks");
|
|
144
|
-
assertTrue(lines.some(l => l.includes("low") && l.includes("med") && l.includes("high")), "heatmap legend present");
|
|
145
273
|
assertTrue(lines.some(l => l.includes("1 low, 1 med, 2 high")), "risk summary counts");
|
|
146
274
|
assertTrue(lines.some(l => l.includes("1 high-risk not started")), "high-risk not started warning");
|
|
147
275
|
}
|
|
@@ -173,12 +301,10 @@ console.log("\n=== Search/Filter ===");
|
|
|
173
301
|
],
|
|
174
302
|
});
|
|
175
303
|
|
|
176
|
-
// Filter by keyword "auth"
|
|
177
304
|
const filtered = renderProgressView(data, mockTheme, 80, { text: "auth", field: "all" });
|
|
178
305
|
assertTrue(filtered.some(l => l.includes("M001")), "filter shows matching milestone");
|
|
179
306
|
assertTrue(filtered.some(l => l.includes("Filter (all): auth")), "filter indicator present");
|
|
180
307
|
|
|
181
|
-
// Filter by risk "high"
|
|
182
308
|
const riskFiltered = renderProgressView(data, mockTheme, 80, { text: "high", field: "risk" });
|
|
183
309
|
assertTrue(riskFiltered.some(l => l.includes("M001")), "risk filter shows milestone with high-risk slice");
|
|
184
310
|
}
|
|
@@ -214,6 +340,14 @@ console.log("\n=== renderDepsView ===");
|
|
|
214
340
|
milestoneSlack: new Map([["M001", 0], ["M002", 0]]),
|
|
215
341
|
sliceSlack: new Map([["S01", 0], ["S02", 0]]),
|
|
216
342
|
},
|
|
343
|
+
sliceVerifications: [
|
|
344
|
+
{
|
|
345
|
+
milestoneId: "M001", sliceId: "S01",
|
|
346
|
+
verificationResult: "passed", blockerDiscovered: false,
|
|
347
|
+
keyDecisions: [], patternsEstablished: [],
|
|
348
|
+
provides: ["api-types"], requires: [],
|
|
349
|
+
},
|
|
350
|
+
],
|
|
217
351
|
});
|
|
218
352
|
|
|
219
353
|
const lines = renderDepsView(data, mockTheme, 80);
|
|
@@ -222,6 +356,8 @@ console.log("\n=== renderDepsView ===");
|
|
|
222
356
|
assertTrue(lines.some(l => l.includes("S01") && l.includes("S02")), "shows slice dep edge");
|
|
223
357
|
assertTrue(lines.some(l => l.includes("Critical Path")), "shows critical path section");
|
|
224
358
|
assertTrue(lines.some(l => l.includes("[CRITICAL]")), "shows CRITICAL badge");
|
|
359
|
+
assertTrue(lines.some(l => l.includes("Data Flow")), "shows data flow section");
|
|
360
|
+
assertTrue(lines.some(l => l.includes("api-types")), "shows provides artifact");
|
|
225
361
|
}
|
|
226
362
|
|
|
227
363
|
{
|
|
@@ -260,13 +396,6 @@ console.log("\n=== renderMetricsView ===");
|
|
|
260
396
|
cost: 1.50,
|
|
261
397
|
duration: 40000,
|
|
262
398
|
},
|
|
263
|
-
{
|
|
264
|
-
phase: "planning",
|
|
265
|
-
units: 2,
|
|
266
|
-
tokens: { input: 400, output: 200, cacheRead: 100, cacheWrite: 50, total: 750 },
|
|
267
|
-
cost: 1.00,
|
|
268
|
-
duration: 20000,
|
|
269
|
-
},
|
|
270
399
|
],
|
|
271
400
|
byModel: [
|
|
272
401
|
{
|
|
@@ -276,6 +405,11 @@ console.log("\n=== renderMetricsView ===");
|
|
|
276
405
|
cost: 2.50,
|
|
277
406
|
},
|
|
278
407
|
],
|
|
408
|
+
byTier: [
|
|
409
|
+
{ tier: "standard", units: 3, tokens: { input: 600, output: 300, cacheRead: 100, cacheWrite: 50, total: 1050 }, cost: 1.50, downgraded: 0 },
|
|
410
|
+
{ tier: "light", units: 2, tokens: { input: 400, output: 200, cacheRead: 100, cacheWrite: 50, total: 750 }, cost: 1.00, downgraded: 1 },
|
|
411
|
+
],
|
|
412
|
+
tierSavingsLine: "Dynamic routing: 1/5 units downgraded (20%), cost: $1.00",
|
|
279
413
|
bySlice: [
|
|
280
414
|
{ sliceId: "M001/S01", units: 3, tokens: { input: 600, output: 300, cacheRead: 100, cacheWrite: 50, total: 1050 }, cost: 1.50, duration: 40000 },
|
|
281
415
|
{ sliceId: "M001/S02", units: 2, tokens: { input: 400, output: 200, cacheRead: 100, cacheWrite: 50, total: 750 }, cost: 1.00, duration: 20000 },
|
|
@@ -288,11 +422,11 @@ console.log("\n=== renderMetricsView ===");
|
|
|
288
422
|
assertTrue(lines.some(l => l.includes("$2.50")), "shows total cost");
|
|
289
423
|
assertTrue(lines.some(l => l.includes("execution")), "shows phase name");
|
|
290
424
|
assertTrue(lines.some(l => l.includes("claude-opus-4-6")), "shows model name");
|
|
291
|
-
assertTrue(lines.some(l => l.includes("
|
|
292
|
-
assertTrue(lines.some(l => l.includes("
|
|
293
|
-
assertTrue(lines.some(l => l.includes("
|
|
294
|
-
assertTrue(lines.some(l => l.includes("
|
|
295
|
-
assertTrue(lines.some(l => l.includes("
|
|
425
|
+
assertTrue(lines.some(l => l.includes("By Tier")), "shows tier breakdown section");
|
|
426
|
+
assertTrue(lines.some(l => l.includes("standard")), "shows tier name");
|
|
427
|
+
assertTrue(lines.some(l => l.includes("Dynamic routing")), "shows tier savings line");
|
|
428
|
+
assertTrue(lines.some(l => l.includes("Tools: 15")), "shows tool call count");
|
|
429
|
+
assertTrue(lines.some(l => l.includes("10") && l.includes("sent")), "shows message counts");
|
|
296
430
|
}
|
|
297
431
|
|
|
298
432
|
{
|
|
@@ -320,32 +454,16 @@ console.log("\n=== renderTimelineView ===");
|
|
|
320
454
|
toolCalls: 5,
|
|
321
455
|
assistantMessages: 3,
|
|
322
456
|
userMessages: 1,
|
|
323
|
-
|
|
324
|
-
{
|
|
325
|
-
type: "plan-slice",
|
|
326
|
-
id: "M001/S02",
|
|
327
|
-
model: "claude-opus-4-6",
|
|
328
|
-
startedAt: now - 60000,
|
|
329
|
-
finishedAt: now - 30000,
|
|
330
|
-
tokens: { input: 300, output: 150, cacheRead: 50, cacheWrite: 25, total: 525 },
|
|
331
|
-
cost: 0.18,
|
|
332
|
-
toolCalls: 2,
|
|
333
|
-
assistantMessages: 2,
|
|
334
|
-
userMessages: 1,
|
|
457
|
+
tier: "standard",
|
|
335
458
|
},
|
|
336
459
|
],
|
|
337
460
|
});
|
|
338
461
|
|
|
339
|
-
// Wide terminal — Gantt view
|
|
340
|
-
const ganttLines = renderTimelineView(data, mockTheme, 120);
|
|
341
|
-
assertTrue(ganttLines.length >= 2, "gantt view produces lines for each unit");
|
|
342
|
-
|
|
343
|
-
// Narrow terminal — list view
|
|
344
462
|
const listLines = renderTimelineView(data, mockTheme, 80);
|
|
345
|
-
assertTrue(listLines.length >=
|
|
463
|
+
assertTrue(listLines.length >= 1, "list view produces lines");
|
|
346
464
|
assertTrue(listLines.some(l => l.includes("execute-task")), "shows unit type");
|
|
347
|
-
assertTrue(listLines.some(l => l.includes("
|
|
348
|
-
assertTrue(listLines.some(l => l.includes("
|
|
465
|
+
assertTrue(listLines.some(l => l.includes("[standard]")), "shows tier in timeline");
|
|
466
|
+
assertTrue(listLines.some(l => l.includes("opus-4-6")), "shows shortened model");
|
|
349
467
|
}
|
|
350
468
|
|
|
351
469
|
{
|
|
@@ -379,15 +497,21 @@ console.log("\n=== renderAgentView ===");
|
|
|
379
497
|
cost: 0.12, toolCalls: 5, assistantMessages: 3, userMessages: 1,
|
|
380
498
|
},
|
|
381
499
|
],
|
|
500
|
+
health: {
|
|
501
|
+
budgetCeiling: 10, tokenProfile: "standard",
|
|
502
|
+
truncationRate: 15.5, continueHereRate: 5.0,
|
|
503
|
+
tierBreakdown: [], tierSavingsLine: "",
|
|
504
|
+
toolCalls: 20, assistantMessages: 15, userMessages: 8,
|
|
505
|
+
},
|
|
506
|
+
captures: { entries: [], pendingCount: 3, totalCount: 5 },
|
|
382
507
|
});
|
|
383
508
|
|
|
384
509
|
const lines = renderAgentView(data, mockTheme, 80);
|
|
385
510
|
assertTrue(lines.length > 0, "agent view produces output");
|
|
386
511
|
assertTrue(lines.some(l => l.includes("ACTIVE")), "shows active status");
|
|
387
|
-
assertTrue(lines.some(l => l.includes("
|
|
388
|
-
assertTrue(lines.some(l => l.includes("
|
|
389
|
-
assertTrue(lines.some(l => l.includes("
|
|
390
|
-
assertTrue(lines.some(l => l.includes("$1.23")), "shows session cost");
|
|
512
|
+
assertTrue(lines.some(l => l.includes("Pressure")), "shows pressure section");
|
|
513
|
+
assertTrue(lines.some(l => l.includes("15.5%")), "shows truncation rate");
|
|
514
|
+
assertTrue(lines.some(l => l.includes("Pending captures: 3")), "shows pending captures");
|
|
391
515
|
}
|
|
392
516
|
|
|
393
517
|
{
|
|
@@ -396,25 +520,6 @@ console.log("\n=== renderAgentView ===");
|
|
|
396
520
|
assertTrue(lines.some(l => l.includes("No agent activity")), "shows no-activity message");
|
|
397
521
|
}
|
|
398
522
|
|
|
399
|
-
{
|
|
400
|
-
const data = makeVisualizerData({
|
|
401
|
-
agentActivity: {
|
|
402
|
-
currentUnit: null,
|
|
403
|
-
elapsed: 0,
|
|
404
|
-
completedUnits: 5,
|
|
405
|
-
totalSlices: 10,
|
|
406
|
-
completionRate: 1.5,
|
|
407
|
-
active: false,
|
|
408
|
-
sessionCost: 0.50,
|
|
409
|
-
sessionTokens: 20000,
|
|
410
|
-
},
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
const lines = renderAgentView(data, mockTheme, 80);
|
|
414
|
-
assertTrue(lines.some(l => l.includes("IDLE")), "shows idle status");
|
|
415
|
-
assertTrue(lines.some(l => l.includes("Not in auto mode")), "shows not-in-auto message");
|
|
416
|
-
}
|
|
417
|
-
|
|
418
523
|
// ─── renderChangelogView ────────────────────────────────────────────────────
|
|
419
524
|
|
|
420
525
|
console.log("\n=== renderChangelogView ===");
|
|
@@ -430,21 +535,28 @@ console.log("\n=== renderChangelogView ===");
|
|
|
430
535
|
oneLiner: "Added JWT-based auth with refresh token rotation",
|
|
431
536
|
filesModified: [
|
|
432
537
|
{ path: "src/auth/jwt.ts", description: "JWT token generation and validation" },
|
|
433
|
-
{ path: "src/auth/middleware.ts", description: "Express middleware for auth checks" },
|
|
434
538
|
],
|
|
435
539
|
completedAt: "2026-03-15T14:30:00Z",
|
|
436
540
|
},
|
|
437
541
|
],
|
|
438
542
|
},
|
|
543
|
+
sliceVerifications: [
|
|
544
|
+
{
|
|
545
|
+
milestoneId: "M001", sliceId: "S01",
|
|
546
|
+
verificationResult: "passed", blockerDiscovered: false,
|
|
547
|
+
keyDecisions: ["Use RS256 for JWT signing"],
|
|
548
|
+
patternsEstablished: ["Repository pattern for data access"],
|
|
549
|
+
provides: [], requires: [],
|
|
550
|
+
},
|
|
551
|
+
],
|
|
439
552
|
});
|
|
440
553
|
|
|
441
554
|
const lines = renderChangelogView(data, mockTheme, 80);
|
|
442
|
-
assertTrue(lines.length > 0, "changelog view produces output");
|
|
443
555
|
assertTrue(lines.some(l => l.includes("M001/S01")), "shows slice reference");
|
|
444
|
-
assertTrue(lines.some(l => l.includes("
|
|
445
|
-
assertTrue(lines.some(l => l.includes("
|
|
446
|
-
assertTrue(lines.some(l => l.includes("
|
|
447
|
-
assertTrue(lines.some(l => l.includes("
|
|
556
|
+
assertTrue(lines.some(l => l.includes("Decisions:")), "shows decisions section");
|
|
557
|
+
assertTrue(lines.some(l => l.includes("RS256")), "shows decision content");
|
|
558
|
+
assertTrue(lines.some(l => l.includes("Patterns:")), "shows patterns section");
|
|
559
|
+
assertTrue(lines.some(l => l.includes("Repository pattern")), "shows pattern content");
|
|
448
560
|
}
|
|
449
561
|
|
|
450
562
|
{
|
|
@@ -466,11 +578,126 @@ console.log("\n=== renderExportView ===");
|
|
|
466
578
|
assertTrue(lines.some(l => l.includes("[s]")), "shows snapshot option");
|
|
467
579
|
}
|
|
468
580
|
|
|
581
|
+
// ─── renderKnowledgeView ────────────────────────────────────────────────────
|
|
582
|
+
|
|
583
|
+
console.log("\n=== renderKnowledgeView ===");
|
|
584
|
+
|
|
469
585
|
{
|
|
470
|
-
const data = makeVisualizerData(
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
586
|
+
const data = makeVisualizerData({
|
|
587
|
+
knowledge: {
|
|
588
|
+
exists: true,
|
|
589
|
+
rules: [{ id: "K001", scope: "global", content: "Always use transactions" }],
|
|
590
|
+
patterns: [{ id: "P001", content: "Repository pattern for DB access" }],
|
|
591
|
+
lessons: [{ id: "L001", content: "Cache invalidation needs TTL" }],
|
|
592
|
+
},
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
const lines = renderKnowledgeView(data, mockTheme, 80);
|
|
596
|
+
assertTrue(lines.some(l => l.includes("Rules")), "shows rules section");
|
|
597
|
+
assertTrue(lines.some(l => l.includes("K001")), "shows rule ID");
|
|
598
|
+
assertTrue(lines.some(l => l.includes("Always use transactions")), "shows rule content");
|
|
599
|
+
assertTrue(lines.some(l => l.includes("Patterns")), "shows patterns section");
|
|
600
|
+
assertTrue(lines.some(l => l.includes("P001")), "shows pattern ID");
|
|
601
|
+
assertTrue(lines.some(l => l.includes("Lessons Learned")), "shows lessons section");
|
|
602
|
+
assertTrue(lines.some(l => l.includes("L001")), "shows lesson ID");
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
{
|
|
606
|
+
const data = makeVisualizerData({
|
|
607
|
+
knowledge: { exists: false, rules: [], patterns: [], lessons: [] },
|
|
608
|
+
});
|
|
609
|
+
const lines = renderKnowledgeView(data, mockTheme, 80);
|
|
610
|
+
assertTrue(lines.some(l => l.includes("No KNOWLEDGE.md found")), "shows no-knowledge message");
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// ─── renderCapturesView ─────────────────────────────────────────────────────
|
|
614
|
+
|
|
615
|
+
console.log("\n=== renderCapturesView ===");
|
|
616
|
+
|
|
617
|
+
{
|
|
618
|
+
const data = makeVisualizerData({
|
|
619
|
+
captures: {
|
|
620
|
+
entries: [
|
|
621
|
+
{ id: "CAP-abc123", text: "Need to add error handling", timestamp: "2026-03-15T10:00:00Z", status: "pending", classification: "inject" },
|
|
622
|
+
{ id: "CAP-def456", text: "Consider caching layer", timestamp: "2026-03-15T11:00:00Z", status: "triaged", classification: "defer" },
|
|
623
|
+
{ id: "CAP-ghi789", text: "Fixed typo in config", timestamp: "2026-03-15T12:00:00Z", status: "resolved", classification: "quick-task" },
|
|
624
|
+
],
|
|
625
|
+
pendingCount: 1,
|
|
626
|
+
totalCount: 3,
|
|
627
|
+
},
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
const lines = renderCapturesView(data, mockTheme, 80);
|
|
631
|
+
assertTrue(lines.some(l => l.includes("3") && l.includes("total")), "shows total count");
|
|
632
|
+
assertTrue(lines.some(l => l.includes("1") && l.includes("pending")), "shows pending count");
|
|
633
|
+
assertTrue(lines.some(l => l.includes("CAP-abc123")), "shows capture ID");
|
|
634
|
+
assertTrue(lines.some(l => l.includes("(inject)")), "shows classification badge");
|
|
635
|
+
assertTrue(lines.some(l => l.includes("[pending]")), "shows status badge");
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
{
|
|
639
|
+
const data = makeVisualizerData({
|
|
640
|
+
captures: { entries: [], pendingCount: 0, totalCount: 0 },
|
|
641
|
+
});
|
|
642
|
+
const lines = renderCapturesView(data, mockTheme, 80);
|
|
643
|
+
assertTrue(lines.some(l => l.includes("No captures recorded")), "shows empty state");
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// ─── renderHealthView ───────────────────────────────────────────────────────
|
|
647
|
+
|
|
648
|
+
console.log("\n=== renderHealthView ===");
|
|
649
|
+
|
|
650
|
+
{
|
|
651
|
+
const data = makeVisualizerData({
|
|
652
|
+
totals: {
|
|
653
|
+
units: 10, tokens: { input: 5000, output: 2000, cacheRead: 1000, cacheWrite: 500, total: 8500 },
|
|
654
|
+
cost: 5.00, duration: 120000, toolCalls: 50,
|
|
655
|
+
assistantMessages: 30, userMessages: 15,
|
|
656
|
+
totalTruncationSections: 3, continueHereFiredCount: 1,
|
|
657
|
+
},
|
|
658
|
+
health: {
|
|
659
|
+
budgetCeiling: 20.00,
|
|
660
|
+
tokenProfile: "standard",
|
|
661
|
+
truncationRate: 30.0,
|
|
662
|
+
continueHereRate: 10.0,
|
|
663
|
+
tierBreakdown: [
|
|
664
|
+
{ tier: "standard", units: 7, tokens: { input: 3500, output: 1400, cacheRead: 700, cacheWrite: 350, total: 5950 }, cost: 3.50, downgraded: 0 },
|
|
665
|
+
{ tier: "light", units: 3, tokens: { input: 1500, output: 600, cacheRead: 300, cacheWrite: 150, total: 2550 }, cost: 1.50, downgraded: 2 },
|
|
666
|
+
],
|
|
667
|
+
tierSavingsLine: "Dynamic routing: 2/10 units downgraded (20%), cost: $1.50",
|
|
668
|
+
toolCalls: 50,
|
|
669
|
+
assistantMessages: 30,
|
|
670
|
+
userMessages: 15,
|
|
671
|
+
},
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
const lines = renderHealthView(data, mockTheme, 80);
|
|
675
|
+
assertTrue(lines.some(l => l.includes("Budget")), "shows budget section");
|
|
676
|
+
assertTrue(lines.some(l => l.includes("Ceiling")), "shows budget ceiling");
|
|
677
|
+
assertTrue(lines.some(l => l.includes("$20.00")), "shows ceiling amount");
|
|
678
|
+
assertTrue(lines.some(l => l.includes("Pressure")), "shows pressure section");
|
|
679
|
+
assertTrue(lines.some(l => l.includes("30.0%")), "shows truncation rate");
|
|
680
|
+
assertTrue(lines.some(l => l.includes("Routing")), "shows routing section");
|
|
681
|
+
assertTrue(lines.some(l => l.includes("standard")), "shows tier name");
|
|
682
|
+
assertTrue(lines.some(l => l.includes("2 downgraded")), "shows downgraded count");
|
|
683
|
+
assertTrue(lines.some(l => l.includes("Dynamic routing")), "shows savings line");
|
|
684
|
+
assertTrue(lines.some(l => l.includes("Session")), "shows session section");
|
|
685
|
+
assertTrue(lines.some(l => l.includes("Tool calls: 50")), "shows tool calls");
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
{
|
|
689
|
+
const data = makeVisualizerData({
|
|
690
|
+
health: {
|
|
691
|
+
budgetCeiling: undefined, tokenProfile: "compact",
|
|
692
|
+
truncationRate: 0, continueHereRate: 0,
|
|
693
|
+
tierBreakdown: [], tierSavingsLine: "",
|
|
694
|
+
toolCalls: 0, assistantMessages: 0, userMessages: 0,
|
|
695
|
+
},
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
const lines = renderHealthView(data, mockTheme, 80);
|
|
699
|
+
assertTrue(lines.some(l => l.includes("No budget ceiling set")), "shows no-ceiling message");
|
|
700
|
+
assertTrue(lines.some(l => l.includes("compact")), "shows token profile");
|
|
474
701
|
}
|
|
475
702
|
|
|
476
703
|
// ─── Report ─────────────────────────────────────────────────────────────────
|
|
@@ -135,7 +135,7 @@ export async function showTriageConfirmation(
|
|
|
135
135
|
recommended: cls === proposed,
|
|
136
136
|
}));
|
|
137
137
|
|
|
138
|
-
const choice = await showNextAction(ctx
|
|
138
|
+
const choice = await showNextAction(ctx, {
|
|
139
139
|
title: `Triage: ${result.captureId}`,
|
|
140
140
|
summary,
|
|
141
141
|
actions,
|
|
@@ -265,6 +265,8 @@ export interface PhaseSkipPreferences {
|
|
|
265
265
|
skip_reassess?: boolean;
|
|
266
266
|
skip_slice_research?: boolean;
|
|
267
267
|
skip_milestone_validation?: boolean;
|
|
268
|
+
/** When true, auto-mode pauses before each slice for discussion (#789). */
|
|
269
|
+
require_slice_discussion?: boolean;
|
|
268
270
|
}
|
|
269
271
|
|
|
270
272
|
export interface NotificationPreferences {
|