@withpica/mcp-server 1.3.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.
Files changed (347) hide show
  1. package/.claude/settings.local.json +5 -0
  2. package/CHANGELOG.md +1850 -0
  3. package/README.md +304 -0
  4. package/assets/fonts/GeistSans-Light.woff2 +0 -0
  5. package/assets/fonts/InstrumentSerif-Italic.woff2 +0 -0
  6. package/assets/fonts/InstrumentSerif-Regular.woff2 +0 -0
  7. package/dist/apps/download.d.ts +2 -0
  8. package/dist/apps/download.d.ts.map +1 -0
  9. package/dist/apps/download.js +125 -0
  10. package/dist/apps/download.js.map +1 -0
  11. package/dist/apps/generated/shared-bundle.d.ts +5 -0
  12. package/dist/apps/generated/shared-bundle.d.ts.map +1 -0
  13. package/dist/apps/generated/shared-bundle.js +7 -0
  14. package/dist/apps/generated/shared-bundle.js.map +1 -0
  15. package/dist/apps/release.d.ts +2 -0
  16. package/dist/apps/release.d.ts.map +1 -0
  17. package/dist/apps/release.js +69 -0
  18. package/dist/apps/release.js.map +1 -0
  19. package/dist/apps/shared.d.ts +15 -0
  20. package/dist/apps/shared.d.ts.map +1 -0
  21. package/dist/apps/shared.js +480 -0
  22. package/dist/apps/shared.js.map +1 -0
  23. package/dist/apps/upload.d.ts +2 -0
  24. package/dist/apps/upload.d.ts.map +1 -0
  25. package/dist/apps/upload.js +280 -0
  26. package/dist/apps/upload.js.map +1 -0
  27. package/dist/config.d.ts +14 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +73 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/index.d.ts +3 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +35 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/prompts/index.d.ts +86 -0
  36. package/dist/prompts/index.d.ts.map +1 -0
  37. package/dist/prompts/index.js +645 -0
  38. package/dist/prompts/index.js.map +1 -0
  39. package/dist/resources/agent-guide.d.ts +15 -0
  40. package/dist/resources/agent-guide.d.ts.map +1 -0
  41. package/dist/resources/agent-guide.js +284 -0
  42. package/dist/resources/agent-guide.js.map +1 -0
  43. package/dist/resources/index.d.ts +66 -0
  44. package/dist/resources/index.d.ts.map +1 -0
  45. package/dist/resources/index.js +510 -0
  46. package/dist/resources/index.js.map +1 -0
  47. package/dist/resources/llms-primer.d.ts +2 -0
  48. package/dist/resources/llms-primer.d.ts.map +1 -0
  49. package/dist/resources/llms-primer.js +68 -0
  50. package/dist/resources/llms-primer.js.map +1 -0
  51. package/dist/resources/required-schemas.generated.d.ts +455 -0
  52. package/dist/resources/required-schemas.generated.d.ts.map +1 -0
  53. package/dist/resources/required-schemas.generated.js +1041 -0
  54. package/dist/resources/required-schemas.generated.js.map +1 -0
  55. package/dist/resources/required-schemas.source.d.ts +53 -0
  56. package/dist/resources/required-schemas.source.d.ts.map +1 -0
  57. package/dist/resources/required-schemas.source.js +493 -0
  58. package/dist/resources/required-schemas.source.js.map +1 -0
  59. package/dist/resources/welcome.d.ts +14 -0
  60. package/dist/resources/welcome.d.ts.map +1 -0
  61. package/dist/resources/welcome.js +26 -0
  62. package/dist/resources/welcome.js.map +1 -0
  63. package/dist/server-instructions.d.ts +60 -0
  64. package/dist/server-instructions.d.ts.map +1 -0
  65. package/dist/server-instructions.js +93 -0
  66. package/dist/server-instructions.js.map +1 -0
  67. package/dist/server.d.ts +52 -0
  68. package/dist/server.d.ts.map +1 -0
  69. package/dist/server.js +334 -0
  70. package/dist/server.js.map +1 -0
  71. package/dist/tools/access-simulate.d.ts +23 -0
  72. package/dist/tools/access-simulate.d.ts.map +1 -0
  73. package/dist/tools/access-simulate.js +162 -0
  74. package/dist/tools/access-simulate.js.map +1 -0
  75. package/dist/tools/agent-identity.d.ts +36 -0
  76. package/dist/tools/agent-identity.d.ts.map +1 -0
  77. package/dist/tools/agent-identity.js +274 -0
  78. package/dist/tools/agent-identity.js.map +1 -0
  79. package/dist/tools/agreement-types.d.ts +27 -0
  80. package/dist/tools/agreement-types.d.ts.map +1 -0
  81. package/dist/tools/agreement-types.js +281 -0
  82. package/dist/tools/agreement-types.js.map +1 -0
  83. package/dist/tools/agreements.d.ts +20 -0
  84. package/dist/tools/agreements.d.ts.map +1 -0
  85. package/dist/tools/agreements.js +282 -0
  86. package/dist/tools/agreements.js.map +1 -0
  87. package/dist/tools/analytics.d.ts +20 -0
  88. package/dist/tools/analytics.d.ts.map +1 -0
  89. package/dist/tools/analytics.js +130 -0
  90. package/dist/tools/analytics.js.map +1 -0
  91. package/dist/tools/app-tools.d.ts +15 -0
  92. package/dist/tools/app-tools.d.ts.map +1 -0
  93. package/dist/tools/app-tools.js +388 -0
  94. package/dist/tools/app-tools.js.map +1 -0
  95. package/dist/tools/assets.d.ts +25 -0
  96. package/dist/tools/assets.d.ts.map +1 -0
  97. package/dist/tools/assets.js +454 -0
  98. package/dist/tools/assets.js.map +1 -0
  99. package/dist/tools/audio-files.d.ts +20 -0
  100. package/dist/tools/audio-files.d.ts.map +1 -0
  101. package/dist/tools/audio-files.js +409 -0
  102. package/dist/tools/audio-files.js.map +1 -0
  103. package/dist/tools/audit.d.ts +19 -0
  104. package/dist/tools/audit.d.ts.map +1 -0
  105. package/dist/tools/audit.js +58 -0
  106. package/dist/tools/audit.js.map +1 -0
  107. package/dist/tools/auth.d.ts +22 -0
  108. package/dist/tools/auth.d.ts.map +1 -0
  109. package/dist/tools/auth.js +212 -0
  110. package/dist/tools/auth.js.map +1 -0
  111. package/dist/tools/bulk.d.ts +22 -0
  112. package/dist/tools/bulk.d.ts.map +1 -0
  113. package/dist/tools/bulk.js +164 -0
  114. package/dist/tools/bulk.js.map +1 -0
  115. package/dist/tools/calendar.d.ts +15 -0
  116. package/dist/tools/calendar.d.ts.map +1 -0
  117. package/dist/tools/calendar.js +68 -0
  118. package/dist/tools/calendar.js.map +1 -0
  119. package/dist/tools/collaborators.d.ts +21 -0
  120. package/dist/tools/collaborators.d.ts.map +1 -0
  121. package/dist/tools/collaborators.js +381 -0
  122. package/dist/tools/collaborators.js.map +1 -0
  123. package/dist/tools/comparisons.d.ts +22 -0
  124. package/dist/tools/comparisons.d.ts.map +1 -0
  125. package/dist/tools/comparisons.js +80 -0
  126. package/dist/tools/comparisons.js.map +1 -0
  127. package/dist/tools/credits.d.ts +39 -0
  128. package/dist/tools/credits.d.ts.map +1 -0
  129. package/dist/tools/credits.js +541 -0
  130. package/dist/tools/credits.js.map +1 -0
  131. package/dist/tools/custody-hints.d.ts +16 -0
  132. package/dist/tools/custody-hints.d.ts.map +1 -0
  133. package/dist/tools/custody-hints.js +27 -0
  134. package/dist/tools/custody-hints.js.map +1 -0
  135. package/dist/tools/custody.d.ts +38 -0
  136. package/dist/tools/custody.d.ts.map +1 -0
  137. package/dist/tools/custody.js +281 -0
  138. package/dist/tools/custody.js.map +1 -0
  139. package/dist/tools/dashboard.d.ts +22 -0
  140. package/dist/tools/dashboard.d.ts.map +1 -0
  141. package/dist/tools/dashboard.js +258 -0
  142. package/dist/tools/dashboard.js.map +1 -0
  143. package/dist/tools/directory.d.ts +15 -0
  144. package/dist/tools/directory.d.ts.map +1 -0
  145. package/dist/tools/directory.js +107 -0
  146. package/dist/tools/directory.js.map +1 -0
  147. package/dist/tools/discovery.d.ts +49 -0
  148. package/dist/tools/discovery.d.ts.map +1 -0
  149. package/dist/tools/discovery.js +851 -0
  150. package/dist/tools/discovery.js.map +1 -0
  151. package/dist/tools/disputes.d.ts +18 -0
  152. package/dist/tools/disputes.d.ts.map +1 -0
  153. package/dist/tools/disputes.js +62 -0
  154. package/dist/tools/disputes.js.map +1 -0
  155. package/dist/tools/documents.d.ts +15 -0
  156. package/dist/tools/documents.d.ts.map +1 -0
  157. package/dist/tools/documents.js +37 -0
  158. package/dist/tools/documents.js.map +1 -0
  159. package/dist/tools/duplicates.d.ts +25 -0
  160. package/dist/tools/duplicates.d.ts.map +1 -0
  161. package/dist/tools/duplicates.js +108 -0
  162. package/dist/tools/duplicates.js.map +1 -0
  163. package/dist/tools/enrichment.d.ts +56 -0
  164. package/dist/tools/enrichment.d.ts.map +1 -0
  165. package/dist/tools/enrichment.js +616 -0
  166. package/dist/tools/enrichment.js.map +1 -0
  167. package/dist/tools/exports.d.ts +19 -0
  168. package/dist/tools/exports.d.ts.map +1 -0
  169. package/dist/tools/exports.js +184 -0
  170. package/dist/tools/exports.js.map +1 -0
  171. package/dist/tools/feedback.d.ts +22 -0
  172. package/dist/tools/feedback.d.ts.map +1 -0
  173. package/dist/tools/feedback.js +100 -0
  174. package/dist/tools/feedback.js.map +1 -0
  175. package/dist/tools/forbidden-keywords.d.ts +62 -0
  176. package/dist/tools/forbidden-keywords.d.ts.map +1 -0
  177. package/dist/tools/forbidden-keywords.js +99 -0
  178. package/dist/tools/forbidden-keywords.js.map +1 -0
  179. package/dist/tools/gap-hints.d.ts +53 -0
  180. package/dist/tools/gap-hints.d.ts.map +1 -0
  181. package/dist/tools/gap-hints.js +245 -0
  182. package/dist/tools/gap-hints.js.map +1 -0
  183. package/dist/tools/groups.d.ts +29 -0
  184. package/dist/tools/groups.d.ts.map +1 -0
  185. package/dist/tools/groups.js +186 -0
  186. package/dist/tools/groups.js.map +1 -0
  187. package/dist/tools/import-documents.d.ts +21 -0
  188. package/dist/tools/import-documents.d.ts.map +1 -0
  189. package/dist/tools/import-documents.js +206 -0
  190. package/dist/tools/import-documents.js.map +1 -0
  191. package/dist/tools/import.d.ts +31 -0
  192. package/dist/tools/import.d.ts.map +1 -0
  193. package/dist/tools/import.js +610 -0
  194. package/dist/tools/import.js.map +1 -0
  195. package/dist/tools/index.d.ts +293 -0
  196. package/dist/tools/index.d.ts.map +1 -0
  197. package/dist/tools/index.js +1182 -0
  198. package/dist/tools/index.js.map +1 -0
  199. package/dist/tools/integrations.d.ts +19 -0
  200. package/dist/tools/integrations.d.ts.map +1 -0
  201. package/dist/tools/integrations.js +120 -0
  202. package/dist/tools/integrations.js.map +1 -0
  203. package/dist/tools/labels.d.ts +20 -0
  204. package/dist/tools/labels.d.ts.map +1 -0
  205. package/dist/tools/labels.js +48 -0
  206. package/dist/tools/labels.js.map +1 -0
  207. package/dist/tools/licensing.d.ts +40 -0
  208. package/dist/tools/licensing.d.ts.map +1 -0
  209. package/dist/tools/licensing.js +436 -0
  210. package/dist/tools/licensing.js.map +1 -0
  211. package/dist/tools/memory.d.ts +21 -0
  212. package/dist/tools/memory.d.ts.map +1 -0
  213. package/dist/tools/memory.js +120 -0
  214. package/dist/tools/memory.js.map +1 -0
  215. package/dist/tools/metadata.d.ts +15 -0
  216. package/dist/tools/metadata.d.ts.map +1 -0
  217. package/dist/tools/metadata.js +1532 -0
  218. package/dist/tools/metadata.js.map +1 -0
  219. package/dist/tools/multimedia.d.ts +19 -0
  220. package/dist/tools/multimedia.d.ts.map +1 -0
  221. package/dist/tools/multimedia.js +371 -0
  222. package/dist/tools/multimedia.js.map +1 -0
  223. package/dist/tools/my-reported-issues.d.ts +32 -0
  224. package/dist/tools/my-reported-issues.d.ts.map +1 -0
  225. package/dist/tools/my-reported-issues.js +123 -0
  226. package/dist/tools/my-reported-issues.js.map +1 -0
  227. package/dist/tools/notes.d.ts +21 -0
  228. package/dist/tools/notes.d.ts.map +1 -0
  229. package/dist/tools/notes.js +115 -0
  230. package/dist/tools/notes.js.map +1 -0
  231. package/dist/tools/notifications.d.ts +28 -0
  232. package/dist/tools/notifications.d.ts.map +1 -0
  233. package/dist/tools/notifications.js +417 -0
  234. package/dist/tools/notifications.js.map +1 -0
  235. package/dist/tools/onboarding.d.ts +24 -0
  236. package/dist/tools/onboarding.d.ts.map +1 -0
  237. package/dist/tools/onboarding.js +81 -0
  238. package/dist/tools/onboarding.js.map +1 -0
  239. package/dist/tools/people.d.ts +254 -0
  240. package/dist/tools/people.d.ts.map +1 -0
  241. package/dist/tools/people.js +481 -0
  242. package/dist/tools/people.js.map +1 -0
  243. package/dist/tools/projects.d.ts +20 -0
  244. package/dist/tools/projects.d.ts.map +1 -0
  245. package/dist/tools/projects.js +316 -0
  246. package/dist/tools/projects.js.map +1 -0
  247. package/dist/tools/public-filter.d.ts +43 -0
  248. package/dist/tools/public-filter.d.ts.map +1 -0
  249. package/dist/tools/public-filter.js +356 -0
  250. package/dist/tools/public-filter.js.map +1 -0
  251. package/dist/tools/publishers.d.ts +30 -0
  252. package/dist/tools/publishers.d.ts.map +1 -0
  253. package/dist/tools/publishers.js +105 -0
  254. package/dist/tools/publishers.js.map +1 -0
  255. package/dist/tools/purchases.d.ts +27 -0
  256. package/dist/tools/purchases.d.ts.map +1 -0
  257. package/dist/tools/purchases.js +9 -0
  258. package/dist/tools/purchases.js.map +1 -0
  259. package/dist/tools/recording-attribution-hints.d.ts +24 -0
  260. package/dist/tools/recording-attribution-hints.d.ts.map +1 -0
  261. package/dist/tools/recording-attribution-hints.js +27 -0
  262. package/dist/tools/recording-attribution-hints.js.map +1 -0
  263. package/dist/tools/recordings.d.ts +96 -0
  264. package/dist/tools/recordings.d.ts.map +1 -0
  265. package/dist/tools/recordings.js +564 -0
  266. package/dist/tools/recordings.js.map +1 -0
  267. package/dist/tools/recovery-hints.d.ts +40 -0
  268. package/dist/tools/recovery-hints.d.ts.map +1 -0
  269. package/dist/tools/recovery-hints.js +827 -0
  270. package/dist/tools/recovery-hints.js.map +1 -0
  271. package/dist/tools/release-rich.d.ts +31 -0
  272. package/dist/tools/release-rich.d.ts.map +1 -0
  273. package/dist/tools/release-rich.js +245 -0
  274. package/dist/tools/release-rich.js.map +1 -0
  275. package/dist/tools/releases.d.ts +36 -0
  276. package/dist/tools/releases.d.ts.map +1 -0
  277. package/dist/tools/releases.js +649 -0
  278. package/dist/tools/releases.js.map +1 -0
  279. package/dist/tools/report-issue.d.ts +21 -0
  280. package/dist/tools/report-issue.d.ts.map +1 -0
  281. package/dist/tools/report-issue.js +101 -0
  282. package/dist/tools/report-issue.js.map +1 -0
  283. package/dist/tools/royalties.d.ts +23 -0
  284. package/dist/tools/royalties.d.ts.map +1 -0
  285. package/dist/tools/royalties.js +262 -0
  286. package/dist/tools/royalties.js.map +1 -0
  287. package/dist/tools/search.d.ts +30 -0
  288. package/dist/tools/search.d.ts.map +1 -0
  289. package/dist/tools/search.js +115 -0
  290. package/dist/tools/search.js.map +1 -0
  291. package/dist/tools/send.d.ts +17 -0
  292. package/dist/tools/send.d.ts.map +1 -0
  293. package/dist/tools/send.js +188 -0
  294. package/dist/tools/send.js.map +1 -0
  295. package/dist/tools/sessions.d.ts +18 -0
  296. package/dist/tools/sessions.d.ts.map +1 -0
  297. package/dist/tools/sessions.js +153 -0
  298. package/dist/tools/sessions.js.map +1 -0
  299. package/dist/tools/settings.d.ts +23 -0
  300. package/dist/tools/settings.d.ts.map +1 -0
  301. package/dist/tools/settings.js +365 -0
  302. package/dist/tools/settings.js.map +1 -0
  303. package/dist/tools/share-links.d.ts +22 -0
  304. package/dist/tools/share-links.d.ts.map +1 -0
  305. package/dist/tools/share-links.js +188 -0
  306. package/dist/tools/share-links.js.map +1 -0
  307. package/dist/tools/signup.d.ts +26 -0
  308. package/dist/tools/signup.d.ts.map +1 -0
  309. package/dist/tools/signup.js +266 -0
  310. package/dist/tools/signup.js.map +1 -0
  311. package/dist/tools/split-sheets.d.ts +25 -0
  312. package/dist/tools/split-sheets.d.ts.map +1 -0
  313. package/dist/tools/split-sheets.js +309 -0
  314. package/dist/tools/split-sheets.js.map +1 -0
  315. package/dist/tools/storage-config.d.ts +13 -0
  316. package/dist/tools/storage-config.d.ts.map +1 -0
  317. package/dist/tools/storage-config.js +245 -0
  318. package/dist/tools/storage-config.js.map +1 -0
  319. package/dist/tools/subscription.d.ts +60 -0
  320. package/dist/tools/subscription.d.ts.map +1 -0
  321. package/dist/tools/subscription.js +440 -0
  322. package/dist/tools/subscription.js.map +1 -0
  323. package/dist/tools/sync-placements.d.ts +31 -0
  324. package/dist/tools/sync-placements.d.ts.map +1 -0
  325. package/dist/tools/sync-placements.js +431 -0
  326. package/dist/tools/sync-placements.js.map +1 -0
  327. package/dist/tools/team.d.ts +22 -0
  328. package/dist/tools/team.d.ts.map +1 -0
  329. package/dist/tools/team.js +144 -0
  330. package/dist/tools/team.js.map +1 -0
  331. package/dist/tools/telegram.d.ts +21 -0
  332. package/dist/tools/telegram.d.ts.map +1 -0
  333. package/dist/tools/telegram.js +144 -0
  334. package/dist/tools/telegram.js.map +1 -0
  335. package/dist/tools/uploads.d.ts +17 -0
  336. package/dist/tools/uploads.d.ts.map +1 -0
  337. package/dist/tools/uploads.js +165 -0
  338. package/dist/tools/uploads.js.map +1 -0
  339. package/dist/tools/works.d.ts +71 -0
  340. package/dist/tools/works.d.ts.map +1 -0
  341. package/dist/tools/works.js +694 -0
  342. package/dist/tools/works.js.map +1 -0
  343. package/package.json +54 -0
  344. package/scripts/build-required-schemas.ts +233 -0
  345. package/scripts/bundle-apps.ts +61 -0
  346. package/scripts/refresh-schema-mirror.ts +182 -0
  347. package/server.json +20 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,1850 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@withpica/mcp-server` 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
+ ## [2.48.0] - 2026-05-03
15
+
16
+ ### Changed
17
+
18
+ - **Tool description scrub (PR #188).** Stripped internal-only ADR pointers and
19
+ email-vendor names from user-visible tool descriptions across batch A
20
+ (agreement-types, agreements, bulk, collaborators, credits), batch B
21
+ (app-tools, feedback, projects, enrichment, recordings), and batch C.
22
+ Replaced ADR-N references with the concept the ADR documented (e.g.
23
+ "ADR-198 round-trip" → "verify the credit persisted") and removed
24
+ Postmark from collaborator bulk-invite description and elicitation
25
+ warning text. Tool descriptions surface to third-party agents and shouldn't
26
+ reveal internal infrastructure choices.
27
+
28
+ - **recovery_hints expansion (PR #188).** Annotation fix + additional
29
+ recovery hints for tools that fan out across sections.
30
+
31
+ - **`pica_releases_show` best-effort catch markers (ADR-224 convention).** Marked
32
+ the two best-effort catches in `releases-rich.show()` (tracks + cover-art
33
+ fallbacks) with `/* best-effort */` to match the ADR-224 Phase 4 lint
34
+ convention. No behaviour change — the catches were already documented inline;
35
+ this just makes the marker greppable so future scope extensions to `_show`
36
+ tools recognise the intent. Surface audit confirmed all 9 `_inspect` tools
37
+ addressed, 22 `_list` tools clean, no swallow patterns elsewhere.
38
+
39
+ ## [2.47.0] - 2026-05-02
40
+
41
+ ### Added
42
+
43
+ - **ADR-222 W3 — sync placements MCP tool surface (6 tools).**
44
+ - `pica_sync_placements_query` — list placements with filters (work_id, status, verification_status, brand, production_company, person_id, recording_id, source_license_enquiry_id, min_fee, currency).
45
+ - `pica_sync_placements_inspect` — fetch one placement with linked recordings, sources, agreement, and parties.
46
+ - `pica_sync_placements_create` — atomic create (placement + draft sync_license agreement + ≥1 agreement_party + recordings + evidence sources in a single Postgres transaction). Empty `contacts[]` rejects with structured `MISSING_CONTACT` (`next_tool: "pica_people_query"`). New people auto-created inline via `person_name` instead of `person_id`.
47
+ - `pica_sync_placements_update` — patch placement fields. Operator-only when `verification_status='operator_verified'|'disputed'` or `confidentiality_level` changes (throws structured `OPERATOR_REQUIRED`); illegal status transitions throw `INVALID_TRANSITION`.
48
+ - `pica_sync_placements_delete` — operator-only hard delete (two-step confirmation token). Customer agents receive structured `OPERATOR_REQUIRED` with `next_tool: "pica_sync_placements_update"` pointing at the soft-delete path (`status: 'terminated'`).
49
+ - `pica_sync_placements_cite` — attach an evidence source; auto-recomputes `verification_status` (any non-attestation kind → `evidence_attached`).
50
+
51
+ All 4 mutating tools wrapped with `withBillingGate`. Stdio path delegates to `pica.syncPlacements.*` (new `@withpica/mcp-sdk` resource). HTTP transport mirrors via the shared `ToolRegistry`. Paired with W4's REST routes at `/api/admin/sync-placements`.
52
+
53
+ - **`pica://schemas/sync-placement-required` workflow schema resource (ADR-214).** Required + recommended fields for `pica_sync_placements_create` plus 4 companion call entries (inspect / update / cite / delete) and a worked example. Embeds the three `sync_placements` CHECK enums (`status` 5 values, `verification_status` 5 values, `confidentiality_level` 3 values) via the build-time generator + `schema-mirror.json` extension. Lives on both stdio (via the schema generator) and HTTP transport (`UI_RESOURCE_DEFS` in `app/api/mcp/route.ts`).
54
+
55
+ - **`WorkflowTag` union expanded 15 → 16 values** (added `sync-placement-required`). All 6 sync-placement tools tagged with this workflow; `lint-required-schemas` enforces forward + inverse coverage.
56
+
57
+ - **`schema-mirror.json` extended with `sync_placements` table** for status / verification_status / confidentiality_level CHECK enum embedding.
58
+
59
+ - **6 cost-model entries in `lib/billing/tool-cost-model.ts`** (READ for query/inspect, WRITE for create/update/delete/cite). Unblocks ADR-180 lint cost-model coverage check; ADR-215 shadow-metering will record `billable_events` rows on these tools from first call.
60
+
61
+ - **`sync_placements` discovery category** in `mcp-server/src/tools/discovery.ts` — layered-discovery agents (ChatGPT, Claude.ai connectors with `MCP_LAYERED_DISCOVERY=1`) can find the 6 tools via `pica_discover`.
62
+
63
+ - **MCP scope mapping** for the 6 tools under existing `read:agreements` (query + inspect) and `write:agreements` (create + update + delete + cite). Bundled under the agreements scope rather than minting a new public scope for one feature — every placement is backed by a sync_license agreement.
64
+
65
+ - **Four group-membership tools (ADR-223 Phase 5).** Customers can now
66
+ manage group → member relationships on people directly via AI:
67
+ - `pica_group_add_member` — add a person to a group person row.
68
+ Server-side trigger enforces parent.is_group=true and same-org
69
+ constraint; tool surfaces friendly errors at the route layer.
70
+ Defaults: `role='member'`, `receive_notifications=true` (opt-out
71
+ per membership). Wrapped in `withBillingGate`.
72
+ - `pica_group_remove_member` — set `left_at` on the active row.
73
+ Rows are never deleted; member history is preserved.
74
+ - `pica_group_list_members` — active members by default;
75
+ `include_inactive=true` for history.
76
+ - `pica_person_list_groups` — inverse: every group a person is or
77
+ was a member of.
78
+ Role enum: `member`, `founder`, `lead`, `touring_member`,
79
+ `session`, `guest`, `producer_in_residence`. Free-text `role_label`
80
+ for variants outside the enum. Tools route through `mcp-sdk`
81
+ `groups` resource → `/admin/groups/*` and
82
+ `/admin/people/{id}/groups` HTTP routes.
83
+
84
+ ### Changed
85
+
86
+ - **`@withpica/mcp-sdk` peer bumped to `^1.20.0`.** Required for the
87
+ new `groups` and `syncPlacements` resources; older SDK versions lack
88
+ `PicaClient.groups` and `PicaClient.syncPlacements`.
89
+
90
+ ### Notes
91
+
92
+ - The 4 mutating sync-placement tools (`_create`, `_update`, `_delete`, `_cite`) need ADR-198 holdout contract specs in the sibling `Good-FM/pica-holdout-tests` repo. Coordinator follow-up — Path A from W3 Stage 1 audit §11.E.
93
+ - The brief's references to a `mcp-server/src/__tests__/contract-baseline.json` file and a `lint:contract-baseline` script are out of date; both were removed in ADR-180 Phase 3 (the lint chain is now fully strict by default — `scripts/lint-mcp-tools.ts` runs as part of `prepublishOnly`). W3 reinterpreted Stage 4 as ADR-180 metadata + cost-model + taxonomy entries (all added) plus ADR-198 holdout contracts (sibling repo, follow-up).
94
+
95
+ ## [2.46.0] - 2026-05-02
96
+
97
+ ### Changed
98
+
99
+ - **`pica_update_my_identity` now accepts `full_name`.** Customers can
100
+ update the name on their PICA account via AI (e.g., fix typos from
101
+ signup). Routes to `user_profiles.full_name`; rolls back via
102
+ `revertMyIdentity` if the agent-action stamp insert fails. Tool
103
+ description rewritten to lead with name capture. Closes the
104
+ edit-symmetry gap surfaced during the SEV-1 sprint: previously the
105
+ user could AI-rename their org but not their own name.
106
+
107
+ - **`pica_update_organisation_profile` now accepts `name`.** Customers can
108
+ rename their organisation via AI (e.g., fix signup typos, replace the
109
+ default "My Organization" placeholder). Updates `organisations.name`
110
+ directly; non-empty TRIM validation matches the DB-layer SEV-1 guard
111
+ shipped earlier on 2026-05-01. Tool description updated to mention the
112
+ typo-fix use case. Closes the placeholder-name lock-in trap surfaced
113
+ during the SEV-1 onboarding-stuck-state cleanup.
114
+
115
+ ## [2.45.0] - 2026-05-01
116
+
117
+ ### Added
118
+
119
+ - **ADR-214 Phase 3a — 3 new workflow schema resources.**
120
+ - `pica://schemas/session-required` (studio session logging — `pica_sessions_create` primary; `pica_sessions_types` companion for session_type_id lookup; `pica_sessions_get` / `_list` for read).
121
+ - `pica://schemas/split-sheet-required` (publishing royalty splits on works — `pica_split_sheet_generate` primary; `pica_split_sheet_send` / `_get` / `_list` companions).
122
+ - `pica://schemas/recording-splits-required` (master ownership splits on recordings — `pica_recording_splits_create` primary with ADR-200 form-confirmation gate; `pica_recording_splits_verify` / `_list` companions).
123
+
124
+ Each derives required + recommended fields from live tool input schemas at build time; `recording-splits-required` embeds the `split_type` and `role` CHECK enums (4 + 8 values respectively) from a hand-edited `schema-mirror.json` entry verified against prod project `fwgcmjhlwevdnxgqmkmh`.
125
+
126
+ - **WorkflowTag union expanded 12 → 15 values** (added `session-required`, `split-sheet-required`, `recording-splits-required`). 11 tools migrated from `"infrastructure"` to their P3a workflow tag (4 sessions + 4 split-sheet + 3 recording-splits).
127
+
128
+ - **Agent-guide expanded 6 → 14 sections** for authenticated mode:
129
+ - 3 new write workflow sections (sessions, split-sheet, recording-splits) with canonical tool sequences and schema-URI footers.
130
+ - 1 new identifier-assign narrative section explaining the inline-update pattern (`pica_*_update` accepts identifiers as inline fields including satellite-routed person identifiers — `isni`, `musicbrainz_id`, `wikidata_id`, `discogs_artist_id`, `deezer_artist_id` route to `person_enrichment` automatically; the surface is uniform).
131
+ - 4 new read-workflow sections covering find-duplicates → merge, query → inspect → resolve gap-finding chain, lookup-person by industry identifier, and audit catalog completeness via dashboard tools.
132
+
133
+ Authenticated guide now ~12,750 B (lobby variant unchanged ~855 B).
134
+
135
+ - **`schema-mirror.json` extended with `recording_splits` table** for `split_type` + `role` CHECK enum embedding. `sessions.status` and `split_sheets.status` documented inline in schema `summary` fields rather than `enum_tables` because they are not DB-CHECK-enforced.
136
+
137
+ - **2 new MCP prompts.**
138
+ - `log-a-session` — guided studio session logging with optional `work_id` argument.
139
+ - `set-recording-splits` — guided master ownership split assignment with ADR-200 propose-and-confirm + verify flow; takes optional `recording_id`.
140
+
141
+ - **`_meta.schemas` dispatcher emit on workflow-tagged tool results.** New `attachSchemaHints` private method on `ToolRegistry` mirrors the existing `attachSessionState` pattern verbatim — same merge semantics, null-safe handling, fail-open behavior. Every tool whose `workflows` field references one or more schema URIs auto-emits `_meta.schemas: ["pica://schemas/<workflow>-required", ...]` on successful results. 47 workflow-tagged tools across 13 files automatically tagged via the dispatcher hook (no per-executor edits). `ToolResult._meta` interface widened to `{ session_state?: SessionState; schemas?: string[]; [key: string]: unknown }`. Cross-transport survival verified — both HTTP (`app/api/mcp/route.ts`) and stdio (`mcp-server/src/server.ts`) preserve `_meta` end-to-end.
142
+
143
+ - **Cost-model entries for ADR-217 + ADR-218 tools** (`pica_notifications_recent` → READ, `pica_notification_acknowledge` → WRITE, `pica_storage_configure_start` + `pica_storage_disconnect` → ADMIN). Unblocks ADR-180 lint cost-model coverage check; ADR-215 shadow-metering now records `billable_events` rows for these tools.
144
+
145
+ ### Changed
146
+
147
+ - **11 existing prompts updated to reference ADR-214 schema URIs** where the workflow shape is implicated: `analyze-catalog`, `find-duplicates`, `enrich-metadata`, `verify-works`, `assess-catalog-health`, `audit-credits`, `new-catalog-setup`, `close-the-loop`, `register-my-works`, `prepare-for-sync`, `workspace-autopilot`. Agents invoking a refreshed prompt pick up the relevant `pica://schemas/<workflow>-required` (and `pica://docs/agent-guide` where orientation helps) on first read.
148
+
149
+ - **`pica_merge_duplicates.entity_type` now accepts both forms.** Previously the enum was singular (`"work" | "person"`) while `pica_find_duplicates` was plural (`"works" | "people"`) — a real footgun documented in ADR-214 P3a Stage 1 R4. Tool now accepts all four (`works` / `people` / `work` / `person`); canonical plural form (`works` / `people`) matches the rest of the catalog tools. Internally coerces to plural for the success message and to singular for the SDK call. Backwards-compatible — no existing caller breaks. Success message no longer renders the broken `work(s)` / `person(s)` artifact when callers pass the plural form. The R4 confirm-branch (two-step ADR-200 confirmation flow) also uses canonical coercion with a try/catch fallback to "entities" so unknown entity_types don't break the confirm UX.
150
+
151
+ ### Fixed
152
+
153
+ - **`pica_recordings_by_work` drift cleanup.** Removed tool was still referenced in:
154
+ - `mcp-server/src/prompts/index.ts` `verify-works` prompt body — swapped to `pica_recordings_query` with `work_id` filter (single-line drift fix).
155
+ - `mcp-server/src/tools/recovery-hints.ts` `next_tool` annotation — swapped to `pica_recordings_query`.
156
+ - `mcp-server/README.md` Recordings Management section — section refreshed to current 5 tools (`_query`, `_inspect`, `_create`, `_update`, `_delete`); count corrected 6 → 5. Larger README drift in works/people/etc. sections flagged as separate cleanup.
157
+ - `@withpica/mcp-utils` `recovery-hints.ts` DUPLICATE_ISRC `next_tool` — same swap (mcp-utils@1.15.1).
158
+
159
+ - **Source ↔ dist invariant restored** for `prompts/index.{js,d.ts,*.map}` (PR #173 source landed without committed dist regen — develop's dist had been missing `log-a-session` + `set-recording-splits`) and `tools/recovery-hints.{js,*.map}` (source was correct; dist was stale). No semantic change beyond what was already on develop; clears phantom local-tsc errors per `feedback_root_tsc_stale_mcp_dist`.
160
+
161
+ ### Dependencies
162
+
163
+ - `@withpica/mcp-utils` `^1.14.0` → `^1.15.1` (recovery-hints `next_tool` fix).
164
+
165
+ ## [2.44.0] - 2026-04-30
166
+
167
+ ### Added
168
+
169
+ - **ADR-214 Phase 2 — 6 new workflow schema resources.**
170
+ - `pica://schemas/audio-upload-required` (3-step chain: presigned →
171
+ complete → analyze + poll)
172
+ - `pica://schemas/enrichment-resolve-required` (resolve fan-out →
173
+ proposals_list → proposal_apply / reject)
174
+ - `pica://schemas/agreement-required`
175
+ - `pica://schemas/multimedia-required`
176
+ - `pica://schemas/export-required`
177
+ - `pica://schemas/claim-required`
178
+
179
+ Each derives required + recommended fields from the live tool input
180
+ schemas at build time and embeds CHECK enums from `schema-mirror.json`.
181
+ Agent-guide expanded with 6 workflow sections (4 net-new, 2 rewrites
182
+ with schema-URI footers); intro bumps "five core" → "eleven core" and
183
+ "~227 tools" → "~231 tools".
184
+
185
+ - **WorkflowTag union expanded to 12 values** (5 Phase 1 + 6 Phase 2 +
186
+ `infrastructure`). 28 tools migrated from `"infrastructure"` to their
187
+ Phase 2 workflow tag (4 audio-upload, 6 enrichment-resolve, 4
188
+ agreement, 4 multimedia, 5 export, 5 claim).
189
+ - **`schema-mirror.json` extended with 6 new tables** for Phase 2
190
+ CHECK-constraint enum resolution (agreements, discovered_artists,
191
+ discovered_credits, discovered_custody, enrichment_proposals,
192
+ multimedia_items). Verified live against prod project
193
+ `fwgcmjhlwevdnxgqmkmh`.
194
+ - **HTTP transport coverage** — `app/api/mcp/route.ts` `UI_RESOURCE_DEFS`
195
+ - `UI_RESOURCE_BODIES` extended with the 6 new schema URIs (matches
196
+ the Phase 1 pattern from PR #152). Per
197
+ `feedback_cross_transport_resource_coverage`.
198
+
199
+ ## [2.42.0] - 2026-04-30
200
+
201
+ ### Added
202
+
203
+ - **ADR-218 Primitive B — `pica_notifications_recent` tool.** New read-only
204
+ MCP tool (`risk: "safe"`, `retry_safe: true`) returning the cross-transport
205
+ `discovery_events` feed for the calling org, ordered by `created_at` DESC
206
+ with optional `unread_only: boolean` filter (per-surface dedup against
207
+ `seen_in`). Default limit 20, max 100. Distinct from `pica_notifications_list`
208
+ which targets the person-scoped `pica.notifications` system; this reads the
209
+ org-wide ledger that web bell + telegram dispatcher also share.
210
+ - **ADR-218 Primitive C — `pica_notification_acknowledge` tool.** New
211
+ mutating tool (`risk: "mutating"`, `retry_safe: true`) that appends `'mcp'`
212
+ to each event's `seen_in` array. Idempotent — re-acknowledging is a no-op.
213
+ Org-scoped server-side: out-of-org ids are silently skipped. Empty
214
+ `event_ids` returns a `VALIDATION_ERROR` without hitting the API.
215
+ - \*\*Both tools registered in the existing `notifications` taxonomy bucket
216
+ - TOOL*METADATA (`category: "comms"`)\*\* + tagged `workflows: "infrastructure"`
217
+ per ADR-214 W4. Ride alongside the legacy `pica_notifications*_`and`pica*notify*_` families — the agent disambiguates from the descriptions.
218
+
219
+ ### Changed
220
+
221
+ - **ADR-218 Primitive D — telegram dispatch dedup.** `telegramNotificationService.notifyEvent`
222
+ now consults `discovery_events` for an existing undismissed row matching
223
+ `(organisation_id, event_type, entity_id)` where `'mcp' = ANY(seen_in)`.
224
+ When found, suppresses the entire dispatch — closes the re-nag loop for
225
+ `until_resolved`-strategy alerts. Fresh `one_shot` events with no prior
226
+ row still fire normally. Lookup is fail-soft: any DB error logs a debug
227
+ and proceeds with dispatch (better an extra ping than a silently-dropped
228
+ alert).
229
+ - **ADR-218 Primitive A — `_meta.session_state` envelope gains optional
230
+ `notifications` field.** `fetchSessionCounts` propagates the cross-transport
231
+ unread summary from the catalog-stats response into the envelope. Missing
232
+ field on older API servers leaves the envelope key off (no fabricated zero).
233
+
234
+ ### Bumped
235
+
236
+ - `@withpica/mcp-sdk` peer to `^1.18.0` (`DiscoveriesResource.recent` +
237
+ `.acknowledge` methods + `NotificationsSummary` type on `CatalogStats`).
238
+ - `@withpica/mcp-utils` peer to `^1.14.0` (optional `notifications` field on
239
+ `SessionStateCounts` + exported `NotificationsSummary` type).
240
+
241
+ ## [2.41.0] - 2026-04-30
242
+
243
+ ### Added
244
+
245
+ - **ADR-210 P3 — `getAuthenticatedInstructions(slice)` + `getTrialEndingClause(slice)`
246
+ exports in `src/server-instructions.ts`.** New helpers that optionally append
247
+ a state-conditional trial-ending nudge to the authenticated handshake
248
+ instructions. The clause fires only when `billing_state === 'trial'` AND
249
+ `trial_days_remaining` is non-null AND `<= 3`; in all other cases the
250
+ function returns the unchanged base const. Pass `null` when no slice is
251
+ available — slice-less callers fail safe. Existing
252
+ `SERVER_INSTRUCTIONS_AUTHENTICATED` const is unchanged (parity with
253
+ `lib/mcp/server-instructions.ts` preserved).
254
+ - **New `TrialNudgeSlice` interface export.** Minimal shape consumed by
255
+ the helper: `{ billing_state: string; trial_days_remaining: number | null }`.
256
+ Structurally compatible with the platform's `OrgBillingSlice` type so
257
+ callers can pass either.
258
+
259
+ ### Note on stdio behaviour
260
+
261
+ The stdio binary in this release continues to call the equivalent of
262
+ `getAuthenticatedInstructions(null)` at boot (returns the unchanged const) —
263
+ trial state is not resolvable at boot without a `pica.catalogStats()` round
264
+ trip. Stdio agents still see live `trial_days_remaining` via
265
+ `_meta.session_state` on every write-tool result. A future phase may add
266
+ boot-time slice resolution; this release ships the helper itself so the
267
+ HTTP transport (`/api/mcp`) can use it immediately on a per-request basis.
268
+
269
+ ## [2.40.0] - 2026-04-30
270
+
271
+ ### Changed
272
+
273
+ - **ADR-214 W4 — `workflows` field is now required on `ToolDefinition`.**
274
+ Flips the optional `workflows?: WorkflowTag | WorkflowTag[]` field
275
+ introduced in W1 to a required `workflows: WorkflowTag | WorkflowTag[]`.
276
+ TypeScript compilation now enforces that every new tool authored
277
+ declares its workflow membership at the source site — no escape
278
+ hatch except the explicit `"infrastructure"` opt-out. Drift
279
+ prevention mechanism #1 from ADR-214 §"Drift prevention" is now
280
+ fully load-bearing. `lint-required-schemas.ts` hardened: the
281
+ parallel-window warning for untagged tools becomes a hard error
282
+ (defence-in-depth in case a tool somehow reaches the registry
283
+ without a `workflows` field at runtime).
284
+
285
+ ### Added
286
+
287
+ - **ADR-214 W2 — agent-guide + required-fields schema resources.**
288
+ Two new resource families on the catalog `mcp-server`:
289
+ - `pica://docs/agent-guide` — workflow narrative for agents. Visible
290
+ in both lobby and authenticated modes; content branches on
291
+ `lobbyMode`. Lobby variant (~865 bytes) covers the signup → magic
292
+ link flow + what unlocks. Authenticated variant (~4.3 KB) lists the
293
+ five core workflows (register a work, add a recording, add audio,
294
+ add recording credits, enrich metadata) with verbatim tool sequences
295
+ and 8 common gotchas — verified against the live tool registry on
296
+ 2026-04-30.
297
+ - `pica://schemas/work-required`, `pica://schemas/recording-required`,
298
+ `pica://schemas/work-credits-required`,
299
+ `pica://schemas/recording-credits-required`,
300
+ `pica://schemas/person-required` — JSON contracts derived at build
301
+ time from each tool's `inputSchema` (in `ToolRegistry`) joined with
302
+ `schema-mirror.json` for live CHECK constraint enums. Authenticated
303
+ mode only.
304
+ - **Build-time generator + schema mirror.**
305
+ - `mcp-server/scripts/build-required-schemas.ts` — runs as part of
306
+ `npm run prebuild` (chained after `bundle-apps.ts`); reads
307
+ `required-schemas.source.ts` + `ToolRegistry` + `schema-mirror.json`
308
+ and emits the deterministic `required-schemas.generated.ts`
309
+ (committed to git so PR diffs surface drift, per
310
+ `feedback_type_regen_cumulative_drift`).
311
+ - `mcp-server/src/resources/schema-mirror.json` — committed snapshot
312
+ of CHECK constraint enums for `works`, `recordings`, `work_credits`,
313
+ `recording_credits`, `audio_files`. Refresh via
314
+ `mcp-server/scripts/refresh-schema-mirror.ts` (humans only; CI never
315
+ auto-regenerates).
316
+ - **Inverse-coverage CI lint (`scripts/lint-required-schemas.ts`).**
317
+ Walks `ToolRegistry` and `REQUIRED_SCHEMAS_SOURCE` from both
318
+ directions: every tool whose `workflows` field tags it for a workflow
319
+ must appear in the source file; every source reference must resolve
320
+ to a real tool. During the parallel-development window (W1 still in
321
+ flight), tools missing the `workflows` field emit a single summary
322
+ warning (per coordinator decision Stage 1 §R2). Once W4 makes the
323
+ field required, the warning becomes an error.
324
+ - **Agent-guide drift lint (`scripts/lint-agent-guide.ts`).** Greps
325
+ every `pica_*` token in `agent-guide.ts` against `ToolRegistry` (in
326
+ both `discoveryMode` settings, so meta-tools like `pica_discover` are
327
+ resolvable). Catches stale references after tool renames.
328
+ - **Meta-tests** for both lints (per `feedback_meta_test_load_bearing`):
329
+ 3 / 3 regressions caught and reverted before ship — see
330
+ `docs/follow-ups/2026-04-30-adr214-w2-meta-test-outcomes.md`.
331
+
332
+ ### Changed
333
+
334
+ - `mcp-server/package.json` — `prebuild` now chains
335
+ `bundle-apps.ts && build-required-schemas.ts`. New scripts
336
+ `lint:required-schemas` and `lint:agent-guide` added; both wired into
337
+ `prepublishOnly` after the existing checks.
338
+ - `mcp-server/src/resources/index.ts` — registers 6 new URIs across
339
+ `listResources()` (1 in the lobby branch, 5 in the authenticated
340
+ branch) and `readResource()` (1 case for the agent-guide variant
341
+ branch, 5 cases for the schema URIs).
342
+
343
+ ### Dependencies
344
+
345
+ - `pg` + `@types/pg` added as devDependencies (used only by
346
+ `refresh-schema-mirror.ts` for direct Postgres CHECK-constraint pulls
347
+ against staging).
348
+
349
+ ### Internal
350
+
351
+ - **ADR-214 W1 — `WorkflowTag` type + optional `workflows` field on tool
352
+ definitions.** Adds a union type
353
+ (`"work-required" | "recording-required" | "work-credits-required"
354
+ | "recording-credits-required" | "person-required" | "infrastructure"`)
355
+ and a `workflows?: WorkflowTag | WorkflowTag[]` field to
356
+ `ToolDefinition` at `mcp-server/src/tools/index.ts`. All 231 tools now
357
+ carry the field — 8 catalog-core tools (`pica_works_create`,
358
+ `pica_works_update`, `pica_recordings_create`,
359
+ `pica_recordings_update`, `pica_people_create`, `pica_people_update`,
360
+ `pica_credits_update`, `pica_recording_credits_update`) reference one
361
+ or more Phase 1 workflows; the remaining 223 carry
362
+ `"infrastructure"`. Field is optional in W1 to keep the rollout
363
+ additive; W4 (post-merge of W1 + W2 resource scaffolding) flips it to
364
+ required so every future tool is forced to declare its workflow at
365
+ compile time. No runtime behaviour change in this release.
366
+
367
+ ## [2.39.0] - 2026-04-30
368
+
369
+ ### Added
370
+
371
+ - **ADR-211 Phase 1 — `pica_signup_start` unauthenticated tool.** New
372
+ agent-discoverable signup verb available without a connection key on
373
+ both stdio (lobby mode) and HTTP `/api/mcp` (anonymous mode). Mints
374
+ nothing locally — every invocation calls
375
+ `POST /api/public/onboarding/signup-start` so the
376
+ `ONBOARDING_TOKEN_SECRET` signing secret stays on the backend, never
377
+ in customer-distributed binaries. Returns a 15-minute JWT-bound
378
+ `/onboard/<token>` URL via `resource_link` (universal floor) +
379
+ capability-gated `elicitation/create url` (mode: "url"). Constructor
380
+ takes `{apiUrl, transport, clientId?}` — stdio binary stamps
381
+ `transport: "stdio"`, the HTTP carve-out stamps `transport: "http"`
382
+ and threads through any DCR `client_id` for OAuth resume.
383
+
384
+ - **`SERVER_INSTRUCTIONS_UNAUTHENTICATED` lobby variant.** Short
385
+ ~600-char handshake text pointing the agent at the 3 lobby tools
386
+ (`pica_signup_start`, `pica_sign_in`, `pica_sign_out`) instead of the
387
+ full 200+ catalog surface. Selected at boot when `lobbyMode === true`
388
+ (stdio binary without `PICA_API_KEY`) and at handshake when
389
+ `/api/mcp` is invoked without a Bearer token. Catalog-tool guidance
390
+ omitted because no catalog tools are reachable in lobby mode.
391
+
392
+ - **`SERVER_INSTRUCTIONS_AUTHENTICATED` alias** of the legacy
393
+ `SERVER_INSTRUCTIONS` export — the unaliased symbol stays exported
394
+ unchanged for backward compatibility.
395
+
396
+ ### Changed
397
+
398
+ - **Lobby surface is now THREE tools** (was two): `pica_signup_start`
399
+ joins the existing `pica_sign_in` + `pica_sign_out` pair. Additive,
400
+ not replacement — Phase 1 evaluates consolidation in Phase 2 once
401
+ the `/onboard/<token>` page is live and the JWT-bound flow is the
402
+ preferred path. ADR-211 § Primitive A editorial amendment 2026-04-30
403
+ reflects this.
404
+
405
+ ### Notes
406
+
407
+ - **`ONBOARDING_TOKEN_SECRET` env var required** on backend
408
+ environments (preview + prod already provisioned 2026-04-30). The
409
+ `lib/auth/scoped-jwt.ts` substrate gained an additive
410
+ `options.secretEnvVar` parameter so each scoped-JWT consumer
411
+ (upload-token, onboarding-token, future ADR-214 storage-config) can
412
+ rotate its signing secret independently. SUPABASE_JWT_SECRET still
413
+ serves as the local-dev fallback in both modes.
414
+
415
+ - **No new exports in `@withpica/mcp-utils` or `@withpica/mcp-sdk`** —
416
+ Phase 1 consumes existing exports (`clientSupportsUrlElicitation`,
417
+ `CallerContext`) only. Per
418
+ `feedback_workspace_package_publish_discipline.md`: no bumps needed
419
+ upstream of this release.
420
+
421
+ ## [2.38.0] - 2026-04-30
422
+
423
+ ### Added
424
+
425
+ - **ADR-208 Phase 3 Primitive D — `pica_release_show` rich-render tool.**
426
+ The catalog's first MCP tool returning `image` + `text` content blocks
427
+ in a single agent turn. Cover art ships as a base64 JPEG ≤512px;
428
+ markdown summary covers title, year, primary artists, label name, UPC,
429
+ catalog number, and tracklist with ISRCs and durations. Read-only
430
+ (`readOnlyHint: true`). Registered in
431
+ `mcp-server/src/tools/discovery.ts` `CATEGORIES.releases.tools` in
432
+ the same commit as the `ToolRegistry` registration per the layered-
433
+ discovery completeness rule.
434
+ - **`_meta.ui.resourceUri = "ui://pica/release"`** — MCP Apps clients
435
+ (Claude Desktop, Cursor) render the iframe via the new resource at
436
+ `mcp-server/src/apps/release.ts`. Phase 3 ships the resource stub
437
+ (title + markdown + cover image binding); full interactive iframe
438
+ with track-list expand and inline streaming embeds is queued under
439
+ the ADR-200 Phase 1.x backlog.
440
+ - **`structuredContent`** envelope — `{ title, markdown, cover_base64,
441
+ cover_mime_type, resource_link_uri }`. Apps clients prefer this over
442
+ re-decoding the image content block; non-Apps clients ignore it.
443
+
444
+ ### Notes
445
+
446
+ - **Universal floor is `image + text` only in Phase 3.** A `resource_link`
447
+ block is intentionally omitted because no release UI page exists in
448
+ the codebase yet (verified — neither `/portal/releases/[id]` nor
449
+ `/admin/releases/[id]`). Building one is queued under
450
+ `docs/follow-ups/2026-04-30-adr208-phase3-5-release-detail-page.md`
451
+ and ADR-208 § Primitive D was editorially amended on develop
452
+ (`30ceefc9d`) to reflect the deferral.
453
+ - **"Key credits" deferred from the markdown body.** The existing
454
+ `releasesService.listTracks()` join surfaces work + recording artist
455
+ but not `work_credits`; adding the join widens Phase 3 scope. Will
456
+ land alongside ADR-213 when credit-attribution surfaces consume the
457
+ data cheaply.
458
+ - **Sharp lives in the main Next.js app, not in this stdio binary.**
459
+ Cover-art bytes come from the new `/api/admin/releases/[id]/cover-art-thumbnail`
460
+ endpoint that does the resize + cache server-side, so the
461
+ customer-distributed `@withpica/mcp-server` install stays free of
462
+ sharp's ~50MB platform-specific native binaries.
463
+
464
+ ### Changed
465
+
466
+ - **Bumps `@withpica/mcp-sdk` peer to ^1.17.0** to consume the new
467
+ `ReleasesResource.getCoverArtThumbnail()` method.
468
+ `@withpica/mcp-utils` stays at ^1.12.0 (T2.4's bump absorbed via the rebase).
469
+
470
+ ## [2.37.0] - 2026-04-30
471
+
472
+ ### Added
473
+
474
+ - **ADR-210 Phase 2 — `pica_subscription_status` and `pica_subscription_manage`.**
475
+ Two new tools shipping the explicit billing read + action surface
476
+ that complements Phase 1's ambient `_meta.session_state.billing_slice`.
477
+ - `pica_subscription_status` (`readOnlyHint: true`) wraps the
478
+ existing `GET /api/admin/subscription` route and flattens it into
479
+ the 9-field shape ADR-210 § Phase 2 specifies (`billing_state`,
480
+ `trial_days_remaining`, `trial_ends_at`, `current_tier`,
481
+ `capacity_used`, `capacity_limit`, `capacity_pct`,
482
+ `recommended_tier`, `summary`). The `summary` line is a
483
+ server-side template the agent uses verbatim — predictable
484
+ wording, less variance across connectors.
485
+ - `pica_subscription_manage` (`readOnlyHint: false`) is a single-verb
486
+ dispatcher over the existing `POST /api/admin/subscription`
487
+ (subscribe / upgrade) and `POST /api/admin/subscription/portal`
488
+ (manage / cancel) routes. Returns `{url, expires_at, surface}`.
489
+ Subscribe / upgrade without `tier` returns a recoverable error
490
+ with `next_tool: pica_subscription_status` so the agent can
491
+ chain to read `recommended_tier` first rather than auto-pick.
492
+ Universal-floor `resource_link` content block ships on every
493
+ success response per ADR-200 Phase 1; `elicitation/create url`
494
+ fires only when `clientSupportsUrlElicitation(server)` (the
495
+ capability gate is mandatory because `elicitInput` with
496
+ `mode: "url"` throws synchronously against non-supporters per
497
+ `feedback_mcp_sdk_capability_gates_elicitation.md`).
498
+ - **`subscription` category in `discovery.ts:CATEGORIES`** ("view your
499
+ billing state, manage your subscription, and pick a tier"). Lint
500
+ enforced by `scripts/lint-mcp-tools.ts` per
501
+ `feedback_mcp_taxonomy_completeness.md`.
502
+
503
+ ### Changed
504
+
505
+ - **Bumps `@withpica/mcp-sdk` peer to ^1.16.0** to consume the new
506
+ `SubscriptionResource`. `@withpica/mcp-utils` stays at ^1.12.0
507
+ (T2.4's bump absorbed via the rebase).
508
+
509
+ ## [2.36.0] - 2026-04-30
510
+
511
+ ### Added
512
+
513
+ - **ADR-213 Primitive A — `pica_recordings_create` post-create attribution hints.**
514
+ Every successful create call now appends up to three Important-severity
515
+ hints via the new `buildRecordingAttributionHints(recording)` helper
516
+ (`mcp-server/src/tools/recording-attribution-hints.ts`). Mirror of
517
+ `buildCustodyHints` for works:
518
+ - `recording_ownership_unset` — fires when `ownership_percentage IS NULL`.
519
+ Suggests `pica_recordings_update ownership_percentage:N`.
520
+ - `recording_no_credits` — always fires (we never know credits from a
521
+ single fresh row). Suggests the new `pica_recording_credits_update`.
522
+ - `recording_master_unclaimed` — fires when `ownership_percentage IS NULL`.
523
+ Alternative path for multi-party master claims via `pica_custody_claim`.
524
+ NULL-only triggers: `0` is "explicit zero", no hint. Negative-path
525
+ covered by jest at `recording-attribution-hints.test.ts` per
526
+ `feedback_meta_test_load_bearing.md`.
527
+ - **ADR-213 Primitive B — `pica_recording_credits_update`.** First-party
528
+ recording-side write tool; closes the work/recording credit-write
529
+ asymmetry. Writes to `recording_credits` (NOT the trade-secret
530
+ enrichment-cascade-fed `credits` table — see `.claude/rules/ip-protection.md`).
531
+ Uses the 16-role `RECORDING_CREDIT_ROLES` enum (`MainArtist`,
532
+ `FeaturedArtist`, `Producer`, `Mixer`, `Engineer`, ... `Other`).
533
+ Songwriting credits (Writer, Composer, Lyricist, Arranger as a publishing
534
+ role) continue to route through `pica_credits_update` on the parent work.
535
+ Registered in `discovery.ts` `CATEGORIES.credits` in the same commit per
536
+ `feedback_mcp_taxonomy_completeness.md`. Listed under `write:catalog` scope
537
+ in `lib/services/mcp-scopes.ts`. `nextSteps` points at
538
+ `pica_recordings_inspect sections:["recording_credits"]` for ADR-198
539
+ round-trip verification.
540
+ - **ADR-213 Primitive A.1 — `pica_recordings_inspect recording_credits`
541
+ section.** Additive (not replacement). The existing `credits` section
542
+ (work-side credits via parent work) keeps its current behaviour. New
543
+ `recording_credits` section reads first-party operator-authored credits
544
+ directly from the `recording_credits` table via the new
545
+ `pica.recordingCredits.list()` SDK method.
546
+ - **`TOOL_METADATA` entry for `pica_recording_credits_update`** in
547
+ `mcp-server/src/tools/metadata.ts` (catalog/mutating/non-retry-safe).
548
+
549
+ ### Changed
550
+
551
+ - **Bumps `@withpica/mcp-sdk` peer to ^1.15.0** and `@withpica/mcp-utils` to
552
+ ^1.12.0 to consume the new `RecordingCreditsResource` and the metadata
553
+ entry shipped alongside ADR-213.
554
+ - **Tool count moves from 224 → 225** with the addition of
555
+ `pica_recording_credits_update`.
556
+
557
+ ## [2.35.0] - 2026-04-29
558
+
559
+ ### Added
560
+
561
+ - **ADR-208 Phase 2 — `pica_upload` returns a JWT-bound `/upload/<token>` URL.**
562
+ The executor now calls `pica.uploads.createSession()` for server-side
563
+ mint of a 600s-TTL HS256 JWT scoped to the caller's org / user /
564
+ bucket-key / acceptFilter. Universal floor (`resource_link`) and
565
+ capability-gated `elicitation/create url` shapes unchanged — only the
566
+ URL flips from `${webBase}/workspace` to `${webBase}/upload/<jwt>`.
567
+ Tool description updated; obsolete Phase 1.5 forward-reference removed.
568
+
569
+ ### Changed
570
+
571
+ - **`session_state.pending_uploads` now reads from
572
+ `organisations.pending_uploads_count`** (atomic +1 on JWT mint via
573
+ `/api/admin/uploads/sessions`, atomic -1 on JWT-path completion via
574
+ `/api/upload/[token]`). Phase 1's stub at `0` is gone. Atomic semantics
575
+ via the `inc_pending_uploads` SECURITY DEFINER RPC; `GREATEST(0, ...)`
576
+ clamp prevents negative drift. Sits alongside T1.2's billing fields on
577
+ the same `_meta.session_state` envelope — no shared edit to
578
+ `mcp-server-shared/mcp-utils/src/session-state.ts`.
579
+
580
+ ### Notes
581
+
582
+ - Fail-soft: if `createSession()` throws (network blip, route 5xx), the
583
+ executor falls back to the legacy workspace URL and surfaces the error
584
+ in the `text_summary`. The card still works for MCP Apps clients via
585
+ `_meta.ui.resourceUri` regardless.
586
+
587
+ ### Bumped
588
+
589
+ - `@withpica/mcp-sdk` dependency range bumped to `^1.14.0`
590
+ (`UploadsResource`, `CreateUploadSession*` types,
591
+ `CatalogStats.pending_uploads_count` now consumed).
592
+ - `@withpica/mcp-utils` dependency range bumped to `^1.11.0`
593
+ (T1.2's billing-fields extension on `SessionStateCounts`).
594
+ - `mcp-server/server.json` registry manifest version bumped to `2.35.0`
595
+ in lockstep with the npm package.
596
+
597
+ ## [2.34.0] - 2026-04-29
598
+
599
+ ### Added
600
+
601
+ - **ADR-210 Phase 1 — billing slice on `_meta.session_state`.** The
602
+ `fetchSessionCounts` private in `ToolRegistry` now resolves the four
603
+ billing fields (`billing_state`, `trial_days_remaining`, `current_tier`,
604
+ `capacity_pct`) from `pica.catalogStats().billing_slice` alongside the
605
+ existing counts. `attachSessionState` flows them onto every successful
606
+ write-tool result through the same `_meta.session_state` envelope (no
607
+ new emission path — extends the existing one) so the agent sees ambient
608
+ billing posture between mutations without a `pica_subscription_status`
609
+ round-trip. Phase 2 will land that explicit read tool; Phase 1 ships
610
+ the substrate the tool reads from.
611
+ - Same fail-soft posture as the existing fetcher: when `this.pica` is
612
+ missing (HTTP-discovery without bearer scope), or when the SDK response
613
+ is missing `billing_slice` (older server pre-Phase-1), the fetcher
614
+ emits a conservative `{ billing_state: "trial", trial_days_remaining:
615
+ null, current_tier: null, capacity_pct: 0 }` rather than fabricating
616
+ "active" — the agent never sees misleading "active" billing for an
617
+ uninitialized context.
618
+
619
+ ### Bumped
620
+
621
+ - `@withpica/mcp-sdk` dependency range bumped to `^1.13.0`
622
+ (`CatalogStats.billing_slice` field now consumed).
623
+ - `@withpica/mcp-utils` dependency range bumped to `^1.11.0`
624
+ (`SessionStateCounts` shape extended with `BillingSlice` fields).
625
+ - `mcp-server/server.json` registry manifest version bumped to `2.34.0`
626
+ in lockstep with the npm package.
627
+
628
+ ## [2.33.0] - 2026-04-29
629
+
630
+ ### Added
631
+
632
+ - **ADR-208 Primitive B — `_meta.session_state` attached to write-tool results.**
633
+ The central `ToolRegistry.executeTool` wrapper now composes the six-key
634
+ session-state envelope (`works_count`, `recordings_count`,
635
+ `completeness_pct`, `mutations_this_session`, `since_last_briefing`,
636
+ `pending_uploads`) for every tool whose risk is `mutating` or
637
+ `destructive` (`readOnlyHint: false`), and attaches it under
638
+ `result._meta.session_state`. Read tools (`risk: safe`) skip this
639
+ entirely so the high-volume read path stays cheap; failed mutations
640
+ (`isError: true`) also skip because catalog state didn't change.
641
+ `pica_dashboard_briefing` running successfully resets the
642
+ `since_last_briefing` counter — handled in the wrapper, not the tool.
643
+ Cache key is org-scoped via `config.picaApiKey` (stdio) or
644
+ `callerContext.callerIdentity` (HTTP); two orgs sharing a worker
645
+ process never share state. Fail-open: any error in session-state
646
+ composition is swallowed and the result returns without `_meta.session_state`.
647
+ See `@withpica/mcp-utils@1.10.0` for the underlying `buildSessionState`
648
+ helper and the load-bearing cross-org isolation regression test.
649
+
650
+ ### Changed
651
+
652
+ - Bump `@withpica/mcp-utils` dep range to `^1.10.0` to pick up the
653
+ `buildSessionState` / `incrementSessionMutations` /
654
+ `resetSinceLastBriefing` exports that compose Primitive B.
655
+
656
+ ## [2.32.0] - 2026-04-28
657
+
658
+ ### Changed
659
+
660
+ - Bump `@withpica/mcp-utils` dep range to `^1.9.0`. The previously-pinned `^1.8.0`
661
+ resolved (via the npm registry) to a tarball that pre-dated the addition of
662
+ `clientSupportsUrlElicitation` and `elicitBulkConfirmation` to the source — Vercel
663
+ builds where the lockfile resolved from registry instead of the local workspace
664
+ link failed with `TS2305`. 1.9.0 republishes the same source state with both
665
+ exports present, so registry-pinned lockfiles now build cleanly without needing
666
+ the workspace-link override.
667
+
668
+ ## [2.31.0] - 2026-04-28
669
+
670
+ ### Added
671
+
672
+ - **ADR-200 Phase 1 — `ToolExecutorContext` plumbed through the registry.**
673
+ `ToolExecutor` now takes an optional second arg `(args, ctx?)` carrying the
674
+ per-request `Server` reference. `server.ts` passes `{ server }` through to
675
+ `executeTool`; the discovery dispatcher (`pica_execute`) forwards it to its
676
+ delegate. Existing executors with the legacy `(args)` signature keep working
677
+ unchanged — only tools that need `server.elicitInput()` opt into the second
678
+ arg. Pre-existing destructive-confirmation gate (two-step token) is
679
+ preserved.
680
+ - **`pica_upload` portable across non-MCP-Apps clients.** Response now ships
681
+ with a `resource_link` content block (universal MCP floor) alongside the
682
+ legacy text envelope and `_meta.ui.resourceUri` — Apps clients render the
683
+ iframe unchanged, ChatGPT / Gemini / Claude Code / curl-style clients see a
684
+ clickable link to the workspace upload page. Clients that advertised
685
+ `capabilities.elicitation.url` additionally receive a server-issued
686
+ `elicitation/create url` consent prompt; the call is gated on the new
687
+ `clientSupportsUrlElicitation` helper from `@withpica/mcp-utils@1.8.0` so
688
+ callers without the capability never see the SDK's synchronous
689
+ "Client does not support url elicitation" throw. `elicitationId` is a
690
+ per-call UUID. Universal floor remains usable when the user declines or the
691
+ elicitation times out — the resource_link in the response is the fallback.
692
+ - **`pica_download` ships a `resource_link` for the signed file URL.** Same
693
+ universal-floor improvement on the download surface — text envelope still
694
+ carries the JSON shape ADR-152 cards expect, plus the new resource_link
695
+ exposes the URL/filename/mime to clients that render link blocks.
696
+ - **ADR-200 Phase 1 — form-confirmation gate on the 4 customer-MCP Class D
697
+ bulk tools** (`pica_works_bulk_update`, `pica_people_bulk_update_roles`,
698
+ `pica_recording_splits_create`, `pica_collaborators_invite_bulk`). Each
699
+ now calls `elicitBulkConfirmation` from `@withpica/mcp-utils@1.8.0`
700
+ after the validation + dry_run paths but before persisting. The gate
701
+ fires only when the connected client advertises
702
+ `capabilities.elicitation`, and in that case the destructive write only
703
+ proceeds if the form returns `accept` with `confirm: true`. Universal
704
+ floor: clients without elicitation continue to execute as before
705
+ (existing destructive-token gate, where applicable, remains
706
+ authoritative). 11 new tests cover decline, accept-without-confirm,
707
+ no-caps fallback, and dry_run-skips-elicitation across the four tools.
708
+ `team_comms_send` (5th Class D tool) is gated in
709
+ `@withpica/team-mcp-server@1.3.0`.
710
+ - **`ToolResult.content` widened to permit `resource_link` blocks.** Legacy
711
+ `Array<{ type, text }>` shape kept compatible via a structural union; tools
712
+ that only return text need no changes.
713
+
714
+ ### Changed
715
+
716
+ - **Tool descriptions for `pica_upload` / `pica_download` updated** to point
717
+ at the ADR-200 fallback ladder rather than the prose "tell the user to use
718
+ the workspace dashboard" hint that ADR-152 originally shipped. Behaviour
719
+ for MCP Apps clients is unchanged.
720
+
721
+ ### Removed
722
+
723
+ - **9 nested `withCreditGate(...)` wrappers unwrapped** across `tools/audio-files.ts` (2), `tools/exports.ts` (3), and `tools/enrichment.ts` (4). Each always ran inside a `withBillingGate(...)`; the inner wrapper was a no-op shim retained since ADR-162 disabled credit gating. Unwrapping leaves the subscription check as the sole gate on these tools, which matches the billing model.
724
+ - **`tests/utils/credit-gate-mpp.test.ts` + `credit-gate-mpp-paths.test.ts` deleted.** Both suites exercised a disabled MPP + pay-per-credit path that no longer has any production call-sites. `tests/tools/metadata.test.ts` also drops its `credit-gated tools should have credits_required set` assertion — redundant now that `credits_required` is gone from the shared `@withpica/mcp-utils` type (companion entry in that package's CHANGELOG). `tests/tools/credits.test.ts` stale `describe("pica_credits_balance")` block (and associated `mockCreditsBalance` setup) removed — that tool was pulled from the surface 2026-04-22 but the tests were missed in that pass.
725
+ - **`src/__mocks__/mppx-server.ts` + `mppx-mcp-sdk-server.ts` deleted** and the matching `moduleNameMapper` entries removed from `jest.config.js`. Both mocks existed only to stub out `mppx` for the now-deleted MPP unit tests. The `testPathIgnorePatterns` entry pointing at `credit-gate-mpp-paths.test.ts` is also removed (ghost reference to the deleted file).
726
+ - **"credit-gated" prose stripped from tool descriptions** in `tools/app-tools.ts` (`pica_car_preview` description + carPreview reuse comment) and `tools/documents.ts` (`pica_documents_analyse` description). These strings were advertised in the tool description, telling agents a tool was "credit-gated (5 credits)" when it's actually subscription-gated at workspace level.
727
+ - **`mppx` runtime dep still listed in `package.json`** — left in place to avoid lockfile churn; no `src/` consumer remains after this commit. Next publisher should drop it and rerun `npm install` to clean the lockfile.
728
+
729
+ ## [2.30.0] - 2026-04-27
730
+
731
+ ### Added
732
+
733
+ - **`pica_audio_inspect` basic section surfaces 4 previously-invisible
734
+ columns** — `recording_id`, `stem_label`, `version_label`, and
735
+ `classification`. All four are real columns on `audio_files` written by
736
+ `pica_audio_complete_upload`. The 5th audit-flagged field
737
+ (`content_type`) is mapped to `audio_format` at write time and was
738
+ already surfaced. Closes a Phase 2 gap from the 2026-04-27 read-write
739
+ parity audit. SDK type `AudioFile` extended with the same three
740
+ optional fields (classification was already there).
741
+ - **`pica_organisation_profile` includes `org_type`** — paired read tool's
742
+ underlying `/admin/settings/organisation-profile` SELECT now returns
743
+ the CHECK-enum value that `pica_update_organisation_profile` already
744
+ accepted (publisher / label / pro / sync_library / client / venue /
745
+ distributor / other). Same class as the settings/identity fan-out
746
+ fixed in 2.29.0 — write side accepted, read side truncated.
747
+ - **`pica_physical_assets_inspect` adds a `links` section** — surfaces
748
+ the typed-edge rows that `pica_physical_assets_link_work` and
749
+ `pica_physical_assets_link_recording` write to `work_production_assets`
750
+ and `recording_production_assets`. Pre-fix the link rows were
751
+ write-only from the MCP surface even though both
752
+ `/admin/assets/[id]/{work,recording}-links` GET endpoints already
753
+ existed. SDK gains `assets.listWorkLinks(id)` and
754
+ `assets.listRecordingLinks(id)`.
755
+ - **`dry_run` flag on three more Class D mutating tools** —
756
+ `pica_recording_splits_create`, `pica_collaborators_invite_bulk`,
757
+ and `team_comms_send`. Completes the Class D coverage started in the
758
+ ADR-199 5a part 1 commit (`a10006e5b`). Each tool early-returns
759
+ `{ dry_run: true, would_affect, sample / target_count }` after
760
+ validation and before the mutating SDK call, so agents can preview
761
+ bulk effects and external-comms dispatch before committing. For
762
+ `team_comms_send`, the preview echoes recipient and length-only
763
+ metadata; the message body is not surfaced to keep ops messaging
764
+ off the dry-run trace.
765
+
766
+ ### Fixed
767
+
768
+ - **`pica_recordings_inspect` no longer hallucinates into the void on 404.**
769
+ ADR-198 verification 2026-04-26 found the inspect tool was returning 200
770
+ with `recording_error: "API request failed: 404 ..."` for every missing
771
+ entity / missing route handler. Agents read this as a successful empty
772
+ result and proceeded to call downstream sections (credits, audio) that
773
+ also 404'd silently — no Sentry alert, no audit row, no user-visible
774
+ error. Fix: basic-section catch now re-throws `EntityNotFoundError`
775
+ (new typed export from `@withpica/mcp-sdk` 1.12.0+), so 404 surfaces
776
+ as a hard `isError: true` envelope. Non-404 errors on the basic fetch
777
+ still get absorbed into `recording_error` (preserves the partial-result
778
+ pattern for transient failures).
779
+
780
+ ## [2.29.0] - 2026-04-25
781
+
782
+ ### Fixed
783
+
784
+ - **94 previously-undiscoverable tools retrofitted into the layered-discovery
785
+ taxonomy.** Same bug class that bit four times in three weeks
786
+ (`pica_upload`/`pica_download` since ADR-152, `pica_submit_feedback` since
787
+ ADR-184, `pica_report_issue`/`pica_my_reported_issues` from ADR-196 Phase 3):
788
+ registered in `ToolRegistry` but absent from `CATEGORIES` in
789
+ `mcp-server/src/tools/discovery.ts`, so layered-discovery agents (default
790
+ for ChatGPT and Claude.ai connectors with `MCP_LAYERED_DISCOVERY=1`) could
791
+ not find them via `pica_discover`. The 2026-04-25 hardening that added
792
+ blocking `checkTaxonomyCompleteness` to `scripts/lint-mcp-tools.ts`
793
+ surfaced 94 grandfathered violators in the baseline. This release retrofits
794
+ every one. Fourteen new categories — `agreements`, `collaborators`,
795
+ `custody`, `physical_assets`, `recording_splits`, `royalties_statements`,
796
+ `share_links`, `split_sheets`, `licensing`, `notifications`, `messaging`,
797
+ `agent_identity`, `telegram`, `labels` — and the tools fold into existing
798
+ ones (`releases`, `analytics`, `enrichment`, `import`, `projects`,
799
+ `profile`) where they belong. `scripts/mcp-tool-lint-baseline.json
800
+ → missing_taxonomy` is now empty.
801
+ - **`pica_upload` and `pica_download` newly reachable via `pica_discover`** —
802
+ the two generic harness cards (ADR-152) had been silently absent from the
803
+ `CATEGORIES` taxonomy since they shipped. `pica_upload` added to the
804
+ existing `uploads` category alongside the programmatic `pica_upload_file` +
805
+ `pica_upload_complete` pair. `pica_download` added to the `export` category
806
+ since it's the delivery side of any export-tool flow.
807
+
808
+ ### Changed
809
+
810
+ - **`CATEGORIES` is now exported** from `mcp-server/src/tools/discovery.ts`
811
+ so `scripts/lint-mcp-tools.ts` can read it. Compile-time only; no
812
+ consumer change.
813
+
814
+ ## [2.28.1] - 2026-04-25
815
+
816
+ ### Fixed
817
+
818
+ - **`pica_report_issue`, `pica_my_reported_issues`, and `pica_submit_feedback`
819
+ were unreachable via `pica_discover`** — the layered-discovery taxonomy
820
+ in `mcp-server/src/tools/discovery.ts` did not list them in any of its
821
+ 26 categories, so agents using the layered flow (default for ChatGPT
822
+ and Claude.ai connectors that need to keep their context window
823
+ manageable) literally couldn't find these tools. Real-world failure
824
+ caught 2026-04-25: a Claude Desktop session dogfooding the issue-
825
+ reporting flow returned "no feedback or support tool exposed in the
826
+ PICA MCP" and suggested `pica_notes_create` as the closest match —
827
+ the exact failure mode `pica_report_issue` was designed to catch
828
+ (which it couldn't, because it wasn't discoverable). New `feedback`
829
+ category added to the discovery taxonomy listing all three tools.
830
+ `pica_submit_feedback` had been silently invisible since ADR-184
831
+ shipped — same bug class, same fix.
832
+
833
+ ### Changed
834
+
835
+ - **`pica_report_issue` description tightened** to instruct the agent
836
+ on WHEN to call: PROACTIVELY without being asked when the agent itself
837
+ hits a workflow gap, AND on-demand when the user says "this is broken"
838
+ / "this didn't work". Previously the description was descriptive
839
+ ("file a structured issue when…") which left agents reading it as a
840
+ passive option rather than a recommended habit. Also adds a
841
+ cross-reference to `pica_my_reported_issues` for the resolution-poll
842
+ side of the closed loop.
843
+
844
+ ## [2.28.0] - 2026-04-24
845
+
846
+ ### Added
847
+
848
+ - **ADR-196 Phase 4a — `pica_my_reported_issues` tool.** Org-scoped
849
+ customer-side polling tool that closes the loop on `pica_report_issue`.
850
+ Lets the agent answer "did anyone fix that thing I reported?" without
851
+ going through the operator surface. Returns the issue, current status,
852
+ resolution_note, and occurrence_count for each issue the calling org
853
+ has reported or been impacted by. Default sort most-recently-touched
854
+ first; optional `status` filter (open / triaged / investigating /
855
+ resolved / wont_fix). Tool metadata: `category=comms`, `risk=safe`,
856
+ `retry_safe=true`. Pairs with `@withpica/mcp-sdk@1.12.0` for the new
857
+ `OpsIssuesResource.listMine()` method.
858
+
859
+ ### Changed
860
+
861
+ - **`mcp-server/src/config.ts` VERSION constant is now derived from
862
+ `package.json`** via `createRequire(import.meta.url)("../package.json")`,
863
+ not a hardcoded literal. Drift-proof — future bumps no longer require
864
+ manual sync between the two files. The version-sync lint in
865
+ `scripts/lint-mcp-tools.ts` now accepts both forms (literal still
866
+ blocks on drift; derived is always valid). Motivated by two
867
+ consecutive publishes (2.27.0 + 2.28.0) being blocked by the stale
868
+ literal — the trap is now permanently sealed.
869
+
870
+ ### Fixed
871
+
872
+ - **`mcp-server/src/tools/discovery.ts` no longer references
873
+ `metadata.credits_required`** — the property was removed from
874
+ `ToolMetadata` in the chore/drop-mcp-credit-gating cleanup (per
875
+ ADR-162: PICA is subscription-only) but two stale references in
876
+ `discovery.ts` slipped through, blocking the publish until fixed.
877
+ No tool carries the field anymore so the conditional spread was
878
+ dead code; replaced with a comment recording the history. The
879
+ comment itself is removed in chore/drop-mcp-credit-gating
880
+ (this PR) — credit gating is gone for good.
881
+
882
+ ### Changed
883
+
884
+ - **ADR-199 Week 1 — `withBillingGate` extended to every write-tool
885
+ surface.** Previously the gate only covered `audio-files.ts`,
886
+ `exports.ts`, and `enrichment.ts` (8 tools). Now wraps 38 write
887
+ executors across 9 tool families: `agreements` (4), `agreement-types`
888
+ (5 — `renderTemplate` deliberately ungated as it's a pure read),
889
+ `custody` (4), `people` (3), `works` (5), `recordings` (3), `credits`
890
+ (1), `assets` (7 — `assetExport` deliberately ungated to match
891
+ `pica_export_catalog_csv`), and `dashboard` claim/review tools (4).
892
+ Read tools (query / list / inspect / history / search / stats /
893
+ pulse / briefing) intentionally not wrapped. Behaviour change for
894
+ agents on hibernated workspaces: write tools that previously executed
895
+ now return the lobby error. Operation labels in the lobby message
896
+ use domain terms ("agreement creation", "physical asset link",
897
+ "custody claim", "discovery review", etc.). The gate itself reads
898
+ from `organisations.billing_state` via the new effective-state route
899
+ (see `[Unreleased]` in `@withpica/mcp-utils`); `is_internal=true`
900
+ organisations bypass the gate. Rollback path is the
901
+ `ADR199_READ_BILLING_FROM_ORG` env var on the Vercel app — flipping
902
+ to `false` reverts the read source to `user_profiles.billing_state`
903
+ without an MCP redeploy.
904
+ - **ADR-199 Week 1 language sweep — agent-facing copy moves to domain
905
+ terms.** "Your organisation" / "this organisation" / "your org"
906
+ swept to "your catalog" (where the noun is the music data) or "your
907
+ account" (where no domain term fits) across `audit`, `collaborators`,
908
+ `custody`, `dashboard`, `directory`, `memory`, `metadata`,
909
+ `my-reported-issues`, `releases`, and `settings` tool descriptions.
910
+ Internal identifiers (`pica_organisation_profile`,
911
+ `pica_update_organisation_profile`, `org_type` parameter, the
912
+ `"organisation"` memory-visibility enum value) deliberately
913
+ preserved — those are wire-protocol or schema names, not copy.
914
+ Industry term "Performing rights organisation" preserved (it's a
915
+ PRO, not a withPICA org). Display names in `metadata.ts`
916
+ (`view organisation profile` / `update your organisation profile`)
917
+ swept to `view account profile` / `update your account profile`.
918
+
919
+ ## [2.27.0] - 2026-04-24
920
+
921
+ ### Added
922
+
923
+ - **ADR-196 Phase 3 — `pica_report_issue` tool.** Lets an agent file a
924
+ structured issue when a workflow breaks in a way raw tool failures can't
925
+ capture (`workflow_gap` / `inconsistent_result` / `missing_step` /
926
+ `data_issue` / `ux_confusion`). Auto-dedupes via the v2 signature
927
+ (sha256 of `"v2|{kind}|{canonicalised_summary}"`), so two reports of
928
+ the same problem with different wording collapse into one
929
+ `ops_issues` row. Operators triage from the same record. Raw tool
930
+ errors continue to auto-populate `ops_issues` via the `mcp-audit.ts`
931
+ upsert path — agents should NOT call `pica_report_issue` for those
932
+ (it would create a duplicate). Tool metadata: `category=comms`,
933
+ `risk=mutating`, `retry_safe=true`. Pairs with
934
+ `@withpica/mcp-sdk@1.11.0` and `@withpica/mcp-utils@1.7.0` published
935
+ in the same cycle.
936
+
937
+ ### Fixed
938
+
939
+ - **`config.ts` VERSION constant bumped to 2.27.0** to match the
940
+ `package.json` version. The `version-sync` lint in
941
+ `scripts/lint-mcp-tools.ts` blocked the initial 2.27.0 publish until
942
+ this was corrected — caught a pre-existing trap where the banner
943
+ version is hardcoded in source rather than derived from `package.json`
944
+ at build time. Future bumps must update both files; consider
945
+ auto-deriving in a follow-up.
946
+ - **`pica_report_issue` tool — drop double-unwrap of SDK response.**
947
+ `OpsIssuesResource.reportIssue()` now returns the unwrapped payload
948
+ (mcp-sdk@1.11.0 tightened the return type), so the tool's previous
949
+ `result?.data || result` fallback was dead code that didn't
950
+ typecheck. Now `const data = result;` directly.
951
+
952
+ ## [2.26.0] - 2026-04-22
953
+
954
+ Version leapfrogs 2.25.0 (which was published to npm without a matching commit / changelog entry in this repo, discovered during this publish cycle). 2.26.0 ships from a clean main at commit `a3c8ca870` with the full bundle below. Pairs with `@withpica/mcp-sdk@1.10.0` and `@withpica/mcp-utils@1.6.0`, both published the same day.
955
+
956
+ ### Removed
957
+
958
+ - **Billing-credit tools removed from the MCP surface:** `pica_credits_balance` (credits.ts), `pica_credits_history` (settings.ts), `pica_credits_purchase` (purchases.ts tombstoned to an empty class). See `docs/MCP_REFINEMENT_LOG.md` entry B-001. withPICA is subscription-only at £9.99/mo; surfacing a credit-balance + credit-history + credit-purchase tool trio contradicted the billing model and misled agents (caught 2026-04-22 when an agent transcript opened with "998,894 credits — plenty. Running the export now."). The underlying SDK methods (`creditsBalance.*`, `settings.creditsHistory`) and `lib/services/credits/**` infra remain intact — only the MCP tool surface shrinks. `pica_credits_list` and `pica_credits_update` are **kept**: they're work_credits (songwriter roles + splits on a work), not billing credits.
959
+ - **`CREDIT_INSUFFICIENT` recovery hints pointing at `pica_credits_balance`** removed from `recovery-hints.ts` for `pica_resolve_work`, `pica_export_song_registration`, `pica_export_catalog_asset_report`, `pica_audio_analyze`. Paired tests under `__tests__/tools/recovery-hints.test.ts` + `settings.test.ts` updated to assert the new shape.
960
+
961
+ ### Changed
962
+
963
+ - **Credit-gating language stripped from tool descriptions** — `pica_audio_identify` ("Costs 3 pica credits on match…"), `pica_export_song_registration` ("Costs 1 pica credit."), `pica_export_industry_ready` (same), `pica_export_catalog_asset_report` ("Costs 5 pica credits…"), and the 3 `pica_resolve_*` tools in `enrichment.ts` ("Costs 1 pica credit per call."). The `withCreditGate` / `withBillingGate` runtime wrappers are **left in place** — only the agent-facing prompt-gating copy goes. Same B-001 refinement entry.
964
+ - **Server instructions** (`src/server-instructions.ts`, mirrored in `lib/mcp/server-instructions.ts` via the parity test) open with a one-line disambiguation from `@picahq/mcp` (Pica AI / picaos.com) — a different product whose short name collides with ours. Helps agents that have both connectors installed (or users who pasted their withPICA key into the wrong config) recognise which server they're actually talking to. See the picaos name-collision memory rule.
965
+ - **`pica_catalog_diligence` now returns structured JSON** instead of failing with a JSON-parse error on binary ZIP bytes. The fix lives in `@withpica/mcp-sdk`'s `AnalyticsResource.catalogDiligence()` — the SDK now requests `?format=json`. See the mcp-sdk CHANGELOG for detail. MCP refinement log: "Singleton — `pica_catalog_diligence` returns ZIP parsed as JSON".
966
+
967
+ ### Fixed
968
+
969
+ - **ADR-174 Phase 2c — inverse phantom in `pica_works_update` (works slice).** Three jsonb compliance fields (`ai_disclosure`, `provenance_attestation`, `training_rights`) are satellite-routed to `work_licensing` via `WORK_SATELLITE_FIELDS` and accepted by both the HTTP route allow-list and the service layer, but were missing from `WORK_WRITE_PROPERTIES`. Agents following the `pica_works_update with ai_disclosure: ...` completion hint at works.ts:577 were hitting schema-level silent-drop (or strict-validator 400s). Added all three properties to the write schema with shapes copy-pasted from the parallel fields on `pica_recordings_update` (recordings.ts:193). Tool description updated to distinguish audio-trait satellite fields (still not exposed) from the three compliance satellite fields (now exposed). Full audit of the other 22 customer-MCP write tools yielded zero further inverse phantoms — see `docs/audits/2026-04-21-mcp-inverse-phantom-audit.md`.
970
+
971
+ ### Added
972
+
973
+ - **ADR-189 Phase 4 slice 3: `pica_claim_artist` MCP tool.** INSTANT path for artist-claim on discovery-backed evidence. Wraps `artistClaimingService.processClaimDecision` to reuse the existing `work_claims.artist_claim_status` / `claimed_by_person_id` / `claim_confirmed_at` update path + `performer` work_credits insert. Refuses (409 `ADMIN_REVIEW_IN_PROGRESS`) when an open admin `artist_claims` row exists for the same (work, person) — returns `admin_review_id` in the body so the agent surface can route the user to resolve it. Rate-limited to 20/hour per user via the shared `claim_write` bucket. Wrapped in `withAgentActionStamp` when grant-authed — rollback captures pre-write `work_claims` row + tracks whether a new performer credit was inserted (deleted on compensation) or pre-existed (left alone). **Schema drift carryover:** the plan proposed capturing rollback state from 4 `works` columns, but live staging (`rtxcxazevrgcjnudvggf`) keeps the artist-claim lifecycle columns (`artist_claim_status`, `claimed_by_person_id`, `claim_confirmed_at`) on the `work_claims` satellite — only `primary_artist_id` lives on `works`. Service captures + restores from `work_claims` accordingly. The live `artist_claims.claim_status` CHECK constraint has no `under_review` state (only `pending | approved | rejected | withdrawn`), so the open-review gate checks `claim_status = 'pending'` only.
974
+
975
+ ### Removed
976
+
977
+ - **ADR-154 F13: seven deprecated per-source enrich tools removed.** `pica_enrich_work_{mlc,musicbrainz,discogs,spotify,youtube}` and `pica_people_enrich_{isni,musicbrainz}` (tombstoned since ADR-179 Phase 1/2, 2026-04-17) are no longer registered — every call has returned a `-32070 TOOL_DEPRECATED` error for a full minor cycle, ending the one-minor deprecation window per ADR-179 Decision 2. Callers must use `pica_resolve_work(sources: [...])` or `pica_resolve_person(sources: [...])` instead; the `tools/list`, `metadata`, `recovery-hints`, and category-`discovery` surfaces shed the seven stale entries in this release. Downstream impact: clients that hardcoded the tool names now get `tools/list`-level absence rather than a deprecation envelope — fail-fast instead of fail-with-suggestion.
978
+
979
+ ### Changed
980
+
981
+ - **ADR-154 F14: completion-hint sweep for the seven removed tools.** Updated every `→ then:` and hint-string reference that pointed at the F13 tombstones across `enrichment.ts`, `people.ts` (3 sites), `collaborators.ts`, `works.ts` (2 sites), `search.ts`, `server-instructions.ts`, `prompts/index.ts` (3 sites), and `resources/llms-primer.ts`. Agents discovering tools via descriptions will no longer be trained toward dead tool names. The ADR-179 "Replaces the five/two per-source tools" phrasing is gone from the resolver descriptions too — resolvers stand on their own now.
982
+ - **ADR-180 Phase 3: full TOOL_METADATA coverage.** 29 tools retrofitted in `mcp-server/src/tools/metadata.ts` across eight family-scoped commits — resolve (3), cascade (3), enrichment proposals (4), collaborators (4), notify-user scheduling (3), physical-assets links (4), misc singletons (5), and the ADR-185 Part 1 agent-identity drift (3). `scripts/mcp-tool-lint-baseline.json` is deleted; MCP Tool Lint now runs in fully-strict mode. No behaviour change — tool discovery, audit categorisation, and risk-tier gating now classify the same 29 tools they couldn't classify before. `credits_required` deliberately omitted from new entries (credit gating is a no-op pass-through since ADR-162). Retry-safety follows ADR-180's `risk × retry_safe` table — e.g. `pica_enrichment_proposal_apply` is `retry_safe: false` (writes to entity columns), `_reject` is `retry_safe: true` (content-hash suppression is set-once). ADR-180 flipped from `Proposed` to `Accepted`.
983
+ - **ADR-193 Surfaces 1+3: peer-connector coaching + URI source conventions (server-instructions addendum).** Handshake copy coaches agents to check peer MCPs (email / drive / notes / calendar / DAW) before asking users to paste or type data, and to cite findings via `pica_enrichment_propose` `sources[].url` using URI schemes — `gmail://` `gdrive://` `notion://` `file://` `telegram://` `calendar://` `daw://` `user://` `web://`. See `docs/mcp-source-uri-conventions.md` in the main repo for shapes. First concrete build for ADR-190 Principles 2 + 3 (Agent-Mediated Source Discovery). A latent HTTP-transport gap was fixed in the same develop commit (`63eef17f8`) — `/api/mcp/route.ts` was not wiring `SERVER_INSTRUCTIONS` into its Server constructor, so remote agentic clients (ChatGPT Apps, Claude Desktop remote, Cursor) saw zero coaching. The stdio transport in this package was always serving instructions correctly; only the remote transport was affected.
984
+
985
+ ### Added
986
+
987
+ - **ADR-193 Surface 2: `gap_hints` envelope on 4 read tools.** `pica_works_inspect`, `pica_agreements_inspect`, `pica_people_inspect`, and `pica_enrichment_proposals_list` now emit an optional `gap_hints[]` field on `structuredContent` when a real gap is present. Each hint is capability-named (ADR-190 Principle 2 — `email_search` / `drive_search` / `filesystem_search` / `notes_search` / `calendar_search` / `web_search`, never vendor names), carries a concrete `query_shape`, and pre-fills the `then_call: "pica_enrichment_propose"` with the exact `then_args_shape` the agent should emit back (including URI-citation scaffolding from Surface 3). Gated by `MCP_GAP_HINTS_ENABLED=1` — off by default in prod. Empty array / omitted envelope when there's no real gap. Flat additive — the existing `CompletionHint` pipeline on `works_inspect` is untouched. Bundled: `enrich-metadata` prompt references the peer-connector pattern and points the agent at `gap_hints`.
988
+ - **ADR-193 Surface 4: `pica_enrichment_propose` accepts `proposal_action: "create"`.** Closes the reserved-but-unwired create path from ADR-178 Phase 1. The tool schema now accepts `entity_type: "recording" | "agreement" | "person"` paired with `parent_entity_type` + `parent_entity_id` for create proposals. Apply-path branches on `rule_id === "agent_research"` and routes to `recordingsService.create` (parent required; `work_id` linkage), `agreementsService.create` (optional work parent, linked via `agreementWorksService.addWork` after create), or `peopleAdminService.create` (standalone — people have no parent FK). Recording creates seed `field_sources` verbatim from `proposal.sources[].url`, preserving URI schemes (gmail://, gdrive://, notion://, file://, telegram://, user://, web://) per ADR-193 AC 5. Agreements + people don't carry `field_sources` on the main table today; provenance URIs are captured in `resolution_note` until a follow-up migration adds the column. Work + publisher creation remain explicitly out of scope (dedup-critical — deferred to future ADR). Migration `20260422_01_adr193_proposal_parent_fields` adds nullable `parent_entity_type` + `parent_entity_id` columns with a CHECK pair + partial index for the review-queue scan. Legacy `artist_title_to_youtube` create rule is untouched (it continues to overload `entity_id` as the parent work id). 4 new service-layer tests green; total proposal-service suite 42/42.
989
+ - **ADR-185 Part 1: three new session-auth-only tools.** `pica_create_agent_identity`, `pica_issue_agent_grant`, `pica_list_my_agent_grants`. Back a user-issued agent-identity + scoped-grant primitive — the substrate for Parts 2 (settings UI) and 3 (per-write provenance stamping). All three require `write:agent_identity` scope AND session-auth (raw API key / OAuth); the HTTP MCP dispatcher refuses `pica_grant_` callers with a structured `reason: "session_auth_required"` error before execution per AC 12. Subject is always the authenticated user — caller-supplied `user_id` is dropped per ADR-184 rule 2 / ADR-185 rule 1. Grant tokens use the format `pica_grant_<64 hex>` and are hashed at rest with HMAC-SHA256 + `API_KEY_HASH_PEPPER` (same scheme as api_keys per ADR-185 line 193 + ADR-167 D-5).
990
+ - **ADR-185 Part 2: two new session-auth-only tools.** `pica_revoke_agent_grant` (DELETE `/admin/agent-grants/:id`, idempotent, 404 masks ownership failures) and `pica_get_agent_activity` (GET `/admin/agent-activity`, paginated, optionally filtered by identity or grant). Both appended to `SESSION_AUTH_ONLY_TOOLS` in the HTTP MCP dispatcher and to the `write:agent_identity` scope bucket. Together with the Part 1 trio this completes the five-tool agent-identity surface the ADR Scope requires. Revocation takes effect on the next request (AC: within 60s — `resolveGrantToken` checks `revoked_at` on every call, no cache layer).
991
+ - **ADR-185 Part 3 passes 1-5: agent-action provenance stamping wraps 27 write-tool families.** Part 3 layers two complementary wrappers over existing write tools so every per-grant write records a row in `mcp_agent_actions` for audit + revoke-replay. `withAgentActionStamp` (compensation-after): handler runs, stamps; on stamp failure, compensation undoes the write via captured prior state — used for creates and updates (soft-delete families get meaningful delete compensation — flip `is_deleted` back). `withAgentActionStampFirst` (stamp-first, pass 4): stamp commits BEFORE the destructive op; stamp-ok + handler-fail logs a "ghost stamp" at error level — used for hard-delete families where compensation is impossible. Both wrappers are no-ops when the caller is not an agent grant (session-auth / raw API key writes are unaffected). Families covered across the five passes: works/recordings/people/agreements/releases/notes creates; notes_delete; sessions_create; share_links_create; projects_create; multimedia_create; recording_splits_create; works_update; recordings_update; people_update; agreements_update; projects_update; notes_update; releases_update; people_delete; publishers_create; the six hard-delete families (works/recordings/agreements/projects/sessions/releases) via the stamp-first variant; and pass 5's `pica_projects_attach_works` (project_works insert wrapped, GET + POST migrated from `requireAuth` + `getUserProfile` to `withOrgContext` for consistency). `pica_sessions_update` remains deferred — action-branching route (start/complete/cancel + participant add/remove + regular update) needs a dedicated design slice before wrapping.
992
+ - **New tool** `pica_submit_feedback`: agent-native feedback submission. Routes bug_report→devops, feature_request→ceo, question→comms, other→category-mapped. Requires `write:feedback` scope. Subject is always the authenticated user per ADR-184 rule 2. (ADR-184 slice 8 — landed on develop 2026-04-19 post-2.23.0 publish.)
993
+ - **ADR-189 Phase 3: two new identity-capture tools.** `pica_update_my_identity` (stage_name / IPI / ISNI / IPN / PRO) and `pica_update_organisation_profile` (org_type / display_name / tagline / ipi_number). Both admin-scoped, both `retry_safe: true` (idempotent upserts — re-applying the same IPI leaves the row in the same state). Subject derived from auth (no `user_id` / `organisation_id` parameters — ADR-184 rule 2). After the identity write, `pica_update_my_identity` re-runs cross-org discovery and returns the count of newly-visible credits / custody / artist-link rows so the agent can surface "found N more — claim them?" in the same conversation turn. Rate-limited at 20 writes/hour/user via `checkActionRateLimit` (R1 mitigation). Admin routes (`POST /api/admin/my-identity`, `POST /api/admin/organisation-profile`) wrap in `withAgentActionStamp` when the caller presents an agent grant (ADR-185 Part 3) — UPDATE compensation captures pre-write state via read-before-write and PATCHes the row back on stamp failure, or deletes a lazy-created person row.
994
+ - **ADR-189 Phase 4 Task 1: `pica_claim_credit`.** New activation-loop tool that drains a `discovered_credits` row into a `work_credits` row in the calling org, giving the user `view` access to the linked work. Check-and-set on `discovered_credits.status` prevents double-claims in concurrent sessions. Rate-limited to 20/hour per user via `checkActionRateLimit`. Returns `is_first_claim: true` on first-ever claim by the user (derived from `agent_action_log` stamp count). Wraps in `withAgentActionStamp` for grant callers — compensating transaction calls `revertClaimCredit` (flips discovery back to `pending` + deletes the `work_credits` row) if the stamp INSERT fails. Error taxonomy: `DISCOVERY_NOT_FOUND` (404), `DISCOVERY_ALREADY_RESOLVED` (409), `EVIDENCE_REVOKED` (410), `RATE_LIMITED` (429 + `Retry-After`). `pica_claim_credit` added to `ADMIN_ONLY_TOOLS` in `mcp-scopes.ts`; metadata entry `category: "discovery", risk: "mutating", retry_safe: false`. Route: `POST /api/admin/discoveries/[id]/claim-credit`. SDK method: `pica.discoveries.claimCredit(id)`.
995
+ - **ADR-189 Phase 4 Task 2: `pica_claim_custody` + +72h auto-approve worker.** Drains a `discovered_custody` row into a pending `custody_claims` row (status=`pending`, `chain`=custody_type, `custody_source`=`claimed`, provenance in `evidence.source`=`"auto-discovered-via-email"`). Schedules a silent-consent auto-approve by inserting a `scheduled_notifications` row (`source=pica_claim_custody`, `deliver_at`=+72h, message=`custody_auto_approve:<uuid>`). Does NOT mutate `works.{composition,master}_custodian_org_id` immediately — the 1-minute cron fires `scheduledNotificationsService.drainDue()` which now dispatches `source=pica_claim_custody` rows to a new `handleCustodyAutoApprove` branch that runs the **Delta 1 stale-promotion guard**: UPDATE `works` custodian columns ONLY IF the snapshot captured at claim time (`expected_previous_custodian_org_id` + `expected_custody_source` + `custody_side` — migration `20260421_01_custody_claims_expected_previous`) still matches; otherwise flip the claim to `superseded` (new status) and leave the catalog untouched. Error taxonomy identical to `pica_claim_credit`. `pica_claim_custody` was already in `ADMIN_ONLY_TOOLS` since Phase 4 Task 0; this ships the actual wiring. Route: `POST /api/admin/discoveries/[id]/claim-custody`. SDK method: `pica.discoveries.claimCustody(id)`. Stamp compensation via `revertClaimCustody` flips discovery back to pending, cancels the scheduled_notification, deletes the custody_claims row.
996
+
997
+ ## [2.24.0] - 2026-04-21
998
+
999
+ ### Fixed
1000
+
1001
+ - **`pica_integrations_status` no longer tells users to "connect Spotify".** Two real-user failures on Claude Desktop (2026-04-21) traced back to the tool lumping platform-level Spotify/YouTube (PICA has its own credentials; no per-user OAuth exists or has ever existed) into the same "Available to connect" list as genuine user-OAuth peer connectors (Google/Notion/Airtable/Telegram). Failure modes observed: (1) user pasted a Spotify track URL → agent replied "head to your Pica dashboard and add Spotify as an integration"; (2) user asked "what songs do I have in pica" with a catalog holding 1 work → agent replied "you currently have no connections set up in Pica — so there are no songs or any other data accessible." Reshape: the tool now returns `peerConnectors` (the 4 actual OAuth services) separately from `platformReads` (Spotify, YouTube, MusicBrainz, MLC, ISNI, Discogs, with the tool name for each). Summary leads with "PICA catalog is ALWAYS accessible via pica_works_query, pica_people_query, pica_dashboard_briefing, pica_search_all — no setup required." The dead `connectedProviders.includes("spotify")` check that could never evaluate true was removed.
1002
+ - **Server instructions: catalog-is-always-accessible guidance.** Handshake now explicitly states (a) the catalog is always accessible via the read tools with zero setup, (b) `pica_integrations_status` showing "0 connected" refers to optional peer connectors, NOT the catalog — call `pica_works_query` to check, (c) Spotify/YouTube URLs go through `pica_import_streaming_link` / `pica_import_youtube_link` directly; no per-user Spotify/YouTube OAuth exists to set up, do not tell the user to "connect Spotify in your dashboard". Replaces earlier copy that left the agent free to hallucinate a dashboard-integration flow. `lib/mcp/server-instructions.ts` parity copy updated in lockstep; the HTTP transport at `/api/mcp` picks up the new text on next handshake without requiring a redeploy of this package. Under the 2000-char token budget at 1833 chars.
1003
+
1004
+ ## [2.23.0] - 2026-04-19
1005
+
1006
+ ### Added
1007
+
1008
+ - **ADR-181 Phase 1: `pica_audit_list` ported from `@withpica/mcp-server-settings`
1009
+ (ADR-154 F6).** Closes the one trailing-gap tool from the source-merge audit —
1010
+ every other tool the three sub-servers exposed was already registered by
1011
+ `mcp-server`'s superset. Registered in `lib/services/mcp-scopes.ts`
1012
+ `ADMIN_ONLY_TOOLS` alongside the team / org-profile admin operations; the
1013
+ `mcp_audit_log` read is org-scoped and matches the existing admin posture
1014
+ for `pica_organisation_profile` / `pica_team_list`. Landed in `54ae935d9`
1015
+ via PR #50.
1016
+ - **ADR-181 Phase 1: bundle-size CI gate per Decision 2.** New
1017
+ `scripts/check-mcp-bundle.ts` walks `mcp-server/dist/`, sums byte size
1018
+ (excluding source maps), and fails if total > 210 MB (70% × Vercel's
1019
+ 300 MB serverless-function cap). Runs on every push / PR that touches
1020
+ `mcp-server/**`, `mcp-server-shared/**`, the script, or the workflow
1021
+ itself (`.github/workflows/mcp-bundle-size.yml`). `package.json`
1022
+ `prepublishOnly` invokes it locally so a bloated bundle can't ship out
1023
+ of a developer machine. Current measurement on this branch:
1024
+ 0.79 MB / 210 MB limit (0.38% of cap). Landed in `558315069` via PR #50.
1025
+
1026
+ ## [2.22.0] - 2026-04-18
1027
+
1028
+ ### Added
1029
+
1030
+ - **ADR-174 Phase 2 item 7 follow-up: `pica_projects_attach_works` (stdio).**
1031
+ Closes the `work_ids` FIELD_NOT_WIRED gap on `pica_projects_create` /
1032
+ `_update`. Pre-slice the MCP tools advertised `work_ids` but the admin
1033
+ route silently dropped it — the route redirect message already pointed
1034
+ agents at `POST /api/admin/projects/[id]/works`, but no MCP tool
1035
+ exposed that path. The new tool accepts
1036
+ `{ project_id, works: [{ work_id, project_day?, notes? }...] }` and
1037
+ attaches each item via `ProjectsResource.attachWork` with per-item
1038
+ result reporting (`attached[]`, `skipped[]` for already-linked,
1039
+ `failed[]` for other errors). Registered in `lib/services/mcp-scopes.ts`
1040
+ under `write:catalog`.
1041
+
1042
+ ### Changed
1043
+
1044
+ - **ADR-174 Phase 2 item 22: `pica_publishers_create` reshaped.** Pre-slice
1045
+ the schema exposed only `{ name, ipi }` (2 fields) and the SDK's
1046
+ `PublishersResource.create` hit a 404 — the admin route did not exist.
1047
+ The companion slice 1 commit added `POST /api/admin/publishers`;
1048
+ this slice reshapes the tool to match. All 8 audit-row-22
1049
+ Add-candidates surfaced (`legal_name`, `country`, `isni`,
1050
+ `publisher_type`, `wikidata_id`, `parent_publisher_id`,
1051
+ `founded_date`, `headquarters`) plus the explicit `ipi → ipi_number`
1052
+ rename. `parent_publisher_id` description steers agents at
1053
+ `pica_publishers_query` to resolve the parent UUID. Required fields:
1054
+ `name`, `ipi_number`. The route is idempotent on `ipi_number` — a
1055
+ duplicate IPI returns the existing row with `already_existed: true`
1056
+ instead of failing.
1057
+
1058
+ - **ADR-174 Phase 2 items 14+15: `pica_agreements_create` / `_update`
1059
+ reshaped to consume `AGREEMENTS_WRITE_PROPERTIES` from
1060
+ `@withpica/mcp-utils`.** Tool schemas now advertise all 13
1061
+ Add-candidate columns from audit rows 14+15. Tool descriptions steer
1062
+ agents toward `counterparty_org_id` (ADR-176 first-class-party) over
1063
+ free-text `other_party_name` — use `pica_search_all` to resolve an
1064
+ org name to an ID. `_update` description calls out that
1065
+ counterparty_org_id changes require the linked-org check at the
1066
+ route layer (orgLinkingService.areLinked). No tool signature change
1067
+ otherwise; existing fields preserved.
1068
+
1069
+ ### Route-side companion (non-package, same slice)
1070
+
1071
+ - `app/api/admin/agreements/route.ts` POST and
1072
+ `app/api/admin/agreements/[id]/route.ts` PATCH — phantom/unknown key
1073
+ rejection via `AGREEMENT_POST_ALLOWED_FIELDS` /
1074
+ `AGREEMENT_PATCH_ALLOWED_FIELDS` /
1075
+ `AGREEMENT_WRITE_PHANTOM_REDIRECTS` in
1076
+ `lib/services/agreements-write-constants.ts`. Pre-slice both routes
1077
+ spread `body` straight into the Supabase insert/update — effectively
1078
+ a wide-open write surface. Also surfaces and fixes pre-existing dark
1079
+ code in the PATCH test file (3 tests were sending `name` and `type`
1080
+ — phantom field names that silently dropped against `title` and
1081
+ `agreement_type`).
1082
+
1083
+ - `app/api/admin/publishers/route.ts` POST (NEW) — publishers had no
1084
+ admin route at all pre-slice, so `pica_publishers_create` and the
1085
+ SDK's `PublishersResource.create` 404'd at runtime. Slice 1
1086
+ (0ba4d400d) adds the route with phantom/unknown-field rejection via
1087
+ `PUBLISHERS_POST_ALLOWED_FIELDS` / `PUBLISHERS_WRITE_PHANTOM_REDIRECTS`
1088
+ in `lib/services/publishers-write-constants.ts`, idempotent
1089
+ deduplication by `ipi_number`, FK pre-validation on
1090
+ `parent_publisher_id`, and server-stamped provenance.
1091
+
1092
+ - **ADR-174 Phase 2 item 21: `pica_multimedia_create` reshaped.** Added
1093
+ 15 real-column fields that were invisible to agents pre-ADR-174:
1094
+ `credits`, `duration_seconds`, `collection_id`, `display_order`,
1095
+ `is_featured`, `is_published`, `venue`, `event_name`,
1096
+ `performance_date`, `setlist_position`, `sync_side`, and the external
1097
+ identifier set (`spotify_url`, `spotify_track_uri`, `spotify_track_id`,
1098
+ `youtube_url`, `youtube_video_id`, `soundcloud_url`, `thumbnail_url`).
1099
+ Description now points agents at `POST /api/admin/multimedia/upload`
1100
+ for file uploads and `pica_multimedia_link_youtube` for the YouTube
1101
+ enrichment flow — the generic create surface is for external-URL
1102
+ linking and performance-context metadata.
1103
+
1104
+ ### Route-side companion (non-package, same slice)
1105
+
1106
+ - `app/api/admin/multimedia/route.ts` POST — phantom/unknown key guard
1107
+ via `MULTIMEDIA_POST_ALLOWED_FIELDS` /
1108
+ `MULTIMEDIA_POST_PHANTOM_REDIRECTS` in
1109
+ `lib/services/multimedia-write-constants.ts`. Redirects upload-flow
1110
+ columns (s3*key, file_name, …) to `/api/admin/multimedia/upload`,
1111
+ enrichment columns (youtube_view_count, spotify_popularity) to their
1112
+ respective cascades, and scanner columns (virus_scan*\*) to the
1113
+ scanner flow. Also closes a latent privilege-escalation path: pre-slice
1114
+ the route overwrote `body.user_id` with the authenticated session's
1115
+ id, but a caller could still _attempt_ to pass `user_id` (silently
1116
+ overwritten). The guard now 400s on `user_id` / `organisation_id`
1117
+ injection attempts with a clear PHANTOM_FIELD message.
1118
+
1119
+ - **ADR-174 Phase 2 item 13: `pica_sessions_create` reshaped.** Dropped
1120
+ `additionalProperties: true` per Decision 2. Added 6 previously-missing
1121
+ real columns from audit row 13 as explicit Zod properties:
1122
+ `description`, `timezone`, `is_all_day`, `location_url`, `recording_id`,
1123
+ `status` (enum: scheduled / in_progress / completed / cancelled), plus
1124
+ the `metadata` jsonb bag and the `participants` relational array
1125
+ (already handled by the service but undocumented in the tool surface).
1126
+ `recurrence_rule` deferred — the service's `CreateSessionParams` type
1127
+ needs to accept it first (tracked in the route-guard PHANTOM_REDIRECT
1128
+ entry).
1129
+
1130
+ ### Route-side companion (non-package, same slice)
1131
+
1132
+ - `app/api/admin/sessions/route.ts` POST now reads `body.status` and
1133
+ `body.metadata` (pre-slice silently dropped) and 400s on phantom /
1134
+ unknown keys via `SESSION_POST_ALLOWED_FIELDS` /
1135
+ `SESSION_POST_PHANTOM_REDIRECTS` in
1136
+ `lib/services/sessions-write-constants.ts`.
1137
+
1138
+ - **ADR-174 Phase 2 item 20: `pica_share_links_create` reshaped to
1139
+ consume `SHARE_LINKS_WRITE_PROPERTIES` from `@withpica/mcp-utils`.**
1140
+ Tool schema now advertises all 13 add-candidate columns from audit
1141
+ row 20 that were previously invisible to agents (access_type,
1142
+ allowed_person_ids, allow_comments, allow_view_collaborators,
1143
+ allow_view_financials, notify_on_access, watermark_audio,
1144
+ sent_to_emails, playlist_name, allow_streaming, include_all_files,
1145
+ included_file_ids, description). Executor widened to pass every
1146
+ caller-provided property through to the SDK / admin route — the
1147
+ route-layer allow-list (slice 1) rejects anything outside the
1148
+ contract. `password` remains the canonical plain-text input; the
1149
+ route hashes to `password_hash`.
1150
+
1151
+ - **ADR-174 Phase 2 items 16+17: `pica_agreement_types_create` / `_update`
1152
+ reshaped to consume `AGREEMENT_TYPES_WRITE_PROPERTIES` from
1153
+ `@withpica/mcp-utils`.** Dropped the inlined property map in favour of
1154
+ the shared module that documents per-branch applicability. Phantom
1155
+ fields `title`, `description`, `points_percentage`, `recoupment_terms`,
1156
+ `rights_assigned` removed from the schema (agents sending them now fail
1157
+ fast at the admin route guard with a `PHANTOM_FIELD` redirect pointing
1158
+ at the canonical column or resolution path). Tool descriptions updated
1159
+ to truthfully list the required fields per branch (template needs
1160
+ `name` + `category` + `templateText`; producer needs `producer_id` +
1161
+ `royalty_points` + `deliverables` + `work_id`|`recording_id`;
1162
+ work_for_hire needs `contractor_id` + `contractor_role` + `fee_amount`
1163
+ - `services_description` + `work_id`|`recording_id`). Tool description
1164
+ for `_update` now calls out that PATCH on producer_agreements and
1165
+ work_for_hire_agreements is action-only — the generic update path has
1166
+ no live field-update surface on those two branches until a follow-up
1167
+ slice promotes the action-based PATCH handlers to accept field
1168
+ updates.
1169
+
1170
+ ### Added
1171
+
1172
+ - **ADR-179 Phase 1: `pica_resolve_work` (stdio).** Outcome-shaped
1173
+ resolver that fans a work out across every eligible enrichment source
1174
+ in one call. Replaces the five `pica_enrich_work_*` tools' role at
1175
+ the agent layer. Returns `applied[]` / `proposals[]` / `errors[]` /
1176
+ `recovery_hints[]`. `isError` is set only when every source that ran
1177
+ errored — partial failure is a non-error receipt. Credit + billing
1178
+ gates wire through the `external_resolver_call` action key.
1179
+ - **ADR-179 Phase 2: `pica_resolve_person` (stdio).** Person-side
1180
+ resolver mirroring `pica_resolve_work`. Sources are narrower —
1181
+ `isni` | `musicbrainz` — covering the identity-graph cascade rules
1182
+ (ISNI→Wikidata and MBID→Wikidata crosswalks plus their downstream
1183
+ awards / biography enrichment). Same output shape, same isError
1184
+ semantics, same credit-gate action key as the work resolver.
1185
+ Registered in `lib/services/mcp-scopes.ts` under `write:people` and
1186
+ listed in the layered-discovery `enrichment` category so
1187
+ `pica_discover` surfaces it above the deprecated
1188
+ `pica_people_enrich_*` pair.
1189
+
1190
+ ### Deprecated
1191
+
1192
+ - **`pica_enrich_work_mlc`, `pica_enrich_work_musicbrainz`,
1193
+ `pica_enrich_work_discogs`, `pica_enrich_work_spotify`,
1194
+ `pica_enrich_work_youtube`.** All five now return
1195
+ `TOOL_DEPRECATED` (jsonrpc code -32070) with a suggested-call
1196
+ payload pointing at `pica_resolve_work` with the correct `sources`
1197
+ narrowing. Tool definitions stay registered so `tools/list` and
1198
+ `pica_tool_details` can still surface them with a migration hint for
1199
+ one minor version — removal scheduled for the next minor after
1200
+ ADR-179 Phase 4's publish.
1201
+ - **`pica_people_enrich_isni`, `pica_people_enrich_musicbrainz`.**
1202
+ Both now return `TOOL_DEPRECATED` (jsonrpc code -32070) with a
1203
+ suggested-call payload pointing at
1204
+ `pica_resolve_person(sources: ['isni' | 'musicbrainz'])`. Tool
1205
+ definitions stay registered until the next minor; same one-minor-
1206
+ version deprecation window as the work-side five.
1207
+
1208
+ ### Changed
1209
+
1210
+ - `pica_tool_details` responses for the five deprecated work tools
1211
+ now carry a `TOOL_DEPRECATED` entry in `recovery_hints` as the first
1212
+ item. Existing `NO_MATCH` / `MISSING_INPUT` hints are kept behind
1213
+ it — they are dead code today but stay in the registry until tool
1214
+ removal so downstream consumers don't see a mid-version
1215
+ disappearance.
1216
+ - Same treatment applied to the two deprecated person tools:
1217
+ `pica_people_enrich_isni` and `pica_people_enrich_musicbrainz` each
1218
+ get a `TOOL_DEPRECATED` recovery hint prepended to their existing
1219
+ `NO_MATCH` entry.
1220
+
1221
+ ## [2.22.0] — 2026-04-16
1222
+
1223
+ ### Changed
1224
+
1225
+ - **ADR-174 Phase 2 item 10 (recording_splits): reshape
1226
+ `pica_recording_splits_create`.** Adopts the shared
1227
+ `RECORDING_SPLITS_WRITE_PROPERTIES` from `@withpica/mcp-utils@1.4.0`,
1228
+ dropping `additionalProperties: true` per Decision 2. All 9 audit-
1229
+ Keep fields now enumerated as explicit Zod properties — no phantom
1230
+ additions, no renames. Description-level hint on `role` replaced
1231
+ with a proper `enum` array matching the route's validRoles allow-
1232
+ list. Schema is now byte-identical to `@withpica/mcp-server-business`
1233
+ (both consume the shared module) — pre-slice they were independent
1234
+ byte-divergent-risk copies.
1235
+
1236
+ ### Route-side companion (non-package, same slice)
1237
+
1238
+ - `app/api/admin/recordings/[id]/splits/route.ts` POST — UNKNOWN_FIELD
1239
+ guard runs before the required-field check so misspelled keys fail
1240
+ fast with the field name. See the slice commit.
1241
+
1242
+ ## [2.21.0] — 2026-04-16
1243
+
1244
+ ### Fixed
1245
+
1246
+ - **ADR-174 Phase 2 item 24 (team): `pica_team_update_role` now actually
1247
+ updates role.** Pre-ADR-174 the tool was named `_update_role` but its
1248
+ Zod schema only accepted `permissions` — the `role` field was missing
1249
+ entirely. The admin PATCH route at `/api/admin/team/[id]` hard-
1250
+ destructured `{ permissions }` and silently dropped every other
1251
+ field, so even if an agent hand-crafted a call with `role` the DB
1252
+ write would not happen. Audit row 24 flagged this as "Add `role`, or
1253
+ rename the tool." Fixed by adding `role: string` to the MCP Zod
1254
+ schema, widening the route to build the update object from whichever
1255
+ of `role` / `permissions` are provided, and making the old
1256
+ "permissions required" check accept "at least one of role or
1257
+ permissions." `id` stays required; `role` and `permissions` are now
1258
+ both optional but at least one must be set.
1259
+
1260
+ ### Route-side companion (non-package, same slice)
1261
+
1262
+ - `app/api/admin/team/[id]/route.ts` PATCH — phantom/unknown key
1263
+ rejection via `TEAM_MEMBERSHIP_PATCH_ALLOWED_FIELDS` (allow-list of
1264
+ `permissions` + `role`), error message updated from "permissions
1265
+ required" to "at least one of permissions or role is required", and
1266
+ "failed to update permissions" to "failed to update team membership"
1267
+ (now-generic — it updates role too).
1268
+
1269
+ ## [2.20.0] — 2026-04-16
1270
+
1271
+ ### Changed
1272
+
1273
+ - **ADR-174 Phase 2 item 7 (projects): reshape `pica_projects_create` /
1274
+ `pica_projects_update` Zod schemas.** Exposed 9 Add-candidate fields
1275
+ from audit row 18 that were already plumbed end-to-end through the
1276
+ route and service but invisible to agents via tool discovery:
1277
+ `start_date`, `end_date`, `location_name`, `location_address`,
1278
+ `location_url`, `virtual_url`, `is_open`, `max_participants`, `status`
1279
+ (enum: draft / scheduled / active / completed / cancelled). Also
1280
+ surfaced the route-level `generate_invite_code` flag and the
1281
+ freeform `metadata` jsonb object. Dropped `work_ids` from both
1282
+ schemas — the pre-ADR-174 tool advertised `work_ids` but the admin
1283
+ POST / PATCH routes never routed it to the `project_works` junction
1284
+ (see commit `edf890a24` for the route-side FIELD_NOT_WIRED rejection
1285
+ and redirect message pointing at
1286
+ `POST /api/admin/projects/[id]/works`). The `project_type`
1287
+ description replaces the pre-ADR-174 "album, ep, compilation, single,
1288
+ mixtape" hint (none of which are valid backend values) with the
1289
+ actual convention: writing_camp, recording_session, production,
1290
+ mixing, mastering, retreat, other.
1291
+
1292
+ ### Route-side companion (non-package, same slice)
1293
+
1294
+ - `app/api/admin/projects/route.ts` POST and
1295
+ `app/api/admin/projects/[id]/route.ts` PATCH — phantom/unknown key
1296
+ rejection with `FIELD_NOT_WIRED` redirect for `work_ids`. See commit
1297
+ `edf890a24`.
1298
+
1299
+ ## [2.19.0] — 2026-04-16
1300
+
1301
+ ### Added
1302
+
1303
+ - **ADR-178: `pica_enrichment_propose` stdio tool.** New agentic write
1304
+ tool that files enrichment proposals sourced from open-web research
1305
+ (Audiomack, Songdata, MusicBrainz page, label portals, artist bios,
1306
+ etc.) rather than from PICA's structured cascade. Every proposed
1307
+ field must cite at least one source URL — `sources[].fields` arrays
1308
+ form the trust moat, and the server rejects uncited claims with
1309
+ `code: MISSING_SOURCE`. Source type routes the proposal as
1310
+ `source = 'agent_research'`, `rule_id = 'agent_research'` on the
1311
+ existing `enrichment_proposals` table (no new queue, no new review
1312
+ tools — reuses `pica_enrichment_proposals_list` / `_apply` /
1313
+ `_reject` from `2.10.0`).
1314
+
1315
+ Tool description carries ADR-178 Decision 3 language verbatim: when
1316
+ the user is in-session, the agent asks for approval directly and
1317
+ calls `pica_enrichment_proposal_apply` after confirmation — the
1318
+ dashboard card is the receipt, not the workflow. This shapes agent
1319
+ behaviour in-context without needing a new code path for "in-
1320
+ session approval".
1321
+
1322
+ Wrapped in `withBillingGate` and (via
1323
+ `@withpica/mcp-utils@1.3.0`) `withCreditGate` under the new
1324
+ `enrichment_propose` action key. Credit gating is telemetric only
1325
+ while ADR-162 keeps the subscription gate on; the wrap is already
1326
+ in place so re-enabling billing doesn't need a tool-surface change.
1327
+
1328
+ ### Fixed
1329
+
1330
+ - **ADR-178 slice 1b regression caught in smoke test:** agent-research
1331
+ proposals whose `proposed_fields` cite columns that don't exist on
1332
+ the target table (tempo_bpm, musical_key, producers — the Heinzmann
1333
+ transcript's fields, not columns on `works`) used to 500 with a
1334
+ Postgres "column does not exist" error because the service built a
1335
+ column-scoped `SELECT` from the proposed keys. Fix snapshots the
1336
+ full live row and builds `current_fields` from the intersection of
1337
+ proposed keys and actual columns. Unknown keys now land as pending
1338
+ proposals with an empty baseline instead of crashing the request.
1339
+ Apply path for unknown-column fields is a separate open question on
1340
+ the ADR (see Open Question 5).
1341
+
1342
+ ## [2.18.0] — 2026-04-16
1343
+
1344
+ ### Changed
1345
+
1346
+ - **ADR-174 Phase 2 item 6: reshape `pica_credits_update` Zod schema.**
1347
+ Dropped phantom `publisher_name` and `publisher_ipi` properties —
1348
+ `work_credits` has no columns for either. Agents now resolve a
1349
+ publisher name or IPI to a UUID via `pica_publishers_query` (or
1350
+ create one via `pica_publishers_create`) and pass the result as
1351
+ `publisher_id`. Added three audit "Add candidate" columns to the
1352
+ per-credit-object shape: `is_primary` (boolean), `notes` (string),
1353
+ `attestation_status` (enum: pending / attested / disputed /
1354
+ declined). `attested_at` / `attested_by` remain service-managed.
1355
+ Description refresh calls out `credit_type` as the canonical column
1356
+ name stored behind the `role` alias and `writer_split_percentage`
1357
+ behind `splits`. No required-field change — `person_id`, `role`,
1358
+ `splits` stay required.
1359
+
1360
+ ### Route-side companion (non-package, same slice)
1361
+
1362
+ - `app/api/admin/works/[id]/credits/route.ts` POST — phantom/unknown
1363
+ key rejection on each `credits[i]` element with field name + index
1364
+ in the error payload, plus a mirror-fill step that normalises
1365
+ `role` ↔ `credit_type` and `splits` ↔ `writer_split_percentage` so
1366
+ callers sending either spelling flow through. See commit
1367
+ `dbfb098ae` for the server-side guard.
1368
+
1369
+ ### Not covered by this slice
1370
+
1371
+ - `work_collaborators` (publishing-side POST at
1372
+ `app/api/admin/works/[id]/collaborators/route.ts`) was not in the
1373
+ ADR-174 audit — the MCP tool's `updateCollaborators` SDK hop hits
1374
+ that route for writer/composer/lyricist/arranger roles today and
1375
+ inherits a separate column set. Tracked as a follow-up slice.
1376
+
1377
+ ## [2.17.0] — 2026-04-16
1378
+
1379
+ ### Changed
1380
+
1381
+ - **ADR-174 Phase 2 item 5: reshape `pica_physical_assets_create` and
1382
+ `pica_physical_assets_update` Zod schemas.** Adopted the shared
1383
+ `PHYSICAL_ASSETS_WRITE_PROPERTIES` from `@withpica/mcp-utils@1.2.0`,
1384
+ dropped `additionalProperties: true` on both tools, and moved 11
1385
+ phantom top-level fields (`current_valuation`, `valuation_currency`,
1386
+ `valuation_source`, `valuation_date`, `valuation_notes`,
1387
+ `reverb_listing_url`, `ebay_item_url`, `insured`,
1388
+ `insurance_provider`, `insurance_policy_number`, `insurance_coverage`)
1389
+ off the top-level surface. Agents set these via
1390
+ `external_references: { current_valuation: 1500, insurer: "ACME", ... }`
1391
+ per the ADR-174 Open Decision 1 (2026-04-14) resolution. Two fields
1392
+ were renamed at the jsonb layer: `insurance_provider → insurer`,
1393
+ `insurance_coverage → insured_value`. `asset_type`, `condition`,
1394
+ `acquisition_method`, `license_type`, and `status` gained proper
1395
+ `enum` arrays matching the underlying `physical_assets_*_check` CHECK
1396
+ constraints — pre-reshape they were loose strings with the enum
1397
+ hinted in the description (so callers could pass `studio_equipment`
1398
+ at the MCP layer and get a 500 from the CHECK constraint at the DB
1399
+ layer).
1400
+ - **No description lie.** Both tool descriptions now explicitly name
1401
+ `external_references` as the home for valuation/insurance/DSP URL
1402
+ details rather than the pre-ADR-174 "tracks … valuation, photos,
1403
+ insurance, and status" claim that the schema couldn't honour.
1404
+
1405
+ ### Route-side companion (non-package, same slice)
1406
+
1407
+ - `app/api/admin/assets/route.ts` POST and
1408
+ `app/api/admin/assets/[id]/route.ts` PATCH — phantom/unknown key
1409
+ rejection with redirect messages (400 + `PHANTOM_FIELD` /
1410
+ `UNKNOWN_FIELD` error codes). See commit `ced46b889` for the
1411
+ server-side guard.
1412
+
1413
+ ## [2.16.0] — 2026-04-15
1414
+
1415
+ ### Added
1416
+
1417
+ - **ADR-173: five release-track tools.** Closes the gap flagged by two
1418
+ independent external MCP reviewers on 2026-04-14 ("release layer looks
1419
+ shallow"). New tools on the stdio transport:
1420
+ - `pica_releases_attach_track` — attach a recording and/or work at a
1421
+ specific `(disc_number, track_number)`. Idempotent on position.
1422
+ At least one of `recording_id` / `work_id` is required.
1423
+ - `pica_releases_list_tracks` — list tracks in `(disc, track)` order
1424
+ with inlined title/artist/ISRC/duration from the linked recording
1425
+ and work.
1426
+ - `pica_releases_detach_track` — soft-confirmation detach by position
1427
+ (preview without `confirm:true`, delete with).
1428
+ - `pica_releases_reorder_tracks` — transactional positional reorder
1429
+ via the `reorder_release_tracks_atomic` Postgres RPC. Rejects
1430
+ duplicate positions in the payload before any DB write.
1431
+ - `pica_releases_attach_recording_with_work` — compound workflow that
1432
+ auto-pulls the recording's linked work onto the new track row.
1433
+
1434
+ ### Changed
1435
+
1436
+ - **`pica_works_inspect` and `pica_recordings_inspect` gain a `releases`
1437
+ section.** Lazy (only fetched when requested). Returns every release
1438
+ the entity appears on with its track position. Answers "which albums
1439
+ is this master on?" in one call — previously unanswerable via MCP.
1440
+
1441
+ ### Fixed
1442
+
1443
+ - **`pica_releases_list_tracks` 500 on every call.** Pre-merge E2E
1444
+ caught two latent bugs in the `listTracks` service query: a missing
1445
+ FK `release_tracks.recording_id → recordings(id)` (PostgREST could
1446
+ not resolve the `recording:recordings(...)` embed) and a
1447
+ `duration_seconds` column reference where the live column is
1448
+ `duration_ms`. Fixed in migration
1449
+ `20260415_01_adr173_fix_release_tracks_recording_fk.sql` +
1450
+ a rename in `lib/services/releases.ts`. The migration also NULLs 85
1451
+ orphan `recording_id` values on production left behind by the
1452
+ 2026-04-04 soundslikefez duplicate-works cleanup.
1453
+
1454
+ ### Note on version number
1455
+
1456
+ This release would have been `2.15.0` per the original ADR-173
1457
+ implementation record, but `2.15.0` was taken on `develop` by the
1458
+ ADR-174 Phase 2 item 4 slice while the ADR-173 fix commits were in
1459
+ flight. Bumped to `2.16.0` to keep the published package timeline
1460
+ linear.
1461
+
1462
+ ## [2.15.0] — 2026-04-15
1463
+
1464
+ ### Changed
1465
+
1466
+ - **ADR-174 Phase 2 item 4: `pica_people_create` / `pica_people_update`
1467
+ schema reconciliation.** Introduced `PEOPLE_WRITE_PROPERTIES` as the
1468
+ canonical source of truth for the people write surface — every
1469
+ property maps to a real column on either `public.people` or
1470
+ `public.person_enrichment`. `additionalProperties: true` is off;
1471
+ unknown keys 400 at the HTTP layer (see develop commit
1472
+ `fbea9e2a3`).
1473
+ - **Satellite-routing made explicit.** Eleven fields remain in the
1474
+ schema but their descriptions now name `person_enrichment` as the
1475
+ write target: external identifiers (`isni`, `musicbrainz_id`,
1476
+ `wikidata_id`, `discogs_artist_id`, `deezer_artist_id`) and
1477
+ biographical data (`date_of_birth`, `gender`, `nationality`,
1478
+ `birth_place`, `instruments`, `career_start_year`). The service
1479
+ fans these out through `syncPersonEnrichmentSatellite`. Correction
1480
+ to the original audit (row 7) landed in ADR-174's Corrections
1481
+ block: six of these fields were classified as "Remove — no column
1482
+ on people", which missed the satellite hop. They are not phantom
1483
+ writes, and subsequent slices must audit satellite write paths
1484
+ before classifying any field as phantom.
1485
+ - **Twelve add-candidates surfaced** (audit row 7 "Missing writable
1486
+ columns"): `middle_name`, `person_type`, `company`, `position`,
1487
+ `territory`, `social_media`, `emails`, `pro_name`,
1488
+ `pro_member_number`, `mcps_member_number`, `relationship_strength`,
1489
+ `email_preferences`. All verified against `public.people` columns
1490
+ 2026-04-15 (project `fwgcmjhlwevdnxgqmkmh`).
1491
+ - **Deprecated duplicates rejected.** `type` (deprecated dup of
1492
+ `person_type`) and `role` (deprecated singular of `roles`) are
1493
+ now 400 PHANTOM_FIELD with a redirect message naming the canonical
1494
+ column. Both DB columns still exist as unused dead space —
1495
+ removing them is out of scope and scheduled for ADR-165-style
1496
+ cleanup.
1497
+ - **Description lies removed.** The audit (row 8) flagged
1498
+ `pica_people_update` description as "Additional fields are also
1499
+ accepted" with no enumeration. That sentence is gone from both
1500
+ `create` and `update` descriptions.
1501
+
1502
+ ### Breaking
1503
+
1504
+ - Callers that were passing the deprecated `type` / `role`
1505
+ duplicates now get a 400 with a redirect hint — previously the
1506
+ keys were silently dropped by the ORM. Same failure-mode calculus
1507
+ as the works / recordings slices — the writes were already
1508
+ failing, now they fail visibly.
1509
+ - Callers that were passing arbitrary unlisted keys now get a 400 —
1510
+ previously `additionalProperties: true` let them through and the
1511
+ ORM dropped them silently. Zero rows observed in `people.metadata`
1512
+ jsonb for any of the pre-existing phantom keys (verified during
1513
+ ADR-174 Phase 1 2026-04-14).
1514
+
1515
+ ## [2.14.0] — 2026-04-14
1516
+
1517
+ ### Changed
1518
+
1519
+ - **ADR-174 Phase 2: `pica_recordings_create` / `pica_recordings_update`
1520
+ schema reconciliation.** Introduced `RECORDING_WRITE_PROPERTIES` as
1521
+ the canonical source of truth for the recordings write surface —
1522
+ every property maps to a real column on `public.recordings`. Added
1523
+ thirteen fields the DB exposes that the tool was hiding:
1524
+ `duration_ms`, `preview_url`, `album_art_url`, `spotify_url`,
1525
+ `spotify_track_uri`, `spotify_track_id`, `youtube_video_id`,
1526
+ `youtube_url`, `apple_music_url`, `deezer_track_id`,
1527
+ `mlc_recording_id`, `mlc_song_code`, `isrc_prefix`. The
1528
+ `version_type` field is now enum-restricted to the ADR-166 values
1529
+ (`master`, `alternate_master`, `music_video`, `lyric_video`,
1530
+ `live_performance`, `acoustic`, `remix`, `cover`, `alternate`),
1531
+ matching the `recordings_version_type_check` DB constraint.
1532
+ - **`pica_recordings_create` default `version_type` changed from
1533
+ `"original"` to `"master"`.** Pre-fix the executor defaulted to
1534
+ `"original"`, which is not a valid version_type — every call without
1535
+ an explicit type tripped the recording-type CHECK constraint and
1536
+ surfaced as a 500 from the service. `"master"` is the DB-level
1537
+ default and the canonical ADR-166 value.
1538
+ - **Title rename made explicit.** `recording_title` is the canonical
1539
+ column on `public.recordings`. The tool keeps `title` as an input
1540
+ alias for ergonomics; the schema now declares both fields with the
1541
+ rename called out in their descriptions, instead of relying on
1542
+ `additionalProperties: true` to hide the translation.
1543
+ - Tool descriptions now steer album metadata (`album_name`,
1544
+ `album_release_date`, `upc`, `track_number`) to
1545
+ `pica_releases_create/update`, ISWCs to `pica_works_create/update`,
1546
+ and label metadata to `pica_releases_*.label_organization_id` via
1547
+ `pica_labels_query`. `duration_seconds` is explicitly named as the
1548
+ works convention; `recordings` carries `duration_ms`.
1549
+
1550
+ ### Removed
1551
+
1552
+ - **ADR-174 Phase 2: seven phantom fields rejected on
1553
+ `pica_recordings_create` / `pica_recordings_update`.** The Zod schema
1554
+ no longer accepts them and `additionalProperties: true` is gone:
1555
+ `album_name`, `album_release_date`, `upc`, `track_number`, `label`,
1556
+ `duration_seconds`, `iswc` — none of these corresponded to columns on
1557
+ `recordings`. The HTTP route at `POST/PATCH /api/admin/recordings[/id]`
1558
+ now 400s on any of these keys with a redirect message naming the
1559
+ correct tool (commit `cffa6f947`).
1560
+
1561
+ ## [2.13.1] — 2026-04-14
1562
+
1563
+ ### Changed
1564
+
1565
+ - **ADR-174 Phase 2: `pica_works_bulk_update.updates` schema gated on
1566
+ `WORK_WRITE_PROPERTIES`.** The bulk tool was the last write-path
1567
+ surface that still accepted any key — `updates: { type: "object" }`
1568
+ with no property list (audit row 25). Now validates against the same
1569
+ canonical schema as `pica_works_update`: phantom keys (label, upc,
1570
+ album_name, …) and arbitrary unlisted keys fail fast with a
1571
+ descriptive `VALIDATION_ERROR` before the SDK is called. One bad key
1572
+ invalidates the whole batch — no partial writes.
1573
+
1574
+ ## [2.13.0] — 2026-04-14
1575
+
1576
+ ### Changed
1577
+
1578
+ - **ADR-174 Phase 2: `pica_works_create` / `pica_works_update` schema
1579
+ reconciliation.** Introduced `WORK_WRITE_PROPERTIES` as the canonical
1580
+ source of truth for the works write surface — every property maps to
1581
+ a real column on `public.works`. Added five fields the DB exposes
1582
+ that the tool was hiding: `tempo`, `key`, `display_artist`,
1583
+ `published`, `tunecode`. Tool descriptions now steer album/release
1584
+ metadata (`album_name`, `album_art_url`, `track_number`, `upc`,
1585
+ `spotify_url`) to `pica_releases_create/update` and label metadata to
1586
+ `pica_releases_*.label_organization_id` via `pica_labels_query`.
1587
+
1588
+ ### Removed
1589
+
1590
+ - **ADR-174 Phase 2: seven phantom fields removed from
1591
+ `pica_works_create` / `pica_works_update`.** `label`, `spotify_url`,
1592
+ `album_name`, `album_release_date`, `album_art_url`, `track_number`,
1593
+ `upc` — none of these corresponded to columns on `works`. The HTTP
1594
+ route at `POST/PATCH /api/admin/works[/id]` now 400s on any of these
1595
+ keys with a redirect message naming the correct tool (commit
1596
+ `9d68b16b1`). Previously they routed silently into the
1597
+ `work_album_metadata` / `work_spotify_data` satellites that ADR-165
1598
+ marked as dead — a write succeeded but no reader could find the
1599
+ value.
1600
+ - **ADR-174 Phase 2: `additionalProperties: true` removed from both
1601
+ works write schemas.** The tool no longer silently accepts arbitrary
1602
+ keys; unknown keys surface as validation errors. Description lies
1603
+ about `available_for_licensing`, `vocal_type`, `energy`,
1604
+ `danceability` also removed — those fields live on satellite tables
1605
+ and are not exposed through MCP.
1606
+
1607
+ ## [2.12.0] — 2026-04-14
1608
+
1609
+ ### Added
1610
+
1611
+ - **ADR-174 Phase 2: `pica_labels_query` tool** — read-only resolution of
1612
+ label names to `organisations.id`. Returns label organisations
1613
+ (`org_type='label'`) whose name or display_name matches the substring
1614
+ query, for use as `releases.label_organization_id` via
1615
+ `pica_releases_create` / `pica_releases_update`. `query` and `limit`
1616
+ both optional; limit defaults to 50, max 100. Category: catalog.
1617
+ Annotations: `readOnlyHint: true`.
1618
+
1619
+ ### Changed
1620
+
1621
+ - **ADR-174 Phase 2: `pica_releases_create` / `pica_releases_update`
1622
+ schema reconciliation.** Input schemas now expose the nine ADR-174
1623
+ Decision 3 fields that `releases` actually stores:
1624
+ `label_organization_id`, `distributor_organization_id`,
1625
+ `pre_release_date`, `artwork_url`, `spotify_album_uri`, `spotify_url`,
1626
+ `apple_music_url`, `other_urls`, `notes`. Tool descriptions now
1627
+ direct agents to call `pica_labels_query` (new) or `pica_search_all`
1628
+ to resolve a label/distributor name to an organisation ID before
1629
+ writing.
1630
+
1631
+ ### Removed
1632
+
1633
+ - **ADR-174 Phase 2: freetext `label` removed from
1634
+ `pica_releases_create` / `pica_releases_update`.** The field never
1635
+ corresponded to a real column on `releases` — the DB models labels
1636
+ via `label_organization_id` FK. Agents must now resolve a label name
1637
+ to an organisation ID (via `pica_labels_query`) instead of passing a
1638
+ string. Pre-fix behaviour: tool schema accepted `label`, service
1639
+ propagated it to the DB, the DB rejected it as `42703 column does not
1640
+ exist`, every call 500'd. No working integrations could have relied
1641
+ on this — the change is strictly a fix, not a break.
1642
+
1643
+ ## [2.11.0] — 2026-04-13
1644
+
1645
+ ### Changed
1646
+
1647
+ - **ADR-171: Prompts replaced with workflow-level skills.**
1648
+ 11 prompts → 10 skills, each with decision trees, domain knowledge,
1649
+ enrichment source priority, and the shared preamble (tone, prerequisite
1650
+ check, summary pattern). Deployed as upgraded prompts; will convert to
1651
+ MCP skills format when the spec extension ships.
1652
+
1653
+ New skills: `workspace-autopilot`, `establish-identity`,
1654
+ `catalog-your-music`, `upload-and-analyse`, `close-the-loop`,
1655
+ `manage-collaborators`, `establish-ownership`, `production-assets`,
1656
+ `stay-connected`, `export-and-report`.
1657
+
1658
+ Retired prompts: `analyze-catalog`, `find-duplicates`,
1659
+ `enrich-metadata`, `verify-works`, `assess-catalog-health`,
1660
+ `audit-credits`, `new-catalog-setup`, `register-my-works`,
1661
+ `prepare-for-sync`. Functionality folded into new skills —
1662
+ see design spec for mapping.
1663
+ - `workspace-autopilot` now routes through the full journey sequence
1664
+ (identity → catalog → audio → gaps → collaborators → ownership →
1665
+ notifications → exports) instead of the old 5-condition router.
1666
+ - `close-the-loop` absorbs 7 former prompts and adds the enrichment
1667
+ cascade decision tree (MLC first if IPI, MusicBrainz second, Spotify
1668
+ third) and inline duplicate detection.
1669
+ - `export-and-report` absorbs `analyze-catalog`, `register-my-works`,
1670
+ and `prepare-for-sync` into a single export/report skill with CAR,
1671
+ CWR, CSV, provenance, sync readiness, and carbon footprint paths.
1672
+
1673
+ ## [2.10.0] — 2026-04-11
1674
+
1675
+ ### Added
1676
+
1677
+ - **ADR-163: Tier B enrichment proposal review tools.**
1678
+ - `pica_enrichment_proposals_list` — list pending proposals
1679
+ awaiting review. Filters: `entity_type`, `entity_id`,
1680
+ `rule_id`, `source`, `limit` (1..100, default 20), `offset`.
1681
+ Only `status='pending'` rows are returned. Backed by
1682
+ `GET /api/admin/enrichment-proposals`.
1683
+ - `pica_enrichment_proposal_apply` — apply a pending proposal.
1684
+ For update proposals, runs drift detection first: if the
1685
+ entity has changed since the proposal was created, returns
1686
+ `{ status: 'drift_detected', conflicts }` without writing.
1687
+ Agents surface conflicts to the user before retrying with
1688
+ `force=true`. For create proposals (`artist_title_to_youtube`),
1689
+ a uniqueness check runs instead and cannot be forced. Backed
1690
+ by `POST /api/admin/enrichment-proposals/:id/apply`.
1691
+ - `pica_enrichment_proposal_reject` — reject a pending proposal
1692
+ with an optional `resolution_note`. Content-hash suppression
1693
+ (ADR-163) permanently blocks re-proposal of identical content
1694
+ — no cooldown, no timer. Backed by
1695
+ `POST /api/admin/enrichment-proposals/:id/reject`.
1696
+
1697
+ - **ADR-166: YouTube import as a recording-version source.**
1698
+ - `pica_import_youtube_link` MCP tool wraps the Phase 3 orchestrator.
1699
+ Takes a YouTube URL, returns a preview (items + classification +
1700
+ work match), then `confirm: true` executes the import as a new
1701
+ recording on an existing or newly-created work. Supports
1702
+ `selectedVideoIds`, `targetWorkId`, and `overrideVersionType`
1703
+ for fine-grained agent control. Landed in `78da58344`
1704
+ (feat(adr-166): phase 4 — pica_import_youtube_link MCP tool + SDK
1705
+ methods).
1706
+
1707
+ ### Changed
1708
+
1709
+ - `pica_cascade_health` outcome bucket list extended to include
1710
+ the ADR-163 Phase 1 `proposed` and `suppressed` outcomes. Tool
1711
+ description now reads `wrote / no_match / already_enriched /
1712
+ error / proposed / suppressed`. Counters populate automatically
1713
+ from `cascadeOutcomeCounter` — no schema change required for
1714
+ existing `/api/admin/cascade-health` or
1715
+ `/api/internal/cascade-health` consumers.
1716
+
1717
+ - Several mcp-server source files got minor reformatting from ADR-165's
1718
+ flattener strip (removing `work_spotify_data` + `work_album_metadata`
1719
+ fields from the Work shape) and ADR-166's cascade rule rewrites.
1720
+ These are consumer-invisible at the MCP tool surface — the tools
1721
+ still accept the same inputs and return the same outputs — but the
1722
+ underlying `PicaClient.works` reads + writes now route through the
1723
+ ADR-165 overlay. See the ADR-165 and ADR-166 implementation records
1724
+ for details.
1725
+
1726
+ ### Fixed
1727
+
1728
+ - `pica_run_person_cascade` tool description had a dangling
1729
+ `→ then: pica_people_inspect` chain with no parenthetical reason hint,
1730
+ which the `composability-chains.test.ts` linter caught as a content
1731
+ bug. Description updated to `→ then: pica_people_inspect (see what
1732
+ the cascade wrote)`. Fixed in `3a2843636` (test(mcp-server): fix 10
1733
+ pre-existing test failures across 8 suites).
1734
+
1735
+ ### Notes
1736
+
1737
+ - Backwards-compatible minor bump. Three new tools, one widened
1738
+ description, no removals or signature changes.
1739
+ - Depends on `@withpica/mcp-sdk@^1.4.0` for the new
1740
+ `EnrichmentResource.listEnrichmentProposals` /
1741
+ `applyEnrichmentProposal` / `rejectEnrichmentProposal` methods.
1742
+ - Source additions landed across ADR-163 Phase 3d (`ff9cf265a`) and
1743
+ Phase 6 (`ff97faa56`).
1744
+ - Registry: https://www.npmjs.com/package/@withpica/mcp-server/v/2.10.0
1745
+ - Published alongside `@withpica/mcp-sdk@1.4.0` and
1746
+ `@withpica/mcp-server-business@1.3.0` in ADR-163 Phase 6.
1747
+
1748
+ ## [2.9.0] — 2026-04-11
1749
+
1750
+ ### Added
1751
+
1752
+ - **ADR-164 audit follow-up: three new cascade MCP tools**
1753
+ - `pica_run_work_cascade(work_id)` — manually re-evaluate a work
1754
+ against every ADR-164 cascade rule and fire those whose
1755
+ preconditions are satisfied. Idempotent. Fire-and-forget. Backed by
1756
+ `POST /api/admin/works/:id/cascade-run`.
1757
+ - `pica_run_person_cascade(person_id)` — same for people. Fires
1758
+ `ipi_to_mlc_works` (MLC writer/publisher splits),
1759
+ `mbid_to_wikidata_crosswalk`, `isni_to_wikidata_crosswalk`,
1760
+ `wikidata_to_awards`, `wikidata_to_biography`, and
1761
+ `google_contact_suggest`. Backed by
1762
+ `POST /api/admin/people/:id/cascade-run`.
1763
+ - `pica_cascade_health` — snapshot of in-process cascade counters
1764
+ (ADR-164 Decision 5). Org-auth twin of the operator-only
1765
+ `/api/internal/cascade-health` endpoint. Returns per-rule failure
1766
+ counts bucketed by reason + outcome totals. Process-global, not
1767
+ persistent across serverless cold starts — treat as a spot-check.
1768
+
1769
+ ### Notes
1770
+
1771
+ - Source additions landed in `38901f281` (ADR-164 audit follow-ups).
1772
+ Version bump + rebuilt dist + publish tagged in `edfbcb07b`.
1773
+ - Minor bump per semver — new tools, no removed or renamed surface.
1774
+ - Registry URL:
1775
+ https://www.npmjs.com/package/@withpica/mcp-server/v/2.9.0
1776
+ - Tarball verified post-publish by pulling
1777
+ `withpica-mcp-server-2.9.0.tgz` from the registry and grepping for
1778
+ all three new tool names in `package/dist/tools/enrichment.js`.
1779
+
1780
+ ## [2.8.0] — 2026-04-10
1781
+
1782
+ ### Changed
1783
+
1784
+ - **ADR-162: subscription-based billing, credit gating disabled.**
1785
+ `withCreditGate` is now a pass-through — all tools are free for
1786
+ active subscribers. The MPP (Micropayment Protocol) machinery is
1787
+ retained in `@withpica/mcp-utils` for a future pay-per-credit
1788
+ re-enable but is dormant. Version bump carried in `7c4f5d24a`
1789
+ (`chore(adr-162): version bumps for npm publish`).
1790
+
1791
+ ## [2.7.0] — 2026-04-08
1792
+
1793
+ ### Added
1794
+
1795
+ - **ADR-158c custody tool release.** Six `pica_custody_*` tools go
1796
+ live: claim, accept, decline, dispute, incoming list, history.
1797
+ Version bump in `91dd1c275` (`chore(adr-158c): version bumps for
1798
+ custody tool release (Phase 6b)`).
1799
+
1800
+ ## [2.6.2] — pre-2026-04-08
1801
+
1802
+ ### Fixed
1803
+
1804
+ - Stale version constant in the boot banner — the banner was still
1805
+ reporting an older version after an earlier bump. Fixed in
1806
+ `980dabc02` (`fix(mcp-server): correct stale version constant in
1807
+ boot banner (2.6.2)`).
1808
+
1809
+ ## [2.6.1] — pre-2026-04-08
1810
+
1811
+ ### Fixed
1812
+
1813
+ - MCP server now emits `tools/list_changed` + `resources/list_changed`
1814
+ notifications after sign-in and sign-out, so clients refresh the
1815
+ tool list without a reconnect. Fixed in `f1ba2a211`.
1816
+
1817
+ ## [2.6.0] — 2026-04-07
1818
+
1819
+ ### Changed
1820
+
1821
+ - **ADR-155 launch — publish 6 packages.** Catalog server rebaselined
1822
+ from the broken `3.0.0` publish (deprecated + unpublished from npm
1823
+ because `file:` deps had been baked into the tarball, leaving every
1824
+ fresh installer dead) to `2.6.0`. Five new sibling packages
1825
+ (`@withpica/mcp-sdk`, `@withpica/mcp-utils`,
1826
+ `@withpica/mcp-server-business`, `-enrichment`, `-settings`)
1827
+ published at `1.0.0` alongside with real semver deps so `npm
1828
+ install` actually resolves on user machines.
1829
+ - `connect.withpica.com` leads with the no-api-key lobby-mode flow.
1830
+ Landed in `e235aed40` (`feat(mcp): ADR-155 launch — publish 6
1831
+ packages, lobby-mode connect copy`).
1832
+
1833
+ ## Pre-2.6.0 — pre-changelog era
1834
+
1835
+ Earlier versions (`2.0.0` through `2.5.x`) covered the pre-ADR-155
1836
+ monolithic MCP server. Version history for that era is reconstructable
1837
+ via `git log --follow -- mcp-server/package.json`. Notable milestones:
1838
+
1839
+ - `2.5.x` — MCP Apps prebuild script + ext-apps devDependency added
1840
+ - `2.4.x` — build/publish polish, `.vercel/` excluded from tarball
1841
+ - `~2.0.0` — ADR-149 agentic hardening (write tiers, ProposedAction,
1842
+ confirmation, audit, annotations)
1843
+
1844
+ [Unreleased]: https://github.com/withpica/pica/compare/edfbcb07b...HEAD
1845
+ [2.9.0]: https://github.com/withpica/pica/compare/7c4f5d24a...edfbcb07b
1846
+ [2.8.0]: https://github.com/withpica/pica/compare/91dd1c275...7c4f5d24a
1847
+ [2.7.0]: https://github.com/withpica/pica/compare/980dabc02...91dd1c275
1848
+ [2.6.2]: https://github.com/withpica/pica/compare/f1ba2a211...980dabc02
1849
+ [2.6.1]: https://github.com/withpica/pica/compare/e235aed40...f1ba2a211
1850
+ [2.6.0]: https://github.com/withpica/pica/commit/e235aed40