Skip to content

refactor: own the CGO-free switch and guard the surface in core (#345) - #347

Merged
antoinetoussaint-byte merged 3 commits into
mainfrom
issue-345-refactor-investigate-core-s-cgo-dependency-surface-and
Aug 23, 2026
Merged

refactor: own the CGO-free switch and guard the surface in core (#345)#347
antoinetoussaint-byte merged 3 commits into
mainfrom
issue-345-refactor-investigate-core-s-cgo-dependency-surface-and

Conversation

@antoinetoussaint-byte

Copy link
Copy Markdown
Contributor

Closes #345.

Summary

  • Own the cgo/no-cgo switch in core so consumers stop reinventing it. cli#456 fixed the concrete instance downstream by splitting on a codefly_nosemantic build tag; this is the core-side generalization it revealed. code/codeserver.New(root) is the single entry point — the default build installs the tree-sitter analyzer (code/semantic), -tags codefly_nosemantic returns a CGO-free DefaultCodeServer. codefly_nosemantic is standardized as the canonical, cross-repo tag. The switch lives in a new code/codeserver package because code/semantic imports code, so the switch cannot sit in code without an import cycle.
  • Guard against cgo creep as an enforced contract. scripts/check_cgo_free.sh (make check-cgo-free + a CI step in go.yml) builds every package with CGO_ENABLED=0 -tags codefly_nosemantic except a documented allowlist (code/semantic today). A new dependency that drags cgo into the CGO-free surface now fails in core at the introducing PR, with a clear message — instead of at a downstream companion publish weeks later.
  • Loud-fail preserved. The default (untagged) build still imports code/semantic, so an accidental CGO_ENABLED=0 build of the full server fails at link time rather than silently dropping semantics. Dropping semantics is only ever explicit, via the tag.

Investigation findings (full cgo inventory, ownership-boundary decision, tag semantics, and the allowlist) are documented in docs/cgo.md. The entire cgo surface is confirmed to be the single code/semantic package — no sqlite or other cgo dependencies.

The out-of-process option (serving tree-sitter from a separate cgo agent) was evaluated and deferred — it contradicts the in-process source path and adds an IPC hop; noted as a revisit-if-the-gateway-moves item in docs/cgo.md.

Test plan

  • go test ./code/codeserver/ — new test asserts the default build wires the analyzer (real tree-sitter semantic index over a Python source tree, no mocks).
  • go test -tags codefly_nosemantic ./code/codeserver/ — analyzer test is correctly gated out; package still compiles CGO-free.
  • make check-cgo-free passes; verified it fails (with the build constraints exclude all Go files error) when code/semantic is removed from the allowlist.
  • go build ./... (default) and go vet ./code/codeserver/ clean; gofmt clean.

antoinetoussaint-byte and others added 3 commits August 23, 2026 16:02
Confine the cgo/no-cgo build switch to core and enforce the CGO-free
surface as a contract:

- Add code/codeserver.New: a build-tag-split constructor. The default
  build installs the tree-sitter analyzer; -tags codefly_nosemantic
  returns a CGO-free DefaultCodeServer. Consumers get one call and no
  build tags of their own. codefly_nosemantic is the canonical tag.
- Add scripts/check_cgo_free.sh (make check-cgo-free + CI step) that
  builds every package CGO-free except a documented cgo allowlist, so
  cgo creep fails in core at the introducing PR.
- Document the CGO surface, ownership boundary, tag semantics, and
  allowlist in docs/cgo.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- The cgo surface table said no non-test package imports code/semantic;
  code/codeserver now does on the default build. Clarify it stays out of
  the CGO-free build via the codefly_nosemantic tag.
- Fix "code/code/semantic" typo in the guard's failure message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The build-tag-aware constructor lives in code/codeserver because the
import cycle (code/semantic imports code) forbids it in package code, so
a consumer browsing package code's constructors/options never finds it
and reinvents the cgo/no-cgo split — the exact duplication this issue
removes. Signpost the packaged constructor at WithSemanticAnalyzer, the
manual mechanism a reinventor reaches for.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@antoinetoussaint-byte
antoinetoussaint-byte merged commit ad09c9d into main Aug 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[refactor] Investigate core's CGO dependency surface and where the CGO-free switch should live

1 participant