# cap (taicpp) Port of the CAP section of `../tai.py` (`CAP_VERSION` ... `TAI_CAP_MANIFEST`), normative text in `../cap.md`. Namespace `detz::cap`, sources in `src/cap/`, one class per `.h`/`.cpp` pair. The C++ names are the Python names in camelCase; behavior is verified by running both programs (see Verification). **Wire parsing is untrusted input**: every byte here comes off a socket, so the parsers follow [cpp-safety.md](cpp-safety.md) (overflow-safe size checks, unsigned range-checked lengths, guarded shifts, no exception escaping the read loop, hostile-input tests under sanitizers). We do not accept regressions in that. ## Spec delta (this milestone) - Real `TAI_CAP_MANIFEST` replaces the one-line placeholder (`CapAgentManifest::TAI_CAP_MANIFEST`, `--cap-manifest` prints it plus the `print()` newline; byte-identical to `tai.py --cap-manifest`). - All Cap classes ported: events, errors, bindings, manifest, registry, session config, stream-json, speak session, the four drivers, answerer, session, fleet, CLI. The old `Orchestrator` grant/check placeholder is gone. - Layer `wire_*` (namespace `detz::wire`) supplies what Python's stdlib gave tai.py: `Json` (json), `WireToml` (tomllib), `WireRegex` (re), `WireProc` / `WirePty` (subprocess, PtyProc), `WireHttp` (urllib, http.client, http.server), `WireArgParse` (argparse), `WireShlex`, `WireDifflib`, `WireHash`, `WireText`, `WireOs`. ## Parity table (Python -> C++) | Python | C++ | |---|---| | `CAP_VERSION` `CAP_MANIFEST_SCHEMA` `CAP_PROFILE_CODING` `CAP_MANIFEST_REVISION` `CAP_PROBE_TIMEOUT` `CAP_ERROR_CODES` `CAP_ERROR_STRINGS` `CAP_SESSION_CONFIG_ENV` `CAP_SPEAK_MAX_TURNS` `CAP_SPEAK_DIFF_MAX` `CAP_PTY_SETTLE_MS` `CAP_PTY_IDLE_MS` `CAP_PTY_SUBMIT_GAP_MS` `CAP_PTY_RESUBMITS_MAX` `CAP_PTY_SCROLLBACK` `CAP_PTY_INIT_TIMEOUT` `CAP_STREAM_LINE_MAX` `CAP_STREAM_STDERR_KEEP` `CAP_SESSION_POLL` `CAP_TURN_TIMEOUT` `CAP_WORKTREE_DIR` `CAP_ROUTE_QUEUE_MAX` `CAP_FLEET_DIFF_MAX` `CAP_MENTION_RE` `CAP_ACP_VERSION` `CAP_ACP_TERMINALS_MAX` `CAP_ACP_TERM_BUF` `CAP_ACP_TERM_WAIT_MAX` `CAP_ACP_FS_MAX` `CAP_A2A_TIMEOUT` `CAP_ANSWER_TIMEOUT` `CAP_ANSWER_PARALLEL` `CAP_ANSWER_MARKER` `CAP_ANSWER_RISKS` | `cap_constants.h` (same names) | | `CAP_ERROR_SYMBOLS` | `capErrorNumeric()` in `cap_error.h` | | `TAI_CAP_MANIFEST` | `CapAgentManifest::TAI_CAP_MANIFEST()` | | `CapError` | `cap_error.h` | | `CapEvent` | `CapEvent` (`KINDS`, `DIRECTIONS`, `REQUIRED`, `ENUMS`, `make`, `validate`, `direction`) | | `CapBinding` | `CapBinding` (`ORDER`, `UNSUPPORTED`, `declared`, `select`) | | `CapManifest` | `CapManifest` | | `CapRegistry` | `CapRegistry` | | `CapSessionConfig` | `CapSessionConfig` | | `CapStreamJson` | `CapStreamJson` | | `CapSpeakSession`, `cap_interrupt`, `cap_speak_main` | `CapSpeakSession`, `CapInterrupt`, `CapSpeakMain` | | `CapDriver` | `CapDriver` (`CapDriver::create` in `cap_driver_factory.cpp`) | | `CapPtyDriver` | `CapPtyDriver` over `WirePty` and `CapVtScreen` (port of `TuiVtScreen`, `CapScreen` seam) | | `CapPipeReader`, `cap_proc_kill`, `cap_proc_reap`, `cap_stderr_drain` | `CapPipeReader`, `CapProcUtil`, `CapStderrDrain` | | `CapStreamDriver` `CapAcpDriver` `CapA2aDriver` | same names | | `CapAnswerer` | `CapAnswerer` | | `CapTurnResult` `CapSession` `CapFleet` | same names | | `cap_cli_main` `cap_cli_help` `cap_resolve_main` `cap_chat_main` `cap_run_main` `cap_fleet_plan` `cap_print_result` `cap_build_answerer` `cap_answer_flags` | `CapCli` static methods | ## Event kinds `cap.session.ready`, `cap.text_chunk`, `cap.tool_call.start`, `cap.tool_call.delta`, `cap.tool_call.end`, `cap.plan`, `cap.thought`, `cap.ask_user`, `cap.permission.request`, `cap.usage`, `cap.error`, `cap.artifact`, `cap.fs.change`, `cap.pty.raw_bytes`, `cap.user_input.inject`, `cap.cancel`, `cap.session.config`, `cap.ask_user.answer`, `cap.permission.response`. ## Errors Symbols: `cap_manifest_missing`, `cap_session_config_missing`, `cap_unsupported_capability`, `cap_budget_exceeded`, `cap_invalid_answer`, `cap_unknown_permission`, `cap_queued_input_unsupported`, `cap_cancel_unsupported`, `cap_binding_unavailable`, `cap_profile_unsupported`, `cap_scope_violation`, `cap_path_not_found`, `cap_io_error`, `cap_terminal_unavailable`, `cap_terminal_killed`. String codes: `rate_limit`, `auth_error`, `tool_timeout`, `context_overflow`, `model_unavailable`, `pty_died`, `parse_failed`, `git_dirty`, `test_failed`, `merge_conflict`, `language_server_down`. ## Seams (host-provided) `CapAgentPort` / `CapSpeakHost` (the agent for `--cap-speak`), `WireLog` (debug log sink), `WireApp::setVersion` (VERSION on the wire), `CapPtyDriver::setScreenFactory` (swap the VT screen). Details and the exact hooks: `docs/wiring/capmcp.md`. ## Differences from Python (all declared) - `CapAnswerer` runs `[binary, --auto, prompt]` directly; Python ran `[sys.executable, tai.py, ...]`. Default binary is `/proc/self/exe`. - `CapVtScreen` parses SGR but does not store colors/attributes (text-only consumer) and keeps no scrollback history. - Regex: ECMAScript engine with Python syntax translation. Python-only syntax beyond named groups, `\A`, `\Z`, `$`, bare `{`/`}`, leading `(?i)` is not translated; compile error texts differ from `re.error`. - argparse help is plain (no 3.14 color). - Dates in TOML come back as strings. - Terminal `terminal/output` keeps the `read(65536)` blocking-chunk behavior. - Signals: SIGINT/SIGTERM set a flag polled by waits (`CapInterrupt`). ## Agents, models and `@agent` mentions taicpp lists the installed CAP agents, discovers their models (manifest `[models]` list, optional `--cap-models` probe), and lets a message start with `@agent`, `@agent:model` or `@model`, matched fuzzily and run in a supervised panel on the multiplexer screen. Everything about it is in [cap-agents.md](cap-agents.md); the matching in [fuzzy.md](fuzzy.md); the panels, supervision and result collection in [orchestration.md](orchestration.md). CAP itself (events, bindings, manifest, fleet) is unchanged by this and stays specified on this page. ## Verification `tests/capmcp_diff.py` (JSON, TOML, str(), float repr, regex vs CPython), `tests/capmcp_cli_diff.py` (`--cap-manifest`, `--cap resolve|chat|run` incl. stream-json, PTY, ACP and A2A fake agents, argparse errors at four widths vs `tai.py`), `tests/capmcp_unit.cpp` (tables and drift check).