Skip to content

v0.0.1

Pre-release
Pre-release

Choose a tag to compare

@AlyShmahell AlyShmahell released this 28 Aug 13:02
· 3 commits to main since this release

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

[0.0.1] - 2026-08-28

First public release. Matchora is a Go service that ingests title rows or scans a
video library, searches YAML-defined metadata APIs, and ranks candidates with a
local llama.cpp embedder or instruct model.

Added

Matching and providers

  • Generic GET + JSON-path provider engine. Provider names are not hardcoded in Go.
  • Shipped providers: TVMaze, Jikan v4, OMDb (movies, keyed), TMDB movie and TMDB TV (keyed).
  • Type allowlists so a typed job only calls providers that list that type.
  • Fast pass plus deferred providers (defer: true) when hit count or best score is too low.
  • Parallel provider GETs per title; per-job HTTP clocks so a slow deferred call does not stall the batch.
  • Per-provider pacing (min_interval_ms), retries, per-attempt timeouts, capped exponential backoff, and Retry-After.
  • Provider cooldown after consecutive GET failures (jittered skip, reset on success).
  • Ranking: MiniLM embeddings (cosine) or instruct chat; lexical token overlap + year bonus if the embed server is down.
  • Auto-matched vs manual vs unmatched from min_score / min_margin; user confirm via select.
  • Season/episode catalog fetch for TV providers (TVMaze, TMDB TV), including a catalog-only request that does not change the match.
  • Optional provider detail GET (OMDb plot) and poster downloads.
  • skip_episode_posters on ingest, scan, rematch, retry, select, and catalog.

Ingest and scan

  • POST /v1/ingest for CSV (header) or JSON arrays: title, year, type, season, episode, imdb.
  • CSV alias map (ingest.aliases) and type rewrite (episode/seasontv).
  • Instruct fallback to map unknown CSV columns using config/ingest.md.
  • POST /v1/scan lists videos under browse_root, groups dirty names with a local instruct model (config/prompt.md), then matches in the worker.
  • Scan grouping progress via GET /v1/scan/status.
  • Expected Plex / Jellyfin / Infuse trees (movies vs series roots, optional {tmdb-…} / {imdb-tt…} ids).

Catalog

  • Matched, selected, and cataloged titles written under {data_dir}/catalog as [uniqueid-id] Title (Year)/ trees.
  • tvshow.nfo / movie.nfo, season folders, episode .nfo, and downloaded posters.
  • Distinct uniqueid slugs so TMDB movie vs TV ids cannot collide (tmdb-movie, tmdb-tv, OMDb imdb).
  • GET /v1/catalog and GET /v1/catalog/{provider}/{id}; posters at /poster.jpg (and season/episode variants).
  • Clearing jobs does not delete the catalog tree.

Runtime and llama.cpp

  • HTTP admin server on :7680 (User-Agent: matchora/{version}).
  • Writable {exeDir}/data: jobs.json, optional config.yaml overlay, secrets (YAML map of API keys).
  • GET/POST /v1/secrets report which key slots are set and merge the secrets file (values never returned). Slots are provider API keys only.
  • GET/POST /v1/config read and deep-merge {data_dir}/config.yaml (same shape as default.yaml). Never includes secrets.
  • Listen address is llama.host / llama.port (defaults 127.0.0.1 / 8080); llama.base_url is derived as http://{host}:{port}/v1.
  • On start, probe that URL. A healthy listener is left alone. If it is down, install llama.cpp + GGUFs into {exeDir}/vendor/llama.cpp and spawn one llama-server on 127.0.0.1 at that port (embed + optional instruct). Distinct llm_base_url (e.g. a stub) is left alone.
  • After a successful secrets or config POST, return the JSON body, stop a spawned llama-server, and re-exec so the next Load / llama.Start applies the files. Setters write files only.
  • --prepare runs that install, verifies models, stops the spawned server, and exits.
  • Dist is binary + config/ + public/ only; llama.cpp is not in the slim tree.

Admin console

  • Verification UI at / (folder picker via GET /v1/fs, ingest upload, scan, job cards).
  • Secrets panel for provider keys and llama panel for host/port; both wait for /health after the process restart.
  • Live match wait log, sticky status chips, score heatmap, retry errors/unmatched, clear jobs.
  • Manual candidate select and per-candidate seasons catalog.
  • Skip-episode-posters checkbox persisted in localStorage.

HTTP API

  • GET /, /health, /v1/fs, /v1/jobs, /v1/match/log, /v1/scan/status, /v1/catalog, /v1/catalog/{provider}/{id}
  • GET/POST /v1/secrets, GET/POST /v1/config
  • POST /v1/ingest, /v1/scan, /v1/match, /v1/retry, /v1/jobs/{id}/select, /v1/jobs/{id}/catalog
  • DELETE /v1/jobs (empty list and abort in-flight scan grouping)

Build, package, and tests

  • Podman linux/amd64 dist builder (./build/run: run, rebuild, prepare, package).
  • Slim tarball matchora-*-linux-amd64.tar.gz (binary, config, public, LICENSE).
  • Bundled tarball matchora-*-linux-amd64-llama.tar.gz (same plus llama.cpp, GGUFs, and fetched third-party licenses).
  • Podman-only unit, smoke (stub metadata + stub chat; waits for /health after secrets POST), and optional live (MATCHORA_LIVE=1) harness.
  • BSD 3-Clause license.