@withpica/mcp-sdk 1.47.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -11,6 +11,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [2.0.0] - 2026-06-26
15
+
16
+ ### Removed
17
+
18
+ - **BREAKING — `Work` read interface:** removed legacy scalar society fields
19
+ `prs_registered`, `ppl_registered`, and `mlc_song_code` (ADR-278, society-agnostic
20
+ read shape). Replaced by `society_registrations` (see Added).
21
+
22
+ ### Added
23
+
24
+ - **`society_registrations?: SocietyRegistration[]`** on the `Work` and `Recording`
25
+ read interfaces — an array of `{ society_code, registered, external_id }` entries,
26
+ one per society (any PRO/NRO/CMO, any territory). Replaces the removed `Work`
27
+ scalars; `Recording` had no legacy society fields to remove.
28
+ - **New shared type `SocietyRegistration`** exported from the package root.
29
+
30
+ ### Changed
31
+
32
+ - Write-input field names (`prs_work_id`, `mlc_recording_id`, `ppl_recording_id`,
33
+ `prs_number`, `ppl_number`, `mcps_member_number`) are **unchanged** — this is a
34
+ read-type breaking change only.
35
+
36
+ ## [1.48.0] - 2026-06-25
37
+
38
+ ### Added
39
+
40
+ - **`resolveRelease(id, body)`** → `POST /admin/releases/:id/resolve`, plus the
41
+ `ResolveReleaseResult` type. Backs `pica_resolve_release` (release-grain
42
+ Spotify gap-fill enrichment through the authority gate).
43
+ - **`CatalogHealthResource`** — `catalogHealth()` (`GET /admin/catalog-health`,
44
+ whole-catalog completeness + cleanliness verdict), `catalogHealthPlan(body)`
45
+ (derives an actionable fix-plan + `planToken`), and `catalogHealthFix(body)`
46
+ (applies accepted `actionIds` / `all_safe_auto`, returning honest
47
+ `applied` / `skipped`). Plus the `CatalogHealth*` result types. Back
48
+ `pica_catalog_health` / `_plan` / `_fix` (ADR-272 / ADR-273).
49
+ - **`DocumentsResource`** — `listCatalog(params)`, `read(id, params)` (bounded
50
+ content read), and `link(id, entity_type, entity_id)` (provenance link to a
51
+ work / person / recording). Backs the ADR-274 document bridge
52
+ (`pica_documents_list` / `_read` / `_link`).
53
+
14
54
  ## [1.47.0] - 2026-06-22
15
55
 
16
56
  ### Added
package/dist/index.d.ts CHANGED
@@ -92,6 +92,42 @@ export interface ResolveRecordingResult {
92
92
  skipped_lower_authority: SkippedAuthorityReceipt[];
93
93
  recovery_hints: string[];
94
94
  }
95
+ /**
96
+ * Release resolver result. Mirrors the server-side `ResolveReleaseResult`
97
+ * in the resolver service. Duplicated here — no type-sharing mechanism with
98
+ * the PICA monorepo; drift is caught by the holdout suite.
99
+ */
100
+ export interface ResolveReleaseResult {
101
+ entity_type: "release";
102
+ entity_id: string;
103
+ /** v1 is Spotify-only; field narrowed to reflect the single eligible source. */
104
+ sources_run: Array<"spotify">;
105
+ applied: Array<{
106
+ source: "spotify";
107
+ rule_id: string;
108
+ fields: string[];
109
+ target_entity_type: "release";
110
+ target_entity_id: string;
111
+ }>;
112
+ proposals: Array<{
113
+ proposal_id: string;
114
+ source: "spotify";
115
+ rule_id: string;
116
+ confidence: number | null;
117
+ field_count: number;
118
+ signals: Record<string, unknown> | null;
119
+ }>;
120
+ errors: Array<{
121
+ source: "spotify";
122
+ rule_id?: string;
123
+ error_code: string;
124
+ retry_after_ms?: number;
125
+ message?: string;
126
+ }>;
127
+ overwrote: OverwriteReceipt[];
128
+ skipped_lower_authority: SkippedAuthorityReceipt[];
129
+ recovery_hints: string[];
130
+ }
95
131
  /**
96
132
  * ADR-179 Phase 2 person resolver result. Mirrors the server-side
97
133
  * `ResolvePersonResult` in `lib/services/enrichment-cascade/resolver.ts`.
@@ -224,6 +260,16 @@ interface PaginatedResult<T> {
224
260
  total: number;
225
261
  hasMore: boolean;
226
262
  }
263
+ /**
264
+ * Society registration record returned on work and recording read results
265
+ * (ADR-278: society-agnostic shape — replaces legacy prs_registered /
266
+ * ppl_registered / mlc_song_code scalar fields on Work).
267
+ */
268
+ export interface SocietyRegistration {
269
+ society_code: string;
270
+ registered: boolean;
271
+ external_id: string | null;
272
+ }
227
273
  interface Work {
228
274
  id: string;
229
275
  title: string;
@@ -246,11 +292,9 @@ interface Work {
246
292
  youtube_view_count?: number;
247
293
  spotify_popularity?: number;
248
294
  spotify_streams?: number;
249
- prs_registered?: boolean;
250
- ppl_registered?: boolean;
251
295
  published?: boolean;
252
296
  is_featured?: boolean;
253
- mlc_song_code?: string;
297
+ society_registrations?: SocietyRegistration[];
254
298
  completeness_score?: number | null;
255
299
  ai_disclosure?: Record<string, unknown>;
256
300
  provenance_attestation?: Record<string, unknown>;
@@ -278,6 +322,8 @@ interface Recording {
278
322
  isrc?: string;
279
323
  duration_seconds?: number;
280
324
  work_id?: string;
325
+ notes?: string | null;
326
+ society_registrations?: SocietyRegistration[];
281
327
  created_at: string;
282
328
  updated_at: string;
283
329
  }
@@ -951,9 +997,14 @@ declare class AudioFilesResource extends BaseResource {
951
997
  work_id?: string;
952
998
  file_type?: string;
953
999
  unprocessed?: boolean;
1000
+ unassigned?: boolean;
954
1001
  limit?: number;
955
1002
  }): Promise<AudioFile[]>;
956
1003
  get(id: string): Promise<AudioFile>;
1004
+ update(id: string, body: {
1005
+ work_id?: string | null;
1006
+ recording_id?: string | null;
1007
+ }): Promise<AudioFile>;
957
1008
  analyze(id: string, options?: {
958
1009
  forceReAnalyze?: boolean;
959
1010
  enableAudio?: boolean;
@@ -1009,10 +1060,7 @@ declare class MultimediaResource extends BaseResource {
1009
1060
  person_id?: string;
1010
1061
  limit?: number;
1011
1062
  offset?: number;
1012
- }): Promise<{
1013
- data: MultimediaItem[];
1014
- count: number;
1015
- }>;
1063
+ }): Promise<PaginatedResult<MultimediaItem>>;
1016
1064
  create(data: Partial<MultimediaItem>): Promise<MultimediaItem>;
1017
1065
  importFromUrl(params: {
1018
1066
  url: string;
@@ -1305,6 +1353,22 @@ declare class EnrichmentResource extends BaseResource {
1305
1353
  */
1306
1354
  force?: boolean;
1307
1355
  }): Promise<ResolveRecordingResult>;
1356
+ /**
1357
+ * Resolve a release against every eligible enrichment source.
1358
+ * v1 is Spotify-only — a release resolve always re-checks Spotify and
1359
+ * gap-fills empty fields via the authority gate (no idempotence stamps
1360
+ * exist for releases). `force` is accepted for API parity but has no
1361
+ * distinct effect here.
1362
+ *
1363
+ * @param releaseId UUID of the release to resolve.
1364
+ * @param options
1365
+ * sources: optional whitelist. v1 supports `spotify` only.
1366
+ * force: accepted for parity; no distinct effect for releases.
1367
+ */
1368
+ resolveRelease(releaseId: string, options?: {
1369
+ sources?: Array<"spotify">;
1370
+ force?: boolean;
1371
+ }): Promise<ResolveReleaseResult>;
1308
1372
  /**
1309
1373
  * ADR-164: manually re-evaluate a work against every cascade rule.
1310
1374
  * Idempotent — rules whose preconditions are already satisfied skip.
@@ -1443,10 +1507,118 @@ declare class RegistrationResource extends BaseResource {
1443
1507
  getCoverage(): Promise<any>;
1444
1508
  getWorkCascadeStatus(workId: string): Promise<any>;
1445
1509
  }
1510
+ export interface CatalogHealthItem {
1511
+ grain: "work" | "recording" | "release" | "person";
1512
+ issue: string;
1513
+ dimension: "completeness" | "cleanliness";
1514
+ severity: "high" | "medium" | "low";
1515
+ count: number;
1516
+ sampleIds: string[];
1517
+ truncated: boolean;
1518
+ needsScope: string | null;
1519
+ actionableByCaller: boolean;
1520
+ }
1521
+ export interface CatalogHealthVerdict {
1522
+ score: number | null;
1523
+ dimensionScores: {
1524
+ completeness: number | null;
1525
+ cleanliness: number | null;
1526
+ };
1527
+ assessed: string[];
1528
+ notAssessed: string[];
1529
+ items: CatalogHealthItem[];
1530
+ generatedAt: string;
1531
+ }
1532
+ export interface CatalogHealthPlanAction {
1533
+ actionId: string;
1534
+ issue: string;
1535
+ actionKind: string;
1536
+ disposition: "auto" | "propose";
1537
+ destructive: boolean;
1538
+ needsScope: string;
1539
+ actionableByCaller: boolean;
1540
+ entityRefs: {
1541
+ type: string;
1542
+ id: string;
1543
+ }[];
1544
+ preview: Record<string, unknown>;
1545
+ }
1546
+ export interface CatalogHealthResidualItem {
1547
+ issue: string;
1548
+ count: number;
1549
+ reason: string;
1550
+ next_tool?: string;
1551
+ }
1552
+ export interface CatalogHealthPlan {
1553
+ score: number | null;
1554
+ dimensionScores: {
1555
+ completeness: number | null;
1556
+ cleanliness: number | null;
1557
+ };
1558
+ targetScore: number;
1559
+ actions: CatalogHealthPlanAction[];
1560
+ residual: CatalogHealthResidualItem[];
1561
+ planToken: string;
1562
+ generatedAt: string;
1563
+ }
1564
+ export interface CatalogHealthAppliedResult {
1565
+ actionId: string;
1566
+ met: true;
1567
+ summary: string;
1568
+ }
1569
+ export interface CatalogHealthSkippedResult {
1570
+ actionId: string;
1571
+ met: false;
1572
+ reason: "scope_denied" | "guard_blocked" | "stale" | "not_accepted";
1573
+ }
1574
+ export interface CatalogHealthFixResult {
1575
+ applied: CatalogHealthAppliedResult[];
1576
+ skipped: CatalogHealthSkippedResult[];
1577
+ verdict: unknown;
1578
+ outcomesRecorded: number;
1579
+ }
1446
1580
  declare class HealthResource extends BaseResource {
1447
1581
  getWorksHealth(): Promise<any>;
1448
1582
  getLowScoreWorks(): Promise<any>;
1449
1583
  getWorkCompleteness(workId: string): Promise<any>;
1584
+ /**
1585
+ * ADR-277 WS2 — opt-in per-field provenance for a work: one entry per
1586
+ * non-null field with its stakes tier + attestation / corroboration flags.
1587
+ * Pure derivation server-side; backs the `field_provenance` inspect section.
1588
+ */
1589
+ fieldProvenanceWork(workId: string): Promise<any>;
1590
+ /**
1591
+ * ADR-277 WS2 — opt-in per-field provenance for a recording (see
1592
+ * fieldProvenanceWork). Backs the recording `field_provenance` inspect section.
1593
+ */
1594
+ fieldProvenanceRecording(recordingId: string): Promise<any>;
1595
+ /**
1596
+ * ADR-272 — org-scoped catalog health verdict (completeness + cleanliness
1597
+ * with a ranked punch-list). The route returns `{ success, data: verdict }`;
1598
+ * BaseResource.request unwraps the `{ success, data }` envelope via
1599
+ * `data.data || data`, so this resolves to the verdict object directly
1600
+ * (NOT a second `.data` — the recurring double-unwrap trap). Typed against
1601
+ * the UNWRAPPED shape.
1602
+ */
1603
+ catalogHealth(): Promise<CatalogHealthVerdict>;
1604
+ /**
1605
+ * ADR-273 — scope-gated fix plan. POSTs to /admin/catalog-health/plan,
1606
+ * returns a CatalogHealthPlan with actionable fix-actions + planToken.
1607
+ * Mutates nothing.
1608
+ */
1609
+ catalogHealthPlan(body: {
1610
+ targetScore?: number;
1611
+ only?: string[];
1612
+ }): Promise<CatalogHealthPlan>;
1613
+ /**
1614
+ * ADR-273 — apply accepted fix actions from a prior plan. Requires planToken
1615
+ * from catalogHealthPlan; accept is a list of actionIds (or "all_safe_auto").
1616
+ * Returns honest per-action met/unmet plus a fresh verdict.
1617
+ */
1618
+ catalogHealthFix(body: {
1619
+ planToken: string;
1620
+ accept: string[];
1621
+ }): Promise<CatalogHealthFixResult>;
1450
1622
  }
1451
1623
  declare class DashboardResource extends BaseResource {
1452
1624
  discoveries(params?: {
@@ -2148,6 +2320,13 @@ declare class ExportResource extends BaseResource {
2148
2320
  }): Promise<any>;
2149
2321
  industryReady(params?: {
2150
2322
  work_ids?: string[];
2323
+ /**
2324
+ * "zip" (default) returns a signed-URL JSON envelope to the generated ZIP
2325
+ * on S3. "json" returns the structured export data inline — reachable by
2326
+ * sandboxed agents whose allowlist excludes the S3 host (ops_issue
2327
+ * 8662c489).
2328
+ */
2329
+ format?: "zip" | "json";
2151
2330
  }): Promise<any>;
2152
2331
  catalogAssetReport(params: {
2153
2332
  sections: {
@@ -2503,6 +2682,20 @@ declare class ImportResource extends BaseResource {
2503
2682
  }
2504
2683
  declare class DocumentsResource extends BaseResource {
2505
2684
  analyse(id: string): Promise<Record<string, unknown>>;
2685
+ listCatalog(params?: {
2686
+ parsed_status?: string;
2687
+ limit?: number;
2688
+ offset?: number;
2689
+ }): Promise<{
2690
+ documents: unknown[];
2691
+ total: number;
2692
+ has_more: boolean;
2693
+ }>;
2694
+ read(id: string, params?: {
2695
+ offset?: number;
2696
+ max_chars?: number;
2697
+ }): Promise<Record<string, unknown>>;
2698
+ link(id: string, entity_type: string, entity_id: string): Promise<unknown>;
2506
2699
  }
2507
2700
  interface CollaboratorInvite {
2508
2701
  id: string;
@@ -3353,6 +3546,17 @@ declare class StatementsResource extends BaseResource {
3353
3546
  sort?: string;
3354
3547
  }): Promise<any>;
3355
3548
  get(batchId: string): Promise<any>;
3549
+ listPending(q?: {
3550
+ limit?: number;
3551
+ offset?: number;
3552
+ parsed_status?: string;
3553
+ }): Promise<Record<string, unknown>>;
3554
+ ingestDocument(payload: {
3555
+ document_id: string;
3556
+ source: string;
3557
+ statement_period?: string;
3558
+ rows: unknown[];
3559
+ }): Promise<Record<string, unknown>>;
3356
3560
  }
3357
3561
  declare class ShareLinksResource extends BaseResource {
3358
3562
  list(params?: {