Skip to content

buildAgentsContext crashes with ENOENT when AGENTS.md is absent #13

Description

@rdh073

Bug: buildAgentsContext crashes with ENOENT when AGENTS.md is absent

Summary

git-ai-review exits immediately with an uncaught ENOENT if the
repo root has no AGENTS.md. There is no fallback path — even a
trivial run on a fresh repo aborts before any review can start. The
file should be optional: when missing, the reviewer should fall back
to the prompt header alone.

Affected versions

  • git-ai-review@2.4.2 (current latest on npm at time of report)
  • Likely earlier 2.x as well — bug exists since buildAgentsContext
    was introduced.

Minimal repro

mkdir /tmp/gar-bug && cd /tmp/gar-bug
git init -q
echo "console.log('hi');" > foo.js
git add foo.js
npx git-ai-review

Expected: review runs, header-only prompt sent to the configured
sub-agent, JSON verdict returned.

Actual:

Error: ENOENT: no such file or directory, open 'AGENTS.md'
    at Object.readFileSync (node:fs:451:20)
    at buildAgentsContext (.../dist/prompt.js:99:20)
    at buildPrompt (.../dist/review.js:153:21)
    ...

Process exits non-zero before buildPrompt returns.

Root cause

dist/prompt.js:

export function buildAgentsContext(cwd = process.cwd()) {
    const agentsPath = resolve(cwd, 'AGENTS.md');
    const agents = readFileSync(agentsPath, 'utf8'); // ← throws ENOENT
    ...
}

readFileSync is called without an existence check; the call site in
buildPrompt unconditionally injects the result into the prompt. No
caller catches the error, so it propagates to the top level.

Suggested fix

Treat missing AGENTS.md as "no project-specific overrides" — return
an empty context, and have buildPrompt skip the Here is the full AGENTS.md for reference: section when the context is empty.

src/prompt.ts:

export function buildAgentsContext(cwd = process.cwd()): AgentsContext {
  const agentsPath = resolve(cwd, "AGENTS.md");
  if (!existsSync(agentsPath)) {
    return { agents: "", referenced: [] };
  }
  const agents = readFileSync(agentsPath, "utf8");
  const references = extractReferencedMarkdownFiles(agents);
  const trackedMdFiles = listTrackedMarkdownFiles();
  return {
    agents,
    referenced: buildReferencedMarkdownContext(
      references,
      trackedMdFiles,
      (file) => readFileSync(resolve(cwd, file), "utf8"),
      new Set(["AGENTS.md"])
    ),
  };
}

src/review.ts:

export function buildPrompt(diff: string, cwd = process.cwd(), diffLabel = "Staged diff"): string {
  const context = buildAgentsContext(cwd);
  return [
    ...resolvePromptHeaderLines(),
    ...(context.agents
      ? ["", "Here is the full AGENTS.md for reference:", context.agents]
      : []),
    ...(context.referenced.length > 0
      ? [
          "",
          "Additional markdown files referenced by AGENTS.md (full contents):",
          ...context.referenced,
        ]
      : []),
    "",
    "Respond with ONLY a JSON object matching this schema (no markdown, no backticks, no explanation):",
    JSON.stringify(REVIEW_SCHEMA, null, 2),
    "",
    `${diffLabel}:`,
    diff,
  ].join("\n");
}

Add existsSync to the node:fs import in src/prompt.ts.

Suggested regression tests

describe("buildAgentsContext", () => {
  it("returns empty context when AGENTS.md is missing", () => {
    const tmp = mkdtempSync(join(tmpdir(), "gar-"));
    expect(buildAgentsContext(tmp)).toEqual({ agents: "", referenced: [] });
  });
});

describe("buildPrompt", () => {
  it("omits the AGENTS.md section when context is empty", () => {
    const tmp = mkdtempSync(join(tmpdir(), "gar-"));
    const prompt = buildPrompt("diff --git a/x b/x\n+hi", tmp);
    expect(prompt).not.toContain("Here is the full AGENTS.md for reference");
    expect(prompt).toContain("Respond with ONLY a JSON object");
    expect(prompt).toContain("diff --git a/x b/x");
  });
});

Why this is at least P1

The default header line — "You are a strict reviewer for all AGENTS.md rules." — implies the file is the source of truth. But
making the file required without documentation is a footgun for any
first-time user running npx git-ai-review in an existing repo
without project conventions yet. The first impression is "broken
tool"; the fix is one existsSync check.

Workaround until released

Either:

touch AGENTS.md  # any non-empty content works; empty also works after this fix

Or patch the npx-cached copy locally (transient, lost on
npm cache clean or new version download).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions