# Comate CLI Domain Model

Canonical language for Comate CLI command discovery, transient terminal display, and session reporting boundaries.

## Slash Command Language

**Core Slash Command**:
A slash command backed by a hardcoded Python handler registered in `SLASH_COMMAND_SPECS` (e.g. `/help`, `/model`, `/exit`). Registered with `SlashCommandSource = "builtin"` on the *execution* axis.
_Avoid_: builtin command (ambiguous), native command

**Default Custom Command**:
A markdown-resource slash command shipped inside the `comate_cli` package under `terminal_agent/builtin_commands/`. Loaded via the custom-command pipeline (frontmatter + template), with `source_scope = "default"` on the *source* axis. User-authored custom commands of the same name override it.
_Avoid_: builtin command (ambiguous), bundled command

**Execution Axis** (`SlashCommandSource`):
Describes how a registered command is dispatched. Values: `"builtin"` (hardcoded handler), `"custom"` (markdown template render), `"skill"` (skill slash). Orthogonal to the Source Axis.

**Source Axis** (`CustomSlashCommand.source_scope`):
Describes where a markdown-template command's definition lives. Values: `"project"`, `"user"`, `"plugin"`, `"default"`. Determines override priority only.

**Reserved Name Set** (`builtin_names`):
The set of names derived from `SLASH_COMMAND_SPECS` (Core Slash Commands) that user-authored custom commands may not shadow. A custom command whose name collides with this set is silently skipped with a warning during discovery. **Default Custom Command names do NOT belong to this set** — they are overrideable by design.

**Override Priority Chain**:
`project > user > default` (plus `plugin` registered independently at runtime). When a Default Custom Command and a user/project custom command share a name, the higher-priority scope wins silently (no warning); only the winning entry reaches the registry.

## Streaming Display Language

**Streaming Markdown Container**:
A multi-line Markdown construct in transient assistant output that must remain intact until it can be committed as one immutable scrollback unit. Fenced code blocks and tables are containers; ordinary prose lines are not.
_Avoid_: code buffer, partial Markdown entry

**Fence Boundary Recognition**:
The narrow streaming operation that recognizes a fenced code block's opening and closing delimiter so the whole container can be committed atomically. It accepts zero to three leading spaces, preserves the opening line and its complete info string verbatim, and treats the info string as opaque. This operation does not parse Markdown or perform syntax highlighting.
_Avoid_: Markdown parsing, lexer detection

**Immutable Scrollback Commit**:
The point at which staged terminal output is appended to terminal scrollback and can no longer be replaced. An open Streaming Markdown Container remains transient until its closing boundary or a normal turn boundary makes it complete.
_Avoid_: history render, live Markdown rerender

## Session Reporting Language

**Session Report**:
A durable, session-scoped digest of user turns, model usage, tool activity, health counters, and an optional title, maintained for best-effort upload. It is not a transcript or an event stream.
_Avoid_: session transcript, telemetry event

**Active Report Lifecycle**:
The interval in which a Session Report belongs to the currently active interactive session and is eligible for periodic maintenance. Replacing the active session ends the old lifecycle before the new one begins.
_Avoid_: application lifetime, process lifetime

**Committed Title Input**:
The first non-empty user-authored input accepted as durable session work. Rejected submissions and queued inputs cancelled before admission are not Committed Title Inputs.
_Avoid_: first keypress, submitted text (ambiguous)

**Durable Title Completion**:
A successfully persisted title for a Session Report. Resuming the same session reuses this fact instead of generating another title.
_Avoid_: generated-title flag, controller completion

**Usage Ledger**:
The session's monotonic accumulated record of actual LLM usage. It is the source of truth for the token usage projected into a Session Report.
_Avoid_: context tokens, report tokens

**Report Snapshot**:
A point-in-time, uploadable projection of session-report state and the committed Usage Ledger. It is not an independent token-usage authority.
_Avoid_: usage ledger, live report

**Exit Summary**:
The user-visible terminal result committed before risky process cleanup: Token usage and
resume guidance in TUI mode, or the completed text/JSON result in print mode. It is not
cleanup telemetry and cannot depend on session shutdown succeeding.

**Session Soft Shutdown Budget**:
The maximum time the CLI awaits one session close task before requesting cancellation and
continuing without awaiting cancellation completion. It is capped at eight seconds and by
the remaining Process Exit Deadline. It is not a hard timeout.

**Process Exit Deadline**:
The first-arm-wins, ten-second process deadline that begins only after the Exit Summary has
been flushed. A daemon watchdog enforces it with non-zero hard exit; later cleanup cannot
refresh it.

**Final Report Upload Attempt**:
The process-exit-only, best-effort network attempt for an already durable `ended=true`
Report Snapshot. It shares the Process Exit Deadline with session cleanup; ACK may remove
an unchanged spool, while failure, cancellation, or budget exhaustion preserves it.

## Relationships

- A **Core Slash Command** is always registered with `source="builtin"` on the Execution Axis. Its name belongs to the **Reserved Name Set** and cannot be overridden by any markdown-template command.
- A **Default Custom Command** is registered with `source="custom"` on the Execution Axis (same dispatch path as project/user/plugin custom commands) and `source_scope="default"` on the Source Axis.
- The **Execution Axis** and **Source Axis** are independent. A single registered command carries a value on each.
- The word "builtin" appears only on the Execution Axis (`source="builtin"`) and refers exclusively to **Core Slash Commands**. The Source Axis value `"default"` refers exclusively to **Default Custom Commands**.
- **Default Custom Commands** are loaded from package resources via `importlib.resources`, parsed by the same frontmatter pipeline as project/user commands, and subject to the **Override Priority Chain** at registration time.
- A **Default Custom Command** parse failure is a developer-visible error (raised at discovery), not a user-visible warning, because package resources are trusted input maintained by the comate_cli maintainers.
- The **Reserved Name Set** gates discovery only; it prevents user-authored markdown commands from shadowing **Core Slash Commands**, and only Core Slash Commands.
- **Fence Boundary Recognition** belongs to the streaming lifecycle: `EventRenderer` preserves container atomicity, while Rich remains responsible for Markdown parsing, selecting the first info-string word as the lexer name, syntax highlighting, and plaintext fallback for unknown lexers.
- A fenced code opening or closing delimiter may have zero to three leading spaces. Four or more leading spaces retain Markdown's indented-code semantics and must not open or close a fenced container.
- A normally completed turn may add a synthetic closing delimiter before the **Immutable Scrollback Commit**. An interrupted turn discards its uncommitted container instead.
- The stable-prefix parser used by `codebase_claude` is a separate prototype candidate for nested Markdown structures; it is not part of the fenced-code boundary fix.
- At most one **Active Report Lifecycle** exists in a TUI process. Replacing the active session ends periodic maintenance for the old Session Report before starting it for the new one.
- A **Committed Title Input** exists only after session admission succeeds. A rejected or cancelled input cannot reserve the session title.
- **Durable Title Completion** is scoped by session identity: resuming the same session preserves it, while a rewind fork creates a new session that may generate its own title.
- A **Report Snapshot** observes the **Usage Ledger** only after pending usage has been committed; the snapshot cannot lead its source ledger.
- Failed title-attempt limits belong to one **Active Report Lifecycle** and may reset on a later resume when no Durable Title Completion exists.
- The **Exit Summary** is flushed before the **Process Exit Deadline** is armed and cannot
  depend on a **Session Soft Shutdown Budget** completing.
- Every **Session Soft Shutdown Budget** and the **Final Report Upload Attempt** consume the
  same **Process Exit Deadline**; neither creates or refreshes a deadline.
- Ending an **Active Report Lifecycle** during in-process session replacement still schedules
  best-effort upload without process-exit cancellation rules. Only process exit hands the
  final upload task to the CLI epilogue.

## Flagged ambiguities

- None currently. The original "builtin" collision between Execution Axis and Source Axis has been resolved by reserving "builtin" for Core Slash Commands and introducing "default" for the new shipped markdown resources.
