feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
// Cli is the CLI surface layer for the Core command tree.
|
|
|
|
|
//
|
2026-03-24 19:24:17 +00:00
|
|
|
// c := core.New(core.WithOption("name", "myapp")).Value.(*Core)
|
|
|
|
|
// c.Command("deploy", core.Command{Action: handler})
|
2026-03-20 12:08:19 +00:00
|
|
|
// c.Cli().Run()
|
2026-03-18 01:43:03 +00:00
|
|
|
package core
|
|
|
|
|
|
|
|
|
|
import (
|
2026-03-20 12:17:30 +00:00
|
|
|
"io"
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
"os"
|
2026-03-18 01:43:03 +00:00
|
|
|
)
|
|
|
|
|
|
2026-03-24 19:48:12 +00:00
|
|
|
// CliOptions holds configuration for the Cli service.
|
|
|
|
|
type CliOptions struct{}
|
|
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
// Cli is the CLI surface for the Core command tree.
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
type Cli struct {
|
2026-03-24 19:48:12 +00:00
|
|
|
*ServiceRuntime[CliOptions]
|
2026-03-20 12:17:30 +00:00
|
|
|
output io.Writer
|
2026-03-20 12:08:19 +00:00
|
|
|
banner func(*Cli) string
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-24 19:48:12 +00:00
|
|
|
// Register creates a Cli service factory for core.WithService.
|
2026-03-24 19:26:44 +00:00
|
|
|
//
|
2026-03-24 19:48:12 +00:00
|
|
|
// core.New(core.WithService(core.CliRegister))
|
|
|
|
|
func CliRegister(c *Core) Result {
|
|
|
|
|
cl := &Cli{output: os.Stdout}
|
|
|
|
|
cl.ServiceRuntime = NewServiceRuntime[CliOptions](c, CliOptions{})
|
|
|
|
|
return c.RegisterService("cli", cl)
|
2026-03-24 19:26:44 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:17:30 +00:00
|
|
|
// Print writes to the CLI output (defaults to os.Stdout).
|
|
|
|
|
//
|
|
|
|
|
// c.Cli().Print("hello %s", "world")
|
|
|
|
|
func (cl *Cli) Print(format string, args ...any) {
|
2026-03-20 12:20:36 +00:00
|
|
|
Print(cl.output, format, args...)
|
2026-03-20 12:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetOutput sets the CLI output writer.
|
|
|
|
|
//
|
|
|
|
|
// c.Cli().SetOutput(os.Stderr)
|
|
|
|
|
func (cl *Cli) SetOutput(w io.Writer) {
|
|
|
|
|
cl.output = w
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
// Run resolves os.Args to a command path and executes it.
|
|
|
|
|
//
|
|
|
|
|
// c.Cli().Run()
|
|
|
|
|
// c.Cli().Run("deploy", "to", "homelab")
|
2026-03-20 13:30:22 +00:00
|
|
|
func (cl *Cli) Run(args ...string) Result {
|
2026-03-20 12:08:19 +00:00
|
|
|
if len(args) == 0 {
|
|
|
|
|
args = os.Args[1:]
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:15:57 +00:00
|
|
|
clean := FilterArgs(args)
|
2026-03-24 19:48:12 +00:00
|
|
|
c := cl.Core()
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
|
2026-03-24 19:48:12 +00:00
|
|
|
if c == nil || c.commands == nil {
|
2026-03-20 17:35:09 +00:00
|
|
|
if cl.banner != nil {
|
|
|
|
|
cl.Print(cl.banner(cl))
|
|
|
|
|
}
|
|
|
|
|
return Result{}
|
|
|
|
|
}
|
|
|
|
|
|
feat: implement RFC plans 1-5 — Registry[T], Action/Task, Process, primitives
Plans 1-5 complete for core/go scope. 456 tests, 84.4% coverage, 100% AX-7 naming.
Critical bugs (Plan 1):
- P4-3+P7-3: ACTION broadcast calls all handlers with panic recovery
- P7-2+P7-4: RunE() with defer ServiceShutdown, Run() delegates
- P3-1: Startable/Stoppable return Result (breaking, clean)
- P9-1: Zero os/exec — App.Find() rewritten with os.Stat+PATH
- I3: Embed() removed, I15: New() comment fixed
- I9: CommandLifecycle removed → Command.Managed field
Registry[T] (Plan 2):
- Universal thread-safe named collection with 3 lock modes
- All 5 registries migrated: services, commands, drive, data, lock
- Insertion order preserved (fixes P4-1)
- c.RegistryOf("name") cross-cutting accessor
Action/Task system (Plan 3):
- Action type with Run()/Exists(), ActionHandler signature
- c.Action("name") dual-purpose accessor (register/invoke)
- TaskDef with Steps — sequential chain, async dispatch, previous-input piping
- Panic recovery on all Action execution
- broadcast() internal, ACTION() sugar
Process primitive (Plan 4):
- c.Process() returns Action sugar — Run/RunIn/RunWithEnv/Start/Kill/Exists
- No deps added — delegates to c.Action("process.*")
- Permission-by-registration: no handler = no capability
Missing primitives (Plan 5):
- core.ID() — atomic counter + crypto/rand suffix
- ValidateName() / SanitisePath() — reusable validation
- Fs.WriteAtomic() — write-to-temp-then-rename
- Fs.NewUnrestricted() / Fs.Root() — legitimate sandbox bypass
- AX-7: 456/456 tests renamed to TestFile_Function_{Good,Bad,Ugly}
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 15:18:25 +00:00
|
|
|
if c.commands.Len() == 0 {
|
2026-03-20 12:08:19 +00:00
|
|
|
if cl.banner != nil {
|
2026-03-20 12:17:30 +00:00
|
|
|
cl.Print(cl.banner(cl))
|
2026-03-20 12:08:19 +00:00
|
|
|
}
|
2026-03-20 13:30:22 +00:00
|
|
|
return Result{}
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
// Resolve command path from args
|
|
|
|
|
var cmd *Command
|
|
|
|
|
var remaining []string
|
|
|
|
|
|
|
|
|
|
for i := len(clean); i > 0; i-- {
|
2026-03-20 12:23:05 +00:00
|
|
|
path := JoinPath(clean[:i]...)
|
feat: implement RFC plans 1-5 — Registry[T], Action/Task, Process, primitives
Plans 1-5 complete for core/go scope. 456 tests, 84.4% coverage, 100% AX-7 naming.
Critical bugs (Plan 1):
- P4-3+P7-3: ACTION broadcast calls all handlers with panic recovery
- P7-2+P7-4: RunE() with defer ServiceShutdown, Run() delegates
- P3-1: Startable/Stoppable return Result (breaking, clean)
- P9-1: Zero os/exec — App.Find() rewritten with os.Stat+PATH
- I3: Embed() removed, I15: New() comment fixed
- I9: CommandLifecycle removed → Command.Managed field
Registry[T] (Plan 2):
- Universal thread-safe named collection with 3 lock modes
- All 5 registries migrated: services, commands, drive, data, lock
- Insertion order preserved (fixes P4-1)
- c.RegistryOf("name") cross-cutting accessor
Action/Task system (Plan 3):
- Action type with Run()/Exists(), ActionHandler signature
- c.Action("name") dual-purpose accessor (register/invoke)
- TaskDef with Steps — sequential chain, async dispatch, previous-input piping
- Panic recovery on all Action execution
- broadcast() internal, ACTION() sugar
Process primitive (Plan 4):
- c.Process() returns Action sugar — Run/RunIn/RunWithEnv/Start/Kill/Exists
- No deps added — delegates to c.Action("process.*")
- Permission-by-registration: no handler = no capability
Missing primitives (Plan 5):
- core.ID() — atomic counter + crypto/rand suffix
- ValidateName() / SanitisePath() — reusable validation
- Fs.WriteAtomic() — write-to-temp-then-rename
- Fs.NewUnrestricted() / Fs.Root() — legitimate sandbox bypass
- AX-7: 456/456 tests renamed to TestFile_Function_{Good,Bad,Ugly}
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 15:18:25 +00:00
|
|
|
if r := c.commands.Get(path); r.OK {
|
|
|
|
|
cmd = r.Value.(*Command)
|
2026-03-20 12:08:19 +00:00
|
|
|
remaining = clean[i:]
|
|
|
|
|
break
|
|
|
|
|
}
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
if cmd == nil {
|
|
|
|
|
if cl.banner != nil {
|
2026-03-20 12:17:30 +00:00
|
|
|
cl.Print(cl.banner(cl))
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
2026-03-20 12:08:19 +00:00
|
|
|
cl.PrintHelp()
|
2026-03-20 13:30:22 +00:00
|
|
|
return Result{}
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
2026-03-20 12:08:19 +00:00
|
|
|
|
2026-03-20 12:17:30 +00:00
|
|
|
// Build options from remaining args
|
2026-03-24 19:17:12 +00:00
|
|
|
opts := NewOptions()
|
2026-03-20 12:08:19 +00:00
|
|
|
for _, arg := range remaining {
|
2026-03-20 12:15:57 +00:00
|
|
|
key, val, valid := ParseFlag(arg)
|
|
|
|
|
if valid {
|
2026-03-20 18:36:30 +00:00
|
|
|
if Contains(arg, "=") {
|
2026-03-24 19:17:12 +00:00
|
|
|
opts.Set(key, val)
|
2026-03-20 12:08:19 +00:00
|
|
|
} else {
|
2026-03-24 19:17:12 +00:00
|
|
|
opts.Set(key, true)
|
2026-03-20 12:08:19 +00:00
|
|
|
}
|
2026-03-20 12:24:39 +00:00
|
|
|
} else if !IsFlag(arg) {
|
2026-03-24 19:17:12 +00:00
|
|
|
opts.Set("_arg", arg)
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-20 18:48:02 +00:00
|
|
|
if cmd.Action != nil {
|
|
|
|
|
return cmd.Run(opts)
|
|
|
|
|
}
|
|
|
|
|
return Result{E("core.Cli.Run", Concat("command \"", cmd.Path, "\" is not executable"), nil), false}
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
// PrintHelp prints available commands.
|
|
|
|
|
//
|
|
|
|
|
// c.Cli().PrintHelp()
|
|
|
|
|
func (cl *Cli) PrintHelp() {
|
2026-03-24 19:48:12 +00:00
|
|
|
c := cl.Core()
|
|
|
|
|
if c == nil || c.commands == nil {
|
2026-03-20 12:08:19 +00:00
|
|
|
return
|
|
|
|
|
}
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
name := ""
|
2026-03-24 19:48:12 +00:00
|
|
|
if c.app != nil {
|
|
|
|
|
name = c.app.Name
|
2026-03-20 12:08:19 +00:00
|
|
|
}
|
|
|
|
|
if name != "" {
|
2026-03-20 12:17:30 +00:00
|
|
|
cl.Print("%s commands:", name)
|
2026-03-20 12:08:19 +00:00
|
|
|
} else {
|
2026-03-20 12:17:30 +00:00
|
|
|
cl.Print("Commands:")
|
2026-03-20 12:08:19 +00:00
|
|
|
}
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
|
feat: implement RFC plans 1-5 — Registry[T], Action/Task, Process, primitives
Plans 1-5 complete for core/go scope. 456 tests, 84.4% coverage, 100% AX-7 naming.
Critical bugs (Plan 1):
- P4-3+P7-3: ACTION broadcast calls all handlers with panic recovery
- P7-2+P7-4: RunE() with defer ServiceShutdown, Run() delegates
- P3-1: Startable/Stoppable return Result (breaking, clean)
- P9-1: Zero os/exec — App.Find() rewritten with os.Stat+PATH
- I3: Embed() removed, I15: New() comment fixed
- I9: CommandLifecycle removed → Command.Managed field
Registry[T] (Plan 2):
- Universal thread-safe named collection with 3 lock modes
- All 5 registries migrated: services, commands, drive, data, lock
- Insertion order preserved (fixes P4-1)
- c.RegistryOf("name") cross-cutting accessor
Action/Task system (Plan 3):
- Action type with Run()/Exists(), ActionHandler signature
- c.Action("name") dual-purpose accessor (register/invoke)
- TaskDef with Steps — sequential chain, async dispatch, previous-input piping
- Panic recovery on all Action execution
- broadcast() internal, ACTION() sugar
Process primitive (Plan 4):
- c.Process() returns Action sugar — Run/RunIn/RunWithEnv/Start/Kill/Exists
- No deps added — delegates to c.Action("process.*")
- Permission-by-registration: no handler = no capability
Missing primitives (Plan 5):
- core.ID() — atomic counter + crypto/rand suffix
- ValidateName() / SanitisePath() — reusable validation
- Fs.WriteAtomic() — write-to-temp-then-rename
- Fs.NewUnrestricted() / Fs.Root() — legitimate sandbox bypass
- AX-7: 456/456 tests renamed to TestFile_Function_{Good,Bad,Ugly}
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 15:18:25 +00:00
|
|
|
c.commands.Each(func(path string, cmd *Command) {
|
|
|
|
|
if cmd.Hidden || (cmd.Action == nil && !cmd.IsManaged()) {
|
|
|
|
|
return
|
2026-03-20 12:08:19 +00:00
|
|
|
}
|
2026-03-24 19:48:12 +00:00
|
|
|
tr := c.I18n().Translate(cmd.I18nKey())
|
2026-03-20 17:20:08 +00:00
|
|
|
desc, _ := tr.Value.(string)
|
|
|
|
|
if desc == "" || desc == cmd.I18nKey() {
|
2026-03-20 12:17:30 +00:00
|
|
|
cl.Print(" %s", path)
|
2026-03-20 12:08:19 +00:00
|
|
|
} else {
|
2026-03-20 12:17:30 +00:00
|
|
|
cl.Print(" %-30s %s", path, desc)
|
2026-03-20 12:08:19 +00:00
|
|
|
}
|
feat: implement RFC plans 1-5 — Registry[T], Action/Task, Process, primitives
Plans 1-5 complete for core/go scope. 456 tests, 84.4% coverage, 100% AX-7 naming.
Critical bugs (Plan 1):
- P4-3+P7-3: ACTION broadcast calls all handlers with panic recovery
- P7-2+P7-4: RunE() with defer ServiceShutdown, Run() delegates
- P3-1: Startable/Stoppable return Result (breaking, clean)
- P9-1: Zero os/exec — App.Find() rewritten with os.Stat+PATH
- I3: Embed() removed, I15: New() comment fixed
- I9: CommandLifecycle removed → Command.Managed field
Registry[T] (Plan 2):
- Universal thread-safe named collection with 3 lock modes
- All 5 registries migrated: services, commands, drive, data, lock
- Insertion order preserved (fixes P4-1)
- c.RegistryOf("name") cross-cutting accessor
Action/Task system (Plan 3):
- Action type with Run()/Exists(), ActionHandler signature
- c.Action("name") dual-purpose accessor (register/invoke)
- TaskDef with Steps — sequential chain, async dispatch, previous-input piping
- Panic recovery on all Action execution
- broadcast() internal, ACTION() sugar
Process primitive (Plan 4):
- c.Process() returns Action sugar — Run/RunIn/RunWithEnv/Start/Kill/Exists
- No deps added — delegates to c.Action("process.*")
- Permission-by-registration: no handler = no capability
Missing primitives (Plan 5):
- core.ID() — atomic counter + crypto/rand suffix
- ValidateName() / SanitisePath() — reusable validation
- Fs.WriteAtomic() — write-to-temp-then-rename
- Fs.NewUnrestricted() / Fs.Root() — legitimate sandbox bypass
- AX-7: 456/456 tests renamed to TestFile_Function_{Good,Bad,Ugly}
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 15:18:25 +00:00
|
|
|
})
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
// SetBanner sets the banner function.
|
|
|
|
|
//
|
|
|
|
|
// c.Cli().SetBanner(func(_ *core.Cli) string { return "My App v1.0" })
|
|
|
|
|
func (cl *Cli) SetBanner(fn func(*Cli) string) {
|
|
|
|
|
cl.banner = fn
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-20 12:08:19 +00:00
|
|
|
// Banner returns the banner string.
|
|
|
|
|
func (cl *Cli) Banner() string {
|
|
|
|
|
if cl.banner != nil {
|
|
|
|
|
return cl.banner(cl)
|
|
|
|
|
}
|
2026-03-24 19:48:12 +00:00
|
|
|
c := cl.Core()
|
|
|
|
|
if c != nil && c.app != nil && c.app.Name != "" {
|
|
|
|
|
return c.app.Name
|
2026-03-20 12:08:19 +00:00
|
|
|
}
|
|
|
|
|
return ""
|
feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00
|
|
|
}
|