2026-03-16 11:10:33 +00:00
// SPDX-License-Identifier: EUPL-1.2
2026-03-30 22:30:05 +00:00
// core.New(core.WithService(agentic.Register))
2026-03-16 11:10:33 +00:00
package agentic
import (
"context"
2026-04-01 18:28:42 +00:00
"crypto/sha256"
2026-03-16 11:10:33 +00:00
"encoding/base64"
2026-04-01 18:28:42 +00:00
"encoding/hex"
2026-03-21 17:10:43 +00:00
"sync"
2026-03-16 11:10:33 +00:00
"time"
2026-03-21 11:10:31 +00:00
"dappco.re/go/agent/pkg/lib"
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-22 14:15:41 +00:00
"dappco.re/go/core/forge"
2026-03-29 20:15:58 +00:00
coremcp "forge.lthn.ai/core/mcp/pkg/mcp"
2026-03-16 11:10:33 +00:00
"github.com/modelcontextprotocol/go-sdk/mcp"
)
2026-03-30 22:30:05 +00:00
// options := agentic.AgentOptions{}
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
type AgentOptions struct { }
2026-03-30 22:30:05 +00:00
// core.New(core.WithService(agentic.Register))
2026-03-16 11:10:33 +00:00
type PrepSubsystem struct {
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
* core . ServiceRuntime [ AgentOptions ]
2026-03-30 21:41:45 +00:00
forge * forge . Forge
forgeURL string
forgeToken string
brainURL string
brainKey string
codePath string
startupContext context . Context
2026-03-31 05:28:26 +00:00
dispatchMu sync . Mutex
2026-03-30 21:41:45 +00:00
drainMu sync . Mutex
pokeCh chan struct { }
frozen bool
2026-03-31 05:28:26 +00:00
backoff map [ string ] time . Time
failCount map [ string ] int
2026-04-02 07:18:38 +00:00
providers * ProviderManager
2026-03-31 05:28:26 +00:00
workspaces * core . Registry [ * WorkspaceStatus ]
2026-03-16 11:10:33 +00:00
}
2026-03-22 06:42:42 +00:00
var _ coremcp . Subsystem = ( * PrepSubsystem ) ( nil )
2026-03-30 22:30:05 +00:00
// subsystem := agentic.NewPrep()
// subsystem.SetCompletionNotifier(monitor)
2026-03-16 11:10:33 +00:00
func NewPrep ( ) * PrepSubsystem {
2026-03-30 18:52:15 +00:00
home := HomeDir ( )
2026-03-16 11:10:33 +00:00
refactor(agentic): adopt core.Env() + core.Path() across package
Replace all os.UserHomeDir/os.Getenv/os.Hostname with core.Env().
Replace all filepath.Base/Dir/Glob/IsAbs with core.PathBase/PathDir/
PathGlob/PathIsAbs.
10 files migrated: paths, prep, review_queue, remote, dispatch,
ingest, mirror, plan, verify, watch.
Imports eliminated: 5x os, 7x filepath. All file I/O and path
construction now routes through Core primitives.
Bumps dappco.re/go/core to v0.6.0.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 10:15:15 +00:00
forgeToken := core . Env ( "FORGE_TOKEN" )
2026-03-16 11:10:33 +00:00
if forgeToken == "" {
refactor(agentic): adopt core.Env() + core.Path() across package
Replace all os.UserHomeDir/os.Getenv/os.Hostname with core.Env().
Replace all filepath.Base/Dir/Glob/IsAbs with core.PathBase/PathDir/
PathGlob/PathIsAbs.
10 files migrated: paths, prep, review_queue, remote, dispatch,
ingest, mirror, plan, verify, watch.
Imports eliminated: 5x os, 7x filepath. All file I/O and path
construction now routes through Core primitives.
Bumps dappco.re/go/core to v0.6.0.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 10:15:15 +00:00
forgeToken = core . Env ( "GITEA_TOKEN" )
2026-03-16 11:10:33 +00:00
}
refactor(agentic): adopt core.Env() + core.Path() across package
Replace all os.UserHomeDir/os.Getenv/os.Hostname with core.Env().
Replace all filepath.Base/Dir/Glob/IsAbs with core.PathBase/PathDir/
PathGlob/PathIsAbs.
10 files migrated: paths, prep, review_queue, remote, dispatch,
ingest, mirror, plan, verify, watch.
Imports eliminated: 5x os, 7x filepath. All file I/O and path
construction now routes through Core primitives.
Bumps dappco.re/go/core to v0.6.0.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 10:15:15 +00:00
brainKey := core . Env ( "CORE_BRAIN_KEY" )
2026-03-16 11:10:33 +00:00
if brainKey == "" {
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
if r := fs . Read ( core . JoinPath ( home , ".claude" , "brain.key" ) ) ; r . OK {
brainKey = core . Trim ( r . Value . ( string ) )
2026-03-16 11:10:33 +00:00
}
}
2026-03-22 14:15:41 +00:00
forgeURL := envOr ( "FORGE_URL" , "https://forge.lthn.ai" )
2026-04-01 17:54:26 +00:00
subsystem := & PrepSubsystem {
2026-03-22 14:15:41 +00:00
forge : forge . NewForge ( forgeURL , forgeToken ) ,
forgeURL : forgeURL ,
2026-03-17 18:13:44 +00:00
forgeToken : forgeToken ,
brainURL : envOr ( "CORE_BRAIN_URL" , "https://api.lthn.sh" ) ,
brainKey : brainKey ,
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
codePath : envOr ( "CODE_PATH" , core . JoinPath ( home , "Code" ) ) ,
2026-03-23 16:08:08 +00:00
backoff : make ( map [ string ] time . Time ) ,
failCount : make ( map [ string ] int ) ,
2026-03-26 06:38:02 +00:00
workspaces : core . NewRegistry [ * WorkspaceStatus ] ( ) ,
2026-03-16 11:10:33 +00:00
}
2026-04-01 17:54:26 +00:00
subsystem . loadRuntimeState ( )
return subsystem
2026-03-16 11:10:33 +00:00
}
2026-03-30 22:30:05 +00:00
// c.Action("agentic.dispatch").Run(ctx, options)
2026-04-02 08:40:24 +00:00
// core.Println(c.Actions()) // inspect the registered action names at startup
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
func ( s * PrepSubsystem ) OnStartup ( ctx context . Context ) core . Result {
c := s . Core ( )
2026-03-26 06:38:02 +00:00
c . SetEntitlementChecker ( func ( action string , qty int , _ context . Context ) core . Entitlement {
if ! core . HasPrefix ( action , "agentic." ) {
return core . Entitlement { Allowed : true , Unlimited : true }
}
2026-03-26 07:16:48 +00:00
if core . HasPrefix ( action , "agentic.monitor." ) || core . HasPrefix ( action , "agentic.complete" ) {
return core . Entitlement { Allowed : true , Unlimited : true }
}
2026-03-26 06:38:02 +00:00
switch action {
case "agentic.status" , "agentic.scan" , "agentic.watch" ,
2026-04-01 16:50:26 +00:00
"agentic.issue.get" , "agentic.issue.list" , "agentic.issue.assign" , "agentic.pr.get" , "agentic.pr.list" ,
2026-03-31 11:42:02 +00:00
"agentic.prompt" , "agentic.task" , "agentic.flow" , "agentic.persona" ,
2026-04-02 06:39:02 +00:00
"agentic.prompt.version" , "agentic.setup" ,
2026-03-31 19:04:06 +00:00
"agentic.sync.status" , "agentic.fleet.nodes" , "agentic.fleet.stats" , "agentic.fleet.events" ,
2026-03-31 11:42:02 +00:00
"agentic.credits.balance" , "agentic.credits.history" ,
2026-04-01 21:04:39 +00:00
"agentic.subscription.detect" , "agentic.subscription.budget" ,
"agentic.message.send" , "agentic.message.inbox" , "agentic.message.conversation" :
2026-03-26 06:38:02 +00:00
return core . Entitlement { Allowed : true , Unlimited : true }
}
if s . frozen {
return core . Entitlement { Allowed : false , Reason : "agent queue is frozen — shutting down" }
}
return core . Entitlement { Allowed : true }
} )
lib . MountData ( c )
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
RegisterHTTPTransport ( c )
c . Drive ( ) . New ( core . NewOptions (
core . Option { Key : "name" , Value : "forge" } ,
core . Option { Key : "transport" , Value : s . forgeURL } ,
core . Option { Key : "token" , Value : s . forgeToken } ,
) )
c . Drive ( ) . New ( core . NewOptions (
core . Option { Key : "name" , Value : "brain" } ,
core . Option { Key : "transport" , Value : s . brainURL } ,
core . Option { Key : "token" , Value : s . brainKey } ,
) )
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.sync.push" , s . handleSyncPush ) . Description = "Push completed dispatch state to the platform API"
2026-03-31 07:27:15 +00:00
c . Action ( "agent.sync.push" , s . handleSyncPush ) . Description = "Push completed dispatch state to the platform API"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.sync.pull" , s . handleSyncPull ) . Description = "Pull fleet context from the platform API"
2026-03-31 07:27:15 +00:00
c . Action ( "agent.sync.pull" , s . handleSyncPull ) . Description = "Pull fleet context from the platform API"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.sync.status" , s . handleSyncStatus ) . Description = "Get fleet sync status from the platform API"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.sync.status" , s . handleSyncStatus ) . Description = "Get fleet sync status from the platform API"
2026-03-31 14:23:12 +00:00
c . Action ( "agentic.auth.provision" , s . handleAuthProvision ) . Description = "Provision a platform API key for an authenticated agent user"
c . Action ( "agent.auth.provision" , s . handleAuthProvision ) . Description = "Provision a platform API key for an authenticated agent user"
c . Action ( "agentic.auth.revoke" , s . handleAuthRevoke ) . Description = "Revoke a platform API key"
c . Action ( "agent.auth.revoke" , s . handleAuthRevoke ) . Description = "Revoke a platform API key"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.fleet.register" , s . handleFleetRegister ) . Description = "Register a fleet node with the platform API"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.fleet.register" , s . handleFleetRegister ) . Description = "Register a fleet node with the platform API"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.fleet.heartbeat" , s . handleFleetHeartbeat ) . Description = "Send a heartbeat for a fleet node"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.fleet.heartbeat" , s . handleFleetHeartbeat ) . Description = "Send a heartbeat for a fleet node"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.fleet.deregister" , s . handleFleetDeregister ) . Description = "Deregister a fleet node from the platform API"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.fleet.deregister" , s . handleFleetDeregister ) . Description = "Deregister a fleet node from the platform API"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.fleet.nodes" , s . handleFleetNodes ) . Description = "List registered fleet nodes"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.fleet.nodes" , s . handleFleetNodes ) . Description = "List registered fleet nodes"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.fleet.task.assign" , s . handleFleetAssignTask ) . Description = "Assign a fleet task to an agent"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.fleet.task.assign" , s . handleFleetAssignTask ) . Description = "Assign a fleet task to an agent"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.fleet.task.complete" , s . handleFleetCompleteTask ) . Description = "Complete a fleet task and report results"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.fleet.task.complete" , s . handleFleetCompleteTask ) . Description = "Complete a fleet task and report results"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.fleet.task.next" , s . handleFleetNextTask ) . Description = "Ask the platform for the next fleet task"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.fleet.task.next" , s . handleFleetNextTask ) . Description = "Ask the platform for the next fleet task"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.fleet.stats" , s . handleFleetStats ) . Description = "Get fleet activity statistics"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.fleet.stats" , s . handleFleetStats ) . Description = "Get fleet activity statistics"
2026-03-31 19:04:06 +00:00
c . Action ( "agentic.fleet.events" , s . handleFleetEvents ) . Description = "Read fleet task assignment events from the platform API"
c . Action ( "agent.fleet.events" , s . handleFleetEvents ) . Description = "Read fleet task assignment events from the platform API"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.credits.award" , s . handleCreditsAward ) . Description = "Award credits to a fleet node"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.credits.award" , s . handleCreditsAward ) . Description = "Award credits to a fleet node"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.credits.balance" , s . handleCreditsBalance ) . Description = "Get credit balance for a fleet node"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.credits.balance" , s . handleCreditsBalance ) . Description = "Get credit balance for a fleet node"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.credits.history" , s . handleCreditsHistory ) . Description = "List credit entries for a fleet node"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.credits.history" , s . handleCreditsHistory ) . Description = "List credit entries for a fleet node"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.subscription.detect" , s . handleSubscriptionDetect ) . Description = "Detect available provider capabilities"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.subscription.detect" , s . handleSubscriptionDetect ) . Description = "Detect available provider capabilities"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.subscription.budget" , s . handleSubscriptionBudget ) . Description = "Get the compute budget for a fleet node"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.subscription.budget" , s . handleSubscriptionBudget ) . Description = "Get the compute budget for a fleet node"
2026-03-31 11:42:02 +00:00
c . Action ( "agentic.subscription.budget.update" , s . handleSubscriptionBudgetUpdate ) . Description = "Update the compute budget for a fleet node"
2026-03-31 11:02:11 +00:00
c . Action ( "agent.subscription.budget.update" , s . handleSubscriptionBudgetUpdate ) . Description = "Update the compute budget for a fleet node"
2026-04-01 21:04:39 +00:00
c . Action ( "agentic.message.send" , s . handleMessageSend ) . Description = "Send a direct message between agents"
c . Action ( "agent.message.send" , s . handleMessageSend ) . Description = "Send a direct message between agents"
c . Action ( "agentic.message.inbox" , s . handleMessageInbox ) . Description = "List direct messages for an agent"
c . Action ( "agent.message.inbox" , s . handleMessageInbox ) . Description = "List direct messages for an agent"
c . Action ( "agentic.message.conversation" , s . handleMessageConversation ) . Description = "List a direct conversation between two agents"
c . Action ( "agent.message.conversation" , s . handleMessageConversation ) . Description = "List a direct conversation between two agents"
2026-03-31 07:27:15 +00:00
2026-03-26 06:38:02 +00:00
c . Action ( "agentic.dispatch" , s . handleDispatch ) . Description = "Prep workspace and spawn a subagent"
2026-04-01 20:34:04 +00:00
c . Action ( "agentic.dispatch.sync" , s . handleDispatchSync ) . Description = "Dispatch a single task synchronously and block until it completes"
2026-04-02 01:47:17 +00:00
c . Action ( "agentic.dispatch.start" , s . handleDispatchStart ) . Description = "Start the dispatch queue runner"
c . Action ( "agentic.dispatch.shutdown" , s . handleDispatchShutdown ) . Description = "Freeze the dispatch queue gracefully"
c . Action ( "agentic.dispatch.shutdown_now" , s . handleDispatchShutdownNow ) . Description = "Hard stop the dispatch queue and kill running agents"
2026-03-26 06:38:02 +00:00
c . Action ( "agentic.prep" , s . handlePrep ) . Description = "Clone repo and build agent prompt"
c . Action ( "agentic.status" , s . handleStatus ) . Description = "List workspace states (running/completed/blocked)"
c . Action ( "agentic.resume" , s . handleResume ) . Description = "Resume a blocked or completed workspace"
c . Action ( "agentic.scan" , s . handleScan ) . Description = "Scan Forge repos for actionable issues"
c . Action ( "agentic.watch" , s . handleWatch ) . Description = "Watch workspace for changes and report"
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
2026-03-26 06:38:02 +00:00
c . Action ( "agentic.qa" , s . handleQA ) . Description = "Run build + test QA checks on workspace"
c . Action ( "agentic.auto-pr" , s . handleAutoPR ) . Description = "Create PR from completed workspace"
c . Action ( "agentic.verify" , s . handleVerify ) . Description = "Verify PR and auto-merge if clean"
2026-04-01 22:07:42 +00:00
c . Action ( "agentic.commit" , s . handleCommit ) . Description = "Write the final dispatch record to the workspace journal"
2026-03-26 06:38:02 +00:00
c . Action ( "agentic.ingest" , s . handleIngest ) . Description = "Create issues from agent findings"
c . Action ( "agentic.poke" , s . handlePoke ) . Description = "Drain next queued task from the queue"
c . Action ( "agentic.mirror" , s . handleMirror ) . Description = "Mirror agent branches to GitHub"
2026-04-02 06:39:02 +00:00
c . Action ( "agentic.setup" , s . handleSetup ) . Description = "Scaffold a workspace with .core config files and optional templates"
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
2026-03-26 06:38:02 +00:00
c . Action ( "agentic.issue.get" , s . handleIssueGet ) . Description = "Get a Forge issue by number"
c . Action ( "agentic.issue.list" , s . handleIssueList ) . Description = "List Forge issues for a repo"
c . Action ( "agentic.issue.create" , s . handleIssueCreate ) . Description = "Create a Forge issue"
2026-04-01 16:43:47 +00:00
c . Action ( "agentic.issue.update" , s . handleIssueRecordUpdate ) . Description = "Update a tracked platform issue by slug"
c . Action ( "agentic.issue.comment" , s . handleIssueRecordComment ) . Description = "Add a comment to a tracked platform issue"
c . Action ( "agentic.issue.archive" , s . handleIssueRecordArchive ) . Description = "Archive a tracked platform issue by slug"
2026-03-26 06:38:02 +00:00
c . Action ( "agentic.pr.get" , s . handlePRGet ) . Description = "Get a Forge PR by number"
c . Action ( "agentic.pr.list" , s . handlePRList ) . Description = "List Forge PRs for a repo"
c . Action ( "agentic.pr.merge" , s . handlePRMerge ) . Description = "Merge a Forge PR"
2026-03-31 19:18:58 +00:00
c . Action ( "agentic.pr.close" , s . handlePRClose ) . Description = "Close a Forge PR"
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
2026-03-26 06:38:02 +00:00
c . Action ( "agentic.review-queue" , s . handleReviewQueue ) . Description = "Run CodeRabbit review on completed workspaces"
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
2026-03-26 06:38:02 +00:00
c . Action ( "agentic.epic" , s . handleEpic ) . Description = "Create sub-issues from an epic plan"
2026-03-31 11:22:36 +00:00
c . Action ( "plan.create" , s . handlePlanCreate ) . Description = "Create a structured implementation plan"
2026-03-31 13:58:57 +00:00
c . Action ( "plan.get" , s . handlePlanGet ) . Description = "Read an implementation plan by ID or slug"
2026-03-31 11:22:36 +00:00
c . Action ( "plan.read" , s . handlePlanRead ) . Description = "Read an implementation plan by ID"
c . Action ( "plan.update" , s . handlePlanUpdate ) . Description = "Update plan status, phases, notes, or agent assignment"
2026-03-31 15:12:33 +00:00
c . Action ( "plan.update_status" , s . handlePlanUpdateStatus ) . Description = "Update an implementation plan lifecycle status by slug"
2026-04-01 15:42:26 +00:00
c . Action ( "plan.from.issue" , s . handlePlanFromIssue ) . Description = "Create a plan from a tracked issue"
2026-04-01 15:28:47 +00:00
c . Action ( "plan.check" , s . handlePlanCheck ) . Description = "Check whether a plan or phase is complete"
2026-03-31 13:58:57 +00:00
c . Action ( "plan.archive" , s . handlePlanArchive ) . Description = "Archive an implementation plan by slug"
2026-04-01 16:14:16 +00:00
c . Action ( "plan.delete" , s . handlePlanDelete ) . Description = "Delete an implementation plan by ID"
2026-03-31 11:22:36 +00:00
c . Action ( "plan.list" , s . handlePlanList ) . Description = "List implementation plans with optional filters"
2026-04-02 06:29:46 +00:00
c . Action ( "agentic.plan.create" , s . handlePlanCreate ) . Description = "Create a structured implementation plan"
c . Action ( "agentic.plan.get" , s . handlePlanGet ) . Description = "Read an implementation plan by ID or slug"
c . Action ( "agentic.plan.read" , s . handlePlanRead ) . Description = "Read an implementation plan by ID"
c . Action ( "agentic.plan.update" , s . handlePlanUpdate ) . Description = "Update plan status, phases, notes, or agent assignment"
c . Action ( "agentic.plan.update_status" , s . handlePlanUpdateStatus ) . Description = "Update an implementation plan lifecycle status by slug"
c . Action ( "agentic.plan.from.issue" , s . handlePlanFromIssue ) . Description = "Create a plan from a tracked issue"
c . Action ( "agentic.plan.check" , s . handlePlanCheck ) . Description = "Check whether a plan or phase is complete"
c . Action ( "agentic.plan.archive" , s . handlePlanArchive ) . Description = "Archive an implementation plan by slug"
c . Action ( "agentic.plan.delete" , s . handlePlanDelete ) . Description = "Delete an implementation plan by ID"
c . Action ( "agentic.plan.list" , s . handlePlanList ) . Description = "List implementation plans with optional filters"
2026-03-31 13:58:57 +00:00
c . Action ( "phase.get" , s . handlePhaseGet ) . Description = "Read a plan phase by slug and order"
c . Action ( "phase.update_status" , s . handlePhaseUpdateStatus ) . Description = "Update plan phase status by slug and order"
c . Action ( "phase.add_checkpoint" , s . handlePhaseAddCheckpoint ) . Description = "Append a checkpoint note to a plan phase"
2026-04-02 06:29:46 +00:00
c . Action ( "agentic.phase.get" , s . handlePhaseGet ) . Description = "Read a plan phase by slug and order"
c . Action ( "agentic.phase.update_status" , s . handlePhaseUpdateStatus ) . Description = "Update plan phase status by slug and order"
c . Action ( "agentic.phase.add_checkpoint" , s . handlePhaseAddCheckpoint ) . Description = "Append a checkpoint note to a plan phase"
2026-04-01 11:48:59 +00:00
c . Action ( "task.create" , s . handleTaskCreate ) . Description = "Create a plan task in a phase"
2026-03-31 13:58:57 +00:00
c . Action ( "task.update" , s . handleTaskUpdate ) . Description = "Update a plan task by slug, phase, and identifier"
c . Action ( "task.toggle" , s . handleTaskToggle ) . Description = "Toggle a plan task between pending and completed"
2026-04-02 06:29:46 +00:00
c . Action ( "agentic.task.create" , s . handleTaskCreate ) . Description = "Create a plan task in a phase"
c . Action ( "agentic.task.update" , s . handleTaskUpdate ) . Description = "Update a plan task by slug, phase, and identifier"
c . Action ( "agentic.task.toggle" , s . handleTaskToggle ) . Description = "Toggle a plan task between pending and completed"
2026-03-31 12:06:40 +00:00
c . Action ( "session.start" , s . handleSessionStart ) . Description = "Start an agent session for a plan"
c . Action ( "session.get" , s . handleSessionGet ) . Description = "Read a session by session ID"
c . Action ( "session.list" , s . handleSessionList ) . Description = "List sessions with optional plan or status filters"
c . Action ( "session.continue" , s . handleSessionContinue ) . Description = "Continue a session from its latest saved context"
c . Action ( "session.end" , s . handleSessionEnd ) . Description = "End a session with status and summary"
2026-04-01 21:50:36 +00:00
c . Action ( "session.complete" , s . handleSessionEnd ) . Description = "Mark a session completed with status, summary, and handoff notes"
2026-03-31 13:39:24 +00:00
c . Action ( "session.log" , s . handleSessionLog ) . Description = "Append a typed work-log entry to a stored session"
c . Action ( "session.artifact" , s . handleSessionArtifact ) . Description = "Record a created, modified, deleted, or reviewed artifact for a session"
2026-04-02 00:33:10 +00:00
c . Action ( "session.handoff" , s . handleSessionHandoff ) . Description = "Hand off a session with notes for the next agent"
2026-03-31 13:39:24 +00:00
c . Action ( "session.resume" , s . handleSessionResume ) . Description = "Resume a paused or handed-off session from local cache"
c . Action ( "session.replay" , s . handleSessionReplay ) . Description = "Build replay context for a session from work logs and artifacts"
2026-04-02 06:29:46 +00:00
c . Action ( "agentic.session.start" , s . handleSessionStart ) . Description = "Start an agent session for a plan"
c . Action ( "agentic.session.get" , s . handleSessionGet ) . Description = "Read a session by session ID"
c . Action ( "agentic.session.list" , s . handleSessionList ) . Description = "List sessions with optional plan or status filters"
c . Action ( "agentic.session.continue" , s . handleSessionContinue ) . Description = "Continue a session from its latest saved context"
c . Action ( "agentic.session.end" , s . handleSessionEnd ) . Description = "End a session with status and summary"
c . Action ( "agentic.session.complete" , s . handleSessionEnd ) . Description = "Mark a session completed with status, summary, and handoff notes"
c . Action ( "agentic.session.log" , s . handleSessionLog ) . Description = "Append a typed work-log entry to a stored session"
c . Action ( "agentic.session.artifact" , s . handleSessionArtifact ) . Description = "Record a created, modified, deleted, or reviewed artifact for a session"
c . Action ( "agentic.session.handoff" , s . handleSessionHandoff ) . Description = "Hand off a session with notes for the next agent"
c . Action ( "agentic.session.resume" , s . handleSessionResume ) . Description = "Resume a paused or handed-off session from local cache"
c . Action ( "agentic.session.replay" , s . handleSessionReplay ) . Description = "Build replay context for a session from work logs and artifacts"
2026-03-31 13:39:24 +00:00
c . Action ( "state.set" , s . handleStateSet ) . Description = "Store shared plan state for later sessions"
c . Action ( "state.get" , s . handleStateGet ) . Description = "Read shared plan state by key"
c . Action ( "state.list" , s . handleStateList ) . Description = "List shared plan state for a plan"
2026-04-01 13:58:16 +00:00
c . Action ( "state.delete" , s . handleStateDelete ) . Description = "Delete shared plan state by key"
2026-04-02 06:29:46 +00:00
c . Action ( "agentic.state.set" , s . handleStateSet ) . Description = "Store shared plan state for later sessions"
c . Action ( "agentic.state.get" , s . handleStateGet ) . Description = "Read shared plan state by key"
c . Action ( "agentic.state.list" , s . handleStateList ) . Description = "List shared plan state for a plan"
c . Action ( "agentic.state.delete" , s . handleStateDelete ) . Description = "Delete shared plan state by key"
2026-03-31 14:39:40 +00:00
c . Action ( "template.list" , s . handleTemplateList ) . Description = "List available YAML plan templates"
2026-04-02 05:07:54 +00:00
c . Action ( "agentic.template.list" , s . handleTemplateList ) . Description = "List available YAML plan templates"
2026-03-31 14:39:40 +00:00
c . Action ( "template.preview" , s . handleTemplatePreview ) . Description = "Preview a YAML plan template with variable substitution"
2026-04-02 05:07:54 +00:00
c . Action ( "agentic.template.preview" , s . handleTemplatePreview ) . Description = "Preview a YAML plan template with variable substitution"
2026-03-31 14:39:40 +00:00
c . Action ( "template.create_plan" , s . handleTemplateCreatePlan ) . Description = "Create a stored plan from a YAML template"
2026-04-02 05:07:54 +00:00
c . Action ( "agentic.template.create_plan" , s . handleTemplateCreatePlan ) . Description = "Create a stored plan from a YAML template"
2026-03-31 15:12:33 +00:00
c . Action ( "issue.create" , s . handleIssueRecordCreate ) . Description = "Create a tracked platform issue"
c . Action ( "issue.get" , s . handleIssueRecordGet ) . Description = "Read a tracked platform issue by slug"
c . Action ( "issue.list" , s . handleIssueRecordList ) . Description = "List tracked platform issues with optional filters"
c . Action ( "issue.update" , s . handleIssueRecordUpdate ) . Description = "Update a tracked platform issue by slug"
2026-04-01 16:50:26 +00:00
c . Action ( "issue.assign" , s . handleIssueRecordAssign ) . Description = "Assign an agent or user to a tracked platform issue"
2026-03-31 15:12:33 +00:00
c . Action ( "issue.comment" , s . handleIssueRecordComment ) . Description = "Add a comment to a tracked platform issue"
2026-04-01 18:00:50 +00:00
c . Action ( "issue.report" , s . handleIssueRecordReport ) . Description = "Post a structured report comment to a tracked platform issue"
2026-03-31 15:12:33 +00:00
c . Action ( "issue.archive" , s . handleIssueRecordArchive ) . Description = "Archive a tracked platform issue by slug"
2026-04-02 04:23:14 +00:00
c . Action ( "agentic.issue.create" , s . handleIssueRecordCreate ) . Description = "Create a tracked platform issue"
2026-04-01 16:50:26 +00:00
c . Action ( "agentic.issue.assign" , s . handleIssueRecordAssign ) . Description = "Assign an agent or user to a tracked platform issue"
2026-04-02 04:23:14 +00:00
c . Action ( "agentic.issue.comment" , s . handleIssueRecordComment ) . Description = "Add a comment to a tracked platform issue"
2026-04-01 18:00:50 +00:00
c . Action ( "agentic.issue.report" , s . handleIssueRecordReport ) . Description = "Post a structured report comment to a tracked platform issue"
2026-03-31 15:12:33 +00:00
c . Action ( "sprint.create" , s . handleSprintCreate ) . Description = "Create a tracked platform sprint"
c . Action ( "sprint.get" , s . handleSprintGet ) . Description = "Read a tracked platform sprint by slug"
c . Action ( "sprint.list" , s . handleSprintList ) . Description = "List tracked platform sprints with optional filters"
c . Action ( "sprint.update" , s . handleSprintUpdate ) . Description = "Update a tracked platform sprint by slug"
c . Action ( "sprint.archive" , s . handleSprintArchive ) . Description = "Archive a tracked platform sprint by slug"
2026-03-31 15:27:15 +00:00
c . Action ( "content.generate" , s . handleContentGenerate ) . Description = "Generate content using the platform content pipeline"
2026-04-02 05:03:08 +00:00
c . Action ( "agentic.generate" , s . handleContentGenerate ) . Description = "Generate content using the platform content pipeline"
2026-04-02 06:29:46 +00:00
c . Action ( "agentic.content.generate" , s . handleContentGenerate ) . Description = "Generate content using the platform content pipeline"
2026-03-31 15:52:31 +00:00
c . Action ( "content.batch" , s . handleContentBatchGenerate ) . Description = "Start or continue batch content generation"
2026-03-31 15:27:15 +00:00
c . Action ( "content.batch.generate" , s . handleContentBatchGenerate ) . Description = "Start or continue batch content generation"
c . Action ( "content.batch_generate" , s . handleContentBatchGenerate ) . Description = "Start or continue batch content generation"
2026-03-31 15:52:31 +00:00
c . Action ( "content_batch" , s . handleContentBatchGenerate ) . Description = "Start or continue batch content generation"
2026-04-02 06:29:46 +00:00
c . Action ( "agentic.content.batch" , s . handleContentBatchGenerate ) . Description = "Start or continue batch content generation"
c . Action ( "agentic.content.batch.generate" , s . handleContentBatchGenerate ) . Description = "Start or continue batch content generation"
c . Action ( "agentic.content.batch_generate" , s . handleContentBatchGenerate ) . Description = "Start or continue batch content generation"
c . Action ( "agentic.content_batch" , s . handleContentBatchGenerate ) . Description = "Start or continue batch content generation"
2026-03-31 15:27:15 +00:00
c . Action ( "content.brief.create" , s . handleContentBriefCreate ) . Description = "Create a reusable content brief"
c . Action ( "content.brief_create" , s . handleContentBriefCreate ) . Description = "Create a reusable content brief"
c . Action ( "content.brief.get" , s . handleContentBriefGet ) . Description = "Read a content brief by ID or slug"
c . Action ( "content.brief_get" , s . handleContentBriefGet ) . Description = "Read a content brief by ID or slug"
c . Action ( "content.brief.list" , s . handleContentBriefList ) . Description = "List content briefs with optional filters"
c . Action ( "content.brief_list" , s . handleContentBriefList ) . Description = "List content briefs with optional filters"
c . Action ( "content.status" , s . handleContentStatus ) . Description = "Read batch content generation status"
c . Action ( "content.usage.stats" , s . handleContentUsageStats ) . Description = "Read content provider usage statistics"
c . Action ( "content.usage_stats" , s . handleContentUsageStats ) . Description = "Read content provider usage statistics"
c . Action ( "content.from.plan" , s . handleContentFromPlan ) . Description = "Generate content from plan context"
c . Action ( "content.from_plan" , s . handleContentFromPlan ) . Description = "Generate content from plan context"
2026-04-01 15:34:37 +00:00
c . Action ( "content.schema.generate" , s . handleContentSchemaGenerate ) . Description = "Generate SEO schema JSON-LD for article, FAQ, or how-to content"
2026-04-02 06:29:46 +00:00
c . Action ( "agentic.content.brief.create" , s . handleContentBriefCreate ) . Description = "Create a reusable content brief"
c . Action ( "agentic.content.brief.get" , s . handleContentBriefGet ) . Description = "Read a content brief by ID or slug"
c . Action ( "agentic.content.brief.list" , s . handleContentBriefList ) . Description = "List content briefs with optional filters"
c . Action ( "agentic.content.status" , s . handleContentStatus ) . Description = "Read batch content generation status"
c . Action ( "agentic.content.usage.stats" , s . handleContentUsageStats ) . Description = "Read content provider usage statistics"
c . Action ( "agentic.content.usage_stats" , s . handleContentUsageStats ) . Description = "Read content provider usage statistics"
c . Action ( "agentic.content.from.plan" , s . handleContentFromPlan ) . Description = "Generate content from plan context"
c . Action ( "agentic.content.from_plan" , s . handleContentFromPlan ) . Description = "Generate content from plan context"
c . Action ( "agentic.content.schema.generate" , s . handleContentSchemaGenerate ) . Description = "Generate SEO schema JSON-LD for article, FAQ, or how-to content"
2026-03-26 06:38:02 +00:00
2026-03-29 21:56:45 +00:00
c . Action ( "agentic.prompt" , s . handlePrompt ) . Description = "Read a system prompt by slug"
2026-04-01 21:20:44 +00:00
c . Action ( "agentic.prompt.version" , s . handlePromptVersion ) . Description = "Read the current prompt snapshot for a workspace"
2026-03-29 21:56:45 +00:00
c . Action ( "agentic.task" , s . handleTask ) . Description = "Read a task plan by slug"
c . Action ( "agentic.flow" , s . handleFlow ) . Description = "Read a build/release flow by slug"
c . Action ( "agentic.persona" , s . handlePersona ) . Description = "Read a persona by path"
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
c . Task ( "agent.completion" , core . Task {
2026-04-01 22:07:42 +00:00
Description : "QA → PR → Verify → Commit → Ingest → Poke" ,
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
Steps : [ ] core . Step {
{ Action : "agentic.qa" } ,
{ Action : "agentic.auto-pr" } ,
{ Action : "agentic.verify" } ,
2026-04-01 22:07:42 +00:00
{ Action : "agentic.commit" , Async : true } ,
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
{ Action : "agentic.ingest" , Async : true } ,
{ Action : "agentic.poke" , Async : true } ,
} ,
} )
2026-04-01 22:07:42 +00:00
c . Action ( "agentic.complete" , s . handleComplete ) . Description = "Run completion pipeline (QA → PR → Verify → Commit → Ingest → Poke) in background"
2026-03-26 06:38:02 +00:00
s . hydrateWorkspaces ( )
2026-04-01 14:31:46 +00:00
if planRetentionDays ( core . NewOptions ( ) ) > 0 {
go s . runPlanCleanupLoop ( ctx , planRetentionScheduleInterval )
}
2026-04-02 03:46:09 +00:00
if s . forgeToken != "" {
go s . runPRManageLoop ( ctx , prManageScheduleInterval )
}
2026-03-26 06:38:02 +00:00
2026-03-29 21:56:45 +00:00
c . RegisterQuery ( s . handleWorkspaceQuery )
2026-03-26 06:38:02 +00:00
2026-03-24 17:42:16 +00:00
s . StartRunner ( )
2026-03-24 21:16:20 +00:00
s . registerCommands ( ctx )
2026-03-25 00:03:22 +00:00
s . registerWorkspaceCommands ( )
2026-03-25 00:06:46 +00:00
s . registerForgeCommands ( )
2026-03-31 11:02:11 +00:00
s . registerPlatformCommands ( )
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
return core . Result { OK : true }
2026-03-24 17:42:16 +00:00
}
2026-03-30 22:40:28 +00:00
// s.registerCommands(ctx)
2026-03-24 21:16:20 +00:00
2026-03-30 22:30:05 +00:00
// subsystem := agentic.NewPrep()
// _ = subsystem.OnShutdown(context.Background())
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
func ( s * PrepSubsystem ) OnShutdown ( ctx context . Context ) core . Result {
2026-03-24 17:42:16 +00:00
s . frozen = true
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
return core . Result { OK : true }
2026-03-24 17:42:16 +00:00
}
2026-03-17 17:45:04 +00:00
2026-03-31 04:33:36 +00:00
// s.hydrateWorkspaces()
2026-03-31 06:20:14 +00:00
// s.workspaces.Names() // ["core/go-io/task-5", "ws-blocked", "ws-ready-for-review"]
2026-03-26 06:38:02 +00:00
func ( s * PrepSubsystem ) hydrateWorkspaces ( ) {
if s . workspaces == nil {
s . workspaces = core . NewRegistry [ * WorkspaceStatus ] ( )
}
2026-03-29 21:19:37 +00:00
for _ , path := range WorkspaceStatusPaths ( ) {
2026-03-30 21:22:54 +00:00
workspaceDir := core . PathDir ( path )
result := ReadStatusResult ( workspaceDir )
2026-03-30 19:40:02 +00:00
st , ok := workspaceStatusValue ( result )
if ! ok {
2026-03-29 21:19:37 +00:00
continue
2026-03-26 06:38:02 +00:00
}
2026-03-30 21:22:54 +00:00
s . workspaces . Set ( WorkspaceName ( workspaceDir ) , st )
2026-03-26 06:38:02 +00:00
}
}
2026-03-30 22:30:05 +00:00
// s.TrackWorkspace("core/go-io/task-5", st)
2026-03-26 06:38:02 +00:00
func ( s * PrepSubsystem ) TrackWorkspace ( name string , st * WorkspaceStatus ) {
if s . workspaces != nil {
s . workspaces . Set ( name , st )
}
}
2026-03-30 22:30:05 +00:00
// s.Workspaces().Names() // all workspace names
// s.Workspaces().List("core/*") // org-scoped workspaces
2026-03-31 06:20:14 +00:00
// s.Workspaces().Each(func(name string, workspaceStatus *WorkspaceStatus) { core.Println(name, workspaceStatus.Status) })
2026-03-26 06:38:02 +00:00
func ( s * PrepSubsystem ) Workspaces ( ) * core . Registry [ * WorkspaceStatus ] {
return s . workspaces
}
2026-03-16 11:10:33 +00:00
func envOr ( key , fallback string ) string {
refactor(agentic): adopt core.Env() + core.Path() across package
Replace all os.UserHomeDir/os.Getenv/os.Hostname with core.Env().
Replace all filepath.Base/Dir/Glob/IsAbs with core.PathBase/PathDir/
PathGlob/PathIsAbs.
10 files migrated: paths, prep, review_queue, remote, dispatch,
ingest, mirror, plan, verify, watch.
Imports eliminated: 5x os, 7x filepath. All file I/O and path
construction now routes through Core primitives.
Bumps dappco.re/go/core to v0.6.0.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 10:15:15 +00:00
if v := core . Env ( key ) ; v != "" {
2026-03-16 11:10:33 +00:00
return v
}
return fallback
}
2026-03-30 22:30:05 +00:00
// subsystem := agentic.NewPrep()
// name := subsystem.Name()
// _ = name // "agentic"
2026-03-16 11:10:33 +00:00
func ( s * PrepSubsystem ) Name ( ) string { return "agentic" }
2026-04-01 16:09:04 +00:00
// subsystem := agentic.NewPrep()
// subsystem.SetCore(core.New(core.WithOption("name", "core-agent")))
func ( s * PrepSubsystem ) SetCore ( c * core . Core ) {
if s == nil || c == nil {
return
}
s . ServiceRuntime = core . NewServiceRuntime ( c , AgentOptions { } )
}
2026-03-30 22:30:05 +00:00
// subsystem := agentic.NewPrep()
// subsystem.RegisterTools(server)
2026-03-16 11:10:33 +00:00
func ( s * PrepSubsystem ) RegisterTools ( server * mcp . Server ) {
mcp . AddTool ( server , & mcp . Tool {
Name : "agentic_prep_workspace" ,
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
Description : "Prepare an agent workspace: clone repo, create branch, build prompt with context." ,
2026-03-16 11:10:33 +00:00
} , s . prepWorkspace )
s . registerDispatchTool ( server )
s . registerStatusTool ( server )
s . registerResumeTool ( server )
2026-04-01 20:22:00 +00:00
mcp . AddTool ( server , & mcp . Tool {
Name : "agentic_complete" ,
2026-04-01 22:07:42 +00:00
Description : "Run the completion pipeline (QA → PR → Verify → Commit → Ingest → Poke) in the background." ,
2026-04-01 20:22:00 +00:00
} , s . completeTool )
2026-04-01 22:07:42 +00:00
s . registerCommitTool ( server )
2026-03-16 11:10:33 +00:00
s . registerCreatePRTool ( server )
s . registerListPRsTool ( server )
2026-04-01 16:38:21 +00:00
s . registerClosePRTool ( server )
2026-03-16 11:10:33 +00:00
s . registerEpicTool ( server )
2026-03-17 17:45:04 +00:00
s . registerMirrorTool ( server )
s . registerRemoteDispatchTool ( server )
s . registerRemoteStatusTool ( server )
s . registerReviewQueueTool ( server )
2026-03-31 15:12:33 +00:00
s . registerPlatformTools ( server )
2026-03-23 16:08:08 +00:00
s . registerShutdownTools ( server )
2026-03-31 12:06:40 +00:00
s . registerSessionTools ( server )
2026-03-31 13:39:24 +00:00
s . registerStateTools ( server )
2026-03-31 13:58:57 +00:00
s . registerPhaseTools ( server )
s . registerTaskTools ( server )
2026-04-01 21:57:55 +00:00
s . registerPromptTools ( server )
2026-03-31 14:39:40 +00:00
s . registerTemplateTools ( server )
2026-03-31 15:12:33 +00:00
s . registerIssueTools ( server )
2026-04-01 21:04:39 +00:00
s . registerMessageTools ( server )
2026-03-31 15:12:33 +00:00
s . registerSprintTools ( server )
2026-04-01 23:34:05 +00:00
s . registerPRTools ( server )
2026-03-31 15:27:15 +00:00
s . registerContentTools ( server )
2026-04-01 12:33:57 +00:00
s . registerLanguageTools ( server )
2026-04-02 06:39:02 +00:00
s . registerSetupTool ( server )
2026-03-16 11:10:33 +00:00
mcp . AddTool ( server , & mcp . Tool {
Name : "agentic_scan" ,
Description : "Scan Forge repos for open issues with actionable labels (agentic, help-wanted, bug)." ,
} , s . scan )
s . registerPlanTools ( server )
2026-03-17 04:31:19 +00:00
s . registerWatchTool ( server )
2026-03-16 11:10:33 +00:00
}
2026-03-30 22:30:05 +00:00
// subsystem := agentic.NewPrep()
// _ = subsystem.Shutdown(context.Background())
2026-03-16 11:10:33 +00:00
func ( s * PrepSubsystem ) Shutdown ( _ context . Context ) error { return nil }
2026-03-30 22:30:05 +00:00
// input := agentic.PrepInput{Repo: "go-io", Issue: 15, Task: "Migrate to Core primitives"}
2026-03-16 11:10:33 +00:00
type PrepInput struct {
2026-03-31 05:34:44 +00:00
Repo string ` json:"repo" `
Org string ` json:"org,omitempty" `
Task string ` json:"task,omitempty" `
Agent string ` json:"agent,omitempty" `
Issue int ` json:"issue,omitempty" `
PR int ` json:"pr,omitempty" `
Branch string ` json:"branch,omitempty" `
Tag string ` json:"tag,omitempty" `
Template string ` json:"template,omitempty" `
PlanTemplate string ` json:"plan_template,omitempty" `
Variables map [ string ] string ` json:"variables,omitempty" `
Persona string ` json:"persona,omitempty" `
DryRun bool ` json:"dry_run,omitempty" `
2026-03-16 11:10:33 +00:00
}
2026-03-30 22:30:05 +00:00
// out := agentic.PrepOutput{Success: true, WorkspaceDir: ".core/workspace/core/go-io/task-15"}
2026-03-16 11:10:33 +00:00
type PrepOutput struct {
2026-04-01 18:28:42 +00:00
Success bool ` json:"success" `
WorkspaceDir string ` json:"workspace_dir" `
RepoDir string ` json:"repo_dir" `
Branch string ` json:"branch" `
Prompt string ` json:"prompt,omitempty" `
PromptVersion string ` json:"prompt_version,omitempty" `
Memories int ` json:"memories" `
Consumers int ` json:"consumers" `
Resumed bool ` json:"resumed" `
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
}
2026-03-30 22:30:05 +00:00
// dir := workspaceDir("core", "go-io", PrepInput{Issue: 15})
// dir == ".core/workspace/core/go-io/task-15"
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
func workspaceDir ( org , repo string , input PrepInput ) ( string , error ) {
2026-03-30 07:30:42 +00:00
r := workspaceDirResult ( org , repo , input )
if ! r . OK {
err , _ := r . Value . ( error )
if err == nil {
err = core . E ( "workspaceDir" , "failed to resolve workspace directory" , nil )
}
return "" , err
}
2026-03-30 21:22:54 +00:00
workspaceDir , ok := r . Value . ( string )
if ! ok || workspaceDir == "" {
2026-03-30 07:30:42 +00:00
return "" , core . E ( "workspaceDir" , "invalid workspace directory result" , nil )
}
2026-03-30 21:22:54 +00:00
return workspaceDir , nil
2026-03-30 07:30:42 +00:00
}
2026-03-30 22:30:05 +00:00
// r := workspaceDirResult("core", "go-io", PrepInput{Issue: 15})
// if r.OK { workspaceDir := r.Value.(string) }
2026-03-30 07:30:42 +00:00
func workspaceDirResult ( org , repo string , input PrepInput ) core . Result {
2026-04-02 08:58:17 +00:00
orgName , ok := validateName ( org )
if ! ok {
return core . Result { Value : core . E ( "workspaceDir" , "invalid org name" , nil ) , OK : false }
2026-03-30 14:32:01 +00:00
}
2026-04-02 08:58:17 +00:00
repoName , ok := validateName ( repo )
if ! ok {
return core . Result { Value : core . E ( "workspaceDir" , "invalid repo name" , nil ) , OK : false }
2026-03-30 14:32:01 +00:00
}
2026-04-02 08:58:17 +00:00
base := core . JoinPath ( WorkspaceRoot ( ) , orgName , repoName )
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
switch {
case input . PR > 0 :
2026-03-30 07:30:42 +00:00
return core . Result { Value : core . JoinPath ( base , core . Sprintf ( "pr-%d" , input . PR ) ) , OK : true }
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
case input . Issue > 0 :
2026-03-30 07:30:42 +00:00
return core . Result { Value : core . JoinPath ( base , core . Sprintf ( "task-%d" , input . Issue ) ) , OK : true }
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
case input . Branch != "" :
2026-03-30 07:30:42 +00:00
return core . Result { Value : core . JoinPath ( base , input . Branch ) , OK : true }
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
case input . Tag != "" :
2026-03-30 07:30:42 +00:00
return core . Result { Value : core . JoinPath ( base , input . Tag ) , OK : true }
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
default :
2026-03-30 07:30:42 +00:00
return core . Result { Value : core . E ( "workspaceDir" , "one of issue, pr, branch, or tag is required" , nil ) , OK : false }
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
}
2026-03-16 11:10:33 +00:00
}
func ( s * PrepSubsystem ) prepWorkspace ( ctx context . Context , _ * mcp . CallToolRequest , input PrepInput ) ( * mcp . CallToolResult , PrepOutput , error ) {
if input . Repo == "" {
2026-03-22 03:41:07 +00:00
return nil , PrepOutput { } , core . E ( "prepWorkspace" , "repo is required" , nil )
2026-03-16 11:10:33 +00:00
}
if input . Org == "" {
input . Org = "core"
}
if input . Template == "" {
input . Template = "coding"
}
2026-03-30 21:30:49 +00:00
workspaceResult := workspaceDirResult ( input . Org , input . Repo , input )
if ! workspaceResult . OK {
err , _ := workspaceResult . Value . ( error )
2026-03-30 07:30:42 +00:00
if err == nil {
err = core . E ( "prepWorkspace" , "workspace path not resolved" , nil )
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
return nil , PrepOutput { } , err
2026-03-21 16:22:18 +00:00
}
2026-03-30 21:30:49 +00:00
workspaceDir , ok := workspaceResult . Value . ( string )
2026-03-30 21:22:54 +00:00
if ! ok || workspaceDir == "" {
2026-03-30 07:30:42 +00:00
return nil , PrepOutput { } , core . E ( "prepWorkspace" , "invalid workspace path" , nil )
}
2026-03-21 16:22:18 +00:00
2026-03-30 21:22:54 +00:00
repoDir := workspaceRepoDir ( workspaceDir )
metaDir := workspaceMetaDir ( workspaceDir )
out := PrepOutput { WorkspaceDir : workspaceDir , RepoDir : repoDir }
2026-03-16 11:10:33 +00:00
2026-03-30 14:32:01 +00:00
repoPath := core . JoinPath ( s . codePath , input . Org , input . Repo )
2026-03-30 15:48:21 +00:00
process := s . Core ( ) . Process ( )
2026-03-16 11:10:33 +00:00
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
if r := fs . EnsureDir ( metaDir ) ; ! r . OK {
return nil , PrepOutput { } , core . E ( "prep" , "failed to create meta dir" , nil )
2026-03-21 15:59:48 +00:00
}
2026-03-16 11:10:33 +00:00
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
resumed := fs . IsDir ( core . JoinPath ( repoDir , ".git" ) )
out . Resumed = resumed
2026-03-16 11:10:33 +00:00
2026-03-29 09:22:58 +01:00
if resumed {
2026-03-30 15:48:21 +00:00
r := process . RunIn ( ctx , repoDir , "git" , "rev-parse" , "--abbrev-ref" , "HEAD" )
currentBranch := ""
if r . OK {
currentBranch = core . Trim ( r . Value . ( string ) )
}
2026-03-29 20:15:58 +00:00
defaultBranch := s . DefaultBranch ( repoDir )
if currentBranch == "" || currentBranch == "HEAD" {
currentBranch = defaultBranch
}
if currentBranch != "" {
2026-03-30 15:48:21 +00:00
process . RunIn ( ctx , repoDir , "git" , "checkout" , currentBranch )
if process . RunIn ( ctx , repoDir , "git" , "ls-remote" , "--exit-code" , "--heads" , "origin" , currentBranch ) . OK {
process . RunIn ( ctx , repoDir , "git" , "pull" , "--ff-only" , "origin" , currentBranch )
2026-03-29 20:15:58 +00:00
} else if defaultBranch != "" {
2026-03-30 15:48:21 +00:00
process . RunIn ( ctx , repoDir , "git" , "fetch" , "origin" , defaultBranch )
2026-03-29 20:15:58 +00:00
}
}
2026-03-29 09:22:58 +01:00
}
2026-03-30 21:22:54 +00:00
if result := lib . ExtractWorkspace ( "default" , workspaceDir , & lib . WorkspaceData {
2026-03-22 15:20:42 +00:00
Repo : input . Repo ,
Branch : "" ,
Task : input . Task ,
Agent : input . Agent ,
2026-03-30 19:14:14 +00:00
} ) ; ! result . OK {
if err , ok := result . Value . ( error ) ; ok {
return nil , PrepOutput { } , core . E ( "prepWorkspace" , "extract default workspace template" , err )
}
return nil , PrepOutput { } , core . E ( "prepWorkspace" , "extract default workspace template" , nil )
}
2026-03-22 15:20:42 +00:00
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
if ! resumed {
2026-03-30 15:48:21 +00:00
if r := process . RunIn ( ctx , "." , "git" , "clone" , repoPath , repoDir ) ; ! r . OK {
2026-03-26 06:38:02 +00:00
return nil , PrepOutput { } , core . E ( "prep" , core . Concat ( "git clone failed for " , input . Repo ) , nil )
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
}
2026-03-16 11:10:33 +00:00
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
taskSlug := sanitiseBranchSlug ( input . Task , 40 )
if taskSlug == "" {
if input . Issue > 0 {
taskSlug = core . Sprintf ( "issue-%d" , input . Issue )
} else if input . PR > 0 {
taskSlug = core . Sprintf ( "pr-%d" , input . PR )
} else {
taskSlug = core . Sprintf ( "work-%d" , time . Now ( ) . Unix ( ) )
}
}
branchName := core . Sprintf ( "agent/%s" , taskSlug )
2026-03-16 11:10:33 +00:00
2026-03-30 15:48:21 +00:00
if r := process . RunIn ( ctx , repoDir , "git" , "checkout" , "-b" , branchName ) ; ! r . OK {
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
return nil , PrepOutput { } , core . E ( "prep.branch" , core . Sprintf ( "failed to create branch %q" , branchName ) , nil )
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
}
out . Branch = branchName
} else {
2026-03-30 15:48:21 +00:00
r := process . RunIn ( ctx , repoDir , "git" , "rev-parse" , "--abbrev-ref" , "HEAD" )
if r . OK {
out . Branch = core . Trim ( r . Value . ( string ) )
}
2026-03-16 11:10:33 +00:00
}
2026-03-27 06:50:54 +00:00
lang := detectLanguage ( repoPath )
if lang == "php" {
if r := lib . WorkspaceFile ( "default" , "CODEX-PHP.md.tmpl" ) ; r . OK {
2026-03-30 21:22:54 +00:00
codexPath := core . JoinPath ( workspaceDir , "CODEX.md" )
2026-03-27 06:50:54 +00:00
fs . Write ( codexPath , r . Value . ( string ) )
}
}
2026-03-30 21:22:54 +00:00
s . cloneWorkspaceDeps ( ctx , workspaceDir , repoDir , input . Org )
2026-04-01 09:45:11 +00:00
if err := s . runWorkspaceLanguagePrep ( ctx , workspaceDir , repoDir ) ; err != nil {
return nil , PrepOutput { } , err
}
2026-03-26 07:37:43 +00:00
2026-03-30 21:22:54 +00:00
docsDir := core . JoinPath ( workspaceDir , ".core" , "reference" , "docs" )
2026-03-27 04:39:06 +00:00
if ! fs . IsDir ( docsDir ) {
docsRepo := core . JoinPath ( s . codePath , input . Org , "docs" )
if fs . IsDir ( core . JoinPath ( docsRepo , ".git" ) ) {
2026-03-30 15:48:21 +00:00
process . RunIn ( ctx , "." , "git" , "clone" , "--depth" , "1" , docsRepo , docsDir )
2026-03-27 04:39:06 +00:00
}
}
2026-03-30 21:22:54 +00:00
s . copyRepoSpecs ( workspaceDir , input . Repo )
2026-03-29 09:22:58 +01:00
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
out . Prompt , out . Memories , out . Consumers = s . buildPrompt ( ctx , input , out . Branch , repoPath )
2026-04-01 18:28:42 +00:00
if versionResult := writePromptSnapshot ( workspaceDir , out . Prompt ) ; ! versionResult . OK {
err , _ := versionResult . Value . ( error )
if err == nil {
err = core . E ( "prepWorkspace" , "failed to write prompt snapshot" , nil )
}
return nil , PrepOutput { } , err
} else if version , ok := versionResult . Value . ( string ) ; ok {
out . PromptVersion = version
}
2026-03-16 11:10:33 +00:00
out . Success = true
return nil , out , nil
}
2026-03-31 04:33:36 +00:00
// s.copyRepoSpecs("/tmp/workspace", "go-io") // copies plans/core/go/io/**/RFC*.md → /tmp/workspace/specs/
// s.copyRepoSpecs("/tmp/workspace", "core-bio") // copies plans/core/php/bio/**/RFC*.md → /tmp/workspace/specs/
2026-03-30 21:22:54 +00:00
func ( s * PrepSubsystem ) copyRepoSpecs ( workspaceDir , repo string ) {
2026-03-29 09:22:58 +01:00
fs := ( & core . Fs { } ) . NewUnrestricted ( )
plansBase := core . JoinPath ( s . codePath , "host-uk" , "core" , "plans" )
if ! fs . IsDir ( plansBase ) {
return
}
var specDir string
switch {
case core . HasPrefix ( repo , "go-" ) :
pkg := core . TrimPrefix ( repo , "go-" )
specDir = core . JoinPath ( plansBase , "core" , "go" , pkg )
case core . HasPrefix ( repo , "core-" ) :
mod := core . TrimPrefix ( repo , "core-" )
specDir = core . JoinPath ( plansBase , "core" , "php" , mod )
case repo == "go" :
specDir = core . JoinPath ( plansBase , "core" , "go" )
default :
specDir = core . JoinPath ( plansBase , "core" , repo )
}
if ! fs . IsDir ( specDir ) {
return
}
2026-03-30 21:22:54 +00:00
specsDir := core . JoinPath ( workspaceDir , "specs" )
2026-03-29 09:22:58 +01:00
fs . EnsureDir ( specsDir )
patterns := [ ] string {
core . JoinPath ( specDir , "RFC*.md" ) ,
core . JoinPath ( specDir , "*" , "RFC*.md" ) ,
core . JoinPath ( specDir , "*" , "*" , "RFC*.md" ) ,
core . JoinPath ( specDir , "*" , "*" , "*" , "RFC*.md" ) ,
}
for _ , pattern := range patterns {
for _ , entry := range core . PathGlob ( pattern ) {
rel := entry [ len ( specDir ) + 1 : ]
dst := core . JoinPath ( specsDir , rel )
fs . EnsureDir ( core . PathDir ( dst ) )
r := fs . Read ( entry )
if r . OK {
fs . Write ( dst , r . Value . ( string ) )
}
}
}
}
2026-03-31 06:12:53 +00:00
// _, out, err := prep.PrepareWorkspace(ctx, input)
func ( s * PrepSubsystem ) PrepareWorkspace ( ctx context . Context , input PrepInput ) ( * mcp . CallToolResult , PrepOutput , error ) {
2026-03-22 14:15:41 +00:00
return s . prepWorkspace ( ctx , nil , input )
}
2026-04-01 12:25:51 +00:00
// _, out, err := prep.TestPrepWorkspace(ctx, input)
func ( s * PrepSubsystem ) TestPrepWorkspace ( ctx context . Context , input PrepInput ) ( * mcp . CallToolResult , PrepOutput , error ) {
return s . prepWorkspace ( ctx , nil , input )
}
2026-03-31 06:12:53 +00:00
// prompt, memories, consumers := prep.BuildPrompt(ctx, input, "dev", repoPath)
func ( s * PrepSubsystem ) BuildPrompt ( ctx context . Context , input PrepInput , branch , repoPath string ) ( string , int , int ) {
2026-04-01 12:25:51 +00:00
return s . buildPrompt ( ctx , input , branch , repoPath )
}
// prompt, memories, consumers := prep.TestBuildPrompt(ctx, input, "dev", repoPath)
func ( s * PrepSubsystem ) TestBuildPrompt ( ctx context . Context , input PrepInput , branch , repoPath string ) ( string , int , int ) {
2026-03-22 14:15:41 +00:00
return s . buildPrompt ( ctx , input , branch , repoPath )
}
2026-04-02 07:23:08 +00:00
// prompt, memoryCount, consumerCount := prep.buildPrompt(ctx, input, "dev", "/srv/repos/go-io")
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
func ( s * PrepSubsystem ) buildPrompt ( ctx context . Context , input PrepInput , branch , repoPath string ) ( string , int , int ) {
2026-04-02 07:23:08 +00:00
promptBuilder := core . NewBuilder ( )
memoryCount := 0
consumerCount := 0
2026-03-16 11:10:33 +00:00
2026-04-02 07:23:08 +00:00
promptBuilder . WriteString ( "TASK: " )
promptBuilder . WriteString ( input . Task )
promptBuilder . WriteString ( "\n\n" )
2026-03-16 11:10:33 +00:00
2026-04-02 07:23:08 +00:00
promptBuilder . WriteString ( core . Sprintf ( "REPO: %s/%s on branch %s\n" , input . Org , input . Repo , branch ) )
promptBuilder . WriteString ( core . Sprintf ( "LANGUAGE: %s\n" , detectLanguage ( repoPath ) ) )
promptBuilder . WriteString ( core . Sprintf ( "BUILD: %s\n" , detectBuildCmd ( repoPath ) ) )
promptBuilder . WriteString ( core . Sprintf ( "TEST: %s\n\n" , detectTestCmd ( repoPath ) ) )
2026-03-16 11:10:33 +00:00
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
if input . Persona != "" {
2026-04-02 07:23:08 +00:00
if personaResult := lib . Persona ( input . Persona ) ; personaResult . OK {
promptBuilder . WriteString ( "PERSONA:\n" )
promptBuilder . WriteString ( personaResult . Value . ( string ) )
promptBuilder . WriteString ( "\n\n" )
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
}
2026-03-16 11:10:33 +00:00
}
2026-04-02 07:23:08 +00:00
if workflowResult := lib . Flow ( detectLanguage ( repoPath ) ) ; workflowResult . OK {
promptBuilder . WriteString ( "WORKFLOW:\n" )
promptBuilder . WriteString ( workflowResult . Value . ( string ) )
promptBuilder . WriteString ( "\n\n" )
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
if input . Issue > 0 {
2026-04-02 07:23:08 +00:00
if issueBody := s . getIssueBody ( ctx , input . Org , input . Repo , input . Issue ) ; issueBody != "" {
promptBuilder . WriteString ( "ISSUE:\n" )
promptBuilder . WriteString ( issueBody )
promptBuilder . WriteString ( "\n\n" )
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
}
2026-03-16 11:10:33 +00:00
}
2026-04-02 07:23:08 +00:00
if brainContext , count := s . brainRecall ( ctx , input . Repo ) ; brainContext != "" {
promptBuilder . WriteString ( "CONTEXT (from OpenBrain):\n" )
promptBuilder . WriteString ( brainContext )
promptBuilder . WriteString ( "\n\n" )
memoryCount = count
2026-03-16 11:10:33 +00:00
}
2026-04-02 07:23:08 +00:00
if consumerList , count := s . findConsumersList ( input . Repo ) ; consumerList != "" {
promptBuilder . WriteString ( "CONSUMERS (modules that import this repo):\n" )
promptBuilder . WriteString ( consumerList )
promptBuilder . WriteString ( "\n\n" )
consumerCount = count
2026-03-16 11:10:33 +00:00
}
2026-04-02 07:23:08 +00:00
if gitLog := s . getGitLog ( repoPath ) ; gitLog != "" {
promptBuilder . WriteString ( "RECENT CHANGES:\n```\n" )
promptBuilder . WriteString ( gitLog )
promptBuilder . WriteString ( "```\n\n" )
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
if input . PlanTemplate != "" {
2026-04-02 07:23:08 +00:00
if planText := s . renderPlan ( input . PlanTemplate , input . Variables , input . Task ) ; planText != "" {
promptBuilder . WriteString ( "PLAN:\n" )
promptBuilder . WriteString ( planText )
promptBuilder . WriteString ( "\n\n" )
2026-03-16 11:10:33 +00:00
}
}
2026-04-02 07:23:08 +00:00
promptBuilder . WriteString ( "CONSTRAINTS:\n" )
promptBuilder . WriteString ( "- Read CODEX.md for coding conventions (if it exists)\n" )
promptBuilder . WriteString ( "- Read CLAUDE.md for project-specific instructions (if it exists)\n" )
promptBuilder . WriteString ( "- Commit with conventional commit format: type(scope): description\n" )
promptBuilder . WriteString ( "- Co-Authored-By: Virgil <virgil@lethean.io>\n" )
promptBuilder . WriteString ( "- Run build and tests before committing\n" )
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
2026-04-02 07:23:08 +00:00
return promptBuilder . String ( ) , memoryCount , consumerCount
2026-03-16 11:10:33 +00:00
}
2026-04-01 18:28:42 +00:00
// writePromptSnapshot stores an immutable prompt snapshot for a workspace.
//
// snapshot := writePromptSnapshot("/srv/.core/workspace/core/go-io/task-42", "TASK: Fix tests")
func writePromptSnapshot ( workspaceDir , prompt string ) core . Result {
if workspaceDir == "" || core . Trim ( prompt ) == "" {
return core . Result { OK : true }
}
hash := promptSnapshotHash ( prompt )
snapshot := PromptVersionSnapshot {
Hash : hash ,
CreatedAt : time . Now ( ) . UTC ( ) . Format ( time . RFC3339 ) ,
Content : prompt ,
}
metaDir := WorkspaceMetaDir ( workspaceDir )
snapshotDir := core . JoinPath ( metaDir , "prompt-versions" )
if r := fs . EnsureDir ( snapshotDir ) ; ! r . OK {
err , _ := r . Value . ( error )
if err == nil {
err = core . E ( "prepWorkspace" , "failed to create prompt snapshot directory" , nil )
}
return core . Result { Value : err , OK : false }
}
snapshotPath := core . JoinPath ( snapshotDir , core . Concat ( hash , ".json" ) )
if ! fs . Exists ( snapshotPath ) {
if r := fs . WriteAtomic ( snapshotPath , core . JSONMarshalString ( snapshot ) ) ; ! r . OK {
err , _ := r . Value . ( error )
if err == nil {
err = core . E ( "prepWorkspace" , "failed to write prompt snapshot" , nil )
}
return core . Result { Value : err , OK : false }
}
}
if r := fs . WriteAtomic ( core . JoinPath ( metaDir , "prompt-version.json" ) , core . JSONMarshalString ( snapshot ) ) ; ! r . OK {
err , _ := r . Value . ( error )
if err == nil {
err = core . E ( "prepWorkspace" , "failed to write prompt version index" , nil )
}
return core . Result { Value : err , OK : false }
}
return core . Result { Value : hash , OK : true }
}
2026-04-01 21:20:44 +00:00
// snapshot := readPromptSnapshot("/srv/.core/workspace/core/go-io/task-42")
func readPromptSnapshot ( workspaceDir string ) ( PromptVersionSnapshot , error ) {
if workspaceDir == "" {
return PromptVersionSnapshot { } , core . E ( "readPromptSnapshot" , "workspace is required" , nil )
}
snapshotPath := core . JoinPath ( WorkspaceMetaDir ( workspaceDir ) , "prompt-version.json" )
result := fs . Read ( snapshotPath )
if ! result . OK {
err , _ := result . Value . ( error )
if err == nil {
err = core . E ( "readPromptSnapshot" , "prompt snapshot not found" , nil )
}
return PromptVersionSnapshot { } , err
}
var snapshot PromptVersionSnapshot
if parseResult := core . JSONUnmarshalString ( result . Value . ( string ) , & snapshot ) ; ! parseResult . OK {
err , _ := parseResult . Value . ( error )
return PromptVersionSnapshot { } , core . E ( "readPromptSnapshot" , "failed to parse prompt snapshot" , err )
}
return snapshot , nil
}
2026-04-01 18:28:42 +00:00
// snapshot := PromptVersionSnapshot{Hash: "f2c8...", Content: "TASK: Fix tests"}
type PromptVersionSnapshot struct {
Hash string ` json:"hash" `
CreatedAt string ` json:"created_at" `
Content string ` json:"content" `
}
func promptSnapshotHash ( prompt string ) string {
sum := sha256 . Sum256 ( [ ] byte ( prompt ) )
return hex . EncodeToString ( sum [ : ] )
}
2026-04-02 07:23:08 +00:00
// _ = s.runWorkspaceLanguagePrep(ctx, "/srv/.core/workspace/core/go-io/task-42", "/srv/Code/core/go-io")
2026-04-01 09:45:11 +00:00
func ( s * PrepSubsystem ) runWorkspaceLanguagePrep ( ctx context . Context , workspaceDir , repoDir string ) error {
process := s . Core ( ) . Process ( )
if fs . IsFile ( core . JoinPath ( repoDir , "go.mod" ) ) {
if result := process . RunIn ( ctx , repoDir , "go" , "mod" , "download" ) ; ! result . OK {
return core . E ( "prepWorkspace" , "go mod download failed" , nil )
}
}
if fs . IsFile ( core . JoinPath ( repoDir , "go.mod" ) ) && ( fs . IsFile ( core . JoinPath ( workspaceDir , "go.work" ) ) || fs . IsFile ( core . JoinPath ( repoDir , "go.work" ) ) ) {
if result := process . RunIn ( ctx , repoDir , "go" , "work" , "sync" ) ; ! result . OK {
return core . E ( "prepWorkspace" , "go work sync failed" , nil )
}
}
if fs . IsFile ( core . JoinPath ( repoDir , "composer.json" ) ) {
if result := process . RunIn ( ctx , repoDir , "composer" , "install" ) ; ! result . OK {
return core . E ( "prepWorkspace" , "composer install failed" , nil )
}
}
if fs . IsFile ( core . JoinPath ( repoDir , "package.json" ) ) {
if result := process . RunIn ( ctx , repoDir , "npm" , "install" ) ; ! result . OK {
return core . E ( "prepWorkspace" , "npm install failed" , nil )
}
}
return nil
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
func ( s * PrepSubsystem ) getIssueBody ( ctx context . Context , org , repo string , issue int ) string {
2026-03-22 14:15:41 +00:00
idx := core . Sprintf ( "%d" , issue )
iss , err := s . forge . Issues . Get ( ctx , forge . Params { "owner" : org , "repo" : repo , "index" : idx } )
if err != nil {
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
return ""
2026-03-16 11:10:33 +00:00
}
2026-03-22 14:15:41 +00:00
return core . Sprintf ( "# %s\n\n%s" , iss . Title , iss . Body )
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
func ( s * PrepSubsystem ) brainRecall ( ctx context . Context , repo string ) ( string , int ) {
2026-03-16 11:10:33 +00:00
if s . brainKey == "" {
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
return "" , 0
2026-03-16 11:10:33 +00:00
}
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
body := core . JSONMarshalString ( map [ string ] any {
"query" : core . Concat ( "architecture conventions key interfaces for " , repo ) ,
2026-03-16 11:10:33 +00:00
"top_k" : 10 ,
"project" : repo ,
"agent_id" : "cladius" ,
} )
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
r := HTTPPost ( ctx , core . Concat ( s . brainURL , "/v1/brain/recall" ) , body , s . brainKey , "Bearer" )
if ! r . OK {
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
return "" , 0
2026-03-17 19:27:44 +00:00
}
2026-03-16 11:10:33 +00:00
var result struct {
Memories [ ] map [ string ] any ` json:"memories" `
}
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
core . JSONUnmarshalString ( r . Value . ( string ) , & result )
2026-03-16 11:10:33 +00:00
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
if len ( result . Memories ) == 0 {
return "" , 0
}
2026-03-16 11:10:33 +00:00
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
b := core . NewBuilder ( )
2026-03-16 11:10:33 +00:00
for i , mem := range result . Memories {
memType , _ := mem [ "type" ] . ( string )
memContent , _ := mem [ "content" ] . ( string )
memProject , _ := mem [ "project" ] . ( string )
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
b . WriteString ( core . Sprintf ( "%d. [%s] %s: %s\n" , i + 1 , memType , memProject , memContent ) )
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
return b . String ( ) , len ( result . Memories )
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
func ( s * PrepSubsystem ) findConsumersList ( repo string ) ( string , int ) {
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
goWorkPath := core . JoinPath ( s . codePath , "go.work" )
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
modulePath := core . Concat ( "forge.lthn.ai/core/" , repo )
2026-03-16 11:10:33 +00:00
2026-03-22 03:41:07 +00:00
r := fs . Read ( goWorkPath )
if ! r . OK {
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
return "" , 0
2026-03-16 11:10:33 +00:00
}
2026-03-22 03:41:07 +00:00
workData := r . Value . ( string )
2026-03-16 11:10:33 +00:00
var consumers [ ] 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
for _ , line := range core . Split ( workData , "\n" ) {
line = core . Trim ( line )
if ! core . HasPrefix ( line , "./" ) {
2026-03-16 11:10:33 +00:00
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
dir := core . JoinPath ( s . codePath , core . TrimPrefix ( line , "./" ) )
goMod := core . JoinPath ( dir , "go.mod" )
2026-03-22 03:41:07 +00:00
mr := fs . Read ( goMod )
if ! mr . OK {
2026-03-16 11:10:33 +00:00
continue
}
2026-03-22 03:41:07 +00:00
modData := mr . Value . ( string )
2026-03-26 06:38:02 +00:00
if core . Contains ( modData , modulePath ) && ! core . HasPrefix ( modData , core . Concat ( "module " , modulePath ) ) {
refactor(agentic): adopt core.Env() + core.Path() across package
Replace all os.UserHomeDir/os.Getenv/os.Hostname with core.Env().
Replace all filepath.Base/Dir/Glob/IsAbs with core.PathBase/PathDir/
PathGlob/PathIsAbs.
10 files migrated: paths, prep, review_queue, remote, dispatch,
ingest, mirror, plan, verify, watch.
Imports eliminated: 5x os, 7x filepath. All file I/O and path
construction now routes through Core primitives.
Bumps dappco.re/go/core to v0.6.0.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 10:15:15 +00:00
consumers = append ( consumers , core . PathBase ( dir ) )
2026-03-16 11:10:33 +00:00
}
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
if len ( consumers ) == 0 {
return "" , 0
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
b := core . NewBuilder ( )
for _ , c := range consumers {
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
b . WriteString ( core . Concat ( "- " , c , "\n" ) )
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
}
b . WriteString ( core . Sprintf ( "Breaking change risk: %d consumers.\n" , len ( consumers ) ) )
return b . String ( ) , len ( consumers )
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
func ( s * PrepSubsystem ) getGitLog ( repoPath string ) string {
2026-03-30 15:48:21 +00:00
r := s . Core ( ) . Process ( ) . RunIn ( context . Background ( ) , repoPath , "git" , "log" , "--oneline" , "-20" )
if ! r . OK {
return ""
}
return core . Trim ( r . Value . ( string ) )
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
func ( s * PrepSubsystem ) pullWikiContent ( ctx context . Context , org , repo string ) string {
2026-03-22 14:15:41 +00:00
pages , err := s . forge . Wiki . ListPages ( ctx , org , repo )
if err != nil || len ( pages ) == 0 {
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
return ""
2026-03-16 11:10:33 +00:00
}
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
b := core . NewBuilder ( )
2026-03-22 14:15:41 +00:00
for _ , meta := range pages {
name := meta . SubURL
if name == "" {
name = meta . Title
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
}
2026-03-30 21:41:45 +00:00
page , pageErr := s . forge . Wiki . GetPage ( ctx , org , repo , name )
if pageErr != nil || page . ContentBase64 == "" {
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
continue
}
2026-03-22 14:15:41 +00:00
content , _ := base64 . StdEncoding . DecodeString ( page . ContentBase64 )
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
b . WriteString ( core . Concat ( "### " , meta . Title , "\n\n" ) )
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
b . WriteString ( string ( content ) )
b . WriteString ( "\n\n" )
}
return b . String ( )
}
func ( s * PrepSubsystem ) renderPlan ( templateSlug string , variables map [ string ] string , task string ) string {
2026-04-01 15:12:53 +00:00
definition , _ , err := loadPlanTemplateDefinition ( templateSlug , variables )
2026-03-31 14:39:40 +00:00
if err != nil {
refactor(agentic): workspace = clone, prompt replaces files
Major simplification of the dispatch model:
- Workspace dir: .core/workspace/{org}/{repo}/{pr|task|branch|tag}/
- Clone into repo/ (not src/), metadata in .meta/
- One of issue, pr, branch, or tag required for dispatch
- All context (brain, consumers, git log, wiki, plan) assembled
into prompt string — no TODO.md, PROMPT.md, CONTEXT.md files
- Resume detection: skip clone if repo/.git exists
- Default agent changed to codex
- spawnAgent drops srcDir param, runs from repo/
- No --skip-git-repo-check (repo/ IS a git repo)
- All downstream files: srcDir → repoDir
Track PRs, not workspace iterations.
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 13:41:59 +00:00
return ""
}
2026-03-31 14:39:40 +00:00
return renderPlanMarkdown ( definition , task )
2026-03-16 11:10:33 +00:00
}
2026-03-18 14:03:06 +00:00
func detectLanguage ( repoPath string ) string {
2026-03-21 17:10:43 +00:00
checks := [ ] struct {
file string
lang string
} {
{ "go.mod" , "go" } ,
{ "composer.json" , "php" } ,
{ "package.json" , "ts" } ,
{ "Cargo.toml" , "rust" } ,
{ "requirements.txt" , "py" } ,
{ "CMakeLists.txt" , "cpp" } ,
{ "Dockerfile" , "docker" } ,
}
for _ , c := range checks {
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
if fs . IsFile ( core . JoinPath ( repoPath , c . file ) ) {
2026-03-21 17:10:43 +00:00
return c . lang
2026-03-18 14:03:06 +00:00
}
}
return "go"
}
func detectBuildCmd ( repoPath string ) string {
switch detectLanguage ( repoPath ) {
case "go" :
return "go build ./..."
case "php" :
return "composer install"
case "ts" :
return "npm run build"
case "py" :
return "pip install -e ."
case "rust" :
return "cargo build"
case "cpp" :
return "cmake --build ."
default :
return "go build ./..."
}
}
func detectTestCmd ( repoPath string ) string {
switch detectLanguage ( repoPath ) {
case "go" :
return "go test ./..."
case "php" :
return "composer test"
case "ts" :
return "npm test"
case "py" :
return "pytest"
case "rust" :
return "cargo test"
case "cpp" :
return "ctest"
default :
return "go test ./..."
}
}