pi-crew 0.9.52 → 0.9.53
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 +18 -0
- package/index.ts +39 -10
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
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.53] — HOTFIX: extension-load regression in published npm installs (2026-07-29)
|
|
7
|
+
|
|
8
|
+
**Fixes the v0.9.52 regression** where every fresh `npm install pi-crew` failed at extension load with `Cannot find module './src/extension/register.ts'`. Affected all platforms.
|
|
9
|
+
|
|
10
|
+
### Root cause
|
|
11
|
+
v0.9.52's PKG-2 (Sprint 6) excluded `src/` from the npm tarball to slim it (16→4.8MB), but `index.ts` — the extension entry Pi loads via strip-types — still had **top-level static imports** from `./src/extension/register.ts` and `./src/runtime/run-tracker.ts`. The module loader resolves static imports BEFORE any code in the file runs, so the load failed before the shipped, self-contained `dist/index.mjs` bundle was ever tried. Pre-0.9.52 this was masked because `src/` was shipped alongside.
|
|
12
|
+
|
|
13
|
+
CI missed it because the `test:bundle` step loads `dist/index.mjs` directly (with repo peerDeps), and the CI-5 smoke test used `node --check` (syntax only — does not resolve imports).
|
|
14
|
+
|
|
15
|
+
### Fix (`index.ts`)
|
|
16
|
+
The src/ imports are now **dynamic `import()`** inside the fallback path only. The self-contained `dist/index.mjs` bundle (always shipped in the tarball) is the default and loads without `src/`. The src/ fallback is reached only when the bundle is absent — i.e. dev clones without a built `dist/`. Published installs never touch `src/`. No behavior change for bundle users; the fallback semantics (`PI_CREW_USE_BUNDLE=0` opt-out) are preserved.
|
|
17
|
+
|
|
18
|
+
### Regression guard
|
|
19
|
+
New `test/unit/extension-entry-load.test.ts` asserts `index.ts` has no static top-level `./src/` value imports (and that the dynamic src/ fallback imports still exist). Would have caught v0.9.52. Runs in CI's Test step on all platforms.
|
|
20
|
+
|
|
21
|
+
### Note on v0.9.52
|
|
22
|
+
v0.9.52 is **deprecated** on npm — upgrade to 0.9.53. If you installed 0.9.52, run `npm install pi-crew@latest` (or `npx pi install npm:pi-crew`).
|
|
23
|
+
|
|
6
24
|
## [0.9.52] — Sprint 1-6: security hardening, durability, god-module refactor, tarball slim (2026-07-28)
|
|
7
25
|
|
|
8
26
|
A full audit-driven upgrade pass — 6 sprints, ~60 findings from `REVIEW-UPGRADE-2026-07-27.md`, independently verified in `VERIFY-2026-07-27.md` (~22% of the original report's claims corrected: 4 false positives, count inflations, stale line refs). Test suite 6446 unit + 191 integration, 0 fail. CI green on ubuntu/macos/windows.
|
package/index.ts
CHANGED
|
@@ -47,18 +47,29 @@
|
|
|
47
47
|
* avoid recursion), the bundle flip risk is acceptable.
|
|
48
48
|
*/
|
|
49
49
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
50
|
-
import { registerPiTeams as registerPiTeamsFromSrc } from "./src/extension/register.ts";
|
|
51
|
-
import { waitForRun as waitForRunFromSrc } from "./src/runtime/run-tracker.ts";
|
|
52
50
|
import { accessSync } from "node:fs";
|
|
53
51
|
import { fileURLToPath } from "node:url";
|
|
54
52
|
import { dirname, resolve } from "node:path";
|
|
55
53
|
|
|
56
|
-
//
|
|
57
|
-
//
|
|
54
|
+
// IMPORTANT: src/ imports here MUST be dynamic (lazy `import()`), never
|
|
55
|
+
// top-level static imports. Published npm packages ship only dist/index.mjs
|
|
56
|
+
// in the tarball (src/ is excluded by the package.json "files" field — keeps
|
|
57
|
+
// the package ~5MB instead of ~16MB). A top-level static
|
|
58
|
+
// `import { x } from "./src/..."` is resolved by the module loader BEFORE
|
|
59
|
+
// this file's code runs, so it would break every fresh `npm install`
|
|
60
|
+
// (Cannot find module './src/...'). Dynamic import() defers src/ resolution
|
|
61
|
+
// to the fallback path below, which only executes when the bundle is
|
|
62
|
+
// unavailable — i.e. dev clones that still have src/. Published installs
|
|
63
|
+
// always ship + load the bundle, so src/ is never touched there.
|
|
64
|
+
|
|
65
|
+
// Minimal bundle shape — loose types because dist/index.mjs has no .d.ts
|
|
66
|
+
// (it's a build artifact, not source). The src fallback types use
|
|
67
|
+
// `typeof import(...)` type queries, which are type-only constructs erased
|
|
68
|
+
// at runtime (no module load) — they stay in sync with the real modules.
|
|
58
69
|
type BundleModule = {
|
|
59
70
|
default?: (pi: ExtensionAPI) => void;
|
|
60
|
-
waitForRun?: typeof
|
|
61
|
-
registerPiTeams?: (
|
|
71
|
+
waitForRun?: typeof import("./src/runtime/run-tracker.ts").waitForRun;
|
|
72
|
+
registerPiTeams?: typeof import("./src/extension/register.ts").registerPiTeams;
|
|
62
73
|
};
|
|
63
74
|
|
|
64
75
|
const OPT_OUT = new Set(["0", "false", "no", "off"]);
|
|
@@ -91,8 +102,26 @@ if (!envForceOff) {
|
|
|
91
102
|
}
|
|
92
103
|
}
|
|
93
104
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
105
|
+
// Lazy src/ fallback — only resolved when the bundle is unavailable
|
|
106
|
+
// (dev clones without a built dist/). NEVER imported in published
|
|
107
|
+
// installs, where the bundle always ships + loads above. This dynamic
|
|
108
|
+
// import() is what lets us exclude src/ from the npm tarball.
|
|
109
|
+
let srcRegister:
|
|
110
|
+
| typeof import("./src/extension/register.ts").registerPiTeams
|
|
111
|
+
| undefined;
|
|
112
|
+
let srcWaitForRun:
|
|
113
|
+
| typeof import("./src/runtime/run-tracker.ts").waitForRun
|
|
114
|
+
| undefined;
|
|
115
|
+
if (!bundleModule) {
|
|
116
|
+
({ registerPiTeams: srcRegister } = await import(
|
|
117
|
+
"./src/extension/register.ts",
|
|
118
|
+
));
|
|
119
|
+
({ waitForRun: srcWaitForRun } = await import(
|
|
120
|
+
"./src/runtime/run-tracker.ts",
|
|
121
|
+
));
|
|
122
|
+
}
|
|
97
123
|
|
|
98
|
-
export
|
|
124
|
+
export const waitForRun = bundleModule?.waitForRun ?? srcWaitForRun!;
|
|
125
|
+
export const registerPiTeams: (pi: ExtensionAPI) => void =
|
|
126
|
+
bundleModule?.registerPiTeams ?? srcRegister!;
|
|
127
|
+
export default bundleModule?.default ?? ((pi: ExtensionAPI) => srcRegister!(pi));
|