2026-03-16 11:10:33 +00:00
// SPDX-License-Identifier: EUPL-1.2
package agentic
import (
"os"
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
"strconv"
2026-03-16 11:10:33 +00:00
"syscall"
"time"
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
core "dappco.re/go/core"
2026-03-16 11:10:33 +00:00
"gopkg.in/yaml.v3"
)
// DispatchConfig controls agent dispatch behaviour.
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
//
// cfg := agentic.DispatchConfig{DefaultAgent: "claude", DefaultTemplate: "coding"}
2026-03-16 11:10:33 +00:00
type DispatchConfig struct {
DefaultAgent string ` yaml:"default_agent" `
DefaultTemplate string ` yaml:"default_template" `
WorkspaceRoot string ` yaml:"workspace_root" `
}
// RateConfig controls pacing between task dispatches.
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
//
// rate := agentic.RateConfig{ResetUTC: "06:00", SustainedDelay: 120, BurstWindow: 2, BurstDelay: 15}
2026-03-16 11:10:33 +00:00
type RateConfig struct {
ResetUTC string ` yaml:"reset_utc" ` // Daily quota reset time (UTC), e.g. "06:00"
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
DailyLimit int ` yaml:"daily_limit" ` // Max requests per day (0 = unknown)
MinDelay int ` yaml:"min_delay" ` // Minimum seconds between task starts
SustainedDelay int ` yaml:"sustained_delay" ` // Delay when pacing for full-day use
BurstWindow int ` yaml:"burst_window" ` // Hours before reset where burst kicks in
BurstDelay int ` yaml:"burst_delay" ` // Delay during burst window
2026-03-16 11:10:33 +00:00
}
// AgentsConfig is the root of config/agents.yaml.
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
//
// cfg := agentic.AgentsConfig{Version: 1, Dispatch: agentic.DispatchConfig{DefaultAgent: "claude"}}
2026-03-16 11:10:33 +00:00
type AgentsConfig struct {
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
Version int ` yaml:"version" `
Dispatch DispatchConfig ` yaml:"dispatch" `
Concurrency map [ string ] int ` yaml:"concurrency" `
2026-03-16 11:10:33 +00:00
Rates map [ string ] RateConfig ` yaml:"rates" `
}
// loadAgentsConfig reads config/agents.yaml from the code path.
func ( s * PrepSubsystem ) loadAgentsConfig ( ) * AgentsConfig {
paths := [ ] string {
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
core . JoinPath ( CoreRoot ( ) , "agents.yaml" ) ,
core . JoinPath ( s . codePath , "core" , "agent" , "config" , "agents.yaml" ) ,
2026-03-16 11:10:33 +00:00
}
for _ , path := range paths {
2026-03-22 03:41:07 +00:00
r := fs . Read ( path )
if ! r . OK {
2026-03-16 11:10:33 +00:00
continue
}
var cfg AgentsConfig
2026-03-22 03:41:07 +00:00
if err := yaml . Unmarshal ( [ ] byte ( r . Value . ( string ) ) , & cfg ) ; err != nil {
2026-03-16 11:10:33 +00:00
continue
}
return & cfg
}
return & AgentsConfig {
Dispatch : DispatchConfig {
DefaultAgent : "claude" ,
DefaultTemplate : "coding" ,
} ,
Concurrency : map [ string ] int {
"claude" : 1 ,
"gemini" : 3 ,
} ,
}
}
// delayForAgent calculates how long to wait before spawning the next task
// for a given agent type, based on rate config and time of day.
func ( s * PrepSubsystem ) delayForAgent ( agent string ) time . Duration {
cfg := s . loadAgentsConfig ( )
2026-03-21 16:05:59 +00:00
// Strip variant suffix (claude:opus → claude) for config lookup
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
base := baseAgent ( agent )
2026-03-21 16:05:59 +00:00
rate , ok := cfg . Rates [ base ]
2026-03-16 11:10:33 +00:00
if ! ok || rate . SustainedDelay == 0 {
return 0
}
// Parse reset time
resetHour , resetMin := 6 , 0
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
parts := core . Split ( rate . ResetUTC , ":" )
if len ( parts ) >= 2 {
if hour , err := strconv . Atoi ( core . Trim ( parts [ 0 ] ) ) ; err == nil {
resetHour = hour
}
if min , err := strconv . Atoi ( core . Trim ( parts [ 1 ] ) ) ; err == nil {
resetMin = min
}
}
2026-03-16 11:10:33 +00:00
now := time . Now ( ) . UTC ( )
resetToday := time . Date ( now . Year ( ) , now . Month ( ) , now . Day ( ) , resetHour , resetMin , 0 , 0 , time . UTC )
if now . Before ( resetToday ) {
// Reset hasn't happened yet today — reset was yesterday
resetToday = resetToday . AddDate ( 0 , 0 , - 1 )
}
nextReset := resetToday . AddDate ( 0 , 0 , 1 )
hoursUntilReset := nextReset . Sub ( now ) . Hours ( )
// Burst mode: if within burst window of reset, use burst delay
if rate . BurstWindow > 0 && hoursUntilReset <= float64 ( rate . BurstWindow ) {
return time . Duration ( rate . BurstDelay ) * time . Second
}
// Sustained mode
return time . Duration ( rate . SustainedDelay ) * time . Second
}
// countRunningByAgent counts running workspaces for a specific agent type.
func ( s * PrepSubsystem ) countRunningByAgent ( agent string ) int {
2026-03-17 18:13:44 +00:00
wsRoot := WorkspaceRoot ( )
2026-03-16 11:10:33 +00:00
refactor(agentic): route file I/O through core.Fs
Replace raw os.* file operations with Core Fs equivalents:
- os.Stat → fs.Exists/fs.IsFile/fs.IsDir (resume, pr, plan, mirror, prep)
- os.ReadDir → fs.List (queue, status, plan, mirror, review_queue)
- os.Remove → fs.Delete (dispatch)
- os.OpenFile(append) → fs.Append (events, review_queue)
- strings.Replace → core.Replace (scan)
Eliminates os import from resume.go, pr.go. Eliminates strings
import from scan.go. Trades os for io in events.go.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 09:08:45 +00:00
r := fs . List ( wsRoot )
if ! r . OK {
2026-03-16 11:10:33 +00:00
return 0
}
refactor(agentic): route file I/O through core.Fs
Replace raw os.* file operations with Core Fs equivalents:
- os.Stat → fs.Exists/fs.IsFile/fs.IsDir (resume, pr, plan, mirror, prep)
- os.ReadDir → fs.List (queue, status, plan, mirror, review_queue)
- os.Remove → fs.Delete (dispatch)
- os.OpenFile(append) → fs.Append (events, review_queue)
- strings.Replace → core.Replace (scan)
Eliminates os import from resume.go, pr.go. Eliminates strings
import from scan.go. Trades os for io in events.go.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 09:08:45 +00:00
entries := r . Value . ( [ ] os . DirEntry )
2026-03-16 11:10:33 +00:00
count := 0
for _ , entry := range entries {
if ! entry . IsDir ( ) {
continue
}
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
st , err := readStatus ( core . JoinPath ( wsRoot , entry . Name ( ) ) )
2026-03-16 11:10:33 +00:00
if err != nil || st . Status != "running" {
continue
}
2026-03-17 19:35:15 +00:00
if baseAgent ( st . Agent ) != agent {
2026-03-16 11:10:33 +00:00
continue
}
2026-03-17 19:35:15 +00:00
if st . PID > 0 && syscall . Kill ( st . PID , 0 ) == nil {
count ++
2026-03-16 11:10:33 +00:00
}
}
return count
}
// baseAgent strips the model variant (gemini:flash → gemini).
func baseAgent ( agent string ) string {
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
return core . SplitN ( agent , ":" , 2 ) [ 0 ]
2026-03-16 11:10:33 +00:00
}
// canDispatchAgent checks if we're under the concurrency limit for a specific agent type.
func ( s * PrepSubsystem ) canDispatchAgent ( agent string ) bool {
cfg := s . loadAgentsConfig ( )
base := baseAgent ( agent )
limit , ok := cfg . Concurrency [ base ]
if ! ok || limit <= 0 {
return true
}
return s . countRunningByAgent ( base ) < limit
}
// drainQueue finds the oldest queued workspace and spawns it if a slot is available.
2026-03-21 17:10:43 +00:00
// Applies rate-based delay between spawns. Serialised via drainMu to prevent
// concurrent drainers from exceeding concurrency limits.
2026-03-16 11:10:33 +00:00
func ( s * PrepSubsystem ) drainQueue ( ) {
2026-03-21 17:10:43 +00:00
s . drainMu . Lock ( )
defer s . drainMu . Unlock ( )
2026-03-17 18:13:44 +00:00
wsRoot := WorkspaceRoot ( )
2026-03-16 11:10:33 +00:00
refactor(agentic): route file I/O through core.Fs
Replace raw os.* file operations with Core Fs equivalents:
- os.Stat → fs.Exists/fs.IsFile/fs.IsDir (resume, pr, plan, mirror, prep)
- os.ReadDir → fs.List (queue, status, plan, mirror, review_queue)
- os.Remove → fs.Delete (dispatch)
- os.OpenFile(append) → fs.Append (events, review_queue)
- strings.Replace → core.Replace (scan)
Eliminates os import from resume.go, pr.go. Eliminates strings
import from scan.go. Trades os for io in events.go.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 09:08:45 +00:00
r := fs . List ( wsRoot )
if ! r . OK {
2026-03-16 11:10:33 +00:00
return
}
refactor(agentic): route file I/O through core.Fs
Replace raw os.* file operations with Core Fs equivalents:
- os.Stat → fs.Exists/fs.IsFile/fs.IsDir (resume, pr, plan, mirror, prep)
- os.ReadDir → fs.List (queue, status, plan, mirror, review_queue)
- os.Remove → fs.Delete (dispatch)
- os.OpenFile(append) → fs.Append (events, review_queue)
- strings.Replace → core.Replace (scan)
Eliminates os import from resume.go, pr.go. Eliminates strings
import from scan.go. Trades os for io in events.go.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 09:08:45 +00:00
entries := r . Value . ( [ ] os . DirEntry )
2026-03-16 11:10:33 +00:00
for _ , entry := range entries {
if ! entry . IsDir ( ) {
continue
}
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
wsDir := core . JoinPath ( wsRoot , entry . Name ( ) )
2026-03-16 11:10:33 +00:00
st , err := readStatus ( wsDir )
if err != nil || st . Status != "queued" {
continue
}
if ! s . canDispatchAgent ( st . Agent ) {
continue
}
// Apply rate delay before spawning
delay := s . delayForAgent ( st . Agent )
if delay > 0 {
time . Sleep ( delay )
}
// Re-check concurrency after delay (another task may have started)
if ! s . canDispatchAgent ( st . Agent ) {
continue
}
refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package
All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli
Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00
srcDir := core . JoinPath ( wsDir , "src" )
2026-03-21 16:36:26 +00:00
prompt := "Read PROMPT.md for instructions. All context files (CLAUDE.md, TODO.md, CONTEXT.md, CONSUMERS.md, RECENT.md) are in the current directory. Work in this directory."
2026-03-16 11:10:33 +00:00
2026-03-16 17:52:55 +00:00
pid , _ , err := s . spawnAgent ( st . Agent , prompt , wsDir , srcDir )
2026-03-16 11:10:33 +00:00
if err != nil {
continue
}
st . Status = "running"
2026-03-16 17:52:55 +00:00
st . PID = pid
2026-03-16 11:10:33 +00:00
st . Runs ++
writeStatus ( wsDir , st )
return
}
}