pi-crew 0.9.50 → 0.9.51
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 +115 -0
- package/dist/build-meta.json +42 -33
- package/dist/index.mjs +149 -54
- package/dist/index.mjs.map +4 -4
- package/docs/decisions/2026-07-26-c6-mascot-visibility-not-wired.md +84 -0
- package/package.json +1 -1
- package/skills/distill-software/SKILL.md +24 -1
- package/src/ui/live-run-sidebar.ts +5 -13
- package/src/ui/loaders.ts +6 -176
- package/src/ui/mascot.ts +14 -1
- package/src/ui/render-scheduler.ts +60 -6
- package/src/ui/run-dashboard.ts +12 -21
- package/src/ui/shared-overlay-scheduler.ts +96 -0
- package/src/ui/widget/index.ts +45 -11
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,121 @@
|
|
|
3
3
|
> **Note:** `atomic-write-v2.ts` / `AtomicWriter` mentioned in historical entries below was consolidated into `atomic-write.ts` as of v0.9.42. This changelog is preserved as historical record — the migration was completed (the v2 class was never adopted; v1 won on simplicity + symlink-safety + link+unlink atomicity). See `docs/migration/atomic-write-v2-migration.md` for the decision rationale.
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## [0.9.51] — Complete the UI animation audit + Windows coalescing fix (2026-07-26)
|
|
7
|
+
|
|
8
|
+
Closes out the remaining deferred findings from `reports/ui-animation-audit-2026-07-24.md`
|
|
9
|
+
(R1, R4, C4, C3, C9; C6 analyzed-then-closed-with-reasoning) and fixes the
|
|
10
|
+
underlying Windows event-log coalescing bug that a v0.9.49 test had been
|
|
11
|
+
papering over with a `process.platform === "win32"` skip. All 15 audit
|
|
12
|
+
findings are now resolved (11 applied in v0.9.50 + these + C6 closed).
|
|
13
|
+
|
|
14
|
+
### Remaining audit findings applied
|
|
15
|
+
|
|
16
|
+
- **R1 — `render-scheduler.ts` fallbackLoop idle-stop** (`c46dc0e`): the
|
|
17
|
+
self-perpetuating `fallbackLoop` (`schedule()`→`lastEventAt`) never let the
|
|
18
|
+
UI idle, re-rendering ~every `fallbackMs` forever on a hung run. Now calls
|
|
19
|
+
a new `armDebouncedRender()` that does NOT touch `lastEventAt`; an
|
|
20
|
+
`idleFallbackRenders` counter caps consecutive idle catch-up renders
|
|
21
|
+
(default 8) then stops. `lastEventAt` is advanced only by real external
|
|
22
|
+
events, which reset the count + re-arm a stopped loop. **+3 tests** — one
|
|
23
|
+
asserts the scheduler STOPS rendering when idle, closing audit Root Gap #2
|
|
24
|
+
("no test asserts the scheduler ever stops rendering when idle").
|
|
25
|
+
- **R4 — `render-scheduler.ts` flush re-entrancy backoff** (`c46dc0e`): the
|
|
26
|
+
cap-hit path (`iterations >= 5`) now calls
|
|
27
|
+
`armDebouncedRender(debounceMs * 2^exp)` with exponential backoff
|
|
28
|
+
(`CAP_BACKOFF_MAX_EXP=5`) instead of re-arming `schedule()`.
|
|
29
|
+
`consecutiveCapHits` resets on a clean flush. Stops the latent sustained
|
|
30
|
+
~75ms render loop. +1 test.
|
|
31
|
+
- **C4 — `widget/index.ts` signature cache (invalidate-on-write)**
|
|
32
|
+
(`c46dc0e`): the prior blind-TTL cache (reverted in v0.9.50) caused stale
|
|
33
|
+
reads that skipped genuine re-renders. Now `cachedBuildSignature` is
|
|
34
|
+
invalidated in the widget's `RenderScheduler` `onInvalidate` callback (fires
|
|
35
|
+
on `run:state`/`worker:lifecycle`/`ui:invalidate`), plus in `invalidate()`
|
|
36
|
+
and on dispose. A 100ms TTL remains as a safety net only.
|
|
37
|
+
`notificationCount` is appended post-cache so notification changes still
|
|
38
|
+
re-render. +1 test asserting a genuine state change triggers re-render.
|
|
39
|
+
- **C9 — dead loaders removal** (`c46dc0e`): `CrewBorderedLoader` +
|
|
40
|
+
`CountdownTimer` were dead production code (referenced only in
|
|
41
|
+
`test/unit/loaders.test.ts`, never instantiated in `src/` or re-exported
|
|
42
|
+
from the public index). Removed both classes (`loaders.ts` → 6-line
|
|
43
|
+
documenting comment) + deleted the test file. **Preserved** the 2
|
|
44
|
+
`DynamicCrewBorder` tests (a LIVE class used by `mascot.ts`,
|
|
45
|
+
`settings-overlay.ts`, `run-dashboard.ts`) → moved to new
|
|
46
|
+
`test/unit/dynamic-border.test.ts`.
|
|
47
|
+
- **C3 — shared `RenderScheduler` fan-out dedup** (`3a50094`): the 3 overlays
|
|
48
|
+
(widget + sidebar + dashboard) each instantiated an identical
|
|
49
|
+
`RenderScheduler` (same run-event-bus channels, debounce 75ms, fallback
|
|
50
|
+
750ms) → 9 subscriptions + 9 live timers + 3× per-event `schedule()` CPU
|
|
51
|
+
during active runs. Now ONE shared scheduler (module singleton in
|
|
52
|
+
`src/ui/shared-overlay-scheduler.ts`) fans out `render` + `onInvalidate` to
|
|
53
|
+
registered overlays, with per-callback try/catch isolation + ref-counted
|
|
54
|
+
disposal. Dedups 9→3 subscriptions, 9→3 timers, 3→1 `schedule()`/event,
|
|
55
|
+
and coalesces 3 independent debounce flushes → 1 batch per event burst.
|
|
56
|
+
+5 tests (fan-out render/invalidate, dispose ref-count, error isolation ×2).
|
|
57
|
+
- **C6 — mascot visibility gate: CLOSED, not wired** (`c46dc0e` gate +
|
|
58
|
+
`01ee10f` decision): the `setVisible()` gate was implemented + tested, but
|
|
59
|
+
after reading pi source (`earendil-works/pi@cee5ff75`) the wiring was
|
|
60
|
+
deliberately NOT done. `ctx.ui.custom()` does expose
|
|
61
|
+
`onHandle→OverlayHandle.isFocused()` (a usable "not obscured" proxy), so
|
|
62
|
+
wiring is feasible — BUT pi composites ALL non-hidden overlays
|
|
63
|
+
(`tui.ts:1044` `visibleEntries` → `component.render()` at `:1054`), so the
|
|
64
|
+
host STILL calls `mascot.render()` when obscured: C6 does not save the
|
|
65
|
+
render() work it appears to target, only cheap + coalesced + redundant
|
|
66
|
+
`requestRender()` pokes. Net benefit near zero. The correct fix is a
|
|
67
|
+
pi-core compositing optimization (skip `render()` for occluded overlays) —
|
|
68
|
+
upstream, not pi-crew. See `docs/decisions/2026-07-26-c6-mascot-visibility-not-wired.md`.
|
|
69
|
+
|
|
70
|
+
### Windows event-log coalescing — attempted, REVERTED (remains unfixed)
|
|
71
|
+
|
|
72
|
+
An adaptive burst coalesce window (`NOTIFY_COALESCE_BURST_MS = 3000ms`) was
|
|
73
|
+
attempted to fix the Windows coalescing bug (the v0.9.49 `Rule 3` test had a
|
|
74
|
+
`process.platform === "win32"` skip hiding it). **Reverted** — verified on
|
|
75
|
+
Windows CI (run `30235357951`) that the 3000ms burst window is STILL shorter
|
|
76
|
+
than Windows's 3-5s completion spread, so coalescing still did not occur; AND
|
|
77
|
+
the 3000ms coalesce timer (not cancelled on `session_shutdown`) fired after
|
|
78
|
+
test temp-dir deletion → `ENOENT mkdir` unhandledRejection that failed the
|
|
79
|
+
whole `subagent-tools-integration` file on Windows. Restored the v0.9.50
|
|
80
|
+
behavior (800ms constant coalesce). The `win32` test skip is **retained** —
|
|
81
|
+
the underlying Windows coalescing bug remains unfixed (tracked from v0.9.49;
|
|
82
|
+
widening further would delay ALL notifications by 5s+ on every platform).
|
|
83
|
+
subagent-tools-integration 14/14 on Linux/macOS; both Rule 3 assertions
|
|
84
|
+
skipped on Windows.
|
|
85
|
+
|
|
86
|
+
### distill-software: Transfer vs Audit mode (`418b9f2`, bonus)
|
|
87
|
+
|
|
88
|
+
From real distillation runs (audit-only distillation produced 0 visible
|
|
89
|
+
features for the target; artifact-level gates were ALL-GREEN while code had
|
|
90
|
+
runtime bugs needing multiple review rounds):
|
|
91
|
+
- **Phase 0 #7**: Transfer (default for "distill X to Y") vs Audit mode.
|
|
92
|
+
Transfer enumerates source CAPABILITIES (features not files) and applies
|
|
93
|
+
the gaps; deliverable = visible/behavioral new features. Audit enumerates
|
|
94
|
+
conventions; deliverable = invisible refactors. Decomposition follows mode.
|
|
95
|
+
- **Phase 1**: CAPABILITY DEPTH check before SKIP on PRESENCE=yes — surface
|
|
96
|
+
match can mask a capability gap.
|
|
97
|
+
- **Phase 3 APPLY-LOG**: 5 post-APPLY integration checks — WIRED, VISIBLE
|
|
98
|
+
DELTA, RUNTIME, API VERIFIED, RESOURCE LIFECYCLE.
|
|
99
|
+
|
|
100
|
+
### Repo hygiene
|
|
101
|
+
|
|
102
|
+
- **`.claude/worktrees/*` orphan gitlinks removed** (`0e6cba5`): 7 gitlinks
|
|
103
|
+
(mode 160000, no `.gitmodules`) were stranded in the index from a prior
|
|
104
|
+
`.claude`-based tooling experiment, producing non-blocking `git exit code
|
|
105
|
+
128` warnings. Removed from index + added `.claude/` to `.gitignore`
|
|
106
|
+
(`a0b2b1e`).
|
|
107
|
+
|
|
108
|
+
### Verification
|
|
109
|
+
|
|
110
|
+
- `npm run test:critical` → 97/97 pass; render-scheduler 9/9, crew-widget
|
|
111
|
+
6/6, mascot 7/7, dynamic-border 2/2, shared-overlay-scheduler 5/5,
|
|
112
|
+
subagent-tools-integration 14/14.
|
|
113
|
+
- `npm run typecheck` → exit 0; `npm run lint` → clean;
|
|
114
|
+
`npx biome format .` → clean.
|
|
115
|
+
- `npm run build:bundle` → 2690.6 KB, md5 `29e7a4d04ab8ad0542a3af3ef3d42426`.
|
|
116
|
+
- **real-test-pi-crew** all 8 tiers green (Tier 6 pty definitive — pi renders
|
|
117
|
+
full TUI, no crash; Tier 7 smoke team `team_20260727032433` fast-fix 3/3,
|
|
118
|
+
no hang).
|
|
119
|
+
|
|
120
|
+
|
|
6
121
|
## [0.9.50] — UI animation audit + distillation toolkit v2 (2026-07-25)
|
|
7
122
|
|
|
8
123
|
Eliminates a class of timer-leak / flicker bugs surfaced by the UI animation
|
package/dist/build-meta.json
CHANGED
|
@@ -7150,7 +7150,7 @@
|
|
|
7150
7150
|
"format": "esm"
|
|
7151
7151
|
},
|
|
7152
7152
|
"src/ui/render-scheduler.ts": {
|
|
7153
|
-
"bytes":
|
|
7153
|
+
"bytes": 10286,
|
|
7154
7154
|
"imports": [
|
|
7155
7155
|
{
|
|
7156
7156
|
"path": "src/utils/internal-error.ts",
|
|
@@ -7160,6 +7160,27 @@
|
|
|
7160
7160
|
],
|
|
7161
7161
|
"format": "esm"
|
|
7162
7162
|
},
|
|
7163
|
+
"src/ui/shared-overlay-scheduler.ts": {
|
|
7164
|
+
"bytes": 3382,
|
|
7165
|
+
"imports": [
|
|
7166
|
+
{
|
|
7167
|
+
"path": "src/utils/internal-error.ts",
|
|
7168
|
+
"kind": "import-statement",
|
|
7169
|
+
"original": "../utils/internal-error.ts"
|
|
7170
|
+
},
|
|
7171
|
+
{
|
|
7172
|
+
"path": "src/ui/render-scheduler.ts",
|
|
7173
|
+
"kind": "import-statement",
|
|
7174
|
+
"original": "./render-scheduler.ts"
|
|
7175
|
+
},
|
|
7176
|
+
{
|
|
7177
|
+
"path": "src/ui/run-event-bus.ts",
|
|
7178
|
+
"kind": "import-statement",
|
|
7179
|
+
"original": "./run-event-bus.ts"
|
|
7180
|
+
}
|
|
7181
|
+
],
|
|
7182
|
+
"format": "esm"
|
|
7183
|
+
},
|
|
7163
7184
|
"src/runtime/stale-reconciler.ts": {
|
|
7164
7185
|
"bytes": 28257,
|
|
7165
7186
|
"imports": [
|
|
@@ -7381,7 +7402,7 @@
|
|
|
7381
7402
|
"format": "esm"
|
|
7382
7403
|
},
|
|
7383
7404
|
"src/ui/widget/index.ts": {
|
|
7384
|
-
"bytes":
|
|
7405
|
+
"bytes": 15361,
|
|
7385
7406
|
"imports": [
|
|
7386
7407
|
{
|
|
7387
7408
|
"path": "src/config/defaults.ts",
|
|
@@ -7399,14 +7420,9 @@
|
|
|
7399
7420
|
"original": "../pi-ui-compat.ts"
|
|
7400
7421
|
},
|
|
7401
7422
|
{
|
|
7402
|
-
"path": "src/ui/
|
|
7403
|
-
"kind": "import-statement",
|
|
7404
|
-
"original": "../render-scheduler.ts"
|
|
7405
|
-
},
|
|
7406
|
-
{
|
|
7407
|
-
"path": "src/ui/run-event-bus.ts",
|
|
7423
|
+
"path": "src/ui/shared-overlay-scheduler.ts",
|
|
7408
7424
|
"kind": "import-statement",
|
|
7409
|
-
"original": "../
|
|
7425
|
+
"original": "../shared-overlay-scheduler.ts"
|
|
7410
7426
|
},
|
|
7411
7427
|
{
|
|
7412
7428
|
"path": "src/ui/spinner.ts",
|
|
@@ -10724,7 +10740,7 @@
|
|
|
10724
10740
|
"format": "esm"
|
|
10725
10741
|
},
|
|
10726
10742
|
"src/ui/run-dashboard.ts": {
|
|
10727
|
-
"bytes":
|
|
10743
|
+
"bytes": 39738,
|
|
10728
10744
|
"imports": [
|
|
10729
10745
|
{
|
|
10730
10746
|
"path": "node:fs",
|
|
@@ -10822,14 +10838,9 @@
|
|
|
10822
10838
|
"original": "./overlays/help-overlay.ts"
|
|
10823
10839
|
},
|
|
10824
10840
|
{
|
|
10825
|
-
"path": "src/ui/
|
|
10826
|
-
"kind": "import-statement",
|
|
10827
|
-
"original": "./render-scheduler.ts"
|
|
10828
|
-
},
|
|
10829
|
-
{
|
|
10830
|
-
"path": "src/ui/run-event-bus.ts",
|
|
10841
|
+
"path": "src/ui/shared-overlay-scheduler.ts",
|
|
10831
10842
|
"kind": "import-statement",
|
|
10832
|
-
"original": "./
|
|
10843
|
+
"original": "./shared-overlay-scheduler.ts"
|
|
10833
10844
|
},
|
|
10834
10845
|
{
|
|
10835
10846
|
"path": "src/ui/spinner.ts",
|
|
@@ -10970,7 +10981,7 @@
|
|
|
10970
10981
|
"format": "esm"
|
|
10971
10982
|
},
|
|
10972
10983
|
"src/ui/mascot.ts": {
|
|
10973
|
-
"bytes":
|
|
10984
|
+
"bytes": 15362,
|
|
10974
10985
|
"imports": [
|
|
10975
10986
|
{
|
|
10976
10987
|
"path": "src/utils/visual.ts",
|
|
@@ -11672,7 +11683,7 @@
|
|
|
11672
11683
|
"format": "esm"
|
|
11673
11684
|
},
|
|
11674
11685
|
"src/ui/live-run-sidebar.ts": {
|
|
11675
|
-
"bytes":
|
|
11686
|
+
"bytes": 11692,
|
|
11676
11687
|
"imports": [
|
|
11677
11688
|
{
|
|
11678
11689
|
"path": "node:fs",
|
|
@@ -11715,14 +11726,9 @@
|
|
|
11715
11726
|
"original": "../utils/visual.ts"
|
|
11716
11727
|
},
|
|
11717
11728
|
{
|
|
11718
|
-
"path": "src/ui/
|
|
11719
|
-
"kind": "import-statement",
|
|
11720
|
-
"original": "./render-scheduler.ts"
|
|
11721
|
-
},
|
|
11722
|
-
{
|
|
11723
|
-
"path": "src/ui/run-event-bus.ts",
|
|
11729
|
+
"path": "src/ui/shared-overlay-scheduler.ts",
|
|
11724
11730
|
"kind": "import-statement",
|
|
11725
|
-
"original": "./
|
|
11731
|
+
"original": "./shared-overlay-scheduler.ts"
|
|
11726
11732
|
},
|
|
11727
11733
|
{
|
|
11728
11734
|
"path": "src/ui/spinner.ts",
|
|
@@ -13126,7 +13132,7 @@
|
|
|
13126
13132
|
"imports": [],
|
|
13127
13133
|
"exports": [],
|
|
13128
13134
|
"inputs": {},
|
|
13129
|
-
"bytes":
|
|
13135
|
+
"bytes": 6020579
|
|
13130
13136
|
},
|
|
13131
13137
|
"dist/index.mjs": {
|
|
13132
13138
|
"imports": [
|
|
@@ -15722,7 +15728,10 @@
|
|
|
15722
15728
|
"bytesInOutput": 21485
|
|
15723
15729
|
},
|
|
15724
15730
|
"src/ui/render-scheduler.ts": {
|
|
15725
|
-
"bytesInOutput":
|
|
15731
|
+
"bytesInOutput": 7918
|
|
15732
|
+
},
|
|
15733
|
+
"src/ui/shared-overlay-scheduler.ts": {
|
|
15734
|
+
"bytesInOutput": 1681
|
|
15726
15735
|
},
|
|
15727
15736
|
"src/runtime/stale-reconciler.ts": {
|
|
15728
15737
|
"bytesInOutput": 15684
|
|
@@ -15743,7 +15752,7 @@
|
|
|
15743
15752
|
"bytesInOutput": 6263
|
|
15744
15753
|
},
|
|
15745
15754
|
"src/ui/widget/index.ts": {
|
|
15746
|
-
"bytesInOutput":
|
|
15755
|
+
"bytesInOutput": 10057
|
|
15747
15756
|
},
|
|
15748
15757
|
"src/ui/tool-progress-formatter.ts": {
|
|
15749
15758
|
"bytesInOutput": 2682
|
|
@@ -16106,7 +16115,7 @@
|
|
|
16106
16115
|
"bytesInOutput": 4154
|
|
16107
16116
|
},
|
|
16108
16117
|
"src/ui/run-dashboard.ts": {
|
|
16109
|
-
"bytesInOutput":
|
|
16118
|
+
"bytesInOutput": 30630
|
|
16110
16119
|
},
|
|
16111
16120
|
"src/ui/overlays/confirm-overlay.ts": {
|
|
16112
16121
|
"bytesInOutput": 2237
|
|
@@ -16124,7 +16133,7 @@
|
|
|
16124
16133
|
"bytesInOutput": 1913
|
|
16125
16134
|
},
|
|
16126
16135
|
"src/ui/mascot.ts": {
|
|
16127
|
-
"bytesInOutput":
|
|
16136
|
+
"bytesInOutput": 16274
|
|
16128
16137
|
},
|
|
16129
16138
|
"src/ui/settings-overlay.ts": {
|
|
16130
16139
|
"bytesInOutput": 30796
|
|
@@ -16142,7 +16151,7 @@
|
|
|
16142
16151
|
"bytesInOutput": 4563
|
|
16143
16152
|
},
|
|
16144
16153
|
"src/ui/live-run-sidebar.ts": {
|
|
16145
|
-
"bytesInOutput":
|
|
16154
|
+
"bytesInOutput": 9640
|
|
16146
16155
|
},
|
|
16147
16156
|
"src/extension/registration/ui.ts": {
|
|
16148
16157
|
"bytesInOutput": 4277
|
|
@@ -16340,7 +16349,7 @@
|
|
|
16340
16349
|
"bytesInOutput": 81
|
|
16341
16350
|
}
|
|
16342
16351
|
},
|
|
16343
|
-
"bytes":
|
|
16352
|
+
"bytes": 2754801
|
|
16344
16353
|
}
|
|
16345
16354
|
}
|
|
16346
16355
|
}
|