Day 13 — 'the cross-repo trap.'
A subtle SR8 deploy bug: werbos was calling Agent(one_call_per_iteration=...) but the pinned pitts SHA didn't accept that kwarg, so every POST /api/chats 500'd with TypeError on container restart. Root cause was sneakier than the symptom — the deploy script was only pulling the werbos repo on SR8, leaving its 9 sibling repos (pitts, pfm, mcculloch, etc.) silently stale. Two fixes: bump the pitts pin to a SHA that has the kwarg, and teach redeploy.sh to pull every sibling before building. Plus Phase 17 / Sprint NP.1 (npm install -g werbos) lands on the roadmap. 3 commits.
“the cross-repo trap.”
Late-night fire drill that turned into a deploy-hygiene fix.
The symptom
POST /api/chats returning 500 immediately after a SR8 redeploy.
Stack trace pointed straight at Agent.__init__() rejecting a kwarg
one_call_per_iteration that werbos was passing on every session
construction.
The trap underneath: werbos/session/chat.py had been bumped to
pass that kwarg, but pyproject.toml was still pinned at an older
pitts SHA (107adb2) that didn’t accept it. The local editable
checkout of pitts had the matching code, but uncommitted — so
local tests passed, the live SR8 build broke. Cross-repo half-
finished change.
Fix in two layers
- Layer 1 — pitts upstream. Commit + push the
one_call_per_iterationsafety belt (pittsc8e1867), then bump the werbos pin (7c07747) to consume it. 2 regression tests for the dispatch behavior: with the flag, only the FIRST tool_call from a multi-call AssistantMessage fires; the model re-decides on iteration N+1. - Layer 2 — the deploy trap that produced the bug. The bigger
realization was why I’d missed the version mismatch:
deploy/sr8/redeploy.shonlygit pulled the werbos repo, but the docker build context on SR8 copies nine sibling repos (pitts,pfm,mcculloch,partyparrot-py,observe,watchtower,warden,beacon,werbos-suite-ui) directly into the build context. Pulling only werbos silently shipped stale sibling code. Re-bake the script (1a4f369) to pull every expected sibling,--ff-onlyso divergence surfaces loudly, skip any repo with uncommitted work. Trap closed permanently.
Phase 17 / Sprint NP.1 — npm install -g werbos
Captured the npm-wrapper plan as a sprint on the roadmap
(d8f48f5). Architecture: thin JS shim over system Python,
child_process.spawn('python3', ['-m', 'werbos', ...]) — no
bundled Python (~40 MB × 3 platforms is the wrong trade for
Phase 1), no Node-Python bridge dependency. Lockstep version
with the PyPI wheel; mac + linux only for Phase 1; Tauri
explicitly deferred.
The acceptance criterion locked early: a clean machine with
only python3 + node installed must run npm install -g werbos
and end up with a working werbos binary that pulls in every
needed file, sets up data directories, and launches both
werbos chat and werbos serve end-to-end. Real test, not
“the install succeeded.”
Aphorism worth keeping
“Pulling only werbos silently shipped stale sibling code.”
Cross-repo changes need cross-repo deploys. The lesson the trap
taught: redeploy.sh is part of the codebase, not just an
operator note. If the script lies about what it pulls, the
build will eventually disagree with the source.