## Testing


## Input


Inline test input descriptor modeling an event payload.


Usage

``` python
Input(
    *,
    command=None,
    file=None,
    content=None,
    old=None,
    tool=None,
    tool_input=None,
    prompt=None,
    script=None,
    agent_type=None,
    agent_id=None,
    model=None,
    output=None,
    error=None,
    reason=None,
    source=None,
    permission_mode=None,
    cwd=None,
    skip_permissions=None,
    offset=None,
    limit=None,
    transcript=None,
    tasks=None,
    llm=None
)
```


Set the fields the target event reads; all default to `None`.


#### Parameters


`command: str | None = None`  
Bash command for `PreToolUse`/`PostToolUse`.

`file: str | `<a href="testing.html#captain_hook.FileFixture" class="gdls-link gdls-code"><code>FileFixture</code></a>` | None = None`  
The tool's file path. A [FileFixture](testing.md#captain_hook.FileFixture) materializes a real temp file so size/stat-based guards run; a `str` stays a virtual path.

`content: str | None = None`  
New file content for [Edit](prompt-contexts.md#captain_hook.Edit)/`Write`.

`old: str | None = None`  
Pre-edit content for [Edit](prompt-contexts.md#captain_hook.Edit) and [diff_lint](primitives.md#captain_hook.diff_lint).

`tool: str | None = None`  
Tool name when no condition pins it.

`tool_input: dict[str, Any] | None = None`  
Verbatim raw tool-input mapping -- an escape hatch that wins over the input synthesized from the other fields.

`prompt: str | None = None`  
An Agent/Task call's prompt, or `UserPromptSubmit` text.

`script: str | None = None`  
A [Workflow](state-sessions.md#captain_hook.Workflow) tool's script source (synthesizes a Workflow call).

`agent_type: str | None = None`  
Subagent type for subagent events (an Agent/Task call's `subagent_type`).

`agent_id: str | None = None`  
Subagent/teammate id -- a non-empty value makes `evt.is_subagent` true (and fills subagent events' [agent_id](events-results.md#captain_hook.BaseHookEvent.agent_id)); each id also gets its own `max_fires` budget.

`model: str | None = None`  
Model for an Agent/Task call's `model` input field.

`output: str | None = None`  
The tool result surfaced to `PostToolUse` as `evt.tool_response`.

`error: str | None = None`  
The failure text surfaced to `PostToolUseFailure` as `evt.error`.

`reason: str | None = None`  
`SessionEnd` reason.

`source: str | None = None`  
`SessionStart` source (`startup`/`resume`/`clear`/`compact`).

`permission_mode: str | None = None`  
Permission mode, e.g. `"plan"` for plan-mode gating.

`cwd: str | None = None`  
The session working directory surfaced as `evt.cwd`, for hooks that resolve relative tool paths.

`skip_permissions: bool | None = None`  
Pre-seeds `evt.skip_permissions` (normally the process-tree walk for `--dangerously-skip-permissions`); `None` leaves the real walk in place.

`offset: int | None = None`  
`Read` call offset.

`limit: int | None = None`  
`Read` call limit.

`transcript: Path | `<a href="testing.html#captain_hook.TranscriptFixture" class="gdls-link gdls-code"><code>TranscriptFixture</code></a>` | list[dict[str, Any]] | None = None`  
Session history for transcript conditions -- a path, a [TranscriptFixture](testing.md#captain_hook.TranscriptFixture), or a raw list of transcript-line dicts.

`tasks: list[dict[str, Any]] | None = None`  
The native task list read via `evt.tasks`.

`llm: dict[str, Any] | None = None`  
Per-test LLM stub overrides merged over the default stub verdict (`fire`/[block](prompt-contexts.md#captain_hook.Excerpts.block)/`action`/`reasoning`), e.g. `llm={"fire": False}` to exercise an LLM hook's judge-declines path.


## T


Namespaced transcript-fixture builders for `Input(transcript=[...])` in inline tests.


Usage

``` python
T()
```


Every builder returns a plain dict -- a bare transcript line or a content block -- that `~captain_hook.testing.types.TranscriptFixture` accepts as-is, so `T.*` builders and hand-written raw dicts mix freely in one `transcript` list. Line builders ([user()](testing.md#captain_hook.T.user), [assistant()](testing.md#captain_hook.T.assistant)) emit the envelope-free shape the fixture loader completes; block builders delegate to `cc_transcript.synthetic` so the shapes cannot drift from the parser.


#### Example

``` python
>>> from captain_hook.testing.types import Input
>>> Input(transcript=[
...     T.user("Re-enter plan mode, don't do any more work."),
...     T.assistant(T.tool("EnterPlanMode")),
...     *T.tool_turn("Bash", result="ModuleNotFoundError", is_error=True, command="uv run pytest"),
... ])
```

Input(transcript=…)


#### Methods

| Name | Description |
|----|----|
| [assistant()](#captain_hook.T.assistant) | An [assistant](testing.md#captain_hook.T.assistant) transcript line whose message carries `content`. |
| [result()](#captain_hook.T.result) | A `tool_result` content block; [of](events-results.md#captain_hook.HookResult.of) correlates it to the call it answers. |
| [thinking()](#captain_hook.T.thinking) | A [thinking](testing.md#captain_hook.T.thinking) content block for [assistant()](testing.md#captain_hook.T.assistant). |
| [tool()](#captain_hook.T.tool) | A `tool_use` content block invoking [name](files-commands.md#captain_hook.Call.name); keyword arguments become its input. |
| [tool_turn()](#captain_hook.T.tool_turn) | A paired assistant tool-call line and user tool-result line with matched ids. |
| [user()](#captain_hook.T.user) | A [user](testing.md#captain_hook.T.user) transcript line whose message carries `content`. |


##### assistant()


An [assistant](testing.md#captain_hook.T.assistant) transcript line whose message carries `content`.


Usage

``` python
assistant(*content, **meta)
```


##### Parameters


`content: str | dict[str, Any] = ()`  
Text strings (wrapped as `text` blocks) or raw content-block dicts, typically a [tool()](testing.md#captain_hook.T.tool) call block.

`meta: Any = {}`  
Envelope fields merged onto the line.


##### Example

``` python
>>> T.assistant("planning the change")
```

{'type': 'assistant', 'message': {'content': \[{'type': 'text', 'text': 'planning the change'}\]}}


##### result()


A `tool_result` content block; [of](events-results.md#captain_hook.HookResult.of) correlates it to the call it answers.


Usage

``` python
result(content="ok", *, of=None, is_error=False)
```


##### Parameters


`content: str = ``"ok"`  
The result text surfaced to the tool caller.

`of: dict[str, Any] | str | None = None`  
The call this result answers -- a [tool()](testing.md#captain_hook.T.tool) block (its id is read), a raw `tool_use` id string, or `None` to mint a fresh unpaired id.

`is_error: bool = ``False`  
Marks a failed call, lifting to a failure in the parsed session.


##### Example

``` python
>>> call = T.tool("Bash", command="uv run pytest")
>>> T.result("ModuleNotFoundError", of=call, is_error=True)
```

{'type': 'tool_result', 'tool_use_id': …, 'content': 'ModuleNotFoundError', 'is_error': True}


##### thinking()


A [thinking](testing.md#captain_hook.T.thinking) content block for [assistant()](testing.md#captain_hook.T.assistant).


Usage

``` python
thinking(text)
```


##### Example

``` python
>>> T.assistant(T.thinking("The user asked for a rename only."))
```

{'type': 'assistant', 'message': {'content': \[{'type': 'thinking', 'thinking': …}\]}}


##### tool()


A `tool_use` content block invoking [name](files-commands.md#captain_hook.Call.name); keyword arguments become its input.


Usage

``` python
tool(name, /, *, id=None, **input)
```


##### Parameters


`name: str`  
The tool name, e.g. `"Bash"` or `"EnterPlanMode"`.

`id: str | None = None`  
The `tool_use` id; a fresh `tu-N` id is minted when omitted. Keep explicit ids outside the `tu-<int>` namespace auto-minting uses.

`input: Any = {}`  
The tool input fields, e.g. `command="uv run pytest"`.


##### Example

``` python
>>> T.tool("Bash", command="uv run pytest")
```

{'type': 'tool_use', 'id': …, 'name': 'Bash', 'input': {'command': 'uv run pytest'}}


##### tool_turn()


A paired assistant tool-call line and user tool-result line with matched ids.


Usage

``` python
tool_turn(name, /, *, result="ok", is_error=False, **input)
```


Splat the returned pair into a `transcript` list to model one full tool round-trip.


##### Parameters


`name: str`  
The tool name, e.g. `"Bash"`.

`result: str = ``"ok"`  
The tool-result content joined back to the call.

`is_error: bool = ``False`  
Marks the call as failed.

`input: Any = {}`  
The tool input fields, e.g. `command="uv run pytest"`.


##### Example

``` python
>>> T.tool_turn("Bash", result="ModuleNotFoundError", is_error=True, command="uv run pytest")
```

\[{'type': 'assistant', …}, {'type': 'user', …}\]


##### user()


A [user](testing.md#captain_hook.T.user) transcript line whose message carries `content`.


Usage

``` python
user(*content, **meta)
```


##### Parameters


`content: str | dict[str, Any] = ()`  
Text strings (wrapped as `text` blocks) or raw content-block dicts.

`meta: Any = {}`  
Envelope fields merged onto the line, e.g. `isMeta=True` for a meta turn.


##### Example

``` python
>>> T.user("ship it")
```

{'type': 'user', 'message': {'content': \[{'type': 'text', 'text': 'ship it'}\]}}


## Allow


Inline test expectation: the hook should allow (return None or action `"allow"`).


Usage

``` python
Allow(*, explicit=False)
```


`explicit=True` requires an actual allow result -- `None` no longer matches, so e.g. a `PermissionRequest` hook must have answered the dialog itself.


#### Parameter Attributes


`explicit: bool = ``False`  


## Block


Inline test expectation: the hook should block. Optional regex `pattern` matches the block message.


Usage

``` python
Block(*, pattern=None)
```


#### Parameter Attributes


`pattern: str | None = None`  


## Warn


Inline test expectation: the hook should warn. Optional regex `pattern` matches the warning message.


Usage

``` python
Warn(*, pattern=None)
```


#### Parameter Attributes


`pattern: str | None = None`  


## Rewrite


Inline test expectation: the hook should rewrite the tool input.


Usage

``` python
Rewrite(pattern=None, **fields)
```


`pattern` is a substring matched against the rewritten command (`updated_input["command"]`) -- substring, not regex, so an absolute path prefix in the rewritten command does not break the match. Additional keyword arguments substring-match against the named `updated_input` field, so an Agent auto-upgrade can assert `Rewrite(model="sonnet")`; all given fields (and `pattern`) must match.


#### Parameter Attributes


`pattern: str | None = None`  

`fields: str = {}`  


## Ask


Inline test expectation: the hook returned no result (`None`).


Usage

``` python
Ask()
```


For `PermissionRequest` hooks this means the permission dialog shows; a [warn](events-results.md#captain_hook.BaseHookEvent.warn) result fails [Ask()](testing.md#captain_hook.Ask).


## FileFixture


Inline-test file descriptor: materialized to a real temp file so size/stat-based guards run for real.


Usage

``` python
FileFixture(*, size=None, content=None, name=None, home=False)
```


`home=True` materializes the file under a per-test temporary "home" directory instead of the shared fixture directory, and `run_inline_tests` swaps `$HOME` to that directory for the duration of that one test's hook execution -- restored afterward even on failure -- so an `os.path.expanduser`-based hook resolves deterministically. Requires [name](files-commands.md#captain_hook.Call.name).


#### Parameter Attributes


`size: int | None = None`  

`content: str | None = None`  

`name: str | None = None`  

`home: bool = ``False`  


## TranscriptFixture


A lightweight transcript stub for use in inline tests.


Usage

``` python
TranscriptFixture(messages)
```


Wraps a list of raw transcript-line dicts that get lifted into a query `Session` when the test runs; missing envelope fields are synthesized.
