Commit Graph

8 Commits

Author SHA1 Message Date
Andrey Kumanyaev a9bf2f6fed Route every home-isolating test through the shared sandbox
Nine test files each rolled their own isolation, and every one of them
moved HOME alone. On Windows that left them pointed at the real profile:
the init suite merged hooks into the real ~/.codex/config.toml, the
instructions suite handed the real home to SyncGlobalSkills, which
prunes shipped skills out of ~/.claude/skills, and the platform suite
ran MigrateToUnifiedHome against the developer's real ~/.config/gortex.

The platform and config tests were not merely leaking either — they
assert Home() resolves to <temp>/.gortex, which cannot hold on Windows
while the home lookup ignores HOME. They fail there today.

No behaviour changes on Unix; the local clearXDG and isolateInitTestEnv
helpers give way to the shared ones so a tenth copy is not written next.
2026-08-08 17:31:19 +02:00
Tien Dung Dao 3714a07507 fix(windows): hide daemon background subprocesses 2026-07-19 21:36:34 +07:00
Andrey Kumanyaev 834dd487ff feat(daemon): standing soft memory limit and post-burst heap release
The daemon ran with no memory envelope: GOGC defaults, no GOMEMLIMIT, and
the only GC tuning scoped to the cold-index window. One allocation burst
(warmup passes, an hourly janitor tick, a whole-graph analysis) pinned the
process footprint at its peak indefinitely — observed at 16.2 GB on a
16 GiB machine, with the GC then burning 27-77% CPU at idle marking the
bloated heap.

Boot now installs a standing soft limit — GOMEMLIMIT respected verbatim
when set, else GORTEX_DAEMON_MEMLIMIT, else daemon.memory_limit from
config, else hostRAM/4 clamped to [1 GiB, 8 GiB] — and the four burst
boundaries (warmup complete, janitor ticks that did work, cold-index
window close, MCP whole-graph analysis) hand the high-water heap back to
the OS via a forced scavenge, logged with the freed byte count.
GORTEX_DAEMON_MEMRELEASE=0 disables the releases. The cold-index tuning
window captures and restores the standing limit, so the two compose.
2026-07-11 20:55:29 +02:00
Andrey Kumanyaev 032de8bdc3 feat(daemon): reclaim a mostly-dead store file with a guarded boot VACUUM
Row-shedding maintenance (orphan purges, the duplicate-collapse
migration, resolver cleanups) returns pages to SQLite's freelist, where
future writes reuse them — but only VACUUM returns them to the
filesystem, and nothing ever ran it: a live store pinned 4.4 GB of
freelist inside a 6.8 GB file. Boot now measures the freelist right
after the orphan purge and, when the dead fraction dominates (>50% of
pages AND >1 GiB reclaimable AND the volume has 1.5x the file size
available for VACUUM's transient copy), runs a one-time compaction
before the warmup loop starts writing — logged up front as
minutes-scale work, non-fatal on any failure, and skippable with
GORTEX_SKIP_STORE_COMPACT=1. Measured on a byte-copy of that live
store: 81 s to shrink 6.8 GB to 2.06 GB. A memory-mode daemon skips the
whole path via the capability probe; the disk-headroom check reads
statfs through a platform helper with a Windows counterpart.
2026-07-11 09:27:40 +02:00
Andrey Kumanyaev f396f7aece coarse daily-rollup aggregator with hard allow-list and value bucketing 2026-06-18 07:22:19 +02:00
Andrey Kumanyaev 431c0b290e feat(paths): unify per-user state under ~/.gortex
Gortex split its per-user state across three roots — config in
~/.config/gortex, cache in ~/.cache/gortex, and a flat ~/.gortex for the
store / models / memories. Collapse them into one tree:

  ~/.gortex/
  ├── config.yaml, servers.toml
  ├── cache/    (daemon socket/pid/log, snapshots, eval/token/… caches)
  ├── store/    (the on-disk backend + WAL/shm sidecars)
  ├── models/   (downloaded embedding models)
  └── memories/

The XDG variables stay an explicit escape hatch: an absolute
XDG_CONFIG_HOME / XDG_DATA_HOME / XDG_CACHE_HOME (and the GORTEX_DAEMON_*
overrides) still wins and routes that category to the standard
<base>/gortex location, so XDG-strict setups, sandboxes, and the test
suite are unaffected.

internal/platform/xdg.go is the single resolver: ConfigDir/DataDir
collapse to ~/.gortex, CacheDir/OSCacheDir to ~/.gortex/cache, and new
StoreDir / ModelsDir / MemoriesDir hang the durable sub-trees off
DataDir. The scattered callers route through it; the Legacy* aliases
are gone.

MigrateToUnifiedHome folds an older split layout into the new tree on
first run — best-effort, idempotent, rename-based, and a no-op under an
XDG override. It is wired into the root command's PersistentPreRun so it
lands before any command opens the store or reads config. Models are
treated as durable data (kept out of cache so a wipe doesn't drop large
downloads); the stale daemon socket/pid are left to regenerate.
2026-06-01 12:36:16 +02:00
Andrey Kumanyaev e94fafca8a platform: consolidate config/data/cache paths behind an XDG resolver
Add internal/platform/xdg.go exposing the three XDG base categories for
Gortex (config / data / cache), each honouring its XDG_*_HOME variable
when set to an absolute path and falling back to the historical Gortex
default when unset. A relative XDG_*_HOME value is ignored per the XDG
spec.

Route every scattered config/data/cache path computation through the
resolver: the global config path and viper search path, the snapshot
FileStore, the eval index cache, the token-count and wiki-enhance
caches, the savings store, the daemon state directory, the per-machine
server id, the saved-scope store, the global memories store, the daemon
servers file, the hook telemetry / session-state files, the embedding
model cache, and the eval quality/recall caches.

Back-compat: when the relevant XDG variable is unset each subsystem
resolves to exactly the location it used before, so existing installs
are not orphaned. Subsystems that historically rooted their cache at
os.UserCacheDir() (savings, server id, scopes, bench) keep that root as
the unset fallback; subsystems on the legacy ~/.gortex directory keep
that as their unset fallback. Only an explicitly set XDG variable moves
data, and it is now honoured consistently on every platform.
2026-05-22 14:27:20 +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