Repository navigation
fix: session native tools and extensions details - #330
Conversation
|
Too many files changed for review (177 files, 100 file limit). Bypass the limit by tagging |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (4)
📒 Files selected for processing (23)
Disabled knowledge base sources:
WalkthroughThe change reconciles bundled extension provenance, redesigns marketplace detail views and routing, adds Darwin MCP peer inspection, replaces loop status filtering, updates SSE handshakes, and bases live-data ownership on window stack activity. ChangesBundled provenance reconciliation
Darwin MCP peer inspection
Marketplace detail redesign
Loop catalog filters
Window live-data eligibility
Extension log stream handshake
Settings import paths
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant MarketplaceRoute
participant MarketplaceDetail
participant InstalledState
participant MCPServer
User->>MarketplaceRoute: open marketplace entry
MarketplaceRoute->>MarketplaceDetail: pass kind, entry ID, and market tab
MarketplaceDetail->>InstalledState: load installed detail state
InstalledState->>MCPServer: resolve installed server and authorization state
MCPServer-->>InstalledState: return runtime and authorization data
InstalledState-->>MarketplaceDetail: render management detail
MarketplaceDetail-->>User: display detail sections and actions
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
React Doctor found 1 new issue in 1 file · 1 error · score 84 / 100 (Needs work) · 0 fixed · vs Errors
Reviewed by React Doctor for commit |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (14)
internal/extension/provenance.go (1)
126-135: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMake the
ChecksumVerifiedrule explicit per source.
ChecksumVerified: source != SourceMarketplacemarks every non-marketplace source as checksum-verified, includingSourceUserandSourceWorkspace. The sibling helperLocalPathProvenance(lines 100-109) setsChecksumVerified: falsefor local paths and attaches an unverified diagnostic. The two paths now disagree for the same kind of local install. A reader cannot tell which rule is authoritative.Consider a switch on
sourceso each source states its own verification and tier, instead of one negated comparison plus a follow-upif.♻️ Suggested clarification
- provenance := ExtensionProvenance{ - InstalledFrom: installedFromForSource(source), - SourceURL: strings.TrimSpace(sourceURL), - ChecksumSHA256: strings.TrimSpace(checksum), - ChecksumVerified: source != SourceMarketplace, - RegistryTier: ExtensionRegistryTierUnverified, - Permissions: append([]string(nil), permissions...), - InstalledAt: installedAt.UTC(), - InstalledBy: extensionTrustInstalledByOperator, - } - if source == SourceBundled { - provenance.RegistryTier = ExtensionRegistryTierOfficial - } - return provenance + provenance := ExtensionProvenance{ + InstalledFrom: installedFromForSource(source), + SourceURL: strings.TrimSpace(sourceURL), + ChecksumSHA256: strings.TrimSpace(checksum), + RegistryTier: ExtensionRegistryTierUnverified, + Permissions: append([]string(nil), permissions...), + InstalledAt: installedAt.UTC(), + InstalledBy: extensionTrustInstalledByOperator, + } + switch source { + case SourceBundled: + // First-party artifact: checksum is computed from the embedded payload. + provenance.ChecksumVerified = true + provenance.RegistryTier = ExtensionRegistryTierOfficial + case SourceMarketplace: + // Remote archive: verification happens in the marketplace install path. + provenance.ChecksumVerified = false + default: + // Local path installs: checksum is recomputed at install time. + provenance.ChecksumVerified = true + } + return provenance🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/extension/provenance.go` around lines 126 - 135, Update the provenance construction around ExtensionProvenance to use an explicit source-based switch for ChecksumVerified and RegistryTier, rather than source != SourceMarketplace. Ensure SourceMarketplace, SourceUser, and SourceWorkspace each state their intended verification and tier consistently with LocalPathProvenance, while preserving the existing permissions, timestamps, installer, and checksum fields.internal/extension/registry_bundled.go (1)
30-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLog the provenance rewrite.
This function rewrites persisted trust evidence for an installed extension and produces no log record and no event. An operator cannot tell later that the stored provenance changed, or why the trust decision moved from
blockedtoverified. Add anslogrecord with the extension name, the previousinstalled_from, and the previousregistry_tierbefore the update.The coding guidelines require
slogininternalproduction code and a canonical event for every domain operation.♻️ Suggested addition
if bytes.Equal(currentJSON, provenanceJSON) { return nil } + slog.Info( + "reconciling bundled extension provenance", + "extension", info.Name, + "previous_installed_from", info.Provenance.InstalledFrom, + "previous_registry_tier", info.Provenance.RegistryTier, + "registry_tier", provenance.RegistryTier, + ) result, err := r.db.ExecContext(🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/extension/registry_bundled.go` around lines 30 - 47, Before rewriting persisted provenance in the function containing the `extensionInstallProvenance` comparison, emit the canonical provenance-update event and an `slog` record. Include the extension name plus the previous provenance’s `installed_from` and `registry_tier`, and ensure the event/log occurs only when `bytes.Equal(currentJSON, provenanceJSON)` is false and before persistence.Source: Coding guidelines
extensions/dev-cycle/embed_test.go (1)
172-172: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert against the exported constant instead of the literal.
Both assertions compare
InstalledFromwith the literal"bundled". The PR addsextensionpkg.ExtensionInstalledFromBundledfor this value, and the adjacent assertions already use exported constants. Use the constant so the test tracks the contract rather than a copied string.💚 Proposed fix
- if installed.Provenance.InstalledFrom != "bundled" || + if installed.Provenance.InstalledFrom != extensionpkg.ExtensionInstalledFromBundled || installed.Provenance.RegistryTier != extensionpkg.ExtensionRegistryTierOfficial ||- if after.Provenance.InstalledFrom != "bundled" || + if after.Provenance.InstalledFrom != extensionpkg.ExtensionInstalledFromBundled || after.Provenance.RegistryTier != extensionpkg.ExtensionRegistryTierOfficial ||Also applies to: 334-334
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@extensions/dev-cycle/embed_test.go` at line 172, Update both assertions on installed.Provenance.InstalledFrom in the relevant test to compare against the exported extensionpkg.ExtensionInstalledFromBundled constant instead of the duplicated "bundled" literal, matching the adjacent assertions.internal/api/core/marketplace_installed_detail.go (1)
128-128: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCentralize the installed marketplace manage paths.
internal/api/core/marketplace_paths.goalready holdsmarketplaceExtensionsInstalledPath, but the MCP and skill paths remain inline literals at four sites. Declare matching constants and reference them everywhere.
internal/api/core/marketplace_installed_detail.go#L128-L128: replace the/marketplace/mcpsliteral, and the/marketplace/skillsliteral at line 191, with the new constants.internal/api/core/marketplace_list.go#L257-L320: replace the/marketplace/mcpsliteral at line 257 and the/marketplace/skillsliteral at line 320 with the same constants.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/marketplace_installed_detail.go` at line 128, Centralize the installed marketplace manage paths by declaring constants alongside marketplaceExtensionsInstalledPath in marketplace_paths.go, then update internal/api/core/marketplace_installed_detail.go lines 128-191 and internal/api/core/marketplace_list.go lines 257-320 to use those constants instead of inline MCP and skill path literals.internal/api/core/marketplace_list.go (1)
257-257: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReuse shared path constants here too.
These two literals duplicate the values used in
internal/api/core/marketplace_installed_detail.go. Replace them with the shared constants declared ininternal/api/core/marketplace_paths.go.Also applies to: 320-320
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/api/core/marketplace_list.go` at line 257, Replace the duplicated managePath literals in the marketplace list entries with the shared path constants from marketplace_paths.go, including the occurrence near line 320. Reuse the existing constants without changing the surrounding marketplace behavior.web/src/systems/marketplace/components/marketplace-detail.tsx (1)
27-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider a kind-to-view map.
Three independent ternaries render the kind views. An unrecognized
kindrenders the lede with no body and no diagnostic. A small record keyed by kind makes the dispatch exhaustive and keeps the JSX flat.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/components/marketplace-detail.tsx` around lines 27 - 41, Replace the independent kind checks in the marketplace detail component with a kind-to-view record keyed by the supported marketplace kinds, then render the selected view through that map while preserving the existing props for each view. Make the dispatch exhaustive so an unrecognized kind produces an explicit diagnostic instead of rendering only the lede.web/src/systems/marketplace/components/marketplace-kind-page.tsx (1)
113-122: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider limiting
config_scopeto MCP routes.
page.mcpConfigScopealways resolves to a value, because the hook derives a default whensearch.config_scopeis absent. Every kind link therefore emitsconfig_scopein the URL, including the skills and extensions routes where the value has no effect. Pass the parameter only when the destination is the MCP route, or only when the current search already carries it.♻️ Proposed change
render={ <Link search={{ - config_scope: page.mcpConfigScope, + config_scope: item.kind === "mcp" ? page.mcpConfigScope : undefined, q: page.query || undefined, tab: page.scope === "market" ? "market" : undefined, }} to={item.to} /> }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/components/marketplace-kind-page.tsx` around lines 113 - 122, Update the kind-link `Link` search configuration so `config_scope` is included only for MCP destinations, or when the current search explicitly contains it, instead of always using the defaulted `page.mcpConfigScope`. Preserve the existing query and tab behavior for skills, extensions, and MCP routes.web/src/systems/marketplace/components/marketplace-detail-shell.tsx (2)
17-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConfirm the fixed rail width matches the documented 320px contract.
The doc comment at Lines 6-10 states a 320px rail. The grid template uses
20rem. Those match only while the root font size is 16px. If the design system defines a rail width token, use it instead of the literal20rem.As per coding guidelines: "Use tokens from
packages/ui/src/tokens.cssandDESIGN.mdfor all color, type, radius, spacing, and motion values; do not invent design values."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/components/marketplace-detail-shell.tsx` around lines 17 - 24, Update the rail column definition in MarketplaceDetailColumns to use the existing design-system token for the documented 320px rail width, rather than the literal 20rem value. Reuse the token defined in packages/ui/src/tokens.css or DESIGN.md and preserve the current responsive grid behavior.Source: Coding guidelines
44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRemove manual
useIdwiring onCollapsiblecomponents.@compozy/ui’sCollapsibledelegates to@base-ui/react/collapsible, which automatically associates trigger and content. TheuseId().replace(/:/g, "")value is not needed, at bothmarketplace-detail-shell.tsx:44andmarketplace-detail-shell.tsx:145.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/components/marketplace-detail-shell.tsx` at line 44, Remove the manual useId-based panelId wiring from both Collapsible usages in marketplace-detail-shell.tsx at lines 44-44 and 145-145; remove the associated panelId references and rely on Collapsible’s automatic trigger/content association.web/src/systems/marketplace/components/marketplace-detail-mcp.tsx (1)
322-327: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse
cnfor the status cell classes.The rest of this file and
marketplace-detail-shell.tsxcompose classes withcn. This helper concatenates strings manually and encodes the grid position rules in index arithmetic, which breaks silently if the cell count changes.♻️ Proposed refactor
-function cnStatusCell(index: number): string { - const base = "flex flex-col items-start gap-1.5 px-3.5 py-2.5"; - const divider = index % 2 === 0 ? " border-r border-line-soft" : ""; - const top = index >= 2 ? " border-t border-line-soft" : ""; - return `${base}${divider}${top}`; -} +const STATUS_CELL_CLASS = cn( + "flex flex-col items-start gap-1.5 px-3.5 py-2.5", + "border-line-soft not-nth-[2n]:border-r [&:nth-child(n+3)]:border-t" +);An equivalent option is to keep the function and wrap the parts in
cn.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/components/marketplace-detail-mcp.tsx` around lines 322 - 327, Update cnStatusCell to compose its conditional status-cell classes with the existing cn utility instead of manual string interpolation. Preserve the current base, divider, and top-border class rules while passing them as separate conditional arguments, avoiding index-derived concatenation that can silently break when the grid changes.web/src/systems/marketplace/hooks/use-marketplace-detail-mcp-server.ts (1)
22-24: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueThe
entry.namefallback can bind the wrong server.
entry.nameis the catalog display name.server.nameis the installed identity. If a catalog entry's display name equals an unrelated installed server name, this fallback resolves the wrong row, and the detail view then shows that server's status, tools, and registration. Consider restricting the fallback tocatalog_entry, or comparing a normalized slug rather than the display name.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/hooks/use-marketplace-detail-mcp-server.ts` around lines 22 - 24, Update the server lookup around the find callback to avoid matching server.name against entry.name, since display names can identify unrelated installed servers. Restrict matching to the catalog_entry identity, or use an established normalized-slug comparison if one already exists, while preserving the existing catalog entry match behavior.web/src/systems/marketplace/components/marketplace-detail-mcp-topbar.tsx (1)
64-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueExtract the duplicated fallback branch.
The branch at Lines 64-76 and the branch at Lines 82-99 render the same
MarketplaceEntryStatusandMarketplaceEntryActionpair. Only theMCPAuthorizeDialogdiffers. Extract the shared pair into a local component and render the dialog conditionally.♻️ Proposed refactor
+ const standardHead = ( + <> + <MarketplaceEntryStatus entry={entry} /> + <MarketplaceEntryAction + emphasis="primary" + entry={entry} + onAction={onAction} + pending={pending} + /> + </> + ); + + if (!polledServer) return standardHead; + + const status = composeMCPRowStatus(polledServer); + const label = status.authorizeLabel; + const authFilter = deriveMCPAuthFilter(polledServer); + + if (!label) { + return ( + <> + {standardHead} + <MCPAuthorizeDialog + authorize={authorize} + scope={authFilter?.scope ?? "global"} + server={polledServer} + /> + </> + ); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/components/marketplace-detail-mcp-topbar.tsx` around lines 64 - 99, In the component containing the polledServer status flow, extract the shared MarketplaceEntryStatus and MarketplaceEntryAction pair into a local component or reusable render path. Use it in both the !polledServer branch and the !label branch, while rendering MCPAuthorizeDialog only conditionally for the latter with its existing authorize, scope, and server props.web/src/systems/marketplace/components/marketplace-detail-extension-installed.tsx (1)
363-364: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePass
factsinto the runtime card instead of recomputing it.The parent computes
factsat Line 96 and passes it toMarketplaceExtensionManageCardandMarketplaceExtensionProvenanceCard.MarketplaceExtensionRuntimeCardcallsextensionTrustFacts(extension)again. Reuse the single computed value so all cards read identical facts and the derivation runs once per render.♻️ Proposed refactor
-function MarketplaceExtensionRuntimeCard({ extension }: { extension: ExtensionEntry }) { - const facts = extensionTrustFacts(extension); +function MarketplaceExtensionRuntimeCard({ + extension, + facts, +}: { + extension: ExtensionEntry; + facts: ReturnType<typeof extensionTrustFacts>; +}) {Update the call site at Line 121:
- <MarketplaceExtensionRuntimeCard extension={extension} /> + <MarketplaceExtensionRuntimeCard extension={extension} facts={facts} />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/components/marketplace-detail-extension-installed.tsx` around lines 363 - 364, Update MarketplaceExtensionRuntimeCard to accept the already-derived facts value as a prop, remove its direct extensionTrustFacts(extension) call, and pass facts from the parent call site alongside the other cards so trust facts are computed once and shared consistently.web/src/systems/marketplace/components/marketplace-detail-skill-installed.tsx (1)
153-192: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse the shared manage-fallback instead of duplicating it.
MarketplaceSkillManageFallbackrepeats the layout, spinner and alert icons, testId scheme, error paragraph, and retry button ofMarketplaceDetailManageFallbackCardinweb/src/systems/marketplace/components/marketplace-detail-manage-state.tsx, which the installed-extension detail already uses. Two copies of the same failure-state contract will diverge. Extract the inner body of the shared component (for exampleMarketplaceDetailManageFallbackBody) and consume it from both files, keeping the card wrapper optional.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/systems/marketplace/components/marketplace-detail-skill-installed.tsx` around lines 153 - 192, Extract the duplicated loading/error content from MarketplaceSkillManageFallback into a shared component such as MarketplaceDetailManageFallbackBody in marketplace-detail-manage-state.tsx. Reuse that body from both MarketplaceDetailManageFallbackCard and MarketplaceSkillManageFallback, keeping the card wrapper optional while preserving the existing loading/error states, test IDs, message, error details, icons, and retry behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@extensions/dev-cycle/embed_test.go`:
- Around line 303-307: Update the stale fixture in the provenance test by
inverting stale.ChecksumVerified and stale.AllowUnverified from their asserted
expected values, while preserving the existing assertions around
extensionInstallProvenance so the test independently verifies repair of all four
provenance fields.
In `@internal/extension/provenance.go`:
- Around line 119-140: Update extensionInstallProvenance so SourceUser and
SourceWorkspace remain checksum-unverified; do not derive ChecksumVerified
solely from source != SourceMarketplace. Preserve the existing unverified
RegistryTier and ensure exposed provenance and event payloads never claim local
extensions are checksum verified.
In `@internal/extension/registry_bundled.go`:
- Around line 48-64: Update the affected-row validation in the bundled
provenance reconciliation flow after RowsAffected to treat affected == 0 as a
successful no-op, while still returning an error when affected > 1. Preserve the
existing ExecContext, RowsAffected error handling, and single-row success
behavior.
In `@web/src/routes/_app/marketplace`.$kind.$entryId.tsx:
- Around line 14-20: Update the marketplace detail navigation search in
web/src/routes/_app/marketplace.$kind.$entryId.tsx lines 14-20 and the
corresponding MarketplaceCard navigation in
web/src/systems/marketplace/components/marketplace-card.tsx lines 40-50 to use a
shallow search update that preserves existing scope and workspace_id parameters
while setting tab to "market"; do not replace the full search object with only
the tab value.
In
`@web/src/systems/marketplace/components/__tests__/marketplace-components.test.tsx`:
- Around line 1532-1533: Update the marketplace card link and its test
expectation to use the declared detail-route shape
`/_app/marketplace/$kind/$entryId`, such as
`/marketplace/skill/git-flow?tab=market`, instead of the nonexistent
`/marketplace/skill/docs-sync?tab=market` path; keep the `/marketplace/skills`
route check unchanged.
In `@web/src/systems/marketplace/components/marketplace-detail-lede.tsx`:
- Around line 63-65: Update the marketplace detail rendering around
entry.description to trim and validate the value before rendering the paragraph.
Render the existing description <p> only when the trimmed description is
non-empty, and use the trimmed value for its content while preserving the
current styling.
In `@web/src/systems/marketplace/components/marketplace-detail-mcp-topbar.tsx`:
- Around line 49-62: Update the MCP authorization polling flow around
authPollQuery and the useEffect to handle authPollQuery.error instead of
silently falling back to stale server data. Store or propagate the polling error
through the existing authorization state, then render it in the authorize
dialog/topbar flow so failures are surfaced and awaiting authorization can exit
or display the error.
In `@web/src/systems/marketplace/components/marketplace-detail-mcp.tsx`:
- Around line 46-69: Update the installedUnresolved fallback in the marketplace
MCP detail component to distinguish a disabled workspace-scoped query from an
actual loading or error state. When queryEnabled is false because no workspace
is selected, avoid rendering the retry-based MarketplaceDetailManageFallbackCard
and show the appropriate workspace-selection message instead; preserve the
existing fallback behavior for enabled queries.
- Around line 107-122: Align the banner condition in
MarketplaceMCPAuthorizationSection with the topbar button’s
composeMCPRowStatus(server).authorizeLabel logic so it only promises an
Authorize button when that button is rendered. Preserve the existing OAuth
banner behavior, and handle non-OAuth states such as stdio needs_login by
suppressing the banner or using copy and an action target that actually exists.
In
`@web/src/systems/marketplace/components/marketplace-detail-skill-installed.tsx`:
- Around line 331-335: Update both error-rendering sections in
web/src/systems/marketplace/components/marketplace-detail-skill-installed.tsx at
lines 331-335 and 403-406 to use a trimmed non-empty error message, falling back
to the existing section-specific text when empty or whitespace-only. Apply this
to the content-load error and skill-resolution error handling.
---
Nitpick comments:
In `@extensions/dev-cycle/embed_test.go`:
- Line 172: Update both assertions on installed.Provenance.InstalledFrom in the
relevant test to compare against the exported
extensionpkg.ExtensionInstalledFromBundled constant instead of the duplicated
"bundled" literal, matching the adjacent assertions.
In `@internal/api/core/marketplace_installed_detail.go`:
- Line 128: Centralize the installed marketplace manage paths by declaring
constants alongside marketplaceExtensionsInstalledPath in marketplace_paths.go,
then update internal/api/core/marketplace_installed_detail.go lines 128-191 and
internal/api/core/marketplace_list.go lines 257-320 to use those constants
instead of inline MCP and skill path literals.
In `@internal/api/core/marketplace_list.go`:
- Line 257: Replace the duplicated managePath literals in the marketplace list
entries with the shared path constants from marketplace_paths.go, including the
occurrence near line 320. Reuse the existing constants without changing the
surrounding marketplace behavior.
In `@internal/extension/provenance.go`:
- Around line 126-135: Update the provenance construction around
ExtensionProvenance to use an explicit source-based switch for ChecksumVerified
and RegistryTier, rather than source != SourceMarketplace. Ensure
SourceMarketplace, SourceUser, and SourceWorkspace each state their intended
verification and tier consistently with LocalPathProvenance, while preserving
the existing permissions, timestamps, installer, and checksum fields.
In `@internal/extension/registry_bundled.go`:
- Around line 30-47: Before rewriting persisted provenance in the function
containing the `extensionInstallProvenance` comparison, emit the canonical
provenance-update event and an `slog` record. Include the extension name plus
the previous provenance’s `installed_from` and `registry_tier`, and ensure the
event/log occurs only when `bytes.Equal(currentJSON, provenanceJSON)` is false
and before persistence.
In
`@web/src/systems/marketplace/components/marketplace-detail-extension-installed.tsx`:
- Around line 363-364: Update MarketplaceExtensionRuntimeCard to accept the
already-derived facts value as a prop, remove its direct
extensionTrustFacts(extension) call, and pass facts from the parent call site
alongside the other cards so trust facts are computed once and shared
consistently.
In `@web/src/systems/marketplace/components/marketplace-detail-mcp-topbar.tsx`:
- Around line 64-99: In the component containing the polledServer status flow,
extract the shared MarketplaceEntryStatus and MarketplaceEntryAction pair into a
local component or reusable render path. Use it in both the !polledServer branch
and the !label branch, while rendering MCPAuthorizeDialog only conditionally for
the latter with its existing authorize, scope, and server props.
In `@web/src/systems/marketplace/components/marketplace-detail-mcp.tsx`:
- Around line 322-327: Update cnStatusCell to compose its conditional
status-cell classes with the existing cn utility instead of manual string
interpolation. Preserve the current base, divider, and top-border class rules
while passing them as separate conditional arguments, avoiding index-derived
concatenation that can silently break when the grid changes.
In `@web/src/systems/marketplace/components/marketplace-detail-shell.tsx`:
- Around line 17-24: Update the rail column definition in
MarketplaceDetailColumns to use the existing design-system token for the
documented 320px rail width, rather than the literal 20rem value. Reuse the
token defined in packages/ui/src/tokens.css or DESIGN.md and preserve the
current responsive grid behavior.
- Line 44: Remove the manual useId-based panelId wiring from both Collapsible
usages in marketplace-detail-shell.tsx at lines 44-44 and 145-145; remove the
associated panelId references and rely on Collapsible’s automatic
trigger/content association.
In
`@web/src/systems/marketplace/components/marketplace-detail-skill-installed.tsx`:
- Around line 153-192: Extract the duplicated loading/error content from
MarketplaceSkillManageFallback into a shared component such as
MarketplaceDetailManageFallbackBody in marketplace-detail-manage-state.tsx.
Reuse that body from both MarketplaceDetailManageFallbackCard and
MarketplaceSkillManageFallback, keeping the card wrapper optional while
preserving the existing loading/error states, test IDs, message, error details,
icons, and retry behavior.
In `@web/src/systems/marketplace/components/marketplace-detail.tsx`:
- Around line 27-41: Replace the independent kind checks in the marketplace
detail component with a kind-to-view record keyed by the supported marketplace
kinds, then render the selected view through that map while preserving the
existing props for each view. Make the dispatch exhaustive so an unrecognized
kind produces an explicit diagnostic instead of rendering only the lede.
In `@web/src/systems/marketplace/components/marketplace-kind-page.tsx`:
- Around line 113-122: Update the kind-link `Link` search configuration so
`config_scope` is included only for MCP destinations, or when the current search
explicitly contains it, instead of always using the defaulted
`page.mcpConfigScope`. Preserve the existing query and tab behavior for skills,
extensions, and MCP routes.
In `@web/src/systems/marketplace/hooks/use-marketplace-detail-mcp-server.ts`:
- Around line 22-24: Update the server lookup around the find callback to avoid
matching server.name against entry.name, since display names can identify
unrelated installed servers. Restrict matching to the catalog_entry identity, or
use an established normalized-slug comparison if one already exists, while
preserving the existing catalog entry match behavior.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 47627486-a83a-4286-939b-16e5cfbcde87
⛔ Files ignored due to path filters (106)
.github/workflows/ci.ymlis excluded by!**/*.ymldocs/design/opendesign/.od-skills/web-prototype-04e8971585/SKILL.mdis excluded by!docs/design/**/*,!**/*.mddocs/design/opendesign/.od-skills/web-prototype-04e8971585/assets/template.htmlis excluded by!docs/design/**/*docs/design/opendesign/.od-skills/web-prototype-04e8971585/example.htmlis excluded by!docs/design/**/*docs/design/opendesign/.od-skills/web-prototype-04e8971585/open-design.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/.od-skills/web-prototype-04e8971585/references/checklist.mdis excluded by!docs/design/**/*,!**/*.mddocs/design/opendesign/.od-skills/web-prototype-04e8971585/references/layouts.mdis excluded by!docs/design/**/*,!**/*.mddocs/design/opendesign/CleanShot-2026-08-02-at-00.46.42_2x.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-index.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-detail.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-editor-states.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-editor.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-inventories.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-node-controls.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-quarantine-sheet.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-run-detail-states.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-run-detail.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loop-run-form.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/loops-loops-catalog.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/site-docs-landing.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/site-docs-sidebar.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/site-example-page.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/site-marketplace-detail.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/site-marketplace-hero-v2.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/site-marketplace-list.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_captures/site-marketplace.pngis excluded by!**/*.png,!docs/design/**/*docs/design/opendesign/_done/marketplace/UNIFIED-CATALOG-SPEC.mdis excluded by!docs/design/**/*,!**/*.mddocs/design/opendesign/_done/session/SESSION-REDESIGN-SPEC.mdis excluded by!docs/design/**/*,!**/*.mddocs/design/opendesign/_done/session/_vc-capture-fast.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/session/_vc-capture-fast.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/session/_vc-capture-normal.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/session/_vc-capture-normal.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/session/index.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/session/index.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/session/runtime-selector-variations.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/session/runtime-selector-variations.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/session/session-chat.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/session/session-chat.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/session/session-design-system.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/session/session-design-system.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/session/session-sidebar.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/session/session-sidebar.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/session/session.cssis excluded by!docs/design/**/*docs/design/opendesign/_done/site/site-docs-landing.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/site/site-docs-landing.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/site/site-docs-sidebar.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/site/site-docs-sidebar.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/site/site-example-page.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/site/site-example-page.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/site/site-marketplace-detail.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/site/site-marketplace-detail.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/site/site-marketplace-list.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/site/site-marketplace-list.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/site/site-marketplace.htmlis excluded by!docs/design/**/*docs/design/opendesign/_done/site/site-marketplace.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/_done/site/site.cssis excluded by!docs/design/**/*docs/design/opendesign/_done/site/site.jsis excluded by!docs/design/**/*docs/design/opendesign/empty-states/jobs-empty-suggestions.htmlis excluded by!docs/design/**/*docs/design/opendesign/empty-states/jobs-empty-suggestions.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/empty-states/tasks-empty-templates.htmlis excluded by!docs/design/**/*docs/design/opendesign/empty-states/tasks-empty-templates.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/empty-states/triggers-empty-suggestions.htmlis excluded by!docs/design/**/*docs/design/opendesign/empty-states/triggers-empty-suggestions.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/marketplace/extension-detail.htmlis excluded by!docs/design/**/*docs/design/opendesign/marketplace/extension-detail.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/marketplace/index.htmlis excluded by!docs/design/**/*docs/design/opendesign/marketplace/index.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/marketplace/marketplace.cssis excluded by!docs/design/**/*docs/design/opendesign/marketplace/mcp-detail.htmlis excluded by!docs/design/**/*docs/design/opendesign/marketplace/mcp-detail.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/design/opendesign/marketplace/skill-detail.htmlis excluded by!docs/design/**/*docs/design/opendesign/marketplace/skill-detail.html.artifact.jsonis excluded by!docs/design/**/*,!**/*.jsondocs/qa/charters/CH-bundled-extension-trust.mdis excluded by!**/*.mddocs/qa/charters/CH-codex-native-tools-cgo0.mdis excluded by!**/*.mddocs/qa/charters/CH-marketplace-installed-default.mdis excluded by!**/*.mddocs/qa/charters/CH-visible-session-window-streams.mdis excluded by!**/*.mddocs/qa/journeys/J-13-follow-a-live-run.mdis excluded by!**/*.mddocs/qa/journeys/J-extension-kit-lifecycle.mdis excluded by!**/*.mddocs/qa/journeys/J-extension-policy-admin.mdis excluded by!**/*.mddocs/qa/journeys/J-marketplace-acquisition.mdis excluded by!**/*.mddocs/qa/reports/2026-08-07-critical-runtime-ui-fixes.mdis excluded by!**/*.mddocs/qa/scenarios/ET-001.mdis excluded by!**/*.mddocs/qa/scenarios/ET-048.mdis excluded by!**/*.mddocs/qa/scenarios/ET-bundled-extension-trust.mdis excluded by!**/*.mddocs/qa/scenarios/ET-compozy-native-tool-invocation.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-extension-detail.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-extension-kit-inventory.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-extensions-manage.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-marketplace-installed-management.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-marketplace-kind-navigation.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-marketplace-landing-browse.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-marketplace-mcp-authorize-installed.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-mcp-remote-editor.mdis excluded by!**/*.mddocs/qa/scenarios/ET-web-mcp-status-matrix.mdis excluded by!**/*.mddocs/qa/scenarios/RT-visible-session-streaming.mdis excluded by!**/*.mdinternal/testutil/acpmock/testdata/os_shell_multi_session_fixture.jsonis excluded by!**/*.jsonpackages/site/content/docs/configuration/mcp-json.mdxis excluded by!**/*.mdxpackages/site/content/docs/marketplace/index.mdxis excluded by!**/*.mdxskills/compozy/references/extensions.mdis excluded by!**/*.mdweb/e2e/__tests__/marketplace.spec.tsis excluded by!web/e2e/**web/e2e/__tests__/os-shell.spec.tsis excluded by!web/e2e/**web/e2e/__tests__/settings.spec.tsis excluded by!web/e2e/**web/e2e/fixtures/__tests__/browser-artifact-session.test.tsis excluded by!**/fixtures/**,!web/e2e/**web/src/systems/marketplace/components/stories/marketplace-overlays.stories.tsxis excluded by!**/*.stories.tsxweb/src/systems/marketplace/routes/marketplace.stories.tsxis excluded by!**/*.stories.tsxweb/src/systems/settings/routes/mcp-servers.stories.tsxis excluded by!**/*.stories.tsx
📒 Files selected for processing (65)
extensions/dev-cycle/embed_test.goextensions/dev-cycle/install.gointernal/api/core/marketplace_installed_detail.gointernal/api/core/marketplace_list.gointernal/api/core/marketplace_paths.gointernal/api/core/marketplace_test.gointernal/api/core/settings_test.gointernal/extension/provenance.gointernal/extension/registry_bundled.gointernal/extension/registry_install.gointernal/extension/registry_scan.gointernal/mcp/peer_darwin.gointernal/mcp/peer_darwin_cgo.gointernal/mcp/peer_darwin_nocgo.gointernal/mcp/peer_test.gointernal/settings/section_skills_target.gointernal/settings/service_test.goweb/src/routes/_app/marketplace.$kind.$entryId.tsxweb/src/routes/_app/settings/-skills-settings-page.tsxweb/src/storybook/route-story-registry.tsweb/src/systems/extensions/components/extension-kit-inventory-panel.tsxweb/src/systems/extensions/components/extension-log-panel.tsxweb/src/systems/loops/components/__tests__/loop-catalog.test.tsxweb/src/systems/loops/components/catalog/loop-catalog-filters.tsxweb/src/systems/loops/lib/__tests__/loop-list-filters.test.tsweb/src/systems/loops/lib/loop-list-filters.tsweb/src/systems/marketplace/components/__tests__/marketplace-action-controller.test.tsxweb/src/systems/marketplace/components/__tests__/marketplace-components.test.tsxweb/src/systems/marketplace/components/__tests__/marketplace-detail-manage.test.tsxweb/src/systems/marketplace/components/index.tsweb/src/systems/marketplace/components/marketplace-card.tsxweb/src/systems/marketplace/components/marketplace-detail-extension-actions.tsxweb/src/systems/marketplace/components/marketplace-detail-extension-installed.tsxweb/src/systems/marketplace/components/marketplace-detail-extension-manage.tsxweb/src/systems/marketplace/components/marketplace-detail-extension-sections.tsxweb/src/systems/marketplace/components/marketplace-detail-extension.tsxweb/src/systems/marketplace/components/marketplace-detail-lede.tsxweb/src/systems/marketplace/components/marketplace-detail-manage-state.tsxweb/src/systems/marketplace/components/marketplace-detail-mcp-manage.tsxweb/src/systems/marketplace/components/marketplace-detail-mcp-topbar.tsxweb/src/systems/marketplace/components/marketplace-detail-mcp.tsxweb/src/systems/marketplace/components/marketplace-detail-meta.tsxweb/src/systems/marketplace/components/marketplace-detail-shell.tsxweb/src/systems/marketplace/components/marketplace-detail-skill-installed.tsxweb/src/systems/marketplace/components/marketplace-detail-skill-manage.tsxweb/src/systems/marketplace/components/marketplace-detail-skill.tsxweb/src/systems/marketplace/components/marketplace-detail-warnings.tsxweb/src/systems/marketplace/components/marketplace-detail.tsxweb/src/systems/marketplace/components/marketplace-kind-page.tsxweb/src/systems/marketplace/components/use-marketplace-action-controller.tsxweb/src/systems/marketplace/hooks/use-marketplace-detail-mcp-server.tsweb/src/systems/marketplace/hooks/use-marketplace-kind-page.tsweb/src/systems/marketplace/lib/marketplace-kind-search.tsweb/src/systems/marketplace/mocks/fixtures.tsweb/src/systems/os/apps/dashboard/__tests__/dashboard-window.test.tsxweb/src/systems/os/apps/marketplace/marketplace-detail-location.tsxweb/src/systems/os/apps/marketplace/marketplace-detail-search.tsweb/src/systems/os/apps/session/__tests__/session-window.test.tsxweb/src/systems/os/hooks/use-window-live-data-enabled.tsweb/src/systems/settings/adapters/__tests__/settings-api.test.tsweb/src/systems/settings/hooks/__tests__/use-settings-skills-page.test.tsxweb/src/systems/settings/hooks/use-settings-network-page.tsweb/src/systems/settings/hooks/use-settings-providers-page.tsweb/src/systems/settings/hooks/use-settings-skills-page.tsweb/src/systems/settings/mocks/fixtures.ts
💤 Files with no reviewable changes (7)
- internal/mcp/peer_darwin_nocgo.go
- internal/mcp/peer_darwin_cgo.go
- web/src/systems/marketplace/components/marketplace-detail-mcp-manage.tsx
- web/src/systems/marketplace/components/marketplace-detail-extension-manage.tsx
- web/src/systems/marketplace/components/marketplace-detail-meta.tsx
- web/src/systems/marketplace/components/marketplace-detail-skill-manage.tsx
- web/src/systems/loops/components/tests/loop-catalog.test.tsx
| "/marketplace/skills" | ||
| ); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Locate the marketplace route files and their search schemas.
fd -t f 'marketplace' web/src/routes
# Inspect the detail route search validation and the kind route.
fd -t f 'marketplace' web/src/routes --exec rg -n -C6 'validateSearch|tab|kind'
# Inspect the path helpers that build these links.
fd -t f 'marketplace-detail-search|marketplace-kind-search|marketplace-paths' web/src internal --exec rg -n -C6 'tab|market|installed'Repository: compozy/compozy
Length of output: 4697
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the marketplace test lines around the reviewed links and the utility paths used there.
sed -n '1515,1585p' web/src/systems/marketplace/components/__tests__/marketplace-components.test.tsx
# Find implementations/helpers that build marketplace links and resolve the exact strings.
rg -n -C4 'marketplaceKindPath|marketplaceRouteKindFor|/marketplace/skills|tab=market|Installed|installed' web/src/systems/marketplace web/src/routes/_app --glob '!**/*.test.tsx'Repository: compozy/compozy
Length of output: 50372
Fix the marketplace card link to use an existing route shape.
/marketplace/skills is a declared route, so this check is valid. The link /marketplace/skill/docs-sync?tab=market targets no declared route; use the detail route /_app/marketplace/$kind/$entryId shape, such as /marketplace/skill/git-flow?tab=market, or add the missing route.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@web/src/systems/marketplace/components/__tests__/marketplace-components.test.tsx`
around lines 1532 - 1533, Update the marketplace card link and its test
expectation to use the declared detail-route shape
`/_app/marketplace/$kind/$entryId`, such as
`/marketplace/skill/git-flow?tab=market`, instead of the nonexistent
`/marketplace/skill/docs-sync?tab=market` path; keep the `/marketplace/skills`
route check unchanged.
| aria-hidden="true" | ||
| className="grid size-(--size-provider-logo-well) shrink-0 place-items-center rounded-lg border border-line bg-elevated text-muted" | ||
| > | ||
| <Icon className="size-5" /> |
There was a problem hiding this comment.
React Doctor · react-hooks-js/static-components (error)
This component misses React Compiler's automatic memoization & re-renders more than it should: Cannot create components during render. Rewrite the flagged code so the compiler can optimize it.
Fix → Components created during render will reset their state each time they are created. Declare components outside of render.
Summary by CodeRabbit