# Generated types

The files under `./generated/` mirror TypeScript types **generated by `xtask`
in the private [`tmai-core`](https://github.com/trust-delta/tmai-core) repo**
from its Rust `serde` structs (via [`ts-rs`](https://github.com/Aleph-Alpha/ts-rs)
and [`utoipa`](https://github.com/juhaku/utoipa)). The output lands here via
the `gen-spec-pr` bot PRs that also refresh `api-spec/` at the monorepo root
in lockstep. The WebUI consumes the result; it never imports from
`tmai-core` directly.

Do **not** hand-edit anything in `./generated/`.

## What lives where

- `generated/*.ts` — TypeScript types for every public payload (`CoreEvent`,
  `TaskMetaSnapshot`, `WorktreeInfo`, …).
- `generated/openapi.json` — OpenAPI 3 document for the REST surface.
- `index.ts` — barrel re-exports for consumers.
- `sse-event.ts` — typed narrower that turns the untyped `SSEHandlers.onEvent`
  payload into a discriminated `CoreEvent`.

## How the sync works

`tmai-core`'s CI runs a workflow that:

1. Runs `cargo run -p xtask -- gen-{openapi,schema,ts-types,mcp-snapshot}` to
   regenerate the wire artefacts.
2. Opens a `bot/gen-spec-pr/<core-sha>` branch on `trust-delta/tmai` (this
   monorepo) carrying the updated `api-spec/openapi.json`,
   `api-spec/corevents.schema.json`, `api-spec/mcp-tools.json`, and the
   refreshed `clients/react/src/types/generated/*.ts`.

When the bot PR lands on `main`, the React types are already in place. No
manual sync step is required — but if you need to pull the artefact early
(e.g. to test an in-flight contract change), you can run the matching
`xtask` invocation against your local `tmai-core` checkout and copy the
output here. CI will reject hand edits that don't come from the bot path.

If a contract shape looks wrong here, fix it in `tmai-core` → trigger a
fresh `gen-spec-pr` → merge the bot PR. **Never** patch `./generated/`
in place: the next bot PR will overwrite it and the silent drift wedges
the next bot CI run.

## Adding a new generated type to the barrel

When `tmai-core` exports a new top-level type and it lands in
`./generated/`, expose it from the barrel:

```ts
// src/types/index.ts
export type { NewPayload } from "./generated/NewPayload";
```

Then consumers can import via the barrel:

```ts
import type { NewPayload } from "@/types";
```

## Why this indirection

`tmai-core` is private for IP reasons, but its wire shapes must be public
so alternative UIs can be built. The `api-spec/` directory at the monorepo
root is the public surface; this `./generated/` tree is the TypeScript
projection of that surface for the React WebUI specifically. Other
language clients consume the same shapes via the OpenAPI document or the
JSON Schema for SSE events.
