soju levels

Purpose: List and assign course levels on vocabulary registry entries and grammar pattern files. Catalog of valid ids lives in data/content/levels.yaml.

Omitted level means unassigned (not a silent default to 1A). Present level values must be keys in levels.yaml; unlisted ids fail write paths and soju registry / poe validate.

Reads

data/content/levels.yaml, data/content/registry/vocabulary.yaml, data/content/grammar/ (manifest + patterns)

Writes

Vocabulary level fields, or grammar pattern level fields (by --kind)

Exit codes

0 success · 1 error · 2 usage error

levels

                                                                              
 Usage: soju levels [OPTIONS] COMMAND [ARGS]...                               
                                                                              
 List and assign vocabulary and grammar course levels.                        
                                                                              
╭─ Options ──────────────────────────────────────────────────────────────────╮
│ --help          Show this message and exit.                                │
╰────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ─────────────────────────────────────────────────────────────────╮
│ list-unassigned  List entries with no course level tag.                    │
│ set              Assign a course level to selected vocabulary or grammar   │
│                  entries.                                                  │
╰────────────────────────────────────────────────────────────────────────────╯

list-unassigned

                                                                              
 Usage: soju levels list-unassigned [OPTIONS]                                 
                                                                              
 List entries with no course level tag.                                       
                                                                              
╭─ Options ──────────────────────────────────────────────────────────────────╮
│ --format        <str>  Output format: table (default) or ids               │
│                        [default: table]                                    │
│ --kind          <str>  Target kind: vocabulary (default) or grammar        │
│                        [default: vocabulary]                               │
│ --type          <str>  Filter by vocabulary type id (e.g. noun, verb)      │
│ --help                 Show this message and exit.                         │
╰────────────────────────────────────────────────────────────────────────────╯

set

                                                                              
 Usage: soju levels set [OPTIONS]                                             
                                                                              
 Assign a course level to selected vocabulary or grammar entries.             
                                                                              
╭─ Options ──────────────────────────────────────────────────────────────────╮
│ *  --level                 <str>   Course level id from levels.yaml        │
│                                    [required]                              │
│    --kind                  <str>   Target kind: vocabulary (default) or    │
│                                    grammar                                 │
│                                    [default: vocabulary]                   │
│    --all-unassigned                Assign every unassigned entry of the    │
│                                    chosen kind                             │
│    --id                    <str>   Vocabulary UUID or grammar pattern id   │
│                                    (repeatable)                            │
│    --ids-file              <path>  File of ids (one per line); use - for   │
│                                    stdin                                   │
│    --dry-run                                                               │
│    --force                         Allow overwriting an existing level tag │
│    --help                          Show this message and exit.             │
╰────────────────────────────────────────────────────────────────────────────╯

Kinds

--kind vocabulary (default) targets registry entries by UUID. --kind grammar targets grammar pattern ids from the grammar manifest.

Selection for set

Exactly one selection mode:

  • --all-unassigned — every entry of the chosen kind with no level

  • --id — one or more ids (repeatable)

  • --ids-file — one id per line (- = stdin)

Use --force to overwrite an existing level tag. Prefer --dry-run first.

Examples

# List unassigned vocabulary (table or ids-only)
uv run soju levels list-unassigned
uv run soju levels list-unassigned --format ids

# Stamp every unassigned vocab entry to 1A
uv run soju levels set --level 1A --all-unassigned --dry-run
uv run soju levels set --level 1A --all-unassigned

# Partial retag by UUID
uv run soju levels set --level 1B --id <uuid> --id <uuid>

# Grammar patterns
uv run soju levels list-unassigned --kind grammar
uv run soju levels set --kind grammar --level 1A --all-unassigned

# Pipe ids
uv run soju levels list-unassigned --format ids | uv run soju levels set --level 1A --ids-file -

Import vs retag

New vocabulary can take an optional course level at import time (soju import words|verbs --level or per-record level). Omitted = unassigned. To retag existing vocab or grammar, use soju levels — do not mass-edit YAML by hand. See soju import.

Unassigned vocabulary is excluded from Practice (unless Include supplemental content) and from course AI prompt word lists. soju fill-examples --local still generates for unassigned rows in the selected band; stamp or import with --level when you want them in the course band — see soju fill-examples.