vibe-coding-master 0.4.3 → 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.
@@ -81,12 +81,54 @@ export function createGitAdapter(runner) {
81
81
  }
82
82
  return result.stdout;
83
83
  },
84
- async getStagedStatus(repoRoot) {
85
- const result = await runGit(runner, repoRoot, ["diff", "--cached", "--name-status"]);
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 staged Git changes.",
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 project = await requireCurrentProject(deps.projectService);
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(project.repoRoot);
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 project = await requireCurrentProject(deps.projectService);
17
- return deps.harnessService.applyHarness(project.repoRoot);
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 project = await requireCurrentProject(deps.projectService);
21
- return deps.harnessService.getHarnessFileContent(project.repoRoot, request.query.path ?? "");
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 project = await requireCurrentProject(deps.projectService);
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(project.repoRoot, request.query.path ?? "", request.body.content);
32
+ return deps.harnessService.updateHarnessFileContent(task.worktreePath, request.query.path ?? "", request.body.content);
33
33
  });
34
- app.post("/api/projects/harness/tasks/:taskSlug/commit-and-rebase", async (request) => {
35
- const project = await requireCurrentProject(deps.projectService);
36
- const task = await deps.taskService.loadTask(project.repoRoot, request.params.taskSlug);
37
- return deps.harnessService.commitAndRebaseTask(project.repoRoot, {
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 requireCurrentProject(deps.projectService);
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 requireCurrentProject(deps.projectService);
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 requireCurrentProject(deps.projectService);
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 requireCurrentProject(deps.projectService);
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
+ }