vibe-coding-master 0.3.21 → 0.3.23
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 +2 -2
- package/dist/backend/api/artifact-routes.js +8 -1
- package/dist/backend/api/codex-translation-routes.js +24 -0
- package/dist/backend/api/project-routes.js +3 -1
- package/dist/backend/api/task-routes.js +3 -1
- package/dist/backend/server.js +10 -1
- package/dist/backend/services/artifact-service.js +10 -3
- package/dist/backend/services/codex-hook-service.js +30 -9
- package/dist/backend/services/codex-translation-service.js +183 -79
- package/dist/backend/services/session-service.js +190 -38
- package/dist/backend/services/status-service.js +3 -1
- package/dist/backend/services/translation-service.js +15 -4
- package/dist/backend/templates/handoff.js +3 -3
- package/dist/backend/templates/harness/architect-agent.js +3 -2
- package/dist/backend/templates/harness/coder-agent.js +6 -1
- package/dist/shared/types/app-settings.js +3 -2
- package/dist-frontend/assets/index-C2xTNLmb.js +95 -0
- package/dist-frontend/assets/index-Cfum1Prr.css +32 -0
- package/dist-frontend/index.html +2 -2
- package/docs/codex-translation-plan.md +108 -86
- package/docs/product-design.md +5 -5
- package/docs/v0.4-custom-workflow-plan.md +785 -0
- package/docs/vcm-cc-best-practices.md +15 -12
- package/package.json +1 -1
- package/dist-frontend/assets/index-DOKW0Y5n.js +0 -95
- package/dist-frontend/assets/index-Dmefx9m7.css +0 -32
package/README.md
CHANGED
|
@@ -237,7 +237,7 @@ the base repo has uncommitted changes, when the current branch has no upstream,
|
|
|
237
237
|
or when the active task is an inline task using the base repo directly. It does
|
|
238
238
|
not stash, merge, or mutate task worktrees.
|
|
239
239
|
|
|
240
|
-
When VCM is connected to an active task, the bottom of the sidebar shows a task status dock. It stays outside the collapsible groups and shows the active VCM Session title, task status, start time, total elapsed time, total Round count, and role active runtime.
|
|
240
|
+
When VCM is connected to an active task, the bottom of the sidebar shows a task status dock. It stays outside the collapsible groups and shows the active VCM Session title, task status, start time, total elapsed time, total Round count, and role active runtime. The dock also shows the Current Round while it is running, or the Last Round after a flow pause, including start time, total elapsed time, role active runtime, Turn count, and Round status.
|
|
241
241
|
|
|
242
242
|
## Mobile Gateway
|
|
243
243
|
|
|
@@ -586,7 +586,7 @@ The normal path is timer-driven: `Stop` starts a backend timer, and `UserPromptS
|
|
|
586
586
|
|
|
587
587
|
When `Flow pause alert` is enabled, the frontend polls the task Round state and deduplicates each stopped Round so the same stopped state does not alert on every poll. Flow duration is measured from the first `UserPromptSubmit` to `stoppedAt`, falling back to the last `Stop` when needed. If the flow lasted less than 2 minutes, it plays the local chime 3 times at 1.4 second intervals. If the flow lasted 2 minutes or longer, it shows a modal alert and repeats the local chime until the user clicks `Confirm`. A stopped Round can mean normal completion, user decision needed, dispatch failure, or another workflow interruption; the point is to get the user to look with the right amount of urgency.
|
|
588
588
|
|
|
589
|
-
The
|
|
589
|
+
The Round dock separates wall-clock Round duration from role active runtime. For a running Round, `Total` is `now - Round.startedAt`; for a stopped Round, it is `stoppedAt - Round.startedAt`. `Role runtime` is only the accumulated time between each Turn's `UserPromptSubmit` and `Stop`; `Turn count` is the number of accepted prompts inside the Round.
|
|
590
590
|
|
|
591
591
|
## Resume Behavior
|
|
592
592
|
|
|
@@ -64,11 +64,18 @@ export function registerArtifactRoutes(app, deps) {
|
|
|
64
64
|
const task = await deps.taskService.loadTask(project.repoRoot, request.params.taskSlug);
|
|
65
65
|
const taskRepoRoot = getTaskRuntimeRepoRoot(task);
|
|
66
66
|
const paths = deps.artifactService.getHandoffPaths(taskRepoRoot, task.handoffDir);
|
|
67
|
+
const artifactPath = paths.roleLogPaths[request.params.role];
|
|
68
|
+
if (!artifactPath) {
|
|
69
|
+
return {
|
|
70
|
+
role: request.params.role,
|
|
71
|
+
content: ""
|
|
72
|
+
};
|
|
73
|
+
}
|
|
67
74
|
return {
|
|
68
75
|
role: request.params.role,
|
|
69
76
|
content: await deps.artifactService.readArtifact({
|
|
70
77
|
repoRoot: taskRepoRoot,
|
|
71
|
-
artifactPath
|
|
78
|
+
artifactPath
|
|
72
79
|
})
|
|
73
80
|
};
|
|
74
81
|
});
|
|
@@ -4,6 +4,30 @@ export function registerCodexTranslationRoutes(app, deps) {
|
|
|
4
4
|
const project = await requireCurrentProject(deps.projectService);
|
|
5
5
|
return deps.codexTranslationService.getState(project.repoRoot);
|
|
6
6
|
});
|
|
7
|
+
app.get("/api/translation/codex/session", async () => {
|
|
8
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
9
|
+
return (await deps.sessionService.getProjectTranslatorSession(project.repoRoot)) ?? null;
|
|
10
|
+
});
|
|
11
|
+
app.post("/api/translation/codex/session/ensure", async (request) => {
|
|
12
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
13
|
+
return deps.sessionService.ensureProjectTranslatorSession(project.repoRoot, request.body);
|
|
14
|
+
});
|
|
15
|
+
app.post("/api/translation/codex/session/start", async (request) => {
|
|
16
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
17
|
+
return deps.sessionService.startProjectTranslatorSession(project.repoRoot, request.body);
|
|
18
|
+
});
|
|
19
|
+
app.post("/api/translation/codex/session/resume", async (request) => {
|
|
20
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
21
|
+
return deps.sessionService.resumeProjectTranslatorSession(project.repoRoot, request.body);
|
|
22
|
+
});
|
|
23
|
+
app.post("/api/translation/codex/session/restart", async (request) => {
|
|
24
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
25
|
+
return deps.sessionService.restartProjectTranslatorSession(project.repoRoot, request.body);
|
|
26
|
+
});
|
|
27
|
+
app.post("/api/translation/codex/session/stop", async () => {
|
|
28
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
29
|
+
return deps.sessionService.stopProjectTranslatorSession(project.repoRoot);
|
|
30
|
+
});
|
|
7
31
|
app.get("/api/translation/codex/source-files", async (request) => {
|
|
8
32
|
const project = await requireCurrentProject(deps.projectService);
|
|
9
33
|
return deps.codexTranslationService.browseSourceFiles(project.repoRoot, {
|
|
@@ -4,7 +4,9 @@ export function registerProjectRoutes(app, deps) {
|
|
|
4
4
|
return deps.projectService.getRecentRepositoryPaths();
|
|
5
5
|
});
|
|
6
6
|
app.post("/api/projects/connect", async (request) => {
|
|
7
|
-
|
|
7
|
+
const project = await deps.projectService.connectProject(request.body);
|
|
8
|
+
await deps.codexTranslationService?.cleanupStartupRuntime(project.repoRoot);
|
|
9
|
+
return project;
|
|
8
10
|
});
|
|
9
11
|
app.get("/api/projects/current", async () => {
|
|
10
12
|
return deps.projectService.getCurrentProject();
|
|
@@ -88,7 +88,9 @@ function degradedArtifactSummary(handoffDir) {
|
|
|
88
88
|
logsDir,
|
|
89
89
|
messagesDir,
|
|
90
90
|
roleCommandPaths: Object.fromEntries(DISPATCHABLE_ROLES.map((role) => [role, `${roleCommandsDir}/${role}.md`])),
|
|
91
|
-
roleLogPaths: Object.fromEntries(ROLE_NAMES
|
|
91
|
+
roleLogPaths: Object.fromEntries(ROLE_NAMES
|
|
92
|
+
.filter((role) => role !== "codex-translator")
|
|
93
|
+
.map((role) => [role, `${logsDir}/${role}.log`])),
|
|
92
94
|
messageRoutePaths: {},
|
|
93
95
|
architecturePlanPath: `${handoffDir}/architecture-plan.md`,
|
|
94
96
|
knownIssuesPath: `${handoffDir}/known-issues.md`,
|
package/dist/backend/server.js
CHANGED
|
@@ -72,10 +72,14 @@ export async function createServer(deps, options = {}) {
|
|
|
72
72
|
codexReviewService: deps.codexReviewService
|
|
73
73
|
});
|
|
74
74
|
registerCodexTranslationRoutes(app, {
|
|
75
|
+
projectService: deps.projectService,
|
|
76
|
+
codexTranslationService: deps.codexTranslationService,
|
|
77
|
+
sessionService: deps.sessionService
|
|
78
|
+
});
|
|
79
|
+
registerProjectRoutes(app, {
|
|
75
80
|
projectService: deps.projectService,
|
|
76
81
|
codexTranslationService: deps.codexTranslationService
|
|
77
82
|
});
|
|
78
|
-
registerProjectRoutes(app, { projectService: deps.projectService });
|
|
79
83
|
registerHarnessRoutes(app, {
|
|
80
84
|
projectService: deps.projectService,
|
|
81
85
|
harnessService: deps.harnessService
|
|
@@ -118,6 +122,7 @@ export async function createServer(deps, options = {}) {
|
|
|
118
122
|
registerGatewayRoutes(app, { gatewayService: deps.gatewayService });
|
|
119
123
|
registerTerminalWs(app, { runtime: deps.runtime });
|
|
120
124
|
app.addHook("onReady", async () => {
|
|
125
|
+
await cleanupRecentTranslationRuntime(deps);
|
|
121
126
|
await deps.gatewayService.start();
|
|
122
127
|
});
|
|
123
128
|
app.addHook("onClose", async () => {
|
|
@@ -134,6 +139,10 @@ export async function createServer(deps, options = {}) {
|
|
|
134
139
|
}
|
|
135
140
|
return app;
|
|
136
141
|
}
|
|
142
|
+
async function cleanupRecentTranslationRuntime(deps) {
|
|
143
|
+
const repoRoots = await deps.projectService.getRecentRepositoryPaths();
|
|
144
|
+
await Promise.all(repoRoots.map((repoRoot) => deps.codexTranslationService.cleanupStartupRuntime(repoRoot)));
|
|
145
|
+
}
|
|
137
146
|
export async function startServer(options = {}) {
|
|
138
147
|
const host = options.host ?? "127.0.0.1";
|
|
139
148
|
const port = options.port ?? 4173;
|
|
@@ -42,8 +42,7 @@ export function createArtifactService(fs) {
|
|
|
42
42
|
architect: path.posix.join(logsDir, "architect.log"),
|
|
43
43
|
coder: path.posix.join(logsDir, "coder.log"),
|
|
44
44
|
reviewer: path.posix.join(logsDir, "reviewer.log"),
|
|
45
|
-
"codex-reviewer": path.posix.join(logsDir, "codex-reviewer.log")
|
|
46
|
-
"codex-translator": path.posix.join(logsDir, "codex-translator.log")
|
|
45
|
+
"codex-reviewer": path.posix.join(logsDir, "codex-reviewer.log")
|
|
47
46
|
},
|
|
48
47
|
messageRoutePaths: getDefaultMessageRoutePaths(messagesDir),
|
|
49
48
|
architecturePlanPath: path.posix.join(handoffDir, "architecture-plan.md"),
|
|
@@ -179,7 +178,15 @@ export function createArtifactService(fs) {
|
|
|
179
178
|
});
|
|
180
179
|
}
|
|
181
180
|
const paths = this.getHandoffPaths(input.repoRoot, input.handoffDir);
|
|
182
|
-
|
|
181
|
+
const roleLogPath = paths.roleLogPaths[input.role];
|
|
182
|
+
if (!roleLogPath) {
|
|
183
|
+
throw new VcmError({
|
|
184
|
+
code: "ROLE_LOG_UNAVAILABLE",
|
|
185
|
+
message: `${input.role} does not write a handoff log.`,
|
|
186
|
+
statusCode: 409
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
await fs.appendText(resolveRepoPath(input.repoRoot, roleLogPath), input.content);
|
|
183
190
|
}
|
|
184
191
|
};
|
|
185
192
|
}
|
|
@@ -18,6 +18,13 @@ export function createCodexHookService(deps) {
|
|
|
18
18
|
statusCode: 409
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
|
+
if (input.role === "codex-translator") {
|
|
22
|
+
return {
|
|
23
|
+
project,
|
|
24
|
+
config: undefined,
|
|
25
|
+
taskRepoRoot: undefined
|
|
26
|
+
};
|
|
27
|
+
}
|
|
21
28
|
const config = await deps.projectService.loadConfig(project.repoRoot);
|
|
22
29
|
const task = await deps.taskService.loadTask(project.repoRoot, input.taskSlug);
|
|
23
30
|
const taskRepoRoot = getTaskRuntimeRepoRoot(task);
|
|
@@ -37,16 +44,30 @@ export function createCodexHookService(deps) {
|
|
|
37
44
|
});
|
|
38
45
|
}
|
|
39
46
|
const context = await getHookContext(input);
|
|
40
|
-
const session =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
const session = input.role === "codex-translator"
|
|
48
|
+
? await deps.sessionService.recordProjectTranslatorHookEvent(context.project.repoRoot, {
|
|
49
|
+
eventName,
|
|
50
|
+
sessionId: stringOrUndefined(input.event.session_id),
|
|
51
|
+
transcriptPath: stringOrUndefined(input.event.transcript_path),
|
|
52
|
+
cwd: stringOrUndefined(input.event.cwd)
|
|
53
|
+
})
|
|
54
|
+
: await deps.sessionService.recordRoleHookEvent(context.project.repoRoot, {
|
|
55
|
+
taskSlug: input.taskSlug,
|
|
56
|
+
role: input.role,
|
|
57
|
+
eventName,
|
|
58
|
+
sessionId: stringOrUndefined(input.event.session_id),
|
|
59
|
+
transcriptPath: stringOrUndefined(input.event.transcript_path),
|
|
60
|
+
cwd: stringOrUndefined(input.event.cwd),
|
|
61
|
+
allowSessionMismatch: true
|
|
62
|
+
});
|
|
49
63
|
if (input.role === "codex-reviewer") {
|
|
64
|
+
if (!context.config || !context.taskRepoRoot) {
|
|
65
|
+
throw new VcmError({
|
|
66
|
+
code: "CODEX_HOOK_TASK_CONTEXT_MISSING",
|
|
67
|
+
message: "Codex Reviewer hook is missing task context.",
|
|
68
|
+
statusCode: 500
|
|
69
|
+
});
|
|
70
|
+
}
|
|
50
71
|
await deps.roundService.recordRoleTurnEvent({
|
|
51
72
|
repoRoot: context.project.repoRoot,
|
|
52
73
|
stateRepoRoot: context.taskRepoRoot,
|