Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0a4c589
style: gofmt and goimports fixes for lint
Delqhi Jun 14, 2026
5ac0bd9
test(coverage): remaining test hooks for superpowers, vane, tui/chat …
Delqhi Jun 14, 2026
b989b00
test(coverage): add missing test hooks and tests for tui/chat, superp…
Delqhi Jun 14, 2026
aaeccdc
test(coverage): 100% statement coverage for todo package
Delqhi Jun 15, 2026
0754a8e
test(coverage): 100% statement coverage for superpowers, internal/tui…
Delqhi Jun 15, 2026
cfef82f
feat(skills): bundle 23 project-local skills into sin-code binary
Delqhi Jun 15, 2026
7880df5
chore(deps): add github.com/Songmu/skillsmith for bundled skills
Delqhi Jun 15, 2026
d150dff
style: fix ruff import blank line in validate_skill.py
Delqhi Jun 15, 2026
6dead01
style: fix ruff lint errors across Python codebase
Delqhi Jun 15, 2026
3be5cd1
style: fix pycodestyle E127/E128/E302/E306 in sin_delegate
Delqhi Jun 15, 2026
3c10b55
style: sort imports in test_intelligence_multirepo.py
Delqhi Jun 15, 2026
e486f8d
style: fix ruff/pycodestyle/pyflakes lint errors and go vet sync.Once…
Delqhi Jun 15, 2026
c7cd762
style: fix ruff/pycodestyle/pyflakes across entire repo and go vet sy…
Delqhi Jun 15, 2026
6b091cd
ci: configure git identity and mcp for delegate tests; goimports fixes
Jun 15, 2026
e7417d0
security: fix gosec alerts in todo/audit, todo/id, webui/server (sha1…
Jun 15, 2026
4181bc2
fix: gosec G115/G204 and flaky ledger benchmark threshold
Jun 15, 2026
8970090
feat(skills): add shop-skills category with cj-dropshipping, stripe, …
Jun 15, 2026
ce45db8
chore(skills): add MIT LICENSE files to shop-skills
Jun 15, 2026
293feaa
chore(skills): add context/frameworks/tasks/templates content to shop…
Jun 15, 2026
5499973
feat(skills): add infrastructure-skills category with supabase, cloud…
Jun 15, 2026
cd6fd69
feat(skills): reorganize all bundled skills into category directories…
Jun 15, 2026
03faf1f
style(skills): gofmt flatfs.go
Jun 15, 2026
dc884d8
feat(skills): rename all bundled skills to skill-<category>-<name> an…
Jun 15, 2026
9901bff
test(bench): relax flaky ledger append threshold from 7s to 15s
Jun 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion cmd/sin-code/internal/attachments/attachments.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ var (
osReadDir = os.ReadDir
)


type Attachment struct {
ID string `json:"id"`
Hash string `json:"hash"`
Expand Down
10 changes: 5 additions & 5 deletions cmd/sin-code/internal/attachments/attachments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,11 @@ func TestGetInfoError(t *testing.T) {

type infoErrEntry string

func (e infoErrEntry) Name() string { return string(e) }
func (e infoErrEntry) IsDir() bool { return false }
func (e infoErrEntry) Type() os.FileMode { return 0 }
func (e infoErrEntry) Info() (os.FileInfo, error) { return nil, fmt.Errorf("info error") }
func (e infoErrEntry) String() string { return string(e) }
func (e infoErrEntry) Name() string { return string(e) }
func (e infoErrEntry) IsDir() bool { return false }
func (e infoErrEntry) Type() os.FileMode { return 0 }
func (e infoErrEntry) Info() (os.FileInfo, error) { return nil, fmt.Errorf("info error") }
func (e infoErrEntry) String() string { return string(e) }

func TestGetPrefixMismatch(t *testing.T) {
dir := t.TempDir()
Expand Down
16 changes: 12 additions & 4 deletions cmd/sin-code/internal/superpowers/mcpserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ import (
"sync"
)

// testHook variables expose hard-to-reach error paths to the test suite.
var (
mcpListFunc = List
mcpFindFunc = Find
mcpGetFunc = Get
mcpReadFile = os.ReadFile
)

// Server is the stdio MCP server. Construct with NewServer, then call
// Serve(ctx) which blocks until ctx is cancelled or stdin reaches EOF.
type Server struct {
Expand Down Expand Up @@ -123,7 +131,7 @@ func (s *Server) result(req *jsonRPCRequest, v any) *jsonRPCResponse {
func (s *Server) callTool(ctx context.Context, req *jsonRPCRequest, p *toolCallParams) *jsonRPCResponse {
switch p.Name {
case "superpowers_list_skills":
all, err := List("")
all, err := mcpListFunc("")
if err != nil {
return s.errResult(req, err)
}
Expand All @@ -134,7 +142,7 @@ func (s *Server) callTool(ctx context.Context, req *jsonRPCRequest, p *toolCallP
MaxResults int `json:"max_results"`
}
_ = json.Unmarshal(p.Arguments, &args)
hits, err := Find(args.Query, args.MaxResults)
hits, err := mcpFindFunc(args.Query, args.MaxResults)
if err != nil {
return s.errResult(req, err)
}
Expand All @@ -144,11 +152,11 @@ func (s *Server) callTool(ctx context.Context, req *jsonRPCRequest, p *toolCallP
Name string `json:"name"`
}
_ = json.Unmarshal(p.Arguments, &args)
info, err := Get(args.Name)
info, err := mcpGetFunc(args.Name)
if err != nil {
return s.errResult(req, err)
}
body, rerr := os.ReadFile(info.Path)
body, rerr := mcpReadFile(info.Path)
if rerr != nil {
return s.errResult(req, rerr)
}
Expand Down
8 changes: 6 additions & 2 deletions cmd/sin-code/internal/superpowers/overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
// sentinels (defined in superpowers.go) and is detected via a substring
// search. Any other text in the file is preserved verbatim.
func AppendOverlay(path string) bool {
body, err := os.ReadFile(path)
body, err := overlayReadFile(path)
if err != nil {
return false
}
Expand All @@ -40,9 +40,13 @@ func AppendOverlay(path string) bool {
}
b.WriteByte('\n')
b.WriteString(overlay)
return os.WriteFile(path, []byte(b.String()), 0o644) == nil
return overlayWriteFile(path, []byte(b.String()), 0o644) == nil
}

// testHook variables expose hard-to-reach error paths to the test suite.
var overlayReadFile = os.ReadFile
var overlayWriteFile = os.WriteFile

// OverlayKind tags the rendered block with a stable identifier so the
// same RenderOverlay can produce skill- vs root-level overlays with
// different wording.
Expand Down
75 changes: 48 additions & 27 deletions cmd/sin-code/internal/superpowers/superpowers.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,27 @@
// corpus on `main`.
const DefaultBranch = "main"

// testHook variables expose hard-to-reach error paths to the test suite
// without heavy refactoring. They are restored per-test via t.Cleanup.
var (
osUserHomeDir = os.UserHomeDir
osMkdirAll = os.MkdirAll
osStat = os.Stat
osReadFile = os.ReadFile
osWriteFile = os.WriteFile
osCreateTemp = os.CreateTemp
osRenameHook = os.Rename
jsonMarshalIndent = json.MarshalIndent
jsonUnmarshal = json.Unmarshal
ioCopyHook = io.Copy
fileWriteHook = func(f *os.File, p []byte) (int, error) { return f.Write(p) }
fileCloseHook = func(f *os.File) error { return f.Close() }
runGitHook = runGit
currentShaHook = currentSHA
currentBranchHook = currentBranch
walkDirHook = filepath.WalkDir
)

// OverlayMarker is the sentinel HTML comment that delimiters the
// automatically-appended overlay block. Idempotency: if the marker is
// already present in a SKILL.md, AppendOverlay is a no-op for that file.
Expand All @@ -49,7 +70,7 @@
return v
}
// Use os.UserHomeDir for cross-platform safety (macOS/Linux/Windows).
if h, err := os.UserHomeDir(); err == nil {
if h, err := osUserHomeDir(); err == nil {
return filepath.Join(h, ".local", "share", "sin-code")
}
// Last resort: cwd-relative fallback so the function is total.
Expand Down Expand Up @@ -124,25 +145,25 @@
}
start := time.Now()
dst := SkillsDir()
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
if err := osMkdirAll(filepath.Dir(dst), 0o755); err != nil {
return nil, fmt.Errorf("mkdir: %w", err)
}
if _, err := os.Stat(filepath.Join(dst, ".git")); err == nil {
if err := runGit(ctx, dst, "fetch", "--depth", "1", "origin", branch); err != nil {
if _, err := osStat(filepath.Join(dst, ".git")); err == nil {
if err := runGitHook(ctx, dst, "fetch", "--depth", "1", "origin", branch); err != nil {
return nil, err
}
if err := runGit(ctx, dst, "reset", "--hard", "FETCH_HEAD"); err != nil {
if err := runGitHook(ctx, dst, "reset", "--hard", "FETCH_HEAD"); err != nil {
return nil, err
}
} else {
if err := os.MkdirAll(dst, 0o755); err != nil {
if err := osMkdirAll(dst, 0o755); err != nil {
return nil, fmt.Errorf("mkdir dst: %w", err)
}
if err := runGit(ctx, ".", "clone", "--depth", "1", "--branch", branch, repoURL, dst); err != nil {
if err := runGitHook(ctx, ".", "clone", "--depth", "1", "--branch", branch, repoURL, dst); err != nil {
return nil, err
}
}
sha, err := currentSHA(ctx, dst)
sha, err := currentShaHook(ctx, dst)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -181,13 +202,13 @@
return nil, errors.New("pin: empty sha")
}
dst := SkillsDir()
if _, err := os.Stat(filepath.Join(dst, ".git")); err != nil {
if _, err := osStat(filepath.Join(dst, ".git")); err != nil {
return nil, fmt.Errorf("pin: not installed (%s missing .git): %w", dst, err)
}
if err := runGit(ctx, dst, "reset", "--hard", sha); err != nil {
if err := runGitHook(ctx, dst, "reset", "--hard", sha); err != nil {
return nil, err
}
branch, _ := currentBranch(ctx, dst)
branch, _ := currentBranchHook(ctx, dst)
state := PinState{SHA: sha, Branch: branch, UpdatedAt: time.Now().UTC()}
if err := WriteJSON(PinFile(), state); err != nil {
return nil, err
Expand All @@ -206,15 +227,15 @@
// CurrentPin reads the .sin-code-pin file. Returns (nil, nil) if the
// caller has not run Install yet — that is NOT an error, just "not pinned".
func CurrentPin() (*PinState, error) {
b, err := os.ReadFile(PinFile())
b, err := osReadFile(PinFile())
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil, nil
}
return nil, err
}
var p PinState
if err := json.Unmarshal(b, &p); err != nil {
if err := jsonUnmarshal(b, &p); err != nil {
return nil, err
}
return &p, nil
Expand All @@ -229,11 +250,11 @@
if root == "" {
root = SkillsDir()
}
if _, err := os.Stat(root); err != nil {
if _, err := osStat(root); err != nil {
return nil, nil // not installed → empty result, not an error
}
var out []SkillInfo
err := filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error {
err := walkDirHook(root, func(p string, d os.DirEntry, err error) error {
if err != nil {
return nil // skip unreadable entries; do not abort the walk
}
Expand All @@ -243,7 +264,7 @@
if d.Name() != "SKILL.md" {
return nil
}
body, rerr := os.ReadFile(p)
body, rerr := osReadFile(p)
if rerr != nil {
return nil
}
Expand Down Expand Up @@ -318,7 +339,7 @@
const start = "<!-- SIN-Code superpowers:begin -->"
const end = "<!-- SIN-Code superpowers:end -->"
block := start + "\n" + prompt + "\n" + end + "\n"
existing, err := os.ReadFile(agentsPath)
existing, err := osReadFile(agentsPath)
if err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}
Expand All @@ -336,7 +357,7 @@
}
body += "\n" + block
}
return os.WriteFile(agentsPath, []byte(body), 0o644)
return osWriteFile(agentsPath, []byte(body), 0o644)
}

// ── Internal helpers ──────────────────────────────────────────────────
Expand Down Expand Up @@ -392,29 +413,29 @@
// The parent directory of path is created on demand — callers do not
// need to MkdirAll beforehand.
func WriteJSON(path string, v any) error {
data, err := json.MarshalIndent(v, "", " ")
data, err := jsonMarshalIndent(v, "", " ")
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
if err := osMkdirAll(filepath.Dir(path), 0o755); err != nil {
return err
}
tmp, err := os.CreateTemp(filepath.Dir(path), ".superpowers-*.json.tmp")
tmp, err := osCreateTemp(filepath.Dir(path), ".superpowers-*.json.tmp")
if err != nil {
return err
}
tmpName := tmp.Name()
defer os.Remove(tmpName)
if _, err := io.Copy(tmp, strings.NewReader(string(data))); err != nil {
tmp.Close()
if _, err := ioCopyHook(tmp, strings.NewReader(string(data))); err != nil {
fileCloseHook(tmp)

Check warning

Code scanning / gosec

Errors unhandled Warning

Errors unhandled
return err
}
if _, err := tmp.Write([]byte("\n")); err != nil {
tmp.Close()
if _, err := fileWriteHook(tmp, []byte("\n")); err != nil {
fileCloseHook(tmp)

Check warning

Code scanning / gosec

Errors unhandled Warning

Errors unhandled
return err
}
if err := tmp.Close(); err != nil {
if err := fileCloseHook(tmp); err != nil {
return err
}
return os.Rename(tmpName, path)
return osRenameHook(tmpName, path)
}
6 changes: 3 additions & 3 deletions cmd/sin-code/internal/trace/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ const defaultShutdownTimeout = 5 * time.Second

// Test hooks for error paths.
var (
stdouttraceNew = stdouttrace.New
otlptracehttpNew = otlptracehttp.New
resourceNew = resource.New
stdouttraceNew = stdouttrace.New
otlptracehttpNew = otlptracehttp.New
resourceNew = resource.New
)

// ProviderConfig configures InitProvider.
Expand Down
14 changes: 12 additions & 2 deletions cmd/sin-code/internal/tui/agent_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ import (
"github.com/OpenSIN-Code/SIN-Code/cmd/sin-code/internal/session"
)

var (
// test hooks (overridable in tests to exercise error paths without
// heavy refactoring or heavy external dependencies).
osGetwd = os.Getwd
sessionOpen = session.Open
storeStartOrResume = func(s *session.Store, id string) (*session.Session, error) { return s.StartOrResume(id) }
loopbuilderBuild = loopbuilder.Build
storeClose = func(s *session.Store) error { return s.Close() }
)

// EventKind enumerates the discrete signals the runner emits.
type EventKind int

Expand Down Expand Up @@ -122,7 +132,7 @@ const (
// session store, and starts a new resumable session.
func NewAgentRunner(ctx context.Context, cfg Config) (*AgentRunner, error) {
if cfg.Workspace == "" {
wd, err := os.Getwd()
wd, err := osGetwd()
if err != nil {
return nil, fmt.Errorf("agentrunner: resolve workspace: %w", err)
}
Expand All @@ -138,7 +148,7 @@ func NewAgentRunner(ctx context.Context, cfg Config) (*AgentRunner, error) {
if err := os.MkdirAll(filepath.Dir(dbPath), 0o755); err != nil {
return nil, fmt.Errorf("agentrunner: mkdir sessions: %w", err)
}
store, err := session.Open(dbPath)
store, err := sessionOpen(dbPath)
if err != nil {
return nil, fmt.Errorf("agentrunner: open sessions: %w", err)
}
Expand Down
Loading
Loading