vibe-coding-master 0.6.18 → 0.6.20
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/cli/install-vcm-harness.js +18 -2
- package/dist/backend/services/harness-service.js +13 -3
- package/dist/backend/services/job-guard-service.js +82 -10
- package/dist/backend/services/runtime-recovery-service.js +13 -0
- package/dist/backend/templates/harness/architect-agent.js +14 -9
- package/dist/backend/templates/harness/coder-agent.js +13 -0
- package/dist/backend/templates/harness/coder-worker-agent.js +72 -0
- package/dist/backend/templates/harness/project-manager-agent.js +7 -0
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import process from "node:process";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { renderArchitectHarnessRules } from "../templates/harness/architect-agent.js";
|
|
8
8
|
import { renderCoderHarnessRules } from "../templates/harness/coder-agent.js";
|
|
9
|
+
import { renderCoderWorkerHarnessRules } from "../templates/harness/coder-worker-agent.js";
|
|
9
10
|
import { renderGateReviewerAgentRules, renderRequestGateReviewTool, renderTranslatorAgentRules, renderVcmGateReviewSkillRules } from "../templates/harness/gate-review.js";
|
|
10
11
|
import { renderHarnessEngineerHarnessRules } from "../templates/harness/harness-engineer-agent.js";
|
|
11
12
|
import { renderRootClaudeHarnessRules } from "../templates/harness/claude-root.js";
|
|
@@ -52,7 +53,8 @@ const AGENT_FRONTMATTER = {
|
|
|
52
53
|
description: "VCM architecture role for plans, module boundaries, public contracts, verifiable behavior, and docs sync."
|
|
53
54
|
},
|
|
54
55
|
coder: {
|
|
55
|
-
description: "VCM implementation role for scoped code changes and focused tests."
|
|
56
|
+
description: "VCM implementation role for scoped code changes and focused tests.",
|
|
57
|
+
tools: "Read, Grep, Glob, Bash, Edit, Write, Agent"
|
|
56
58
|
},
|
|
57
59
|
reviewer: {
|
|
58
60
|
description: "VCM independent review role for acceptance, test adequacy, scope checks, and risk findings."
|
|
@@ -65,6 +67,10 @@ const AGENT_FRONTMATTER = {
|
|
|
65
67
|
},
|
|
66
68
|
"harness-engineer": {
|
|
67
69
|
description: "VCM project-scoped harness maintenance role for harness diagnosis, diff proposals, and VCM issue drafts."
|
|
70
|
+
},
|
|
71
|
+
"vcm-coder-worker": {
|
|
72
|
+
description: "Bounded VCM implementation worker for assigned modules, files, and VCM:CODE markers from Coder.",
|
|
73
|
+
model: "inherit"
|
|
68
74
|
}
|
|
69
75
|
};
|
|
70
76
|
const MANAGED_FILES = [
|
|
@@ -146,6 +152,14 @@ const MANAGED_FILES = [
|
|
|
146
152
|
commentStyle: "html",
|
|
147
153
|
category: "agent-harness-engineer",
|
|
148
154
|
content: renderHarnessEngineerHarnessRules()
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
path: ".claude/agents/vcm-coder-worker.md",
|
|
158
|
+
title: "VCM Coder Worker Agent",
|
|
159
|
+
agentName: "vcm-coder-worker",
|
|
160
|
+
commentStyle: "html",
|
|
161
|
+
category: "agent-coder-worker",
|
|
162
|
+
content: renderCoderWorkerHarnessRules()
|
|
149
163
|
}
|
|
150
164
|
];
|
|
151
165
|
const DURABLE_DOC_TEMPLATES = [
|
|
@@ -528,7 +542,9 @@ function renderManagedBlock(definition) {
|
|
|
528
542
|
function renderNewManagedFile(definition, block) {
|
|
529
543
|
if (definition.agentName) {
|
|
530
544
|
const frontmatter = AGENT_FRONTMATTER[definition.agentName];
|
|
531
|
-
|
|
545
|
+
const tools = frontmatter.tools ?? "Read, Grep, Glob, Bash, Edit, Write";
|
|
546
|
+
const model = frontmatter.model ? `\nmodel: ${frontmatter.model}` : "";
|
|
547
|
+
return `---\nname: ${definition.agentName}\ndescription: ${frontmatter.description}\ntools: ${tools}${model}\n---\n\n# ${definition.title}\n\n${block}\n`;
|
|
532
548
|
}
|
|
533
549
|
return `# ${definition.title}\n\n${block}\n`;
|
|
534
550
|
}
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { promisify } from "node:util";
|
|
4
4
|
import { renderArchitectHarnessRules } from "../templates/harness/architect-agent.js";
|
|
5
5
|
import { renderCoderHarnessRules } from "../templates/harness/coder-agent.js";
|
|
6
|
+
import { renderCoderWorkerHarnessRules } from "../templates/harness/coder-worker-agent.js";
|
|
6
7
|
import { renderGateReviewerAgentRules, renderRequestGateReviewTool, renderTranslatorAgentRules, renderVcmGateReviewSkillRules } from "../templates/harness/gate-review.js";
|
|
7
8
|
import { renderHarnessEngineerHarnessRules } from "../templates/harness/harness-engineer-agent.js";
|
|
8
9
|
import { renderRootClaudeHarnessRules } from "../templates/harness/claude-root.js";
|
|
@@ -135,6 +136,13 @@ const HARNESS_FILES = [
|
|
|
135
136
|
frontmatter: renderAgentFrontmatter("harness-engineer", "VCM project-scoped harness maintenance role for harness diagnosis, diff proposals, and VCM issue drafts."),
|
|
136
137
|
renderRules: renderHarnessEngineerHarnessRules
|
|
137
138
|
},
|
|
139
|
+
{
|
|
140
|
+
kind: "agent-coder-worker",
|
|
141
|
+
path: ".claude/agents/vcm-coder-worker.md",
|
|
142
|
+
title: "VCM Coder Worker Agent",
|
|
143
|
+
frontmatter: renderAgentFrontmatter("vcm-coder-worker", "Bounded VCM implementation worker for assigned modules, files, and VCM:CODE markers from Coder.", { model: "inherit" }),
|
|
144
|
+
renderRules: renderCoderWorkerHarnessRules
|
|
145
|
+
},
|
|
138
146
|
{
|
|
139
147
|
kind: "tool-request-gate-review",
|
|
140
148
|
path: ".ai/tools/request-gate-review",
|
|
@@ -161,7 +169,7 @@ const HARNESS_FILES = [
|
|
|
161
169
|
kind: "agent-coder",
|
|
162
170
|
path: ".claude/agents/coder.md",
|
|
163
171
|
title: "Coder Agent",
|
|
164
|
-
frontmatter: renderAgentFrontmatter("coder", "VCM implementation role for scoped code changes and focused tests."),
|
|
172
|
+
frontmatter: renderAgentFrontmatter("coder", "VCM implementation role for scoped code changes and focused tests.", { tools: "Read, Grep, Glob, Bash, Edit, Write, Agent" }),
|
|
165
173
|
renderRules: renderCoderHarnessRules
|
|
166
174
|
},
|
|
167
175
|
{
|
|
@@ -1279,8 +1287,10 @@ function isVcmHookMatcher(value) {
|
|
|
1279
1287
|
function isPlainObject(value) {
|
|
1280
1288
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1281
1289
|
}
|
|
1282
|
-
function renderAgentFrontmatter(name, description) {
|
|
1283
|
-
|
|
1290
|
+
function renderAgentFrontmatter(name, description, options = {}) {
|
|
1291
|
+
const tools = options.tools ?? "Read, Grep, Glob, Bash, Edit, Write";
|
|
1292
|
+
const model = options.model ? `\nmodel: ${options.model}` : "";
|
|
1293
|
+
return `---\nname: ${name}\ndescription: ${description}\ntools: ${tools}${model}\n---`;
|
|
1284
1294
|
}
|
|
1285
1295
|
function renderSkillFrontmatter(name, description) {
|
|
1286
1296
|
return `---\nname: ${name}\ndescription: ${description}\n---`;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
const ACTIVE_JOB_STATUSES = new Set(["queued", "starting", "running"]);
|
|
4
|
+
const ACTIVE_CODER_WORKER_STATUSES = new Set(["planned", "running", "completed", "failed"]);
|
|
4
5
|
const QUEUED_JOB_FRESH_MS = 120_000;
|
|
5
6
|
export const MAX_CONSECUTIVE_STOP_BLOCKS = 3;
|
|
6
7
|
export function createJobGuardService(deps = {}) {
|
|
@@ -73,19 +74,26 @@ export function createJobGuardService(deps = {}) {
|
|
|
73
74
|
async evaluateStop(input) {
|
|
74
75
|
const key = stateKey(input);
|
|
75
76
|
const jobs = await findActiveJobs(input.taskRepoRoot);
|
|
76
|
-
|
|
77
|
+
const coderWorkerTasks = input.role === "coder"
|
|
78
|
+
? await findActiveCoderWorkerTasks(input.taskRepoRoot)
|
|
79
|
+
: [];
|
|
80
|
+
if (jobs.length === 0 && coderWorkerTasks.length === 0) {
|
|
77
81
|
blockStates.delete(key);
|
|
78
82
|
return { behavior: "allow" };
|
|
79
83
|
}
|
|
80
|
-
const
|
|
84
|
+
const jobProgressMtimeMs = jobs.reduce((latest, job) => job.leaseMtimeMs !== undefined && (latest === undefined || job.leaseMtimeMs > latest)
|
|
81
85
|
? job.leaseMtimeMs
|
|
82
86
|
: latest, undefined);
|
|
87
|
+
const workerProgressMtimeMs = coderWorkerTasks.reduce((latest, task) => task.stateMtimeMs !== undefined && (latest === undefined || task.stateMtimeMs > latest)
|
|
88
|
+
? task.stateMtimeMs
|
|
89
|
+
: latest, undefined);
|
|
90
|
+
const progressMtimeMs = latestMtime(jobProgressMtimeMs, workerProgressMtimeMs);
|
|
83
91
|
let state = blockStates.get(key) ?? { count: 0 };
|
|
84
|
-
const
|
|
85
|
-
&&
|
|
86
|
-
&& state.
|
|
87
|
-
&&
|
|
88
|
-
if (
|
|
92
|
+
const progressChanged = state.count > 0
|
|
93
|
+
&& progressMtimeMs !== undefined
|
|
94
|
+
&& state.lastProgressMtimeMs !== undefined
|
|
95
|
+
&& progressMtimeMs > state.lastProgressMtimeMs;
|
|
96
|
+
if (progressChanged) {
|
|
89
97
|
state = { count: 0 };
|
|
90
98
|
}
|
|
91
99
|
if (state.count >= MAX_CONSECUTIVE_STOP_BLOCKS) {
|
|
@@ -94,24 +102,88 @@ export function createJobGuardService(deps = {}) {
|
|
|
94
102
|
blockStates.delete(key);
|
|
95
103
|
return { behavior: "allow" };
|
|
96
104
|
}
|
|
97
|
-
blockStates.set(key, { count: state.count + 1,
|
|
98
|
-
return { behavior: "block", reason: buildBlockReason(jobs) };
|
|
105
|
+
blockStates.set(key, { count: state.count + 1, lastProgressMtimeMs: progressMtimeMs });
|
|
106
|
+
return { behavior: "block", reason: buildBlockReason(jobs, coderWorkerTasks) };
|
|
99
107
|
},
|
|
100
108
|
notePromptSubmitted(input) {
|
|
101
109
|
blockStates.delete(stateKey(input));
|
|
102
110
|
}
|
|
103
111
|
};
|
|
104
112
|
}
|
|
113
|
+
async function findActiveCoderWorkerTasks(taskRepoRoot) {
|
|
114
|
+
const tasksRoot = path.join(taskRepoRoot, ".ai/vcm/coder-workers/tasks");
|
|
115
|
+
let entries;
|
|
116
|
+
try {
|
|
117
|
+
entries = await fs.readdir(tasksRoot);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
const tasks = [];
|
|
123
|
+
for (const entry of entries.sort()) {
|
|
124
|
+
if (!entry.endsWith(".json")) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const statePath = path.join(tasksRoot, entry);
|
|
128
|
+
let state;
|
|
129
|
+
try {
|
|
130
|
+
state = JSON.parse(await fs.readFile(statePath, "utf8"));
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const status = typeof state.status === "string" ? state.status : "";
|
|
136
|
+
if (state.handled === true || !ACTIVE_CODER_WORKER_STATUSES.has(status)) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
let stateMtimeMs;
|
|
140
|
+
try {
|
|
141
|
+
stateMtimeMs = (await fs.stat(statePath)).mtimeMs;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
stateMtimeMs = undefined;
|
|
145
|
+
}
|
|
146
|
+
tasks.push({
|
|
147
|
+
workerId: typeof state.workerId === "string" ? state.workerId : path.basename(entry, ".json"),
|
|
148
|
+
status,
|
|
149
|
+
reportPath: typeof state.reportPath === "string" ? state.reportPath : undefined,
|
|
150
|
+
error: typeof state.error === "string" ? state.error : undefined,
|
|
151
|
+
stateMtimeMs
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return tasks;
|
|
155
|
+
}
|
|
105
156
|
function stateKey(input) {
|
|
106
157
|
return `${input.repoRoot}::${input.taskSlug}::${input.role}`;
|
|
107
158
|
}
|
|
108
|
-
function buildBlockReason(jobs) {
|
|
159
|
+
function buildBlockReason(jobs, coderWorkerTasks) {
|
|
160
|
+
if (jobs.length > 0 && coderWorkerTasks.length === 0) {
|
|
161
|
+
return buildValidationJobBlockReason(jobs);
|
|
162
|
+
}
|
|
163
|
+
if (jobs.length === 0) {
|
|
164
|
+
return buildCoderWorkerBlockReason(coderWorkerTasks);
|
|
165
|
+
}
|
|
166
|
+
return `${buildValidationJobBlockReason(jobs)}\n${buildCoderWorkerBlockReason(coderWorkerTasks)}`;
|
|
167
|
+
}
|
|
168
|
+
function buildValidationJobBlockReason(jobs) {
|
|
109
169
|
const first = jobs[0];
|
|
110
170
|
const listing = jobs.map((job) => `${job.jobId} (${job.status})`).join(", ");
|
|
111
171
|
return `VCM: validation job ${listing} is still running. Do not end the turn while a validation job is running. `
|
|
112
172
|
+ `Run \`.ai/tools/watch-job ${first.jobId}\` again now and keep watching until it reports a terminal result `
|
|
113
173
|
+ `(success, failed, timeout, or orphaned), then record the result.`;
|
|
114
174
|
}
|
|
175
|
+
function buildCoderWorkerBlockReason(tasks) {
|
|
176
|
+
const listing = tasks.map((task) => `${task.workerId} (${task.status})`).join(", ");
|
|
177
|
+
const reports = tasks
|
|
178
|
+
.map((task) => task.reportPath)
|
|
179
|
+
.filter((reportPath) => Boolean(reportPath));
|
|
180
|
+
const reportHint = reports.length > 0 ? ` Review report(s): ${reports.join(", ")}.` : "";
|
|
181
|
+
return `VCM: coder worker task ${listing} is still unhandled. Do not end the Coder turn while worker tasks are unhandled. `
|
|
182
|
+
+ `Wait for worker subagents, review reports and commits, resolve failed or incomplete workers, set \`handled: true\` in each worker state, and continue.${reportHint}`;
|
|
183
|
+
}
|
|
184
|
+
function latestMtime(...values) {
|
|
185
|
+
return values.reduce((latest, value) => value !== undefined && (latest === undefined || value > latest) ? value : latest, undefined);
|
|
186
|
+
}
|
|
115
187
|
function numberOrUndefined(value) {
|
|
116
188
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
117
189
|
}
|
|
@@ -5,6 +5,7 @@ const TRANSLATOR_SESSION_PATH = ".ai/vcm/translations/session.json";
|
|
|
5
5
|
const HARNESS_ENGINEER_SESSION_PATH = ".ai/vcm/harness-engineer/session.json";
|
|
6
6
|
const BOOTSTRAP_SESSION_PATH = ".ai/vcm/bootstrap/session.json";
|
|
7
7
|
const HARNESS_FEEDBACK_STATE_PATH = ".ai/vcm/harness-feedback/state.json";
|
|
8
|
+
const CODER_WORKERS_RUNTIME_DIR = ".ai/vcm/coder-workers";
|
|
8
9
|
const RECOVERABLE_FEEDBACK_STATES = new Set(["analyzing", "applying"]);
|
|
9
10
|
export function createRuntimeRecoveryService(deps) {
|
|
10
11
|
const now = deps.now ?? (() => new Date().toISOString());
|
|
@@ -28,6 +29,7 @@ export function createRuntimeRecoveryService(deps) {
|
|
|
28
29
|
const roundRecovered = await recoverRound(taskRepoRoot, config.stateRoot, task.taskSlug, recoveredAt, context);
|
|
29
30
|
await recoverMessages(taskRepoRoot, config.stateRoot, task.taskSlug, recoveredAt, context);
|
|
30
31
|
await recoverGateReview(taskRepoRoot, recoveredAt, context);
|
|
32
|
+
await cleanupCoderWorkers(taskRepoRoot, context);
|
|
31
33
|
if ((roundRecovered || task.status === "running") && !hasLiveTaskSession(task.taskSlug)) {
|
|
32
34
|
await deps.taskService.updateTaskStatus(repoRoot, task.taskSlug, "stopped");
|
|
33
35
|
}
|
|
@@ -230,6 +232,17 @@ export function createRuntimeRecoveryService(deps) {
|
|
|
230
232
|
});
|
|
231
233
|
context.changedPaths.add(relativePath);
|
|
232
234
|
}
|
|
235
|
+
async function cleanupCoderWorkers(taskRepoRoot, context) {
|
|
236
|
+
const absolutePath = path.join(taskRepoRoot, CODER_WORKERS_RUNTIME_DIR);
|
|
237
|
+
if (!(await deps.fs.pathExists(absolutePath))) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (!deps.fs.removePath) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
await deps.fs.removePath(absolutePath, { recursive: true, force: true });
|
|
244
|
+
context.changedPaths.add(CODER_WORKERS_RUNTIME_DIR);
|
|
245
|
+
}
|
|
233
246
|
async function recoverHarnessBootstrap(repoRoot, _timestamp, context) {
|
|
234
247
|
const absolutePath = path.join(repoRoot, BOOTSTRAP_SESSION_PATH);
|
|
235
248
|
const state = await readJsonIfExists(absolutePath);
|
|
@@ -71,7 +71,9 @@ export function renderArchitectHarnessRules() {
|
|
|
71
71
|
|
|
72
72
|
In Architecture Diagnosis Mode, treat the current failure as a signal that the architecture may be wrong or incomplete. Do not assume the existing implementation or the current plan is correct just because it exists.
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
First define the diagnosis boundary: the affected feature or module. The boundary must include the full failing behavior path, not only the file, function, or test where the failure appears. Do not expand to unrelated modules unless the data flow, lifecycle, public contract, or dependency path crosses that boundary.
|
|
75
|
+
|
|
76
|
+
Within that boundary, read enough code, tests, durable docs, generated context, and handoff artifacts to reconstruct the current architecture. Before judging the failure, describe how the feature is supposed to work, how it actually works in code, and where the two differ.
|
|
75
77
|
|
|
76
78
|
Analyze the problem from these angles:
|
|
77
79
|
|
|
@@ -83,16 +85,19 @@ Analyze the problem from these angles:
|
|
|
83
85
|
- **Failure Model:** Identify how the architecture should behave when the operation fails, is interrupted, retries, resumes, restarts, receives duplicate events, receives events out of order, or observes partial output. Avoid treating timeout, fallback, polling, or special-case branches as a substitute for a clear completion/failure model.
|
|
84
86
|
- **Evidence:** Use code, docs, handoff artifacts, tests, logs, and generated context as evidence. Existing code is evidence, not authority. If the code contradicts the intended architecture, say so directly.
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
Treat "local implementation bug" as an exception that must be proven. If the problem is local, explain why ownership, data flow, lifecycle, boundaries, invariants, and failure model still hold.
|
|
89
|
+
|
|
90
|
+
Your diagnosis should identify:
|
|
87
91
|
|
|
88
|
-
1.
|
|
89
|
-
2.
|
|
90
|
-
3.
|
|
91
|
-
4.
|
|
92
|
-
5.
|
|
93
|
-
6.
|
|
92
|
+
1. The diagnosis boundary.
|
|
93
|
+
2. How the feature is supposed to work.
|
|
94
|
+
3. How it actually works in code.
|
|
95
|
+
4. Where the two differ.
|
|
96
|
+
5. Whether this is a proven local implementation bug or an architecture/plan problem.
|
|
97
|
+
6. If local, why the architecture still holds.
|
|
98
|
+
7. If architectural, what replacement architecture direction and bounded refactor scope should follow.
|
|
94
99
|
|
|
95
|
-
Do not propose a code-level patch until the architecture diagnosis is complete.
|
|
100
|
+
Do not propose a code-level patch until the architecture diagnosis is complete.
|
|
96
101
|
|
|
97
102
|
### Replan And Drift
|
|
98
103
|
|
|
@@ -5,6 +5,7 @@ export function renderCoderHarnessRules() {
|
|
|
5
5
|
### Role Scope
|
|
6
6
|
|
|
7
7
|
- Own implementation and baseline implementation tests inside the approved task scope, role message, and architecture plan.
|
|
8
|
+
- When parallel worker implementation is used, own worker task splitting, worker prompts, worker result review, integration, final Scaffold Completion, and coder-level validation.
|
|
8
9
|
- Do not decide architecture, module boundaries, public contracts, dependency direction, durable docs updates, or final test adequacy.
|
|
9
10
|
|
|
10
11
|
### Coder Implementation Discipline
|
|
@@ -51,6 +52,18 @@ export function renderCoderHarnessRules() {
|
|
|
51
52
|
- Do not stop incomplete work because of workload, session length, context size, or task size.
|
|
52
53
|
- If the architecture plan is still valid, continue implementation instead of requesting Replan.
|
|
53
54
|
|
|
55
|
+
### Parallel Worker Implementation
|
|
56
|
+
|
|
57
|
+
- Coder may use Claude Code subagents to invoke \`vcm-coder-worker\` for parallel implementation.
|
|
58
|
+
- Use workers only when the task touches multiple modules and at least two modules each contain more than 10 \`VCM:CODE\` markers.
|
|
59
|
+
- Before invoking workers, count \`VCM:CODE\` markers by module and create one runtime state file per worker under \`.ai/vcm/coder-workers/tasks/<worker-id>.json\`.
|
|
60
|
+
- Assign one worker task per module with more than 10 markers; group modules with 10 or fewer markers into one worker task.
|
|
61
|
+
- Each worker prompt must include task worktree, architecture plan path, worker state path, report path, assigned modules/files/markers, allowed implementation scope, validation scope, and commit requirement.
|
|
62
|
+
- Invoke worker subagents in parallel only through \`vcm-coder-worker\`.
|
|
63
|
+
- Stay in the same Coder turn until all worker subagents finish and Coder has reviewed and integrated their reports and commits. Do not end the turn to wait for worker callbacks.
|
|
64
|
+
- After workers finish, review each report and commit, resolve missing implementation, conflicts, invalid edits, and remaining \`VCM:CODE\` markers, then mark \`handled: true\` in each worker state.
|
|
65
|
+
- Run coder-level baseline validation, include worker commits and final integration status in Scaffold Completion, and delete \`.ai/vcm/coder-workers/\`.
|
|
66
|
+
|
|
54
67
|
### Handoff
|
|
55
68
|
|
|
56
69
|
- In the route message back to project-manager, include a \`Scaffold Completion\` section when the architecture plan contains a Scaffold Manifest.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export function renderCoderWorkerHarnessRules() {
|
|
2
|
+
return `
|
|
3
|
+
## VCM Coder Worker Rules
|
|
4
|
+
|
|
5
|
+
You are \`vcm-coder-worker\`, a bounded implementation worker invoked by Coder.
|
|
6
|
+
|
|
7
|
+
### Scope
|
|
8
|
+
|
|
9
|
+
- Implement only the module, files, Scaffold Manifest IDs, and \`VCM:CODE\` markers assigned by Coder.
|
|
10
|
+
- Stay inside the current task worktree.
|
|
11
|
+
- Do not change unassigned modules, files, durable docs, generated context, workflow files, role definitions, or project configuration unless Coder explicitly assigns them.
|
|
12
|
+
- Do not decide architecture, module boundaries, public contracts, dependency direction, validation strategy, Replan, or final acceptance.
|
|
13
|
+
- If the assigned implementation conflicts with the architecture plan or code reality, stop and report the conflict to Coder.
|
|
14
|
+
|
|
15
|
+
### Worker Runtime State
|
|
16
|
+
|
|
17
|
+
- Coder assigns a worker state path and report path.
|
|
18
|
+
- Before editing, read the assigned worker state file and update only that file from \`planned\` to \`running\`.
|
|
19
|
+
- After implementation, write the assigned report file, update only the assigned worker state to \`completed\`, and set \`commitHash\` after committing.
|
|
20
|
+
- If blocked or failed, update only the assigned worker state to \`failed\`, write the reason in \`error\`, and write the report with remaining work.
|
|
21
|
+
- Do not set \`handled: true\`; only Coder may do that after reviewing and integrating the worker result.
|
|
22
|
+
|
|
23
|
+
### Inputs
|
|
24
|
+
|
|
25
|
+
- Read Coder's delegation message.
|
|
26
|
+
- Read \`.ai/vcm/handoffs/architecture-plan.md\`.
|
|
27
|
+
- Read assigned source files and tests.
|
|
28
|
+
- Read relevant module architecture docs only when referenced by the architecture plan or delegation message.
|
|
29
|
+
- Read \`.ai/generated/module-index.json\` and \`.ai/generated/public-surface.json\` when needed to confirm module or public surface boundaries.
|
|
30
|
+
- Stop before editing if the assigned module, files, \`VCM:CODE\` markers, behavior contract, validation expectation, worker state path, or report path is unclear.
|
|
31
|
+
|
|
32
|
+
### Implementation Discipline
|
|
33
|
+
|
|
34
|
+
- Implement the assigned \`VCM:CODE\` markers completely and remove those markers before completion.
|
|
35
|
+
- Preserve architect-defined file responsibilities, callable-surface signatures, visibility, exports, contracts, and error boundaries.
|
|
36
|
+
- Do not add or change cross-file callable surface unless the architecture plan explicitly defines it.
|
|
37
|
+
- Do not fake completion: no hardcoded success, disabled logic, swallowed errors, test-only shortcuts, or silent fallback that hides failure.
|
|
38
|
+
- Implement behavior from the approved architecture, existing domain model, real inputs, and project runtime flow.
|
|
39
|
+
- Keep changes limited to the assigned module or files.
|
|
40
|
+
- Preserve existing behavior unless the architecture plan explicitly changes it.
|
|
41
|
+
- Keep source comments durable: behavior, contracts, invariants, error boundaries, or non-obvious logic only.
|
|
42
|
+
- Do not copy task context, handoff instructions, temporary rationale, or coder guidance into source comments.
|
|
43
|
+
|
|
44
|
+
### Tests
|
|
45
|
+
|
|
46
|
+
- Run only L0/L1 checks relevant to the assigned module or files.
|
|
47
|
+
- Add or update unit tests only for the assigned module when needed for baseline coverage.
|
|
48
|
+
- Do not run integration, E2E, smoke, full-suite, browser, multi-service, or final validation checks.
|
|
49
|
+
- Do not weaken, delete, or skip tests to make validation pass.
|
|
50
|
+
- If assigned-module tests cannot run, report the exact reason to Coder.
|
|
51
|
+
|
|
52
|
+
### Git
|
|
53
|
+
|
|
54
|
+
- Commit the worker's completed changes before returning to Coder.
|
|
55
|
+
- Commit only changes made for the assigned module or files.
|
|
56
|
+
- Stage only assigned files; do not use \`git add -A\`, \`git add .\`, \`git commit -a\`, or broad path staging.
|
|
57
|
+
- Use a concise commit message that identifies the assigned module or implementation scope.
|
|
58
|
+
- If committing fails because the worktree changed concurrently, report the failure to Coder and do not attempt broad conflict resolution.
|
|
59
|
+
|
|
60
|
+
### Output To Coder
|
|
61
|
+
|
|
62
|
+
Return a concise completion report with:
|
|
63
|
+
|
|
64
|
+
- assigned module/files
|
|
65
|
+
- completed Scaffold Manifest IDs or \`VCM:CODE\` markers
|
|
66
|
+
- files changed
|
|
67
|
+
- tests/checks run
|
|
68
|
+
- commit hash
|
|
69
|
+
- remaining risks or skipped checks
|
|
70
|
+
- any architecture-plan/code-reality conflict
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
@@ -57,6 +57,13 @@ After Architecture Diagnosis Mode:
|
|
|
57
57
|
|
|
58
58
|
- If architect reports no architecture change is needed, continue the existing Debug Mode or Replan flow.
|
|
59
59
|
- If architect reports an architecture problem, route architect for a normal architecture plan or replan before coder work.
|
|
60
|
+
- If the implementation produced from that diagnosis still fails Reviewer validation with blocking issues, pause the workflow and report to the user.
|
|
61
|
+
|
|
62
|
+
PM should summarize:
|
|
63
|
+
|
|
64
|
+
- why Architecture Diagnosis Mode was triggered
|
|
65
|
+
- what the Architect diagnosed
|
|
66
|
+
- what Reviewer still found wrong
|
|
60
67
|
|
|
61
68
|
### Worktree
|
|
62
69
|
|