pi-crew 0.9.20 → 0.9.22
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 +64 -0
- package/dist/build-meta.json +72 -24
- package/dist/index.mjs +698 -307
- package/dist/index.mjs.map +4 -4
- package/package.json +1 -1
- package/src/extension/cross-extension-rpc.ts +16 -3
- package/src/extension/team-tool/run.ts +33 -4
- package/src/runtime/background-runner.ts +7 -0
- package/src/runtime/dynamic-workflow-context.ts +3 -3
- package/src/runtime/task-runner.ts +4 -4
- package/src/runtime/team-runner.ts +130 -1
- package/src/runtime/tool-output-pruner.ts +5 -3
- package/src/state/event-log.ts +168 -12
- package/src/state/types.ts +5 -0
- package/src/utils/token-counter.ts +67 -0
- package/src/worktree/worktree-manager.ts +363 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v0.9.22] — fix: batch buffered event-log flush (25-85x faster) (2026-07-07)
|
|
4
|
+
|
|
5
|
+
P0 follow-up to v0.9.21 event batching. The buffered flush path was calling `appendEventInsideLock` per-event, which triggered an `fsyncSync` per queued event. This defeated the entire point of batching — for 100 buffered events the flush took ~3s on tmpfs instead of the expected ~20ms.
|
|
6
|
+
|
|
7
|
+
### Highlights
|
|
8
|
+
|
|
9
|
+
- **Buffered flush now coalesces fsyncs.** New `appendEventBatchInsideLock()` computes metadata for the whole queue, then performs 1 `appendFileSync` + 1 `fsyncSync` + 1 `persistSequence` + 1 cache update at the end. Resolves all queued promises with their finalized events.
|
|
10
|
+
- **Side fixes for batch correctness.** `nextSequence()` cannot be called per-event in Phase 1 (no writes between calls → all events get the same seq). Now computes `startingSeq` once and increments locally. `setTimeout` callback no longer returns a floating Promise from `flushOneEventLogBuffer`. `process.on('exit')` guards `flushEventLogBuffer()` with a size > 0 check to avoid creating a new floating Promise on every exit.
|
|
11
|
+
|
|
12
|
+
### Performance
|
|
13
|
+
|
|
14
|
+
| Workload | Before | After | Speedup |
|
|
15
|
+
|---|---|---|---|
|
|
16
|
+
| 100 buffered events | 3,314 ms | 132 ms | 25x |
|
|
17
|
+
| 1,000 buffered events | 29,205 ms | 343 ms | 85x |
|
|
18
|
+
|
|
19
|
+
### Verification
|
|
20
|
+
|
|
21
|
+
| Gate | Result |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `event-log-async.test.ts` | ✅ 16/16 pass |
|
|
24
|
+
| `event-log-batch.test.ts` | ✅ all pass |
|
|
25
|
+
| `event-log-buffered.test.ts` | ✅ seq uniqueness restored |
|
|
26
|
+
| `event-log-race.test.ts` | ✅ all pass |
|
|
27
|
+
| `event-log-leak.test.ts` H2 | ✅ pass |
|
|
28
|
+
| `event-log-leak.test.ts` H1/H3 | ⚠️ cancelled under `--test-force-exit` (node:test framework detects pending work; tracked separately) |
|
|
29
|
+
| `per-task-budget.test.ts`, `token-counter.test.ts` | ✅ all pass |
|
|
30
|
+
|
|
31
|
+
### Files
|
|
32
|
+
|
|
33
|
+
- MOD: `src/state/event-log.ts` — added `appendEventBatchInsideLock()`, fixed `nextSequence()` batching, fixed floating Promise in `setTimeout` callback, guarded `process.on('exit')` flush
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## [v0.9.21] — P0 performance fixes: event batching, async worktree, per-task budget, token counter (2026-07-07)
|
|
38
|
+
|
|
39
|
+
Four P0 performance fixes identified by a parallel performance review (4 subagents: runtime, token efficiency, architecture, security overhead). All fixes are backward-compatible; no breaking changes.
|
|
40
|
+
|
|
41
|
+
### Highlights
|
|
42
|
+
|
|
43
|
+
- **Event log batching (P0).** The event log now uses a 50ms flush interval instead of immediate per-event writes. This reduces fsync calls from 1 per event to 1 per batch. New helpers: `appendEventBuffered()`, `flushEventBuffer()`. Force flush on run completion and shutdown. `src/state/event-log.ts`; 12 tests in `test/unit/event-log-batch.test.ts`.
|
|
44
|
+
|
|
45
|
+
- **Async worktree operations (P0).** `execFileSync` → async `execFile` for non-blocking I/O. `findGitRoot()` cached via Map to avoid repeated disk reads. `assertCleanLeader()` uses async execFile. Dynamic workflow context updated to use async worktree. `src/worktree/worktree-manager.ts`, `src/runtime/task-runner.ts`, `src/runtime/dynamic-workflow-context.ts`; 7 tests in `test/unit/worktree-async.test.ts`.
|
|
46
|
+
|
|
47
|
+
- **Per-task token budget enforcement (P0).** `executeTeamRun()` now enforces `budgetTotal`/`budgetAbort` thresholds. Budget warning and abort events emitted when limits exceeded. `TeamRunManifest` includes `budgetTotal`, `budgetWarning`, `budgetAbort`, `budgetUnlimited` fields. Budget propagation chain: MCP tool → handleRun → executeTeamRun → manifest persistence. `src/runtime/team-runner.ts`, `src/extension/team-tool/run.ts`, `src/state/types.ts`; 14 tests in `test/unit/per-task-budget.test.ts`.
|
|
48
|
+
|
|
49
|
+
- **Accurate token counting (P0).** New `token-counter.ts` with `ceil(alpha/4) + punctuation` formula. Replaces `char/4` heuristic for better accuracy on code. Single-pass O(n) algorithm, no dependencies. Tool output pruner uses `countTokens()` for accurate pruning. `src/utils/token-counter.ts`, `src/runtime/tool-output-pruner.ts`; 9 tests in `test/unit/token-counter.test.ts`.
|
|
50
|
+
|
|
51
|
+
### Verification
|
|
52
|
+
|
|
53
|
+
| Gate | Result |
|
|
54
|
+
|---|---|
|
|
55
|
+
| All unit tests (21 files) | ✅ 187/187 pass |
|
|
56
|
+
| New P0 tests (4 files) | ✅ 67/67 pass |
|
|
57
|
+
| Live E2E (fast-fix workflow) | ✅ 3/3 tasks, budget propagation verified |
|
|
58
|
+
| Extension load | ✅ |
|
|
59
|
+
|
|
60
|
+
### Files
|
|
61
|
+
|
|
62
|
+
- NEW: `src/utils/token-counter.ts`, `test/unit/event-log-batch.test.ts`, `test/unit/per-task-budget.test.ts`, `test/unit/token-counter.test.ts`, `test/unit/worktree-async.test.ts`
|
|
63
|
+
- MOD: `src/state/event-log.ts`, `src/worktree/worktree-manager.ts`, `src/runtime/team-runner.ts`, `src/runtime/task-runner.ts`, `src/runtime/dynamic-workflow-context.ts`, `src/runtime/tool-output-pruner.ts`, `src/extension/team-tool/run.ts`, `src/extension/cross-extension-rpc.ts`, `src/runtime/background-runner.ts`, `src/state/types.ts`
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
3
67
|
## [v0.9.20] — security hardening: RPC HMAC auth + per-task API key scoping + safe-bash whitelist (2026-07-06)
|
|
4
68
|
|
|
5
69
|
Three defense-in-depth security upgrades distilled from cross-source research (52+ repos) and the H-1/H-2/H-6 audit findings. All three are additive (no breaking changes); two are opt-in via env vars, one is default-on.
|
package/dist/build-meta.json
CHANGED
|
@@ -6351,7 +6351,7 @@
|
|
|
6351
6351
|
"format": "esm"
|
|
6352
6352
|
},
|
|
6353
6353
|
"src/state/event-log.ts": {
|
|
6354
|
-
"bytes":
|
|
6354
|
+
"bytes": 44845,
|
|
6355
6355
|
"imports": [
|
|
6356
6356
|
{
|
|
6357
6357
|
"path": "node:crypto",
|
|
@@ -7233,7 +7233,7 @@
|
|
|
7233
7233
|
"format": "esm"
|
|
7234
7234
|
},
|
|
7235
7235
|
"src/utils/env-filter.ts": {
|
|
7236
|
-
"bytes":
|
|
7236
|
+
"bytes": 6523,
|
|
7237
7237
|
"imports": [
|
|
7238
7238
|
{
|
|
7239
7239
|
"path": "src/utils/redaction.ts",
|
|
@@ -7341,7 +7341,7 @@
|
|
|
7341
7341
|
"format": "esm"
|
|
7342
7342
|
},
|
|
7343
7343
|
"src/runtime/child-pi.ts": {
|
|
7344
|
-
"bytes":
|
|
7344
|
+
"bytes": 60312,
|
|
7345
7345
|
"imports": [
|
|
7346
7346
|
{
|
|
7347
7347
|
"path": "node:child_process",
|
|
@@ -14125,11 +14125,22 @@
|
|
|
14125
14125
|
],
|
|
14126
14126
|
"format": "esm"
|
|
14127
14127
|
},
|
|
14128
|
-
"src/
|
|
14129
|
-
"bytes":
|
|
14128
|
+
"src/utils/token-counter.ts": {
|
|
14129
|
+
"bytes": 2162,
|
|
14130
14130
|
"imports": [],
|
|
14131
14131
|
"format": "esm"
|
|
14132
14132
|
},
|
|
14133
|
+
"src/runtime/tool-output-pruner.ts": {
|
|
14134
|
+
"bytes": 12320,
|
|
14135
|
+
"imports": [
|
|
14136
|
+
{
|
|
14137
|
+
"path": "src/utils/token-counter.ts",
|
|
14138
|
+
"kind": "import-statement",
|
|
14139
|
+
"original": "../utils/token-counter.ts"
|
|
14140
|
+
}
|
|
14141
|
+
],
|
|
14142
|
+
"format": "esm"
|
|
14143
|
+
},
|
|
14133
14144
|
"src/runtime/task-output-context.ts": {
|
|
14134
14145
|
"bytes": 26832,
|
|
14135
14146
|
"imports": [
|
|
@@ -14358,7 +14369,7 @@
|
|
|
14358
14369
|
"format": "esm"
|
|
14359
14370
|
},
|
|
14360
14371
|
"src/worktree/worktree-manager.ts": {
|
|
14361
|
-
"bytes":
|
|
14372
|
+
"bytes": 40499,
|
|
14362
14373
|
"imports": [
|
|
14363
14374
|
{
|
|
14364
14375
|
"path": "node:child_process",
|
|
@@ -14380,6 +14391,11 @@
|
|
|
14380
14391
|
"kind": "import-statement",
|
|
14381
14392
|
"external": true
|
|
14382
14393
|
},
|
|
14394
|
+
{
|
|
14395
|
+
"path": "node:util",
|
|
14396
|
+
"kind": "import-statement",
|
|
14397
|
+
"external": true
|
|
14398
|
+
},
|
|
14383
14399
|
{
|
|
14384
14400
|
"path": "src/config/config.ts",
|
|
14385
14401
|
"kind": "import-statement",
|
|
@@ -14794,7 +14810,7 @@
|
|
|
14794
14810
|
"format": "esm"
|
|
14795
14811
|
},
|
|
14796
14812
|
"src/runtime/task-runner.ts": {
|
|
14797
|
-
"bytes":
|
|
14813
|
+
"bytes": 54735,
|
|
14798
14814
|
"imports": [
|
|
14799
14815
|
{
|
|
14800
14816
|
"path": "node:fs",
|
|
@@ -15103,7 +15119,7 @@
|
|
|
15103
15119
|
"format": "esm"
|
|
15104
15120
|
},
|
|
15105
15121
|
"src/runtime/team-runner.ts": {
|
|
15106
|
-
"bytes":
|
|
15122
|
+
"bytes": 75896,
|
|
15107
15123
|
"imports": [
|
|
15108
15124
|
{
|
|
15109
15125
|
"path": "node:fs",
|
|
@@ -15631,7 +15647,7 @@
|
|
|
15631
15647
|
"format": "esm"
|
|
15632
15648
|
},
|
|
15633
15649
|
"src/runtime/dynamic-workflow-context.ts": {
|
|
15634
|
-
"bytes":
|
|
15650
|
+
"bytes": 40944,
|
|
15635
15651
|
"imports": [
|
|
15636
15652
|
{
|
|
15637
15653
|
"path": "node:crypto",
|
|
@@ -15768,7 +15784,7 @@
|
|
|
15768
15784
|
"format": "esm"
|
|
15769
15785
|
},
|
|
15770
15786
|
"src/extension/team-tool/run.ts": {
|
|
15771
|
-
"bytes":
|
|
15787
|
+
"bytes": 44253,
|
|
15772
15788
|
"imports": [
|
|
15773
15789
|
{
|
|
15774
15790
|
"path": "src/agents/discover-agents.ts",
|
|
@@ -17096,14 +17112,30 @@
|
|
|
17096
17112
|
],
|
|
17097
17113
|
"format": "esm"
|
|
17098
17114
|
},
|
|
17115
|
+
"src/extension/rpc-hmac.ts": {
|
|
17116
|
+
"bytes": 7500,
|
|
17117
|
+
"imports": [
|
|
17118
|
+
{
|
|
17119
|
+
"path": "node:crypto",
|
|
17120
|
+
"kind": "import-statement",
|
|
17121
|
+
"external": true
|
|
17122
|
+
}
|
|
17123
|
+
],
|
|
17124
|
+
"format": "esm"
|
|
17125
|
+
},
|
|
17099
17126
|
"src/extension/cross-extension-rpc.ts": {
|
|
17100
|
-
"bytes":
|
|
17127
|
+
"bytes": 10981,
|
|
17101
17128
|
"imports": [
|
|
17102
17129
|
{
|
|
17103
17130
|
"path": "src/utils/safe-paths.ts",
|
|
17104
17131
|
"kind": "import-statement",
|
|
17105
17132
|
"original": "../utils/safe-paths.ts"
|
|
17106
17133
|
},
|
|
17134
|
+
{
|
|
17135
|
+
"path": "src/extension/rpc-hmac.ts",
|
|
17136
|
+
"kind": "import-statement",
|
|
17137
|
+
"original": "./rpc-hmac.ts"
|
|
17138
|
+
},
|
|
17107
17139
|
{
|
|
17108
17140
|
"path": "src/runtime/live-control-realtime.ts",
|
|
17109
17141
|
"kind": "import-statement",
|
|
@@ -18166,7 +18198,7 @@
|
|
|
18166
18198
|
"imports": [],
|
|
18167
18199
|
"exports": [],
|
|
18168
18200
|
"inputs": {},
|
|
18169
|
-
"bytes":
|
|
18201
|
+
"bytes": 6479322
|
|
18170
18202
|
},
|
|
18171
18203
|
"dist/index.mjs": {
|
|
18172
18204
|
"imports": [
|
|
@@ -19205,6 +19237,11 @@
|
|
|
19205
19237
|
"kind": "import-statement",
|
|
19206
19238
|
"external": true
|
|
19207
19239
|
},
|
|
19240
|
+
{
|
|
19241
|
+
"path": "node:util",
|
|
19242
|
+
"kind": "import-statement",
|
|
19243
|
+
"external": true
|
|
19244
|
+
},
|
|
19208
19245
|
{
|
|
19209
19246
|
"path": "node:fs",
|
|
19210
19247
|
"kind": "import-statement",
|
|
@@ -19545,6 +19582,11 @@
|
|
|
19545
19582
|
"kind": "import-statement",
|
|
19546
19583
|
"external": true
|
|
19547
19584
|
},
|
|
19585
|
+
{
|
|
19586
|
+
"path": "node:crypto",
|
|
19587
|
+
"kind": "import-statement",
|
|
19588
|
+
"external": true
|
|
19589
|
+
},
|
|
19548
19590
|
{
|
|
19549
19591
|
"path": "@earendil-works/pi-tui",
|
|
19550
19592
|
"kind": "import-statement",
|
|
@@ -20349,7 +20391,7 @@
|
|
|
20349
20391
|
"bytesInOutput": 4478
|
|
20350
20392
|
},
|
|
20351
20393
|
"src/state/event-log.ts": {
|
|
20352
|
-
"bytesInOutput":
|
|
20394
|
+
"bytesInOutput": 26234
|
|
20353
20395
|
},
|
|
20354
20396
|
"src/hooks/registry.ts": {
|
|
20355
20397
|
"bytesInOutput": 4422
|
|
@@ -20448,7 +20490,7 @@
|
|
|
20448
20490
|
"bytesInOutput": 291
|
|
20449
20491
|
},
|
|
20450
20492
|
"src/utils/env-filter.ts": {
|
|
20451
|
-
"bytesInOutput":
|
|
20493
|
+
"bytesInOutput": 3511
|
|
20452
20494
|
},
|
|
20453
20495
|
"src/runtime/compact-pipeline.ts": {
|
|
20454
20496
|
"bytesInOutput": 517
|
|
@@ -20487,7 +20529,7 @@
|
|
|
20487
20529
|
"bytesInOutput": 1642
|
|
20488
20530
|
},
|
|
20489
20531
|
"src/runtime/child-pi.ts": {
|
|
20490
|
-
"bytesInOutput":
|
|
20532
|
+
"bytesInOutput": 41851
|
|
20491
20533
|
},
|
|
20492
20534
|
"src/runtime/heartbeat-gradient.ts": {
|
|
20493
20535
|
"bytesInOutput": 953
|
|
@@ -21377,8 +21419,11 @@
|
|
|
21377
21419
|
"src/runtime/goal-achievement.ts": {
|
|
21378
21420
|
"bytesInOutput": 2922
|
|
21379
21421
|
},
|
|
21422
|
+
"src/utils/token-counter.ts": {
|
|
21423
|
+
"bytesInOutput": 685
|
|
21424
|
+
},
|
|
21380
21425
|
"src/runtime/tool-output-pruner.ts": {
|
|
21381
|
-
"bytesInOutput":
|
|
21426
|
+
"bytesInOutput": 5527
|
|
21382
21427
|
},
|
|
21383
21428
|
"src/runtime/task-output-context.ts": {
|
|
21384
21429
|
"bytesInOutput": 12672
|
|
@@ -21423,7 +21468,7 @@
|
|
|
21423
21468
|
"bytesInOutput": 2538
|
|
21424
21469
|
},
|
|
21425
21470
|
"src/worktree/worktree-manager.ts": {
|
|
21426
|
-
"bytesInOutput":
|
|
21471
|
+
"bytesInOutput": 21100
|
|
21427
21472
|
},
|
|
21428
21473
|
"src/runtime/event-stream-bridge.ts": {
|
|
21429
21474
|
"bytesInOutput": 2321
|
|
@@ -21489,7 +21534,7 @@
|
|
|
21489
21534
|
"bytesInOutput": 6123
|
|
21490
21535
|
},
|
|
21491
21536
|
"src/runtime/task-runner.ts": {
|
|
21492
|
-
"bytesInOutput":
|
|
21537
|
+
"bytesInOutput": 42475
|
|
21493
21538
|
},
|
|
21494
21539
|
"src/runtime/workflow-state.ts": {
|
|
21495
21540
|
"bytesInOutput": 2471
|
|
@@ -21507,7 +21552,7 @@
|
|
|
21507
21552
|
"bytesInOutput": 3398
|
|
21508
21553
|
},
|
|
21509
21554
|
"src/runtime/team-runner.ts": {
|
|
21510
|
-
"bytesInOutput":
|
|
21555
|
+
"bytesInOutput": 57404
|
|
21511
21556
|
},
|
|
21512
21557
|
"src/runtime/pipeline-runner.ts": {
|
|
21513
21558
|
"bytesInOutput": 11755
|
|
@@ -21558,13 +21603,13 @@
|
|
|
21558
21603
|
"bytesInOutput": 1460
|
|
21559
21604
|
},
|
|
21560
21605
|
"src/runtime/dynamic-workflow-context.ts": {
|
|
21561
|
-
"bytesInOutput":
|
|
21606
|
+
"bytesInOutput": 20207
|
|
21562
21607
|
},
|
|
21563
21608
|
"src/runtime/dynamic-workflow-runner.ts": {
|
|
21564
21609
|
"bytesInOutput": 6259
|
|
21565
21610
|
},
|
|
21566
21611
|
"src/extension/team-tool/run.ts": {
|
|
21567
|
-
"bytesInOutput":
|
|
21612
|
+
"bytesInOutput": 34875
|
|
21568
21613
|
},
|
|
21569
21614
|
"src/extension/team-tool.ts": {
|
|
21570
21615
|
"bytesInOutput": 35293
|
|
@@ -21672,7 +21717,7 @@
|
|
|
21672
21717
|
"bytesInOutput": 6698
|
|
21673
21718
|
},
|
|
21674
21719
|
"src/observability/exporters/otlp-exporter.ts": {
|
|
21675
|
-
"bytesInOutput":
|
|
21720
|
+
"bytesInOutput": 7442
|
|
21676
21721
|
},
|
|
21677
21722
|
"src/observability/metrics-primitives.ts": {
|
|
21678
21723
|
"bytesInOutput": 5869
|
|
@@ -21753,7 +21798,10 @@
|
|
|
21753
21798
|
"bytesInOutput": 1204
|
|
21754
21799
|
},
|
|
21755
21800
|
"src/extension/cross-extension-rpc.ts": {
|
|
21756
|
-
"bytesInOutput":
|
|
21801
|
+
"bytesInOutput": 8532
|
|
21802
|
+
},
|
|
21803
|
+
"src/extension/rpc-hmac.ts": {
|
|
21804
|
+
"bytesInOutput": 3514
|
|
21757
21805
|
},
|
|
21758
21806
|
"src/extension/message-renderers.ts": {
|
|
21759
21807
|
"bytesInOutput": 2457
|
|
@@ -21783,7 +21831,7 @@
|
|
|
21783
21831
|
"bytesInOutput": 81
|
|
21784
21832
|
}
|
|
21785
21833
|
},
|
|
21786
|
-
"bytes":
|
|
21834
|
+
"bytes": 3097798
|
|
21787
21835
|
}
|
|
21788
21836
|
}
|
|
21789
21837
|
}
|