@pellux/goodvibes-agent 1.3.0 → 1.4.2

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +0 -1
  3. package/dist/package/{ast-grep-napi.linux-x64-gnu-swtppvy9.node → ast-grep-napi.linux-x64-gnu-mkk8xwww.node} +0 -0
  4. package/dist/package/{ast-grep-napi.linux-x64-musl-ttfcdtap.node → ast-grep-napi.linux-x64-musl-ryqtgdv6.node} +0 -0
  5. package/dist/package/main.js +55623 -55535
  6. package/docs/README.md +0 -1
  7. package/docs/tools-and-commands.md +0 -3
  8. package/package.json +1 -1
  9. package/release/release-notes.md +7 -156
  10. package/src/agent/competitive-feature-inventory.ts +1 -1
  11. package/src/agent/setup-wizard.ts +28 -21
  12. package/src/cli/tui-startup.ts +2 -2
  13. package/src/input/agent-workspace-activation.ts +2 -2
  14. package/src/input/agent-workspace-categories.ts +3 -20
  15. package/src/input/agent-workspace-onboarding-finish.ts +21 -0
  16. package/src/input/agent-workspace-settings.ts +14 -19
  17. package/src/input/agent-workspace-setup-snapshot.ts +2 -10
  18. package/src/input/agent-workspace-setup.ts +14 -47
  19. package/src/input/agent-workspace-snapshot.ts +0 -7
  20. package/src/input/agent-workspace-types.ts +5 -2
  21. package/src/input/agent-workspace.ts +19 -8
  22. package/src/input/commands.ts +0 -4
  23. package/src/input/handler.ts +70 -5
  24. package/src/main.ts +1 -40
  25. package/src/panels/builtin/agent.ts +0 -28
  26. package/src/renderer/agent-workspace-context-lines.ts +11 -42
  27. package/src/renderer/agent-workspace.ts +414 -31
  28. package/src/renderer/help-overlay.ts +0 -2
  29. package/src/tools/agent-harness-setup-posture.ts +7 -7
  30. package/src/version.ts +1 -1
  31. package/docs/project-planning.md +0 -81
  32. package/src/input/commands/planning-runtime.ts +0 -215
  33. package/src/input/commands/work-plan-runtime.ts +0 -191
  34. package/src/panels/plan-dashboard-panel.ts +0 -274
  35. package/src/panels/project-planning-panel.ts +0 -721
  36. package/src/panels/work-plan-panel.ts +0 -175
  37. package/src/planning/project-planning-coordinator.ts +0 -543
@@ -1,274 +0,0 @@
1
- import type { Line } from '../types/grid.ts';
2
- import type { ExecutionPlan, PlanItem, PlanItemStatus } from '@pellux/goodvibes-sdk/platform/core';
3
- import { BasePanel } from './base-panel.ts';
4
- import type { PlanDashboardQuery } from '../runtime/ui-service-queries.ts';
5
- import {
6
- buildEmptyState,
7
- buildPanelLine,
8
- buildPanelWorkspace,
9
- resolveScrollablePanelSection,
10
- DEFAULT_PANEL_PALETTE,
11
- type PanelWorkspaceSection,
12
- } from './polish.ts';
13
-
14
- // ---------------------------------------------------------------------------
15
- // Status display maps
16
- // ---------------------------------------------------------------------------
17
-
18
- const STATUS_ICON: Record<PlanItemStatus, string> = {
19
- complete: '✓',
20
- in_progress: '▸',
21
- pending: '•',
22
- failed: '✗',
23
- skipped: '–',
24
- };
25
-
26
- const STATUS_FG: Record<PlanItemStatus, string> = {
27
- complete: '#22c55e',
28
- in_progress: '#00ffff',
29
- pending: '244',
30
- failed: '#ef4444',
31
- skipped: '238',
32
- };
33
-
34
- // ---------------------------------------------------------------------------
35
- // PlanDashboardPanel
36
- // ---------------------------------------------------------------------------
37
-
38
- export class PlanDashboardPanel extends BasePanel {
39
- private scrollOffset = 0;
40
- private selectedIndex = 0;
41
-
42
- // Flat list of navigable row indices (set during render)
43
- private totalRows = 0;
44
- private readonly planManager: PlanDashboardQuery;
45
-
46
- constructor(planManager: PlanDashboardQuery) {
47
- super('plan', 'Plan', 'P', 'agent');
48
- this.planManager = planManager;
49
- }
50
-
51
- override onActivate(): void {
52
- super.onActivate();
53
- // Re-read plan from disk each time the panel is activated
54
- this.markDirty();
55
- }
56
-
57
- // --------------------------------------------------------------------------
58
- // Input
59
- // --------------------------------------------------------------------------
60
-
61
- handleInput(key: string): boolean {
62
- if (key === 'up' || key === 'k') {
63
- if (this.selectedIndex > 0) {
64
- this.selectedIndex--;
65
- this.markDirty();
66
- return true;
67
- }
68
- } else if (key === 'down' || key === 'j') {
69
- if (this.selectedIndex < this.totalRows - 1) {
70
- this.selectedIndex++;
71
- this.markDirty();
72
- return true;
73
- }
74
- }
75
- return false;
76
- }
77
-
78
- // --------------------------------------------------------------------------
79
- // Render
80
- // --------------------------------------------------------------------------
81
-
82
- render(width: number, height: number): Line[] {
83
- return this.trackedRender(() => {
84
- const plan = this.planManager.getActive();
85
- if (!plan) {
86
- return buildPanelWorkspace(width, height, {
87
- title: ' Plan Dashboard',
88
- intro: 'Track the active execution plan, item status, phase grouping, and overall completion.',
89
- sections: [
90
- {
91
- lines: buildEmptyState(
92
- width,
93
- ' No active execution plan',
94
- 'Use /plan to create a plan and the execution dashboard will populate here.',
95
- [],
96
- DEFAULT_PANEL_PALETTE,
97
- ),
98
- },
99
- ],
100
- palette: DEFAULT_PANEL_PALETTE,
101
- });
102
- }
103
- return this.renderPlan(plan, width, height);
104
- });
105
- }
106
-
107
- // --------------------------------------------------------------------------
108
- // Empty state
109
- // --------------------------------------------------------------------------
110
-
111
- private renderPlan(plan: ExecutionPlan, width: number, height: number): Line[] {
112
- const phaseOrder: string[] = [];
113
- const byPhase = new Map<string, PlanItem[]>();
114
- for (const item of plan.items) {
115
- if (!byPhase.has(item.phase)) {
116
- byPhase.set(item.phase, []);
117
- phaseOrder.push(item.phase);
118
- }
119
- byPhase.get(item.phase)!.push(item);
120
- }
121
-
122
- // Build a set of complete item IDs for dependency blocking detection
123
- const completeIds = new Set(
124
- plan.items
125
- .filter((i) => i.status === 'complete' || i.status === 'skipped')
126
- .map((i) => i.id),
127
- );
128
-
129
- let rowCount = 0;
130
- let selectedLineIndex = 0;
131
- const planLines: Line[] = [];
132
-
133
- for (const phase of phaseOrder) {
134
- const items = byPhase.get(phase)!;
135
- planLines.push(this.renderPhaseHeaderLine(phase, items, width));
136
- for (const item of items) {
137
- const isSelected = rowCount === this.selectedIndex;
138
- if (isSelected) selectedLineIndex = planLines.length;
139
- const isBlocked =
140
- item.status === 'pending' &&
141
- item.dependencies !== undefined &&
142
- item.dependencies.length > 0 &&
143
- !item.dependencies.every((depId) => completeIds.has(depId));
144
-
145
- planLines.push(this.renderItem(item, isSelected, isBlocked, width));
146
- rowCount++;
147
- }
148
- }
149
-
150
- this.totalRows = rowCount;
151
- if (this.selectedIndex >= this.totalRows) {
152
- this.selectedIndex = Math.max(0, this.totalRows - 1);
153
- }
154
-
155
- const total = plan.items.length;
156
- const done = plan.items.filter((i) => i.status === 'complete' || i.status === 'skipped').length;
157
- const pct = total > 0 ? Math.round((done / total) * 100) : 0;
158
- const summary: PanelWorkspaceSection = {
159
- title: 'Summary',
160
- lines: [
161
- buildPanelLine(width, [
162
- [' Status ', DEFAULT_PANEL_PALETTE.label],
163
- [plan.status, this.statusColor(plan.status)],
164
- [' Progress ', DEFAULT_PANEL_PALETTE.label],
165
- [`${pct}%`, pct === 100 ? DEFAULT_PANEL_PALETTE.good : DEFAULT_PANEL_PALETTE.info],
166
- [' Items ', DEFAULT_PANEL_PALETTE.label],
167
- [`${done}/${total}`, DEFAULT_PANEL_PALETTE.value],
168
- ]),
169
- ],
170
- };
171
-
172
- const planSection = resolveScrollablePanelSection(width, height, {
173
- intro: plan.title,
174
- footerLines: [
175
- buildPanelLine(width, [[' Up/Down', DEFAULT_PANEL_PALETTE.info], [' navigate', DEFAULT_PANEL_PALETTE.dim]]),
176
- ],
177
- palette: DEFAULT_PANEL_PALETTE,
178
- beforeSections: [summary],
179
- section: {
180
- title: 'Execution Plan',
181
- scrollableLines: planLines,
182
- selectedIndex: selectedLineIndex,
183
- scrollOffset: this.scrollOffset,
184
- minRows: 8,
185
- },
186
- });
187
- this.scrollOffset = planSection.scrollOffset;
188
-
189
- return buildPanelWorkspace(width, height, {
190
- title: ` Plan Dashboard`,
191
- intro: plan.title,
192
- sections: [
193
- summary,
194
- planSection.section,
195
- ],
196
- footerLines: [
197
- buildPanelLine(width, [[' Up/Down', DEFAULT_PANEL_PALETTE.info], [' navigate', DEFAULT_PANEL_PALETTE.dim]]),
198
- ],
199
- palette: DEFAULT_PANEL_PALETTE,
200
- });
201
- }
202
-
203
- // --------------------------------------------------------------------------
204
- // Header — title + overall completion percentage
205
- // --------------------------------------------------------------------------
206
-
207
- private renderPhaseHeaderLine(phase: string, items: PlanItem[], width: number): Line {
208
- const done = items.filter(
209
- (i) => i.status === 'complete' || i.status === 'skipped',
210
- ).length;
211
- const total = items.length;
212
- const active = items.some((i) => i.status === 'in_progress');
213
- const failed = items.some((i) => i.status === 'failed');
214
-
215
- const phaseFg = failed ? '#ef4444' : active ? '#00ffff' : done === total ? '#22c55e' : '250';
216
-
217
- const barW = 8;
218
- const filledB = total > 0 ? Math.round((done / total) * barW) : 0;
219
- const bar = '#'.repeat(filledB) + '-'.repeat(barW - filledB);
220
-
221
- const progressText = `[${bar}] ${done}/${total}`;
222
- const phaseText = ` > ${phase}`;
223
- const spacer = Math.max(1, width - phaseText.length - progressText.length - 1);
224
- return buildPanelLine(width, [
225
- [phaseText, phaseFg],
226
- [' '.repeat(spacer), phaseFg],
227
- [progressText, phaseFg],
228
- [' ', phaseFg],
229
- ]);
230
- }
231
-
232
- // --------------------------------------------------------------------------
233
- // Individual item
234
- // --------------------------------------------------------------------------
235
-
236
- private renderItem(
237
- item: PlanItem,
238
- isSelected: boolean,
239
- isBlocked: boolean,
240
- width: number,
241
- ): Line {
242
- const icon = STATUS_ICON[item.status];
243
- const fg = isBlocked ? '238' : STATUS_FG[item.status];
244
- const dim = item.status === 'skipped' || isBlocked;
245
-
246
- // Indent blocked items to visually signal they depend on others
247
- const indent = isBlocked ? ' ' : ' ';
248
- const selectedMark = isSelected ? '▸' : ' ';
249
-
250
- let text = `${selectedMark}${indent}${icon} ${item.description}`;
251
-
252
- // Append agent ID for in-progress and complete items
253
- if (item.agentId && (item.status === 'in_progress' || item.status === 'complete')) {
254
- text += ` [${item.agentId}]`;
255
- }
256
-
257
- // Append dependency note for blocked items (first unmet dep description)
258
- if (isBlocked && item.dependencies && item.dependencies.length > 0) {
259
- text += ' (blocked)';
260
- }
261
-
262
- return buildPanelLine(width, [[text, fg, isSelected ? '#1e293b' : undefined]]);
263
- }
264
-
265
- private statusColor(status: ExecutionPlan['status']): string {
266
- return status === 'complete'
267
- ? DEFAULT_PANEL_PALETTE.good
268
- : status === 'failed'
269
- ? DEFAULT_PANEL_PALETTE.bad
270
- : status === 'active'
271
- ? DEFAULT_PANEL_PALETTE.info
272
- : DEFAULT_PANEL_PALETTE.dim;
273
- }
274
- }