Marketplace: pin the commit the user reviewed (final review I2)

Install and update pinned whatever the marketplace head was when the
click landed, so a background refresh between review and click could
pin content nobody saw (including a hook's shell commands).
install_marketplace_item and update_marketplace_item now take
expected_commit and refuse with "changed since you reviewed this item —
review it again" unless it is still the head. The UI passes the head the
selected item was read at (Browse), the head frozen with a pending hook
confirm (whose commands are frozen too), and the head of the accepted
diff (Installed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 10:11:19 -07:00
co-authored by Claude Opus 5.5
parent f2ebddd073
commit dd019cf2c0
13 changed files with 197 additions and 65 deletions
+6 -4
View File
@@ -449,8 +449,9 @@ export const updateMarketplace = (marketplace: Marketplace) =>
invoke<AppSettings>("update_marketplace", { marketplace });
export const removeMarketplace = (marketplaceId: string) =>
invoke<AppSettings>("remove_marketplace", { marketplaceId });
export const installMarketplaceItem = (item: MarketplaceItemRef, scope: InstallScope) =>
invoke<AppSettings>("install_marketplace_item", { item, scope });
/** `expectedCommit`: the head the user reviewed; the backend refuses if it moved. */
export const installMarketplaceItem = (item: MarketplaceItemRef, scope: InstallScope, expectedCommit: string) =>
invoke<AppSettings>("install_marketplace_item", { item, scope, expectedCommit });
export const uninstallMarketplaceItem = (item: MarketplaceItemRef, scope: InstallScope) =>
invoke<void>("uninstall_marketplace_item", { item, scope });
export const setGlobalItemDisabled = (
@@ -466,8 +467,9 @@ export const marketplaceItemDiff = (
fromCommit: string,
toCommit: string,
) => invoke<FileDiff[]>("marketplace_item_diff", { item, fromCommit, toCommit });
export const updateMarketplaceItem = (item: MarketplaceItemRef, scope: InstallScope) =>
invoke<void>("update_marketplace_item", { item, scope });
/** `expectedCommit`: the head whose diff the user accepted; the backend refuses if it moved. */
export const updateMarketplaceItem = (item: MarketplaceItemRef, scope: InstallScope, expectedCommit: string) =>
invoke<void>("update_marketplace_item", { item, scope, expectedCommit });
export const applyMarketplaceNow = (projectId?: string) =>
invoke<ProjectSyncResult[]>("apply_marketplace_now", { projectId: projectId ?? null });
export const getMarketplaceSyncReport = (projectId: string) =>