@withpica/mcp-sdk 1.4.0 → 1.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 ADDED
@@ -0,0 +1,237 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@withpica/mcp-sdk` will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ > **Rule of the road:** every version bump to this package MUST land with a
9
+ > matching entry here in the same commit. See the project's "npm publish
10
+ > discipline" memory entry for the enforcement rationale.
11
+
12
+ ## [Unreleased]
13
+
14
+ ## [1.7.0] - 2026-04-18
15
+
16
+ ### Fixed
17
+
18
+ - **ADR-179 Phase 3 SDK gap: `EnrichmentResource.resolveRecording` method
19
+ added.** The type `ResolveRecordingResult` shipped with commit
20
+ `63d97dd28` but the method itself was missing — `mcp-server/` stdio
21
+ tool `pica_resolve_recording` called `this.pica.enrichment.resolveRecording(...)`
22
+ against a method that didn't exist, breaking sub-package typecheck and
23
+ runtime. Signature mirrors `resolveWork` / `resolvePerson`:
24
+ `resolveRecording(recordingId, { sources?, includeFuzzy? })`. Routes to
25
+ `POST /admin/recordings/{id}/resolve`.
26
+
27
+ ### Added
28
+
29
+ - **ADR-174 Phase 2 item 7 follow-up: `ProjectsResource.attachWork`.** New
30
+ SDK method wrapping `POST /admin/projects/{id}/works` — closes the
31
+ `work_ids` gap on `pica_projects_create` / `_update` where the admin
32
+ route silently dropped the field. Signature:
33
+ `attachWork(projectId, { work_id, project_day?, notes? })`. Backs the
34
+ new `pica_projects_attach_works` batch MCP tool (loops one SDK call
35
+ per item) in `@withpica/mcp-server`.
36
+
37
+ ### Changed
38
+
39
+ - **ADR-174 Phase 2 item 22: `PublishersResource.create` signature widened
40
+ to `Record<string, unknown>`.** Pre-slice the method was typed
41
+ `{ name: string; ipi?: string }` and returned 404 at runtime (the route
42
+ did not exist). With the new `POST /api/admin/publishers` route shipped
43
+ in the companion commit, the SDK now accepts the full audit-row-22
44
+ surface (name, ipi_number, legal_name, country, isni, publisher_type,
45
+ wikidata_id, parent_publisher_id, founded_date, headquarters). The
46
+ `ipi → ipi_number` rename is explicit at the route layer — callers
47
+ still passing `ipi` get a PHANTOM_FIELD error with a rename hint.
48
+
49
+ ### Added
50
+
51
+ - **ADR-179 Phase 1: `EnrichmentResource.resolveWork(workId, options?)`.**
52
+ Outcome-shaped resolver that fans a work out across every eligible
53
+ enrichment source in one call. Wraps the new `POST /admin/works/{id}/resolve`
54
+ endpoint. Accepts an optional `sources` whitelist (`mlc` | `spotify` |
55
+ `youtube` | `musicbrainz` | `discogs`) and `includeFuzzy` flag.
56
+ Returns `ResolveWorkResult` with `applied[]` (Tier A writes),
57
+ `proposals[]` (Tier B review queue rows), `errors[]` (per-source
58
+ failures with circuit-breaker retry hints), and `recovery_hints[]`.
59
+ `ResolveWorkResult` is exported from the SDK's public surface.
60
+ The five per-source `enrichWorkMlc` / `enrichWorkSpotify` /
61
+ `enrichWorkYouTube` / `enrichWorkMusicBrainz` / `enrichWorkDiscogs`
62
+ methods remain available this release but are deprecated at the MCP
63
+ tool layer; the next minor will remove them from the SDK.
64
+ - **ADR-179 Phase 2: `EnrichmentResource.resolvePerson(personId, options?)`.**
65
+ Outcome-shaped person resolver mirroring `resolveWork`. Wraps the new
66
+ `POST /admin/people/{id}/resolve` endpoint. Accepts an optional
67
+ `sources` whitelist (`isni` | `musicbrainz`) and `includeFuzzy` flag.
68
+ Returns `ResolvePersonResult` with the same applied/proposals/errors
69
+ shape. The legacy `PeopleResource.enrichFromISNI` /
70
+ `enrichFromMusicBrainz` methods remain available this release but
71
+ are deprecated at the MCP tool layer; the next minor will remove
72
+ them from the SDK.
73
+ - **ADR-179 Phase 3: `EnrichmentResource.resolveRecording(recordingId, options?)`.**
74
+ Outcome-shaped recording resolver mirroring `resolveWork` /
75
+ `resolvePerson`. Wraps the new `POST /admin/recordings/{id}/resolve`
76
+ endpoint. Accepts an optional `sources` whitelist (`spotify` |
77
+ `youtube` | `musicbrainz` | `discogs`) and `includeFuzzy` flag.
78
+ Returns `ResolveRecordingResult` with the same applied/proposals/
79
+ errors shape. First recording-side enrichment surface on the SDK.
80
+ MusicBrainz + Discogs adapters are stubs server-side for now —
81
+ they surface eligibility via `sources_run` but make no external
82
+ calls until their corresponding cascade rules ship.
83
+ - `/resolve` path added to `LONG_TIMEOUT_PATTERNS` so the fan-out (up
84
+ to five sequential external API calls) gets the 120s long-timeout
85
+ instead of the default 30s. Covers both the work and person resolver
86
+ routes.
87
+
88
+ ## [1.7.0] — 2026-04-16
89
+
90
+ ### Added
91
+
92
+ - **ADR-178: `EnrichmentResource.proposeAgentResearch(input)`.** New
93
+ SDK method wraps the `POST /admin/enrichment-proposals` route that
94
+ backs the `pica_enrichment_propose` MCP tool (stdio in
95
+ `@withpica/mcp-server@2.17.0`, HTTP in
96
+ `@withpica/mcp-server-business@1.5.0`). Input is snake_case through-
97
+ out (matches the REST route, matches the agent-facing tool schema —
98
+ no case-translation layer). Response on success is `{ proposal_id,
99
+ source: 'agent_research', rule_id: 'agent_research', status:
100
+ 'pending' }`. Five documented client-error shapes surface through
101
+ `ApiError`: `MISSING_SOURCE` (400), `MISSING_FIELDS` (400),
102
+ `INVALID_SOURCE_SHAPE` (400), `ENTITY_NOT_FOUND` (404),
103
+ `DUPLICATE_SUPPRESSED` (409). Consumers parse the error code from
104
+ the JSON response body inside the thrown `ApiError` — the MCP tool
105
+ layer lifts it into `structuredContent.code` so agents can reason
106
+ about failure shape without free-text parsing.
107
+
108
+ ## [1.6.0] — 2026-04-14
109
+
110
+ ### Added
111
+
112
+ - **ADR-173: release-track primitives on `ReleasesResource`.** Five new
113
+ methods back the ADR-173 MCP tools: `attachTrack`, `listTracks`,
114
+ `detachTrack`, `reorderTracks`, `attachRecordingWithWork`. Routes map
115
+ to new admin endpoints under `/admin/releases/[id]/tracks` (and
116
+ sub-paths `/reorder`, `/detach`, `/attach-recording-with-work`).
117
+ - **`WorksResource.listReleases` + `RecordingsResource.listReleases`.**
118
+ Back the new `releases` section on `pica_works_inspect` and
119
+ `pica_recordings_inspect` — each returns every release the entity
120
+ appears on with its track position.
121
+
122
+ ## [1.5.0] — 2026-04-14
123
+
124
+ ### Added
125
+
126
+ - **ADR-174 Phase 2: `LabelsResource`** — new read-only SDK resource for
127
+ resolving label names to `organisations.id` (used as
128
+ `releases.label_organization_id`). `pica.labels.list({ query?, limit? })`
129
+ returns an array of `LabelOrganisation` rows (organisations with
130
+ `org_type='label'`). Exports the `LabelOrganisation` type.
131
+
132
+ ## [1.4.0] — 2026-04-11
133
+
134
+ ### Added
135
+
136
+ - **ADR-166: YouTube import SDK methods** (`78da58344`)
137
+ - `ImportResource.youtubeLinkPreview(url)` — POSTs to
138
+ `/admin/import/youtube-link` with just `url`. Returns the preview
139
+ payload (items + classification + work match).
140
+ - `ImportResource.youtubeLinkImport(url, options)` — POSTs with
141
+ `confirm: true` plus optional `selectedVideoIds`, `targetWorkId`,
142
+ `overrideVersionType`. Returns the import result.
143
+ - **ADR-163: Tier B enrichment proposal review SDK methods** (`ff9cf265a`)
144
+ - `EnrichmentResource.listEnrichmentProposals(params)` — GETs
145
+ `/admin/enrichment-proposals` with filter query params (`entity_type`,
146
+ `entity_id`, `rule_id`, `source`, `limit`, `offset`). Returns the
147
+ page of pending proposals.
148
+ - `EnrichmentResource.applyEnrichmentProposal(id, options)` — POSTs to
149
+ `/admin/enrichment-proposals/:id/apply` with `{ force, resolution_note }`.
150
+ For update proposals, drift detection runs first; if the entity has
151
+ changed since the proposal was created, the response is
152
+ `{ status: 'drift_detected', conflicts }` and nothing is written —
153
+ pass `force: true` on retry after reviewing the conflicts. For
154
+ create proposals a uniqueness check runs and cannot be forced.
155
+ - `EnrichmentResource.rejectEnrichmentProposal(id, options)` — POSTs
156
+ to `/admin/enrichment-proposals/:id/reject` with `{ resolution_note }`.
157
+ Content-hash suppression permanently blocks re-proposal of the same
158
+ exact content.
159
+
160
+ ### Notes
161
+
162
+ - Two additive changes, no signature changes to existing methods. Minor
163
+ bump per semver.
164
+ - Consumer packages pin `"@withpica/mcp-sdk": "^1.0.0"`, so the caret
165
+ range picks up `1.4.0` automatically.
166
+ - Source additions landed earlier: YouTube methods in `78da58344`
167
+ (feat(adr-166): phase 4 — pica_import_youtube_link MCP tool + SDK
168
+ methods), Tier B proposal methods in `ff9cf265a` (feat(adr-163) phase
169
+ 3c+3d).
170
+ - Version bump carried in `ff97faa56` (feat(adr-163 phase 6): MCP HTTP
171
+ transport parity + version bumps). That commit shipped the bump
172
+ without its matching changelog entry — this is the follow-up commit
173
+ closing the discipline gap.
174
+
175
+ ## [1.3.0] — 2026-04-11
176
+
177
+ ### Added
178
+
179
+ - **ADR-164: cascade control + observability SDK methods.**
180
+ - `runWorkCascade(workId)` — manually re-evaluate a work against every
181
+ ADR-164 cascade rule. POSTs to `/admin/works/:id/cascade-run`. Agents
182
+ can retry enrichment after a fix without waiting for the daily sweep.
183
+ - `runPersonCascade(personId)` — same for people. POSTs to
184
+ `/admin/people/:id/cascade-run`.
185
+ - `getCascadeHealth()` — snapshot of the in-process cascade failure +
186
+ outcome counters. GETs `/admin/cascade-health` (org-auth twin of the
187
+ operator-only `/api/internal/cascade-health` endpoint that uses
188
+ `CRON_SECRET`).
189
+
190
+ ### Notes
191
+
192
+ - All three additions are backwards-compatible. Minor bump per semver.
193
+ - All `@withpica/*` consumer packages pin `"@withpica/mcp-sdk": "^1.0.0"`,
194
+ so a `1.3.0` caret range picks up automatically — no transitive bumps.
195
+ - Tagged in commit `edfbcb07b` (`chore(mcp-sdk): bump to 1.3.0`), which
196
+ also carried the matching `mcp-server@2.9.0` bump + rebuilt dist.
197
+ - Source additions landed earlier in `38901f281` (ADR-164 audit
198
+ follow-ups).
199
+
200
+ ## [1.2.0] — 2026-04-10
201
+
202
+ ### Changed
203
+
204
+ - Version bump carried in `7c4f5d24a` (`chore(adr-162): version bumps for
205
+ npm publish`) alongside the ADR-162 subscription-based billing rollout.
206
+ No user-visible SDK API changes — the bump reflects the coupled release
207
+ of all `@withpica/*` packages under the new billing contract.
208
+
209
+ ## [1.1.0] — 2026-04-08
210
+
211
+ ### Changed
212
+
213
+ - Carried in `91dd1c275` (`chore(adr-158c): version bumps for custody
214
+ tool release (Phase 6b)`). Releases the custody-claim / custody-respond
215
+ / custody-history tool surface via coupled bumps across the MCP package
216
+ set.
217
+
218
+ ## [1.0.0] — 2026-04-07
219
+
220
+ ### Added
221
+
222
+ - Initial public release. Package split out from the legacy monolithic
223
+ `mcp-server` in `e235aed40` (`feat(mcp): ADR-155 launch — publish 6
224
+ packages, lobby-mode connect copy`). Provides the shared `PicaClient`
225
+ class that every `@withpica/mcp-server-*` package consumes for REST
226
+ access to PICA.
227
+
228
+ > **Pre-changelog era:** before `1.0.0`, the SDK lived inline in
229
+ > `@withpica/mcp-server` source. Version history for that era is
230
+ > reconstructable via `git log --follow -- mcp-server-shared/mcp-sdk/`.
231
+
232
+ [Unreleased]: https://github.com/withpica/pica/compare/ff97faa56...HEAD
233
+ [1.4.0]: https://github.com/withpica/pica/compare/edfbcb07b...ff97faa56
234
+ [1.3.0]: https://github.com/withpica/pica/compare/7c4f5d24a...edfbcb07b
235
+ [1.2.0]: https://github.com/withpica/pica/compare/91dd1c275...7c4f5d24a
236
+ [1.1.0]: https://github.com/withpica/pica/compare/e235aed40...91dd1c275
237
+ [1.0.0]: https://github.com/withpica/pica/commit/e235aed40
package/dist/index.d.ts CHANGED
@@ -2,6 +2,107 @@
2
2
  * Lightweight PICA SDK client for MCP server
3
3
  * Uses the PICA API directly without external dependencies
4
4
  */
5
+ /**
6
+ * ADR-179 resolver result shape. Mirrors the server-side
7
+ * `ResolveWorkResult` in `lib/services/enrichment-cascade/resolver.ts`.
8
+ * Duplicated here because this package has no type-sharing mechanism
9
+ * with the PICA monorepo; drift is caught by the holdout suite.
10
+ */
11
+ export interface ResolveWorkResult {
12
+ entity_type: "work";
13
+ entity_id: string;
14
+ sources_run: Array<"mlc" | "spotify" | "youtube" | "musicbrainz" | "discogs">;
15
+ applied: Array<{
16
+ source: "mlc" | "spotify" | "youtube" | "musicbrainz" | "discogs";
17
+ rule_id: string;
18
+ fields: string[];
19
+ target_entity_type: "work";
20
+ target_entity_id: string;
21
+ }>;
22
+ proposals: Array<{
23
+ proposal_id: string;
24
+ source: "mlc" | "spotify" | "youtube" | "musicbrainz" | "discogs";
25
+ rule_id: string;
26
+ confidence: number | null;
27
+ field_count: number;
28
+ signals: Record<string, unknown> | null;
29
+ }>;
30
+ errors: Array<{
31
+ source: "mlc" | "spotify" | "youtube" | "musicbrainz" | "discogs";
32
+ rule_id?: string;
33
+ error_code: string;
34
+ retry_after_ms?: number;
35
+ message?: string;
36
+ }>;
37
+ recovery_hints: string[];
38
+ }
39
+ /**
40
+ * ADR-179 Phase 3 recording resolver result. Mirrors the server-side
41
+ * `ResolveRecordingResult` in `lib/services/enrichment-cascade/resolver.ts`.
42
+ */
43
+ export interface ResolveRecordingResult {
44
+ entity_type: "recording";
45
+ entity_id: string;
46
+ sources_run: Array<"spotify" | "youtube" | "musicbrainz" | "discogs">;
47
+ applied: Array<{
48
+ source: "spotify" | "youtube" | "musicbrainz" | "discogs";
49
+ rule_id: string;
50
+ fields: string[];
51
+ target_entity_type: "recording";
52
+ target_entity_id: string;
53
+ }>;
54
+ proposals: Array<{
55
+ proposal_id: string;
56
+ source: "spotify" | "youtube" | "musicbrainz" | "discogs";
57
+ rule_id: string;
58
+ confidence: number | null;
59
+ field_count: number;
60
+ signals: Record<string, unknown> | null;
61
+ }>;
62
+ errors: Array<{
63
+ source: "spotify" | "youtube" | "musicbrainz" | "discogs";
64
+ rule_id?: string;
65
+ error_code: string;
66
+ retry_after_ms?: number;
67
+ message?: string;
68
+ }>;
69
+ recovery_hints: string[];
70
+ }
71
+ /**
72
+ * ADR-179 Phase 2 person resolver result. Mirrors the server-side
73
+ * `ResolvePersonResult` in `lib/services/enrichment-cascade/resolver.ts`.
74
+ * Duplicated here for the same reason as `ResolveWorkResult` — this
75
+ * package has no type-sharing mechanism with the PICA monorepo; drift
76
+ * is caught by the holdout suite.
77
+ */
78
+ export interface ResolvePersonResult {
79
+ entity_type: "person";
80
+ entity_id: string;
81
+ sources_run: Array<"isni" | "musicbrainz">;
82
+ applied: Array<{
83
+ source: "isni" | "musicbrainz";
84
+ rule_id: string;
85
+ fields: string[];
86
+ target_entity_type: "person";
87
+ target_entity_id: string;
88
+ }>;
89
+ proposals: Array<{
90
+ proposal_id: string;
91
+ source: "isni" | "musicbrainz";
92
+ rule_id: string;
93
+ confidence: number | null;
94
+ field_count: number;
95
+ signals: Record<string, unknown> | null;
96
+ }>;
97
+ errors: Array<{
98
+ source: "isni" | "musicbrainz";
99
+ rule_id?: string;
100
+ error_code: string;
101
+ retry_after_ms?: number;
102
+ message?: string;
103
+ }>;
104
+ recovery_hints: string[];
105
+ }
5
106
  interface CatalogStats {
6
107
  works: {
7
108
  total: number;
@@ -298,6 +399,18 @@ declare class BaseResource {
298
399
  protected apiKey: string;
299
400
  protected debug: boolean;
300
401
  constructor(baseUrl: string, apiKey: string, debug: boolean);
402
+ /**
403
+ * Vercel Deployment Protection bypass header for preview self-fetches.
404
+ *
405
+ * When the SDK is used server-side on a Vercel preview (e.g. the MCP
406
+ * HTTP route calling back into its own admin resolve routes),
407
+ * Vercel's edge wraps the internal call in deployment protection and
408
+ * 401s before the request reaches the route handler. "Protection
409
+ * Bypass for Automation" auto-injects VERCEL_AUTOMATION_BYPASS_SECRET
410
+ * at runtime; forward it as the documented header so self-fetches
411
+ * reach the actual route. Empty outside Vercel — safe no-op.
412
+ */
413
+ private getBypassHeaders;
301
414
  private fetchWithTimeout;
302
415
  private fetchWithRetry;
303
416
  protected request<T>(method: string, path: string, body?: any): Promise<T>;
@@ -330,6 +443,16 @@ declare class WorksResource extends BaseResource {
330
443
  * from the work side. Withdrawn links are filtered server-side.
331
444
  */
332
445
  listProductionAssets(workId: string): Promise<ProductionAssetLink[]>;
446
+ /**
447
+ * ADR-173 Decision 2: list every release this work appears on, with
448
+ * its track position. Distinct from listProductionAssets — this is
449
+ * release-context, not physical-asset provenance.
450
+ */
451
+ listReleases(workId: string): Promise<Array<{
452
+ release: Record<string, any>;
453
+ track_number: number;
454
+ disc_number: number | null;
455
+ }>>;
333
456
  }
334
457
  declare class PeopleResource extends BaseResource {
335
458
  list(params?: {
@@ -612,6 +735,16 @@ declare class RecordingsResource extends BaseResource {
612
735
  * from the recording side. Withdrawn links are filtered server-side.
613
736
  */
614
737
  listProductionAssets(recordingId: string): Promise<ProductionAssetLink[]>;
738
+ /**
739
+ * ADR-173 Decision 2: list every release this recording appears on,
740
+ * with its track position. Backs the `releases` section on
741
+ * pica_recordings_inspect.
742
+ */
743
+ listReleases(recordingId: string): Promise<Array<{
744
+ release: Record<string, any>;
745
+ track_number: number;
746
+ disc_number: number | null;
747
+ }>>;
615
748
  }
616
749
  declare class EnrichmentResource extends BaseResource {
617
750
  enrichWork(workId: string): Promise<any>;
@@ -623,6 +756,63 @@ declare class EnrichmentResource extends BaseResource {
623
756
  enrichWorkDiscogs(workId: string): Promise<any>;
624
757
  enrichWorkSpotify(workId: string): Promise<any>;
625
758
  enrichWorkYouTube(workId: string): Promise<any>;
759
+ /**
760
+ * ADR-179 outcome resolver — fan a work out across every eligible
761
+ * enrichment source and return a structured receipt.
762
+ *
763
+ * The orchestration lives server-side (see
764
+ * `lib/services/enrichment-cascade/resolver.ts`); this SDK method is
765
+ * the thin wrapper the MCP tool layer calls. Future Tasks-primitive
766
+ * conversion (ADR-171) will turn the request into a Task so agents
767
+ * receive per-source status events as each provider resolves. Today
768
+ * the shape is the final receipt only — callers treat the object
769
+ * returned here as that single terminal event.
770
+ *
771
+ * sources: optional whitelist. Omit to fan out to every
772
+ * eligible source (mlc, spotify, youtube,
773
+ * musicbrainz, discogs).
774
+ * includeFuzzy: defaults true. When false, Tier B cascade rules
775
+ * (fuzzy matches that would file review proposals)
776
+ * are skipped entirely.
777
+ */
778
+ resolveWork(workId: string, options?: {
779
+ sources?: Array<"mlc" | "spotify" | "youtube" | "musicbrainz" | "discogs">;
780
+ includeFuzzy?: boolean;
781
+ }): Promise<ResolveWorkResult>;
782
+ /**
783
+ * ADR-179 Phase 2 — person resolver. Fans a person across the two
784
+ * eligible identity-graph sources (ISNI + MusicBrainz) and returns
785
+ * a structured receipt in the same shape as `resolveWork`. Replaces
786
+ * the legacy `PeopleResource.enrichFromISNI` / `enrichFromMusicBrainz`
787
+ * calls at the MCP tool layer — those SDK methods stay available this
788
+ * release but are deprecated via `pica_people_enrich_*` returning
789
+ * `TOOL_DEPRECATED`.
790
+ *
791
+ * sources: optional whitelist. Omit to run both sources.
792
+ * Allowed: `isni` | `musicbrainz`.
793
+ * includeFuzzy: defaults true. When false, Tier B cascade rules
794
+ * (fuzzy matches that would file review proposals)
795
+ * are skipped entirely.
796
+ */
797
+ resolvePerson(personId: string, options?: {
798
+ sources?: Array<"isni" | "musicbrainz">;
799
+ includeFuzzy?: boolean;
800
+ }): Promise<ResolvePersonResult>;
801
+ /**
802
+ * ADR-179 Phase 3 — recording resolver. Fans a recording across eligible
803
+ * master-side sources (Spotify, YouTube, MusicBrainz, Discogs) and returns
804
+ * a structured receipt in the same shape as `resolveWork` / `resolvePerson`.
805
+ *
806
+ * sources: optional whitelist. Omit to run every eligible source.
807
+ * Allowed: `spotify` | `youtube` | `musicbrainz` | `discogs`.
808
+ * includeFuzzy: defaults true. When false, Tier B cascade rules
809
+ * (fuzzy matches that would file review proposals)
810
+ * are skipped entirely.
811
+ */
812
+ resolveRecording(recordingId: string, options?: {
813
+ sources?: Array<"spotify" | "youtube" | "musicbrainz" | "discogs">;
814
+ includeFuzzy?: boolean;
815
+ }): Promise<ResolveRecordingResult>;
626
816
  /**
627
817
  * ADR-164: manually re-evaluate a work against every cascade rule.
628
818
  * Idempotent — rules whose preconditions are already satisfied skip.
@@ -675,6 +865,42 @@ declare class EnrichmentResource extends BaseResource {
675
865
  rejectEnrichmentProposal(proposalId: string, options?: {
676
866
  resolution_note?: string;
677
867
  }): Promise<any>;
868
+ /**
869
+ * ADR-178: File a proposal sourced from open-web agent research.
870
+ *
871
+ * Distinct from cascade-sourced proposals. Every `proposed_fields`
872
+ * key must appear in at least one `sources[].fields` array —
873
+ * unsourced claims return a 400 with `code: "MISSING_SOURCE"` and
874
+ * the proposal is not persisted. The server hard-codes
875
+ * `source = 'agent_research'` and `rule_id = 'agent_research'`;
876
+ * callers omit both.
877
+ *
878
+ * Response codes carried through to the caller:
879
+ * - 201: `{ proposal_id, source, rule_id, status }` (pending)
880
+ * - 409 `DUPLICATE_SUPPRESSED`: identical content already filed
881
+ * - 400 `MISSING_SOURCE`: uncited proposed field or empty sources
882
+ * - 400 `MISSING_FIELDS`: proposed_fields was empty
883
+ * - 400 `INVALID_SOURCE_SHAPE`: a source entry lacked url/fields/accessed_at
884
+ * - 404 `ENTITY_NOT_FOUND`: entity_id not in caller's org
885
+ */
886
+ proposeAgentResearch(input: {
887
+ entity_type: "work" | "person" | "recording";
888
+ entity_id: string;
889
+ proposed_fields: Record<string, unknown>;
890
+ sources: Array<{
891
+ url: string;
892
+ fields: string[];
893
+ accessed_at: string;
894
+ }>;
895
+ confidence_score?: number | null;
896
+ rationale?: string;
897
+ proposal_action?: "update" | "create";
898
+ }): Promise<{
899
+ proposal_id: string;
900
+ source: "agent_research";
901
+ rule_id: "agent_research";
902
+ status: "pending";
903
+ }>;
678
904
  /** Preview what a Spotify URL would do — delegates to streaming-link */
679
905
  spotifyUrlPreview(url: string): Promise<any>;
680
906
  /** Execute import/enrich from a Spotify URL — delegates to streaming-link */
@@ -717,6 +943,16 @@ declare class SettingsResource extends BaseResource {
717
943
  storageConfig(): Promise<any>;
718
944
  orgProfile(): Promise<any>;
719
945
  userProfile(): Promise<any>;
946
+ /**
947
+ * Update the authenticated user's privacy / marketing-preference flags.
948
+ * Parity with ADR-183's settings-tab toggles — exposes the same fields
949
+ * the web UI writes, so an agent can unsubscribe on the user's behalf
950
+ * without leaving the conversation. ADR-184 slice 5.
951
+ */
952
+ updatePrivacySettings(params: {
953
+ receive_news_announcements?: boolean;
954
+ receive_monthly_digest?: boolean;
955
+ }): Promise<any>;
720
956
  }
721
957
  declare class CalendarResource extends BaseResource {
722
958
  getEvents(params: {
@@ -1206,6 +1442,11 @@ declare class ProjectsResource extends BaseResource {
1206
1442
  create(data: Record<string, any>): Promise<any>;
1207
1443
  update(id: string, data: Record<string, any>): Promise<any>;
1208
1444
  delete(id: string): Promise<any>;
1445
+ attachWork(projectId: string, data: {
1446
+ work_id: string;
1447
+ project_day?: number | null;
1448
+ notes?: string | null;
1449
+ }): Promise<any>;
1209
1450
  }
1210
1451
  declare class SplitSheetsResource extends BaseResource {
1211
1452
  listForWork(workId: string): Promise<any>;
@@ -1224,10 +1465,21 @@ declare class PublishersResource extends BaseResource {
1224
1465
  query?: string;
1225
1466
  limit?: number;
1226
1467
  }): Promise<any>;
1227
- create(data: {
1228
- name: string;
1229
- ipi?: string;
1230
- }): Promise<any>;
1468
+ create(data: Record<string, unknown>): Promise<any>;
1469
+ }
1470
+ export interface LabelOrganisation {
1471
+ id: string;
1472
+ name: string;
1473
+ display_name: string | null;
1474
+ country: string | null;
1475
+ website: string | null;
1476
+ verification_status: string | null;
1477
+ }
1478
+ declare class LabelsResource extends BaseResource {
1479
+ list(params?: {
1480
+ query?: string;
1481
+ limit?: number;
1482
+ }): Promise<LabelOrganisation[]>;
1231
1483
  }
1232
1484
  declare class ReleasesResource extends BaseResource {
1233
1485
  list(params?: {
@@ -1237,6 +1489,48 @@ declare class ReleasesResource extends BaseResource {
1237
1489
  create(data: Record<string, any>): Promise<any>;
1238
1490
  update(id: string, data: Record<string, any>): Promise<any>;
1239
1491
  delete(id: string): Promise<any>;
1492
+ /**
1493
+ * ADR-173: attach a recording and/or work to a release at a
1494
+ * specific (disc, track) position. Idempotent on position.
1495
+ */
1496
+ attachTrack(releaseId: string, data: {
1497
+ recording_id?: string | null;
1498
+ work_id?: string | null;
1499
+ track_number: number;
1500
+ disc_number?: number;
1501
+ }): Promise<any>;
1502
+ /**
1503
+ * ADR-173: list tracks on a release in (disc, track) order with
1504
+ * inlined work + recording summary fields.
1505
+ */
1506
+ listTracks(releaseId: string): Promise<any>;
1507
+ /**
1508
+ * ADR-173: soft-confirmation detach by position. Call without
1509
+ * confirm:true to get a preview; call with confirm:true to execute.
1510
+ */
1511
+ detachTrack(releaseId: string, data: {
1512
+ track_number: number;
1513
+ disc_number?: number;
1514
+ confirm?: boolean;
1515
+ }): Promise<any>;
1516
+ /**
1517
+ * ADR-173: transactional positional reorder. Input is the full
1518
+ * new order as [{ track_id, track_number, disc_number }].
1519
+ */
1520
+ reorderTracks(releaseId: string, newOrder: Array<{
1521
+ track_id: string;
1522
+ track_number: number;
1523
+ disc_number?: number;
1524
+ }>): Promise<any>;
1525
+ /**
1526
+ * ADR-173 Decision 4: compound attach that resolves the
1527
+ * recording's work_id server-side before creating the track row.
1528
+ */
1529
+ attachRecordingWithWork(releaseId: string, data: {
1530
+ recording_id: string;
1531
+ track_number: number;
1532
+ disc_number?: number;
1533
+ }): Promise<any>;
1240
1534
  }
1241
1535
  declare class SessionsResource extends BaseResource {
1242
1536
  list(params?: {
@@ -1416,6 +1710,7 @@ export declare class PicaClient {
1416
1710
  splitSheets: SplitSheetsResource;
1417
1711
  recordingSplits: RecordingSplitsResource;
1418
1712
  publishers: PublishersResource;
1713
+ labels: LabelsResource;
1419
1714
  agreementTemplates: AgreementTemplatesResource;
1420
1715
  producerAgreements: ProducerAgreementsResource;
1421
1716
  workForHire: WorkForHireResource;