Commit graph

387 commits

Author SHA1 Message Date
Snider
cd87500426 refactor: update import paths from cli to go package structure
Some checks are pending
Security Scan / Go Vulnerability Check (push) Waiting to run
Security Scan / Secret Detection (push) Waiting to run
Security Scan / Dependency & Config Scan (push) Waiting to run
2026-02-16 13:47:52 +00:00
4eb1e02f5e feat/ml-integration (#2)
Co-authored-by: Charon (snider-linux) <charon@lethean.io>
Co-authored-by: Snider <snider@host.uk.com>
Co-authored-by: Virgil <virgil@lethean.io>
Co-authored-by: Claude <developers@lethean.io>
Reviewed-on: #2
Co-authored-by: Snider <snider@lethean.io>
Co-committed-by: Snider <snider@lethean.io>
2026-02-16 06:19:09 +00:00
Claude
5e9a9c2790 feat: integrate lab dashboard as core lab serve
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>
2026-02-16 05:53:52 +00:00
Claude
1f3a1bcc47 feat: port 11 LEM data management commands into core ml
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>
2026-02-16 05:53:52 +00:00
Claude
3269a773f4 feat: add Metal memory budget monitoring after each request
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>
2026-02-16 05:53:52 +00:00
Claude
6b603ee20b fix: remove Go-side array ref tracking, rely on MLX-C refcounting
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>
2026-02-16 05:53:52 +00:00
Claude
8cdafc8d66 fix: add GC-based memory management for MLX array handles
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>
2026-02-16 05:53:52 +00:00
Claude
9688e086ca fix: add Metal cache management to prevent memory growth
- 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>
2026-02-16 05:53:52 +00:00
Claude
098f496364 fix: correct SDPA mask mode and slice logits to last position 2026-02-16 05:53:52 +00:00
Claude
09da05d799 fix: use affine quantization mode and infer head_dim from weights 2026-02-16 05:53:52 +00:00
Claude
d3c31aa5a6 debug: add shape logging and stderr error handler for inference debugging 2026-02-16 05:53:52 +00:00
Claude
56c6e2fa8d feat: support quantized inference (4-bit) for Gemma 3
- Add QuantizedLinear with QuantizedMatmul for packed uint32 weights
- Add quantized Embedding with Dequantize before lookup
- Parse quantization config (group_size, bits) from config.json
- Detect .scales/.biases weight tensors and auto-select quantized path
- Add Dequantize op wrapping mlx_dequantize
- Add safety guard to KVCache.Update for malformed shapes
- Handle tied embeddings with quantization (AsLinear helper)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
a4fde16998 fix: handle both string and array merge formats in tokenizer
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>
2026-02-16 05:53:52 +00:00
Claude
2a67653bf7 feat: handle nested text_config and language_model weight prefix
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>
2026-02-16 05:53:52 +00:00
Claude
9ae86017f4 chore: target macOS 26.0, fix duplicate -lstdc++ linker warning
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
e9d9a3c3a0 fix: remove unused vars in TopP sampler placeholder
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
a0f77960a1 fix: resolve CGo type conflict in error handler
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>
2026-02-16 05:53:52 +00:00
Claude
5e2d941b4d fix: correct 20 mlx-c API mismatches for v0.4.1
- Use _axis/_axes variants for softmax, argmax, topk, sum, mean, squeeze,
  concatenate, argpartition
- Fix size_t vs int for count parameters throughout
- Fix int64_t strides in as_strided
- Add mlx_optional_int + mode param to quantized_matmul
- Use mlx_array_new() for null arrays (freqs, key, mask, sinks)
- Fix expand_dims to single-axis signature
- Fix compile callback signature (size_t index)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
c6597691bb fix: correct mlx_closure_new_func_payload signature for mlx-c v0.4.1
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
bc28aad526 feat: add native MLX backend for Apple Silicon inference (pkg/mlx)
CGo wrapper for mlx-c providing zero-Python Metal GPU inference.
Includes Gemma 3 model architecture, BPE tokenizer, KV cache,
composable sampling, and OpenAI-compatible serve command.

Build-tagged (darwin && arm64 && mlx) with stubs for cross-platform.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
548256312d feat: add ML inference, scoring, and training pipeline (pkg/ml)
Port LEM scoring/training pipeline into CoreGo as pkg/ml with:
- Inference abstraction with HTTP, llama-server, and Ollama backends
- 3-tier scoring engine (heuristic, exact, LLM judge)
- Capability and content probes for model evaluation
- GGUF/safetensors format converters, MLX to PEFT adapter conversion
- DuckDB integration for training data pipeline
- InfluxDB metrics for lab dashboard
- Training data export (JSONL + Parquet)
- Expansion generation pipeline with distributed workers
- 10 CLI commands under 'core ml' (score, probe, export, expand, status, gguf, convert, agent, worker)
- 5 MCP tools (ml_generate, ml_score, ml_probe, ml_status, ml_backends)

All 37 ML tests passing. Binary builds at 138MB with all commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
52d358daa2 refactor: rename module from github.com/host-uk/core to forge.lthn.ai/core/cli
Move module identity to our own Forgejo instance. All import paths
updated across 434 Go files, sub-module go.mod files, and go.work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Snider
2373a7d439 feat(bugseti): migrate from GitHub gh CLI to Forgejo SDK
Replace all exec.Command("gh", ...) calls with the existing pkg/forge
wrapper around the Forgejo Go SDK. BugSETI no longer requires the gh
CLI to be installed.

Changes:
- fetcher: use forge.ListIssues/GetIssue instead of gh issue list/view
- submit: use forge.ForkRepo/CreatePullRequest instead of gh pr create
- seeder: use git clone with forge URL + token auth instead of gh clone
- ghcheck: CheckForge() returns *forge.Client via forge.NewFromConfig()
- config: add ForgeURL/ForgeToken fields (GitHubToken kept for migration)
- pkg/forge: add Token(), GetCurrentUser(), ForkRepo(), CreatePullRequest(),
  ListIssueComments(), and label filtering to ListIssuesOpts

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-16 05:53:52 +00:00
Claude
5de7ee4fb8 fix(security): sanitize path components in journal logging (#46)
Prevent path traversal in Journal.Append() by validating RepoOwner and
RepoName before using them in file paths. Malicious values like
"../../etc/cron.d" could previously write outside the journal baseDir.

Defence layers:
- Reject inputs containing path separators (/ or \)
- Reject ".." and "." traversal components
- Validate against safe character regex ^[a-zA-Z0-9][a-zA-Z0-9._-]*$
- Verify resolved absolute path stays within baseDir

Closes #46
CVSS 6.3 — OWASP A01:2021-Broken Access Control

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
0edbc35ffc fix(security): move Gemini API key from URL query params to header (#47)
Pass the API key via x-goog-api-key HTTP header instead of the URL
query parameter to prevent credential leakage in proxy logs, web
server access logs, and monitoring systems.

Resolves: #47 (CVSS 5.3, OWASP A09:2021)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Athena
7a474d0690 feat(agentic): add agent allowance system for model quotas and budgets
Implements quota enforcement for agents including daily token limits,
daily job limits, concurrent job caps, model allowlists, and global
per-model budgets. Quota recovery returns 50% for failed jobs and
100% for cancelled jobs.

Go: AllowanceService with MemoryStore, AllowanceStore interface, and
25 tests covering all enforcement paths.

Laravel: migration for 5 tables (agent_allowances, quota_usage,
model_quotas, usage_reports, repo_limits), Eloquent models,
AllowanceService, QuotaMiddleware, and REST API routes.

Closes #99

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Athena
46273a0f5c feat(agentic): add agent trust model with tiered access control
Implements the security wall between non-aligned agents (issue #97).

Adds pkg/trust with:
- Three trust tiers: Full (Tier 3), Verified (Tier 2), Untrusted (Tier 1)
- Agent registry with mutex-protected concurrent access
- Policy engine with capability-based access control
- Repo-scoped permissions for Tier 2 agents
- Default policies matching the spec (rate limits, approval gates, denials)
- 49 tests covering all tiers, capabilities, edge cases, and helpers

Closes #97

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 05:53:52 +00:00
Claude
b00e0df89c
fix(agentci): resolve agents by Forgejo username, not config key
Adds FindByForgejoUser() to Spinner so dispatch matches issues
assigned to Forgejo users (Virgil, Claude, Charon) even when the
agent config key differs (e.g. Hypnos → forgejo_user: Claude).

Searches config key first (direct match), then ForgejoUser field.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:08:17 +00:00
Claude
3ccb67bddd
feat(agentci): rate limiting and native Go dispatch runner
Adds pkg/ratelimit for Gemini API rate limiting with sliding window
(RPM/TPM/RPD), persistent state, and token counting. Replaces the
bash agent-runner.sh with a native Go implementation under
`core ai dispatch {run,watch,status}` for local queue processing.

Rate limiting:
- Per-model quotas (RPM, TPM, RPD) with 1-minute sliding window
- WaitForCapacity blocks until capacity available or context cancelled
- Persistent state in ~/.core/ratelimits.yaml
- Default quotas for Gemini 3 Pro/Flash, 2.5 Pro, 2.0 Flash/Lite
- CountTokens helper calls Google tokenizer API
- CLI: core ai ratelimits {show,reset,count,config,check}

Dispatch runner:
- core ai dispatch run — process single ticket from queue
- core ai dispatch watch — daemon mode with configurable interval
- core ai dispatch status — show queue/active/done counts
- Supports claude/codex/gemini runners with rate-limited Gemini
- File-based locking with stale PID detection
- Completion handler updates issue labels on success/failure

Closes #42

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:08:16 +00:00
Claude
d92762ecdc
feat(agentci): Clotho orchestrator and security hardening
Adds the Clotho dual-run verification system and hardens the entire
agent dispatch pipeline against command injection, token exposure,
and SSH MitM attacks. Breaks the agentci→handlers circular dependency.

Security:
- SanitizePath (regex whitelist + filepath.Base) for all dispatch inputs
- EscapeShellArg for shell argument safety
- SecureSSHCommand (StrictHostKeyChecking=yes, BatchMode=yes)
- ForgeToken removed from ticket JSON, transferred via .env with 0600
- ssh-keyscan on agent add populates known_hosts before first connection

Clotho:
- Spinner orchestrator determines Standard vs Dual execution mode
- Config-driven via ClothoConfig (strategy, validation_threshold)
- Agent runner supports claude/codex/gemini backends with dual-run
- Divergence detection compares thread outputs via git diff

API:
- LoadActiveAgents() returns map[string]AgentConfig (no handlers import)
- LoadClothoConfig() reads clotho section from config
- Forge helpers: AssignIssue, EnsureLabel, AddIssueLabels

32 tests pass (19 agentci + 13 dispatch).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:08:16 +00:00
Claude
4c8be587bf
feat(agentci): add tests and Gemini 3 tiered batch pipeline
- Add 15 tests for pkg/agentci/config.go (load, save, remove, list, round-trip)
- Extend dispatch_test.go from 4 to 12 tests (match edge cases, ticket JSON
  serialization, model/runner variants, execute error paths)
- Add gemini-batch-runner.sh: rate-limit-aware tiered pipeline using
  Flash Lite → Gemini 3 Flash → Gemini 3 Pro with 80% TPM safety margin
- Generate docs/pkg-batch{1-6}-analysis.md covering all 33 packages
  using ~893K tokens total (vs 5.54M single-shot), zero rate limit hits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 03:07:52 +00:00
Virgil
00dfd27072 Merge pull request 'feat(agentci): package dispatch for multi-agent deployment' (#39) from feat/agentci-packaging into new 2026-02-09 11:25:48 +00:00
Snider
0a3c0204d1 fix(agentci): use log.E() error pattern, add Charm SSH TODOs
Replace fmt.Errorf() with structured log.E() errors in agentci, forge,
jobrunner packages. Update PipelineSignal comment to reflect dispatch
fields. Add TODO markers for charmbracelet/ssh migration across all
exec ssh call sites.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-09 11:15:11 +00:00
Claude
67dc130424
feat(agentci): add model/runner fields for multi-backend support
Tickets now carry model (sonnet/haiku/opus) and runner (claude/codex)
fields. agent-runner.sh dispatches to the right backend. Defaults to
claude with sonnet model for cost efficiency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:58:46 +00:00
Claude
6ae525d54f
feat(agentci): package dispatch system for multi-agent deployment
Config-driven agent targets replace hardcoded map so new agents
can be added via CLI instead of recompiling. Includes setup script
for bootstrapping agent machines and CLI commands for management.

- Add pkg/agentci with config types and CRUD (LoadAgents, SaveAgent, etc.)
- Add CLI: core ai agent {add,list,status,logs,setup,remove}
- Add scripts/agent-setup.sh (SSH bootstrap: dirs, cron, prereq check)
- Headless loads agents from ~/.core/config.yaml
- Dispatch ticket includes forgejo_user for dynamic clone URLs
- agent-runner.sh reads username from ticket JSON, not hardcoded

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:36:23 +00:00
Claude
b8b0a2e5b8
feat(jobrunner): add agent dispatch handler and queue runner
Dispatch handler matches child issues that need coding (no PR yet,
assigned to a known agent) and SCPs ticket JSON to the agent's
queue directory via SSH. Includes dedup across queue/active/done
and posts dispatch comments on issues.

- Extend PipelineSignal with NeedsCoding, Assignee, IssueTitle, IssueBody
- Extend ForgejoSource to emit signals for unstarted children
- Add DispatchHandler with Match/Execute (SCP ticket delivery)
- Add agent-runner.sh cron-based queue runner for agent machines
- Wire dispatch handler into headless mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:10:08 +00:00
Snider
e8119a49eb fix(core-ide): use path-based routing for multi-window SPA, clean up formatting
Switch Angular from hash-based to path-based routing so each Wails window
(/tray, /main, /settings) loads its correct route. Archive GitHub Actions
workflows to .gh-actions/, update Forgejo deploy registry to dappco.re/osi,
and apply gofmt/alignment fixes across packages.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-09 01:50:57 +00:00
Snider
b32858d135 updates 2026-02-09 01:27:40 +00:00
Claude
ccead55c0e
feat(jobrunner): port from GitHub to Forgejo using pkg/forge
Replace all GitHub API and gh CLI dependencies with Forgejo SDK via
pkg/forge. The bash dispatcher burned a week of credit in a day due to
bugs — the jobrunner now talks directly to Forgejo.

- Add forge client methods: CreateIssueComment, CloseIssue, MergePullRequest,
  SetPRDraft, ListPRReviews, GetCombinedStatus, DismissReview
- Create ForgejoSource implementing JobSource (epic polling, checklist
  parsing, commit status via combined status API)
- Rewrite all 5 handlers to accept *forge.Client instead of shelling out
- Replace ResolveThreadsHandler with DismissReviewsHandler (Forgejo has
  no thread resolution API — dismiss stale REQUEST_CHANGES reviews instead)
- Delete pkg/jobrunner/github/ and handlers/exec.go entirely
- Update internal/core-ide/headless.go to wire Forgejo source and handlers
- All 33 tests pass with mock Forgejo HTTP servers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 00:40:49 +00:00
Snider
4127509ccd fix: resolve conflict markers and remove legacy code after branch consolidation
- Remove conflict markers from 19 files that were accidentally committed
  during merge resolutions (keeping HEAD versions)
- Remove legacy root-level code (core.go, main.go, config/, crypt/,
  display/, filesystem/, workspace/, docs/*.go, cmd/app/) from old
  architecture predating pkg/ restructure
- Remove duplicate pkg/config/loader.go (Load/Save already in config.go)
- Fix import alias in cmd_apply.go (errors -> core)

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-08 22:08:35 +00:00
Snider
b84a1ec29e Merge branch 'fix/consolidate-workflows' into new 2026-02-08 22:00:21 +00:00
Snider
cf0011c508 Merge branch 'feat/prod-infra' into new 2026-02-08 21:59:43 +00:00
Snider
084807975a Merge branch 'feat/release-and-installers' into new 2026-02-08 21:59:18 +00:00
Snider
d3550d2658 fix: resolve API signature mismatches after IO migration merge
Reconcile callers with actual function signatures after merging IO
migration branches. Some functions gained io.Medium params (repos.*),
others kept their original signatures (release.*, cache.*, container.*).

- Add io.Local to repos.LoadRegistry/FindRegistry/ScanDirectory callers
- Remove extra io.Local from release.ConfigExists/LoadConfig/WriteConfig callers
- Fix cache.New call (remove nil Medium arg)
- Add missing IsCPPProject to build discovery
- Add missing fields to mcp.Service struct (subsystems, logger, etc.)
- Add DefaultTCPAddr constant to mcp transport
- Fix node.go interface check (coreio.Medium, not coreio.Node)
- Fix container.linuxkit LoadState/EnsureLogsDir arg counts
- Fix vm templates to use package-level functions
- Remove unused Medium field from DaemonOptions

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-08 21:55:10 +00:00
Snider
e0b18aa6a2 Merge branch 'feature/cli-batch' into new
# Conflicts:
#	internal/cmd/dev/cmd_file_sync.go
#	internal/cmd/docs/cmd_sync.go
#	internal/cmd/sdk/generators/go.go
#	internal/cmd/setup/cmd_registry.go
#	pkg/cli/daemon.go
#	pkg/io/local/client.go
#	pkg/io/local/client_test.go
#	pkg/mcp/transport_tcp.go
2026-02-08 21:29:47 +00:00
Snider
59a986ea41 Merge branch 'feature/io-batch' into new
# Conflicts:
#	go.mod
#	go.sum
#	internal/cmd/dev/cmd_apply.go
#	internal/cmd/dev/cmd_file_sync.go
#	internal/cmd/docs/cmd_scan.go
#	internal/cmd/docs/cmd_sync.go
#	internal/cmd/help/cmd.go
#	internal/cmd/sdk/generators/go.go
#	internal/cmd/setup/cmd_registry.go
#	internal/variants/full.go
#	pkg/io/io.go
#	pkg/io/local/client.go
#	pkg/io/local/client_test.go
#	pkg/mcp/mcp.go
#	pkg/mcp/mcp_test.go
#	pkg/mcp/transport_tcp.go
2026-02-08 21:29:39 +00:00
Snider
83b5e10742 Merge branch 'chore/io-migrate-repos-medium-11165034141497363118' into new
# Conflicts:
#	internal/cmd/setup/cmd_github.go
#	pkg/repos/registry.go
2026-02-08 21:29:24 +00:00
Snider
fd4cbdee8f Merge branch 'chore/io-migrate-build-8873543635510272463' into new
# Conflicts:
#	pkg/build/checksum.go
#	pkg/build/config.go
#	pkg/build/discovery.go
#	pkg/build/discovery_test.go
#	pkg/io/io.go
#	pkg/io/local/client.go
#	pkg/release/release.go
2026-02-08 21:29:14 +00:00
Snider
1ac04479f6 Merge branch 'fix/io-migration-repos' into new
# Conflicts:
#	pkg/repos/registry.go
2026-02-08 21:28:50 +00:00
Snider
948dd16761 Merge branch 'fix/io-migration-release' into new
# Conflicts:
#	pkg/release/config.go
#	pkg/release/release.go
2026-02-08 21:28:43 +00:00