vibe-coding-master 0.9.5 → 0.9.6
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 +10 -16
- package/dist/backend/adapters/claude-adapter.js +4 -5
- package/dist/backend/role-tool-policy.js +11 -10
- package/dist/backend/runtime/node-pty-runtime.js +39 -8
- package/dist/backend/server.js +0 -4
- package/dist/backend/services/gate-review-service.js +6 -2
- package/dist/backend/services/harness-service.js +6 -23
- package/dist/backend/services/session-service.js +2 -19
- package/dist/backend/services/workflow-control-service.js +9 -3
- package/dist/backend/templates/harness/architect-agent.js +8 -11
- package/dist/backend/templates/harness/architect-evidence-worker-agent.js +3 -3
- package/dist/backend/templates/harness/gate-review.js +29 -27
- package/dist/backend/templates/harness/project-manager-agent.js +2 -2
- package/dist/backend/templates/harness/vcm-code-navigation-skill.js +13 -9
- package/dist-frontend/assets/{index-CjM9OqZh.js → index-Bsd4k8YI.js} +35 -35
- package/dist-frontend/assets/{index-Bs4g_1yF.css → index-CRUqb0PX.css} +1 -1
- package/dist-frontend/index.html +2 -2
- package/package.json +1 -1
- package/scripts/verify-package.mjs +0 -2
- package/dist/backend/services/code-intelligence-service.js +0 -255
- package/dist/backend/services/lsp-plugin.js +0 -64
- package/scripts/claude-plugins/vcm-lsp-bridge/.claude-plugin/plugin.json +0 -88
- package/scripts/claude-plugins/vcm-lsp-bridge/vcm-lsp-proxy.mjs +0 -273
package/README.md
CHANGED
|
@@ -511,22 +511,16 @@ Use it to:
|
|
|
511
511
|
- merge task harness commits back to the connected repository branch when
|
|
512
512
|
appropriate
|
|
513
513
|
|
|
514
|
-
VCM
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
only locate candidates after the correct LSP query is demonstrably partial.
|
|
525
|
-
At the architecture-plan gate, Reviewer checks that every decision-bearing
|
|
526
|
-
relationship cites its evidence source and re-queries it with LSP. Other roles
|
|
527
|
-
use generated context and ordinary source reads. Harness Studio
|
|
528
|
-
reports whether the server executable and plugin can run; the role Session
|
|
529
|
-
performs the real workspace indexing and semantic query retries.
|
|
514
|
+
VCM roles navigate code without language servers, so a task does not hold a
|
|
515
|
+
semantic index in memory per session. Architect preloads `vcm-code-navigation`
|
|
516
|
+
and establishes relationships with exact source-text search over the whole
|
|
517
|
+
project source tree, searching every spelling that can reach a symbol and
|
|
518
|
+
reading every match. Accessors, backing fields, trait items, implementations,
|
|
519
|
+
wrappers, and aliases are searched as separate symbols, and each relationship
|
|
520
|
+
records the search that produced it. At the architecture-plan gate, Reviewer
|
|
521
|
+
checks that every decision-bearing relationship cites its evidence source and
|
|
522
|
+
reruns the recorded search. Other roles use generated context and ordinary
|
|
523
|
+
source reads.
|
|
530
524
|
|
|
531
525
|
Harness Engineer is task-scoped and runs from the active task worktree. The
|
|
532
526
|
backend automatically starts a fresh Harness Engineer for each active task or
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { roleRuntimeDisallowedTools,
|
|
1
|
+
import { roleRuntimeDisallowedTools, roleUsesRuntimeDenyList } from "../role-tool-policy.js";
|
|
2
2
|
import { isCodexBridgeSessionModel } from "../../shared/types/session.js";
|
|
3
3
|
import { VcmError } from "../errors.js";
|
|
4
4
|
export function createClaudeAdapter(runner) {
|
|
@@ -20,10 +20,9 @@ export function createClaudeAdapter(runner) {
|
|
|
20
20
|
}
|
|
21
21
|
return result.stdout.trim();
|
|
22
22
|
},
|
|
23
|
-
buildRoleStartCommand(role, command = "claude", permissionMode = "default", claudeSessionId, resume = false, model = "default", effort = "default", settingsOverride, appendSystemPrompt
|
|
24
|
-
const args =
|
|
25
|
-
|
|
26
|
-
if (lspEnabled) {
|
|
23
|
+
buildRoleStartCommand(role, command = "claude", permissionMode = "default", claudeSessionId, resume = false, model = "default", effort = "default", settingsOverride, appendSystemPrompt) {
|
|
24
|
+
const args = [];
|
|
25
|
+
if (roleUsesRuntimeDenyList(role)) {
|
|
27
26
|
args.push("--disallowedTools", roleRuntimeDisallowedTools(role).join(","));
|
|
28
27
|
}
|
|
29
28
|
else {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const FRONTMATTER_DISALLOWED_TOOLS = [
|
|
2
2
|
"NotebookEdit",
|
|
3
3
|
"WebFetch",
|
|
4
4
|
"WebSearch"
|
|
@@ -32,19 +32,19 @@ const NON_VCM_ROLE_RUNTIME_TOOLS = [
|
|
|
32
32
|
"WebSearch",
|
|
33
33
|
"Workflow"
|
|
34
34
|
];
|
|
35
|
-
export const CODE_ROLE_DISALLOWED_TOOLS = [...
|
|
35
|
+
export const CODE_ROLE_DISALLOWED_TOOLS = [...FRONTMATTER_DISALLOWED_TOOLS];
|
|
36
36
|
export const REVIEWER_DISALLOWED_TOOLS = [
|
|
37
37
|
"Agent",
|
|
38
38
|
"Edit",
|
|
39
|
-
...
|
|
39
|
+
...FRONTMATTER_DISALLOWED_TOOLS
|
|
40
40
|
];
|
|
41
|
-
// The evidence worker reads and
|
|
42
|
-
// or delegates.
|
|
41
|
+
// The evidence worker reads and searches but never runs commands, edits code,
|
|
42
|
+
// or delegates.
|
|
43
43
|
export const EVIDENCE_WORKER_DISALLOWED_TOOLS = [
|
|
44
44
|
"Agent",
|
|
45
45
|
"Bash",
|
|
46
46
|
"Edit",
|
|
47
|
-
...
|
|
47
|
+
...FRONTMATTER_DISALLOWED_TOOLS
|
|
48
48
|
];
|
|
49
49
|
export const CODE_ROLE_RUNTIME_DISALLOWED_TOOLS = [...NON_VCM_ROLE_RUNTIME_TOOLS];
|
|
50
50
|
export const REVIEWER_RUNTIME_DISALLOWED_TOOLS = [
|
|
@@ -52,10 +52,11 @@ export const REVIEWER_RUNTIME_DISALLOWED_TOOLS = [
|
|
|
52
52
|
"Edit",
|
|
53
53
|
...NON_VCM_ROLE_RUNTIME_TOOLS
|
|
54
54
|
];
|
|
55
|
-
// Architect
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
// Architect and Reviewer Agent frontmatter uses a deny list, so their launch
|
|
56
|
+
// also removes the runtime tools no VCM workflow role may use.
|
|
57
|
+
const RUNTIME_DENY_LIST_ROLE_NAMES = new Set(["architect", "reviewer"]);
|
|
58
|
+
export function roleUsesRuntimeDenyList(role) {
|
|
59
|
+
return RUNTIME_DENY_LIST_ROLE_NAMES.has(role);
|
|
59
60
|
}
|
|
60
61
|
export function roleRuntimeDisallowedTools(role) {
|
|
61
62
|
if (role === "reviewer") {
|
|
@@ -46,7 +46,7 @@ export function createNodePtyTerminalRuntime(deps) {
|
|
|
46
46
|
process: child,
|
|
47
47
|
listeners: new Set(),
|
|
48
48
|
logWriter,
|
|
49
|
-
replayBuffer:
|
|
49
|
+
replayBuffer: new TerminalReplayBuffer(),
|
|
50
50
|
disposed: false
|
|
51
51
|
};
|
|
52
52
|
entries.set(session.id, entry);
|
|
@@ -55,7 +55,7 @@ export function createNodePtyTerminalRuntime(deps) {
|
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
57
|
entry.session.lastOutputAt = now();
|
|
58
|
-
entry.replayBuffer
|
|
58
|
+
entry.replayBuffer.append(data);
|
|
59
59
|
entry.logWriter.append(data);
|
|
60
60
|
emit(entry, {
|
|
61
61
|
sessionId: session.id,
|
|
@@ -150,7 +150,8 @@ export function createNodePtyTerminalRuntime(deps) {
|
|
|
150
150
|
subscribe(sessionId, listener, options = {}) {
|
|
151
151
|
const entry = getEntry(entries, sessionId);
|
|
152
152
|
entry.listeners.add(listener);
|
|
153
|
-
|
|
153
|
+
const replay = options.replay !== false ? entry.replayBuffer.text() : "";
|
|
154
|
+
if (replay) {
|
|
154
155
|
listener({
|
|
155
156
|
id: `evt_${Date.now()}_${Math.random().toString(16).slice(2)}`,
|
|
156
157
|
sessionId,
|
|
@@ -158,7 +159,7 @@ export function createNodePtyTerminalRuntime(deps) {
|
|
|
158
159
|
role: entry.session.role,
|
|
159
160
|
type: "output",
|
|
160
161
|
timestamp: now(),
|
|
161
|
-
data:
|
|
162
|
+
data: replay
|
|
162
163
|
});
|
|
163
164
|
}
|
|
164
165
|
else if (options.replay !== false && entry.input.logPath) {
|
|
@@ -257,11 +258,41 @@ export function tailTerminalReplay(data, limitBytes = TERMINAL_REPLAY_TAIL_LIMIT
|
|
|
257
258
|
const firstLineBreak = tail.indexOf("\n");
|
|
258
259
|
return firstLineBreak >= 0 ? tail.slice(firstLineBreak + 1) : tail;
|
|
259
260
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
261
|
+
// Keeps the recent terminal output for subscriber replay. PTY output arrives in
|
|
262
|
+
// many small chunks, so appending measures only the new chunk and drops whole
|
|
263
|
+
// old chunks; the exact tail is cut only when a subscriber asks for it.
|
|
264
|
+
export class TerminalReplayBuffer {
|
|
265
|
+
limitBytes;
|
|
266
|
+
chunks = [];
|
|
267
|
+
head = 0;
|
|
268
|
+
bytes = 0;
|
|
269
|
+
constructor(limitBytes = TERMINAL_REPLAY_TAIL_LIMIT_BYTES) {
|
|
270
|
+
this.limitBytes = limitBytes;
|
|
271
|
+
}
|
|
272
|
+
append(data) {
|
|
273
|
+
if (!data) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const bytes = Buffer.byteLength(data, "utf8");
|
|
277
|
+
this.chunks.push({ data, bytes });
|
|
278
|
+
this.bytes += bytes;
|
|
279
|
+
// Drop a chunk only while the rest still covers the limit.
|
|
280
|
+
while (this.head < this.chunks.length - 1 && this.bytes - this.chunks[this.head].bytes >= this.limitBytes) {
|
|
281
|
+
this.bytes -= this.chunks[this.head].bytes;
|
|
282
|
+
this.head += 1;
|
|
283
|
+
}
|
|
284
|
+
if (this.head > 1024 && this.head * 2 > this.chunks.length) {
|
|
285
|
+
this.chunks = this.chunks.slice(this.head);
|
|
286
|
+
this.head = 0;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
text() {
|
|
290
|
+
if (this.head >= this.chunks.length) {
|
|
291
|
+
return "";
|
|
292
|
+
}
|
|
293
|
+
const joined = this.chunks.slice(this.head).map((chunk) => chunk.data).join("");
|
|
294
|
+
return tailTerminalReplay(joined, this.limitBytes);
|
|
263
295
|
}
|
|
264
|
-
return tailTerminalReplay(`${current}${data}`, limitBytes);
|
|
265
296
|
}
|
|
266
297
|
export function buildPtyEnvironment(baseEnv, inputEnv = {}) {
|
|
267
298
|
const env = {
|
package/dist/backend/server.js
CHANGED
|
@@ -35,7 +35,6 @@ import { createJobGuardService } from "./services/job-guard-service.js";
|
|
|
35
35
|
import { createProjectService } from "./services/project-service.js";
|
|
36
36
|
import { createSessionRegistry } from "./runtime/session-registry.js";
|
|
37
37
|
import { createSessionService } from "./services/session-service.js";
|
|
38
|
-
import { createHarnessCodeIntelligenceDetector } from "./services/code-intelligence-service.js";
|
|
39
38
|
import { createMessageService } from "./services/message-service.js";
|
|
40
39
|
import { createRoundService } from "./services/round-service.js";
|
|
41
40
|
import { createRuntimeCoordinatorService } from "./services/runtime-coordinator-service.js";
|
|
@@ -258,7 +257,6 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
258
257
|
});
|
|
259
258
|
const taskService = createTaskService({ fs, git, artifactService, projectService });
|
|
260
259
|
const taskWorkflowService = createTaskWorkflowService({ fs });
|
|
261
|
-
const codeIntelligenceDetector = createHarnessCodeIntelligenceDetector(fs, { runner });
|
|
262
260
|
const sessionService = createSessionService({
|
|
263
261
|
fs,
|
|
264
262
|
runtime,
|
|
@@ -268,13 +266,11 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
268
266
|
projectService,
|
|
269
267
|
taskService,
|
|
270
268
|
taskWorkflowService,
|
|
271
|
-
codeIntelligenceDetector,
|
|
272
269
|
codexBridgeIntegration,
|
|
273
270
|
apiUrl: options.apiUrl
|
|
274
271
|
});
|
|
275
272
|
const harnessService = createHarnessService({
|
|
276
273
|
fs,
|
|
277
|
-
commandRunner: runner,
|
|
278
274
|
git,
|
|
279
275
|
runtime,
|
|
280
276
|
harnessEngineerSessions: sessionService,
|
|
@@ -1568,10 +1568,14 @@ async function captureGateInputSnapshots(fs, taskRepoRoot, requestId, sourcePath
|
|
|
1568
1568
|
return snapshots;
|
|
1569
1569
|
}
|
|
1570
1570
|
// The reviewer judges authorization and scope against the flow's PM route
|
|
1571
|
-
// messages, captured like any other immutable Gate input.
|
|
1571
|
+
// messages, captured like any other immutable Gate input. Tester commits are
|
|
1572
|
+
// part of every reviewed range, so routes to Tester are always included.
|
|
1572
1573
|
async function captureRouteMessageSnapshot(deps, context, requestId, codeDiffSources) {
|
|
1573
1574
|
const sourcePath = path.posix.join(context.stateRoot, "messages", `${context.taskSlug}.jsonl`);
|
|
1574
|
-
const roles = new Set(
|
|
1575
|
+
const roles = new Set([
|
|
1576
|
+
...codeDiffSources.map((source) => source === "coder" ? "coder" : "architect"),
|
|
1577
|
+
"tester"
|
|
1578
|
+
]);
|
|
1575
1579
|
const flow = await collectFlowRouteMessages(deps.fs, deps.workflowControlService, context, roles);
|
|
1576
1580
|
if (flow.messages.length === 0) {
|
|
1577
1581
|
return { sourcePath, status: "missing" };
|
|
@@ -38,8 +38,6 @@ import { renderResolveDurableDocAssignmentTool } from "../templates/harness/reso
|
|
|
38
38
|
import { submitTerminalInput } from "../runtime/terminal-submit.js";
|
|
39
39
|
import { VcmError } from "../errors.js";
|
|
40
40
|
import { bumpHarnessRevision, readHarnessRevisionState } from "./harness-revision.js";
|
|
41
|
-
import { createHarnessCodeIntelligenceDetector } from "./code-intelligence-service.js";
|
|
42
|
-
import { lspUnavailableWarning } from "./lsp-plugin.js";
|
|
43
41
|
const execFileAsync = promisify(execFile);
|
|
44
42
|
const BOOTSTRAP_SESSION_PATH = ".ai/vcm/bootstrap/session.json";
|
|
45
43
|
const HARNESS_ENGINEER_SESSION_PATH = ".ai/vcm/harness-engineer/session.json";
|
|
@@ -369,20 +367,14 @@ export function createHarnessService(deps) {
|
|
|
369
367
|
? normalizeArchitectWorkerSettings(await deps.getArchitectWorkerSettings())
|
|
370
368
|
: DEFAULT_ARCHITECT_WORKER_SETTINGS;
|
|
371
369
|
}
|
|
372
|
-
const codeIntelligenceDetector = createHarnessCodeIntelligenceDetector(deps.fs, {
|
|
373
|
-
runner: deps.commandRunner
|
|
374
|
-
});
|
|
375
370
|
return {
|
|
376
371
|
async getHarnessStatus(repoRoot) {
|
|
377
|
-
const
|
|
378
|
-
analyzeHarnessFiles(deps.fs, repoRoot, await resolveArchitectWorkerSettings()),
|
|
379
|
-
codeIntelligenceDetector.detect(repoRoot)
|
|
380
|
-
]);
|
|
372
|
+
const analyses = await analyzeHarnessFiles(deps.fs, repoRoot, await resolveArchitectWorkerSettings());
|
|
381
373
|
const legacyChanges = await analyzeLegacyCodexHarnessPaths(deps.fs, repoRoot);
|
|
382
374
|
const manifestChange = deps.runFixedInstaller
|
|
383
375
|
? await analyzeHarnessManifest(deps.fs, repoRoot, vcmVersion)
|
|
384
376
|
: undefined;
|
|
385
|
-
return renderHarnessStatus(await readHarnessRevisionValue(deps.fs, repoRoot), analyses, legacyChanges, manifestChange
|
|
377
|
+
return renderHarnessStatus(await readHarnessRevisionValue(deps.fs, repoRoot), analyses, legacyChanges, manifestChange);
|
|
386
378
|
},
|
|
387
379
|
async getHarnessFileContent(repoRoot, filePath) {
|
|
388
380
|
return readHarnessFileContent(deps.fs, repoRoot, filePath);
|
|
@@ -411,17 +403,14 @@ export function createHarnessService(deps) {
|
|
|
411
403
|
harnessCommit = (await commitHarnessVisibleChanges(deps.git, repoRoot, "[VCM Harness] Update harness file")).harnessCommit;
|
|
412
404
|
}
|
|
413
405
|
const file = await readHarnessFileContent(deps.fs, repoRoot, definition.path);
|
|
414
|
-
const
|
|
415
|
-
analyzeHarnessFiles(deps.fs, repoRoot, await resolveArchitectWorkerSettings()),
|
|
416
|
-
codeIntelligenceDetector.detect(repoRoot)
|
|
417
|
-
]);
|
|
406
|
+
const analyses = await analyzeHarnessFiles(deps.fs, repoRoot, await resolveArchitectWorkerSettings());
|
|
418
407
|
const legacyChanges = await analyzeLegacyCodexHarnessPaths(deps.fs, repoRoot);
|
|
419
408
|
const manifestChange = deps.runFixedInstaller
|
|
420
409
|
? await analyzeHarnessManifest(deps.fs, repoRoot, vcmVersion)
|
|
421
410
|
: undefined;
|
|
422
411
|
return {
|
|
423
412
|
file,
|
|
424
|
-
status: renderHarnessStatus(await readHarnessRevisionValue(deps.fs, repoRoot), analyses, legacyChanges, manifestChange
|
|
413
|
+
status: renderHarnessStatus(await readHarnessRevisionValue(deps.fs, repoRoot), analyses, legacyChanges, manifestChange),
|
|
425
414
|
harnessCommit
|
|
426
415
|
};
|
|
427
416
|
},
|
|
@@ -1393,7 +1382,7 @@ async function removeLegacyCodexHarnessPaths(fs, repoRoot) {
|
|
|
1393
1382
|
}
|
|
1394
1383
|
return changes;
|
|
1395
1384
|
}
|
|
1396
|
-
function renderHarnessStatus(harnessRevision, analyses, legacyChanges = [], manifestChange
|
|
1385
|
+
function renderHarnessStatus(harnessRevision, analyses, legacyChanges = [], manifestChange) {
|
|
1397
1386
|
const files = analyses.map((analysis) => analysis.status);
|
|
1398
1387
|
const plannedChanges = analyses
|
|
1399
1388
|
.map((analysis) => analysis.plannedChange)
|
|
@@ -1419,13 +1408,7 @@ function renderHarnessStatus(harnessRevision, analyses, legacyChanges = [], mani
|
|
|
1419
1408
|
files,
|
|
1420
1409
|
needsApply: plannedChanges.length > 0,
|
|
1421
1410
|
plannedChanges,
|
|
1422
|
-
|
|
1423
|
-
warnings: [
|
|
1424
|
-
...(plannedChanges.length > 0 ? ["Review and commit VCM Harness changes before starting long-running work."] : []),
|
|
1425
|
-
...((codeIntelligence?.languages ?? [])
|
|
1426
|
-
.filter((language) => language.state !== "server_runnable")
|
|
1427
|
-
.map(lspUnavailableWarning))
|
|
1428
|
-
]
|
|
1411
|
+
warnings: plannedChanges.length > 0 ? ["Review and commit VCM Harness changes before starting long-running work."] : []
|
|
1429
1412
|
};
|
|
1430
1413
|
}
|
|
1431
1414
|
async function readHarnessRevisionValue(fs, repoRoot) {
|
|
@@ -7,7 +7,6 @@ import { resolveRepoPath } from "../adapters/filesystem.js";
|
|
|
7
7
|
import { submitTerminalInput } from "../runtime/terminal-submit.js";
|
|
8
8
|
import { readHarnessRevisionState } from "./harness-revision.js";
|
|
9
9
|
import { getTaskRuntimeRepoRoot } from "./task-service.js";
|
|
10
|
-
import { roleUsesLsp, prepareTaskLspPlugin, renderLspNotice, VCM_LSP_PLUGIN_DIR } from "./lsp-plugin.js";
|
|
11
10
|
const TRANSLATOR_ROLE = "translator";
|
|
12
11
|
const HARNESS_ENGINEER_ROLE = "harness-engineer";
|
|
13
12
|
const TRANSLATION_DIR = ".ai/vcm/translations";
|
|
@@ -79,16 +78,8 @@ export function createSessionService(deps) {
|
|
|
79
78
|
// Transcript paths come from Claude Code hook payloads; VCM does not derive
|
|
80
79
|
// them from Claude Code's project-directory encoding.
|
|
81
80
|
const transcriptPath = launchMode === "resume" ? persisted?.transcriptPath : undefined;
|
|
82
|
-
const lspStatus = roleUsesLsp(role) && deps.codeIntelligenceDetector
|
|
83
|
-
? await deps.codeIntelligenceDetector.detect(taskRepoRoot, { refresh: true })
|
|
84
|
-
: undefined;
|
|
85
|
-
const lspPluginDirs = roleUsesLsp(role)
|
|
86
|
-
? lspStatus ? await prepareTaskLspPlugin(deps.fs, taskRepoRoot, lspStatus) : [VCM_LSP_PLUGIN_DIR]
|
|
87
|
-
: [];
|
|
88
|
-
const appendSystemPrompt = [input.appendSystemPrompt, lspStatus && renderLspNotice(lspStatus, role)]
|
|
89
|
-
.filter(Boolean).join("\n\n") || undefined;
|
|
90
81
|
const startCommand = {
|
|
91
|
-
...deps.claude.buildRoleStartCommand(role, config.claudeCommand, permissionMode, resumeClaudeSessionId, launchMode === "resume", model, effort, modelSettingsOverride, appendSystemPrompt
|
|
82
|
+
...deps.claude.buildRoleStartCommand(role, config.claudeCommand, permissionMode, resumeClaudeSessionId, launchMode === "resume", model, effort, modelSettingsOverride, input.appendSystemPrompt),
|
|
92
83
|
cwd: taskRepoRoot
|
|
93
84
|
};
|
|
94
85
|
const runtimeSessionToken = randomUUID();
|
|
@@ -107,15 +98,7 @@ export function createSessionService(deps) {
|
|
|
107
98
|
VCM_ROLE: role,
|
|
108
99
|
VCM_SESSION_ID: claudeSessionId || undefined,
|
|
109
100
|
VCM_RUNTIME_SESSION_TOKEN: runtimeSessionToken
|
|
110
|
-
}, modelEnvironment,
|
|
111
|
-
...buildUsageTelemetryEnvironment(deps.apiUrl, role, model),
|
|
112
|
-
...(lspPluginDirs.length > 0
|
|
113
|
-
? {
|
|
114
|
-
ENABLE_LSP_TOOL: "true",
|
|
115
|
-
ENABLE_TOOL_SEARCH: "false"
|
|
116
|
-
}
|
|
117
|
-
: {})
|
|
118
|
-
}),
|
|
101
|
+
}, modelEnvironment, buildUsageTelemetryEnvironment(deps.apiUrl, role, model)),
|
|
119
102
|
cols: input.cols,
|
|
120
103
|
rows: input.rows
|
|
121
104
|
});
|
|
@@ -890,10 +890,16 @@ async function allowedAfterTester(fs, input, state, currentFlow, codeSource, opt
|
|
|
890
890
|
if (test.value === "incomplete" || test.infrastructure === "repair-required")
|
|
891
891
|
return [`${currentFlow}/tester`];
|
|
892
892
|
const validation = await gateState(fs, input, "validation-adequacy");
|
|
893
|
+
const unapprovedFailure = test.value === "fail" && !test.hasUserApprovedCoverageGap;
|
|
893
894
|
if (freshGateDecision(state, currentFlow, "tester", "validation-adequacy", validation) === "request_changes") {
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
895
|
+
// Findings on a genuine failure may be Tester-owned (wrong tests or
|
|
896
|
+
// evidence) or need the production investigation that Tester Failure
|
|
897
|
+
// starts; PM routes by who can dispose of them.
|
|
898
|
+
return unapprovedFailure && options.testerFailureFlow
|
|
899
|
+
? [`${currentFlow}/tester`, `${options.testerFailureFlow}/architect`]
|
|
900
|
+
: [`${currentFlow}/tester`];
|
|
901
|
+
}
|
|
902
|
+
if (unapprovedFailure) {
|
|
897
903
|
return options.testerFailureFlow ? [`${options.testerFailureFlow}/architect`] : [];
|
|
898
904
|
}
|
|
899
905
|
if (!gatePassedForDispatch(state, currentFlow, "tester", "validation-adequacy", validation))
|
|
@@ -21,13 +21,10 @@ ${renderRoleMemoryRules("architect")}
|
|
|
21
21
|
### Semantic Code Navigation
|
|
22
22
|
|
|
23
23
|
- Follow the preloaded \`vcm-code-navigation\` skill whenever work requires code definitions, implementations, references, callers, callees, or behavior paths. This applies in every Architect mode and in direct user communication.
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- Use Glob to locate files and Read to inspect complete code. Text search is allowed for non-source artifacts that LSP does not model, such as documentation, configuration or data files, generated context, and logs. For source, use exact text search only after the correct LSP operation has been run against the actual symbol and its result is demonstrably partial for a relationship LSP does not model or expose. Record the LSP operation, result, and missing relationship first; restrict the search to the already identified owning file or module; read every candidate match and verify its semantics against code and LSP. Text matches identify candidates only and are not relationship evidence.
|
|
29
|
-
- Cost, latency, round trips, batching, parallelism, or an expectation of equivalent results never permits source-code text search. Wait for the role-session LSP and follow the skill's bounded retry procedure.
|
|
30
|
-
- If LSP cannot resolve a required project-owned relationship, record it as unresolved. Do not replace semantic evidence with text matches.
|
|
24
|
+
- Navigate project source with exact source-text search (\`Grep\` or \`rg\`), Glob, generated context, and complete reads. Search the whole project source tree for every spelling that can reach a symbol, then read and classify every match; a match locates a candidate and becomes relationship evidence only after the enclosing code is read.
|
|
25
|
+
- Search results are symbol-name evidence. An accessor, its backing field, a trait declaration, its implementation method, a wrapper, and an alias are separate symbols. Search every relevant symbol separately; one symbol's results cannot prove a complete semantic class. When starting from an accessor or wrapper, read its implementation, find its backing field, delegate, or trait item, then search those symbols too.
|
|
26
|
+
- Record the exact search pattern and scope behind each relationship claim, so a reviewer can rerun it.
|
|
27
|
+
- If a project-owned relationship cannot be established from searches and reads, for example because a macro, code generation, configuration-excluded code, or runtime dispatch hides it, record it as unresolved with the reason. Do not treat a missing match as proof of absence.
|
|
31
28
|
|
|
32
29
|
### Work Persistence
|
|
33
30
|
|
|
@@ -72,9 +69,9 @@ ${renderRoleMemoryRules("architect")}
|
|
|
72
69
|
### Planning Code Reading
|
|
73
70
|
|
|
74
71
|
- Do not plan from session memory, architecture docs, generated context, or code comments alone. Re-read current-worktree source and verify actual behavior from implementation.
|
|
75
|
-
- Use \`vcm-code-navigation\` for symbol definitions, implementations, references, call hierarchies, and bounded behavior paths. Start from generated indexes, use
|
|
76
|
-
- Delegate bounded supporting implementation and document reading, and bounded
|
|
77
|
-
- If
|
|
72
|
+
- Use \`vcm-code-navigation\` for symbol definitions, implementations, references, call hierarchies, and bounded behavior paths. Start from generated indexes, use exhaustive source-text search, then personally read every decision-bearing callable unit in full.
|
|
73
|
+
- Delegate bounded supporting implementation and document reading, and bounded relationship collection for supporting symbols, to \`vcm-architect-evidence-worker\` when it would otherwise add substantial raw context. Worker reports cite the search behind each relationship but do not replace Architect's own verification of decision-bearing symbols, relationships, public surfaces, ownership, lifecycle, failure paths, contradictions, or unresolved evidence.
|
|
74
|
+
- If searches and reads cannot establish a required project-owned relationship, record the limitation in \`architecture-evidence.md\` and leave it unresolved.
|
|
78
75
|
- Define the planning boundary as the affected feature or module and identify every existing or intended observable entry point for the behavior being changed.
|
|
79
76
|
- Personally read the complete implementation of each decision-bearing existing entry point. Supporting entry points may be covered by accepted evidence-worker reports when their facts do not determine the architecture decision.
|
|
80
77
|
- Follow every project-owned call path the plan will change through cross-module calls, state reads and writes, persistence, side effects, completion and failure signals, and consumers.
|
|
@@ -237,7 +234,7 @@ The code-reading phase is complete only when:
|
|
|
237
234
|
- every indirect callback, event, hook, queue, route, and dynamic dispatch path has been resolved
|
|
238
235
|
- every relevant state reader and writer has been read
|
|
239
236
|
- every relevant cross-file surface caller and consumer has been read
|
|
240
|
-
- every semantic relationship records
|
|
237
|
+
- every semantic relationship records search, runtime, external-boundary, or generated-boundary evidence
|
|
241
238
|
- no unresolved project-owned symbol remains
|
|
242
239
|
|
|
243
240
|
Do not diagnose the root cause or choose a fix before the Code Reading Closure is complete.
|
|
@@ -12,8 +12,8 @@ You are \`vcm-architect-evidence-worker\`, a foreground evidence-collection suba
|
|
|
12
12
|
- Record repository facts with exact repo-relative file paths and symbol or section names.
|
|
13
13
|
- Separate verified facts, contradictions, and unresolved items.
|
|
14
14
|
- Do not design architecture, recommend implementation, decide scope, change contracts, edit project files, run validation, or communicate with project-manager or the user.
|
|
15
|
-
-
|
|
16
|
-
-
|
|
15
|
+
- Establish every definition, reference, caller, callee, and implementation relationship you report with exact Grep searches over the whole project source tree, then read and classify every match. Search an accessor, its backing field, a trait declaration, its implementation, a wrapper, and an alias separately, and search every spelling that can reach each symbol.
|
|
16
|
+
- A match becomes relationship evidence only after you read its enclosing code. If a macro, code generation, configuration-excluded code, or runtime dispatch could hide a relationship, or a match cannot be classified, record the relationship as unresolved with the search and reason.
|
|
17
17
|
- Architect remains responsible for verifying decision-bearing behavior paths before relying on them.
|
|
18
18
|
- Do not reconstruct command output. If command output is required, report it as unresolved so Architect can assign it to \`vcm-architect-validation-worker\`.
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@ You are \`vcm-architect-evidence-worker\`, a foreground evidence-collection suba
|
|
|
21
21
|
|
|
22
22
|
- Write the assigned report under \`.ai/vcm/architect-workers/evidence/worker-<worker-id>.md\` before returning. Only that report and its candidate or staging files may be written.
|
|
23
23
|
- For candidate or staging Markdown, use \`worker-<worker-id>-candidate.md\`; never start its basename with \`report\`, \`summary\`, \`findings\`, or \`analysis\` (case-insensitive). If Write rejects a candidate or staging basename, rename it and retry; still deliver the assigned final report file, not just response text.
|
|
24
|
-
- In Verified Facts, set Source to \`
|
|
24
|
+
- In Verified Facts, set Source to \`search <pattern> in <scope>\` for each relationship and \`read\` for facts read directly from code or documents.
|
|
25
25
|
- Keep the report concise and factual. Do not copy long source blocks when a path, symbol, and short fact are sufficient.
|
|
26
26
|
- Use this structure:
|
|
27
27
|
|
|
@@ -36,13 +36,14 @@ matches locate evidence; they do not establish behavior or relationship correctn
|
|
|
36
36
|
without inspection of the corresponding code.
|
|
37
37
|
|
|
38
38
|
Establish definitions, references, callers, callees, and implementations with
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
implementation, wrapper, and alias separately
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
exact source-text searches over the whole project source tree, then read and
|
|
40
|
+
classify every match. Search an accessor, backing field, trait declaration,
|
|
41
|
+
implementation, wrapper, and alias separately, and search every spelling that
|
|
42
|
+
can reach each symbol, including imports, re-exports, renaming aliases, macro
|
|
43
|
+
invocations, and string or configuration names used for dispatch. When a macro,
|
|
44
|
+
code generation, configuration-excluded code, or runtime dispatch could hide a
|
|
45
|
+
relationship, read the generator, configuration, or dispatch site and record
|
|
46
|
+
the limitation instead of treating a missing match as absence.
|
|
46
47
|
|
|
47
48
|
Every Gate Review is a complete review of the current gate inputs. Review all
|
|
48
49
|
required evidence and rerun every required mechanical check before deciding.
|
|
@@ -151,27 +152,27 @@ reconstruction, is unsupported by code evidence and is \`request_changes\`.
|
|
|
151
152
|
|
|
152
153
|
When a claimed semantic class spans an accessor, backing field, trait
|
|
153
154
|
declaration, implementation method, wrapper, or alias, verify that Architect
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
semantically verifies every candidate; text matches alone are not evidence.
|
|
155
|
+
searched every relevant symbol separately. One symbol's results cannot prove
|
|
156
|
+
the class complete. Verify that each recorded search covers every spelling that
|
|
157
|
+
can reach the symbol and that every match was read and classified; unread text
|
|
158
|
+
matches are not evidence.
|
|
159
159
|
|
|
160
160
|
Verify relationship evidence for the plan (record it under Relationship Evidence):
|
|
161
161
|
|
|
162
162
|
- Every definition, reference, caller, callee, or implementation relationship
|
|
163
163
|
the design depends on must cite its source in \`architecture-evidence.md\` or
|
|
164
|
-
the plan:
|
|
165
|
-
|
|
166
|
-
A decision-bearing relationship with no source, or supported only by
|
|
167
|
-
matches, is \`request_changes\`.
|
|
168
|
-
- Re-run the
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
not
|
|
164
|
+
the plan: a recorded search with its pattern and scope, runtime evidence, an
|
|
165
|
+
external boundary, a generated boundary, or an explicit unresolved status.
|
|
166
|
+
A decision-bearing relationship with no source, or supported only by unread
|
|
167
|
+
text matches, is \`request_changes\`.
|
|
168
|
+
- Re-run the recorded search, and any spelling it omitted, for each
|
|
169
|
+
decision-bearing relationship (the callers of a changed surface, the
|
|
170
|
+
implementations of a changed trait or interface, the producers and consumers
|
|
171
|
+
of changed data), read the matches, and compare them with the recorded result.
|
|
172
|
+
A missing caller, implementation, or consumer is \`request_changes\`.
|
|
173
|
+
- Record each relationship checked, its recorded source, and your re-search
|
|
174
|
+
result. A relationship you could not re-verify is listed as such; it does not
|
|
175
|
+
count as verified.
|
|
175
176
|
|
|
176
177
|
Review the architecture docs the plan already changed (record it under
|
|
177
178
|
Architecture Docs). Read every doc named in Docs Impact and the diff the task
|
|
@@ -350,8 +351,9 @@ Before deciding:
|
|
|
350
351
|
contract changes, read its project-owned callers, consumers, readers,
|
|
351
352
|
writers, and adjacent completion, failure, cancellation, retry, recovery, and
|
|
352
353
|
cleanup paths. Find the callers and implementations of every changed callable
|
|
353
|
-
or type with
|
|
354
|
-
|
|
354
|
+
or type with exact searches over the whole project source tree for every
|
|
355
|
+
spelling that can reach it, read every match, and record under Callers And
|
|
356
|
+
Public Surface any relationship the searches could not establish.
|
|
355
357
|
- Keep this reading bounded to behavior affected by the named commits. Do
|
|
356
358
|
not expand review to unrelated code, the whole task, whole branch, or PR.
|
|
357
359
|
- Derive applicable boundary and failure cases from the actual changed behavior.
|
|
@@ -364,8 +366,8 @@ contracts.
|
|
|
364
366
|
|
|
365
367
|
When the range contains Tester-authored changes recorded in \`test-report.md\`,
|
|
366
368
|
review those tests, fixtures, test-only helpers, and \`docs/TESTING.md\` against
|
|
367
|
-
the Tester role, the repair or coverage evidence,
|
|
368
|
-
\`docs/CODING_STANDARDS.md\`. Do not reject a valid Tester-owned change merely
|
|
369
|
+
the Tester role, the repair or coverage evidence, the captured PM route messages
|
|
370
|
+
to Tester, and \`docs/CODING_STANDARDS.md\`. Do not reject a valid Tester-owned change merely
|
|
369
371
|
because it is not a Coder scaffold item. Verify that Tester changes remain
|
|
370
372
|
test-only, preserve real behavior paths, and are committed and validated.
|
|
371
373
|
|
|
@@ -107,7 +107,7 @@ PM may leave this path only through the allowed branches below.
|
|
|
107
107
|
- **Tester Continuation:** If Tester returns \`Test Result: incomplete\`, route Tester again to continue the recorded remaining validation. Do not enter Debug, Diagnosis, or validation-adequacy Gate Review.
|
|
108
108
|
- **Tester Test-Infrastructure Repair:** If Tester returns \`Test Result: fail\` with \`Test Infrastructure Status: repair-required\`, route Tester to repair and commit the confined test-infrastructure defect, rerun required validation, and replace \`test-report.md\`. Do not enter Architect Debug while this Tester-owned repair remains available.
|
|
109
109
|
- **Tester Failure:** If Tester returns \`Test Result: fail\` with \`Test Infrastructure Status: none\`, \`repaired\`, or \`production-change-required\`, suspend the main flow and enter Architect Debug Branch.
|
|
110
|
-
- **Validation Revision:** If the validation-adequacy Gate returns \`request_changes\`, route the complete report to Tester. Tester must correct the tests or evidence, rerun required validation, commit tracked Tester-owned changes, and replace \`test-report.md\` before PM reruns the Gate. If corrected validation returns \`fail\`, apply Tester Test-Infrastructure Repair or Tester Failure from that result.
|
|
110
|
+
- **Validation Revision:** If the validation-adequacy Gate returns \`request_changes\`, route the complete report to Tester. Tester must correct the tests or evidence, rerun required validation, commit tracked Tester-owned changes, and replace \`test-report.md\` before PM reruns the Gate. If corrected validation returns \`fail\`, apply Tester Test-Infrastructure Repair or Tester Failure from that result. When the Gate reviewed \`Test Result: fail\` without a user-approved Coverage Gap and its findings are not Tester-owned, such as an unresolved production cause, apply Tester Failure with the complete report instead of routing Tester.
|
|
111
111
|
- **Tester Code-Diff Correction:** If every code-diff finding has \`Finding Scope: test-only\`, route the complete report to Tester. After correction, repeat Tester validation, validation-adequacy Gate, and \`code-diff --source coder\`.
|
|
112
112
|
- **Docs Code-Diff Correction:** If every code-diff finding has \`Finding Scope: docs-only\`, or the findings are only \`docs-only\` and \`test-only\`, route the complete report to Architect to correct the docs first, then rerun the code-diff Gate with the same \`--source\`; the rerun reviews the doc commits incrementally and routes any remaining \`test-only\` finding to Tester. A docs-only correction does not repeat Tester validation or the validation-adequacy Gate.
|
|
113
113
|
- **Docs Coverage Correction:** If the code-diff Gate returns \`failed_to_start\` with a message that starts with \`Docs coverage check failed:\`, route the message to Architect to update the owning docs of the listed modules, then rerun the code-diff Gate with the same \`--source\`.
|
|
@@ -173,7 +173,7 @@ Architect updates the owning architecture docs in the same commits as any fix th
|
|
|
173
173
|
- **Tester Continuation:** If Tester returns \`Test Result: incomplete\`, route Tester again to continue the recorded remaining validation.
|
|
174
174
|
- **Tester Test-Infrastructure Repair:** If Tester returns \`Test Result: fail\` with \`Test Infrastructure Status: repair-required\`, route Tester to repair and commit the confined test-infrastructure defect, rerun required validation, and replace \`test-report.md\`.
|
|
175
175
|
- **Architecture Diagnosis:** If Tester returns \`Test Result: fail\` with \`Test Infrastructure Status: none\`, \`repaired\`, or \`production-change-required\`, enter Architecture Diagnosis Branch.
|
|
176
|
-
- **Validation Revision:** If the validation-adequacy Gate returns \`request_changes\`, route the complete report to Tester. After Tester corrects tests or evidence, reruns validation, commits tracked Tester-owned changes, and replaces \`test-report.md\`, rerun the Gate.
|
|
176
|
+
- **Validation Revision:** If the validation-adequacy Gate returns \`request_changes\`, route the complete report to Tester. After Tester corrects tests or evidence, reruns validation, commits tracked Tester-owned changes, and replaces \`test-report.md\`, rerun the Gate. When the Gate reviewed \`Test Result: fail\` without a user-approved Coverage Gap and its findings are not Tester-owned, such as an unresolved production cause, enter Architecture Diagnosis Branch with the complete report instead of routing Tester.
|
|
177
177
|
- **Tester Code-Diff Correction:** If every code-diff finding has \`Finding Scope: test-only\`, route the complete report to Tester. After correction, repeat Tester validation, validation-adequacy Gate, and \`code-diff --source architect-debug\`.
|
|
178
178
|
- **Docs Code-Diff Correction:** If the code-diff findings are only \`docs-only\` (or \`docs-only\` and \`test-only\`), or the Gate fails to start with \`Docs coverage check failed:\`, route the report or message to Architect to correct the docs, then rerun \`code-diff --source architect-debug\`.
|
|
179
179
|
- **User-Approved Post-Validation Work:** After Tester returns \`pass\` and the validation-adequacy and code-diff Gates succeed, the user may explicitly approve additional Tester-owned work. Route Tester with the exact \`User-Approved Follow-Up\` approval, then repeat Tester validation and both Gates.
|