Files
Maven/vendor/modernc.org/libc/CLAUDE.md
T
kami 6c92f85d10 feat(ecosystem): compliant Praxis/Hexis integration + vendored build
Bring the Nexus/Praxis/Hexis integration in line with
MAVEN_ECOSYSTEM_ARCHITECTURE.md:

- Praxis over HTTP: drop the in-process praxis.db open (praxisstore/
  praxistools) and call praxisd's /api/v1/tools/* API via a new praxisClient.
  Honors the "no component reads another's DB" invariant (AC#12).
  PraxisConfig.DBPath -> URL.
- Hexis confirmation gate: mutating capabilities (ReadOnly=false) now park a
  bound pendingHexis confirmation and require a spoken "да" before executing;
  read-only run immediately (AC#7, no auto attention->action).
- Capability safety: >1 verb match is ambiguous -> ask instead of firing the
  first; ambiguous Nexus resolution asks for clarification (AC#2).
- Correlation IDs on Hexis execute, recorded in the cross-service trace.
- Bug: importance arrives as JSON float64 over HTTP, not int.
- Tests: confirm-gate, decline, read-only, and ambiguity paths.

Build: vendor/ bakes in the hexis client (replace-directed at a sibling repo
outside the Docker context); Dockerfile builds from vendor and no longer
`go mod download`s the unreachable replace paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 20:24:33 +04:00

107 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this is
`modernc.org/libc` is a partial reimplementation of C libc in pure Go. It is the **runtime** for C programs translated to Go by the `modernc.org/ccgo` transpiler (notably `modernc.org/sqlite`). It is not a standalone library for general use; its API tracks the needs of ccgo-generated code and may change incompatibly between versions.
Compatibility note: callers of this package (e.g. `modernc.org/sqlite`) must use the libc version that matches their generated code (see the consumer's `go.mod`). Do not bump the libc version of a downstream consumer in isolation without re-translating its C sources.
## Architectural split: musl-derived vs hand-written
This is the most important thing to understand before editing any file. There are two completely separate code paths selected by build constraint:
1. **musl-derived (linux/amd64, arm64, loong64, ppc64le, s390x, riscv64, 386, arm)** — the libc implementation is generated by transpiling musl-libc's C source to Go via `ccgo/v4`. The canonical build tag is:
```
//go:build linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm)
```
Generated files for this path: `ccgo_linux_*.go` (~4 MB each, the bulk of the musl translation), the per-arch `musl_*.go` files written by older tooling, and on amd64 the assembly stubs in `abi0_linux_amd64.{go,s}` (generated by `qbecc --abi0wrap`). The hand-written glue lives in `libc_musl.go`, `etc_musl.go`, `mem_brk_musl.go`, `mem_musl.go`, `memgrind_musl.go`, `pthread_musl.go`, `syscall_musl.go`, `aliases.go`, `atomic.go`, `atomic{32,64}.go`, `builtin{32,64}.go`, `libc_linux_statfs.go`.
2. **Hand-written (darwin, freebsd, netbsd, openbsd, illumos, windows, linux/mips64le)** — the libc surface is implemented by hand in Go, with the negated build constraint:
```
//go:build !(linux && (amd64 || arm64 || loong64 || ppc64le || s390x || riscv64 || 386 || arm))
```
Main files: `libc.go`, `libc_unix.go`, `libc_unix{1,2,3}.go`, `libc_<goos>.go`, `libc_<goos>_<goarch>.go`, `libc_windows*.go`, `pthread.go`, `mem.go`, `memgrind.go`, `mem_brk.go`. These ports also pull in an older set of ccgo/v3-generated `musl_<goos>_<goarch>.go` files for the platform-independent pieces (strtod, math, network, etc.).
When you make a change you almost always need to make it in both code paths. Look at the existing build tag of the file you're editing — if it has the long `linux && (amd64 || ...)` form, you're in the musl path, and there's a sibling file with the negated tag that needs the parallel change.
## Common commands
Build / sanity check:
- `go build ./...` — current platform only
- `make editor` — fast iteration: compile tests to /dev/null, build generator, lint generated asm
- `make build_all_targets` — full cross-compile sweep across all supported GOOS/GOARCH × build tags (slow; required before submitting per `CONTRIBUTING.md`)
- `make vet` — vet, filtering out known abi0 false positives
Tests:
- `make short-test` — `go test -short` plus log-grep summary
- `make test` — full test, 24h timeout
- `make xtest` — full test with `-tags=ccgo.dmesg,ccgo.assert` (verbose ccgo debugging)
- `make libc-test` — runs only `TestLibc`, which transpiles and runs the musl libc-test suite under `testdata/nsz.repo.hu/libc-test`
- `make xlibc` — `TestLibc` with debug tags
- `make membrk-test` — full test with `-tags=libc.membrk` (the sbrk-style debug allocator)
- Run one test: `go test -v -run TestStrtod -count=1`
- Filter `TestLibc` subtests: `go test -v -run TestLibc -re '<regexp>'` (the `-re` flag is defined in `all_musl_test.go`)
Regenerate musl-derived code:
- `make generate` — downloads the pinned musl tarball if needed, re-translates it via `go run generator.go` into `$DIR` (default `/tmp/libc`), then rebuilds and short-tests. **Only works on linux.** Output files (`ccgo_linux_*.go`, etc.) are committed to the repo and should not be hand-edited.
- `make dev` — same as `generate` but with `GO_GENERATE_DEV=1` and `-tags=ccgo.dmesg,ccgo.assert` for ccgo debugging
- Cross-arch generation: set `GO_GENERATE_GOARCH=arm64` etc. The `builder.json` `autogen` regex lists which arches CI auto-regenerates; recent commits like `pi32 auto generate` are these.
- Pinned musl version: `internal/archive/archive.go` (currently `musl-7ada6dde6f9dc6a2836c3d92c2f762d35fd229e0`).
## Build tags
Functional tags (passed via `-tags=`):
- `libc.membrk` — replaces malloc with a fixed-size sbrk-style allocator (1 GiB on 64-bit), `free` becomes a no-op, heap pre-filled with PRNG bytes. Used to surface use-after-free in downstream code.
- `libc.memgrind` — wraps the allocator with an audit table; `MemAuditStart` / `MemAuditReport` detect leaks. Adds overhead.
- `libc.dmesg` — appends a per-pid log to `/tmp/libc.log` of major libc events.
- `libc.strace` — flips `__ccgo_strace` to `true` so every `Xfoo` entry prints a trace line. Heavy.
- `libc.memexpvar` — exposes allocator stats through `expvar`.
- `ccgo.dmesg`, `ccgo.assert` — consumed by ccgo during generation, not at runtime.
`libc.membrk` and `libc.memgrind` are mutually exclusive (the file build tags enforce it).
## Symbol naming conventions
ccgo encodes C identifiers with prefixes; the same scheme is used in hand-written files for consistency:
- `Xfoo` — externally visible C function `foo` (e.g. `Xmalloc`, `Xputchar`)
- `Yfoo` — abi0-wrapped entry to `Xfoo` (linux/amd64 only, in `abi0_linux_amd64.go`)
- `Tfoo_t` — typedef'd C type `foo_t` (e.g. `Tsize_t`, `Tssize_t`)
- `Sfoo` — struct tag `foo`, `Ufoo` — union tag, `Ffield` — struct field
- `X__foo` / `X___foo` — C identifiers starting with `_` get folded; both `__errno_location` and `___errno_location` exist
- Lowercase `xfoo`, `_foo` — internal helpers
`capi_<goos>_<goarch>.go` lists every exported symbol — these are the source-of-truth files ccgo consults when linking against this libc. If you add a new `Xfoo`, add it to the relevant `capi_*.go` files too (the generators do this automatically for the musl path).
## TLS — thread-local state
A `*TLS` represents a C "thread". Every `Xfoo` takes one as the first argument. `TLS` is **not safe for concurrent use** — one goroutine per `TLS`.
- Inside an `Xmain`-style entry point: `Start(main)` creates the main TLS, locks the goroutine to the OS thread, and runs `main`.
- Library callers (e.g. sqlite): call `NewTLS()` per goroutine, `defer tls.Close()`. The first `NewTLS()` is the "main" thread and is *not* OS-thread-locked.
- Pthread support: `Xpthread_create` spawns a goroutine with its own TLS. The musl pthread path (`pthread_musl.go`) and the hand-written path (`pthread.go`) implement this separately.
- `tls_linux_amd64.{go,s}` — assembly stubs that let abi0-translated code reach `tls.Alloc` / `tls.Free` without going through Go calling conventions.
## Subpackages
The repo contains a constellation of subpackages under `errno/`, `fcntl/`, `pthread/`, `signal/`, `stdio/`, `stdlib/`, `sys/{types,socket,stat,vfs,random}`, `time/`, `unistd/`, `pwd/`, `grp/`, `netdb/`, `netinet/`, etc. They are thin: mostly typedefs and integer constants for use by ccgo-generated callers. They are not meant to be imported by general Go code.
`internal/archive` — declares the pinned musl version; `internal/autogen` and `internal/overlay` — supporting files for the generator.
## What is generated vs hand-written
Code generated (do not hand-edit; regenerate via `make generate`):
- `ccgo_linux_*.go` — the bulk of the musl translation, one per Linux arch
- `musl_<goos>_<goarch>.go` — older ccgo/v3 generation for non-Linux ports and some helpers
- `abi0_linux_amd64.{go,s}` — qbecc-generated abi0 wrappers
- `capi_*.go` — exported-symbol manifests (regenerated by ccgo)
Anything else (`libc.go`, `libc_musl.go`, `libc_<goos>.go`, `libc_unix*.go`, `mem*.go`, `pthread*.go`, `aliases.go`, etc.) is hand-written.
`generate.go` and `genheaders.go` are old (`//go:build ignore`) ccgo/v3 helpers, kept around but mostly superseded by `generator.go` (ccgo/v4).
## Debugging artifacts in the tree
Several large files in the repo root are debug logs / surface dumps (`log`, `log-test`, `log-generate`, `surface.old`, `surface.new`). They are tracked but stale; do not depend on their contents.