@withpica/mcp-server
Version:
MCP Server for withPICA — enables AI assistants to interact with your withPICA music catalog
187 lines • 132 kB
JavaScript
// Copyright (c) 2025-2026 Withpica Ltd. All rights reserved.
export const SKILLS = {
"audit-credits": {
name: "audit-credits",
description: "Sweep across the catalog for PUBLISHING-SIDE credit gaps and split issues — writer credits on works (composer / lyricist / arranger / publisher), splits not totalling 100%, people without IPI / ISNI identifiers, generic role assignments. Does NOT cover master-side / recording splits — use set-recording-splits per-recording for that. Companion to catalog-audit.",
triggers: ["audit my credits", "check my splits", "find credit gaps", "which writers are missing identifiers", "splits health check"],
audience: "publisher / manager / admin",
tools_required: ["pica_works_query", "pica_credits_list", "pica_people_query", "pica_resolve_person"],
output: "Summary statistics (% of works with credits, average collaborators per work) + ranked list of works with no credits + works with split issues + people who should be enriched with external identifiers + recommendations.",
body: "# audit-credits\n\nRun a **publishing-side** credits-and-splits health sweep across the catalog. Where `catalog-audit` covers the whole picture, this skill drills into the people-and-shares layer — the bit where royalty leak happens most often.\n\n**Scope (load-bearing):** this skill audits **writer credits on works** — composer / lyricist / arranger / publisher percentages that sum to 100% for collection-society payout. The **master-ownership splits on recordings** (artist / producer / label / featured) are a separate domain handled per-recording by `set-recording-splits` — they live on a different table, route to different payouts (label distributor / RIAA neighbouring rights vs PROs), and a catalog-wide audit of those is currently a Stage 2 gap. If the user asks \"are my master splits healthy?\" don't pretend this skill covers it — point them at `set-recording-splits` per-recording and acknowledge the audit gap.\n\n## Pre-flight\n\nIf the audit ends with proposed writes (adding a missing credit, fixing a split), read `pica://schemas/work-credits-required` first — the canonical shape for `pica_credits_update` rows (writer role, splits totalling 100%).\n\n## Step 1 — Sample the catalog\n\nCall `pica_works_query` to get the works. For a small catalog (<100 works), check all. For larger catalogs, sample at least 20 recent works to keep the audit responsive — the user can re-run on a different slice.\n\n## Step 2 — Per-work credit check\n\nFor each sampled work, call `pica_credits_list`. Look for the five common problems:\n\n1. **No credits at all** — the work exists but no writers, composers, or publishers are attached. Highest priority — the work is effectively un-payable.\n2. **Splits don't total 100%** — writer credits exist but the percentages don't sum correctly. PROs will reject registration.\n3. **Only one credited person** — works are usually collaborations. A single-writer work is fine when accurate, but worth flagging in case a co-writer was forgotten.\n4. **Generic roles** — credits with just `writer` (vs the more specific `composer` / `lyricist` / `arranger`). Less critical, but matters for some PROs and for sync licensing.\n5. **People missing IPI / ISNI** — a writer credited on a work, but their person record lacks the IPI / ISNI identifier. Royalties can't route to them.\n\n## Step 3 — Cross-reference people\n\nFor the people credited across the sampled works (call `pica_people_query`):\n\n- How many have an IPI? (needed for PRO payouts)\n- How many have an ISNI? (useful for cross-reference, less critical)\n- Do the same person's roles look consistent across their works? (a producer credited as `writer` on one work and `producer` on another may be a data-entry mistake)\n\nIf a credited person is missing identifiers, suggest `pica_resolve_person` to attempt enrichment from public sources. Treat the resolver as a black box — it returns proposals, the user reviews them.\n\n## Step 4 — Report\n\nProduce in this order:\n\n1. **Headline stats** — \"X% of works have credits, average Y collaborators per work, Z splits issues across the sample\"\n2. **Works with no credits at all** — the highest-priority list. These are the immediate fixes.\n3. **Works with split issues** — splits not totalling 100%, ranked by which works are highest-value (recent, registered, frequently played)\n4. **People without IPI** — names + how many works they're credited on (more works = bigger royalty leak)\n5. **Recommendations** — the 3-5 highest-leverage fixes, ordered by effort-to-impact ratio\n\n## Step 5 — Offers\n\n- \"Want me to walk through fixing one of the no-credits works?\" → routes to `close-the-loop` for that work\n- \"Want me to enrich the writers missing IPI from public sources?\" → `pica_resolve_person` for each\n- \"Want me to export a list for offline review?\" → optional CSV-style summary\n\n## What not to do\n\n- Don't auto-write credits — every credit is a user decision (who wrote what, what %)\n- Don't apply enrichment proposals without user review\n- Don't try to reconcile split issues by guessing the \"correct\" split. The user has to confirm what the actual agreement was.\n- Don't quote internal source-weighting or cascade logic when suggesting enrichment — treat `pica_resolve_person` as a black box that returns proposals\n- Don't speculate about what an unknown person's IPI is. Empty is empty.\n\n## Follow-on skills\n\n- `close-the-loop` — pick a specific gap-heavy work to fix\n- `register-my-works` — once credits are clean, registration is unblocked\n- `set-recording-splits` — credits cover publishing (writer side); master ownership is a separate layer\n",
},
"catalog-audit": {
name: "catalog-audit",
description: "Audit a music catalog for completeness, quality, and registration readiness using PICA's MCP tools. Produces a structured report with statistics, gap analysis, and prioritised improvement actions.",
triggers: ["audit my catalog", "how's my catalog doing", "catalog health", "what needs fixing", "assess my catalog"],
audience: "manager / label / artist",
tools_required: ["pica_dashboard_briefing", "pica_works_inspect", "pica_works_query", "pica_catalog_stats", "pica_find_duplicates"],
output: "Plain-language health summary (suitable for a non-technical stakeholder) + top 3 highest-impact improvements with specific steps + post-fix score estimate + any urgent issues.",
body: "# catalog-audit\n\nAudit a music catalog for completeness, quality, and registration readiness. Use this when a user asks \"how's my catalog doing,\" \"what needs fixing,\" or wants a health check before a release / sync push / sale.\n\n## Step 1 — Orient\n\nCall `pica_dashboard_briefing` first. The briefing returns a single compressed snapshot of catalog state (counts, recent activity, upcoming deadlines, top priorities). This is the cheapest first call and sets the routing decision for everything that follows.\n\n## Step 2 — Pull the PICA Score\n\nCall `pica_works_inspect` with `sections: [\"score\"]` on a representative work, or read the `catalog://health` resource. The score is a 0-100 composite across four pillars (income, ownership, asset, verification). The pillar with the lowest score is the audit's primary subject.\n\nDo NOT speculate about how the score is calculated beyond what the tool returns. Treat it as a black box that reports a number and pillar breakdown.\n\n## Step 3 — Sample for quality\n\nCall `pica_works_query` with `health_filter: \"low_completeness\"` and pull up to 20 works. For a sample of those, call `pica_works_inspect` with `sections: [\"completeness\"]` to see per-work gaps.\n\nCommon patterns to look for (publishing side — writer credits on works):\n- Works with no credits at all\n- Works where writer splits don't total 100%\n- Works with no recordings\n- Recordings with no ISRC\n- People credited on works but missing IPI or ISNI\n\n**Recording-side / master-ownership health** (artist / producer / label splits) is a separate domain handled per-recording by `set-recording-splits` — not surfaced by the score pillars at present. If the user mentions producer points, label splits, or master royalties, flag that this audit doesn't cover them and point to `set-recording-splits` per-recording.\n\n## Step 4 — Duplicate sweep\n\nCall `pica_find_duplicates`. A clean catalog has zero or near-zero duplicate signals. High duplicate counts indicate an import that needs reconciliation before further work.\n\n## Step 5 — Report\n\nProduce three things, in this order:\n\n1. **One-paragraph plain-language summary.** Suitable for a non-technical stakeholder. Lead with \"your catalog has X works and is healthy / has gaps / needs attention\" — not raw numbers.\n2. **Top 3 improvements, prioritised by effort vs impact.** Each with the specific tool call that would address it (e.g. \"add IPI numbers to 12 writers — call `pica_people_query` filtered by `has_ipi: false`, then `pica_people_update` for each\").\n3. **Score forecast.** \"After those fixes, the score would likely rise from X to Y.\"\n\nIf urgent issues exist (e.g. missing ownership data on a work with active royalties, works being licensed whose ownership splits no holder has confirmed) flag them at the top.\n\n## What not to do\n\n- Don't run all sub-workflows at once. The audit is read-only — improvements are a separate user decision.\n- Don't recommend `pica_works_delete` or any destructive operation. The audit's job is to describe, not to mutate.\n- Don't quote raw `pica_works_query` results back at the user verbatim. Summarise.\n\n## Follow-on skills\n\nAfter the audit, the natural next skills are:\n- `catalog-modelling` if the audit surfaces duplicate-title works or blank-ISWC variants that should be recordings under one work\n- `register-my-works` if registration coverage is low\n- `prepare-for-sync` if sync-readiness is the user's goal\n- `close-the-loop` (prompt) if the user wants to fix specific works one at a time\n",
},
"catalog-modelling": {
name: "catalog-modelling",
description: "The data model for a music catalog — how to decide whether something is a work, a recording, or a release, and how to model song variants (instrumental, acoustic, live, remix) correctly. Front-load this before creating or restructuring catalog entities.",
triggers: ["how should I model this", "is this a work or a recording", "instrumental version", "acoustic version", "should this be a separate work", "is this remix a new song", "modified version", "restructure my catalog", "consolidate works"],
audience: "manager / label / artist",
tools_required: ["pica_works_create", "pica_works_update", "pica_recordings_create", "pica_recordings_update", "pica_works_delete", "pica_catalog_health", "pica_find_duplicates"],
output: "A modelling decision (work vs recording vs release) with the exact tool calls to create or restructure the entities, and — when consolidating — a safe repoint-then-relink-then-delete plan that never orphans a release track.",
definition_of_done: "Each composition is ONE work with ONE ISWC; every variant — including a remix with no new writers — is a recording under that work with the correct version_type; a remix that added writers is its own work linked to the original with original_work_id; no blank-ISWC duplicate works sharing a title stem; release tracks resolve to the right work and recording.",
when_not_to_use: "When the thing genuinely IS a separate composition — a remix that added writers (a modified version, which you link rather than fold), or a distinct song that merely shares a title stem.",
body: "# catalog-modelling\n\nUse this before creating or restructuring catalog entities. It answers the\nquestion agents get wrong most often: \"this instrumental / acoustic / live /\nremix version — is it a new work, a recording, or a release?\" Getting it wrong\nsplinters one song into many half-blank works and breaks every downstream\nreport. Getting it right is mechanical once you know the three grains.\n\n## The three grains\n\nPICA separates a song into three distinct entities, each with its own identity\neach answering a different question:\n\n- **work** = the composition, the song as written. carries the **ISWC** (`works.iswc`)\n and the composition credits. one work has many recordings.\n- **recording** = a specific master / sound recording of that work. carries the\n **ISRC** (`recordings.isrc`), the audio, and a `version_type`. it points at its\n work via `recordings.work_id`. a recording has no ISWC of its own — its\n composition identity is the work it hangs off. one recording appears on many\n releases.\n- **release** = a commercial product (single, album, compilation) that bundles\n recordings via `release_tracks`. carries the **UPC** and catalog number.\n\nThe rule the whole model rests on: **a fact lives on exactly one entity, at the\nright grain.** ISWC is a composition fact (work). ISRC is a master fact\n(recording). UPC is a product fact (release). Never put a master or release fact\non a work.\n\n## The decision rule\n\nWhen something new shows up that looks like `<existing work> - <variant>`\n(e.g. \"confetti heart - instrumental\", \"midnight - acoustic\", \"the song - live\nat koko\"):\n\n> it is a **recording under that existing work**, created or repointed with the\n> right `version_type` — **UNLESS** someone added new writing to it, in which\n> case it is a **modified version**: its own work, linked to the original.\n\nSo:\n\n- **same composition, different rendering** (instrumental, acoustic, live_performance, demo,\n edit, backing_track, alternate) → one more **recording** under\n the existing work. set `work_id` to the existing work and `version_type` to the\n variant. do NOT mint a second work.\n- **a remix (or rmx, flip, bootleg, VIP) with no new writers** → also a\n **recording** under the existing work: its own ISRC, the same work, the same\n ISWC, the same writers. `version_type: remix`. the remixer is credited on the\n **recording** (`recording_credits` role `Remixer`), **not** as a writer.\n- **a remix that added writers** (new lyrics, a new melody, a new section) →\n a **modified version** (CWR calls it `MOD`): a separate work with its own\n ISWC and its own writer shares, **linked to the original** with\n `pica_works_update {id, original_work_id: <original work id>}` (or\n `original_work_id` on `pica_works_create`).\n\n**The deciding signal is the writers.** Compare the remix's writers to the\noriginal's: the same people, fewer of them, or none recorded → a recording.\nAnyone the original does not have → a modified version. If you do not know\nwhether writers were added, ask the user — do not guess, and do not assume a\nremix is a new song.\n\n### the version_type values\n\n`version_type` is the canonical way to label a variant recording. the live\n`recordings_version_type_check` constraint (and `VALID_VERSION_TYPES` in\n`lib/services/recordings.ts`) accepts exactly these thirteen values:\n\n`demo`, `master`, `alternate_master`, `music_video`, `lyric_video`,\n`live_performance`, `acoustic`, `remix`, `cover`, `alternate`, `instrumental`,\n`backing_track`, `edit`.\n\na fresh master defaults to `master`. pick the most precise value — prefer\n`instrumental` / `backing_track` / `edit` over the lossy `alternate` catch-all.\n`remix` is the value for a remix recording under the original work (the normal\ncase, above).\n\n## how a modified version links to its original\n\n`works.original_work_id` records it: set it on the modified version to the id\nof the work it modifies, with `pica_works_update` (or on `pica_works_create`).\nIt must name a work in the same catalogue, and a work cannot be a modified\nversion of itself. `null` clears it. The original's page then lists its\nmodified versions, and the modified version says which song it came from.\n\nLinking changes nothing else: both works keep their own writers, shares and\nISWC. It is only for a remix that **added writers** — a remix with the same\nwriters is not linked, it is a recording under the original.\n\n`pica_find_duplicates` (works) pairs each remix-titled work with its original\nand says which case it is: `match_kind: \"remix_recording\"` (move its\nrecordings under the original) or `\"remix_modified_version\"` (link it). Its\n`remix` block names the recordings, any added writers, and a remixer name read\nfrom the title — a name to check against the catalogue, never a person to\ncreate. Never answer a remix pair with `pica_merge_duplicates`: a merge would\nfold the remix's writers into the original's shares.\n\n## composition splits vs master splits\n\nWhen you model a variant, the splits follow the grain (per\n`.claude/rules/business-logic.md`, Credit & Split Tables):\n\n- **composition splits / writer credits** live on the **work**, in\n `work_collaborators` (writer, composer, lyricist, arranger, publisher, with\n `split_percentage`). every recording under that work inherits the same\n composition — you do not re-enter writer splits per variant.\n- **master ownership splits** live on the **recording**, in `recording_splits`\n (`split_type`: master, mechanical, performance, sync); master attribution\n (producer, performer, etc.) lives in `recording_credits`. these are\n per-recording — an instrumental master can have different master ownership\n from the vocal master.\n\nSo an acoustic recording added under an existing work inherits that work's\nwriter splits automatically and only needs its own master splits if the\nownership differs.\n\n## worked example — confetti heart\n\nTake a song \"confetti heart\" with an instrumental, an acoustic, and a remix.\n\n- **confetti heart** → ONE **work** with its ISWC. its writer splits live here in\n `work_collaborators`.\n- **confetti heart (the released master)** → a **recording** under that work,\n `version_type: master`, with its ISRC.\n- **confetti heart (instrumental)** → another **recording** under the SAME work,\n `version_type: instrumental`. same ISWC (inherited via the work), its own ISRC.\n do not create a second \"confetti heart instrumental\" work.\n- **confetti heart (acoustic)** → another **recording** under the same work,\n `version_type: acoustic`.\n- **confetti heart (Féz remix)** with the same writers → another **recording**\n under the SAME work, `version_type: remix`, its own ISRC, with Féz credited on\n the recording as `Remixer`. no second work.\n- **confetti heart (Féz remix)** where Féz wrote a new verse → a **modified\n version**: its own work with its own ISWC and writer shares (the original\n writers plus Féz), linked with `original_work_id` to confetti heart.\n\nThe wrong model — four separate works all titled some variant of \"confetti\nheart\", three of them with blank ISWCs — is exactly what\n`pica_catalog_health` flags as duplicate works sharing a title stem.\n\n## safe consolidation procedure\n\nWhen a catalog already has the wrong shape — e.g. \"confetti heart\",\n\"confetti heart instrumental\", \"confetti heart acoustic\" as three separate works,\ntwo with blank ISWCs — consolidate them under the one real work. Do it in this\norder, and not any other, because deleting a work too early orphans or destroys\nthe release tracks that reference it.\n\n1. **Pick the canonical work** — the one with the real ISWC. this is the keeper.\n2. **Repoint each variant's recording onto the keeper.** for every recording\n hanging off a duplicate work, call `pica_recordings_update` with\n `work_id: <keeper work id>` and the correct `version_type` (e.g.\n `instrumental`, `acoustic`). the recording now belongs to the canonical work\n and keeps its ISRC and master splits.\n3. **Relink any affected release tracks to the keeper.** a `release_tracks` row\n references **both** `work_id` and `recording_id` (the table has\n `CHECK (recording_id IS NOT NULL OR work_id IS NOT NULL)`). any track that\n still points at a soon-to-be-deleted work via `work_id` must be repointed to\n the keeper work first.\n4. **Only now delete the now-empty duplicate work** with `pica_works_delete`.\n\n**Why relink the release tracks before the delete, not after.** Per the deletion\ncontract (`.claude/rules/business-logic.md`), deleting a work auto-detaches its\n`release_tracks` membership by nulling `release_tracks.work_id`. for a track that\nalso carries a recording, nulling the work id is harmless — it keeps its\nrecording. but a **work-only** track (no recording) cannot have its `work_id`\nnulled without violating the CHECK, so the deletion policy **deletes that whole\ntrack** instead (its `deleteWhenOrphanColumns` is `[\"recording_id\"]`). that would\nsilently drop the track from its release. and if the duplicate work still has\nrecordings attached, the delete **archives** the work rather than removing it —\nso you must repoint the recordings (step 2) to actually empty it. relinking the\ntracks first means every track keeps a valid work reference and the final delete\nis a clean no-dependents removal.\n\n## what not to do\n\n- don't mint a new work for an instrumental, acoustic, live_performance, demo, edit, or\n backing_track version. that is a recording under the existing work.\n- don't put an ISWC on a recording or a UPC on a work. facts live at their grain.\n- don't mint a new work for a remix unless it added writers. a remix with the\n same writers is a recording under the original, with the remixer credited on\n the recording — never as a writer.\n- don't merge a remix work into its original with `pica_merge_duplicates` —\n move its recordings (`pica_recordings_update`) or, if it added writers, link\n it (`original_work_id`).\n- don't delete a duplicate work before repointing its recordings and relinking\n its release tracks. order matters; a premature delete orphans or destroys\n tracks.\n- don't re-enter writer splits per variant. composition splits live once, on the\n work; recordings inherit the composition.\n\n## follow-on skills\n\n- `set-recording-splits` — once variants are correctly modelled as recordings,\n set the per-recording master ownership.\n- `catalog-audit` — to sweep the whole catalog for remaining duplicate-title\n works and blank ISWCs.\n- `register-my-works` — registered works pair with cleanly-modelled recordings.\n",
},
"clean-up-artists": {
name: "clean-up-artists",
description: "Find and fix junk/placeholder artist records that have wrongly become the primary artist on many recordings — the \"unknown\" magnet pattern, YouTube \"X - Topic\" channel artists, and duplicate person rows. Diagnoses the mess, proposes a plain-language repoint plan, then fixes it safely with the bulk reassign tool.",
triggers: ["clean up my artists", "fix the unknown artist", "why are so many songs by \"unknown\"", "merge duplicate artists", "my recordings are on the wrong artist", "tidy up the people list"],
audience: "manager / label / artist",
tools_required: ["pica_people_query", "pica_recordings_query", "pica_recordings_bulk_reassign_artist", "pica_merge_duplicates", "pica_people_delete"],
output: "A plain-language summary of which artist records were junk, how many recordings each held, what each recording was repointed to (or cleared), and which junk records were retired. Nothing is changed without showing the plan first.",
body: "# clean-up-artists\n\nFix junk/placeholder **primary artists**. Use this when a user says \"why are 300 songs by 'unknown'\", \"my recordings are on the wrong artist\", or \"clean up the artist list.\"\n\nEvery recording has two artist fields: `primary_artist_id` (the structured link to a `people` row — the source of truth) and `artist_name` (the free-text display label). The bug class this skill fixes is a **junk `people` row that became the `primary_artist_id` for many recordings** — a \"magnet\" — even though each recording's own `artist_name` says who the real artist is.\n\nThe golden rule: **a recording's `primary_artist_id` should match its own `artist_name`, or be null.** This skill makes that true.\n\n## Step 1 — Find the junk magnets\n\nCall `pica_people_query` and look for person rows that are suspicious as artists:\n\n- a generic placeholder name: **\"unknown\"**, \"various artists\", \"n/a\", an untitled/UUID-shaped string;\n- a YouTube channel artefact: ends with **\" - Topic\"** or **\"VEVO\"**;\n- a near-duplicate of a real person (e.g. \"Fez\" and \"Féz\", or the same name twice) with **zero identifiers and zero credits**.\n\nFor each suspect, call `pica_recordings_query` (or inspect the person) to count how many recordings carry it as `primary_artist_id`. A junk row holding **many** recordings is a magnet — prioritise the biggest.\n\nDo NOT touch the legitimately auto-created artists: real names with real credits are correct, even if they were machine-created. Only the junk patterns above are in scope.\n\n## Step 2 — Build the repoint plan from each recording's own `artist_name`\n\nFor the recordings on a junk magnet, group them by their `artist_name`:\n\n- **Real name** (e.g. \"Bee Bakare\", \"Jules Rendell\"): resolve it to the matching real person via `pica_people_query` (exact, case-insensitive, on name or stage name). A single match → repoint there. For a \"X - Topic\" magnet, strip the \" - Topic\" suffix first, then resolve.\n- **Junk / empty / \"unknown\" name**: there is no real artist — the truthful state is **no link** (clear it to null).\n- **Ambiguous** (no match, or more than one match): leave it null rather than guess. Never invent a link.\n\nPresent this plan in plain language before changing anything, e.g.:\n\n> The \"unknown\" artist holds 304 recordings. 279 of them are genuinely unknown (I'll clear those). 25 name a real artist already in your catalog — I'll move 9 to Bee Bakare, 6 to Jules Rendell, 5 to G W C, 2 to Pyramid Park, 2 to Féz, 1 to Ryan Ofei. Then I'll retire the empty \"unknown\" record. OK?\n\n## Step 3 — Preview, then execute the repoints\n\nUse `pica_recordings_bulk_reassign_artist` — one atomic call per target, under normal write scope (no destructive permission needed; it only changes the link, never the label).\n\nFor each real-artist group, pass the explicit `recording_ids` and the resolved `to_person_id`. For the genuinely-unknown remainder, drain the rest off the magnet with `from_person_id: <magnet id>` and `to_person_id: null`.\n\nAlways run with `dry_run: true` first and confirm the `would_affect` count matches your plan, then run for real. When you drain a magnet with `from_person_id`, the response includes `source_now_empty` — that tells you the junk row is safe to retire.\n\n## Step 4 — Retire the emptied junk records\n\nOnce `source_now_empty` is true (no recordings reference it):\n\n- If the junk row is a **duplicate of a real person** (\"Féz\" → \"Fez\", \"Manor Collective - Topic\" → \"Manor Collective\"), prefer `pica_merge_duplicates` to fold it into the canonical person — that preserves any stray references.\n- If it is a pure placeholder with nothing worth keeping (\"unknown\", a UUID name), use `pica_people_delete` to remove it.\n\nNever delete a person that still has recordings, credits, or identifiers — repoint first, retire second.\n\n## Step 5 — Report\n\nSummarise plainly: which junk records were found and how big each was, what each recording was repointed to (or cleared), and which records were retired. End with the healthy state (\"0 recordings now sit on a junk artist\").\n\n## Guardrails\n\n- **Show the plan before acting.** This is a bulk change to identity data — the user confirms Step 2's plan before any write.\n- **Never guess a link.** Ambiguous names get null, not a best-guess person.\n- **The label is not the link.** This skill changes `primary_artist_id`; it leaves `artist_name` alone. If a label is also wrong, that's a separate per-recording edit.\n- The resolver guard already prevents NEW junk artists from being minted, so this should be a one-time cleanup, not a recurring chore.\n",
},
"close-the-loop": {
name: "close-the-loop",
description: "Walk through a single work's gaps one at a time, offering the specific tool call to fix each. The compounding daily-use skill — pair with catalog-audit (which finds gap-heavy works) to fix them.",
triggers: ["close the loop on this song", "what's missing on this work", "fix the gaps on this track", "finish this song", "complete this work"],
audience: "manager / songwriter / artist working on a specific catalog entry",
tools_required: ["pica_works_inspect", "pica_works_query", "pica_credits_list", "pica_credits_update", "pica_resolve_work", "pica_audio_presigned_upload", "pica_audio_analyze"],
output: "A conversational gap-fix loop — one gap surfaced at a time, with the specific tool offer to fix it. After each fix, the completeness score is re-checked so the user sees progress.",
body: "# close-the-loop\n\nWalk through a specific work's gaps one at a time. The user names the work (or you find a gap-heavy one); you find every missing piece and offer to fix each. Pair with `catalog-audit` (which identifies which works need this treatment) for the daily catalog-health flow.\n\nThis is a high-frequency skill — once a manager runs it, they tend to run it again the next day on a different work. Keep it tight and conversational, not a wall of analysis.\n\n## Pre-flight\n\nPer gap class, read the relevant schema resource before writing:\n- `pica://schemas/work-credits-required` — credits + splits\n- `pica://schemas/audio-upload-required` — master audio\n- `pica://schemas/enrichment-resolve-required` — ISWC / ISRC via resolve cascade\n\n## Step 1 — Pick the work\n\nTwo paths:\n- User names a work or gives an ID → use that\n- User says \"fix something\" → call `pica_works_query` with `health_filter: \"low_completeness\"` and offer the top 3. Let the user pick.\n\n## Step 2 — Pull the gap list\n\nFor the chosen work:\n- `pica_works_inspect` with `sections: [\"completeness\"]` — the full per-aspect gap analysis\n- `pica_credits_list` — current credits and splits state\n- `pica_works_inspect` with `sections: [\"enrichment\"]` — which external sources have been tried\n\nSurface the headline number (e.g. \"this work is 60% complete, 4 gaps remaining\"). Don't dump every gap at once.\n\n## Step 3 — Walk the gaps, one at a time\n\nFor each gap, offer the specific action and wait for the user. The most common gap classes:\n\n| Gap | Question + Tool |\n|---|---|\n| Missing credits | \"Who wrote this song?\" → `pica_credits_update` |\n| Splits don't total 100% | \"What's the split between the writers?\" → `pica_credits_update` |\n| No ISWC | \"Want me to check MLC for an ISWC?\" → `pica_resolve_work` with `sources: ['mlc']` |\n| No ISRC | \"Do you have a recording with an ISRC?\" → check recordings, or upload one |\n| No master audio | \"Got a master recording to upload?\" → `pica_audio_presigned_upload` |\n| Audio not analysed | \"Want me to analyse for BPM, key, and mood?\" → `pica_audio_analyze` |\n| No agreements | \"Is there a publishing agreement?\" → flag for `pica_agreements_create` workflow |\n| Not registered | \"Want me to check registration status?\" → `pica_works_inspect` with `sections: [\"registration\"]` |\n\nOrder matters: start with the gap that unblocks the others. Missing credits usually blocks everything else (a work without writers can't be registered, can't be paid out, can't be exported). After credits, ISWC/ISRC tend to be next.\n\n## Step 4 — Re-check after each fix\n\nAfter each successful write, call `pica_works_inspect` with `sections: [\"completeness\"]` again and report the new percentage. The visible-progress feedback is what makes this skill habit-forming.\n\nIf the user skips a gap (\"not ready\"), respect that and move on. Track skipped gaps so the next time the user runs this on the same work, you can re-offer (or honour the skip if they confirmed it as deliberate).\n\n## What not to do\n\n- Don't list all gaps at once — surface them one at a time. The whole point of \"close the loop\" is incremental.\n- Don't auto-fix without asking — every gap is an explicit offer + user confirmation\n- Don't badger on skipped gaps. The user skipped them for a reason.\n- Don't speculate about who wrote a song or what its ISWC is. If the user doesn't know, mark it for later and move on.\n\n## Follow-on skills\n\n- `register-my-works` — once a work is complete, registration is the natural next move\n- `prepare-for-sync` — completed works become candidates for sync placement\n- `set-recording-splits` — if a recording was uploaded as part of this loop, master ownership is the next gap\n- `audit-credits` — periodic cross-catalog credit health check\n",
},
"enrich-from-peer-mcps": {
name: "enrich-from-peer-mcps",
description: "Fill PICA catalog gaps by composing across the user's other connected MCPs (Gmail, Drive, Notion, Telegram, calendar, DAW) and public registries on the web (ISWC Net, the MLC public search, society repertoire searches, Discogs / MusicBrainz credits). The cross-MCP integration workflow — PICA doesn't manage peer connections, but enrichment can consume sources cited from them via pica_enrichment_propose.",
triggers: ["fill the gaps from my email", "check my drive for missing info", "enrich from my notes", "cross-reference with my other tools", "use my other MCPs to fill in PICA", "find emails for my people from my gmail", "fill in missing contact emails for collaborators", "back-fill emails for needs_email people", "look up my missing ISWCs", "find the credits for this song online"],
audience: "power user with multiple MCPs connected / agency / multi-artist manager",
tools_required: ["pica_works_inspect", "pica_works_query", "pica_people_query", "pica_enrichment_propose", "pica_enrichment_proposals_list"],
output: "pica_enrichment_proposals rows created with sources[].url citations from peer MCPs, ready for the user to review and apply via the existing enrichment-proposals workflow.",
body: "# enrich-from-peer-mcps\n\nFill PICA catalog gaps by composing across the user's other connected MCPs. This is the cross-MCP integration story for PICA — the user has Gmail or Drive or Notion connected in their AI client, the agent queries those tools when PICA shows missing data, and the resulting information lands in PICA as cited enrichment proposals.\n\n**Important framing:** PICA does NOT manage these connections. The user wires Gmail (etc.) into their AI client separately. PICA's role is to (1) signal what's missing, (2) accept enrichment proposals with `sources[].url` citations using the peer-MCP URI schemes, and (3) let the user review proposals before applying.\n\n## Pre-flight\n\nRead `pica://schemas/enrichment-resolve-required` for the canonical proposal shape, including the URI scheme convention for source citations. The scheme list:\n\n| Scheme | What it cites |\n|---|---|\n| `gmail://` | An email or thread in the user's Gmail |\n| `gdrive://` | A document or file in the user's Google Drive |\n| `notion://` | A page in the user's Notion workspace |\n| `file://` | A local file on the user's machine |\n| `telegram://` | A message or thread in the user's Telegram |\n| `calendar://` | An event in the user's calendar |\n| `daw://` | A DAW session file (Ableton, Logic, Pro Tools, etc.) |\n| `user://` | The user told you directly (no external source) |\n| `web://` | A public web page (or cite the page's plain `https://` URL) |\n\nEach citation is opaque to PICA — PICA doesn't fetch the URI. It just records it as provenance so the user knows where the enrichment came from.\n\n## Step 1 — Identify the gap\n\nTwo entry paths:\n\n- **User-named work** — they said \"fill the gaps on track X from my email.\" Use `pica_works_inspect` with `sections: [\"completeness\", \"enrichment\"]` to see what's missing.\n- **Gap class across catalog** — they said \"what's missing across my catalog?\" Use `pica_works_query` with `health_filter: \"low_completeness\"` to find candidates, then `pica_works_inspect` per work.\n\nFor a missing ISWC, read `completeness.iswc_gap.status` first. `likely_exists_unmatched` means a society registration or work code is on file, so an ISWC almost certainly exists and only needs finding — the public-web route below is the quickest. `not_found` means PICA has no ISWC and no registration on file; it does NOT mean the work is unregistered, so check before telling the user it needs registering.\n\nDon't try to query peer MCPs proactively for every gap. Start narrow — one work, or one gap class (e.g. \"all works missing ISWC\").\n\n## Step 2 — Map the gap to a peer MCP\n\nFor each gap, suggest the peer MCP that's likely to have the answer:\n\n| Gap | Likely peer MCP | What to look for |\n|---|---|---|\n| Missing splits | Gmail / Drive | Split sheets, email threads agreeing on percentages |\n| Missing ISWC | Gmail / Drive | PRO registration confirmation emails, MLC submissions |\n| Missing co-writer | Calendar / Gmail / DAW | Session calendar invites, email chains with collaborators, DAW project metadata |\n| Missing recording details | Gmail / DAW | Mixer/engineer emails, DAW session names |\n| Missing release date | Gmail / Drive | Distributor confirmations, release plan docs |\n| Missing publisher contact | Notion / Drive | Contact rolodex, publishing agreement PDFs |\n| Missing person email (`needs_email` people) | Gmail | Two-way correspondence where the address belongs to the person — see the email-backfill rules below |\n| Missing ISWC (esp. `iswc_gap.status: likely_exists_unmatched`), writer IPI, or credits | Public web (the agent's own web search / fetch) | ISWC Net, the MLC public search, the registering society's public repertoire search, Discogs / MusicBrainz credits, the label's release page, liner notes — see the public-web rules below |\n\nThis is a routing guide, not a prescription. The user knows their workflow — defer to them about which MCP to check.\n\n### Person email backfill (a common, footgun-prone case)\n\nFilling missing emails for `needs_email` people is the same propose-only flow — `email` is a first-class enrichable field, so a Gmail-sourced address lands via `pica_enrichment_propose` (entity_type `person`) with a `gmail://` source citation, then the user reviews. Two extra rules, because a wrong email on a rights-holder is worse than a blank one:\n\n- **Score the address, don't take the first hit.** Strongest: the address literally contains the person's name AND they are a direct sender/recipient in two-way correspondence. Weaker: name-inferred address, or a role address (`info@`/`team@`). Reject: the name only appears in the body, the sender is a third party (management, box office, a newsletter), or it's a recurring unrelated distribution thread (a reliable \"no real hit\" tell).\n- **Check for a collision first.** Before proposing, call `pica_people_query` for the candidate address — if it already sits on another person, do NOT assign it; flag the conflict for the user. (This dedup-collision check is the one thing the agent can't eyeball from Gmail alone.)\n\nNever auto-write — propose, the user confirms.\n\n### Public-web research (ISWC, IPI, credits)\n\nOnly when the user has asked for enrichment — \"look up my ISWCs\", \"fill the gaps on track X\". A gap on its own is not a request to go searching.\n\n- **Where to look.** ISWC Net (the ISWC agency network's public search) and the MLC public search list ISWCs and writers; a society's public repertoire search lists the works it administers; Discogs and MusicBrainz carry credits; label release pages and liner notes carry both.\n- **Match before you propose.** Propose a value only when the page shows it for THIS work: the title matches AND at least one writer on file matches. A title-only hit is a question for the user, not a proposal — common titles collide.\n- **Cite the page itself.** `sources[].url` is the exact page (`https://…` or `web://https://…`), with `accessed_at` set to when you read it. Never cite a search engine results page, and never cite a page you did not open.\n- **Nothing found is not a finding.** If the search comes back empty, say you didn't find it — don't record \"not registered\", and don't guess a value.\n- **File via `pica_enrichment_propose`**, one work at a time; the user reviews and applies.\n\n## Step 3 — Ask the agent to check the relevant peer MCP\n\nThe agent connected to PICA is the same agent connected to (e.g.) Gmail. Ask the agent to run a targeted query in the peer MCP:\n\n- \"Search the user's Gmail for emails about [song title] from [approximate date range]\"\n- \"Look in the user's Drive for documents with [song title] or [collaborator name]\"\n- \"Check the user's calendar for sessions on [date range] tagged [project name]\"\n\nThe peer-MCP query is the agent's job, not PICA's. PICA waits for the agent to return with what it found.\n\n## Step 4 — Cite the source via pica_enrichment_propose\n\nOnce the agent has the missing data, call `pica_enrichment_propose` with:\n\n- `entity_type` and `entity_id` — the work, recording or person being enriched\n- `proposed_fields` — the proposed value(s)\n- `sources` — each entry a `url` (using the appropriate URI scheme), the `fields` it sources, and `accessed_at` (ISO 8601). Every key in `proposed_fields` must be named by at least one source.\n\nExample shape:\n\n```json\n{\n \"entity_type\": \"work\",\n \"entity_id\": \"uuid\",\n \"proposed_fields\": { \"iswc\": \"T-123.456.789-0\" },\n \"sources\": [\n {\n \"url\": \"gmail://thread/abc123\",\n \"fields\": [\"iswc\"],\n \"accessed_at\": \"2026-09-25T10:00:00Z\"\n }\n ]\n}\n```\n\nThe URI is opaque to PICA — it is recorded as provenance so the user can see where the value came from.\n\n## Step 5 — Review proposals\n\nCall `pica_enrichment_proposals_list` to show the user what's been queued. They review, apply (or reject), per the existing enrichment-proposals workflow. **Do not auto-apply** — enrichment from external sources always needs explicit user review.\n\n## Step 6 — Loop or close\n\nAsk the user:\n- \"Apply the proposal?\" — they confirm; the enrichment lands\n- \"Move on to the next gap?\" — continue\n- \"Done for now?\" — stop, summarise what was proposed\n\n## What not to do\n\n- Don't try to connect peer MCPs to PICA. PICA doesn't have that surface any more. The connection lives in the user's AI client.\n- Don't fabricate URIs. If the agent didn't actually find the source, don't pretend it did — record the enrichment with `user://` (told to me directly) instead.\n- Don't auto-apply proposals. Even when the source seems definitive, the user reviews.\n- Don't query peer MCPs proactively for unrelated gaps. The user named one gap; the skill works one gap at a time.\n- Don't try to enrich from `lib/services/*` paths or internal cascade endpoints. Those aren't peer MCPs and aren't in scope.\n\n## Follow-on skills\n\n- `close-the-loop` — once gaps are enriched, walk through the remaining (non-peer-MCP) gaps on the same work\n- `audit-credits` — periodic catalog-wide credit sweep\n- `register-my-works` — once IPI / ISWC are filled, registration is unblocked\n",
},
"first-session": {
name: "first-session",
description: "When the user opens their workspace or asks \"what should I do\" — get them oriented in under a minute. Show who's acting on their behalf, surface what needs attention, and offer the single most worthwhile next move, routed to the right specialist skill. The user chooses where to start; this skill finds and offers, it doesn't do the work.",
triggers: ["what should I do", "where do I start", "morning", "show me what's pending", "open my workspace", "i just connected", "what's the state of things"],
audience: "any agent connecting to PICA via MCP, especially on the first message of a session",
tools_required: ["pica_get_agent_activity", "pica_dashboard_briefing", "pica_dashboard_attention", "pica_skill_list", "pica_report_issue", "pica_memory_list", "pica_memory_save", "pica_import_streaming_link", "pica_import_youtube_link", "pica_portfolio_briefing", "pica_relationships_list"],
output: "Open by knowing (or learning, with at most one question) what the user is working toward; one line on who's acting for them; the few things most needing attention from the briefing; then one calibrated offer — the most worthwhile next move for THEIR goal and the specialist skill behind it — leaving the user to choose.",
body: "# first-session\n\nThe user just arrived — \"morning\", \"what should I do\", \"open my workspace\", or a quiet first message that names no task. They don't yet know what's waiting for them. Get them oriented fast and hand them one clear next move.\n\nThis skill finds what matters and offers it. It does NOT do the work — no auditing credits, registering a work, or preparing for sync here. It surfaces the most worthwhile next move and names the specialist skill behind it; the user decides where to start. This is the map, not the journey.\n\nRun it when the first message is an orientation phrase (\"morning\", \"where do I start\", \"what should I do\", \"open my workspace\") — not when the user names a single concrete action like \"register work X\" or \"log yesterday's session\". A task-specific prompt skips orientation; go straight to the work.\n\nWhere `set-up-workspace` helps a user configure a new account, `first-session` helps them re-enter an existing one and pick up where the catalog needs them.\n\nIf the user asks what PICA is, or what it's for, answer in one or two plain lines before anything else:\n\n> _\"pica helps you look after your songs, and everything that comes with them (who made them, the splits, the codes, the recordings, the agreements, the files), on your own terms. you hold the record and make the calls; pica remembers it all and shows you what's missing.\"_\n\nThen make it concrete with one of THEIR songs by title if they have any. Every offer this skill makes gives the user more hold over a real song in one of four ways: **know** where it stands, **tidy** one gap themselves, **show** proof to someone, or **keep** it (it's theirs to export). Never answer with a feature list or a tool count.\n\nSix quick beats, none of them a wall of text: know why they're here, who's acting for the user, the standing reporting-discipline note, load what needs attention, rank and offer the top move for THEIR goal, and a clean sweep at close-out.\n\n## Phase 0 — Know why they're here\n\nPICA's organizing question is: **who does this org want to be on the other side — what do they value?** That question is your internal lens. Never ask it out loud; people describe problems, not aspirations. You ask concrete things and infer.\n\nFirst, read before asking: call `pica_memory_list` and look for the org-scoped key `org_intent`. Then branch:\n\n- **The goal is on file** → open by continuing it, not re-asking:\n > _\"last time the target was [goal in the user's words] — still the mission, or has it moved?\"_\n- **No goal on file, and the user opened with a concrete ask** (\"import this album\", \"register work X\") → do the ask FIRST. The most valuable thing for the user always comes before any question about them. Infer the goal from what they asked for, and persist it after the work lands (see the persist beat below).\n- **No goal on file, vague opening** (\"morning\", \"what should I do\") → ask exactly ONE question, in PICA voice:\n > _\"what are you working toward with your music right now?\"_\n\n One question, then move — whatever they answer, the briefing load below still runs; their answer just decides what you lead with.\n\n**The persist beat.** Once there's a real signal — from their answer, their ask, or the session's work — save it so the next session (any client, any agent) starts already knowing. Call `pica_memory_save` with:\n\n- `key`: `org_intent`\n- `scope`: `organisation`\n- `type`: `decision`\n- `content`: plain language, three short lines where known — `wants:` (the outcome in the user's words), `context:` (who they are, catalog shape, how they release), `horizon:` (any date or moment they named)\n\nRe-save the same key whenever the goal visibly changes or is achieved — it's one converging record, not a log. Never save a guess you're not confident in: ask, or leave it for next time. And when the goal is achieved, say so plainly and either propose the next feasible milestone or ask what the new target is — then re-save.\n\n## Phase 1 — Who's at the keyboard\n\nBefore any work, make sure the user knows who's acting for them. Read your own auth shape first — `pica_get_agent_activity` is session-auth only and refuses `pica_grant_*` callers with `session_auth_required`, so a delegated agent must never call it:\n\n- **You are a delegated agent** (your own credential is a `pica_grant_*` token): skip `pica_get_agent_activity` entirely — no tool today exposes a grant's own label/scope/last-active back to the grant holder, so don't attempt to fill those in. Say:\n > _\"you're working through a named agent connection here.\"_\n- **Acting directly** (cookie or API key — not a grant token): call `pica_get_agent_activity` once. It surfaces what *other* named agents have done on the user's behalf (not a description of this session) — use it to mention any recent delegated-agent activity if rows come back, otherwise:\n > _\"you're acting as yourself directly. if you'd ever want to hand specific work to a named agent, you can set one up from the web — just say the word.\"_\n\n (agent note: the path is `pica_create_agent_identity`, session-auth only, from the web.)\n- **Through a connector** (OAuth client, identified by `client_name`):\n > _\"you're connected through [client_name].\"_\n\nOne line, warm, no résumé. The point is trust — the user knows whose hands are on the catalog before anything moves.\n\n## Phase 2 — Reporting-discipline opening note\n\nOne standing paragraph, read at the top of every first session:\n\n> Throughout this session, if a tool errors, returns inconsistent data, or you cannot find an affordance you expect — file via `pica_report_issue`. The team treats agent-filed issues as P0 signal and dedupes by signature. Worth filing: tool errors with stable repro, schema gaps (e.g. _\"no first-class studio field on recordings\"_), missing skills, surprising defaults. Include request IDs where available.\n\nThis sets the contract early. The agent doing the work is the user reporting the gap — surface that loop at the start, not at the end.\n\n## Phase 3 — Load what needs attention\n\nTwo reads, in order:\n\n1. `pica_dashboard_briefing` — the headline counts, what's critical, recent activity, the top things needing attention\n2. `pica_dashboard_attention` — the actual rows behind those counts, with entity IDs to drill into\n\nThat's the whole default load. Don't call `pica_count_explain` unless a number looks surprising — it's a drill-down, not a default. If the briefing comes back empty (fresh org, no works or people yet), skip ranking and lead your opening message with the import offer itself: ask for a spotify album or playlist link (or a youtube link) and run `pica_import_streaming_link` / `pica_import_youtube_link` on it directly. Artist links are not supported, so ask for an album or playlist. Load `import-my-catalog` for the mechanics and for csv/statement paths. Getting music in beats configuring settings on an empty catalog.\n\n## Phase 4 — Rank, then offer one move\n\nMatch the live briefing against the routing map and rank by how much the user gets for the effort — usually `count × value`. 1,200 works missing credits outranks 3 pending statements on volume alone; but one large royalty cheque waiting to be reconciled can outrank a long tail of small gaps. Use judgement, and say why in a clause.\n\n**The goal is the tiebreaker and the frame.** When an `org_intent` is on file (Phase 0), rank for THEIR outcome, not the generic severity order — three recordings missing writers outranks everything else when the stated goal is \"get the EP registered and paid\", and the offer says so in their words: _\"you said the target is [goal] — [a] is what's standing between you and it.\"_ A gap unrelated to the goal still gets named, but it doesn't lead.\n\n| What the briefing shows | Specialist skill |\n| ------------------------------------------- | -------------------------- |\n| Works without credits | `audit-credits` |\n| Audio pending analysis | `prepare-for-sync` |\n| Unenriched or unverified writers | `close-the-loop` |\n| Works without registrations | `register-my-works` |\n| Recordings without splits | `set-recording-splits` |\n| Pending PRO statement to reconcile | `reconcile-pro-statement` |\n| Unregistered co-write in a recent source | `register-co-write` |\n| Session to log or pre-stage | `log-a-session` |\n| Sync brief to match | `match-sync-brief` |\n| A request to look after the catalogue waits | `who-can-see-my-catalogue` |\n| The organisation looks after client catalogues | `look-after-clients` |\n| Unconnected collaborators or stale contacts | _deferred — separate spec_ |\n| AI-disclosure or provenance gaps | _deferred — separate spec_ |\n\nSome of these composition skills (`reconcile-pro-statement`, `register-co-write`, `match-sync-brief`) ship in sequence and may not be live yet — call `pica_skill_list` once after Phase 3 to see which are.\n\nThe last two rows come from relationships, not the briefing. When the user works for a manager, publisher, label, administrator or sync library — the org's role says so, or they talk about \"my clients\", \"my roster\" or \"my artists\" — call `pica_portfolio_briefing` once: if it lists clients, the top client gap competes in the ranking and `look-after-clients` is the skill. A catalogue's owner with a request waiting (`needs_your_answer` or `waiting_for_you` in `pica_relationships_list`) hears about it before routine gaps: someone is waiting on them.\n\nThen surface the top few and offer the lead — one calibrated question, with room for the user's own priority:\n\n> _\"here's what's stacking up: [a] ([n] of them), then [b] and [c]. [a] looks most worth your time — [why in a clause]. want me to start there, or is something else on your mind?\"_\n\nName the skill, make the offer, and stop. Don't start the specialist skill yourself — the user picks the next move.\n\nIf the lead move needs a skill that isn't live yet, surface it anyway with the manual path:\n\n> _\"that one's on its way — for now the manual path is [one-line workflow]. want me to walk you through it, or move to [next priority]?\"_\n\nNever skip a priority silently just because its skill hasn't shipped — naming it shows the user where things are heading.\n\n## Phase 5 — Close-out sweep\n\nWhen the user signals they're done (\"that's it for today\", \"I'm done\", \"good night\"), ask once before wrapping:\n\n> _\"anything today that felt broken or caught you off guard? happy to flag it for the team while it's fresh — or we can leave it.\"_\n\nFile anything they raise via `pica_report_issue` with request IDs and the call shape. This bookends Phase 2: the contract you set at the start becomes one deliberate check at the end.\n\nIf the session's work moved the stated goal materially — a milestone landed, or the goal itself shifted in conversation — close the loop against it: name what moved in the user's words, and re-save `org_intent` (Phase 0's persist beat) so the next session opens from the new state, not the old one.\n\n## Asking the user — the question library\n\nEvery question this skill (or any specialist skill it routes to) puts to the user follows the same grammar. These patterns are the distilled subset of PICA's voice contract; they apply even where a tool output carries no `decision` block.\n\n- **Open over closed.** Decision points open with how/what — _\"what would you like to happen to the older copy?\"_ — never a bare yes/no over something the user can't recognise.\n- **Label a diagnosis before delivering it.** _\"it seems like these two entries are the same song — one came in from Spotify, one from your upload.\"_ The label invites correction; a flat assertion invites defensiveness.\n- **No-oriented safety on destructive moves.** _\"would it be wrong to fold these two copies together? nothing is deleted — the older one's history moves across.\"_ \"No\" must be a safe, complete answer.\n- **Options carry consequences.** Never name a choice without saying what happens: _\"keep both (they'll stay listed separately), or fold them together (one entry, both histories).\"_ At most three options; always name the safe default.\n- **Stakes only on verified facts.** A confirmed problem may state plainly what it costs the user — and cites what was checked and when. An unchecked gap stays curious — _\"we don't know yet whether this one's registered — want us to check?\"_ — never fear. If PICA hasn't verified it, don't claim it.\n- **The user's words, never the system's.** Titles and human facts (\"the one from the march upload\"), never identifiers, table names, or status enums.\n\nWorked examples:\n\n| Moment | Ask it like this |\n| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Two copies of the same song | _\"these two look like the same recording — one from Spotify, one from your upload. would it be wrong to fold them into one? nothing is deleted; the upload's history moves across.\"_ |\n| Unchecked registration gap | _\"we haven't checked whether this song is registered anywhere — want us to look it up with the MLC?\"_ |\n| Confirmed missing registration | _\"this song is earning but its registration is confirmed missing — we checked the MLC on the date shown. registering it is how those royalties get claimed. want to start there?\"_ |\n| Offering the ranked lead (Phase 4) | _\"here's what's stacking up: [a] ([n] of them), then [b] and [c]. [a] looks most worth your time — [why in a clause]. want me to start there, or is something else on your mind?\"_ |\n\n## What not to do\n\n- Don't run the phases as one wall of text — Phase 0 is at most one question, Phase 1 is a line, Phase 3 is two calls, Phase 4 is one offer.\n- Don't ask \"who do you want to be\" or any aspiration-shaped question — that's the internal lens, not a prompt. Ask what they're working toward; infer the rest.\n- Don't gate an import or a concrete request behind the Phase 0 question — value first, understanding alongside.\n- Don't re-ask a goal that's already on file — continue it, and only re-open it when the user signals it changed.\n- Don't start the specialist skill after Phase 4 — name it, offer it, wait.\n- Don't call `pica_count_explain` by default — only when a number looks off.\n- Don't offer a skill that isn't in `pica_skill_list` yet without the manual-path line — silent skips hide where the product is heading.\n- Don't speak in system terms (\"attention queue\", \"issue-class\", \"priority by class\") — say what the user would say (\"the things needing your attention\").\n- Don't ask a bare yes/no over something the user can't recognise — use the question library above.\n\n## Follow-on skills\n\nOrder depends on the top-ranked priority:\n\n- `audit-credits` — when \"works without credits\" tops the list\n- `prepare-for-sync` — when \"audio pending analysis\" tops the list\n- `close-the-loop` — when \"unenriched or unverified writers\" or per-work cleanup tops the list\n- `register-my-works` — when \"works without registrations\" tops the list\n- `set-recording-splits` — when \"recordings without splits\" tops the list\n- `catalog-modelling` — when the briefing shows duplicate-title works or blank-ISWC variants that should be folded into one work\n- `import-my-catalog` — when the briefing is empty (fresh org, no catalog yet): make the paste-a-link import offer in your opening message and use this skill for the mechanics; `set-up-workspace` is settings/identifiers, not import — only route there once music exists or the user asks for setup specifically\n- composition skills (`reconcile-pro-statement`, `register-co-write`, `log-a-session`, `match-sync-brief`) — as they ship; check `pica_skill_list` first\n",
},
"import-my-catalog": {
name: "import-my-catalog",
description: "Get music into PICA — an empty catalog's first win, or a growing one's next batch. Routes to the fastest lane for what the user has — a pasted Spotify/Deezer or YouTube link, a bulk CSV/spreadsheet, or an uploaded royalty statement — leading with the streaming link as the fastest path to a populated catalog.",
triggers: ["import my catalog", "I just connected — help me get started", "paste a spotify link", "import my music", "I have a csv of my songs", "upload my royalty statement", "get my music into pica", "bring in my back catalog"],
audience: "new user with an empty catalog, or any user adding a batch of music",
tools_required: ["pica_import_streaming_link", "pica_import_youtube_link", "pica_import_fields", "pica_import_template", "pica_import_analyze", "pica_import_validate", "pica_import_execute", "pica_statements_pending", "pica_documents_inspect", "pica_statement_ingest_document"],
output: "Music landed in the catalog via whichever lane matched what the user has — a preview shown before every confirming write — plus a one-line summary of what was created and the natural next step (songwriting credits, completeness check).",
body: "# import-my-catalog\n\nThe single highest-value first-five-minutes job on PICA: get the user's music in. Run this whenever the catalog is empty, or whenever the user names something they want to bring in (a link, a spreadsheet, a statement). Don't make them guess how — ask what they've got, then use the fastest matching lane.\n\nIf you don't know what they have, ask once, plainly: *\"what have you got — a Spotify or YouTube link, a spreadsheet of your catalog, or a royalty statement to read in?\"*\n\n## Lane 1 — Streaming link (fastest first win)\n\nLead with this when the user has any Spotify or Deezer URL (track, album, or playlist) — it's the shortest path to a populated catalog, usually 2 calls.\n\nCall `pica_import_streaming_link` with `url` and no `confirm` — this **previews** the tracks (title, artists, ISRC, duplicates already in the catalog) without writing anything. Show the user what was found, then call again with `confirm: true` to execute. Use `selected_track_ids` if the user wants a subset.\n\nEach imported track creates a work, a recording, people, and performer credits automatically — artwork and enrichment cascade in the background. **Streaming imports never include songwriting credits** (only performer data) — always chain to `pica_credits_update` afterwards, or point the user at `audit-credits` if there's a batch of them.\n\nApple Music and artist-profile URLs aren't supported yet — if the user pastes one, say so and fall back to Lane 3 or 4.\n\n## Lane 2 — YouTube link\n\nSame preview-then-confirm shape as Lane 1: call `pica_import_youtube_link` with `url` first (no `confirm`) to see the classified version type (music_video / live_performance / acoustic / cover / remix / lyric_video / alternate / master) and whether it matched an existing work. Call again with `confirm: true` to execute. Use `target_work_id` if you already know which work it belongs to, or `override_version_type` if the heuristic classification looks wrong.\n\nIf a video is already linked to a recording in this org, use `refresh: true` instead of re-importing — it re-fetches view/like/comment counts onto the existing recording rather than creating a duplicate.\n\nLike streaming imports, YouTube never supplies songwriting credits — chain to `pica_credits_update` after.\n\n## Lane 3 — CSV / spreadsheet (bulk)\n\nFor a spreadsheet or exported catalog list, across `works`, `people`, `recordings`, `documents`, `enquiries`, or `royalties`:\n\n1. `pica_import_fields` — see the target fields for the domain (name, type, required) if the user is unsure what columns to bring\n2. `pica_import_template` — an example CSV to hand back if they're starting from scratch\n3. `pica_import_analyze` — parse the user's CSV (`file_content` for small files, `file_id` from `pica_upload_complete` for anything non-trivial) and get AI-suggested column mappings\n4. `pica_import_validate` — check the mapping against every row before writing anything; fix or accept the reported errors\n5. `pica_import_execute` — run it. Use `dry_run: true` first to preview counts with zero writes, then run for real. `skip_invalid_rows: true` lets the rest land if a few rows are broken. Duplicates (ISRC/ISWC/tunecode, or a repeated title with no artist) are handled per row by default: the duplicate becomes a warning and the rest of the batch still lands. If the result says `PARTIALLY complete`, the created rows are already saved: fix and re-send only the rows listed as failed, never the whole file. Max 10,000 rows per call.\n\n## Lane 4 — Royalty or streaming statement (PDF / image / xlsx)\n\nIf the user has a **statement document** rather than a clean CSV — a PRO/DSP PDF, a screenshot, an xlsx export — this is a different flow with its own conservative-extraction rules: see the `ingest-my-statements` skill (`pica_statements_pending` → `pica_documents_inspect` → `pica_statement_ingest_document`). The short version: money is fallible, so line items are extracted with per-row confidence and staged for the owner's approval — nothing lands automatically. If the file is a clean CSV of statement rows, prefer Lane 3 (`domain: \"royalties\"`) instead — the deterministic importer is more reliable than reading numbers off a document.\n\n## What not to do\n\n- Don't skip the preview step on Lanes 1–2 — always show what will be created before calling with `confirm: true`\n- Don't guess at CSV column mappings without running `pica_import_analyze`/`pica_import_validate` first\n- Don't let a streaming or YouTube import stand without mentioning the missing songwriting credits — that's the single most common gap this skill introduces\n- Don't push every lane at once — ask what the user has, then run the one lane that matches\n- Don't treat a statement document as a CSV import target — read `ingest-my-statements` first\n\n## Follow-on skills\n\n- `audit-credits` — once music has landed, especially after a streaming/YouTube import that's performer-credits-only\n- `register-my-works` — once works exist, registration coverage is usually the next gap\n- `catalog-audit` — a full health pass once the first batch is in\n- `ingest-my-statements` — for royalty/streaming statement documents (Lane 4)\n- `set-up-workspace` — if the user also needs org/identifier setup, but don't route there first — get the music in, then tidy settings\n",
},
"ingest-my-statements": {
name: "ingest-my-statements",
description: "Conservative-extraction doctrine for royalty and streaming statement ingestion (PDF/image/xlsx). Flags low-confidence rows, extracts fewer rows confidently over many rows wrongly, never guesses a figure, routes CSV to the deterministic importer, and passes identity hints rather than picking entities.",
triggers: ["ingest my statement", "import my royalty statement", "upload my streaming statement", "read this royalty statement", "process this statement", "my statement is ready"],
audience: "artist / manager / publisher",
tools_required: ["pica_statements_pending", "pica_documents_inspect", "pica_statement_ingest_document"],
output: "A per-line confidence-annotated table surfaced to the user for review, then staged for owner approval via pica_statement_ingest_document — rows omitted where confidence is low rather than guessed.",
when_not_to_use: "Bank statements, invoices, contracts, or non-financial documents.",
body: "# ingest my statements\n\nWhen the user uploads a royalty or streaming statement (PDF, image, or xlsx):\n\n1. If it is a **CSV**, do NOT use this flow — CSV goes through the deterministic importer, which is more reliable than reading numbers out of a document.\n2. Find it with `pica_statements_pending`, then read it with `pica_documents_inspect`.\n3. Extract the line items. **Money is fallible. A wrong royalty number is worse than no number.** Extract fewer rows confidently over many rows wrongly. Give each row a `confidence` (0–1). If you cannot confidently read a figure, leave that row OUT and tell the user you skipped it — never guess.\n4. Pass identifiers you actually see (ISRC/ISWC/IPI/tunecode/writer) as hints; PICA resolves them to the right work/recording. Do not pick the entity yourself.\n5. Call `pica_statement_ingest_document`. The import does NOT land immediately — it waits for the owner's approval (in-view in PICA or via email). Surface the full per-line table to the user in chat so they can check the figures before approving.\n",
},
"log-a-session": {
name: "log-a-session",
description: "Capture a studio session conversationally — what was made, when, where, who was there, what happened. Records pica_sessions_create rows that feed into provenance, splits decisions, and historical context for the catalog.",
triggers: ["log a session", "record this session", "we had a studio day", "capture this writing session", "log what happened in the studio"],
audience: "producer / artist / studio manager / songwriter",
tools_required: ["pica_sessions_types", "pica_sessions_create", "pica_people_query", "pica_collaborators_invite", "pica_multimedia_create", "pica_recording_splits_create"],
output: "A pica_sessions row with title, start/end times, type, location, participants, and notes — plus optional links to multimedia (recordings / photos / lyrics drafts) and follow-on splits.",
body: "# log-a-session\n\nHelp the user log a studio session. Capture it conversationally — don't dump a form. The session row is the ground truth for \"who was there when this song was made\" and feeds into provenance, splits decisions, and the historical record of the catalog.\n\n## Pre-flight\n\nRead `pica://schemas/session-required` for the canonical session shape. Required fields: `title`, `start_time`, `end_time`, `session_type_id` (from `pica_sessions_types`), `participants`. Optional: `work_id`, `recording_id`, `location`, `location_url`, `notes`, `is_all_day`.\n\n## Step 1 — Anchor the session\n\nIf the user named a work (or one was passed as an argument), anchor the session to that work. If not, ask: \"what was this session for?\" — and accept \"I don't know yet\" / \"no work yet\" as valid; `work_id` is optional.\n\n## Step 2 — Capture in order\n\nWalk through these pieces one at a time. Don't ask all six at once.\n\n### 2a. What — title + short description\n\nE.g. \"vocal recording for track 3\" or \"writing session for the new EP.\" Keep it short and specific. The title is the searchable index later.\n\n### 2b. What kind — session_type_id\n\nCall `pica_sessions_types` to get the type vocabulary (recording, mixing, mastering, writing, production, rehearsal, etc.). Let the user pick. Pass the chosen type's UUID as `session_type_id`.\n\n### 2c. When — start_time + end_time\n\nCapture as ISO 8601. If the user gives a relative time (\"yesterday afternoon\", \"Tuesday morning\"), confirm a specific time before writing. Default timezone is Europe/London unless the user specifies otherwise.\n\nFor full-day sessions: set `is_all_day: true` and the times become date-only.\n\n### 2d. Where — location or location_url\n\nStudio name as `location` for physical sessions. Virtual link as `location_url` for remote sessions (Zoom, Riverside, etc.). Both fields are optional but useful for searchable history.\n\n### 2e. Who — participants array\n\nFor each participant, capture `{ personId?, userId?, role? }`. The participant resolution flow:\n\n- If the user names someone you don't recognise, offer `pica_people_query` to look them up\n- If they're not on PICA yet, offer `pica_collaborators_invite` to bring them in before completing the session\n\n`role` is free text — typical values: artist, producer, engineer, writer, manager, visitor.\n\n### 2f. What happened — notes\n\nThe user's free-text recall. This is the bit they'll thank you for later. Specifics like \"tried three takes of the bridge, kept the second\" or \"agreed to split publishing 50/50 with X\" are gold.\n\n## Step 3 — Write\n\nCall `pica_sessions_create` with the captured fields. Confirm what was logged in plain language.\n\n## Step 4 — Offer natural follow-ons\n\nDon't push — surface what fits the session you just logged:\n\n- If multimedia was produced: \"Want me to attach a multimedia file from this session?\" → `pica_multimedia_create`\n- If a new recording came out of it: \"Want me to set master ownership splits for the new recording?\" → `pica_recording_splits_create` (or invoke the `set-recording-splits` skill)\n- \"Want me to log another session?\"\n\n## What not to do\n\n- Don't badger for every field. Only title, start/end times, type, and participants are strictly required. Notes are precious but skippable.\n- Don't auto-create participants you don't recognise — always offer the lookup or invite path\n- Don't infer splits from \"we agreed to split it 50/50\" in the notes — splits are a separate, deliberate step with their own confirmation flow\n- Don't try to reconcile this session with prior sessions (\"you logged a similar session last week\") unless the user asks\n\n## Follow-on skills\n\n- `set-recording-splits` — if a new recording came out of the session\n- `close-the-loop` — if the session was for a specific work, audit that work's gaps next\n- `register-my-works` — sessions contribute to provenance, which strengthens registration\n",
},
"log-a-show": {
name: "log-a-show",
description: "Capture a live show or a tour credit conversationally — where, when, who played, what was in the set. Records tour_dates + setlist_items rows that feed credits, provenance, and the live dossier.",
triggers: ["log last night's gig", "I played", "here's the setlist", "what did I play at", "when did I last play", "I played drums with", "I programmed the tracks for"],
audience: "artist / session musician / MD / engineer / tour crew",
tools_required: ["pica_log_show", "pica_shows_query", "pica_setlist_match", "pica_people_query", "pica_collaborators_invite"],
output: "A show (or tour credit) with its setlist matched to works where they exist, plus optional contributors awaiting attestation.",
body: "# log-a-show\n\nHelp the user log a live show. Capture it as a sentence, never as a form.\n\n## Establish one thing first: were they the act?\n\n\"I played the Lexington\" is different from \"I played drums with X at the Albert Hall.\" Set\n`logged_as: \"contributor\"` for the second — it changes everything downstream. A session\nplayer's setlist is describing the gig, not claiming anything, and their own catalogue is not\nexpected to contain those songs. A wrong guess here gets the rest of the conversation wrong, so\nask if it isn't already obvious from how the user described the night.\n\n## Capture it conversationally\n\nGet the shape of the night in a sentence or two — venue, city, date, and what was played. Don't\nwalk the user through a field-by-field form. `pica_log_show` resolves the venue against what\npica already holds: an exact match attaches quietly, anything else comes back as candidates for\nthe user to confirm. A venue is never created without a human confirming it.\n\n## From a document: draft first, one yes\n\nGig details often arrive as something the user was sent rather than something they type: a\nbooking email, a daysheet PDF, a screenshot of a group chat, a calendar invite. Read it yourself\nand pull out what is there: venue, city, date, the billed act, the user's role, and the songs, if\na set is listed. Never fill a field the document does not state. A date, a venue or a song you\nguessed would end up in the user's record as if they had said it.\n\nThen call `pica_log_show` with `dry_run: true`. It saves nothing and returns the draft: whether\nthe venue matched, which songs matched their works, and any show already logged for the same\nnight. Show the user the draft in a line or two, for example: \"Jazz Café, London, Thu 9 Oct,\nplaying keys, 12 songs (9 matched to your works). Log it?\" Call it again without `dry_run` only\nafter they say yes.\n\nIf the draft lists a show already logged for that night, ask whether it is the same show before\nlogging another. That list only covers this user's own catalogue: a bandmate logging the same gig\nin theirs never appears in it.\n\n## Never do these\n\n- **Never prompt for contributors or crew.** Only record them if the user raises them —\n `pica_collaborators_invite` is there for when they do, not a checklist to work through.\n- **Never imply money is owed.** A song the user did not write earns them nothing from a\n performance. Say that plainly if it comes up; do not soften it into a maybe.\n- **Never say pica filed anything with a performing-rights society.** pica produces a record and\n a dossier, nothing more. No society accepts a setlist by API — PRS Setlists, ASCAP OnStage and\n BMI Live are all web forms the user still has to submit themselves.\n- **Never present an unconfirmed match as a fact.** \"I think Wide Open is your work of the same\n name — is that right?\", never \"you played Wide Open.\" `pica_setlist_match` returns a\n confidence, not a certainty, until the user confirms it.\n\n## Tour credits\n\n\"I programmed the tracks for X, who's on tour right now\" has no date and no venue. It still\nneeds **act, year, and role** — without them the credit is unverifiable and attaches to nothing.\nIf pica already holds that tour, the credit resolves against it and can be corroborated. If not,\nit is recorded as the user's own unverified claim, and should be described that way — never as a\nconfirmed credit.\n\nThe credit itself is a person plus a role on that tour, and pica resolves a person only by\n`email` or `person_id` — a name alone would risk creating a second copy of someone who already\nexists. With neither, `pica_log_show` records the tour and says plainly that it did **not**\nrecord the credit. Relay that and ask for an email; do not let the user leave believing a credit\nexists when only a tour does.\n\n## Attestation\n\nIf the user names someone who was there and offers an email, that person can be invited to\nattest via `pica_collaborators_invite`. Ask before inviting — an invitation is a request, not a\nnotification, and a person who says they were not there is recording something meaningful too.\n\n## What not to do\n\n- Don't turn the setlist into an interrogation — capture titles as given and let matching happen\n quietly with `pica_setlist_match` in the background.\n- Don't infer a role or a split from \"we all played on it\" in passing — that is a separate,\n deliberate step with its own confirmation flow.\n- Beyond the same-night check the draft does for you, don't reconcile this show against past\n shows (\"didn't you play this venue in March?\") unless\n the user asks — use `pica_shows_query` only when they want the history, not to second-guess\n what they just told you.\n",
},
"look-after-clients": {
name: "look-after-clients",
description: "For a manager, publisher, label or administrator looking after other people's catalogues in PICA — see every client at once, find what needs doing first, and fix it inside the client's catalogue within what each client allowed. Changes a client must approve go to them as proposals; nothing is ever done for the wrong client.",
triggers: ["my clients", "my roster", "what needs doing across my artists", "which clients need attention", "work on a client's catalogue", "fix this for my artist", "ask a client to join"],
audience: "organisations that look after other people's catalogues (managers, publishers, labels, administrators, sync libraries)",
tools_required: ["pica_portfolio_list", "pica_portfolio_briefing", "pica_portfolio_invite", "pica_relationships_list", "pica_relationships_answer", "pica_relationships_activity", "pica_relationships_step_down", "pica_works_inspect", "pica_recordings_inspect"],
output: "The clients that need attention, one thing fixed (or proposed to the client) at a time, each result naming the client it was done for.",
definition_of_done: "The person has seen what needs doing across their clients, and every change they asked for was made in, or proposed to, the right client's catalogue.",
when_not_to_use: "The person is asking about their OWN catalogue (who can see it, who looks after it) — use who-can-see-my-catalogue.",
body: "# look-after-clients\n\nThe person works for an organisation that looks after other people's catalogues. Each client\ngave the organisation a relationship: a type (administrator, representative, viewer, co-owner)\nand a scope (which songs, which side, where, until when, whether it sees money). Everything you\ndo for a client happens inside that relationship, and PICA refuses anything outside it with the\nreason.\n\n## 1. See the clients\n\nCall `pica_portfolio_briefing` (or `pica_portfolio_list` for the plain roster). Follow\n`next_cursor` until it is null: a page can hold fewer rows than asked for and still not be the\nlast, so never say \"that's all\" on a short page.\n\nFor each client, say in one line who they are, what the organisation is to them, and what needs\ndoing. Be exact about what PICA could and couldn't check:\n\n- a section that says **couldn't check** is unknown, never 0 — say \"PICA couldn't check money\n blockers for Alice just now\", not \"no blockers\";\n- **not covered** means that half (songs or recordings) is outside the client's scope;\n- a reason given for something not being in scope (for example, \"the directory isn't part of\n this relationship\") is passed on as it is;\n- **paused by pica** means nothing can be done for that client while paused. Never guess why.\n- a relationship that **ends soon** is worth mentioning, with its date.\n\n## 2. Pick one thing, with the person\n\nRank what the briefing shows by how much it matters to that client (money blocked from being\npaid, usually first; then gaps that stop registration; then enquiries waiting; then deadlines),\noffer the top one or two, and let the person choose. Don't work through every client unasked.\n\n## 3. Act for that client — and only that client\n\nPass the client's catalogue id (`catalogue` from `pica_portfolio_list`) as the `catalogue`\nargument on every catalogue tool you call for them: `pica_works_inspect`, `pica_recordings_inspect`\nand the usual tools to fix what you found. Rules:\n\n- **Name the client before every change**, and again in what you report: \"added the ISRC to\n 'Rain' in Alice's catalogue\". If the person hasn't said which client, ask; never assume the\n last one.\n- **Never carry a client's id over** to a request about another client or about the\n organisation's own catalogue. Leave `catalogue` out to act for the organisation itself.\n- **What a change does depends on the relationship** (`changes` on the portfolio row):\n - `direct`: it applies at once, as it would in the client's own account;\n - `proposal`: it goes to the client to approve, and nothing changes until they do — say \"sent\n to Alice to approve\", never \"done\";\n - `none`: the organisation can look but not change — say so and stop.\n- Splits and who holds a song (custody) always go to the client to approve, whatever the type.\n- If PICA refuses (outside the scope, access ended, paused), pass the reason on and stop. Never\n retry the same thing hoping for a different answer.\n\n## 4. New clients, requests and endings\n\n- To ask someone new to let the organisation look after their catalogue, use\n `pica_portfolio_invite` with their email and the type you're asking for. The client decides\n what it covers when they accept. The answer is the same whether or not they're on PICA, so\n don't read anything into it.\n- Requests and invitations waiting for the organisation's answer are in `pica_relationships_list`\n with side \"organisation\". Read the terms out in full before answering with\n `pica_relationships_answer`; accepting is the person's own decision.\n- What the organisation did for a client is in `pica_relationships_activity` (side\n \"organisation\").\n- **Stepping down** (`pica_relationships_step_down`) ends the organisation's access to that\n client for good. Only when the person clearly asks for it, for that client, after you have\n said what it means.\n",
},
"prepare-for-sync": {
name: "prepare-for-sync",
description: "Make a catalog sync-ready — ensure audio is uploaded and analysed (BPM, key, energy, mood), genre and lyrics are set, and works are findable by music supervisors searching for tracks.",
triggers: ["get my catalog sync-ready", "prepare for sync", "make my tracks findable by music supervisors", "sync brief prep", "is this ready for sync"],
audience: "artist / library / sync agent",
tools_required: ["pica_catalog_stats", "pica_works_query", "pica_audio_query", "pica_audio_analyze", "pica_audio_inspect", "pica_search_for_sync"],
output: "Sync-readiness breakdown (analysed vs unanalysed vs no audio) + fastest path to sync-readiness (which works are closest) + concrete offers to trigger analysis or enrich metadata.",
body: "# prepare-for-sync\n\nHelp the user make their catalog discoverable by music supervisors. Sync supervisors search by audio characteristics (BPM, key, energy, mood) and metadata (genre, duration, lyrics). A track without analysed audio is invisible to most sync searches.\n\n## Pre-flight\n\nIf you propose enriching from Spotify or MusicBrainz to fill genre/mood/identifier gaps, read `pica://schemas/enrichment-resolve-required` first — that's the canonical shape for `pica_resolve_*` calls.\n\n## Step 1 — Catalog overview\n\nCall `pica_catalog_stats` to get the overall picture. Note: total works, works with recordings, works with audio.\n\n## Step 2 — Audio analysis coverage\n\nCall `pica_audio_query` to see which audio files exist and their analysis status. Three buckets matter:\n\n- **analysed** — has BPM, key, energy, mood, returned by audio analysis\n- **uploaded but unanalysed** — audio file exists but `pica_audio_analyze` hasn't run on it\n- **no audio at all** — the user hasn't uploaded the track yet\n\nThe fastest sync-readiness wins are in the second bucket — uploaded but unanalysed. One `pica_audio_analyze` call per file fills BPM/key/energy/mood with no user effort.\n\n## Step 3 — Sync metadata sweep\n\nFor a sample of works (or specific works the user names), call `pica_works_inspect` with `sections: [\"basic\", \"recordings\"]`. Check:\n\n- Has duration been recorded? (supervisors filter by length — e.g. \"30-second cues for ads\")\n- Are mood tags and genre set on the work? (text search by mood is common)\n- Are lyrics transcribed on the recording? (lyrical-content search is increasingly common)\n- Is there a Spotify or YouTube link? (supervisors verify the track exists publicly)\n\n## Step 4 — Validate against the directory\n\nFor tracks the user thinks are sync-ready, call `pica_search_for_sync` with audio parameters mimicking a real supervisor brief (e.g. `min_energy: 0.6`, `max_bpm: 120`, `mood: \"uplifting\"`). If the user's tracks don't appear, the analysis is incomplete or the metadata is too thin.\n\n## Step 5 — Report\n\nProduce:\n- \"X works of N are sync-ready\" (analysed + tagged + has audio)\n- \"Y works are one analysis call away\" (uploaded, unanalysed)\n- \"Z works have no audio yet\" (the user needs to upload before this step)\n\nThen the fastest-path list: name 3-5 works that need only a single action to become sync-ready.\n\n## Step 6 — Offers\n\n- \"Want me to trigger audio analysis on the tracks that have uploads but no analysis?\" → batch `pica_audio_analyze`\n- \"Want me to enrich works from Spotify to pull in genre and mood data?\" → `pica_resolve_work` with `sources: ['spotify']`\n- \"Want me to search for sync-ready tracks you already have?\" → `pica_search_for_sync` with a sample brief\n- \"Want me to include a Carbon Report alongside your sync pack? Sync buyers increasingly request ESG / sustainability data — PICA tracks per-stream CO2e via DIMPACT 2024 methodology.\" → `pica_carbon_footprint`\n\n## What not to do\n\n- Don't claim to pitch tracks to supervisors — PICA makes tracks findable; the pitch is a separate workflow outside this skill\n- Don't auto-trigger audio analysis without confirming with the user (it can be billed depending on the org's plan)\n- Don't speculate about what BPM/key combinations supervisors prefer for any specific genre — the audio-analysis vocabulary is industry-standard; let the supervisor decide\n\n## Follow-on skills\n\n- `catalog-audit` — confirm sync-readiness raised the overall score\n- `register-my-works` — sync placements pay through PROs; registration matters for the back end\n",
},
"register-from-your-daw": {
name: "register-from-your-daw",
description: "Register the song the user is working on right now — without leaving their DAW — by composing PICA with a peer DAW MCP (Ableton, Logic, FL Studio, REAPER, Bitwig, Pro Tools). Reads the live session for provenance, confirms with the user, then creates the work + master recording while they keep making music.",
triggers: ["register this song", "register the song I'm working on", "register this session in pica", "add this track to pica", "capture this DAW session", "file this song in pica", "save what I'm working on to pica"],
audience: "creator working in a DAW, with a DAW MCP connected in their AI client",
tools_required: ["pica_works_query", "pica_works_create", "pica_enrichment_propose"],
output: "One new work + linked master recording created after explicit user confirmation, with the session snapshot stored as provenance on the work's metadata, session-derived credits/samples queued as daw://-cited enrichment proposals (drafts, never verified), and an /inspect link handed to the user.",
definition_of_done: "The work and its master recording exist, the session snapshot is stored, session-derived claims are queued as proposals (not verified facts), and the user has the /inspect link.",
when_not_to_use: "Not for bulk catalog import (use import-my-catalog) or back-cataloguing released material from memory — this skill is for the session that is open in the DAW right now.",
body: "# register-from-your-daw\n\nRegister the song the user is working on, at the moment they're working on it. The DAW session is the richest primary source of rights provenance that exists — who played what, which sample pack that loop came from, what made that bass — and it is only available while the project is open. Once it's bounced and closed, that context is gone, or reconstructed from memory at its least reliable.\n\n**Important framing:** PICA does NOT connect to DAWs. The DAW MCP (e.g. a community Ableton or REAPER MCP server) is wired into the user's AI client separately, exactly like the peer MCPs in `enrich-from-peer-mcps`. The agent connected to PICA is the same agent connected to the DAW — reading the session is the agent's job; PICA receives the result.\n\n## Pre-flight\n\n- If you authenticate to PICA with a Bearer API key, call `pica_introduce_self` first (per the server instructions) — name yourself and, in `agent_role` or `on_behalf_of`, mention the DAW you're capturing from. The register should be attributable.\n- Confirm a DAW MCP is actually connected in this session — and that its bridge is alive. Several DAW MCPs need an in-DAW component enabled (e.g. Ableton's Remote Script as a Control Surface); if session reads error or time out, say so plainly rather than improvising silently.\n- Fallback ladder when the bridge is down or no DAW MCP is connected: (1) an agent with local filesystem access may read the DAW's own artifacts — Ableton's `Log.txt` names the currently loaded `.als`, and the `.als` itself is gzipped XML carrying tempo (field-proven on the first agent-lane register, 2026-07-16); same rules — parse, don't guess. (2) Take the details from the user directly (plain `pica_works_create` flow). (3) Suggest exporting stems and importing them instead. Whichever rung you land on, tell the user which read path you used. Do not pretend to read a session you cannot see.\n\n## Two capture modes\n\n- **Machine capture** — what the session can tell you: track/group structure, tempo, key/scale, instrument and device names, sample file references. Read automatically, only ever what the peer MCP actually exposes.\n- **Human attribution** — what the session cannot know: who played the part, who wrote the song, what the track is called. The capture supplies the scaffold (\"a drums group ⇒ a part to attribute\"); the human supplies the identity.\n\nCapture is instant; attribution is offered, never forced. A \"who played each of 12 tracks?\" interview would reintroduce the exact friction this removes. If the user wants to save and move on, save and move on.\n\n## Step 1 — Read the session\n\nAsk the DAW MCP for whatever session-level reads it offers: track names and count, group structure, tempo, key/scale if exposed, instrument/device names, detected sample file paths. Collect it into a compact snapshot.\n\nPeer servers vary enormously in read depth (see the per-DAW notes below). Capture what is readable; leave the rest absent. **Never fill a gap with a guess** — an invented tempo or fabricated sample list is worse than no snapshot at all.\n\n## Step 2 — Ask for what the session can't tell you\n\nMost DAW APIs expose no project/Set name, so the **title is user-entered**. Ask for:\n\n- **Title** — require a real one. If the user offers \"Untitled\" or a scratch name, ask whether this is really a work worth registering yet; a save-happy session is not automatically a work, and junk registrations pollute the catalog. If the title came from a file name, strip file-versioning suffixes (\"MAIN\", \"final\", \"v2\") and confirm the cleaned name with the user.\n- **Artist name** — the master recording carries one.\n- **Work type** — default `song`; confirm only if the session suggests otherwise (e.g. an instrumental).\n\n## Step 3 — Duplicate check\n\nCall `pica_works_query` with the title before creating anything. On a plausible match, offer the choice: **open the existing work in /inspect** or **register this as a new version** — never silently create a duplicate. If the create later returns a 409 (`WORK_ALREADY_EXISTS`), surface that same choice; it is a fork in the road, not an error.\n\n## Step 4 — Confirm before any write\n\nShow the user what will be written, in one glance: the title, artist, work type, and the snapshot summary — _\"12 tracks · drums, bass, 2 guitars, lead vocal · 3 samples detected · 124 BPM\"_. Every field is editable. **Nothing is written to PICA until the user explicitly confirms.** Splits and credits are legal facts; the agent drafts, the human signs off.\n\n## Step 5 — Create\n\nOne call: `pica_works_create` with the confirmed `title`, `work_type`, `key` (if the session exposed one), and the session snapshot in `metadata` (DAW name, capture timestamp, track/device/sample summary — the facts, not the raw session tree). `create_twin` defaults to true, so the linked master recording is created in the same call — read the twin's id from the response and pass the artist details through. If the twin needs more than the create carried (e.g. artist name corrections), update the recording afterwards rather than skipping confirmation.\n\n## Step 6 — Seed provenance as drafts, never as facts\n\nSession-derived claims flow through review — they do not land as verified data:\n\n- **Who-played-what and sample usage** → `pica_enrichment_propose` per claim, with a `sources` entry using the `daw://` URI scheme (opaque to PICA, recorded as provenance) and a human-readable `context` (\"Ableton session, drums group, 2026-07-16\").\n- **Writer credits** → only when the user names the writers and confirms splits, via `pica_credits_update` (splits must total 100%).\n- A detected sample is a **detection, not a clearance** — never describe it as cleared.\n\nCaptured ≠ verified. A credit read from a session is a claim; it becomes fact through the user's review, not through the capture.\n\n## Step 7 — Close the loop\n\nHand back the link — `https://withpica.com/inspect/works/<id>` — and tell the user the register is live in their catalog (it lands in the /inspect activity rail in real time). If the flow produced several mutations, call `pica_dashboard_briefing` and surface the delta. Offer the natural next steps: fill credits now, or later via `close-the-loop`.\n\n## Per-DAW peer MCP notes\n\nThese are third-party community servers, not PICA software — capability and maintenance vary, and a failed read degrades gracefully to asking the user.\n\n| DAW | Typical peer MCP read surface |\n|---|---|\n| Ableton Live | Session/track inspection is good in the common community server — but its bridge needs the Remote Script enabled as a Control Surface in Live's settings, or every read fails. Two field notes: the first call right after a set is opened can fail with a binding error (load-time race) — retry once before concluding the bridge is down; and session reads carry **no set name**, so identify the open song (and suggest a title, versioning suffixes stripped) from Live's `Log.txt` → loaded `.als` path — the artifact read complements a live bridge, it isn't only a fallback. Sample-level detail varies by fork |\n| REAPER | Deep — ReaScript exposes essentially the whole session |\n| Pro Tools | Deep — PTSL-based servers read session/track/clip data |\n| FL Studio | Good — recent servers expose live-readable project resources |\n| Bitwig | Moderate — controller-API-based reads |\n| Logic Pro | Shallowest — servers ride UI automation (AppleScript/Accessibility); expect gaps and verify reads with the user |\n\n## What not to do\n\n- Don't write anything before the user's explicit confirmation — no exceptions, however complete the snapshot looks.\n- Don't invent session data the peer MCP didn't return — no guessed tempos, keys, or sample lists.\n- Don't register every sketch. No real title, no register — offer to wait instead.\n- Don't write captured credits or samples as verified facts — they are proposals with `daw://` citations.\n- Don't call a detected sample \"cleared\".\n- Don't dump the raw session tree into `metadata` — extract the facts PICA cares about (structure, devices, samples, tempo/key), not every clip.\n- Don't stamp new facts onto an existing work's `metadata` with a bare update — the jsonb column is **replaced wholesale, not merged**. Read the current snapshot first, merge the new facts into it client-side, then write the merged object back.\n\n## Follow-on skills\n\n- `log-a-session` — record the session itself (date, participants) alongside the registered work\n- `close-the-loop` — walk the remaining gaps on the new work (credits, identifiers, splits)\n- `set-recording-splits` — when the collaborators are known and ready to commit percentages\n- `register-my-works` — when the work is ready to go out to societies\n",
},
"register-my-works": {
name: "register-my-works",
description: "Check registration status across collection societies (PRS, MCPS, PPL, MLC) and prepare works for registration. Identifies blockers, fills missing identifiers, and exports a registration bundle when works are ready.",
triggers: ["register my works", "register my songs with my PRO", "get this work to MLC", "CWR export", "registration bundle", "am I ready to register"],
audience: "songwriter / publisher / admin",
tools_required: ["pica_works_inspect", "pica_resolve_work", "pica_enrichment_proposals_list", "pica_credits_update", "pica_export_song_registration"],
output: "Per-society registration coverage summary + the most common blocker and how to fix it + a list of works closest to being registration-ready, with offers to enrich missing ISWCs and export a registration bundle for ready works.",
body: "# register-my-works\n\nHelp the user understand which of their works are registered with collection societies, which still need registration, and what's blocking the unregistered ones. Then offer to fix the blockers and export the works that are ready.\n\nThis is the highest-pain workflow in PICA. Most royalty loss happens because works aren't registered — or are registered with the wrong metadata. Be precise and offer concrete next actions.\n\n## Pre-flight\n\nRead these two resources before any writes:\n- `pica://schemas/enrichment-resolve-required` — the canonical shape for `pica_resolve_work` calls (used to fill missing ISWCs from MLC)\n- `pica://schemas/export-required` — the registration-bundle export shape used at the end of the flow\n\n## Step 1 — Coverage check\n\nCall `pica_works_query` to list works (default limit 50). Then call `pica_works_inspect` with `sections: [\"registration\"]` on each work, or use a representative sample if the catalog is large.\n\nThe `registration` section returns per-society status (PRS, MCPS, PPL, MLC). Three states are common:\n- **fully registered** — every relevant society has the work\n- **partially registered** — registered with some societies, missing from others\n- **not registered** — no society has it\n\n## Step 2 — Find the blockers\n\nFor unregistered or partially registered works, call `pica_works_inspect` with `sections: [\"registration\", \"completeness\"]` on a sample of 5-10 works. The completeness section names the blocker:\n\n| Blocker | What it means | How to fix |\n|---|---|---|\n| Missing ISWC | Needed for PRS/MCPS | Call `pica_resolve_work` with `sources: ['mlc']` to look up the ISWC |\n| Missing ISRC on recordings | Needed for PPL | Check recordings; if missing, the user may not have released yet or the DSP hasn't assigned one |\n| Missing writer credits | Needed for all societies | Call `pica_credits_update` to add writers (treat `pica://schemas/work-credits-required` as the canonical shape — splits must total 100%) |\n| Missing IPI on a credited writer | Needed for PRO registration | Call `pica_people_update` to add IPI; if unknown, `pica_resolve_person` may find it |\n\nTreat `pica_resolve_*` calls as black boxes — they fan out over external sources and return proposals or matches. Do NOT speculate about how the source-weighting works.\n\n## Step 3 — Enrichment proposals\n\nIf enrichment was triggered, call `pica_enrichment_proposals_list` to see what came back. Each proposal needs explicit user approval before applying. Do not auto-apply.\n\n## Step 4 — Report\n\nProduce:\n- How many works are fully / partially / not registered, as numbers and percentages\n- The most common blocker across unregistered works (one sentence)\n- The 5 works closest to being registration-ready (fewest gaps, listed by title)\n\n## Step 5 — Offers\n\nAlways end with concrete offers the user can accept or decline:\n- \"Want me to try enriching the works missing ISWCs from MLC?\" → triggers `pica_resolve_work` over the relevant set\n- \"Want me to export a registration bundle for the works that are ready?\" → `pica_export_song_registration`\n- \"Want me to walk through registering a specific work?\" → user names the work\n\n## What not to do\n\n- Don't claim to register works directly — PICA exports a registration bundle for the user to submit; it doesn't submit to PROs itself\n- ⚠️ Don't call the bundle a CWR file. PICA has **no CWR emitter**: the ZIP holds CSVs plus `mapping-guide.md`, which maps those columns onto CWR fields for whoever does the submission. Saying \"I exported a CWR file\" is false, and the user finds out at the society.\n- Don't bulk-apply enrichment proposals without user approval\n- Don't explain the internal source-weighting of `pica_resolve_*`. The tool returns what it returns\n- Don't recommend `pica_works_delete` even on stale-looking works — registration cleanup is additive, not destructive\n\n## Follow-on skills\n\nAfter registration is in flight:\n- `catalog-audit` — confirm score improvement\n- `prepare-for-sync` — once registered, works are more attractive to sync supervisors\n",
},
"set-recording-splits": {
name: "set-recording-splits",
description: "Guided master ownership split assignment on a recording — propose, dry-run preview, explicit confirmation, commit, then verify. Distinct from writer splits (which live as credits on a work). Splits flow into payments — accuracy beats throughput.",
triggers: ["set master splits", "set recording splits", "master ownership", "who owns this recording", "producer split", "split the masters"],
audience: "producer / artist / label / manager",
tools_required: ["pica_recording_splits_list", "pica_recording_splits_create", "pica_recording_splits_verify", "pica_recordings_query", "pica_people_query", "pica_collaborators_invite", "pica_split_sheet_generate", "pica_split_sheet_send"],
output: "Confirmed + verified recording_splits rows totalling 100%, with the option to generate and send a split sheet PDF for signatures.",
body: "# set-recording-splits\n\nHelp the user set master ownership splits on a recording. These are master-side royalty shares — distinct from publishing splits, which are credits on a work. Splits flow into payments, so the skill prioritises accuracy over speed: propose → dry-run → confirm → commit → verify.\n\n## Pre-flight\n\nRead `pica://schemas/recording-splits-required` before any write. The canonical shape is `recording_id`, `person_id`, `percentage`, `split_type`, `role`. **Active shares for one `split_type` + territory may not pass 100%, and a person holds at most one ACTIVE share there (an ended share is history: it neither counts nor blocks a new one)** — the database refuses anything else (`RECORDING_SPLIT_TOTAL_EXCEEDED` / `RECORDING_SPLIT_EXISTS`).\n\n## Step 1 — Pick the recording\n\nIf the user names a recording or gives an ID, use it. Otherwise, call `pica_recordings_query` and let the user pick from recent recordings.\n\n## Step 2 — Show current state\n\nCall `pica_recording_splits_list` for the recording. Three states:\n\n- **Empty** — no splits set yet. Proceed to step 3.\n- **Partial** — some splits exist but don't total 100%. Ask the user whether they want to add the missing shares.\n- **Complete** — splits total 100%. Ask whether the user wants to verify (mark agreed-upon) what's there.\n\n`pica_recording_splits_create` only adds. It refuses a second ACTIVE share for the same person with `RECORDING_SPLIT_EXISTS` (a person whose share has ended can be given a new one), and a share that would take the active total past 100% with `RECORDING_SPLIT_TOTAL_EXCEEDED`. When a recorded share is wrong — a holder-less \"unknown\" row, the wrong percentage or role — fix that row instead of adding around it: `pica_recording_splits_update` (recording_id + split_id + what changes; `person_id` relinks an unknown holder) or, if it should stop counting, `pica_recording_splits_end` (keeps the row as history). Confirm the change with the user first, as in step 5. If the result says `verification_cleared: true`, tell the user the holder's confirmation was cleared and they need to confirm again.\n\nAlways summarise the current state plainly: \"right now this recording has [N] splits totalling [X]%, with [A] holding [P]%...\"\n\n## Step 3 — Capture proposed splits\n\nFor each split row, capture:\n\n- **Who owns this share?** — `person_id` from `pica_people_query`. If the person isn't on PICA yet, offer `pica_collaborators_invite` to bring them in before writing the split.\n- **What percentage?** — together with the shares already recorded, at most 100% for that `split_type` + territory.\n- **What kind?** — `split_type` is one of `master`, `mechanical`, `performance`, `sync` (master ownership is `master`); `role` is one of `owner`, `performer`, `producer`, `engineer`, `mixer`, `masterer`, `label`, `other`.\n\nSum the percentages out loud as you go. If they're not totalling 100% when the user finishes describing them, stop and ask them to adjust before proceeding.\n\n## Step 4 — Dry-run preview\n\nCall `pica_recording_splits_create` with `dry_run: true` for each proposed row. It writes nothing and returns the row that would land, the shares already recorded (`existing_shares`, `active_total`) and `likely_refusal`. Surface that to the user.\n\n- **If `likely_refusal` is set, stop** and tell the user what it says — the write would be refused.\n- **If `existing_shares_checked` is false**, the preview could not read the recorded shares and predicts nothing — say so; do not present it as a clean preview.\n- Each dry run checks one row against what is already recorded, not against the other rows you are proposing — sum the proposed rows yourself. **If they would pass 100% with what is recorded, stop.** Do not proceed to commit.\n\n## Step 5 — Explicit confirmation\n\nSay something like:\n\n> \"I'm about to set [N] splits on this recording totalling 100%:\n> - [A] — [P]% ([type])\n> - [B] — [Q]% ([type])\n> Reply 'yes' to commit, or tell me what to change.\"\n\nWait for the user's explicit \"yes\" (or equivalent). Don't write on ambiguous signals.\n\n## Step 6 — Commit\n\nFor each split, call `pica_recording_splits_create` (this time without `dry_run`). Report each row back as it lands. If any write fails, stop the loop — don't partially commit.\n\n## Step 7 — Verify\n\nVerification marks a split as agreed-upon — a separate state from \"exists in the database.\" It records WHICH PERSON agreed, so it is the split holder's own act: `pica_recording_splits_verify` refuses an agent (`VERIFICATION_REQUIRES_HUMAN_SESSION`) and you cannot do it for them. Tell each holder where to do it: signed in, \"confirm my share\" under ownership splits on the recording's page, `/inspect/recordings/<recording_id>#ownership-splits`. If a holder is someone other than the user, `pica_notify_person` with the `recording_id` sends them a link to that page.\n\n## Step 8 — Offer next moves\n\n- \"Want me to generate a split sheet PDF for signatures?\" → `pica_split_sheet_generate`\n- \"Want me to send the split sheet to the parties?\" → `pica_split_sheet_send`\n- \"Want me to set splits on another recording?\"\n\n## What not to do\n\n- Don't write splits without an explicit \"yes\" from the user\n- Don't proceed if the totals don't equal 100% — re-prompt instead\n- Don't skip telling holders how to verify, and don't retry `pica_recording_splits_verify` after it refuses. Verification is a deliberate moment for the holder, not for you.\n- Don't speculate about typical splits by genre or scene — if the user doesn't know what % someone deserves, that's a business conversation outside this skill\n- Don't conflate with writer splits — those are credits on a work, set via `pica_credits_update`. Different table, different semantics.\n\n## Follow-on skills\n\n- `close-the-loop` — recording splits are usually one gap among several on a work; close-the-loop fits the others\n- `register-my-works` — registered works pair with recordings that have clear ownership chains\n- `audit-credits` — splits health-check across the whole catalog\n",
},
"set-up-workspace": {
name: "set-up-workspace",
description: "Guide a new (or returning) user through PICA workspace setup — org profile, user identity (IPI/ISNI), privacy settings, storage configuration, billing, and team. Routes through 6 setup blocks in order of compound value, skipping the ones already done.",
triggers: ["set up my workspace", "configure my workspace", "what settings do I need", "I just signed up — what should I do first", "set my identifiers", "complete my onboarding", "finish setting up"],
audience: "new user / returning user reconfiguring / admin onboarding a team",
tools_required: ["pica_organisation_profile", "pica_user_profile", "pica_update_organisation_profile", "pica_update_my_identity", "pica_get_privacy_settings", "pica_storage_status", "pica_storage_configure_start", "pica_subscription_status", "pica_acknowledge_onboarding"],
output: "A 6-block setup walkthrough — each block returns \"already done\", \"missing\", or \"ready to do now\" with the specific tool call that completes it. Ends with a one-line summary of what's left and a call to pica_acknowledge_onboarding when the user is satisfied.",
body: "# set-up-workspace\n\nHelp the user get their workspace properly configured. This skill is for the moment right after signup, and for returning users who want to fill gaps they skipped. It is NOT for importing music — that's `import-my-catalog`. This skill is purely about **settings, identifiers, and infrastructure**.\n\nSetup is high-value but low-glamour. Every block has a concrete payoff:\n\n- **No org identifiers** → registrations and exports will be missing critical metadata\n- **No user IPI** → if you write songs, your PRO can't pay you what your catalog earns\n- **No storage configured** → uploads land on PICA's bucket; for BYOC orgs that's a billing surprise\n- **No team invited** → if you're managing a roster, every collaborator is doing duplicate work (team invites are managed by a human in /settings — see Block 5)\n\nPICA does NOT manage external service integrations (Gmail, Drive, Notion, etc.) — those live in the user's AI client (Claude Desktop, Cursor, ChatGPT). The cross-MCP composition workflow is a separate skill (`enrich-from-peer-mcps`) — surface it after setup if the user mentions they use other tools alongside PICA.\n\nThe skill walks 6 blocks in order of compound value. Each block has the same shape: **read current state → describe gap → offer the specific tool call**. Skip blocks where state is already complete.\n\n## Pre-flight\n\nCall `pica_organisation_profile` and `pica_user_profile` first. These two reads give you the orientation for everything that follows — what type of org this is, what role the user plays, what's already set.\n\nIf `pica_organisation_profile` indicates this org was created today (or the user's profile shows no identifiers), assume fresh-signup mode and go through all blocks in order. If the user says \"I want to update my settings\" assume returning-user mode and ask which block matters.\n\n## Block 1 — Org profile\n\nThe organisation's own metadata: legal name, country, business type (publisher / label / artist / management / sync agency / etc), contact, registered office.\n\nWhat to check from `pica_organisation_profile`:\n- Is `name` set to something other than the auto-generated default?\n- Is `country` set? (drives default territory on registrations and exports)\n- Is `business_type` set? (drives which tools are most relevant — e.g. publishers care more about IPI, labels care more about ISRC)\n- For publishers: is the publisher IPI set?\n- For labels: is the label proprietary number set?\n\nIf gaps, offer the specific update via `pica_update_organisation_profile`. Always show the user what you're about to change and ask before writing.\n\n## Block 2 — User identity (IPI / ISNI)\n\nThe connected user's own identifiers as a creator. This is where royalty leak happens — a songwriter without an IPI on their PICA profile will have works registered without the writer-side identifier, which means the PRO can't route royalties to them.\n\nWhat to check from `pica_user_profile`:\n- Is the user named correctly (legal name for registrations, plus any pseudonyms / stage names)\n- Is the user's IPI set?\n- Is the user's ISNI set?\n- Is the user's role/business posture set (writer / producer / artist / publisher rep / etc)\n\nIf missing identifiers and the user doesn't know their IPI:\n- For writers: it comes from their PRO (PRS, ASCAP, BMI, SACEM, etc) — they have it in their PRO portal\n- If they're not a PRO member yet, this block is also a flag to start that process (out of scope — but mention it)\n\nOffer the update via `pica_update_my_identity`. Treat IPI / ISNI as plain strings — the tool validates format.\n\n## Block 3 — Privacy & sharing defaults\n\nCall `pica_get_privacy_settings`. This controls what other PICA users see about the org's catalog by default. Common gotcha: the default is conservative — if the user expects their catalog to appear in PICA's public directory, this block is what turns it on.\n\nWhat to check:\n- Directory visibility — is the org opted into the public directory?\n- Sharing defaults — do new works inherit private or public defaults?\n- Email contact preferences — who can reach the user through PICA\n\nIf the user is a sync-pitch operation or wants their catalog discoverable, surface the directory opt-in clearly. If the user is a high-privacy operation (sale prep, M&A, working with sensitive sync briefs), reinforce the conservative default.\n\n## Block 4 — Storage configuration\n\nCall `pica_storage_status`. PICA supports BYOC storage (bring-your-own-cloud) — the user can wire their own S3/R2/GCS bucket so audio + multimedia live in infrastructure they control.\n\nThree states:\n- **Default (PICA-managed)** — fine for trial and small catalogs. Mention BYOC as an upgrade path for users with compliance needs or existing buckets.\n- **Configuring** — the user is partway through `pica_storage_configure_start` and hasn't completed credential setup. Offer to walk through the remaining steps.\n- **Connected** — confirmed working. Mention the disconnect tool exists if they need it.\n\nIf the user has compliance constraints, sensitive content, or a large existing audio library, call out BYOC as worth doing now (before upload). Cheaper to wire correctly than to migrate later.\n\n## Block 5 — Billing & team\n\nCall `pica_subscription_status`.\n\nBilling:\n- If `billing_state` is `trial` with >3 days remaining, no action needed\n- If trial is ending (≤3 days) or already ended, surface `pica_subscription_manage` to mint a checkout URL\n- If active, confirm the tier matches the user's expected usage\n\nTeam:\n- Team membership is human-only by design — there are no MCP tools for it. If the user is managing a roster, point them at the team section of https://withpica.com/settings to invite teammates and manage roles themselves\n- Distinct from `pica_collaborators_invite` which is for **external** collaborators on specific works (writers, producers) — team is for **PICA-account access**\n\n## Block 6 — Acknowledge & close out\n\nWhen the user is satisfied with setup (whether they completed every block or deliberately skipped some), call `pica_acknowledge_onboarding`. This dismisses the onboarding nudges in the UI so they don't keep getting reminded.\n\nThen summarise:\n- What was set this session (3-5 line bullet list)\n- What's intentionally left for later (e.g. \"you'll add your IPI once your PRO registration finalises\")\n- The natural next step — probably `import-my-catalog` if no catalog yet, or `catalog-audit` if catalog exists\n\n## What not to do\n\n- Don't run all 6 blocks in one giant message. Walk through them. Each block is a check + an offer; the user agrees or declines per block.\n- Don't change settings without showing the user what's about to change and asking confirmation\n- Don't push BYOC storage or paid tiers if the user hasn't asked — surface them, don't sell them\n- Don't speculate about which PRO the user should join — that's a business decision outside this skill\n- Don't try to set IPI/ISNI values you've guessed. If the user doesn't know, leave the field empty and explain where to look\n- Don't try to \"connect Gmail to PICA\" or similar — PICA doesn't manage peer-service integrations. The user wires Gmail/Drive/etc. into their AI client separately; PICA's role is to consume the resulting URIs during enrichment (see `enrich-from-peer-mcps`).\n\n## Follow-on skills\n\n- `import-my-catalog` — if the catalog is empty, this is the natural next move\n- `catalog-audit` — if there's already a catalog, audit it now that identifiers are in place\n- `register-my-works` — once identifiers are set, registration coverage tends to be the next thing the user wants to fix\n- `enrich-from-peer-mcps` (Stage 2) — if the user mentions they have other MCPs connected (Gmail, Drive, etc.), this is the cross-MCP workflow that consumes them\n",
},
"tag-my-songs": {
name: "tag-my-songs",
description: "Help the owner tag their listed songs with what they are about (topics from a fixed list) and how they sound (moods), so people searching the PICA directory by topic can find them. The owner approves every tag; nothing is public before that.",
triggers: ["tag my songs", "which of my songs need topics", "suggest topics for my songs", "help people find my songs in the directory", "what are my songs about"],
audience: "songwriter / artist / catalogue owner",
tools_required: ["pica_topics_untagged", "pica_works_inspect", "pica_recordings_inspect", "pica_topics_propose", "pica_topics_inspect", "pica_topics_review"],
output: "Topics (and moods) proposed for the owner's listed songs, then saved once the owner has approved each set.",
definition_of_done: "Every song the owner chose to tag has approved topics, or the owner decided to leave it untagged or switch topics off.",
when_not_to_use: "The user wants to search the directory for other people's songs (use the directory tools), or to list or hide a song in the directory.",
body: "# tag-my-songs\n\nYou are helping the owner describe their own songs. PICA does not tag songs itself: you read the\nowner's lyrics and audio facts and SUGGEST; the owner decides. Nothing you propose is public until\nthe owner approves it.\n\n## 1. Find the songs\n\nCall `pica_topics_untagged`. It lists the owner's songs that are listed in the directory and\nhave lyrics, but no approved topic. Say how many there are and offer to go through them a few at a\ntime. Never tag songs the owner did not ask about.\n\n## 2. Read, then suggest\n\nFor each song:\n\n- Read the lyrics with `pica_works_inspect`. Tag what the song is actually ABOUT, not words that\n appear once. A song that says \"love\" in passing but is about leaving home is about home and loss.\n- Choose up to five topics, most central first, ONLY from the fixed list:\n love, heartbreak, longing, desire, friendship, family, home, nostalgia, loss, loneliness, hope,\n faith, worship, gratitude, joy, celebration, freedom, empowerment, resilience, struggle,\n rebellion, identity, ambition, money, peace, nature, night, city, travel, summer.\n If nothing fits, propose none. Never invent a topic.\n- For moods, look at how each recording sounds: tempo, key and mode, energy (from\n `pica_recordings_inspect`). Choose from: aggressive, ambient, calm, contemplative, dark, dramatic,\n dreamy, energetic, epic, ethereal, hopeful, intense, melancholic, nostalgic, passionate, playful,\n romantic, sad, tender, tense, triumphant, uplifting, warm. Mood describes the sound; topics\n describe the words. A sad song can be about hope.\n- Save the suggestion with `pica_topics_propose`. It stays private.\n\n## 3. Ask, then save\n\nShow the owner each song's suggested topics and moods in one short line, with a one-line reason\n(\"about leaving home: the chorus returns to the house on the hill\"). Ask them to approve, change or\ndrop each one. Only then call `pica_topics_review`:\n\n- approve what they agreed (`approve`, or `approve_all` when they say \"all of them\");\n- `reject` what they turned down;\n- `set_themes` when they choose their own topics instead;\n- `approve_all_moods` or `approve_moods_for` for moods they agreed.\n\nNever approve on the owner's behalf, and never treat silence as a yes.\n\n## 4. Their controls\n\n- Topics can be switched off for any song (`themes_enabled: false`): it then shows no topics and\n does not appear in topic searches.\n- Lyrics stay private by default. The owner may choose to show a snippet or the full lyrics in the\n public directory (`lyrics_visibility`). Never suggest changing this unless they ask.\n\n## Say it plainly\n\nTalk about \"topics\" and \"moods\", not \"themes\", \"tags\" or field names. Never quote more than a line\nof the lyrics back to the owner when explaining a suggestion.\n",
},
"who-can-see-my-catalogue": {
name: "who-can-see-my-catalogue",
description: "For a catalogue's owner — who looks after your catalogue in PICA, what each one can see and do, what they have done, and how to answer a request, change what someone can do, or end it. You decide every step; nothing is shared without you.",
triggers: ["who can see my catalogue", "who looks after my songs", "what can my manager see", "what has my publisher done", "someone asked to look after my catalogue", "remove my manager's access", "give my manager access"],
audience: "catalogue owners (artists, songwriters, rights holders)",
tools_required: ["pica_relationships_list", "pica_relationships_activity", "pica_relationships_answer", "pica_relationships_grant", "pica_relationships_revoke"],
output: "Every organisation that looks after the catalogue, in plain words — what it may do, what it covers, where it stands — and any step the owner chose, taken on the terms they read.",
definition_of_done: "The owner knows who can see their catalogue and what each can do, and every request they wanted answered, change they wanted made or access they wanted ended is done or waiting for their approval.",
when_not_to_use: "The person works for an organisation and asks about the clients it looks after — use look-after-clients.",
body: "# who-can-see-my-catalogue\n\nThe owner holds the record and decides who else may work on it. Organisations (a manager, a\npublisher, a label) can look after a catalogue only through a relationship the owner accepted,\nand only within it. Your job is to make that visible and to carry out the owner's decisions —\nnever to make them.\n\n## 1. Who, and what each can do\n\nCall `pica_relationships_list` (side \"owner\"). For each relationship, say in plain words:\n\n- **who** and **as what**: \"Rep & Co looks after your catalogue as administrator\";\n- **what that type can do**:\n - administrator: edits and registers your songs and sends exports for you; changes to splits\n or custody come to you to approve;\n - representative: sees and exports what's in scope and suggests changes; every change comes to\n you first;\n - viewer: sees and exports what's in scope, nothing else;\n - co-owner: sees the songs it has a share in;\n- **what it covers**, from `scope_text`: which songs, which side, where, until when, whether it\n sees statements and earnings;\n- **where it stands**, from `status_text`: waiting for your answer, waiting for theirs, active,\n paused by pica (never guess why: \"ask pica if you have questions\"), or ended.\n\nThen say whether anything is waiting for the owner: requests that need their answer, and\ninvitations by email in `waiting_for_you`. If the list says invitations couldn't be checked,\nsay exactly that — it doesn't mean there are none.\n\n## 2. What they have done\n\nWhen the owner asks what an organisation did, call `pica_relationships_activity` (org_id for one\norganisation, relationship_id for one relationship). Read the entries as they are written, newest\nfirst. Ended relationships keep their history.\n\n## 3. Taking a step — the owner's decision, on the terms they read\n\nBefore ANY step, read the owner the exact terms (type, scope, end date, money) and wait for a\nclear yes. Then pass the `version` you read as `expected_version`; if the terms changed in\nbetween, nothing happens and you get the new terms back: read those out and ask again.\n\n- **Answer a request**: `pica_relationships_answer` with action \"accept\" (it can narrow what was\n asked, never widen it), \"decline\" (with a reason, if they want), or \"edit\" to send different\n terms back. To accept an invitation by email, pass its `invite_id` and the organisation it is\n for.\n- **Give someone access**: `pica_relationships_grant` with their email, the type and the scope.\n An administrator sees statements unless the owner says otherwise; say so before sending.\n- **Change what someone can do**: `pica_relationships_answer` with action \"edit\" on the active\n relationship. It applies straight away.\n- **End it**: `pica_relationships_revoke`. It takes effect on their very next request and can't\n be undone; what they did stays in the history.\n\nHow the step happens depends on where you're running:\n\n- through a connected app, the owner is asked to approve it first (by email or in PICA): relay\n the message and check with `pica_approval_status`; nothing happens until they approve;\n- through PICA's own assistant, these steps are done on screen: give the owner the link you get\n back (`screen_url`).\n\nNever take a step the owner didn't ask for, and never present a step as done while it waits for\ntheir approval.\n",
},
};
export const SKILL_NAMES = ["audit-credits", "catalog-audit", "catalog-modelling", "clean-up-artists", "close-the-loop", "enrich-from-peer-mcps", "first-session", "import-my-catalog", "ingest-my-statements", "log-a-session", "log-a-show", "look-after-clients", "prepare-for-sync", "register-from-your-daw", "register-my-works", "set-recording-splits", "set-up-workspace", "tag-my-songs", "who-can-see-my-catalogue"];
//# sourceMappingURL=skills.generated.js.map