vibe-coding-master 0.3.26 → 0.3.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/backend/api/codex-hook-routes.js +0 -7
- package/dist/backend/api/gate-review-routes.js +58 -0
- package/dist/backend/api/task-routes.js +2 -2
- package/dist/backend/cli/install-vcm-harness.js +15 -57
- package/dist/backend/server.js +6 -8
- package/dist/backend/services/app-settings-service.js +15 -15
- package/dist/backend/services/codex-hook-service.js +8 -50
- package/dist/backend/services/{codex-review-service.js → gate-review-service.js} +108 -108
- package/dist/backend/services/harness-service.js +15 -63
- package/dist/backend/services/session-service.js +257 -41
- package/dist/backend/services/task-service.js +2 -2
- package/dist/backend/templates/harness/claude-root.js +2 -2
- package/dist/backend/templates/harness/{codex-review.js → gate-review.js} +35 -278
- package/dist/backend/templates/harness/project-manager-agent.js +7 -7
- package/dist/backend/templates/harness/vcm-final-acceptance-skill.js +5 -5
- package/dist/shared/constants.js +8 -5
- package/dist/shared/types/{codex-review.js → gate-review.js} +1 -1
- package/dist-frontend/assets/{index-CKWy15WL.js → index-DVy34Iwn.js} +31 -31
- package/dist-frontend/index.html +1 -1
- package/docs/codex-translation-plan.md +9 -9
- package/docs/gate-review-gates.md +133 -0
- package/docs/product-design.md +25 -33
- package/package.json +1 -1
- package/scripts/verify-package.mjs +4 -4
- package/dist/backend/api/codex-review-routes.js +0 -58
- package/docs/codex-review-gates.md +0 -593
package/dist-frontend/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>VibeCodingMaster</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-DVy34Iwn.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-Cfum1Prr.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -432,7 +432,7 @@ target-language keyed session directory:
|
|
|
432
432
|
- the persisted session id should be associated with the base repository,
|
|
433
433
|
target language, selected model, selected effort, and harness path
|
|
434
434
|
|
|
435
|
-
The role must not use
|
|
435
|
+
The role must not use Gate Reviewer prompts or permissions.
|
|
436
436
|
|
|
437
437
|
Codex Translator should have durable instructions for both modes:
|
|
438
438
|
|
|
@@ -464,10 +464,10 @@ should be a separate explicit user action.
|
|
|
464
464
|
|
|
465
465
|
When VCM runs inside a Dev Container, Docker, Podman, Kubernetes, or Codespaces
|
|
466
466
|
environment, the container is the sandbox boundary. VCM should auto-detect that
|
|
467
|
-
environment and start Codex Translator with Codex's nested sandbox disabled
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
467
|
+
environment and start Codex Translator with Codex's nested sandbox disabled to
|
|
468
|
+
avoid Linux container `bwrap` and `apply_patch` failures caused by double
|
|
469
|
+
sandboxing. `VCM_SANDBOX=devcontainer` remains an explicit override for
|
|
470
|
+
environments that cannot be auto-detected.
|
|
471
471
|
|
|
472
472
|
## 10. Source Content Safety
|
|
473
473
|
|
|
@@ -1097,7 +1097,7 @@ New backend pieces:
|
|
|
1097
1097
|
- promote completed translations into explicit user-selected repo paths
|
|
1098
1098
|
- get conversation translation request status when needed for debugging
|
|
1099
1099
|
- translator hook service
|
|
1100
|
-
-
|
|
1100
|
+
- project-scoped running/idle tracking for the Codex Translator session
|
|
1101
1101
|
- update the active queue item on `UserPromptSubmit` and `Stop`
|
|
1102
1102
|
- persist `session_id`, `turn_id`, `transcript_path`, and
|
|
1103
1103
|
`last_assistant_message` diagnostics
|
|
@@ -1108,9 +1108,9 @@ POST /api/hooks/codex-translator
|
|
|
1108
1108
|
POST /api/hooks/codex-translator/stop
|
|
1109
1109
|
```
|
|
1110
1110
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1111
|
+
Gate Reviewer services should not be overloaded with translation logic. Shared
|
|
1112
|
+
utility code is fine, but role state, directories, prompts, and permissions
|
|
1113
|
+
should remain separate.
|
|
1114
1114
|
|
|
1115
1115
|
## 19. Relationship To Existing Translation
|
|
1116
1116
|
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Gate Review Gates
|
|
2
|
+
|
|
3
|
+
This document defines VCM Gate Review Gates.
|
|
4
|
+
|
|
5
|
+
Gate Review is an optional quality layer for complex tasks. It uses a fifth
|
|
6
|
+
role, `gate-reviewer`, powered by Claude Code. The role is independent from the
|
|
7
|
+
normal PM -> architect -> coder -> reviewer workflow.
|
|
8
|
+
|
|
9
|
+
## Gates
|
|
10
|
+
|
|
11
|
+
VCM supports three gates:
|
|
12
|
+
|
|
13
|
+
- `architecture-plan`: review architect's plan before coder dispatch.
|
|
14
|
+
- `validation-adequacy`: review reviewer validation coverage before docs sync
|
|
15
|
+
or final acceptance.
|
|
16
|
+
- `final-diff`: review the final diff before PR preparation.
|
|
17
|
+
|
|
18
|
+
Each gate returns only:
|
|
19
|
+
|
|
20
|
+
- `approve`
|
|
21
|
+
- `request_changes`
|
|
22
|
+
|
|
23
|
+
Gate Reviewer does not choose owners, fixes, Replan, or user intervention. PM
|
|
24
|
+
routes follow-up by gate type.
|
|
25
|
+
|
|
26
|
+
## Ownership
|
|
27
|
+
|
|
28
|
+
VCM owns:
|
|
29
|
+
|
|
30
|
+
- global Gate Review switches in `~/.vcm/settings.json`
|
|
31
|
+
- current task gate state under `<taskRepoRoot>/.ai/vcm/gate-reviews/`
|
|
32
|
+
- starting/resuming the project-scoped Gate Reviewer Claude Code session
|
|
33
|
+
- sending the gate prompt
|
|
34
|
+
- waiting for the report
|
|
35
|
+
- marking the Gate Reviewer turn in Round state
|
|
36
|
+
- sending the callback to PM
|
|
37
|
+
|
|
38
|
+
PM owns:
|
|
39
|
+
|
|
40
|
+
- triggering `vcm-gate-review` at the three gate points
|
|
41
|
+
- stopping after a `started` or `running` result
|
|
42
|
+
- handling the VCM callback
|
|
43
|
+
- routing `request_changes` to the responsible normal VCM role
|
|
44
|
+
|
|
45
|
+
Gate Reviewer owns:
|
|
46
|
+
|
|
47
|
+
- reviewing only the requested gate
|
|
48
|
+
- writing only the assigned report
|
|
49
|
+
|
|
50
|
+
## Session Scope
|
|
51
|
+
|
|
52
|
+
Gate Reviewer is project-scoped:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
<baseRepoRoot>/.ai/vcm/gate-reviewer/session.json
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The session is reusable across tasks in the same project. The gate prompt must
|
|
59
|
+
therefore name the current task and task worktree path explicitly. Prior
|
|
60
|
+
session memory can help orientation, but only current worktree evidence can
|
|
61
|
+
decide the gate.
|
|
62
|
+
|
|
63
|
+
Gate reports remain task-scoped:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
<taskRepoRoot>/.ai/vcm/gate-reviews/
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Prompt Shape
|
|
70
|
+
|
|
71
|
+
VCM sends a short prompt:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
[VCM GATE REVIEW]
|
|
75
|
+
Task: <taskSlug>
|
|
76
|
+
Worktree: <taskRepoRoot>
|
|
77
|
+
Gate: <gate>
|
|
78
|
+
Request: <requestId>
|
|
79
|
+
Report: <absolute report path>
|
|
80
|
+
|
|
81
|
+
Evidence:
|
|
82
|
+
- <relative evidence file>
|
|
83
|
+
Diff: inspect git status/diff in Worktree.
|
|
84
|
+
|
|
85
|
+
Write only Report. Start exactly:
|
|
86
|
+
Gate: <gate>
|
|
87
|
+
Request: <requestId>
|
|
88
|
+
Decision: approve|request_changes
|
|
89
|
+
Summary: <one or two sentences>
|
|
90
|
+
[/VCM GATE REVIEW]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Detailed review rules live in `.claude/agents/gate-reviewer.md`, so the prompt
|
|
94
|
+
does not repeat role policy.
|
|
95
|
+
|
|
96
|
+
## Files
|
|
97
|
+
|
|
98
|
+
Harness-managed files:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
.claude/agents/gate-reviewer.md
|
|
102
|
+
.claude/skills/vcm-gate-review/SKILL.md
|
|
103
|
+
.ai/tools/request-gate-review
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Task runtime files:
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
.ai/vcm/gate-reviews/index.json
|
|
110
|
+
.ai/vcm/gate-reviews/architecture-plan-review.md
|
|
111
|
+
.ai/vcm/gate-reviews/validation-adequacy-review.md
|
|
112
|
+
.ai/vcm/gate-reviews/final-diff-review.md
|
|
113
|
+
.ai/vcm/gate-reviews/requests/<request-id>.json
|
|
114
|
+
.ai/vcm/gate-reviews/requests/<request-id>.prompt.md
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Flow
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
PM reaches gate
|
|
121
|
+
-> PM uses vcm-gate-review
|
|
122
|
+
-> VCM checks global gate switch and task state
|
|
123
|
+
-> VCM starts or resumes project Gate Reviewer session
|
|
124
|
+
-> VCM sends short prompt with task/worktree/report paths
|
|
125
|
+
-> VCM marks Gate Reviewer running in current Round
|
|
126
|
+
-> Gate Reviewer writes report
|
|
127
|
+
-> VCM validates report and marks Gate Reviewer idle
|
|
128
|
+
-> VCM callbacks PM
|
|
129
|
+
-> PM continues or routes follow-up
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Close Task stops task-scoped VCM role sessions only. It must not stop the
|
|
133
|
+
project-scoped Gate Reviewer session.
|
package/docs/product-design.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# VibeCodingMaster Product Design
|
|
2
2
|
|
|
3
|
-
Last updated: 2026-06-
|
|
3
|
+
Last updated: 2026-06-21
|
|
4
4
|
|
|
5
5
|
This document describes the current product direction and implemented V1 behavior for VCM.
|
|
6
6
|
|
|
@@ -82,43 +82,40 @@ project-manager
|
|
|
82
82
|
-> project-manager final acceptance, commit, and PR
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
### 4.1
|
|
85
|
+
### 4.1 Gate Review Gates
|
|
86
86
|
|
|
87
|
-
For complex tasks, VCM supports optional
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
For complex tasks, VCM supports optional Gate Review Gates through an
|
|
88
|
+
independent `gate-reviewer` Claude Code role. The reviewer uses a
|
|
89
|
+
project-scoped long-lived session, but every gate prompt names the current task
|
|
90
|
+
and task worktree so task evidence stays explicit.
|
|
90
91
|
|
|
91
92
|
```text
|
|
92
93
|
architect architecture plan
|
|
93
|
-
->
|
|
94
|
+
-> Gate Reviewer checks plan quality before coder starts
|
|
94
95
|
|
|
95
96
|
reviewer review-report
|
|
96
|
-
->
|
|
97
|
+
-> Gate Reviewer checks validation adequacy before final acceptance
|
|
97
98
|
|
|
98
99
|
final task diff
|
|
99
|
-
->
|
|
100
|
+
-> Gate Reviewer checks code and PR readiness before PR preparation
|
|
100
101
|
```
|
|
101
102
|
|
|
102
103
|
Each gate returns `approve` or `request_changes`. PM triggers gates through the
|
|
103
|
-
`vcm-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
`.ai/codex/.codex/hooks.json`, so the fifth role participates in session and
|
|
114
|
-
Round state while a gate is running.
|
|
104
|
+
`vcm-gate-review` skill at the three workflow points; VCM owns the sidebar
|
|
105
|
+
toggles, gate state, Gate Reviewer session, report polling, and PM callback.
|
|
106
|
+
Reports are task-scoped under `.ai/vcm/gate-reviews/`. All three gate toggles
|
|
107
|
+
default to off.
|
|
108
|
+
|
|
109
|
+
When any gate is on, or when a Gate Reviewer session already exists, the task
|
|
110
|
+
workspace shows `Gate Reviewer` as a fifth terminal role. VCM sends a short gate
|
|
111
|
+
prompt into that session and manually marks the role/Round running until the
|
|
112
|
+
assigned report is valid. The role remains outside PM routing and normal
|
|
113
|
+
auto-orchestration.
|
|
115
114
|
Architecture-plan findings return to architect, validation-adequacy findings
|
|
116
115
|
return to reviewer, and final-diff findings go to architect first for
|
|
117
|
-
assessment.
|
|
118
|
-
including `.ai/codex/AGENTS.md` and `.ai/codex/config.toml`, so VCM does not
|
|
119
|
-
require a root-level `AGENTS.md`.
|
|
116
|
+
assessment. Gate Reviewer role rules live in `.claude/agents/gate-reviewer.md`.
|
|
120
117
|
|
|
121
|
-
The detailed design lives in `docs/
|
|
118
|
+
The detailed design lives in `docs/gate-review-gates.md`.
|
|
122
119
|
|
|
123
120
|
### 4.2 Task Worktree Model
|
|
124
121
|
|
|
@@ -389,7 +386,7 @@ The split should stay close to 50/50 width. Both panes expand vertically to fill
|
|
|
389
386
|
|
|
390
387
|
## 8. Flow Pause Detection
|
|
391
388
|
|
|
392
|
-
VCM detects flow pauses from role hook events, not from terminal silence, message history, or pending route files. Claude Code roles report through `.claude/settings.json`;
|
|
389
|
+
VCM detects flow pauses from role hook events, not from terminal silence, message history, or pending route files. Claude Code roles report through `.claude/settings.json`; VCM directly records Gate Reviewer turns while a gate prompt is active.
|
|
393
390
|
|
|
394
391
|
Backend role state:
|
|
395
392
|
|
|
@@ -397,7 +394,7 @@ Backend role state:
|
|
|
397
394
|
- `Stop`: role becomes `idle` and records `lastTurnEndedAt`.
|
|
398
395
|
- `PostCompact`: refreshes role session metadata and records `lastCompactAt` without changing `running`/`idle`.
|
|
399
396
|
- `StopFailure`: first checks completion evidence. If the role already wrote an outgoing route file, VCM marks the role idle and dispatches normally. If not, VCM sends a recovery prompt to the same role without marking it idle.
|
|
400
|
-
- The role tab and flow pause state
|
|
397
|
+
- The role tab and flow pause state react to Claude Code hook events plus VCM-recorded Gate Reviewer gate turns.
|
|
401
398
|
|
|
402
399
|
Task-level Round state:
|
|
403
400
|
|
|
@@ -587,18 +584,13 @@ VCM Harness injects Claude Code hooks into `.claude/settings.json`:
|
|
|
587
584
|
|
|
588
585
|
VCM uses `UserPromptSubmit` as the Claude Code acceptance signal. A successful PTY write only proves VCM delivered text to the embedded terminal; `UserPromptSubmit` proves Claude Code accepted the prompt.
|
|
589
586
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
- `UserPromptSubmit`: posts directly to `/api/hooks/codex-reviewer`, marks the fifth role running, and starts or continues the shared Round state
|
|
593
|
-
- `Stop`: posts directly to `/api/hooks/codex-reviewer/stop`, marks the fifth role idle, and lets the Round settle normally
|
|
594
|
-
|
|
595
|
-
Codex Reviewer hooks do not dispatch route files. PM receives Codex review completion through the Codex Review Gate callback managed by VCM.
|
|
587
|
+
Gate Reviewer does not dispatch route files. PM receives Gate Review completion through the Gate Review callback managed by VCM.
|
|
596
588
|
|
|
597
589
|
The injected role rules require asynchronous file messaging: after writing or updating a route file, the role must end the current Claude Code turn and wait for VCM to deliver a later reply. Roles should use `.claude/skills/vcm-route-message/SKILL.md` to author route files. Roles must not poll files, start shell loops, keep the turn open waiting for another role to answer, paste directly into another role terminal, or use Claude Code Task/Subagent for VCM role delegation.
|
|
598
590
|
|
|
599
591
|
Roles must not run background Bash; a `PreToolUse` hook (`.ai/tools/vcm-bash-guard`) denies `run_in_background`, `nohup`, `setsid`, `disown`, and trailing `&`. The only sanctioned long-running mechanism is `.ai/tools/run-long-check` plus `.ai/tools/watch-job` through `vcm-long-running-validation`: the detached job worker enforces the 60 minute ceiling and a supervision lease that kills unwatched jobs, `watch-job` renews the lease in foreground windows of up to 8 minutes (exit `125` means call it again in the same turn), and the VCM backend blocks a role's turn-end while one of its validation jobs is still running.
|
|
600
592
|
|
|
601
|
-
There is no `vcmctl` in the target design. Hook entrypoints are direct HTTP from Claude Code
|
|
593
|
+
There is no `vcmctl` in the target design. Hook entrypoints are direct HTTP from Claude Code hooks to the local VCM backend.
|
|
602
594
|
|
|
603
595
|
## 13. Translation
|
|
604
596
|
|
package/package.json
CHANGED
|
@@ -16,10 +16,10 @@ const requiredFiles = [
|
|
|
16
16
|
"dist/main.js",
|
|
17
17
|
"dist/backend/server.js",
|
|
18
18
|
"dist/backend/api/harness-routes.js",
|
|
19
|
-
"dist/backend/api/
|
|
19
|
+
"dist/backend/api/gate-review-routes.js",
|
|
20
20
|
"dist/backend/runtime/node-pty-runtime.js",
|
|
21
21
|
"dist/backend/ws/terminal-ws.js",
|
|
22
|
-
"dist/backend/services/
|
|
22
|
+
"dist/backend/services/gate-review-service.js",
|
|
23
23
|
"dist/backend/services/harness-service.js",
|
|
24
24
|
"dist/backend/services/session-service.js",
|
|
25
25
|
"dist/backend/services/project-service.js",
|
|
@@ -29,9 +29,9 @@ const requiredFiles = [
|
|
|
29
29
|
"dist/backend/templates/harness/architect-agent.js",
|
|
30
30
|
"dist/backend/templates/harness/coder-agent.js",
|
|
31
31
|
"dist/backend/templates/harness/reviewer-agent.js",
|
|
32
|
-
"dist/backend/templates/harness/
|
|
32
|
+
"dist/backend/templates/harness/gate-review.js",
|
|
33
33
|
"dist/shared/constants.js",
|
|
34
|
-
"dist/shared/types/
|
|
34
|
+
"dist/shared/types/gate-review.js",
|
|
35
35
|
"dist/shared/types/harness.js",
|
|
36
36
|
"dist/shared/validation/slug-check.js",
|
|
37
37
|
"dist/shared/validation/artifact-check.js",
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { VcmError } from "../errors.js";
|
|
2
|
-
import { isCodexReviewGate } from "../services/codex-review-service.js";
|
|
3
|
-
export function registerCodexReviewRoutes(app, deps) {
|
|
4
|
-
app.get("/api/tasks/:taskSlug/codex-review", async (request) => {
|
|
5
|
-
const project = await requireCurrentProject(deps.projectService);
|
|
6
|
-
return deps.codexReviewService.getState(project.repoRoot, request.params.taskSlug);
|
|
7
|
-
});
|
|
8
|
-
app.put("/api/tasks/:taskSlug/codex-review/settings", async (request) => {
|
|
9
|
-
const project = await requireCurrentProject(deps.projectService);
|
|
10
|
-
return deps.codexReviewService.updateSettings(project.repoRoot, request.params.taskSlug, request.body);
|
|
11
|
-
});
|
|
12
|
-
app.post("/api/tasks/:taskSlug/codex-review/:gate/request", async (request) => {
|
|
13
|
-
const project = await requireCurrentProject(deps.projectService);
|
|
14
|
-
const gate = parseGate(request.params.gate);
|
|
15
|
-
return deps.codexReviewService.requestReviewGate(project.repoRoot, request.params.taskSlug, gate);
|
|
16
|
-
});
|
|
17
|
-
app.post("/api/tasks/:taskSlug/codex-review/:gate/retry", async (request) => {
|
|
18
|
-
const project = await requireCurrentProject(deps.projectService);
|
|
19
|
-
const gate = parseGate(request.params.gate);
|
|
20
|
-
return deps.codexReviewService.retryReviewGate(project.repoRoot, request.params.taskSlug, gate);
|
|
21
|
-
});
|
|
22
|
-
app.post("/api/tasks/:taskSlug/codex-review/:gate/skip", async (request) => {
|
|
23
|
-
const project = await requireCurrentProject(deps.projectService);
|
|
24
|
-
const gate = parseGate(request.params.gate);
|
|
25
|
-
return deps.codexReviewService.skipReviewGate(project.repoRoot, request.params.taskSlug, gate, request.body);
|
|
26
|
-
});
|
|
27
|
-
app.post("/api/tasks/:taskSlug/codex-review/:gate/override", async (request) => {
|
|
28
|
-
const project = await requireCurrentProject(deps.projectService);
|
|
29
|
-
const gate = parseGate(request.params.gate);
|
|
30
|
-
return deps.codexReviewService.overrideReviewGate(project.repoRoot, request.params.taskSlug, gate, request.body);
|
|
31
|
-
});
|
|
32
|
-
app.get("/api/tasks/:taskSlug/codex-review/:gate/report", async (request) => {
|
|
33
|
-
const project = await requireCurrentProject(deps.projectService);
|
|
34
|
-
const gate = parseGate(request.params.gate);
|
|
35
|
-
return deps.codexReviewService.readReport(project.repoRoot, request.params.taskSlug, gate);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
function parseGate(gate) {
|
|
39
|
-
if (!isCodexReviewGate(gate)) {
|
|
40
|
-
throw new VcmError({
|
|
41
|
-
code: "UNKNOWN_CODEX_REVIEW_GATE",
|
|
42
|
-
message: `Unknown Codex review gate: ${gate}`,
|
|
43
|
-
statusCode: 400
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
return gate;
|
|
47
|
-
}
|
|
48
|
-
async function requireCurrentProject(projectService) {
|
|
49
|
-
const project = await projectService.getCurrentProject();
|
|
50
|
-
if (!project) {
|
|
51
|
-
throw new VcmError({
|
|
52
|
-
code: "PROJECT_NOT_CONNECTED",
|
|
53
|
-
message: "Connect a repository first.",
|
|
54
|
-
statusCode: 409
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
return project;
|
|
58
|
-
}
|