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 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 bundles the Claude Code LSP bridge and loads it for Architect and Reviewer
515
- sessions, including Codex Bridge launches; Architect's evidence worker can use it
516
- too. While a language server is still indexing, VCM holds LSP queries until it
517
- is ready and fails them explicitly if indexing does not finish, instead of
518
- returning partial results. The project environment must still
519
- provide the language server for each detected language: `rust-analyzer`,
520
- `typescript-language-server`, `pyright-langserver`, `gopls`, `clangd`, or
521
- `jdtls`. Architect preloads `vcm-code-navigation` and uses LSP for semantic
522
- relationships. Accessors, backing fields, trait items, implementations, wrappers,
523
- and aliases are queried as separate symbols; a bounded source-text fallback may
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, roleUsesLsp } from "../role-tool-policy.js";
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, pluginDirs = []) {
24
- const args = pluginDirs.flatMap((pluginDir) => ["--plugin-dir", pluginDir]);
25
- const lspEnabled = roleUsesLsp(role) && pluginDirs.length > 0;
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 LSP_FRONTMATTER_DISALLOWED_TOOLS = [
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 = [...LSP_FRONTMATTER_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
- ...LSP_FRONTMATTER_DISALLOWED_TOOLS
39
+ ...FRONTMATTER_DISALLOWED_TOOLS
40
40
  ];
41
- // The evidence worker reads and queries LSP but never runs commands, edits code,
42
- // or delegates. A deny list keeps the parent session's LSP tool available.
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
- ...LSP_FRONTMATTER_DISALLOWED_TOOLS
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 makes semantic code claims; Reviewer verifies them at Gate Review.
56
- const LSP_ROLE_NAMES = new Set(["architect", "reviewer"]);
57
- export function roleUsesLsp(role) {
58
- return LSP_ROLE_NAMES.has(role);
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 = appendTerminalReplay(entry.replayBuffer, data);
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
- if (options.replay !== false && entry.replayBuffer) {
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: entry.replayBuffer
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
- export function appendTerminalReplay(current, data, limitBytes = TERMINAL_REPLAY_TAIL_LIMIT_BYTES) {
261
- if (!data) {
262
- return current;
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 = {
@@ -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(codeDiffSources.map((source) => source === "coder" ? "coder" : "architect"));
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 [analyses, codeIntelligence] = await Promise.all([
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, codeIntelligence);
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 [analyses, codeIntelligence] = await Promise.all([
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, codeIntelligence),
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, codeIntelligence) {
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
- codeIntelligence,
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, lspPluginDirs),
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
- return [`${currentFlow}/tester`];
895
- }
896
- if (test.value === "fail" && !test.hasUserApprovedCoverageGap) {
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
- - LSP is mandatory for navigating project source code. Start source-code navigation with a registered LSP server. If a required language server is unavailable, stop the affected work and report its language, command, error, and installation hint through the current communication channel. Resume after the environment is fixed and Architect is restarted; do not substitute source text search.
25
- - Use LSP definitions, implementations, references, document or workspace symbols, and incoming or outgoing calls for all source-code symbol and relationship queries.
26
- - LSP reference results are symbol-specific. An accessor, its backing field, a trait declaration, its implementation method, a wrapper, and an alias are separate symbols. Query every relevant symbol separately; one symbol's reference result cannot prove a complete semantic class. When starting from an accessor or wrapper, read its implementation, resolve its backing field, delegate, or trait item with LSP, then query those symbols too.
27
- - Do not use the built-in \`Grep\` tool or shell text-search commands such as \`grep\`, \`rg\`, \`git grep\`, \`ag\`, or \`ack\` to search project source code, test code, or executable scripts, except for the bounded fallback below. This prohibition includes locating or inferring definitions, implementations, references, callers, callees, symbols, and behavior paths.
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 LSP semantic navigation, then personally read every decision-bearing callable unit in full.
76
- - Delegate bounded supporting implementation and document reading, and bounded LSP relationship collection for supporting symbols, to \`vcm-architect-evidence-worker\` when it would otherwise add substantial raw context. Worker reports cite the LSP operation behind each relationship but do not replace Architect's own LSP verification of decision-bearing symbols, relationships, public surfaces, ownership, lifecycle, failure paths, contradictions, or unresolved evidence.
77
- - If LSP cannot resolve a required project-owned relationship, record the limitation in \`architecture-evidence.md\` and leave it unresolved.
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 LSP, runtime, verified bounded source, external-boundary, or generated-boundary evidence
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
- - Use LSP for every definition, reference, caller, callee, and implementation relationship you report. LSP results are symbol-specific: query an accessor, its backing field, a trait declaration, its implementation, a wrapper, and an alias separately.
16
- - If LSP is unavailable for the language, reports that the server is still indexing, or cannot resolve the relationship, record the relationship as unresolved with the operation and result. Never report a relationship from text matches; text search only locates candidate files.
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 \`LSP <operation>\` for each relationship and \`read\` for facts read directly from code or documents.
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
- LSP when a language server is registered for the language. LSP results are
40
- symbol-specific: query an accessor, backing field, trait declaration,
41
- implementation, wrapper, and alias separately. An LSP query that fails because
42
- the server is still indexing returned no result; retry it, and if it still fails,
43
- record the relationship as not re-verified instead of treating it as empty or
44
- verified. When no server is registered for a language, say so in the report and
45
- verify relationships by reading the complete candidate code.
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
- queried every relevant symbol separately. One symbol's reference result cannot
155
- prove the class complete. If Architect used bounded source fallback, verify the
156
- evidence records the correct prior LSP operation and its missing relationship,
157
- limits candidate search to the identified owning file or module, and
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: an LSP operation, runtime evidence, verified bounded source fallback,
165
- an external boundary, a generated boundary, or an explicit unresolved status.
166
- A decision-bearing relationship with no source, or supported only by text
167
- matches, is \`request_changes\`.
168
- - Re-run the LSP query for each decision-bearing relationship (the callers of a
169
- changed surface, the implementations of a changed trait or interface, the
170
- producers and consumers of changed data) and compare it with the recorded
171
- result. A missing caller, implementation, or consumer is \`request_changes\`.
172
- - Record each relationship checked, its recorded source, and your re-query
173
- result. A relationship that LSP could not re-verify is listed as such; it does
174
- not count as verified.
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 LSP references and implementations, not text search, and record
354
- under Callers And Public Surface any that LSP could not resolve.
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, and
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.