fix(ax): continue AX naming cleanup
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
e825550a90
commit
da25b6f79f
17 changed files with 159 additions and 159 deletions
|
|
@ -239,7 +239,7 @@ func (s *PrepSubsystem) handleAutoPR(ctx context.Context, options core.Options)
|
|||
Repo: workspaceStatus.Repo,
|
||||
Branch: workspaceStatus.Branch,
|
||||
PRURL: workspaceStatus.PRURL,
|
||||
PRNum: extractPRNumber(workspaceStatus.PRURL),
|
||||
PRNum: extractPullRequestNumber(workspaceStatus.PRURL),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -270,13 +270,13 @@ func (s *PrepSubsystem) handleVerify(ctx context.Context, options core.Options)
|
|||
s.Core().ACTION(messages.PRMerged{
|
||||
Repo: workspaceStatus.Repo,
|
||||
PRURL: workspaceStatus.PRURL,
|
||||
PRNum: extractPRNumber(workspaceStatus.PRURL),
|
||||
PRNum: extractPullRequestNumber(workspaceStatus.PRURL),
|
||||
})
|
||||
} else if workspaceStatus.Question != "" {
|
||||
s.Core().ACTION(messages.PRNeedsReview{
|
||||
Repo: workspaceStatus.Repo,
|
||||
PRURL: workspaceStatus.PRURL,
|
||||
PRNum: extractPRNumber(workspaceStatus.PRURL),
|
||||
PRNum: extractPullRequestNumber(workspaceStatus.PRURL),
|
||||
Reason: workspaceStatus.Question,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,18 +23,18 @@ func (s *PrepSubsystem) autoCreatePR(workspaceDir string) {
|
|||
process := s.Core().Process()
|
||||
|
||||
// PRs target dev — agents never merge directly to main
|
||||
base := "dev"
|
||||
defaultBranch := "dev"
|
||||
|
||||
processResult := process.RunIn(ctx, repoDir, "git", "log", "--oneline", core.Concat("origin/", base, "..HEAD"))
|
||||
processResult := process.RunIn(ctx, repoDir, "git", "log", "--oneline", core.Concat("origin/", defaultBranch, "..HEAD"))
|
||||
if !processResult.OK {
|
||||
return
|
||||
}
|
||||
out := core.Trim(processResult.Value.(string))
|
||||
if out == "" {
|
||||
commitLogOutput := core.Trim(processResult.Value.(string))
|
||||
if commitLogOutput == "" {
|
||||
return
|
||||
}
|
||||
|
||||
commitCount := len(core.Split(out, "\n"))
|
||||
commitCount := len(core.Split(commitLogOutput, "\n"))
|
||||
|
||||
org := workspaceStatus.Org
|
||||
if org == "" {
|
||||
|
|
@ -62,7 +62,7 @@ func (s *PrepSubsystem) autoCreatePR(workspaceDir string) {
|
|||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
prURL, _, err := s.forgeCreatePR(ctx, org, workspaceStatus.Repo, workspaceStatus.Branch, base, title, body)
|
||||
pullRequestURL, _, err := s.forgeCreatePR(ctx, org, workspaceStatus.Repo, workspaceStatus.Branch, defaultBranch, title, body)
|
||||
if err != nil {
|
||||
if result := ReadStatusResult(workspaceDir); result.OK {
|
||||
workspaceStatusUpdate, ok := workspaceStatusValue(result)
|
||||
|
|
@ -81,7 +81,7 @@ func (s *PrepSubsystem) autoCreatePR(workspaceDir string) {
|
|||
if !ok {
|
||||
return
|
||||
}
|
||||
workspaceStatusUpdate.PRURL = prURL
|
||||
workspaceStatusUpdate.PRURL = pullRequestURL
|
||||
writeStatusResult(workspaceDir, workspaceStatusUpdate)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func (s *PrepSubsystem) runTask(ctx context.Context, options core.Options) core.
|
|||
repo := options.String("repo")
|
||||
agent := options.String("agent")
|
||||
task := options.String("task")
|
||||
issueStr := options.String("issue")
|
||||
issueValue := options.String("issue")
|
||||
org := options.String("org")
|
||||
|
||||
if repo == "" || task == "" {
|
||||
|
|
@ -56,7 +56,7 @@ func (s *PrepSubsystem) runTask(ctx context.Context, options core.Options) core.
|
|||
org = "core"
|
||||
}
|
||||
|
||||
issue := parseIntStr(issueStr)
|
||||
issue := parseIntStr(issueValue)
|
||||
|
||||
core.Print(nil, "core-agent run task")
|
||||
core.Print(nil, " repo: %s/%s", org, repo)
|
||||
|
|
@ -131,30 +131,30 @@ func (s *PrepSubsystem) cmdPrep(options core.Options) core.Result {
|
|||
prepInput.Branch = "dev"
|
||||
}
|
||||
|
||||
_, out, err := s.TestPrepWorkspace(context.Background(), prepInput)
|
||||
_, prepOutput, err := s.TestPrepWorkspace(context.Background(), prepInput)
|
||||
if err != nil {
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
core.Print(nil, "workspace: %s", out.WorkspaceDir)
|
||||
core.Print(nil, "repo: %s", out.RepoDir)
|
||||
core.Print(nil, "branch: %s", out.Branch)
|
||||
core.Print(nil, "resumed: %v", out.Resumed)
|
||||
core.Print(nil, "memories: %d", out.Memories)
|
||||
core.Print(nil, "consumers: %d", out.Consumers)
|
||||
if out.Prompt != "" {
|
||||
core.Print(nil, "workspace: %s", prepOutput.WorkspaceDir)
|
||||
core.Print(nil, "repo: %s", prepOutput.RepoDir)
|
||||
core.Print(nil, "branch: %s", prepOutput.Branch)
|
||||
core.Print(nil, "resumed: %v", prepOutput.Resumed)
|
||||
core.Print(nil, "memories: %d", prepOutput.Memories)
|
||||
core.Print(nil, "consumers: %d", prepOutput.Consumers)
|
||||
if prepOutput.Prompt != "" {
|
||||
core.Print(nil, "")
|
||||
core.Print(nil, "--- prompt (%d chars) ---", len(out.Prompt))
|
||||
core.Print(nil, "%s", out.Prompt)
|
||||
core.Print(nil, "--- prompt (%d chars) ---", len(prepOutput.Prompt))
|
||||
core.Print(nil, "%s", prepOutput.Prompt)
|
||||
}
|
||||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) cmdStatus(_ core.Options) core.Result {
|
||||
workspaceRoot := WorkspaceRoot()
|
||||
fsys := s.Core().Fs()
|
||||
listResult := fsys.List(workspaceRoot)
|
||||
filesystem := s.Core().Fs()
|
||||
listResult := filesystem.List(workspaceRoot)
|
||||
if !listResult.OK {
|
||||
core.Print(nil, "no workspaces found at %s", workspaceRoot)
|
||||
return core.Result{OK: true}
|
||||
|
|
@ -231,12 +231,12 @@ func (s *PrepSubsystem) cmdExtract(options core.Options) core.Result {
|
|||
return core.Result{Value: core.E("agentic.cmdExtract", core.Concat("extract workspace template ", templateName), nil), OK: false}
|
||||
}
|
||||
|
||||
fsys := s.Core().Fs()
|
||||
filesystem := s.Core().Fs()
|
||||
paths := core.PathGlob(core.JoinPath(target, "*"))
|
||||
for _, p := range paths {
|
||||
name := core.PathBase(p)
|
||||
marker := " "
|
||||
if fsys.IsDir(p) {
|
||||
if filesystem.IsDir(p) {
|
||||
marker = "/"
|
||||
}
|
||||
core.Print(nil, " %s%s", name, marker)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ func (s *PrepSubsystem) cmdWorkspaceList(_ core.Options) core.Result {
|
|||
|
||||
func (s *PrepSubsystem) cmdWorkspaceClean(options core.Options) core.Result {
|
||||
workspaceRoot := WorkspaceRoot()
|
||||
fsys := s.Core().Fs()
|
||||
filesystem := s.Core().Fs()
|
||||
filter := options.String("_arg")
|
||||
if filter == "" {
|
||||
filter = "all"
|
||||
|
|
@ -86,7 +86,7 @@ func (s *PrepSubsystem) cmdWorkspaceClean(options core.Options) core.Result {
|
|||
|
||||
for _, name := range toRemove {
|
||||
path := core.JoinPath(workspaceRoot, name)
|
||||
fsys.DeleteAll(path)
|
||||
filesystem.DeleteAll(path)
|
||||
core.Print(nil, " removed %s", name)
|
||||
}
|
||||
core.Print(nil, "\n %d workspaces removed", len(toRemove))
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ func parseCoreDeps(gomod string) []coreDep {
|
|||
repo := suffix
|
||||
if core.HasPrefix(suffix, "core/") {
|
||||
// core/process → go-process
|
||||
sub := core.TrimPrefix(suffix, "core/")
|
||||
repo = core.Concat("go-", sub)
|
||||
repoSuffix := core.TrimPrefix(suffix, "core/")
|
||||
repo = core.Concat("go-", repoSuffix)
|
||||
} else if suffix == "core" {
|
||||
repo = "go"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,12 +240,12 @@ func agentOutputFile(workspaceDir, agent string) string {
|
|||
|
||||
// detectFinalStatus reads workspace state after agent exit to determine outcome.
|
||||
// Returns (status, question) — "completed", "blocked", or "failed".
|
||||
func detectFinalStatus(repoDir string, exitCode int, procStatus string) (string, string) {
|
||||
func detectFinalStatus(repoDir string, exitCode int, processStatus string) (string, string) {
|
||||
blockedPath := core.JoinPath(repoDir, "BLOCKED.md")
|
||||
if blockedResult := fs.Read(blockedPath); blockedResult.OK && core.Trim(blockedResult.Value.(string)) != "" {
|
||||
return "blocked", core.Trim(blockedResult.Value.(string))
|
||||
}
|
||||
if exitCode != 0 || procStatus == "failed" || procStatus == "killed" {
|
||||
if exitCode != 0 || processStatus == "failed" || processStatus == "killed" {
|
||||
question := ""
|
||||
if exitCode != 0 {
|
||||
question = core.Sprintf("Agent exited with code %d", exitCode)
|
||||
|
|
@ -348,14 +348,14 @@ func (s *PrepSubsystem) broadcastComplete(agent, workspaceDir, finalStatus strin
|
|||
|
||||
// onAgentComplete handles all post-completion logic for a spawned agent.
|
||||
// Called from the monitoring goroutine after the process exits.
|
||||
func (s *PrepSubsystem) onAgentComplete(agent, workspaceDir, outputFile string, exitCode int, procStatus, output string) {
|
||||
func (s *PrepSubsystem) onAgentComplete(agent, workspaceDir, outputFile string, exitCode int, processStatus, output string) {
|
||||
// Save output
|
||||
if output != "" {
|
||||
fs.Write(outputFile, output)
|
||||
}
|
||||
|
||||
repoDir := WorkspaceRepoDir(workspaceDir)
|
||||
finalStatus, question := detectFinalStatus(repoDir, exitCode, procStatus)
|
||||
finalStatus, question := detectFinalStatus(repoDir, exitCode, processStatus)
|
||||
|
||||
// Update workspace status (disk + registry)
|
||||
result := ReadStatusResult(workspaceDir)
|
||||
|
|
|
|||
|
|
@ -727,33 +727,33 @@ func TestHandlers_FindWorkspaceByPR_Ugly_CorruptStatusFile(t *testing.T) {
|
|||
assert.Equal(t, "", result)
|
||||
}
|
||||
|
||||
// --- extractPRNumber ---
|
||||
// --- extractPullRequestNumber ---
|
||||
|
||||
func TestVerify_ExtractPRNumber_Good_FullURL(t *testing.T) {
|
||||
assert.Equal(t, 42, extractPRNumber("https://forge.lthn.ai/core/agent/pulls/42"))
|
||||
assert.Equal(t, 1, extractPRNumber("https://forge.lthn.ai/core/go-io/pulls/1"))
|
||||
assert.Equal(t, 999, extractPRNumber("https://forge.lthn.ai/core/go-log/pulls/999"))
|
||||
func TestVerify_ExtractPullRequestNumber_Good_FullURL(t *testing.T) {
|
||||
assert.Equal(t, 42, extractPullRequestNumber("https://forge.lthn.ai/core/agent/pulls/42"))
|
||||
assert.Equal(t, 1, extractPullRequestNumber("https://forge.lthn.ai/core/go-io/pulls/1"))
|
||||
assert.Equal(t, 999, extractPullRequestNumber("https://forge.lthn.ai/core/go-log/pulls/999"))
|
||||
}
|
||||
|
||||
func TestVerify_ExtractPRNumber_Good_NumberOnly(t *testing.T) {
|
||||
func TestVerify_ExtractPullRequestNumber_Good_NumberOnly(t *testing.T) {
|
||||
// If someone passes a bare number as a URL it should still work
|
||||
assert.Equal(t, 7, extractPRNumber("7"))
|
||||
assert.Equal(t, 7, extractPullRequestNumber("7"))
|
||||
}
|
||||
|
||||
func TestVerify_ExtractPRNumber_Bad_EmptyURL(t *testing.T) {
|
||||
assert.Equal(t, 0, extractPRNumber(""))
|
||||
func TestVerify_ExtractPullRequestNumber_Bad_EmptyURL(t *testing.T) {
|
||||
assert.Equal(t, 0, extractPullRequestNumber(""))
|
||||
}
|
||||
|
||||
func TestVerify_ExtractPRNumber_Bad_TrailingSlash(t *testing.T) {
|
||||
func TestVerify_ExtractPullRequestNumber_Bad_TrailingSlash(t *testing.T) {
|
||||
// URL ending with slash has empty last segment
|
||||
assert.Equal(t, 0, extractPRNumber("https://forge.lthn.ai/core/go-io/pulls/"))
|
||||
assert.Equal(t, 0, extractPullRequestNumber("https://forge.lthn.ai/core/go-io/pulls/"))
|
||||
}
|
||||
|
||||
func TestVerify_ExtractPRNumber_Bad_NonNumericEnd(t *testing.T) {
|
||||
assert.Equal(t, 0, extractPRNumber("https://forge.lthn.ai/core/go-io/pulls/abc"))
|
||||
func TestVerify_ExtractPullRequestNumber_Bad_NonNumericEnd(t *testing.T) {
|
||||
assert.Equal(t, 0, extractPullRequestNumber("https://forge.lthn.ai/core/go-io/pulls/abc"))
|
||||
}
|
||||
|
||||
func TestVerify_ExtractPRNumber_Ugly_JustSlashes(t *testing.T) {
|
||||
func TestVerify_ExtractPullRequestNumber_Ugly_JustSlashes(t *testing.T) {
|
||||
// All slashes — last segment is empty
|
||||
assert.Equal(t, 0, extractPRNumber("///"))
|
||||
assert.Equal(t, 0, extractPullRequestNumber("///"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,11 +128,11 @@ func (s *PrepSubsystem) mirror(ctx context.Context, _ *mcp.CallToolRequest, inpu
|
|||
sync.Pushed = true
|
||||
|
||||
// Create PR: dev → main on GitHub
|
||||
prURL, err := s.createGitHubPR(ctx, repoDir, repo, ahead, files)
|
||||
pullRequestURL, err := s.createGitHubPR(ctx, repoDir, repo, ahead, files)
|
||||
if err != nil {
|
||||
sync.Skipped = core.Sprintf("PR creation failed: %v", err)
|
||||
} else {
|
||||
sync.PRURL = prURL
|
||||
sync.PRURL = pullRequestURL
|
||||
}
|
||||
|
||||
synced = append(synced, sync)
|
||||
|
|
|
|||
|
|
@ -119,25 +119,25 @@ func (s *PrepSubsystem) createPR(ctx context.Context, _ *mcp.CallToolRequest, in
|
|||
}
|
||||
|
||||
// Create PR via Forge API
|
||||
prURL, prNum, err := s.forgeCreatePR(ctx, org, workspaceStatus.Repo, workspaceStatus.Branch, base, title, body)
|
||||
pullRequestURL, pullRequestNumber, err := s.forgeCreatePR(ctx, org, workspaceStatus.Repo, workspaceStatus.Branch, base, title, body)
|
||||
if err != nil {
|
||||
return nil, CreatePROutput{}, core.E("createPR", "failed to create PR", err)
|
||||
}
|
||||
|
||||
// Update status with PR URL
|
||||
workspaceStatus.PRURL = prURL
|
||||
workspaceStatus.PRURL = pullRequestURL
|
||||
writeStatusResult(workspaceDir, workspaceStatus)
|
||||
|
||||
// Comment on issue if tracked
|
||||
if workspaceStatus.Issue > 0 {
|
||||
comment := core.Sprintf("Pull request created: %s", prURL)
|
||||
comment := core.Sprintf("Pull request created: %s", pullRequestURL)
|
||||
s.commentOnIssue(ctx, org, workspaceStatus.Repo, workspaceStatus.Issue, comment)
|
||||
}
|
||||
|
||||
return nil, CreatePROutput{
|
||||
Success: true,
|
||||
PRURL: prURL,
|
||||
PRNum: prNum,
|
||||
PRURL: pullRequestURL,
|
||||
PRNum: pullRequestNumber,
|
||||
Title: title,
|
||||
Branch: workspaceStatus.Branch,
|
||||
Repo: workspaceStatus.Repo,
|
||||
|
|
@ -162,17 +162,17 @@ func (s *PrepSubsystem) buildPRBody(workspaceStatus *WorkspaceStatus) string {
|
|||
}
|
||||
|
||||
func (s *PrepSubsystem) forgeCreatePR(ctx context.Context, org, repo, head, base, title, body string) (string, int, error) {
|
||||
var pr pullRequestView
|
||||
var pullRequest pullRequestView
|
||||
err := s.forge.Client().Post(ctx, core.Sprintf("/api/v1/repos/%s/%s/pulls", org, repo), &forge_types.CreatePullRequestOption{
|
||||
Title: title,
|
||||
Body: body,
|
||||
Head: head,
|
||||
Base: base,
|
||||
}, &pr)
|
||||
}, &pullRequest)
|
||||
if err != nil {
|
||||
return "", 0, core.E("forgeCreatePR", "create PR failed", err)
|
||||
}
|
||||
return pr.HTMLURL, int(pullRequestNumber(pr)), nil
|
||||
return pullRequest.HTMLURL, int(pullRequestNumber(pullRequest)), nil
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) commentOnIssue(ctx context.Context, org, repo string, issue int, comment string) {
|
||||
|
|
@ -275,36 +275,36 @@ func (s *PrepSubsystem) listPRs(ctx context.Context, _ *mcp.CallToolRequest, inp
|
|||
}
|
||||
|
||||
func (s *PrepSubsystem) listRepoPRs(ctx context.Context, org, repo, state string) ([]PRInfo, error) {
|
||||
var prs []pullRequestView
|
||||
err := s.forge.Client().Get(ctx, core.Sprintf("/api/v1/repos/%s/%s/pulls?limit=50&page=1", org, repo), &prs)
|
||||
var pullRequests []pullRequestView
|
||||
err := s.forge.Client().Get(ctx, core.Sprintf("/api/v1/repos/%s/%s/pulls?limit=50&page=1", org, repo), &pullRequests)
|
||||
if err != nil {
|
||||
return nil, core.E("listRepoPRs", core.Concat("failed to list PRs for ", repo), err)
|
||||
}
|
||||
|
||||
var result []PRInfo
|
||||
for _, pr := range prs {
|
||||
prState := pr.State
|
||||
if prState == "" {
|
||||
prState = "open"
|
||||
for _, pullRequest := range pullRequests {
|
||||
pullRequestState := pullRequest.State
|
||||
if pullRequestState == "" {
|
||||
pullRequestState = "open"
|
||||
}
|
||||
if state != "" && state != "all" && prState != state {
|
||||
if state != "" && state != "all" && pullRequestState != state {
|
||||
continue
|
||||
}
|
||||
var labels []string
|
||||
for _, l := range pr.Labels {
|
||||
labels = append(labels, l.Name)
|
||||
for _, label := range pullRequest.Labels {
|
||||
labels = append(labels, label.Name)
|
||||
}
|
||||
result = append(result, PRInfo{
|
||||
Repo: repo,
|
||||
Number: int(pullRequestNumber(pr)),
|
||||
Title: pr.Title,
|
||||
State: prState,
|
||||
Author: pullRequestAuthor(pr),
|
||||
Branch: pr.Head.Ref,
|
||||
Base: pr.Base.Ref,
|
||||
Number: int(pullRequestNumber(pullRequest)),
|
||||
Title: pullRequest.Title,
|
||||
State: pullRequestState,
|
||||
Author: pullRequestAuthor(pullRequest),
|
||||
Branch: pullRequest.Head.Ref,
|
||||
Base: pullRequest.Base.Ref,
|
||||
Labels: labels,
|
||||
Mergeable: pr.Mergeable,
|
||||
URL: pr.HTMLURL,
|
||||
Mergeable: pullRequest.Mergeable,
|
||||
URL: pullRequest.HTMLURL,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ func (s *PrepSubsystem) SetCore(c *core.Core) {
|
|||
// OnStartup implements core.Startable — registers named Actions, starts the queue runner,
|
||||
// and registers CLI commands. The Action registry IS the capability map.
|
||||
//
|
||||
// c.Action("agentic.dispatch").Run(ctx, opts)
|
||||
// c.Action("agentic.dispatch").Run(ctx, options)
|
||||
// c.Actions() // ["agentic.dispatch", "agentic.prep", "agentic.status", ...]
|
||||
func (s *PrepSubsystem) OnStartup(ctx context.Context) core.Result {
|
||||
c := s.Core()
|
||||
|
|
@ -194,7 +194,7 @@ func (s *PrepSubsystem) OnStartup(ctx context.Context) core.Result {
|
|||
})
|
||||
|
||||
// PerformAsync wrapper — runs the completion Task in background with progress tracking.
|
||||
// c.PerformAsync("agentic.complete", opts) broadcasts ActionTaskStarted/Completed.
|
||||
// c.PerformAsync("agentic.complete", options) broadcasts ActionTaskStarted/Completed.
|
||||
c.Action("agentic.complete", s.handleComplete).Description = "Run completion pipeline (QA → PR → Verify) in background"
|
||||
|
||||
// Hydrate workspace registry from disk
|
||||
|
|
@ -552,8 +552,8 @@ func (s *PrepSubsystem) prepWorkspace(ctx context.Context, _ *mcp.CallToolReques
|
|||
// Maps repo name to plans directory: go-io → core/go/io, agent → core/agent, core-bio → core/php/bio.
|
||||
// Preserves subdirectory structure so sub-package specs land in specs/{pkg}/RFC.md.
|
||||
//
|
||||
// s.copyRepoSpecs("/tmp/ws", "go-io") // copies plans/core/go/io/**/RFC*.md → /tmp/ws/specs/
|
||||
// s.copyRepoSpecs("/tmp/ws", "core-bio") // copies plans/core/php/bio/**/RFC*.md → /tmp/ws/specs/
|
||||
// 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/
|
||||
func (s *PrepSubsystem) copyRepoSpecs(workspaceDir, repo string) {
|
||||
fs := (&core.Fs{}).NewUnrestricted()
|
||||
|
||||
|
|
@ -586,7 +586,7 @@ func (s *PrepSubsystem) copyRepoSpecs(workspaceDir, repo string) {
|
|||
}
|
||||
|
||||
// Glob RFC*.md at each depth level (root, 1 deep, 2 deep, 3 deep).
|
||||
// Preserves subdirectory structure: specDir/pkg/sub/RFC.md → specs/pkg/sub/RFC.md
|
||||
// Preserves subdirectory structure: specDir/pkg/nested/RFC.md → specs/pkg/nested/RFC.md
|
||||
specsDir := core.JoinPath(workspaceDir, "specs")
|
||||
fs.EnsureDir(specsDir)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ func (s *PrepSubsystem) autoVerifyAndMerge(workspaceDir string) {
|
|||
org = "core"
|
||||
}
|
||||
|
||||
prNum := extractPRNumber(workspaceStatus.PRURL)
|
||||
if prNum == 0 {
|
||||
pullRequestNumber := extractPullRequestNumber(workspaceStatus.PRURL)
|
||||
if pullRequestNumber == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ func (s *PrepSubsystem) autoVerifyAndMerge(workspaceDir string) {
|
|||
}
|
||||
|
||||
// Attempt 1: run tests and try to merge
|
||||
mergeOutcome := s.attemptVerifyAndMerge(repoDir, org, workspaceStatus.Repo, workspaceStatus.Branch, prNum)
|
||||
mergeOutcome := s.attemptVerifyAndMerge(repoDir, org, workspaceStatus.Repo, workspaceStatus.Branch, pullRequestNumber)
|
||||
if mergeOutcome == mergeSuccess {
|
||||
markMerged()
|
||||
return
|
||||
|
|
@ -56,7 +56,7 @@ func (s *PrepSubsystem) autoVerifyAndMerge(workspaceDir string) {
|
|||
// Attempt 2: rebase onto main and retry
|
||||
if mergeOutcome == mergeConflict || mergeOutcome == testFailed {
|
||||
if s.rebaseBranch(repoDir, workspaceStatus.Branch) {
|
||||
if s.attemptVerifyAndMerge(repoDir, org, workspaceStatus.Repo, workspaceStatus.Branch, prNum) == mergeSuccess {
|
||||
if s.attemptVerifyAndMerge(repoDir, org, workspaceStatus.Repo, workspaceStatus.Branch, pullRequestNumber) == mergeSuccess {
|
||||
markMerged()
|
||||
return
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ func (s *PrepSubsystem) autoVerifyAndMerge(workspaceDir string) {
|
|||
}
|
||||
|
||||
// Both attempts failed — flag for human review
|
||||
s.flagForReview(org, workspaceStatus.Repo, prNum, mergeOutcome)
|
||||
s.flagForReview(org, workspaceStatus.Repo, pullRequestNumber, mergeOutcome)
|
||||
|
||||
if result := ReadStatusResult(workspaceDir); result.OK {
|
||||
workspaceStatusUpdate, ok := workspaceStatusValue(result)
|
||||
|
|
@ -85,13 +85,13 @@ const (
|
|||
)
|
||||
|
||||
// attemptVerifyAndMerge runs tests and tries to merge. Returns the outcome.
|
||||
func (s *PrepSubsystem) attemptVerifyAndMerge(repoDir, org, repo, branch string, prNum int) mergeResult {
|
||||
func (s *PrepSubsystem) attemptVerifyAndMerge(repoDir, org, repo, branch string, pullRequestNumber int) mergeResult {
|
||||
testResult := s.runVerification(repoDir)
|
||||
|
||||
if !testResult.passed {
|
||||
comment := core.Sprintf("## Verification Failed\n\n**Command:** `%s`\n\n```\n%s\n```\n\n**Exit code:** %d",
|
||||
testResult.testCmd, truncate(testResult.output, 2000), testResult.exitCode)
|
||||
s.commentOnIssue(context.Background(), org, repo, prNum, comment)
|
||||
s.commentOnIssue(context.Background(), org, repo, pullRequestNumber, comment)
|
||||
return testFailed
|
||||
}
|
||||
|
||||
|
|
@ -99,14 +99,14 @@ func (s *PrepSubsystem) attemptVerifyAndMerge(repoDir, org, repo, branch string,
|
|||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if mergeResult := s.forgeMergePR(ctx, org, repo, prNum); !mergeResult.OK {
|
||||
if mergeAttempt := s.forgeMergePR(ctx, org, repo, pullRequestNumber); !mergeAttempt.OK {
|
||||
comment := core.Sprintf("## Tests Passed — Merge Failed\n\n`%s` passed but merge failed", testResult.testCmd)
|
||||
s.commentOnIssue(context.Background(), org, repo, prNum, comment)
|
||||
s.commentOnIssue(context.Background(), org, repo, pullRequestNumber, comment)
|
||||
return mergeConflict
|
||||
}
|
||||
|
||||
comment := core.Sprintf("## Auto-Verified & Merged\n\n**Tests:** `%s` — PASS\n\nAuto-merged by core-agent dispatch system.", testResult.testCmd)
|
||||
s.commentOnIssue(context.Background(), org, repo, prNum, comment)
|
||||
s.commentOnIssue(context.Background(), org, repo, pullRequestNumber, comment)
|
||||
return mergeSuccess
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ func (s *PrepSubsystem) rebaseBranch(repoDir, branch string) bool {
|
|||
}
|
||||
|
||||
// flagForReview adds the "needs-review" label to the PR via Forge API.
|
||||
func (s *PrepSubsystem) flagForReview(org, repo string, prNum int, result mergeResult) {
|
||||
func (s *PrepSubsystem) flagForReview(org, repo string, pullRequestNumber int, mergeOutcome mergeResult) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
|
|
@ -151,16 +151,16 @@ func (s *PrepSubsystem) flagForReview(org, repo string, prNum int, result mergeR
|
|||
payload := core.JSONMarshalString(map[string]any{
|
||||
"labels": []int{s.getLabelID(ctx, org, repo, "needs-review")},
|
||||
})
|
||||
url := core.Sprintf("%s/api/v1/repos/%s/%s/issues/%d/labels", s.forgeURL, org, repo, prNum)
|
||||
url := core.Sprintf("%s/api/v1/repos/%s/%s/issues/%d/labels", s.forgeURL, org, repo, pullRequestNumber)
|
||||
HTTPPost(ctx, url, payload, s.forgeToken, "token")
|
||||
|
||||
// Comment explaining the situation
|
||||
reason := "Tests failed after rebase"
|
||||
if result == mergeConflict {
|
||||
if mergeOutcome == mergeConflict {
|
||||
reason = "Merge conflict persists after rebase"
|
||||
}
|
||||
comment := core.Sprintf("## Needs Review\n\n%s. Auto-merge gave up after retry.\n\nLabelled `needs-review` for human attention.", reason)
|
||||
s.commentOnIssue(ctx, org, repo, prNum, comment)
|
||||
s.commentOnIssue(ctx, org, repo, pullRequestNumber, comment)
|
||||
}
|
||||
|
||||
// ensureLabel creates a label if it doesn't exist.
|
||||
|
|
@ -278,20 +278,20 @@ func (s *PrepSubsystem) runNodeTests(repoDir string) verifyResult {
|
|||
}
|
||||
|
||||
// forgeMergePR merges a PR via the Forge API.
|
||||
func (s *PrepSubsystem) forgeMergePR(ctx context.Context, org, repo string, prNum int) core.Result {
|
||||
func (s *PrepSubsystem) forgeMergePR(ctx context.Context, org, repo string, pullRequestNumber int) core.Result {
|
||||
payload := core.JSONMarshalString(map[string]any{
|
||||
"Do": "merge",
|
||||
"merge_message_field": "Auto-merged by core-agent after verification\n\nCo-Authored-By: Virgil <virgil@lethean.io>",
|
||||
"delete_branch_after_merge": true,
|
||||
})
|
||||
|
||||
url := core.Sprintf("%s/api/v1/repos/%s/%s/pulls/%d/merge", s.forgeURL, org, repo, prNum)
|
||||
url := core.Sprintf("%s/api/v1/repos/%s/%s/pulls/%d/merge", s.forgeURL, org, repo, pullRequestNumber)
|
||||
return HTTPPost(ctx, url, payload, s.forgeToken, "token")
|
||||
}
|
||||
|
||||
// extractPRNumber gets the PR number from a Forge PR URL.
|
||||
func extractPRNumber(prURL string) int {
|
||||
parts := core.Split(prURL, "/")
|
||||
// extractPullRequestNumber gets the PR number from a Forge PR URL.
|
||||
func extractPullRequestNumber(pullRequestURL string) int {
|
||||
parts := core.Split(pullRequestURL, "/")
|
||||
if len(parts) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,23 +122,23 @@ func TestVerify_ForgeMergePR_Bad_NetworkError(t *testing.T) {
|
|||
assert.False(t, r.OK)
|
||||
}
|
||||
|
||||
// --- extractPRNumber (additional _Ugly cases) ---
|
||||
// --- extractPullRequestNumber (additional _Ugly cases) ---
|
||||
|
||||
func TestVerify_ExtractPRNumber_Ugly_DoubleSlashEnd(t *testing.T) {
|
||||
assert.Equal(t, 0, extractPRNumber("https://forge.lthn.ai/core/go-io/pulls/42/"))
|
||||
func TestVerify_ExtractPullRequestNumber_Ugly_DoubleSlashEnd(t *testing.T) {
|
||||
assert.Equal(t, 0, extractPullRequestNumber("https://forge.lthn.ai/core/go-io/pulls/42/"))
|
||||
}
|
||||
|
||||
func TestVerify_ExtractPRNumber_Ugly_VeryLargeNumber(t *testing.T) {
|
||||
assert.Equal(t, 999999, extractPRNumber("https://forge.lthn.ai/core/go-io/pulls/999999"))
|
||||
func TestVerify_ExtractPullRequestNumber_Ugly_VeryLargeNumber(t *testing.T) {
|
||||
assert.Equal(t, 999999, extractPullRequestNumber("https://forge.lthn.ai/core/go-io/pulls/999999"))
|
||||
}
|
||||
|
||||
func TestVerify_ExtractPRNumber_Ugly_NegativeNumber(t *testing.T) {
|
||||
func TestVerify_ExtractPullRequestNumber_Ugly_NegativeNumber(t *testing.T) {
|
||||
// atoi of "-5" is -5, parseInt wraps atoi
|
||||
assert.Equal(t, -5, extractPRNumber("https://forge.lthn.ai/core/go-io/pulls/-5"))
|
||||
assert.Equal(t, -5, extractPullRequestNumber("https://forge.lthn.ai/core/go-io/pulls/-5"))
|
||||
}
|
||||
|
||||
func TestVerify_ExtractPRNumber_Ugly_ZeroExplicit(t *testing.T) {
|
||||
assert.Equal(t, 0, extractPRNumber("https://forge.lthn.ai/core/go-io/pulls/0"))
|
||||
func TestVerify_ExtractPullRequestNumber_Ugly_ZeroExplicit(t *testing.T) {
|
||||
assert.Equal(t, 0, extractPullRequestNumber("https://forge.lthn.ai/core/go-io/pulls/0"))
|
||||
}
|
||||
|
||||
// --- ensureLabel ---
|
||||
|
|
@ -410,7 +410,7 @@ func TestVerify_AutoVerifyAndMerge_Bad_InvalidPRURL(t *testing.T) {
|
|||
failCount: make(map[string]int),
|
||||
}
|
||||
|
||||
// extractPRNumber returns 0 for invalid URL, so autoVerifyAndMerge returns early
|
||||
// extractPullRequestNumber returns 0 for invalid URL, so autoVerifyAndMerge returns early
|
||||
assert.NotPanics(t, func() {
|
||||
s.autoVerifyAndMerge(dir)
|
||||
})
|
||||
|
|
@ -519,7 +519,7 @@ func TestAutopr_Truncate_Ugly_EmptyString(t *testing.T) {
|
|||
|
||||
func TestVerify_AutoVerifyAndMerge_Ugly(t *testing.T) {
|
||||
// Workspace with status=completed, repo=test, PRURL="not-a-url"
|
||||
// extractPRNumber returns 0 for "not-a-url" → early return, no panic
|
||||
// extractPullRequestNumber returns 0 for "not-a-url" → early return, no panic
|
||||
dir := t.TempDir()
|
||||
require.NoError(t, writeStatus(dir, &WorkspaceStatus{
|
||||
Status: "completed",
|
||||
|
|
@ -580,17 +580,17 @@ func TestVerify_AttemptVerifyAndMerge_Ugly(t *testing.T) {
|
|||
assert.True(t, commentCalled, "should have posted a comment about test failure")
|
||||
}
|
||||
|
||||
// --- extractPRNumber (extended Ugly) ---
|
||||
// --- extractPullRequestNumber (extended Ugly) ---
|
||||
|
||||
func TestVerify_ExtractPRNumber_Ugly(t *testing.T) {
|
||||
func TestVerify_ExtractPullRequestNumber_Ugly(t *testing.T) {
|
||||
// Just a bare number "5" → last segment is "5" → returns 5
|
||||
assert.Equal(t, 5, extractPRNumber("5"))
|
||||
assert.Equal(t, 5, extractPullRequestNumber("5"))
|
||||
|
||||
// Trailing slash → last segment is empty string → parseInt("") → 0
|
||||
assert.Equal(t, 0, extractPRNumber("https://forge.lthn.ai/core/go-io/pulls/42/"))
|
||||
assert.Equal(t, 0, extractPullRequestNumber("https://forge.lthn.ai/core/go-io/pulls/42/"))
|
||||
|
||||
// Non-numeric string → parseInt("abc") → 0
|
||||
assert.Equal(t, 0, extractPRNumber("abc"))
|
||||
assert.Equal(t, 0, extractPullRequestNumber("abc"))
|
||||
}
|
||||
|
||||
// --- EnsureLabel Ugly ---
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
// Package brain gives MCP and HTTP services the same OpenBrain capability map.
|
||||
//
|
||||
// sub := brain.New(nil)
|
||||
// core.Println(sub.Name())
|
||||
// subsystem := brain.New(nil)
|
||||
// core.Println(subsystem.Name())
|
||||
package brain
|
||||
|
||||
import (
|
||||
|
|
@ -33,36 +33,36 @@ var errBridgeNotAvailable = core.E("brain", "bridge not available", nil)
|
|||
|
||||
// Subsystem routes `brain_*` MCP tools through the shared IDE bridge.
|
||||
//
|
||||
// sub := brain.New(nil)
|
||||
// core.Println(sub.Name()) // "brain"
|
||||
// subsystem := brain.New(nil)
|
||||
// core.Println(subsystem.Name()) // "brain"
|
||||
type Subsystem struct {
|
||||
bridge *ide.Bridge
|
||||
}
|
||||
|
||||
// New builds the bridge-backed OpenBrain subsystem used by MCP.
|
||||
//
|
||||
// sub := brain.New(nil)
|
||||
// core.Println(sub.Name())
|
||||
// subsystem := brain.New(nil)
|
||||
// core.Println(subsystem.Name())
|
||||
func New(bridge *ide.Bridge) *Subsystem {
|
||||
return &Subsystem{bridge: bridge}
|
||||
}
|
||||
|
||||
// Name keeps the subsystem address stable for core.WithService and MCP.
|
||||
//
|
||||
// name := sub.Name() // "brain"
|
||||
// name := subsystem.Name() // "brain"
|
||||
func (s *Subsystem) Name() string { return "brain" }
|
||||
|
||||
// RegisterTools publishes the bridge-backed brain tools on an MCP server.
|
||||
//
|
||||
// sub := brain.New(nil)
|
||||
// sub.RegisterTools(server)
|
||||
// subsystem := brain.New(nil)
|
||||
// subsystem.RegisterTools(server)
|
||||
func (s *Subsystem) RegisterTools(server *mcp.Server) {
|
||||
s.registerBrainTools(server)
|
||||
}
|
||||
|
||||
// Shutdown satisfies the MCP subsystem lifecycle without extra cleanup.
|
||||
//
|
||||
// _ = sub.Shutdown(context.Background())
|
||||
// _ = subsystem.Shutdown(context.Background())
|
||||
func (s *Subsystem) Shutdown(_ context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import (
|
|||
|
||||
// DirectSubsystem talks to OpenBrain over HTTP without the IDE bridge.
|
||||
//
|
||||
// sub := brain.NewDirect()
|
||||
// core.Println(sub.Name()) // "brain"
|
||||
// subsystem := brain.NewDirect()
|
||||
// core.Println(subsystem.Name()) // "brain"
|
||||
type DirectSubsystem struct {
|
||||
apiURL string
|
||||
apiKey string
|
||||
|
|
@ -25,8 +25,8 @@ var _ coremcp.Subsystem = (*DirectSubsystem)(nil)
|
|||
|
||||
// NewDirect builds the HTTP-backed OpenBrain subsystem.
|
||||
//
|
||||
// sub := brain.NewDirect()
|
||||
// core.Println(sub.Name())
|
||||
// subsystem := brain.NewDirect()
|
||||
// core.Println(subsystem.Name())
|
||||
func NewDirect() *DirectSubsystem {
|
||||
apiURL := core.Env("CORE_BRAIN_URL")
|
||||
if apiURL == "" {
|
||||
|
|
@ -58,13 +58,13 @@ func NewDirect() *DirectSubsystem {
|
|||
|
||||
// Name keeps the direct subsystem address stable for core.WithService and MCP.
|
||||
//
|
||||
// name := sub.Name() // "brain"
|
||||
// name := subsystem.Name() // "brain"
|
||||
func (s *DirectSubsystem) Name() string { return "brain" }
|
||||
|
||||
// RegisterTools publishes the direct `brain_*` and `agent_*` tools on an MCP server.
|
||||
//
|
||||
// sub := brain.NewDirect()
|
||||
// sub.RegisterTools(server)
|
||||
// subsystem := brain.NewDirect()
|
||||
// subsystem.RegisterTools(server)
|
||||
func (s *DirectSubsystem) RegisterTools(server *mcp.Server) {
|
||||
mcp.AddTool(server, &mcp.Tool{
|
||||
Name: "brain_remember",
|
||||
|
|
@ -87,7 +87,7 @@ func (s *DirectSubsystem) RegisterTools(server *mcp.Server) {
|
|||
|
||||
// Shutdown satisfies the MCP subsystem lifecycle without extra cleanup.
|
||||
//
|
||||
// _ = sub.Shutdown(context.Background())
|
||||
// _ = subsystem.Shutdown(context.Background())
|
||||
func (s *DirectSubsystem) Shutdown(_ context.Context) error { return nil }
|
||||
|
||||
func brainKeyPath(home string) string {
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import (
|
|||
|
||||
// RegisterMessagingTools adds direct agent messaging tools to an MCP server.
|
||||
//
|
||||
// sub := brain.NewDirect()
|
||||
// sub.RegisterMessagingTools(server)
|
||||
// subsystem := brain.NewDirect()
|
||||
// subsystem.RegisterMessagingTools(server)
|
||||
func (s *DirectSubsystem) RegisterMessagingTools(server *mcp.Server) {
|
||||
mcp.AddTool(server, &mcp.Tool{
|
||||
Name: "agent_send",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
// r := lib.Task("code/review") // r.Value.(string)
|
||||
// r := lib.Persona("secops/dev") // r.Value.(string)
|
||||
// r := lib.Flow("go") // r.Value.(string)
|
||||
// r := lib.ExtractWorkspace("default", "/tmp/ws", data)
|
||||
// r := lib.ExtractWorkspace("default", "/tmp/workspace", data)
|
||||
// core.Println(r.OK)
|
||||
package lib
|
||||
|
||||
|
|
@ -80,18 +80,18 @@ func ensureMounted() core.Result {
|
|||
mountedData := &core.Data{Registry: core.NewRegistry[*core.Embed]()}
|
||||
|
||||
for _, item := range []struct {
|
||||
name string
|
||||
fsys embed.FS
|
||||
basedir string
|
||||
assign func(*core.Embed)
|
||||
name string
|
||||
filesystem embed.FS
|
||||
baseDir string
|
||||
assign func(*core.Embed)
|
||||
}{
|
||||
{name: "prompt", fsys: promptFiles, basedir: "prompt", assign: func(emb *core.Embed) { promptFS = emb }},
|
||||
{name: "task", fsys: taskFiles, basedir: "task", assign: func(emb *core.Embed) { taskFS = emb }},
|
||||
{name: "flow", fsys: flowFiles, basedir: "flow", assign: func(emb *core.Embed) { flowFS = emb }},
|
||||
{name: "persona", fsys: personaFiles, basedir: "persona", assign: func(emb *core.Embed) { personaFS = emb }},
|
||||
{name: "workspace", fsys: workspaceFiles, basedir: "workspace", assign: func(emb *core.Embed) { workspaceFS = emb }},
|
||||
{name: "prompt", filesystem: promptFiles, baseDir: "prompt", assign: func(emb *core.Embed) { promptFS = emb }},
|
||||
{name: "task", filesystem: taskFiles, baseDir: "task", assign: func(emb *core.Embed) { taskFS = emb }},
|
||||
{name: "flow", filesystem: flowFiles, baseDir: "flow", assign: func(emb *core.Embed) { flowFS = emb }},
|
||||
{name: "persona", filesystem: personaFiles, baseDir: "persona", assign: func(emb *core.Embed) { personaFS = emb }},
|
||||
{name: "workspace", filesystem: workspaceFiles, baseDir: "workspace", assign: func(emb *core.Embed) { workspaceFS = emb }},
|
||||
} {
|
||||
mounted := mountEmbed(item.fsys, item.basedir)
|
||||
mounted := mountEmbed(item.filesystem, item.baseDir)
|
||||
if !mounted.OK {
|
||||
mountResult = mounted
|
||||
return
|
||||
|
|
@ -109,21 +109,21 @@ func ensureMounted() core.Result {
|
|||
return mountResult
|
||||
}
|
||||
|
||||
func mountEmbed(fsys embed.FS, basedir string) core.Result {
|
||||
result := core.Mount(fsys, basedir)
|
||||
func mountEmbed(filesystem embed.FS, baseDir string) core.Result {
|
||||
result := core.Mount(filesystem, baseDir)
|
||||
if result.OK {
|
||||
return result
|
||||
}
|
||||
|
||||
if err, ok := result.Value.(error); ok {
|
||||
return core.Result{
|
||||
Value: core.E("lib.mountEmbed", core.Concat("mount ", basedir), err),
|
||||
Value: core.E("lib.mountEmbed", core.Concat("mount ", baseDir), err),
|
||||
OK: false,
|
||||
}
|
||||
}
|
||||
|
||||
return core.Result{
|
||||
Value: core.E("lib.mountEmbed", core.Concat("mount ", basedir), nil),
|
||||
Value: core.E("lib.mountEmbed", core.Concat("mount ", baseDir), nil),
|
||||
OK: false,
|
||||
}
|
||||
}
|
||||
|
|
@ -355,9 +355,9 @@ func ListTasks() []string {
|
|||
}
|
||||
|
||||
result := listNamesRecursive("task", ".")
|
||||
a := core.NewArray(result...)
|
||||
a.Deduplicate()
|
||||
return a.AsSlice()
|
||||
names := core.NewArray(result...)
|
||||
names.Deduplicate()
|
||||
return names.AsSlice()
|
||||
}
|
||||
|
||||
// ListPersonas returns available persona paths, including nested directories.
|
||||
|
|
@ -368,9 +368,9 @@ func ListPersonas() []string {
|
|||
return nil
|
||||
}
|
||||
|
||||
a := core.NewArray(listNamesRecursive("persona", ".")...)
|
||||
a.Deduplicate()
|
||||
return a.AsSlice()
|
||||
names := core.NewArray(listNamesRecursive("persona", ".")...)
|
||||
names.Deduplicate()
|
||||
return names.AsSlice()
|
||||
}
|
||||
|
||||
// listNamesRecursive walks an embed tree via Data.ListNames.
|
||||
|
|
@ -397,7 +397,7 @@ func listNamesRecursive(mount, dir string) []string {
|
|||
subPath := core.JoinPath(mount, relPath)
|
||||
|
||||
// Try as directory — recurse if it has contents
|
||||
if sub := data.ListNames(subPath); sub.OK {
|
||||
if childNames := data.ListNames(subPath); childNames.OK {
|
||||
slugs = append(slugs, listNamesRecursive(mount, relPath)...)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ var _ coremcp.Subsystem = (*Subsystem)(nil)
|
|||
|
||||
// Deprecated: prefer Register with core.WithService(monitor.Register).
|
||||
//
|
||||
// mon.SetCore(c)
|
||||
// monitorService.SetCore(c)
|
||||
func (m *Subsystem) SetCore(coreApp *core.Core) {
|
||||
m.ServiceRuntime = core.NewServiceRuntime(coreApp, Options{})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue