@withpica/mcp-sdk 3.5.0 → 3.7.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,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [3.7.0] - 2026-07-12
15
+
16
+ ### Added
17
+
18
+ - **`WorksResource.dossier(workId)`** — fetches the full song dossier for one
19
+ work (`GET /admin/works/[id]/dossier?format=json`): work, recordings,
20
+ releases, composition credits, people, provenance, AI disclosure, and
21
+ consent, assembled server-side by `assembleSongDossier`. Backs the new
22
+ `dossier` section of `pica_works_inspect`. JSON only in the SDK; the PDF
23
+ export stays on the web UI. `request()` unwraps the `{ success, data }`
24
+ envelope to the dossier itself.
25
+
26
+ ## [3.6.0] - 2026-07-09
27
+
28
+ ### Added
29
+
30
+ - `SocietyAffiliation` gains `affiliation_kind?: "member" | "origin"` and
31
+ `Person` gains `origin_countries?: string[]` (ADR-292), mirroring the same
32
+ fields on the `pica_people_create` / `pica_people_update` write surface.
33
+
34
+ - **`IntegrityResource`** (`client.integrity`) — the SDK surface for the
35
+ registration integrity floor (PR #1595): `assessEntity` (work/recording/
36
+ release grains; release is a documented v1 no-op), `assessOrg`, and the
37
+ `waive` / `revokeWaiver` write pair backing `pica_integrity_waive`.
38
+
39
+ - **`requestWithEnvelope()`** on `BaseResource` — like `request()` but
40
+ returns the FULL parsed `{data, twin?, twin_error?}` envelope instead of
41
+ narrowing to `.data`. `WorksResource.create` / `RecordingsResource.create`
42
+ now use it, so the auto-twin routes' `twin`/`twin_error` sibling fields
43
+ reach callers — `Work`/`Recording` create responses carry `twin` and
44
+ `twin_error` merged onto the returned entity (commit 689298e3c).
45
+
14
46
  ## [3.5.0] - 2026-07-07
15
47
 
16
48
  ### Added
package/dist/index.d.ts CHANGED
@@ -277,6 +277,8 @@ export interface SocietyRegistration {
277
277
  export interface SocietyAffiliation {
278
278
  society_code: string;
279
279
  membership_number: string | null;
280
+ /** ADR-292: `member` (current, default) or `origin` (home-country society for that code). */
281
+ affiliation_kind?: "member" | "origin";
280
282
  }
281
283
  interface Work {
282
284
  id: string;
@@ -314,6 +316,11 @@ interface Work {
314
316
  licensing_notes?: string | null;
315
317
  created_at: string;
316
318
  updated_at: string;
319
+ twin?: {
320
+ id: string;
321
+ recording_title: string;
322
+ } | null;
323
+ twin_error?: string;
317
324
  }
318
325
  interface Person {
319
326
  id: string;
@@ -331,6 +338,8 @@ interface Person {
331
338
  outreach_state?: "ready" | "needs_email" | "needs_disambiguation" | "not_a_target" | "do_not_contact" | "previously_declined";
332
339
  /** Society affiliations (ADR-282: society-agnostic write shape). */
333
340
  society_affiliations?: SocietyAffiliation[];
341
+ /** ADR-292: heritage/origin countries (ISO 3166-1 alpha-2, text[] column on public.people). */
342
+ origin_countries?: string[];
334
343
  created_at: string;
335
344
  updated_at: string;
336
345
  }
@@ -344,6 +353,11 @@ interface Recording {
344
353
  society_registrations?: SocietyRegistration[];
345
354
  created_at: string;
346
355
  updated_at: string;
356
+ twin?: {
357
+ id: string;
358
+ title: string;
359
+ } | null;
360
+ twin_error?: string;
347
361
  }
348
362
  interface ProductionAssetLink {
349
363
  asset_id: string;
@@ -807,6 +821,19 @@ declare class BaseResource {
807
821
  private fetchWithTimeout;
808
822
  private fetchWithRetry;
809
823
  protected request<T>(method: string, path: string, body?: any): Promise<T>;
824
+ /**
825
+ * Like `request`, but returns the FULL parsed envelope instead of
826
+ * narrowing to `.data`. Needed by the two spreadsheet-moment auto-twin
827
+ * routes (`POST /admin/works`, `POST /admin/recordings`), whose response
828
+ * carries `twin`/`twin_error` as siblings of `data` — `request()`'s
829
+ * `return data.data || data` would otherwise silently drop them before
830
+ * the MCP tool ever sees a twin was created.
831
+ */
832
+ protected requestWithEnvelope<T>(method: string, path: string, body?: any): Promise<{
833
+ data: T;
834
+ twin?: unknown;
835
+ twin_error?: string;
836
+ }>;
810
837
  /**
811
838
  * Make a request whose SUCCESS body is raw text, not a JSON envelope —
812
839
  * for routes that stream a generated file (e.g. `text/csv`) rather than
@@ -890,7 +917,9 @@ declare class WorksResource extends BaseResource {
890
917
  has_publisher?: boolean;
891
918
  }): Promise<PaginatedResult<Work>>;
892
919
  get(id: string): Promise<Work>;
893
- create(data: Partial<Work>): Promise<Work>;
920
+ create(data: Partial<Work> & {
921
+ create_twin?: boolean;
922
+ }): Promise<Work>;
894
923
  update(id: string, updates: Partial<Work>): Promise<Work>;
895
924
  delete(id: string): Promise<DeletionResult>;
896
925
  verify(id: string): Promise<Work>;
@@ -912,6 +941,50 @@ declare class WorksResource extends BaseResource {
912
941
  track_number: number;
913
942
  disc_number: number | null;
914
943
  }>>;
944
+ /**
945
+ * Assemble the full song dossier for one work — everything PICA holds about
946
+ * a song in one call (work, recordings, releases, composition credits,
947
+ * people, provenance, AI disclosure, consent). Backs the `dossier` section
948
+ * of pica_works_inspect. JSON format only here; the PDF export lives on the
949
+ * web UI (`GET /admin/works/[id]/dossier?format=pdf`).
950
+ *
951
+ * `request()` unwraps the `{ success, data }` envelope to the dossier itself.
952
+ */
953
+ dossier(workId: string): Promise<{
954
+ schemaVersion: number;
955
+ generatedAt: string;
956
+ work: {
957
+ id: string;
958
+ title: string;
959
+ workType: string | null;
960
+ status: string | null;
961
+ iswc: string | null;
962
+ completenessScore: number | null;
963
+ [k: string]: unknown;
964
+ };
965
+ recordings: unknown[];
966
+ releases: unknown[];
967
+ compositionCredits: unknown[];
968
+ people: unknown[];
969
+ provenance: {
970
+ attestationStatus: string | null;
971
+ hasProvenanceCertificate: boolean;
972
+ certificateId: string | null;
973
+ [k: string]: unknown;
974
+ };
975
+ aiDisclosure: {
976
+ disclosed: boolean;
977
+ [k: string]: unknown;
978
+ };
979
+ consent: {
980
+ workEffective: {
981
+ state: string;
982
+ level?: string;
983
+ };
984
+ [k: string]: unknown;
985
+ };
986
+ [k: string]: unknown;
987
+ }>;
915
988
  /**
916
989
  * Stamp a human-creation provenance attestation. Complement to the
917
990
  * AI-disclosure side — captures who signed, when, the attestation
@@ -1177,6 +1250,79 @@ declare class CreditsBalanceResource extends BaseResource {
1177
1250
  declare class PicaScoreResource extends BaseResource {
1178
1251
  get(): Promise<PicaScore>;
1179
1252
  }
1253
+ /**
1254
+ * Registration Integrity Floor (spec 2026-07-09, Task 8). SDK-local types —
1255
+ * duplicated field-for-field from `lib/services/integrity-floor.ts`'s
1256
+ * exported shapes (the SDK does not import from `lib/`, mcp<->lib
1257
+ * isolation). Keep in sync by hand if the service's exported types change.
1258
+ */
1259
+ export type IntegrityGapCode = "WORK_NO_RECORDING" | "RECORDING_NO_WORK" | "RECORDING_NO_RELEASE" | "WORK_NO_WRITER" | "RECORDING_NO_OWNER" | "COLLABORATOR_NOT_INVITED" | "COLLABORATOR_NOT_ATTESTED";
1260
+ export type IntegrityEntityType = "work" | "recording" | "release" | "person";
1261
+ export interface AttestationProposal {
1262
+ kind: "send_attestation_invites";
1263
+ people: Array<{
1264
+ person_id: string;
1265
+ name: string;
1266
+ has_email: boolean;
1267
+ }>;
1268
+ tool: "pica_collaborators_invite_bulk";
1269
+ note: string;
1270
+ }
1271
+ export interface IntegrityGap {
1272
+ code: IntegrityGapCode;
1273
+ entity: {
1274
+ type: IntegrityEntityType;
1275
+ id: string;
1276
+ label: string;
1277
+ };
1278
+ severity: "critical" | "important";
1279
+ label: string;
1280
+ action_hint: string;
1281
+ proposed_action?: AttestationProposal;
1282
+ waivable: true;
1283
+ }
1284
+ export interface EntityAssessment {
1285
+ entity: {
1286
+ type: IntegrityEntityType;
1287
+ id: string;
1288
+ };
1289
+ gaps: IntegrityGap[];
1290
+ waived_count: number;
1291
+ }
1292
+ export interface OrgIntegritySummary {
1293
+ total_gaps: number;
1294
+ critical_gaps: number;
1295
+ waived_gaps: number;
1296
+ top_gaps: IntegrityGap[];
1297
+ attestation_pending: number;
1298
+ is_empty_catalog: boolean;
1299
+ }
1300
+ declare class IntegrityResource extends BaseResource {
1301
+ /**
1302
+ * GET /admin/integrity/assess?entity_type=&entity_id= -> single-entity assessment.
1303
+ * NOTE: for entity_type "release" this is a documented v1 no-op — no
1304
+ * release-grain gap code exists yet, so `gaps` is always empty by design
1305
+ * (see assessEntity's release branch in lib/services/integrity-floor.ts).
1306
+ */
1307
+ assessEntity(entityType: "work" | "recording" | "release", entityId: string): Promise<EntityAssessment>;
1308
+ /** GET /admin/integrity/assess (no params) -> org-grain summary. */
1309
+ assessOrg(): Promise<OrgIntegritySummary>;
1310
+ /**
1311
+ * POST /admin/integrity/waivers. Duplicate-active-waiver is a 409
1312
+ * (`ConflictError` on the app side) — surfaces here as a non-retryable
1313
+ * `ApiError` with `status === 409` (see `BaseResource.request`).
1314
+ */
1315
+ waive(input: {
1316
+ gap_code: string;
1317
+ entity_type: string;
1318
+ entity_id: string;
1319
+ reason: string;
1320
+ }): Promise<{
1321
+ id: string;
1322
+ }>;
1323
+ /** PATCH /admin/integrity/waivers { waiver_id, revoke: true }. No un-revoke path. */
1324
+ revokeWaiver(waiverId: string): Promise<void>;
1325
+ }
1180
1326
  interface PresignedUploadResult {
1181
1327
  uploadUrl: string;
1182
1328
  uploadId: string;
@@ -1564,7 +1710,9 @@ declare class RecordingsResource extends BaseResource {
1564
1710
  created_to?: string;
1565
1711
  }): Promise<PaginatedResult<Recording>>;
1566
1712
  get(id: string): Promise<Recording>;
1567
- create(data: Partial<Recording>): Promise<Recording>;
1713
+ create(data: Partial<Recording> & {
1714
+ create_twin?: boolean;
1715
+ }): Promise<Recording>;
1568
1716
  update(id: string, updates: Partial<Recording>): Promise<Recording>;
1569
1717
  delete(id: string): Promise<DeletionResult>;
1570
1718
  getByWork(workId: string): Promise<Recording[]>;
@@ -4275,6 +4423,7 @@ export declare class PicaClient {
4275
4423
  shareSend: ShareSendResource;
4276
4424
  accessSimulate: AccessSimulateResource;
4277
4425
  approvals: ApprovalsResource;
4426
+ integrity: IntegrityResource;
4278
4427
  /**
4279
4428
  * Get accurate catalog stats via SQL counts (no pagination limits)
4280
4429
  */