@aemonge-dev/pi-stardeck 0.10.0 → 0.12.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.
@@ -5,7 +5,6 @@ import type { LspCapability, McpCapability } from './capabilities.ts';
5
5
  import type {
6
6
  FooterTelemetrySnapshot,
7
7
  GitStatusSummary,
8
- HeaderActivity,
9
8
  HeaderSnapshot,
10
9
  PiStatusSnapshot,
11
10
  VimMode,
@@ -279,82 +278,34 @@ function spanTreeRows(state: HeaderDeckState, width: number, theme: Theme): stri
279
278
  });
280
279
  }
281
280
 
282
- const ACTIVITY_LABELS: Record<HeaderActivity['kind'], string> = {
283
- understanding: 'interpreting',
284
- inspection: 'inspecting',
285
- synthesis: 'synthesizing',
286
- planning: 'planning',
287
- 'skill-proposal': 'proposing skill',
288
- mutation: 'updating',
289
- implementation: 'implementing',
290
- 'change-review': 'reviewing change',
291
- regression: 'testing',
292
- verification: 'checking',
293
- 'result-review': 'reviewing result',
294
- answering: 'answering',
295
- recovery: 'recovering',
296
- 'awaiting-validation': 'validation',
297
- 'awaiting-input': 'input',
298
- 'operation-aborted': 'stopped',
299
- };
300
-
301
- function activityLabel(state: HeaderDeckState): string {
302
- const pathActivity = state.header?.work?.activityPath?.at(-1);
303
- const pathLabel = safeText(pathActivity?.compact || pathActivity?.label || '');
304
- if (pathLabel) return pathLabel;
305
- const activity = state.header?.work?.activity;
306
- // `awaiting-*` kinds are the rest face — they never speak for the band
307
- // (a focused session still retires; quiet-activity-row amendment).
308
- if (!activity || activity.kind.startsWith('awaiting-')) return '';
309
- return ACTIVITY_LABELS[activity.kind];
310
- }
311
-
312
- /** `editing deck.ts` / `reading schema.yaml` / `subagent: scout`. */
281
+ /** The band speaks only when an observed activity is live — one of the
282
+ * five title-state classes (editing/reading/grepping/bash/subagent).
283
+ * Fabricated phase words (`interpreting`, `planning`, …), the legacy
284
+ * activity projection, and the `awaiting Human` placeholder are gone
285
+ * (Human-directed simplify-deck-defaults): Pi's restored native working
286
+ * indicator owns mid-turn liveness, and the deck narrates only observed
287
+ * reality. */
313
288
  function titleActivityLabel(activity: { class: string; target: string }): string {
314
289
  return activity.class === 'subagent'
315
290
  ? `subagent: ${activity.target}`
316
291
  : `${activity.class} ${activity.target}`;
317
292
  }
318
293
 
319
- /** The line-3 band speaks when either side carries a real signal:
320
- * an observed activity (title-state or legacy) or a turn meter that
321
- * cost tokens or time. Both idle (`awaiting Human` + `— · 0 tok` or
322
- * no meter) is zero activity — the band and its seam retire
323
- * (Human-directed 2026-10-20, quiet-activity-row). */
324
- /** Live phase word from the header's kind-based activity projection —
325
- * fills the gaps between tools (thinking, planning, checking) so the
326
- * band never claims `awaiting Human` mid-turn. The `awaiting-*` kinds
327
- * are the REST face (awaiting Human review/input after settle): they
328
- * never speak for the band, or a focused session would never rest
329
- * (quiet-activity-row amendment). */
330
- function liveKindLabel(state: HeaderDeckState): string {
331
- const activity = state.header?.activity ?? null;
332
- if (!activity || activity.kind.startsWith('awaiting-')) return '';
333
- return ACTIVITY_LABELS[activity.kind] ?? '';
334
- }
335
-
336
- /** The band's current left label: the precise title-state activity when a
337
- * tool is observed, else the live phase word; empty when truly idle. */
294
+ /** The band's current label: the live observed activity; empty when
295
+ * nothing is observed — the band then retires wholesale. */
338
296
  function observedActivityLabel(state: HeaderDeckState): string {
339
- const title = state.header?.title ?? null;
340
- if (title) {
341
- return title.activity ? titleActivityLabel(title.activity) : liveKindLabel(state);
342
- }
343
- return activityLabel(state) || liveKindLabel(state);
297
+ const activity = state.header?.title?.activity ?? null;
298
+ return activity ? titleActivityLabel(activity) : '';
344
299
  }
345
300
 
346
301
  function activityBandSpeaks(state: HeaderDeckState): boolean {
347
- const activitySpeaks = observedActivityLabel(state) !== '';
348
- const turn = state.header?.turn ?? null;
349
- const costSpeaks = turn !== null && (turn.tokens > 0 || turn.elapsedMs > 0);
350
- return activitySpeaks || costSpeaks;
302
+ return observedActivityLabel(state) !== '';
351
303
  }
352
304
 
353
305
  function activityTile(state: HeaderDeckState, theme: Theme): string {
354
- // Line 3 left: the observed activity owns the slot — the live phase word
355
- // between tools, `awaiting Human` only when the session truly rests.
356
- const label = observedActivityLabel(state);
357
- return label ? color(theme, 'text', label) : color(theme, 'dim', 'awaiting Human');
306
+ // Line 3 left: the observed activity owns the slot; the turn cluster
307
+ // rides its right side and retires with it.
308
+ return color(theme, 'text', observedActivityLabel(state));
358
309
  }
359
310
 
360
311
  function turnCostTile(state: HeaderDeckState, theme: Theme): string {
@@ -96,12 +96,7 @@ export type HeaderWork = {
96
96
  activityPath?: HeaderActivitySegment[];
97
97
  };
98
98
 
99
- export const HEADER_SELECTION_SOURCES = [
100
- 'openspec',
101
- 'session-work',
102
- 'subject',
103
- 'legacy',
104
- ] as const;
99
+ export const HEADER_SELECTION_SOURCES = ['openspec', 'subject', 'legacy'] as const;
105
100
 
106
101
  export type HeaderSelection = {
107
102
  source: (typeof HEADER_SELECTION_SOURCES)[number];
@@ -191,40 +186,6 @@ export const HEADER_PRESENTATION = {
191
186
  locationColor: 'success',
192
187
  } as const;
193
188
 
194
- export const IDLE_HEADER_WORK: HeaderWork = {
195
- lifecycle: 'listening',
196
- titles: ['no focused task'],
197
- color: 'accent',
198
- };
199
-
200
- export function displayedHeaderWork(work: HeaderWork | null | undefined): {
201
- work: HeaderWork;
202
- idle: boolean;
203
- } {
204
- return work ? { work, idle: false } : { work: IDLE_HEADER_WORK, idle: true };
205
- }
206
-
207
- export function runtimeHeaderWork(
208
- work: HeaderWork | null | undefined,
209
- agentBusy: boolean,
210
- ): { work: HeaderWork; idle: boolean } {
211
- const displayed = displayedHeaderWork(work);
212
- if (!agentBusy || !displayed.idle) return displayed;
213
- return {
214
- work: {
215
- lifecycle: 'understanding',
216
- titles: ['no focus'],
217
- color: 'accent',
218
- activity: { kind: 'understanding' },
219
- },
220
- idle: false,
221
- };
222
- }
223
-
224
- export function lifecycleStatusLabel(work: HeaderWork | null | undefined): string {
225
- return work ? `⟩ ${work.lifecycle}` : '⟩';
226
- }
227
-
228
189
  export type ContextGauge = {
229
190
  percent: number;
230
191
  percentText: string;
@@ -90,10 +90,10 @@ branch entry. The agent-callable `openspec_focus` tool shares the command's `sta
90
90
  safeguarded `set`, deliberate `replace`, validating `validate`, and persistent `clear`
91
91
  transitions; the `awaitingValidation` flag marks a focused task as awaiting Human
92
92
  validation and auto-clears on the next `set`, `replace`, or `clear`. The
93
- agent-callable `title` tool sets the sanitized session title shown when no OpenSpec
94
- focus owns the row. The retired `work_focus` and `stage` instruments are gone: stages
95
- derive from events and Taskflow phases, and legacy `session-work` entries from old
96
- sessions still restore and render, fail-soft.
93
+ retired `work_focus`, `stage`, and `title` instruments are gone: stages
94
+ derive from events and Taskflow phases, the focus row falls back to the
95
+ native session name (named by `pi-title`) and then to legacy `session-subject`
96
+ entries from old sessions, read defensively and fail-soft.
97
97
 
98
98
  Global routing belongs to native Ramona policy rather than this status package. This
99
99
  package does not inject parent routing prompts, block parent tools, create Session Work