From fe3777c9768f0f0a180a2a17589cd1f767712ac4 Mon Sep 17 00:00:00 2001 From: mick-gsk Date: Thu, 30 Jul 2026 01:04:34 +0200 Subject: [PATCH] feat(guard): guard Go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #779 Measured on real Go repositories: cobra speaks on 0 of 36 files, gin on 2 of 99 — and gin's two are real, `Binding` being defined in both `binding.go` and `binding_nomsgpack.go`. Two decisions worth naming. **Methods on receivers are not indexed.** #779 argued for including them, since `func (s *Store) Validate()` is package-level API in Go. The noise measurement that came between then and now argued louder: `String`, `Error`, `Read` and `Close` sit on every type in a package, and methods are excluded in Python and TypeScript for exactly that reason. Evidence beat the plan. **Trailing-segment matching is reserved for Go.** Go imports carry the whole module path (`github.com/org/repo/internal/db`) while the repository knows itself as `internal/db`, so the resolver drops leading segments until something matches — no `go.mod` parsing needed. Applying the same rule to TypeScript would resolve `lodash/fp` onto a directory named `fp`, and date-fns has one; a test pins that boundary. The `type (...)` block form is deliberately unsupported. Matching names at one indent level would also match struct fields, and a struct field read as a type declaration is the invented symbol these patterns exist to prevent. One bug in the measurement tool, found by the same instinct that has paid off twice today: gin reported zero cross-directory imports, which was too clean. `measure_boundary_reach` called `import_to_dir` without a suffix, so every Go module path fell through the TypeScript branch and resolved to nothing. With the suffix passed, gin goes from 0 to 21 files across 14 edges. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 1 + README.md | 8 +- docs-site/claude-code-plugin.md | 10 +- scripts/gates/measure_noise.py | 8 +- src/drift/guard/build.py | 28 ++++- src/drift/guard/extract.py | 71 ++++++++++++- src/drift/guard/lookup.py | 5 +- tests/guard/test_extract_go.py | 175 ++++++++++++++++++++++++++++++++ tests/guard/test_extract_ts.py | 2 +- 9 files changed, 291 insertions(+), 17 deletions(-) create mode 100644 tests/guard/test_extract_go.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 83924216..cd55b754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Short version: Drift installs as a Claude Code plugin and works inside the agent - add amphetamin — hold the session open on machine-checked work - guard TypeScript and JavaScript, not only Python - notice when the index describes a tree that has moved +- guard Go ### Fixed diff --git a/README.md b/README.md index ac2062eb..f02362f2 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ plugin that fires in every project you open has no business leaving a directory in each of them. A project that wants the index alongside its source opts in by creating a `.drift/` directory. -**Python, TypeScript and JavaScript** (`.py .ts .tsx .js .jsx .mjs .cjs`), in one -index — a name defined in Python is found from TypeScript, because -`validate_token` and `validateToken` normalise to the same thing. Other -languages pass through untouched. +**Python, TypeScript, JavaScript and Go** (`.py .ts .tsx .js .jsx .mjs .cjs .go`), +in one index — a name defined in Python is found from TypeScript, because +`validate_token`, `validateToken` and `ValidateToken` all normalise to the same +thing. Other languages pass through untouched.