164 tests, 41.3% coverage. Tests written against the public API only
(external test package, no _test.go in pkg/core/).
Covers: New(Options), Data, Drive, Config, Service, Error, IPC,
Fs, Cli, Lock, Array, Log, App, Runtime, Task.
Fixes: NewCommand now inits flagset, New() wires Cli root command.
Old tests removed — they referenced With*, RegisterService, and
other patterns that no longer exist.
Co-Authored-By: Virgil <virgil@lethean.io>
- All New* constructors removed (NewApp, NewIO, NewCoreCli, NewBus, NewService, NewCoreI18n, NewConfig)
- New() uses pure struct literals: &App{}, &Fs{}, &Config{ConfigOpts:}, &Cli{opts:}, &Service{}, &Ipc{}, &I18n{}
- Ipc methods moved to func (c *Core) — Ipc is now a DTO
- LockApply only called from WithServiceLock, not on every New()
- Service map lazy-inits on first write
- CliOpts DTO with Version/Name/Description
Co-Authored-By: Virgil <virgil@lethean.io>
C1: mnt_extract.go rename bug — source path was mutated before
reading from fs.FS. Now uses separate sourcePath/targetPath.
C2: cli_command.go os.Stderr = nil — replaced with
flags.SetOutput(io.Discard). No more global nil stderr.
C3: Cli() returned nil — now initialised in New() with
NewCliApp("", "", "").
Found by opus code-reviewer agent (final review pass).
Co-Authored-By: Virgil <virgil@lethean.io>
Brings go-log's errors and logger directly into the Core package:
core.E("pkg.Method", "msg", err) — structured errors
core.Err{Op, Msg, Err, Code} — error type
core.Wrap(err, op, msg) — error wrapping
core.NewLogger(opts) — structured logger
core.Info/Warn/Error/Debug(msg, kv) — logging functions
Removed:
pkg/core/e.go — was re-exporting from go-log, now source is inline
pkg/log/ — was re-exporting, no longer needed
Renames to avoid conflicts:
log.New() → core.NewLogger() (core.New is the DI constructor)
log.Message() → core.ErrorMessage() (core.Message is the IPC type)
go-log still exists as a separate module for external consumers.
Core framework now has errors + logging built-in. Zero deps.
Co-Authored-By: Virgil <virgil@lethean.io>
filepath.Clean("/"+p) returns absolute path, filepath.Join(root, "/abs")
drops root on Linux. Strip leading "/" before joining with sandbox root.
Currently not exploitable (validatePath handles it), but any future
caller of path() with active sandbox would escape. Defensive fix.
Found by Gemini Pro security review.
Co-Authored-By: Virgil <virgil@lethean.io>
Prevents external mutation of crash handler metadata after construction.
Uses maps.Clone (Go 1.21+) as suggested by Gemini Pro review.
Co-Authored-By: Virgil <virgil@lethean.io>
GetString/GetInt/GetBool now delegate to EtcGet[T].
Gemini Pro review finding — three identical functions collapsed to one generic.
Co-Authored-By: Virgil <virgil@lethean.io>
Brings go-io/local into Core as c.Io():
c.Io().Read("config.yaml")
c.Io().Write("output.txt", content)
c.Io().WriteMode("key.pem", data, 0600)
c.Io().IsFile("go.mod")
c.Io().List(".")
c.Io().Delete("temp.txt")
Default: rooted at "/" (full access like os package).
Sandbox: core.WithIO("./data") restricts all operations.
c.Mnt() stays for embedded/mounted assets (read-only).
c.Io() is for local filesystem (read/write/delete).
WithMount stays for mounting fs.FS subdirectories.
WithIO added for sandboxing local I/O.
Based on go-io/local/client.go (~300 lines), zero external deps.
Co-Authored-By: Virgil <virgil@lethean.io>
Replaces the old Features struct with Etc on the Core struct:
c.Etc().Set("api_url", "https://api.lthn.sh")
c.Etc().Enable("coderabbit")
c.Etc().Enabled("coderabbit") // true
c.Etc().GetString("api_url") // "https://api.lthn.sh"
Also adds Var[T] — generic optional variable (from leaanthony/u):
v := core.NewVar("hello")
v.Get() // "hello"
v.IsSet() // true
v.Unset() // zero value, IsSet() = false
Removes Features struct from Core (replaced by Etc).
Thread-safe via sync.RWMutex. Zero external dependencies.
Co-Authored-By: Virgil <virgil@lethean.io>
Mnt is now a built-in capability of the Core struct, not a service:
c.Mnt().ReadString("persona/secops/developer.md")
c.Mnt().Extract(targetDir, data)
Changes:
- Move mnt.go + mnt_extract.go into pkg/core/ (same package)
- Core struct: replace `assets embed.FS` with `mnt *Sub`
- WithAssets now creates a Sub mount (backwards compatible)
- Add WithMount(embed, "basedir") for subdirectory mounting
- Assets() deprecated, delegates to c.Mnt().Embed()
- Top-level core.go re-exports Mount, WithMount, Sub, ExtractOptions
- pkg/mnt still exists independently for standalone use
One import, one struct, methods on the struct:
import core "forge.lthn.ai/core/go"
c, _ := core.New(core.WithAssets(myEmbed))
c.Mnt().ReadString("templates/coding.md")
Co-Authored-By: Virgil <virgil@lethean.io>
- Replace all fmt.Errorf calls with coreerr.E() from go-log for structured
error context (op, msg, underlying error) across core.go, service_manager.go,
and runtime_pkg.go (12 violations fixed)
- Replace local Error type and E() in e.go with re-exports from go-log,
eliminating duplicate implementation while preserving public API
- Add comprehensive tests for pkg/log Service (NewService, OnStartup,
QueryLevel, TaskSetLevel) — coverage 72.2% → 87.8%
- Update CLAUDE.md: Go 1.25 → 1.26, runtime.go → runtime_pkg.go,
document go-log error convention
- No os.ReadFile/os.WriteFile violations found (all I/O uses go-io)
Co-Authored-By: Virgil <virgil@lethean.io>
Services implementing LocaleProvider have their locale FS collected
during RegisterService. The i18n service reads Core.Locales() on
startup to load all translations. Zero explicit wiring needed.
Co-Authored-By: Virgil <virgil@lethean.io>
Attribute-driven, database-backed Action scheduling for CorePHP.
#[Scheduled] attribute on Actions, auto-discovery via scanner,
persist to scheduled_actions table, runtime control via admin.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TDD plan for uptelligence AltumCode version detection + Claude Code
download skill. Covers VendorUpdateCheckerService, vendor seeding,
deployed version sync, and browser-automated download plugin.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two-layer system: uptelligence version detection (5 HTTP GETs)
+ Claude Code skill for browser-automated downloads from
LemonSqueezy (Playwright) and CodeCanyon (Chrome).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move Go MCP server from go-ai + PHP MCP from php-mcp into
a single core/mcp repo producing the core-mcp binary.
Co-Authored-By: Virgil <virgil@lethean.io>
Covers extracting app/Plug/* into 8 core/php-plug-* packages with
Core\Plug\* namespace alignment. Contracts move to core/php framework,
Registry gains register() method for package self-registration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restores the original package split for Plug providers that was
flattened during GitHub→Forge migration. Contracts move into core/php,
8 category packages (social, web3, content, chat, business, cdn,
storage, stock) become independent repos on forge.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full refactor plan: cli.Main() migration, DI services for P2P sync
and wallet, go-process daemon for headless mode, build config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Layer 1 only: core/lint repo with YAML catalog, pkg/lint library
(Rule, Catalog, Matcher, Scanner, Report), and core-lint CLI.
18 seed patterns from the Go ecosystem sweep.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three-layer system: core/lint (pattern catalog + regex matcher),
go-ai MCP subsystem (lint tools for agents), core/agent polish
skill (multi-AI review orchestration). Seeded with 18 patterns
from the Go ecosystem sweep.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>