16 Commits

Author SHA1 Message Date
Andrey Kumanyaev 9449485dcf release: fix the homebrew cask so it loads at all
The generated cask used `pre_install` / `post_install`. Those are formula
DSL methods; a cask has no such stanzas, so brew rejected the file at load
time with

  Error: Cask 'gortex' definition is invalid: undefined method 'pre_install'

Every brew command that touches the cask parses it, so `brew install` and
`brew upgrade` both failed for every macOS user on both arches, starting
with v0.63.7. Closes #639.

Two further defects made a straight rename insufficient:

  * The cask DSL's `system_command` is `SystemCommand.run!`, which raises on
    a non-zero exit. `gortex daemon status` exits 1 exactly when no daemon
    is reachable, so `next unless status.success?` could never run — brew
    would have aborted the install outright on any machine without a live
    daemon. The probe now passes `must_succeed: false`.

  * `preflight` was the wrong hook for stopping the daemon. On upgrade brew
    unlinks the old cask's binary (`start_upgrade` -> `uninstall_artifacts`)
    before installing the new cask's artifacts, so by the time a preflight
    block runs there is no gortex on disk to ask. The stop half could never
    fire on the path it was written for.

`postflight` handles both halves instead: after the new binary is linked,
probe for a daemon and, only if one answers, `daemon restart` — which stops
the old process (blocking until it exits, releasing the store lock) before
starting the new one, so a store migration still runs alone. A fresh install
and CI have no daemon answering and skip it.

The cask body moves out of the release.yml heredoc into
.github/homebrew/gortex.rb.tmpl, rendered by scripts/render-cask.sh. That
makes it reviewable as Ruby, removes the shell-expansion hazards of an
unquoted heredoc, and — the point — lets a real brew load it before
publication. The renderer also refuses a malformed sha256, a version with a
leading "v", or a placeholder that survived substitution. Rendered output is
byte-identical to the published cask apart from the hook block.

Nothing could have caught this: the file was valid Ruby, valid YAML, and the
tap has no CI, so the first machine to evaluate the cask was a user's.
scripts/validate-cask.sh renders the template with dummy values and loads it
through a real brew. It runs on every PR that touches the cask
(.github/workflows/homebrew-cask.yml) and again in build-darwin as the last
gate before the release job pushes to the tap. Both are macOS-only —
Homebrew on Linux cannot load casks. Verified by reintroducing `pre_install`
in the template: the validator fails with the exact error users reported.
2026-08-20 21:16:46 +02:00
Andrey Kumanyaev 1f7bf6ea48 release: link linux binaries statically so they run on any distro
The linux release was dynamically linked despite the README promising a
single static binary with no dependency chain. goreleaser-cross:v1.26 is
Ubuntu 24.04 / GCC 13.3, so the artifacts carried that host's floor —
GLIBCXX_3.4.32 and GLIBC_2.34 — and refused to start anywhere older:

  gortex: /lib/x86_64-linux-gnu/libstdc++.so.6:
          version `GLIBCXX_3.4.32' not found (required by gortex)

Debian 12 caps at GLIBCXX_3.4.30 and Ubuntu 22.04 at 3.4.29, so in practice
the binary only ran on Ubuntu 24.04+/Debian 13+. libstdc++ is in the link at
all because some tree-sitter grammars ship C++ external scanners. Windows
already linked -static; only linux was left dynamic.

Link -static with netgo, osusergo and static_link, which between them remove
every dlopen the binary would otherwise perform at runtime.

verify-static-elf.sh asserts no DT_NEEDED, no PT_INTERP and no symbol-version
requirements. It runs as a goreleaser build post-hook rather than a workflow
step because `goreleaser release` builds and publishes in the same run — a
check after it would only ever be a post-mortem on an already-published
artifact. The release job re-asserts it on the packaged tarballs and then
proves it by execution on debian:11 and alpine.
2026-07-26 17:23:21 +02:00
Andrey Kumanyaev d6880f4915 fix(release): build macOS binaries on a native runner so they load on macOS 15+
The 0.52.2 cask aborted at load on macOS Sequoia/Tahoe with
"__DATA_CONST segment missing SG_READ_ONLY flag" (#176). darwin was
cross-compiled inside goreleaser-cross, whose osxcross ld64 omits the
SG_READ_ONLY flag on the __DATA_CONST segment that the macOS 15+ dyld now
enforces. Apple's ld sets it, so locally built binaries always worked and
the bug only surfaced in the released artifact.

Build darwin on a native macos-15 runner instead:
- new build-darwin job links arm64 natively + amd64 via `clang -arch
  x86_64`, codesigns with rcodesign, smoke-tests the segment flag, and
  runs `gortex version` on the enforcing dyld before handing off archives.
- the release job now builds linux only, merges the darwin tarballs,
  notarizes, appends them to checksums.txt, signs, and uploads.

goreleaser's prebuilt builder is Pro-only, so the homebrew cask (which
references all four os/arch tarballs) is assembled and pushed to the tap
from the release job once every platform's hash exists, instead of by
goreleaser. Completions are still generated at brew-install time.

scripts/verify-macho-readonly.sh is the guard: it fails the release if a
darwin binary ships without SG_READ_ONLY, so this can never regress.
2026-06-27 10:25:19 +02:00
Andrey Kumanyaev b4e5059289 savings: cover OpenAI, Gemini and DeepSeek pricing; refresh model table
Extend the built-in cost-avoided table beyond Anthropic so the dashboard
prices real usage for every provider gortex's LLM features talk to: add
the current OpenAI (GPT-5.x, GPT-4.1, o3/o4-mini), Google Gemini (3.x and
2.5) and DeepSeek models. Replace the unreachable claude-fable-5 with the
live claude-mythos-preview flagship. Refresh the pricing tests, the
landing-page generator's cost_avoided_usd keys, and the savings doc to
the new model ids.
2026-06-16 00:52:56 +02:00
Andrey Kumanyaev 10344e8657 docs: savings ledger lives in the sidecar database
Actualise the savings docs for the sidecar-backed ledger: where it
lives, the transactional durability story, the legacy flat-file import,
and the real recording surface (the read family records too, and the
per-call value is server-side accounting, not a response field).
2026-06-12 00:26:30 +02:00
Andrey Kumanyaev 963afe4242 build(release): statically link the windows .exe, drop DLL bundling
The windows release used to ship gortex.exe plus the mingw C/C++ runtime
DLLs (libstdc++-6 / libgcc_s_seh-1 / libwinpthread-1) it linked
dynamically — the C++ stdlib is pulled in because some tree-sitter
grammars carry C++ external scanners (e.g. go-sitter-forest norg). Link
them statically via -extldflags=-static so the .exe is a single
self-contained binary, and replace the DLL-staging step (the brittle
find_dll scan) with an objdump guard that fails the release if any mingw
runtime import leaks through.

The zip stays — install.ps1, checksums.txt, cosign signing, and
windows/unix artifact parity are all built around it, and it compresses
the large CGo binary — but it now contains only gortex.exe. install.ps1
drops the multi-file / DLL-count install path accordingly.
2026-06-01 11:45:15 +02:00
Andrey Kumanyaev 6166fea3c8 chore(build): remove liblbug fetch/link machinery
The ladybug/Kuzu backend was removed; its build/CI scaffolding is now
dead. Delete scripts/fetch-lbug.sh and drop the liblbug-specific pieces
from Makefile, the GitHub Actions workflows, .goreleaser.yml, .gitignore,
and install.ps1: the fetch steps, the -Wl,--whole-archive /
CGO_LDFLAGS_ALLOW allowlist, and the windows lbug_shared.dll bundling.

Generic CGo (CGO_ENABLED=1 + the C/C++ toolchain) is preserved
everywhere because tree-sitter still needs it. go build ./... is green
with no fetch step.
2026-06-01 10:23:30 +02:00
Andrey Kumanyaev 39e9e43dd2 fix(install): windows one-line installer ships the runtime DLLs
The windows release is now a zip containing gortex.exe + lbug_shared.dll
+ the mingw and VC++ runtime DLLs (gortex links liblbug dynamically on
windows). install.ps1 moved only gortex.exe into the install dir, so the
installed binary couldn't start (missing DLLs). It now installs the whole
archive — exe + DLLs together — since windows resolves DLLs from the
executable's own directory.

The windows zip is built by the separate native-windows release job, so
it isn't in goreleaser's checksums.txt and install.ps1 was silently
skipping SHA-256 verification on windows. The windows job now appends the
zip's sha256 to the release checksums.txt, restoring verification.

install.sh (unix) is unchanged — static linking keeps the tar.gz a single
self-contained binary.
2026-05-29 19:29:29 +02:00
Andrey Kumanyaev c0fd7e1812 build(release): fetch liblbug at build time; static unix, dynamic windows
liblbug native libs are no longer committed — scripts/fetch-lbug.sh
fetches them (pinned LBUG_VERSION=0.17.0) for make / CI / release:
- linux + darwin: STATIC (liblbug.a linked in -> self-contained binary;
  libstdc++ forced static via -Wl,-Bstatic so the binary carries no
  runtime libstdc++.so dependency).
- windows: DYNAMIC — lbug's windows build is MSVC and can't be
  static-linked from mingw; the .exe links lbug_shared.dll directly
  (-l:lbug_shared.dll) and ships the DLL + mingw and VC++ runtime
  alongside.

cgo_shared.go now points at lib/static/<os>-<arch>/ (unix) and
lib/dynamic/windows/ (windows). The committed darwin dylib and the old
download_lbug.sh are removed; .gitignore ignores the fetched lib tree.

CI: every job that builds cmd/gortex or runs go test ./... fetches
liblbug first (ci.yml test/build-windows/build-onnx, init-smoke), so the
link is validated natively on all three OSes.

Release: .goreleaser.yml builds the unix targets only (static); a new
native-windows job in release.yml builds the dynamic .exe, bundles the
runtime DLLs (hard-failing if any is missing), zips, cosign-signs and
appends to the release. Scoop manifest is a follow-up (windows is no
longer a goreleaser artifact).

Validated on darwin: static build is self-contained (no liblbug runtime
dep) and the store_ladybug suite passes against the static lib. Linux and
windows links are validated by CI on their native runners.
2026-05-29 19:24:30 +02:00
Andrey Kumanyaev 4fb7ba1e35 windows: add native Windows support
Gortex now builds and runs on windows/amd64.

- internal/platform isolates OS-specific runtime primitives — shutdown
  signals, process liveness/termination, and detached-spawn attributes
  — behind unix/windows files. The daemon, CLI, and servers call
  through it instead of using syscall directly.
- internal/daemon: a Windows fdlimit stub, daemon state relocated to
  %LocalAppData%\gortex, and the AF_UNIX socket transport reused as-is
  (supported on Windows 10 1803+).
- .goreleaser.yml builds a windows/amd64 zip archive and a Scoop
  manifest; Makefile gains build-windows; release.yml signs, hashes,
  and scans the zip alongside the other artifacts.
- scripts/install.ps1 is a PowerShell installer; install.sh now points
  native-Windows users at it.
- CI builds every package for windows and parse-checks install.ps1.
- internal/thirdparty/renameio vendors github.com/google/renameio with
  an added Windows implementation — upstream v1.0.1 is Unix-only and
  blocked the build through the github.com/coder/hnsw dependency.

daemon install-service stays unsupported on Windows; users run
gortex daemon start --detach instead.
2026-05-21 08:31:11 +02:00
Andrey Kumanyaev 4469c036e3 audit + landing: gortex audit --badge SVG shield + per-tool savings landing page
Three small marketing artifacts that ride on substrate already
shipped:

cmd/gortex/audit.go

  New `gortex audit` top-level command. Indexes the target repo
  (default `.`), computes per-symbol complexity-axis health score
  (fan-in × 2 + fan-out × 1.5 with the same arithmetic shape as
  the `analyze kind=health_score` MCP analyzer's complexity
  component), averages across callable symbols, maps to A-F
  grade.

  Three output modes:
    --format svg   (default) shields.io-style SVG, default at
                   .gortex/badge.svg. Embed in README via
                   ![gortex audit](.gortex/badge.svg). Stdout also
                   prints the paste-ready markdown snippet.
    --format json  structured report: symbol count, mean score,
                   grade, per-grade counts, top-5 worst symbols.
    --format text  one-line "<grade> · <score>" for CLI use.

  10 tests cover the math: grade boundary checks (39.99→F /
  84.99→B / 85.01→A), grade-count sum invariant, non-callable
  kinds skipped, badge SVG validity per grade, colour mapping,
  JSON round-trip.

  Smoke run on the gortex repo: 9,181 callable symbols · mean
  complexity-health 62.3 · grade C.

scripts/landing/per-tool-savings.sh + docs/landing-pages/per-tool-savings.md

  Regenerator script + published landing-page tables sourced from
  the existing cumulative savings store (`gortex savings --verbose
  --json`). Three sections:

    1. Headline totals: source-reading calls, tokens saved,
       efficiency ratio, USD avoided across all 5 priced models.
    2. By language: per-language breakdown sorted by tokens
       saved.
    3. By repository: per-repo breakdown sorted by tokens saved.
    4. By MCP tool: populated once the JSONL event log accumulates
       rows (the JSONL surface landed 2026-05-18; stores predating
       that don't yet have per-tool data). Section emits a clean
       placeholder + re-run note when empty.

  Re-run protocol: `bash scripts/landing/per-tool-savings.sh`.
  Honest about scope: bails clean when the store is empty
  ("use gortex via MCP for a while, then re-run"); never pads
  with synthetic numbers.

  Initial run on the operator's machine: 1,926 calls · 11.5M
  tokens saved · ≈$172.50 avoided at claude-opus-4 input pricing
  across 9 languages and 12 repos.

ROADMAP.md (untracked local working doc)

  Adds a serena-focused scorecard sub-table (11 categories where
  it actually contests Gortex; the main 4-column matrix stays
  unchanged) and a "Phase H reframe" section that re-aims the
  agent-ergonomics narrative against serena's adoption + IDE-
  polish strengths via the gap-analysis paths already on the
  roadmap (C8 npm wrapper, D5 JetBrains plugin, N44 sub-agent
  installer).

Full repo: 4666 / 125 packages green (+10 new tests). go vet +
golangci-lint clean.
2026-05-19 00:29:40 +02:00
Andrey Kumanyaev ff327fa645 add mac release sign 2026-05-07 13:45:48 +02:00
Andrey Kumanyaev 05103e64f6 bench on request, not always 2026-04-27 22:54:42 +02:00
Andrey Kumanyaev 710cba5573 Fix install script and update readme 2026-04-25 21:25:01 +02:00
Andrey Kumanyaev d7652f9683 single line installer 2026-04-25 20:51:47 +02:00
Andrey Kumanyaev d4eba9e89c Add semantic search with multi-tier embedding and RRF fusion
Hybrid BM25 + vector search using Reciprocal Rank Fusion. Four embedding
  tiers: built-in GloVe word vectors (20k words, 50d, always available),
  API provider (Ollama/OpenAI), ONNX backend (GTE-small 384d via
  onnxruntime, build tag embeddings_onnx), and Hugot/GoMLX backends
  (MiniLM via pure Go or XLA, build tags embeddings_hugot/embeddings_gomlx).
  Pure Go HNSW index via coder/hnsw. Pluggable Provider interface with
  NewLocalProvider dispatcher. CLI flags --embeddings, --embeddings-url,
  --embeddings-model on serve and bridge commands. Makefile targets for
  build variants and dependency setup.
2026-04-10 01:27:12 +02:00