Repository navigation
Releases: ProjAnvil/LadyM
Release list
v0.8.1 — Hotfix: .ladyM Project-Local Default DB & ladym init
Highlights
A small but layout-defining hotfix on top of 0.8.0: the personal edition's default SQLite database moves from a flat ./ladym.db in your project root into a dedicated .ladyM/ directory, and a new ladym init command makes the setup explicit and reversible.
- New default:
.ladyM/ladym.db. One dot-directory now holds the db and all its sidecar files (-wal,-shm,.index.lock), keeping the project root clean — the same convention as.wrangler/state,.expo/, and friends. One.gitignoreline (.ladyM/) covers everything, so forgotten-walentries can no longer leak into commits. ladym init. Creates.ladyM/ladym.db(idempotent schema bootstrap), migrates a legacy flat./ladym.db— db plus-wal/-shmsidecars — into.ladyM/, and appends the two-line ignore block to.gitignorewhen one exists (or creates it in a git repo; prints a hint otherwise). Re-running is always safe.- Zero-breakage fallback. If a legacy flat
./ladym.dbexists, it keeps being read — existing memories never vanish behind the new default. Migration happens only when you ask for it (ladym init). Explicit paths (--db,LADYM_DB, tomldb_path) are untouched:initwith an explicit path only bootstraps the schema. - Hook synergy. Hook events land in the per-project
.ladyM/ladym.db(the hook process inherits the harness cwd), so silent capture from 0.8.0 now stays out of version control by default.
Compatibility
- No schema changes; no config format changes. All explicit db-path configuration (
--db,LADYM_DB,ladym.tomldb_path) behaves exactly as before. - Existing flat
./ladym.dblayouts keep working via the read fallback until migrated withladym init(stopserve/workerbefore migrating). - Case note: the directory is spelled
.ladyM(capital M), matching the existing~/.ladyMhome layout.
Installation
Prebuilt binaries for linux/darwin (amd64/arm64) — personal, personal-fulldict, and enterprise flavours — are attached below with SHA256SUMS. Or build from source:
go build -o bin/ladym ./cmd/ladymThen, in your project:
ladym initv0.8.0 — Silent Hook Capture & Plugin Market
Highlights
This release gives LadyM a silent capture path: Claude Code and Codex now feed memory automatically through their lifecycle hooks, without the agent spending a single token or knowing it is happening. Until now every memory write required the agent to choose to call a tool (remember / record_event); starting with 0.8.0, the harness itself records sessions — closing the biggest gap identified in our comparison with ai-memory: a memory system is only as good as its feed.
ladym hook— the hook carrier. One subcommand serves both harnesses: it reads the event JSON from stdin, maps it onto a structured L1 episode through therecord_eventpipeline (controlled-vocabulary action classes, resource extraction fromtool_input, deterministicoperates_onedges), writes it, and exits. Observer semantics throughout: stdout stays empty, unknown events and unknown fields are tolerated (schema drift never breaks the binary), and the exit code is never 2 — it can never block or feed decisions back into the harness.ladym hook install/uninstall. One command merges the observer entries into~/.claude/settings.jsonand~/.codex/hooks.json. User entries and non-hook keys survive verbatim, installs are idempotent (prefix-matched), a one-time.ladym-bakbackup is taken before the first write, and corrupt config files are refused rather than overwritten. Uninstall removes exactly our entries and nothing else.- Plugin market.
plugins/ladym(Claude Code plugin: hooks + MCP server) andplugins/ladym-codex(Codex plugin) ship the same wiring as installable plugins, catalogued under theladym-pluginsmarketplace in this repository. Plugins carry no binaries — every command points at theladymon your PATH, so the binary remains the single source of truth. - Zero-config db placement. Hook events default to a per-project
ladym.db(the hook process inherits the harness cwd), matching the workspace inference (event cwd's directory name). SetLADYM_DBfor a unified library — the workspace then becomes the isolation key. Changing the db never requires reinstalling hooks.
What's Changed
Silent Hook Capture
hookpackage — tolerant parsing of the shared Claude Code / Codex hook event shape (unknown fields ignored), workspace inference (WorkspaceFromCwd), tool-name → action-class mapping onto the canonical 31-word vocabulary (MapToolActionClass; MCP tools and unknown names stay raw for the worker's LLM backfill), andToOperationfor the V1 event set:SessionStart(create),SessionEnd,UserPromptSubmit(prompt observation, bounded at 2000 runes),PostToolUse/PostToolUseFailure(outcomesuccess/fail, file-path resources fromtool_input, tool response bounded at 500 runes), andStop.ladym hookCLI — pipes stdin through the mapping intoEngine.Scope(workspace).RecordOperation. Integration tests prove the full chain: event JSON → episode in the db →operates_onedge → retrievable vialadym recall-ops --resource …. The--harnessflag (written by the installer) lands in theAgentfield, since the two harnesses' event JSON is identical.
Installer
- Merge, never overwrite. The installer reads the whole config document and writes it back — keys like
modelinsettings.jsonsurvive. Entries are recognised as ours by theladym hookcommand prefix, so--harnessdifferences and future flag changes stay idempotent. - Safety rails. One-time
.ladym-bakbackup (never rolled over), parent directories auto-created, corrupt JSON refused with a clear error, uninstall is a no-op when the file is absent, and a file that held nothing but our hooks is removed entirely. - Post-install guidance. Claude Code: restart your session. Codex: run
/hooksto complete the trust review (Codex binds trust to the hook definition hash). A warning is printed whenladymis not onPATH.
Plugins & Marketplace
plugins/ladym/—.claude-plugin/plugin.jsonmanifest, six-eventhooks/hooks.json(including the Claude Code-onlyPostToolUseFailure), and.mcp.jsonregisteringladym serveas the plugin's MCP server.plugins/ladym-codex/—.codex-plugin/plugin.jsonmanifest (explicithooks/mcpServerspointers), five-eventhooks/hooks.jsonwith 10-second timeouts.plugins/.claude-plugin/marketplace.json— theladym-pluginscatalog. Add it from the/pluginbrowser or validate locally withclaude plugin validate plugins/.- Five static-validation tests pin the event sets, command strings, manifests, and MCP configs, so the plugin files cannot drift from the installer.
Documentation
docs/hooks.md— the personal-edition install guide: installation for both harnesses, db placement (per-project default vsLADYM_DBunified library), workspace inference, the event → memory mapping table, verification viarecall-ops, plugin installation, troubleshooting, and the honest known-tradeoffs section.docs/research/— the two research notes behind this release: the ai-memory-vs-LadyM comparison and the hook-carrier selection (Go binary over Python/sh, with the verified hook mechanics of both harnesses).- README (en/zh) and ARCHITECTURE.md updated with the new front-end and project layout.
Compatibility
- No schema changes, no config breaking changes. Existing MCP tools, CLI commands, and SDK surfaces are untouched;
record/rememberkeep their exact 0.7 behaviour (locked by regression tests). - The new capture path is opt-in: nothing is recorded until you run
ladym hook installor install a plugin. - Enterprise edition is unaffected — capture is a personal-edition concern (the enterprise edition is the memory database; clients feed it).
Known Limitations
- No capture-side sanitization yet. Prompts and tool outputs land as captured; a db is a local file, so the exposure surface equals your disk. Path exclusion and secret redaction are planned for the next release — tracked in
docs/hooks.md. - V1 event set only.
PreToolUse,PreCompact, and notification events are not captured (deliberate: no double-writes, bounded L1 growth). Unknown events are tolerated silently and can be added later without breaking installed hooks. - Codex plugin manifest follows the documented
.codex-plugin/plugin.jsonshape as of this release; the plugin systems of both harnesses are still evolving quickly, so the plugin files are intentionally thin (one manifest + one hooks file each).
Installation
Prebuilt binaries for linux/darwin (amd64/arm64) — personal, personal-fulldict, and enterprise flavours — are attached below with SHA256SUMS. Or build from source:
go build -o bin/ladym ./cmd/ladymThen:
ladym hook install --claude # or --codex, or --allFull guide: docs/hooks.md.
v0.7.0 — Operation-History Retrieval & Self-Maintaining L4 Graph
Highlights
This release gives agents a first-class operation-history memory: recording what was done to which resource, and retrieving it back by resource and action instead of free-text similarity. It also turns the L4 associative graph from a passive index into a self-maintaining structure — deterministic projections at write time plus a budgeted maintenance step in the System 2 worker.
- Operation-history retrieval (
recall_ops). A resource × action pivot query answering "how did I last operate on X?". Vector search is confined to resource resolution; an L4operates_ongraph join does the exact filtering; ACT-R activation ranks the results. The read path is LLM-free, and unresolvable resources degrade gracefully to plainrecall. - Structured
record_eventslots. Optionalresourcesandaction_classarguments resolve against a resource registry (L2type=resource, lazily-grown aliases) and linkoperates_onedges deterministically at write time. - Self-maintaining L4 graph. Write-time deterministic projections (
operates_on,produced_from,calls/importsfromcode_refs— all idempotent viaProjectedEdgeIDupserts) plus a newMaintainL4System 2 step: dangling-edge GC every cycle, budgeted slot backfill, gated semantic linking, and resource alias-merge. - Re-index hygiene. Re-indexing a changed file purges its stale symbol memories,
code_symbols/code_refsrows and in-process vector entries first — removed symbols no longer linger. - Documentation matched to code. Architecture claims that ran ahead of the implementation are now accurate, including an honest scoping note: code-ref projection covers same-file call/import relations today; cross-file extraction is future work.
What's Changed
Operation-History Retrieval
recall_ops— new engine query (Scope.RecallOperations/Engine.RecallOperations) with a three-stage pipeline: Stage 1 resolves the resource (exact alias match → vector nearest-neighbour overtype=resourcememories at a read-side threshold of 0.75, below the write-side 0.85); Stage 2 joins L4operates_onedges and filters by normalised action, time window and outcome; Stage 3 ranks with ACT-R activation. Exposed as the 10th MCP tool (recall_ops), a CLI command (ladym recall-ops --resource … --action … --outcome …), and Go SDK one-shot helpers (ladym.RecordOperation/ladym.RecallOperations).- Fallback semantics. Unknown resources never error the caller: the query degrades to a plain
recall(resource + " " + action)and the response is flaggedfallback=true. Cold-start (no resource entities at all) behaves identically.
Structured Event Recording
record_eventaccepts optionalresources(names or aliases) andaction_class. Each resource resolves through the registry — reusing an existing entity, growing its alias list via a vector match, or creating a new one — and the episode gets a deterministicoperates_onedge per resource (ProjectedEdgeID, idempotent upsert). Omitting the new fields reproduces the legacy behaviour byte-for-byte (locked by regression tests).- Action vocabulary.
action_classnormalises against a controlled vocabulary — 31 canonical words across knowledge/code/ops/communication domains plus built-in aliases (run→execute,rm→delete,grep→search, …). Exact match only: unknown actions are preserved asaction_rawfor the worker to backfill, never guessed. Extend via the[resource]config section (actions,action_aliases).
L4 Graph Maintenance
- Write-time deterministic projections.
operates_on(episode/fact → resource) fromrecord_event;produced_from(fact → source episode) plusoperates_oninheritance from consolidation ADD/UPDATE;calls/imports(symbol → symbol) projected fromcode_refsat index time. All machine edges useProjectedEdgeID(proj:+ truncated SHA-256 of src|relation|dst) so re-running a projection upserts instead of duplicating. MaintainL4worker step (System 2 cycle, after Decay):- Dangling-edge GC runs every cycle as correctness hygiene (defence-in-depth for pre-FK databases and external writers; current schema already cascades).
- Slot backfill — heuristic exact-match stamping of
action_classplus optional LLM extraction of resources/actions for episodes recorded before this release (l4_backfillop). - Semantic linking — gated (config flag, LLM availability, minimum recent episodes) same-(layer, action_class)-bucket candidate pairs, similarity-prefiltered and budgeted per cycle (
l4_linkop). - Alias merge — high-similarity resource pairs confirmed by the LLM (
l4_alias_mergeop) merge into one entity: aliases unioned, incomingoperates_onedges re-pointed, superseded entity retired via the standardsupersedeschain.
- Three new agent ops registered in
NAMED_OPS(l4_backfill,l4_link,l4_alias_merge) — each independently configurable via[agents], each fully optional (no LLM configured ⇒ the steps skip cleanly).
Correctness & Storage
NeighborCountsendpoint filtering — neighbour centrality no longer counts edges whose endpoint memory is gone (EXISTS join on both endpoints, both backends).SweepDanglingEdges()— newStoremethod deleting valid edges with missing endpoints, wired into every System 2 cycle.DeleteCodeArtifactsByFile()— newStoremethod for re-index hygiene: removes a file'scode_refs(via subquery, ordered beforecode_symbols),code_symbolsrows, and symbol memories, and keeps the SQLite in-process vector index in sync.- Consolidation provenance — ADD/UPDATE now project
produced_fromand inheritoperates_ontargets onto the new fact. A dead Python-parity branch in the offline classifier (superseded_by == candidateHash, comparing a UUID against a content hash — never true) was removed; replay protection is carried by the content-hash equality check, locked by a regression test.
Documentation
- ARCHITECTURE.md: L1 row documents the resource × action slots; L4 row replaced the aspirational "auto-link on write" with the actual write-time projections + worker maintenance; the storage layout lists all edge relations; new §3b documents the
recall_opspipeline; the MCP front-end lists ten tools. - README (en + zh-CN): new "What's New in 0.7.0" sections,
recall_opsusage for MCP and CLI,[resource]/[maintain]configuration reference.
Testing & Quality
- Coverage (new code on this branch): operations 94.6%, engine 96.5%, code 95.4%; eleven functions initially under 80% were driven to 100% with edge-case suites (+1,240 lines of tests, zero production-code changes); storage reaches 97%+ with the Postgres suite live (
make test-pg). - New suites are scenario-named across the stack:
neighbor_counts_join_test.go,sweep_dangling_test.go,record_operation_test.go,consolidate_provenance_test.go,delete_code_artifacts_test.go,indexer_projection_test.go,recall_operations_test.go,maintain_test.go,maintain_cycle_test.go, and per-file coverage suites. go vetclean on both the default andenterprisebuild configurations; fixture-dependent test files carry//go:build !enterprisetags.
Full Changelog: v0.6.0...v0.7.0
v0.6.0 — Concurrency, High Availability, Observability & Multi-Language SDKs
Highlights
This release removes the last single-threaded bottleneck in the HTTP data plane, makes multi-replica System 2 worker deployments safe, adds first-class Prometheus observability, and ships official Python and TypeScript SDKs alongside the Go client.
- Concurrent HTTP data plane. The global request mutex that serialized every engine call is gone. Requests across workspaces now run fully in parallel; writes serialize only at the storage backend (SQLite WAL single-writer; Postgres fully parallel).
- Multi-replica System 2 workers. Cycle-level leader election (Postgres advisory lock / SQLite flock) lets you run standby workers for failover without duplicate consolidation cycles.
- Prometheus metrics. A native
/metricsendpoint backed byprometheus/client_golang, plus a--metrics-addrflag that exposes metrics from the worker role. - Python & TypeScript SDKs. Zero-runtime-dependency clients for the HTTP data plane, feature-parity with the Go client.
- Test coverage raised to 97.9% (Postgres mode), with scenario-named suites across every package.
What's Changed
Performance & Concurrency
engine.Scope— a zero-I/O, workspace-bound engine view that shares Store/Provider/LLM-agent caches. Per-request state mutation (withWorkspace) is eliminated; the two write endpoints route through scopes. Non-default workspaces get isolated L0 buffers viasync.Map.Handler.muremoved — all 11 lock sites deleted from the API layer. Concurrency is now guarded by fine-grained component locks: the engine's agent-cache mutex, per-workspace working-memory mutexes, and a newRWMutexon the previously unlockedInMemoryVectorIndex.- langgraph retain node no longer constructs a short-lived engine (and store connection) per request — it uses
Scopeinstead. - A 32-goroutine × 4-workspace mixed-workload test verifies isolation and runs clean under
-race.
High Availability
Store.TryAcquireWorkerLock()— new cross-process mutual exclusion for System 2 cycles, mirroring the existing index-lock design: session-scoped Postgres advisory lock (key727276) and SQLiteflock(<db>.worker.lock). Both release automatically on process/session death.- Worker loop and
engine.StartSystem2acquire the lock per cycle: a held lock skips the cycle (standby, not a failure); a crashed replica's work is picked up by any survivor on the next cycle.deploy.replicas: 2+is now safe for the worker role.
Observability
GET /metrics(auth-exempt, outside/api/) serves a Prometheus text exposition viaclient_golang:ladym_http_requests_total{endpoint,status},ladym_http_request_duration_secondshistogram,ladym_http_requests_in_flight,ladym_system2_cycles_total{result},ladym_go_goroutines. Endpoint labels use route patterns, so id-addressed paths cannot explode cardinality; pre-routing rejections (401s) count underendpoint="unknown".ladym worker --metrics-addr :9090serves/metrics+/healthzfrom the worker role.- The existing
/api/metricsJSON shape is unchanged and now reads from the same registry.
SDKs
sdk/python(ladym-client, uv, stdlib-only):remember/recall/record_event/consolidate/stats/link/forget+ memories CRUD,LadymErrorwith HTTP status, injectable transport, 100% statement coverage.sdk/typescript(ladym-client, zero runtime deps, Node ≥ 20 / browsers): camelCase API surface with injectablefetch,AbortSignaltimeouts, 100% line coverage.- Both ship unit suites plus a gated integration leg (
LADYM_SDK_IT=1) that buildsladym, serves a throwaway SQLite instance, and runs the full round-trip.
Testing & Quality
- Coverage: 97.9% in Postgres mode (
make test-pg), up from 95.2%; engine 100%, api 99.6%, cli 98.9%, storage 98.2% (PG),cmd/ladymconsole0→100% on both editions. New suites are scenario-named (e.g.worker_lock_failover_test.go,cjk_dict_global_state_test.go). - Fixed a vector-index delete test whose branch coverage depended on map iteration order, and floored the read-path p95 baseline so the scaling budget is stable on loaded CI runners.
Breaking Changes
None. All public APIs (engine, api, MCP tools, CLI) are backward-compatible; Engine.Remember/RecordEvent signatures are unchanged.
Behavioral notes
/api/metricsendpoint keys are now route patterns (/api/memories/{id}) instead of raw paths, preventing unbounded growth of the JSON map.- The
/metricsresponse Content-Type carriesescaping=underscores(client_golang 1.24 behavior).
Upgrade Guide
- Docker / Compose: pulling the v0.6.0 image is sufficient; no configuration migration. To run standby workers, raise the worker service's replica count — cycles are mutually exclusive automatically.
- Prometheus: add a scrape job per api replica and per worker (
--metrics-addr); see docs/deployment.md §4. - Go library users: no code changes required;
engine.Scopeis additive. - Postgres-backed coverage runs:
make test-pgwithLADYM_TEST_PG_DSNpointing at a pgvector instance.
Dependencies
- Added:
github.com/prometheus/client_golang v1.24.1(plus standard transitive deps). - Runtime dependencies of the SDKs: none.
Full Changelog: v0.5.4...v0.6.0
v0.5.4 — Dependency Hotfix: langchain-golang v0.7.0
What's Changed
Dependency hotfix release — no behavior changes in LadyM itself.
langchain-golang v0.6.3 → v0.7.0
Audited every behavior/breaking change across v0.6.4, v0.6.5, and v0.7.0 against LadyM's usage surface (core/language, core/messages, core/modelconfig, core/schema, core/embeddings, core/tools, partners/openai|anthropic|ollama, langgraph/graph node funcs, langgraph/runtime):
DrawASCII/DrawMermaidoutput format change — not usedCreateAgent/ToolStrategy.HandleErrors/recursion-limit changes — not usedDefaultRetryOnretries every error — LadyM compiles no graphs with retry policies; unaffected- Subgraph checkpoint namespaces per-task — no checkpoint savers used; unaffected
- nil-
DecideHITL interrupt mode, minted AI-message ids — agents middleware not used - Anthropic terminal usage-only stream chunk — no stream consumers; unaffected
runnables.Funcchild config (RunID) — not used- Benefit: openai Chat Completions now honors
InvokeStructured/WithStructuredOutputresponse_format — fixes a silent gap on LadyM's structured-output path
Other direct dependency bumps
github.com/jackc/pgx/v5v5.10.0 → v5.11.0github.com/odvcencio/gotreesitterv0.49.0 → v0.52.0golang.org/x/cryptov0.55.0 → v0.57.0golang.org/x/sysv0.47.0 → v0.48.0modernc.org/sqlitev1.56.0 → v1.58.0
Full test suite green (go build ./..., go test ./...).
Full Changelog: v0.5.3...v0.5.4
v0.5.3
Hotfix Release
New: Hermes Agent memory provider plugin (integrations/hermes/)
Use LadyM as the persistent memory backend for Hermes Agent:
# 1. install the plugin (subdirectory install — no manual file copying)
hermes plugins install ProjAnvil/ladyM/integrations/hermes
# 2. activate the provider, then bootstrap the ladym binary
# (the hermes ladym CLI only exists once ladym is the active provider;
# add --fulldict for the embedded CJK dictionary)
hermes memory setup ladym
hermes ladym install
# 3. verify
hermes memory status # Provider: ladym, available ✓
hermes ladym status # binary path, effective config, store stats- Zero-dependency Python adapter that drives the
ladymbinary over MCP stdio — the Go engine remains the single source of truth. - Recalls through LadyM's two-tier recall before each turn, records every turn as an L1 episodic event, and consolidates (L1 → L2) at session end and before context compression.
- Per-profile SQLite store at
$HERMES_HOME/ladym/ladym.db; offline hashing embeddings by default — no API key, no external service. hermes ladym installdownloads the matching release binary (plain or fulldict variant) with SHA256SUMS verification.- Also installable via pip entry point:
pip install 'git+https://github.com/ProjAnvil/ladyM.git#subdirectory=integrations/hermes'.
Docs: new "Hermes Agent (memory provider)" section in both READMEs; full plugin docs in integrations/hermes/README.md.
Full Changelog: v0.5.2...v0.5.3
v0.5.2 — bounded consolidation: backlog-only scans, ADD rewrites, since bound
What's Changed
Fixes
- Consolidation cost is now bounded by the backlog, not the store — every episode
that completes a consolidation pass (whatever the verdict: ADD / UPDATE / DELETE /
NOOP) is stamped with aconsolidated_atmetadata mark and never re-selected, so
each System 2 cycle pays for new episodes instead of re-embedding and re-classifying
the full history. Unlike a caller-sidesincetimestamp, the stamp survives aborted
passes. Reports exposeskipped_consolidatedacross the engine, HTTP API, MCP
server, and Go client. (d42f856) - ADD verdicts store the LLM's rewritten fact — promoted facts no longer carry the
raw event's recording template shell (agent=… | action=… | observation=…). The
classifier'snew_textis now honored on ADD as well as UPDATE, falling back to the
raw event text when omitted — the offline (no-LLM) classifier always omits it, so
heuristic mode is unchanged. The consolidation prompt and JSON schema now describe
new_textas the distilled fact for both verdicts. (c841747)
Features
sincebound onconsolidate—/api/consolidate, the MCPconsolidatetool,
andConsolidate(ctx, workspace, since)on the Go client accept an optional
unix-secondssince(0 = the whole pending backlog), giving remote deployments an
explicit cost-control handle. (da06014)
Documentation
- README (en + zh-CN) What's New refreshed for the 0.5 line; version bumped to 0.5.2.
(393d8b1)
Upgrade notes
- Downstream integrations that worked around the full re-scan (e.g. assembling their
own incremental cycles with caller-sidesincethreading) can drop that logic:
Consolidate(ws, 0)now means "the pending backlog", not "the whole store". - The Go SDK's
Consolidatesignature gained asince float64parameter — pass0
for the previous behavior.
Full changelog: v0.5.1...v0.5.2
v0.5.1 — CJK support: dictionary-backed Chinese/Japanese/Korean tokenization
Highlights
LadyM now understands Chinese, Japanese, and Korean. CJK text tokenizes out of the box (fully offline), and optional dictionary-backed word segmentation upgrades recall quality — downloaded on demand from the console, baked into Docker images, or compiled into the binary. LadyM never downloads anything on its own.
This release also introduces automated multi-platform releases: every v* tag now publishes prebuilt tarballs for Linux/macOS × amd64/arm64 with a SHA256SUMS file.
What's New
🀄 CJK tokenization (Chinese / Japanese / Korean)
The native hashing tokenizer previously matched only [A-Za-z0-9_] — CJK queries tokenized to an empty set and always scored similarity 0. Now:
- Han runs segment by dictionary word via go-ego/gse (the jieba algorithm, pure Go); kana and hangul tokenize per character with adjacent bigrams.
- Zero-dictionary fallback: without any dictionary, CJK still tokenizes per character — recall keeps working, nothing to configure, nothing to download.
- The default binary stays lean (50MB): gse's embedded dictionaries only link in when explicitly requested (see below).
📦 The dictionary system
Four downloadable variants, sha256-pinned to gse v1.0.2:
| Variant | Content | Download |
|---|---|---|
zh (default) |
Chinese, simplified + traditional | 8.2 MB |
zh_s |
Chinese, simplified only | 4.9 MB |
zh_t |
Chinese, traditional only | 3.4 MB |
jp |
Japanese, kanji + kana | 22.6 MB |
Design guarantees:
- User-triggered only — downloads happen via the console or the admin-gated
POST /api/cjk_dict/download; the tokenization path never touches the network (enforced by a contract test). - Integrity first — every file is sha256-verified before anything is written; failed or tampered downloads leave the existing dictionary untouched.
- Hot reload — downloads and variant switches take effect immediately, no restarts; switching variants cleans up the old files.
- Internal mirrors —
{"mirror_base": "..."}points downloads at an air-gapped internal mirror.
🖥️ Console: Settings → Memory
A new admin Settings page manages the dictionary: variant picker, download/switch/remove, live status (source, version, size, directory). Works in both the personal embedded console and the enterprise ladymconsole service.
🐳 Dict-baked images (Docker)
One command builds and runs every role with the dictionary baked into the image — no shared volume, no downloads, no internet at runtime:
docker compose -f docker-compose.dev.yml -f docker-compose.dev.dict.yml up -d --build
docker compose -f docker-compose.enterprise.yml -f docker-compose.enterprise.dict.yml up -d --buildThe dictionary ships as a thin data layer (/opt/ladym/dict) on top of the regular image: plain docker build . stays dictionary-less, the layer is architecture-independent, air-gapped builds work by placing the pinned files under dict/, and Dockerfile.dict --build-arg BASE=<image> stacks the layer onto any already-released image.
For fleets without baked images, the shared-volume pattern remains: point every instance at one directory (LADYM_DICT_DIR), download once on any instance, and all instances follow within ~30 seconds.
⚙️ Dictionary directory configuration
The dictionary directory (default ~/.ladyM/dict) is now configurable on all three daemon commands, with the usual priority chain:
ladym serve --http :8080 --dict-dir /data/cjk-dict # flag
LADYM_DICT_DIR=/data/cjk-dict ladym serve --http :8080 # env
# ladym.toml: dict_dir = "/data/cjk-dict" # toml📚 Downstream Go consumers
Three ways to get the embedded dictionary — the module version never changes:
- Runtime download — trigger via console/API, or call
storage.DownloadCJKDict(). - Side-effect import —
import _ "github.com/ProjAnvil/LadyM/storage/fulldict"(no build-script changes). - Build tag —
-tags fulldict(what theladym-personal-fulldict-*assets below use).
There is deliberately no v0.5.1-fulldict module version: semver reads that suffix as a pre-release of v0.5.1 and it would confuse go get.
Upgrading
No breaking changes; no migration needed. Optional:
- For better CJK recall quality, download a dictionary: console Settings → Memory, or
curl -X POST -H 'Content-Type: application/json' -d '{"dict":"zh"}' http://localhost:8080/api/cjk_dict/download(admin auth applies). - Docker users can switch to dict-baked images with the compose overrides above.
Release Assets
Built automatically by .github/workflows/release.yml (test gates → 4-platform matrix → upload):
| Asset | What it is |
|---|---|
ladym-personal-<ver>-<os>-<arch>.tar.gz |
Personal edition (dictionary downloadable at runtime) |
ladym-personal-fulldict-<ver>-<os>-<arch>.tar.gz |
Personal edition with the zh dictionary compiled in (~+31MB) |
ladym-enterprise-<ver>-<os>-<arch>.tar.gz |
Enterprise edition (ladym + ladymconsole, Postgres-only) |
SHA256SUMS |
Checksums for every tarball |
Platforms: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64. Static binaries (CGO_ENABLED=0).
Full changelog: v0.5.0...v0.5.1
v0.5.0 — langchain-golang v0.6.2: reasoning effort & native JSON mode
Highlight: langchain-golang v0.5.0 → v0.6.2
LadyM's LLM/LangGraph foundation jumps three releases (v0.6.0 → v0.6.1 → v0.6.2) and puts the new capabilities to work:
- v0.6.0 — Python SDK parity completion: OpenAI
tool_choice, native JSON mode / rawresponse_formatpassthrough,with_structured_outputimprovements, model token counting APIs, checkpoint saver management API, prebuilt react agent helpers. - v0.6.1 — token counting parity: real tiktoken BPE for OpenAI (cl100k_base / o200k_base, official vision-token formula), Anthropic
/messages/count_tokensbacking, usage-metadata-scaled approximate counting. - v0.6.2 —
tiktoken-go/tokenizerv0.8.1. Requires Go ≥ 1.26 (LadyM already targets go 1.26.4).
What's new in LadyM
reasoning_effortconfig knob, plumbed end to end — steer OpenAI o-series / gpt-5 reasoning models (low|medium|high):Also via[llm] reasoning_effort = "high"
LADYM_LLM_REASONING_EFFORTand per-operation[agents.<op>]overrides. Validated at provider construction; anthropic / ollama / http accept and ignore it.- OpenAI-native JSON mode for structured output —
structured_method = "json_mode"now binds the provider-nativeresponse_format={"type":"json_object"}on OpenAI partner models (upstream enforcement) while retaining the schema system prompt, replacing the former prompt-only path. Non-OpenAI models are unchanged.
Verification
go build/go vetgreen on both editions (personal +-tags enterprise)make test-allgreen: personal + live Postgres, enterprise, comment lint- Statement coverage 95.8% (personal + PG); providers 99.5%, config 99.1%
- TDD throughout (RED witnessed per task); two per-task reviews + final whole-branch review: merge-ready
Full Changelog: v0.4.0...v0.5.0
LadyM v0.4.0
LadyM v0.4.0
Highlights
- Dual edition: personal (SQLite/Postgres, embedded console) and enterprise (
-tags enterprise, Postgres-only microservices) - REST API service: every MCP tool is now also available over HTTP, plus /healthz and /api/metrics
- Lightweight auth: database-level username/password (bcrypt, HTTP Basic), optional no-password users,
[auth] enabledtoggle;ladym user add/list/delete/passwd - Vue admin console: Login / Memories / Users / Stats with full CRUD API; embedded in personal build, split into standalone
ladymconsoleconfig-center microservice for enterprise - client/golang: Go SDK for embedding LadyM into other Go programs
- Enterprise compose stack: three-tier docker-compose.enterprise.yml (nginx gateway -> ladym api x2 + console -> Postgres)
Artifacts
ladym-personal-v0.4.0-darwin-arm64.tar.gz— personal edition binaryladym-enterprise-v0.4.0-darwin-arm64.tar.gz— enterprise binaries (ladym + ladymconsole) with compose stack