> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nika.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Transcript show-notes

> T2 chain · podcasts / meetings: raw transcript → typed show-notes (chapters, quotes, summary) in ONE bounded infer.

> **T2 chain · podcasts / meetings**: `nika:read` loads the raw
> transcript, ONE `infer:` with a strict `schema:` extracts chapters +
> pull-quotes + summary as typed data, `nika:jq` shapes the sections,
> and `nika:write` renders the publishable page. The model is called
> exactly once, and its output is schema-validated before anything
> downstream touches it.

## The job

Show-notes are the chore between "episode recorded" and "episode
published": an hour of scrubbing for chapter marks and quotes. This
workflow does the extraction in one bounded model call — bounded in
*shape* (the schema rejects free-form prose) and in *count* (one
infer, so the cost of an episode is the cost of one call, visible in
`nika check` before you run).

## The shape

```mermaid theme={"system"}
flowchart LR
  raw["raw · nika:read"]:::invoke
  notes["notes · typed"]:::infer
  sections["sections · nika:jq"]:::invoke
  page["page · nika:write"]:::invoke
  raw --> notes
  notes --> sections
  sections --> page
  notes --> page
  classDef infer fill:#5b8cff22,stroke:#5b8cff,color:#5b8cff
  classDef invoke fill:#22d3ee22,stroke:#22d3ee,color:#22d3ee
```

## The file

```yaml t2-transcript-shownotes.nika.yaml theme={"system"}
nika: v1
workflow: transcript-shownotes
description: "Raw transcript → typed show-notes (chapters · quotes · summary) · one bounded infer"

model: ollama/llama3.2:3b # local · zero key · deliberately NOT the qwen3.5 convention: a thinking model can burn max_tokens in its think block before the JSON (engine#428) — schema showcases pick a non-thinking model

vars:
  transcript: "./data/transcript.txt"

permits:
  exec: false
  fs:
    read: ["data/**"]
    write: ["out/**"]
  tools: ["nika:read", "nika:jq", "nika:write"]

tasks:
  - id: raw
    invoke:
      tool: "nika:read"
      args: { path: "${{ vars.transcript }}" }

  # ONE bounded model call · the schema is the contract, not a suggestion.
  - id: notes
    depends_on: [raw]
    infer:
      prompt: |
        Turn this transcript into show-notes. Ground every chapter title
        and quote in the text — invent nothing.

        Transcript ·
        ${{ tasks.raw.output }}
      max_tokens: 800
      schema:
        type: object
        additionalProperties: false # a deterministic shape across providers (the checker's strictness hint)
        required: [summary, chapters, quotes]
        properties:
          summary: { type: string }
          chapters:
            type: array
            items:
              type: object
              additionalProperties: false
              required: [title, gist]
              properties:
                title: { type: string }
                gist: { type: string }
          quotes:
            type: array
            items: { type: string }

  # Typed JSON → markdown lines · mechanical, zero second model call.
  - id: sections
    depends_on: [notes]
    invoke:
      tool: "nika:jq"
      args:
        input: "${{ tasks.notes.output }}"
        expression: >-
          {
            chapters: (.chapters | map("- **\(.title)** — \(.gist)") | join("\n")),
            quotes: (.quotes | map("> \(.)") | join("\n\n"))
          }

  - id: page
    depends_on: [sections, notes]
    invoke:
      tool: "nika:write"
      args:
        path: out/show-notes.md
        content: |
          # Show notes

          ${{ tasks.notes.output.summary }}

          ## Chapters

          ${{ tasks.sections.output.chapters }}

          ## Pull quotes

          ${{ tasks.sections.output.quotes }}

          *Generated by [nika](https://nika.sh) · one bounded infer, typed output · the run's trace is the receipt.*

outputs:
  notes:
    value: ${{ tasks.notes.output }}
    type: object
    description: "The typed show-notes · summary + chapters + quotes"
```

## The model choice is part of the lesson

The envelope pins `ollama/llama3.2:3b` — deliberately NOT the
showcase's usual `qwen3.5` — because this is a strict-schema job and a
*thinking* model can burn the whole `max_tokens` budget inside its
think block before emitting the first JSON token (engine issue #428:
the output arrives empty yet the schema demanded content). The rule of
thumb this file encodes: **reasoning showcases pick a thinking model;
strict-schema extraction picks a non-thinking one.**

The typed seam is the other half: because `notes` is schema-shaped,
the jq step reads `.chapters[]` and `.quotes[]` as data — no regex
over model prose, no "hopefully it used the same markdown headings
this time".

## Run it

```bash theme={"system"}
ollama pull llama3.2:3b
git clone https://github.com/supernovae-st/nika-spec && cd nika-spec
nika run examples/showcase/t2-transcript-shownotes.nika.yaml
open out/show-notes.md
```

<Note>
  This workflow is newer than the currently shipped engine pack:
  `nika examples run showcase/t2-transcript-shownotes` says
  `unknown example` until the next engine tag re-vendors the pack.
  Until then, run it from the spec checkout as above — the file is the
  same one the pack will embed, sha-pinned in the spec manifest.
</Note>

Feed it any meeting transcript instead: the schema does not care
whether the speakers were recording a podcast or arguing about a
roadmap.
