@knpkv/control-center 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -17
- package/dist/client/.vite/manifest.json +223 -178
- package/dist/client/assets/{ActiveWorkPage-DJQgGZeV.js → ActiveWorkPage-g2-Jyavo.js} +2 -2
- package/dist/client/assets/{ActiveWorkPage-DJQgGZeV.js.map → ActiveWorkPage-g2-Jyavo.js.map} +1 -1
- package/dist/client/assets/AgentPage-B6GQdZAs.css +1 -0
- package/dist/client/assets/AgentPage-DmVsEe13.js +6 -0
- package/dist/client/assets/AgentPage-DmVsEe13.js.map +1 -0
- package/dist/client/assets/AtlassianOAuthCallbackPage-C8u9ItMj.js +2 -0
- package/dist/client/assets/{AtlassianOAuthCallbackPage-D1F1xE_2.js.map → AtlassianOAuthCallbackPage-C8u9ItMj.js.map} +1 -1
- package/dist/client/assets/AuthorizedSharePage-CVBJ1NTm.js +2 -0
- package/dist/client/assets/AuthorizedSharePage-CVBJ1NTm.js.map +1 -0
- package/dist/client/assets/BrowserCrypto-3BoTVFdl.js +2 -0
- package/dist/client/assets/{BrowserCrypto-DVWR7DFd.js.map → BrowserCrypto-3BoTVFdl.js.map} +1 -1
- package/dist/client/assets/BrowserSessionHydrator-CpZnNm4X.js +2 -0
- package/dist/client/assets/BrowserSessionHydrator-CpZnNm4X.js.map +1 -0
- package/dist/client/assets/CommandSearch-DUeRRbV2.js +2 -0
- package/dist/client/assets/{CommandSearch-CP_QCbkm.js.map → CommandSearch-DUeRRbV2.js.map} +1 -1
- package/dist/client/assets/ItemsPage-BF2ZkSzh.js +2 -0
- package/dist/client/assets/{ItemsPage-BGFUkRL2.js.map → ItemsPage-BF2ZkSzh.js.map} +1 -1
- package/dist/client/assets/{PairPage-DIgzx0K2.js → PairPage-CkaZltHd.js} +2 -2
- package/dist/client/assets/{PairPage-DIgzx0K2.js.map → PairPage-CkaZltHd.js.map} +1 -1
- package/dist/client/assets/PortfolioOverview-CEUHJmGC.js +2 -0
- package/dist/client/assets/PortfolioOverview-CEUHJmGC.js.map +1 -0
- package/dist/client/assets/PullRequestReviewPanel-D1IpvHe2.js +6 -0
- package/dist/client/assets/PullRequestReviewPanel-D1IpvHe2.js.map +1 -0
- package/dist/client/assets/ReleaseRoute-BuQybrsg.js +2 -0
- package/dist/client/assets/{ReleaseRoute-DXJ8Jg60.js.map → ReleaseRoute-BuQybrsg.js.map} +1 -1
- package/dist/client/assets/ReleaseWorkset-BclY0Nvj.js +2 -0
- package/dist/client/assets/ReleaseWorkset-BclY0Nvj.js.map +1 -0
- package/dist/client/assets/ServicesPage-hw5Ee69-.js +2 -0
- package/dist/client/assets/ServicesPage-hw5Ee69-.js.map +1 -0
- package/dist/client/assets/TimelinePage-Cj3V98uI.js +2 -0
- package/dist/client/assets/TimelinePage-Cj3V98uI.js.map +1 -0
- package/dist/client/assets/WorkspaceEntityLink-C_rc8lxi.js +2 -0
- package/dist/client/assets/{WorkspaceEntityLink-AdZ_T-Wk.js.map → WorkspaceEntityLink-C_rc8lxi.js.map} +1 -1
- package/dist/client/assets/WorkspaceEntityRoute-DLLT6fY0.css +1 -0
- package/dist/client/assets/WorkspaceEntityRoute-kbnrQ_lY.js +14 -0
- package/dist/client/assets/WorkspaceEntityRoute-kbnrQ_lY.js.map +1 -0
- package/dist/client/assets/WorkspaceHomeLink-DeYYLEsH.js +2 -0
- package/dist/client/assets/{WorkspaceHomeLink-XbKSPths.js.map → WorkspaceHomeLink-DeYYLEsH.js.map} +1 -1
- package/dist/client/assets/{WorkspacePullRequestDetails-BErJ5bk8.js → WorkspacePullRequestDetails-CizqydjN.js} +3 -3
- package/dist/client/assets/WorkspacePullRequestDetails-CizqydjN.js.map +1 -0
- package/dist/client/assets/{WorkspaceReleaseLayout-cfboC5Qh.js → WorkspaceReleaseLayout-CXAQUhkh.js} +2 -2
- package/dist/client/assets/{WorkspaceReleaseLayout-cfboC5Qh.js.map → WorkspaceReleaseLayout-CXAQUhkh.js.map} +1 -1
- package/dist/client/assets/{WorkspaceRichText-D1M637Ff.js → WorkspaceRichText-CCOciILO.js} +2 -2
- package/dist/client/assets/WorkspaceRichText-CCOciILO.js.map +1 -0
- package/dist/client/assets/WorkspaceSettingsPage-GoBfQzBx.css +1 -0
- package/dist/client/assets/WorkspaceSettingsPage-JG-pN_CA.js +2 -0
- package/dist/client/assets/WorkspaceSettingsPage-JG-pN_CA.js.map +1 -0
- package/dist/client/assets/agent-api-Dl9TuGOJ.js +19 -0
- package/dist/client/assets/agent-api-Dl9TuGOJ.js.map +1 -0
- package/dist/client/assets/atlassianOAuthSetupIntentStorage-DE4ySCTb.js +2 -0
- package/dist/client/assets/atlassianOAuthSetupIntentStorage-DE4ySCTb.js.map +1 -0
- package/dist/client/assets/authenticatedMutationClient-DdowMjyo.js +2 -0
- package/dist/client/assets/{authenticatedMutationClient-Ccwguc3i.js.map → authenticatedMutationClient-DdowMjyo.js.map} +1 -1
- package/dist/client/assets/authorizedShareTransport-CnclcYai.js +2 -0
- package/dist/client/assets/{authorizedShareTransport-DZHgFEkh.js.map → authorizedShareTransport-CnclcYai.js.map} +1 -1
- package/dist/client/assets/client-Dq_XQE_l.js +5 -0
- package/dist/client/assets/client-Dq_XQE_l.js.map +1 -0
- package/dist/client/assets/confluenceTasks-DtKq8_eU.js +5 -0
- package/dist/client/assets/confluenceTasks-DtKq8_eU.js.map +1 -0
- package/dist/client/assets/connectionTestTransport-CPK98z7H.js +2 -0
- package/dist/client/assets/connectionTestTransport-CPK98z7H.js.map +1 -0
- package/dist/client/assets/index-zVjlBm9l.js +11 -0
- package/dist/client/assets/index-zVjlBm9l.js.map +1 -0
- package/dist/client/assets/{patterns-5N-j-AD2-BwypFm-e.js → patterns-5N-j-AD2-DLfaGePK.js} +2 -2
- package/dist/client/assets/{patterns-5N-j-AD2-BwypFm-e.js.map → patterns-5N-j-AD2-DLfaGePK.js.map} +1 -1
- package/dist/client/assets/{presentPortfolio-D3ZIcnqt.js → presentPortfolio-DLEq-vEz.js} +2 -2
- package/dist/client/assets/presentPortfolio-DLEq-vEz.js.map +1 -0
- package/dist/client/assets/{presentWorkspaceItems-Bmh4oEbH.js → presentWorkspaceItems-BOY3FbhO.js} +2 -2
- package/dist/client/assets/{presentWorkspaceItems-Bmh4oEbH.js.map → presentWorkspaceItems-BOY3FbhO.js.map} +1 -1
- package/dist/client/assets/{pullRequestReviewFailures-S74M-fOk.js → pullRequestReviewFailures-CyjTVnSX.js} +2 -2
- package/dist/client/assets/{pullRequestReviewFailures-S74M-fOk.js.map → pullRequestReviewFailures-CyjTVnSX.js.map} +1 -1
- package/dist/client/assets/pullRequestReviewThreadReplay-CXHspFTr.js +2 -0
- package/dist/client/assets/pullRequestReviewThreadReplay-CXHspFTr.js.map +1 -0
- package/dist/client/assets/releaseAgentTransport-DaO4svPu.js +2 -0
- package/dist/client/assets/releaseAgentTransport-DaO4svPu.js.map +1 -0
- package/dist/client/assets/releaseRoutes-B4ciNOJj.js +2 -0
- package/dist/client/assets/{releaseRoutes-BCuIdZyA.js.map → releaseRoutes-B4ciNOJj.js.map} +1 -1
- package/dist/client/assets/serviceOnboarding-D0FmodRi.js +2 -0
- package/dist/client/assets/{serviceOnboarding-Jg_0yNjf.js.map → serviceOnboarding-D0FmodRi.js.map} +1 -1
- package/dist/client/assets/{useWorkspaceDefaultLanding-CzlDdEF-.js → useWorkspaceDefaultLanding-BaQdg0sY.js} +3 -3
- package/dist/client/assets/{useWorkspaceDefaultLanding-CzlDdEF-.js.map → useWorkspaceDefaultLanding-BaQdg0sY.js.map} +1 -1
- package/dist/client/assets/{useWorkspaceItems-Cd3MPke2.js → useWorkspaceItems-B-7JHtm0.js} +2 -2
- package/dist/client/assets/{useWorkspaceItems-Cd3MPke2.js.map → useWorkspaceItems-B-7JHtm0.js.map} +1 -1
- package/dist/client/assets/workspaceEntityRoutes-DqqDa0AB.js +2 -0
- package/dist/client/assets/workspaceEntityRoutes-DqqDa0AB.js.map +1 -0
- package/dist/client/assets/workspaceScrollCapture-BYNfR2wo.js +2 -0
- package/dist/client/assets/workspaceScrollCapture-BYNfR2wo.js.map +1 -0
- package/dist/client/assets/workspaceSettingsTransport-Br4lBmvS.js +2 -0
- package/dist/client/assets/{workspaceSettingsTransport-CZWYL5T7.js.map → workspaceSettingsTransport-Br4lBmvS.js.map} +1 -1
- package/dist/client/build-graph.json +115 -0
- package/dist/client/index.html +1 -1
- package/dist/server/api/agent.d.ts +575 -44
- package/dist/server/api/agent.d.ts.map +1 -1
- package/dist/server/api/deliveryGraph.d.ts +474 -454
- package/dist/server/api/deliveryGraph.d.ts.map +1 -1
- package/dist/server/api/index.d.ts +2 -2
- package/dist/server/api/index.d.ts.map +1 -1
- package/dist/server/api/index.js +4 -4
- package/dist/server/api/liveEvents.d.ts +20 -0
- package/dist/server/api/liveEvents.d.ts.map +1 -1
- package/dist/server/api/portfolio.d.ts +23 -0
- package/dist/server/api/portfolio.d.ts.map +1 -1
- package/dist/server/api/session.d.ts +23 -1
- package/dist/server/api/session.d.ts.map +1 -1
- package/dist/server/api/shares.d.ts +4 -2
- package/dist/server/api/shares.d.ts.map +1 -1
- package/dist/server/assets/{BindConfig-DIsf2Rnh.js → BindConfig-DAASchDn.js} +2405 -322
- package/dist/server/assets/BindConfig-DAASchDn.js.map +1 -0
- package/dist/server/assets/{CodePipelineStateDecoder-CVf1A2zG.js → CodePipelineStateDecoder-CNiFRgSi.js} +2 -2
- package/dist/server/assets/{CodePipelineStateDecoder-CVf1A2zG.js.map → CodePipelineStateDecoder-CNiFRgSi.js.map} +1 -1
- package/dist/server/assets/{agent-CyZ40zs1.js → agent-xQhAQXly.js} +181 -11
- package/dist/server/assets/agent-xQhAQXly.js.map +1 -0
- package/dist/server/assets/{controlCenterApi-ZUX3Y-LE.js → controlCenterApi-DNXK7MT1.js} +6 -5
- package/dist/server/assets/controlCenterApi-DNXK7MT1.js.map +1 -0
- package/dist/server/assets/{descriptor-CKtTnhef.js → descriptor-CCvNzSZL.js} +10 -10
- package/dist/server/assets/{descriptor-CKtTnhef.js.map → descriptor-CCvNzSZL.js.map} +1 -1
- package/dist/server/assets/{failures-mgYDkUZy.js → failures-CesHLYbN.js} +2 -2
- package/dist/server/assets/{failures-mgYDkUZy.js.map → failures-CesHLYbN.js.map} +1 -1
- package/dist/server/assets/{firstPartyServices-D7b8BOek.js → firstPartyServices-Cdzjcs2H.js} +2 -2
- package/dist/server/assets/{firstPartyServices-D7b8BOek.js.map → firstPartyServices-Cdzjcs2H.js.map} +1 -1
- package/dist/server/assets/{manualPluginSynchronization-DFlhKvav.js → manualPluginSynchronization-DFIeUHP9.js} +6 -5
- package/dist/server/assets/manualPluginSynchronization-DFIeUHP9.js.map +1 -0
- package/dist/server/assets/{plugins-D__oMDpI.js → plugins-DiPrfzV8.js} +2 -2
- package/dist/server/assets/{plugins-D__oMDpI.js.map → plugins-DiPrfzV8.js.map} +1 -1
- package/dist/server/assets/{readiness-BhA-Nr9c.js → readiness-31Mqc-9H.js} +3 -3
- package/dist/server/assets/{readiness-BhA-Nr9c.js.map → readiness-31Mqc-9H.js.map} +1 -1
- package/dist/server/assets/{relationshipInferenceMaterialization-DYBcaWhQ.js → relationshipInferenceMaterialization-Dyix96px.js} +1158 -169
- package/dist/server/assets/relationshipInferenceMaterialization-Dyix96px.js.map +1 -0
- package/dist/server/assets/{workspaceSettings-BE713Oe8.js → workspaceSettings-sv8h_h2P.js} +2787 -2700
- package/dist/server/assets/workspaceSettings-sv8h_h2P.js.map +1 -0
- package/dist/server/build-graph.json +144 -4
- package/dist/server/domain/actors.d.ts +12 -12
- package/dist/server/domain/confluenceTasks.d.ts +27 -0
- package/dist/server/domain/confluenceTasks.d.ts.map +1 -0
- package/dist/server/domain/deliveryGraph.d.ts +51 -49
- package/dist/server/domain/deliveryGraph.d.ts.map +1 -1
- package/dist/server/domain/governedAction/bindings.d.ts +26 -12
- package/dist/server/domain/governedAction/bindings.d.ts.map +1 -1
- package/dist/server/domain/governedAction/lifecycle.d.ts +8 -8
- package/dist/server/domain/governedAction/model.d.ts +45 -18
- package/dist/server/domain/governedAction/model.d.ts.map +1 -1
- package/dist/server/domain/governedAction/stateMachine.d.ts +34 -34
- package/dist/server/domain/index.js +6 -6
- package/dist/server/domain/normalizedIssue.d.ts +1 -1
- package/dist/server/domain/normalizedPage.d.ts +1 -0
- package/dist/server/domain/normalizedPage.d.ts.map +1 -1
- package/dist/server/domain/prReview.d.ts +38 -0
- package/dist/server/domain/prReview.d.ts.map +1 -1
- package/dist/server/domain/prReviewReconciliation.d.ts +56 -0
- package/dist/server/domain/prReviewReconciliation.d.ts.map +1 -0
- package/dist/server/domain/prReviewRevision.d.ts +1 -0
- package/dist/server/domain/prReviewRevision.d.ts.map +1 -1
- package/dist/server/domain/readiness/model.d.ts +3 -3
- package/dist/server/domain/release.d.ts +3 -3
- package/dist/server/domain/releasePipelineApproval.d.ts +31 -0
- package/dist/server/domain/releasePipelineApproval.d.ts.map +1 -0
- package/dist/server/domain/releasePublication.d.ts +4 -0
- package/dist/server/domain/releasePublication.d.ts.map +1 -0
- package/dist/server/index.js +8 -8
- package/dist/server/server/agent/AgentJobWorker.d.ts +10 -1
- package/dist/server/server/agent/AgentJobWorker.d.ts.map +1 -1
- package/dist/server/server/agent/ReleaseAgentPrompt.d.ts.map +1 -1
- package/dist/server/server/agent/internal/AgentJobTaskExecutor.d.ts +4 -3
- package/dist/server/server/agent/internal/AgentJobTaskExecutor.d.ts.map +1 -1
- package/dist/server/server/agent/internal/PrReviewSandboxSession.d.ts +17 -1
- package/dist/server/server/agent/internal/PrReviewSandboxSession.d.ts.map +1 -1
- package/dist/server/server/agent/internal/PrReviewTaskExecutor.d.ts +76 -2
- package/dist/server/server/agent/internal/PrReviewTaskExecutor.d.ts.map +1 -1
- package/dist/server/server/agent/internal/PrReviewTelemetry.d.ts +27 -0
- package/dist/server/server/agent/internal/PrReviewTelemetry.d.ts.map +1 -0
- package/dist/server/server/api/ApplicationServices.d.ts +39 -5
- package/dist/server/server/api/ApplicationServices.d.ts.map +1 -1
- package/dist/server/server/api/Handlers.d.ts +1 -1
- package/dist/server/server/api/Handlers.d.ts.map +1 -1
- package/dist/server/server/api/RequestBoundary.d.ts.map +1 -1
- package/dist/server/server/application/GovernedReviewSuggestionPublicationGateway.d.ts.map +1 -1
- package/dist/server/server/application/ReviewSuggestionPublicationGateway.d.ts +4 -0
- package/dist/server/server/application/ReviewSuggestionPublicationGateway.d.ts.map +1 -1
- package/dist/server/server/application/deliveryGraphInspection.d.ts.map +1 -1
- package/dist/server/server/application/index.d.ts +1 -0
- package/dist/server/server/application/index.d.ts.map +1 -1
- package/dist/server/server/application/liveEvents.d.ts.map +1 -1
- package/dist/server/server/application/normalizedPluginPageMaterialization.d.ts.map +1 -1
- package/dist/server/server/application/pipelineExecutionProjection.d.ts +7 -6
- package/dist/server/server/application/pipelineExecutionProjection.d.ts.map +1 -1
- package/dist/server/server/application/portfolioSnapshots.d.ts +2018 -4
- package/dist/server/server/application/portfolioSnapshots.d.ts.map +1 -1
- package/dist/server/server/application/pullRequestReviews.d.ts.map +1 -1
- package/dist/server/server/application/releaseAgent.d.ts +11 -3
- package/dist/server/server/application/releaseAgent.d.ts.map +1 -1
- package/dist/server/server/application/releasePublicationIntent.d.ts +7 -0
- package/dist/server/server/application/releasePublicationIntent.d.ts.map +1 -0
- package/dist/server/server/application/releasePublicationMetadata.d.ts +61 -0
- package/dist/server/server/application/releasePublicationMetadata.d.ts.map +1 -0
- package/dist/server/server/application/releasePublicationSubmissions.d.ts +3730 -0
- package/dist/server/server/application/releasePublicationSubmissions.d.ts.map +1 -0
- package/dist/server/server/application/releaseRunbookHydration.d.ts +2310 -0
- package/dist/server/server/application/releaseRunbookHydration.d.ts.map +1 -0
- package/dist/server/server/application/releaseSynchronization.d.ts.map +1 -1
- package/dist/server/server/cli.js +8 -8
- package/dist/server/server/cli.js.map +1 -1
- package/dist/server/server/governance/governedActionDigests.d.ts +236 -218
- package/dist/server/server/governance/governedActionDigests.d.ts.map +1 -1
- package/dist/server/server/governance/internal/GovernedActionExecutionEngine.d.ts +3 -4
- package/dist/server/server/governance/internal/GovernedActionExecutionEngine.d.ts.map +1 -1
- package/dist/server/server/governance/internal/execution-store/begin.d.ts.map +1 -1
- package/dist/server/server/governance/internal/execution-store/dispatch-inbox.d.ts +1 -1
- package/dist/server/server/governance/internal/execution-store/dispatch-outcome.d.ts +8 -8
- package/dist/server/server/governance/internal/execution-store/provider-outcome-fold.d.ts +2 -2
- package/dist/server/server/governance/internal/execution-store/reconciliation-inbox.d.ts +1 -1
- package/dist/server/server/governance/internal/execution-store/recovery-claim.d.ts +37 -30
- package/dist/server/server/governance/internal/execution-store/recovery-claim.d.ts.map +1 -1
- package/dist/server/server/index.js +5 -5
- package/dist/server/server/internal/codepipeline-state-probe.js +1 -1
- package/dist/server/server/persistence/Database.d.ts +1 -1
- package/dist/server/server/persistence/Database.d.ts.map +1 -1
- package/dist/server/server/persistence/Persistence.d.ts +1549 -577
- package/dist/server/server/persistence/Persistence.d.ts.map +1 -1
- package/dist/server/server/persistence/backup/BackupArchive.d.ts.map +1 -1
- package/dist/server/server/persistence/object-store/BlobPublisher.d.ts.map +1 -1
- package/dist/server/server/persistence/object-store/PinnedDirectory.d.ts +2 -2
- package/dist/server/server/persistence/object-store/PinnedDirectory.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/agentJobModels.d.ts +345 -8
- package/dist/server/server/persistence/repositories/agentJobModels.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/agentJobRepository.d.ts +654 -192
- package/dist/server/server/persistence/repositories/agentJobRepository.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/contract.d.ts +148 -138
- package/dist/server/server/persistence/repositories/delivery-graph/contract.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/decode.d.ts +27 -25
- package/dist/server/server/persistence/repositories/delivery-graph/decode.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/read.d.ts +117 -111
- package/dist/server/server/persistence/repositories/delivery-graph/read.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/rows.d.ts +28 -27
- package/dist/server/server/persistence/repositories/delivery-graph/rows.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/delivery-graph/write.d.ts +50 -48
- package/dist/server/server/persistence/repositories/delivery-graph/write.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/deliveryGraphRepository.d.ts +117 -111
- package/dist/server/server/persistence/repositories/deliveryGraphRepository.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/codec.d.ts +259 -234
- package/dist/server/server/persistence/repositories/governed-action/codec.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/contract.d.ts +68 -46
- package/dist/server/server/persistence/repositories/governed-action/contract.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/read.d.ts +668 -190
- package/dist/server/server/persistence/repositories/governed-action/read.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/transaction.d.ts +680 -206
- package/dist/server/server/persistence/repositories/governed-action/transaction.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/write-preparation.d.ts +38 -31
- package/dist/server/server/persistence/repositories/governed-action/write-preparation.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/write-replay.d.ts +46 -32
- package/dist/server/server/persistence/repositories/governed-action/write-replay.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governed-action/write.d.ts +46 -32
- package/dist/server/server/persistence/repositories/governed-action/write.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/governedActionRepository.d.ts +678 -205
- package/dist/server/server/persistence/repositories/governedActionRepository.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/internal/reviewSuggestionRevisions.d.ts +85 -4
- package/dist/server/server/persistence/repositories/internal/reviewSuggestionRevisions.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/models.d.ts +9 -9
- package/dist/server/server/persistence/repositories/peopleRepository.d.ts +36 -36
- package/dist/server/server/persistence/repositories/providerAccountRepository.d.ts +1 -1
- package/dist/server/server/persistence/repositories/readiness/assessments.d.ts +6 -6
- package/dist/server/server/persistence/repositories/readiness/contract.d.ts +450 -450
- package/dist/server/server/persistence/repositories/readiness/queue.d.ts +14 -14
- package/dist/server/server/persistence/repositories/readinessRepository.d.ts +7 -7
- package/dist/server/server/persistence/repositories/releaseRepository.d.ts +18 -18
- package/dist/server/server/persistence/repositories/retentionRepository.d.ts.map +1 -1
- package/dist/server/server/persistence/repositories/timelineRepository.d.ts +4 -4
- package/dist/server/server/plugins/atlassian/AtlassianOAuthGrants.d.ts.map +1 -1
- package/dist/server/server/plugins/atlassian/AtlassianOAuthScopes.d.ts +9 -0
- package/dist/server/server/plugins/atlassian/AtlassianOAuthScopes.d.ts.map +1 -0
- package/dist/server/server/plugins/atlassian/AtlassianProfiles.d.ts.map +1 -1
- package/dist/server/server/plugins/codecommit/CodeCommitPluginDefinition.d.ts.map +1 -1
- package/dist/server/server/plugins/jira/JiraReadPlugin.d.ts +2 -2
- package/dist/server/server/plugins/jira/JiraReadPlugin.d.ts.map +1 -1
- package/dist/server/server/plugins/jira/JiraReadProvider.d.ts.map +1 -1
- package/dist/server/server/plugins/jira/JiraReleaseVersionLimits.d.ts +8 -0
- package/dist/server/server/plugins/jira/JiraReleaseVersionLimits.d.ts.map +1 -0
- package/dist/server/server/plugins/jira/index.d.ts +1 -1
- package/dist/server/server/plugins/jira/index.d.ts.map +1 -1
- package/dist/server/server/runtime/Bootstrap.d.ts +1 -1
- package/dist/server/server/runtime/Bootstrap.d.ts.map +1 -1
- package/dist/server/server/runtime/ControlCenterServer.d.ts +3 -3
- package/dist/server/server/runtime/ControlCenterServer.d.ts.map +1 -1
- package/dist/server/server/runtime/PrReviewWorkerStartup.d.ts +11 -1
- package/dist/server/server/runtime/PrReviewWorkerStartup.d.ts.map +1 -1
- package/dist/server/server/runtime/RetentionStartup.d.ts.map +1 -1
- package/dist/server/server/runtime/ServerLifecycle.d.ts.map +1 -1
- package/dist/server/server/secrets/SecretStore.d.ts.map +1 -1
- package/package.json +10 -9
- package/dist/client/assets/AgentPage-DGL93TJU.js +0 -3
- package/dist/client/assets/AgentPage-DGL93TJU.js.map +0 -1
- package/dist/client/assets/AgentPage-DVSgQgJa.css +0 -1
- package/dist/client/assets/AtlassianOAuthCallbackPage-D1F1xE_2.js +0 -2
- package/dist/client/assets/AuthorizedSharePage-DCQUFY2I.js +0 -2
- package/dist/client/assets/AuthorizedSharePage-DCQUFY2I.js.map +0 -1
- package/dist/client/assets/BrowserCrypto-DVWR7DFd.js +0 -2
- package/dist/client/assets/BrowserSessionHydrator-DE46feEX.js +0 -2
- package/dist/client/assets/BrowserSessionHydrator-DE46feEX.js.map +0 -1
- package/dist/client/assets/CommandSearch-CP_QCbkm.js +0 -2
- package/dist/client/assets/ItemsPage-BGFUkRL2.js +0 -2
- package/dist/client/assets/PortfolioOverview-D45rk8Hl.js +0 -2
- package/dist/client/assets/PortfolioOverview-D45rk8Hl.js.map +0 -1
- package/dist/client/assets/PullRequestReviewPanel-CqPtjhVW.js +0 -6
- package/dist/client/assets/PullRequestReviewPanel-CqPtjhVW.js.map +0 -1
- package/dist/client/assets/ReleaseRoute-DXJ8Jg60.js +0 -2
- package/dist/client/assets/ReleaseWorkset-Dtzalmji.js +0 -2
- package/dist/client/assets/ReleaseWorkset-Dtzalmji.js.map +0 -1
- package/dist/client/assets/ServicesPage-DGcUjd2H.js +0 -2
- package/dist/client/assets/ServicesPage-DGcUjd2H.js.map +0 -1
- package/dist/client/assets/TimelinePage-Bq1RTQlP.js +0 -2
- package/dist/client/assets/TimelinePage-Bq1RTQlP.js.map +0 -1
- package/dist/client/assets/WorkspaceEntityLink-AdZ_T-Wk.js +0 -2
- package/dist/client/assets/WorkspaceEntityRoute-9iMOV64J.css +0 -1
- package/dist/client/assets/WorkspaceEntityRoute-Bxxnc8us.js +0 -3
- package/dist/client/assets/WorkspaceEntityRoute-Bxxnc8us.js.map +0 -1
- package/dist/client/assets/WorkspaceHomeLink-XbKSPths.js +0 -2
- package/dist/client/assets/WorkspacePullRequestDetails-BErJ5bk8.js.map +0 -1
- package/dist/client/assets/WorkspaceRichText-D1M637Ff.js.map +0 -1
- package/dist/client/assets/WorkspaceSettingsPage-Fy7Wx8Y2.js +0 -2
- package/dist/client/assets/WorkspaceSettingsPage-Fy7Wx8Y2.js.map +0 -1
- package/dist/client/assets/WorkspaceSettingsPage-P6yfac0b.css +0 -1
- package/dist/client/assets/agent-api-QVqt4a0O.js +0 -19
- package/dist/client/assets/agent-api-QVqt4a0O.js.map +0 -1
- package/dist/client/assets/authenticatedMutationClient-Ccwguc3i.js +0 -2
- package/dist/client/assets/authorizedShareTransport-DZHgFEkh.js +0 -2
- package/dist/client/assets/client-D27unen8.js +0 -5
- package/dist/client/assets/client-D27unen8.js.map +0 -1
- package/dist/client/assets/connectionTestTransport-BQ55d6Me.js +0 -2
- package/dist/client/assets/connectionTestTransport-BQ55d6Me.js.map +0 -1
- package/dist/client/assets/index-j5ze816l.js +0 -11
- package/dist/client/assets/index-j5ze816l.js.map +0 -1
- package/dist/client/assets/presentPortfolio-D3ZIcnqt.js.map +0 -1
- package/dist/client/assets/pullRequestReviewThreadReplay-oljKM7Xz.js +0 -2
- package/dist/client/assets/pullRequestReviewThreadReplay-oljKM7Xz.js.map +0 -1
- package/dist/client/assets/releaseRoutes-BCuIdZyA.js +0 -2
- package/dist/client/assets/serviceOnboarding-Jg_0yNjf.js +0 -2
- package/dist/client/assets/workspaceScrollCapture-CJ4QUptr.js +0 -2
- package/dist/client/assets/workspaceScrollCapture-CJ4QUptr.js.map +0 -1
- package/dist/client/assets/workspaceSettingsTransport-CZWYL5T7.js +0 -2
- package/dist/server/assets/BindConfig-DIsf2Rnh.js.map +0 -1
- package/dist/server/assets/agent-CyZ40zs1.js.map +0 -1
- package/dist/server/assets/controlCenterApi-ZUX3Y-LE.js.map +0 -1
- package/dist/server/assets/manualPluginSynchronization-DFlhKvav.js.map +0 -1
- package/dist/server/assets/relationshipInferenceMaterialization-DYBcaWhQ.js.map +0 -1
- package/dist/server/assets/workspaceSettings-BE713Oe8.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PortfolioOverview-D45rk8Hl.js","names":["Random","random.Random","Effect.withFiber","Effect.succeed"],"sources":["../../../../../node_modules/.pnpm/effect@4.0.0-beta.98/node_modules/effect/dist/internal/random.js","../../../../../node_modules/.pnpm/effect@4.0.0-beta.98/node_modules/effect/dist/Random.js","../../../src/client/BrowserSessionStatus.tsx","../../../src/client/portfolio/portfolioFilters.ts","../../../src/client/portfolio/livePortfolioState.ts","../../../src/client/portfolio/usePortfolioSnapshot.ts","../../../src/client/portfolio/PortfolioOverview.module.css","../../../src/client/portfolio/PortfolioOverview.tsx"],"sourcesContent":["import * as Context from \"../Context.js\";\n/** @internal */\nexport const Random = /*#__PURE__*/Context.Reference(\"effect/Random\", {\n defaultValue: () => ({\n nextIntUnsafe() {\n return Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - Number.MIN_SAFE_INTEGER + 1)) + Number.MIN_SAFE_INTEGER;\n },\n nextDoubleUnsafe() {\n return Math.random();\n }\n })\n});\n//# sourceMappingURL=random.js.map","import * as Cause from \"./Cause.js\";\nimport * as Effect from \"./Effect.js\";\nimport { dual } from \"./Function.js\";\nimport * as random from \"./internal/random.js\";\nimport * as Predicate from \"./Predicate.js\";\n/**\n * Represents a service for generating pseudo-random numbers.\n *\n * **When to use**\n *\n * Use to access or provide the random-number generator service used by Effect\n * programs.\n *\n * **Gotchas**\n *\n * The default implementation is based on `Math.random` and is not\n * cryptographically secure. Replace the service with a cryptographically secure\n * implementation before using these generators for security-sensitive values.\n *\n * **Example** (Accessing the random service)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const float = yield* Random.next\n * const integer = yield* Random.nextInt\n * const inRange = yield* Random.nextIntBetween(1, 100)\n *\n * console.log(\"Float:\", float)\n * console.log(\"Integer:\", integer)\n * console.log(\"In range:\", inRange)\n * })\n * ```\n *\n * @category Random Number Generators\n * @since 2.0.0\n */\nexport const Random = random.Random;\nconst randomWith = f => Effect.withFiber(fiber => Effect.succeed(f(fiber.getRef(Random))));\n/**\n * Generates a random number between 0 (inclusive) and 1 (exclusive).\n *\n * **When to use**\n *\n * Use to generate a pseudo-random floating-point number in the standard\n * `[0, 1)` range.\n *\n * **Example** (Generating a random number)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const randomDouble = yield* Random.next\n * console.log(\"Random double:\", randomDouble)\n * })\n * ```\n *\n * @category Random Number Generators\n * @since 2.0.0\n */\nexport const next = /*#__PURE__*/randomWith(r => r.nextDoubleUnsafe());\n/**\n * Generates a random boolean value.\n *\n * **When to use**\n *\n * Use to make a pseudo-random true-or-false choice.\n *\n * **Example** (Generating a random boolean)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const value = yield* Random.nextBoolean\n * console.log(\"Random boolean:\", value)\n * })\n * ```\n *\n * @category Random Number Generators\n * @since 2.0.0\n */\nexport const nextBoolean = /*#__PURE__*/randomWith(r => r.nextDoubleUnsafe() > 0.5);\n/**\n * Generates a random integer between `Number.MIN_SAFE_INTEGER` (inclusive)\n * and `Number.MAX_SAFE_INTEGER` (inclusive).\n *\n * **When to use**\n *\n * Use to generate a pseudo-random safe integer across the full safe-integer\n * range.\n *\n * **Example** (Generating a random integer)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const randomInt = yield* Random.nextInt\n * console.log(\"Random integer:\", randomInt)\n * })\n * ```\n *\n * @category Random Number Generators\n * @since 2.0.0\n */\nexport const nextInt = /*#__PURE__*/randomWith(r => r.nextIntUnsafe());\n/**\n * Generates a random number between `min` (inclusive) and `max` (exclusive).\n *\n * **When to use**\n *\n * Use to generate a pseudo-random floating-point number within a numeric range.\n *\n * **Example** (Generating a bounded random number)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const randomDouble = yield* Random.nextBetween(0, 1)\n * console.log(\"Random double: \", randomDouble)\n * })\n * ```\n *\n * @category Random Number Generators\n * @since 4.0.0\n */\nexport const nextBetween = (min, max) => randomWith(r => r.nextDoubleUnsafe() * (max - min) + min);\n/**\n * Generates a random integer between `min` and `max`.\n *\n * **When to use**\n *\n * Use to generate a pseudo-random integer within a rounded numeric range.\n *\n * **Details**\n *\n * The lower bound is rounded up with `Math.ceil` and the upper bound is\n * rounded down with `Math.floor`. By default the range is inclusive; set\n * `options.halfOpen: true` to exclude the upper bound.\n *\n * **Example** (Generating a bounded random integer)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const diceRoll1 = yield* Random.nextIntBetween(1, 6)\n * const diceRoll2 = yield* Random.nextIntBetween(1, 6, {\n * halfOpen: true\n * })\n * const diceRoll3 = yield* Random.nextIntBetween(0, 10)\n * })\n * ```\n *\n * @category Random Number Generators\n * @since 2.0.0\n */\nexport const nextIntBetween = (min, max, options) => {\n const extra = options?.halfOpen === true ? 0 : 1;\n return randomWith(r => {\n const minInt = Math.ceil(min);\n const maxInt = Math.floor(max);\n return Math.floor(r.nextDoubleUnsafe() * (maxInt - minInt + extra)) + minInt;\n });\n};\n/**\n * Uses the pseudo-random number generator to shuffle the specified iterable.\n *\n * **When to use**\n *\n * Use to randomly reorder an iterable using the active `Random` service.\n *\n * **Example** (Shuffling values)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const values = yield* Random.shuffle([1, 2, 3, 4, 5])\n * console.log(values)\n * })\n * ```\n *\n * @category Random Number Generators\n * @since 2.0.0\n */\nexport const shuffle = elements => randomWith(r => {\n const buffer = Array.from(elements);\n for (let i = buffer.length - 1; i >= 1; i = i - 1) {\n const index = Math.min(i, Math.floor(r.nextDoubleUnsafe() * (i + 1)));\n const value = buffer[i];\n buffer[i] = buffer[index];\n buffer[index] = value;\n }\n return buffer;\n});\n/**\n * Gets a random element from an iterable.\n *\n * **When to use**\n *\n * Use to select one value uniformly from a collection using the active `Random`\n * service.\n *\n * **Details**\n *\n * If the input type is known to be non-empty, the returned effect cannot fail.\n * Otherwise, empty iterables fail with `Cause.NoSuchElementError`.\n *\n * **Example** (Choosing a random value)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const value = yield* Random.choice([\"red\", \"green\", \"blue\"] as const)\n * console.log(value)\n * })\n * ```\n *\n * @category Random Number Generators\n * @since 3.6.0\n */\nexport const choice = elements => {\n const buffer = Array.from(elements);\n return buffer.length === 0 ? Effect.fail(new Cause.NoSuchElementError(\"Cannot select a random element from an empty array\")) : randomWith(r => buffer[Math.min(buffer.length - 1, Math.floor(r.nextDoubleUnsafe() * buffer.length))]);\n};\n/**\n * Seeds the pseudo-random number generator with the specified value.\n *\n * **When to use**\n *\n * Use to run an effect with a deterministic pseudo-random sequence.\n *\n * **Details**\n *\n * Using the same seed produces the same random sequence, which is useful for\n * tests and reproducible simulations.\n *\n * **Gotchas**\n *\n * Use an unpredictable seed when uniqueness or unpredictability matters.\n *\n * **Example** (Seeding random generation)\n *\n * ```ts\n * import { Effect, Random } from \"effect\"\n *\n * const program = Effect.gen(function*() {\n * const value1 = yield* Random.next\n * const value2 = yield* Random.next\n * console.log(value1, value2)\n * })\n *\n * // Same seed produces same sequence\n * const seeded1 = program.pipe(Random.withSeed(\"my-seed\"))\n * const seeded2 = program.pipe(Random.withSeed(\"my-seed\"))\n *\n * // Both will output identical values\n * Effect.runPromise(seeded1)\n * Effect.runPromise(seeded2)\n * ```\n *\n * @category Seeding\n * @since 4.0.0\n */\nexport const withSeed = /*#__PURE__*/dual(2, (self, seed) => Effect.provideService(self, Random, ISAAC_CSPRNG(seed)));\n/*///////////////////////////////////////////////////////////////////////////////////////////////////\nThis is a derivative work copyright (c) 2025 Effectful Technologies Inc, under MIT license.\nThis is a derivative work copyright (c) 2018, William P. \"Mac\" McMeans, under BSD license.\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n3. Neither the name of isaacCSPRNG nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\nOriginal work copyright (c) 2012 Yves-Marie K. Rinquin, under MIT license.\nhttps://github.com/rubycon/isaac.js\n///////////////////////////////////////////////////////////////////////////////////////////////////*/\nfunction ISAAC_CSPRNG(userSeed) {\n // Internal State\n const memory = new Array(256);\n const result = new Array(256);\n let accumulator = 0;\n let lastResult = 0;\n let generation = 0;\n let counter = 0;\n // Initial Seed\n const internalSeed = Predicate.isUndefined(userSeed) ? getInitialSeed() : userSeed;\n seed(internalSeed);\n function getInitialSeed() {\n const uint32a = new Uint32Array(2);\n crypto.getRandomValues(uint32a);\n return uint32a[0] + uint32a[1];\n }\n function reset() {\n accumulator = 0;\n lastResult = 0;\n counter = 0;\n for (let i = 0; i < 256; ++i) {\n memory[i] = 0;\n result[i] = 0;\n }\n generation = 0;\n }\n function seed(userSeed) {\n // The golden ratio ( 2654435769 )\n // See https://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine\n const magicNumber = 0x9e3779b9;\n let a = magicNumber;\n let b = magicNumber;\n let c = magicNumber;\n let d = magicNumber;\n let e = magicNumber;\n let f = magicNumber;\n let g = magicNumber;\n let h = magicNumber;\n let i = 0;\n let seed;\n if (Predicate.isString(userSeed)) {\n seed = toIntArray(userSeed);\n } else {\n seed = [userSeed];\n }\n reset();\n for (i = 0; i < seed.length; i++) {\n result[i & 0xff] += seed[i];\n }\n function mix() {\n a ^= b << 11;\n d = add32(d, a);\n b = add32(b, c);\n b ^= c >>> 2;\n e = add32(e, b);\n c = add32(c, d);\n c ^= d << 8;\n f = add32(f, c);\n d = add32(d, e);\n d ^= e >>> 16;\n g = add32(g, d);\n e = add32(e, f);\n e ^= f << 10;\n h = add32(h, e);\n f = add32(f, g);\n f ^= g >>> 4;\n a = add32(a, f);\n g = add32(g, h);\n g ^= h << 8;\n b = add32(b, g);\n h = add32(h, a);\n h ^= a >>> 9;\n c = add32(c, h);\n a = add32(a, b);\n }\n // Scramble the seed\n for (i = 0; i < 4; i++) {\n mix();\n }\n for (i = 0; i < 256; i += 8) {\n // Use all the information in the seed\n a = add32(a, result[i]);\n b = add32(b, result[i + 1]);\n c = add32(c, result[i + 2]);\n d = add32(d, result[i + 3]);\n e = add32(e, result[i + 4]);\n f = add32(f, result[i + 5]);\n g = add32(g, result[i + 6]);\n h = add32(h, result[i + 7]);\n mix();\n // Fill in the memory with messy stuff\n memory[i] = a;\n memory[i + 1] = b;\n memory[i + 2] = c;\n memory[i + 3] = d;\n memory[i + 4] = e;\n memory[i + 5] = f;\n memory[i + 6] = g;\n memory[i + 7] = h;\n }\n // Second pass to make sure seed affects memory\n for (i = 0; i < 256; i += 8) {\n a = add32(a, memory[i]);\n b = add32(b, memory[i + 1]);\n c = add32(c, memory[i + 2]);\n d = add32(d, memory[i + 3]);\n e = add32(e, memory[i + 4]);\n f = add32(f, memory[i + 5]);\n g = add32(g, memory[i + 6]);\n h = add32(h, memory[i + 7]);\n mix();\n // Fill in the memory with messy stuff (again)\n memory[i] = a;\n memory[i + 1] = b;\n memory[i + 2] = c;\n memory[i + 3] = d;\n memory[i + 4] = e;\n memory[i + 5] = f;\n memory[i + 6] = g;\n memory[i + 7] = h;\n }\n pnrg();\n generation = 256;\n }\n function pnrg(n) {\n let i = 0;\n let x = 0;\n let y = 0;\n n = Predicate.isUndefined(n) ? 1 : Math.abs(Math.floor(n));\n while (n--) {\n counter = add32(counter, 1);\n lastResult = add32(lastResult, counter);\n for (i = 0; i < 256; i++) {\n switch (i & 3) {\n case 0:\n {\n accumulator ^= accumulator << 13;\n break;\n }\n case 1:\n {\n accumulator ^= accumulator >>> 6;\n break;\n }\n case 2:\n {\n accumulator ^= accumulator << 2;\n break;\n }\n case 3:\n {\n accumulator ^= accumulator >>> 16;\n break;\n }\n }\n accumulator = add32(memory[i + 128 & 0xff], accumulator);\n x = memory[i];\n memory[i] = add32(memory[x >>> 2 & 0xff], add32(accumulator, lastResult));\n y = memory[i];\n result[i] = add32(memory[y >>> 10 & 0xff], x);\n lastResult = result[i];\n }\n }\n }\n /**\n * Returns a signed, random integer in the range [-2^31, 2^31).\n */\n function nextInt32() {\n if (!generation--) {\n pnrg();\n generation = 255;\n }\n return result[generation];\n }\n function nextIntUnsafe() {\n return Math.floor(nextDoubleUnsafe() * (Number.MAX_SAFE_INTEGER - Number.MIN_SAFE_INTEGER + 1)) + Number.MIN_SAFE_INTEGER;\n }\n /**\n * Returns a 53-bit fraction in the range [0, 1).\n */\n function nextDoubleUnsafe() {\n const hi = nextInt32() >>> 0 & 0x1FFFFF; // take top 21 bits\n const lo = nextInt32() >>> 0; // full 32 bits\n // 53-bit integer\n const combined = hi * 4294967296 + lo;\n return combined / 0x20000000000000; // [0, 1)\n }\n return {\n nextIntUnsafe,\n nextDoubleUnsafe\n };\n}\n/**\n * 32-bit addition with overflow handling (JavaScript numbers are 53-bit).\n *\n * Example: add32(0xFFFFFFFF, 0x00000001) = 0x00000000 (wraps around)\n */\nfunction add32(x, y) {\n // Add lower 16 bits separately to handle carry\n // Example: x=0x12345678, y=0xABCDEF01\n // lsb = (0x5678 + 0xEF01) = 0x14579\n const lsb = (x & 0xffff) + (y & 0xffff);\n // Add upper 16 bits + carry from lower addition\n // msb = (0x1234 + 0xABCD + (0x14579 >>> 16)) = (0x1234 + 0xABCD + 0x1) = 0xBE02\n const msb = (x >>> 16) + (y >>> 16) + (lsb >>> 16);\n // Combine: upper 16 bits | lower 16 bits (masked to prevent double carry)\n // return (0xBE02 << 16) | (0x14579 & 0xffff) = 0xBE024579\n return msb << 16 | lsb & 0xffff;\n}\nconst seedEncoder = /*#__PURE__*/new TextEncoder();\n/**\n * Convert a string to UTF-8 encoded 32-bit integers (little-endian).\n */\nfunction toIntArray(seed) {\n const bytes = seedEncoder.encode(seed);\n const result = [];\n for (let index = 0; index < bytes.length; index += 4) {\n result.push((bytes[index] ?? 0) << 0 | (bytes[index + 1] ?? 0) << 8 | (bytes[index + 2] ?? 0) << 16 | (bytes[index + 3] ?? 0) << 24);\n }\n return result;\n}\n//# sourceMappingURL=Random.js.map","import { Text } from \"@knpkv/rly/primitives\"\nimport { type ReactElement, useEffect, useRef } from \"react\"\nimport { Link } from \"react-router\"\n\nimport type { SessionSummary } from \"../api/session.js\"\nimport { useBrowserSession } from \"./BrowserSession.js\"\nimport styles from \"./pages.module.css\"\n\nconst sessionLabel = (permission: SessionSummary[\"permission\"]): string =>\n permission === \"workspace-owner\" ? \"Owner browser paired\" : \"Browser paired\"\n\ninterface BrowserSessionStatusProps {\n readonly anonymousAction?: \"link\" | \"status\"\n}\n\n/** Describe this browser's application-wide private session. */\nexport const BrowserSessionStatus = ({ anonymousAction = \"link\" }: BrowserSessionStatusProps = {}): ReactElement => {\n const { state: browserSession } = useBrowserSession()\n const storageAlert = useRef<HTMLSpanElement>(null)\n\n useEffect(() => {\n if (browserSession._tag === \"storage-unavailable\") storageAlert.current?.focus()\n }, [browserSession._tag])\n\n if (browserSession._tag === \"anonymous\") {\n if (anonymousAction === \"status\") {\n return (\n <Text className={styles.sessionStatus} tone=\"secondary\" variant=\"label\">\n Browser not paired\n </Text>\n )\n }\n return (\n <Link className={styles.linkButton} to=\"/pair\">\n Pair this browser\n </Link>\n )\n }\n if (browserSession._tag === \"authenticated\") {\n return (\n <Text className={styles.sessionBadge} variant=\"label\">\n <span aria-hidden=\"true\">✓</span> {sessionLabel(browserSession.session.permission)}\n </Text>\n )\n }\n if (browserSession._tag === \"storage-unavailable\") {\n return (\n <Text\n aria-atomic=\"true\"\n as=\"span\"\n className={styles.sessionStatus}\n ref={storageAlert}\n role=\"alert\"\n tabIndex={-1}\n tone=\"secondary\"\n variant=\"label\"\n >\n {browserSession.session === null\n ? \"Session storage is unavailable. Check storage permissions or space, then reload.\"\n : \"Browser paired, but session storage is unavailable. Check storage permissions or space, then reload.\"}\n </Text>\n )\n }\n return (\n <Text className={styles.sessionStatus} tone=\"secondary\" variant=\"label\">\n {browserSession._tag === \"checking\"\n ? \"Checking this browser…\"\n : browserSession._tag === \"blocked\"\n ? \"Session access blocked on this connection\"\n : \"Server unavailable\"}\n </Text>\n )\n}\n","import type { PortfolioReleasePresentation } from \"./presentPortfolio.js\"\n\n/** Stable URL and presentation identifiers for the four portfolio views. */\nexport type PortfolioFilter = \"all\" | \"attention\" | \"deploying\" | \"shipped\"\n\nexport interface PortfolioFilterOption {\n readonly count: number\n readonly id: PortfolioFilter\n readonly label: string\n}\n\nconst FILTER_LABELS: Readonly<Record<PortfolioFilter, string>> = {\n all: \"All\",\n attention: \"Need attention\",\n deploying: \"Deploying\",\n shipped: \"Shipped\"\n}\n\nconst FILTER_IDS: ReadonlyArray<PortfolioFilter> = [\"all\", \"attention\", \"deploying\", \"shipped\"]\n\n/** Decode the URL-owned filter, recovering to All for missing or unknown values. */\nexport const portfolioFilterFromSearch = (search: string): PortfolioFilter => {\n const value = new URLSearchParams(search).get(\"status\")\n return value === \"attention\" || value === \"deploying\" || value === \"shipped\" ? value : \"all\"\n}\n\n/** Keep unrelated query state while producing a canonical filter search string. */\nexport const portfolioFilterSearch = (search: string, filter: PortfolioFilter): string => {\n const parameters = new URLSearchParams(search)\n if (filter === \"all\") parameters.delete(\"status\")\n else parameters.set(\"status\", filter)\n const encoded = parameters.toString()\n return encoded.length === 0 ? \"\" : `?${encoded}`\n}\n\nconst releaseMatchesFilter = (release: PortfolioReleasePresentation, filter: PortfolioFilter): boolean => {\n switch (filter) {\n case \"all\":\n return true\n case \"attention\":\n return release.readinessVerdict === \"blocked\" ||\n release.readinessVerdict === \"held\" ||\n release.readinessVerdict === \"unknown\"\n case \"deploying\":\n return release.readinessVerdict === \"deploying\" || release.readinessVerdict === \"building\"\n case \"shipped\":\n return release.readinessVerdict === \"shipped\"\n }\n}\n\n/** Select rows from authoritative verdicts rather than copied display labels. */\nexport const filterPortfolioReleases = (\n releases: ReadonlyArray<PortfolioReleasePresentation>,\n filter: PortfolioFilter\n): ReadonlyArray<PortfolioReleasePresentation> => releases.filter((release) => releaseMatchesFilter(release, filter))\n\n/** Recompute all visible counts from the same live release set used for rows. */\nexport const portfolioFilterOptions = (\n releases: ReadonlyArray<PortfolioReleasePresentation>\n): ReadonlyArray<PortfolioFilterOption> =>\n FILTER_IDS.map((id) => ({\n count: filterPortfolioReleases(releases, id).length,\n id,\n label: FILTER_LABELS[id]\n }))\n\n/** Human-readable label for recoverable filter empty states. */\nexport const portfolioFilterLabel = (filter: PortfolioFilter): string => FILTER_LABELS[filter]\n","import type { PortfolioSnapshot } from \"../../api/portfolio.js\"\nimport type { EventCursor } from \"../../domain/identifiers.js\"\n\nexport type PortfolioLoadFailure = \"blocked\" | \"session-expired\" | \"unavailable\"\n\nexport type PortfolioConnectionState =\n | { readonly _tag: \"connecting\" }\n | { readonly _tag: \"connected\" }\n | { readonly _tag: \"reconnecting\"; readonly attempt: number }\n | { readonly _tag: \"offline\" }\n\nexport type PortfolioSnapshotLoadState =\n | { readonly _tag: \"idle\" }\n | { readonly _tag: \"loading\"; readonly sessionKey: string }\n | {\n readonly _tag: \"loaded\"\n readonly awaitingResetSnapshot: boolean\n readonly connection: PortfolioConnectionState\n readonly isSnapshotStale: boolean\n readonly minimumRefreshCursor: EventCursor | null\n readonly sessionKey: string\n readonly snapshot: PortfolioSnapshot\n }\n | { readonly _tag: \"failed\"; readonly sessionKey: string; readonly failure: PortfolioLoadFailure }\n\nexport type PortfolioLiveStateAction =\n | { readonly _tag: \"begin\"; readonly sessionKey: string }\n | { readonly _tag: \"initial-snapshot\"; readonly sessionKey: string; readonly snapshot: PortfolioSnapshot }\n | { readonly _tag: \"caught-up\" }\n | { readonly _tag: \"stream-snapshot\"; readonly snapshot: PortfolioSnapshot }\n | { readonly _tag: \"invalidated\"; readonly eventCursor: EventCursor }\n | { readonly _tag: \"reset-required\"; readonly headCursor: EventCursor }\n | { readonly _tag: \"reconnecting\"; readonly attempt: number }\n | { readonly _tag: \"offline\" }\n | { readonly _tag: \"failed\"; readonly sessionKey: string; readonly failure: PortfolioLoadFailure }\n | { readonly _tag: \"clear\" }\n\nconst laterCursor = (left: EventCursor | null, right: EventCursor): EventCursor =>\n left === null || right > left ? right : left\n\n/** Reduce portfolio transport facts without ever replacing a snapshot from an invalidation event. */\nexport const reducePortfolioLiveState = (\n state: PortfolioSnapshotLoadState,\n action: PortfolioLiveStateAction\n): PortfolioSnapshotLoadState => {\n switch (action._tag) {\n case \"clear\":\n return { _tag: \"idle\" }\n case \"begin\":\n return { _tag: \"loading\", sessionKey: action.sessionKey }\n case \"failed\":\n return { _tag: \"failed\", sessionKey: action.sessionKey, failure: action.failure }\n case \"initial-snapshot\":\n return {\n _tag: \"loaded\",\n awaitingResetSnapshot: false,\n connection: { _tag: \"connecting\" },\n isSnapshotStale: false,\n minimumRefreshCursor: null,\n sessionKey: action.sessionKey,\n snapshot: action.snapshot\n }\n case \"caught-up\":\n if (state._tag !== \"loaded\") return state\n if (\n state.awaitingResetSnapshot ||\n (state.minimumRefreshCursor !== null && state.minimumRefreshCursor > state.snapshot.eventCursor)\n ) {\n return state\n }\n return {\n ...state,\n awaitingResetSnapshot: false,\n connection: { _tag: \"connected\" },\n isSnapshotStale: false,\n minimumRefreshCursor: null\n }\n case \"stream-snapshot\":\n if (state._tag !== \"loaded\") return state\n if (state.minimumRefreshCursor !== null && action.snapshot.eventCursor < state.minimumRefreshCursor) return state\n if (!state.awaitingResetSnapshot && action.snapshot.eventCursor < state.snapshot.eventCursor) return state\n return {\n ...state,\n awaitingResetSnapshot: false,\n connection: { _tag: \"connected\" },\n isSnapshotStale: false,\n minimumRefreshCursor: null,\n snapshot: action.snapshot\n }\n case \"invalidated\":\n if (\n state._tag !== \"loaded\" ||\n state.awaitingResetSnapshot ||\n action.eventCursor <= state.snapshot.eventCursor\n ) {\n return state\n }\n return {\n ...state,\n isSnapshotStale: true,\n minimumRefreshCursor: laterCursor(state.minimumRefreshCursor, action.eventCursor)\n }\n case \"reset-required\":\n if (state._tag !== \"loaded\") return state\n return {\n ...state,\n awaitingResetSnapshot: true,\n isSnapshotStale: true,\n minimumRefreshCursor: laterCursor(state.minimumRefreshCursor, action.headCursor)\n }\n case \"reconnecting\":\n if (state._tag !== \"loaded\") return state\n return {\n ...state,\n connection: { _tag: \"reconnecting\", attempt: action.attempt },\n isSnapshotStale: true\n }\n case \"offline\":\n if (state._tag !== \"loaded\") return state\n return {\n ...state,\n connection: { _tag: \"offline\" },\n isSnapshotStale: true\n }\n }\n}\n\n/** Read the only cursor safe to acknowledge when reconnecting. */\nexport const appliedPortfolioCursor = (state: PortfolioSnapshotLoadState): EventCursor | null =>\n state._tag === \"loaded\" ? state.snapshot.eventCursor : null\n","import * as Cause from \"effect/Cause\"\nimport * as Data from \"effect/Data\"\nimport * as Effect from \"effect/Effect\"\nimport * as Exit from \"effect/Exit\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as Random from \"effect/Random\"\nimport * as Result from \"effect/Result\"\nimport * as Stream from \"effect/Stream\"\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\"\nimport { useCallback, useEffect, useState } from \"react\"\n\nimport { makeControlCenterApiClient } from \"../../api/client.js\"\nimport type { ControlCenterLiveEvent, StreamResetRequired } from \"../../api/liveEvents.js\"\nimport type { PortfolioSnapshot } from \"../../api/portfolio.js\"\nimport type { EventCursor } from \"../../domain/identifiers.js\"\nimport {\n appliedPortfolioCursor,\n type PortfolioLoadFailure,\n type PortfolioSnapshotLoadState,\n reducePortfolioLiveState\n} from \"./livePortfolioState.js\"\n\nexport type {\n PortfolioConnectionState,\n PortfolioLoadFailure,\n PortfolioSnapshotLoadState\n} from \"./livePortfolioState.js\"\n\nexport interface PortfolioSnapshotController {\n readonly retry: () => void\n readonly state: PortfolioSnapshotLoadState\n}\n\nexport interface PortfolioFailureResolutionInput {\n readonly failure: unknown\n readonly onSessionExpired: (sessionKey: string) => void\n readonly sessionKey: string\n}\n\nexport interface PortfolioLiveTransport {\n readonly loadSnapshot: Effect.Effect<PortfolioSnapshot, unknown>\n readonly openStream: (after: EventCursor) => Effect.Effect<Stream.Stream<ControlCenterLiveEvent, unknown>, unknown>\n}\n\nexport interface PortfolioBrowserConnectivity {\n readonly isOnline: Effect.Effect<boolean>\n readonly waitUntilOnline: Effect.Effect<void>\n}\n\nexport interface RunPortfolioLiveControllerOptions {\n readonly connectivity: PortfolioBrowserConnectivity\n readonly onSessionExpired: (sessionKey: string) => void\n readonly onState: (state: PortfolioSnapshotLoadState) => void\n readonly sessionKey: string\n readonly transport: PortfolioLiveTransport\n}\n\nexport interface PortfolioSnapshotDependencies {\n readonly connectivity: PortfolioBrowserConnectivity\n readonly transport: PortfolioLiveTransport\n}\n\nconst MAXIMUM_RECONNECT_DELAY_MILLIS = 30_000\nconst INITIAL_RECONNECT_DELAY_MILLIS = 500\nconst MAXIMUM_RECONNECT_EXPONENT = 16\n\nclass PortfolioStreamProtocolError extends Data.TaggedError(\"PortfolioStreamProtocolError\") {}\n\nclass PortfolioStreamClosedError extends Data.TaggedError(\"PortfolioStreamClosedError\") {}\n\nconst classifyFailure = (failure: unknown): PortfolioLoadFailure => {\n if (!Predicate.hasProperty(failure, \"_tag\") || typeof failure._tag !== \"string\") return \"unavailable\"\n if (failure._tag === \"UnauthorizedApiError\") return \"session-expired\"\n if (failure._tag === \"ForbiddenApiError\") return \"blocked\"\n return \"unavailable\"\n}\n\n/** Calculate one capped equal-jitter delay from a one-based reconnect attempt. */\nexport const portfolioReconnectDelayMillis = (attempt: number, random: number): number => {\n const exponent = Math.min(Math.max(attempt - 1, 0), MAXIMUM_RECONNECT_EXPONENT)\n const ceiling = Math.min(MAXIMUM_RECONNECT_DELAY_MILLIS, INITIAL_RECONNECT_DELAY_MILLIS * 2 ** exponent)\n const halfCeiling = ceiling / 2\n return Math.max(1, Math.floor(halfCeiling + halfCeiling * Math.min(Math.max(random, 0), 1)))\n}\n\nconst reconnectDelay = (attempt: number): Effect.Effect<void> =>\n Random.next.pipe(\n Effect.map((random) => portfolioReconnectDelayMillis(attempt, random)),\n Effect.flatMap(Effect.sleep)\n )\n\nconst hasValidResetCursorRelation = (reset: StreamResetRequired): boolean => {\n if (reset.prunedThroughCursor > reset.headCursor) return false\n switch (reset.reason) {\n case \"retention\":\n return reset.requestedCursor < reset.prunedThroughCursor\n case \"cursor-ahead\":\n return reset.requestedCursor > reset.headCursor\n case \"gap\":\n return reset.prunedThroughCursor <= reset.requestedCursor && reset.requestedCursor < reset.headCursor\n case \"replay-budget\":\n return reset.requestedCursor <= reset.headCursor\n }\n}\n\nconst browserConnectivity: PortfolioBrowserConnectivity = {\n isOnline: Effect.sync(() => navigator.onLine),\n waitUntilOnline: Effect.suspend(() => {\n if (navigator.onLine) return Effect.void\n return Effect.callback<void>((resume) => {\n const handleOnline = (): void => resume(Effect.void)\n window.addEventListener(\"online\", handleOnline, { once: true })\n return Effect.sync(() => window.removeEventListener(\"online\", handleOnline))\n })\n })\n}\n\nconst generatedTransport = Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return {\n loadSnapshot: client.portfolio.snapshot(),\n openStream: (after: EventCursor) =>\n client.liveEvents.stream({\n headers: { \"last-event-id\": after },\n query: { after }\n })\n } satisfies PortfolioLiveTransport\n})\n\n/** Classify one request failure and invalidate only the session that issued an unauthorized read. */\nexport const resolvePortfolioFailure = ({\n failure,\n onSessionExpired,\n sessionKey\n}: PortfolioFailureResolutionInput): Extract<PortfolioSnapshotLoadState, { readonly _tag: \"failed\" }> => {\n const classified = classifyFailure(failure)\n if (classified === \"session-expired\") onSessionExpired(sessionKey)\n return { _tag: \"failed\", sessionKey, failure: classified }\n}\n\nconst runController = Effect.fn(\"PortfolioLiveController.run\")(function*({\n connectivity,\n onSessionExpired,\n onState,\n sessionKey,\n transport\n}: RunPortfolioLiveControllerOptions) {\n let currentState: PortfolioSnapshotLoadState = { _tag: \"loading\", sessionKey }\n\n const publish = (action: Parameters<typeof reducePortfolioLiveState>[1]): Effect.Effect<void> =>\n Effect.sync(() => {\n currentState = reducePortfolioLiveState(currentState, action)\n onState(currentState)\n })\n\n const initialResult = yield* Effect.result(transport.loadSnapshot)\n if (Result.isFailure(initialResult)) {\n const failed = resolvePortfolioFailure({\n failure: initialResult.failure,\n onSessionExpired,\n sessionKey\n })\n yield* publish({ _tag: \"failed\", failure: failed.failure, sessionKey })\n return yield* Effect.never\n }\n yield* publish({ _tag: \"initial-snapshot\", sessionKey, snapshot: initialResult.success })\n\n const refreshSnapshot = Effect.fn(\"PortfolioLiveController.refreshSnapshot\")(function*(\n minimumCursor: EventCursor\n ) {\n const snapshot = yield* transport.loadSnapshot\n if (snapshot.eventCursor < minimumCursor) return yield* Effect.fail(new PortfolioStreamProtocolError())\n yield* publish({ _tag: \"stream-snapshot\", snapshot })\n })\n\n const consumeStream = Effect.fn(\"PortfolioLiveController.consumeStream\")(function*(\n stream: Stream.Stream<ControlCenterLiveEvent, unknown>,\n resumeCursor: EventCursor,\n onUsable: Effect.Effect<void>\n ) {\n let isUsable = false\n let resetHeadCursor = currentState._tag === \"loaded\" && currentState.awaitingResetSnapshot\n ? currentState.minimumRefreshCursor\n : null\n let streamCursor = resumeCursor\n\n const advanceStreamCursor = (cursor: EventCursor): void => {\n if (cursor > streamCursor) streamCursor = cursor\n }\n\n const consumeEvent = (event: ControlCenterLiveEvent): Effect.Effect<void, unknown> => {\n switch (event.event) {\n case \"portfolio.snapshot\": {\n if (event.id !== event.data.eventCursor) return Effect.fail(new PortfolioStreamProtocolError())\n const appliedCursor = appliedPortfolioCursor(currentState)\n if (appliedCursor === null) return Effect.fail(new PortfolioStreamProtocolError())\n if (resetHeadCursor !== null && event.id < resetHeadCursor) {\n return Effect.fail(new PortfolioStreamProtocolError())\n }\n if (resetHeadCursor === null) {\n advanceStreamCursor(event.id)\n } else {\n streamCursor = event.id\n }\n if (resetHeadCursor === null && event.id < appliedCursor) return Effect.void\n resetHeadCursor = null\n return publish({ _tag: \"stream-snapshot\", snapshot: event.data })\n }\n case \"portfolio.invalidated\": {\n if (resetHeadCursor !== null || event.id !== event.data.eventCursor) {\n return Effect.fail(new PortfolioStreamProtocolError())\n }\n advanceStreamCursor(event.id)\n const appliedCursor = appliedPortfolioCursor(currentState)\n if (appliedCursor === null || event.id <= appliedCursor) return Effect.void\n return publish({ _tag: \"invalidated\", eventCursor: event.id }).pipe(\n Effect.andThen(refreshSnapshot(event.id))\n )\n }\n case \"stream.reset-required\": {\n if (event.data.requestedCursor !== streamCursor || !hasValidResetCursorRelation(event.data)) {\n return Effect.fail(new PortfolioStreamProtocolError())\n }\n resetHeadCursor = resetHeadCursor === null || event.data.headCursor > resetHeadCursor\n ? event.data.headCursor\n : resetHeadCursor\n return publish({ _tag: \"reset-required\", headCursor: resetHeadCursor })\n }\n case \"stream.heartbeat\":\n if (resetHeadCursor !== null) return Effect.fail(new PortfolioStreamProtocolError())\n {\n const appliedCursor = appliedPortfolioCursor(currentState)\n if (appliedCursor === null) return Effect.fail(new PortfolioStreamProtocolError())\n advanceStreamCursor(event.data.eventCursor)\n if (event.data.eventCursor <= appliedCursor) return publish({ _tag: \"caught-up\" })\n return publish({ _tag: \"invalidated\", eventCursor: event.data.eventCursor }).pipe(\n Effect.andThen(refreshSnapshot(event.data.eventCursor))\n )\n }\n }\n }\n\n yield* Stream.runForEach(stream, (event) =>\n consumeEvent(event).pipe(\n Effect.tap(() => {\n if (isUsable) return Effect.void\n isUsable = true\n return onUsable\n })\n ))\n return yield* Effect.fail(new PortfolioStreamClosedError())\n })\n\n const reconnect = Effect.fn(\"PortfolioLiveController.reconnect\")(function*() {\n let attempt = 0\n while (true) {\n const isOnline = yield* connectivity.isOnline\n if (!isOnline) {\n yield* publish({ _tag: \"offline\" })\n yield* connectivity.waitUntilOnline\n } else if (attempt > 0) {\n yield* publish({ _tag: \"reconnecting\", attempt })\n yield* reconnectDelay(attempt)\n }\n\n const cursor = appliedPortfolioCursor(currentState)\n if (cursor === null) return yield* Effect.never\n const streamResult = yield* Effect.result(\n Effect.gen(function*() {\n const stream = yield* transport.openStream(cursor)\n return yield* consumeStream(\n stream,\n cursor,\n Effect.sync(() => {\n attempt = 0\n })\n )\n })\n )\n if (Result.isSuccess(streamResult)) return yield* Effect.never\n\n const failure = classifyFailure(streamResult.failure)\n if (failure === \"session-expired\" || failure === \"blocked\") {\n const failed = resolvePortfolioFailure({\n failure: streamResult.failure,\n onSessionExpired,\n sessionKey\n })\n yield* publish({ _tag: \"failed\", failure: failed.failure, sessionKey })\n return yield* Effect.never\n }\n attempt += 1\n }\n })\n\n return yield* reconnect()\n})\n\n/** Run one session-isolated authoritative snapshot and live invalidation controller. */\nexport const runPortfolioLiveController = (options: RunPortfolioLiveControllerOptions): Effect.Effect<never> =>\n runController(options)\n\n/** Load an authoritative portfolio and keep it current through the generated SSE client. */\nexport const usePortfolioSnapshot = (\n sessionKey: string | null,\n onSessionExpired: (sessionKey: string) => void,\n dependencies?: PortfolioSnapshotDependencies\n): PortfolioSnapshotController => {\n const [requestRevision, setRequestRevision] = useState(0)\n const [state, setState] = useState<PortfolioSnapshotLoadState>({ _tag: \"idle\" })\n\n useEffect(() => {\n if (sessionKey === null) {\n setState({ _tag: \"idle\" })\n return\n }\n\n const abortController = new AbortController()\n let isCurrent = true\n setState({ _tag: \"loading\", sessionKey })\n const run = (transport: PortfolioLiveTransport, connectivity: PortfolioBrowserConnectivity): Effect.Effect<never> =>\n runPortfolioLiveController({\n connectivity,\n onSessionExpired,\n onState: (nextState) => {\n if (isCurrent) setState(nextState)\n },\n sessionKey,\n transport\n })\n const program = dependencies === undefined\n ? Effect.flatMap(generatedTransport, (transport) => run(transport, browserConnectivity)).pipe(\n Effect.provide(FetchHttpClient.layer)\n )\n : run(dependencies.transport, dependencies.connectivity)\n\n Effect.runPromiseExit(program, { signal: abortController.signal }).then((exit) => {\n if (!isCurrent || Exit.isSuccess(exit) || Cause.hasInterruptsOnly(exit.cause)) return\n setState({ _tag: \"failed\", failure: \"unavailable\", sessionKey })\n })\n return () => {\n isCurrent = false\n abortController.abort()\n }\n }, [dependencies, onSessionExpired, requestRevision, sessionKey])\n\n const retry = useCallback((): void => setRequestRevision((current) => current + 1), [])\n return { retry, state }\n}\n",".root {\n display: grid;\n gap: clamp(4rem, 9vw, 8rem);\n}\n\n.hero {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 2rem;\n align-items: end;\n}\n\n.heroCopy {\n display: grid;\n gap: 1.5rem;\n}\n\n.title {\n max-inline-size: 10ch;\n text-wrap: balance;\n}\n\n.lede {\n max-inline-size: 42rem;\n text-wrap: pretty;\n}\n\n.session {\n display: grid;\n gap: 0.75rem;\n justify-items: end;\n}\n\n.liveStatus {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: 0.5rem;\n}\n\n.content,\n.readyPortfolio,\n.releaseList {\n display: grid;\n gap: 1.25rem;\n}\n\n.readyPortfolio {\n gap: clamp(2.5rem, 6vw, 5rem);\n}\n\n.filters {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n border-block: 1px solid var(--rly-color-border-1);\n}\n\n.filter {\n display: grid;\n min-inline-size: 0;\n min-block-size: clamp(8rem, 14vw, 12rem);\n align-content: space-between;\n gap: 1rem;\n padding: clamp(1rem, 2.5vw, 2rem);\n border-inline-end: 1px solid var(--rly-color-border-1);\n color: var(--rly-color-text-2);\n font-size: clamp(1.35rem, 2.7vw, 3rem);\n font-weight: 650;\n letter-spacing: -0.04em;\n line-height: 0.95;\n text-decoration: none;\n text-wrap: balance;\n transition:\n background-color 160ms ease,\n color 160ms ease;\n}\n\n.filter:last-child {\n border-inline-end: 0;\n}\n\n.filter:hover {\n background: var(--rly-color-surface-2);\n color: var(--rly-color-text-1);\n}\n\n.filter[data-active=\"true\"] {\n background: var(--rly-color-action-background);\n color: var(--rly-color-action-foreground);\n}\n\n.filter:focus-visible {\n position: relative;\n z-index: 1;\n outline: 3px solid var(--rly-color-focus);\n outline-offset: -3px;\n}\n\n.filterCount {\n font-size: clamp(2.75rem, 6vw, 6.5rem);\n font-variant-numeric: tabular-nums;\n font-weight: 720;\n letter-spacing: -0.07em;\n line-height: 0.8;\n}\n\n.releaseList {\n overflow: hidden;\n border-block-start: 1px solid var(--rly-color-border-1);\n border-radius: var(--rly-radius-group);\n background: var(--rly-color-surface-1);\n}\n\n.statePanel {\n max-inline-size: 46rem;\n}\n\n.firstService {\n display: grid;\n gap: clamp(2rem, 5vw, 4rem);\n}\n\n.firstServiceCopy {\n display: grid;\n max-inline-size: 46rem;\n gap: var(--rly-space-12);\n}\n\n.serviceLauncher {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));\n gap: var(--rly-space-12);\n}\n\n.serviceChoice {\n display: flex;\n min-block-size: 8.5rem;\n align-items: flex-start;\n justify-content: space-between;\n flex-direction: column;\n gap: var(--rly-space-24);\n padding: var(--rly-space-20);\n border: 1px solid var(--rly-color-border-1);\n border-block-start-width: 3px;\n border-radius: var(--rly-radius-group);\n background: var(--rly-color-surface-1);\n color: var(--rly-color-text-1);\n text-decoration: none;\n transition:\n border-color 160ms ease,\n background-color 160ms ease,\n transform 160ms ease;\n}\n\n.serviceChoice[data-service=\"codecommit\"] {\n border-block-start-color: var(--rly-color-service-codecommit);\n}\n\n.serviceChoice[data-service=\"codepipeline\"] {\n border-block-start-color: var(--rly-color-service-codepipeline);\n}\n\n.serviceChoice[data-service=\"jira\"] {\n border-block-start-color: var(--rly-color-service-jira);\n}\n\n.serviceChoice[data-service=\"confluence\"] {\n border-block-start-color: var(--rly-color-service-confluence);\n}\n\n.serviceChoice[data-service=\"clockify\"] {\n border-block-start-color: var(--rly-color-service-clockify);\n}\n\n.serviceChoice:hover {\n border-color: var(--rly-color-border-2);\n background: var(--rly-color-surface-2);\n transform: translateY(-2px);\n}\n\n.serviceChoice:focus-visible {\n outline: 3px solid var(--rly-color-focus);\n outline-offset: 3px;\n}\n\n.serviceAction {\n color: var(--rly-color-text-2);\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n}\n\n.pairAction {\n display: inline-flex;\n min-block-size: 3rem;\n align-items: center;\n padding-inline: 1.25rem;\n border: 1px solid var(--rly-color-border-2);\n border-radius: var(--rly-radius-control);\n background: var(--rly-color-action-background);\n color: var(--rly-color-action-foreground);\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n text-decoration: none;\n}\n\n.loading {\n display: grid;\n gap: 1.5rem;\n padding-block: 1rem;\n}\n\n.loadingRail {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 1rem;\n}\n\n.releaseEntry {\n min-inline-size: 0;\n}\n\n.releaseEntry :global([data-rly-release-fact=\"issues\"]) {\n border-color: var(--rly-color-service-jira);\n}\n\n.releaseEntry :global([data-rly-release-fact=\"pull-requests\"]) {\n border-color: var(--rly-color-service-codecommit);\n}\n\n.releaseEntry :global([data-rly-release-fact=\"pipelines\"]) {\n border-color: var(--rly-color-service-codepipeline);\n}\n\n.releaseEntry :global([data-rly-release-fact=\"gaps\"]) {\n border-color: var(--rly-color-held-ink);\n}\n\n.stageRail {\n padding: var(--rly-space-16) var(--rly-space-24) var(--rly-space-20);\n border-block-end: 1px solid var(--rly-color-border-1);\n}\n\n.sourceWarning {\n margin: 0 var(--rly-space-24) var(--rly-space-20);\n}\n\n@media (max-width: 48rem) {\n .root {\n gap: 4rem;\n }\n\n .hero {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .session {\n justify-items: start;\n }\n\n .liveStatus {\n justify-content: flex-start;\n }\n\n .loadingRail {\n grid-template-columns: 1fr;\n }\n\n .filters {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .filter:nth-child(2) {\n border-inline-end: 0;\n }\n\n .filter:nth-child(-n + 2) {\n border-block-end: 1px solid var(--rly-color-border-1);\n }\n}\n\n@media (max-width: 30rem) {\n .filter {\n min-block-size: 7rem;\n }\n\n .stageRail {\n padding-inline: var(--rly-space-16);\n }\n\n .sourceWarning {\n margin-inline: var(--rly-space-16);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .filter,\n .serviceChoice {\n transition: none;\n }\n\n .serviceChoice:hover {\n transform: none;\n }\n}\n","import { ReleaseRow, ServiceMark, StageRail, type RlyReleaseTransitionNames } from \"@knpkv/rly/patterns\"\nimport { Button, Skeleton, StateLabel, StatePanel, Text } from \"@knpkv/rly/primitives\"\nimport type { ReactElement } from \"react\"\nimport { Link, Navigate, useLocation, useViewTransitionState } from \"react-router\"\n\nimport { firstPartyServiceIdentities } from \"../../domain/firstPartyServices.js\"\nimport { BrowserSessionStatus } from \"../BrowserSessionStatus.js\"\nimport { useBrowserSession } from \"../BrowserSession.js\"\nimport { releaseParentPath, releaseTransitionNames } from \"../releases/releaseRoutes.js\"\nimport { serviceSetupPath } from \"../services/serviceOnboarding.js\"\nimport { useWorkspaceDefaultLandingPath } from \"../settings/useWorkspaceDefaultLanding.js\"\nimport { presentPortfolio, type PortfolioPresentation, type PortfolioReleasePresentation } from \"./presentPortfolio.js\"\nimport {\n filterPortfolioReleases,\n type PortfolioFilter,\n portfolioFilterFromSearch,\n portfolioFilterLabel,\n portfolioFilterOptions,\n portfolioFilterSearch\n} from \"./portfolioFilters.js\"\nimport {\n type PortfolioConnectionState,\n type PortfolioLoadFailure,\n type PortfolioSnapshotLoadState,\n usePortfolioSnapshot\n} from \"./usePortfolioSnapshot.js\"\nimport styles from \"./PortfolioOverview.module.css\"\n\nexport type PortfolioOverviewState =\n | {\n readonly _tag: \"session\"\n readonly reason: \"anonymous\" | \"blocked\" | \"checking\" | \"storage-unavailable\" | \"unavailable\"\n }\n | { readonly _tag: \"loading\" }\n | {\n readonly _tag: \"ready\"\n readonly connection: PortfolioConnectionState\n readonly isSnapshotStale: boolean\n readonly portfolio: PortfolioPresentation\n }\n | { readonly _tag: \"failed\"; readonly failure: PortfolioLoadFailure }\n\nexport interface PortfolioOverviewViewProps {\n readonly onPreviewRelease: (releaseId: PortfolioReleasePresentation[\"id\"]) => void\n readonly onRetry: () => void\n readonly previewPathForRelease?: (releaseId: PortfolioReleasePresentation[\"id\"]) => string\n readonly state: PortfolioOverviewState\n}\n\nexport interface PortfolioOverviewController {\n readonly onRetry: () => void\n readonly state: PortfolioOverviewState\n}\n\ninterface ReleaseDossierProps {\n readonly onPreview: () => void\n readonly release: PortfolioReleasePresentation\n readonly transitionNames?: RlyReleaseTransitionNames\n}\n\nconst connectionPresentation = (\n connection: PortfolioConnectionState,\n isSnapshotStale: boolean\n): { readonly detail: string; readonly label: string; readonly tone: \"caution\" | \"positive\" | \"progress\" } => {\n switch (connection._tag) {\n case \"connecting\":\n return { detail: \"Connecting to live updates.\", label: \"Connecting\", tone: \"progress\" }\n case \"reconnecting\":\n return {\n detail: \"Showing the last snapshot; it may be stale.\",\n label: \"Reconnecting\",\n tone: \"caution\"\n }\n case \"offline\":\n return { detail: \"Showing the last snapshot; it may be stale.\", label: \"Offline\", tone: \"caution\" }\n case \"connected\":\n return isSnapshotStale\n ? { detail: \"Refreshing the authoritative snapshot.\", label: \"Updating\", tone: \"progress\" }\n : { detail: \"Snapshot up to date.\", label: \"Live\", tone: \"positive\" }\n }\n}\n\nconst PortfolioLiveStatus = ({\n connection,\n isSnapshotStale\n}: {\n readonly connection: PortfolioConnectionState\n readonly isSnapshotStale: boolean\n}): ReactElement => {\n const presentation = connectionPresentation(connection, isSnapshotStale)\n return (\n <div aria-atomic=\"true\" aria-live=\"polite\" className={styles.liveStatus} role=\"status\">\n <StateLabel label={presentation.label} size=\"compact\" tone={presentation.tone} />\n <Text tone=\"tertiary\" variant=\"meta\">\n {presentation.detail}\n </Text>\n </div>\n )\n}\n\nconst EmptyPortfolio = (): ReactElement => (\n <section aria-labelledby=\"first-service-title\" className={styles.firstService}>\n <div className={styles.firstServiceCopy}>\n <Text as=\"h2\" id=\"first-service-title\" variant=\"page-title\">\n Choose your first service\n </Text>\n <Text tone=\"secondary\" variant=\"body-large\">\n Enable and verify one source. Its releases, people, and delivery evidence will appear here automatically.\n </Text>\n </div>\n <nav aria-label=\"Services available to enable\" className={styles.serviceLauncher}>\n {firstPartyServiceIdentities.map((service) => (\n <Link\n className={styles.serviceChoice}\n data-service={service.providerId}\n key={service.providerId}\n to={serviceSetupPath(service.providerId)}\n >\n <ServiceMark service={service.providerId} />\n <span className={styles.serviceAction}>Enable</span>\n </Link>\n ))}\n </nav>\n </section>\n)\n\nconst LoadingPortfolio = (): ReactElement => (\n <div className={styles.loading}>\n <Skeleton decorative={false} height=\"1.25rem\" label=\"Loading releases\" width=\"10rem\" />\n <Skeleton decorative height=\"8rem\" variant=\"block\" />\n <div className={styles.loadingRail}>\n <Skeleton decorative height=\"3rem\" variant=\"block\" />\n <Skeleton decorative height=\"3rem\" variant=\"block\" />\n <Skeleton decorative height=\"3rem\" variant=\"block\" />\n </div>\n </div>\n)\n\ntype PortfolioSessionReason = Extract<PortfolioOverviewState, { readonly _tag: \"session\" }>[\"reason\"]\n\ninterface PortfolioSessionBoundaryPresentation {\n readonly announce?: \"assertive\"\n readonly description: string\n readonly title: string\n readonly tone?: \"caution\" | \"critical\"\n}\n\nexport const portfolioSessionBoundaryPresentation = (\n reason: PortfolioSessionReason\n): PortfolioSessionBoundaryPresentation => {\n switch (reason) {\n case \"anonymous\":\n return {\n description:\n \"Pair this browser to read the workspace portfolio. Release facts never load before authentication.\",\n title: \"Release facts stay private\"\n }\n case \"checking\":\n return {\n description: \"Control Center is confirming whether this browser can read the workspace portfolio.\",\n title: \"Checking this browser\"\n }\n case \"blocked\":\n return {\n announce: \"assertive\",\n description: \"This connection cannot read private release facts. Use an allowed Control Center address.\",\n title: \"Portfolio access blocked\",\n tone: \"critical\"\n }\n case \"storage-unavailable\":\n return {\n announce: \"assertive\",\n description:\n \"This browser cannot retain the private session proof. Check storage permissions or space, then reload.\",\n title: \"Session storage unavailable\",\n tone: \"caution\"\n }\n case \"unavailable\":\n return {\n announce: \"assertive\",\n description: \"Control Center could not check this browser session. Check the server, then reload this page.\",\n title: \"Control Center unavailable\",\n tone: \"critical\"\n }\n }\n}\n\nconst SessionBoundary = ({ reason }: Extract<PortfolioOverviewState, { readonly _tag: \"session\" }>): ReactElement => {\n const presentation = portfolioSessionBoundaryPresentation(reason)\n return (\n <StatePanel\n {...presentation}\n action={\n reason === \"anonymous\" ? (\n <Link className={styles.pairAction} to=\"/pair\">\n Pair this browser\n </Link>\n ) : undefined\n }\n className={styles.statePanel}\n />\n )\n}\n\nconst FailedPortfolio = ({\n failure,\n onRetry\n}: {\n readonly failure: PortfolioLoadFailure\n readonly onRetry: () => void\n}): ReactElement => {\n if (failure === \"session-expired\") {\n return (\n <StatePanel\n action={\n <Link className={styles.pairAction} to=\"/pair\">\n Pair this browser\n </Link>\n }\n announce=\"assertive\"\n className={styles.statePanel}\n description=\"Pair this browser again to read the workspace portfolio.\"\n title=\"Pairing expired\"\n tone=\"caution\"\n />\n )\n }\n if (failure === \"blocked\") {\n return (\n <StatePanel\n announce=\"assertive\"\n className={styles.statePanel}\n description=\"This connection cannot read private release facts. Use an allowed Control Center address.\"\n title=\"Portfolio access blocked\"\n tone=\"critical\"\n />\n )\n }\n return (\n <StatePanel\n action={<Button onClick={onRetry}>Try again</Button>}\n announce=\"assertive\"\n className={styles.statePanel}\n description=\"Control Center could not read the saved portfolio. Check the server, then try again.\"\n title=\"Overview unavailable\"\n tone=\"critical\"\n />\n )\n}\n\nconst ReleaseDossier = ({ onPreview, release, transitionNames }: ReleaseDossierProps): ReactElement => (\n <div className={styles.releaseEntry} data-portfolio-release-id={release.id}>\n <ReleaseRow\n onPreview={onPreview}\n previewLabel={`Preview ${release.relay.codename}`}\n release={release.release}\n {...(transitionNames === undefined ? {} : { transitionNames })}\n />\n <StageRail className={styles.stageRail} heading=\"Delivery\" size=\"compact\" stages={release.stages} />\n {release.source.warning === null ? null : (\n <StatePanel\n announce=\"polite\"\n className={styles.sourceWarning}\n description={release.source.warning}\n title=\"Showing preserved source facts\"\n tone=\"caution\"\n />\n )}\n </div>\n)\n\nconst PortfolioFilters = ({\n activeFilter,\n portfolio\n}: {\n readonly activeFilter: PortfolioFilter\n readonly portfolio: PortfolioPresentation\n}): ReactElement => {\n const location = useLocation()\n return (\n <nav aria-label=\"Release filters\" className={styles.filters}>\n {portfolioFilterOptions(portfolio.releases).map((option) => (\n <Link\n aria-current={option.id === activeFilter ? \"page\" : undefined}\n className={styles.filter}\n data-active={option.id === activeFilter ? \"true\" : \"false\"}\n key={option.id}\n to={{ pathname: location.pathname, search: portfolioFilterSearch(location.search, option.id) }}\n >\n <span>{option.label}</span>\n <span\n aria-label={`${String(option.count)} ${option.count === 1 ? \"release\" : \"releases\"}`}\n className={styles.filterCount}\n >\n {option.count}\n </span>\n </Link>\n ))}\n </nav>\n )\n}\n\nconst EmptyFilter = ({ filter }: { readonly filter: PortfolioFilter }): ReactElement => {\n const location = useLocation()\n return (\n <StatePanel\n action={\n <Link\n className={styles.pairAction}\n to={{ pathname: location.pathname, search: portfolioFilterSearch(location.search, \"all\") }}\n >\n Show all releases\n </Link>\n }\n className={styles.statePanel}\n description={`No releases currently match ${portfolioFilterLabel(filter)}. Live updates may change this view.`}\n title=\"Nothing here right now\"\n />\n )\n}\n\nconst TransitioningReleaseDossier = ({\n onPreview,\n originPath,\n previewPath,\n release\n}: ReleaseDossierProps & { readonly originPath: string; readonly previewPath: string }): ReactElement => {\n const location = useLocation()\n const isTransitioning = useViewTransitionState(previewPath)\n return (\n <ReleaseDossier\n onPreview={onPreview}\n release={release}\n {...(isTransitioning && location.pathname === originPath\n ? { transitionNames: releaseTransitionNames(release.id) }\n : {})}\n />\n )\n}\n\nconst ReadyPortfolio = ({\n onPreviewRelease,\n portfolio,\n previewPathForRelease\n}: {\n readonly onPreviewRelease: (releaseId: PortfolioReleasePresentation[\"id\"]) => void\n readonly portfolio: PortfolioPresentation\n readonly previewPathForRelease?: (releaseId: PortfolioReleasePresentation[\"id\"]) => string\n}): ReactElement => {\n if (portfolio.releases.length === 0) return <EmptyPortfolio />\n const location = useLocation()\n const activeFilter = portfolioFilterFromSearch(location.search)\n const releases = filterPortfolioReleases(portfolio.releases, activeFilter)\n return (\n <div className={styles.readyPortfolio}>\n <PortfolioFilters activeFilter={activeFilter} portfolio={portfolio} />\n {releases.length === 0 ? (\n <EmptyFilter filter={activeFilter} />\n ) : (\n <div className={styles.releaseList}>\n {releases.map((release) =>\n previewPathForRelease === undefined ? (\n <ReleaseDossier key={release.id} onPreview={() => onPreviewRelease(release.id)} release={release} />\n ) : (\n <TransitioningReleaseDossier\n key={release.id}\n onPreview={() => onPreviewRelease(release.id)}\n originPath={releaseParentPath(portfolio.workspaceId)}\n previewPath={previewPathForRelease(release.id)}\n release={release}\n />\n )\n )}\n </div>\n )}\n </div>\n )\n}\n\n/** Render every Overview outcome from an explicit controlled state. */\nexport const PortfolioOverviewView = ({\n onPreviewRelease,\n onRetry,\n previewPathForRelease,\n state\n}: PortfolioOverviewViewProps): ReactElement => (\n <section aria-labelledby=\"portfolio-title\" className={styles.root}>\n <header className={styles.hero}>\n <div className={styles.heroCopy}>\n <Text as=\"h1\" className={styles.title} id=\"portfolio-title\" tabIndex={-1} variant=\"verdict\">\n Every release. One view.\n </Text>\n <Text className={styles.lede} tone=\"secondary\" variant=\"body-large\">\n One factual view of releases, people, source health, and every handoff still to prove.\n </Text>\n </div>\n <div className={styles.session}>\n {state._tag === \"session\" && state.reason === \"storage-unavailable\" ? null : (\n <BrowserSessionStatus anonymousAction=\"status\" />\n )}\n {state._tag === \"ready\" ? (\n <>\n <PortfolioLiveStatus connection={state.connection} isSnapshotStale={state.isSnapshotStale} />\n <Text as=\"time\" dateTime={state.portfolio.generatedAt} tone=\"tertiary\" variant=\"meta\">\n Snapshot {state.portfolio.generatedTime}\n </Text>\n </>\n ) : null}\n </div>\n </header>\n\n <div className={styles.content}>\n {state._tag === \"session\" ? <SessionBoundary {...state} /> : null}\n {state._tag === \"loading\" ? <LoadingPortfolio /> : null}\n {state._tag === \"failed\" ? <FailedPortfolio failure={state.failure} onRetry={onRetry} /> : null}\n {state._tag === \"ready\" ? (\n <ReadyPortfolio\n onPreviewRelease={onPreviewRelease}\n portfolio={state.portfolio}\n {...(previewPathForRelease === undefined ? {} : { previewPathForRelease })}\n />\n ) : null}\n </div>\n </section>\n)\n\nconst overviewState = (loadState: PortfolioSnapshotLoadState): PortfolioOverviewState => {\n switch (loadState._tag) {\n case \"idle\":\n return { _tag: \"session\", reason: \"anonymous\" }\n case \"loading\":\n return { _tag: \"loading\" }\n case \"failed\":\n return { _tag: \"failed\", failure: loadState.failure }\n case \"loaded\":\n return {\n _tag: \"ready\",\n connection: loadState.connection,\n isSnapshotStale: loadState.isSnapshotStale,\n portfolio: presentPortfolio(loadState.snapshot)\n }\n }\n}\n\n/** Prevent a prior browser session's snapshot from crossing an authentication transition. */\nexport const selectPortfolioOverviewState = (\n loadState: PortfolioSnapshotLoadState,\n sessionKey: string | null,\n sessionReason: Extract<PortfolioOverviewState, { readonly _tag: \"session\" }>[\"reason\"] = \"anonymous\"\n): PortfolioOverviewState => {\n if (sessionKey === null) return { _tag: \"session\", reason: sessionReason }\n if (loadState._tag === \"idle\" || loadState.sessionKey !== sessionKey) return { _tag: \"loading\" }\n return overviewState(loadState)\n}\n\n/** Read the authenticated live portfolio through one shared route-level controller. */\nexport const usePortfolioOverviewController = (): PortfolioOverviewController => {\n const { invalidateSession, state: browserSession } = useBrowserSession()\n const readableSession =\n browserSession._tag === \"authenticated\"\n ? browserSession.session\n : browserSession._tag === \"storage-unavailable\"\n ? browserSession.session\n : null\n const controller = usePortfolioSnapshot(readableSession?.sessionId ?? null, invalidateSession)\n return {\n onRetry: controller.retry,\n state: selectPortfolioOverviewState(\n controller.state,\n readableSession?.sessionId ?? null,\n browserSession._tag === \"authenticated\" ? \"checking\" : browserSession._tag\n )\n }\n}\n\n/** Load and present the authenticated server portfolio at the root application route. */\nexport const PortfolioOverview = (): ReactElement => {\n const controller = usePortfolioOverviewController()\n const { state } = controller\n const workspaceId = state._tag === \"ready\" ? state.portfolio.workspaceId : null\n const defaultLandingPath = useWorkspaceDefaultLandingPath(workspaceId)\n if (state._tag === \"ready\" && defaultLandingPath !== null) {\n return <Navigate replace to={defaultLandingPath} />\n }\n return <PortfolioOverviewView onPreviewRelease={() => undefined} onRetry={controller.onRetry} state={state} />\n}\n"],"x_google_ignoreList":[0,1],"mappings":"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"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ReviewSuggestionPublicationSurface-DHI3AT1u.js","assets/rolldown-runtime-QTnfLwEv.js","assets/react-CZI7_Jkm.js","assets/jsx-runtime-By8HlURe.js","assets/Dialog-xSrBk0Vv-ClGyDPlc.js","assets/react-dom-cJyBB_A4.js","assets/PortalProvider-BpgZwSpw-aHWGwW1o.js","assets/component-BJeeRuSu-Bu7KhcFC.js","assets/primitives-nKxQGSsE-CJNmac__.js","assets/WorkspacePullRequestDetails.module-CCFLGO4V.js","assets/WorkspacePullRequestDetails-DrPltvYZ.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{t}from"./react-CZI7_Jkm.js";import{t as n}from"./preload-helper-Czpn1I53.js";import{t as r}from"./jsx-runtime-By8HlURe.js";import{s as i,t as a}from"./Dialog-xSrBk0Vv-ClGyDPlc.js";import{r as o}from"./primitives-nKxQGSsE-CJNmac__.js";import{Ai as s,Di as c,Qr as l,Yn as u,Zr as d,ca as f,dr as p,f as m,fr as h,hr as g,m as _,n as v,p as y,yi as b,za as x}from"./agent-api-QVqt4a0O.js";import{a as S,t as C}from"./client-D27unen8.js";import{t as w}from"./authenticatedMutationClient-Ccwguc3i.js";import{t as T}from"./WorkspacePullRequestDetails.module-CCFLGO4V.js";var E=e(t(),1),D=r(),O=e=>{switch(e.anchor._tag){case`line`:return`Line suggestion · ${e.anchor.path}:${String(e.anchor.line)}`;case`file`:return`File suggestion · ${e.anchor.path}:${String(e.anchor.line)}`;case`changes`:return`Whole-change suggestion`}},k=e=>{let t=[],n=[],r=``,i=0,a=0;for(let o of e.split(`
|
|
3
|
-
`)){let e=/^@@ -\d+(?:,(\d+))? \+\d+(?:,(\d+))? @@/u.exec(o);if(e!==null){let s=`⋯ ${r} · ${o}`;t.push(s),n.push(s),i=Number(e[1]??`1`),a=Number(e[2]??`1`);continue}if(i===0&&a===0){o.startsWith(`+++ `)&&(r=o.slice(4).replace(/^b\//u,``));continue}if(o!==`\`){if(o.startsWith(`-`)&&i>0){t.push(o.slice(1)),--i;continue}if(o.startsWith(`+`)&&a>0){n.push(o.slice(1)),--a;continue}if(o.startsWith(` `)&&i>0&&a>0){let e=o.slice(1);t.push(e),n.push(e),--i,--a;continue}}}return{before:t.join(`
|
|
4
|
-
`),after:n.join(`
|
|
5
|
-
`)}},A=e=>`${e.slice(0,1).toUpperCase()}${e.slice(1)}`,j=({canPublish:e,extraActions:t,isPreviewing:n,jobId:r,metadata:i,onPreviewPublication:s,publicationBlockedReason:c,suggestion:l})=>{let u=l.replacement===void 0?null:k(l.replacement.unifiedDiff);return(0,D.jsxs)(`article`,{className:T.suggestionCard,"data-severity":l.severity,children:[(0,D.jsxs)(`header`,{className:T.suggestionHeading,children:[(0,D.jsx)(`span`,{className:T.severity,children:l.severity}),(0,D.jsxs)(`span`,{children:[(0,D.jsx)(`small`,{children:O(l)}),(0,D.jsx)(`strong`,{children:l.title})]}),(0,D.jsxs)(`span`,{className:T.confidence,children:[A(l.state),` · `,l.confidence.level,` confidence`]})]}),i,(0,D.jsx)(o,{children:l.problem}),(0,D.jsxs)(`dl`,{className:T.suggestionDetails,children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`dt`,{children:`Impact`}),(0,D.jsx)(`dd`,{children:l.impact})]}),(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`dt`,{children:`Recommendation`}),(0,D.jsx)(`dd`,{children:l.recommendation})]})]}),(0,D.jsxs)(`details`,{children:[(0,D.jsx)(`summary`,{children:`Evidence and confidence`}),(0,D.jsxs)(`code`,{children:[l.evidence.path,`:`,String(l.evidence.startLine),l.evidence.endLine===l.evidence.startLine?``:`–${String(l.evidence.endLine)}`]}),(0,D.jsx)(`pre`,{children:l.evidence.excerpt}),(0,D.jsx)(o,{children:l.confidence.reason})]}),l.relatedLocations.length===0?null:(0,D.jsxs)(`section`,{"aria-label":`Related locations`,className:T.relatedLocations,children:[(0,D.jsx)(`strong`,{children:`Related locations`}),(0,D.jsx)(`ul`,{children:l.relatedLocations.map(e=>(0,D.jsxs)(`li`,{children:[(0,D.jsxs)(`code`,{children:[e.path,`:`,String(e.startLine),e.endLine===e.startLine?``:`–${String(e.endLine)}`]}),(0,D.jsx)(`span`,{children:e.label})]},`${e.path}:${String(e.startLine)}:${String(e.endLine)}`))})]}),u===null||l.replacement===void 0?null:(0,D.jsxs)(`section`,{"aria-label":`Suggested replacement`,className:T.replacementPreview,children:[(0,D.jsxs)(`header`,{children:[(0,D.jsx)(`strong`,{children:`Suggested replacement`}),(0,D.jsxs)(`span`,{children:[`Inert patch · `,l.replacement.reviewedHead.slice(0,12)]})]}),(0,D.jsx)(o,{children:l.replacement.explanation}),(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`figure`,{children:[(0,D.jsx)(`figcaption`,{children:`Before`}),(0,D.jsx)(`pre`,{children:u.before})]}),(0,D.jsxs)(`figure`,{children:[(0,D.jsx)(`figcaption`,{children:`After`}),(0,D.jsx)(`pre`,{children:u.after})]})]})]}),l.prevention===void 0?null:l.prevention.enforcement===`none`?(0,D.jsxs)(`details`,{className:T.preventionProposal,children:[(0,D.jsx)(`summary`,{children:`Prevention note · no stable guardrail`}),(0,D.jsxs)(o,{children:[l.prevention.summary,` · `,l.prevention.rationale]})]}):(0,D.jsxs)(`details`,{className:T.preventionProposal,children:[(0,D.jsx)(`summary`,{children:`Prevention proposal · separate review required`}),(0,D.jsxs)(o,{children:[l.prevention.summary,` · `,l.prevention.enforcement]}),(0,D.jsxs)(`dl`,{children:[(0,D.jsx)(`dt`,{children:`Recurring evidence`}),(0,D.jsx)(`dd`,{children:l.prevention.recurrenceEvidence}),(0,D.jsx)(`dt`,{children:`Existing rule or configuration`}),(0,D.jsx)(`dd`,{children:l.prevention.existingRuleOrConfig}),(0,D.jsx)(`dt`,{children:`Target file`}),(0,D.jsx)(`dd`,{children:l.prevention.targetFile}),(0,D.jsx)(`dt`,{children:`Source paths`}),(0,D.jsx)(`dd`,{children:l.prevention.sourcePaths.join(`, `)}),(0,D.jsx)(`dt`,{children:`Matcher or invariant`}),(0,D.jsx)(`dd`,{children:l.prevention.matcherOrInvariant}),(0,D.jsx)(`dt`,{children:`Invalid fixture`}),(0,D.jsx)(`dd`,{children:(0,D.jsx)(`pre`,{children:l.prevention.invalidFixture})}),(0,D.jsx)(`dt`,{children:`Valid fixture`}),(0,D.jsx)(`dd`,{children:(0,D.jsx)(`pre`,{children:l.prevention.validFixture})}),(0,D.jsx)(`dt`,{children:`Boundary and exclusions`}),(0,D.jsx)(`dd`,{children:l.prevention.boundary})]})]}),t===void 0&&(!e||l.state!==`draft`)?null:(0,D.jsxs)(`div`,{className:T.suggestionActions,children:[t,e&&l.state===`draft`?(0,D.jsx)(a,{disabled:n||c!==void 0,onClick:()=>s({jobId:r,suggestionId:l.suggestionId}),children:n?`Preparing approval…`:`Review & approve`}):null]}),c===void 0?null:(0,D.jsx)(o,{role:`status`,tone:`secondary`,variant:`meta`,children:c})]})},M=({notes:e})=>e.length===0?null:(0,D.jsxs)(`section`,{"aria-labelledby":`review-notes-title`,className:T.reviewNotes,children:[(0,D.jsxs)(`header`,{children:[(0,D.jsxs)(`span`,{children:[(0,D.jsx)(`small`,{children:`Never publishable`}),(0,D.jsx)(`strong`,{id:`review-notes-title`,children:`Review Notes`})]}),(0,D.jsx)(`span`,{children:e.length})]}),(0,D.jsx)(`ul`,{children:e.map(e=>(0,D.jsxs)(`li`,{children:[(0,D.jsxs)(`span`,{children:[e.reason===`pre-existing`?`Pre-existing`:`Low confidence`,` · `,e.confidence.level]}),(0,D.jsx)(`strong`,{children:e.title}),(0,D.jsx)(o,{children:e.observation}),e.location===void 0?null:(0,D.jsxs)(`code`,{children:[e.location.path,`:`,String(e.location.startLine),e.location.endLine===e.location.startLine?``:`–${String(e.location.endLine)}`]}),(0,D.jsx)(`small`,{children:e.confidence.reason})]},e.noteId))})]}),N=e=>e.author._tag===`operator`?`Operator`:`${e.author.providerId}${e.author.model===null?``:` · ${e.author.model}`}`,P=e=>e.validation._tag===`validated`?`Validated`:`Needs revalidation`,F=({loadEarlier:e,loadingEarlier:t,page:n})=>{let r=[n.current,...n.revisions.filter(({revisionId:e})=>e!==n.current.revisionId)];return(0,D.jsxs)(`div`,{className:T.revisionHistory,children:[(0,D.jsx)(`ol`,{children:r.map(e=>(0,D.jsxs)(`li`,{children:[(0,D.jsxs)(`header`,{children:[(0,D.jsxs)(`strong`,{children:[`Revision `,String(e.sequence)]}),(0,D.jsxs)(`span`,{children:[P(e),` · `,N(e)]})]}),(0,D.jsx)(`time`,{dateTime:d(e.createdAt),children:l(e.createdAt,{dateStyle:`medium`,timeStyle:`short`})}),(0,D.jsxs)(`details`,{children:[(0,D.jsx)(`summary`,{children:e.suggestion.title}),(0,D.jsx)(o,{children:e.suggestion.problem}),(0,D.jsxs)(`dl`,{children:[(0,D.jsx)(`dt`,{children:`Impact`}),(0,D.jsx)(`dd`,{children:e.suggestion.impact}),(0,D.jsx)(`dt`,{children:`Recommendation`}),(0,D.jsx)(`dd`,{children:e.suggestion.recommendation}),(0,D.jsx)(`dt`,{children:`Severity`}),(0,D.jsx)(`dd`,{children:e.suggestion.severity}),(0,D.jsx)(`dt`,{children:`Confidence`}),(0,D.jsxs)(`dd`,{children:[e.suggestion.confidence.level,` · `,e.suggestion.confidence.reason]}),(0,D.jsx)(`dt`,{children:`Evidence`}),(0,D.jsxs)(`dd`,{children:[(0,D.jsxs)(`code`,{children:[e.suggestion.evidence.path,`:`,String(e.suggestion.evidence.startLine)]}),(0,D.jsx)(`pre`,{children:e.suggestion.evidence.excerpt})]}),(0,D.jsx)(`dt`,{children:`Anchor`}),(0,D.jsx)(`dd`,{children:(0,D.jsx)(`code`,{children:JSON.stringify(e.suggestion.anchor)})}),(0,D.jsx)(`dt`,{children:`Related locations`}),(0,D.jsx)(`dd`,{children:e.suggestion.relatedLocations.length===0?`None`:(0,D.jsx)(`pre`,{children:JSON.stringify(e.suggestion.relatedLocations,null,2)})}),(0,D.jsx)(`dt`,{children:`Replacement`}),(0,D.jsx)(`dd`,{children:e.suggestion.replacement===void 0?`None`:(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(o,{children:e.suggestion.replacement.explanation}),(0,D.jsx)(`pre`,{children:e.suggestion.replacement.unifiedDiff})]})}),(0,D.jsx)(`dt`,{children:`Prevention`}),(0,D.jsx)(`dd`,{children:e.suggestion.prevention===void 0?`None`:(0,D.jsx)(`pre`,{children:JSON.stringify(e.suggestion.prevention,null,2)})})]})]})]},e.revisionId))}),n.hasMore?(0,D.jsx)(a,{"aria-busy":t,disabled:t,loading:t,onClick:e,children:t?`Loading earlier revisions…`:`Load earlier revisions`}):null]})},I=g(u({anchor:_.fields.anchor,evidence:_.fields.evidence,relatedLocations:_.fields.relatedLocations,replacement:_.fields.replacement,prevention:_.fields.prevention})),L=[[`Problem`,`problem`],[`Impact`,`impact`],[`Recommendation`,`recommendation`]],R=e=>({title:e.title,severity:e.severity,problem:e.problem,impact:e.impact,evidence:e.evidence,recommendation:e.recommendation,confidence:e.confidence,relatedLocations:e.relatedLocations,...e.prevention===void 0?{}:{prevention:e.prevention},...e.replacement===void 0?{}:{replacement:e.replacement},anchor:e.anchor}),z=e=>h(I)({anchor:e.anchor,evidence:e.evidence,relatedLocations:e.relatedLocations,...e.prevention===void 0?{}:{prevention:e.prevention},...e.replacement===void 0?{}:{replacement:e.replacement}}),B=({canEdit:e,conflict:t,loadEarlier:n,loadingEarlier:r,mode:s,onOpenChange:c,onResolveConflict:l,onSave:u,open:d,page:h,preservedDraft:g,saving:v})=>{let y=h.current,[b,x]=(0,E.useState)(()=>R(y.suggestion)),[S,C]=(0,E.useState)(()=>z(y.suggestion)),[w,O]=(0,E.useState)(!1);(0,E.useEffect)(()=>{if(!d)return;let e=g??R(y.suggestion);x(e),C(z(e)),O(!1)},[y.revisionId,y.suggestion,d,g]);let k=(0,E.useMemo)(()=>`Revision ${String(y.sequence)} · ${P(y)} · ${N(y)}`,[y]),A=()=>{let e=p(I)(S);if(f(e)){O(!0);return}O(!1);let t=p(m)({title:b.title,severity:b.severity,problem:b.problem,impact:b.impact,recommendation:b.recommendation,confidence:b.confidence,...e.success});if(f(t)){O(!0);return}u(t.success)};return(0,D.jsx)(i.Root,{onOpenChange:c,open:d,children:(0,D.jsx)(i.Content,{className:T.revisionDialog,description:k,size:`wide`,title:s===`edit`?`Edit review suggestion`:`Revision history`,children:s===`history`?(0,D.jsx)(F,{loadEarlier:n,loadingEarlier:r,page:h}):(0,D.jsxs)(`form`,{className:T.revisionEditor,onSubmit:e=>{e.preventDefault(),A()},children:[(0,D.jsxs)(`div`,{className:T.revisionEditorLead,children:[(0,D.jsxs)(`label`,{children:[(0,D.jsx)(`span`,{children:`Title`}),(0,D.jsx)(`input`,{maxLength:500,onChange:e=>x({...b,title:e.currentTarget.value}),required:!0,value:b.title})]}),(0,D.jsxs)(`label`,{children:[(0,D.jsx)(`span`,{children:`Severity`}),(0,D.jsxs)(`select`,{onChange:e=>{let t=p(_.fields.severity)(e.currentTarget.value);f(t)||x({...b,severity:t.success})},value:b.severity,children:[(0,D.jsx)(`option`,{value:`P1`,children:`P1`}),(0,D.jsx)(`option`,{value:`P2`,children:`P2`}),(0,D.jsx)(`option`,{value:`P3`,children:`P3`}),(0,D.jsx)(`option`,{value:`P4`,children:`P4`})]})]}),(0,D.jsxs)(`label`,{children:[(0,D.jsx)(`span`,{children:`Confidence`}),(0,D.jsxs)(`select`,{onChange:e=>{let t=p(_.fields.confidence.fields.level)(e.currentTarget.value);f(t)||x({...b,confidence:{...b.confidence,level:t.success}})},value:b.confidence.level,children:[(0,D.jsx)(`option`,{value:`high`,children:`High`}),(0,D.jsx)(`option`,{value:`medium`,children:`Medium`})]})]})]}),L.map(([e,t])=>(0,D.jsxs)(`label`,{children:[(0,D.jsx)(`span`,{children:e}),(0,D.jsx)(`textarea`,{maxLength:4e3,onChange:e=>x({...b,[t]:e.currentTarget.value}),required:!0,rows:4,value:b[t]})]},t)),(0,D.jsxs)(`label`,{children:[(0,D.jsx)(`span`,{children:`Confidence reason`}),(0,D.jsx)(`textarea`,{maxLength:2e3,onChange:e=>x({...b,confidence:{...b.confidence,reason:e.currentTarget.value}}),required:!0,rows:3,value:b.confidence.reason})]}),(0,D.jsxs)(`details`,{className:T.revisionAdvanced,children:[(0,D.jsx)(`summary`,{children:`Advanced evidence, anchor, replacement and prevention`}),(0,D.jsx)(o,{tone:`secondary`,children:`Complete schema-checked JSON. Invalid or incoherent evidence cannot be saved.`}),(0,D.jsx)(`textarea`,{"aria-describedby":w?`revision-advanced-error`:void 0,"aria-invalid":w,"aria-label":`Advanced evidence, anchor, replacement and prevention JSON`,onChange:e=>C(e.currentTarget.value),rows:14,spellCheck:!1,value:S}),w?(0,D.jsx)(`span`,{id:`revision-advanced-error`,role:`alert`,children:`Advanced fields are not a valid complete suggestion.`}):null]}),t?(0,D.jsxs)(`div`,{role:`alert`,children:[(0,D.jsx)(`span`,{children:`A newer revision won. Your draft is preserved, but cannot be saved over the winner.`}),(0,D.jsx)(a,{onClick:l,type:`button`,variant:`quiet`,children:`Use latest revision`})]}):y.validation._tag===`requires-revalidation`?(0,D.jsx)(`span`,{role:`status`,children:`Technical changes remain blocked from publication until revalidated.`}):null,(0,D.jsxs)(`div`,{className:T.revisionDialogActions,children:[(0,D.jsx)(i.Close,{disabled:v,children:`Cancel`}),(0,D.jsx)(a,{disabled:!e||v,loading:v,type:`submit`,children:v?`Saving revision…`:`Save revision`})]})]})})})},V=y.make(24),H={dismiss:(e,t,n)=>s(b(function*(){return yield*(yield*w).agent.dismissReviewSuggestion({params:{entityId:e.entityId,jobId:e.jobId,suggestionId:e.suggestionId},payload:t})}).pipe(c(S)),{signal:n}),edit:(e,t,n)=>s(b(function*(){return yield*(yield*w).agent.editReviewSuggestion({params:{entityId:e.entityId,jobId:e.jobId,suggestionId:e.suggestionId},payload:t})}).pipe(c(S)),{signal:n}),load:(e,t,n)=>s(b(function*(){return yield*(yield*C()).agent.reviewSuggestionRevisions({params:{entityId:e.entityId,jobId:e.jobId,suggestionId:e.suggestionId},query:{...t===null?{}:{before:t},limit:V}})}).pipe(c(S)),{signal:n})},U=(e,t)=>e.entityId===t.entityId&&e.jobId===t.jobId&&e.sessionKey===t.sessionKey&&e.suggestionId===t.suggestionId,W=(e,t)=>{let n=t.current.sequence>e.current.sequence?t.current:e.current;return{current:n,revisions:[...new Map([e.current,t.current,...e.revisions,...t.revisions].filter(({revisionId:e})=>e!==n.revisionId).map(e=>[e.revisionId,e])).values()].sort((e,t)=>t.sequence-e.sequence),hasMore:t.hasMore,nextBeforeSequence:t.nextBeforeSequence}},G=(e,t)=>({current:t,revisions:[e.current,...e.revisions].filter(({revisionId:e})=>e!==t.revisionId).sort((e,t)=>t.sequence-e.sequence),hasMore:e.hasMore,nextBeforeSequence:e.nextBeforeSequence}),K=(e,t)=>({_tag:e,page:t}),q=x(`ConflictApiError`),J=e=>void 0,Y=(e,t=H,n=J)=>{let[r,i]=(0,E.useState)(0),[a,o]=(0,E.useState)(!1),[s,c]=(0,E.useState)({_tag:`idle`}),l=(0,E.useRef)(null),u=(0,E.useRef)(!1),d=(0,E.useRef)(e),f=(0,E.useRef)(n);d.current=e,f.current=n,(0,E.useEffect)(()=>{if(l.current?.abort(),u.current=!1,o(!1),e===null){c({_tag:`idle`});return}let n=e,r=new AbortController;return l.current=r,c({_tag:`loading`}),t.load(n,null,r.signal).then(e=>{r.signal.aborted||d.current===null||!U(d.current,n)||c({_tag:`ready`,page:e})},()=>{r.signal.aborted||d.current===null||!U(d.current,n)||c({_tag:`failed`,draft:null,page:null})}),()=>r.abort()},[r,e,t]);let p=(0,E.useCallback)(n=>{if(e===null||s._tag===`conflict`)return;let r=s._tag===`ready`||s._tag===`failed`?s.page:null;if(r===null)return;let i=e;l.current?.abort(),u.current=!1,o(!1);let a=new AbortController;l.current=a,c({_tag:`saving`,draft:n,page:r}),t.edit(i,{expectedRevisionId:r.current.revisionId,expectedSequence:r.current.sequence,edit:n},a.signal).then(e=>{let n=G(r,e);return t.load(i,null,a.signal).then(e=>K(`refreshed`,e),()=>K(`accepted-refresh-failed`,n))},e=>{if(!q(e))throw e;return t.load(i,null,a.signal).then(e=>(a.signal.aborted||d.current===null||!U(d.current,i)||c({_tag:`conflict`,draft:n,page:e}),K(`conflict`,e)))}).then(e=>{a.signal.aborted||d.current===null||!U(d.current,i)||(c(t=>t._tag===`conflict`?t:e._tag===`accepted-refresh-failed`?{_tag:`failed`,draft:null,page:e.page}:{_tag:`ready`,page:e.page}),e._tag!==`conflict`&&f.current(e.page.current.suggestion))},()=>{a.signal.aborted||d.current===null||!U(d.current,i)||c({_tag:`failed`,draft:n,page:r})})},[e,s,t]),m=(0,E.useCallback)(()=>{if(e===null||s._tag!==`ready`||t.dismiss===void 0)return;let n=e,r=s.page;l.current?.abort(),u.current=!1,o(!1);let i=new AbortController;l.current=i,c({_tag:`dismissing`,page:r}),t.dismiss(n,{expectedRevisionId:r.current.revisionId,expectedSequence:r.current.sequence},i.signal).then(e=>{i.signal.aborted||d.current===null||!U(d.current,n)||(c({_tag:`ready`,page:G(r,e)}),f.current(e.suggestion))},()=>{i.signal.aborted||d.current===null||!U(d.current,n)||c({_tag:`failed`,draft:null,page:r})})},[e,s,t]),h=(0,E.useCallback)(()=>{if(e===null||s._tag!==`ready`&&s._tag!==`conflict`||u.current||!s.page.hasMore||s.page.nextBeforeSequence===null)return;let n=e,r=s.page;l.current?.abort();let i=new AbortController;l.current=i,u.current=!0,o(!0),t.load(n,r.nextBeforeSequence,i.signal).then(e=>{i.signal.aborted||d.current===null||!U(d.current,n)||l.current===i&&(c(t=>t._tag===`ready`||t._tag===`conflict`?{...t,page:W(t.page,e)}:t),u.current=!1,o(!1))},()=>{i.signal.aborted||d.current===null||!U(d.current,n)||l.current===i&&(c(e=>e._tag===`ready`?{_tag:`failed`,draft:null,page:e.page}:e),u.current=!1,o(!1))})},[e,s,t]);return(0,E.useMemo)(()=>({dismiss:m,loadEarlier:h,loadingEarlier:a,resolveConflict:()=>c(e=>e._tag===`conflict`?{_tag:`ready`,page:e.page}:e),retry:()=>{if(s._tag!==`conflict`){if(s._tag===`failed`&&s.draft!==null&&s.page!==null){p(s.draft);return}i(e=>e+1)}},save:p,state:s}),[m,h,a,p,s])},ee=e=>e._tag===`operator`?`Operator`:e.providerId,te=({canEdit:e,entityId:t,isPreviewing:n,jobId:r,onPreviewPublication:s,onSuggestionRevisionAccepted:c,revisionTransport:u=H,sessionKey:f,suggestion:p})=>{let m=Y((0,E.useMemo)(()=>({entityId:t,jobId:r,sessionKey:f,suggestionId:p.suggestionId}),[t,r,f,p.suggestionId]),u,c),[h,g]=(0,E.useState)(`history`),[_,v]=(0,E.useState)(!1),[y,b]=(0,E.useState)(!1),x=m.state._tag===`ready`||m.state._tag===`dismissing`||m.state._tag===`saving`||m.state._tag===`conflict`||m.state._tag===`failed`?m.state.page:null,S=m.state._tag===`saving`||m.state._tag===`conflict`||m.state._tag===`failed`?m.state.draft:null,C=x?.current,w=C===void 0?p:{...C.suggestion,state:p.state===`published`?`published`:C.suggestion.state},O=e&&w.state===`draft`&&m.state._tag!==`dismissing`,k=C?.validation._tag===`requires-revalidation`,A=m.state._tag===`loading`?`Loading the exact revision before publication.`:m.state._tag===`failed`?`Revision history is unavailable. Retry before publishing.`:k?`This technical edit needs agent revalidation before it can be posted.`:void 0,M=e=>{g(e),v(!0)};return(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(j,{canPublish:O,extraActions:(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(a,{disabled:x===null,onClick:()=>M(`history`),variant:`quiet`,children:`History`}),O?(0,D.jsx)(a,{disabled:x===null,onClick:()=>M(`edit`),variant:`quiet`,children:`Edit`}):null,O?(0,D.jsx)(a,{disabled:x===null,onClick:()=>b(!0),variant:`quiet`,children:`Dismiss`}):null,m.state._tag===`dismissing`?(0,D.jsx)(a,{disabled:!0,variant:`quiet`,children:`Dismissing…`}):null,m.state._tag===`failed`?(0,D.jsx)(a,{onClick:m.retry,variant:`quiet`,children:`Retry revision`}):null]}),isPreviewing:n,jobId:r,metadata:C===void 0?null:(0,D.jsxs)(`div`,{className:T.suggestionRevisionMeta,"data-validation":C.validation._tag,children:[(0,D.jsxs)(`strong`,{children:[`Revision `,String(C.sequence)]}),(0,D.jsx)(`span`,{children:C.validation._tag===`validated`?`Validated`:`Needs revalidation`}),(0,D.jsx)(`span`,{children:ee(C.author)}),(0,D.jsx)(`time`,{dateTime:d(C.createdAt),children:l(C.createdAt,{dateStyle:`medium`,timeStyle:`short`})})]}),onPreviewPublication:e=>{C!==void 0&&s({...e,revisionId:C.revisionId})},...A===void 0?{}:{publicationBlockedReason:A},suggestion:w}),x===null?null:(0,D.jsx)(B,{canEdit:O,conflict:m.state._tag===`conflict`,loadEarlier:m.loadEarlier,loadingEarlier:m.loadingEarlier,mode:h,onOpenChange:v,onResolveConflict:m.resolveConflict,onSave:m.save,open:_,page:x,preservedDraft:S,saving:m.state._tag===`saving`}),(0,D.jsx)(i.Root,{onOpenChange:b,open:y,children:(0,D.jsxs)(i.Content,{description:`Dismiss this finding for the reviewed head. It will remain in revision history and will not be posted to CodeCommit.`,size:`default`,title:`Dismiss finding?`,children:[(0,D.jsx)(o,{children:`This records your decision without changing the pull request or publishing a comment.`}),(0,D.jsxs)(`div`,{className:T.publicationActions,children:[(0,D.jsx)(i.Close,{children:`Keep finding`}),(0,D.jsx)(a,{onClick:()=>{b(!1),m.dismiss()},children:`Dismiss finding`})]})]})})]})},ne=e=>{switch(e){case`not-codecommit`:case`not-pull-request`:return`Agent review is available only for synchronized CodeCommit pull requests.`;case`source-stale`:return`Synchronize this pull request before reviewing its immutable head.`;case`release-unavailable`:return`Connect this pull request to a release before asking Relay to review it.`;case`base-revision-unavailable`:return`The base revision has not been synchronized, so an exact review cannot start.`}},re=e=>{switch(e){case`changes-required`:return`Changes Required`;case`non-blocking-suggestions`:return`Non-blocking Suggestions`;case`no-issues-found`:return`No Issues Found`;case`unable-to-conclude`:return`Unable to Conclude`}},X=e=>{let t=Math.round(e/6e4);return`${String(t)} minute${t===1?``:`s`}`},Z=e=>e.displayName??e.providerId,Q=e=>`${Z(e)} review`,ie=[{label:`Correctness`,prompt:`Review correctness, regressions, error handling, and boundary conditions.`},{label:`Security`,prompt:`Review authorization, credential handling, unsafe input, and privilege boundaries.`},{label:`Tests`,prompt:`Review test coverage, failure paths, race conditions, and missing regression guardrails.`}],ae=(0,E.lazy)(()=>n(()=>import(`./ReviewSuggestionPublicationSurface-DHI3AT1u.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10]))),oe=e=>{switch(e._tag){case`operator-message`:return`Local Operator · ${e.prompt}`;case`run-queued`:return`${e.reviewProfile.label} · head ${e.subject.headRevision.slice(0,12)}`;case`run-started`:return e.runtimeMetadata===void 0?`Review sandbox started`:`Review sandbox started · ${e.runtimeMetadata.implementation} ${e.runtimeMetadata.version??``}`.trim();case`progress`:return e.text;case`review-report`:return`${String(e.report.suggestions.length)} suggestions · ${String(e.report.notes.length)} notes`;case`suggestion-revised`:return e.suggestionState===`dismissed`?`Suggestion revision ${String(e.sequence)} · dismissed by operator`:`Suggestion revision ${String(e.sequence)} · ${e.validationState===`validated`?`validated`:`needs revalidation`}`;case`suggestion-published`:return`Suggestion published to CodeCommit`;case`run-completed`:return`Run completed · ${e.outcome}`;case`run-failed`:return e.retryable?`Run failed · retryable`:`Run failed`;case`cancellation-requested`:return`Cancellation requested`;case`usage`:return null}},$=({canEnqueue:e,onCancelPublication:t,onLoadEarlier:n=()=>void 0,onPreviewPublication:r,onPublishSuggestion:s,onRetry:c,onStart:l,onSuggestionRevisionAccepted:u,publication:d,revisionTransport:f,state:p,suggestions:m})=>{let[h,g]=(0,E.useState)(!1),[_,y]=(0,E.useState)(``),[b,x]=(0,E.useState)(null),[S,C]=(0,E.useState)(null),w=(0,E.useMemo)(()=>p._tag===`ready`?p.providerPresets??(p.provider===null?[]:[p.provider]):[],[p]),O=w.find(({providerId:e})=>e===S)??w[0]??null;(0,E.useEffect)(()=>{g(!1),y(``),x(null),C(null)},[p._tag===`idle`?null:`${p.entityId}:${p.baseRevision??``}:${p.headRevision}:${p.sessionKey}`]),(0,E.useEffect)(()=>{if(w.length===0){C(null);return}w.some(({providerId:e})=>e===S)||C(w[0]?.providerId??null)},[w,S]),(0,E.useEffect)(()=>{b===null||p._tag!==`ready`||p.action!==`failed`&&p.action===`idle`&&p.review._tag===`pending`&&(y(e=>e.trim()===b?``:e),x(null))},[p,b]);let k=(0,E.useCallback)(e=>{g(e)},[]),A=(0,E.useCallback)(()=>{O!==null&&(x(null),l(void 0,O.providerId))},[l,O]),j=(0,E.useCallback)(()=>{let e=_.trim();e.length===0||p._tag!==`ready`||p.action===`starting`||(x(e),O!==null&&l(e,O.providerId))},[l,_,O,p]),N=e=>{e.key!==`Enter`||!e.metaKey&&!e.ctrlKey||(e.preventDefault(),j())},P=d._tag===`idle`||d._tag===`previewing`?null:(0,D.jsx)(E.Suspense,{fallback:(0,D.jsx)(`span`,{children:`Preparing publication surface…`}),children:(0,D.jsx)(ae,{onCancel:t,onPublish:s,publication:d})}),F=e=>(0,D.jsxs)(D.Fragment,{children:[e,P]});if(p._tag===`idle`||p._tag===`loading`)return F((0,D.jsxs)(`div`,{"aria-live":`polite`,className:T.reviewStatus,role:`status`,children:[(0,D.jsx)(`strong`,{children:`Loading review state`}),(0,D.jsx)(`span`,{children:`Checking durable review history for this exact head.`}),(0,D.jsx)(`span`,{"aria-hidden":`true`,className:T.reviewRunway})]}));if(p._tag===`failed`)return F((0,D.jsxs)(`div`,{className:T.reviewStatus,children:[(0,D.jsx)(`strong`,{children:`Review state unavailable`}),(0,D.jsx)(`span`,{children:`The current review could not be loaded. No human decision was changed.`}),(0,D.jsx)(a,{onClick:c,children:`Retry`})]}));let I=p.review,L=p.thread?.events??[],R=L.map(e=>({event:e,summary:oe(e)})).filter(e=>e.summary!==null),z=p.thread!==void 0&&(p.thread.historyLoaded||!p.thread.hasEarlier)?R:R.slice(-12),B=(0,D.jsxs)(`section`,{"aria-label":`Review thread`,className:T.reviewThread,children:[(0,D.jsxs)(`header`,{children:[(0,D.jsx)(`strong`,{children:`Review thread`}),(0,D.jsx)(`span`,{children:L.length===0?`No runs yet`:`Durable across pull-request heads`})]}),z.length===0?null:(0,D.jsx)(`ol`,{className:T.reviewThreadEvents,children:z.map(({event:e,summary:t})=>(0,D.jsx)(`li`,{children:(0,D.jsx)(`span`,{children:t})},e.eventSequence))}),p.thread?.hasEarlier?(0,D.jsx)(a,{loading:p.historyAction===`loading`,onClick:n,children:p.historyAction===`loading`?`Loading earlier activity…`:p.historyAction===`failed`?`Retry earlier activity`:`Load earlier activity`}):p.thread===void 0?null:(0,D.jsx)(o,{tone:`secondary`,variant:`meta`,children:`Beginning of review thread`}),e&&p.provider!==null&&I._tag!==`pending`&&I._tag!==`unavailable`?(0,D.jsxs)(`div`,{className:T.reviewThreadComposer,children:[(0,D.jsx)(`label`,{htmlFor:`review-thread-request`,children:`Ask Relay about this pull request`}),w.length>1?(0,D.jsx)(`div`,{"aria-label":`Targeted review agent presets`,className:T.reviewPresetList,role:`radiogroup`,children:w.map(e=>(0,D.jsxs)(`button`,{"aria-checked":e.providerId===O?.providerId,onClick:()=>C(e.providerId),role:`radio`,type:`button`,children:[(0,D.jsx)(`strong`,{children:Q(e)}),(0,D.jsx)(`span`,{children:e.model})]},e.providerId))}):O===null?null:(0,D.jsxs)(`span`,{className:T.reviewSelectedPreset,children:[`Review with `,Z(O),` · `,O.model]}),(0,D.jsx)(`div`,{"aria-label":`Review prompt templates`,className:T.reviewTemplateList,children:ie.map(e=>(0,D.jsx)(a,{onClick:()=>y(e.prompt),children:e.label},e.label))}),(0,D.jsx)(`textarea`,{"aria-describedby":`review-thread-request-help review-thread-request-count`,id:`review-thread-request`,maxLength:v,onChange:e=>y(e.currentTarget.value),onKeyDown:N,placeholder:`Re-check the error handling in the connection flow…`,rows:3,value:_}),(0,D.jsxs)(`div`,{className:T.reviewThreadComposerFooter,children:[(0,D.jsx)(`span`,{id:`review-thread-request-help`,children:`Ctrl/⌘ + Enter to run`}),(0,D.jsxs)(`span`,{id:`review-thread-request-count`,children:[String(_.length),` / `,String(v)]})]}),p.action===`failed`&&b!==null?(0,D.jsx)(`span`,{role:`alert`,children:`Targeted review did not start. Your request is still here—check the provider and worker, then try again.`}):null,(0,D.jsx)(a,{disabled:p.action===`starting`||_.trim().length===0,onClick:j,children:p.action===`starting`?`Starting targeted review…`:`Start targeted review`})]}):null]}),V=e=>F((0,D.jsxs)(D.Fragment,{children:[e,B]})),H=(e,t)=>O===null?null:(0,D.jsxs)(i.Root,{onOpenChange:k,open:h,children:[(0,D.jsx)(i.Trigger,{disabled:p.action===`starting`,children:p.action===`starting`?`Starting review…`:t}),(0,D.jsx)(i.Content,{className:T.reviewLaunchDialog,description:`Relay will inspect the immutable revision in an isolated sandbox. It cannot approve or change the pull request.`,title:`Review this exact head`,children:(0,D.jsxs)(`div`,{className:T.reviewLaunchBody,children:[(0,D.jsx)(`small`,{className:T.reviewLaunchEyebrow,children:`Read-only agent run`}),w.length>1?(0,D.jsx)(`div`,{"aria-label":`Review agent presets`,className:T.reviewPresetList,role:`radiogroup`,children:w.map(e=>(0,D.jsxs)(`button`,{"aria-checked":e.providerId===O.providerId,onClick:()=>C(e.providerId),role:`radio`,type:`button`,children:[(0,D.jsx)(`strong`,{children:Q(e)}),(0,D.jsx)(`span`,{children:e.model})]},e.providerId))}):null,(0,D.jsxs)(`dl`,{className:T.reviewLaunchFacts,children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`dt`,{children:`Exact head`}),(0,D.jsx)(`dd`,{children:(0,D.jsx)(`code`,{children:e})})]}),(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`dt`,{children:`Review profile`}),(0,D.jsx)(`dd`,{children:O.reviewProfile.label})]}),(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`dt`,{children:`Time budget`}),(0,D.jsx)(`dd`,{children:X(O.reviewProfile.budgetMillis)})]}),(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`dt`,{children:`Runtime`}),(0,D.jsx)(`dd`,{children:O.reviewProfile.networkAccess===`blocked`?`Network blocked · sbx`:`Provider connection enabled · sbx`})]})]}),(0,D.jsxs)(`div`,{className:T.reviewLaunchActions,children:[(0,D.jsx)(i.Close,{children:`Keep reading`}),(0,D.jsx)(i.Close,{onClick:A,children:`Start full review`})]})]})})]});if(I._tag===`unavailable`)return V((0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(`strong`,{children:`Review unavailable`}),(0,D.jsx)(`span`,{children:ne(I.reason)})]}));if(I._tag===`pending`){let e=I.state===`queued`?`Review queued`:I.state===`running`?`Reviewing exact head`:`Cancellation requested`;return V((0,D.jsxs)(`div`,{"aria-live":`polite`,className:T.reviewStatus,role:`status`,children:[(0,D.jsx)(`strong`,{children:e}),(0,D.jsxs)(`span`,{children:[`Relay is using `,I.providerId,` · `,I.model,`. This page updates automatically.`]}),(0,D.jsxs)(`span`,{children:[I.reviewProfile.label,` · `,X(I.reviewProfile.budgetMillis),` ·`,` `,I.reviewProfile.networkAccess===`blocked`?`network blocked · sbx`:`provider connection enabled · sbx`]}),I.activity.events.length===0?null:(0,D.jsx)(`ol`,{"aria-label":`Live review activity`,children:I.activity.events.map((e,t)=>(0,D.jsx)(`li`,{children:e},`${String(t)}:${e}`))}),I.activity.truncated?(0,D.jsx)(`span`,{children:`Earlier review activity is not shown.`}):null,(0,D.jsx)(`code`,{className:T.reviewHead,children:I.subject.headRevision}),(0,D.jsx)(`span`,{"aria-hidden":`true`,className:T.reviewRunway})]}))}return I._tag===`failed`?V((0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(`strong`,{children:I.state===`cancelled`?`Review cancelled`:`Review did not finish`}),(0,D.jsx)(`span`,{children:`The failed run did not change approval or publish a recommendation.`}),e&&p.provider!==null?(0,D.jsxs)(D.Fragment,{children:[p.action===`failed`&&b===null?(0,D.jsx)(`span`,{role:`alert`,children:`A new full review could not be started. Check the provider and worker, then try again.`}):null,H(I.subject.headRevision,`Try again`)]}):null]})):I._tag===`completed`?V((0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(`strong`,{children:re(I.outcome)}),I.report.completion.status===`unable-to-conclude`?(0,D.jsx)(o,{children:I.report.completion.reason}):null,(m??I.report.suggestions).length===0?(0,D.jsx)(`span`,{children:`No validated suggestions were retained for this exact head.`}):(0,D.jsx)(`ol`,{className:T.reviewFindings,children:(m??I.report.suggestions).map(t=>(0,D.jsx)(`li`,{children:(0,D.jsx)(te,{canEdit:e,entityId:p.entityId,isPreviewing:d._tag===`previewing`&&d.selection.suggestionId===t.suggestionId,jobId:I.jobId,onPreviewPublication:r,...u===void 0?{}:{onSuggestionRevisionAccepted:u},...f===void 0?{}:{revisionTransport:f},sessionKey:p.sessionKey,suggestion:t})},t.suggestionId))}),(0,D.jsx)(M,{notes:I.report.notes}),(0,D.jsx)(`span`,{children:`Agent advice only. Approve a finding to post it to CodeCommit, or dismiss it locally.`})]})):V((0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(`strong`,{children:`Agent review not run`}),(0,D.jsx)(`span`,{children:`An immutable-head review produces advice, never a human approval.`}),e?p.provider===null?(0,D.jsx)(`span`,{children:`Configure an sbx Review Agent Profile with an Effect AI provider to enable review.`}):(0,D.jsx)(D.Fragment,{children:H(I.subject.headRevision,`Review exact head`)}):(0,D.jsx)(`span`,{children:`Only a workspace owner can start a review.`}),p.action===`failed`?(0,D.jsx)(`span`,{role:`alert`,children:`The review could not be started. Check provider and worker configuration, then retry.`}):null]}))};export{$ as PullRequestReviewPanel,$ as default};
|
|
6
|
-
//# sourceMappingURL=PullRequestReviewPanel-CqPtjhVW.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"mappings":";qoBAOM,EAAe,GAA2C,CAC9D,OAAQ,EAAW,OAAO,KAA1B,CACE,IAAK,OACH,MAAO,qBAAqB,EAAW,OAAO,KAAK,GAAG,OAAO,EAAW,OAAO,IAAI,IACrF,IAAK,OACH,MAAO,qBAAqB,EAAW,OAAO,KAAK,GAAG,OAAO,EAAW,OAAO,IAAI,IACrF,IAAK,UACH,MAAO,yBACX,CACF,EAEM,EACJ,GAIG,CACH,IAAM,EAAS,CAAkB,EAC3B,EAAQ,CAAkB,EAC5B,EAAc,GACd,EAAoB,EACpB,EAAoB,EACxB,IAAK,IAAM,KAAQ,EAAY,MAAM;CAAI,EAAG,CAC1C,IAAM,EAAO,2CAA2C,KAAK,CAAI,EACjE,GAAI,IAAS,KAAM,CACjB,IAAM,EAAW,KAAK,EAAY,KAAK,IACvC,EAAO,KAAK,CAAQ,EACpB,EAAM,KAAK,CAAQ,EACnB,EAAoB,OAAO,EAAK,IAAM,GAAG,EACzC,EAAoB,OAAO,EAAK,IAAM,GAAG,EACzC,QACF,CACA,GAAI,IAAsB,GAAK,IAAsB,EAAG,CAClD,EAAK,WAAW,MAAM,IAAG,EAAc,EAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,QAAS,EAAE,GAC5E,QACF,CACI,OAAS,+BACb,IAAI,EAAK,WAAW,GAAG,GAAK,EAAoB,EAAG,CACjD,EAAO,KAAK,EAAK,MAAM,CAAC,CAAC,EACzB,IACA,QACF,CACA,GAAI,EAAK,WAAW,GAAG,GAAK,EAAoB,EAAG,CACjD,EAAM,KAAK,EAAK,MAAM,CAAC,CAAC,EACxB,IACA,QACF,CACA,GAAI,EAAK,WAAW,GAAG,GAAK,EAAoB,GAAK,EAAoB,EAAG,CAC1E,IAAM,EAAU,EAAK,MAAM,CAAC,EAC5B,EAAO,KAAK,CAAO,EACnB,EAAM,KAAK,CAAO,EAClB,IACA,IACA,QACF,CAbA,CAcF,CACA,MAAO,CACL,OAAQ,EAAO,KAAK;CAAI,EACxB,MAAO,EAAM,KAAK;CAAI,CACxB,CACF,EAEM,EAAwB,GAC5B,GAAG,EAAM,MAAM,EAAG,CAAC,CAAC,CAAC,YAAY,IAAI,EAAM,MAAM,CAAC,IAGvC,GAAwB,CACnC,aACA,eACA,eACA,QACA,WACA,uBACA,2BACA,gBAakB,CAClB,IAAM,EAAc,EAAW,cAAgB,OAAY,KAAO,EAAiB,EAAW,YAAY,WAAW,EAErH,OACE,UAAC,UAAD,CAAS,UAAW,EAAO,eAAgB,gBAAe,EAAW,kBAArE,EACE,UAAC,SAAD,CAAQ,UAAW,EAAO,2BAA1B,EACE,SAAC,OAAD,CAAM,UAAW,EAAO,kBAAW,EAAW,QAAe,IAC7D,UAAC,OAAD,YACE,SAAC,QAAD,UAAQ,EAAY,CAAU,CAAS,IACvC,SAAC,SAAD,UAAS,EAAW,KAAc,EAC9B,KACN,UAAC,OAAD,CAAM,UAAW,EAAO,oBAAxB,CACG,EAAqB,EAAW,KAAK,EAAE,MAAI,EAAW,WAAW,MAAM,aACpE,GACA,IACP,GAED,SAAC,EAAD,UAAO,EAAW,OAAc,IAChC,UAAC,KAAD,CAAI,UAAW,EAAO,2BAAtB,EACE,UAAC,MAAD,YACE,SAAC,KAAD,UAAI,QAAU,IACd,SAAC,KAAD,UAAK,EAAW,MAAW,EACxB,KACL,UAAC,MAAD,YACE,SAAC,KAAD,UAAI,gBAAkB,IACtB,SAAC,KAAD,UAAK,EAAW,cAAmB,EAChC,GACH,KACJ,UAAC,UAAD,YACE,SAAC,UAAD,UAAS,yBAAgC,IACzC,UAAC,OAAD,WACG,EAAW,SAAS,KAAK,IAAE,OAAO,EAAW,SAAS,SAAS,EAC/D,EAAW,SAAS,UAAY,EAAW,SAAS,UACjD,GACA,IAAI,OAAO,EAAW,SAAS,OAAO,GACtC,KACN,SAAC,MAAD,UAAM,EAAW,SAAS,OAAa,IACvC,SAAC,EAAD,UAAO,EAAW,WAAW,MAAa,EACnC,IAER,EAAW,iBAAiB,SAAW,EAAI,MAC1C,UAAC,UAAD,CAAS,aAAW,oBAAoB,UAAW,EAAO,0BAA1D,EACE,SAAC,SAAD,UAAQ,mBAAyB,IACjC,SAAC,KAAD,UACG,EAAW,iBAAiB,IAAK,IAChC,UAAC,KAAD,YACE,UAAC,OAAD,WACG,EAAS,KAAK,IAAE,OAAO,EAAS,SAAS,EACzC,EAAS,UAAY,EAAS,UAAY,GAAK,IAAI,OAAO,EAAS,OAAO,GACvE,KACN,SAAC,OAAD,UAAO,EAAS,KAAY,EAC1B,GANK,GAAG,EAAS,KAAK,GAAG,OAAO,EAAS,SAAS,EAAE,GAAG,OAAO,EAAS,OAAO,GAM9E,CACL,CACC,EACG,IAGV,IAAgB,MAAQ,EAAW,cAAgB,OAAY,MAC9D,UAAC,UAAD,CAAS,aAAW,wBAAwB,UAAW,EAAO,4BAA9D,EACE,UAAC,SAAD,YACE,SAAC,SAAD,UAAQ,uBAA6B,IACrC,UAAC,OAAD,WAAM,iBAAe,EAAW,YAAY,aAAa,MAAM,EAAG,EAAE,CAAQ,GACtE,KACR,SAAC,EAAD,UAAO,EAAW,YAAY,WAAkB,IAChD,UAAC,MAAD,YACE,UAAC,SAAD,YACE,SAAC,aAAD,UAAY,QAAkB,IAC9B,SAAC,MAAD,UAAM,EAAY,MAAY,EACxB,KACR,UAAC,SAAD,YACE,SAAC,aAAD,UAAY,OAAiB,IAC7B,SAAC,MAAD,UAAM,EAAY,KAAW,EACvB,GACL,GACE,IAGV,EAAW,aAAe,OAAY,KAAO,EAAW,WAAW,cAAgB,QAClF,UAAC,UAAD,CAAS,UAAW,EAAO,4BAA3B,EACE,SAAC,UAAD,UAAS,uCAA8C,IACvD,UAAC,EAAD,WACG,EAAW,WAAW,QAAQ,MAAI,EAAW,WAAW,SACrD,GACC,KAET,UAAC,UAAD,CAAS,UAAW,EAAO,4BAA3B,EACE,SAAC,UAAD,UAAS,gDAAuD,IAChE,UAAC,EAAD,WACG,EAAW,WAAW,QAAQ,MAAI,EAAW,WAAW,WACrD,KACN,UAAC,KAAD,YACE,SAAC,KAAD,UAAI,oBAAsB,IAC1B,SAAC,KAAD,UAAK,EAAW,WAAW,kBAAuB,IAClD,SAAC,KAAD,UAAI,gCAAkC,IACtC,SAAC,KAAD,UAAK,EAAW,WAAW,oBAAyB,IACpD,SAAC,KAAD,UAAI,aAAe,IACnB,SAAC,KAAD,UAAK,EAAW,WAAW,UAAe,IAC1C,SAAC,KAAD,UAAI,cAAgB,IACpB,SAAC,KAAD,UAAK,EAAW,WAAW,YAAY,KAAK,IAAI,CAAM,IACtD,SAAC,KAAD,UAAI,sBAAwB,IAC5B,SAAC,KAAD,UAAK,EAAW,WAAW,kBAAuB,IAClD,SAAC,KAAD,UAAI,iBAAmB,IACvB,SAAC,KAAD,WACE,SAAC,MAAD,UAAM,EAAW,WAAW,cAAoB,EAC9C,IACJ,SAAC,KAAD,UAAI,eAAiB,IACrB,SAAC,KAAD,WACE,SAAC,MAAD,UAAM,EAAW,WAAW,YAAkB,EAC5C,IACJ,SAAC,KAAD,UAAI,yBAA2B,IAC/B,SAAC,KAAD,UAAK,EAAW,WAAW,QAAa,EACtC,GACG,IAGV,IAAiB,SAAc,CAAC,GAAc,EAAW,QAAU,SAAW,MAC7E,UAAC,MAAD,CAAK,UAAW,EAAO,2BAAvB,CACG,EACA,GAAc,EAAW,QAAU,SAClC,SAAC,EAAD,CACE,SAAU,GAAgB,IAA6B,OACvD,YACE,EAAqB,CACnB,QACA,aAAc,EAAW,YAC3B,CAAC,WAGF,EAAe,sBAAwB,kBAClC,GACN,IACD,IAEN,IAA6B,OAAY,MACxC,SAAC,EAAD,CAAM,KAAK,SAAS,KAAK,YAAY,QAAQ,gBAC1C,CACG,EAED,GAEb,EAGa,GAAe,CAAE,WAC5B,EAAM,SAAW,EAAI,MACnB,UAAC,UAAD,CAAS,kBAAgB,qBAAqB,UAAW,EAAO,qBAAhE,EACE,UAAC,SAAD,YACE,UAAC,OAAD,YACE,SAAC,QAAD,UAAO,mBAAwB,IAC/B,SAAC,SAAD,CAAQ,GAAG,8BAAqB,cAAoB,EAChD,KACN,SAAC,OAAD,UAAO,EAAM,MAAa,EACpB,KACR,SAAC,KAAD,UACG,EAAM,IAAK,IACV,UAAC,KAAD,YACE,UAAC,OAAD,WACG,EAAK,SAAW,eAAiB,eAAiB,iBAAiB,MAAI,EAAK,WAAW,KACpF,KACN,SAAC,SAAD,UAAS,EAAK,KAAc,IAC5B,SAAC,EAAD,UAAO,EAAK,WAAkB,GAC7B,EAAK,WAAa,OAAY,MAC7B,UAAC,OAAD,WACG,EAAK,SAAS,KAAK,IAAE,OAAO,EAAK,SAAS,SAAS,EACnD,EAAK,SAAS,UAAY,EAAK,SAAS,UAAY,GAAK,IAAI,OAAO,EAAK,SAAS,OAAO,GACtF,KAER,SAAC,QAAD,UAAQ,EAAK,WAAW,MAAc,EACpC,GAbK,EAAK,MAaV,CACL,CACC,EACG,IClQA,EAAuC,GAClD,EAAS,OAAO,OAAS,WACrB,WACA,GAAG,EAAS,OAAO,aAAa,EAAS,OAAO,QAAU,KAAO,GAAK,MAAM,EAAS,OAAO,UAErF,EAA2C,GACtD,EAAS,WAAW,OAAS,YAAc,YAAc,qBAG9C,GAAmC,CAC9C,cACA,iBACA,UAKkB,CAClB,IAAM,EAAY,CAAC,EAAK,QAAS,GAAG,EAAK,UAAU,QAAQ,CAAE,gBAAiB,IAAe,EAAK,QAAQ,UAAU,CAAC,EACrH,OACE,UAAC,MAAD,CAAK,UAAW,EAAO,yBAAvB,EACE,SAAC,KAAD,UACG,EAAU,IAAK,IACd,UAAC,KAAD,YACE,UAAC,SAAD,YACE,UAAC,SAAD,WAAQ,YAAU,OAAO,EAAS,QAAQ,CAAU,KACpD,UAAC,OAAD,WACG,EAAwC,CAAQ,EAAE,MAAI,EAAoC,CAAQ,CAC/F,GACA,KACR,SAAC,OAAD,CAAM,SAAU,EAAmB,EAAS,SAAS,WAClD,EAAqB,EAAS,UAAW,CACxC,UAAW,SACX,UAAW,OACb,CAAC,CACG,IACN,UAAC,UAAD,YACE,SAAC,UAAD,UAAU,EAAS,WAAW,KAAe,IAC7C,SAAC,EAAD,UAAO,EAAS,WAAW,OAAc,IACzC,UAAC,KAAD,YACE,SAAC,KAAD,UAAI,QAAU,IACd,SAAC,KAAD,UAAK,EAAS,WAAW,MAAW,IACpC,SAAC,KAAD,UAAI,gBAAkB,IACtB,SAAC,KAAD,UAAK,EAAS,WAAW,cAAmB,IAC5C,SAAC,KAAD,UAAI,UAAY,IAChB,SAAC,KAAD,UAAK,EAAS,WAAW,QAAa,IACtC,SAAC,KAAD,UAAI,YAAc,IAClB,UAAC,KAAD,WACG,EAAS,WAAW,WAAW,MAAM,MAAI,EAAS,WAAW,WAAW,MACvE,KACJ,SAAC,KAAD,UAAI,UAAY,IAChB,UAAC,KAAD,YACE,UAAC,OAAD,WACG,EAAS,WAAW,SAAS,KAAK,IAAE,OAAO,EAAS,WAAW,SAAS,SAAS,CAC9E,KACN,SAAC,MAAD,UAAM,EAAS,WAAW,SAAS,OAAa,EAC9C,KACJ,SAAC,KAAD,UAAI,QAAU,IACd,SAAC,KAAD,WACE,SAAC,OAAD,UAAO,KAAK,UAAU,EAAS,WAAW,MAAM,CAAQ,EACtD,IACJ,SAAC,KAAD,UAAI,mBAAqB,IACzB,SAAC,KAAD,UACG,EAAS,WAAW,iBAAiB,SAAW,EAC/C,QAEA,SAAC,MAAD,UAAM,KAAK,UAAU,EAAS,WAAW,iBAAkB,KAAM,CAAC,CAAO,EAEzE,IACJ,SAAC,KAAD,UAAI,aAAe,IACnB,SAAC,KAAD,UACG,EAAS,WAAW,cAAgB,OACnC,QAEA,iCACE,SAAC,EAAD,UAAO,EAAS,WAAW,YAAY,WAAkB,IACzD,SAAC,MAAD,UAAM,EAAS,WAAW,YAAY,WAAiB,EACvD,GAEF,IACJ,SAAC,KAAD,UAAI,YAAc,IAClB,SAAC,KAAD,UACG,EAAS,WAAW,aAAe,OAClC,QAEA,SAAC,MAAD,UAAM,KAAK,UAAU,EAAS,WAAW,WAAY,KAAM,CAAC,CAAO,EAEnE,EACF,GACG,GACP,GAnEK,EAAS,UAmEd,CACL,CACC,GACH,EAAK,SACJ,SAAC,EAAD,CAAQ,YAAW,EAAgB,SAAU,EAAgB,QAAS,EAAgB,QAAS,WAC5F,EAAiB,6BAA+B,wBAC3C,GACN,IACD,GAET,ECtFM,EAA+B,EAPJ,EAAc,CAC7C,OAAQ,EAAmB,OAAO,OAClC,SAAU,EAAmB,OAAO,SACpC,iBAAkB,EAAmB,OAAO,iBAC5C,YAAa,EAAmB,OAAO,YACvC,WAAY,EAAmB,OAAO,UACxC,CAC2D,CAAwB,EAC7E,EAAkB,CACtB,CAAC,UAAW,SAAS,EACrB,CAAC,SAAU,QAAQ,EACnB,CAAC,iBAAkB,gBAAgB,CACrC,EAEM,EAAsB,IAA4D,CACtF,MAAO,EAAW,MAClB,SAAU,EAAW,SACrB,QAAS,EAAW,QACpB,OAAQ,EAAW,OACnB,SAAU,EAAW,SACrB,eAAgB,EAAW,eAC3B,WAAY,EAAW,WACvB,iBAAkB,EAAW,iBAC7B,GAAI,EAAW,aAAe,OAAY,CAAC,EAAI,CAAE,WAAY,EAAW,UAAW,EACnF,GAAI,EAAW,cAAgB,OAAY,CAAC,EAAI,CAAE,YAAa,EAAW,WAAY,EACtF,OAAQ,EAAW,MACrB,GAEM,EAAgB,GACpB,EAAkB,CAA4B,CAAC,CAAC,CAC9C,OAAQ,EAAW,OACnB,SAAU,EAAW,SACrB,iBAAkB,EAAW,iBAC7B,GAAI,EAAW,aAAe,OAAY,CAAC,EAAI,CAAE,WAAY,EAAW,UAAW,EACnF,GAAI,EAAW,cAAgB,OAAY,CAAC,EAAI,CAAE,YAAa,EAAW,WAAY,CACxF,CAAC,EAGU,GAAkC,CAC7C,UACA,WACA,cACA,iBACA,OACA,eACA,oBACA,SACA,OACA,OACA,iBACA,YAckB,CAClB,IAAM,EAAU,EAAK,QACf,CAAC,EAAO,sBAA2B,EAAmB,EAAQ,UAAU,CAAC,EACzE,CAAC,EAAU,sBAA8B,EAAa,EAAQ,UAAU,CAAC,EACzE,CAAC,EAAe,kBAA6B,EAAK,GACxD,mBAAgB,CACd,GAAI,CAAC,EAAM,OACX,IAAM,EAAY,GAAkB,EAAmB,EAAQ,UAAU,EACzE,EAAS,CAAS,EAClB,EAAY,EAAa,CAAS,CAAC,EACnC,EAAiB,EAAK,CACxB,EAAG,CAAC,EAAQ,WAAY,EAAQ,WAAY,EAAM,CAAc,CAAC,EACjE,IAAM,oBAEF,YAAY,OAAO,EAAQ,QAAQ,EAAE,KAAK,EACxC,CACF,EAAE,KAAK,EAAoC,CAAO,IACpD,CAAC,CAAO,CACV,EACM,MAAmB,CACvB,IAAM,EAAU,EAA2B,CAA4B,CAAC,CAAC,CAAQ,EACjF,GAAI,EAAiB,CAAO,EAAG,CAC7B,EAAiB,EAAI,EACrB,MACF,CACA,EAAiB,EAAK,EACtB,IAAM,EAAO,EAA2B,CAAsB,CAAC,CAAC,CAC9D,MAAO,EAAM,MACb,SAAU,EAAM,SAChB,QAAS,EAAM,QACf,OAAQ,EAAM,OACd,eAAgB,EAAM,eACtB,WAAY,EAAM,WAClB,GAAG,EAAQ,OACb,CAAC,EACD,GAAI,EAAiB,CAAI,EAAG,CAC1B,EAAiB,EAAI,EACrB,MACF,CACA,EAAO,EAAK,OAAO,CACrB,EAEA,OACE,SAAC,EAAO,KAAR,CAA2B,eAAoB,iBAC7C,SAAC,EAAO,QAAR,CACE,UAAW,EAAO,eACL,cACb,KAAK,OACL,MAAO,IAAS,OAAS,yBAA2B,4BAEnD,IAAS,WACR,SAAC,EAAD,CAA8C,cAA6B,iBAAsB,MAAO,IAExG,UAAC,OAAD,CACE,UAAW,EAAO,eAClB,SAAW,GAAU,CACnB,EAAM,eAAe,EACrB,EAAK,CACP,WALF,EAOE,UAAC,MAAD,CAAK,UAAW,EAAO,4BAAvB,EACE,UAAC,QAAD,YACE,SAAC,OAAD,UAAM,OAAW,IACjB,SAAC,QAAD,CACE,UAAW,IACX,SAAW,GAAU,EAAS,CAAE,GAAG,EAAO,MAAO,EAAM,cAAc,KAAM,CAAC,EAC5E,YACA,MAAO,EAAM,KACd,EACI,KACP,UAAC,QAAD,YACE,SAAC,OAAD,UAAM,UAAc,IACpB,UAAC,SAAD,CACE,SAAW,GAAU,CACnB,IAAM,EAAW,EAA2B,EAAmB,OAAO,QAAQ,CAAC,CAC7E,EAAM,cAAc,KACtB,EACI,EAAiB,CAAQ,GAC7B,EAAS,CAAE,GAAG,EAAO,SAAU,EAAS,OAAQ,CAAC,CACnD,EACA,MAAO,EAAM,kBARf,EAUE,SAAC,SAAD,CAAQ,MAAM,cAAK,IAAU,IAC7B,SAAC,SAAD,CAAQ,MAAM,cAAK,IAAU,IAC7B,SAAC,SAAD,CAAQ,MAAM,cAAK,IAAU,IAC7B,SAAC,SAAD,CAAQ,MAAM,cAAK,IAAU,EACvB,GACH,KACP,UAAC,QAAD,YACE,SAAC,OAAD,UAAM,YAAgB,IACtB,UAAC,SAAD,CACE,SAAW,GAAU,CACnB,IAAM,EAAQ,EAA2B,EAAmB,OAAO,WAAW,OAAO,KAAK,CAAC,CACzF,EAAM,cAAc,KACtB,EACI,EAAiB,CAAK,GAC1B,EAAS,CACP,GAAG,EACH,WAAY,CACV,GAAG,EAAM,WACT,MAAO,EAAM,OACf,CACF,CAAC,CACH,EACA,MAAO,EAAM,WAAW,eAd1B,EAgBE,SAAC,SAAD,CAAQ,MAAM,gBAAO,MAAY,IACjC,SAAC,SAAD,CAAQ,MAAM,kBAAS,QAAc,EAC/B,GACH,GACJ,IACJ,EAAgB,KAAK,CAAC,EAAO,MAC5B,UAAC,QAAD,YACE,SAAC,OAAD,UAAO,CAAY,IACnB,SAAC,WAAD,CACE,UAAW,IACX,SAAW,GACT,EAAS,CACP,GAAG,GACF,GAAQ,EAAM,cAAc,KAC/B,CAAC,EAEH,YACA,KAAM,EACN,MAAO,EAAM,EACd,EACI,GAdK,CAcL,CACR,GACD,UAAC,QAAD,YACE,SAAC,OAAD,UAAM,mBAAuB,IAC7B,SAAC,WAAD,CACE,UAAW,IACX,SAAW,GACT,EAAS,CACP,GAAG,EACH,WAAY,CACV,GAAG,EAAM,WACT,OAAQ,EAAM,cAAc,KAC9B,CACF,CAAC,EAEH,YACA,KAAM,EACN,MAAO,EAAM,WAAW,MACzB,EACI,KACP,UAAC,UAAD,CAAS,UAAW,EAAO,0BAA3B,EACE,SAAC,UAAD,UAAS,uDAA8D,IACvE,SAAC,EAAD,CAAM,KAAK,qBAAY,+EAEjB,IACN,SAAC,WAAD,CACE,mBAAkB,EAAgB,0BAA4B,OAC9D,eAAc,EACd,aAAW,6DACX,SAAW,GAAU,EAAY,EAAM,cAAc,KAAK,EAC1D,KAAM,GACN,WAAY,GACZ,MAAO,CACR,GACA,GACC,SAAC,OAAD,CAAM,GAAG,0BAA0B,KAAK,iBAAQ,sDAE1C,GACJ,IACG,IACR,GACC,UAAC,MAAD,CAAK,KAAK,iBAAV,EACE,SAAC,OAAD,UAAM,qFAAyF,IAC/F,SAAC,EAAD,CAAQ,QAAS,EAAmB,KAAK,SAAS,QAAQ,iBAAQ,qBAE1D,EACL,IACH,EAAQ,WAAW,OAAS,yBAC9B,SAAC,OAAD,CAAM,KAAK,kBAAS,sEAA0E,GAC5F,MACJ,UAAC,MAAD,CAAK,UAAW,EAAO,+BAAvB,EACE,SAAC,EAAO,MAAR,CAAc,SAAU,WAAQ,QAAoB,IACpD,SAAC,EAAD,CAAQ,SAAU,CAAC,GAAW,EAAQ,QAAS,EAAQ,KAAK,kBACzD,EAAS,mBAAqB,eACzB,EACL,GACD,GAEM,EACL,EAEjB,ECnPM,EAAqB,EAAmC,KAAK,EAAE,EAkDxD,EAA8E,CACzF,SAAU,EAAO,EAAS,IACxB,EACE,EAAW,WAAY,CAErB,OAAO,OAAO,MADQ,GACD,MAAM,wBAAwB,CACjD,OAAQ,CACN,SAAU,EAAM,SAChB,MAAO,EAAM,MACb,aAAc,EAAM,YACtB,EACA,QAAS,CACX,CAAC,CACH,CAAC,CAAC,CAAC,KAAK,EAAe,CAAqB,CAAC,EAC7C,CAAE,QAAO,CACX,EACF,MAAO,EAAO,EAAS,IACrB,EACE,EAAW,WAAY,CAErB,OAAO,OAAO,MADQ,GACD,MAAM,qBAAqB,CAC9C,OAAQ,CACN,SAAU,EAAM,SAChB,MAAO,EAAM,MACb,aAAc,EAAM,YACtB,EACA,QAAS,CACX,CAAC,CACH,CAAC,CAAC,CAAC,KAAK,EAAe,CAAqB,CAAC,EAC7C,CAAE,QAAO,CACX,EACF,MAAO,EAAO,EAAQ,IACpB,EACE,EAAW,WAAY,CAErB,OAAO,OAAO,MADQ,EAA2B,GAC5B,MAAM,0BAA0B,CACnD,OAAQ,CACN,SAAU,EAAM,SAChB,MAAO,EAAM,MACb,aAAc,EAAM,YACtB,EACA,MAAO,CACL,GAAI,IAAW,KAAO,CAAC,EAAI,CAAE,QAAO,EACpC,MAAO,CACT,CACF,CAAC,CACH,CAAC,CAAC,CAAC,KAAK,EAAe,CAAqB,CAAC,EAC7C,CAAE,QAAO,CACX,CACJ,EAEM,GACJ,EACA,IAEA,EAAK,WAAa,EAAM,UACxB,EAAK,QAAU,EAAM,OACrB,EAAK,aAAe,EAAM,YAC1B,EAAK,eAAiB,EAAM,aAExB,GACJ,EACA,IACiC,CACjC,IAAM,EAAU,EAAQ,QAAQ,SAAW,EAAS,QAAQ,SACxD,EAAQ,QACR,EAAS,QAWb,MAAO,CACL,UACA,UAAW,CAAC,GAAG,IAZK,IACpB,CACE,EAAS,QACT,EAAQ,QACR,GAAG,EAAS,UACZ,GAAG,EAAQ,SACb,CAAC,CACE,QAAQ,CAAE,gBAAiB,IAAe,EAAQ,UAAU,CAAC,CAC7D,IAAK,GAAa,CAAC,EAAS,WAAY,CAAQ,CAAC,CAIrC,EAAU,OAAO,CAAC,CAAC,CAAC,MAChC,EAAM,IAAU,EAAM,SAAW,EAAK,QACzC,EACA,QAAS,EAAQ,QACjB,mBAAoB,EAAQ,kBAC9B,CACF,EAEM,GACJ,EACA,KACkC,CAClC,QAAS,EACT,UAAW,CAAC,EAAS,QAAS,GAAG,EAAS,SAAS,CAAC,CACjD,QAAQ,CAAE,gBAAiB,IAAe,EAAS,UAAU,CAAC,CAC9D,MAAM,EAAM,IAAU,EAAM,SAAW,EAAK,QAAQ,EACvD,QAAS,EAAS,QAClB,mBAAoB,EAAS,kBAC/B,GAOM,GACJ,EACA,KACiB,CAAE,OAAM,MAAK,GAE1B,EAAkB,EAAmB,kBAAkB,EACvD,EAA0B,GAA0C,OAG7D,GACX,EACA,EAA+C,EAC/C,EAA+C,IAS5C,CACH,GAAM,CAAC,EAAiB,kBAA+B,CAAC,EAClD,CAAC,EAAgB,kBAA8B,EAAK,EACpD,CAAC,EAAO,kBAAoD,CAAE,KAAM,MAAO,CAAC,EAC5E,eAA6C,IAAI,EACjD,eAA2B,EAAK,EAChC,eAAqB,CAAK,EAC1B,eAA0B,CAAU,EAC1C,EAAY,QAAU,EACtB,EAAiB,QAAU,GAE3B,mBAAgB,CAId,GAHA,EAAY,SAAS,MAAM,EAC3B,EAAkB,QAAU,GAC5B,EAAkB,EAAK,EACnB,IAAU,KAAM,CAClB,EAAS,CAAE,KAAM,MAAO,CAAC,EACzB,MACF,CACA,IAAM,EAAU,EACV,EAAQ,IAAI,gBAqBlB,MApBA,GAAY,QAAU,EACtB,EAAS,CAAE,KAAM,SAAU,CAAC,EAC5B,EAAU,KAAK,EAAS,KAAM,EAAM,MAAM,CAAC,CAAC,KACzC,GAAS,CAEN,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,GAEzC,EAAS,CAAE,KAAM,QAAS,MAAK,CAAC,CAClC,MACM,CAEF,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,GAEzC,EAAS,CAAE,KAAM,SAAU,MAAO,KAAM,KAAM,IAAK,CAAC,CACtD,CACF,MACa,EAAM,MAAM,CAC3B,EAAG,CAAC,EAAiB,EAAO,CAAS,CAAC,EAEtC,IAAM,oBAAoB,GAAwC,CAChE,GAAI,IAAU,MAAQ,EAAM,OAAS,WAAY,OACjD,IAAM,EAAW,EAAM,OAAS,SAE5B,EAAM,OAAS,SADf,EAAM,KAGN,KACJ,GAAI,IAAa,KAAM,OACvB,IAAM,EAAU,EAChB,EAAY,SAAS,MAAM,EAC3B,EAAkB,QAAU,GAC5B,EAAkB,EAAK,EACvB,IAAM,EAAQ,IAAI,gBAClB,EAAY,QAAU,EACtB,EAAS,CAAE,KAAM,SAAU,QAAO,KAAM,CAAS,CAAC,EAClD,EAAU,KAAK,EAAS,CACtB,mBAAoB,EAAS,QAAQ,WACrC,iBAAkB,EAAS,QAAQ,SACnC,KAAM,CACR,EAAG,EAAM,MAAM,CAAC,CAAC,KACd,GAAa,CACZ,IAAM,EAAe,EAAyB,EAAU,CAAQ,EAChE,OAAO,EAAU,KAAK,EAAS,KAAM,EAAM,MAAM,CAAC,CAAC,KAChD,GAAS,EAAY,YAAa,CAAI,MACjC,EAAY,0BAA2B,CAAY,CAC3D,CACF,EACC,GAAqB,CACpB,GAAI,CAAC,EAAgB,CAAO,EAAG,MAAM,EACrC,OAAO,EAAU,KAAK,EAAS,KAAM,EAAM,MAAM,CAAC,CAAC,KAAM,IAErD,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,GAEzC,EAAS,CAAE,KAAM,WAAY,QAAO,MAAK,CAAC,EADjC,EAAY,WAAY,CAAI,EAGtC,CACH,CACF,CAAC,CAAC,KACC,GAAY,CAET,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,IAEzC,EAAU,GACR,EAAO,OAAS,WACZ,EACA,EAAQ,OAAS,0BACjB,CAAE,KAAM,SAAU,MAAO,KAAM,KAAM,EAAQ,IAAK,EAClD,CAAE,KAAM,QAAS,KAAM,EAAQ,IAAK,CAC1C,EACI,EAAQ,OAAS,YAAY,EAAiB,QAAQ,EAAQ,KAAK,QAAQ,UAAU,EAC3F,MACM,CAEF,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,GAEzC,EAAS,CAAE,KAAM,SAAU,QAAO,KAAM,CAAS,CAAC,CACpD,CACF,CACF,EAAG,CAAC,EAAO,EAAO,CAAS,CAAC,EAEtB,wBAAkC,CACtC,GAAI,IAAU,MAAQ,EAAM,OAAS,SAAW,EAAU,UAAY,OAAW,OACjF,IAAM,EAAU,EACV,EAAW,EAAM,KACvB,EAAY,SAAS,MAAM,EAC3B,EAAkB,QAAU,GAC5B,EAAkB,EAAK,EACvB,IAAM,EAAQ,IAAI,gBAClB,EAAY,QAAU,EACtB,EAAS,CAAE,KAAM,aAAc,KAAM,CAAS,CAAC,EAC/C,EAAU,QAAQ,EAAS,CACzB,mBAAoB,EAAS,QAAQ,WACrC,iBAAkB,EAAS,QAAQ,QACrC,EAAG,EAAM,MAAM,CAAC,CAAC,KACd,GAAa,CAEV,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,IAEzC,EAAS,CACP,KAAM,QACN,KAAM,EAAyB,EAAU,CAAQ,CACnD,CAAC,EACD,EAAiB,QAAQ,EAAS,UAAU,EAC9C,MACM,CAEF,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,GAEzC,EAAS,CAAE,KAAM,SAAU,MAAO,KAAM,KAAM,CAAS,CAAC,CAC1D,CACF,CACF,EAAG,CAAC,EAAO,EAAO,CAAS,CAAC,EAEtB,wBAAsC,CAC1C,GACE,IAAU,MACT,EAAM,OAAS,SAAW,EAAM,OAAS,YAC1C,EAAkB,SAClB,CAAC,EAAM,KAAK,SACZ,EAAM,KAAK,qBAAuB,KAClC,OACF,IAAM,EAAU,EACV,EAAW,EAAM,KACvB,EAAY,SAAS,MAAM,EAC3B,IAAM,EAAQ,IAAI,gBAClB,EAAY,QAAU,EACtB,EAAkB,QAAU,GAC5B,EAAkB,EAAI,EACtB,EAAU,KACR,EACA,EAAS,mBACT,EAAM,MACR,CAAC,CAAC,KACC,GAAS,CAEN,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,GAErC,EAAY,UAAY,IAC5B,EAAU,GACR,EAAO,OAAS,SAAW,EAAO,OAAS,WACvC,CAAE,GAAG,EAAQ,KAAM,EAAW,EAAO,KAAM,CAAI,CAAE,EACjD,CACN,EACA,EAAkB,QAAU,GAC5B,EAAkB,EAAK,EACzB,MACM,CAEF,EAAM,OAAO,SACb,EAAY,UAAY,MACxB,CAAC,EAAU,EAAY,QAAS,CAAO,GAErC,EAAY,UAAY,IAC5B,EAAU,GACR,EAAO,OAAS,QACZ,CAAE,KAAM,SAAU,MAAO,KAAM,KAAM,EAAO,IAAK,EACjD,CACN,EACA,EAAkB,QAAU,GAC5B,EAAkB,EAAK,EACzB,CACF,CACF,EAAG,CAAC,EAAO,EAAO,CAAS,CAAC,EAE5B,yBAAsB,CACpB,UACA,cACA,iBACA,oBACE,EAAU,GACR,EAAO,OAAS,WACZ,CAAE,KAAM,QAAS,KAAM,EAAO,IAAK,EACnC,CACN,EACF,UAAa,CACP,KAAM,OAAS,WACnB,IACE,EAAM,OAAS,UACf,EAAM,QAAU,MAChB,EAAM,OAAS,KACf,CACA,EAAK,EAAM,KAAK,EAChB,MACF,CACA,EAAoB,GAAa,EAAW,CAAC,CAD7C,CAEF,EACA,OACA,OACF,GAAI,CAAC,EAAS,EAAa,EAAgB,EAAM,CAAK,CAAC,CACzD,ECpZM,GAAe,GACnB,EAAO,OAAS,WAAa,WAAa,EAAO,WAGtC,IAAiC,CAC5C,UACA,WACA,eACA,QACA,uBACA,+BACA,oBAAoB,EACpB,aACA,gBAWkB,CAUlB,IAAM,EAAa,qBARV,CACL,WACA,QACA,aACA,aAAc,EAAW,YAC3B,GACA,CAAC,EAAU,EAAO,EAAY,EAAW,YAAY,CAEP,EAAO,EAAmB,CAA4B,EAChG,CAAC,EAAY,kBAA8C,SAAS,EACpE,CAAC,EAAY,kBAA0B,EAAK,EAC5C,CAAC,EAAa,kBAA2B,EAAK,EAC9C,EACJ,EAAW,MAAM,OAAS,SAC1B,EAAW,MAAM,OAAS,cAC1B,EAAW,MAAM,OAAS,UAC1B,EAAW,MAAM,OAAS,YAEtB,EAAW,MAAM,OAAS,SAD1B,EAAW,MAAM,KAGf,KACF,EACJ,EAAW,MAAM,OAAS,UAAY,EAAW,MAAM,OAAS,YAAc,EAAW,MAAM,OAAS,SACpG,EAAW,MAAM,MACjB,KACA,EAAU,GAAM,QAChB,EACJ,IAAY,OACR,EACA,CACE,GAAG,EAAQ,WACX,MAAO,EAAW,QAAU,YAAc,YAAc,EAAQ,WAAW,KAC7E,EACA,EAAsB,GAAW,EAAoB,QAAU,SAAW,EAAW,MAAM,OAAS,aACpG,EAAoB,GAAS,WAAW,OAAS,wBACjD,EACJ,EAAW,MAAM,OAAS,UACtB,iDACA,EAAW,MAAM,OAAS,SACxB,4DACA,EACE,wEACA,OACJ,EAAc,GAAmC,CACrD,EAAc,CAAI,EAClB,EAAc,EAAI,CACpB,EAEA,OACE,iCACE,SAAC,EAAD,CACE,WAAY,EACZ,cACE,iCACE,SAAC,EAAD,CAAQ,SAAU,IAAS,KAAM,YAAe,EAAW,SAAS,EAAG,QAAQ,iBAAQ,SAE/E,GACP,GACC,SAAC,EAAD,CAAQ,SAAU,IAAS,KAAM,YAAe,EAAW,MAAM,EAAG,QAAQ,iBAAQ,MAE5E,GACN,KACH,GACC,SAAC,EAAD,CAAQ,SAAU,IAAS,KAAM,YAAe,EAAe,EAAI,EAAG,QAAQ,iBAAQ,SAE9E,GACN,KACH,EAAW,MAAM,OAAS,cACzB,SAAC,EAAD,CAAQ,YAAS,QAAQ,iBAAQ,aAEzB,GACN,KACH,EAAW,MAAM,OAAS,UACzB,SAAC,EAAD,CAAQ,QAAS,EAAW,MAAO,QAAQ,iBAAQ,gBAE3C,GACN,IACJ,IAEU,eACP,QACP,SACE,IAAY,OAAY,MACtB,UAAC,MAAD,CAAK,UAAW,EAAO,uBAAwB,kBAAiB,EAAQ,WAAW,cAAnF,EACE,UAAC,SAAD,WAAQ,YAAU,OAAO,EAAQ,QAAQ,CAAU,KACnD,SAAC,OAAD,UAAO,EAAQ,WAAW,OAAS,YAAc,YAAc,oBAA2B,IAC1F,SAAC,OAAD,UAAO,GAAY,EAAQ,MAAM,CAAQ,IACzC,SAAC,OAAD,CAAM,SAAU,EAAmB,EAAQ,SAAS,WACjD,EAAqB,EAAQ,UAAW,CACvC,UAAW,SACX,UAAW,OACb,CAAC,CACG,EACH,IAGT,qBAAuB,GAAc,CAC/B,IAAY,QAChB,EAAqB,CACnB,GAAG,EACH,WAAY,EAAQ,UACtB,CAAC,CACH,EACA,GAAK,IAA6B,OAAY,CAAC,EAAI,CAAE,0BAAyB,EAC9E,WAAY,CACb,GACA,IAAS,KAAO,MACf,SAAC,EAAD,CACE,QAAS,EACT,SAAU,EAAW,MAAM,OAAS,WACpC,YAAa,EAAW,YACxB,eAAgB,EAAW,eAC3B,KAAM,EACN,aAAc,EACd,kBAAmB,EAAW,gBAC9B,OAAQ,EAAW,KACnB,KAAM,EACA,OACU,iBAChB,OAAQ,EAAW,MAAM,OAAS,QACnC,IAEH,SAAC,EAAO,KAAR,CAAa,aAAc,EAAgB,KAAM,YAC/C,UAAC,EAAO,QAAR,CACE,YAAY,uHACZ,KAAK,UACL,MAAM,4BAHR,EAKE,SAAC,EAAD,UAAM,uFAA2F,IACjG,UAAC,MAAD,CAAK,UAAW,EAAO,4BAAvB,EACE,SAAC,EAAO,MAAR,UAAc,cAA0B,IACxC,SAAC,EAAD,CACE,YAAe,CACb,EAAe,EAAK,EACpB,EAAW,QAAQ,CACrB,WACD,iBAEO,EACL,GACS,GACL,EACb,GAEN,ECxKM,GACJ,GAKW,CACX,OAAQ,EAAR,CACE,IAAK,iBACL,IAAK,mBACH,MAAO,4EACT,IAAK,eACH,MAAO,qEACT,IAAK,sBACH,MAAO,2EACT,IAAK,4BACH,MAAO,+EACX,CACF,EAEM,GACJ,GACG,CACH,OAAQ,EAAR,CACE,IAAK,mBACH,MAAO,mBACT,IAAK,2BACH,MAAO,2BACT,IAAK,kBACH,MAAO,kBACT,IAAK,qBACH,MAAO,oBACX,CACF,EAEM,EAAgB,GAAiC,CACrD,IAAM,EAAU,KAAK,MAAM,EAAe,GAAM,EAChD,MAAO,GAAG,OAAO,CAAO,EAAE,SAAS,IAAY,EAAI,GAAK,KAC1D,EAEM,EACJ,GACW,EAAS,aAAe,EAAS,WAExC,EAAuB,GAAyD,GAAG,EAAa,CAAQ,EAAE,SAE1G,GAGD,CACH,CACE,MAAO,cACP,OAAQ,2EACV,EACA,CACE,MAAO,WACP,OAAQ,oFACV,EACA,CACE,MAAO,QACP,OAAQ,0FACV,CACF,EAEM,wBAAgD,OAAO,8FAA0C,EAEjG,GAAsB,GAAuD,CACjF,OAAQ,EAAM,KAAd,CACE,IAAK,mBACH,MAAO,oBAAoB,EAAM,SACnC,IAAK,aACH,MAAO,GAAG,EAAM,cAAc,MAAM,UAAU,EAAM,QAAQ,aAAa,MAAM,EAAG,EAAE,IACtF,IAAK,cACH,OAAO,EAAM,kBAAoB,OAC7B,yBACA,4BAA4B,EAAM,gBAAgB,eAAe,GAAG,EAAM,gBAAgB,SAAW,KAAK,KAAK,EACrH,IAAK,WACH,OAAO,EAAM,KACf,IAAK,gBACH,MAAO,GAAG,OAAO,EAAM,OAAO,YAAY,MAAM,EAAE,iBAAiB,OAAO,EAAM,OAAO,MAAM,MAAM,EAAE,QACvG,IAAK,qBACH,OAAO,EAAM,kBAAoB,YAC7B,uBAAuB,OAAO,EAAM,QAAQ,EAAE,0BAC9C,uBAAuB,OAAO,EAAM,QAAQ,EAAE,KAAK,EAAM,kBAAoB,YAAc,YAAc,uBAC/G,IAAK,uBACH,MAAO,qCACT,IAAK,gBACH,MAAO,mBAAmB,EAAM,UAClC,IAAK,aACH,OAAO,EAAM,UAAY,yBAA2B,aACtD,IAAK,yBACH,MAAO,yBACT,IAAK,QACH,OAAO,IACX,CACF,EAGa,GAA0B,CACrC,aACA,sBACA,oBAAsB,OACtB,uBACA,sBACA,UACA,UACA,+BACA,cACA,oBACA,QACA,iBAckB,CAClB,GAAM,CAAC,EAAY,kBAA0B,EAAK,EAC5C,CAAC,EAAS,kBAAuB,EAAE,EACnC,CAAC,EAAkB,kBAA+C,IAAI,EACtE,CAAC,EAAoB,kBAAiE,IAAI,EAC1F,oBACG,EAAM,OAAS,QAAW,EAAM,kBAAoB,EAAM,WAAa,KAAO,CAAC,EAAI,CAAC,EAAM,QAAQ,GAAM,CAAC,EAChH,CAAC,CAAK,CACR,EACM,EACJ,EAAgB,MAAM,CAAE,gBAAiB,IAAe,CAAkB,GAAK,EAAgB,IAAM,MAKvG,mBAAgB,CACd,EAAc,EAAK,EACnB,EAAW,EAAE,EACb,EAAoB,IAAI,EACxB,EAAsB,IAAI,CAC5B,EAAG,CARD,EAAM,OAAS,OACX,KACA,GAAG,EAAM,SAAS,GAAG,EAAM,cAAgB,GAAG,GAAG,EAAM,aAAa,GAAG,EAAM,YAMnE,CAAC,GACjB,mBAAgB,CACd,GAAI,EAAgB,SAAW,EAAG,CAChC,EAAsB,IAAI,EAC1B,MACF,CACK,EAAgB,MAAM,CAAE,gBAAiB,IAAe,CAAkB,GAC7E,EAAsB,EAAgB,EAAE,EAAE,YAAc,IAAI,CAEhE,EAAG,CAAC,EAAiB,CAAkB,CAAC,GACxC,mBAAgB,CACV,IAAqB,MAAQ,EAAM,OAAS,SAC5C,EAAM,SAAW,UACjB,EAAM,SAAW,QAAU,EAAM,OAAO,OAAS,YACnD,EAAY,GAAa,EAAQ,KAAK,IAAM,EAAmB,GAAK,CAAQ,EAC5E,EAAoB,IAAI,EAE5B,EAAG,CAAC,EAAO,CAAgB,CAAC,EAC5B,IAAM,oBAAgC,GAAwB,CAC5D,EAAc,CAAI,CACpB,EAAG,CAAC,CAAC,EACC,wBAA2C,CAC3C,IAAqB,OACzB,EAAoB,IAAI,EACxB,EAAQ,OAAW,EAAiB,UAAU,EAChD,EAAG,CAAC,EAAS,CAAgB,CAAC,EACxB,wBAA+C,CACnD,IAAM,EAAS,EAAQ,KAAK,EACxB,EAAO,SAAW,GAAK,EAAM,OAAS,SAAW,EAAM,SAAW,aACtE,EAAoB,CAAM,EACtB,IAAqB,MACzB,EAAQ,EAAQ,EAAiB,UAAU,EAC7C,EAAG,CAAC,EAAS,EAAS,EAAkB,CAAK,CAAC,EACxC,EAAyB,GAAoD,CAC7E,EAAM,MAAQ,SAAY,CAAC,EAAM,SAAW,CAAC,EAAM,UACvD,EAAM,eAAe,EACrB,EAAqB,EACvB,EACM,EACJ,EAAY,OAAS,QAAU,EAAY,OAAS,aAAe,MACjE,SAAC,WAAD,CAAU,UAAU,SAAC,OAAD,UAAM,gCAAoC,aAC5D,SAAC,GAAD,CACE,SAAU,EACV,UAAW,EACE,aACd,EACO,GAER,EAAmB,IACvB,gCACG,EACA,CACD,IAGJ,GAAI,EAAM,OAAS,QAAU,EAAM,OAAS,UAC1C,OAAO,GACL,UAAC,MAAD,CAAK,YAAU,SAAS,UAAW,EAAO,aAAc,KAAK,kBAA7D,EACE,SAAC,SAAD,UAAQ,sBAA4B,IACpC,SAAC,OAAD,UAAM,sDAA0D,IAChE,SAAC,OAAD,CAAM,cAAY,OAAO,UAAW,EAAO,YAAe,EACvD,GACP,EAEF,GAAI,EAAM,OAAS,SACjB,OAAO,GACL,UAAC,MAAD,CAAK,UAAW,EAAO,sBAAvB,EACE,SAAC,SAAD,UAAQ,0BAAgC,IACxC,SAAC,OAAD,UAAM,wEAA4E,IAClF,SAAC,EAAD,CAAQ,QAAS,WAAS,OAAa,EACpC,GACP,EAGF,IAAM,EAAS,EAAM,OACf,EAAe,EAAM,QAAQ,QAAU,CAAC,EACxC,EAAwB,EAC3B,IAAK,IAAW,CAAE,QAAO,QAAS,GAAmB,CAAK,CAAE,EAAE,CAAC,CAC/D,OAEG,GAIG,EAAK,UAAY,IACxB,EAEI,EADwB,EAAM,SAAW,SAAc,EAAM,OAAO,eAAiB,CAAC,EAAM,OAAO,YACrD,EAAwB,EAAsB,MAAM,GAAG,EACrG,GACJ,UAAC,UAAD,CAAS,aAAW,gBAAgB,UAAW,EAAO,sBAAtD,EACE,UAAC,SAAD,YACE,SAAC,SAAD,UAAQ,eAAqB,IAC7B,SAAC,OAAD,UAAO,EAAa,SAAW,EAAI,cAAgB,mCAA0C,EACvF,IACP,EAAoB,SAAW,EAAI,MAClC,SAAC,KAAD,CAAI,UAAW,EAAO,4BACnB,EAAoB,KAAK,CAAE,QAAO,cACjC,SAAC,KAAD,WACE,SAAC,OAAD,UAAO,CAAc,EACnB,EAFK,EAAM,aAEX,CACL,CACC,GAEL,EAAM,QAAQ,YACb,SAAC,EAAD,CAAQ,QAAS,EAAM,gBAAkB,UAAW,QAAS,WAC1D,EAAM,gBAAkB,UACrB,4BACA,EAAM,gBAAkB,SACtB,yBACA,uBACA,GACN,EAAM,SAAW,OAIjB,MAHF,SAAC,EAAD,CAAM,KAAK,YAAY,QAAQ,gBAAO,4BAEhC,GAEP,GAAc,EAAM,WAAa,MAAQ,EAAO,OAAS,WAAa,EAAO,OAAS,eACrF,UAAC,MAAD,CAAK,UAAW,EAAO,8BAAvB,EACE,SAAC,QAAD,CAAO,QAAQ,iCAAwB,mCAAwC,GAC9E,EAAgB,OAAS,GACxB,SAAC,MAAD,CAAK,aAAW,gCAAgC,UAAW,EAAO,iBAAkB,KAAK,sBACtF,EAAgB,IAAK,IACpB,UAAC,SAAD,CACE,eAAc,EAAO,aAAe,GAAkB,WAEtD,YAAe,EAAsB,EAAO,UAAU,EACtD,KAAK,QACL,KAAK,kBALP,EAOE,SAAC,SAAD,UAAS,EAAoB,CAAM,CAAU,IAC7C,SAAC,OAAD,UAAO,EAAO,KAAY,EACpB,GAPD,EAAO,UAON,CACT,CACE,GACH,IAAqB,KAAO,MAC9B,UAAC,OAAD,CAAM,UAAW,EAAO,8BAAxB,CAA8C,eAC/B,EAAa,CAAgB,EAAE,MAAI,EAAiB,KAC7D,KAER,SAAC,MAAD,CAAK,aAAW,0BAA0B,UAAW,EAAO,4BACzD,GAAwB,IAAK,IAC5B,SAAC,EAAD,CAA6B,YAAe,EAAW,EAAS,MAAM,WACnE,EAAS,KACJ,EAFK,EAAS,KAEd,CACT,CACE,IACL,SAAC,WAAD,CACE,mBAAiB,yDACjB,GAAG,wBACH,UAAW,EACX,SAAW,GAAU,EAAW,EAAM,cAAc,KAAK,EACzD,UAAW,EACX,YAAY,sDACZ,KAAM,EACN,MAAO,CACR,IACD,UAAC,MAAD,CAAK,UAAW,EAAO,oCAAvB,EACE,SAAC,OAAD,CAAM,GAAG,sCAA6B,uBAA2B,IACjE,UAAC,OAAD,CAAM,GAAG,uCAAT,CACG,OAAO,EAAQ,MAAM,EAAE,MAAI,OAAO,CAAmC,CAClE,GACH,IACJ,EAAM,SAAW,UAAY,IAAqB,MACjD,SAAC,OAAD,CAAM,KAAK,iBAAQ,0GAEb,GACJ,MACJ,SAAC,EAAD,CAAQ,SAAU,EAAM,SAAW,YAAc,EAAQ,KAAK,CAAC,CAAC,SAAW,EAAG,QAAS,WACpF,EAAM,SAAW,WAAa,4BAA8B,uBACvD,EACL,IACH,IACG,IAEL,EAAc,GAClB,GACE,gCACG,EACA,CACD,GACJ,EACI,GAAgB,EAAsB,IAC1C,IAAqB,KAAO,MAC1B,UAAC,EAAO,KAAR,CAAa,aAAc,EAAkB,KAAM,WAAnD,EACE,SAAC,EAAO,QAAR,CAAgB,SAAU,EAAM,SAAW,oBACxC,EAAM,SAAW,WAAa,mBAAqB,CACtC,IAChB,SAAC,EAAO,QAAR,CACE,UAAW,EAAO,mBAClB,YAAY,kHACZ,MAAM,mCAEN,UAAC,MAAD,CAAK,UAAW,EAAO,0BAAvB,EACE,SAAC,QAAD,CAAO,UAAW,EAAO,6BAAqB,qBAA0B,GACvE,EAAgB,OAAS,GACxB,SAAC,MAAD,CAAK,aAAW,uBAAuB,UAAW,EAAO,iBAAkB,KAAK,sBAC7E,EAAgB,IAAK,IACpB,UAAC,SAAD,CACE,eAAc,EAAO,aAAe,EAAiB,WAErD,YAAe,EAAsB,EAAO,UAAU,EACtD,KAAK,QACL,KAAK,kBALP,EAOE,SAAC,SAAD,UAAS,EAAoB,CAAM,CAAU,IAC7C,SAAC,OAAD,UAAO,EAAO,KAAY,EACpB,GAPD,EAAO,UAON,CACT,CACE,GACH,MACJ,UAAC,KAAD,CAAI,UAAW,EAAO,2BAAtB,EACE,UAAC,MAAD,YACE,SAAC,KAAD,UAAI,YAAc,IAClB,SAAC,KAAD,WACE,SAAC,OAAD,UAAO,CAAmB,EACxB,EACD,KACL,UAAC,MAAD,YACE,SAAC,KAAD,UAAI,gBAAkB,IACtB,SAAC,KAAD,UAAK,EAAiB,cAAc,KAAU,EAC3C,KACL,UAAC,MAAD,YACE,SAAC,KAAD,UAAI,aAAe,IACnB,SAAC,KAAD,UAAK,EAAa,EAAiB,cAAc,YAAY,CAAM,EAChE,KACL,UAAC,MAAD,YACE,SAAC,KAAD,UAAI,SAAW,IACf,SAAC,KAAD,UACG,EAAiB,cAAc,gBAAkB,UAC9C,wBACA,mCACF,EACD,GACH,KACJ,UAAC,MAAD,CAAK,UAAW,EAAO,6BAAvB,EACE,SAAC,EAAO,MAAR,UAAc,cAA0B,IACxC,SAAC,EAAO,MAAR,CAAc,QAAS,WAAkB,mBAA+B,EACrE,GACF,GACS,EACL,IAEjB,GAAI,EAAO,OAAS,cAClB,OAAO,GACL,iCACE,SAAC,SAAD,UAAQ,oBAA0B,IAClC,SAAC,OAAD,UAAO,GAAmB,EAAO,MAAM,CAAQ,EAC/C,GACJ,EAEF,GAAI,EAAO,OAAS,UAAW,CAC7B,IAAM,EACJ,EAAO,QAAU,SACb,gBACA,EAAO,QAAU,UACf,uBACA,yBACR,OAAO,GACL,UAAC,MAAD,CAAK,YAAU,SAAS,UAAW,EAAO,aAAc,KAAK,kBAA7D,EACE,SAAC,SAAD,UAAS,CAAc,IACvB,UAAC,OAAD,WAAM,kBACY,EAAO,WAAW,MAAI,EAAO,MAAM,oCAC/C,KACN,UAAC,OAAD,WACG,EAAO,cAAc,MAAM,MAAI,EAAa,EAAO,cAAc,YAAY,EAAE,KAAG,IAClF,EAAO,cAAc,gBAAkB,UACpC,wBACA,mCACA,IACL,EAAO,SAAS,OAAO,SAAW,EAAI,MACrC,SAAC,KAAD,CAAI,aAAW,gCACZ,EAAO,SAAS,OAAO,KAAK,EAAO,KAClC,SAAC,KAAD,UAAuC,CAAU,EAAxC,GAAG,OAAO,CAAK,EAAE,GAAG,GAAoB,CAClD,CACC,GAEL,EAAO,SAAS,WAAY,SAAC,OAAD,UAAM,uCAA2C,GAAI,MAClF,SAAC,OAAD,CAAM,UAAW,EAAO,oBAAa,EAAO,QAAQ,YAAmB,IACvE,SAAC,OAAD,CAAM,cAAY,OAAO,UAAW,EAAO,YAAe,EACvD,GACP,CACF,CAuDA,OAtDI,EAAO,OAAS,SACX,GACL,iCACE,SAAC,SAAD,UAAS,EAAO,QAAU,YAAc,mBAAqB,uBAAgC,IAC7F,SAAC,OAAD,UAAM,qEAAyE,GAC9E,GAAc,EAAM,WAAa,MAChC,gCACG,EAAM,SAAW,UAAY,IAAqB,MACjD,SAAC,OAAD,CAAM,KAAK,iBAAQ,wFAEb,GACJ,KACH,EAAa,EAAO,QAAQ,aAAc,WAAW,CACtD,IACA,IACJ,GACJ,EAEE,EAAO,OAAS,YACX,GACL,iCACE,SAAC,SAAD,UAAS,GAAa,EAAO,OAAO,CAAU,GAC7C,EAAO,OAAO,WAAW,SAAW,sBACnC,SAAC,EAAD,UAAO,EAAO,OAAO,WAAW,MAAa,GAC3C,MACF,GAAe,EAAO,OAAO,aAAa,SAAW,GACrD,SAAC,OAAD,UAAM,6DAAiE,IAEvE,SAAC,KAAD,CAAI,UAAW,EAAO,yBAClB,GAAe,EAAO,OAAO,aAAa,IAAK,IAC/C,SAAC,KAAD,WACE,SAAC,GAAD,CACE,QAAS,EACT,SAAU,EAAM,SAChB,aACE,EAAY,OAAS,cAAgB,EAAY,UAAU,eAAiB,EAAW,aAEzF,MAAO,EAAO,MACQ,uBACtB,GAAK,IAAiC,OAAY,CAAC,EAAI,CAAE,8BAA6B,EACtF,GAAK,IAAsB,OAAY,CAAC,EAAI,CAAE,mBAAkB,EAChE,WAAY,EAAM,WACN,YACb,EACC,EAdK,EAAW,YAchB,CACL,CACC,IAEN,SAAC,EAAD,CAAa,MAAO,EAAO,OAAO,KAAQ,IAC1C,SAAC,OAAD,UAAM,uFAA2F,EACjG,GACJ,EAGK,GACL,iCACE,SAAC,SAAD,UAAQ,sBAA4B,IACpC,SAAC,OAAD,UAAM,mEAAuE,GAC3E,EAEE,EAAM,WAAa,MACrB,SAAC,OAAD,UAAM,oFAAwF,IAE9F,8BAAG,EAAa,EAAO,QAAQ,aAAc,mBAAmB,CAAI,IAJpE,SAAC,OAAD,UAAM,4CAAgD,GAMvD,EAAM,SAAW,UAChB,SAAC,OAAD,CAAM,KAAK,iBAAQ,uFAA2F,GAC5G,IACJ,GACJ,CACF","names":[],"ignoreList":[],"sources":["../../../src/client/entities/ReviewSuggestionPresentation.tsx","../../../src/client/entities/ReviewSuggestionRevisionHistory.tsx","../../../src/client/entities/ReviewSuggestionRevisionDialog.tsx","../../../src/client/entities/useReviewSuggestionRevisions.ts","../../../src/client/entities/VersionedReviewSuggestionCard.tsx","../../../src/client/entities/PullRequestReviewPanel.tsx"],"sourcesContent":["import { Button, Text } from \"@knpkv/rly/primitives\"\nimport type { ReactElement, ReactNode } from \"react\"\n\nimport type { JobId } from \"../../domain/identifiers.js\"\nimport type { PrReviewNote, PrReviewSuggestion } from \"../../domain/prReview.js\"\nimport styles from \"./WorkspacePullRequestDetails.module.css\"\n\nconst anchorLabel = (suggestion: PrReviewSuggestion): string => {\n switch (suggestion.anchor._tag) {\n case \"line\":\n return `Line suggestion · ${suggestion.anchor.path}:${String(suggestion.anchor.line)}`\n case \"file\":\n return `File suggestion · ${suggestion.anchor.path}:${String(suggestion.anchor.line)}`\n case \"changes\":\n return \"Whole-change suggestion\"\n }\n}\n\nconst replacementSides = (\n unifiedDiff: string\n): {\n readonly after: string\n readonly before: string\n} => {\n const before = new Array<string>()\n const after = new Array<string>()\n let currentPath = \"\"\n let oldLinesRemaining = 0\n let newLinesRemaining = 0\n for (const line of unifiedDiff.split(\"\\n\")) {\n const hunk = /^@@ -\\d+(?:,(\\d+))? \\+\\d+(?:,(\\d+))? @@/u.exec(line)\n if (hunk !== null) {\n const boundary = `⋯ ${currentPath} · ${line}`\n before.push(boundary)\n after.push(boundary)\n oldLinesRemaining = Number(hunk[1] ?? \"1\")\n newLinesRemaining = Number(hunk[2] ?? \"1\")\n continue\n }\n if (oldLinesRemaining === 0 && newLinesRemaining === 0) {\n if (line.startsWith(\"+++ \")) currentPath = line.slice(4).replace(/^b\\//u, \"\")\n continue\n }\n if (line === \"\\\\") continue\n if (line.startsWith(\"-\") && oldLinesRemaining > 0) {\n before.push(line.slice(1))\n oldLinesRemaining -= 1\n continue\n }\n if (line.startsWith(\"+\") && newLinesRemaining > 0) {\n after.push(line.slice(1))\n newLinesRemaining -= 1\n continue\n }\n if (line.startsWith(\" \") && oldLinesRemaining > 0 && newLinesRemaining > 0) {\n const content = line.slice(1)\n before.push(content)\n after.push(content)\n oldLinesRemaining -= 1\n newLinesRemaining -= 1\n continue\n }\n }\n return {\n before: before.join(\"\\n\"),\n after: after.join(\"\\n\")\n }\n}\n\nconst suggestionStateLabel = (state: PrReviewSuggestion[\"state\"]): string =>\n `${state.slice(0, 1).toUpperCase()}${state.slice(1)}`\n\n/** Present one publishable, evidence-backed suggestion without owning its lifecycle. */\nexport const ReviewSuggestionCard = ({\n canPublish,\n extraActions,\n isPreviewing,\n jobId,\n metadata,\n onPreviewPublication,\n publicationBlockedReason,\n suggestion\n}: {\n readonly canPublish: boolean\n readonly extraActions?: ReactNode\n readonly isPreviewing: boolean\n readonly jobId: JobId\n readonly metadata?: ReactNode\n readonly onPreviewPublication: (selection: {\n readonly jobId: JobId\n readonly suggestionId: PrReviewSuggestion[\"suggestionId\"]\n }) => void\n readonly publicationBlockedReason?: string\n readonly suggestion: PrReviewSuggestion\n}): ReactElement => {\n const replacement = suggestion.replacement === undefined ? null : replacementSides(suggestion.replacement.unifiedDiff)\n\n return (\n <article className={styles.suggestionCard} data-severity={suggestion.severity}>\n <header className={styles.suggestionHeading}>\n <span className={styles.severity}>{suggestion.severity}</span>\n <span>\n <small>{anchorLabel(suggestion)}</small>\n <strong>{suggestion.title}</strong>\n </span>\n <span className={styles.confidence}>\n {suggestionStateLabel(suggestion.state)} · {suggestion.confidence.level} confidence\n </span>\n </header>\n {metadata}\n\n <Text>{suggestion.problem}</Text>\n <dl className={styles.suggestionDetails}>\n <div>\n <dt>Impact</dt>\n <dd>{suggestion.impact}</dd>\n </div>\n <div>\n <dt>Recommendation</dt>\n <dd>{suggestion.recommendation}</dd>\n </div>\n </dl>\n <details>\n <summary>Evidence and confidence</summary>\n <code>\n {suggestion.evidence.path}:{String(suggestion.evidence.startLine)}\n {suggestion.evidence.endLine === suggestion.evidence.startLine\n ? \"\"\n : `–${String(suggestion.evidence.endLine)}`}\n </code>\n <pre>{suggestion.evidence.excerpt}</pre>\n <Text>{suggestion.confidence.reason}</Text>\n </details>\n\n {suggestion.relatedLocations.length === 0 ? null : (\n <section aria-label=\"Related locations\" className={styles.relatedLocations}>\n <strong>Related locations</strong>\n <ul>\n {suggestion.relatedLocations.map((location) => (\n <li key={`${location.path}:${String(location.startLine)}:${String(location.endLine)}`}>\n <code>\n {location.path}:{String(location.startLine)}\n {location.endLine === location.startLine ? \"\" : `–${String(location.endLine)}`}\n </code>\n <span>{location.label}</span>\n </li>\n ))}\n </ul>\n </section>\n )}\n\n {replacement === null || suggestion.replacement === undefined ? null : (\n <section aria-label=\"Suggested replacement\" className={styles.replacementPreview}>\n <header>\n <strong>Suggested replacement</strong>\n <span>Inert patch · {suggestion.replacement.reviewedHead.slice(0, 12)}</span>\n </header>\n <Text>{suggestion.replacement.explanation}</Text>\n <div>\n <figure>\n <figcaption>Before</figcaption>\n <pre>{replacement.before}</pre>\n </figure>\n <figure>\n <figcaption>After</figcaption>\n <pre>{replacement.after}</pre>\n </figure>\n </div>\n </section>\n )}\n\n {suggestion.prevention === undefined ? null : suggestion.prevention.enforcement === \"none\" ? (\n <details className={styles.preventionProposal}>\n <summary>Prevention note · no stable guardrail</summary>\n <Text>\n {suggestion.prevention.summary} · {suggestion.prevention.rationale}\n </Text>\n </details>\n ) : (\n <details className={styles.preventionProposal}>\n <summary>Prevention proposal · separate review required</summary>\n <Text>\n {suggestion.prevention.summary} · {suggestion.prevention.enforcement}\n </Text>\n <dl>\n <dt>Recurring evidence</dt>\n <dd>{suggestion.prevention.recurrenceEvidence}</dd>\n <dt>Existing rule or configuration</dt>\n <dd>{suggestion.prevention.existingRuleOrConfig}</dd>\n <dt>Target file</dt>\n <dd>{suggestion.prevention.targetFile}</dd>\n <dt>Source paths</dt>\n <dd>{suggestion.prevention.sourcePaths.join(\", \")}</dd>\n <dt>Matcher or invariant</dt>\n <dd>{suggestion.prevention.matcherOrInvariant}</dd>\n <dt>Invalid fixture</dt>\n <dd>\n <pre>{suggestion.prevention.invalidFixture}</pre>\n </dd>\n <dt>Valid fixture</dt>\n <dd>\n <pre>{suggestion.prevention.validFixture}</pre>\n </dd>\n <dt>Boundary and exclusions</dt>\n <dd>{suggestion.prevention.boundary}</dd>\n </dl>\n </details>\n )}\n\n {extraActions === undefined && (!canPublish || suggestion.state !== \"draft\") ? null : (\n <div className={styles.suggestionActions}>\n {extraActions}\n {canPublish && suggestion.state === \"draft\" ? (\n <Button\n disabled={isPreviewing || publicationBlockedReason !== undefined}\n onClick={() =>\n onPreviewPublication({\n jobId,\n suggestionId: suggestion.suggestionId\n })\n }\n >\n {isPreviewing ? \"Preparing approval…\" : \"Review & approve\"}\n </Button>\n ) : null}\n </div>\n )}\n {publicationBlockedReason === undefined ? null : (\n <Text role=\"status\" tone=\"secondary\" variant=\"meta\">\n {publicationBlockedReason}\n </Text>\n )}\n </article>\n )\n}\n\n/** Keep non-publishable observations visibly separate from actionable suggestions. */\nexport const ReviewNotes = ({ notes }: { readonly notes: ReadonlyArray<PrReviewNote> }): ReactElement | null =>\n notes.length === 0 ? null : (\n <section aria-labelledby=\"review-notes-title\" className={styles.reviewNotes}>\n <header>\n <span>\n <small>Never publishable</small>\n <strong id=\"review-notes-title\">Review Notes</strong>\n </span>\n <span>{notes.length}</span>\n </header>\n <ul>\n {notes.map((note) => (\n <li key={note.noteId}>\n <span>\n {note.reason === \"pre-existing\" ? \"Pre-existing\" : \"Low confidence\"} · {note.confidence.level}\n </span>\n <strong>{note.title}</strong>\n <Text>{note.observation}</Text>\n {note.location === undefined ? null : (\n <code>\n {note.location.path}:{String(note.location.startLine)}\n {note.location.endLine === note.location.startLine ? \"\" : `–${String(note.location.endLine)}`}\n </code>\n )}\n <small>{note.confidence.reason}</small>\n </li>\n ))}\n </ul>\n </section>\n )\n","import { Button, Text } from \"@knpkv/rly/primitives\"\nimport * as DateTime from \"effect/DateTime\"\nimport type { ReactElement } from \"react\"\n\nimport type { PrReviewSuggestionRevision, PrReviewSuggestionRevisionPage } from \"../../domain/prReviewRevision.js\"\nimport styles from \"./WorkspacePullRequestDetails.module.css\"\n\nexport const reviewSuggestionRevisionAuthorLabel = (revision: PrReviewSuggestionRevision): string =>\n revision.author._tag === \"operator\"\n ? \"Operator\"\n : `${revision.author.providerId}${revision.author.model === null ? \"\" : ` · ${revision.author.model}`}`\n\nexport const reviewSuggestionRevisionValidationLabel = (revision: PrReviewSuggestionRevision): string =>\n revision.validation._tag === \"validated\" ? \"Validated\" : \"Needs revalidation\"\n\n/** Inspect complete immutable suggestion history without leaving the diff. */\nexport const ReviewSuggestionRevisionHistory = ({\n loadEarlier,\n loadingEarlier,\n page\n}: {\n readonly loadEarlier: () => void\n readonly loadingEarlier: boolean\n readonly page: PrReviewSuggestionRevisionPage\n}): ReactElement => {\n const revisions = [page.current, ...page.revisions.filter(({ revisionId }) => revisionId !== page.current.revisionId)]\n return (\n <div className={styles.revisionHistory}>\n <ol>\n {revisions.map((revision) => (\n <li key={revision.revisionId}>\n <header>\n <strong>Revision {String(revision.sequence)}</strong>\n <span>\n {reviewSuggestionRevisionValidationLabel(revision)} · {reviewSuggestionRevisionAuthorLabel(revision)}\n </span>\n </header>\n <time dateTime={DateTime.formatIso(revision.createdAt)}>\n {DateTime.formatLocal(revision.createdAt, {\n dateStyle: \"medium\",\n timeStyle: \"short\"\n })}\n </time>\n <details>\n <summary>{revision.suggestion.title}</summary>\n <Text>{revision.suggestion.problem}</Text>\n <dl>\n <dt>Impact</dt>\n <dd>{revision.suggestion.impact}</dd>\n <dt>Recommendation</dt>\n <dd>{revision.suggestion.recommendation}</dd>\n <dt>Severity</dt>\n <dd>{revision.suggestion.severity}</dd>\n <dt>Confidence</dt>\n <dd>\n {revision.suggestion.confidence.level} · {revision.suggestion.confidence.reason}\n </dd>\n <dt>Evidence</dt>\n <dd>\n <code>\n {revision.suggestion.evidence.path}:{String(revision.suggestion.evidence.startLine)}\n </code>\n <pre>{revision.suggestion.evidence.excerpt}</pre>\n </dd>\n <dt>Anchor</dt>\n <dd>\n <code>{JSON.stringify(revision.suggestion.anchor)}</code>\n </dd>\n <dt>Related locations</dt>\n <dd>\n {revision.suggestion.relatedLocations.length === 0 ? (\n \"None\"\n ) : (\n <pre>{JSON.stringify(revision.suggestion.relatedLocations, null, 2)}</pre>\n )}\n </dd>\n <dt>Replacement</dt>\n <dd>\n {revision.suggestion.replacement === undefined ? (\n \"None\"\n ) : (\n <>\n <Text>{revision.suggestion.replacement.explanation}</Text>\n <pre>{revision.suggestion.replacement.unifiedDiff}</pre>\n </>\n )}\n </dd>\n <dt>Prevention</dt>\n <dd>\n {revision.suggestion.prevention === undefined ? (\n \"None\"\n ) : (\n <pre>{JSON.stringify(revision.suggestion.prevention, null, 2)}</pre>\n )}\n </dd>\n </dl>\n </details>\n </li>\n ))}\n </ol>\n {page.hasMore ? (\n <Button aria-busy={loadingEarlier} disabled={loadingEarlier} loading={loadingEarlier} onClick={loadEarlier}>\n {loadingEarlier ? \"Loading earlier revisions…\" : \"Load earlier revisions\"}\n </Button>\n ) : null}\n </div>\n )\n}\n","import { Button, Dialog, Text } from \"@knpkv/rly/primitives\"\nimport * as Result from \"effect/Result\"\nimport * as Schema from \"effect/Schema\"\nimport { type ReactElement, useEffect, useMemo, useState } from \"react\"\n\nimport { PrReviewSuggestion } from \"../../domain/prReview.js\"\nimport { PrReviewSuggestionEdit, type PrReviewSuggestionRevisionPage } from \"../../domain/prReviewRevision.js\"\nimport {\n ReviewSuggestionRevisionHistory,\n reviewSuggestionRevisionAuthorLabel,\n reviewSuggestionRevisionValidationLabel\n} from \"./ReviewSuggestionRevisionHistory.js\"\nimport styles from \"./WorkspacePullRequestDetails.module.css\"\n\nconst AdvancedSuggestionFields = Schema.Struct({\n anchor: PrReviewSuggestion.fields.anchor,\n evidence: PrReviewSuggestion.fields.evidence,\n relatedLocations: PrReviewSuggestion.fields.relatedLocations,\n replacement: PrReviewSuggestion.fields.replacement,\n prevention: PrReviewSuggestion.fields.prevention\n})\nconst AdvancedSuggestionFieldsJson = Schema.fromJsonString(AdvancedSuggestionFields)\nconst narrativeFields = [\n [\"Problem\", \"problem\"],\n [\"Impact\", \"impact\"],\n [\"Recommendation\", \"recommendation\"]\n] satisfies ReadonlyArray<readonly [string, \"impact\" | \"problem\" | \"recommendation\"]>\n\nconst editableSuggestion = (suggestion: PrReviewSuggestion): PrReviewSuggestionEdit => ({\n title: suggestion.title,\n severity: suggestion.severity,\n problem: suggestion.problem,\n impact: suggestion.impact,\n evidence: suggestion.evidence,\n recommendation: suggestion.recommendation,\n confidence: suggestion.confidence,\n relatedLocations: suggestion.relatedLocations,\n ...(suggestion.prevention === undefined ? {} : { prevention: suggestion.prevention }),\n ...(suggestion.replacement === undefined ? {} : { replacement: suggestion.replacement }),\n anchor: suggestion.anchor\n})\n\nconst advancedJson = (suggestion: PrReviewSuggestionEdit): string =>\n Schema.encodeSync(AdvancedSuggestionFieldsJson)({\n anchor: suggestion.anchor,\n evidence: suggestion.evidence,\n relatedLocations: suggestion.relatedLocations,\n ...(suggestion.prevention === undefined ? {} : { prevention: suggestion.prevention }),\n ...(suggestion.replacement === undefined ? {} : { replacement: suggestion.replacement })\n })\n\n/** Edit or inspect one immutable suggestion revision without leaving the diff. */\nexport const ReviewSuggestionRevisionDialog = ({\n canEdit,\n conflict,\n loadEarlier,\n loadingEarlier,\n mode,\n onOpenChange,\n onResolveConflict,\n onSave,\n open,\n page,\n preservedDraft,\n saving\n}: {\n readonly canEdit: boolean\n readonly conflict: boolean\n readonly loadEarlier: () => void\n readonly loadingEarlier: boolean\n readonly mode: \"edit\" | \"history\"\n readonly onOpenChange: (open: boolean) => void\n readonly onResolveConflict: () => void\n readonly onSave: (edit: PrReviewSuggestionEdit) => void\n readonly open: boolean\n readonly page: PrReviewSuggestionRevisionPage\n readonly preservedDraft: PrReviewSuggestionEdit | null\n readonly saving: boolean\n}): ReactElement => {\n const current = page.current\n const [draft, setDraft] = useState(() => editableSuggestion(current.suggestion))\n const [advanced, setAdvanced] = useState(() => advancedJson(current.suggestion))\n const [advancedError, setAdvancedError] = useState(false)\n useEffect(() => {\n if (!open) return\n const nextDraft = preservedDraft ?? editableSuggestion(current.suggestion)\n setDraft(nextDraft)\n setAdvanced(advancedJson(nextDraft))\n setAdvancedError(false)\n }, [current.revisionId, current.suggestion, open, preservedDraft])\n const description = useMemo(\n () =>\n `Revision ${String(current.sequence)} · ${reviewSuggestionRevisionValidationLabel(\n current\n )} · ${reviewSuggestionRevisionAuthorLabel(current)}`,\n [current]\n )\n const save = (): void => {\n const decoded = Schema.decodeUnknownResult(AdvancedSuggestionFieldsJson)(advanced)\n if (Result.isFailure(decoded)) {\n setAdvancedError(true)\n return\n }\n setAdvancedError(false)\n const edit = Schema.decodeUnknownResult(PrReviewSuggestionEdit)({\n title: draft.title,\n severity: draft.severity,\n problem: draft.problem,\n impact: draft.impact,\n recommendation: draft.recommendation,\n confidence: draft.confidence,\n ...decoded.success\n })\n if (Result.isFailure(edit)) {\n setAdvancedError(true)\n return\n }\n onSave(edit.success)\n }\n\n return (\n <Dialog.Root onOpenChange={onOpenChange} open={open}>\n <Dialog.Content\n className={styles.revisionDialog}\n description={description}\n size=\"wide\"\n title={mode === \"edit\" ? \"Edit review suggestion\" : \"Revision history\"}\n >\n {mode === \"history\" ? (\n <ReviewSuggestionRevisionHistory loadEarlier={loadEarlier} loadingEarlier={loadingEarlier} page={page} />\n ) : (\n <form\n className={styles.revisionEditor}\n onSubmit={(event) => {\n event.preventDefault()\n save()\n }}\n >\n <div className={styles.revisionEditorLead}>\n <label>\n <span>Title</span>\n <input\n maxLength={500}\n onChange={(event) => setDraft({ ...draft, title: event.currentTarget.value })}\n required\n value={draft.title}\n />\n </label>\n <label>\n <span>Severity</span>\n <select\n onChange={(event) => {\n const severity = Schema.decodeUnknownResult(PrReviewSuggestion.fields.severity)(\n event.currentTarget.value\n )\n if (Result.isFailure(severity)) return\n setDraft({ ...draft, severity: severity.success })\n }}\n value={draft.severity}\n >\n <option value=\"P1\">P1</option>\n <option value=\"P2\">P2</option>\n <option value=\"P3\">P3</option>\n <option value=\"P4\">P4</option>\n </select>\n </label>\n <label>\n <span>Confidence</span>\n <select\n onChange={(event) => {\n const level = Schema.decodeUnknownResult(PrReviewSuggestion.fields.confidence.fields.level)(\n event.currentTarget.value\n )\n if (Result.isFailure(level)) return\n setDraft({\n ...draft,\n confidence: {\n ...draft.confidence,\n level: level.success\n }\n })\n }}\n value={draft.confidence.level}\n >\n <option value=\"high\">High</option>\n <option value=\"medium\">Medium</option>\n </select>\n </label>\n </div>\n {narrativeFields.map(([label, field]) => (\n <label key={field}>\n <span>{label}</span>\n <textarea\n maxLength={4_000}\n onChange={(event) =>\n setDraft({\n ...draft,\n [field]: event.currentTarget.value\n })\n }\n required\n rows={4}\n value={draft[field]}\n />\n </label>\n ))}\n <label>\n <span>Confidence reason</span>\n <textarea\n maxLength={2_000}\n onChange={(event) =>\n setDraft({\n ...draft,\n confidence: {\n ...draft.confidence,\n reason: event.currentTarget.value\n }\n })\n }\n required\n rows={3}\n value={draft.confidence.reason}\n />\n </label>\n <details className={styles.revisionAdvanced}>\n <summary>Advanced evidence, anchor, replacement and prevention</summary>\n <Text tone=\"secondary\">\n Complete schema-checked JSON. Invalid or incoherent evidence cannot be saved.\n </Text>\n <textarea\n aria-describedby={advancedError ? \"revision-advanced-error\" : undefined}\n aria-invalid={advancedError}\n aria-label=\"Advanced evidence, anchor, replacement and prevention JSON\"\n onChange={(event) => setAdvanced(event.currentTarget.value)}\n rows={14}\n spellCheck={false}\n value={advanced}\n />\n {advancedError ? (\n <span id=\"revision-advanced-error\" role=\"alert\">\n Advanced fields are not a valid complete suggestion.\n </span>\n ) : null}\n </details>\n {conflict ? (\n <div role=\"alert\">\n <span>A newer revision won. Your draft is preserved, but cannot be saved over the winner.</span>\n <Button onClick={onResolveConflict} type=\"button\" variant=\"quiet\">\n Use latest revision\n </Button>\n </div>\n ) : current.validation._tag === \"requires-revalidation\" ? (\n <span role=\"status\">Technical changes remain blocked from publication until revalidated.</span>\n ) : null}\n <div className={styles.revisionDialogActions}>\n <Dialog.Close disabled={saving}>Cancel</Dialog.Close>\n <Button disabled={!canEdit || saving} loading={saving} type=\"submit\">\n {saving ? \"Saving revision…\" : \"Save revision\"}\n </Button>\n </div>\n </form>\n )}\n </Dialog.Content>\n </Dialog.Root>\n )\n}\n","import * as Effect from \"effect/Effect\"\nimport * as Predicate from \"effect/Predicate\"\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\nimport type {\n DismissReviewSuggestionRequest,\n DismissReviewSuggestionResponse,\n EditReviewSuggestionRequest,\n EditReviewSuggestionResponse,\n ReviewSuggestionRevisionPage\n} from \"../../api/agent.js\"\nimport { makeControlCenterApiClient } from \"../../api/client.js\"\nimport type { EntityId, JobId } from \"../../domain/identifiers.js\"\nimport type { PrReviewSuggestion, PrReviewSuggestionId } from \"../../domain/prReview.js\"\nimport {\n type PrReviewSuggestionEdit,\n PrReviewSuggestionRevisionPageSize,\n type PrReviewSuggestionRevisionSequence\n} from \"../../domain/prReviewRevision.js\"\nimport { makeAuthenticatedMutationClient } from \"../authenticatedMutationClient.js\"\n\nconst REVISION_PAGE_SIZE = PrReviewSuggestionRevisionPageSize.make(24)\n\nexport interface ReviewSuggestionRevisionScope {\n readonly entityId: EntityId\n readonly jobId: JobId\n readonly sessionKey: string\n readonly suggestionId: PrReviewSuggestionId\n}\n\nexport interface ReviewSuggestionRevisionTransport {\n readonly dismiss?: (\n scope: ReviewSuggestionRevisionScope,\n request: DismissReviewSuggestionRequest,\n signal: AbortSignal\n ) => Promise<DismissReviewSuggestionResponse>\n readonly edit: (\n scope: ReviewSuggestionRevisionScope,\n request: EditReviewSuggestionRequest,\n signal: AbortSignal\n ) => Promise<EditReviewSuggestionResponse>\n readonly load: (\n scope: ReviewSuggestionRevisionScope,\n before: PrReviewSuggestionRevisionSequence | null,\n signal: AbortSignal\n ) => Promise<ReviewSuggestionRevisionPage>\n}\n\nexport type ReviewSuggestionRevisionAccepted = (suggestion: PrReviewSuggestion) => void\n\nexport type ReviewSuggestionRevisionState =\n | { readonly _tag: \"idle\" }\n | { readonly _tag: \"loading\" }\n | { readonly _tag: \"ready\"; readonly page: ReviewSuggestionRevisionPage }\n | { readonly _tag: \"dismissing\"; readonly page: ReviewSuggestionRevisionPage }\n | {\n readonly _tag: \"saving\"\n readonly draft: PrReviewSuggestionEdit\n readonly page: ReviewSuggestionRevisionPage\n }\n | {\n readonly _tag: \"conflict\"\n readonly draft: PrReviewSuggestionEdit\n readonly page: ReviewSuggestionRevisionPage\n }\n | {\n readonly _tag: \"failed\"\n readonly draft: PrReviewSuggestionEdit | null\n readonly page: ReviewSuggestionRevisionPage | null\n }\n\nexport const browserReviewSuggestionRevisionTransport: ReviewSuggestionRevisionTransport = {\n dismiss: (scope, request, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.dismissReviewSuggestion({\n params: {\n entityId: scope.entityId,\n jobId: scope.jobId,\n suggestionId: scope.suggestionId\n },\n payload: request\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n edit: (scope, request, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeAuthenticatedMutationClient\n return yield* client.agent.editReviewSuggestion({\n params: {\n entityId: scope.entityId,\n jobId: scope.jobId,\n suggestionId: scope.suggestionId\n },\n payload: request\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n ),\n load: (scope, before, signal) =>\n Effect.runPromise(\n Effect.gen(function*() {\n const client = yield* makeControlCenterApiClient()\n return yield* client.agent.reviewSuggestionRevisions({\n params: {\n entityId: scope.entityId,\n jobId: scope.jobId,\n suggestionId: scope.suggestionId\n },\n query: {\n ...(before === null ? {} : { before }),\n limit: REVISION_PAGE_SIZE\n }\n })\n }).pipe(Effect.provide(FetchHttpClient.layer)),\n { signal }\n )\n}\n\nconst sameScope = (\n left: ReviewSuggestionRevisionScope,\n right: ReviewSuggestionRevisionScope\n): boolean =>\n left.entityId === right.entityId &&\n left.jobId === right.jobId &&\n left.sessionKey === right.sessionKey &&\n left.suggestionId === right.suggestionId\n\nconst mergePages = (\n retained: ReviewSuggestionRevisionPage,\n earlier: ReviewSuggestionRevisionPage\n): ReviewSuggestionRevisionPage => {\n const current = earlier.current.sequence > retained.current.sequence\n ? earlier.current\n : retained.current\n const revisions = new Map(\n [\n retained.current,\n earlier.current,\n ...retained.revisions,\n ...earlier.revisions\n ]\n .filter(({ revisionId }) => revisionId !== current.revisionId)\n .map((revision) => [revision.revisionId, revision])\n )\n return {\n current,\n revisions: [...revisions.values()].sort(\n (left, right) => right.sequence - left.sequence\n ),\n hasMore: earlier.hasMore,\n nextBeforeSequence: earlier.nextBeforeSequence\n }\n}\n\nconst pageWithAcceptedRevision = (\n retained: ReviewSuggestionRevisionPage,\n accepted: ReviewSuggestionRevisionPage[\"current\"]\n): ReviewSuggestionRevisionPage => ({\n current: accepted,\n revisions: [retained.current, ...retained.revisions]\n .filter(({ revisionId }) => revisionId !== accepted.revisionId)\n .sort((left, right) => right.sequence - left.sequence),\n hasMore: retained.hasMore,\n nextBeforeSequence: retained.nextBeforeSequence\n})\n\ntype SaveOutcome =\n | { readonly _tag: \"accepted-refresh-failed\"; readonly page: ReviewSuggestionRevisionPage }\n | { readonly _tag: \"conflict\"; readonly page: ReviewSuggestionRevisionPage }\n | { readonly _tag: \"refreshed\"; readonly page: ReviewSuggestionRevisionPage }\n\nconst saveOutcome = (\n _tag: SaveOutcome[\"_tag\"],\n page: ReviewSuggestionRevisionPage\n): SaveOutcome => ({ _tag, page })\n\nconst conflictFailure = Predicate.isTagged(\"ConflictApiError\")\nconst ignoreAcceptedRevision = (_suggestion: PrReviewSuggestion): void => undefined\n\n/** Scope-safe browser controller for one stable suggestion's immutable revisions. */\nexport const useReviewSuggestionRevisions = (\n scope: ReviewSuggestionRevisionScope | null,\n transport: ReviewSuggestionRevisionTransport = browserReviewSuggestionRevisionTransport,\n onAccepted: ReviewSuggestionRevisionAccepted = ignoreAcceptedRevision\n): {\n readonly dismiss: () => void\n readonly loadEarlier: () => void\n readonly loadingEarlier: boolean\n readonly resolveConflict: () => void\n readonly retry: () => void\n readonly save: (draft: PrReviewSuggestionEdit) => void\n readonly state: ReviewSuggestionRevisionState\n} => {\n const [requestRevision, setRequestRevision] = useState(0)\n const [loadingEarlier, setLoadingEarlier] = useState(false)\n const [state, setState] = useState<ReviewSuggestionRevisionState>({ _tag: \"idle\" })\n const activeAbort = useRef<AbortController | null>(null)\n const loadingEarlierRef = useRef(false)\n const latestScope = useRef(scope)\n const latestOnAccepted = useRef(onAccepted)\n latestScope.current = scope\n latestOnAccepted.current = onAccepted\n\n useEffect(() => {\n activeAbort.current?.abort()\n loadingEarlierRef.current = false\n setLoadingEarlier(false)\n if (scope === null) {\n setState({ _tag: \"idle\" })\n return\n }\n const current = scope\n const abort = new AbortController()\n activeAbort.current = abort\n setState({ _tag: \"loading\" })\n transport.load(current, null, abort.signal).then(\n (page) => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return\n setState({ _tag: \"ready\", page })\n },\n () => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return\n setState({ _tag: \"failed\", draft: null, page: null })\n }\n )\n return () => abort.abort()\n }, [requestRevision, scope, transport])\n\n const save = useCallback((draft: PrReviewSuggestionEdit): void => {\n if (scope === null || state._tag === \"conflict\") return\n const retained = state._tag === \"ready\"\n ? state.page\n : state._tag === \"failed\"\n ? state.page\n : null\n if (retained === null) return\n const current = scope\n activeAbort.current?.abort()\n loadingEarlierRef.current = false\n setLoadingEarlier(false)\n const abort = new AbortController()\n activeAbort.current = abort\n setState({ _tag: \"saving\", draft, page: retained })\n transport.edit(current, {\n expectedRevisionId: retained.current.revisionId,\n expectedSequence: retained.current.sequence,\n edit: draft\n }, abort.signal).then(\n (accepted) => {\n const acceptedPage = pageWithAcceptedRevision(retained, accepted)\n return transport.load(current, null, abort.signal).then(\n (page) => saveOutcome(\"refreshed\", page),\n () => saveOutcome(\"accepted-refresh-failed\", acceptedPage)\n )\n },\n (failure: unknown) => {\n if (!conflictFailure(failure)) throw failure\n return transport.load(current, null, abort.signal).then((page) => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return saveOutcome(\"conflict\", page)\n setState({ _tag: \"conflict\", draft, page })\n return saveOutcome(\"conflict\", page)\n })\n }\n ).then(\n (outcome) => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return\n setState((latest) =>\n latest._tag === \"conflict\"\n ? latest\n : outcome._tag === \"accepted-refresh-failed\"\n ? { _tag: \"failed\", draft: null, page: outcome.page }\n : { _tag: \"ready\", page: outcome.page }\n )\n if (outcome._tag !== \"conflict\") latestOnAccepted.current(outcome.page.current.suggestion)\n },\n () => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return\n setState({ _tag: \"failed\", draft, page: retained })\n }\n )\n }, [scope, state, transport])\n\n const dismiss = useCallback((): void => {\n if (scope === null || state._tag !== \"ready\" || transport.dismiss === undefined) return\n const current = scope\n const retained = state.page\n activeAbort.current?.abort()\n loadingEarlierRef.current = false\n setLoadingEarlier(false)\n const abort = new AbortController()\n activeAbort.current = abort\n setState({ _tag: \"dismissing\", page: retained })\n transport.dismiss(current, {\n expectedRevisionId: retained.current.revisionId,\n expectedSequence: retained.current.sequence\n }, abort.signal).then(\n (accepted) => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return\n setState({\n _tag: \"ready\",\n page: pageWithAcceptedRevision(retained, accepted)\n })\n latestOnAccepted.current(accepted.suggestion)\n },\n () => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return\n setState({ _tag: \"failed\", draft: null, page: retained })\n }\n )\n }, [scope, state, transport])\n\n const loadEarlier = useCallback((): void => {\n if (\n scope === null ||\n (state._tag !== \"ready\" && state._tag !== \"conflict\") ||\n loadingEarlierRef.current ||\n !state.page.hasMore ||\n state.page.nextBeforeSequence === null\n ) return\n const current = scope\n const retained = state.page\n activeAbort.current?.abort()\n const abort = new AbortController()\n activeAbort.current = abort\n loadingEarlierRef.current = true\n setLoadingEarlier(true)\n transport.load(\n current,\n retained.nextBeforeSequence,\n abort.signal\n ).then(\n (page) => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return\n if (activeAbort.current !== abort) return\n setState((latest) =>\n latest._tag === \"ready\" || latest._tag === \"conflict\"\n ? { ...latest, page: mergePages(latest.page, page) }\n : latest\n )\n loadingEarlierRef.current = false\n setLoadingEarlier(false)\n },\n () => {\n if (\n abort.signal.aborted ||\n latestScope.current === null ||\n !sameScope(latestScope.current, current)\n ) return\n if (activeAbort.current !== abort) return\n setState((latest) =>\n latest._tag === \"ready\"\n ? { _tag: \"failed\", draft: null, page: latest.page }\n : latest\n )\n loadingEarlierRef.current = false\n setLoadingEarlier(false)\n }\n )\n }, [scope, state, transport])\n\n return useMemo(() => ({\n dismiss,\n loadEarlier,\n loadingEarlier,\n resolveConflict: () =>\n setState((latest) =>\n latest._tag === \"conflict\"\n ? { _tag: \"ready\", page: latest.page }\n : latest\n ),\n retry: () => {\n if (state._tag === \"conflict\") return\n if (\n state._tag === \"failed\" &&\n state.draft !== null &&\n state.page !== null\n ) {\n save(state.draft)\n return\n }\n setRequestRevision((revision) => revision + 1)\n },\n save,\n state\n }), [dismiss, loadEarlier, loadingEarlier, save, state])\n}\n","import { Button, Dialog, Text } from \"@knpkv/rly/primitives\"\nimport * as DateTime from \"effect/DateTime\"\nimport { type ReactElement, useMemo, useState } from \"react\"\n\nimport type { EntityId, JobId } from \"../../domain/identifiers.js\"\nimport type { PrReviewSuggestion } from \"../../domain/prReview.js\"\nimport type { PrReviewSuggestionRevisionAuthor } from \"../../domain/prReviewRevision.js\"\nimport { ReviewSuggestionCard } from \"./ReviewSuggestionPresentation.js\"\nimport { ReviewSuggestionRevisionDialog } from \"./ReviewSuggestionRevisionDialog.js\"\nimport {\n browserReviewSuggestionRevisionTransport,\n useReviewSuggestionRevisions,\n type ReviewSuggestionRevisionScope,\n type ReviewSuggestionRevisionTransport\n} from \"./useReviewSuggestionRevisions.js\"\nimport type { ReviewSuggestionPublicationTarget } from \"./usePullRequestReview.js\"\nimport styles from \"./WorkspacePullRequestDetails.module.css\"\n\nconst authorLabel = (author: PrReviewSuggestionRevisionAuthor): string =>\n author._tag === \"operator\" ? \"Operator\" : author.providerId\n\n/** Enrich one immediate review-report card with its durable current revision. */\nexport const VersionedReviewSuggestionCard = ({\n canEdit,\n entityId,\n isPreviewing,\n jobId,\n onPreviewPublication,\n onSuggestionRevisionAccepted,\n revisionTransport = browserReviewSuggestionRevisionTransport,\n sessionKey,\n suggestion\n}: {\n readonly canEdit: boolean\n readonly entityId: EntityId\n readonly isPreviewing: boolean\n readonly jobId: JobId\n readonly onPreviewPublication: (selection: ReviewSuggestionPublicationTarget) => void\n readonly onSuggestionRevisionAccepted?: (suggestion: PrReviewSuggestion) => void\n readonly revisionTransport?: ReviewSuggestionRevisionTransport\n readonly sessionKey: string\n readonly suggestion: PrReviewSuggestion\n}): ReactElement => {\n const scope: ReviewSuggestionRevisionScope = useMemo(\n () => ({\n entityId,\n jobId,\n sessionKey,\n suggestionId: suggestion.suggestionId\n }),\n [entityId, jobId, sessionKey, suggestion.suggestionId]\n )\n const controller = useReviewSuggestionRevisions(scope, revisionTransport, onSuggestionRevisionAccepted)\n const [dialogMode, setDialogMode] = useState<\"edit\" | \"history\">(\"history\")\n const [dialogOpen, setDialogOpen] = useState(false)\n const [dismissOpen, setDismissOpen] = useState(false)\n const page =\n controller.state._tag === \"ready\" ||\n controller.state._tag === \"dismissing\" ||\n controller.state._tag === \"saving\" ||\n controller.state._tag === \"conflict\"\n ? controller.state.page\n : controller.state._tag === \"failed\"\n ? controller.state.page\n : null\n const preservedDraft =\n controller.state._tag === \"saving\" || controller.state._tag === \"conflict\" || controller.state._tag === \"failed\"\n ? controller.state.draft\n : null\n const current = page?.current\n const presentedSuggestion: PrReviewSuggestion =\n current === undefined\n ? suggestion\n : {\n ...current.suggestion,\n state: suggestion.state === \"published\" ? \"published\" : current.suggestion.state\n }\n const suggestionCanMutate = canEdit && presentedSuggestion.state === \"draft\" && controller.state._tag !== \"dismissing\"\n const validationBlocked = current?.validation._tag === \"requires-revalidation\"\n const publicationBlockedReason =\n controller.state._tag === \"loading\"\n ? \"Loading the exact revision before publication.\"\n : controller.state._tag === \"failed\"\n ? \"Revision history is unavailable. Retry before publishing.\"\n : validationBlocked\n ? \"This technical edit needs agent revalidation before it can be posted.\"\n : undefined\n const openDialog = (mode: \"edit\" | \"history\"): void => {\n setDialogMode(mode)\n setDialogOpen(true)\n }\n\n return (\n <>\n <ReviewSuggestionCard\n canPublish={suggestionCanMutate}\n extraActions={\n <>\n <Button disabled={page === null} onClick={() => openDialog(\"history\")} variant=\"quiet\">\n History\n </Button>\n {suggestionCanMutate ? (\n <Button disabled={page === null} onClick={() => openDialog(\"edit\")} variant=\"quiet\">\n Edit\n </Button>\n ) : null}\n {suggestionCanMutate ? (\n <Button disabled={page === null} onClick={() => setDismissOpen(true)} variant=\"quiet\">\n Dismiss\n </Button>\n ) : null}\n {controller.state._tag === \"dismissing\" ? (\n <Button disabled variant=\"quiet\">\n Dismissing…\n </Button>\n ) : null}\n {controller.state._tag === \"failed\" ? (\n <Button onClick={controller.retry} variant=\"quiet\">\n Retry revision\n </Button>\n ) : null}\n </>\n }\n isPreviewing={isPreviewing}\n jobId={jobId}\n metadata={\n current === undefined ? null : (\n <div className={styles.suggestionRevisionMeta} data-validation={current.validation._tag}>\n <strong>Revision {String(current.sequence)}</strong>\n <span>{current.validation._tag === \"validated\" ? \"Validated\" : \"Needs revalidation\"}</span>\n <span>{authorLabel(current.author)}</span>\n <time dateTime={DateTime.formatIso(current.createdAt)}>\n {DateTime.formatLocal(current.createdAt, {\n dateStyle: \"medium\",\n timeStyle: \"short\"\n })}\n </time>\n </div>\n )\n }\n onPreviewPublication={(selection) => {\n if (current === undefined) return\n onPreviewPublication({\n ...selection,\n revisionId: current.revisionId\n })\n }}\n {...(publicationBlockedReason === undefined ? {} : { publicationBlockedReason })}\n suggestion={presentedSuggestion}\n />\n {page === null ? null : (\n <ReviewSuggestionRevisionDialog\n canEdit={suggestionCanMutate}\n conflict={controller.state._tag === \"conflict\"}\n loadEarlier={controller.loadEarlier}\n loadingEarlier={controller.loadingEarlier}\n mode={dialogMode}\n onOpenChange={setDialogOpen}\n onResolveConflict={controller.resolveConflict}\n onSave={controller.save}\n open={dialogOpen}\n page={page}\n preservedDraft={preservedDraft}\n saving={controller.state._tag === \"saving\"}\n />\n )}\n <Dialog.Root onOpenChange={setDismissOpen} open={dismissOpen}>\n <Dialog.Content\n description=\"Dismiss this finding for the reviewed head. It will remain in revision history and will not be posted to CodeCommit.\"\n size=\"default\"\n title=\"Dismiss finding?\"\n >\n <Text>This records your decision without changing the pull request or publishing a comment.</Text>\n <div className={styles.publicationActions}>\n <Dialog.Close>Keep finding</Dialog.Close>\n <Button\n onClick={() => {\n setDismissOpen(false)\n controller.dismiss()\n }}\n >\n Dismiss finding\n </Button>\n </div>\n </Dialog.Content>\n </Dialog.Root>\n </>\n )\n}\n","import { Button, Dialog, Text } from \"@knpkv/rly/primitives\"\nimport { type KeyboardEvent, type ReactElement, lazy, Suspense, useCallback, useEffect, useMemo, useState } from \"react\"\n\nimport {\n MAXIMUM_REVIEW_THREAD_PROMPT_LENGTH,\n type DurableAgentProviderId,\n type DurableAgentPrompt,\n type PullRequestReviewThreadEvent\n} from \"../../api/agent.js\"\nimport type { PrReviewSuggestion } from \"../../domain/prReview.js\"\nimport { ReviewNotes } from \"./ReviewSuggestionPresentation.js\"\nimport { VersionedReviewSuggestionCard } from \"./VersionedReviewSuggestionCard.js\"\nimport type { ReviewSuggestionRevisionTransport } from \"./useReviewSuggestionRevisions.js\"\nimport type {\n PullRequestReviewControllerState,\n PullRequestReviewPublicationState,\n ReviewSuggestionPublicationTarget\n} from \"./usePullRequestReview.js\"\nimport styles from \"./WorkspacePullRequestDetails.module.css\"\n\nconst unavailableMessage = (\n reason: Extract<PullRequestReviewControllerState, { readonly _tag: \"ready\" }>[\"review\"] extends infer Review\n ? Review extends { readonly _tag: \"unavailable\"; readonly reason: infer Reason }\n ? Reason\n : never\n : never\n): string => {\n switch (reason) {\n case \"not-codecommit\":\n case \"not-pull-request\":\n return \"Agent review is available only for synchronized CodeCommit pull requests.\"\n case \"source-stale\":\n return \"Synchronize this pull request before reviewing its immutable head.\"\n case \"release-unavailable\":\n return \"Connect this pull request to a release before asking Relay to review it.\"\n case \"base-revision-unavailable\":\n return \"The base revision has not been synchronized, so an exact review cannot start.\"\n }\n}\n\nconst outcomeLabel = (\n outcome: \"changes-required\" | \"non-blocking-suggestions\" | \"no-issues-found\" | \"unable-to-conclude\"\n) => {\n switch (outcome) {\n case \"changes-required\":\n return \"Changes Required\"\n case \"non-blocking-suggestions\":\n return \"Non-blocking Suggestions\"\n case \"no-issues-found\":\n return \"No Issues Found\"\n case \"unable-to-conclude\":\n return \"Unable to Conclude\"\n }\n}\n\nconst formatBudget = (budgetMillis: number): string => {\n const minutes = Math.round(budgetMillis / 60_000)\n return `${String(minutes)} minute${minutes === 1 ? \"\" : \"s\"}`\n}\n\nconst providerName = (\n provider: NonNullable<Extract<PullRequestReviewControllerState, { readonly _tag: \"ready\" }>[\"provider\"]>\n): string => provider.displayName ?? provider.providerId\n\nconst providerReviewLabel = (provider: Parameters<typeof providerName>[0]): string => `${providerName(provider)} review`\n\nconst REVIEW_PROMPT_TEMPLATES: ReadonlyArray<{\n readonly label: string\n readonly prompt: string\n}> = [\n {\n label: \"Correctness\",\n prompt: \"Review correctness, regressions, error handling, and boundary conditions.\"\n },\n {\n label: \"Security\",\n prompt: \"Review authorization, credential handling, unsafe input, and privilege boundaries.\"\n },\n {\n label: \"Tests\",\n prompt: \"Review test coverage, failure paths, race conditions, and missing regression guardrails.\"\n }\n]\n\nconst ReviewSuggestionPublicationSurface = lazy(() => import(\"./ReviewSuggestionPublicationSurface.js\"))\n\nconst threadEventSummary = (event: PullRequestReviewThreadEvent): string | null => {\n switch (event._tag) {\n case \"operator-message\":\n return `Local Operator · ${event.prompt}`\n case \"run-queued\":\n return `${event.reviewProfile.label} · head ${event.subject.headRevision.slice(0, 12)}`\n case \"run-started\":\n return event.runtimeMetadata === undefined\n ? \"Review sandbox started\"\n : `Review sandbox started · ${event.runtimeMetadata.implementation} ${event.runtimeMetadata.version ?? \"\"}`.trim()\n case \"progress\":\n return event.text\n case \"review-report\":\n return `${String(event.report.suggestions.length)} suggestions · ${String(event.report.notes.length)} notes`\n case \"suggestion-revised\":\n return event.suggestionState === \"dismissed\"\n ? `Suggestion revision ${String(event.sequence)} · dismissed by operator`\n : `Suggestion revision ${String(event.sequence)} · ${event.validationState === \"validated\" ? \"validated\" : \"needs revalidation\"}`\n case \"suggestion-published\":\n return \"Suggestion published to CodeCommit\"\n case \"run-completed\":\n return `Run completed · ${event.outcome}`\n case \"run-failed\":\n return event.retryable ? \"Run failed · retryable\" : \"Run failed\"\n case \"cancellation-requested\":\n return \"Cancellation requested\"\n case \"usage\":\n return null\n }\n}\n\n/** Render durable agent advice without conflating it with human disposition. */\nexport const PullRequestReviewPanel = ({\n canEnqueue,\n onCancelPublication,\n onLoadEarlier = () => undefined,\n onPreviewPublication,\n onPublishSuggestion,\n onRetry,\n onStart,\n onSuggestionRevisionAccepted,\n publication,\n revisionTransport,\n state,\n suggestions\n}: {\n readonly canEnqueue: boolean\n readonly onCancelPublication: () => void\n readonly onLoadEarlier?: () => void\n readonly onPreviewPublication: (selection: ReviewSuggestionPublicationTarget) => void\n readonly onPublishSuggestion: (finalContent: string) => void\n readonly onRetry: () => void\n readonly onStart: (prompt?: DurableAgentPrompt, providerId?: DurableAgentProviderId) => void\n readonly onSuggestionRevisionAccepted?: (suggestion: PrReviewSuggestion) => void\n readonly publication: PullRequestReviewPublicationState\n readonly revisionTransport?: ReviewSuggestionRevisionTransport\n readonly state: PullRequestReviewControllerState\n readonly suggestions?: ReadonlyArray<PrReviewSuggestion>\n}): ReactElement => {\n const [launchOpen, setLaunchOpen] = useState(false)\n const [request, setRequest] = useState(\"\")\n const [submittedRequest, setSubmittedRequest] = useState<string | null>(null)\n const [selectedProviderId, setSelectedProviderId] = useState<DurableAgentProviderId | null>(null)\n const providerPresets = useMemo(\n () => (state._tag === \"ready\" ? (state.providerPresets ?? (state.provider === null ? [] : [state.provider])) : []),\n [state]\n )\n const selectedProvider =\n providerPresets.find(({ providerId }) => providerId === selectedProviderId) ?? providerPresets[0] ?? null\n const requestScope =\n state._tag === \"idle\"\n ? null\n : `${state.entityId}:${state.baseRevision ?? \"\"}:${state.headRevision}:${state.sessionKey}`\n useEffect(() => {\n setLaunchOpen(false)\n setRequest(\"\")\n setSubmittedRequest(null)\n setSelectedProviderId(null)\n }, [requestScope])\n useEffect(() => {\n if (providerPresets.length === 0) {\n setSelectedProviderId(null)\n return\n }\n if (!providerPresets.some(({ providerId }) => providerId === selectedProviderId)) {\n setSelectedProviderId(providerPresets[0]?.providerId ?? null)\n }\n }, [providerPresets, selectedProviderId])\n useEffect(() => {\n if (submittedRequest === null || state._tag !== \"ready\") return\n if (state.action === \"failed\") return\n if (state.action === \"idle\" && state.review._tag === \"pending\") {\n setRequest((current) => (current.trim() === submittedRequest ? \"\" : current))\n setSubmittedRequest(null)\n }\n }, [state, submittedRequest])\n const changeLaunchOpen = useCallback((open: boolean): void => {\n setLaunchOpen(open)\n }, [])\n const submitFullReview = useCallback((): void => {\n if (selectedProvider === null) return\n setSubmittedRequest(null)\n onStart(undefined, selectedProvider.providerId)\n }, [onStart, selectedProvider])\n const submitTargetedReview = useCallback((): void => {\n const prompt = request.trim()\n if (prompt.length === 0 || state._tag !== \"ready\" || state.action === \"starting\") return\n setSubmittedRequest(prompt)\n if (selectedProvider === null) return\n onStart(prompt, selectedProvider.providerId)\n }, [onStart, request, selectedProvider, state])\n const handleComposerKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>): void => {\n if (event.key !== \"Enter\" || (!event.metaKey && !event.ctrlKey)) return\n event.preventDefault()\n submitTargetedReview()\n }\n const publicationSurface =\n publication._tag === \"idle\" || publication._tag === \"previewing\" ? null : (\n <Suspense fallback={<span>Preparing publication surface…</span>}>\n <ReviewSuggestionPublicationSurface\n onCancel={onCancelPublication}\n onPublish={onPublishSuggestion}\n publication={publication}\n />\n </Suspense>\n )\n const withPublication = (content: ReactElement): ReactElement => (\n <>\n {content}\n {publicationSurface}\n </>\n )\n\n if (state._tag === \"idle\" || state._tag === \"loading\") {\n return withPublication(\n <div aria-live=\"polite\" className={styles.reviewStatus} role=\"status\">\n <strong>Loading review state</strong>\n <span>Checking durable review history for this exact head.</span>\n <span aria-hidden=\"true\" className={styles.reviewRunway} />\n </div>\n )\n }\n if (state._tag === \"failed\") {\n return withPublication(\n <div className={styles.reviewStatus}>\n <strong>Review state unavailable</strong>\n <span>The current review could not be loaded. No human decision was changed.</span>\n <Button onClick={onRetry}>Retry</Button>\n </div>\n )\n }\n\n const review = state.review\n const threadEvents = state.thread?.events ?? []\n const presentedThreadEvents = threadEvents\n .map((event) => ({ event, summary: threadEventSummary(event) }))\n .filter(\n (\n item\n ): item is {\n readonly event: PullRequestReviewThreadEvent\n readonly summary: string\n } => item.summary !== null\n )\n const completeThreadVisible = state.thread !== undefined && (state.thread.historyLoaded || !state.thread.hasEarlier)\n const visibleThreadEvents = completeThreadVisible ? presentedThreadEvents : presentedThreadEvents.slice(-12)\n const threadSurface = (\n <section aria-label=\"Review thread\" className={styles.reviewThread}>\n <header>\n <strong>Review thread</strong>\n <span>{threadEvents.length === 0 ? \"No runs yet\" : \"Durable across pull-request heads\"}</span>\n </header>\n {visibleThreadEvents.length === 0 ? null : (\n <ol className={styles.reviewThreadEvents}>\n {visibleThreadEvents.map(({ event, summary }) => (\n <li key={event.eventSequence}>\n <span>{summary}</span>\n </li>\n ))}\n </ol>\n )}\n {state.thread?.hasEarlier ? (\n <Button loading={state.historyAction === \"loading\"} onClick={onLoadEarlier}>\n {state.historyAction === \"loading\"\n ? \"Loading earlier activity…\"\n : state.historyAction === \"failed\"\n ? \"Retry earlier activity\"\n : \"Load earlier activity\"}\n </Button>\n ) : state.thread !== undefined ? (\n <Text tone=\"secondary\" variant=\"meta\">\n Beginning of review thread\n </Text>\n ) : null}\n {canEnqueue && state.provider !== null && review._tag !== \"pending\" && review._tag !== \"unavailable\" ? (\n <div className={styles.reviewThreadComposer}>\n <label htmlFor=\"review-thread-request\">Ask Relay about this pull request</label>\n {providerPresets.length > 1 ? (\n <div aria-label=\"Targeted review agent presets\" className={styles.reviewPresetList} role=\"radiogroup\">\n {providerPresets.map((preset) => (\n <button\n aria-checked={preset.providerId === selectedProvider?.providerId}\n key={preset.providerId}\n onClick={() => setSelectedProviderId(preset.providerId)}\n role=\"radio\"\n type=\"button\"\n >\n <strong>{providerReviewLabel(preset)}</strong>\n <span>{preset.model}</span>\n </button>\n ))}\n </div>\n ) : selectedProvider === null ? null : (\n <span className={styles.reviewSelectedPreset}>\n Review with {providerName(selectedProvider)} · {selectedProvider.model}\n </span>\n )}\n <div aria-label=\"Review prompt templates\" className={styles.reviewTemplateList}>\n {REVIEW_PROMPT_TEMPLATES.map((template) => (\n <Button key={template.label} onClick={() => setRequest(template.prompt)}>\n {template.label}\n </Button>\n ))}\n </div>\n <textarea\n aria-describedby=\"review-thread-request-help review-thread-request-count\"\n id=\"review-thread-request\"\n maxLength={MAXIMUM_REVIEW_THREAD_PROMPT_LENGTH}\n onChange={(event) => setRequest(event.currentTarget.value)}\n onKeyDown={handleComposerKeyDown}\n placeholder=\"Re-check the error handling in the connection flow…\"\n rows={3}\n value={request}\n />\n <div className={styles.reviewThreadComposerFooter}>\n <span id=\"review-thread-request-help\">Ctrl/⌘ + Enter to run</span>\n <span id=\"review-thread-request-count\">\n {String(request.length)} / {String(MAXIMUM_REVIEW_THREAD_PROMPT_LENGTH)}\n </span>\n </div>\n {state.action === \"failed\" && submittedRequest !== null ? (\n <span role=\"alert\">\n Targeted review did not start. Your request is still here—check the provider and worker, then try again.\n </span>\n ) : null}\n <Button disabled={state.action === \"starting\" || request.trim().length === 0} onClick={submitTargetedReview}>\n {state.action === \"starting\" ? \"Starting targeted review…\" : \"Start targeted review\"}\n </Button>\n </div>\n ) : null}\n </section>\n )\n const withThread = (content: ReactElement): ReactElement =>\n withPublication(\n <>\n {content}\n {threadSurface}\n </>\n )\n const reviewLaunch = (headRevision: string, triggerLabel: string): ReactElement | null =>\n selectedProvider === null ? null : (\n <Dialog.Root onOpenChange={changeLaunchOpen} open={launchOpen}>\n <Dialog.Trigger disabled={state.action === \"starting\"}>\n {state.action === \"starting\" ? \"Starting review…\" : triggerLabel}\n </Dialog.Trigger>\n <Dialog.Content\n className={styles.reviewLaunchDialog}\n description=\"Relay will inspect the immutable revision in an isolated sandbox. It cannot approve or change the pull request.\"\n title=\"Review this exact head\"\n >\n <div className={styles.reviewLaunchBody}>\n <small className={styles.reviewLaunchEyebrow}>Read-only agent run</small>\n {providerPresets.length > 1 ? (\n <div aria-label=\"Review agent presets\" className={styles.reviewPresetList} role=\"radiogroup\">\n {providerPresets.map((preset) => (\n <button\n aria-checked={preset.providerId === selectedProvider.providerId}\n key={preset.providerId}\n onClick={() => setSelectedProviderId(preset.providerId)}\n role=\"radio\"\n type=\"button\"\n >\n <strong>{providerReviewLabel(preset)}</strong>\n <span>{preset.model}</span>\n </button>\n ))}\n </div>\n ) : null}\n <dl className={styles.reviewLaunchFacts}>\n <div>\n <dt>Exact head</dt>\n <dd>\n <code>{headRevision}</code>\n </dd>\n </div>\n <div>\n <dt>Review profile</dt>\n <dd>{selectedProvider.reviewProfile.label}</dd>\n </div>\n <div>\n <dt>Time budget</dt>\n <dd>{formatBudget(selectedProvider.reviewProfile.budgetMillis)}</dd>\n </div>\n <div>\n <dt>Runtime</dt>\n <dd>\n {selectedProvider.reviewProfile.networkAccess === \"blocked\"\n ? \"Network blocked · sbx\"\n : \"Provider connection enabled · sbx\"}\n </dd>\n </div>\n </dl>\n <div className={styles.reviewLaunchActions}>\n <Dialog.Close>Keep reading</Dialog.Close>\n <Dialog.Close onClick={submitFullReview}>Start full review</Dialog.Close>\n </div>\n </div>\n </Dialog.Content>\n </Dialog.Root>\n )\n if (review._tag === \"unavailable\") {\n return withThread(\n <>\n <strong>Review unavailable</strong>\n <span>{unavailableMessage(review.reason)}</span>\n </>\n )\n }\n if (review._tag === \"pending\") {\n const label =\n review.state === \"queued\"\n ? \"Review queued\"\n : review.state === \"running\"\n ? \"Reviewing exact head\"\n : \"Cancellation requested\"\n return withThread(\n <div aria-live=\"polite\" className={styles.reviewStatus} role=\"status\">\n <strong>{label}</strong>\n <span>\n Relay is using {review.providerId} · {review.model}. This page updates automatically.\n </span>\n <span>\n {review.reviewProfile.label} · {formatBudget(review.reviewProfile.budgetMillis)} ·{\" \"}\n {review.reviewProfile.networkAccess === \"blocked\"\n ? \"network blocked · sbx\"\n : \"provider connection enabled · sbx\"}\n </span>\n {review.activity.events.length === 0 ? null : (\n <ol aria-label=\"Live review activity\">\n {review.activity.events.map((event, index) => (\n <li key={`${String(index)}:${event}`}>{event}</li>\n ))}\n </ol>\n )}\n {review.activity.truncated ? <span>Earlier review activity is not shown.</span> : null}\n <code className={styles.reviewHead}>{review.subject.headRevision}</code>\n <span aria-hidden=\"true\" className={styles.reviewRunway} />\n </div>\n )\n }\n if (review._tag === \"failed\") {\n return withThread(\n <>\n <strong>{review.state === \"cancelled\" ? \"Review cancelled\" : \"Review did not finish\"}</strong>\n <span>The failed run did not change approval or publish a recommendation.</span>\n {canEnqueue && state.provider !== null ? (\n <>\n {state.action === \"failed\" && submittedRequest === null ? (\n <span role=\"alert\">\n A new full review could not be started. Check the provider and worker, then try again.\n </span>\n ) : null}\n {reviewLaunch(review.subject.headRevision, \"Try again\")}\n </>\n ) : null}\n </>\n )\n }\n if (review._tag === \"completed\") {\n return withThread(\n <>\n <strong>{outcomeLabel(review.outcome)}</strong>\n {review.report.completion.status === \"unable-to-conclude\" ? (\n <Text>{review.report.completion.reason}</Text>\n ) : null}\n {(suggestions ?? review.report.suggestions).length === 0 ? (\n <span>No validated suggestions were retained for this exact head.</span>\n ) : (\n <ol className={styles.reviewFindings}>\n {(suggestions ?? review.report.suggestions).map((suggestion) => (\n <li key={suggestion.suggestionId}>\n <VersionedReviewSuggestionCard\n canEdit={canEnqueue}\n entityId={state.entityId}\n isPreviewing={\n publication._tag === \"previewing\" && publication.selection.suggestionId === suggestion.suggestionId\n }\n jobId={review.jobId}\n onPreviewPublication={onPreviewPublication}\n {...(onSuggestionRevisionAccepted === undefined ? {} : { onSuggestionRevisionAccepted })}\n {...(revisionTransport === undefined ? {} : { revisionTransport })}\n sessionKey={state.sessionKey}\n suggestion={suggestion}\n />\n </li>\n ))}\n </ol>\n )}\n <ReviewNotes notes={review.report.notes} />\n <span>Agent advice only. Approve a finding to post it to CodeCommit, or dismiss it locally.</span>\n </>\n )\n }\n\n return withThread(\n <>\n <strong>Agent review not run</strong>\n <span>An immutable-head review produces advice, never a human approval.</span>\n {!canEnqueue ? (\n <span>Only a workspace owner can start a review.</span>\n ) : state.provider === null ? (\n <span>Configure an sbx Review Agent Profile with an Effect AI provider to enable review.</span>\n ) : (\n <>{reviewLaunch(review.subject.headRevision, \"Review exact head\")}</>\n )}\n {state.action === \"failed\" ? (\n <span role=\"alert\">The review could not be started. Check provider and worker configuration, then retry.</span>\n ) : null}\n </>\n )\n}\n\nexport default PullRequestReviewPanel\n"],"file":"PullRequestReviewPanel-CqPtjhVW.js"}
|