@aemonge-dev/pi-stardeck 0.0.0-stage → 0.5.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/LICENSE +21 -0
- package/README.md +239 -2
- package/demo/pi-stardeck.tape +59 -0
- package/docs/architecture.md +103 -0
- package/docs/assets/pi-stardeck.gif +0 -0
- package/docs/development.md +128 -0
- package/licenses/README.md +17 -0
- package/licenses/pi-fancy-footer-LICENSE +21 -0
- package/licenses/pi-vim-LICENSE +21 -0
- package/package.json +81 -4
- package/packages/pi-fancy-footer-full-palette/LICENSE +21 -0
- package/packages/pi-fancy-footer-full-palette/LOCAL-CHANGES.md +41 -0
- package/packages/pi-fancy-footer-full-palette/README.md +468 -0
- package/packages/pi-fancy-footer-full-palette/package.json +52 -0
- package/packages/pi-fancy-footer-full-palette/src/api.ts +204 -0
- package/packages/pi-fancy-footer-full-palette/src/config-editor.ts +634 -0
- package/packages/pi-fancy-footer-full-palette/src/config.ts +852 -0
- package/packages/pi-fancy-footer-full-palette/src/data-widgets.ts +259 -0
- package/packages/pi-fancy-footer-full-palette/src/git.ts +130 -0
- package/packages/pi-fancy-footer-full-palette/src/index.ts +479 -0
- package/packages/pi-fancy-footer-full-palette/src/layout.ts +309 -0
- package/packages/pi-fancy-footer-full-palette/src/provider-status.ts +1466 -0
- package/packages/pi-fancy-footer-full-palette/src/render.ts +1061 -0
- package/packages/pi-fancy-footer-full-palette/src/shared.ts +903 -0
- package/packages/pi-stardeck/README.md +219 -0
- package/packages/pi-stardeck/index.ts +691 -0
- package/packages/pi-stardeck/package.json +32 -0
- package/packages/pi-stardeck/src/activity-age.ts +184 -0
- package/packages/pi-stardeck/src/capabilities.ts +105 -0
- package/packages/pi-stardeck/src/deck.ts +807 -0
- package/packages/pi-stardeck/src/gauge.ts +1323 -0
- package/packages/pi-stardeck/src/git-refresh.ts +5 -0
- package/packages/pi-stardeck/src/process-resources.ts +428 -0
- package/packages/pi-stardeck/src/title-state.ts +195 -0
- package/packages/pi-stardeck/src/title.ts +443 -0
- package/packages/pi-vim-top-border/LICENSE +21 -0
- package/packages/pi-vim-top-border/LOCAL-CHANGES.md +71 -0
- package/packages/pi-vim-top-border/README.md +577 -0
- package/packages/pi-vim-top-border/clipboard-mirror.ts +451 -0
- package/packages/pi-vim-top-border/clipboard-policy.ts +23 -0
- package/packages/pi-vim-top-border/cursor-shape.ts +131 -0
- package/packages/pi-vim-top-border/index.ts +4195 -0
- package/packages/pi-vim-top-border/input-keys.ts +49 -0
- package/packages/pi-vim-top-border/mode-change-command.ts +120 -0
- package/packages/pi-vim-top-border/mode-colors.ts +97 -0
- package/packages/pi-vim-top-border/mode-label.ts +62 -0
- package/packages/pi-vim-top-border/motions.ts +297 -0
- package/packages/pi-vim-top-border/package.json +47 -0
- package/packages/pi-vim-top-border/prompt-external-editor.ts +152 -0
- package/packages/pi-vim-top-border/prompt-rail.ts +334 -0
- package/packages/pi-vim-top-border/prompt-status.ts +131 -0
- package/packages/pi-vim-top-border/settings.ts +287 -0
- package/packages/pi-vim-top-border/text-objects.ts +389 -0
- package/packages/pi-vim-top-border/types.ts +51 -0
- package/packages/pi-vim-top-border/visual.ts +65 -0
- package/packages/pi-vim-top-border/word-boundary-cache.ts +196 -0
- package/packages/status/README.md +398 -0
- package/packages/status/index.ts +1717 -0
- package/packages/status/package.json +33 -0
- package/packages/status/src/active-work.ts +235 -0
- package/packages/status/src/config.ts +218 -0
- package/packages/status/src/diagnostics.ts +238 -0
- package/packages/status/src/goal-block.ts +377 -0
- package/packages/status/src/goal.ts +170 -0
- package/packages/status/src/ledger.ts +101 -0
- package/packages/status/src/openspec.ts +394 -0
- package/packages/status/src/orchestration.ts +237 -0
- package/packages/status/src/publisher.ts +1294 -0
- package/packages/status/src/reducer.ts +190 -0
- package/packages/status/src/runtime-runs.ts +267 -0
- package/packages/status/src/state.ts +178 -0
- package/packages/status/src/title-activity.ts +224 -0
- package/packages/status/src/title-state.ts +218 -0
- package/packages/status/src/turn-cost.ts +63 -0
- package/packages/status/src/types.ts +228 -0
- package/src/deck-surface.ts +46 -0
- package/src/health.ts +228 -0
- package/src/index.ts +28 -0
- package/src/pi-status.ts +334 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
# status
|
|
2
|
+
|
|
3
|
+
A small local [Pi](https://pi.dev) extension that gathers project status and publishes
|
|
4
|
+
structured widgets to `pi-fancy-footer`. It never renders a footer, status block, or
|
|
5
|
+
editor widget itself.
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Pi tool lifecycle + session/Goal metadata + OpenSpec CLI + aggregate JSON state
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
normalized immutable state
|
|
14
|
+
│
|
|
15
|
+
▼
|
|
16
|
+
bounded header events + pi-fancy-footer snapshots
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The five stable widget IDs are:
|
|
20
|
+
|
|
21
|
+
- `galactica.work`
|
|
22
|
+
- `galactica.openspec-progress`
|
|
23
|
+
- `galactica.openspec`
|
|
24
|
+
- `galactica.diagnostics`
|
|
25
|
+
- `galactica.orchestration`
|
|
26
|
+
|
|
27
|
+
`pi-fancy-footer` remains the only visible footer renderer and supplies native model,
|
|
28
|
+
thinking, context, quota, location, Git, pull-request, and diff information.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
This repository loads the package from Pi settings:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"packages": ["npm:pi-fancy-footer", "./packages/status"]
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The relative package path is resolved from `~/.pi/agent/settings.json`, so the managed
|
|
41
|
+
source lives at `.pi/agent/packages/status` in Galactica.
|
|
42
|
+
|
|
43
|
+
## OpenSpec detection
|
|
44
|
+
|
|
45
|
+
The provider uses the installed OpenSpec CLI and reads only each listed change's bounded
|
|
46
|
+
`.openspec.yaml` schema marker to distinguish Ramona Ideas from Plans:
|
|
47
|
+
|
|
48
|
+
1. `openspec list --json` finds changes, aggregate progress, state, and the OpenSpec
|
|
49
|
+
root. The always-visible footer totals completed/total Plans and Tasks. Changes
|
|
50
|
+
marked `schema: ramona-idea` are excluded from Plan and Task totals; generic OpenSpec
|
|
51
|
+
changes count as Plans.
|
|
52
|
+
2. An explicitly selected change is matched by exact ID. With no explicit selection,
|
|
53
|
+
focused collection stops; repository recency never chooses a change.
|
|
54
|
+
3. `openspec show <change> --json` supplies the concise title.
|
|
55
|
+
4. `openspec instructions apply --change <change> --json` supplies task state and the
|
|
56
|
+
schema-resolved task artifact path.
|
|
57
|
+
5. The task artifact is read once per refresh to recover labels such as `3.8` and kinds
|
|
58
|
+
such as Story, Spike, Lab, or Hack.
|
|
59
|
+
|
|
60
|
+
The session focus takes precedence over configured `openspec.change`, which takes
|
|
61
|
+
precedence over `PI_OPENSPEC_CHANGE`. Configuration and environment values can select a
|
|
62
|
+
change for collection/debugging, but they do not create session task focus or expose an
|
|
63
|
+
active OpenSpec footer by themselves.
|
|
64
|
+
|
|
65
|
+
## Session focus and terminal title
|
|
66
|
+
|
|
67
|
+
A Pi session has zero or one explicit OpenSpec task focus, optional read-only Pi Goal
|
|
68
|
+
state, and an independent ephemeral Session Work state. Display priority is OpenSpec
|
|
69
|
+
Task → Goal → Session Work → safe direct fallback. OpenSpec focus clears active Session
|
|
70
|
+
Work when acquired, preventing hidden or stale work from resurfacing later.
|
|
71
|
+
|
|
72
|
+
Session Work is stored only as versioned custom entries on the active Pi session branch;
|
|
73
|
+
it never creates a repository status file. It supports this lifecycle:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
/work
|
|
77
|
+
/work set Implement session metadata
|
|
78
|
+
/work validate
|
|
79
|
+
/work clear
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
When no OpenSpec portfolio is available, the matching row-one footer fallback is the
|
|
83
|
+
compact `▶ Focus` or `◇ Validate`; an active Goal uses ` Goal`, and an entirely empty
|
|
84
|
+
project uses ` no OpenSpec`. The detailed Session Work intent remains in the header
|
|
85
|
+
instead of being duplicated in the footer. Active and validation states also replace the
|
|
86
|
+
fallback terminal title. Reload, resume, and tree navigation restore the newest valid
|
|
87
|
+
branch entry. The agent-callable `work_focus` tool exposes the same `status`, `set`,
|
|
88
|
+
`validate`, and `clear` actions. The agent-callable `openspec_focus` tool likewise
|
|
89
|
+
shares the command's `status`, safeguarded `set`, deliberate `replace`, and persistent
|
|
90
|
+
`clear` transitions.
|
|
91
|
+
|
|
92
|
+
Global routing belongs to native Ramona policy rather than this status package. This
|
|
93
|
+
package does not inject parent routing prompts, block parent tools, create Session Work
|
|
94
|
+
for a global route, or promote a raw request into OpenSpec focus. It continues to own
|
|
95
|
+
branch-local OpenSpec and Session Work state, commands, restoration, titles, and footer
|
|
96
|
+
publication.
|
|
97
|
+
|
|
98
|
+
The header projection uses the rich lifecycle `understanding`, `working`, `waiting`,
|
|
99
|
+
`assuring`, `learning`, `answering`, `blocked`, `listening`, or `aborted`. It separately
|
|
100
|
+
publishes one explicit selection with OpenSpec Task → Goal → Session Work precedence,
|
|
101
|
+
or `null` when no work is selected. A controlled suggestion enum communicates only
|
|
102
|
+
Human-facing reporting cues such as `requesting-validation`,
|
|
103
|
+
`awaiting-continuation`, or `requesting-redirection`; it never carries generated
|
|
104
|
+
prose. Direct tool
|
|
105
|
+
categories, read-only Pi Goal state, and known Taskflow phases move the lifecycle
|
|
106
|
+
without exposing arguments or raw node prose. Goal state is restored from Pi's canonical
|
|
107
|
+
`goal-state` session entries without enabling Goal RPC. An active Goal renders bounded
|
|
108
|
+
automatic-turn progress from `pi-goal.json`; paused, blocked, limited, external-wait,
|
|
109
|
+
and complete states render controlled labels. Complete projects as
|
|
110
|
+
`awaiting Human validation` rather than Human acceptance. Raw Goal objectives, wait
|
|
111
|
+
reasons, completion summaries, paths, and Goal IDs never enter the visible header. While
|
|
112
|
+
a Goal exists, a session-scoped 500 ms in-memory branch monitor catches idle
|
|
113
|
+
`/goal pause`, clear, and menu transitions; it performs no filesystem, process,
|
|
114
|
+
provider, or network work and stops when Goal state is cleared. A stopped Goal remains
|
|
115
|
+
visible while Pi is idle so its terminal reason is honest, but the next ordinary
|
|
116
|
+
non-Goal turn automatically returns the title to current Ramona, OpenSpec, Session Work,
|
|
117
|
+
or direct activity. This display transition never mutates Goal or focus state; a later
|
|
118
|
+
Goal resume automatically reclaims the title. During a Taskflow tool run, structured
|
|
119
|
+
streaming state temporarily replaces the normal focus with the running top-level phase
|
|
120
|
+
ID, such as `working ⟩ work-fragment`; promoted child IDs and generated output remain
|
|
121
|
+
hidden. Visible assistant text moves it to `answering`; settling with selected work
|
|
122
|
+
moves it to `waiting`; no selected work returns to `listening`. Direct tool starts
|
|
123
|
+
describe the bounded operation, while tool completion immediately moves to a bounded
|
|
124
|
+
transition: read-only inspection → `finalizing current request`, mutation →
|
|
125
|
+
`reviewing applied changes`, and verification → `reviewing check results`. Parallel
|
|
126
|
+
tools keep the newest remaining operation visible until all complete; any failed
|
|
127
|
+
operation transitions to bounded recovery. This prevents a completed command from
|
|
128
|
+
looking permanently active while Pi prepares its next action. A Ctrl-C assistant stop
|
|
129
|
+
reason moves it to `aborted` and remains visible until the next turn resets it to
|
|
130
|
+
`understanding`. Legacy work titles still preserve the existing explicit fallback states for compatible
|
|
131
|
+
consumers. The additive selection field contains only an exact OpenSpec Task, Goal, or
|
|
132
|
+
Session Work; otherwise it is `null`, so the deck renders a stable dim ` —`. `Direct
|
|
133
|
+
response` is never presented as selection and Human prompt text is never copied into it.
|
|
134
|
+
|
|
135
|
+
The header protocol also carries a bounded `activeRuns` aggregate. Bash is active from
|
|
136
|
+
Pi's `tool_execution_start` through `tool_execution_end` and contributes only one child
|
|
137
|
+
run. Subagent progress is read structurally from `pi-subagent` result details: a call is
|
|
138
|
+
active only after `sawAgentStart`, before `sawAgentSettled`, and while its `exitCode`
|
|
139
|
+
remains `-1`. Placeholder headline totals are never used because they include queued
|
|
140
|
+
calls. The aggregate contains only child-run and subagent integers; prompts, agent names,
|
|
141
|
+
PIDs, arguments, and child output are discarded. The main Pi process is intentionally
|
|
142
|
+
absent. The deck always renders both counts in its first-row runtime capsule and changes
|
|
143
|
+
zero/live color instead of publishing state-dependent display visibility.
|
|
144
|
+
|
|
145
|
+
The generic outer request has no `change` or `task` arguments and therefore creates no
|
|
146
|
+
durable focus side effect here. Existing specialized Taskflow calls may still acquire
|
|
147
|
+
exact OpenSpec focus from non-placeholder `change` and `task` arguments. Legacy `none`
|
|
148
|
+
placeholders are ignored. Human slash commands remain Human-owned manual controls; the
|
|
149
|
+
agent tool may act only on explicit Human direction or an exact declared Task handoff,
|
|
150
|
+
never inferred material Plan selection or Human validation.
|
|
151
|
+
|
|
152
|
+
A Pi session acquires OpenSpec focus before an OpenSpec-aware Taskflow tool run executes
|
|
153
|
+
when its input contains string `change` and `task` arguments:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"action": "run",
|
|
158
|
+
"args": {
|
|
159
|
+
"change": "show-active-openspec-in-pi-title",
|
|
160
|
+
"task": "1.1"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Taskflow slash-command invocations do not pass through Pi's `tool_call` hook. Set focus
|
|
166
|
+
manually before those runs:
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
/openspec-focus
|
|
170
|
+
/openspec-focus show-active-openspec-in-pi-title 1.1
|
|
171
|
+
/openspec-focus replace another-change 2.1
|
|
172
|
+
/openspec-focus clear
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Aggregate portfolio progress is independent of focus and remains visible as:
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
7/15 › 36/45
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
It occupies the right side of footer row one, opposite the full PWD and Git state. It
|
|
182
|
+
updates from `openspec list --json`; task-list `` replaces `Plans` and notebook ``
|
|
183
|
+
replaces `Tasks`. If no OpenSpec portfolio exists, the slot prefers compact active scope
|
|
184
|
+
(` Goal`, then `▶ Focus` or `◇ Validate`) before falling back to dim ` no OpenSpec`.
|
|
185
|
+
Focused-change metadata remains separate and does not replace these totals. The
|
|
186
|
+
no-argument form reports the current focus without changing it. The matching tool calls
|
|
187
|
+
are:
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{"action":"status"}
|
|
191
|
+
{"action":"set","change":"show-active-openspec-in-pi-title","task":"1.1"}
|
|
192
|
+
{"action":"replace","change":"another-change","task":"2.1"}
|
|
193
|
+
{"action":"clear"}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`set` acquires empty focus but refuses a different active Task. `replace` makes that
|
|
197
|
+
switch deliberate. Both acquisition paths clear conflicting Session Work before the
|
|
198
|
+
OpenSpec branch entry is appended. Missing or empty identifiers fail without writing an
|
|
199
|
+
entry, while `clear` appends the branch-local no-focus state.
|
|
200
|
+
|
|
201
|
+
A conflicting Taskflow tool run is blocked until focus is cleared or deliberately
|
|
202
|
+
replaced. Focus is stored as a versioned custom entry on the active Pi session branch,
|
|
203
|
+
so reload/resume restores the newest valid task or clear entry. Unrelated turns and
|
|
204
|
+
Taskflow success, failure, blocking, pause, or approval states do not clear focus or
|
|
205
|
+
modify OpenSpec task checkboxes.
|
|
206
|
+
|
|
207
|
+
The extension emits a fallback title immediately at session start, then updates it after
|
|
208
|
+
asynchronous OpenSpec metadata resolves:
|
|
209
|
+
|
|
210
|
+
- focused metadata: `π {change} › {task-id} {short task}`
|
|
211
|
+
- focused IDs only: `π {change} › {task-id}`
|
|
212
|
+
- Session Work validation: `π Validate › {intent}`
|
|
213
|
+
- active Session Work: `π {intent}`
|
|
214
|
+
- no focus: `π {session name || repository basename || cwd basename}`
|
|
215
|
+
|
|
216
|
+
Control characters and repeated whitespace are removed, titles are bounded, and an
|
|
217
|
+
unchanged refresh does not emit a duplicate title update. Without explicit focus, the
|
|
218
|
+
aggregate footer still reports Plan and Task totals without selecting a change. The
|
|
219
|
+
legacy focused-status producer also gives quiet state feedback:
|
|
220
|
+
|
|
221
|
+
- actionable task work exists: dim `○ OpenSpec · no focus`
|
|
222
|
+
- no actionable task work exists: dim `○ OpenSpec · clear`
|
|
223
|
+
- no `openspec/` project exists: row one shows Goal or Focus when active, otherwise dim
|
|
224
|
+
` no OpenSpec`
|
|
225
|
+
- OpenSpec status cannot be read: the last aggregate remains while focused status
|
|
226
|
+
reports unavailable
|
|
227
|
+
|
|
228
|
+
While focused, it prioritizes the active action over duplicated metadata:
|
|
229
|
+
|
|
230
|
+
```text
|
|
231
|
+
[-] 1/2 ▶ 1.1 Create root-level `greeting.txt` with exact contents
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The ratio replaces a redundant percentage, the focused task replaces the change title,
|
|
235
|
+
and regular output is published without a producer-side character cap. Fancy Footer
|
|
236
|
+
therefore truncates only when the allocated terminal width is genuinely exhausted.
|
|
237
|
+
|
|
238
|
+
## Diagnostics sources
|
|
239
|
+
|
|
240
|
+
The first existing aggregate JSON file is used:
|
|
241
|
+
|
|
242
|
+
- `.pi/status/diagnostics.json`
|
|
243
|
+
- `.pi/diagnostics.json`
|
|
244
|
+
- `.galactica/diagnostics.json`
|
|
245
|
+
- `.taskflow/diagnostics.json`
|
|
246
|
+
- `status/diagnostics.json`
|
|
247
|
+
|
|
248
|
+
A configured `sourceFile` takes precedence. Accepted aggregate fields include `errors`,
|
|
249
|
+
`blockers`, `warnings`, `diagnostics`/`findings`, `tests`, `typecheck`, and `updatedAt`;
|
|
250
|
+
nested `summary` and `checks` objects are also accepted. Filenames and word counts are
|
|
251
|
+
never displayed.
|
|
252
|
+
|
|
253
|
+
An optional diagnostics command must be expressed without a shell:
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"diagnostics": {
|
|
258
|
+
"command": ["my-status-command", "--json"],
|
|
259
|
+
"runAutomatically": false
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The equivalent `{ "executable": "...", "args": ["..."] }` form is accepted. It runs only
|
|
265
|
+
on `/galactica-status-refresh`, or at the conservative configured interval when
|
|
266
|
+
`runAutomatically` is true. Pi's argument-array process API enforces the timeout and
|
|
267
|
+
terminates timed-out children.
|
|
268
|
+
|
|
269
|
+
## Orchestration sources
|
|
270
|
+
|
|
271
|
+
The first existing JSON state file is used:
|
|
272
|
+
|
|
273
|
+
- `.pi/status/orchestration.json`
|
|
274
|
+
- `.pi/orchestration.json`
|
|
275
|
+
- `.taskflow/state.json`
|
|
276
|
+
- `.taskflow/run-state.json`
|
|
277
|
+
- `.galactica/orchestration.json`
|
|
278
|
+
|
|
279
|
+
A configured `orchestration.stateFile` takes precedence. Useful fields include `phase`,
|
|
280
|
+
`state`/`status`, `activeWorkers`, `workers`/`agents`, `currentTask`, `openspecTaskId`,
|
|
281
|
+
`startedAt`, `elapsedMs`, and `updatedAt`. While orchestration is running, known phase
|
|
282
|
+
or node vocabulary is classified into an allowlisted title activity—understanding,
|
|
283
|
+
inspection, synthesis, planning, skill proposal, mutation, implementation, change
|
|
284
|
+
review, regression, verification, result review, recovery, waiting reason, or abort—and
|
|
285
|
+
attached to the current OpenSpec, Goal, Session Work, or explicit empty focus. Task
|
|
286
|
+
text, paths, generated prose, and promoted child IDs never enter the lifecycle title;
|
|
287
|
+
unknown vocabulary produces no activity. The bounded top-level phase ID is the only
|
|
288
|
+
exact Taskflow identifier shown. Named Taskflow runs invoked by the assistant through
|
|
289
|
+
Pi's tool API publish controlled activity immediately, then consume structured
|
|
290
|
+
`tool_execution_update` state for the live phase and restore normal focus when tool
|
|
291
|
+
execution ends, so validation is driven by ordinary conversation rather than Human slash
|
|
292
|
+
commands. The legacy `openspecTaskId` field is parsed for compatibility but never
|
|
293
|
+
establishes active task focus. No arbitrary process inspection occurs.
|
|
294
|
+
|
|
295
|
+
## Configuration
|
|
296
|
+
|
|
297
|
+
The optional configuration file is `~/.pi/agent/galactica-status.json` (the actual Pi
|
|
298
|
+
configuration directory in this installation). This repository keeps the source at
|
|
299
|
+
`.pi/agent/galactica-status.json` and links the runtime path to it; the same applies to
|
|
300
|
+
`.pi/agent/fancy-footer.json`. Defaults work without the status-provider file.
|
|
301
|
+
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"version": 1,
|
|
305
|
+
"enabled": true,
|
|
306
|
+
"openspec": {
|
|
307
|
+
"enabled": true,
|
|
308
|
+
"change": null
|
|
309
|
+
},
|
|
310
|
+
"diagnostics": {
|
|
311
|
+
"enabled": true,
|
|
312
|
+
"sourceFile": null,
|
|
313
|
+
"command": null,
|
|
314
|
+
"intervalSeconds": 300,
|
|
315
|
+
"runAutomatically": false,
|
|
316
|
+
"timeoutSeconds": 15
|
|
317
|
+
},
|
|
318
|
+
"orchestration": {
|
|
319
|
+
"enabled": true,
|
|
320
|
+
"stateFile": null
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Unknown or invalid fields are ignored and reported by the debug command; they do not
|
|
326
|
+
prevent Pi from starting. `openspec.change` is an explicit collection target, not a
|
|
327
|
+
session-scoped task focus.
|
|
328
|
+
|
|
329
|
+
## Commands
|
|
330
|
+
|
|
331
|
+
- `/work` — show Session Work; use `set <intent>`, `validate`, or `clear` to transition
|
|
332
|
+
explicit ephemeral focus metadata.
|
|
333
|
+
- `/openspec-focus` — show the current focus; pass `<change> <task>` or
|
|
334
|
+
`set <change> <task>` to focus, `replace <change> <task>` to deliberately replace, or
|
|
335
|
+
`clear` to persist no focus.
|
|
336
|
+
- `/galactica-status` — concise integration and normalized-state summary.
|
|
337
|
+
- `/galactica-status-refresh` — reload configuration and refresh all enabled sources;
|
|
338
|
+
this is the only default trigger for an optional command.
|
|
339
|
+
- `/galactica-status-debug` — project root, detected paths, source metadata, refresh
|
|
340
|
+
timestamps, bounded errors, and currently published snapshots. Raw source files and
|
|
341
|
+
command output are not dumped.
|
|
342
|
+
|
|
343
|
+
## Refresh and failure behavior
|
|
344
|
+
|
|
345
|
+
Initialization is fire-and-forget, so prompt rendering never waits for filesystem or
|
|
346
|
+
subprocess work. The fallback title is emitted synchronously before initialization.
|
|
347
|
+
Results are cached. Only small, directly relevant directories are watched
|
|
348
|
+
non-recursively; events are debounced. Footer snapshots and terminal titles are emitted
|
|
349
|
+
only when changed. Watchers and timers are closed on shutdown/reload.
|
|
350
|
+
|
|
351
|
+
Missing optional state hides its widget. Malformed or transiently unreadable state
|
|
352
|
+
preserves the last good value and marks it stale. Errors remain bounded and visible only
|
|
353
|
+
through debug output. Expensive test suites are never started unless explicitly
|
|
354
|
+
configured.
|
|
355
|
+
|
|
356
|
+
## Widget protocol
|
|
357
|
+
|
|
358
|
+
This package implements the import-free `pi-fancy-footer` **protocol 1** shipped by
|
|
359
|
+
`pi-fancy-footer` **3.0.1**:
|
|
360
|
+
|
|
361
|
+
- channel `pi-fancy-footer:widget`: complete `upsert` and `remove` messages;
|
|
362
|
+
- channel `pi-fancy-footer:ready`: republish current snapshots after footer startup;
|
|
363
|
+
- supported content is sanitized plain text with icon/color, optional theme-native bold,
|
|
364
|
+
and row/position/alignment/fill/minimum-width defaults.
|
|
365
|
+
|
|
366
|
+
Protocol 1 does not expose semantic-status, priority, tooltip, or width-callback fields.
|
|
367
|
+
The producer therefore orders text by semantic priority and publishes complete regular
|
|
368
|
+
content; Fancy Footer owns final width allocation and truncation.
|
|
369
|
+
|
|
370
|
+
Pi 0.84.2 and `pi-fancy-footer` 3.0.1 run on the pnpm-managed Node 24.19.0 runtime,
|
|
371
|
+
satisfying both packages' declared engine requirements.
|
|
372
|
+
|
|
373
|
+
## Adding another provider
|
|
374
|
+
|
|
375
|
+
1. Add a module that returns a normalized domain value without rendering UI.
|
|
376
|
+
2. Add the value to `StatusSnapshot` and the atomic refresh batch.
|
|
377
|
+
3. Convert it to one stable namespaced widget in `publisher.ts`.
|
|
378
|
+
4. Add only direct candidate paths to the non-recursive watcher set.
|
|
379
|
+
5. Test malformed input, stale preservation, unchanged suppression, and removal.
|
|
380
|
+
|
|
381
|
+
## Uninstall
|
|
382
|
+
|
|
383
|
+
From the Galactica repository:
|
|
384
|
+
|
|
385
|
+
```sh
|
|
386
|
+
# Remove the two package entries from .pi/agent/settings.json.
|
|
387
|
+
rm -f ~/.pi/agent/galactica-status.json ~/.pi/agent/fancy-footer.json
|
|
388
|
+
rm -rf .pi/agent/packages/status
|
|
389
|
+
rm -f .pi/agent/galactica-status.json .pi/agent/fancy-footer.json
|
|
390
|
+
mv .pi/agent/extensions/openspec-footer.ts.disabled \
|
|
391
|
+
.pi/agent/extensions/openspec-footer.ts
|
|
392
|
+
mv .pi/agent/extensions/pi-footer.json.disabled \
|
|
393
|
+
.pi/agent/extensions/pi-footer.json
|
|
394
|
+
npm --prefix ~/.pi/agent/npm uninstall pi-fancy-footer
|
|
395
|
+
npm --prefix ~/.pi/agent/npm install pi-footer
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Then restore `npm:pi-footer` in settings and run `/reload` or restart Pi.
|