Topic "{topic}". A previous step produced a flat list of learning items that is TOO FINE-GRAINED for a table of contents — single environment variables, single CLI flags, single config fields, near-synonyms. Your job is **card sorting**: group the items into a small set of **theme blocks**, so that EVERY item lands in exactly one theme. Nothing is discarded — grouping never loses an item; it only organises them.

Think of the result as chapters: ~15–25 themes for a whole topic, each a coherent learning block that a learner meets as one unit. A theme with only one fitting item is fine (a genuinely standalone concept), but prefer pulling related items together over leaving many singletons.

CANDIDATES you may group (your starting point — a pre-clustered neighbourhood):
{candidates}

FULL ITEM LIST (you may pull in ANY numbers below that share the theme):
{list}

## How to form a theme
- **One coherent subject.** The members belong together because a learner would study them as one block — the parts/facets/instances of one model, system, setup, tool family, or category. Examples of the *kind* of grouping (not domain rules): many individual settings/variables/flags of one configuration → one „…-Konfiguration" theme; the parts of one setup → one „…-Setup" theme; a base concept plus its variants/instances → one theme.
- **Lexical dissimilarity is NORMAL.** Facets of one theme often read very differently — that is not a reason to split them.
- **Title:** name the theme after the shared subject. A real self-contained heading; must NOT contain „ — " (reserved separator) — use „(…)" or „:".
- **Description:** name EVERY member explicitly (the next step recovers them as sub-points). E.g. „Environment-Konfiguration: APP_ENV, APP_SECRET, DATABASE_URL, MAILER_DSN, …".
- **Members:** the item NUMBERS from the full list. Each number goes into exactly ONE theme; do not repeat a number across themes.

Assign as many items as you confidently can. Items you are unsure about you may leave out — a later completion step and a singleton fallback catch them; never force a bad fit.

Write ONLY the JSON file to: {out_path}

Format (`umbrellas` = the themes; may be empty if nothing fits together):
{{"umbrellas": [{{"title": "Environment-Konfiguration", "description": "Konfiguration über Umgebungsvariablen: APP_ENV, APP_SECRET, DATABASE_URL, MAILER_DSN, .env-Dateien.", "members": [1, 2, 5, 12, 34]}}]}}
