Franklin Agent 3.37.0 — the dependency backlog, cleared
`ws` was never actually declared. `src/serve/server.ts` imported it while `package.json` never listed it — it resolved only because a transitive dependency happened to hoist it to the top of `node_modules`. Any shift in that tree, or in npm's hoisting, would have broken `franklin serve` at runtime with nothing in CI to catch it. The types were wrong too (`@types/ws` pinned at 7 while ws 8 actually ran), which is precisely why the bump 3.35.6 backed out of failed to compile.
Seven majors taken, each verified beyond the suite — typescript 5.9→7.0 (compiled with both and diffed `dist/`: 2 cosmetic differences), ink 6→7 (rendered the real `VimInput`), commander 13→15 (ran the built CLI), @slack/bolt 4→5, sharp 0.34→0.35 (ran the real downscale pipeline), codegraph 0.9.7→1.5.0 (real MCP handshake), @types/node 22→26.
Two security findings fixed, the rest upstream-blocked. sharp 0.35.3 clears the inherited libvips CVEs, which sit on a reachable path — Franklin runs user-supplied images through sharp before vision calls. An override keyed on the ws advisory range (not the package name) removes the vulnerable copy `@ethersproject/providers` dragged in, while leaving jayson on 7.5.13 and viem on 8.21.0 — both already outside the range. High findings 8 → 6, total 31 → 29; every remaining one reports `fixAvailable: false`.
CodeGraph is unpinned. 1.x added an `exports` map that stopped listing `./npm-shim.js` even though the file still ships as the package's `bin`. Franklin now resolves the manifest and walks to the shim beside it. 1.5.0 consolidates the old five tools into a single `codegraph_explore`; nothing hardcodes those names.
Two upgrades deliberately declined. `@polymarket/builder-signing-sdk` 1.0.0 type-conflicts with the copy `builder-relayer-client` bundles, and that package is at its latest while still requiring `^0.0.8`. `@polymarket/clob-client-v2` 1.1.0 adds a `waitForResolvedTrades` step so `postOrder` now waits on settlement hashes — live behavior on the order-placement path that no local test covers — so it stays pinned pending the paired blockrun-mcp re-sync.