feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
|
|
|
|
|
|
package agentic
|
|
|
|
|
|
|
|
|
|
import (
|
2026-03-26 06:38:02 +00:00
|
|
|
"context"
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
"strings"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
2026-03-30 20:12:39 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
test: batch 1 — add 80 Bad/Ugly tests for paths, plan, status, shutdown, forge cmds
Fill missing Good/Bad/Ugly categories for:
- paths.go: LocalFs, WorkspaceRoot, CoreRoot, PlansRoot, AgentName, GitHubOrg, parseInt, DefaultBranch
- plan.go: planCreate/Read/Update/Delete/List Ugly, planPath Ugly, validPlanStatus Ugly
- status.go: writeStatus Bad, status Good/Bad
- shutdown.go: dispatchStart/shutdownGraceful Bad/Ugly, shutdownNow Ugly
- commands_forge.go: all 9 cmd* functions Ugly (with httptest mocks)
- sanitise.go: Bad/Ugly for all 5 functions
- prep.go: various lifecycle Bad/Ugly
Gap: 260 → 208 missing categories
Tests: 566 → 646 (+80)
Coverage: 74.4%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:43:35 +00:00
|
|
|
|
|
|
|
|
core "dappco.re/go/core"
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
)
|
|
|
|
|
|
2026-03-25 08:32:08 +00:00
|
|
|
func TestPaths_CoreRoot_Good_EnvVar(t *testing.T) {
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
|
|
|
|
|
assert.Equal(t, "/tmp/test-core", CoreRoot())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-25 08:32:08 +00:00
|
|
|
func TestPaths_CoreRoot_Good_Fallback(t *testing.T) {
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
t.Setenv("CORE_WORKSPACE", "")
|
2026-03-30 18:52:15 +00:00
|
|
|
home := HomeDir()
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
assert.Equal(t, home+"/Code/.core", CoreRoot())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 18:52:15 +00:00
|
|
|
func TestPaths_CoreRoot_Good_CoreHome(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "")
|
|
|
|
|
t.Setenv("CORE_HOME", "/tmp/core-home")
|
|
|
|
|
assert.Equal(t, "/tmp/core-home/Code/.core", CoreRoot())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_HomeDir_Good_CoreHome(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_HOME", "/tmp/core-home")
|
|
|
|
|
t.Setenv("HOME", "/tmp/home")
|
|
|
|
|
t.Setenv("DIR_HOME", "/tmp/dir-home")
|
|
|
|
|
assert.Equal(t, "/tmp/core-home", HomeDir())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_HomeDir_Good_HomeFallback(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_HOME", "")
|
|
|
|
|
t.Setenv("HOME", "/tmp/home")
|
|
|
|
|
t.Setenv("DIR_HOME", "/tmp/dir-home")
|
|
|
|
|
assert.Equal(t, "/tmp/home", HomeDir())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-25 08:32:08 +00:00
|
|
|
func TestPaths_WorkspaceRoot_Good(t *testing.T) {
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
|
|
|
|
|
assert.Equal(t, "/tmp/test-core/workspace", WorkspaceRoot())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-29 21:11:46 +00:00
|
|
|
func TestPaths_WorkspaceHelpers_Good(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
|
|
|
|
|
wsDir := core.JoinPath(WorkspaceRoot(), "core", "go-io", "task-5")
|
|
|
|
|
metaDir := WorkspaceMetaDir(wsDir)
|
|
|
|
|
|
|
|
|
|
assert.Equal(t, core.JoinPath(wsDir, "status.json"), WorkspaceStatusPath(wsDir))
|
|
|
|
|
assert.Equal(t, core.JoinPath(wsDir, "repo"), WorkspaceRepoDir(wsDir))
|
|
|
|
|
assert.Equal(t, core.JoinPath(wsDir, ".meta"), metaDir)
|
|
|
|
|
assert.Equal(t, core.JoinPath(wsDir, "repo", "BLOCKED.md"), WorkspaceBlockedPath(wsDir))
|
|
|
|
|
assert.Equal(t, core.JoinPath(wsDir, "repo", "ANSWER.md"), WorkspaceAnswerPath(wsDir))
|
|
|
|
|
assert.Equal(t, "core/go-io/task-5", WorkspaceName(wsDir))
|
|
|
|
|
|
|
|
|
|
assert.True(t, fs.EnsureDir(metaDir).OK)
|
|
|
|
|
assert.True(t, fs.Write(core.JoinPath(metaDir, "agent-codex.log"), "done").OK)
|
|
|
|
|
assert.Contains(t, WorkspaceLogFiles(wsDir), core.JoinPath(metaDir, "agent-codex.log"))
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 20:12:39 +00:00
|
|
|
func TestPaths_WorkspaceHelpers_Good_BranchNameWithSlash(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
|
|
|
|
|
wsDir := core.JoinPath(WorkspaceRoot(), "core", "go-io", "feature", "new-ui")
|
|
|
|
|
|
|
|
|
|
require.True(t, fs.EnsureDir(WorkspaceRepoDir(wsDir)).OK)
|
|
|
|
|
require.True(t, fs.EnsureDir(WorkspaceMetaDir(wsDir)).OK)
|
|
|
|
|
require.True(t, fs.Write(WorkspaceStatusPath(wsDir), "{}").OK)
|
|
|
|
|
|
|
|
|
|
assert.Equal(t, "core/go-io/feature/new-ui", WorkspaceName(wsDir))
|
|
|
|
|
assert.Contains(t, WorkspaceStatusPaths(), WorkspaceStatusPath(wsDir))
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-25 08:32:08 +00:00
|
|
|
func TestPaths_PlansRoot_Good(t *testing.T) {
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
|
|
|
|
|
assert.Equal(t, "/tmp/test-core/plans", PlansRoot())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-25 08:32:08 +00:00
|
|
|
func TestPaths_AgentName_Good_EnvVar(t *testing.T) {
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
t.Setenv("AGENT_NAME", "clotho")
|
|
|
|
|
assert.Equal(t, "clotho", AgentName())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-25 08:32:08 +00:00
|
|
|
func TestPaths_AgentName_Good_Fallback(t *testing.T) {
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
t.Setenv("AGENT_NAME", "")
|
|
|
|
|
name := AgentName()
|
|
|
|
|
assert.True(t, name == "cladius" || name == "charon", "expected cladius or charon, got %s", name)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-25 08:32:08 +00:00
|
|
|
func TestPaths_GitHubOrg_Good_EnvVar(t *testing.T) {
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
t.Setenv("GITHUB_ORG", "myorg")
|
|
|
|
|
assert.Equal(t, "myorg", GitHubOrg())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-25 08:32:08 +00:00
|
|
|
func TestPaths_GitHubOrg_Good_Fallback(t *testing.T) {
|
feat: rewrite CLAUDE.md, add tests for agentic + prompts packages
CLAUDE.md:
- Complete rewrite reflecting current architecture (30 files, 6.5K lines)
- Documents all 33 MCP tools, 7 agent types, dispatch flow
- Removes all references to deleted packages
Tests:
- pkg/agentic: 20 tests covering paths, extractPRNumber, truncate,
countFindings, parseRetryAfter, resolveHost, baseAgent, validPlanStatus,
generatePlanID, extractJSONField
- pkg/prompts: 7 tests covering Template, Persona, ListTemplates,
ListPersonas, prefix duplication check
Fix: rename support/support-responder → support/responder (caught by test)
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 22:09:29 +00:00
|
|
|
t.Setenv("GITHUB_ORG", "")
|
|
|
|
|
assert.Equal(t, "dAppCore", GitHubOrg())
|
|
|
|
|
}
|
|
|
|
|
|
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +00:00
|
|
|
// --- DefaultBranch ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_DefaultBranch_Good(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
|
|
|
|
|
|
|
|
|
// Init git repo with "main" branch
|
2026-03-26 06:38:02 +00:00
|
|
|
testCore.Process().Run(context.Background(), "git", "init", "-b", "main", dir)
|
|
|
|
|
testCore.Process().RunIn(context.Background(), dir, "git", "config", "user.name", "Test")
|
|
|
|
|
testCore.Process().RunIn(context.Background(), dir, "git", "config", "user.email", "test@test.com")
|
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +00:00
|
|
|
|
2026-03-26 06:38:02 +00:00
|
|
|
fs.Write(dir+"/README.md", "# Test")
|
|
|
|
|
testCore.Process().RunIn(context.Background(), dir, "git", "add", ".")
|
|
|
|
|
testCore.Process().RunIn(context.Background(), dir, "git", "commit", "-m", "init")
|
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +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
|
|
|
branch := testPrep.DefaultBranch(dir)
|
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +00:00
|
|
|
assert.Equal(t, "main", branch)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_DefaultBranch_Bad(t *testing.T) {
|
|
|
|
|
// Non-git directory — should return "main" (default)
|
|
|
|
|
dir := t.TempDir()
|
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
|
|
|
branch := testPrep.DefaultBranch(dir)
|
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +00:00
|
|
|
assert.Equal(t, "main", branch)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_DefaultBranch_Ugly(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
|
|
|
|
|
|
|
|
|
// Init git repo with "master" branch
|
2026-03-26 06:38:02 +00:00
|
|
|
testCore.Process().Run(context.Background(), "git", "init", "-b", "master", dir)
|
|
|
|
|
testCore.Process().RunIn(context.Background(), dir, "git", "config", "user.name", "Test")
|
|
|
|
|
testCore.Process().RunIn(context.Background(), dir, "git", "config", "user.email", "test@test.com")
|
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +00:00
|
|
|
|
2026-03-26 06:38:02 +00:00
|
|
|
fs.Write(dir+"/README.md", "# Test")
|
|
|
|
|
testCore.Process().RunIn(context.Background(), dir, "git", "add", ".")
|
|
|
|
|
testCore.Process().RunIn(context.Background(), dir, "git", "commit", "-m", "init")
|
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +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
|
|
|
branch := testPrep.DefaultBranch(dir)
|
test: add Good/Bad/Ugly for status, paths, auto_pr, prep — agentic 74.0%
New properly named tests:
- TestStatus_Status_Ugly — dead PID detection (blocked/completed/failed)
- TestPaths_DefaultBranch_{Good,Bad,Ugly} — main/master/non-git
- TestAutoPR_AutoCreatePR_{Good,Bad,Ugly} — early returns + no commits
- TestPrep_BuildPrompt_{Good,Bad,Ugly} — basic/empty/persona+issue
558 agentic tests, 74.0% coverage
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:16:53 +00:00
|
|
|
assert.Equal(t, "master", branch)
|
|
|
|
|
}
|
test: batch 1 — add 80 Bad/Ugly tests for paths, plan, status, shutdown, forge cmds
Fill missing Good/Bad/Ugly categories for:
- paths.go: LocalFs, WorkspaceRoot, CoreRoot, PlansRoot, AgentName, GitHubOrg, parseInt, DefaultBranch
- plan.go: planCreate/Read/Update/Delete/List Ugly, planPath Ugly, validPlanStatus Ugly
- status.go: writeStatus Bad, status Good/Bad
- shutdown.go: dispatchStart/shutdownGraceful Bad/Ugly, shutdownNow Ugly
- commands_forge.go: all 9 cmd* functions Ugly (with httptest mocks)
- sanitise.go: Bad/Ugly for all 5 functions
- prep.go: various lifecycle Bad/Ugly
Gap: 260 → 208 missing categories
Tests: 566 → 646 (+80)
Coverage: 74.4%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:43:35 +00:00
|
|
|
|
|
|
|
|
// --- LocalFs Bad/Ugly ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_LocalFs_Bad_ReadNonExistent(t *testing.T) {
|
|
|
|
|
f := LocalFs()
|
|
|
|
|
r := f.Read("/tmp/nonexistent-path-" + strings.Repeat("x", 20) + "/file.txt")
|
|
|
|
|
assert.False(t, r.OK, "reading a non-existent file should fail")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_LocalFs_Ugly_EmptyPath(t *testing.T) {
|
|
|
|
|
f := LocalFs()
|
|
|
|
|
assert.NotPanics(t, func() {
|
|
|
|
|
f.Read("")
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- WorkspaceRoot Bad/Ugly ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_WorkspaceRoot_Bad_EmptyEnv(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "")
|
2026-03-30 18:52:15 +00:00
|
|
|
home := HomeDir()
|
test: batch 1 — add 80 Bad/Ugly tests for paths, plan, status, shutdown, forge cmds
Fill missing Good/Bad/Ugly categories for:
- paths.go: LocalFs, WorkspaceRoot, CoreRoot, PlansRoot, AgentName, GitHubOrg, parseInt, DefaultBranch
- plan.go: planCreate/Read/Update/Delete/List Ugly, planPath Ugly, validPlanStatus Ugly
- status.go: writeStatus Bad, status Good/Bad
- shutdown.go: dispatchStart/shutdownGraceful Bad/Ugly, shutdownNow Ugly
- commands_forge.go: all 9 cmd* functions Ugly (with httptest mocks)
- sanitise.go: Bad/Ugly for all 5 functions
- prep.go: various lifecycle Bad/Ugly
Gap: 260 → 208 missing categories
Tests: 566 → 646 (+80)
Coverage: 74.4%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:43:35 +00:00
|
|
|
// Should fall back to ~/Code/.core/workspace
|
|
|
|
|
assert.Equal(t, home+"/Code/.core/workspace", WorkspaceRoot())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-29 21:11:46 +00:00
|
|
|
func TestPaths_WorkspaceHelpers_Bad(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "/tmp/test-core")
|
|
|
|
|
assert.Equal(t, "/status.json", WorkspaceStatusPath(""))
|
|
|
|
|
assert.Equal(t, "/repo", WorkspaceRepoDir(""))
|
|
|
|
|
assert.Equal(t, "/.meta", WorkspaceMetaDir(""))
|
|
|
|
|
assert.Equal(t, "workspace", WorkspaceName(WorkspaceRoot()))
|
|
|
|
|
assert.Empty(t, WorkspaceLogFiles("/tmp/missing-workspace"))
|
|
|
|
|
}
|
|
|
|
|
|
test: batch 1 — add 80 Bad/Ugly tests for paths, plan, status, shutdown, forge cmds
Fill missing Good/Bad/Ugly categories for:
- paths.go: LocalFs, WorkspaceRoot, CoreRoot, PlansRoot, AgentName, GitHubOrg, parseInt, DefaultBranch
- plan.go: planCreate/Read/Update/Delete/List Ugly, planPath Ugly, validPlanStatus Ugly
- status.go: writeStatus Bad, status Good/Bad
- shutdown.go: dispatchStart/shutdownGraceful Bad/Ugly, shutdownNow Ugly
- commands_forge.go: all 9 cmd* functions Ugly (with httptest mocks)
- sanitise.go: Bad/Ugly for all 5 functions
- prep.go: various lifecycle Bad/Ugly
Gap: 260 → 208 missing categories
Tests: 566 → 646 (+80)
Coverage: 74.4%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:43:35 +00:00
|
|
|
func TestPaths_WorkspaceRoot_Ugly_TrailingSlash(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "/tmp/test-core/")
|
|
|
|
|
// Verify it still constructs a valid path (JoinPath handles trailing slash)
|
|
|
|
|
ws := WorkspaceRoot()
|
|
|
|
|
assert.NotEmpty(t, ws)
|
|
|
|
|
assert.Contains(t, ws, "workspace")
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-29 21:11:46 +00:00
|
|
|
func TestPaths_WorkspaceHelpers_Ugly(t *testing.T) {
|
|
|
|
|
root := t.TempDir()
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", root)
|
|
|
|
|
wsRoot := WorkspaceRoot()
|
|
|
|
|
|
|
|
|
|
shallow := core.JoinPath(wsRoot, "ws-flat")
|
|
|
|
|
deep := core.JoinPath(wsRoot, "core", "go-io", "task-12")
|
|
|
|
|
ignored := core.JoinPath(wsRoot, "core", "go-io", "task-12", "extra")
|
|
|
|
|
|
|
|
|
|
assert.True(t, fs.EnsureDir(shallow).OK)
|
|
|
|
|
assert.True(t, fs.EnsureDir(deep).OK)
|
|
|
|
|
assert.True(t, fs.EnsureDir(ignored).OK)
|
|
|
|
|
assert.True(t, fs.Write(core.JoinPath(shallow, "status.json"), "{}").OK)
|
|
|
|
|
assert.True(t, fs.Write(core.JoinPath(deep, "status.json"), "{}").OK)
|
|
|
|
|
assert.True(t, fs.Write(core.JoinPath(ignored, "status.json"), "{}").OK)
|
|
|
|
|
|
|
|
|
|
paths := WorkspaceStatusPaths()
|
|
|
|
|
assert.Contains(t, paths, core.JoinPath(shallow, "status.json"))
|
|
|
|
|
assert.Contains(t, paths, core.JoinPath(deep, "status.json"))
|
|
|
|
|
assert.NotContains(t, paths, core.JoinPath(ignored, "status.json"))
|
|
|
|
|
}
|
|
|
|
|
|
test: batch 1 — add 80 Bad/Ugly tests for paths, plan, status, shutdown, forge cmds
Fill missing Good/Bad/Ugly categories for:
- paths.go: LocalFs, WorkspaceRoot, CoreRoot, PlansRoot, AgentName, GitHubOrg, parseInt, DefaultBranch
- plan.go: planCreate/Read/Update/Delete/List Ugly, planPath Ugly, validPlanStatus Ugly
- status.go: writeStatus Bad, status Good/Bad
- shutdown.go: dispatchStart/shutdownGraceful Bad/Ugly, shutdownNow Ugly
- commands_forge.go: all 9 cmd* functions Ugly (with httptest mocks)
- sanitise.go: Bad/Ugly for all 5 functions
- prep.go: various lifecycle Bad/Ugly
Gap: 260 → 208 missing categories
Tests: 566 → 646 (+80)
Coverage: 74.4%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:43:35 +00:00
|
|
|
// --- CoreRoot Bad/Ugly ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_CoreRoot_Bad_WhitespaceEnv(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", " ")
|
|
|
|
|
// Non-empty string (whitespace) will be used as-is
|
|
|
|
|
root := CoreRoot()
|
|
|
|
|
assert.Equal(t, " ", root)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_CoreRoot_Ugly_UnicodeEnv(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "/tmp/\u00e9\u00e0\u00fc")
|
|
|
|
|
assert.NotPanics(t, func() {
|
|
|
|
|
root := CoreRoot()
|
|
|
|
|
assert.Equal(t, "/tmp/\u00e9\u00e0\u00fc", root)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- PlansRoot Bad/Ugly ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_PlansRoot_Bad_EmptyEnv(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "")
|
2026-03-30 18:52:15 +00:00
|
|
|
home := HomeDir()
|
test: batch 1 — add 80 Bad/Ugly tests for paths, plan, status, shutdown, forge cmds
Fill missing Good/Bad/Ugly categories for:
- paths.go: LocalFs, WorkspaceRoot, CoreRoot, PlansRoot, AgentName, GitHubOrg, parseInt, DefaultBranch
- plan.go: planCreate/Read/Update/Delete/List Ugly, planPath Ugly, validPlanStatus Ugly
- status.go: writeStatus Bad, status Good/Bad
- shutdown.go: dispatchStart/shutdownGraceful Bad/Ugly, shutdownNow Ugly
- commands_forge.go: all 9 cmd* functions Ugly (with httptest mocks)
- sanitise.go: Bad/Ugly for all 5 functions
- prep.go: various lifecycle Bad/Ugly
Gap: 260 → 208 missing categories
Tests: 566 → 646 (+80)
Coverage: 74.4%
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 08:43:35 +00:00
|
|
|
assert.Equal(t, home+"/Code/.core/plans", PlansRoot())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_PlansRoot_Ugly_NestedPath(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_WORKSPACE", "/a/b/c/d/e/f")
|
|
|
|
|
assert.Equal(t, "/a/b/c/d/e/f/plans", PlansRoot())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- AgentName Bad/Ugly ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_AgentName_Bad_WhitespaceEnv(t *testing.T) {
|
|
|
|
|
t.Setenv("AGENT_NAME", " ")
|
|
|
|
|
// Whitespace is non-empty, so returned as-is
|
|
|
|
|
assert.Equal(t, " ", AgentName())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_AgentName_Ugly_UnicodeEnv(t *testing.T) {
|
|
|
|
|
t.Setenv("AGENT_NAME", "\u00e9nchantr\u00efx")
|
|
|
|
|
assert.NotPanics(t, func() {
|
|
|
|
|
name := AgentName()
|
|
|
|
|
assert.Equal(t, "\u00e9nchantr\u00efx", name)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- GitHubOrg Bad/Ugly ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_GitHubOrg_Bad_WhitespaceEnv(t *testing.T) {
|
|
|
|
|
t.Setenv("GITHUB_ORG", " ")
|
|
|
|
|
assert.Equal(t, " ", GitHubOrg())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_GitHubOrg_Ugly_SpecialChars(t *testing.T) {
|
|
|
|
|
t.Setenv("GITHUB_ORG", "org/with/slashes")
|
|
|
|
|
assert.NotPanics(t, func() {
|
|
|
|
|
org := GitHubOrg()
|
|
|
|
|
assert.Equal(t, "org/with/slashes", org)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- parseInt Bad/Ugly ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_ParseInt_Bad_EmptyString(t *testing.T) {
|
|
|
|
|
assert.Equal(t, 0, parseInt(""))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_ParseInt_Bad_NonNumeric(t *testing.T) {
|
|
|
|
|
assert.Equal(t, 0, parseInt("abc"))
|
|
|
|
|
assert.Equal(t, 0, parseInt("12.5"))
|
|
|
|
|
assert.Equal(t, 0, parseInt("0xff"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_ParseInt_Bad_WhitespaceOnly(t *testing.T) {
|
|
|
|
|
assert.Equal(t, 0, parseInt(" "))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_ParseInt_Ugly_NegativeNumber(t *testing.T) {
|
|
|
|
|
assert.Equal(t, -42, parseInt("-42"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_ParseInt_Ugly_VeryLargeNumber(t *testing.T) {
|
|
|
|
|
assert.Equal(t, 0, parseInt("99999999999999999999999"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPaths_ParseInt_Ugly_LeadingTrailingWhitespace(t *testing.T) {
|
|
|
|
|
assert.Equal(t, 42, parseInt(" 42 "))
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
// --- fs (NewUnrestricted) Good ---
|
2026-03-25 09:19:05 +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
|
|
|
func TestPaths_Fs_Good_Unrestricted(t *testing.T) {
|
|
|
|
|
assert.NotNil(t, fs, "package-level fs should be non-nil")
|
|
|
|
|
assert.IsType(t, &core.Fs{}, fs)
|
2026-03-25 09:19:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- parseInt Good ---
|
|
|
|
|
|
|
|
|
|
func TestPaths_ParseInt_Good(t *testing.T) {
|
|
|
|
|
assert.Equal(t, 42, parseInt("42"))
|
|
|
|
|
assert.Equal(t, 0, parseInt("0"))
|
|
|
|
|
}
|