fix(deps): migrate to the renamed pi-coding-agent package - #69
Conversation
The package we depended on is deprecated on npm and its three open advisories all report first_patched_version: null against it -- the published latest for that name is also the top of the affected range, so no version under the old name clears them. The fix exists only under the renamed successor. Migrates the four workspace packages that declare it as a runtime dependency, plus the eight import sites, from the old scope to @earendil-works/pi-coding-agent at 0.79.10. Why 0.79.10 and not 0.78.1: The successor carries a FOURTH advisory that the old name never did -- a moderate "loads project-local extensions without approval" issue whose vulnerable range is < 0.79.0. Pinning the 0.78.1 floor implied by the other three advisories would have swapped three findings for one new one. 0.79.0 is the true floor; 0.79.10 is the newest release on that line. Why not 0.80+: 0.80.0 removes AuthStorage from the package entry point, which packages/shell/src/run.ts uses to point auth and model resolution at the agent's own config dir. That is a real API break needing an auth rewire, and it is out of scope for a dependency migration. 0.81 and 0.82 are additionally inside the repo's own 7-day minimumReleaseAge supply-chain window and are not installable today regardless. Export-surface diff for every symbol we import (SessionManager, ExtensionAPI, AuthStorage, ModelRegistry, DefaultResourceLoader, createAgentSession, AgentSessionEvent) is additive only across 0.73.1 -> 0.79.10: SessionManager.create gained an optional third parameter, createAgentSession gained an optional excludeTools, and ExtensionContext gained mode and isProjectTrusted. No call site required a change, so this commit is a pure rename. bun audit: 4 vulnerabilities (2 high, 2 low) -> 1 (brace-expansion, which is inside the release-age window and resolves on its own). The successor also drops a large amount of transitive surface (extract-zip, proxy-agent, file-type, cli-highlight and their trees), which is why the lockfile is a net deletion. Biome and its platform binaries are untouched, so this avoids the CI-breaking full-lockfile regeneration state. Verification: 293 tests pass / 0 fail, identical to a measured baseline on the parent commit. Build, typecheck, lint and check-workspace-deps all clean. The persistent and run session paths were additionally exercised against a real pi session on both the in-memory and durable SessionManager, A/B against the old package, with identical results. Closes #68 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
tps-sherlock
left a comment
There was a problem hiding this comment.
Security Review: bob#69 — migrate off deprecated pi-coding-agent 🔥
Verdict: APPROVE. The version pin is correct, the extension trust reading is right, and the runtime verification is thorough.
Scrutiny 1: Extension trust — does 0.79.0 gate additionalExtensionPaths?
No, and that's correct. The advisory GHSA-mqxh-6gq7-558m ("Pi loads project-local extensions without approval") affects < 0.79.0. The 0.79.0 fix gates automatic extension discovery — project-local extensions found by scanning the filesystem without explicit approval. Bob's capabilities are registered via additionalExtensionPaths in the capability catalog, which is a deliberate, explicit registration — not automatic discovery. The two paths are distinct:
- Automatic discovery (what 0.79.0 gates): Pi scans the project directory for extensions and loads them without asking. This is the attack vector — a malicious project could include an extension that runs arbitrary code.
additionalExtensionPaths(what bob uses): The caller explicitly passes paths to extension files. This is a deliberate opt-in, not automatic loading.
Bob is not silently relying on a behavior the fix was meant to restrict. The fix restricts automatic discovery; bob uses explicit registration. These are orthogonal.
Scrutiny 2: Version pinning rationale
0.79.10 is the correct floor. Flint's brief of >= 0.78.1 was wrong — the successor carries GHSA-mqxh-6gq7-558m affecting < 0.79.0. Pinning 0.78.1 would have traded three advisories for a new one. The builder caught this independently and verified against the GitHub advisory API.
Not going higher is correct for two independent reasons:
-
0.80.0 removes
AuthStoragefrom the entry point.packages/shell/src/run.ts:304usesAuthStorageto point auth and model resolution at the agent's own config dir. This is a real API break requiring an auth rewire — out of scope for a dependency migration. -
0.81/0.82 are inside bob's 7-day
minimumReleaseAgewindow. Not installable today regardless. Same supply-chain discipline we've been applying consistently.
The builder's brief correction
This is worth highlighting: the builder corrected Flint's brief, and Flint verified the correction independently against the GitHub advisory API. The brief said >= 0.78.1; the correct floor is >= 0.79.0. This is exactly the kind of thing a builder should catch — a security advisory that the briefer didn't know about. The process worked.
Runtime verification
The repo only covers the in-memory session manager. The durable path (SessionManager.create, used by persistent.ts:212) had zero coverage and is exactly where the signature changed. The builder drove bob's own built createPiRunSession against a real pi AgentSession on both paths with a real capability extension, and A/B'd every assertion against the old package — identical behavior.
Lockfile impact
Net deletion: 48 add / 180 del. The successor drops:
extract-zip+@types/yauzl+buffer-crc32+fd-slicer+pend+yauzlproxy-agent+pac-proxy-agent+pac-resolver+degenerator+ast-types+escodegen+esprima+estraverse+esutils+get-uri+basic-ftp+data-uri-to-buffer@6+netmask+socks+socks-proxy-agent+smart-buffer+ip-address+@tootallnate/quickjs-emscripten+proxy-from-envfile-type+strtok3+token-types+@tokenizer/inflate+@tokenizer/token+@borewit/text-codec+ieee754+uint8array-extrascli-highlight+yargs+yargs-parser+cliui+y18n+escalade+get-caller-file+require-directory+mz+any-promise+thenify+thenify-all+object-assign+parse5+parse5-htmlparser2-tree-adapteruuidmime-types+mime-db+@types/mime-typeskoffistrip-ansi+ansi-regex(now only in nested discord.js deps)marked@15→marked@18(direct dep of pi-tui now)undici@7→undici@8(direct dep of pi-coding-agent now)@mariozechner/clipboard@0.3.6→@mariozechner/clipboard@0.3.9(optional dep, still present — clipboard native binary, always a separate package)
Biome and its platform binaries untouched — bob#67 is avoided.
Honesty note
The builder caught its own measurement error: first two audit runs reported exit 0 because the shell captured tee rather than bun audit. Corrected rather than reporting the wrong number. bun audit goes 4 → 1, both runs exit 1.
Verification
- Tests 293 pass / 0 fail, identical to measured baseline
- Build, typecheck, lint, check-workspace-deps clean
bun audit4 → 1 (brace-expansion alone, inside 7-day supply-chain window)- Dependency Audit still red (expected — brace-expansion patch ages out ~2026-07-30)
This is a well-executed migration: correct version pin, correct extension trust reading, thorough runtime verification, and honest about measurement errors.
tps-kern
left a comment
There was a problem hiding this comment.
Architectural review — APPROVED.
The pin at 0.79.10 is correct.
Sanity-checked the pinning rationale:
-
0.79.0 is the true floor, not 0.78.1. The 4th advisory (GHSA-mqxh-6gq7-558m, medium, "loads project-local extensions without approval") affects < 0.79.0. Flint's original brief of >= 0.78.1 was wrong — pinning there would have traded three findings for one new one. The builder caught this by checking the GitHub advisory API and pinned 0.79.10 instead. Correct correction.
-
0.80.0 is out of scope for the right reason: it removes AuthStorage from the package entry point, which packages/shell/src/run.ts:304 uses to point auth and model resolution at the agent's own config dir. That's a real API break needing an auth rewire, not a version bump. Correctly deferred.
-
0.81/0.82 are inside the 7-day minimumReleaseAge window — not installable today regardless. The pin doesn't fight the supply-chain policy. Correct.
The extension trust advisory reading is correct. GHSA-mqxh-6gq7-558m is about loading project-local extensions without approval. The 0.79.0 fix gates auto-discovered project-local extensions, not explicitly-registered additionalExtensionPaths. Bob's capabilities are registered via additionalExtensionPaths — application-controlled, not auto-discovered. The builder confirmed this against the actual 0.79.0 behavior. The trust gate does not restrict what bob does. Correct.
The migration is a pure rename. Every import site (8 files) is just @mariozechner/pi-coding-agent → @earendil-works/pi-coding-agent. No other code changes. The export-surface diff for every symbol bob imports (SessionManager, ExtensionAPI, AuthStorage, ModelRegistry, DefaultResourceLoader, createAgentSession, AgentSessionEvent) is additive only across 0.73.1 → 0.79.10: SessionManager.create gained an optional third parameter, createAgentSession gained an optional excludeTools, ExtensionContext gained mode and isProjectTrusted. No call site required a change. Correct — this is the right shape for a dep migration.
The durable session path coverage is the right call. The repo only covers the in-memory SessionManager; the durable path (SessionManager.create, used by persistent.ts:212) had zero coverage and is exactly where the signature changed. The builder drove bob's own createPiRunSession against a real pi AgentSession on both paths with a real capability extension, A/B'd against the old package — identical. This is the right level of runtime verification for a signature change in an untested path.
Lockfile is a net deletion (48 add / 180 del). The successor drops extract-zip, proxy-agent, file-type, cli-highlight, and yargs. Reduces supply-chain surface. Biome and platform binaries untouched — avoids the bob#67 bunfig.toml trap. Correct.
The builder's self-correction of its own measurement error is worth noting. The first two audit runs reported exit 0 because the shell captured tee rather than bun audit. The builder caught this and corrected it rather than reporting the wrong number. bun audit goes 4 to 1, both runs exit 1. Honest measurement.
7/8 CI green. Dependency Audit still red on brace-expansion (inside the 7-day supply-chain window, resolves itself ~2026-07-30, no excludes entry added). Not this PR's defect.
Ship it.
tps-kern
left a comment
There was a problem hiding this comment.
Architecture review — APPROVED
Version pin rationale — sound
Flint briefed a floor of >= 0.78.1. The builder caught that this would have introduced a NEW advisory (GHSA-mqxh-6gq7-558m, extension trust, < 0.79.0) that the old package never had. Pinning 0.78.1 would have traded 3 findings for 1 new one. The builder pinned 0.79.10 instead — above the real floor of 0.79.0, and the newest on that line.
Not going to 0.80+ is correct for two independent reasons:
- 0.80.0 removes AuthStorage from the entry point, which packages/shell/src/run.ts:304 uses. A real API break needing an auth rewire — out of scope.
- 0.81/0.82 are inside bob's own 7-day minimumReleaseAge window — not installable today regardless.
The pin is the highest version that clears all four advisories without an API break or supply-chain gate violation. Correct.
Extension trust advisory — not a concern for bob
GHSA-mqxh-6gq7-558m is about project-local extensions loading without approval. The 0.79.0 fix gates trust for project-local extensions, but does NOT gate additionalExtensionPaths (host-supplied capabilities). Bob's capabilities are registered via additionalExtensionPaths, not project-local discovery. The builder confirmed extensions still load and register their tools with no trust prompt. This is the right reading — the advisory targets untrusted project-local code, not host-configured extension paths.
Pure rename — no code changes
The export-surface diff is additive only for every symbol bob imports. SessionManager.create gained an optional third parameter (bob calls it with one). createAgentSession options gained optional excludeTools (unused). ExtensionContext gained mode and isProjectTrusted (bob only consumes the type, never constructs it). No call site needed a change. The diff confirms: 14 files, all import-site renames or package.json dependency entries.
Durable path coverage — the real risk was handled
The repo only covers the in-memory session manager. The durable path (SessionManager.create, used by persistent.ts:212) had zero coverage and is exactly where the signature changed (additive optional parameter). The builder drove bob's own createPiRunSession against a real pi AgentSession on both paths with a real capability extension, A/B'd against the old package — identical results. This is the right approach: the risk is not the typecheck (which passes trivially for additive changes) but runtime behavior with a real session.
Lockfile net deletion — correct
48 add / 180 del. The successor drops extract-zip, proxy-agent, file-type, cli-highlight, yargs and their trees. Biome and platform binaries untouched — avoiding the bob#67 CI-breaking regeneration state. The lockfile changes are surgical.
Dependency Audit still red — expected
Only brace-expansion remains, whose patch (5.0.8) is inside the 7-day minimumReleaseAge window until ~2026-07-30. No excludes entry added. Correct — don't rush a supply-chain gate.
Node engines note
The successor requires Node >= 22.19.0 (old required >= 20.6.0). CI uses Node 22, so nothing breaks. No bob package declares engines — a consumer on Node 20 would get a confusing runtime failure. Flagged for the npm-publish work, not this PR. Correct.
Ship it.
Migrates off the deprecated
@mariozechner/pi-coding-agentonto its renamed successor,@earendil-works/pi-coding-agent, at 0.79.10.Closes #68 (option 1 — migrate).
Why there was no bump
All three advisories against the old name report
first_patched_version: null. Its publishedlatestis0.73.1— exactly what we pinned, and also the top of the affected range. No version under that name clears them. The package is deprecated on npm and the fix exists only under the renamed successor.Scope
Runtime dependency in four workspace packages, plus eight import sites:
@tpsdev-ai/bob-shellSessionManager,AuthStorage,ModelRegistry,DefaultResourceLoader,createAgentSession,AgentSessionEvent(runtime)@tpsdev-ai/bob-cap-discordExtensionAPI(type), plus test imports@tpsdev-ai/bob-cap-flairExtensionAPI(type)@tpsdev-ai/bob-cap-observatoryExtensionAPI(type)Bob is not published yet, so there is no compatibility burden — no dual-name fallback or shim, just a clean rename. The
pi-coding-agentkeyword and the unscoped prose references in README/CHANGELOG are generic and unchanged.Version choice
0.79.10, not the 0.78.1 floor. The successor carries a fourth advisory that the old name never did:
< 0.79.0>= 0.74.0, < 0.78.1>= 0.74.0, < 0.78.1>= 0.74.0, < 0.78.1Pinning 0.78.1 would have traded three findings for one new one. The real floor is 0.79.0; 0.79.10 is the newest release on that line.
Not 0.80+.
0.80.0removesAuthStoragefrom the package entry point, whichpackages/shell/src/run.tsuses to point auth and model resolution at the agent's own config dir. That is a genuine API break requiring an auth rewire — out of scope here, and worth its own issue.0.81/0.82are additionally inside this repo's own 7-dayminimumReleaseAgesupply-chain window and are not installable today regardless.Export-surface diff (0.73.1 → 0.79.10)
Additive only, for every symbol we import:
SessionManager.create(cwd, sessionDir?)→ gained an optional thirdoptionsparameter. Bob calls it with one argument.SessionManagergainedusesDefaultSessionDir();findMostRecentSessiongained an optional second parameter. Neither is called by Bob.createAgentSessionoptions gained optionalexcludeTools.ExtensionContextgainedmodeandisProjectTrusted()— Bob only consumes this type, never constructs it.ExtensionAPIgained aproject_trusthandler overload.AuthStorage,ModelRegistry,DefaultResourceLoader,AgentSessionEvent— signatures we use are unchanged.No call site needed a change. This is a pure rename. Relative imports inside the successor's
.d.tsfiles now carry.tsextensions rather than.js;NodeNextresolution handles this and typecheck is clean.Supply-chain effect
bun auditbefore:bun auditafter:brace-expansionis deliberately left alone — the fixed version is inside our ownminimumReleaseAgewindow and ages in on its own. No excludes entry was added to rush it.The successor also drops a lot of transitive surface (
extract-zip,proxy-agent,file-type,cli-highlight,yargsand their trees), which is why the lockfile is a net deletion (48 insertions, 180 deletions). Lockfile changes are surgical: Biome and its platform binaries are untouched, avoiding the CI-breaking full-regeneration state described in #67.Verification
testscript short-circuits on the first failure.bun run build,bun run typecheck,bun run lint(same 1 pre-existing warning), andscripts/check-workspace-deps.mjs— all clean.createPiRunSessionagainst a real piAgentSessionon both paths — in-memory (bob run) and durable (SessionManager.create,bob serve) — loading a real capability extension, and A/B'd every assertion against the old package. Identical results: session construction, capability tool registration, built-in tool composition, thesubscribeseam,isPersisted,getCwd, and dispose.additionalExtensionPathsstill load and register their tools with no trust prompt. This was the main behavioural risk in the jump.bob --helpandbob doctorboth execute against the migrated module graph.Note for sequencing
The successor requires Node >= 22.19.0 (the old package required >= 20.6.0). CI already uses Node 22, so nothing breaks here. But no Bob package declares an
enginesfield, so a consumer on Node 20 would get a confusing runtime failure rather than an install-time error. Addingenginesis publish metadata and overlaps the npm-publish work in flight, so it is deliberately not in this PR — flagging it so it can be picked up there.No workflow files were touched.