claude-teammate 0.1.317 → 0.1.319

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-teammate",
3
- "version": "0.1.317",
3
+ "version": "0.1.319",
4
4
  "description": "CLI bootstrapper for Claude Teammate.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,14 +23,37 @@ function formatPriorWorkContext(input) {
23
23
  return `${sections.join("\n")}\n`;
24
24
  }
25
25
 
26
- // Pre-baked code-graph grounding (symbols + call paths) injected by the worker.
27
- // Empty when codegraph is unavailable, so prompts are unchanged in that case.
26
+ // Code-graph grounding injected by the worker. Two parts, each optional:
27
+ // 1. a pre-baked seed (symbols + call paths from one explore query)
28
+ // 2. usage instructions so Claude can drive codegraph itself via Bash for
29
+ // adaptive drill-down (the seed is one query; the live tool is unlimited)
30
+ // Both empty when codegraph is unavailable, so prompts are unchanged then.
28
31
  function formatCodegraphContext(input) {
29
32
  const ctx = String(input.codegraphContext || "").trim();
30
- if (!ctx) {
33
+ const repoPath = String(input.codegraphRepoPath || "").trim();
34
+ const bin = String(input.codegraphBin || "").trim();
35
+ if (!ctx && !(bin && repoPath)) {
31
36
  return "";
32
37
  }
33
- return `\nCode graph context (symbols + call paths relevant to this task — use it to locate code precisely and avoid hallucinating APIs that do not exist in this repository):\n${ctx}\n`;
38
+ const sections = [];
39
+ if (ctx) {
40
+ sections.push(
41
+ `Code graph context (symbols + call paths relevant to this task — use it to locate code precisely and avoid hallucinating APIs that do not exist in this repository):\n${ctx}`
42
+ );
43
+ }
44
+ if (bin && repoPath) {
45
+ sections.push(
46
+ [
47
+ "Code graph tool: a CodeGraph index of this repository is already built. When you need to locate a symbol, trace call paths, or gauge blast radius before editing, run these via Bash. ALWAYS pass `-p` to point at the indexed checkout (your working directory is a separate worktree without an index):",
48
+ `- ${bin} explore "<what you are looking for>" -p ${repoPath}`,
49
+ `- ${bin} node <SymbolOrFile> -p ${repoPath}`,
50
+ `- ${bin} callers <Symbol> -p ${repoPath}`,
51
+ `- ${bin} impact <Symbol> -p ${repoPath}`,
52
+ "Prefer these over blind grep when chasing how code connects. The tool is optional — if a command errors, fall back to Read/Grep and keep going."
53
+ ].join("\n")
54
+ );
55
+ }
56
+ return `\n${sections.join("\n\n")}\n`;
34
57
  }
35
58
 
36
59
  const INCLUDE_RESOURCE_LINKS_RULE =
@@ -1,5 +1,6 @@
1
- import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
1
+ import { mkdir, readdir, readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
+ import { atomicWriteFile } from "../fs-atomic.js";
3
4
  import {
4
5
  extractSkillFailures,
5
6
  inferBypassedSkills,
@@ -665,7 +666,10 @@ async function appendSkillFixEvent(eventsRoot, fields) {
665
666
  if (!Array.isArray(events)) events = [];
666
667
  events.unshift({ ts: new Date().toISOString(), ...fields });
667
668
  events = events.slice(0, SKILL_FIX_EVENTS_MAX);
668
- await writeFile(file, JSON.stringify(events, null, 2), "utf8");
669
+ // Atomic write (tmp + rename) so a concurrent reader never sees a
670
+ // half-written file. The per-path write chain serializes writes but not
671
+ // reads-vs-writes; rename gives readers all-or-nothing.
672
+ await atomicWriteFile(file, JSON.stringify(events, null, 2));
669
673
  } catch {
670
674
  // never throw — event logging is best-effort
671
675
  }
@@ -101,6 +101,14 @@ export async function exploreCodegraph(repoPath, query, logger) {
101
101
  return out.length > CONTEXT_MAX_CHARS ? `${out.slice(0, CONTEXT_MAX_CHARS)}\n[codegraph context truncated]` : out;
102
102
  }
103
103
 
104
+ // Public: resolved absolute path to the codegraph binary (or null when not
105
+ // found). Lets the prompt layer tell Claude exactly which binary to invoke via
106
+ // Bash — robust to the implementation subprocess having a thinner PATH than the
107
+ // worker. Memoized via resolveCodegraphBin; warns at most once.
108
+ export async function getCodegraphBin(logger) {
109
+ return resolveCodegraphBin(logger);
110
+ }
111
+
104
112
  // Test seam: reset the memoized binary resolution.
105
113
  export function __resetCodegraphBinForTests() {
106
114
  resolvedBin = undefined;
@@ -14,7 +14,7 @@ import {
14
14
  prepareRepoForBranch,
15
15
  removeWorktree
16
16
  } from "../repo.js";
17
- import { ensureCodegraphIndex, exploreCodegraph } from "./codegraph-context.js";
17
+ import { ensureCodegraphIndex, exploreCodegraph, getCodegraphBin } from "./codegraph-context.js";
18
18
  import { buildEpicMemoryPromptSnapshot, persistEpicImplementationKnowledge } from "./epic-memory.js";
19
19
  import {
20
20
  clearForgePullRequestBlocked,
@@ -201,11 +201,20 @@ export async function processPullRequestImplementation({
201
201
  await ensureGitExcludes(cgRepoPath, [".codegraph/"]);
202
202
  await ensureCodegraphIndex(cgRepoPath, logger);
203
203
  }
204
+ // Query an indexed checkout, NOT the worktree. The worktree (repoPath) is a
205
+ // `-wt-` sibling with no .codegraph/, so exploring it would always return
206
+ // empty. The primary clone (repo.local_path) is the one we just indexed and
207
+ // reflects the existing codebase Claude must ground against.
208
+ const codegraphQueryPath = codegraphRepoPaths.includes(repo.local_path) ? repo.local_path : repoPath;
204
209
  const codegraphContext = await exploreCodegraph(
205
- repoPath,
210
+ codegraphQueryPath,
206
211
  `${issueKey} ${detail.title} ${stripImplementationPlan(nextBody).slice(0, 500)}`,
207
212
  logger
208
213
  );
214
+ // Absolute binary path so the prompt can tell Claude exactly what to run via
215
+ // Bash for adaptive drill-down (codegraph explore/node/callers/impact -p ...).
216
+ // Null when codegraph is unavailable — the prompt then omits the usage block.
217
+ const codegraphBin = await getCodegraphBin(logger);
209
218
 
210
219
  // Resume the prior Claude conversation for this PR branch so a follow-up
211
220
  // comment / reopen keeps the model's earlier context instead of rebuilding
@@ -303,6 +312,8 @@ export async function processPullRequestImplementation({
303
312
  pullRequest: { ...detail, body: nextBody },
304
313
  step: stepText,
305
314
  codegraphContext,
315
+ codegraphRepoPath: codegraphQueryPath,
316
+ codegraphBin,
306
317
  memory: { epic: epicSnapshot },
307
318
  epicContext: epicMemory,
308
319
  branchDiff: stepBranchDiff,
@@ -368,6 +379,8 @@ export async function processPullRequestImplementation({
368
379
  latestComment,
369
380
  branchDiff,
370
381
  codegraphContext,
382
+ codegraphRepoPath: codegraphQueryPath,
383
+ codegraphBin,
371
384
  repoPath,
372
385
  repoPaths: repoAccess.repoPaths,
373
386
  branchName: detail.headRef,