Move Dockerfile.app, Dockerfile.web, nginx/, php/, and docker-compose
to core-php where they belong. Promote Dockerfile.core to root Dockerfile.
Simplify deploy workflow to only build the CLI image.
Co-Authored-By: Virgil <virgil@lethean.io>
Remove all external blank imports from main.go (go-ai, go-api, go-crypt,
go-devops, go-ml, go-netops, go-scm) and delete cmd/ai/. Business logic
moved to proper repos: go-agent, go-agentic, go-ai.
Clean .core/ — remove LinuxKit VM templates, Claude Code plugin, and
ephemeral issue plans. Keep only CLI build/release config.
Drops 504 lines from go.mod/go.sum. CLI no longer pulls ollama, qdrant,
duckdb, or other ML dependencies into its binary or security scan scope.
Co-Authored-By: Virgil <virgil@lethean.io>
- Upgrade Go to 1.26, FrankenPHP to v1.11.2 (CVE-2026-24894)
- Add non-root USER to all Dockerfiles (Trivy misconfig)
- Upgrade gitleaks to v8.24.3 with arch detection
Co-Authored-By: Virgil <virgil@lethean.io>
- Fix 11 non-constant format string warnings in cmd/session
(use cli.Print format args instead of fmt.Sprintf wrapper)
- Remove leftover .github/workflows/ from cmd/updater
(ci.yml and release.yml from when updater was standalone)
Co-Authored-By: Virgil <virgil@lethean.io>
The gitleaks install was fragile: depended on GitHub API (rate limits),
jq being present, and hardcoded x64 arch. Now pins v8.24.3, detects
arch, uses curl -f for proper error handling, and verifies install.
Co-Authored-By: Virgil <virgil@lethean.io>
- Move 40 ML command files to forge.lthn.ai/core/go-ml/cmd
- Remove all replace directives from go.mod
- Remove go.work (repos resolve from forge directly)
- Fix cache.New call to match updated API signature
- Update main.go import to forge.lthn.ai/core/go-ml/cmd
Co-Authored-By: Virgil <virgil@lethean.io>
New command group for OpenAPI spec generation and SDK codegen:
- `core api spec` generates OpenAPI 3.1 spec (JSON/YAML) from route groups
- `core api sdk` generates client SDKs via openapi-generator-cli
- Adds go-api dependency for SpecBuilder, ExportSpec, SDKGenerator
Co-Authored-By: Virgil <virgil@lethean.io>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When an agent job fails in under 30 seconds (indicating rate limiting
or auth rejection), the watcher now:
- Requeues the ticket back to the queue instead of marking it done
- Applies exponential backoff: 2x, 4x, 8x the base poll interval
- Resets backoff to 1x on successful job completion
This prevents burning through the entire queue during rate-limited
periods. Tested on Clotho (AU) with 15m base → 30m/60m/120m backoff.
Co-Authored-By: Charon <charon@lethean.io>
Tickets generated by poll-forge.sh don't include forge_token.
The dispatch runner now checks FORGE_TOKEN env var as fallback,
and gracefully skips reporting if no token is available.
Co-Authored-By: Charon <charon@lethean.io>
Virgil split go-ai into standalone modules (go-agentic, go-ml, go-mlx,
go-rag). This migrates all CLI imports to the new module paths and fixes
API mismatches from the split.
Key changes:
- go-ai/agentic → go-agentic (cmd/ai, cmd/dev)
- go-ai/ml → go-ml (31 files in cmd/ml)
- go-ai/rag → go-rag (3 files in cmd/rag)
- go-ai/mlx → go-mlx (1 file)
- Fix go.work path (../core → ../go)
- Add all split repos to go.work and go.mod
- Simplify daemon to goroutine-based MCP (remove missing supervisor)
- Wire go-agentic SQLiteRegistry into dispatch watch (--agent-id flag)
- Add `core ai agent fleet` command for local registry status
- Fix rag collections API (PointCount, Status string)
- Fix ml live/expand-status to use available go-ml API
Co-Authored-By: Charon <charon@lethean.io>
Wire `core module install/remove/list/update` commands to the
marketplace.Installer from pkg/marketplace. Follows the exact
pattern established by cmd/plugin/.
- install: clone from Git repo with optional ed25519 verification
- list: table output of installed modules
- update: pull latest + re-verify manifest (supports --all)
- remove: confirmation prompt then cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Final two Python pipeline gaps ported to Go — InfluxDB live generation
progress and DuckDB expansion pipeline status. Python scripts can now
be archived.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add --max-context flag to serve (sliding window, default 4 messages)
to prevent KV-cache explosion on multi-turn conversations
- Pass server max-tokens to chat UI HTML attribute instead of
hardcoded 2048 in JavaScript
- Add chat.js and chat_embed.go for embedded LEM chat UI
Co-Authored-By: Virgil <virgil@lethean.io>
Runs the same prompts through baseline and fine-tuned models, scores
both with the heuristic scorer, and outputs a comparison report with
LEK score deltas and improvement/regression counts.
Uses built-in content probes by default, or custom prompts file.
Co-Authored-By: Virgil <virgil@lethean.io>
Lesson command runs prompts from YAML definitions with state tracking,
sandwich signing, and interactive review mode. Sequence command runs
multiple lessons in order (vertical/strict or horizontal/flexible).
State files enable resume after interruption. Both output chat JSONL
compatible with 'core ml train'.
Co-Authored-By: Virgil <virgil@lethean.io>
Sandwich format wraps seed prompts with KB preamble (axioms framework)
and LEK-1 kernel postfix, then generates responses via local MLX
inference. Outputs chat JSONL compatible with 'core ml train'.
Supports --dry-run mode to output prompts without inference.
Co-Authored-By: Virgil <virgil@lethean.io>
Native MLX LoRA training on Apple Silicon — no Python required.
Reads chat-format JSONL, applies LoRA to target projections,
trains with AdamW + masked cross-entropy loss on assistant tokens.
Usage: core ml train --model-path /path/to/model --data training.jsonl
Co-Authored-By: Virgil <virgil@lethean.io>
Add compiled binary to gitignore. Remove entries for deleted paths
(cmd/bugseti/bugseti, internal/core-ide/core-ide).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove internal/bugseti/ (now core/bugseti repo), cmd/bugseti/
(now core/bugseti/cmd/), and internal/tools/ (i18n-validate
moved to core/go). core/cli internal/ is now empty.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- Extract PHP/Laravel commands to `core/php` repo (42 files, standalone module)
- Extract CI/release + SDK commands to `core/ci` repo (10 files)
- Remove `internal/variants/` build tag system entirely
- Move all 30 remaining command packages from `internal/cmd/` to top-level `cmd/`
- Rewrite `main.go` with direct imports — no more variant selection
- PHP and CI are now optional via commented import lines in main.go
Co-authored-by: Claude <developers@lethean.io>
Reviewed-on: #2
Co-authored-by: Charon <charon@lthn.ai>
Co-committed-by: Charon <charon@lthn.ai>
- Change module from forge.lthn.ai/core/go to forge.lthn.ai/core/cli
- Remove pkg/ directory (now served from core/go)
- Add require + replace for forge.lthn.ai/core/go => ../go
- Update go.work to include ../go workspace module
- Fix all internal/cmd/* imports: pkg/ refs → forge.lthn.ai/core/go/pkg/
- Rename internal/cmd/sdk package to sdkcmd (avoids conflict with pkg/sdk)
- Remove SDK library files from internal/cmd/sdk/ (now in core/go/pkg/sdk/)
- Remove duplicate RAG helper functions from internal/cmd/rag/
- Remove stale cmd/core-ide/ (now in core/ide repo)
- Update IDE variant to remove core-ide import
- Fix test assertion for new module name
- Run go mod tidy to sync dependencies
core/cli is now a pure CLI application importing core/go for packages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Claude <developers@lethean.io>
Reviewed-on: #1
Port the standalone lab dashboard (lab.lthn.io) into the core CLI as
pkg/lab/ with collectors, handlers, and HTML templates. The dashboard
monitors machines, Docker containers, Forgejo, HuggingFace models,
training runs, and InfluxDB metrics with SSE live updates.
New command: core lab serve --bind :8080
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ports all remaining LEM pipeline commands from pkg/lem into core ml,
eliminating the standalone LEM CLI dependency. Each command is split
into reusable business logic (pkg/ml/) and a thin cobra wrapper
(internal/cmd/ml/).
New commands: query, inventory, metrics, ingest, normalize, seed-influx,
consolidate, import-all, approve, publish, coverage.
Adds Path(), Exec(), QueryRowScan() convenience methods to DB type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tracks model size at load time and checks Metal active memory after
each generation. If usage exceeds 3× model size, forces double GC
and cache clear as a safety net.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Go wrapper was tracking inter-array references via desc.inputs,
creating chains that kept all intermediate arrays alive across requests.
After 3-4 requests, Metal memory grew to 170GB+ and macOS killed the
process.
Fix: remove desc.inputs/numRefs entirely. MLX-C has its own internal
reference counting — when Go GC finalizes an Array wrapper, it calls
mlx_array_free which decrements the C-side refcount. If the C-side
count reaches 0, Metal memory is freed. Go GC + MLX-C refcounting
together handle all lifecycle management correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Go GC cannot see Metal/C memory pressure, so intermediate arrays from
each forward pass accumulated without bound, causing OOM kills after
3-4 requests. Fix: runtime.SetFinalizer on every Array releases C
handles when GC collects them, and runtime.GC() is forced every 4
tokens during generation. Also adds SetMemoryLimit(24GB) as a hard
Metal ceiling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ClearCache() wrapping mlx_clear_cache
- Clear Metal allocator cache every 8 tokens during generation
- Set 16GB cache limit on backend init
- Prevents GPU memory from growing unbounded during inference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gemma 3 tokenizer.json uses [["a","b"],...] format for merges
instead of the ["a b",...] format. Support both.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Supports both multimodal (Gemma3ForConditionalGeneration) and
text-only configs. Resolves weights with language_model. prefix
fallback. Computes head_dim from hidden_size when missing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use pure C callback instead of //export to avoid const char* vs
GoString type mismatch in cgo-generated headers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>