# Inbox Shared Test Conventions ## Purpose This document captures shared assumptions used by multiple `inbox` test-plan documents so command and workflow files can stay focused on behavior rather than repeating setup boilerplate. ## Recommended Fixture Shape Use an isolated temp workspace per case: - database path: `TMPDIR/coord.db` - optional body file: `TMPDIR/body.md` - optional artifact file: `TMPDIR/artifact.txt` Recommended bootstrap command: ```bash inbox --db TMPDIR/coord.db --json init ``` ## Global Flags Root-level flags apply to every subcommand: - `--db`: SQLite database path, default `.agents/coord.db` - `--json`: emit machine-readable JSON - `--agent`: acting agent identity shortcut used by commands that accept agent context When a command-specific `--agent` or `--from` flag is omitted, the root `--agent` value may be used instead. Cases that verify fallback behavior should state that explicitly. ## Success JSON Contract Successful JSON output uses this shape: ```json { "ok": true, "command": "send", "data": {} } ``` Shared assertion points: - `ok` is `true` - `command` matches the invoked subcommand - `data` contains the command-specific payload ## Error JSON Contract Failure JSON output uses this shape: ```json { "ok": false, "error": { "code": "invalid_input", "message": "..." } } ``` Shared assertion points: - `ok` is `false` - `error.code` matches the stable contract - `error.message` is present and human-readable ## Exit Code Contract The current CLI contract uses these exit codes: | Exit Code | Meaning | Typical Error Code | | --- | --- | --- | | `0` | success | none | | `10` | no matching work / timeout without match | `no_matching_work` | | `20` | lease conflict | `lease_conflict` | | `30` | invalid input, invalid state, usage-style error | `invalid_input` or `invalid_state` | | `40` | referenced thread or message missing | `not_found` | | `50` | unexpected internal failure | `internal_error` | When a case expects no result, assert both the exit code and the JSON error code. ## Body Input Rules Commands that support `--body` and `--body-file` follow these rules: - `--body` and `--body-file` are mutually exclusive - `--body-file` content is read verbatim into the message body - unreadable `--body-file` should be treated as `invalid_input` Relevant commands: - `send` - `update` - `reply` - `done` - `fail` ## Artifact Rules Commands with artifact support use these shared rules: - `--artifact` may be repeated - `--artifact-kind` may be specified once for all artifacts, or once per artifact - `--artifact-metadata-json` may be specified once for all artifacts, or once per artifact - `--artifact-kind` and `--artifact-metadata-json` are invalid without at least one `--artifact` - an empty artifact path is invalid input When artifact behavior is under test, assert at least: - artifact count - artifact `path` - artifact `kind` - metadata presence when supplied ## Read And Unread Assertions Unread-related cases should verify behavior from the agent's point of view, not only raw message existence. Recommended checks: - `fetch --unread` returns a thread before read acknowledgement - `show --mark-read` clears unread state for that agent - a new message to the same thread makes the thread unread again - `wait-reply` may clear blocked unread state for the waiting agent when the reply is consumed ## Workflow Authoring Rule If a case spans multiple commands, place the end-to-end narrative in `workflows/README.md` first, then add narrower command-level cases only when they introduce behavior that is easier to reason about in isolation.