@groeponline/pi-wishcraft 1.2.0 → 1.3.1
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/CHANGELOG.md +8 -0
- package/ROADMAP.md +142 -204
- package/docs/design/signal.md +51 -48
- package/package.json +1 -1
- package/src/config/appearance.ts +0 -1
- package/src/extension/core/segment-context.ts +20 -20
- package/src/extension/core/state.ts +2 -1
- package/src/extension/core/types.ts +4 -1
- package/src/extension/session/session-lifecycle.ts +9 -65
- package/src/extension/session/session-notifications.ts +91 -0
- package/src/extension/ui/deck/component.ts +46 -13
- package/src/extension/ui/deck/render.ts +4 -4
- package/src/extension/ui/deck/session-snapshot.ts +52 -34
- package/src/extension/ui/deck/types.ts +14 -7
- package/src/extension/ui/signal-layout.ts +0 -1
- package/src/signal/controller.ts +12 -0
- package/src/signal/integration.ts +7 -3
- package/src/theme/tokens/mapping.ts +11 -52
- package/src/theme/tokens/types.ts +3 -36
- package/src/usage/token-budget.ts +23 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.3.1] - 2026-08-25
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- Make protected-main releases promote only an exact bot-generated candidate SHA after its own canonical `Verify` check succeeds.
|
|
9
|
+
- Keep `package-lock.json` version metadata synchronized with release commits and resolve the dev-only `nanoid` advisory at 3.3.18.
|
|
10
|
+
|
|
11
|
+
## [1.3.0] - 2026-08-25
|
|
12
|
+
|
|
5
13
|
## [1.2.0] - 2026-08-24
|
|
6
14
|
|
|
7
15
|
### Changed
|
package/ROADMAP.md
CHANGED
|
@@ -1,208 +1,146 @@
|
|
|
1
1
|
# Roadmap — pi-wishcraft
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
|
28
|
-
|
|
29
|
-
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
-
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
- PR0 design corpus — geland (`docs/design/`).
|
|
106
|
-
- PR1 motion engine — geland (`src/motion/`): één scheduler op de bestaande
|
|
107
|
-
coalescing timer, semantische events, 6 channels, 0 FPS zonder consumers.
|
|
108
|
-
- PR2 semantic tokens — geland (`src/config/tokens.ts`): `PresetDef.tokens`
|
|
109
|
-
is optioneel en `DEFAULT_TOKENS` reproduceert `getDefaultColors()`.
|
|
110
|
-
- PR3 structural presets — geland (`src/config/structural-presets.ts`,
|
|
111
|
-
`src/config/appearance.ts`): 10 signature presets, mixable layers, Nerd/ASCII
|
|
112
|
-
glyph fallbacks; legacy layout presets ongewijzigd.
|
|
113
|
-
- PR4 animated Signal — geland (`src/signal/`): drie lanes, lifecycle-driven
|
|
114
|
-
motion op één gedeelde scheduler, `/signal` primair en 0 FPS in rust.
|
|
115
|
-
- PR5 Deck — geland (`src/extension/ui/deck/`): unified overlay via
|
|
116
|
-
`ctx.ui.custom`, Alt+P en `/wishcraft`, elf routes, jump/search navigatie.
|
|
117
|
-
- PR6 Appearance / Gallery — geland: Deck Motion gallery + composer,
|
|
118
|
-
50+ catalog defs, Enter assigns `powerline.appearance.motion`.
|
|
119
|
-
- PR7 accessibility — geland: `src/theme/detect.ts`,
|
|
120
|
-
`src/motion/accessibility.ts`, `powerline.motionLevel`.
|
|
121
|
-
- PR8 Craft + docs — geland: Deck Skill Workbench, idea/guardrail panes,
|
|
122
|
-
`skills/wishcraft-tui/references/*`, project subagents.
|
|
123
|
-
|
|
124
|
-
## Top-15 track: remaining maturity gaps
|
|
125
|
-
|
|
126
|
-
Written 2026-08-20, rebaselined on 0.27.1 (code review, not this ROADMAP
|
|
127
|
-
alone). Feature density is high; several original gaps closed in
|
|
128
|
-
0.23–0.27. What remains is the maturity layer that separates a top-15 pi
|
|
129
|
-
extension from a feature-rich prototype.
|
|
130
|
-
|
|
131
|
-
### Already shipped (0.22.x–0.27.x)
|
|
132
|
-
- **CHE-41 per-segment detail** — `→` in Navigate, snapshot on open (0.22.1).
|
|
133
|
-
- **CHE-42 drill-down** — #19 + Configure in #13.
|
|
134
|
-
- **Changelog roll** — version headers drive the what's-new panel.
|
|
135
|
-
- **Per-segment fault isolation** — throwing custom segments show `!id`
|
|
136
|
-
instead of blanking the footer (#34, 0.23.1).
|
|
137
|
-
- **macOS open_ports** — netstat dot-address parsing (#34, 0.23.1).
|
|
138
|
-
- **GitHub Release per npm tag** (#25, 0.23.2).
|
|
139
|
-
- **CodeQL proto-pollution hardening** (#27, 0.23.3).
|
|
140
|
-
- **setupHooks wired** (#26, 0.23.4).
|
|
141
|
-
- **Policy engine** — declarative deny/inject, no spawn (GRO-1418, #29,
|
|
142
|
-
0.24.0).
|
|
143
|
-
- **`/skills doctor`** — broken frontmatter, dupes, unused, budget
|
|
144
|
-
(GRO-1416, #28, 0.24.0 / 0.25.0 tag).
|
|
145
|
-
- **`/skills new` templates** — no marketplace (GRO-1417, #32, 0.26.0).
|
|
146
|
-
- **`/ideas` review overlay** — status, tags, skill insert (GRO-1419, #31,
|
|
147
|
-
0.27.0).
|
|
148
|
-
- **English operator UI** — overlays, skill manager, `/wishcraft` TUI
|
|
149
|
-
(GRO-1422, #24, 0.27.1).
|
|
150
|
-
- **`powerline.skills.count` + read hints + Status trim** (GRO-1420, 0.23.0).
|
|
151
|
-
- **1.0.0 cockpit cut** — README lists doctor, templates, policy, and
|
|
152
|
-
idea-review (GRO-1421). Semver leaves 0.x.
|
|
153
|
-
|
|
154
|
-
### Remaining open gaps (maturity)
|
|
155
|
-
P1 — differentiation and quality:
|
|
156
|
-
1. **Settings contract to pi core.** No `contributes.settings`/schema;
|
|
157
|
-
users hand-edit JSON. *Fix: typed settings schema + contributions.*
|
|
158
|
-
2. **Zero-config first run.** Install still expects JSON edits for the most
|
|
159
|
-
useful features. *Fix: sensible defaults + first-run setup overlay.*
|
|
160
|
-
3. **Perf budget / low-power mode.** Status renders every ~33ms; heavy
|
|
161
|
-
segments (bash-history, git) can hit the hot path. *Fix: configurable
|
|
162
|
-
refresh + lite mode / repeating scheduler with 0 FPS idle. Scheduler landed
|
|
163
|
-
in PR1 (`src/motion/scheduler.ts`); the segment hot path is still open.*
|
|
164
|
-
4. **Accessibility (no-color / reduced-motion).** Truecolor + animations
|
|
165
|
-
(vibes, rainbow think) break on terminals without truecolor. *Fix:
|
|
166
|
-
`NO_COLOR`/8-color + reduced-motion respect (PR7).*
|
|
167
|
-
|
|
168
|
-
P2 — full product, post-1.0:
|
|
169
|
-
5. **Preset editor in-menu** — custom JSON-only today (addressed in PR3 & PR6).
|
|
170
|
-
6. **Skill install from repo/npm** — discovery + doctor exist; install and
|
|
171
|
-
curate missing (addressed in PR8).
|
|
172
|
-
7. **Host-status integration** — `ctx.ui.setStatus` beside the footer so
|
|
173
|
-
status also shows in host UI (`skills.count` is a start; full coverage
|
|
174
|
-
remains).
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
## vNext Milestone: The Stacked PR Plan
|
|
179
|
-
|
|
180
|
-
The complete vNext architecture is detailed in **[`docs/design/vnext-release-plan.md`](docs/design/vnext-release-plan.md)** and executed across 9 stacked pull requests:
|
|
181
|
-
|
|
182
|
-
```mermaid
|
|
183
|
-
graph LR
|
|
184
|
-
PR0["PR0: Design Corpus"] --> PR1["PR1: Motion Engine"]
|
|
185
|
-
PR1 --> PR2["PR2: Semantic Tokens"]
|
|
186
|
-
PR2 --> PR3["PR3: Preset Contract"]
|
|
187
|
-
PR3 --> PR4["PR4: Animated Signal"]
|
|
188
|
-
PR4 --> PR5["PR5: Wishcraft Deck"]
|
|
189
|
-
PR5 --> PR6["PR6: Appearance & Gallery"]
|
|
190
|
-
PR6 --> PR7["PR7: First-Class A11y"]
|
|
191
|
-
PR7 --> PR8["PR8: Craft, Skills & Docs"]
|
|
3
|
+
Baseline: **v1.2.0**, published 2026-08-24.
|
|
4
|
+
|
|
5
|
+
Pi is the engine. Wishcraft is the operator experience layer: Signal, Deck, skills, ideas, shell UX, hooks, repairs and policy without forking Pi core.
|
|
6
|
+
|
|
7
|
+
Historical 0.x/1.0/vNext campaign detail belongs in `CHANGELOG.md` and `docs/design/`. This file describes only the current product contract and work that is still open.
|
|
8
|
+
|
|
9
|
+
## Product boundary
|
|
10
|
+
|
|
11
|
+
Wishcraft may extend the Pi experience, but it does not become:
|
|
12
|
+
|
|
13
|
+
- a Pi fork or second agent engine;
|
|
14
|
+
- a fleet/orchestration control plane;
|
|
15
|
+
- a SaaS integrations bundle;
|
|
16
|
+
- a second plugin runtime competing with Pi extensions;
|
|
17
|
+
- a telemetry collector by default.
|
|
18
|
+
|
|
19
|
+
External systems should connect through small contribution/integration contracts. Vendor-specific control planes belong outside Wishcraft.
|
|
20
|
+
|
|
21
|
+
## Release line
|
|
22
|
+
|
|
23
|
+
| Release | Theme | State | Done means |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| **1.2** | Operator Layer | shipped | Deck, universal Signal, structural appearance, motion gallery/composer, skill workbench and first-class motion accessibility |
|
|
26
|
+
| **1.3** | Hardening | current | release invariant, render-path performance, one token source of truth, explicit renderer/lifecycle contracts, regression coverage |
|
|
27
|
+
| **1.4** | Extension Contract | next | typed settings registry plus small contribution APIs; no new plugin runtime |
|
|
28
|
+
| **1.5** | Craft Ecosystem | later | curated skill/package workflows built on Pi-native distribution and the contribution contract |
|
|
29
|
+
| **2.0** | Stable Experience Platform | target | documented compatibility policy, migrations, performance budgets and stable public extension points |
|
|
30
|
+
|
|
31
|
+
## 1.3 — Hardening
|
|
32
|
+
|
|
33
|
+
No feature dump. This release exists to make the v1.2 surface trustworthy.
|
|
34
|
+
|
|
35
|
+
### P0 — release integrity
|
|
36
|
+
|
|
37
|
+
- One reusable `Verify` contract for PR verification and release gating.
|
|
38
|
+
- Verify includes whitespace, typecheck, unit tests, circular dependency check and Pi package contract.
|
|
39
|
+
- Release jobs depend on Verify and re-check the synchronized `origin/main` tree before tagging.
|
|
40
|
+
- `main` should require the Verify check in repository rules before merge.
|
|
41
|
+
|
|
42
|
+
### P0 — render/runtime performance
|
|
43
|
+
|
|
44
|
+
- Deck paint must not run filesystem-backed skill discovery, skill doctor or settings parsing.
|
|
45
|
+
- Expensive Deck data is cached as static snapshot state and refreshed only on open, relevant navigation or mutation.
|
|
46
|
+
- Live model/Git/context/queue/Signal state remains cheap to repaint.
|
|
47
|
+
- Idle motion stays 0 FPS.
|
|
48
|
+
|
|
49
|
+
### P0 — appearance consistency
|
|
50
|
+
|
|
51
|
+
- `src/config/types.ts` + `src/config/tokens.ts` are the canonical token contract.
|
|
52
|
+
- `src/theme/tokens/*` is compatibility-only; it may re-export but may not define a second palette or semantic mapping.
|
|
53
|
+
- One structural base must paint the same semantic roles regardless of the configuration path used to select it.
|
|
54
|
+
|
|
55
|
+
### P0 — Signal contract
|
|
56
|
+
|
|
57
|
+
- Signal is the universal status renderer for legacy and structural presets.
|
|
58
|
+
- Legacy presets keep their existing segment/layout/color contract unless a structural appearance layer is explicitly selected.
|
|
59
|
+
- Terminal one-shots (`success`, `warning`, `error`) settle to `idle/ready` after their finite burst.
|
|
60
|
+
- Reduced/off/screen-reader modes communicate state without requiring animation.
|
|
61
|
+
|
|
62
|
+
### P1 — verification matrix
|
|
63
|
+
|
|
64
|
+
Add/keep regression coverage for:
|
|
65
|
+
|
|
66
|
+
- widths around 40 / 80 / 120+ columns;
|
|
67
|
+
- ASCII, Nerd Font and `NO_COLOR` rendering;
|
|
68
|
+
- full / reduced / functional / off motion;
|
|
69
|
+
- Deck render hot-path invariants;
|
|
70
|
+
- legacy preset color compatibility;
|
|
71
|
+
- release-gate dependency order;
|
|
72
|
+
- Linux and macOS system-segment parsing.
|
|
73
|
+
|
|
74
|
+
## 1.4 — Extension Contract
|
|
75
|
+
|
|
76
|
+
The next architecture step is **composability**, not more built-in routes.
|
|
77
|
+
|
|
78
|
+
### Typed settings registry
|
|
79
|
+
|
|
80
|
+
One registry should drive:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
settings definition
|
|
84
|
+
│
|
|
85
|
+
├─ parsing + validation
|
|
86
|
+
├─ defaults + migrations
|
|
87
|
+
├─ /wishcraft settings
|
|
88
|
+
├─ Pi settings contribution (where supported)
|
|
89
|
+
└─ generated documentation/examples
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This removes duplicate knowledge about settings and enables a real zero-config first run.
|
|
93
|
+
|
|
94
|
+
### Small contribution API
|
|
95
|
+
|
|
96
|
+
Target capabilities, subject to Pi host APIs:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
registerDeckRoute()
|
|
100
|
+
registerSignalSource()
|
|
101
|
+
registerMotion()
|
|
102
|
+
registerAppearanceContribution()
|
|
103
|
+
registerRecipeOrAction()
|
|
104
|
+
contributeSettings()
|
|
192
105
|
```
|
|
193
106
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
-
|
|
207
|
-
|
|
208
|
-
|
|
107
|
+
Rules:
|
|
108
|
+
|
|
109
|
+
- Pi remains the package/extension runtime.
|
|
110
|
+
- Contributions are data/callback contracts, not arbitrary nested plugin loaders.
|
|
111
|
+
- Public contracts are versioned and capability-scoped.
|
|
112
|
+
- A failing contribution cannot take down Signal or the Deck.
|
|
113
|
+
|
|
114
|
+
## 1.5 — Craft Ecosystem
|
|
115
|
+
|
|
116
|
+
After the contribution/settings contracts are stable:
|
|
117
|
+
|
|
118
|
+
- skill import/install workflows from explicit trusted sources;
|
|
119
|
+
- curated recipes/actions that compose existing Wishcraft/Pi capabilities;
|
|
120
|
+
- package discovery surfaced through Pi-native package distribution rather than a parallel Wishcraft marketplace;
|
|
121
|
+
- export/import of appearance and motion recipes with validation.
|
|
122
|
+
|
|
123
|
+
## 2.0 — Stable Experience Platform
|
|
124
|
+
|
|
125
|
+
2.0 is justified when the public contracts, not the feature count, are stable.
|
|
126
|
+
|
|
127
|
+
Required before 2.0:
|
|
128
|
+
|
|
129
|
+
- compatibility and deprecation policy;
|
|
130
|
+
- settings migrations with round-trip tests;
|
|
131
|
+
- measured render/performance budgets;
|
|
132
|
+
- stable contribution API with fault isolation;
|
|
133
|
+
- release provenance and required repository checks;
|
|
134
|
+
- docs generated from canonical contracts where practical;
|
|
135
|
+
- no known duplicate sources of truth for tokens, settings or release verification.
|
|
136
|
+
|
|
137
|
+
## Always-on engineering rules
|
|
138
|
+
|
|
139
|
+
- English operator UI.
|
|
140
|
+
- No synchronous discovery work in paint/render loops.
|
|
141
|
+
- No background animation when nothing consumes it.
|
|
142
|
+
- Core Pi tools are not silently rewritten by Wishcraft repairs.
|
|
143
|
+
- Policies and hooks remain explicitly disableable.
|
|
144
|
+
- Security-sensitive paths fail closed.
|
|
145
|
+
- Package/release verification runs before npm publication.
|
|
146
|
+
- New features must fit the operator-layer boundary above.
|
package/docs/design/signal.md
CHANGED
|
@@ -1,68 +1,71 @@
|
|
|
1
|
-
# Signal —
|
|
1
|
+
# Signal — Animated status contract
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Signal is Wishcraft's status renderer for stock Pi. `/signal` is primary; `/powerline` remains a compatibility alias. No-args toggles the surface, `/signal menu` opens Navigate / Configure / Status, and `/signal <preset>` changes the information preset.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **Compatibility Alias**: `/powerline` (retained for backward compatibility).
|
|
7
|
+
Signal divides status into three lanes:
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
```text
|
|
10
|
+
LEFT / IDENTITY CENTER / ACTIVITY RIGHT / CONTEXT
|
|
11
|
+
model · git · workspace lifecycle · tool · motion context · queue
|
|
12
|
+
```
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
A typical frame:
|
|
15
15
|
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
│ LEFT LANE CENTER LANE RIGHT LANE │
|
|
19
|
-
│ Model · Git Status Live Activity & Tools Context · Queue │
|
|
20
|
-
├──────────────────────────────┼──────────────────────────────┼────────────────────┤
|
|
21
|
-
│ ◆ GPT-5.6 ╾━━━━ main ━━━━ │ ╾✦╼━━━━ read_file ━━━━━━━ │ ctx █████░ 47% │
|
|
22
|
-
└──────────────────────────────┴──────────────────────────────┴────────────────────┘
|
|
16
|
+
```text
|
|
17
|
+
◆ GPT-5.6 main ╾✦╼ read_file ctx █████░ 47% · q1
|
|
23
18
|
```
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
- Active Model badge (with provider color accent)
|
|
27
|
-
- Git branch and repository clean/dirty status
|
|
28
|
-
- Workspace directory (truncated gracefully on compact displays)
|
|
20
|
+
## Renderer contract
|
|
29
21
|
|
|
30
|
-
|
|
31
|
-
- Current agent state (Thinking, Streaming, Tool Execution)
|
|
32
|
-
- Active tool call indicator (`read_file`, `grep`, `execute_command`)
|
|
33
|
-
- Traveling motion pulse representing data throughput
|
|
22
|
+
**Signal is the universal status-line renderer.** This is intentional, including for the legacy layout preset names (`default`, `minimal`, `compact`, `full`, `nerd`, `ascii`, `chef`). There is no second legacy renderer hidden behind those names.
|
|
34
23
|
|
|
35
|
-
|
|
36
|
-
- Context window progress bar and percentage
|
|
37
|
-
- Queued user/agent instructions count
|
|
38
|
-
- Session cost / token consumption (if enabled)
|
|
24
|
+
Compatibility is preserved at the data/config layer:
|
|
39
25
|
|
|
40
|
-
|
|
26
|
+
- legacy presets still define their existing segment selection, layout options, separators, and explicit colors;
|
|
27
|
+
- with no structural appearance layer selected, legacy preset colors remain exact;
|
|
28
|
+
- structural preset names (`lanternwake` … `crucible`) opt into the vNext appearance personality and semantic-token palette;
|
|
29
|
+
- `powerline.appearance.*` may mix palette, Signal grammar, chrome, glyphs, deck, welcome, and motion independently.
|
|
41
30
|
|
|
42
|
-
|
|
31
|
+
In other words: **one renderer, two compatible preset contracts**. A future change that restores a second renderer or silently remaps legacy colors is a breaking change and requires explicit migration tests.
|
|
43
32
|
|
|
44
|
-
|
|
33
|
+
## Three lanes
|
|
45
34
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
t1: ◆ GPT-5.6 ━╾▓▒░━━━ main ━━━━━━━━━ read ━━━━━━━━━ ctx 47%
|
|
50
|
-
t2: ◆ GPT-5.6 ━━━╾▓▒░━ main ━━━━━━━━━ read ━━━━━━━━━ ctx 47%
|
|
51
|
-
t3: ◆ GPT-5.6 ━━━━━━━━ main ╾▓▒░━━━━━ read ━━━━━━━━━ ctx 47%
|
|
52
|
-
```
|
|
35
|
+
1. **Identity / workspace** — model, Git state, path/workspace identity.
|
|
36
|
+
2. **Activity** — thinking, streaming, tool execution, compacting and one-shot outcomes.
|
|
37
|
+
3. **Context / queue** — context usage and queued/parked work.
|
|
53
38
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
Width pressure is resolved inside Signal; lanes may compact or omit optional detail, but their semantic order stays identity → activity → context.
|
|
40
|
+
|
|
41
|
+
## Motion lifecycle
|
|
42
|
+
|
|
43
|
+
Signal owns no timer. It leases the shared MotionScheduler only while a motion channel needs frames.
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
idle / ready 0 FPS
|
|
47
|
+
│
|
|
48
|
+
├─ thinking / streaming / tool.start / compact → active state
|
|
49
|
+
│
|
|
50
|
+
└─ success | warning | error → finite burst
|
|
51
|
+
↓
|
|
52
|
+
idle / ready
|
|
53
|
+
0 FPS
|
|
59
54
|
```
|
|
60
55
|
|
|
61
|
-
|
|
56
|
+
Terminal one-shots (`success`, `warning`, `error`) settle their semantic state back to `idle/ready` when the final frame completes. This prevents a completed agent run from leaving `done` painted indefinitely without keeping a background timer alive.
|
|
57
|
+
|
|
58
|
+
Reduced/functional/off motion policies may suppress frames entirely; status text must still communicate the state. `NO_COLOR`, screen-reader flags and ASCII fallback are first-class inputs to the same policy.
|
|
59
|
+
|
|
60
|
+
## Fault isolation
|
|
61
|
+
|
|
62
|
+
Signal builds on Wishcraft's segment isolation:
|
|
63
|
+
|
|
64
|
+
- a failing custom segment is isolated instead of blanking the full status surface;
|
|
65
|
+
- cached Git/session state is preferred during transient refreshes;
|
|
66
|
+
- separators collapse around hidden/empty segments;
|
|
67
|
+
- rendering must not perform unrelated discovery work such as the Deck skill doctor.
|
|
62
68
|
|
|
63
|
-
##
|
|
69
|
+
## Performance invariant
|
|
64
70
|
|
|
65
|
-
|
|
66
|
-
- Every segment executes in an isolated `try/catch` wrapper.
|
|
67
|
-
- If an individual segment fails (e.g. git command timeout or unexpected API response), it degrades gracefully to a silent fallback or a compact warning glyph without crashing the surrounding status line.
|
|
68
|
-
- Segment separators adjust dynamically when neighboring segments are hidden or empty.
|
|
71
|
+
Idle is 0 FPS. Continuous animation uses the shared coalescing scheduler. Expensive filesystem-backed discovery belongs outside paint/render paths; status rendering consumes already-resolved/cached state.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@groeponline/pi-wishcraft",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Operator cockpit for Pi: live powerline status, searchable skills, idea queue, sticky Bash, hooks, policy controls, and session UX.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
package/src/config/appearance.ts
CHANGED
|
@@ -62,7 +62,6 @@ export function resolveAppearanceMix(
|
|
|
62
62
|
config: AppearanceMixConfig = {},
|
|
63
63
|
): ResolvedAppearance {
|
|
64
64
|
const baseName = config.base ?? "lanternwake";
|
|
65
|
-
const base = getStructuralPreset(baseName);
|
|
66
65
|
|
|
67
66
|
const paletteName = layerPreset(config, "palette", baseName);
|
|
68
67
|
const signalName = layerPreset(config, "signalLayout", baseName);
|
|
@@ -15,14 +15,8 @@ import { getDefaultColors } from "../../theme/theme.ts";
|
|
|
15
15
|
import { getGitStatus } from "../../git/status.ts";
|
|
16
16
|
import { getQueueContext } from "../queue/queue-context.ts";
|
|
17
17
|
import { getUsageTokenTotal } from "../../usage/ledger.ts";
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
loadUsageFileFromDisk,
|
|
21
|
-
tokenTotal,
|
|
22
|
-
totalsForRange,
|
|
23
|
-
} from "../../usage/usage-store.ts";
|
|
24
|
-
import { parseTokenBudget } from "../../usage/token-budget.ts";
|
|
25
|
-
import { readSettings } from "../settings/settings-io.ts";
|
|
18
|
+
import { tokenBudgetSnapshotForDay } from "../../usage/token-budget.ts";
|
|
19
|
+
import { dayKey } from "../../usage/usage-store.ts";
|
|
26
20
|
import {
|
|
27
21
|
CUSTOM_COMPACTION_STATUS_KEY,
|
|
28
22
|
EDITOR_STATUS_DEFER_MS,
|
|
@@ -120,10 +114,16 @@ export function installFooterStatusRepaintHook(
|
|
|
120
114
|
};
|
|
121
115
|
}
|
|
122
116
|
|
|
117
|
+
export interface BuildSegmentContextOptions {
|
|
118
|
+
/** Omit token-budget data from lightweight UI snapshots. */
|
|
119
|
+
includeTokenBudget?: boolean;
|
|
120
|
+
}
|
|
121
|
+
|
|
123
122
|
export function buildSegmentContext(
|
|
124
123
|
rt: RuntimeState,
|
|
125
124
|
ctx: any,
|
|
126
125
|
theme: Theme,
|
|
126
|
+
options: BuildSegmentContextOptions = {},
|
|
127
127
|
): SegmentContext {
|
|
128
128
|
const presetDef = getPreset(config.preset);
|
|
129
129
|
const colors: ColorScheme = liveColorScheme(
|
|
@@ -205,6 +205,10 @@ export function buildSegmentContext(
|
|
|
205
205
|
getQueueContext(ctx),
|
|
206
206
|
rt.powerlineCompacting,
|
|
207
207
|
);
|
|
208
|
+
const budgetSnapshot = tokenBudgetSnapshotForDay(
|
|
209
|
+
rt.tokenBudgetSnapshot,
|
|
210
|
+
dayKey(Date.now()),
|
|
211
|
+
);
|
|
208
212
|
|
|
209
213
|
return {
|
|
210
214
|
model: ctx.model,
|
|
@@ -234,18 +238,14 @@ export function buildSegmentContext(
|
|
|
234
238
|
effectiveCustomItems,
|
|
235
239
|
options: segmentOptions,
|
|
236
240
|
segmentLabels: new Map(Object.entries(config.segmentLabels)),
|
|
237
|
-
tokenBudget:
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
totalsForRange(loadUsageFileFromDisk(), todayStart, now + 1),
|
|
245
|
-
);
|
|
246
|
-
return { dailyLimit, dailyUsed };
|
|
247
|
-
})(),
|
|
241
|
+
tokenBudget:
|
|
242
|
+
options.includeTokenBudget === false
|
|
243
|
+
? undefined
|
|
244
|
+
: {
|
|
245
|
+
dailyLimit: budgetSnapshot.dailyLimit,
|
|
246
|
+
dailyUsed: budgetSnapshot.dailyUsed,
|
|
247
|
+
},
|
|
248
248
|
theme,
|
|
249
249
|
colors,
|
|
250
250
|
};
|
|
251
|
-
}
|
|
251
|
+
}
|
|
@@ -117,6 +117,7 @@ export function createRuntimeState(
|
|
|
117
117
|
currentEditor: null,
|
|
118
118
|
costAlertNotified: false,
|
|
119
119
|
tokenBudgetNotifiedLevel: 0,
|
|
120
|
+
tokenBudgetSnapshot: { day: "", dailyLimit: null, dailyUsed: 0 },
|
|
120
121
|
bashModeActive: false,
|
|
121
122
|
bashTranscript: new BashTranscriptStore(bashModeSettings),
|
|
122
123
|
bashCompletionEngine: new BashCompletionEngine(),
|
|
@@ -174,4 +175,4 @@ export function createRuntimeState(
|
|
|
174
175
|
});
|
|
175
176
|
|
|
176
177
|
return rt;
|
|
177
|
-
}
|
|
178
|
+
}
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
SessionTokenStatsCache,
|
|
12
12
|
} from "../../usage/ledger.ts";
|
|
13
13
|
import type { CoreContextUsageCache } from "../../usage/context.ts";
|
|
14
|
+
import type { TokenBudgetSnapshot } from "../../usage/token-budget.ts";
|
|
14
15
|
import type { WelcomeDismissScheduler } from "../../welcome/auto-dismiss.ts";
|
|
15
16
|
import type { RenderScheduler } from "../../render/timer.ts";
|
|
16
17
|
import type { MotionPolicy, MotionScheduler } from "../../motion/index.ts";
|
|
@@ -68,6 +69,8 @@ export interface RuntimeState {
|
|
|
68
69
|
costAlertNotified: boolean;
|
|
69
70
|
/** Highest daily-budget warning already shown this session (0 / 80 / 100). */
|
|
70
71
|
tokenBudgetNotifiedLevel: 0 | 80 | 100;
|
|
72
|
+
/** Event-driven token-budget snapshot consumed by render paths without disk I/O. */
|
|
73
|
+
tokenBudgetSnapshot: TokenBudgetSnapshot;
|
|
71
74
|
bashModeActive: boolean;
|
|
72
75
|
bashTranscript: BashTranscriptStore;
|
|
73
76
|
bashCompletionEngine: BashCompletionEngine;
|
|
@@ -105,4 +108,4 @@ export interface RuntimeState {
|
|
|
105
108
|
motionPolicy: MotionPolicy;
|
|
106
109
|
/** Live Signal event, motion frame, and activity label. */
|
|
107
110
|
signal: SignalRuntime;
|
|
108
|
-
}
|
|
111
|
+
}
|