Skip to content

Repository files navigation

dealscan

The first open-source music-business contract agent, built on Meta's Muse Glimmer.

Point it at a producer agreement, a distribution deal, or a publishing contract. It tells you what kind of deal it is, pulls out the terms that decide who gets paid, and explains the clauses that should worry you — in plain English, not legalese.

dealscan analyze contract.pdf

Out comes a markdown deal report and a structured JSON file.


Why

Most musicians sign their first few contracts without a lawyer, because a lawyer costs more than the advance. dealscan is not a substitute for one. It is the read-through you do before you pay for one — so you walk into that conversation knowing which three clauses to ask about.

It runs on Muse Glimmer 30B, Meta's Apache-2.0 agentic model. The hosted path via OpenRouter is verified end to end. Because the weights are open, running it entirely on your own machine is the goal — that path exists today but is experimental; see Known limitations.

Install

git clone https://github.com/SoundDeal/dealscan
cd dealscan
uv sync

Requires Python 3.11+.

Quickstart — OpenRouter

The default backend. Get a key from openrouter.ai.

export DEALSCAN_API_KEY=sk-or-v1-...
uv run dealscan analyze examples/producer_agreement_synthetic.txt

That writes two files next to your contract:

  • producer_agreement_synthetic.dealscan.md — the deal report
  • producer_agreement_synthetic.dealscan.json — structured output

Quickstart — local with Ollama (experimental)

No key and no network, so the contract never leaves your machine.

ollama pull muse-glimmer:30b
uv run dealscan analyze contract.pdf --local

--local points dealscan at http://localhost:11434/v1. The 30B model runs on a single 24GB consumer GPU or an Apple Silicon Mac with enough unified memory.

⚠️ Experimental. This path has not been verified end to end. Configuration resolution for --local is unit-tested, but no run against a real Ollama server has been completed — Ollama's OpenAI-compatible shim may differ from OpenRouter in how it returns tool_calls or accepts image content. If you hit a problem here, please open an issue; verifying this path is roadmap item #1.

Example output

Example dealscan report

Real output from meta/muse-glimmer-30b, analyzing the synthetic producer agreement in examples/. Trimmed to fit; see docs/ for how it was produced.

Excerpt from a report on the synthetic producer agreement
# Deal Report — producer_agreement_synthetic.txt

**Deal type:** Producer Agreement
**Classification confidence:** 94%

## Key Terms

| Term | What the contract says | Read |
| --- | --- | --- |
| **Advance** | $7,500 per master, recoupable | Market |
| **Royalty Rate / Points** | 3 points of Net Receipts | Below market |
| **Reversion** | _Not addressed_ | Not addressed |

## Red Flags

### 1. Work made for hire reaches the composition — `HIGH`

> melodic and lyrical contributions

**In plain English:** The company claims the songwriting you contribute, not
just the recording.

Configuration

dealscan talks to any OpenAI-compatible /chat/completions endpoint.

Variable Default Notes
DEALSCAN_API_KEY Required unless --local
DEALSCAN_API_BASE https://openrouter.ai/api/v1 http://localhost:11434/v1 with --local
DEALSCAN_MODEL meta/muse-glimmer-30b muse-glimmer:30b with --local

Anything speaking the OpenAI chat format works — vLLM, llama.cpp's server, LM Studio. Set DEALSCAN_API_BASE and DEALSCAN_MODEL and go.

dealscan analyze <contract>       Analyze a .pdf or .txt contract
  --local                         Use local Ollama instead of OpenRouter
  --model / --api-base            Override the backend for one run
  --out-dir DIR                   Where to write the .md and .json
  --max-steps N                   Agent step budget (default 15)
  --no-images                     Disable the page-image fallback
  --quiet                         Don't print the report to stdout

dealscan prompts [name]           List or print the prompt pack

How it works

A small tool-calling loop, capped at 15 steps:

  1. classify_deal_type — identifies the deal and loads the matching prompt pack, which is fed back to the model for the rest of the run.
  2. extract_pdf_text — pages through the contract on demand.
  3. extract_terms — advance, royalty, term, territory, options, ownership, recoupment, reversion. All eight, every time; a missing term is recorded as absent rather than dropped.
  4. check_red_flags — clauses that materially disadvantage the creator, each with a plain-English explanation and a question to ask about it.
  5. explain_term — glossary lookups for jargon.

The structured tools are validated with Pydantic before anything enters the report. A tool call with bad arguments comes back to the model as an error it can see and correct — one retry, then it surfaces to you rather than silently producing a half-empty report.

Scanned PDFs: text is extracted per page with PyMuPDF. Any page with no extractable text is rendered to PNG and sent to the model as an image, since Muse Glimmer is multimodal. Pages that went down that path are noted in the report so you know to treat their quotes with extra care.

Prompts

Every prompt is a versioned markdown file in src/dealscan/prompts/ — one shared system prompt plus one per deal type:

producer_agreement · single_song_assignment · publishing_admin · distribution · artist_360 · sync_license · co_publishing

They are data, not code. Edit the markdown, bump the version in the front matter, no Python required.

⚠️ The prompts are first drafts and are marked TODO — NEEDS DOMAIN REVIEW. They were written by software engineers from general industry knowledge, not by a music attorney. The term ranges in them are rules of thumb that vary by genre, territory, leverage, and year. They need review by a music-business professional before anyone relies on this output.

Examples

examples/ contains two synthetic contracts — a producer agreement and a digital distribution deal — written for this project as test data. Every party, sum, and clause is invented, and both are watermarked as fictional. They are not templates and not drawn from any real agreement.

No real contract text belongs in this repository. Keep your own contracts out of it; contracts/ and scratch/ are gitignored for that purpose.

Eval harness

dealscan eval benchmarks any set of OpenAI-compatible models on music-contract analysis, using the same pipeline dealscan analyze uses.

cp models.yaml.example models.yaml
export OPENROUTER_API_KEY=sk-or-v1-...
dealscan eval --config models.yaml --dry-run   # validate first
dealscan eval --config models.yaml

It scores against 8 synthetic contracts with hand-written gold labels covering all seven deal types — 64 term slots, 11 of them genuinely absent, 54 planted red flags.

The headline metric is hallucination rate: of the terms a contract genuinely does not address, what fraction did the model invent a value for? A model that fabricates a royalty rate for a deal that has none is worse than useless to someone deciding whether to sign, so it is reported first and separately from accuracy. A model can post perfect recall and still rank last.

Also measured: deal-type accuracy, term precision/recall with fuzzy value matching, red-flag recall and precision, and explanation quality against a rubric. An LLM judge is used only where programmatic scoring cannot work — matching a free-text finding to a planted flag, and rating explanations. It is blind to which model produced what, every judge call is logged verbatim for audit, and it is swappable with --judge-model. Runs are resumable, so a crash does not re-spend API calls.

📄 METHODOLOGY.md — what is measured, the scoring rules, the judge's role and its bias, how to reproduce, how to add a model, and the limitations.

📊 results/sample/report.md — an example report. The models in it are fictional and the numbers fabricated; it exists to show the format.

No leaderboard is published in this repo yet. The harness and methodology ship first. Real results come after the gold labels get a domain review — they are first drafts marked TODO — NEEDS DOMAIN REVIEW, and publishing rankings derived from unreviewed labels would be exactly the kind of confident, unfounded number this tool exists to help people avoid.

Development

uv sync --extra dev
uv run pytest

Known limitations

Multi-page scanned PDFs are slow and expensive. Pages with no extractable text are rendered to images and placed in the opening message, which a stateless chat API re-sends on every agent step — so a scan costs roughly pages × steps image uploads. A single scanned page analyzes in well under two minutes; a 3-page scan did not complete in ~8 minutes during testing and was abandoned. Digital PDFs and .txt files are unaffected. Planned fixes: lower the render zoom, cap the rendered long edge in pixels, or move page images out of the opening message into a tool result fetched on demand. Until then, prefer OCR'ing long scans before analysis.

--local (Ollama) is experimental. Config resolution for it is unit-tested, but the path has not been verified end to end against a running Ollama server. Its OpenAI-compatible shim may handle tool_calls or image content differently from OpenRouter. Roadmap item #1.

Verified surface, precisely: the OpenRouter path against meta/muse-glimmer-30b — text contracts and single-page image fallback, both confirmed end to end. Everything else is tested against a mocked backend.

Prompt quality is unmeasured. All eight prompt files are first drafts marked TODO — NEEDS DOMAIN REVIEW. Output reads well, but "reads well" is not an eval — see the eval harness on the roadmap.

The model can be confidently wrong. It can miss a clause, misread one, or quote a section number incorrectly. Quotes drawn from pages that took the image fallback are flagged in the report; treat them with extra care.

Disclaimer

dealscan is not legal advice. It is an automated first read produced by a language model. It can miss clauses, misread them, and be confidently wrong. It does not know your leverage, your genre, your territory, or what you agreed to in the room. Nothing it outputs creates an attorney-client relationship.

Have a qualified music attorney review any agreement before you sign it.

Roadmap

  1. Verify and harden the --local Ollama path — confirm tool_calls and image content work against Ollama's OpenAI-compatible shim, then drop the experimental label. Running entirely offline is half the point of building on an open-weights model, so this comes first.
  2. Fix image handling for multi-page scans — cap the rendered long edge, lower the render zoom, and move page images out of the opening message into a tool result fetched on demand, so cost stops scaling with pages × steps.
  3. MCP server mode — expose dealscan's tools over the Model Context Protocol so any MCP client can analyze a contract in-conversation.
  4. More deal types — management agreements, band/partnership agreements, mixing and mastering engineer deals, beat licences, session musician agreements, neighbouring-rights and sub-publishing deals.
  5. Eval harnessshipped in v0.2.0. See METHODOLOGY.md. Still to come: a domain review of the gold labels, then published results; repeat runs to estimate variance; and adversarial contracts drafted to mislead an automated reader.

License

MIT. See LICENSE.


Analyzed by dealscan · Benchmark this deal against real market data at sounddeal.com

About

Open-source music-business contract agent built on Meta's Muse Glimmer 30B. Extracts deal terms, flags red-flag clauses, reads scanned PDFs.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages