# glue issues and gaps Found while wiring `src/glue`. Each entry names the file and the smallest repro. Nothing here was patched around silently; items marked "glue side" are limits the glue itself has. ## Open 1. **No vault seal.** `src/seal` is empty (another agent ports `Seal`). `repl::Boot` uses `store::NullSeal` when `TAI_PASSPHRASE` is unset: the banner says `seal: off`, python says `on (default key)`. An explicit `TAI_PASSPHRASE=x` is refused: `seal error: TAI_PASSPHRASE is set but this build links no vault seal` (exit 2). Repro: `TAI_PASSPHRASE=x build/detz --version` works (before boot), `TAI_PASSPHRASE=x build/detz hi` exits 2. Closes with a `store::SealPort` implementation passed as `BootOptions::seal_factory` in `src/glue/app_bundle.cpp` (one line). 2. **`SysInfo.collect_sysinfo` was ported by no module** (`tai.py` 8978-9008). `src/comms/comms.cpp` only has a stub `sys_info()`. The glue carries `SysInfoProbe` (sequential, each check timed, 10 s ceiling); the python runs the checks on threads. `python` and `venv` checks report the native binary instead of an interpreter. 3. **`release` tool cannot work natively.** `do_release` rewrites the `VERSION =` line of the running script. The binary has no script. `OpsAdapter::do_release` throws and the tool reports the error; the native flow is `make release PART=... MSG=...` in `taicpp/`. `ensure_self_backup` at boot is not called for the same reason. 4. **Ctrl-C does not kill the call in flight** (glue side). `AgentReplHost` expires `agent.deadline`, the loop stops at the next step. A running HTTP call, shell command or sandbox exec finishes first. `agent::Agent` has no cancellation point inside `ChatClient::complete`. 5. **MCP port is bound to the main agent** (glue side). `McpHostAdapter` asks approvals, names the audit actor and runs the resolver subagent through the primary agent, and uses the primary store connection. A worker agent on its own thread that calls an MCP tool therefore shares the primary sqlite connection. tai.py passes the calling agent (`app`) instead. Needs the port to carry the caller, i.e. `McpPort::call(..., Agent&)`. 6. **`docs/wiring/capmcp.md` does not exist.** The task listed it; `cap`/`mcp` were wired from the headers (`cap_agent_port.h`, `mcp_serve_main.h`, `mcp_host.h`) and `cap.md`/`mcp.md`. 7. **`src/cli`**: `Command::run()` is still the stub (`--help`/`--version` only) and `Parser::parse` maps `argc <= 1` to `--help`, whereas tai.py starts the REPL. `main.cpp` therefore calls `Parser::parseOpts` and `GlueApp::run` (which prints help only for an explicit `--help`). The other agent that rewrites `src/cli` should drop `Command` or keep `parseOpts` and the `Options` fields stable. 8. **`Makefile`**: `-I../../moloapp/src` resolves from `taicpp/` of the main checkout only. From a git worktree (`.claude/worktrees/*/taicpp`) it needs `CXXFLAGS=... -I/home/retoor/projects/moloapp/src`. `make test` builds `tests/test_main.cpp`, which still calls the removed placeholder API (`llm::ChatClient("openai", ...)`, `ModelHealth`, `Opencode`, `feed_sse`, `provider_info`; docs/wiring/agent.md); not touched here. 9. **`probe_backend` in the REPL banner** runs sequentially with a 6 s timeout per backend, like python: a dead backend delays the prompt. Not changed. 10. **Not covered by a committed test:** `--tui-local` (driven once over a pty by a throwaway script: it drew, ran a real model turn whose answer reached the vault session, and `/quit` exited 0), `--tui` (grr client; without a tty it exits 2 with `tui unavailable`, no grr server was started), `--mplex` and `--plexer-wrap` (without a tty they answer `no server running on ...` / `open terminal failed: not a terminal`, exit 1; the multiplexer session itself was not started), `--install` (run once against a throwaway `HOME`: binary copy, bash hook, venv and six bundled skills written, exit 0), `--update-models` (read-only discovery ran), `--eval-retrieval` and `--stats-rag` (empty vault only). 11. **`--cap-speak` string content.** A `{"type":"user","message":{"role":"user","content":"text"}}` frame (content a plain string) is split into one character per line before it reaches the model. This is the literal tai.py behavior (`cap_stream_json.cpp` mirrors `for block in message.get("content")`); real clients send a block list, which `tests/glue_flags.py` uses. Noted so nobody files it as a port bug. ## Fixed in the glue (one-line integration errors) - None needed in other modules: every compile error was on the glue side.