reviewflow 3.22.0 → 3.24.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 +22 -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 +30 -6
- package/dist/dashboard/modules/desktopNotifications.d.ts +7 -1
- package/dist/dashboard/modules/desktopNotifications.d.ts.map +1 -1
- package/dist/dashboard/modules/desktopNotifications.js +194 -15
- package/dist/dashboard/modules/desktopNotifications.js.map +1 -1
- package/dist/dashboard/modules/i18n.d.ts.map +1 -1
- package/dist/dashboard/modules/i18n.js +22 -2
- package/dist/dashboard/modules/i18n.js.map +1 -1
- package/dist/dashboard/modules/settingsModal.d.ts +17 -0
- package/dist/dashboard/modules/settingsModal.d.ts.map +1 -1
- package/dist/dashboard/modules/settingsModal.js +33 -0
- package/dist/dashboard/modules/settingsModal.js.map +1 -1
- package/dist/frameworks/claude/claudeInvoker.d.ts +2 -0
- package/dist/frameworks/claude/claudeInvoker.d.ts.map +1 -1
- package/dist/frameworks/claude/claudeInvoker.js +14 -3
- package/dist/frameworks/claude/claudeInvoker.js.map +1 -1
- package/dist/frameworks/queue/pQueueAdapter.d.ts +27 -0
- package/dist/frameworks/queue/pQueueAdapter.d.ts.map +1 -1
- package/dist/frameworks/queue/pQueueAdapter.js +4 -0
- package/dist/frameworks/queue/pQueueAdapter.js.map +1 -1
- 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/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.d.ts.map +1 -1
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.js +13 -0
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.js.map +1 -1
- package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.d.ts +4 -2
- package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.d.ts.map +1 -1
- package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.js +21 -0
- package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.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/githubPullRequestEvent.guard.d.ts +12 -0
- package/dist/modules/platform-integration/entities/github/githubPullRequestEvent.guard.d.ts.map +1 -1
- package/dist/modules/platform-integration/entities/github/githubPullRequestEvent.guard.js +4 -0
- package/dist/modules/platform-integration/entities/github/githubPullRequestEvent.guard.js.map +1 -1
- 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 +171 -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 +132 -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/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/modules/worktree-management/entities/gitCommand/gitCommand.gateway.d.ts +1 -1
- package/dist/modules/worktree-management/entities/gitCommand/gitCommand.gateway.d.ts.map +1 -1
- package/dist/modules/worktree-management/services/claudeCwd.d.ts +15 -0
- package/dist/modules/worktree-management/services/claudeCwd.d.ts.map +1 -0
- package/dist/modules/worktree-management/services/claudeCwd.js +45 -0
- package/dist/modules/worktree-management/services/claudeCwd.js.map +1 -0
- 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/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/units/config/projectConfig.test.js +62 -0
- package/dist/tests/units/config/projectConfig.test.js.map +1 -1
- package/dist/tests/units/dashboard/modules/desktopNotifications.test.js +230 -13
- package/dist/tests/units/dashboard/modules/desktopNotifications.test.js.map +1 -1
- package/dist/tests/units/dashboard/modules/settingsModal.test.js +106 -2
- package/dist/tests/units/dashboard/modules/settingsModal.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 +6 -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 +10 -0
- package/dist/tests/units/interface-adapters/controllers/webhook/gitlab.controller.test.js.map +1 -1
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.test.js +39 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.test.js.map +1 -1
- package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.test.js +69 -0
- package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.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/services/claudeCwd.test.d.ts +2 -0
- package/dist/tests/units/modules/worktree-management/services/claudeCwd.test.d.ts.map +1 -0
- package/dist/tests/units/modules/worktree-management/services/claudeCwd.test.js +111 -0
- package/dist/tests/units/modules/worktree-management/services/claudeCwd.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/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,28 @@ 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.24.0](https://github.com/DGouron/review-flow/compare/reviewflow-v3.23.0...reviewflow-v3.24.0) (2026-05-26)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
* **dashboard:** expose qualityThreshold in settings + read-only display ([#214](https://github.com/DGouron/review-flow/issues/214)) ([2d65635](https://github.com/DGouron/review-flow/commit/2d65635b1a24d4d6e30b52f79c21d1ab131e5cf8))
|
|
14
|
+
* **dashboard:** rich, interactive desktop notifications ([#213](https://github.com/DGouron/review-flow/issues/213)) ([3c2580a](https://github.com/DGouron/review-flow/commit/3c2580a104147da67c7bd71bd943a47f9f6517b2))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
* **worktree:** preserve sub-path between localPath and gitRoot when launching Claude ([#216](https://github.com/DGouron/review-flow/issues/216)) ([b4867c8](https://github.com/DGouron/review-flow/commit/b4867c8c8809dd93e72980357aad309cdd82e1e6))
|
|
20
|
+
|
|
21
|
+
## [3.23.0](https://github.com/DGouron/review-flow/compare/reviewflow-v3.22.0...reviewflow-v3.23.0) (2026-05-26)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
* **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))
|
|
27
|
+
* **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))
|
|
28
|
+
* **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))
|
|
29
|
+
|
|
8
30
|
## [3.22.0](https://github.com/DGouron/review-flow/compare/reviewflow-v3.21.0...reviewflow-v3.22.0) (2026-05-25)
|
|
9
31
|
|
|
10
32
|
|
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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"}
|
|
@@ -399,6 +399,7 @@
|
|
|
399
399
|
buildSettingsViewModel,
|
|
400
400
|
renderSettingsModalHtml,
|
|
401
401
|
validateExternalLink,
|
|
402
|
+
validateQualityThreshold,
|
|
402
403
|
extractFormPayload,
|
|
403
404
|
} from './modules/settingsModal.js';
|
|
404
405
|
|
|
@@ -664,10 +665,18 @@
|
|
|
664
665
|
|
|
665
666
|
const desktopPayload = getDesktopNotificationPayload(notification, t);
|
|
666
667
|
if (!desktopPayload) return;
|
|
667
|
-
new Notification(desktopPayload.title, {
|
|
668
|
+
const desktopNotif = new Notification(desktopPayload.title, {
|
|
668
669
|
body: desktopPayload.body,
|
|
669
670
|
tag: desktopPayload.tag,
|
|
671
|
+
icon: desktopPayload.iconDataUri,
|
|
670
672
|
});
|
|
673
|
+
desktopNotif.onclick = () => {
|
|
674
|
+
window.focus();
|
|
675
|
+
if (desktopPayload.url) {
|
|
676
|
+
window.open(desktopPayload.url, '_blank', 'noopener');
|
|
677
|
+
}
|
|
678
|
+
desktopNotif.close();
|
|
679
|
+
};
|
|
671
680
|
}
|
|
672
681
|
|
|
673
682
|
function dispatchReviewNotifications(activeReviews, recentReviews) {
|
|
@@ -1708,12 +1717,13 @@
|
|
|
1708
1717
|
const assigneeDisplay = mr.assignment?.displayName || assigneeUsername;
|
|
1709
1718
|
const ownerLabel = t('lane.owner', { owner: assigneeDisplay });
|
|
1710
1719
|
const qualityScore = typeof mr.latestScore === 'number' ? mr.latestScore : null;
|
|
1711
|
-
const
|
|
1720
|
+
const activeQualityTarget = currentProjectConfig?.qualityThreshold ?? QUALITY_TARGET_SCORE;
|
|
1721
|
+
const qualityProgress = getQualityProgress(qualityScore, activeQualityTarget);
|
|
1712
1722
|
const qualityTarget = qualityProgress.qualityTarget;
|
|
1713
1723
|
const qualityDelta = qualityProgress.targetDelta;
|
|
1714
1724
|
const qualityState = qualityScore === null
|
|
1715
1725
|
? 'unknown'
|
|
1716
|
-
: qualityScore >=
|
|
1726
|
+
: qualityScore >= activeQualityTarget
|
|
1717
1727
|
? 'excellent'
|
|
1718
1728
|
: qualityScore >= 6
|
|
1719
1729
|
? 'warning'
|
|
@@ -1722,7 +1732,7 @@
|
|
|
1722
1732
|
? t('quality.notAvailable')
|
|
1723
1733
|
: qualityScore >= 10
|
|
1724
1734
|
? t('quality.perfect')
|
|
1725
|
-
: qualityScore >=
|
|
1735
|
+
: qualityScore >= activeQualityTarget
|
|
1726
1736
|
? t('quality.onTarget')
|
|
1727
1737
|
: qualityScore >= 6
|
|
1728
1738
|
? t('quality.belowTarget')
|
|
@@ -1852,7 +1862,9 @@
|
|
|
1852
1862
|
const pendingApprovalCount = document.getElementById('pending-approval-count');
|
|
1853
1863
|
|
|
1854
1864
|
pendingFixSection.classList.remove('hidden');
|
|
1855
|
-
const rankedPendingFix = rankPendingFixForNowLane(currentData.pendingFix
|
|
1865
|
+
const rankedPendingFix = rankPendingFixForNowLane(currentData.pendingFix, {
|
|
1866
|
+
qualityTarget: currentProjectConfig?.qualityThreshold ?? QUALITY_TARGET_SCORE,
|
|
1867
|
+
});
|
|
1856
1868
|
const queueLanesModel = buildQueueLanesModel(rankedPendingFix, currentData.pendingApproval);
|
|
1857
1869
|
|
|
1858
1870
|
mrDataStore.clear();
|
|
@@ -2577,13 +2589,21 @@
|
|
|
2577
2589
|
if (errorEl) errorEl.textContent = linkValidation.message;
|
|
2578
2590
|
return;
|
|
2579
2591
|
}
|
|
2592
|
+
const thresholdRaw = payload.qualityThreshold ?? '';
|
|
2593
|
+
const thresholdValidation = validateQualityThreshold(thresholdRaw);
|
|
2594
|
+
if (!thresholdValidation.ok) {
|
|
2595
|
+
if (errorEl) errorEl.textContent = thresholdValidation.message;
|
|
2596
|
+
return;
|
|
2597
|
+
}
|
|
2598
|
+
const requestBody = { ...payload };
|
|
2599
|
+
requestBody.qualityThreshold = thresholdRaw === '' ? null : Number(thresholdRaw);
|
|
2580
2600
|
try {
|
|
2581
2601
|
const response = await fetch(
|
|
2582
2602
|
`${API_URL}/api/project-config?path=${encodeURIComponent(activeTabId)}`,
|
|
2583
2603
|
{
|
|
2584
2604
|
method: 'PATCH',
|
|
2585
2605
|
headers: { 'Content-Type': 'application/json' },
|
|
2586
|
-
body: JSON.stringify(
|
|
2606
|
+
body: JSON.stringify(requestBody),
|
|
2587
2607
|
},
|
|
2588
2608
|
);
|
|
2589
2609
|
if (!response.ok) {
|
|
@@ -2591,6 +2611,10 @@
|
|
|
2591
2611
|
if (errorEl) errorEl.textContent = errorPayload?.error || 'Échec de la sauvegarde';
|
|
2592
2612
|
return;
|
|
2593
2613
|
}
|
|
2614
|
+
const updated = await response.json().catch(() => null);
|
|
2615
|
+
if (updated?.config) {
|
|
2616
|
+
currentProjectConfig = updated.config;
|
|
2617
|
+
}
|
|
2594
2618
|
closeSettingsModal();
|
|
2595
2619
|
refreshOverviewSection();
|
|
2596
2620
|
} catch {
|
|
@@ -10,7 +10,7 @@ export function shouldNotifyDesktop(options: {
|
|
|
10
10
|
/**
|
|
11
11
|
* @param {{ kind: string, review: Record<string, unknown> }} notification
|
|
12
12
|
* @param {(key: string, params?: Record<string, string | number>) => string} translate
|
|
13
|
-
* @returns {{ title: string, body: string, tag: string } | null}
|
|
13
|
+
* @returns {{ title: string, body: string, tag: string, url: string | null, iconDataUri: string } | null}
|
|
14
14
|
*/
|
|
15
15
|
export function getDesktopNotificationPayload(notification: {
|
|
16
16
|
kind: string;
|
|
@@ -19,5 +19,11 @@ export function getDesktopNotificationPayload(notification: {
|
|
|
19
19
|
title: string;
|
|
20
20
|
body: string;
|
|
21
21
|
tag: string;
|
|
22
|
+
url: string | null;
|
|
23
|
+
iconDataUri: string;
|
|
22
24
|
} | null;
|
|
25
|
+
export type KindFormat = {
|
|
26
|
+
emoji: string;
|
|
27
|
+
labelKey: string;
|
|
28
|
+
};
|
|
23
29
|
//# sourceMappingURL=desktopNotifications.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"desktopNotifications.d.ts","sourceRoot":"","sources":["../../../src/dashboard/modules/desktopNotifications.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH,6CAHW;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC5E,OAAO,CAMnB;
|
|
1
|
+
{"version":3,"file":"desktopNotifications.d.ts","sourceRoot":"","sources":["../../../src/dashboard/modules/desktopNotifications.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH,6CAHW;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAC;IAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC5E,OAAO,CAMnB;AAyLD;;;;GAIG;AACH,4DAJW;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,aACjD,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,MAAM,GAC/D;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAoBxG;;WA5Ma,MAAM;cACN,MAAM"}
|
|
@@ -8,31 +8,210 @@ export function shouldNotifyDesktop(options) {
|
|
|
8
8
|
return options.isDocumentHidden;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {Object} KindFormat
|
|
13
|
+
* @property {string} emoji
|
|
14
|
+
* @property {string} labelKey
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** @type {Record<string, KindFormat>} */
|
|
18
|
+
const KIND_FORMATS = {
|
|
19
|
+
reviewStarted: { emoji: '🔍', labelKey: 'notify.label.reviewStarted' },
|
|
20
|
+
followupStarted: { emoji: '🔁', labelKey: 'notify.label.followupStarted' },
|
|
21
|
+
reviewCompleted: { emoji: '✅', labelKey: 'notify.label.reviewCompleted' },
|
|
22
|
+
followupCompleted: { emoji: '✅', labelKey: 'notify.label.followupCompleted' },
|
|
23
|
+
reviewFailed: { emoji: '❌', labelKey: 'notify.label.reviewFailed' },
|
|
24
|
+
reviewPendingConfirmation: { emoji: '⏳', labelKey: 'notify.label.reviewPendingConfirmation' },
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Size category thresholds (sum of additions + deletions).
|
|
28
|
+
// Tweak here if you find them off — kept central on purpose.
|
|
29
|
+
const SIZE_THRESHOLD_SMALL_MAX = 50;
|
|
30
|
+
const SIZE_THRESHOLD_MEDIUM_MAX = 300;
|
|
31
|
+
const SIZE_EMOJI = { small: '🪶', medium: '🚀', big: '🐘' };
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {unknown} value
|
|
35
|
+
* @returns {number | null}
|
|
36
|
+
*/
|
|
37
|
+
function toFiniteNumber(value) {
|
|
38
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {Record<string, unknown> | undefined} sizeMetrics
|
|
43
|
+
* @returns {'small' | 'medium' | 'big'}
|
|
44
|
+
*/
|
|
45
|
+
function categorizeSize(sizeMetrics) {
|
|
46
|
+
if (!sizeMetrics) return 'small';
|
|
47
|
+
const additions = toFiniteNumber(sizeMetrics.additions);
|
|
48
|
+
const deletions = toFiniteNumber(sizeMetrics.deletions);
|
|
49
|
+
if (additions !== null && deletions !== null) {
|
|
50
|
+
const total = additions + deletions;
|
|
51
|
+
if (total < SIZE_THRESHOLD_SMALL_MAX) return 'small';
|
|
52
|
+
if (total < SIZE_THRESHOLD_MEDIUM_MAX) return 'medium';
|
|
53
|
+
return 'big';
|
|
54
|
+
}
|
|
55
|
+
const filesChanged = toFiniteNumber(sizeMetrics.filesChanged);
|
|
56
|
+
if (filesChanged !== null) {
|
|
57
|
+
if (filesChanged <= 3) return 'small';
|
|
58
|
+
if (filesChanged <= 10) return 'medium';
|
|
59
|
+
return 'big';
|
|
60
|
+
}
|
|
61
|
+
return 'small';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {Record<string, unknown>} review
|
|
66
|
+
* @returns {string | null}
|
|
67
|
+
*/
|
|
68
|
+
function buildSizeLine(review) {
|
|
69
|
+
const metrics = review.sizeMetrics;
|
|
70
|
+
if (!metrics || typeof metrics !== 'object') return null;
|
|
71
|
+
const typed = /** @type {Record<string, unknown>} */ (metrics);
|
|
72
|
+
const additions = toFiniteNumber(typed.additions);
|
|
73
|
+
const deletions = toFiniteNumber(typed.deletions);
|
|
74
|
+
const filesChanged = toFiniteNumber(typed.filesChanged);
|
|
75
|
+
const hasAnyStat = additions !== null || deletions !== null || filesChanged !== null;
|
|
76
|
+
if (!hasAnyStat) return null;
|
|
77
|
+
const emoji = SIZE_EMOJI[categorizeSize(typed)];
|
|
78
|
+
const parts = [];
|
|
79
|
+
if (additions !== null && deletions !== null) {
|
|
80
|
+
parts.push(`+${additions}/-${deletions}`);
|
|
81
|
+
}
|
|
82
|
+
if (filesChanged !== null) {
|
|
83
|
+
parts.push(`${filesChanged} files`);
|
|
84
|
+
}
|
|
85
|
+
return `${emoji} ${parts.join(' · ')}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @param {unknown} actor
|
|
90
|
+
* @returns {string | null}
|
|
91
|
+
*/
|
|
92
|
+
function resolveActorName(actor) {
|
|
93
|
+
if (!actor || typeof actor !== 'object') return null;
|
|
94
|
+
const typed = /** @type {{ displayName?: unknown, username?: unknown }} */ (actor);
|
|
95
|
+
if (typeof typed.displayName === 'string' && typed.displayName.length > 0) {
|
|
96
|
+
return typed.displayName;
|
|
97
|
+
}
|
|
98
|
+
if (typeof typed.username === 'string' && typed.username.length > 0) {
|
|
99
|
+
return typed.username;
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {Record<string, unknown>} review
|
|
106
|
+
* @returns {string | null}
|
|
107
|
+
*/
|
|
108
|
+
function resolveAuthor(review) {
|
|
109
|
+
return resolveActorName(review.author) ?? resolveActorName(review.assignedBy);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @param {Record<string, unknown>} review
|
|
114
|
+
* @returns {string | null}
|
|
115
|
+
*/
|
|
116
|
+
function resolveProjectShortName(review) {
|
|
117
|
+
if (typeof review.project !== 'string' || review.project.length === 0) return null;
|
|
118
|
+
const segments = review.project.split('/');
|
|
119
|
+
const last = segments[segments.length - 1];
|
|
120
|
+
return last && last.length > 0 ? last : null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {Record<string, unknown>} review
|
|
125
|
+
* @returns {'gitlab' | 'github'}
|
|
126
|
+
*/
|
|
127
|
+
function resolvePlatform(review) {
|
|
128
|
+
const id = typeof review.id === 'string' ? review.id : '';
|
|
129
|
+
return id.startsWith('github') ? 'github' : 'gitlab';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {Record<string, unknown>} review
|
|
134
|
+
* @returns {'!' | '#'}
|
|
135
|
+
*/
|
|
136
|
+
function resolveMrPrefix(review) {
|
|
137
|
+
return resolvePlatform(review) === 'github' ? '#' : '!';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const PLATFORM_ICONS = {
|
|
141
|
+
gitlab: buildPlatformIconDataUri('GL', 'FC6D26'),
|
|
142
|
+
github: buildPlatformIconDataUri('GH', '181717'),
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @param {string} label
|
|
147
|
+
* @param {string} hexColor
|
|
148
|
+
* @returns {string}
|
|
149
|
+
*/
|
|
150
|
+
function buildPlatformIconDataUri(label, hexColor) {
|
|
151
|
+
const svg =
|
|
152
|
+
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">` +
|
|
153
|
+
`<rect width="64" height="64" rx="12" fill="#${hexColor}"/>` +
|
|
154
|
+
`<text x="32" y="42" font-size="28" text-anchor="middle" fill="white" ` +
|
|
155
|
+
`font-family="-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif" font-weight="700">${label}</text>` +
|
|
156
|
+
'</svg>';
|
|
157
|
+
return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @param {KindFormat} format
|
|
162
|
+
* @param {(key: string) => string} translate
|
|
163
|
+
* @param {Record<string, unknown>} review
|
|
164
|
+
* @returns {string}
|
|
165
|
+
*/
|
|
166
|
+
function buildTitle(format, translate, review) {
|
|
167
|
+
const mrNumber = typeof review.mrNumber === 'number' ? String(review.mrNumber) : '?';
|
|
168
|
+
const mrToken = `${resolveMrPrefix(review)}${mrNumber}`;
|
|
169
|
+
const label = translate(format.labelKey);
|
|
170
|
+
const author = resolveAuthor(review);
|
|
171
|
+
const segments = author
|
|
172
|
+
? [`${format.emoji} ${label}`, author, mrToken]
|
|
173
|
+
: [`${format.emoji} ${label}`, mrToken];
|
|
174
|
+
return segments.join(' · ');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @param {Record<string, unknown>} review
|
|
179
|
+
* @returns {string}
|
|
180
|
+
*/
|
|
181
|
+
function buildBody(review) {
|
|
182
|
+
const lines = [];
|
|
183
|
+
const title = typeof review.title === 'string' ? review.title.trim() : '';
|
|
184
|
+
if (title.length > 0) lines.push(title);
|
|
185
|
+
const sizeLine = buildSizeLine(review);
|
|
186
|
+
const project = resolveProjectShortName(review);
|
|
187
|
+
const secondLineParts = [];
|
|
188
|
+
if (sizeLine) secondLineParts.push(sizeLine);
|
|
189
|
+
if (project) secondLineParts.push(project);
|
|
190
|
+
if (secondLineParts.length > 0) lines.push(secondLineParts.join(' · '));
|
|
191
|
+
return lines.join('\n');
|
|
192
|
+
}
|
|
193
|
+
|
|
11
194
|
/**
|
|
12
195
|
* @param {{ kind: string, review: Record<string, unknown> }} notification
|
|
13
196
|
* @param {(key: string, params?: Record<string, string | number>) => string} translate
|
|
14
|
-
* @returns {{ title: string, body: string, tag: string } | null}
|
|
197
|
+
* @returns {{ title: string, body: string, tag: string, url: string | null, iconDataUri: string } | null}
|
|
15
198
|
*/
|
|
16
199
|
export function getDesktopNotificationPayload(notification, translate) {
|
|
200
|
+
const format = KIND_FORMATS[notification.kind];
|
|
201
|
+
if (!format) return null;
|
|
202
|
+
|
|
17
203
|
const mrNumber = typeof notification.review.mrNumber === 'number'
|
|
18
204
|
? String(notification.review.mrNumber)
|
|
19
205
|
: '?';
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
followupStarted: 'notify.followupStarted',
|
|
24
|
-
reviewCompleted: 'notify.reviewCompleted',
|
|
25
|
-
followupCompleted: 'notify.followupCompleted',
|
|
26
|
-
reviewFailed: 'notify.reviewFailed',
|
|
27
|
-
reviewPendingConfirmation: 'notify.reviewPendingConfirmation',
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const messageKey = messageKeyByKind[notification.kind];
|
|
31
|
-
if (!messageKey) return null;
|
|
206
|
+
const url = typeof notification.review.mrUrl === 'string' && notification.review.mrUrl.length > 0
|
|
207
|
+
? notification.review.mrUrl
|
|
208
|
+
: null;
|
|
32
209
|
|
|
33
210
|
return {
|
|
34
|
-
title: translate
|
|
35
|
-
body:
|
|
211
|
+
title: buildTitle(format, translate, notification.review),
|
|
212
|
+
body: buildBody(notification.review),
|
|
36
213
|
tag: `reviewflow-${notification.kind}-${mrNumber}`,
|
|
214
|
+
url,
|
|
215
|
+
iconDataUri: PLATFORM_ICONS[resolvePlatform(notification.review)],
|
|
37
216
|
};
|
|
38
217
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"desktopNotifications.js","sourceRoot":"","sources":["../../../src/dashboard/modules/desktopNotifications.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAO;IACzC,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACnD,IAAI,OAAO,CAAC,iBAAiB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,OAAO,CAAC,gBAAgB,CAAC;AAClC,CAAC;AAED;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"desktopNotifications.js","sourceRoot":"","sources":["../../../src/dashboard/modules/desktopNotifications.js"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/dashboard/modules/i18n.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/dashboard/modules/i18n.js"],"names":[],"mappings":"AAw1BA,6BAA6B;AAC7B,+BADc,IAAI,GAAG,IAAI,CAGxB;AAED,oCAAoC;AACpC,sCADY,IAAI,GAAG,IAAI,QAGtB;AAED;;;;GAIG;AACH,uBAJW,MAAM,WACN,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAC7B,MAAM,CAUlB"}
|
|
@@ -60,7 +60,7 @@ const translations = {
|
|
|
60
60
|
'quality.trendFlat': 'Stable',
|
|
61
61
|
'quality.trendUnknown': 'No trend yet',
|
|
62
62
|
|
|
63
|
-
// Notifications
|
|
63
|
+
// Notifications — toast labels (in-page)
|
|
64
64
|
'notify.reviewStarted': 'Review started for !{{mrNumber}}',
|
|
65
65
|
'notify.followupStarted': 'Follow-up started for !{{mrNumber}}',
|
|
66
66
|
'notify.reviewCompleted': 'Review completed for !{{mrNumber}}',
|
|
@@ -69,6 +69,13 @@ const translations = {
|
|
|
69
69
|
'notify.followupRequested': 'Follow-up requested for !{{mrNumber}}',
|
|
70
70
|
'notify.reviewPendingConfirmation': 'Review awaiting your confirmation for !{{mrNumber}}',
|
|
71
71
|
'notify.desktopTitle': 'Reviewflow alert',
|
|
72
|
+
// Notifications — desktop labels (short, used in rich payload)
|
|
73
|
+
'notify.label.reviewStarted': 'Review',
|
|
74
|
+
'notify.label.followupStarted': 'Follow-up',
|
|
75
|
+
'notify.label.reviewCompleted': 'Review done',
|
|
76
|
+
'notify.label.followupCompleted': 'Follow-up done',
|
|
77
|
+
'notify.label.reviewFailed': 'Review failed',
|
|
78
|
+
'notify.label.reviewPendingConfirmation': 'Awaiting confirmation',
|
|
72
79
|
|
|
73
80
|
// Loading
|
|
74
81
|
'loading.data': 'Syncing dashboard data...',
|
|
@@ -176,6 +183,9 @@ const translations = {
|
|
|
176
183
|
'settings.reviewFollowupSkill': 'Review followup skill',
|
|
177
184
|
'settings.externalLink': 'External link (HTTPS)',
|
|
178
185
|
'settings.externalLinkPlaceholder': 'https://notion.so/team/project',
|
|
186
|
+
'settings.qualityThreshold': 'Quality threshold (0-10)',
|
|
187
|
+
'settings.qualityThresholdPlaceholder': 'e.g. 7',
|
|
188
|
+
'settings.qualityThresholdHint': 'Approval is reverted when score falls below this threshold. Leave empty to disable.',
|
|
179
189
|
'settings.cancel': 'Cancel',
|
|
180
190
|
'settings.save': 'Save',
|
|
181
191
|
'empty.reviewsNoProject': 'Load a project to see reviews',
|
|
@@ -475,7 +485,7 @@ const translations = {
|
|
|
475
485
|
'quality.trendFlat': 'Stable',
|
|
476
486
|
'quality.trendUnknown': 'Pas de tendance',
|
|
477
487
|
|
|
478
|
-
// Notifications
|
|
488
|
+
// Notifications — toast labels (in-page)
|
|
479
489
|
'notify.reviewStarted': 'Review démarrée pour !{{mrNumber}}',
|
|
480
490
|
'notify.followupStarted': 'Follow-up démarré pour !{{mrNumber}}',
|
|
481
491
|
'notify.reviewCompleted': 'Review terminée pour !{{mrNumber}}',
|
|
@@ -484,6 +494,13 @@ const translations = {
|
|
|
484
494
|
'notify.followupRequested': 'Follow-up demandé pour !{{mrNumber}}',
|
|
485
495
|
'notify.reviewPendingConfirmation': 'Review en attente de votre confirmation pour !{{mrNumber}}',
|
|
486
496
|
'notify.desktopTitle': 'Alerte Reviewflow',
|
|
497
|
+
// Notifications — desktop labels (short, used in rich payload)
|
|
498
|
+
'notify.label.reviewStarted': 'Review',
|
|
499
|
+
'notify.label.followupStarted': 'Follow-up',
|
|
500
|
+
'notify.label.reviewCompleted': 'Review terminée',
|
|
501
|
+
'notify.label.followupCompleted': 'Follow-up terminé',
|
|
502
|
+
'notify.label.reviewFailed': 'Review échouée',
|
|
503
|
+
'notify.label.reviewPendingConfirmation': 'En attente',
|
|
487
504
|
|
|
488
505
|
// Loading
|
|
489
506
|
'loading.data': 'Synchronisation des données du dashboard...',
|
|
@@ -591,6 +608,9 @@ const translations = {
|
|
|
591
608
|
'settings.reviewFollowupSkill': 'Skill de review followup',
|
|
592
609
|
'settings.externalLink': 'Lien externe (HTTPS)',
|
|
593
610
|
'settings.externalLinkPlaceholder': 'https://notion.so/team/projet',
|
|
611
|
+
'settings.qualityThreshold': 'Seuil de qualité (0-10)',
|
|
612
|
+
'settings.qualityThresholdPlaceholder': 'ex. 7',
|
|
613
|
+
'settings.qualityThresholdHint': "L'approbation est annulée si le score passe sous ce seuil. Laisser vide pour désactiver.",
|
|
594
614
|
'settings.cancel': 'Annuler',
|
|
595
615
|
'settings.save': 'Enregistrer',
|
|
596
616
|
'empty.reviewsNoProject': 'Charger un projet pour voir les reviews',
|