reviewflow 3.21.0 → 3.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +44 -1
- package/dist/config/projectConfig.d.ts +1 -0
- package/dist/config/projectConfig.d.ts.map +1 -1
- package/dist/config/projectConfig.js +13 -0
- package/dist/config/projectConfig.js.map +1 -1
- package/dist/dashboard/index.html +258 -44
- package/dist/dashboard/modules/animations.d.ts +164 -0
- package/dist/dashboard/modules/animations.d.ts.map +1 -0
- package/dist/dashboard/modules/animations.js +405 -0
- package/dist/dashboard/modules/animations.js.map +1 -0
- package/dist/dashboard/modules/cardCounters.d.ts +16 -1
- package/dist/dashboard/modules/cardCounters.d.ts.map +1 -1
- package/dist/dashboard/modules/cardCounters.js +36 -2
- package/dist/dashboard/modules/cardCounters.js.map +1 -1
- package/dist/dashboard/modules/i18n.d.ts.map +1 -1
- package/dist/dashboard/modules/i18n.js +20 -2
- package/dist/dashboard/modules/i18n.js.map +1 -1
- package/dist/dashboard/modules/settingsModal.d.ts.map +1 -1
- package/dist/dashboard/modules/settingsModal.js +28 -8
- package/dist/dashboard/modules/settingsModal.js.map +1 -1
- package/dist/dashboard/styles.css +731 -372
- package/dist/main/routes.d.ts.map +1 -1
- package/dist/main/routes.js +20 -0
- package/dist/main/routes.js.map +1 -1
- package/dist/main/server.d.ts.map +1 -1
- package/dist/main/server.js +22 -0
- package/dist/main/server.js.map +1 -1
- package/dist/modules/claude-invocation/interface-adapters/gateways/reviewReport.fileSystem.gateway.d.ts +1 -0
- package/dist/modules/claude-invocation/interface-adapters/gateways/reviewReport.fileSystem.gateway.d.ts.map +1 -1
- package/dist/modules/claude-invocation/interface-adapters/gateways/reviewReport.fileSystem.gateway.js +26 -5
- package/dist/modules/claude-invocation/interface-adapters/gateways/reviewReport.fileSystem.gateway.js.map +1 -1
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.d.ts.map +1 -1
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.js +1 -0
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.js.map +1 -1
- package/dist/modules/platform-integration/entities/approvalRevocation/approvalRevocation.gateway.d.ts +10 -0
- package/dist/modules/platform-integration/entities/approvalRevocation/approvalRevocation.gateway.d.ts.map +1 -0
- package/dist/modules/platform-integration/entities/approvalRevocation/approvalRevocation.gateway.js +2 -0
- package/dist/modules/platform-integration/entities/approvalRevocation/approvalRevocation.gateway.js.map +1 -0
- package/dist/modules/platform-integration/entities/github/githubIssueCommentEvent.guard.d.ts +50 -0
- package/dist/modules/platform-integration/entities/github/githubIssueCommentEvent.guard.d.ts.map +1 -0
- package/dist/modules/platform-integration/entities/github/githubIssueCommentEvent.guard.js +21 -0
- package/dist/modules/platform-integration/entities/github/githubIssueCommentEvent.guard.js.map +1 -0
- package/dist/modules/platform-integration/entities/github/githubPullRequestReviewEvent.guard.d.ts +53 -0
- package/dist/modules/platform-integration/entities/github/githubPullRequestReviewEvent.guard.d.ts.map +1 -0
- package/dist/modules/platform-integration/entities/github/githubPullRequestReviewEvent.guard.js +23 -0
- package/dist/modules/platform-integration/entities/github/githubPullRequestReviewEvent.guard.js.map +1 -0
- package/dist/modules/platform-integration/entities/gitlab/gitlabNoteEvent.guard.d.ts +62 -0
- package/dist/modules/platform-integration/entities/gitlab/gitlabNoteEvent.guard.d.ts.map +1 -0
- package/dist/modules/platform-integration/entities/gitlab/gitlabNoteEvent.guard.js +33 -0
- package/dist/modules/platform-integration/entities/gitlab/gitlabNoteEvent.guard.js.map +1 -0
- package/dist/modules/platform-integration/entities/noteComment/noteCommentPost.gateway.d.ts +9 -0
- package/dist/modules/platform-integration/entities/noteComment/noteCommentPost.gateway.d.ts.map +1 -0
- package/dist/modules/platform-integration/entities/noteComment/noteCommentPost.gateway.js +2 -0
- package/dist/modules/platform-integration/entities/noteComment/noteCommentPost.gateway.js.map +1 -0
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/eventFilter.d.ts +28 -0
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/eventFilter.d.ts.map +1 -1
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/eventFilter.js +48 -0
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/eventFilter.js.map +1 -1
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/github.controller.d.ts +10 -0
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/github.controller.d.ts.map +1 -1
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/github.controller.js +159 -1
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/github.controller.js.map +1 -1
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/gitlab.controller.d.ts +10 -0
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/gitlab.controller.d.ts.map +1 -1
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/gitlab.controller.js +129 -5
- package/dist/modules/platform-integration/interface-adapters/controllers/webhook/gitlab.controller.js.map +1 -1
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.github.cli.gateway.d.ts +8 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.github.cli.gateway.d.ts.map +1 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.github.cli.gateway.js +15 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.github.cli.gateway.js.map +1 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.gitlab.cli.gateway.d.ts +8 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.gitlab.cli.gateway.d.ts.map +1 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.gitlab.cli.gateway.js +12 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/approvalRevocation.gitlab.cli.gateway.js.map +1 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.github.cli.gateway.d.ts +8 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.github.cli.gateway.d.ts.map +1 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.github.cli.gateway.js +11 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.github.cli.gateway.js.map +1 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.gitlab.cli.gateway.d.ts +8 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.gitlab.cli.gateway.d.ts.map +1 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.gitlab.cli.gateway.js +12 -0
- package/dist/modules/platform-integration/interface-adapters/gateways/cli/noteCommentPost.gitlab.cli.gateway.js.map +1 -0
- package/dist/modules/review-execution/entities/reviewContext/reviewContext.gateway.d.ts +1 -0
- package/dist/modules/review-execution/entities/reviewContext/reviewContext.gateway.d.ts.map +1 -1
- package/dist/modules/review-execution/entities/reviewContext/reviewContext.schema.d.ts +10 -2
- package/dist/modules/review-execution/entities/reviewContext/reviewContext.schema.d.ts.map +1 -1
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.factory.d.ts +11 -0
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.factory.d.ts.map +1 -0
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.factory.js +22 -0
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.factory.js.map +1 -0
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.guard.d.ts +10 -0
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.guard.d.ts.map +1 -1
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.schema.d.ts +31 -1
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.schema.d.ts.map +1 -1
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.schema.js +11 -1
- package/dist/modules/review-execution/entities/reviewContext/reviewContextResult.schema.js.map +1 -1
- package/dist/modules/review-execution/interface-adapters/gateways/reviewContext.fileSystem.gateway.d.ts +1 -0
- package/dist/modules/review-execution/interface-adapters/gateways/reviewContext.fileSystem.gateway.d.ts.map +1 -1
- package/dist/modules/review-execution/interface-adapters/gateways/reviewContext.fileSystem.gateway.js +27 -1
- package/dist/modules/review-execution/interface-adapters/gateways/reviewContext.fileSystem.gateway.js.map +1 -1
- package/dist/modules/review-execution/services/reviewRecovery.service.d.ts +33 -0
- package/dist/modules/review-execution/services/reviewRecovery.service.d.ts.map +1 -0
- package/dist/modules/review-execution/services/reviewRecovery.service.js +80 -0
- package/dist/modules/review-execution/services/reviewRecovery.service.js.map +1 -0
- package/dist/modules/tracking/entities/bypassMarker/bypassMarker.d.ts +10 -0
- package/dist/modules/tracking/entities/bypassMarker/bypassMarker.d.ts.map +1 -0
- package/dist/modules/tracking/entities/bypassMarker/bypassMarker.js +17 -0
- package/dist/modules/tracking/entities/bypassMarker/bypassMarker.js.map +1 -0
- package/dist/modules/tracking/entities/qualityGate/qualityGate.d.ts +15 -0
- package/dist/modules/tracking/entities/qualityGate/qualityGate.d.ts.map +1 -0
- package/dist/modules/tracking/entities/qualityGate/qualityGate.js +24 -0
- package/dist/modules/tracking/entities/qualityGate/qualityGate.js.map +1 -0
- package/dist/modules/tracking/entities/tracking/trackedMr.d.ts +6 -0
- package/dist/modules/tracking/entities/tracking/trackedMr.d.ts.map +1 -1
- package/dist/modules/tracking/entities/tracking/trackedMr.js.map +1 -1
- package/dist/modules/tracking/interface-adapters/controllers/http/mrTracking.routes.d.ts +1 -0
- package/dist/modules/tracking/interface-adapters/controllers/http/mrTracking.routes.d.ts.map +1 -1
- package/dist/modules/tracking/interface-adapters/controllers/http/mrTracking.routes.js +14 -3
- package/dist/modules/tracking/interface-adapters/controllers/http/mrTracking.routes.js.map +1 -1
- package/dist/modules/tracking/interface-adapters/controllers/http/mrTrackingAdvanced.routes.d.ts.map +1 -1
- package/dist/modules/tracking/interface-adapters/controllers/http/mrTrackingAdvanced.routes.js +1 -0
- package/dist/modules/tracking/interface-adapters/controllers/http/mrTrackingAdvanced.routes.js.map +1 -1
- package/dist/modules/tracking/usecases/tracking/handlePlatformApproval.usecase.d.ts +28 -0
- package/dist/modules/tracking/usecases/tracking/handlePlatformApproval.usecase.d.ts.map +1 -0
- package/dist/modules/tracking/usecases/tracking/handlePlatformApproval.usecase.js +37 -0
- package/dist/modules/tracking/usecases/tracking/handlePlatformApproval.usecase.js.map +1 -0
- package/dist/modules/tracking/usecases/tracking/recordBypass.usecase.d.ts +28 -0
- package/dist/modules/tracking/usecases/tracking/recordBypass.usecase.d.ts.map +1 -0
- package/dist/modules/tracking/usecases/tracking/recordBypass.usecase.js +28 -0
- package/dist/modules/tracking/usecases/tracking/recordBypass.usecase.js.map +1 -0
- package/dist/modules/tracking/usecases/tracking/recordReviewCompletion.usecase.d.ts +1 -0
- package/dist/modules/tracking/usecases/tracking/recordReviewCompletion.usecase.d.ts.map +1 -1
- package/dist/modules/tracking/usecases/tracking/recordReviewCompletion.usecase.js +10 -1
- package/dist/modules/tracking/usecases/tracking/recordReviewCompletion.usecase.js.map +1 -1
- package/dist/modules/tracking/usecases/tracking/trackAssignment.usecase.d.ts.map +1 -1
- package/dist/modules/tracking/usecases/tracking/trackAssignment.usecase.js +1 -0
- package/dist/modules/tracking/usecases/tracking/trackAssignment.usecase.js.map +1 -1
- package/dist/modules/tracking/usecases/tracking/transitionState.usecase.d.ts +15 -2
- package/dist/modules/tracking/usecases/tracking/transitionState.usecase.d.ts.map +1 -1
- package/dist/modules/tracking/usecases/tracking/transitionState.usecase.js +8 -2
- package/dist/modules/tracking/usecases/tracking/transitionState.usecase.js.map +1 -1
- package/dist/tests/acceptance/170-prebuilt-worktree-lifecycle.acceptance.test.js +1 -0
- package/dist/tests/acceptance/170-prebuilt-worktree-lifecycle.acceptance.test.js.map +1 -1
- package/dist/tests/acceptance/180-quality-threshold-block-approval-iter-B.acceptance.test.d.ts +17 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval-iter-B.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval-iter-B.acceptance.test.js +294 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval-iter-B.acceptance.test.js.map +1 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval-iter-C.acceptance.test.d.ts +16 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval-iter-C.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval-iter-C.acceptance.test.js +316 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval-iter-C.acceptance.test.js.map +1 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval.acceptance.test.d.ts +20 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval.acceptance.test.js +146 -0
- package/dist/tests/acceptance/180-quality-threshold-block-approval.acceptance.test.js.map +1 -0
- package/dist/tests/acceptance/91-dashboard-multi-project-overview.acceptance.test.js +2 -0
- package/dist/tests/acceptance/91-dashboard-multi-project-overview.acceptance.test.js.map +1 -1
- package/dist/tests/factories/projectConfig.factory.d.ts +1 -0
- package/dist/tests/factories/projectConfig.factory.d.ts.map +1 -1
- package/dist/tests/factories/projectConfig.factory.js +3 -0
- package/dist/tests/factories/projectConfig.factory.js.map +1 -1
- package/dist/tests/factories/trackedMr.factory.d.ts.map +1 -1
- package/dist/tests/factories/trackedMr.factory.js +1 -0
- package/dist/tests/factories/trackedMr.factory.js.map +1 -1
- package/dist/tests/stubs/approvalRevocation.stub.d.ts +7 -0
- package/dist/tests/stubs/approvalRevocation.stub.d.ts.map +1 -0
- package/dist/tests/stubs/approvalRevocation.stub.js +11 -0
- package/dist/tests/stubs/approvalRevocation.stub.js.map +1 -0
- package/dist/tests/stubs/noteCommentPost.stub.d.ts +6 -0
- package/dist/tests/stubs/noteCommentPost.stub.d.ts.map +1 -0
- package/dist/tests/stubs/noteCommentPost.stub.js +7 -0
- package/dist/tests/stubs/noteCommentPost.stub.js.map +1 -0
- package/dist/tests/stubs/reviewContextGateway.stub.d.ts +1 -0
- package/dist/tests/stubs/reviewContextGateway.stub.d.ts.map +1 -1
- package/dist/tests/stubs/reviewContextGateway.stub.js +3 -0
- package/dist/tests/stubs/reviewContextGateway.stub.js.map +1 -1
- package/dist/tests/units/config/projectConfig.test.js +62 -0
- package/dist/tests/units/config/projectConfig.test.js.map +1 -1
- package/dist/tests/units/dashboard/modules/animations.test.d.ts +10 -0
- package/dist/tests/units/dashboard/modules/animations.test.d.ts.map +1 -0
- package/dist/tests/units/dashboard/modules/animations.test.js +223 -0
- package/dist/tests/units/dashboard/modules/animations.test.js.map +1 -0
- package/dist/tests/units/dashboard/modules/cardCounters.test.js +56 -0
- package/dist/tests/units/dashboard/modules/cardCounters.test.js.map +1 -1
- package/dist/tests/units/entities/reviewContext/reviewContext.schema.test.js +1 -0
- package/dist/tests/units/entities/reviewContext/reviewContext.schema.test.js.map +1 -1
- package/dist/tests/units/entities/reviewContext/reviewContextResult.factory.test.d.ts +2 -0
- package/dist/tests/units/entities/reviewContext/reviewContextResult.factory.test.d.ts.map +1 -0
- package/dist/tests/units/entities/reviewContext/reviewContextResult.factory.test.js +43 -0
- package/dist/tests/units/entities/reviewContext/reviewContextResult.factory.test.js.map +1 -0
- package/dist/tests/units/entities/reviewContext/reviewContextResult.guard.test.js +7 -3
- package/dist/tests/units/entities/reviewContext/reviewContextResult.guard.test.js.map +1 -1
- package/dist/tests/units/entities/reviewContext/reviewContextResult.schema.test.js +12 -1
- package/dist/tests/units/entities/reviewContext/reviewContextResult.schema.test.js.map +1 -1
- package/dist/tests/units/interface-adapters/controllers/webhook/eventFilter.test.js +50 -1
- package/dist/tests/units/interface-adapters/controllers/webhook/eventFilter.test.js.map +1 -1
- package/dist/tests/units/interface-adapters/controllers/webhook/github.controller.test.js +63 -0
- package/dist/tests/units/interface-adapters/controllers/webhook/github.controller.test.js.map +1 -1
- package/dist/tests/units/interface-adapters/controllers/webhook/gitlab.controller.test.js +11 -0
- package/dist/tests/units/interface-adapters/controllers/webhook/gitlab.controller.test.js.map +1 -1
- package/dist/tests/units/interface-adapters/gateways/reviewContext.fileSystem.gateway.test.js +64 -4
- package/dist/tests/units/interface-adapters/gateways/reviewContext.fileSystem.gateway.test.js.map +1 -1
- package/dist/tests/units/modules/claude-invocation/interface-adapters/gateways/reviewReport.fileSystem.gateway.test.js +56 -0
- package/dist/tests/units/modules/claude-invocation/interface-adapters/gateways/reviewReport.fileSystem.gateway.test.js.map +1 -1
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.test.js +1 -1
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.test.js.map +1 -1
- package/dist/tests/units/modules/platform-integration/entities/github/githubIssueCommentEvent.guard.test.d.ts +2 -0
- package/dist/tests/units/modules/platform-integration/entities/github/githubIssueCommentEvent.guard.test.d.ts.map +1 -0
- package/dist/tests/units/modules/platform-integration/entities/github/githubIssueCommentEvent.guard.test.js +39 -0
- package/dist/tests/units/modules/platform-integration/entities/github/githubIssueCommentEvent.guard.test.js.map +1 -0
- package/dist/tests/units/modules/platform-integration/entities/github/githubPullRequestReviewEvent.guard.test.d.ts +2 -0
- package/dist/tests/units/modules/platform-integration/entities/github/githubPullRequestReviewEvent.guard.test.d.ts.map +1 -0
- package/dist/tests/units/modules/platform-integration/entities/github/githubPullRequestReviewEvent.guard.test.js +54 -0
- package/dist/tests/units/modules/platform-integration/entities/github/githubPullRequestReviewEvent.guard.test.js.map +1 -0
- package/dist/tests/units/modules/platform-integration/entities/gitlab/gitlabNoteEvent.guard.test.d.ts +2 -0
- package/dist/tests/units/modules/platform-integration/entities/gitlab/gitlabNoteEvent.guard.test.d.ts.map +1 -0
- package/dist/tests/units/modules/platform-integration/entities/gitlab/gitlabNoteEvent.guard.test.js +48 -0
- package/dist/tests/units/modules/platform-integration/entities/gitlab/gitlabNoteEvent.guard.test.js.map +1 -0
- package/dist/tests/units/modules/tracking/entities/bypassMarker/bypassMarker.test.d.ts +2 -0
- package/dist/tests/units/modules/tracking/entities/bypassMarker/bypassMarker.test.d.ts.map +1 -0
- package/dist/tests/units/modules/tracking/entities/bypassMarker/bypassMarker.test.js +29 -0
- package/dist/tests/units/modules/tracking/entities/bypassMarker/bypassMarker.test.js.map +1 -0
- package/dist/tests/units/modules/tracking/entities/qualityGate/qualityGate.test.d.ts +2 -0
- package/dist/tests/units/modules/tracking/entities/qualityGate/qualityGate.test.d.ts.map +1 -0
- package/dist/tests/units/modules/tracking/entities/qualityGate/qualityGate.test.js +52 -0
- package/dist/tests/units/modules/tracking/entities/qualityGate/qualityGate.test.js.map +1 -0
- package/dist/tests/units/modules/tracking/interface-adapters/controllers/http/mrTracking.routes.test.d.ts +2 -0
- package/dist/tests/units/modules/tracking/interface-adapters/controllers/http/mrTracking.routes.test.d.ts.map +1 -0
- package/dist/tests/units/modules/tracking/interface-adapters/controllers/http/mrTracking.routes.test.js +103 -0
- package/dist/tests/units/modules/tracking/interface-adapters/controllers/http/mrTracking.routes.test.js.map +1 -0
- package/dist/tests/units/modules/tracking/usecases/tracking/handlePlatformApproval.usecase.test.d.ts +2 -0
- package/dist/tests/units/modules/tracking/usecases/tracking/handlePlatformApproval.usecase.test.d.ts.map +1 -0
- package/dist/tests/units/modules/tracking/usecases/tracking/handlePlatformApproval.usecase.test.js +113 -0
- package/dist/tests/units/modules/tracking/usecases/tracking/handlePlatformApproval.usecase.test.js.map +1 -0
- package/dist/tests/units/modules/tracking/usecases/tracking/recordBypass.usecase.test.d.ts +2 -0
- package/dist/tests/units/modules/tracking/usecases/tracking/recordBypass.usecase.test.d.ts.map +1 -0
- package/dist/tests/units/modules/tracking/usecases/tracking/recordBypass.usecase.test.js +77 -0
- package/dist/tests/units/modules/tracking/usecases/tracking/recordBypass.usecase.test.js.map +1 -0
- package/dist/tests/units/modules/worktree-management/usecases/sweepStaleWorktrees.usecase.test.js +1 -0
- package/dist/tests/units/modules/worktree-management/usecases/sweepStaleWorktrees.usecase.test.js.map +1 -1
- package/dist/tests/units/services/reviewRecovery.service.test.d.ts +2 -0
- package/dist/tests/units/services/reviewRecovery.service.test.d.ts.map +1 -0
- package/dist/tests/units/services/reviewRecovery.service.test.js +49 -0
- package/dist/tests/units/services/reviewRecovery.service.test.js.map +1 -0
- package/dist/tests/units/services/runReviewRecovery.service.test.d.ts +2 -0
- package/dist/tests/units/services/runReviewRecovery.service.test.d.ts.map +1 -0
- package/dist/tests/units/services/runReviewRecovery.service.test.js +199 -0
- package/dist/tests/units/services/runReviewRecovery.service.test.js.map +1 -0
- package/dist/tests/units/usecases/tracking/recordReviewCompletion.usecase.test.js +71 -0
- package/dist/tests/units/usecases/tracking/recordReviewCompletion.usecase.test.js.map +1 -1
- package/dist/tests/units/usecases/tracking/transitionState.usecase.test.js +87 -4
- package/dist/tests/units/usecases/tracking/transitionState.usecase.test.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.23.0](https://github.com/DGouron/review-flow/compare/reviewflow-v3.22.0...reviewflow-v3.23.0) (2026-05-26)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
* **tracking:** block approval below quality threshold (SPEC-180 iter A) ([#209](https://github.com/DGouron/review-flow/issues/209)) ([9b1f4ca](https://github.com/DGouron/review-flow/commit/9b1f4ca9b40df65b612176465014592f7aab9a73))
|
|
14
|
+
* **tracking:** comment-based bypass for quality gate (SPEC-180 iter B) ([#211](https://github.com/DGouron/review-flow/issues/211)) ([77e6356](https://github.com/DGouron/review-flow/commit/77e6356c2780f6300cd6a127f170a282ba72c4e0))
|
|
15
|
+
* **tracking:** platform unapprove + FR comment on non-qualified MR (SPEC-180 iter C) ([#212](https://github.com/DGouron/review-flow/issues/212)) ([35c5e32](https://github.com/DGouron/review-flow/commit/35c5e320bb8879fc26d14253be4071de0d08d78b))
|
|
16
|
+
|
|
17
|
+
## [3.22.0](https://github.com/DGouron/review-flow/compare/reviewflow-v3.21.0...reviewflow-v3.22.0) (2026-05-25)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
* **dashboard:** operator's console redesign + animations ([#204](https://github.com/DGouron/review-flow/issues/204)) ([8b33ebd](https://github.com/DGouron/review-flow/commit/8b33ebd28bc09a85280371c499f68d73927eb18e))
|
|
23
|
+
|
|
8
24
|
## [3.21.0](https://github.com/DGouron/review-flow/compare/reviewflow-v3.20.0...reviewflow-v3.21.0) (2026-05-25)
|
|
9
25
|
|
|
10
26
|
|
package/README.md
CHANGED
|
@@ -26,7 +26,11 @@ GitLab/GitHub webhook ──► Review server receives event
|
|
|
26
26
|
Queue deduplicates & schedules
|
|
27
27
|
│
|
|
28
28
|
▼
|
|
29
|
-
|
|
29
|
+
Pre-built worktree ensured
|
|
30
|
+
(~/.reviewflow/worktrees/...)
|
|
31
|
+
│
|
|
32
|
+
▼
|
|
33
|
+
Claude Code dispatched in --bg mode
|
|
30
34
|
│
|
|
31
35
|
┌─────────┼─────────┐
|
|
32
36
|
▼ ▼ ▼
|
|
@@ -45,6 +49,7 @@ GitLab/GitHub webhook ──► Review server receives event
|
|
|
45
49
|
│
|
|
46
50
|
▼
|
|
47
51
|
Dev pushes fixes ──► Auto follow-up
|
|
52
|
+
(same worktree, fast-forwarded)
|
|
48
53
|
```
|
|
49
54
|
|
|
50
55
|
---
|
|
@@ -148,6 +153,43 @@ Review behavior is defined by [Claude Code skills](https://docs.anthropic.com/en
|
|
|
148
153
|
|
|
149
154
|
---
|
|
150
155
|
|
|
156
|
+
## Under the Hood
|
|
157
|
+
|
|
158
|
+
For contributors and curious operators — what actually happens between the webhook and the posted review.
|
|
159
|
+
|
|
160
|
+
### Background sessions, not foreground spawn
|
|
161
|
+
|
|
162
|
+
Earlier versions of Reviewflow invoked `claude -p` and streamed JSON in the foreground. The server now dispatches each review as a **detached background session** with `claude --bg`. The Fastify process returns the session ID immediately and observes completion asynchronously.
|
|
163
|
+
|
|
164
|
+
Completion is detected via **three independent signals in first-wins semantics**:
|
|
165
|
+
|
|
166
|
+
1. **MCP `set_phase('completed')`** — Claude's skill calls the MCP server when the review finishes
|
|
167
|
+
2. **`claude agents --json` polling** — every 30s, looks for `completed` / `failed` / `stopped`
|
|
168
|
+
3. **15-minute hard timeout** — backstop if the other two miss
|
|
169
|
+
|
|
170
|
+
Whichever fires first wins; the other two are cancelled. The review report is then read from `<worktree>/.claude/reviews/report-<mrNumber>.md` and the session is cleaned with `claude stop` + `claude rm`.
|
|
171
|
+
|
|
172
|
+
### Isolated git worktrees
|
|
173
|
+
|
|
174
|
+
Each MR runs in its own pre-built git worktree at `~/.reviewflow/worktrees/<platform>-<slug>-<mrNumber>`. This:
|
|
175
|
+
|
|
176
|
+
- **Isolates concurrent reviews** so they cannot step on each other's index
|
|
177
|
+
- **Keeps your main checkout untouched** — `git checkout` inside Claude no longer pollutes your working branch
|
|
178
|
+
- **Speeds up followups** — the worktree is fetched + reset to the new HEAD, never recreated from scratch
|
|
179
|
+
- **Self-cleans** — `removeWorktree` runs on merge/close, plus a daily sweep reclaims worktrees of MRs closed >24h ago or with `mtime` >7 days
|
|
180
|
+
|
|
181
|
+
Full state machine: [Worktree Lifecycle](https://dgouron.github.io/review-flow/architecture/worktree-lifecycle).
|
|
182
|
+
|
|
183
|
+
### Supervisor health
|
|
184
|
+
|
|
185
|
+
The Claude agents supervisor (long-running daemon that hosts background sessions) is probed every 60 seconds. If it dies, a detached spawn brings it back under a PID-validated file lock at `~/.reviewflow/supervisor.lock`. The `/health` endpoint surfaces the live state and reports `status: degraded` when the supervisor is down — Reviewflow keeps booting, but reviews will fail fast.
|
|
186
|
+
|
|
187
|
+
### Token budget cap
|
|
188
|
+
|
|
189
|
+
Every session's token usage is parsed from the Claude transcript and persisted. A configurable monthly budget caps further dispatch and broadcasts a budget panel update over WebSocket whenever a session completes. The hourly billing audit calls `claude /usage` and pauses dispatch if it detects unexpected API-pool usage (the OAuth subscription is the only billing path that should be active).
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
151
193
|
## Quick Start
|
|
152
194
|
|
|
153
195
|
### 1. Install
|
|
@@ -219,6 +261,7 @@ For detailed setup, see the **[Quick Start Guide](https://dgouron.github.io/revi
|
|
|
219
261
|
| Review Skills Guide | [guide/review-skills](https://dgouron.github.io/review-flow/guide/review-skills) |
|
|
220
262
|
| MCP Tools Reference | [reference/mcp-tools](https://dgouron.github.io/review-flow/reference/mcp-tools) |
|
|
221
263
|
| Architecture | [architecture](https://dgouron.github.io/review-flow/architecture/) |
|
|
264
|
+
| Worktree Lifecycle | [architecture/worktree-lifecycle](https://dgouron.github.io/review-flow/architecture/worktree-lifecycle) |
|
|
222
265
|
| Deployment | [deployment](https://dgouron.github.io/review-flow/deployment/) |
|
|
223
266
|
| Troubleshooting | [guide/troubleshooting](https://dgouron.github.io/review-flow/guide/troubleshooting) |
|
|
224
267
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../src/config/projectConfig.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sEAAsE,CAAC;AAC5G,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8DAA8D,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yEAAyE,CAAC;AAC7G,OAAO,EACL,KAAK,WAAW,EAKjB,MAAM,kEAAkE,CAAC;AAG1E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"projectConfig.d.ts","sourceRoot":"","sources":["../../src/config/projectConfig.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sEAAsE,CAAC;AAC5G,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8DAA8D,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yEAAyE,CAAC;AAC7G,OAAO,EACL,KAAK,WAAW,EAKjB,MAAM,kEAAkE,CAAC;AAG1E,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,eAAe,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAwFD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAU9E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CA0EjF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,GAAG,SAAS,CAOjF;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,GAChB,eAAe,EAAE,GAAG,SAAS,CAgB/B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAO9D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAOjE;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,GAAG,SAAS,CAOlF"}
|
|
@@ -18,6 +18,15 @@ function parseRetentionDays(value) {
|
|
|
18
18
|
}
|
|
19
19
|
return DEFAULT_RETENTION_DAYS;
|
|
20
20
|
}
|
|
21
|
+
function parseQualityThreshold(value) {
|
|
22
|
+
if (value === undefined || value === null) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < 0 || value > 10) {
|
|
26
|
+
throw new Error('Invalid qualityThreshold: must be an integer between 0 and 10');
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
21
30
|
function validateAgents(agents) {
|
|
22
31
|
if (!Array.isArray(agents)) {
|
|
23
32
|
return false;
|
|
@@ -134,6 +143,10 @@ export function parseProjectConfig(parsed) {
|
|
|
134
143
|
if (externalLink !== undefined) {
|
|
135
144
|
config.externalLink = externalLink;
|
|
136
145
|
}
|
|
146
|
+
const qualityThreshold = parseQualityThreshold(parsed.qualityThreshold);
|
|
147
|
+
if (qualityThreshold !== undefined) {
|
|
148
|
+
config.qualityThreshold = qualityThreshold;
|
|
149
|
+
}
|
|
137
150
|
return config;
|
|
138
151
|
}
|
|
139
152
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectConfig.js","sourceRoot":"","sources":["../../src/config/projectConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,OAAO,EAEL,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,mBAAmB,GACpB,MAAM,kEAAkE,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"projectConfig.js","sourceRoot":"","sources":["../../src/config/projectConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,13 +4,25 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Reviewflow Dashboard</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
7
10
|
<link rel="stylesheet" href="styles.css">
|
|
8
11
|
<script src="https://unpkg.com/lucide@latest"></script>
|
|
9
12
|
</head>
|
|
10
13
|
<body>
|
|
11
14
|
<div class="container">
|
|
12
15
|
<header>
|
|
13
|
-
<div class="logo"
|
|
16
|
+
<div class="logo" aria-label="Reviewflow">
|
|
17
|
+
<svg viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
|
18
|
+
<rect class="logo-frame" x="2" y="2" width="40" height="40" rx="10"/>
|
|
19
|
+
<line class="logo-line" x1="10" y1="14" x2="26" y2="14"/>
|
|
20
|
+
<line class="logo-line logo-line--accent" x1="10" y1="22" x2="20" y2="22"/>
|
|
21
|
+
<line class="logo-line" x1="10" y1="30" x2="24" y2="30"/>
|
|
22
|
+
<path class="logo-check" d="M28 26 L31 29 L36 22"/>
|
|
23
|
+
<circle class="logo-pulse" cx="20" cy="22" r="1.7"/>
|
|
24
|
+
</svg>
|
|
25
|
+
</div>
|
|
14
26
|
<h1>Reviewflow</h1>
|
|
15
27
|
<div class="header-actions">
|
|
16
28
|
<div class="version-update-wrapper">
|
|
@@ -37,6 +49,29 @@
|
|
|
37
49
|
</button>
|
|
38
50
|
<section id="manage-panel" class="manage-panel" aria-label="Manage projects" data-open="false"></section>
|
|
39
51
|
<nav id="dashboard-tabs" class="dashboard-tab-bar-wrapper" aria-label="Project tabs"></nav>
|
|
52
|
+
<div class="context-chips" aria-label="Toolchain status">
|
|
53
|
+
<div class="toolchain-chip">
|
|
54
|
+
<span class="toolchain-chip-label" id="i18n-card-claude-cli"></span>
|
|
55
|
+
<div id="claude-status" class="card-claude checking">
|
|
56
|
+
<span class="status" id="i18n-claude-checking"></span>
|
|
57
|
+
<span class="version"></span>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="toolchain-chip" id="git-cli-card">
|
|
61
|
+
<span class="toolchain-chip-label" id="git-cli-label"></span>
|
|
62
|
+
<div id="git-cli-status" class="card-claude checking">
|
|
63
|
+
<span class="status" id="i18n-git-load-project"></span>
|
|
64
|
+
<span class="version"></span>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="toolchain-chip toolchain-chip-model">
|
|
68
|
+
<span class="toolchain-chip-label" id="i18n-card-model"></span>
|
|
69
|
+
<select id="model-select" class="model-select" onchange="changeModel(this.value)">
|
|
70
|
+
<option value="opus" id="i18n-model-opus"></option>
|
|
71
|
+
<option value="sonnet" id="i18n-model-sonnet"></option>
|
|
72
|
+
</select>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
40
75
|
</div>
|
|
41
76
|
|
|
42
77
|
<div id="cards-scope-marker" class="cards-scope-marker" data-scope-kind="overview">
|
|
@@ -57,44 +92,21 @@
|
|
|
57
92
|
<div class="card-label" id="i18n-card-completed"></div>
|
|
58
93
|
<div id="completed-count" class="card-value">-</div>
|
|
59
94
|
</div>
|
|
60
|
-
<div class="card">
|
|
61
|
-
<div class="card-label" id="i18n-card-claude-cli"></div>
|
|
62
|
-
<div id="claude-status" class="card-claude checking">
|
|
63
|
-
<span class="status" id="i18n-claude-checking"></span>
|
|
64
|
-
<span class="version"></span>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
<div class="card" id="git-cli-card">
|
|
68
|
-
<div class="card-label" id="git-cli-label"></div>
|
|
69
|
-
<div id="git-cli-status" class="card-claude checking">
|
|
70
|
-
<span class="status" id="i18n-git-load-project"></span>
|
|
71
|
-
<span class="version"></span>
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
<div class="card">
|
|
75
|
-
<div class="card-label" id="i18n-card-model"></div>
|
|
76
|
-
<div class="card-model">
|
|
77
|
-
<select id="model-select" class="model-select" onchange="changeModel(this.value)">
|
|
78
|
-
<option value="opus" id="i18n-model-opus"></option>
|
|
79
|
-
<option value="sonnet" id="i18n-model-sonnet"></option>
|
|
80
|
-
</select>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
95
|
</div>
|
|
84
96
|
|
|
85
97
|
<div class="dashboard-layout">
|
|
86
98
|
<aside class="dashboard-sidebar" aria-label="Project tools">
|
|
87
|
-
<
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
<option value="en">English</option>
|
|
91
|
-
<option value="fr">Français</option>
|
|
92
|
-
</select>
|
|
93
|
-
</div>
|
|
99
|
+
<button type="button" id="open-settings-modal-btn" class="sidebar-settings-button" hidden>
|
|
100
|
+
<span class="sidebar-settings-button__prefix">// SETTINGS</span>
|
|
101
|
+
</button>
|
|
94
102
|
|
|
95
103
|
<span id="config-status" class="config-status hidden"></span>
|
|
96
104
|
|
|
97
|
-
<
|
|
105
|
+
<section id="worktree-section" aria-label="Worktree pool"></section>
|
|
106
|
+
</aside>
|
|
107
|
+
|
|
108
|
+
<main class="dashboard-main">
|
|
109
|
+
<div class="focus-strip attention-strip" aria-label="Attention indicators">
|
|
98
110
|
<div class="focus-chip focus-now">
|
|
99
111
|
<div class="focus-copy">
|
|
100
112
|
<span class="focus-label" id="i18n-strip-now"></span>
|
|
@@ -119,14 +131,6 @@
|
|
|
119
131
|
<button id="focus-strip-toggle" class="focus-toggle-btn" onclick="toggleFocusStripMode()"></button>
|
|
120
132
|
</div>
|
|
121
133
|
|
|
122
|
-
<section id="worktree-section" aria-label="Worktree pool"></section>
|
|
123
|
-
|
|
124
|
-
<button type="button" id="open-settings-modal-btn" class="sidebar-settings-button" hidden>
|
|
125
|
-
<span class="sidebar-settings-button__prefix">// SETTINGS</span>
|
|
126
|
-
</button>
|
|
127
|
-
</aside>
|
|
128
|
-
|
|
129
|
-
<main class="dashboard-main">
|
|
130
134
|
<section id="overview-section" class="overview-section" aria-label="Multi-project overview"></section>
|
|
131
135
|
|
|
132
136
|
<div id="data-loading-state" class="data-loading hidden" role="status" aria-live="polite">
|
|
@@ -154,7 +158,11 @@
|
|
|
154
158
|
<span id="pending-reviews-count" class="badge-count hidden">0</span>
|
|
155
159
|
</div>
|
|
156
160
|
<div id="pending-reviews" class="section-content">
|
|
157
|
-
<div class="empty-state" id="
|
|
161
|
+
<div class="heartbeat-empty-state" id="pending-reviews-empty-state">
|
|
162
|
+
<span class="heartbeat-label">// STANDBY</span>
|
|
163
|
+
<span class="heartbeat-message" id="i18n-empty-pending-reviews">No reviews waiting for confirmation</span>
|
|
164
|
+
<div class="heartbeat-line-container" id="heartbeat-line" aria-hidden="true"></div>
|
|
165
|
+
</div>
|
|
158
166
|
</div>
|
|
159
167
|
</div>
|
|
160
168
|
|
|
@@ -323,9 +331,30 @@
|
|
|
323
331
|
|
|
324
332
|
<dialog id="settings-modal" class="settings-modal" aria-labelledby="settings-modal-title"></dialog>
|
|
325
333
|
|
|
334
|
+
<!-- UI language select — kept in DOM for JS wiring; visual control lives in settings modal -->
|
|
335
|
+
<select id="language-select" style="display:none" aria-hidden="true" onchange="changeLanguage(this.value)">
|
|
336
|
+
<option value="en">English</option>
|
|
337
|
+
<option value="fr">Français</option>
|
|
338
|
+
</select>
|
|
339
|
+
|
|
326
340
|
<script type="module">
|
|
327
341
|
import { t, setLanguage, getLanguage } from './modules/i18n.js';
|
|
328
342
|
import { formatTime, formatDuration, formatPhase, formatLogTime } from './modules/formatting.js';
|
|
343
|
+
import {
|
|
344
|
+
reducedMotion,
|
|
345
|
+
animateMount,
|
|
346
|
+
animateCounter as animateCounterValue,
|
|
347
|
+
slideTabUnderline,
|
|
348
|
+
heartbeat,
|
|
349
|
+
pulseLive,
|
|
350
|
+
springIn,
|
|
351
|
+
liftCard,
|
|
352
|
+
unliftCard,
|
|
353
|
+
pulseStatusDot,
|
|
354
|
+
breatheLogo,
|
|
355
|
+
crossFadeTab,
|
|
356
|
+
toggleHeight,
|
|
357
|
+
} from './modules/animations.js';
|
|
329
358
|
import { escapeHtml, markdownToHtml, sanitizeHttpUrl } from './modules/html.js';
|
|
330
359
|
import { getAgentIcon, icon, refreshIcons } from './modules/icons.js';
|
|
331
360
|
import { MAX_RECONNECT_ATTEMPTS, RECONNECT_DELAY, STORAGE_KEY_CURRENT, STORAGE_KEY_FOCUS_STRIP_MODE, QUALITY_TARGET_SCORE } from './modules/constants.js';
|
|
@@ -334,7 +363,7 @@
|
|
|
334
363
|
import { renderOverviewHtml } from './modules/overview.js';
|
|
335
364
|
import { getDesktopNotificationPayload, shouldNotifyDesktop } from './modules/desktopNotifications.js';
|
|
336
365
|
import { getLoadingPresentation, getQuietRefreshSectionIdentifiers } from './modules/loading.js';
|
|
337
|
-
import { computeCardCounters } from './modules/cardCounters.js';
|
|
366
|
+
import { computeCardCounters, extractGithubSlug } from './modules/cardCounters.js';
|
|
338
367
|
import { collectReviewNotifications, createReviewNotificationState } from './modules/notifications.js';
|
|
339
368
|
import { resolveReviewAssigneeDisplay } from './modules/assignee.js';
|
|
340
369
|
import { buildQueueLanesModel } from './modules/queueLanes.js';
|
|
@@ -804,6 +833,13 @@
|
|
|
804
833
|
document.getElementById('focus-next-count').textContent = String(nextCount);
|
|
805
834
|
document.getElementById('focus-blocked-count').textContent = String(blocked);
|
|
806
835
|
|
|
836
|
+
const chipNow = document.querySelector('.focus-chip.focus-now');
|
|
837
|
+
const chipNext = document.querySelector('.focus-chip.focus-next');
|
|
838
|
+
const chipBlocked = document.querySelector('.focus-chip.focus-blocked');
|
|
839
|
+
if (chipNow) chipNow.dataset.active = nowCount > 0 ? 'true' : 'false';
|
|
840
|
+
if (chipNext) chipNext.dataset.active = nextCount > 0 ? 'true' : 'false';
|
|
841
|
+
if (chipBlocked) chipBlocked.dataset.active = blocked > 0 ? 'critical' : 'false';
|
|
842
|
+
|
|
807
843
|
const activeReviewsSection = document.getElementById('active-reviews-section');
|
|
808
844
|
const activeReviewsEl = document.getElementById('active-reviews');
|
|
809
845
|
const activeReviewsCount = document.getElementById('active-reviews-count');
|
|
@@ -2392,7 +2428,11 @@
|
|
|
2392
2428
|
} else {
|
|
2393
2429
|
const repository = availableRepositories.find((r) => r.localPath === activeTabId);
|
|
2394
2430
|
const projectName = repository?.name ?? activeTabId.split('/').filter(Boolean).pop() ?? activeTabId;
|
|
2395
|
-
|
|
2431
|
+
const aliases = [];
|
|
2432
|
+
const slug = extractGithubSlug(repository?.remoteUrl);
|
|
2433
|
+
if (slug) aliases.push(slug);
|
|
2434
|
+
if (repository?.name) aliases.push(repository.name);
|
|
2435
|
+
scope = { kind: 'project', localPath: activeTabId, projectName, aliases };
|
|
2396
2436
|
}
|
|
2397
2437
|
const counters = computeCardCounters({
|
|
2398
2438
|
activeReviews: currentData.activeReviews,
|
|
@@ -2428,6 +2468,7 @@
|
|
|
2428
2468
|
handleTabClick(tabId);
|
|
2429
2469
|
});
|
|
2430
2470
|
});
|
|
2471
|
+
setupTabUnderline();
|
|
2431
2472
|
}
|
|
2432
2473
|
|
|
2433
2474
|
function handleTabClick(tabId) {
|
|
@@ -2499,6 +2540,11 @@
|
|
|
2499
2540
|
});
|
|
2500
2541
|
dialog.innerHTML = renderSettingsModalHtml(viewModel);
|
|
2501
2542
|
bindSettingsModalForm(dialog);
|
|
2543
|
+
const uiLangSelect = dialog.querySelector('#settings-modal-ui-language');
|
|
2544
|
+
if (uiLangSelect) {
|
|
2545
|
+
const hiddenSelect = document.getElementById('language-select');
|
|
2546
|
+
uiLangSelect.value = hiddenSelect ? hiddenSelect.value : getLanguage();
|
|
2547
|
+
}
|
|
2502
2548
|
dialog.showModal();
|
|
2503
2549
|
} catch (error) {
|
|
2504
2550
|
showToast(t('toast.error') || 'Erreur', 'error');
|
|
@@ -2627,6 +2673,12 @@
|
|
|
2627
2673
|
isManagePanelOpen = !isManagePanelOpen;
|
|
2628
2674
|
toggle.setAttribute('aria-expanded', isManagePanelOpen ? 'true' : 'false');
|
|
2629
2675
|
renderManagePanel();
|
|
2676
|
+
const panel = document.getElementById('manage-panel');
|
|
2677
|
+
if (panel) {
|
|
2678
|
+
loadAnimeApi().then((anime) => {
|
|
2679
|
+
if (anime) toggleHeight(panel, isManagePanelOpen, { animeApi: anime });
|
|
2680
|
+
}).catch(() => {});
|
|
2681
|
+
}
|
|
2630
2682
|
});
|
|
2631
2683
|
}
|
|
2632
2684
|
|
|
@@ -3390,7 +3442,169 @@
|
|
|
3390
3442
|
}
|
|
3391
3443
|
|
|
3392
3444
|
refreshWorktreeSection({ animate: true });
|
|
3393
|
-
setInterval(() => refreshWorktreeSection({ animate: false }),
|
|
3445
|
+
setInterval(() => refreshWorktreeSection({ animate: false }), 5000);
|
|
3446
|
+
|
|
3447
|
+
// === Operator's Console boot animations ===
|
|
3448
|
+
|
|
3449
|
+
let heartbeatStop = null;
|
|
3450
|
+
|
|
3451
|
+
async function bootAnimations() {
|
|
3452
|
+
const anime = await loadAnimeApi();
|
|
3453
|
+
if (!anime) return;
|
|
3454
|
+
|
|
3455
|
+
// Logo breath — daemon-alive signal
|
|
3456
|
+
const logo = document.querySelector('.logo');
|
|
3457
|
+
if (logo) breatheLogo(logo, { animeApi: anime });
|
|
3458
|
+
|
|
3459
|
+
// Online status dot pulse
|
|
3460
|
+
const statusDot = document.querySelector('.status-dot');
|
|
3461
|
+
if (statusDot) pulseStatusDot(statusDot, { animeApi: anime });
|
|
3462
|
+
|
|
3463
|
+
// Metric cards stagger mount
|
|
3464
|
+
const cards = document.querySelectorAll('.cards > .card');
|
|
3465
|
+
if (cards.length > 0) animateMount(cards, { animeApi: anime });
|
|
3466
|
+
|
|
3467
|
+
// Sidebar slide-in
|
|
3468
|
+
const sidebar = document.querySelector('.dashboard-sidebar');
|
|
3469
|
+
if (sidebar && !reducedMotion()) {
|
|
3470
|
+
anime.animate(sidebar, {
|
|
3471
|
+
opacity: [{ from: 0, to: 1 }],
|
|
3472
|
+
translateX: [{ from: -8, to: 0 }],
|
|
3473
|
+
duration: 280,
|
|
3474
|
+
easing: 'easeOutCubic',
|
|
3475
|
+
});
|
|
3476
|
+
}
|
|
3477
|
+
|
|
3478
|
+
// Attention strip mount (focus-strip promoted to main)
|
|
3479
|
+
const focusChips = document.querySelectorAll('.focus-chip');
|
|
3480
|
+
if (focusChips.length > 0) animateMount(focusChips, { animeApi: anime, staggerMs: 40, yOffset: 8 });
|
|
3481
|
+
|
|
3482
|
+
// Heartbeat on pending-reviews empty state
|
|
3483
|
+
startHeartbeat(anime);
|
|
3484
|
+
|
|
3485
|
+
// Card hover lift — wire to existing cards
|
|
3486
|
+
wireCardHovers(anime);
|
|
3487
|
+
|
|
3488
|
+
// Settings modal spring-in
|
|
3489
|
+
wireSettingsModal(anime);
|
|
3490
|
+
}
|
|
3491
|
+
|
|
3492
|
+
function startHeartbeat(anime) {
|
|
3493
|
+
const container = document.getElementById('heartbeat-line');
|
|
3494
|
+
if (!container) return;
|
|
3495
|
+
if (heartbeatStop) heartbeatStop.stop();
|
|
3496
|
+
heartbeatStop = heartbeat(container, { animeApi: anime });
|
|
3497
|
+
}
|
|
3498
|
+
|
|
3499
|
+
function wireCardHovers(anime) {
|
|
3500
|
+
const cards = document.querySelectorAll('.cards > .card');
|
|
3501
|
+
for (const card of cards) {
|
|
3502
|
+
card.addEventListener('mouseenter', () => liftCard(card, { animeApi: anime }));
|
|
3503
|
+
card.addEventListener('mouseleave', () => unliftCard(card, { animeApi: anime }));
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
|
|
3507
|
+
function wireSettingsModal(anime) {
|
|
3508
|
+
const modal = document.getElementById('settings-modal');
|
|
3509
|
+
if (!modal) return;
|
|
3510
|
+
modal.addEventListener('animationsjs-open', () => springIn(modal, { animeApi: anime }));
|
|
3511
|
+
}
|
|
3512
|
+
|
|
3513
|
+
// Tab underline glide — set up after tab bar renders
|
|
3514
|
+
let tabUnderlineEl = null;
|
|
3515
|
+
|
|
3516
|
+
function setupTabUnderline() {
|
|
3517
|
+
const tabBar = document.querySelector('.dashboard-tab-bar');
|
|
3518
|
+
if (!tabBar) return;
|
|
3519
|
+
|
|
3520
|
+
if (!tabUnderlineEl) {
|
|
3521
|
+
tabUnderlineEl = document.createElement('div');
|
|
3522
|
+
tabUnderlineEl.className = 'tab-underline-indicator';
|
|
3523
|
+
tabBar.style.position = 'relative';
|
|
3524
|
+
tabBar.appendChild(tabUnderlineEl);
|
|
3525
|
+
}
|
|
3526
|
+
|
|
3527
|
+
const activeTab = tabBar.querySelector('.is-active');
|
|
3528
|
+
if (activeTab) {
|
|
3529
|
+
loadAnimeApi().then((anime) => {
|
|
3530
|
+
if (anime && tabUnderlineEl) slideTabUnderline(tabUnderlineEl, activeTab, { animeApi: anime });
|
|
3531
|
+
}).catch(() => {});
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
// Counter animation — wrap renderCardCounters and focus strip to animate changes
|
|
3536
|
+
const originalCounterIds = ['running-count', 'queued-count', 'completed-count', 'focus-now-count', 'focus-next-count', 'focus-blocked-count'];
|
|
3537
|
+
const previousCounterValues = {};
|
|
3538
|
+
|
|
3539
|
+
function animateCounterChanges(anime) {
|
|
3540
|
+
for (const id of originalCounterIds) {
|
|
3541
|
+
const el = document.getElementById(id);
|
|
3542
|
+
if (!el) continue;
|
|
3543
|
+
if (el.dataset.animating === 'true') continue;
|
|
3544
|
+
const currentText = el.textContent;
|
|
3545
|
+
const currentVal = parseInt(currentText, 10);
|
|
3546
|
+
const prevVal = previousCounterValues[id];
|
|
3547
|
+
if (!Number.isNaN(currentVal) && prevVal !== undefined && prevVal !== currentVal) {
|
|
3548
|
+
el.dataset.animating = 'true';
|
|
3549
|
+
animateCounterValue(el, prevVal, currentVal, {
|
|
3550
|
+
animeApi: anime,
|
|
3551
|
+
onComplete: () => {
|
|
3552
|
+
el.dataset.animating = 'false';
|
|
3553
|
+
previousCounterValues[id] = currentVal;
|
|
3554
|
+
},
|
|
3555
|
+
});
|
|
3556
|
+
} else if (!Number.isNaN(currentVal)) {
|
|
3557
|
+
previousCounterValues[id] = currentVal;
|
|
3558
|
+
}
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3561
|
+
|
|
3562
|
+
// Observe counter element changes
|
|
3563
|
+
async function observeCounters() {
|
|
3564
|
+
const anime = await loadAnimeApi();
|
|
3565
|
+
if (!anime) return;
|
|
3566
|
+
|
|
3567
|
+
// Snapshot initial values
|
|
3568
|
+
for (const id of originalCounterIds) {
|
|
3569
|
+
const el = document.getElementById(id);
|
|
3570
|
+
if (el) {
|
|
3571
|
+
const val = parseInt(el.textContent, 10);
|
|
3572
|
+
if (!Number.isNaN(val)) previousCounterValues[id] = val;
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
|
|
3576
|
+
const observer = new MutationObserver(() => animateCounterChanges(anime));
|
|
3577
|
+
for (const id of originalCounterIds) {
|
|
3578
|
+
const el = document.getElementById(id);
|
|
3579
|
+
if (el) observer.observe(el, { childList: true, characterData: true, subtree: true });
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
|
|
3583
|
+
// Visibility change — pause/resume heartbeat to save battery
|
|
3584
|
+
document.addEventListener('visibilitychange', () => {
|
|
3585
|
+
loadAnimeApi().then((anime) => {
|
|
3586
|
+
if (!anime) return;
|
|
3587
|
+
if (document.hidden) {
|
|
3588
|
+
if (heartbeatStop) heartbeatStop.stop();
|
|
3589
|
+
} else {
|
|
3590
|
+
startHeartbeat(anime);
|
|
3591
|
+
}
|
|
3592
|
+
}).catch(() => {});
|
|
3593
|
+
});
|
|
3594
|
+
|
|
3595
|
+
// Boot animations & observers exactly once, regardless of readyState timing
|
|
3596
|
+
let __animationsBooted = false;
|
|
3597
|
+
function bootOnce() {
|
|
3598
|
+
if (__animationsBooted) return;
|
|
3599
|
+
__animationsBooted = true;
|
|
3600
|
+
bootAnimations();
|
|
3601
|
+
observeCounters();
|
|
3602
|
+
}
|
|
3603
|
+
if (document.readyState !== 'loading') {
|
|
3604
|
+
bootOnce();
|
|
3605
|
+
} else {
|
|
3606
|
+
window.addEventListener('DOMContentLoaded', bootOnce);
|
|
3607
|
+
}
|
|
3394
3608
|
</script>
|
|
3395
3609
|
</body>
|
|
3396
3610
|
</html>
|