vibe-coding-master 0.4.2 → 0.4.4
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/dist/backend/adapters/git-adapter.js +45 -18
- package/dist/backend/api/harness-routes.js +38 -29
- package/dist/backend/services/harness-service.js +314 -120
- package/dist/backend/services/task-service.js +33 -20
- package/dist-frontend/assets/{index-kJDZAzjD.css → index-12kW1cl6.css} +1 -1
- package/dist-frontend/assets/index-Bck3Mfz8.js +94 -0
- package/dist-frontend/index.html +2 -2
- package/docs/product-design.md +2 -2
- package/docs/v0.4-harness-optimization-plan.md +4 -3
- package/package.json +1 -1
- package/scripts/clean-build.mjs +1 -1
- package/scripts/harness-tools/generate-public-surface +1 -1
- package/dist-frontend/assets/index-uYhgIwNK.js +0 -94
- package/scripts/harness-tools/__pycache__/generate-module-indexcpython-314.pyc +0 -0
- package/scripts/harness-tools/__pycache__/generate-public-surfacecpython-314.pyc +0 -0
|
@@ -81,12 +81,54 @@ export function createGitAdapter(runner) {
|
|
|
81
81
|
}
|
|
82
82
|
return result.stdout;
|
|
83
83
|
},
|
|
84
|
-
async
|
|
85
|
-
const result = await runGit(runner, repoRoot, [
|
|
84
|
+
async getStatusPorcelainV1(repoRoot) {
|
|
85
|
+
const result = await runGit(runner, repoRoot, [
|
|
86
|
+
"status",
|
|
87
|
+
"--porcelain=v1",
|
|
88
|
+
"-z",
|
|
89
|
+
"--untracked-files=all"
|
|
90
|
+
]);
|
|
86
91
|
if (result.exitCode !== 0) {
|
|
87
92
|
throw new VcmError({
|
|
88
93
|
code: "GIT_ERROR",
|
|
89
|
-
message: "Unable to read
|
|
94
|
+
message: "Unable to read Git status.",
|
|
95
|
+
statusCode: 400,
|
|
96
|
+
hint: result.stderr
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return result.stdout;
|
|
100
|
+
},
|
|
101
|
+
async getCommitInfo(repoRoot, ref = "HEAD") {
|
|
102
|
+
const result = await runGit(runner, repoRoot, ["show", "-s", "--format=%H%x00%s%x00%cI", ref]);
|
|
103
|
+
if (result.exitCode !== 0) {
|
|
104
|
+
throw new VcmError({
|
|
105
|
+
code: "GIT_ERROR",
|
|
106
|
+
message: "Unable to read Git commit.",
|
|
107
|
+
statusCode: 400,
|
|
108
|
+
hint: result.stderr
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const [sha = "", subject = "", committedAt = ""] = result.stdout.split("\0");
|
|
112
|
+
return {
|
|
113
|
+
sha: sha.trim(),
|
|
114
|
+
subject: subject.trim(),
|
|
115
|
+
committedAt: committedAt.trim() || undefined
|
|
116
|
+
};
|
|
117
|
+
},
|
|
118
|
+
async getCommitDiff(repoRoot, ref = "HEAD") {
|
|
119
|
+
const result = await runGit(runner, repoRoot, [
|
|
120
|
+
"show",
|
|
121
|
+
"--format=",
|
|
122
|
+
"--no-ext-diff",
|
|
123
|
+
"--binary",
|
|
124
|
+
"--src-prefix=a/",
|
|
125
|
+
"--dst-prefix=b/",
|
|
126
|
+
ref
|
|
127
|
+
]);
|
|
128
|
+
if (result.exitCode !== 0) {
|
|
129
|
+
throw new VcmError({
|
|
130
|
+
code: "GIT_ERROR",
|
|
131
|
+
message: "Unable to read Git commit diff.",
|
|
90
132
|
statusCode: 400,
|
|
91
133
|
hint: result.stderr
|
|
92
134
|
});
|
|
@@ -149,21 +191,6 @@ export function createGitAdapter(runner) {
|
|
|
149
191
|
}
|
|
150
192
|
return this.getHeadCommit(repoRoot);
|
|
151
193
|
},
|
|
152
|
-
async rebase(repoRoot, upstream) {
|
|
153
|
-
const result = await runGit(runner, repoRoot, ["rebase", upstream]);
|
|
154
|
-
if (result.exitCode !== 0) {
|
|
155
|
-
throw new VcmError({
|
|
156
|
-
code: "GIT_REBASE_FAILED",
|
|
157
|
-
message: "Unable to rebase task branch onto the harness commit.",
|
|
158
|
-
statusCode: 409,
|
|
159
|
-
hint: result.stderr || result.stdout
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
return {
|
|
163
|
-
stdout: result.stdout,
|
|
164
|
-
stderr: result.stderr
|
|
165
|
-
};
|
|
166
|
-
},
|
|
167
194
|
async createWorktree(input) {
|
|
168
195
|
const result = await runGit(runner, input.repoRoot, [
|
|
169
196
|
"worktree",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { isOpenFileLimitError, VcmError } from "../errors.js";
|
|
2
2
|
export function registerHarnessRoutes(app, deps) {
|
|
3
|
-
app.get("/api/projects/harness", async () => {
|
|
4
|
-
const
|
|
3
|
+
app.get("/api/projects/harness", async (request) => {
|
|
4
|
+
const { task } = await requireHarnessTaskContext(deps, request.query.taskSlug);
|
|
5
5
|
try {
|
|
6
|
-
return await deps.harnessService.getHarnessStatus(
|
|
6
|
+
return await deps.harnessService.getHarnessStatus(task.worktreePath);
|
|
7
7
|
}
|
|
8
8
|
catch (error) {
|
|
9
9
|
if (isOpenFileLimitError(error)) {
|
|
@@ -12,16 +12,16 @@ export function registerHarnessRoutes(app, deps) {
|
|
|
12
12
|
throw error;
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
|
-
app.post("/api/projects/harness/apply", async () => {
|
|
16
|
-
const
|
|
17
|
-
return deps.harnessService.applyHarness(
|
|
15
|
+
app.post("/api/projects/harness/apply", async (request) => {
|
|
16
|
+
const { task } = await requireHarnessTaskContext(deps, request.body?.taskSlug);
|
|
17
|
+
return deps.harnessService.applyHarness(task.worktreePath);
|
|
18
18
|
});
|
|
19
19
|
app.get("/api/projects/harness/file", async (request) => {
|
|
20
|
-
const
|
|
21
|
-
return deps.harnessService.getHarnessFileContent(
|
|
20
|
+
const { task } = await requireHarnessTaskContext(deps, request.query.taskSlug);
|
|
21
|
+
return deps.harnessService.getHarnessFileContent(task.worktreePath, request.query.path ?? "");
|
|
22
22
|
});
|
|
23
23
|
app.put("/api/projects/harness/file", async (request) => {
|
|
24
|
-
const
|
|
24
|
+
const { task } = await requireHarnessTaskContext(deps, request.query.taskSlug ?? request.body?.taskSlug);
|
|
25
25
|
if (typeof request.body?.content !== "string") {
|
|
26
26
|
throw new VcmError({
|
|
27
27
|
code: "HARNESS_FILE_CONTENT_INVALID",
|
|
@@ -29,22 +29,17 @@ export function registerHarnessRoutes(app, deps) {
|
|
|
29
29
|
statusCode: 400
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
return deps.harnessService.updateHarnessFileContent(
|
|
32
|
+
return deps.harnessService.updateHarnessFileContent(task.worktreePath, request.query.path ?? "", request.body.content);
|
|
33
33
|
});
|
|
34
|
-
app.
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
return deps.harnessService.
|
|
38
|
-
taskSlug: task.taskSlug,
|
|
39
|
-
branch: task.branch,
|
|
40
|
-
worktreePath: task.worktreePath,
|
|
41
|
-
changedFiles: request.body?.changedFiles ?? []
|
|
42
|
-
});
|
|
34
|
+
app.get("/api/projects/harness/repository-diff", async (request) => {
|
|
35
|
+
const { task } = await requireHarnessTaskContext(deps, request.query.taskSlug);
|
|
36
|
+
const scope = request.query.scope === "all" ? "all" : "harness";
|
|
37
|
+
return deps.harnessService.getRepositoryDiff(task.worktreePath, scope);
|
|
43
38
|
});
|
|
44
|
-
app.get("/api/projects/harness/bootstrap", async () => {
|
|
45
|
-
const project = await
|
|
39
|
+
app.get("/api/projects/harness/bootstrap", async (request) => {
|
|
40
|
+
const { project, task } = await requireHarnessTaskContext(deps, request.query.taskSlug);
|
|
46
41
|
try {
|
|
47
|
-
return await deps.harnessService.getBootstrapStatus(project.repoRoot);
|
|
42
|
+
return await deps.harnessService.getBootstrapStatus(project.repoRoot, task.worktreePath);
|
|
48
43
|
}
|
|
49
44
|
catch (error) {
|
|
50
45
|
if (isOpenFileLimitError(error)) {
|
|
@@ -54,20 +49,20 @@ export function registerHarnessRoutes(app, deps) {
|
|
|
54
49
|
}
|
|
55
50
|
});
|
|
56
51
|
app.post("/api/projects/harness/bootstrap/start", async (request) => {
|
|
57
|
-
const project = await
|
|
58
|
-
return deps.harnessService.startHarnessBootstrap(project.repoRoot, request.body ?? {});
|
|
52
|
+
const { project, task } = await requireHarnessTaskContext(deps, request.body?.taskSlug);
|
|
53
|
+
return deps.harnessService.startHarnessBootstrap(project.repoRoot, task.worktreePath, request.body ?? {});
|
|
59
54
|
});
|
|
60
55
|
app.post("/api/projects/harness/bootstrap/restart", async (request) => {
|
|
61
|
-
const project = await
|
|
62
|
-
return deps.harnessService.restartHarnessBootstrap(project.repoRoot, request.body ?? {});
|
|
56
|
+
const { project, task } = await requireHarnessTaskContext(deps, request.body?.taskSlug);
|
|
57
|
+
return deps.harnessService.restartHarnessBootstrap(project.repoRoot, task.worktreePath, request.body ?? {});
|
|
63
58
|
});
|
|
64
59
|
app.post("/api/projects/harness/bootstrap/stop", async () => {
|
|
65
60
|
const project = await requireCurrentProject(deps.projectService);
|
|
66
61
|
return deps.harnessService.stopHarnessBootstrap(project.repoRoot);
|
|
67
62
|
});
|
|
68
|
-
app.post("/api/projects/harness/bootstrap/run", async () => {
|
|
69
|
-
const project = await
|
|
70
|
-
return deps.harnessService.runHarnessBootstrap(project.repoRoot);
|
|
63
|
+
app.post("/api/projects/harness/bootstrap/run", async (request) => {
|
|
64
|
+
const { project, task } = await requireHarnessTaskContext(deps, request.body?.taskSlug);
|
|
65
|
+
return deps.harnessService.runHarnessBootstrap(project.repoRoot, task.worktreePath);
|
|
71
66
|
});
|
|
72
67
|
app.get("/api/projects/harness/engineer/session", async () => {
|
|
73
68
|
const project = await requireCurrentProject(deps.projectService);
|
|
@@ -140,3 +135,17 @@ async function requireCurrentProject(projectService) {
|
|
|
140
135
|
}
|
|
141
136
|
return project;
|
|
142
137
|
}
|
|
138
|
+
async function requireHarnessTaskContext(deps, taskSlug) {
|
|
139
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
140
|
+
const normalizedTaskSlug = taskSlug?.trim();
|
|
141
|
+
if (!normalizedTaskSlug) {
|
|
142
|
+
throw new VcmError({
|
|
143
|
+
code: "HARNESS_TASK_REQUIRED",
|
|
144
|
+
message: "Select or create an active task before changing VCM Harness.",
|
|
145
|
+
statusCode: 409,
|
|
146
|
+
hint: "VCM writes harness changes only to the active task worktree."
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const task = await deps.taskService.loadTask(project.repoRoot, normalizedTaskSlug);
|
|
150
|
+
return { project, task };
|
|
151
|
+
}
|