core/src/pi-manifest
What a pi package’s manifest declares, and where pi will look for it (#221) — THE one place that knows pi’s manifest-resource layout.
TWO pi ASSUMPTIONS LIVE HERE, AND NOWHERE ELSE:
- a
pi.*value is a resource path or an array of them (docs/packages.md§ Dependencies), so reading them means flattening one level; - a resource path beginning
node_modules/is a LITERAL path relative to the package root — not a specifier pi resolves — so the file must be there on disk. Our harness manifest depends on that at the file level: it namesnode_modules/@ladbabynpm/picc-permission-modes/index.tsandnode_modules/pi-multi-account/index.ts, source paths inside vendor packages rather than export-map entries.
⚠ pi does NOT error on a manifest resource path that does not exist — it skips it
SILENTLY (verified 2026-09-03: the vendor extension did not load and nothing was
reported). That is why missingVendorPaths exists at all, and why both launch points
refuse on a non-empty result instead of starting.
⚠ ONE COPY. Before #221 the flatten-and-filter existed three times — scripts/enso.ts’s
launcher decisions, scripts/link-vendor-packages.ts, and the server’s
assertVendorLinks — with the prefix spelled as a constant in two of them and as a bare
literal in the third, which is why the no-duplicate-shapes gate never named them. The
cost of three was that a change in how pi resolves resources would have to land in three
files in two languages, and the one that was missed becomes the silent path — the exact
failure packages/web/src/server/index.ts records having already cost a debugging detour.
⚠ node: — a subpath (@enso/core/pi-manifest), never the barrel (#211).
pi manifest
Section titled “pi manifest”declaredResources()
Section titled “declaredResources()”declaredResources(
manifest):string[]
Defined in: core/src/pi-manifest.ts:87
Every resource path the manifest declares under pi.*, flattened, in declaration order.
A non-string entry is not a resource path and is dropped rather than coerced — a hand-edited
manifest should not turn into a check against "42".
Parameters
Section titled “Parameters”manifest
Section titled “manifest”unknown
Returns
Section titled “Returns”string[]
missingVendorPaths()
Section titled “missingVendorPaths()”missingVendorPaths(
manifest,packageRoot):string[]
Defined in: core/src/pi-manifest.ts:111
The declared node_modules/… paths that are not under packageRoot.
Only the vendor paths are checked: a repo-local resource (./extensions/…) is the
package’s own and is there or the package is broken, whereas the vendor ones are
materialized by the installer and npm workspaces used to hoist them away.
Parameters
Section titled “Parameters”manifest
Section titled “manifest”unknown
packageRoot
Section titled “packageRoot”string
Returns
Section titled “Returns”string[]
vendorPackageNames()
Section titled “vendorPackageNames()”vendorPackageNames(
manifest):string[]
Defined in: core/src/pi-manifest.ts:124
The package names those vendor paths reach into, deduplicated.
⚠ A scoped package carries its scope in the FIRST TWO segments (@scope/name), so the
name is not simply the first one — node_modules/@ladbabynpm/picc-permission-modes/index.ts
names @ladbabynpm/picc-permission-modes, not @ladbabynpm.
Parameters
Section titled “Parameters”manifest
Section titled “manifest”unknown
Returns
Section titled “Returns”string[]