Snider
7e2783dcf5
feat: add core.Path() + core.Env() fallthrough + PathGlob/PathIsAbs/CleanPath
...
Path() builds OS-aware absolute paths using Env("DS") — single point
of responsibility for filesystem paths. Relative paths anchor to
DIR_HOME. cleanPath resolves .. and double separators.
Env() now falls through to os.Getenv for unknown keys — universal
replacement for os.Getenv. Core keys (OS, DIR_HOME, etc.) take
precedence, arbitrary env vars pass through.
New exports: Path, PathBase, PathDir, PathExt, PathIsAbs, PathGlob,
CleanPath. Info init moved to init() so Path() can be used during
population without init cycle. DIR_HOME respects CORE_HOME env var
override for agent workspace sandboxing.
13 path tests, 17 env tests — all passing.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 09:50:50 +00:00
Snider
8c2b9c2506
feat: add core.Env() — read-only system information registry
...
Env is environment, Config is ours. Provides centralised access to
system facts (OS, ARCH, hostname, user, directories, timestamps)
via string key lookup, populated once at package init.
Keys: OS, ARCH, GO, DS, PS, HOSTNAME, USER, PID, NUM_CPU,
DIR_HOME, DIR_CONFIG, DIR_CACHE, DIR_DATA, DIR_TMP, DIR_CWD,
DIR_DOWNLOADS, DIR_CODE, CORE_START.
17 tests covering all keys + unknown key + Core instance accessor.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 09:08:26 +00:00
a06b779e3c
Merge pull request '[agent/claude] Review the README.md and docs/ directory. Verify all code ex...' ( #20 ) from agent/review-the-readme-md-and-docs--directory into main
CI / test (push) Failing after 5s
2026-03-21 11:10:43 +00:00
Snider
77780812cf
docs: rewrite CLAUDE.md for current API, remove stale AGENTS.md
...
CLAUDE.md now documents the DTO/Options/Result pattern.
AGENTS.md was a copy of old CLAUDE.md with wrong API patterns.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 10:07:05 +00:00
Snider
2d52b83f60
docs: rewrite documentation suite against AX spec
...
Codex-authored docs covering primitives, commands, messaging,
lifecycle, subsystems, and getting started — all using the current
DTO/Options/Result API with concrete usage examples.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 10:05:04 +00:00
df1576b101
Merge pull request #11 from dAppCore/dev
...
fix: strip module prefix from coverage paths for Codecov
2026-03-21 09:17:10 +00:00
Snider
954cd714a1
fix: strip module prefix from coverage paths for Codecov
...
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 09:16:24 +00:00
76f8ae41b9
Merge pull request #10 from dAppCore/dev
...
fix: add Codecov token to CI workflow
2026-03-21 09:13:42 +00:00
Snider
b01b7f4d88
fix: add Codecov token to CI workflow
...
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 09:12:39 +00:00
397ec2cec5
Merge pull request #9 from dAppCore/dev
...
docs: rewrite README + add CI/Codecov
2026-03-21 09:00:56 +00:00
Snider
01135ac8bd
docs: rewrite README + add CI workflow with Codecov
...
README reflects current API — DI framework, not the old CLI/GUI app.
CI runs tests with coverage on push to main.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 09:00:13 +00:00
3bf175b3d1
Merge pull request #8 from dAppCore/dev
...
refactor: flatten polyglot layout to standard Go module
2026-03-21 08:27:52 +00:00
Snider
fbd646456a
refactor: flatten polyglot layout to standard Go module
...
Move source from go/core/ to root, tests from go/tests/ to tests/.
Module path dappco.re/go/core resolves cleanly — builds and tests pass.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-21 08:27:14 +00:00
3642a819f1
Merge pull request #7 from dAppCore/dev
...
go update
2026-03-21 06:26:52 +00:00
Snider
2fa8b32db2
go update
2026-03-21 06:25:59 +00:00
8de5e20ab5
Merge pull request #6 from dAppCore/dev
...
go update
2026-03-20 21:36:22 +00:00
Snider
3e507c9813
go update
2026-03-20 21:35:22 +00:00
6942a019cb
Merge pull request #5 from dAppCore/dev
...
go update
2026-03-20 21:23:40 +00:00
Snider
104416676b
go update
2026-03-20 21:14:38 +00:00
dcf677309d
Merge pull request #4 from dAppCore/dev
...
go update
2026-03-20 21:06:05 +00:00
Snider
b34899ca00
go update
2026-03-20 21:00:48 +00:00
d6dada1461
Merge pull request #3 from dAppCore/dev
...
chore: module path update
2026-03-20 20:43:16 +00:00
Snider
1728c2930c
refactor: update imports from forge.lthn.ai/core/go to dappco.re/go/core
...
All .go imports, test fixtures, and embed.go code generation updated
to match the new module path.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 20:16:38 +00:00
Snider
41c50da68b
go update
2026-03-20 19:58:41 +00:00
cee07f05dd
Merge pull request #2 from dAppCore/dev
...
feat: AX audit + Codex review — polish pass
2026-03-20 18:52:43 +00:00
Snider
73eed891ca
fix: CodeRabbit re-review — 3 findings resolved
...
- cli: dispatch through Start for lifecycle-backed commands
- command: reject empty/malformed path segments
- error: fix typo CauseorJoin → ErrorJoin in doc comment
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 18:48:02 +00:00
Snider
af6b618196
fix: CodeRabbit review — 7 findings resolved
...
- cli: preserve explicit empty flag values (--name=)
- cli: skip placeholder commands in help output
- command: fail fast on non-executable placeholder Run
- command: lifecycle-backed commands count as registered
- runtime: wrap non-error OnStop payloads in error
- fs: error on protected path deletion (was silent Result{})
- error: log crash report I/O failures instead of swallowing
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 18:36:30 +00:00
Snider
e17217a630
refactor: camelCase — waitgroup → waitGroup
...
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 18:03:31 +00:00
Snider
d5f295cb7d
refactor: AX naming — wg → waitgroup, ctx → context
...
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 18:02:07 +00:00
Snider
bde8d4c7cc
feat: lifecycle context — Core.Context() for cooperative shutdown
...
- Core holds context.Context + CancelFunc
- New() creates background context
- ServiceStartup creates fresh context from caller's ctx (restart safe)
- ServiceShutdown cancels context before draining tasks
- c.Context() accessor lets task handlers check Done() for graceful exit
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 17:59:43 +00:00
Snider
629adb056b
fix: lifecycle — clear shutdown flag on startup, document waiter goroutine
...
- ServiceStartup clears c.shutdown so Core supports restart cycles
- ServiceShutdown waiter goroutine documented as inherent to sync.WaitGroup
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 17:56:21 +00:00
Snider
61b034335a
fix: Codex review round 4 — panic recovery, subtree preservation
...
- PerformAsync: defer/recover wraps task execution, broadcasts error on panic
- Command: preserve existing subtree when overwriting placeholder parent
Remaining known architectural:
- fs.go TOCTOU (needs openat/fd-based ops)
- Global lockMap (needs per-Core registry)
- ServiceShutdown goroutine on timeout (inherent to wg.Wait)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 17:52:48 +00:00
Snider
ee9e715243
fix: Codex review round 3 — 5 remaining findings
...
- Command: allow overwriting auto-created parent placeholders
- NewWithFactories: wrap original factory error cause
- I18n.SetTranslator: reapply saved locale to new translator
- Options/Drive: copy slices on intake (prevent aliasing)
- Embed.path: returns Result, rejects traversal with error
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 17:46:47 +00:00
Snider
bf1f8e51ad
fix: Codex review round 2 — path traversal, shutdown order, races
...
High:
- embed.Extract: safePath validates all rendered paths stay under targetDir
- embed.path: reject .. traversal on arbitrary fs.FS
- ServiceShutdown: drain background tasks BEFORE stopping services
Medium:
- cli.Run: command lookup holds registry RLock (race fix)
- NewWithFactories: propagate factory/registration failures
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 17:35:09 +00:00
Snider
4c3a671b48
fix: Codex review — medium/low severity issues resolved
...
Medium:
- Config zero-value safe (nil ConfigOptions guards on all mutators)
- ServiceShutdown collects and returns first OnStop error
- Default logger uses atomic.Pointer (race fix)
- Command registration rejects duplicates (like Service)
Low:
- Array.AsSlice returns copy, not backing slice
- fs.validatePath constructs error on sandbox escape (was nil)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 17:25:12 +00:00
Snider
f1bd36db2e
fix(critical): Codex review — 7 high-severity issues resolved
...
Critical:
- Result.Result() zero args returns receiver instead of panicking
High:
- i18n.SetLanguage: added mutex, forwards to translator
- embed.GetAsset: hold RLock through assets map read (race fix)
- cli.PrintHelp: safe type assertion on Translate result
- task.PerformAsync: guard nil task in reflect.TypeOf
- Service/Command registries initialised in New() (race fix)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 17:20:08 +00:00
Snider
bc06480b58
fix: AX audit round 7 — Err.Err renamed to Err.Cause
...
Remaining 32 Rule 1 violations are valid but not P0:
- Subsystem accessors returning typed pointers (fluent API)
- Error creators returning error (should return Result)
- Void fire-and-forget operations (Must, Progress, Log)
- Iterator returning iter.Seq (should use modern Go patterns)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 16:54:27 +00:00
Snider
2f39e8e1f4
fix: AX audit round 6 — Result returns, naming, literal style
...
- Data.Get, Drive.Get → Result (was typed pointers)
- I18n.Translator, I18n.Locales → Result
- Translator interface: Translate returns Result
- Array.Filter → Result, Core.Embed → Result
- Embed.BaseDir → BaseDirectory
- TaskState.ID → Identifier, SetTaskIdentifier method fix
- fs.go: Result{nil, true} → Result{OK: true} (5 lines)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 16:46:39 +00:00
Snider
298322ed89
fix: AX audit round 5 — full naming, Result returns throughout
...
Renames (via GoLand refactor):
- Option.K → Key, Option.V → Value
- Err.Op → Operation, Err.Msg → Message, Err.Err → Error
- CrashSystem.OS → OperatingSystem, Arch → Architecture
- TaskID → TaskIdentifier, TaskWithID → TaskWithIdentifier
- Ipc → IPC, BaseDir → BaseDirectory
- ServiceRuntime.Opts → Options
Return type changes:
- Options.Get, Config.Get → Result (was (any, bool))
- Embed.ReadDir → Result (was ([]fs.DirEntry, error))
- Translator.Translate, I18n.Translate → Result (was string)
Rule 6:
- data.go: propagate opts.Get failure, typed error for bad fs.FS
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 16:32:43 +00:00
Snider
cf25af1a13
fix: AX audit round 4 — semantic naming, Result returns
...
- Op → Operation, AllOps → AllOperations (no abbreviations)
- Translator.T → Translator.Translate (avoids testing.T confusion)
- Lock.Mu → Lock.Mutex, ServiceRuntime.Opts → .Options
- ErrorLog.Error/Warn return Result instead of error
- ErrorPanic.Reports returns Result instead of ([]CrashReport, error)
- Core.LogError/LogWarn simplified to passthrough
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 16:00:41 +00:00
Snider
b2d0deb99b
fix: AX audit round 3 — 8 violations resolved
...
- core.go: Result{Value: wrapped} → Result{wrapped, false} (explicit failure)
- error.go: fmt.Sprint → Sprint wrapper, removed fmt import
- fs.go: Stat/Open propagate validatePath failures (return vp)
- lock.go: Startables/Stoppables return Result
- task.go: PerformAsync returns Result
- runtime.go: updated to unwrap Result from Startables/Stoppables
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 15:49:33 +00:00
Snider
8801e2ea10
fix: final AX audit — 9 remaining violations resolved
...
- fs.go: propagate validatePath failures (return vp) instead of bare Result{}
- app.go: Find() returns Result instead of *App
- log.go: fmt import removed — uses Sprint/Sprintf/Print from string.go/utils.go
- string.go: added Sprint() and Sprintf() wrappers for any-to-string formatting
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 15:43:19 +00:00
Snider
f8e1459bd1
fix: AX audit — eloquent Result literals, renamed abbreviations, error propagation
...
- Result{x, true} positional literals replace verbose Result{Value: x, OK: true}
- Result{err, false} replaces bare Result{} where errors were swallowed
- ErrCode → ErrorCode, LogPan → LogPanic (no abbreviations)
- NewBuilder()/NewReader() wrappers in string.go, removed strings import from embed.go
- fmt.Errorf in log.go replaced with NewError(fmt.Sprint(...))
- 14 files, 66 audit violations resolved
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 15:36:33 +00:00
Snider
a845866c25
fix: embed.go Result{}.Result() pattern + utils test coverage
...
- embed.go: replace 27 manual Result{} constructions with Result{}.Result()
— errors now propagate instead of being silently swallowed
- utils_test.go: add 22 tests for IsFlag, Arg, ArgString, ArgInt, ArgBool,
and Result.Result() (252 tests, 78.8% coverage)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 15:25:37 +00:00
Snider
b0ec660e78
fix: fs.go use Result{}.Result() return value, i18n uses i.locale
...
fs.go: Value receiver Result() returns new Result — must use return
value not discard it. Changed from r.Result(...); return *r to
return Result{}.Result(os.ReadDir(...)).
i18n: SetLanguage sets i.locale directly. Language() reads i.locale.
Translator reload is core/go-i18n's responsibility.
231 tests passing.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 15:13:36 +00:00
Snider
9bcb367dd0
feat: Command() and i18n.SetLanguage() return Result
...
Command(path, Command{Action: handler}) — typed struct input, Result output.
Command fields exported: Name, Description, Path, Action, Lifecycle, Flags, Hidden.
i18n.SetLanguage returns Result instead of error.
All public methods across core/go now return Result where applicable.
231 tests, 76.5% coverage.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 14:44:29 +00:00
Snider
3bab201229
feat: fs.go returns Result throughout
...
All 14 public Fs methods return Result instead of (value, error).
validatePath returns Result internally.
Tests updated to use r.OK / r.Value pattern.
231 tests, 77.1% coverage.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 14:37:06 +00:00
Snider
7d34436fc6
feat: Result.Result() — unified get/set, AX pattern
...
Zero args returns Value. With args, sets Value from Go (value, error).
r.Result() // get
r.Result(file, err) // set — OK = err == nil
r.Result(value) // set — OK = true
One method. Get and set. Same pattern as Service(), Command().
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 14:33:26 +00:00
Snider
9161ed2a79
refactor: Result.New() and Result.Result() — pointer receiver, AX pattern
...
New() sets Value/OK on the receiver and returns *Result.
Result() returns the Value. Both pointer receivers.
r := &Result{}
r.New(file, err) // OK = err == nil
val := r.Result()
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 14:32:16 +00:00
Snider
01dec6dbe7
feat: Result.New() — maps Go (value, error) to Result
...
Result{}.New(file, err) // OK = err == nil, Value = file
Result{}.New(value) // OK = true, Value = value
Result{}.New() // OK = false
Enables: return Result{}.New(s.fsys.Open(path))
Replaces manual if err != nil { return Result{} } blocks.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-20 14:27:12 +00:00