From af0e09b389f07b0427501653743053600e78b949 Mon Sep 17 00:00:00 2001 From: Dshuishui Date: Tue, 11 Aug 2026 18:16:09 +0800 Subject: [PATCH] feat(extraction): exclude FM-Agent's work directory by default FM-Agent writes fm_agent/ into the project it analyses. It holds one copy of every function extracted from that project plus the scripts staged to produce them, so indexing it lists each function twice and mixes tool code in with project code - on a four-function Python project, 43 of 47 function nodes. Add `fm_agent` to DEFAULT_IGNORE_DIRS. Unlike the entries around it this name is not from the github/gitignore templates and could plausibly be real source, which is why upstream would not carry it; a project that does own an fm_agent/ directory opts back in with a `.gitignore` negation, as for any other default-ignored directory. The supported way to express this is an `exclude` entry in the project's codegraph.json, which is what FM-Agent does today. It works, but it means FM-Agent creates a file in a repository it does not own, on every project it analyses, purely to describe its own artifacts. Carrying the exclusion in the build it already pins removes that: nothing is written outside FM-Agent's own work directory. The codegraph.json write stays until the pinned fork build is guaranteed to be the one running, since an upstream build has no other mechanism. Measured on a project holding fm_agent/ with neither codegraph.json nor .gitignore: 79 nodes before, 6 after - and 79 again with `!fm_agent/` in .gitignore. FORK.md now records the patch in a table, states that each one must be re-applied on every upstream sync, and names the real pinned base (upstream main c6aaa20, which is past v1.5.0) alongside why the version marker still reads 1.5.0-fmagent.N. The policy paragraph is brought in line with what the last sync actually did: merging an untagged upstream commit is allowed when what we need is unreleased, and then the verification burden is ours. Version bumped to 1.5.0-fmagent.2. --- FORK.md | 39 +++++++++++++++++++++++++++------------ package-lock.json | 4 ++-- package.json | 2 +- src/extraction/index.ts | 8 ++++++++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/FORK.md b/FORK.md index e56bc240d..49d2cb1f3 100644 --- a/FORK.md +++ b/FORK.md @@ -3,14 +3,26 @@ FM-Agent's maintenance fork of [colbymchenry/codegraph](https://github.com/colbymchenry/codegraph). -**Pinned base:** upstream `v1.5.0`. Upstream shipped the C macro-attribute -extraction fix (issue #1211, PR #1311) in v1.5.0, so this base carries it -natively — the fork no longer needs its own patch on top. +**Pinned base:** upstream `main` at `c6aaa20358cd6adcd04b87bdef8e5803ad146f3a` +(2026-08-07). That is *past* `v1.5.0` and before whatever upstream tags next: +`v1.5.0` was 104 commits behind, and the incremental-sync convergence work, the +first-class `union` nodes and the WAL growth fix in between all matter to how +FM-Agent reads the graph. The version marker keeps saying `1.5.0-fmagent.N` +because it is the last upstream *release* this descends from — the exact base is +this commit. -**Patches:** none currently — this base is byte-identical to upstream v1.5.0. The -fork is kept as standing infrastructure so an urgent fix upstream hasn't shipped -can be applied and released quickly if needed; each such fix would live as a -merged pull request here. +Upstream shipped the C macro-attribute extraction fix (issue #1211, PR #1311) in +v1.5.0, so the base carries it natively; the fork no longer needs its own patch +for it. + +**Patches:** one, listed below. Apart from it the tree matches the pinned base, so +the fork stays cheap to re-sync. Every patch lives as a merged pull request here +and must be **re-applied on each upstream sync** — if a merge drops one, this list +is what catches it. + +| File | Patch | +|------|-------| +| `src/extraction/index.ts` | `fm_agent` added to `DEFAULT_IGNORE_DIRS`. FM-Agent writes its work directory into the project it analyses, holding one copy of every function it extracts plus the scripts staged to produce them, so indexing it lists each function twice and mixes tool code in with project code. Upstream deliberately keeps names that could be real source out of that list, so this stays fork-only; a project that does own an `fm_agent/` directory opts back in with a `.gitignore` negation (`!fm_agent/`). | **Version marker:** `codegraph --version` → `1.5.0-fmagent.N` identifies a build from this fork. Note this is a SemVer pre-release of `1.5.0`, so it sorts *below* @@ -27,8 +39,11 @@ bundles (darwin/linux/windows, arm64/x64) with the native Rust extraction kernel. FM-Agent's `install.sh` pins one via `CODEGRAPH_VERSION`. **Policy:** pin to a base, don't chase upstream — update only when we need -something a newer upstream release carries. Base updates land via a pull request -that **merges** the target upstream tag into `main` (so upstream stays an ancestor -— blame, audits and future syncs follow upstream history) and re-applies this -fork layer; merge such PRs with a merge commit, not a squash. Upstream is tracked -via the `upstream` git remote. +something a newer upstream state carries. Prefer a tagged release; an untagged +`main` commit is fair game when what we need is not released yet, and then the +commit id *is* the base (record it above, and verify the build ourselves — +nothing upstream has vetted it). Base updates land via a pull request that +**merges** that upstream point into `main` (so upstream stays an ancestor — blame, +audits and future syncs follow upstream history) and re-applies this fork layer; +merge such PRs with a merge commit, not a squash. Upstream is tracked via the +`upstream` git remote. diff --git a/package-lock.json b/package-lock.json index e1bc5169f..b10985a80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@colbymchenry/codegraph", - "version": "1.5.0-fmagent.1", + "version": "1.5.0-fmagent.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@colbymchenry/codegraph", - "version": "1.5.0-fmagent.1", + "version": "1.5.0-fmagent.2", "license": "MIT", "dependencies": { "@clack/prompts": "^1.3.0", diff --git a/package.json b/package.json index 6b6afd96e..5cc4ede48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@colbymchenry/codegraph", - "version": "1.5.0-fmagent.1", + "version": "1.5.0-fmagent.2", "description": "Supercharge AI coding agents with semantic code intelligence — surgical context, fewer tool calls, faster answers. 100% local.", "repository": { "type": "git", diff --git a/src/extraction/index.ts b/src/extraction/index.ts index 22108d1d1..1d63cfce1 100644 --- a/src/extraction/index.ts +++ b/src/extraction/index.ts @@ -196,6 +196,14 @@ const DEFAULT_IGNORE_DIRS: ReadonlySet = new Set([ '__history', '__recovery', // Generic cache '.cache', + // FORK-SPECIFIC (see FORK.md): FM-Agent's work directory. It holds one copy of + // every function FM-Agent extracts from the project, plus the scripts it stages + // to produce them, so indexing it lists each function twice and mixes tool code + // in with project code. Unlike the entries above, this name is not from the + // github/gitignore templates and could plausibly be real source — which is why + // it stays fork-only. A project that does own an `fm_agent/` directory opts back + // in with a `.gitignore` negation (`!fm_agent/`), as for any default-ignored dir. + 'fm_agent', ]); /**